From 8c0f2ed48e871960ad4a2c07b94868408d1b2b4b Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Mon, 9 Jan 2023 15:58:32 +0100 Subject: [PATCH 01/58] move disputes to simple-disputes --- Cargo.lock | 1 + zrml/prediction-markets/src/lib.rs | 79 +------------ zrml/simple-disputes/Cargo.toml | 1 + zrml/simple-disputes/src/lib.rs | 184 +++++++++++++++++++++++++---- 4 files changed, 167 insertions(+), 98 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f9d02c5c5..c19c8d2e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12996,6 +12996,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "orml-traits", "pallet-balances", "pallet-timestamp", "parity-scale-codec", diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 045ec7e0c..8ee475df1 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -534,24 +534,13 @@ mod pallet { pub fn dispute( origin: OriginFor, #[pallet::compact] market_id: MarketIdOf, - outcome: OutcomeReport, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - let disputes = Disputes::::get(market_id); + let curr_block_num = >::block_number(); let market = >::market(&market_id)?; - ensure!( - matches!(market.status, MarketStatus::Reported | MarketStatus::Disputed), - Error::::InvalidMarketStatus - ); - let num_disputes: u32 = disputes.len().saturated_into(); - Self::validate_dispute(&disputes, &market, num_disputes, &outcome)?; - T::AssetManager::reserve_named( - &Self::reserve_id(), - Asset::Ztg, - &who, - default_dispute_bond::(disputes.len()), - )?; + ensure!(market.status == MarketStatus::Reported, Error::::InvalidMarketStatus); + match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { T::Authorized::on_dispute(&disputes, &market_id, &market)? @@ -563,12 +552,10 @@ mod pallet { T::SimpleDisputes::on_dispute(&disputes, &market_id, &market)? } } + Self::remove_last_dispute_from_market_ids_per_dispute_block(&disputes, &market_id)?; Self::set_market_as_disputed(&market, &market_id)?; - let market_dispute = MarketDispute { at: curr_block_num, by: who, outcome }; - >::try_mutate(market_id, |disputes| { - disputes.try_push(market_dispute.clone()).map_err(|_| >::StorageOverflow) - })?; + // each dispute resets dispute_duration let dispute_duration_ends_at_block = curr_block_num.saturating_add(market.deadlines.dispute_duration); @@ -579,7 +566,6 @@ mod pallet { Self::deposit_event(Event::MarketDisputed( market_id, MarketStatus::Disputed, - market_dispute, )); // TODO(#782): add court benchmark Ok((Some(T::WeightInfo::dispute_authorized(num_disputes, CacheSize::get()))).into()) @@ -1441,15 +1427,6 @@ mod pallet { /// The origin that is allowed to destroy markets. type DestroyOrigin: EnsureOrigin; - /// The base amount of currency that must be bonded in order to create a dispute. - #[pallet::constant] - type DisputeBond: Get>; - - /// The additional amount of currency that must be bonded when creating a subsequent - /// dispute. - #[pallet::constant] - type DisputeFactor: Get>; - /// Event type Event: From> + IsType<::Event>; @@ -1692,7 +1669,7 @@ mod pallet { /// A market has been closed \[market_id\] MarketClosed(MarketIdOf), /// A market has been disputed \[market_id, new_market_status, new_outcome\] - MarketDisputed(MarketIdOf, MarketStatus, MarketDispute), + MarketDisputed(MarketIdOf, MarketStatus), /// An advised market has ended before it was approved or rejected. \[market_id\] MarketExpired(MarketIdOf), /// A pending market has been rejected as invalid with a reason. \[market_id, reject_reason\] @@ -1837,17 +1814,6 @@ mod pallet { #[pallet::storage_version(STORAGE_VERSION)] pub struct Pallet(PhantomData); - /// For each market, this holds the dispute information for each dispute that's - /// been issued. - #[pallet::storage] - pub type Disputes = StorageMap< - _, - Blake2_128Concat, - MarketIdOf, - BoundedVec, T::MaxDisputes>, - ValueQuery, - >; - #[pallet::storage] pub type MarketIdsPerOpenBlock = StorageMap< _, @@ -2149,26 +2115,6 @@ mod pallet { } } - fn ensure_can_not_dispute_the_same_outcome( - disputes: &[MarketDispute], - report: &Report, - outcome: &OutcomeReport, - ) -> DispatchResult { - if let Some(last_dispute) = disputes.last() { - ensure!(&last_dispute.outcome != outcome, Error::::CannotDisputeSameOutcome); - } else { - ensure!(&report.outcome != outcome, Error::::CannotDisputeSameOutcome); - } - - Ok(()) - } - - #[inline] - fn ensure_disputes_does_not_exceed_max_disputes(num_disputes: u32) -> DispatchResult { - ensure!(num_disputes < T::MaxDisputes::get(), Error::::MaxDisputesReached); - Ok(()) - } - fn ensure_market_is_active(market: &MarketOf) -> DispatchResult { ensure!(market.status == MarketStatus::Active, Error::::MarketIsNotActive); Ok(()) @@ -2806,19 +2752,6 @@ mod pallet { Ok(T::WeightInfo::start_subsidy(total_assets.saturated_into())) } - fn validate_dispute( - disputes: &[MarketDispute], - market: &MarketOf, - num_disputes: u32, - outcome_report: &OutcomeReport, - ) -> DispatchResult { - let report = market.report.as_ref().ok_or(Error::::MarketIsNotReported)?; - ensure!(market.matches_outcome_report(outcome_report), Error::::OutcomeMismatch); - Self::ensure_can_not_dispute_the_same_outcome(disputes, report, outcome_report)?; - Self::ensure_disputes_does_not_exceed_max_disputes(num_disputes)?; - Ok(()) - } - fn construct_market( creator: T::AccountId, creator_fee: u8, diff --git a/zrml/simple-disputes/Cargo.toml b/zrml/simple-disputes/Cargo.toml index ee00bd310..11629771a 100644 --- a/zrml/simple-disputes/Cargo.toml +++ b/zrml/simple-disputes/Cargo.toml @@ -7,6 +7,7 @@ scale-info = { version = "2.1.1", default-features = false, features = ["derive" sp-runtime = { branch = "polkadot-v0.9.26", default-features = false, git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, path = "../../primitives" } zrml-market-commons = { default-features = false, path = "../market-commons" } +orml-traits = { branch = "polkadot-v0.9.26", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } [dev-dependencies] pallet-balances = { branch = "polkadot-v0.9.26", git = "https://github.com/paritytech/substrate" } diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index 2609fe844..37612e807 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -31,51 +31,101 @@ pub use simple_disputes_pallet_api::SimpleDisputesPalletApi; mod pallet { use crate::SimpleDisputesPalletApi; use core::marker::PhantomData; + use frame_system::pallet_prelude::*; use frame_support::{ dispatch::DispatchResult, traits::{Currency, Get, Hooks, IsType}, PalletId, + pallet_prelude::*, + transactional, }; use sp_runtime::DispatchError; use zeitgeist_primitives::{ traits::DisputeApi, - types::{Market, MarketDispute, MarketDisputeMechanism, MarketStatus, OutcomeReport}, + types::{Report, Asset, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, OutcomeReport}, }; + use sp_runtime::traits::Saturating; + use sp_runtime::SaturatedConversion; + use zeitgeist_primitives::traits::ZeitgeistAssetManager; use zrml_market_commons::MarketCommonsPalletApi; - - type BalanceOf = - as Currency<::AccountId>>::Balance; - pub(crate) type CurrencyOf = - <::MarketCommons as MarketCommonsPalletApi>::Currency; - pub(crate) type MarketIdOf = - <::MarketCommons as MarketCommonsPalletApi>::MarketId; - pub(crate) type MomentOf = <::MarketCommons as MarketCommonsPalletApi>::Moment; - pub(crate) type MarketOf = Market< - ::AccountId, - BalanceOf, - ::BlockNumber, - MomentOf, - >; - - #[pallet::call] - impl Pallet {} + use orml_traits::currency::NamedMultiReservableCurrency; #[pallet::config] pub trait Config: frame_system::Config { + /// Shares of outcome assets and native currency + type AssetManager: ZeitgeistAssetManager< + Self::AccountId, + Balance = as Currency>::Balance, + CurrencyId = Asset>, + ReserveIdentifier = [u8; 8], + >; + /// Event type Event: From> + IsType<::Event>; + /// The base amount of currency that must be bonded in order to create a dispute. + #[pallet::constant] + type DisputeBond: Get>; + + /// The additional amount of currency that must be bonded when creating a subsequent + /// dispute. + #[pallet::constant] + type DisputeFactor: Get>; + /// The identifier of individual markets. type MarketCommons: MarketCommonsPalletApi< AccountId = Self::AccountId, BlockNumber = Self::BlockNumber, >; + /// The maximum number of disputes allowed on any single market. + #[pallet::constant] + type MaxDisputes: Get; + /// The pallet identifier. #[pallet::constant] type PalletId: Get; + + #[pallet::constant] + type PredictionMarketsPalletId: Get; } + type BalanceOf = + as Currency<::AccountId>>::Balance; + pub(crate) type CurrencyOf = + <::MarketCommons as MarketCommonsPalletApi>::Currency; + pub(crate) type MarketIdOf = + <::MarketCommons as MarketCommonsPalletApi>::MarketId; + pub(crate) type MomentOf = <::MarketCommons as MarketCommonsPalletApi>::Moment; + pub(crate) type MarketOf = Market< + ::AccountId, + BalanceOf, + ::BlockNumber, + MomentOf, + >; + + #[pallet::pallet] + pub struct Pallet(PhantomData); + + /// For each market, this holds the dispute information for each dispute that's + /// been issued. + #[pallet::storage] + pub type Disputes = StorageMap< + _, + Blake2_128Concat, + MarketIdOf, + BoundedVec, T::MaxDisputes>, + ValueQuery, + >; + + #[pallet::event] + #[pallet::generate_deposit(fn deposit_event)] + pub enum Event + where + T: Config, { + OutcomeReserved { market_id: MarketIdOf, dispute: MarketDispute }, + } + #[pallet::error] pub enum Error { /// 1. Any resolution must either have a `Disputed` or `Reported` market status @@ -83,16 +133,93 @@ mod pallet { InvalidMarketStatus, /// On dispute or resolution, someone tried to pass a non-simple-disputes market type MarketDoesNotHaveSimpleDisputesMechanism, + StorageOverflow, + OutcomeMismatch, + CannotDisputeSameOutcome, + MarketIsNotReported, + MaxDisputesReached, } - #[pallet::event] - pub enum Event - where - T: Config, {} - #[pallet::hooks] impl Hooks for Pallet {} + #[pallet::call] + impl Pallet { + #[pallet::weight(5000)] + #[transactional] + pub fn reserve_outcome( + origin: OriginFor, + #[pallet::compact] market_id: MarketIdOf, + outcome: OutcomeReport, + ) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + let market = T::MarketCommons::market(&market_id)?; + ensure!( + market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, + Error::::MarketDoesNotHaveSimpleDisputesMechanism + ); + ensure!( + market.status == MarketStatus::Disputed, + Error::::InvalidMarketStatus + ); + ensure!(market.matches_outcome_report(&outcome), Error::::OutcomeMismatch); + let report = market.report.as_ref().ok_or(Error::::MarketIsNotReported)?; + + let now = >::block_number(); + let disputes = Disputes::::get(&market_id); + let num_disputes: u32 = disputes.len().saturated_into(); + + Self::ensure_can_not_dispute_the_same_outcome(&disputes, report, &outcome)?; + Self::ensure_disputes_does_not_exceed_max_disputes(num_disputes)?; + + T::AssetManager::reserve_named( + &Self::reserve_id(), + Asset::Ztg, + &who, + default_dispute_bond::(disputes.len()), + )?; + + let market_dispute = MarketDispute { at: now, by: who, outcome }; + >::try_mutate(market_id, |disputes| { + disputes.try_push(market_dispute.clone()).map_err(|_| >::StorageOverflow) + })?; + + Self::deposit_event(Event::OutcomeReserved { + market_id, + dispute: market_dispute, + }); + + Ok((Some(5000)).into()) + } + } + + impl Pallet { + #[inline] + pub fn reserve_id() -> [u8; 8] { + T::PredictionMarketsPalletId::get().0 + } + + fn ensure_can_not_dispute_the_same_outcome( + disputes: &[MarketDispute], + report: &Report, + outcome: &OutcomeReport, + ) -> DispatchResult { + if let Some(last_dispute) = disputes.last() { + ensure!(&last_dispute.outcome != outcome, Error::::CannotDisputeSameOutcome); + } else { + ensure!(&report.outcome != outcome, Error::::CannotDisputeSameOutcome); + } + + Ok(()) + } + + #[inline] + fn ensure_disputes_does_not_exceed_max_disputes(num_disputes: u32) -> DispatchResult { + ensure!(num_disputes < T::MaxDisputes::get(), Error::::MaxDisputesReached); + Ok(()) + } + } + impl DisputeApi for Pallet where T: Config, @@ -137,6 +264,13 @@ mod pallet { impl SimpleDisputesPalletApi for Pallet where T: Config {} - #[pallet::pallet] - pub struct Pallet(PhantomData); + // No-one can bound more than BalanceOf, therefore, this functions saturates + pub(crate) fn default_dispute_bond(n: usize) -> BalanceOf + where + T: Config, + { + T::DisputeBond::get().saturating_add( + T::DisputeFactor::get().saturating_mul(n.saturated_into::().into()), + ) + } } From 1977d2ac69fc8e1823eed2700c686269eaae79e1 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Wed, 11 Jan 2023 14:47:53 +0100 Subject: [PATCH 02/58] move more to simple-disputes --- primitives/src/traits/dispute_api.rs | 9 +- zrml/prediction-markets/src/lib.rs | 73 +++----------- zrml/simple-disputes/src/lib.rs | 138 +++++++++++++++++---------- 3 files changed, 105 insertions(+), 115 deletions(-) diff --git a/primitives/src/traits/dispute_api.rs b/primitives/src/traits/dispute_api.rs index 17d062692..a332874c9 100644 --- a/primitives/src/traits/dispute_api.rs +++ b/primitives/src/traits/dispute_api.rs @@ -40,11 +40,7 @@ pub trait DisputeApi { /// /// Further interaction with the dispute API (if necessary) **should** happen through an /// associated pallet. **May** assume that `market.dispute_mechanism` refers to the calling dispute API. - fn on_dispute( - previous_disputes: &[MarketDispute], - market_id: &Self::MarketId, - market: &MarketOfDisputeApi, - ) -> DispatchResult; + fn on_dispute(market_id: &Self::MarketId, market: &MarketOfDisputeApi) -> DispatchResult; /// Manage market resolution of a disputed market. /// @@ -56,7 +52,6 @@ pub trait DisputeApi { /// Returns the dispute mechanism's report if available, otherwise `None`. If `None` is /// returned, this means that the dispute could not be resolved. fn on_resolution( - disputes: &[MarketDispute], market_id: &Self::MarketId, market: &MarketOfDisputeApi, ) -> Result, DispatchError>; @@ -68,7 +63,6 @@ pub trait DisputeApi { /// /// Returns the future resolution block if available, otherwise `None`. fn get_auto_resolve( - disputes: &[MarketDispute], market_id: &Self::MarketId, market: &MarketOfDisputeApi, ) -> Result, DispatchError>; @@ -77,7 +71,6 @@ pub trait DisputeApi { /// was unable to come to a conclusion. /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. fn has_failed( - disputes: &[MarketDispute], market_id: &Self::MarketId, market: &MarketOfDisputeApi, ) -> Result; diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 3602be26f..7b009462b 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -521,7 +521,7 @@ mod pallet { #[pallet::compact] market_id: MarketIdOf, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - + let curr_block_num = >::block_number(); let market = >::market(&market_id)?; ensure!(market.status == MarketStatus::Reported, Error::::InvalidMarketStatus); @@ -529,22 +529,18 @@ mod pallet { // TODO(#782): use multiple benchmarks paths for different dispute mechanisms match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { - T::Authorized::on_dispute(&disputes, &market_id, &market)? - } - MarketDisputeMechanism::Court => { - T::Court::on_dispute(&disputes, &market_id, &market)? + T::Authorized::on_dispute(&market_id, &market)? } + MarketDisputeMechanism::Court => T::Court::on_dispute(&market_id, &market)?, MarketDisputeMechanism::SimpleDisputes => { - T::SimpleDisputes::on_dispute(&disputes, &market_id, &market)? + T::SimpleDisputes::on_dispute(&market_id, &market)? } } Self::set_market_as_disputed(&market, &market_id)?; - let market_dispute = MarketDispute { at: curr_block_num, by: who, outcome }; - Self::deposit_event(Event::MarketDisputed( - market_id, - MarketStatus::Disputed, - )); + + Self::deposit_event(Event::MarketDisputed(market_id, MarketStatus::Disputed)); + Ok((Some(T::WeightInfo::dispute_authorized())).into()) } @@ -2003,13 +1999,13 @@ mod pallet { // TODO(#782): use multiple benchmarks paths for different dispute mechanisms let auto_resolve_block_opt = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { - T::Authorized::get_auto_resolve(&disputes, market_id, &market)? + T::Authorized::get_auto_resolve(market_id, &market)? } MarketDisputeMechanism::Court => { - T::Court::get_auto_resolve(&disputes, market_id, &market)? + T::Court::get_auto_resolve(market_id, &market)? } MarketDisputeMechanism::SimpleDisputes => { - T::SimpleDisputes::get_auto_resolve(&disputes, market_id, &market)? + T::SimpleDisputes::get_auto_resolve(market_id, &market)? } }; if let Some(auto_resolve_block) = auto_resolve_block_opt { @@ -2290,8 +2286,6 @@ mod pallet { market: &MarketOf, ) -> Result { let report = market.report.as_ref().ok_or(Error::::MarketIsNotReported)?; - let disputes = Disputes::::get(market_id); - let mut resolved_outcome_option = None; #[cfg(feature = "with-global-disputes")] @@ -2306,13 +2300,11 @@ mod pallet { if resolved_outcome_option.is_none() { resolved_outcome_option = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { - T::Authorized::on_resolution(&disputes, market_id, market)? - } - MarketDisputeMechanism::Court => { - T::Court::on_resolution(&disputes, market_id, market)? + T::Authorized::on_resolution(market_id, market)? } + MarketDisputeMechanism::Court => T::Court::on_resolution(market_id, market)?, MarketDisputeMechanism::SimpleDisputes => { - T::SimpleDisputes::on_resolution(&disputes, market_id, market)? + T::SimpleDisputes::on_resolution(market_id, market)? } }; } @@ -2320,53 +2312,16 @@ mod pallet { let resolved_outcome = resolved_outcome_option.unwrap_or_else(|| report.outcome.clone()); - let mut correct_reporters: Vec = Vec::new(); - // If the oracle reported right, return the OracleBond, otherwise slash it to // pay the correct reporters. - let mut overall_imbalance = NegativeImbalanceOf::::zero(); if report.by == market.oracle && report.outcome == resolved_outcome { Self::unreserve_oracle_bond(market_id)?; } else { let imbalance = Self::slash_oracle_bond(market_id, None)?; + // TODO what should be done with the OracleBond imbalance? overall_imbalance.subsume(imbalance); } - for (i, dispute) in disputes.iter().enumerate() { - let actual_bond = default_dispute_bond::(i); - if dispute.outcome == resolved_outcome { - T::AssetManager::unreserve_named( - &Self::reserve_id(), - Asset::Ztg, - &dispute.by, - actual_bond, - ); - - correct_reporters.push(dispute.by.clone()); - } else { - let (imbalance, _) = CurrencyOf::::slash_reserved_named( - &Self::reserve_id(), - &dispute.by, - actual_bond.saturated_into::().saturated_into(), - ); - overall_imbalance.subsume(imbalance); - } - } - - // Fold all the imbalances into one and reward the correct reporters. The - // number of correct reporters might be zero if the market defaults to the - // report after abandoned dispute. In that case, the rewards remain slashed. - if let Some(reward_per_each) = - overall_imbalance.peek().checked_div(&correct_reporters.len().saturated_into()) - { - for correct_reporter in &correct_reporters { - let (actual_reward, leftover) = overall_imbalance.split(reward_per_each); - overall_imbalance = leftover; - CurrencyOf::::resolve_creating(correct_reporter, actual_reward); - } - } - T::Slash::on_unbalanced(overall_imbalance); - Ok(resolved_outcome) } diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index acd23bad6..0b19c7c46 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -31,25 +31,27 @@ pub use simple_disputes_pallet_api::SimpleDisputesPalletApi; mod pallet { use crate::SimpleDisputesPalletApi; use core::marker::PhantomData; - use frame_system::pallet_prelude::*; use frame_support::{ dispatch::DispatchResult, ensure, - traits::{Currency, Get, Hooks, IsType}, - PalletId, pallet_prelude::*, - transactional, + traits::{Currency, Get, Hooks, Imbalance, IsType, NamedReservableCurrency, OnUnbalanced}, + transactional, PalletId, + }; + use frame_system::pallet_prelude::*; + use orml_traits::currency::NamedMultiReservableCurrency; + use sp_runtime::{ + traits::{CheckedDiv, Saturating}, + DispatchError, SaturatedConversion, }; - use sp_runtime::{traits::Saturating, DispatchError}; use zeitgeist_primitives::{ - traits::{DisputeApi, DisputeResolutionApi}, - types::{Report, Asset, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, OutcomeReport}, + traits::{DisputeApi, DisputeResolutionApi, ZeitgeistAssetManager}, + types::{ + Asset, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, OutcomeReport, + Report, + }, }; - use sp_runtime::traits::Saturating; - use sp_runtime::SaturatedConversion; - use zeitgeist_primitives::traits::ZeitgeistAssetManager; use zrml_market_commons::MarketCommonsPalletApi; - use orml_traits::currency::NamedMultiReservableCurrency; #[pallet::config] pub trait Config: frame_system::Config { @@ -96,12 +98,17 @@ mod pallet { #[pallet::constant] type PredictionMarketsPalletId: Get; + + /// Handler for slashed funds. + type Slash: OnUnbalanced>; } type BalanceOf = - as Currency<::AccountId>>::Balance; + as Currency<::AccountId>>::Balance; pub(crate) type CurrencyOf = <::MarketCommons as MarketCommonsPalletApi>::Currency; + pub(crate) type NegativeImbalanceOf = + as Currency<::AccountId>>::NegativeImbalance; pub(crate) type MarketIdOf = <::MarketCommons as MarketCommonsPalletApi>::MarketId; pub(crate) type MomentOf = <::MarketCommons as MarketCommonsPalletApi>::Moment; @@ -130,9 +137,13 @@ mod pallet { #[pallet::generate_deposit(fn deposit_event)] pub enum Event where - T: Config, { - OutcomeReserved { market_id: MarketIdOf, dispute: MarketDispute }, - } + T: Config, + { + OutcomeReserved { + market_id: MarketIdOf, + dispute: MarketDispute, + }, + } #[pallet::error] pub enum Error { @@ -166,10 +177,7 @@ mod pallet { market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, Error::::MarketDoesNotHaveSimpleDisputesMechanism ); - ensure!( - market.status == MarketStatus::Disputed, - Error::::InvalidMarketStatus - ); + ensure!(market.status == MarketStatus::Disputed, Error::::InvalidMarketStatus); ensure!(market.matches_outcome_report(&outcome), Error::::OutcomeMismatch); let report = market.report.as_ref().ok_or(Error::::MarketIsNotReported)?; @@ -192,10 +200,13 @@ mod pallet { disputes.try_push(market_dispute.clone()).map_err(|_| >::StorageOverflow) })?; - Self::deposit_event(Event::OutcomeReserved { - market_id, - dispute: market_dispute, - }); + // each dispute resets dispute_duration + Self::remove_auto_resolve(disputes.as_slice(), &market_id, &market); + let dispute_duration_ends_at_block = + now.saturating_add(market.deadlines.dispute_duration); + T::DisputeResolution::add_auto_resolve(&market_id, dispute_duration_ends_at_block)?; + + Self::deposit_event(Event::OutcomeReserved { market_id, dispute: market_dispute }); Ok((Some(5000)).into()) } @@ -261,27 +272,16 @@ mod pallet { type Moment = MomentOf; type Origin = T::Origin; - fn on_dispute( - disputes: &[MarketDispute], - market_id: &Self::MarketId, - market: &MarketOf, - ) -> DispatchResult { + fn on_dispute(_: &Self::MarketId, market: &MarketOf) -> DispatchResult { ensure!( market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, Error::::MarketDoesNotHaveSimpleDisputesMechanism ); - Self::remove_auto_resolve(disputes, market_id, market); - let curr_block_num = >::block_number(); - // each dispute resets dispute_duration - let dispute_duration_ends_at_block = - curr_block_num.saturating_add(market.deadlines.dispute_duration); - T::DisputeResolution::add_auto_resolve(market_id, dispute_duration_ends_at_block)?; Ok(()) } fn on_resolution( - disputes: &[MarketDispute], - _: &Self::MarketId, + market_id: &Self::MarketId, market: &MarketOf, ) -> Result, DispatchError> { ensure!( @@ -290,30 +290,72 @@ mod pallet { ); ensure!(market.status == MarketStatus::Disputed, Error::::InvalidMarketStatus); - if let Some(last_dispute) = disputes.last() { - Ok(Some(last_dispute.outcome.clone())) - } else { - Err(Error::::InvalidMarketStatus.into()) + let disputes = Disputes::::get(market_id); + + let last_dispute = match disputes.last() { + Some(l) => l, + // if there are no disputes, then the market is resolved with the default report + None => return Ok(None), + }; + + let resolved_outcome = last_dispute.outcome.clone(); + + let mut correct_reporters: Vec = Vec::new(); + + let mut overall_imbalance = NegativeImbalanceOf::::zero(); + + for (i, dispute) in disputes.iter().enumerate() { + let actual_bond = default_dispute_bond::(i); + if dispute.outcome == resolved_outcome { + T::AssetManager::unreserve_named( + &Self::reserve_id(), + Asset::Ztg, + &dispute.by, + actual_bond, + ); + + correct_reporters.push(dispute.by.clone()); + } else { + let (imbalance, _) = CurrencyOf::::slash_reserved_named( + &Self::reserve_id(), + &dispute.by, + actual_bond.saturated_into::().saturated_into(), + ); + overall_imbalance.subsume(imbalance); + } + } + + // Fold all the imbalances into one and reward the correct reporters. The + // number of correct reporters might be zero if the market defaults to the + // report after abandoned dispute. In that case, the rewards remain slashed. + if let Some(reward_per_each) = + overall_imbalance.peek().checked_div(&correct_reporters.len().saturated_into()) + { + for correct_reporter in &correct_reporters { + let (actual_reward, leftover) = overall_imbalance.split(reward_per_each); + overall_imbalance = leftover; + CurrencyOf::::resolve_creating(correct_reporter, actual_reward); + } } + + T::Slash::on_unbalanced(overall_imbalance); + + Ok(Some(resolved_outcome)) } fn get_auto_resolve( - disputes: &[MarketDispute], - _: &Self::MarketId, + market_id: &Self::MarketId, market: &MarketOf, ) -> Result, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, Error::::MarketDoesNotHaveSimpleDisputesMechanism ); - Ok(Self::get_auto_resolve(disputes, market)) + let disputes = Disputes::::get(market_id); + Ok(Self::get_auto_resolve(disputes.as_slice(), market)) } - fn has_failed( - _: &[MarketDispute], - _: &Self::MarketId, - market: &MarketOf, - ) -> Result { + fn has_failed(_: &Self::MarketId, market: &MarketOf) -> Result { ensure!( market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, Error::::MarketDoesNotHaveSimpleDisputesMechanism From c8699d4d5237d21a63672d89a029da74dbe8c5d5 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Wed, 11 Jan 2023 16:45:53 +0100 Subject: [PATCH 03/58] wip --- Cargo.lock | 1 + primitives/src/traits/dispute_api.rs | 7 +++ zrml/authorized/src/lib.rs | 31 +++++------- zrml/court/src/lib.rs | 25 +++++----- zrml/prediction-markets/src/lib.rs | 72 +++++++++++----------------- zrml/simple-disputes/Cargo.toml | 4 ++ zrml/simple-disputes/src/lib.rs | 65 ++++++++++++++++++++++--- zrml/simple-disputes/src/weights.rs | 67 ++++++++++++++++++++++++++ 8 files changed, 191 insertions(+), 81 deletions(-) create mode 100644 zrml/simple-disputes/src/weights.rs diff --git a/Cargo.lock b/Cargo.lock index c19c8d2e9..19cff4536 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13004,6 +13004,7 @@ dependencies = [ "sp-io", "sp-runtime", "zeitgeist-primitives", + "zrml-global-disputes", "zrml-market-commons", ] diff --git a/primitives/src/traits/dispute_api.rs b/primitives/src/traits/dispute_api.rs index a332874c9..5a87f8e00 100644 --- a/primitives/src/traits/dispute_api.rs +++ b/primitives/src/traits/dispute_api.rs @@ -74,6 +74,13 @@ pub trait DisputeApi { market_id: &Self::MarketId, market: &MarketOfDisputeApi, ) -> Result; + + /// Called, when a global dispute is started. + /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. + fn on_global_dispute( + market_id: &Self::MarketId, + market: &MarketOfDisputeApi, + ) -> DispatchResult; } type MarketOfDisputeResolutionApi = Market< diff --git a/zrml/authorized/src/lib.rs b/zrml/authorized/src/lib.rs index d33cc2789..7c46b2ae4 100644 --- a/zrml/authorized/src/lib.rs +++ b/zrml/authorized/src/lib.rs @@ -46,10 +46,7 @@ mod pallet { use sp_runtime::{traits::Saturating, DispatchError}; use zeitgeist_primitives::{ traits::{DisputeApi, DisputeResolutionApi}, - types::{ - AuthorityReport, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, - OutcomeReport, - }, + types::{AuthorityReport, Market, MarketDisputeMechanism, MarketStatus, OutcomeReport}, }; use zrml_market_commons::MarketCommonsPalletApi; @@ -156,8 +153,6 @@ mod pallet { MarketDoesNotHaveDisputeMechanismAuthorized, /// An account attempts to submit a report to an undisputed market. MarketIsNotDisputed, - /// Only one dispute is allowed. - OnlyOneDisputeAllowed, /// The report does not match the market's type. OutcomeMismatch, } @@ -195,21 +190,15 @@ mod pallet { type Moment = MomentOf; type Origin = T::Origin; - fn on_dispute( - disputes: &[MarketDispute], - _: &Self::MarketId, - market: &MarketOf, - ) -> DispatchResult { + fn on_dispute(_: &Self::MarketId, market: &MarketOf) -> DispatchResult { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Authorized, Error::::MarketDoesNotHaveDisputeMechanismAuthorized ); - ensure!(disputes.is_empty(), Error::::OnlyOneDisputeAllowed); Ok(()) } fn on_resolution( - _: &[MarketDispute], market_id: &Self::MarketId, market: &MarketOf, ) -> Result, DispatchError> { @@ -222,7 +211,6 @@ mod pallet { } fn get_auto_resolve( - _: &[MarketDispute], market_id: &Self::MarketId, market: &MarketOf, ) -> Result, DispatchError> { @@ -233,11 +221,7 @@ mod pallet { Ok(Self::get_auto_resolve(market_id)) } - fn has_failed( - _: &[MarketDispute], - _: &Self::MarketId, - market: &MarketOf, - ) -> Result { + fn has_failed(_: &Self::MarketId, market: &MarketOf) -> Result { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Authorized, Error::::MarketDoesNotHaveDisputeMechanismAuthorized @@ -245,6 +229,15 @@ mod pallet { Ok(false) } + + fn on_global_dispute(_: &Self::MarketId, market: &MarketOf) -> DispatchResult { + ensure!( + market.dispute_mechanism == MarketDisputeMechanism::Authorized, + Error::::MarketDoesNotHaveDisputeMechanismAuthorized + ); + + Ok(()) + } } impl AuthorizedPalletApi for Pallet where T: Config {} diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index c1d08183b..e48020cd3 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -509,17 +509,14 @@ mod pallet { type Moment = MomentOf; type Origin = T::Origin; - fn on_dispute( - disputes: &[MarketDispute], - market_id: &Self::MarketId, - market: &MarketOf, - ) -> DispatchResult { + fn on_dispute(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, Error::::MarketDoesNotHaveCourtMechanism ); let jurors: Vec<_> = Jurors::::iter().collect(); - let necessary_jurors_num = Self::necessary_jurors_num(disputes); + // TODO &[] was disputes list before: how to handle it now without disputes from pm? + let necessary_jurors_num = Self::necessary_jurors_num(&[]); let mut rng = Self::rng(); let random_jurors = Self::random_jurors(&jurors, necessary_jurors_num, &mut rng); let curr_block_num = >::block_number(); @@ -535,7 +532,6 @@ mod pallet { // voted outcome (winner of the losing majority) are placed as tardy instead of // being slashed. fn on_resolution( - _: &[MarketDispute], market_id: &Self::MarketId, market: &MarketOf, ) -> Result, DispatchError> { @@ -564,7 +560,6 @@ mod pallet { } fn get_auto_resolve( - _: &[MarketDispute], _: &Self::MarketId, market: &MarketOf, ) -> Result, DispatchError> { @@ -575,17 +570,21 @@ mod pallet { Ok(None) } - fn has_failed( - _: &[MarketDispute], - _: &Self::MarketId, - market: &MarketOf, - ) -> Result { + fn has_failed(_: &Self::MarketId, market: &MarketOf) -> Result { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, Error::::MarketDoesNotHaveCourtMechanism ); Ok(false) } + + fn on_global_dispute(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { + ensure!( + market.dispute_mechanism == MarketDisputeMechanism::Court, + Error::::MarketDoesNotHaveCourtMechanism + ); + Ok(()) + } } impl CourtPalletApi for Pallet where T: Config {} diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 7b009462b..3bb07cff3 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -1297,36 +1297,33 @@ mod pallet { Error::::InvalidDisputeMechanism ); - let disputes = >::get(market_id); - ensure!( - disputes.len() == T::MaxDisputes::get() as usize, - Error::::MaxDisputesNeeded - ); - ensure!( T::GlobalDisputes::is_not_started(&market_id), Error::::GlobalDisputeAlreadyStarted ); - // add report outcome to voting choices - if let Some(report) = &market.report { - T::GlobalDisputes::push_voting_outcome( - &market_id, - report.outcome.clone(), - &report.by, - >::zero(), - )?; - } + let has_failed = match market.dispute_mechanism { + MarketDisputeMechanism::Authorized => { + T::Authorized::has_failed(market_id, &market)? + } + MarketDisputeMechanism::Court => T::Court::has_failed(market_id, &market)?, + MarketDisputeMechanism::SimpleDisputes => { + T::SimpleDisputes::has_failed(market_id, &market)? + } + }; + ensure!(has_failed, Error::::MarketDisputeMechanismNotFailed); - for (index, MarketDispute { at: _, by, outcome }) in disputes.iter().enumerate() { - let dispute_bond = default_dispute_bond::(index); - T::GlobalDisputes::push_voting_outcome( - &market_id, - outcome.clone(), - by, - dispute_bond, - )?; - } + match market.dispute_mechanism { + MarketDisputeMechanism::Authorized => { + T::Authorized::on_global_dispute(market_id, &market)? + } + MarketDisputeMechanism::Court => { + T::Court::on_global_dispute(market_id, &market)? + } + MarketDisputeMechanism::SimpleDisputes => { + T::SimpleDisputes::on_global_dispute(market_id, &market)? + } + }; // TODO(#372): Allow court with global disputes. // ensure, that global disputes controls the resolution now @@ -1573,8 +1570,8 @@ mod pallet { MarketStartTooLate, /// The maximum number of disputes has been reached. MaxDisputesReached, - /// The maximum number of disputes is needed for this operation. - MaxDisputesNeeded, + /// The market dispute mechanism has not failed. + MarketDisputeMechanismNotFailed, /// Tried to settle missing bond. MissingBond, /// The number of categories for a categorical market is too low. @@ -1980,7 +1977,7 @@ mod pallet { /// Clears this market from being stored for automatic resolution. fn clear_auto_resolve(market_id: &MarketIdOf) -> Result<(u32, u32), DispatchError> { let market = >::market(market_id)?; - let (ids_len, disputes_len) = match market.status { + let ids_len = match market.status { MarketStatus::Reported => { let report = market.report.ok_or(Error::::MarketIsNotReported)?; let dispute_duration_ends_at_block = @@ -1995,7 +1992,6 @@ mod pallet { ) } MarketStatus::Disputed => { - let disputes = Disputes::::get(market_id); // TODO(#782): use multiple benchmarks paths for different dispute mechanisms let auto_resolve_block_opt = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { @@ -2010,15 +2006,15 @@ mod pallet { }; if let Some(auto_resolve_block) = auto_resolve_block_opt { let ids_len = remove_auto_resolve::(market_id, auto_resolve_block); - (ids_len, disputes.len() as u32) + (ids_len, 0u32) } else { - (0u32, disputes.len() as u32) + (0u32, 0u32) } } _ => (0u32, 0u32), }; - Ok((ids_len, disputes_len)) + Ok((ids_len, 1u32)) } pub(crate) fn do_buy_complete_set( @@ -2319,7 +2315,7 @@ mod pallet { } else { let imbalance = Self::slash_oracle_bond(market_id, None)?; // TODO what should be done with the OracleBond imbalance? - overall_imbalance.subsume(imbalance); + // overall_imbalance.subsume(imbalance); } Ok(resolved_outcome) @@ -2353,7 +2349,7 @@ mod pallet { m.resolved_outcome = Some(resolved_outcome.clone()); Ok(()) })?; - Disputes::::remove(market_id); + Self::deposit_event(Event::MarketResolved( *market_id, MarketStatus::Resolved, @@ -2727,16 +2723,6 @@ mod pallet { } } - // No-one can bound more than BalanceOf, therefore, this functions saturates - pub(crate) fn default_dispute_bond(n: usize) -> BalanceOf - where - T: Config, - { - T::DisputeBond::get().saturating_add( - T::DisputeFactor::get().saturating_mul(n.saturated_into::().into()), - ) - } - fn remove_item(items: &mut BoundedVec, item: &I) { if let Some(pos) = items.iter().position(|i| i == item) { items.swap_remove(pos); diff --git a/zrml/simple-disputes/Cargo.toml b/zrml/simple-disputes/Cargo.toml index 11629771a..85f45c0f1 100644 --- a/zrml/simple-disputes/Cargo.toml +++ b/zrml/simple-disputes/Cargo.toml @@ -8,6 +8,7 @@ sp-runtime = { branch = "polkadot-v0.9.26", default-features = false, git = "htt zeitgeist-primitives = { default-features = false, path = "../../primitives" } zrml-market-commons = { default-features = false, path = "../market-commons" } orml-traits = { branch = "polkadot-v0.9.26", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } +zrml-global-disputes = { default-features = false, path = "../global-disputes", optional = true } [dev-dependencies] pallet-balances = { branch = "polkadot-v0.9.26", git = "https://github.com/paritytech/substrate" } @@ -34,6 +35,9 @@ std = [ try-runtime = [ "frame-support/try-runtime", ] +with-global-disputes = [ + "zrml-global-disputes", +] [package] authors = ["Zeitgeist PM "] diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index 0b19c7c46..5405792ab 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -23,20 +23,21 @@ extern crate alloc; mod mock; mod simple_disputes_pallet_api; mod tests; +pub mod weights; pub use pallet::*; pub use simple_disputes_pallet_api::SimpleDisputesPalletApi; #[frame_support::pallet] mod pallet { - use crate::SimpleDisputesPalletApi; + use crate::{weights::WeightInfoZeitgeist, SimpleDisputesPalletApi}; use core::marker::PhantomData; use frame_support::{ dispatch::DispatchResult, ensure, - pallet_prelude::*, + pallet_prelude::{Blake2_128Concat, DispatchResultWithPostInfo, StorageMap, ValueQuery}, traits::{Currency, Get, Hooks, Imbalance, IsType, NamedReservableCurrency, OnUnbalanced}, - transactional, PalletId, + transactional, BoundedVec, PalletId, }; use frame_system::pallet_prelude::*; use orml_traits::currency::NamedMultiReservableCurrency; @@ -51,6 +52,8 @@ mod pallet { Report, }, }; + #[cfg(feature = "with-global-disputes")] + use zrml_global_disputes::GlobalDisputesPalletApi; use zrml_market_commons::MarketCommonsPalletApi; #[pallet::config] @@ -82,6 +85,14 @@ mod pallet { #[pallet::constant] type DisputeFactor: Get>; + /// See [`GlobalDisputesPalletApi`]. + #[cfg(feature = "with-global-disputes")] + type GlobalDisputes: GlobalDisputesPalletApi< + MarketIdOf, + Self::AccountId, + BalanceOf, + >; + /// The identifier of individual markets. type MarketCommons: MarketCommonsPalletApi< AccountId = Self::AccountId, @@ -101,6 +112,9 @@ mod pallet { /// Handler for slashed funds. type Slash: OnUnbalanced>; + + /// Weights generated by benchmarks + type WeightInfo: WeightInfoZeitgeist; } type BalanceOf = @@ -340,6 +354,8 @@ mod pallet { T::Slash::on_unbalanced(overall_imbalance); + Disputes::::remove(market_id); + Ok(Some(resolved_outcome)) } @@ -355,13 +371,50 @@ mod pallet { Ok(Self::get_auto_resolve(disputes.as_slice(), market)) } - fn has_failed(_: &Self::MarketId, market: &MarketOf) -> Result { + fn has_failed( + market_id: &Self::MarketId, + market: &MarketOf, + ) -> Result { ensure!( market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, Error::::MarketDoesNotHaveSimpleDisputesMechanism ); - // TODO when does simple disputes fail? - Ok(false) + let disputes = >::get(market_id); + Ok(disputes.len() == T::MaxDisputes::get() as usize) + } + + fn on_global_dispute( + #[allow(dead_code, unused)] market_id: &Self::MarketId, + market: &MarketOf, + ) -> DispatchResult { + ensure!( + market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, + Error::::MarketDoesNotHaveSimpleDisputesMechanism + ); + #[cfg(feature = "with-global-disputes")] + { + let disputes = >::get(market_id); + // add report outcome to voting choices + if let Some(report) = &market.report { + T::GlobalDisputes::push_voting_outcome( + market_id, + report.outcome.clone(), + &report.by, + >::zero(), + )?; + } + + for (index, MarketDispute { at: _, by, outcome }) in disputes.iter().enumerate() { + let dispute_bond = default_dispute_bond::(index); + T::GlobalDisputes::push_voting_outcome( + market_id, + outcome.clone(), + by, + dispute_bond, + )?; + } + } + Ok(()) } } diff --git a/zrml/simple-disputes/src/weights.rs b/zrml/simple-disputes/src/weights.rs new file mode 100644 index 000000000..248c8f7e0 --- /dev/null +++ b/zrml/simple-disputes/src/weights.rs @@ -0,0 +1,67 @@ +// Copyright 2021-2022 Zeitgeist PM LLC. +// +// This file is part of Zeitgeist. +// +// Zeitgeist is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the +// Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// Zeitgeist is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Zeitgeist. If not, see . + +//! Autogenerated weights for zrml_prediction_markets +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-01-09, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/zeitgeist +// benchmark +// pallet +// --chain=dev +// --steps=10 +// --repeat=1000 +// --pallet=zrml_prediction_markets +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./zrml/prediction-markets/src/weights.rs +// --template=./misc/weight_template.hbs + +#![allow(unused_parens)] +#![allow(unused_imports)] + +use core::marker::PhantomData; +use frame_support::{traits::Get, weights::Weight}; + +/// Trait containing the required functions for weight retrival within +/// zrml_prediction_markets (automatically generated) +pub trait WeightInfoZeitgeist { + fn start_global_dispute(m: u32, n: u32) -> Weight; +} + +pub struct WeightInfo(PhantomData); +impl WeightInfoZeitgeist for WeightInfo { + // Storage: MarketCommons Markets (r:1 w:0) + // Storage: PredictionMarkets Disputes (r:1 w:0) + // Storage: GlobalDisputes Winners (r:1 w:1) + // Storage: GlobalDisputes Outcomes (r:7 w:7) + // Storage: PredictionMarkets MarketIdsPerDisputeBlock (r:2 w:2) + fn start_global_dispute(m: u32, n: u32) -> Weight { + (94_106_000 as Weight) + // Standard Error: 0 + .saturating_add((15_000 as Weight).saturating_mul(m as Weight)) + // Standard Error: 0 + .saturating_add((20_000 as Weight).saturating_mul(n as Weight)) + .saturating_add(T::DbWeight::get().reads(12 as Weight)) + .saturating_add(T::DbWeight::get().writes(10 as Weight)) + } +} From ae91749216a69d96b510b3c7473e4b880870dd19 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 12 Jan 2023 16:06:55 +0100 Subject: [PATCH 04/58] wip --- Cargo.lock | 3 ++ primitives/src/traits/dispute_api.rs | 9 ++--- zrml/authorized/src/lib.rs | 10 +++++ zrml/authorized/src/mock.rs | 11 ------ zrml/court/src/lib.rs | 10 +++++ zrml/court/src/mock.rs | 6 --- zrml/prediction-markets/src/lib.rs | 34 +++++++++++----- zrml/prediction-markets/src/mock.rs | 9 ++++- zrml/simple-disputes/Cargo.toml | 3 ++ zrml/simple-disputes/src/lib.rs | 9 +++++ zrml/simple-disputes/src/mock.rs | 59 ++++++++++++++++++++++++---- zrml/simple-disputes/src/tests.rs | 15 +++---- 12 files changed, 131 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 19cff4536..2432a6a68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12996,9 +12996,12 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "orml-currencies", + "orml-tokens", "orml-traits", "pallet-balances", "pallet-timestamp", + "pallet-treasury", "parity-scale-codec", "scale-info", "sp-io", diff --git a/primitives/src/traits/dispute_api.rs b/primitives/src/traits/dispute_api.rs index 5a87f8e00..53f40585b 100644 --- a/primitives/src/traits/dispute_api.rs +++ b/primitives/src/traits/dispute_api.rs @@ -81,6 +81,10 @@ pub trait DisputeApi { market_id: &Self::MarketId, market: &MarketOfDisputeApi, ) -> DispatchResult; + + /// Called, when a market is destroyed. + /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. + fn clear(market_id: &Self::MarketId, market: &MarketOfDisputeApi) -> DispatchResult; } type MarketOfDisputeResolutionApi = Market< @@ -134,9 +138,4 @@ pub trait DisputeResolutionApi { /// /// Returns the number of elements in the storage structure. fn remove_auto_resolve(market_id: &Self::MarketId, resolve_at: Self::BlockNumber) -> u32; - - /// Get the disputes of a market. - fn get_disputes( - market_id: &Self::MarketId, - ) -> BoundedVec, Self::MaxDisputes>; } diff --git a/zrml/authorized/src/lib.rs b/zrml/authorized/src/lib.rs index 7c46b2ae4..ea4fd70ae 100644 --- a/zrml/authorized/src/lib.rs +++ b/zrml/authorized/src/lib.rs @@ -238,6 +238,16 @@ mod pallet { Ok(()) } + + fn clear(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { + ensure!( + market.dispute_mechanism == MarketDisputeMechanism::Authorized, + Error::::MarketDoesNotHaveDisputeMechanismAuthorized + ); + + AuthorizedOutcomeReports::::remove(market_id); + Ok(()) + } } impl AuthorizedPalletApi for Pallet where T: Config {} diff --git a/zrml/authorized/src/mock.rs b/zrml/authorized/src/mock.rs index 056e59f1e..49b277a68 100644 --- a/zrml/authorized/src/mock.rs +++ b/zrml/authorized/src/mock.rs @@ -112,17 +112,6 @@ impl DisputeResolutionApi for MockResolution { ids.len() as u32 }) } - - fn get_disputes( - _market_id: &Self::MarketId, - ) -> BoundedVec, Self::MaxDisputes> { - BoundedVec::try_from(vec![MarketDispute { - at: 42u64, - by: BOB, - outcome: OutcomeReport::Scalar(42), - }]) - .unwrap() - } } impl crate::Config for Runtime { diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index e48020cd3..2368bfeac 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -585,6 +585,16 @@ mod pallet { ); Ok(()) } + + fn clear(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { + ensure!( + market.dispute_mechanism == MarketDisputeMechanism::Court, + Error::::MarketDoesNotHaveCourtMechanism + ); + let _ = Votes::::clear_prefix(market_id, u32::max_value(), None); + let _ = RequestedJurors::::clear_prefix(market_id, u32::max_value(), None); + Ok(()) + } } impl CourtPalletApi for Pallet where T: Config {} diff --git a/zrml/court/src/mock.rs b/zrml/court/src/mock.rs index 11cfe03ee..174eeebbc 100644 --- a/zrml/court/src/mock.rs +++ b/zrml/court/src/mock.rs @@ -98,12 +98,6 @@ impl DisputeResolutionApi for NoopResolution { fn remove_auto_resolve(_market_id: &Self::MarketId, _resolve_at: Self::BlockNumber) -> u32 { 0u32 } - - fn get_disputes( - _market_id: &Self::MarketId, - ) -> BoundedVec, Self::MaxDisputes> { - Default::default() - } } impl crate::Config for Runtime { diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 3bb07cff3..967214d5b 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -261,8 +261,8 @@ mod pallet { let open_ids_len = Self::clear_auto_open(&market_id)?; let close_ids_len = Self::clear_auto_close(&market_id)?; let (ids_len, disputes_len) = Self::clear_auto_resolve(&market_id)?; + Self::clear_dispute_mechanism(&market_id)?; >::remove_market(&market_id)?; - Disputes::::remove(market_id); Self::deposit_event(Event::MarketDestroyed(market_id)); @@ -1787,6 +1787,17 @@ mod pallet { #[pallet::storage_version(STORAGE_VERSION)] pub struct Pallet(PhantomData); + /// For each market, this holds the dispute information for each dispute that's + /// been issued. + #[pallet::storage] + pub type Disputes = StorageMap< + _, + Blake2_128Concat, + MarketIdOf, + BoundedVec, T::MaxDisputes>, + ValueQuery, + >; + #[pallet::storage] pub type MarketIdsPerOpenBlock = StorageMap< _, @@ -2014,7 +2025,19 @@ mod pallet { _ => (0u32, 0u32), }; - Ok((ids_len, 1u32)) + Ok((ids_len, 0u32)) + } + + fn clear_dispute_mechanism(market_id: &MarketIdOf) -> DispatchResult { + let market = >::market(market_id)?; + match market.dispute_mechanism { + MarketDisputeMechanism::Authorized => T::Authorized::clear(market_id, &market)?, + MarketDisputeMechanism::Court => T::Court::clear(market_id, &market)?, + MarketDisputeMechanism::SimpleDisputes => { + T::SimpleDisputes::clear(market_id, &market)? + } + }; + Ok(()) } pub(crate) fn do_buy_complete_set( @@ -2779,12 +2802,5 @@ mod pallet { fn remove_auto_resolve(market_id: &Self::MarketId, resolve_at: Self::BlockNumber) -> u32 { remove_auto_resolve::(market_id, resolve_at) } - - fn get_disputes( - market_id: &Self::MarketId, - ) -> BoundedVec, Self::MaxDisputes> - { - Disputes::::get(market_id) - } } } diff --git a/zrml/prediction-markets/src/mock.rs b/zrml/prediction-markets/src/mock.rs index f44b7b8ba..a746f9cb1 100644 --- a/zrml/prediction-markets/src/mock.rs +++ b/zrml/prediction-markets/src/mock.rs @@ -142,8 +142,6 @@ impl crate::Config for Runtime { type CloseOrigin = EnsureSignedBy; type Court = Court; type DestroyOrigin = EnsureSignedBy; - type DisputeBond = DisputeBond; - type DisputeFactor = DisputeFactor; type Event = Event; #[cfg(feature = "with-global-disputes")] type GlobalDisputes = GlobalDisputes; @@ -305,10 +303,17 @@ impl zrml_rikiddo::Config for Runtime { } impl zrml_simple_disputes::Config for Runtime { + type AssetManager = AssetManager; type Event = Event; + type DisputeBond = DisputeBond; + type DisputeFactor = DisputeFactor; type DisputeResolution = prediction_markets::Pallet; type MarketCommons = MarketCommons; + type MaxDisputes = MaxDisputes; type PalletId = SimpleDisputesPalletId; + type PredictionMarketsPalletId = PmPalletId; + type Slash = Treasury; + type WeightInfo = zrml_simple_disputes::weights::WeightInfo; } #[cfg(feature = "with-global-disputes")] diff --git a/zrml/simple-disputes/Cargo.toml b/zrml/simple-disputes/Cargo.toml index 85f45c0f1..59b787812 100644 --- a/zrml/simple-disputes/Cargo.toml +++ b/zrml/simple-disputes/Cargo.toml @@ -11,7 +11,10 @@ orml-traits = { branch = "polkadot-v0.9.26", default-features = false, git = "ht zrml-global-disputes = { default-features = false, path = "../global-disputes", optional = true } [dev-dependencies] +orml-currencies = { branch = "polkadot-v0.9.26", git = "https://github.com/open-web3-stack/open-runtime-module-library"} +orml-tokens = { branch = "polkadot-v0.9.26", git = "https://github.com/open-web3-stack/open-runtime-module-library"} pallet-balances = { branch = "polkadot-v0.9.26", git = "https://github.com/paritytech/substrate" } +pallet-treasury = { branch = "polkadot-v0.9.26", git = "https://github.com/paritytech/substrate" } pallet-timestamp = { branch = "polkadot-v0.9.26", git = "https://github.com/paritytech/substrate" } sp-io = { branch = "polkadot-v0.9.26", git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, features = ["mock"], path = "../../primitives" } diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index 5405792ab..095fa3ad7 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -416,6 +416,15 @@ mod pallet { } Ok(()) } + + fn clear(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { + ensure!( + market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, + Error::::MarketDoesNotHaveSimpleDisputesMechanism + ); + Disputes::::remove(market_id); + Ok(()) + } } impl SimpleDisputesPalletApi for Pallet where T: Config {} diff --git a/zrml/simple-disputes/src/mock.rs b/zrml/simple-disputes/src/mock.rs index 5e6afbcd6..4efacea60 100644 --- a/zrml/simple-disputes/src/mock.rs +++ b/zrml/simple-disputes/src/mock.rs @@ -30,7 +30,7 @@ use sp_runtime::{ }; use zeitgeist_primitives::{ constants::mock::{ - BlockHashCount, MaxReserves, MinimumPeriod, PmPalletId, SimpleDisputesPalletId, + BlockHashCount, MaxReserves, MinimumPeriod, PmPalletId, SimpleDisputesPalletId, DisputeFactor, DisputeBond, MaxDisputes, }, traits::DisputeResolutionApi, types::{ @@ -47,8 +47,10 @@ construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsicTest, { Balances: pallet_balances::{Call, Config, Event, Pallet, Storage}, + AssetManager: orml_currencies::{Call, Pallet, Storage}, MarketCommons: zrml_market_commons::{Pallet, Storage}, SimpleDisputes: zrml_simple_disputes::{Event, Pallet, Storage}, + Treasury: pallet_treasury::{Call, Event, Pallet, Storage}, System: frame_system::{Call, Config, Event, Pallet, Storage}, Timestamp: pallet_timestamp::{Pallet}, } @@ -86,19 +88,20 @@ impl DisputeResolutionApi for NoopResolution { fn remove_auto_resolve(_market_id: &Self::MarketId, _resolve_at: Self::BlockNumber) -> u32 { 0u32 } - - fn get_disputes( - _market_id: &Self::MarketId, - ) -> BoundedVec, Self::MaxDisputes> { - Default::default() - } } impl crate::Config for Runtime { + type AssetManager = AssetManager; type Event = (); + type DisputeBond = DisputeBond; + type DisputeFactor = DisputeFactor; type DisputeResolution = NoopResolution; type MarketCommons = MarketCommons; + type MaxDisputes = MaxDisputes; type PalletId = SimpleDisputesPalletId; + type PredictionMarketsPalletId = PmPalletId; + type Slash = Treasury; + type WeightInfo = zrml_simple_disputes::weights::WeightInfo; } impl frame_system::Config for Runtime { @@ -140,6 +143,29 @@ impl pallet_balances::Config for Runtime { type WeightInfo = (); } +impl orml_currencies::Config for Runtime { + type GetNativeCurrencyId = GetNativeCurrencyId; + type MultiCurrency = Tokens; + type NativeCurrency = BasicCurrencyAdapter; + type WeightInfo = (); +} + +impl orml_tokens::Config for Runtime { + type Amount = Amount; + type Balance = Balance; + type CurrencyId = CurrencyId; + type DustRemovalWhitelist = Everything; + type Event = Event; + type ExistentialDeposits = ExistentialDeposits; + type MaxLocks = (); + type MaxReserves = MaxReserves; + type OnDust = (); + type OnKilledTokenAccount = (); + type OnNewTokenAccount = (); + type ReserveIdentifier = [u8; 8]; + type WeightInfo = (); +} + impl zrml_market_commons::Config for Runtime { type Currency = Balances; type MarketId = MarketId; @@ -154,6 +180,25 @@ impl pallet_timestamp::Config for Runtime { type WeightInfo = (); } +impl pallet_treasury::Config for Runtime { + type ApproveOrigin = EnsureSignedBy; + type Burn = (); + type BurnDestination = (); + type Currency = Balances; + type Event = Event; + type MaxApprovals = MaxApprovals; + type OnSlash = (); + type PalletId = TreasuryPalletId; + type ProposalBond = (); + type ProposalBondMinimum = (); + type ProposalBondMaximum = (); + type RejectOrigin = EnsureSignedBy; + type SpendFunds = (); + type SpendOrigin = NeverEnsureOrigin; + type SpendPeriod = (); + type WeightInfo = (); +} + pub struct ExtBuilder; impl ExtBuilder { diff --git a/zrml/simple-disputes/src/tests.rs b/zrml/simple-disputes/src/tests.rs index 251377533..5b0233045 100644 --- a/zrml/simple-disputes/src/tests.rs +++ b/zrml/simple-disputes/src/tests.rs @@ -19,9 +19,9 @@ use crate::{ mock::{ExtBuilder, Runtime, SimpleDisputes}, - Error, MarketOf, + Error, MarketOf, Disputes, }; -use frame_support::assert_noop; +use frame_support::{assert_noop, BoundedVec}; use zeitgeist_primitives::{ traits::DisputeApi, types::{ @@ -53,7 +53,7 @@ fn on_dispute_denies_non_simple_disputes_markets() { let mut market = DEFAULT_MARKET; market.dispute_mechanism = MarketDisputeMechanism::Court; assert_noop!( - SimpleDisputes::on_dispute(&[], &0, &market), + SimpleDisputes::on_dispute(&0, &market), Error::::MarketDoesNotHaveSimpleDisputesMechanism ); }); @@ -65,7 +65,7 @@ fn on_resolution_denies_non_simple_disputes_markets() { let mut market = DEFAULT_MARKET; market.dispute_mechanism = MarketDisputeMechanism::Court; assert_noop!( - SimpleDisputes::on_resolution(&[], &0, &market), + SimpleDisputes::on_resolution(&0, &market), Error::::MarketDoesNotHaveSimpleDisputesMechanism ); }); @@ -76,12 +76,13 @@ fn on_resolution_sets_the_last_dispute_of_disputed_markets_as_the_canonical_outc ExtBuilder.build().execute_with(|| { let mut market = DEFAULT_MARKET; market.status = MarketStatus::Disputed; - let disputes = [ + let disputes = BoundedVec::try_from([ MarketDispute { at: 0, by: 0, outcome: OutcomeReport::Scalar(0) }, MarketDispute { at: 0, by: 0, outcome: OutcomeReport::Scalar(20) }, - ]; + ].to_vec()).unwrap(); + Disputes::::insert(&0, &disputes); assert_eq!( - &SimpleDisputes::on_resolution(&disputes, &0, &market).unwrap().unwrap(), + &SimpleDisputes::on_resolution(&0, &market).unwrap().unwrap(), &disputes.last().unwrap().outcome ) }); From 228d3338f69539f958d73a140eecdfd49ed4539f Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Fri, 13 Jan 2023 11:09:09 +0100 Subject: [PATCH 05/58] some mock preparation --- primitives/src/traits/dispute_api.rs | 4 +- zrml/authorized/src/mock.rs | 5 +- zrml/court/src/lib.rs | 2 +- zrml/prediction-markets/src/benchmarks.rs | 74 ++++++++--------------- zrml/prediction-markets/src/lib.rs | 18 +++--- zrml/prediction-markets/src/mock.rs | 2 + zrml/simple-disputes/src/lib.rs | 5 +- zrml/simple-disputes/src/mock.rs | 61 +++++++++++++++++-- zrml/simple-disputes/src/tests.rs | 14 +++-- 9 files changed, 111 insertions(+), 74 deletions(-) diff --git a/primitives/src/traits/dispute_api.rs b/primitives/src/traits/dispute_api.rs index 53f40585b..d415be8d3 100644 --- a/primitives/src/traits/dispute_api.rs +++ b/primitives/src/traits/dispute_api.rs @@ -15,8 +15,8 @@ // You should have received a copy of the GNU General Public License // along with Zeitgeist. If not, see . -use crate::{market::MarketDispute, outcome_report::OutcomeReport, types::Market}; -use frame_support::{dispatch::DispatchResult, pallet_prelude::Weight, BoundedVec}; +use crate::{outcome_report::OutcomeReport, types::Market}; +use frame_support::{dispatch::DispatchResult, pallet_prelude::Weight}; use sp_runtime::DispatchError; // Abstraction of the market type, which is not a part of `DisputeApi` because Rust doesn't support diff --git a/zrml/authorized/src/mock.rs b/zrml/authorized/src/mock.rs index 49b277a68..2d7b3014a 100644 --- a/zrml/authorized/src/mock.rs +++ b/zrml/authorized/src/mock.rs @@ -25,7 +25,6 @@ use frame_support::{ construct_runtime, ord_parameter_types, pallet_prelude::{DispatchError, Weight}, traits::Everything, - BoundedVec, }; use frame_system::EnsureSignedBy; use sp_runtime::{ @@ -39,8 +38,8 @@ use zeitgeist_primitives::{ }, traits::DisputeResolutionApi, types::{ - AccountIdTest, Balance, BlockNumber, BlockTest, Hash, Index, Market, MarketDispute, - MarketId, Moment, OutcomeReport, UncheckedExtrinsicTest, + AccountIdTest, Balance, BlockNumber, BlockTest, Hash, Index, Market, + MarketId, Moment, UncheckedExtrinsicTest, }, }; diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index 2368bfeac..22f8180c1 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -578,7 +578,7 @@ mod pallet { Ok(false) } - fn on_global_dispute(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { + fn on_global_dispute(_: &Self::MarketId, market: &MarketOf) -> DispatchResult { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, Error::::MarketDoesNotHaveCourtMechanism diff --git a/zrml/prediction-markets/src/benchmarks.rs b/zrml/prediction-markets/src/benchmarks.rs index efac65a47..bd78f52fb 100644 --- a/zrml/prediction-markets/src/benchmarks.rs +++ b/zrml/prediction-markets/src/benchmarks.rs @@ -222,7 +222,7 @@ fn setup_reported_categorical_market_with_pool::MarketCommons as MarketCommonsPalletApi>::MarketId: From<::MarketId>, } @@ -246,13 +246,8 @@ benchmarks! { let pool_id = >::market_pool(&market_id)?; - for i in 1..=d { - let outcome = OutcomeReport::Categorical((i % a).saturated_into()); - let disputor = account("disputor", i, 0); - let dispute_bond = crate::pallet::default_dispute_bond::(i as usize); - T::AssetManager::deposit(Asset::Ztg, &disputor, dispute_bond)?; - let _ = Pallet::::dispute(RawOrigin::Signed(disputor).into(), market_id, outcome)?; - } + let disputor = account("disputor", 1, 0); + let _ = Pallet::::dispute(RawOrigin::Signed(disputor).into(), market_id)?; let market = >::market(&market_id)?; @@ -467,24 +462,16 @@ benchmarks! { let outcome = OutcomeReport::Scalar(0); let disputor = account("disputor", 1, 0); - let dispute_bond = crate::pallet::default_dispute_bond::(0_usize); - T::AssetManager::deposit( - Asset::Ztg, - &disputor, - dispute_bond, - )?; - Pallet::::dispute(RawOrigin::Signed(disputor).into(), market_id, outcome)?; - let disputes = Disputes::::get(market_id); - // Authorize the outcome with the highest number of correct reporters to maximize the - // number of transfers required (0 has (d+1)//2 reports, 1 has d//2 reports). + Pallet::::dispute(RawOrigin::Signed(disputor).into(), market_id)?; + + let now = >::block_number(); AuthorizedPallet::::authorize_market_outcome( T::AuthorizedDisputeResolutionOrigin::successful_origin(), market_id.into(), OutcomeReport::Scalar(0), )?; - let last_dispute = disputes.last().unwrap(); - let resolves_at = last_dispute.at.saturating_add(market.deadlines.dispute_duration); + let resolves_at = now.saturating_add(::CorrectionPeriod::get()); for i in 0..r { MarketIdsPerDisputeBlock::::try_mutate( resolves_at, @@ -519,17 +506,9 @@ benchmarks! { Ok(()) })?; - let outcome = OutcomeReport::Categorical(0u16); let disputor = account("disputor", 1, 0); - let dispute_bond = crate::pallet::default_dispute_bond::(0_usize); - T::AssetManager::deposit( - Asset::Ztg, - &disputor, - dispute_bond, - )?; - Pallet::::dispute(RawOrigin::Signed(disputor).into(), market_id, outcome)?; + Pallet::::dispute(RawOrigin::Signed(disputor).into(), market_id)?; - let disputes = Disputes::::get(market_id); // Authorize the outcome with the highest number of correct reporters to maximize the // number of transfers required (0 has (d+1)//2 reports, 1 has d//2 reports). AuthorizedPallet::::authorize_market_outcome( @@ -538,9 +517,9 @@ benchmarks! { OutcomeReport::Categorical(0), )?; - let last_dispute = disputes.last().unwrap(); let market = >::market(&market_id)?; - let resolves_at = last_dispute.at.saturating_add(market.deadlines.dispute_duration); + let now = >::block_number(); + let resolves_at = now.saturating_add(::CorrectionPeriod::get()); for i in 0..r { MarketIdsPerDisputeBlock::::try_mutate( resolves_at, @@ -798,22 +777,27 @@ benchmarks! { market_ids_1.try_push(i.saturated_into()).unwrap(); } - let max_dispute_len = T::MaxDisputes::get(); + let disputor: T::AccountId = account("Disputor", 1, 0); + let _ = Call::::dispute { + market_id, + } + .dispatch_bypass_filter(RawOrigin::Signed(disputor.clone()).into())?; + + let max_dispute_len = ::MaxDisputes::get(); for i in 0..max_dispute_len { // ensure that the MarketIdsPerDisputeBlock does not interfere // with the start_global_dispute execution block >::set_block_number(i.saturated_into()); - let disputor: T::AccountId = account("Disputor", i, 0); - T::AssetManager::deposit(Asset::Ztg, &disputor, (u128::MAX).saturated_into())?; - let _ = Call::::dispute { + let reserver: T::AccountId = account("Reserver", i, 0); + T::AssetManager::deposit(Asset::Ztg, &reserver, (u128::MAX).saturated_into())?; + let _ = zrml_simple_disputes::Call::::reserve_outcome { market_id, - outcome: OutcomeReport::Scalar(i.into()), - } - .dispatch_bypass_filter(RawOrigin::Signed(disputor.clone()).into())?; + outcome: OutcomeReport::Scalar(i.saturated_into()), + }.dispatch_bypass_filter(RawOrigin::Signed(reserver.clone()).into())?; } let market = >::market(&market_id.saturated_into()).unwrap(); - let disputes = Disputes::::get(market_id); + let disputes = zrml_simple_disputes::Disputes::::get(market_id); let last_dispute = disputes.last().unwrap(); let dispute_duration_ends_at_block = last_dispute.at + market.deadlines.dispute_duration; let mut market_ids_2: BoundedVec, CacheSize> = BoundedVec::try_from( @@ -858,9 +842,7 @@ benchmarks! { let market = >::market(&market_id)?; - // only one dispute allowed for authorized mdm - let dispute_outcome = OutcomeReport::Scalar(1u128); - let call = Call::::dispute { market_id, outcome: dispute_outcome }; + let call = Call::::dispute { market_id }; }: { call.dispatch_bypass_filter(RawOrigin::Signed(caller).into())?; } @@ -908,10 +890,8 @@ benchmarks! { Pallet::::dispute( RawOrigin::Signed(caller).into(), market_id, - OutcomeReport::Categorical(0), )?; - // Authorize the outcome with the highest number of correct reporters to maximize the - // number of transfers required (0 has (d+1)//2 reports, 1 has d//2 reports). + AuthorizedPallet::::authorize_market_outcome( T::AuthorizedDisputeResolutionOrigin::successful_origin(), market_id.into(), @@ -953,10 +933,8 @@ benchmarks! { Pallet::::dispute( RawOrigin::Signed(caller).into(), market_id, - OutcomeReport::Scalar(1) )?; - // Authorize the outcome with the highest number of correct reporters to maximize the - // number of transfers required (0 has (d+1)//2 reports, 1 has d//2 reports). + AuthorizedPallet::::authorize_market_outcome( T::AuthorizedDisputeResolutionOrigin::successful_origin(), market_id.into(), diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 967214d5b..141c32000 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -51,7 +51,7 @@ mod pallet { use orml_traits::{MultiCurrency, NamedMultiReservableCurrency}; use sp_arithmetic::per_things::{Perbill, Percent}; use sp_runtime::{ - traits::{CheckedDiv, Saturating, Zero}, + traits::{Saturating, Zero}, DispatchError, DispatchResult, SaturatedConversion, }; use zeitgeist_primitives::{ @@ -1304,24 +1304,24 @@ mod pallet { let has_failed = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { - T::Authorized::has_failed(market_id, &market)? + T::Authorized::has_failed(&market_id, &market)? } - MarketDisputeMechanism::Court => T::Court::has_failed(market_id, &market)?, + MarketDisputeMechanism::Court => T::Court::has_failed(&market_id, &market)?, MarketDisputeMechanism::SimpleDisputes => { - T::SimpleDisputes::has_failed(market_id, &market)? + T::SimpleDisputes::has_failed(&market_id, &market)? } }; ensure!(has_failed, Error::::MarketDisputeMechanismNotFailed); match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { - T::Authorized::on_global_dispute(market_id, &market)? + T::Authorized::on_global_dispute(&market_id, &market)? } MarketDisputeMechanism::Court => { - T::Court::on_global_dispute(market_id, &market)? + T::Court::on_global_dispute(&market_id, &market)? } MarketDisputeMechanism::SimpleDisputes => { - T::SimpleDisputes::on_global_dispute(market_id, &market)? + T::SimpleDisputes::on_global_dispute(&market_id, &market)? } }; @@ -1988,7 +1988,7 @@ mod pallet { /// Clears this market from being stored for automatic resolution. fn clear_auto_resolve(market_id: &MarketIdOf) -> Result<(u32, u32), DispatchError> { let market = >::market(market_id)?; - let ids_len = match market.status { + let (ids_len, mdm_len) = match market.status { MarketStatus::Reported => { let report = market.report.ok_or(Error::::MarketIsNotReported)?; let dispute_duration_ends_at_block = @@ -2025,7 +2025,7 @@ mod pallet { _ => (0u32, 0u32), }; - Ok((ids_len, 0u32)) + Ok((ids_len, mdm_len)) } fn clear_dispute_mechanism(market_id: &MarketIdOf) -> DispatchResult { diff --git a/zrml/prediction-markets/src/mock.rs b/zrml/prediction-markets/src/mock.rs index a746f9cb1..988ca53b4 100644 --- a/zrml/prediction-markets/src/mock.rs +++ b/zrml/prediction-markets/src/mock.rs @@ -308,6 +308,8 @@ impl zrml_simple_disputes::Config for Runtime { type DisputeBond = DisputeBond; type DisputeFactor = DisputeFactor; type DisputeResolution = prediction_markets::Pallet; + #[cfg(feature = "with-global-disputes")] + type GlobalDisputes = GlobalDisputes; type MarketCommons = MarketCommons; type MaxDisputes = MaxDisputes; type PalletId = SimpleDisputesPalletId; diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index f0fd01684..040ef8dda 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -39,10 +39,11 @@ mod pallet { traits::{Currency, Get, Hooks, Imbalance, IsType, NamedReservableCurrency, OnUnbalanced}, transactional, BoundedVec, PalletId, }; + use alloc::vec::Vec; use frame_system::pallet_prelude::*; use orml_traits::currency::NamedMultiReservableCurrency; use sp_runtime::{ - traits::{CheckedDiv, Saturating}, + traits::{CheckedDiv, Saturating, Zero}, DispatchError, SaturatedConversion, }; use zeitgeist_primitives::{ @@ -196,7 +197,7 @@ mod pallet { let report = market.report.as_ref().ok_or(Error::::MarketIsNotReported)?; let now = >::block_number(); - let disputes = Disputes::::get(&market_id); + let disputes = Disputes::::get(market_id); let num_disputes: u32 = disputes.len().saturated_into(); Self::ensure_can_not_dispute_the_same_outcome(&disputes, report, &outcome)?; diff --git a/zrml/simple-disputes/src/mock.rs b/zrml/simple-disputes/src/mock.rs index 4efacea60..16a23d2a7 100644 --- a/zrml/simple-disputes/src/mock.rs +++ b/zrml/simple-disputes/src/mock.rs @@ -22,23 +22,38 @@ use frame_support::{ construct_runtime, pallet_prelude::{DispatchError, Weight}, traits::Everything, - BoundedVec, }; +use frame_system::EnsureSignedBy; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, }; +use frame_support::ord_parameter_types; use zeitgeist_primitives::{ constants::mock::{ - BlockHashCount, MaxReserves, MinimumPeriod, PmPalletId, SimpleDisputesPalletId, DisputeFactor, DisputeBond, MaxDisputes, + BlockHashCount, DisputeBond, DisputeFactor, MaxDisputes, MaxReserves, MinimumPeriod, + PmPalletId, SimpleDisputesPalletId, GetNativeCurrencyId, MaxApprovals, TreasuryPalletId, }, traits::DisputeResolutionApi, types::{ - AccountIdTest, Balance, BlockNumber, BlockTest, Hash, Index, Market, MarketDispute, - MarketId, Moment, UncheckedExtrinsicTest, + AccountIdTest, Balance, BlockNumber, BlockTest, Hash, Index, Market, + MarketId, Moment, UncheckedExtrinsicTest, BasicCurrencyAdapter, }, }; +pub const ALICE: AccountIdTest = 0; +pub const BOB: AccountIdTest = 1; +pub const CHARLIE: AccountIdTest = 2; +pub const DAVE: AccountIdTest = 3; +pub const EVE: AccountIdTest = 4; +pub const FRED: AccountIdTest = 5; +pub const SUDO: AccountIdTest = 69; + +ord_parameter_types! { + pub const Sudo: AccountIdTest = SUDO; +} + +#[cfg(feature = "with-global-disputes")] construct_runtime!( pub enum Runtime where @@ -50,9 +65,30 @@ construct_runtime!( AssetManager: orml_currencies::{Call, Pallet, Storage}, MarketCommons: zrml_market_commons::{Pallet, Storage}, SimpleDisputes: zrml_simple_disputes::{Event, Pallet, Storage}, + GlobalDisputes: zrml_global_disputes::{Event, Pallet, Storage}, + System: frame_system::{Call, Config, Event, Pallet, Storage}, + Timestamp: pallet_timestamp::{Pallet}, + Tokens: orml_tokens::{Config, Event, Pallet, Storage}, Treasury: pallet_treasury::{Call, Event, Pallet, Storage}, + } +); + +#[cfg(not(feature = "with-global-disputes"))] +construct_runtime!( + pub enum Runtime + where + Block = BlockTest, + NodeBlock = BlockTest, + UncheckedExtrinsic = UncheckedExtrinsicTest, + { + Balances: pallet_balances::{Call, Config, Event, Pallet, Storage}, + AssetManager: orml_currencies::{Call, Pallet, Storage}, + MarketCommons: zrml_market_commons::{Pallet, Storage}, + SimpleDisputes: zrml_simple_disputes::{Event, Pallet, Storage}, System: frame_system::{Call, Config, Event, Pallet, Storage}, Timestamp: pallet_timestamp::{Pallet}, + Tokens: orml_tokens::{Config, Event, Pallet, Storage}, + Treasury: pallet_treasury::{Call, Event, Pallet, Storage}, } ); @@ -96,6 +132,8 @@ impl crate::Config for Runtime { type DisputeBond = DisputeBond; type DisputeFactor = DisputeFactor; type DisputeResolution = NoopResolution; + #[cfg(feature = "with-global-disputes")] + type GlobalDisputes = GlobalDisputes; type MarketCommons = MarketCommons; type MaxDisputes = MaxDisputes; type PalletId = SimpleDisputesPalletId; @@ -104,6 +142,21 @@ impl crate::Config for Runtime { type WeightInfo = zrml_simple_disputes::weights::WeightInfo; } +#[cfg(feature = "with-global-disputes")] +impl zrml_global_disputes::Config for Runtime { + type Event = Event; + type MarketCommons = MarketCommons; + type Currency = Balances; + type GlobalDisputeLockId = GlobalDisputeLockId; + type GlobalDisputesPalletId = GlobalDisputesPalletId; + type MaxGlobalDisputeVotes = MaxGlobalDisputeVotes; + type MaxOwners = MaxOwners; + type MinOutcomeVoteAmount = MinOutcomeVoteAmount; + type RemoveKeysLimit = RemoveKeysLimit; + type VotingOutcomeFee = VotingOutcomeFee; + type WeightInfo = zrml_global_disputes::weights::WeightInfo; +} + impl frame_system::Config for Runtime { type AccountData = pallet_balances::AccountData; type AccountId = AccountIdTest; diff --git a/zrml/simple-disputes/src/tests.rs b/zrml/simple-disputes/src/tests.rs index 5b0233045..c256998fc 100644 --- a/zrml/simple-disputes/src/tests.rs +++ b/zrml/simple-disputes/src/tests.rs @@ -19,7 +19,7 @@ use crate::{ mock::{ExtBuilder, Runtime, SimpleDisputes}, - Error, MarketOf, Disputes, + Disputes, Error, MarketOf, }; use frame_support::{assert_noop, BoundedVec}; use zeitgeist_primitives::{ @@ -76,10 +76,14 @@ fn on_resolution_sets_the_last_dispute_of_disputed_markets_as_the_canonical_outc ExtBuilder.build().execute_with(|| { let mut market = DEFAULT_MARKET; market.status = MarketStatus::Disputed; - let disputes = BoundedVec::try_from([ - MarketDispute { at: 0, by: 0, outcome: OutcomeReport::Scalar(0) }, - MarketDispute { at: 0, by: 0, outcome: OutcomeReport::Scalar(20) }, - ].to_vec()).unwrap(); + let disputes = BoundedVec::try_from( + [ + MarketDispute { at: 0, by: 0, outcome: OutcomeReport::Scalar(0) }, + MarketDispute { at: 0, by: 0, outcome: OutcomeReport::Scalar(20) }, + ] + .to_vec(), + ) + .unwrap(); Disputes::::insert(&0, &disputes); assert_eq!( &SimpleDisputes::on_resolution(&0, &market).unwrap().unwrap(), From 1f05799c9349444d6d6a199a1dd83ffc59fa75e1 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Fri, 13 Jan 2023 14:18:31 +0100 Subject: [PATCH 06/58] wip --- runtime/common/src/lib.rs | 9 ++++-- zrml/authorized/src/mock.rs | 4 +-- zrml/authorized/src/tests.rs | 27 ++++------------ zrml/court/src/mock.rs | 6 ++-- zrml/court/src/tests.rs | 30 ++++++++--------- .../fuzz/pm_full_workflow.rs | 1 - zrml/prediction-markets/src/benchmarks.rs | 31 ++++++++++++------ zrml/prediction-markets/src/lib.rs | 5 ++- zrml/prediction-markets/src/mock.rs | 9 ++++-- zrml/prediction-markets/src/tests.rs | 2 +- zrml/simple-disputes/src/lib.rs | 9 +++--- zrml/simple-disputes/src/mock.rs | 32 +++++++++---------- zrml/simple-disputes/src/tests.rs | 2 +- 13 files changed, 85 insertions(+), 82 deletions(-) diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 70389df19..ee42b6c10 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -986,8 +986,6 @@ macro_rules! impl_config_traits { type Court = Court; type CloseOrigin = EnsureRootOrTwoThirdsAdvisoryCommittee; type DestroyOrigin = EnsureRootOrAllAdvisoryCommittee; - type DisputeBond = DisputeBond; - type DisputeFactor = DisputeFactor; type Event = Event; #[cfg(feature = "with-global-disputes")] type GlobalDisputes = GlobalDisputes; @@ -1042,10 +1040,17 @@ macro_rules! impl_config_traits { } impl zrml_simple_disputes::Config for Runtime { + type AssetManager = AssetManager; + type DisputeBond = DisputeBond; + type DisputeFactor = DisputeFactor; type DisputeResolution = zrml_prediction_markets::Pallet; type Event = Event; type MarketCommons = MarketCommons; + type MaxDisputes = MaxDisputes; type PalletId = SimpleDisputesPalletId; + type PredictionMarketsPalletId = PmPalletId; + type Slash = Treasury; + type WeightInfo = zrml_simple_disputes::weights::WeightInfo; } #[cfg(feature = "with-global-disputes")] diff --git a/zrml/authorized/src/mock.rs b/zrml/authorized/src/mock.rs index 2d7b3014a..adef4d071 100644 --- a/zrml/authorized/src/mock.rs +++ b/zrml/authorized/src/mock.rs @@ -38,8 +38,8 @@ use zeitgeist_primitives::{ }, traits::DisputeResolutionApi, types::{ - AccountIdTest, Balance, BlockNumber, BlockTest, Hash, Index, Market, - MarketId, Moment, UncheckedExtrinsicTest, + AccountIdTest, Balance, BlockNumber, BlockTest, Hash, Index, Market, MarketId, Moment, + UncheckedExtrinsicTest, }, }; diff --git a/zrml/authorized/src/tests.rs b/zrml/authorized/src/tests.rs index 7cd33883c..4c5550000 100644 --- a/zrml/authorized/src/tests.rs +++ b/zrml/authorized/src/tests.rs @@ -26,7 +26,7 @@ use crate::{ use frame_support::{assert_noop, assert_ok, dispatch::DispatchError}; use zeitgeist_primitives::{ traits::DisputeApi, - types::{AuthorityReport, MarketDispute, MarketDisputeMechanism, MarketStatus, OutcomeReport}, + types::{AuthorityReport, MarketDisputeMechanism, MarketStatus, OutcomeReport}, }; use zrml_market_commons::Markets; @@ -156,22 +156,10 @@ fn authorize_market_outcome_fails_on_unauthorized_account() { }); } -#[test] -fn on_dispute_fails_if_disputes_is_not_empty() { - ExtBuilder::default().build().execute_with(|| { - let dispute = - MarketDispute { by: crate::mock::ALICE, at: 0, outcome: OutcomeReport::Scalar(1) }; - assert_noop!( - Authorized::on_dispute(&[dispute], &0, &market_mock::()), - Error::::OnlyOneDisputeAllowed - ); - }); -} - #[test] fn on_resolution_fails_if_no_report_was_submitted() { ExtBuilder::default().build().execute_with(|| { - let report = Authorized::on_resolution(&[], &0, &market_mock::()).unwrap(); + let report = Authorized::on_resolution(&0, &market_mock::()).unwrap(); assert!(report.is_none()); }); } @@ -186,7 +174,7 @@ fn on_resolution_removes_stored_outcomes() { 0, OutcomeReport::Scalar(2) )); - assert_ok!(Authorized::on_resolution(&[], &0, &market)); + assert_ok!(Authorized::on_resolution(&0, &market)); assert_eq!(AuthorizedOutcomeReports::::get(0), None); }); } @@ -207,10 +195,7 @@ fn on_resolution_returns_the_reported_outcome() { 0, OutcomeReport::Scalar(2) )); - assert_eq!( - Authorized::on_resolution(&[], &0, &market).unwrap(), - Some(OutcomeReport::Scalar(2)) - ); + assert_eq!(Authorized::on_resolution(&0, &market).unwrap(), Some(OutcomeReport::Scalar(2))); }); } @@ -255,7 +240,7 @@ fn get_auto_resolve_works() { )); let now = frame_system::Pallet::::block_number(); let resolve_at = now + ::CorrectionPeriod::get(); - assert_eq!(Authorized::get_auto_resolve(&[], &0, &market).unwrap(), Some(resolve_at),); + assert_eq!(Authorized::get_auto_resolve(&0, &market).unwrap(), Some(resolve_at),); }); } @@ -263,6 +248,6 @@ fn get_auto_resolve_works() { fn get_auto_resolve_returns_none_without_market_storage() { ExtBuilder::default().build().execute_with(|| { let market = market_mock::(); - assert_eq!(Authorized::get_auto_resolve(&[], &0, &market).unwrap(), None,); + assert_eq!(Authorized::get_auto_resolve(&0, &market).unwrap(), None,); }); } diff --git a/zrml/court/src/mock.rs b/zrml/court/src/mock.rs index 174eeebbc..bc41187cf 100644 --- a/zrml/court/src/mock.rs +++ b/zrml/court/src/mock.rs @@ -23,7 +23,7 @@ use frame_support::{ pallet_prelude::{DispatchError, Weight}, parameter_types, traits::Everything, - BoundedVec, PalletId, + PalletId, }; use sp_runtime::{ testing::Header, @@ -36,8 +36,8 @@ use zeitgeist_primitives::{ }, traits::DisputeResolutionApi, types::{ - AccountIdTest, Balance, BlockNumber, BlockTest, Hash, Index, Market, MarketDispute, - MarketId, Moment, UncheckedExtrinsicTest, + AccountIdTest, Balance, BlockNumber, BlockTest, Hash, Index, Market, MarketId, Moment, + UncheckedExtrinsicTest, }, }; diff --git a/zrml/court/src/tests.rs b/zrml/court/src/tests.rs index c2ecc4b32..b20b4ca18 100644 --- a/zrml/court/src/tests.rs +++ b/zrml/court/src/tests.rs @@ -130,7 +130,7 @@ fn on_dispute_denies_non_court_markets() { let mut market = DEFAULT_MARKET; market.dispute_mechanism = MarketDisputeMechanism::SimpleDisputes; assert_noop!( - Court::on_dispute(&[], &0, &market), + Court::on_dispute(&0, &market), Error::::MarketDoesNotHaveCourtMechanism ); }); @@ -142,7 +142,7 @@ fn on_resolution_denies_non_court_markets() { let mut market = DEFAULT_MARKET; market.dispute_mechanism = MarketDisputeMechanism::SimpleDisputes; assert_noop!( - Court::on_resolution(&[], &0, &market), + Court::on_resolution(&0, &market), Error::::MarketDoesNotHaveCourtMechanism ); }); @@ -154,7 +154,7 @@ fn on_dispute_stores_jurors_that_should_vote() { setup_blocks(123); let _ = Court::join_court(Origin::signed(ALICE)); let _ = Court::join_court(Origin::signed(BOB)); - Court::on_dispute(&[], &0, &DEFAULT_MARKET).unwrap(); + Court::on_dispute(&0, &DEFAULT_MARKET).unwrap(); assert_noop!( Court::join_court(Origin::signed(ALICE)), Error::::JurorAlreadyExists @@ -171,11 +171,11 @@ fn on_resolution_awards_winners_and_slashes_losers() { Court::join_court(Origin::signed(ALICE)).unwrap(); Court::join_court(Origin::signed(BOB)).unwrap(); Court::join_court(Origin::signed(CHARLIE)).unwrap(); - Court::on_dispute(&[], &0, &DEFAULT_MARKET).unwrap(); + Court::on_dispute(&0, &DEFAULT_MARKET).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(2)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(3)).unwrap(); - let _ = Court::on_resolution(&[], &0, &DEFAULT_MARKET).unwrap(); + let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(Balances::free_balance(ALICE), 998 * BASE + 3 * BASE); assert_eq!(Balances::reserved_balance_named(&Court::reserve_id(), &ALICE), 2 * BASE); assert_eq!(Balances::free_balance(BOB), 996 * BASE); @@ -192,11 +192,11 @@ fn on_resolution_decides_market_outcome_based_on_the_majority() { Court::join_court(Origin::signed(ALICE)).unwrap(); Court::join_court(Origin::signed(BOB)).unwrap(); Court::join_court(Origin::signed(CHARLIE)).unwrap(); - Court::on_dispute(&[], &0, &DEFAULT_MARKET).unwrap(); + Court::on_dispute(&0, &DEFAULT_MARKET).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); - let outcome = Court::on_resolution(&[], &0, &DEFAULT_MARKET).unwrap(); + let outcome = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(outcome, Some(OutcomeReport::Scalar(1))); }); } @@ -208,8 +208,8 @@ fn on_resolution_sets_late_jurors_as_tardy() { Court::join_court(Origin::signed(ALICE)).unwrap(); Court::join_court(Origin::signed(BOB)).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); - Court::on_dispute(&[], &0, &DEFAULT_MARKET).unwrap(); - let _ = Court::on_resolution(&[], &0, &DEFAULT_MARKET).unwrap(); + Court::on_dispute(&0, &DEFAULT_MARKET).unwrap(); + let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(Jurors::::get(ALICE).unwrap().status, JurorStatus::Ok); assert_eq!(Jurors::::get(BOB).unwrap().status, JurorStatus::Tardy); }); @@ -222,11 +222,11 @@ fn on_resolution_sets_jurors_that_voted_on_the_second_most_voted_outcome_as_tard Court::join_court(Origin::signed(ALICE)).unwrap(); Court::join_court(Origin::signed(BOB)).unwrap(); Court::join_court(Origin::signed(CHARLIE)).unwrap(); - Court::on_dispute(&[], &0, &DEFAULT_MARKET).unwrap(); + Court::on_dispute(&0, &DEFAULT_MARKET).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); - let _ = Court::on_resolution(&[], &0, &DEFAULT_MARKET).unwrap(); + let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(Jurors::::get(CHARLIE).unwrap().status, JurorStatus::Tardy); }); } @@ -239,8 +239,8 @@ fn on_resolution_punishes_tardy_jurors_that_failed_to_vote_a_second_time() { Court::join_court(Origin::signed(BOB)).unwrap(); Court::set_stored_juror_as_tardy(&BOB).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); - Court::on_dispute(&[], &0, &DEFAULT_MARKET).unwrap(); - let _ = Court::on_resolution(&[], &0, &DEFAULT_MARKET).unwrap(); + Court::on_dispute(&0, &DEFAULT_MARKET).unwrap(); + let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); let join_court_stake = 40000000000; let slash = join_court_stake / 5; assert_eq!(Balances::free_balance(Court::treasury_account_id()), INITIAL_BALANCE + slash); @@ -256,11 +256,11 @@ fn on_resolution_removes_requested_jurors_and_votes() { Court::join_court(Origin::signed(ALICE)).unwrap(); Court::join_court(Origin::signed(BOB)).unwrap(); Court::join_court(Origin::signed(CHARLIE)).unwrap(); - Court::on_dispute(&[], &0, &DEFAULT_MARKET).unwrap(); + Court::on_dispute(&0, &DEFAULT_MARKET).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); - let _ = Court::on_resolution(&[], &0, &DEFAULT_MARKET).unwrap(); + let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(RequestedJurors::::iter().count(), 0); assert_eq!(Votes::::iter().count(), 0); }); diff --git a/zrml/prediction-markets/fuzz/pm_full_workflow.rs b/zrml/prediction-markets/fuzz/pm_full_workflow.rs index e6025f9f5..cc9ba7879 100644 --- a/zrml/prediction-markets/fuzz/pm_full_workflow.rs +++ b/zrml/prediction-markets/fuzz/pm_full_workflow.rs @@ -74,7 +74,6 @@ fuzz_target!(|data: Data| { let _ = PredictionMarkets::dispute( Origin::signed(data.report_origin.into()), dispute_market_id, - outcome(data.report_outcome), ); let _ = PredictionMarkets::on_initialize(5); diff --git a/zrml/prediction-markets/src/benchmarks.rs b/zrml/prediction-markets/src/benchmarks.rs index bd78f52fb..b9b07568d 100644 --- a/zrml/prediction-markets/src/benchmarks.rs +++ b/zrml/prediction-markets/src/benchmarks.rs @@ -230,8 +230,6 @@ benchmarks! { admin_destroy_disputed_market{ // The number of assets. let a in (T::MinCategories::get().into())..T::MaxCategories::get().into(); - // The number of disputes. - let d in 1..T::MaxDisputes::get(); // The number of market ids per open time frame. let o in 0..63; // The number of market ids per close time frame. @@ -244,6 +242,11 @@ benchmarks! { OutcomeReport::Categorical(0u16), )?; + >::mutate_market(&market_id, |market| { + market.dispute_mechanism = MarketDisputeMechanism::Authorized; + Ok(()) + })?; + let pool_id = >::market_pool(&market_id)?; let disputor = account("disputor", 1, 0); @@ -270,9 +273,14 @@ benchmarks! { ).unwrap(); } - let disputes = Disputes::::get(market_id); - let last_dispute = disputes.last().unwrap(); - let resolves_at = last_dispute.at.saturating_add(market.deadlines.dispute_duration); + AuthorizedPallet::::authorize_market_outcome( + T::AuthorizedDisputeResolutionOrigin::successful_origin(), + market_id.into(), + OutcomeReport::Scalar(0), + )?; + + let now = >::block_number(); + let resolves_at = now.saturating_add(::CorrectionPeriod::get()); for i in 0..r { MarketIdsPerDisputeBlock::::try_mutate( resolves_at, @@ -781,23 +789,26 @@ benchmarks! { let _ = Call::::dispute { market_id, } - .dispatch_bypass_filter(RawOrigin::Signed(disputor.clone()).into())?; + .dispatch_bypass_filter(RawOrigin::Signed(disputor).into())?; let max_dispute_len = ::MaxDisputes::get(); for i in 0..max_dispute_len { // ensure that the MarketIdsPerDisputeBlock does not interfere // with the start_global_dispute execution block >::set_block_number(i.saturated_into()); - let reserver: T::AccountId = account("Reserver", i, 0); - T::AssetManager::deposit(Asset::Ztg, &reserver, (u128::MAX).saturated_into())?; + let reserver: T::AccountId = account("Reserver", i, 0); + ::AssetManager::deposit(Asset::Ztg, &reserver, (u128::MAX).saturated_into())?; + let market_id_number: u128 = market_id.saturated_into::(); let _ = zrml_simple_disputes::Call::::reserve_outcome { - market_id, + market_id: market_id_number.saturated_into(), outcome: OutcomeReport::Scalar(i.saturated_into()), }.dispatch_bypass_filter(RawOrigin::Signed(reserver.clone()).into())?; } let market = >::market(&market_id.saturated_into()).unwrap(); - let disputes = zrml_simple_disputes::Disputes::::get(market_id); + let market_id_number: u128 = market_id.saturated_into::(); + let market_id_simple: zrml_simple_disputes::MarketIdOf = market_id_number.saturated_into(); + let disputes = zrml_simple_disputes::Disputes::::get(market_id_simple); let last_dispute = disputes.last().unwrap(); let dispute_duration_ends_at_block = last_dispute.at + market.deadlines.dispute_duration; let mut market_ids_2: BoundedVec, CacheSize> = BoundedVec::try_from( diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 141c32000..52c0c6cf5 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -520,9 +520,8 @@ mod pallet { origin: OriginFor, #[pallet::compact] market_id: MarketIdOf, ) -> DispatchResultWithPostInfo { - let who = ensure_signed(origin)?; + ensure_signed(origin)?; - let curr_block_num = >::block_number(); let market = >::market(&market_id)?; ensure!(market.status == MarketStatus::Reported, Error::::InvalidMarketStatus); @@ -2336,7 +2335,7 @@ mod pallet { if report.by == market.oracle && report.outcome == resolved_outcome { Self::unreserve_oracle_bond(market_id)?; } else { - let imbalance = Self::slash_oracle_bond(market_id, None)?; + let _imbalance = Self::slash_oracle_bond(market_id, None)?; // TODO what should be done with the OracleBond imbalance? // overall_imbalance.subsume(imbalance); } diff --git a/zrml/prediction-markets/src/mock.rs b/zrml/prediction-markets/src/mock.rs index 988ca53b4..4476b3eb8 100644 --- a/zrml/prediction-markets/src/mock.rs +++ b/zrml/prediction-markets/src/mock.rs @@ -458,16 +458,19 @@ mod tests { ); assert_ne!( ::AdvisoryBond::get(), - ::DisputeBond::get() + ::DisputeBond::get() ); assert_ne!( ::OracleBond::get(), ::ValidityBond::get() ); - assert_ne!(::OracleBond::get(), ::DisputeBond::get()); + assert_ne!( + ::OracleBond::get(), + ::DisputeBond::get() + ); assert_ne!( ::ValidityBond::get(), - ::DisputeBond::get() + ::DisputeBond::get() ); } } diff --git a/zrml/prediction-markets/src/tests.rs b/zrml/prediction-markets/src/tests.rs index d41136a57..c0bd6044a 100644 --- a/zrml/prediction-markets/src/tests.rs +++ b/zrml/prediction-markets/src/tests.rs @@ -19,7 +19,7 @@ #![allow(clippy::reversed_empty_ranges)] use crate::{ - default_dispute_bond, mock::*, Config, Disputes, Error, Event, LastTimeFrame, MarketIdsForEdit, + mock::*, Config, Disputes, Error, Event, LastTimeFrame, MarketIdsForEdit, MarketIdsPerCloseBlock, MarketIdsPerDisputeBlock, MarketIdsPerOpenBlock, MarketIdsPerReportBlock, }; diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index 040ef8dda..7902d1b98 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -31,6 +31,7 @@ pub use simple_disputes_pallet_api::SimpleDisputesPalletApi; #[frame_support::pallet] mod pallet { use crate::{weights::WeightInfoZeitgeist, SimpleDisputesPalletApi}; + use alloc::vec::Vec; use core::marker::PhantomData; use frame_support::{ dispatch::DispatchResult, @@ -39,11 +40,12 @@ mod pallet { traits::{Currency, Get, Hooks, Imbalance, IsType, NamedReservableCurrency, OnUnbalanced}, transactional, BoundedVec, PalletId, }; - use alloc::vec::Vec; use frame_system::pallet_prelude::*; use orml_traits::currency::NamedMultiReservableCurrency; + #[cfg(feature = "with-global-disputes")] + use sp_runtime::traits::Zero; use sp_runtime::{ - traits::{CheckedDiv, Saturating, Zero}, + traits::{CheckedDiv, Saturating}, DispatchError, SaturatedConversion, }; use zeitgeist_primitives::{ @@ -124,8 +126,7 @@ mod pallet { <::MarketCommons as MarketCommonsPalletApi>::Currency; pub(crate) type NegativeImbalanceOf = as Currency<::AccountId>>::NegativeImbalance; - pub(crate) type MarketIdOf = - <::MarketCommons as MarketCommonsPalletApi>::MarketId; + pub type MarketIdOf = <::MarketCommons as MarketCommonsPalletApi>::MarketId; pub(crate) type MomentOf = <::MarketCommons as MarketCommonsPalletApi>::Moment; pub(crate) type MarketOf = Market< ::AccountId, diff --git a/zrml/simple-disputes/src/mock.rs b/zrml/simple-disputes/src/mock.rs index 16a23d2a7..59ba06cb3 100644 --- a/zrml/simple-disputes/src/mock.rs +++ b/zrml/simple-disputes/src/mock.rs @@ -19,34 +19,34 @@ use crate::{self as zrml_simple_disputes}; use frame_support::{ - construct_runtime, + construct_runtime, ord_parameter_types, pallet_prelude::{DispatchError, Weight}, - traits::Everything, + traits::{Everything, NeverEnsureOrigin}, }; use frame_system::EnsureSignedBy; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, }; -use frame_support::ord_parameter_types; use zeitgeist_primitives::{ constants::mock::{ - BlockHashCount, DisputeBond, DisputeFactor, MaxDisputes, MaxReserves, MinimumPeriod, - PmPalletId, SimpleDisputesPalletId, GetNativeCurrencyId, MaxApprovals, TreasuryPalletId, + BlockHashCount, DisputeBond, DisputeFactor, ExistentialDeposits, GetNativeCurrencyId, + MaxApprovals, MaxDisputes, MaxReserves, MinimumPeriod, PmPalletId, SimpleDisputesPalletId, + TreasuryPalletId, }, traits::DisputeResolutionApi, types::{ - AccountIdTest, Balance, BlockNumber, BlockTest, Hash, Index, Market, - MarketId, Moment, UncheckedExtrinsicTest, BasicCurrencyAdapter, + AccountIdTest, Amount, Balance, BasicCurrencyAdapter, BlockNumber, BlockTest, CurrencyId, + Hash, Index, Market, MarketId, Moment, UncheckedExtrinsicTest, }, }; -pub const ALICE: AccountIdTest = 0; -pub const BOB: AccountIdTest = 1; -pub const CHARLIE: AccountIdTest = 2; -pub const DAVE: AccountIdTest = 3; -pub const EVE: AccountIdTest = 4; -pub const FRED: AccountIdTest = 5; +#[cfg(feature = "with-global-disputes")] +use zeitgeist_primitives::constants::mock::{ + GlobalDisputeLockId, GlobalDisputesPalletId, MaxGlobalDisputeVotes, MaxOwners, + MinOutcomeVoteAmount, RemoveKeysLimit, VotingOutcomeFee, +}; + pub const SUDO: AccountIdTest = 69; ord_parameter_types! { @@ -144,7 +144,7 @@ impl crate::Config for Runtime { #[cfg(feature = "with-global-disputes")] impl zrml_global_disputes::Config for Runtime { - type Event = Event; + type Event = (); type MarketCommons = MarketCommons; type Currency = Balances; type GlobalDisputeLockId = GlobalDisputeLockId; @@ -208,7 +208,7 @@ impl orml_tokens::Config for Runtime { type Balance = Balance; type CurrencyId = CurrencyId; type DustRemovalWhitelist = Everything; - type Event = Event; + type Event = (); type ExistentialDeposits = ExistentialDeposits; type MaxLocks = (); type MaxReserves = MaxReserves; @@ -238,7 +238,7 @@ impl pallet_treasury::Config for Runtime { type Burn = (); type BurnDestination = (); type Currency = Balances; - type Event = Event; + type Event = (); type MaxApprovals = MaxApprovals; type OnSlash = (); type PalletId = TreasuryPalletId; diff --git a/zrml/simple-disputes/src/tests.rs b/zrml/simple-disputes/src/tests.rs index c256998fc..a62d21549 100644 --- a/zrml/simple-disputes/src/tests.rs +++ b/zrml/simple-disputes/src/tests.rs @@ -84,7 +84,7 @@ fn on_resolution_sets_the_last_dispute_of_disputed_markets_as_the_canonical_outc .to_vec(), ) .unwrap(); - Disputes::::insert(&0, &disputes); + Disputes::::insert(0, &disputes); assert_eq!( &SimpleDisputes::on_resolution(&0, &market).unwrap().unwrap(), &disputes.last().unwrap().outcome From 0b80b7d9aad8069d939039717e1011971e9a08aa Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Fri, 13 Jan 2023 15:40:24 +0100 Subject: [PATCH 07/58] fix tests --- runtime/common/src/lib.rs | 2 + zrml/prediction-markets/Cargo.toml | 1 + zrml/prediction-markets/src/benchmarks.rs | 2 +- zrml/prediction-markets/src/tests.rs | 133 ++++++++++------------ zrml/simple-disputes/src/lib.rs | 2 +- 5 files changed, 66 insertions(+), 74 deletions(-) diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index ee42b6c10..1eb054835 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -1045,6 +1045,8 @@ macro_rules! impl_config_traits { type DisputeFactor = DisputeFactor; type DisputeResolution = zrml_prediction_markets::Pallet; type Event = Event; + #[cfg(feature = "with-global-disputes")] + type GlobalDisputes = GlobalDisputes; type MarketCommons = MarketCommons; type MaxDisputes = MaxDisputes; type PalletId = SimpleDisputesPalletId; diff --git a/zrml/prediction-markets/Cargo.toml b/zrml/prediction-markets/Cargo.toml index 0720f9b84..67a3b6d8d 100644 --- a/zrml/prediction-markets/Cargo.toml +++ b/zrml/prediction-markets/Cargo.toml @@ -80,6 +80,7 @@ try-runtime = [ ] with-global-disputes = [ "zrml-global-disputes", + "zrml-simple-disputes/with-global-disputes", ] [package] diff --git a/zrml/prediction-markets/src/benchmarks.rs b/zrml/prediction-markets/src/benchmarks.rs index b9b07568d..622bad072 100644 --- a/zrml/prediction-markets/src/benchmarks.rs +++ b/zrml/prediction-markets/src/benchmarks.rs @@ -276,7 +276,7 @@ benchmarks! { AuthorizedPallet::::authorize_market_outcome( T::AuthorizedDisputeResolutionOrigin::successful_origin(), market_id.into(), - OutcomeReport::Scalar(0), + OutcomeReport::Categorical(0u16), )?; let now = >::block_number(); diff --git a/zrml/prediction-markets/src/tests.rs b/zrml/prediction-markets/src/tests.rs index c0bd6044a..dff638bbc 100644 --- a/zrml/prediction-markets/src/tests.rs +++ b/zrml/prediction-markets/src/tests.rs @@ -42,7 +42,6 @@ use zeitgeist_primitives::{ MultiHash, OutcomeReport, PoolStatus, ScalarPosition, ScoringRule, }, }; -use zrml_authorized::Error as AuthorizedError; use zrml_market_commons::MarketCommonsPalletApi; use zrml_swaps::Pools; @@ -407,11 +406,7 @@ fn admin_destroy_market_correctly_slashes_permissionless_market_disputed() { OutcomeReport::Categorical(1) )); run_to_block(grace_period + 2); - assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), - 0, - OutcomeReport::Categorical(0) - )); + assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); assert_ok!(AssetManager::deposit(Asset::Ztg, &ALICE, 2 * SENTINEL_AMOUNT)); assert_ok!(Balances::reserve_named( &PredictionMarkets::reserve_id(), @@ -445,12 +440,13 @@ fn admin_destroy_market_correctly_unreserves_dispute_bonds() { OutcomeReport::Categorical(1) )); run_to_block(grace_period + 2); - assert_ok!(PredictionMarkets::dispute( + assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(0) )); - assert_ok!(PredictionMarkets::dispute( + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(DAVE), 0, OutcomeReport::Categorical(1) @@ -479,11 +475,11 @@ fn admin_destroy_market_correctly_unreserves_dispute_bonds() { ); assert_eq!( Balances::free_balance(CHARLIE), - balance_free_before_charlie + default_dispute_bond::(0) + balance_free_before_charlie + zrml_simple_disputes::default_dispute_bond::(0) ); assert_eq!( Balances::free_balance(DAVE), - balance_free_before_dave + default_dispute_bond::(1), + balance_free_before_dave + zrml_simple_disputes::default_dispute_bond::(1), ); assert!(Disputes::::get(market_id).is_empty()); }); @@ -638,11 +634,7 @@ fn admin_destroy_market_correctly_slashes_advised_market_disputed() { 0, OutcomeReport::Categorical(1) )); - assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), - 0, - OutcomeReport::Categorical(0) - )); + assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); assert_ok!(AssetManager::deposit(Asset::Ztg, &ALICE, 2 * SENTINEL_AMOUNT)); assert_ok!(Balances::reserve_named( &PredictionMarkets::reserve_id(), @@ -2053,7 +2045,8 @@ fn it_allows_to_dispute_the_outcome_of_a_market() { let dispute_at = grace_period + 2; run_to_block(dispute_at); - assert_ok!(PredictionMarkets::dispute( + assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(0) @@ -2062,7 +2055,7 @@ fn it_allows_to_dispute_the_outcome_of_a_market() { let market = MarketCommons::market(&0).unwrap(); assert_eq!(market.status, MarketStatus::Disputed); - let disputes = crate::Disputes::::get(0); + let disputes = zrml_simple_disputes::Disputes::::get(0); assert_eq!(disputes.len(), 1); let dispute = &disputes[0]; assert_eq!(dispute.at, dispute_at); @@ -2077,7 +2070,7 @@ fn it_allows_to_dispute_the_outcome_of_a_market() { } #[test] -fn dispute_fails_authority_reported_already() { +fn dispute_fails_disputed_already() { ExtBuilder::default().build().execute_with(|| { let end = 2; assert_ok!(PredictionMarkets::create_market( @@ -2106,15 +2099,11 @@ fn dispute_fails_authority_reported_already() { let dispute_at = grace_period + 2; run_to_block(dispute_at); - assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), - 0, - OutcomeReport::Categorical(0) - )); + assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); assert_noop!( - PredictionMarkets::dispute(Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(1)), - AuthorizedError::::OnlyOneDisputeAllowed + PredictionMarkets::dispute(Origin::signed(CHARLIE), 0), + Error::::InvalidMarketStatus, ); }); } @@ -2223,10 +2212,12 @@ fn it_resolves_a_disputed_market() { OutcomeReport::Categorical(0) )); + assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); + let dispute_at_0 = report_at + 1; run_to_block(dispute_at_0); - assert_ok!(PredictionMarkets::dispute( + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(1) @@ -2235,7 +2226,7 @@ fn it_resolves_a_disputed_market() { let dispute_at_1 = report_at + 2; run_to_block(dispute_at_1); - assert_ok!(PredictionMarkets::dispute( + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(DAVE), 0, OutcomeReport::Categorical(0) @@ -2244,7 +2235,7 @@ fn it_resolves_a_disputed_market() { let dispute_at_2 = report_at + 3; run_to_block(dispute_at_2); - assert_ok!(PredictionMarkets::dispute( + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(EVE), 0, OutcomeReport::Categorical(1) @@ -2264,7 +2255,7 @@ fn it_resolves_a_disputed_market() { assert_eq!(eve_reserved, DisputeBond::get() + 2 * DisputeFactor::get()); // check disputes length - let disputes = crate::Disputes::::get(0); + let disputes = zrml_simple_disputes::Disputes::::get(0); assert_eq!(disputes.len(), 3); // make sure the old mappings of market id per dispute block are erased @@ -2287,7 +2278,7 @@ fn it_resolves_a_disputed_market() { let market_after = MarketCommons::market(&0).unwrap(); assert_eq!(market_after.status, MarketStatus::Resolved); - let disputes = crate::Disputes::::get(0); + let disputes = zrml_simple_disputes::Disputes::::get(0); assert_eq!(disputes.len(), 0); assert_ok!(PredictionMarkets::redeem_shares(Origin::signed(CHARLIE), 0)); @@ -2343,7 +2334,7 @@ fn dispute_fails_unless_reported_or_disputed_market(status: MarketStatus) { })); assert_noop!( - PredictionMarkets::dispute(Origin::signed(EVE), 0, OutcomeReport::Categorical(1)), + PredictionMarkets::dispute(Origin::signed(EVE), 0), Error::::InvalidMarketStatus ); }); @@ -2376,31 +2367,25 @@ fn start_global_dispute_works() { )); let dispute_at_0 = end + grace_period + 2; run_to_block(dispute_at_0); - for i in 1..=::MaxDisputes::get() { - if i == 1 { - #[cfg(feature = "with-global-disputes")] - assert_noop!( - PredictionMarkets::start_global_dispute(Origin::signed(CHARLIE), market_id), - Error::::InvalidMarketStatus - ); - } else { - #[cfg(feature = "with-global-disputes")] - assert_noop!( - PredictionMarkets::start_global_dispute(Origin::signed(CHARLIE), market_id), - Error::::MaxDisputesNeeded - ); - } - assert_ok!(PredictionMarkets::dispute( + assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), market_id,)); + for i in 1..=::MaxDisputes::get() { + #[cfg(feature = "with-global-disputes")] + assert_noop!( + PredictionMarkets::start_global_dispute(Origin::signed(CHARLIE), market_id), + Error::::MarketDisputeMechanismNotFailed + ); + + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(CHARLIE), market_id, - OutcomeReport::Categorical(i.saturated_into()) + OutcomeReport::Categorical(i.saturated_into()), )); run_blocks(1); let market = MarketCommons::market(&market_id).unwrap(); assert_eq!(market.status, MarketStatus::Disputed); } - let disputes = crate::Disputes::::get(market_id); + let disputes = zrml_simple_disputes::Disputes::::get(market_id); assert_eq!(disputes.len(), ::MaxDisputes::get() as usize); let last_dispute = disputes.last().unwrap(); @@ -2421,7 +2406,8 @@ fn start_global_dispute_works() { Some((Zero::zero(), vec![BOB])), ); for i in 1..=::MaxDisputes::get() { - let dispute_bond = crate::default_dispute_bond::((i - 1).into()); + let dispute_bond = + zrml_simple_disputes::default_dispute_bond::((i - 1).into()); assert_eq!( GlobalDisputes::get_voting_outcome_info( &market_id, @@ -2479,11 +2465,7 @@ fn start_global_dispute_fails_on_wrong_mdm() { run_to_block(dispute_at_0); // only one dispute allowed for authorized mdm - assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), - market_id, - OutcomeReport::Categorical(1u32.saturated_into()) - )); + assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), market_id,)); run_blocks(1); let market = MarketCommons::market(&market_id).unwrap(); assert_eq!(market.status, MarketStatus::Disputed); @@ -2879,15 +2861,20 @@ fn full_scalar_market_lifecycle() { assert_eq!(report.outcome, OutcomeReport::Scalar(100)); // dispute - assert_ok!(PredictionMarkets::dispute(Origin::signed(DAVE), 0, OutcomeReport::Scalar(25))); - let disputes = crate::Disputes::::get(0); + assert_ok!(PredictionMarkets::dispute(Origin::signed(DAVE), 0)); + assert_ok!(SimpleDisputes::reserve_outcome( + Origin::signed(DAVE), + 0, + OutcomeReport::Scalar(25) + )); + let disputes = zrml_simple_disputes::Disputes::::get(0); assert_eq!(disputes.len(), 1); run_blocks(market.deadlines.dispute_duration); let market_after_resolve = MarketCommons::market(&0).unwrap(); assert_eq!(market_after_resolve.status, MarketStatus::Resolved); - let disputes = crate::Disputes::::get(0); + let disputes = zrml_simple_disputes::Disputes::::get(0); assert_eq!(disputes.len(), 0); // give EVE some shares @@ -3064,11 +3051,7 @@ fn authorized_correctly_resolves_disputed_market() { let dispute_at = grace_period + 1 + 1; run_to_block(dispute_at); - assert_ok!(PredictionMarkets::dispute( - Origin::signed(CHARLIE), - 0, - OutcomeReport::Categorical(1) - )); + assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); let charlie_balance = Balances::free_balance(&CHARLIE); assert_eq!(charlie_balance, 1_000 * BASE - CENT - DisputeBond::get()); @@ -3482,7 +3465,8 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark 0, OutcomeReport::Categorical(0) )); - assert_ok!(PredictionMarkets::dispute( + assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(1) @@ -3528,7 +3512,8 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_approved_advised_ma 0, OutcomeReport::Categorical(0) )); - assert_ok!(PredictionMarkets::dispute( + assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(1) @@ -3576,13 +3561,14 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark 0, OutcomeReport::Categorical(0) )); + assert_ok!(PredictionMarkets::dispute(Origin::signed(EVE), 0,)); // EVE disputes with wrong outcome - assert_ok!(PredictionMarkets::dispute( + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(EVE), 0, OutcomeReport::Categorical(1) )); - assert_ok!(PredictionMarkets::dispute( + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(0) @@ -3631,13 +3617,14 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_advised_approved_ma 0, OutcomeReport::Categorical(0) )); + assert_ok!(PredictionMarkets::dispute(Origin::signed(EVE), 0,)); // EVE disputes with wrong outcome - assert_ok!(PredictionMarkets::dispute( + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(EVE), 0, OutcomeReport::Categorical(1) )); - assert_ok!(PredictionMarkets::dispute( + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(0) @@ -3687,13 +3674,14 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark 0, OutcomeReport::Categorical(0) )); + assert_ok!(PredictionMarkets::dispute(Origin::signed(EVE), 0,)); // EVE disputes with wrong outcome - assert_ok!(PredictionMarkets::dispute( + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(EVE), 0, OutcomeReport::Categorical(1) )); - assert_ok!(PredictionMarkets::dispute( + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(FRED), 0, OutcomeReport::Categorical(0) @@ -3741,13 +3729,14 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_advised_approved_ma 0, OutcomeReport::Categorical(0) )); + assert_ok!(PredictionMarkets::dispute(Origin::signed(EVE), 0,)); // EVE disputes with wrong outcome - assert_ok!(PredictionMarkets::dispute( + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(EVE), 0, OutcomeReport::Categorical(1) )); - assert_ok!(PredictionMarkets::dispute( + assert_ok!(SimpleDisputes::reserve_outcome( Origin::signed(FRED), 0, OutcomeReport::Categorical(0) diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index 7902d1b98..b49cbc4d9 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -443,7 +443,7 @@ mod pallet { impl SimpleDisputesPalletApi for Pallet where T: Config {} // No-one can bound more than BalanceOf, therefore, this functions saturates - pub(crate) fn default_dispute_bond(n: usize) -> BalanceOf + pub fn default_dispute_bond(n: usize) -> BalanceOf where T: Config, { From 6236d510a52e603455abf54e02a4607c5c361758 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Mon, 16 Jan 2023 09:28:18 +0100 Subject: [PATCH 08/58] taplo fmt --- zrml/simple-disputes/Cargo.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zrml/simple-disputes/Cargo.toml b/zrml/simple-disputes/Cargo.toml index 59b787812..e7c02f8d3 100644 --- a/zrml/simple-disputes/Cargo.toml +++ b/zrml/simple-disputes/Cargo.toml @@ -2,20 +2,20 @@ frame-benchmarking = { branch = "polkadot-v0.9.26", default-features = false, optional = true, git = "https://github.com/paritytech/substrate" } frame-support = { branch = "polkadot-v0.9.26", default-features = false, git = "https://github.com/paritytech/substrate" } frame-system = { branch = "polkadot-v0.9.26", default-features = false, git = "https://github.com/paritytech/substrate" } +orml-traits = { branch = "polkadot-v0.9.26", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } parity-scale-codec = { default-features = false, features = ["derive", "max-encoded-len"], version = "3.0.0" } scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } sp-runtime = { branch = "polkadot-v0.9.26", default-features = false, git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, path = "../../primitives" } -zrml-market-commons = { default-features = false, path = "../market-commons" } -orml-traits = { branch = "polkadot-v0.9.26", default-features = false, git = "https://github.com/open-web3-stack/open-runtime-module-library" } zrml-global-disputes = { default-features = false, path = "../global-disputes", optional = true } +zrml-market-commons = { default-features = false, path = "../market-commons" } [dev-dependencies] -orml-currencies = { branch = "polkadot-v0.9.26", git = "https://github.com/open-web3-stack/open-runtime-module-library"} -orml-tokens = { branch = "polkadot-v0.9.26", git = "https://github.com/open-web3-stack/open-runtime-module-library"} +orml-currencies = { branch = "polkadot-v0.9.26", git = "https://github.com/open-web3-stack/open-runtime-module-library" } +orml-tokens = { branch = "polkadot-v0.9.26", git = "https://github.com/open-web3-stack/open-runtime-module-library" } pallet-balances = { branch = "polkadot-v0.9.26", git = "https://github.com/paritytech/substrate" } -pallet-treasury = { branch = "polkadot-v0.9.26", git = "https://github.com/paritytech/substrate" } pallet-timestamp = { branch = "polkadot-v0.9.26", git = "https://github.com/paritytech/substrate" } +pallet-treasury = { branch = "polkadot-v0.9.26", git = "https://github.com/paritytech/substrate" } sp-io = { branch = "polkadot-v0.9.26", git = "https://github.com/paritytech/substrate" } zeitgeist-primitives = { default-features = false, features = ["mock"], path = "../../primitives" } From e4a09a98d993096ba8e3eaf3b9666febd77bac0e Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Mon, 16 Jan 2023 12:27:58 +0100 Subject: [PATCH 09/58] update court authorized mdms --- zrml/authorized/src/lib.rs | 16 ++++++++++--- zrml/court/src/lib.rs | 49 +++++++++++++++++++++++++++++--------- zrml/court/src/tests.rs | 30 ++++++++++++++--------- 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/zrml/authorized/src/lib.rs b/zrml/authorized/src/lib.rs index ea4fd70ae..35e742264 100644 --- a/zrml/authorized/src/lib.rs +++ b/zrml/authorized/src/lib.rs @@ -96,16 +96,21 @@ mod pallet { let report_opt = AuthorizedOutcomeReports::::get(market_id); let (report, ids_len) = match &report_opt { - Some(report) => (AuthorityReport { resolve_at: report.resolve_at, outcome }, 0u32), + Some(report) => ( + AuthorityReport { resolve_at: report.resolve_at, outcome: outcome.clone() }, + 0u32, + ), None => { let resolve_at = now.saturating_add(T::CorrectionPeriod::get()); let ids_len = T::DisputeResolution::add_auto_resolve(&market_id, resolve_at)?; - (AuthorityReport { resolve_at, outcome }, ids_len) + (AuthorityReport { resolve_at, outcome: outcome.clone() }, ids_len) } }; AuthorizedOutcomeReports::::insert(market_id, report); + Self::deposit_event(Event::AuthorityReported { market_id, outcome }); + if report_opt.is_none() { Ok(Some(T::WeightInfo::authorize_market_outcome_first_report(ids_len)).into()) } else { @@ -158,9 +163,14 @@ mod pallet { } #[pallet::event] + #[pallet::generate_deposit(pub(crate) fn deposit_event)] pub enum Event where - T: Config, {} + T: Config, + { + /// The Authority reported. + AuthorityReported { market_id: MarketIdOf, outcome: OutcomeReport }, + } #[pallet::hooks] impl Hooks for Pallet {} diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index 22f8180c1..c667a7fb9 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -66,7 +66,7 @@ mod pallet { }; use zeitgeist_primitives::{ traits::{DisputeApi, DisputeResolutionApi}, - types::{Market, MarketDispute, MarketDisputeMechanism, OutcomeReport}, + types::{Market, MarketDispute, MarketDisputeMechanism, MarketStatus, OutcomeReport}, }; use zrml_market_commons::MarketCommonsPalletApi; @@ -98,6 +98,36 @@ mod pallet { #[pallet::call] impl Pallet { + #[pallet::weight(1_000_000_000_000)] + pub fn appeal(origin: OriginFor, market_id: MarketIdOf) -> DispatchResult { + // TODO take a bond from the caller + ensure_signed(origin)?; + let market = T::MarketCommons::market(&market_id)?; + ensure!( + market.status == MarketStatus::Disputed, + Error::::MarketIsNotDisputed + ); + ensure!( + market.dispute_mechanism == MarketDisputeMechanism::Court, + Error::::MarketDoesNotHaveCourtMechanism + ); + + let jurors: Vec<_> = Jurors::::iter().collect(); + // TODO &[] was disputes list before: how to handle it now without disputes from pm? + let necessary_jurors_num = Self::necessary_jurors_num(&[]); + let mut rng = Self::rng(); + let random_jurors = Self::random_jurors(&jurors, necessary_jurors_num, &mut rng); + let curr_block_num = >::block_number(); + let block_limit = curr_block_num.saturating_add(T::CourtCaseDuration::get()); + for (ai, _) in random_jurors { + RequestedJurors::::insert(market_id, ai, block_limit); + } + + Self::deposit_event(Event::MarketAppealed { market_id }); + + Ok(()) + } + // MARK(non-transactional): `remove_juror_from_all_courts_of_all_markets` is infallible. #[pallet::weight(T::WeightInfo::exit_court())] pub fn exit_court(origin: OriginFor) -> DispatchResult { @@ -198,6 +228,8 @@ mod pallet { NoVotes, /// Forbids voting of unknown accounts OnlyJurorsCanVote, + /// The market is not in a state where it can be disputed. + MarketIsNotDisputed, } #[pallet::event] @@ -208,6 +240,10 @@ mod pallet { { ExitedJuror(T::AccountId, Juror), JoinedJuror(T::AccountId, Juror), + /// A market has been appealed. + MarketAppealed { + market_id: MarketIdOf, + }, } #[pallet::hooks] @@ -514,16 +550,7 @@ mod pallet { market.dispute_mechanism == MarketDisputeMechanism::Court, Error::::MarketDoesNotHaveCourtMechanism ); - let jurors: Vec<_> = Jurors::::iter().collect(); - // TODO &[] was disputes list before: how to handle it now without disputes from pm? - let necessary_jurors_num = Self::necessary_jurors_num(&[]); - let mut rng = Self::rng(); - let random_jurors = Self::random_jurors(&jurors, necessary_jurors_num, &mut rng); - let curr_block_num = >::block_number(); - let block_limit = curr_block_num.saturating_add(T::CourtCaseDuration::get()); - for (ai, _) in random_jurors { - RequestedJurors::::insert(market_id, ai, block_limit); - } + Ok(()) } diff --git a/zrml/court/src/tests.rs b/zrml/court/src/tests.rs index b20b4ca18..5d74739ae 100644 --- a/zrml/court/src/tests.rs +++ b/zrml/court/src/tests.rs @@ -19,8 +19,8 @@ use crate::{ mock::{ - Balances, Court, ExtBuilder, Origin, RandomnessCollectiveFlip, Runtime, System, ALICE, BOB, - CHARLIE, INITIAL_BALANCE, + Balances, Court, ExtBuilder, MarketCommons, Origin, RandomnessCollectiveFlip, Runtime, + System, ALICE, BOB, CHARLIE, INITIAL_BALANCE, }, Error, Juror, JurorStatus, Jurors, MarketOf, RequestedJurors, Votes, }; @@ -36,6 +36,7 @@ use zeitgeist_primitives::{ MarketStatus, MarketType, OutcomeReport, ScoringRule, }, }; +use zrml_market_commons::MarketCommonsPalletApi; const DEFAULT_MARKET: MarketOf = Market { creation: MarketCreation::Permissionless, @@ -49,7 +50,7 @@ const DEFAULT_MARKET: MarketOf = Market { deadlines: Deadlines { grace_period: 1_u64, oracle_duration: 1_u64, dispute_duration: 1_u64 }, report: None, resolved_outcome: None, - status: MarketStatus::Closed, + status: MarketStatus::Disputed, scoring_rule: ScoringRule::CPMM, bonds: MarketBonds { creation: None, oracle: None }, }; @@ -149,12 +150,13 @@ fn on_resolution_denies_non_court_markets() { } #[test] -fn on_dispute_stores_jurors_that_should_vote() { +fn appeal_stores_jurors_that_should_vote() { ExtBuilder::default().build().execute_with(|| { setup_blocks(123); let _ = Court::join_court(Origin::signed(ALICE)); let _ = Court::join_court(Origin::signed(BOB)); - Court::on_dispute(&0, &DEFAULT_MARKET).unwrap(); + MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); + Court::appeal(Origin::signed(ALICE), 0).unwrap(); assert_noop!( Court::join_court(Origin::signed(ALICE)), Error::::JurorAlreadyExists @@ -171,7 +173,8 @@ fn on_resolution_awards_winners_and_slashes_losers() { Court::join_court(Origin::signed(ALICE)).unwrap(); Court::join_court(Origin::signed(BOB)).unwrap(); Court::join_court(Origin::signed(CHARLIE)).unwrap(); - Court::on_dispute(&0, &DEFAULT_MARKET).unwrap(); + MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); + Court::appeal(Origin::signed(ALICE), 0).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(2)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(3)).unwrap(); @@ -192,7 +195,8 @@ fn on_resolution_decides_market_outcome_based_on_the_majority() { Court::join_court(Origin::signed(ALICE)).unwrap(); Court::join_court(Origin::signed(BOB)).unwrap(); Court::join_court(Origin::signed(CHARLIE)).unwrap(); - Court::on_dispute(&0, &DEFAULT_MARKET).unwrap(); + MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); + Court::appeal(Origin::signed(ALICE), 0).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); @@ -208,7 +212,8 @@ fn on_resolution_sets_late_jurors_as_tardy() { Court::join_court(Origin::signed(ALICE)).unwrap(); Court::join_court(Origin::signed(BOB)).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); - Court::on_dispute(&0, &DEFAULT_MARKET).unwrap(); + MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); + Court::appeal(Origin::signed(ALICE), 0).unwrap(); let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(Jurors::::get(ALICE).unwrap().status, JurorStatus::Ok); assert_eq!(Jurors::::get(BOB).unwrap().status, JurorStatus::Tardy); @@ -222,7 +227,8 @@ fn on_resolution_sets_jurors_that_voted_on_the_second_most_voted_outcome_as_tard Court::join_court(Origin::signed(ALICE)).unwrap(); Court::join_court(Origin::signed(BOB)).unwrap(); Court::join_court(Origin::signed(CHARLIE)).unwrap(); - Court::on_dispute(&0, &DEFAULT_MARKET).unwrap(); + MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); + Court::appeal(Origin::signed(ALICE), 0).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); @@ -239,7 +245,8 @@ fn on_resolution_punishes_tardy_jurors_that_failed_to_vote_a_second_time() { Court::join_court(Origin::signed(BOB)).unwrap(); Court::set_stored_juror_as_tardy(&BOB).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); - Court::on_dispute(&0, &DEFAULT_MARKET).unwrap(); + MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); + Court::appeal(Origin::signed(ALICE), 0).unwrap(); let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); let join_court_stake = 40000000000; let slash = join_court_stake / 5; @@ -256,7 +263,8 @@ fn on_resolution_removes_requested_jurors_and_votes() { Court::join_court(Origin::signed(ALICE)).unwrap(); Court::join_court(Origin::signed(BOB)).unwrap(); Court::join_court(Origin::signed(CHARLIE)).unwrap(); - Court::on_dispute(&0, &DEFAULT_MARKET).unwrap(); + MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); + Court::appeal(Origin::signed(ALICE), 0).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); From a67c50d7204446f859afe65d1da4e668d84b9169 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Mon, 16 Jan 2023 13:44:55 +0100 Subject: [PATCH 10/58] add dispute bond to market storage --- primitives/src/constants/mock.rs | 5 ++- primitives/src/market.rs | 18 ++++++-- runtime/battery-station/src/parameters.rs | 14 +++--- runtime/common/src/lib.rs | 5 ++- runtime/zeitgeist/src/parameters.rs | 14 +++--- zrml/court/src/lib.rs | 11 +++-- zrml/court/src/tests.rs | 2 +- zrml/market-commons/src/tests.rs | 2 +- zrml/prediction-markets/src/lib.rs | 51 +++++++++++++--------- zrml/prediction-markets/src/migrations.rs | 8 +++- zrml/prediction-markets/src/mock.rs | 25 +++++------ zrml/prediction-markets/src/tests.rs | 4 +- zrml/simple-disputes/src/lib.rs | 52 +++++++++-------------- zrml/simple-disputes/src/mock.rs | 6 +-- zrml/simple-disputes/src/tests.rs | 17 ++++++-- 15 files changed, 138 insertions(+), 96 deletions(-) diff --git a/primitives/src/constants/mock.rs b/primitives/src/constants/mock.rs index 515924b50..5295c53ea 100644 --- a/primitives/src/constants/mock.rs +++ b/primitives/src/constants/mock.rs @@ -40,8 +40,7 @@ parameter_types! { // Prediction Market parameters parameter_types! { pub const AdvisoryBond: Balance = 25 * CENT; - pub const DisputeBond: Balance = 5 * BASE; - pub const DisputeFactor: Balance = 2 * BASE; + pub const DisputeBond: Balance = 20 * BASE; pub const GlobalDisputePeriod: BlockNumber = 7 * BLOCKS_PER_DAY; pub const MaxCategories: u16 = 10; pub const MaxDisputes: u16 = 6; @@ -66,6 +65,8 @@ parameter_types! { // Simple disputes parameters parameter_types! { pub const SimpleDisputesPalletId: PalletId = PalletId(*b"zge/sedp"); + pub const OutcomeBond: Balance = 5 * BASE; + pub const OutcomeFactor: Balance = 2 * BASE; } // Swaps parameters diff --git a/primitives/src/market.rs b/primitives/src/market.rs index 9584fd274..450478e97 100644 --- a/primitives/src/market.rs +++ b/primitives/src/market.rs @@ -83,6 +83,7 @@ impl Bond { pub struct MarketBonds { pub creation: Option>, pub oracle: Option>, + pub dispute: Option>, } impl MarketBonds { @@ -92,14 +93,16 @@ impl MarketBonds { Some(bond) if bond.who == *who => bond.value, _ => BA::zero(), }; - value_or_default(&self.creation).saturating_add(value_or_default(&self.oracle)) + value_or_default(&self.creation) + .saturating_add(value_or_default(&self.oracle)) + .saturating_add(value_or_default(&self.dispute)) } } // Used primarily for testing purposes. impl Default for MarketBonds { fn default() -> Self { - MarketBonds { creation: None, oracle: None } + MarketBonds { creation: None, oracle: None, dispute: None } } } @@ -166,13 +169,22 @@ pub enum MarketCreation { Advised, } +// TODO to remove, when Disputes storage item is removed #[derive(Clone, Decode, Encode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] -pub struct MarketDispute { +pub struct OldMarketDispute { pub at: BlockNumber, pub by: AccountId, pub outcome: OutcomeReport, } +#[derive(Clone, Decode, Encode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] +pub struct MarketDispute { + pub at: BlockNumber, + pub by: AccountId, + pub outcome: OutcomeReport, + pub bond: Balance, +} + /// How a market should resolve disputes #[derive(Clone, Decode, Encode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] pub enum MarketDisputeMechanism { diff --git a/runtime/battery-station/src/parameters.rs b/runtime/battery-station/src/parameters.rs index ed4fd4d2d..ab693358e 100644 --- a/runtime/battery-station/src/parameters.rs +++ b/runtime/battery-station/src/parameters.rs @@ -149,11 +149,9 @@ parameter_types! { pub const AdvisoryBond: Balance = 25 * CENT; pub const AdvisoryBondSlashPercentage: Percent = Percent::from_percent(0); /// (Slashable) Bond that is provided for disputing the outcome. - /// Slashed in case the final outcome does not match the dispute for which the `DisputeBond` - /// was deposited. - pub const DisputeBond: Balance = 5 * BASE; - /// `DisputeBond` is increased by this factor after every dispute. - pub const DisputeFactor: Balance = 2 * BASE; + /// Unreserved in case the dispute was justified otherwise slashed. + /// This is when the resolved outcome is different to the default (reported) outcome. + pub const DisputeBond: Balance = 25 * BASE; /// Maximum Categories a prediciton market can have (excluding base asset). pub const MaxCategories: u16 = MAX_CATEGORIES; /// Maximum number of disputes. @@ -217,6 +215,12 @@ parameter_types! { // Simple disputes parameters /// Pallet identifier, mainly used for named balance reserves. pub const SimpleDisputesPalletId: PalletId = SD_PALLET_ID; + /// (Slashable) Bond that is provided for overriding the last outcome addition. + /// Slashed in case the final outcome does not match the dispute for which the `OutcomeBond` + /// was deposited. + pub const OutcomeBond: Balance = 5 * BASE; + /// `OutcomeBond` is increased by this factor after every new outcome addition. + pub const OutcomeFactor: Balance = 2 * BASE; // Swaps parameters /// A precentage from the withdrawal amount a liquidity provider wants to withdraw diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 1eb054835..d52f9189d 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -986,6 +986,7 @@ macro_rules! impl_config_traits { type Court = Court; type CloseOrigin = EnsureRootOrTwoThirdsAdvisoryCommittee; type DestroyOrigin = EnsureRootOrAllAdvisoryCommittee; + type DisputeBond = DisputeBond; type Event = Event; #[cfg(feature = "with-global-disputes")] type GlobalDisputes = GlobalDisputes; @@ -1041,8 +1042,8 @@ macro_rules! impl_config_traits { impl zrml_simple_disputes::Config for Runtime { type AssetManager = AssetManager; - type DisputeBond = DisputeBond; - type DisputeFactor = DisputeFactor; + type OutcomeBond = OutcomeBond; + type OutcomeFactor = OutcomeFactor; type DisputeResolution = zrml_prediction_markets::Pallet; type Event = Event; #[cfg(feature = "with-global-disputes")] diff --git a/runtime/zeitgeist/src/parameters.rs b/runtime/zeitgeist/src/parameters.rs index 060e26a5b..acda8068d 100644 --- a/runtime/zeitgeist/src/parameters.rs +++ b/runtime/zeitgeist/src/parameters.rs @@ -149,11 +149,9 @@ parameter_types! { pub const AdvisoryBond: Balance = 200 * BASE; pub const AdvisoryBondSlashPercentage: Percent = Percent::from_percent(0); /// (Slashable) Bond that is provided for disputing the outcome. - /// Slashed in case the final outcome does not match the dispute for which the `DisputeBond` - /// was deposited. - pub const DisputeBond: Balance = 2_000 * BASE; - /// `DisputeBond` is increased by this factor after every dispute. - pub const DisputeFactor: Balance = 2 * BASE; + /// Unreserved in case the dispute was justified otherwise slashed. + /// This is when the resolved outcome is different to the default (reported) outcome. + pub const DisputeBond: Balance = 5_000 * BASE; /// Maximum Categories a prediciton market can have (excluding base asset). pub const MaxCategories: u16 = MAX_CATEGORIES; /// Maximum number of disputes. @@ -217,6 +215,12 @@ parameter_types! { // Simple disputes parameters /// Pallet identifier, mainly used for named balance reserves. DO NOT CHANGE. pub const SimpleDisputesPalletId: PalletId = SD_PALLET_ID; + /// (Slashable) Bond that is provided for overriding the last outcome addition. + /// Slashed in case the final outcome does not match the dispute for which the `OutcomeBond` + /// was deposited. + pub const OutcomeBond: Balance = 2_000 * BASE; + /// `OutcomeBond` is increased by this factor after every new outcome addition. + pub const OutcomeFactor: Balance = 2 * BASE; // Swaps parameters /// A precentage from the withdrawal amount a liquidity provider wants to withdraw diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index c667a7fb9..d67b3790e 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -103,10 +103,7 @@ mod pallet { // TODO take a bond from the caller ensure_signed(origin)?; let market = T::MarketCommons::market(&market_id)?; - ensure!( - market.status == MarketStatus::Disputed, - Error::::MarketIsNotDisputed - ); + ensure!(market.status == MarketStatus::Disputed, Error::::MarketIsNotDisputed); ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, Error::::MarketDoesNotHaveCourtMechanism @@ -427,7 +424,9 @@ mod pallet { // // Result is capped to `usize::MAX` or in other words, capped to a very, very, very // high number of jurors. - fn necessary_jurors_num(disputes: &[MarketDispute]) -> usize { + fn necessary_jurors_num( + disputes: &[MarketDispute>], + ) -> usize { let len = disputes.len(); INITIAL_JURORS_NUM.saturating_add(SUBSEQUENT_JURORS_FACTOR.saturating_mul(len)) } @@ -545,7 +544,7 @@ mod pallet { type Moment = MomentOf; type Origin = T::Origin; - fn on_dispute(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { + fn on_dispute(_: &Self::MarketId, market: &MarketOf) -> DispatchResult { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, Error::::MarketDoesNotHaveCourtMechanism diff --git a/zrml/court/src/tests.rs b/zrml/court/src/tests.rs index 5d74739ae..589434e98 100644 --- a/zrml/court/src/tests.rs +++ b/zrml/court/src/tests.rs @@ -52,7 +52,7 @@ const DEFAULT_MARKET: MarketOf = Market { resolved_outcome: None, status: MarketStatus::Disputed, scoring_rule: ScoringRule::CPMM, - bonds: MarketBonds { creation: None, oracle: None }, + bonds: MarketBonds { creation: None, oracle: None, dispute: None }, }; const DEFAULT_SET_OF_JURORS: &[(u128, Juror)] = &[ (7, Juror { status: JurorStatus::Ok }), diff --git a/zrml/market-commons/src/tests.rs b/zrml/market-commons/src/tests.rs index f54664819..02bd5d030 100644 --- a/zrml/market-commons/src/tests.rs +++ b/zrml/market-commons/src/tests.rs @@ -45,7 +45,7 @@ const MARKET_DUMMY: Market = Market resolved_outcome: None, scoring_rule: ScoringRule::CPMM, status: MarketStatus::Disputed, - bonds: MarketBonds { creation: None, oracle: None }, + bonds: MarketBonds { creation: None, oracle: None, dispute: None }, }; #[test] diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 52c0c6cf5..d479cfab0 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -58,9 +58,9 @@ mod pallet { constants::MILLISECS_PER_BLOCK, traits::{DisputeApi, DisputeResolutionApi, Swaps, ZeitgeistAssetManager}, types::{ - Asset, Bond, Deadlines, Market, MarketBonds, MarketCreation, MarketDispute, - MarketDisputeMechanism, MarketPeriod, MarketStatus, MarketType, MultiHash, - OutcomeReport, Report, ScalarPosition, ScoringRule, SubsidyUntil, + Asset, Bond, Deadlines, Market, MarketBonds, MarketCreation, MarketDisputeMechanism, + MarketPeriod, MarketStatus, MarketType, MultiHash, OldMarketDispute, OutcomeReport, + Report, ScalarPosition, ScoringRule, SubsidyUntil, }, }; #[cfg(feature = "with-global-disputes")] @@ -520,7 +520,7 @@ mod pallet { origin: OriginFor, #[pallet::compact] market_id: MarketIdOf, ) -> DispatchResultWithPostInfo { - ensure_signed(origin)?; + let who = ensure_signed(origin)?; let market = >::market(&market_id)?; ensure!(market.status == MarketStatus::Reported, Error::::InvalidMarketStatus); @@ -536,7 +536,15 @@ mod pallet { } } - Self::set_market_as_disputed(&market, &market_id)?; + let dispute_bond = T::DisputeBond::get(); + + T::AssetManager::reserve_named(&Self::reserve_id(), Asset::Ztg, &who, dispute_bond)?; + + >::mutate_market(&market_id, |m| { + m.status = MarketStatus::Disputed; + m.bonds.dispute = Some(Bond::new(who.clone(), dispute_bond)); + Ok(()) + })?; Self::deposit_event(Event::MarketDisputed(market_id, MarketStatus::Disputed)); @@ -650,10 +658,12 @@ mod pallet { MarketCreation::Advised => MarketBonds { creation: Some(Bond::new(sender.clone(), T::AdvisoryBond::get())), oracle: Some(Bond::new(sender.clone(), T::OracleBond::get())), + ..Default::default() }, MarketCreation::Permissionless => MarketBonds { creation: Some(Bond::new(sender.clone(), T::ValidityBond::get())), oracle: Some(Bond::new(sender.clone(), T::OracleBond::get())), + ..Default::default() }, }; @@ -1399,6 +1409,10 @@ mod pallet { /// The origin that is allowed to destroy markets. type DestroyOrigin: EnsureOrigin; + /// The base amount of currency that must be bonded in order to create a dispute. + #[pallet::constant] + type DisputeBond: Get>; + /// Event type Event: From> + IsType<::Event>; @@ -1793,7 +1807,7 @@ mod pallet { _, Blake2_128Concat, MarketIdOf, - BoundedVec, T::MaxDisputes>, + BoundedVec, T::MaxDisputes>, ValueQuery, >; @@ -1879,8 +1893,10 @@ mod pallet { impl Pallet { impl_unreserve_bond!(unreserve_creation_bond, creation); impl_unreserve_bond!(unreserve_oracle_bond, oracle); + impl_unreserve_bond!(unreserve_dispute_bond, dispute); impl_slash_bond!(slash_creation_bond, creation); impl_slash_bond!(slash_oracle_bond, oracle); + impl_slash_bond!(slash_dispute_bond, dispute); pub fn outcome_assets( market_id: MarketIdOf, @@ -2340,6 +2356,15 @@ mod pallet { // overall_imbalance.subsume(imbalance); } + if report.outcome != resolved_outcome { + // If the report outcome was wrong, the dispute was justified + Self::unreserve_dispute_bond(market_id)?; + } else { + // TODO what should be done with the DisputeBond imbalance? + let _imbalance = Self::slash_dispute_bond(market_id, None)?; + // overall_imbalance.subsume(imbalance); + } + Ok(resolved_outcome) } @@ -2621,20 +2646,6 @@ mod pallet { )) } - // If the market is already disputed, does nothing. - fn set_market_as_disputed( - market: &MarketOf, - market_id: &MarketIdOf, - ) -> DispatchResult { - if market.status != MarketStatus::Disputed { - >::mutate_market(market_id, |m| { - m.status = MarketStatus::Disputed; - Ok(()) - })?; - } - Ok(()) - } - // If a market has a pool that is `Active`, then changes from `Active` to `Clean`. If // the market does not exist or the market does not have a pool, does nothing. fn clean_up_pool( diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 618ebcf94..49aee5ec3 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -123,7 +123,7 @@ impl OnRuntimeUpgrade for RecordBonds::OracleBond::get(), is_settled: false, }), + dispute: None, }, ), construct_markets( @@ -334,6 +335,7 @@ mod tests { value: ::OracleBond::get(), is_settled: true, }), + dispute: None, }, ), construct_markets( @@ -350,6 +352,7 @@ mod tests { value: ::OracleBond::get(), is_settled: false, }), + dispute: None, }, ), construct_markets( @@ -366,6 +369,7 @@ mod tests { value: ::OracleBond::get(), is_settled: false, }), + dispute: None, }, ), construct_markets( @@ -382,6 +386,7 @@ mod tests { value: ::OracleBond::get(), is_settled: true, }), + dispute: None, }, ), // Technically, the market below has the wrong scoring rule, but that's irrelevant to @@ -400,6 +405,7 @@ mod tests { value: ::OracleBond::get(), is_settled: true, }), + dispute: None, }, ), ] diff --git a/zrml/prediction-markets/src/mock.rs b/zrml/prediction-markets/src/mock.rs index 4476b3eb8..516a9ee5c 100644 --- a/zrml/prediction-markets/src/mock.rs +++ b/zrml/prediction-markets/src/mock.rs @@ -36,13 +36,13 @@ use substrate_fixed::{types::extra::U33, FixedI128, FixedU128}; use zeitgeist_primitives::{ constants::mock::{ AuthorizedPalletId, BalanceFractionalDecimals, BlockHashCount, CorrectionPeriod, - CourtCaseDuration, CourtPalletId, DisputeFactor, ExistentialDeposit, ExistentialDeposits, - ExitFee, GetNativeCurrencyId, LiquidityMiningPalletId, MaxApprovals, MaxAssets, - MaxCategories, MaxDisputeDuration, MaxDisputes, MaxEditReasonLen, MaxGracePeriod, - MaxInRatio, MaxMarketPeriod, MaxOracleDuration, MaxOutRatio, MaxRejectReasonLen, - MaxReserves, MaxSubsidyPeriod, MaxSwapFee, MaxTotalWeight, MaxWeight, MinAssets, - MinCategories, MinDisputeDuration, MinLiquidity, MinOracleDuration, MinSubsidy, - MinSubsidyPeriod, MinWeight, MinimumPeriod, PmPalletId, SimpleDisputesPalletId, + CourtCaseDuration, CourtPalletId, ExistentialDeposit, ExistentialDeposits, ExitFee, + GetNativeCurrencyId, LiquidityMiningPalletId, MaxApprovals, MaxAssets, MaxCategories, + MaxDisputeDuration, MaxDisputes, MaxEditReasonLen, MaxGracePeriod, MaxInRatio, + MaxMarketPeriod, MaxOracleDuration, MaxOutRatio, MaxRejectReasonLen, MaxReserves, + MaxSubsidyPeriod, MaxSwapFee, MaxTotalWeight, MaxWeight, MinAssets, MinCategories, + MinDisputeDuration, MinLiquidity, MinOracleDuration, MinSubsidy, MinSubsidyPeriod, + MinWeight, MinimumPeriod, OutcomeBond, OutcomeFactor, PmPalletId, SimpleDisputesPalletId, StakeWeight, SwapsPalletId, TreasuryPalletId, BASE, CENT, MILLISECS_PER_BLOCK, }, types::{ @@ -142,6 +142,7 @@ impl crate::Config for Runtime { type CloseOrigin = EnsureSignedBy; type Court = Court; type DestroyOrigin = EnsureSignedBy; + type DisputeBond = DisputeBond; type Event = Event; #[cfg(feature = "with-global-disputes")] type GlobalDisputes = GlobalDisputes; @@ -305,8 +306,8 @@ impl zrml_rikiddo::Config for Runtime { impl zrml_simple_disputes::Config for Runtime { type AssetManager = AssetManager; type Event = Event; - type DisputeBond = DisputeBond; - type DisputeFactor = DisputeFactor; + type OutcomeBond = OutcomeBond; + type OutcomeFactor = OutcomeFactor; type DisputeResolution = prediction_markets::Pallet; #[cfg(feature = "with-global-disputes")] type GlobalDisputes = GlobalDisputes; @@ -458,7 +459,7 @@ mod tests { ); assert_ne!( ::AdvisoryBond::get(), - ::DisputeBond::get() + ::DisputeBond::get() ); assert_ne!( ::OracleBond::get(), @@ -466,11 +467,11 @@ mod tests { ); assert_ne!( ::OracleBond::get(), - ::DisputeBond::get() + ::DisputeBond::get() ); assert_ne!( ::ValidityBond::get(), - ::DisputeBond::get() + ::DisputeBond::get() ); } } diff --git a/zrml/prediction-markets/src/tests.rs b/zrml/prediction-markets/src/tests.rs index dff638bbc..b62e6cef4 100644 --- a/zrml/prediction-markets/src/tests.rs +++ b/zrml/prediction-markets/src/tests.rs @@ -34,7 +34,7 @@ use test_case::test_case; use orml_traits::MultiCurrency; use sp_runtime::traits::{AccountIdConversion, SaturatedConversion, Zero}; use zeitgeist_primitives::{ - constants::mock::{DisputeFactor, BASE, CENT, MILLISECS_PER_BLOCK}, + constants::mock::{OutcomeFactor, BASE, CENT, MILLISECS_PER_BLOCK}, traits::Swaps as SwapsPalletApi, types::{ AccountIdTest, Asset, Balance, BlockNumber, Bond, Deadlines, Market, MarketBonds, @@ -3941,6 +3941,7 @@ fn report_fails_if_reporter_is_not_the_oracle() { MarketBonds { creation: Some(Bond::new(ALICE, ::AdvisoryBond::get())), oracle: Some(Bond::new(ALICE, ::OracleBond::get())), + dispute: None, } )] #[test_case( @@ -3950,6 +3951,7 @@ fn report_fails_if_reporter_is_not_the_oracle() { MarketBonds { creation: Some(Bond::new(ALICE, ::ValidityBond::get())), oracle: Some(Bond::new(ALICE, ::OracleBond::get())), + dispute: None, } )] fn create_market_sets_the_correct_market_parameters_and_reserves_the_correct_amount( diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index b49cbc4d9..bbd7b9b55 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -74,7 +74,7 @@ mod pallet { /// The base amount of currency that must be bonded in order to create a dispute. #[pallet::constant] - type DisputeBond: Get>; + type OutcomeBond: Get>; type DisputeResolution: DisputeResolutionApi< AccountId = Self::AccountId, @@ -86,7 +86,7 @@ mod pallet { /// The additional amount of currency that must be bonded when creating a subsequent /// dispute. #[pallet::constant] - type DisputeFactor: Get>; + type OutcomeFactor: Get>; /// See [`GlobalDisputesPalletApi`]. #[cfg(feature = "with-global-disputes")] @@ -145,7 +145,7 @@ mod pallet { _, Blake2_128Concat, MarketIdOf, - BoundedVec, T::MaxDisputes>, + BoundedVec>, T::MaxDisputes>, ValueQuery, >; @@ -157,7 +157,7 @@ mod pallet { { OutcomeReserved { market_id: MarketIdOf, - dispute: MarketDispute, + dispute: MarketDispute>, }, } @@ -204,14 +204,11 @@ mod pallet { Self::ensure_can_not_dispute_the_same_outcome(&disputes, report, &outcome)?; Self::ensure_disputes_does_not_exceed_max_disputes(num_disputes)?; - T::AssetManager::reserve_named( - &Self::reserve_id(), - Asset::Ztg, - &who, - default_dispute_bond::(disputes.len()), - )?; + let bond = default_outcome_bond::(disputes.len()); - let market_dispute = MarketDispute { at: now, by: who, outcome }; + T::AssetManager::reserve_named(&Self::reserve_id(), Asset::Ztg, &who, bond)?; + + let market_dispute = MarketDispute { at: now, by: who, outcome, bond }; >::try_mutate(market_id, |disputes| { disputes.try_push(market_dispute.clone()).map_err(|_| >::StorageOverflow) })?; @@ -235,7 +232,7 @@ mod pallet { } fn ensure_can_not_dispute_the_same_outcome( - disputes: &[MarketDispute], + disputes: &[MarketDispute>], report: &Report, outcome: &OutcomeReport, ) -> DispatchResult { @@ -255,7 +252,7 @@ mod pallet { } fn get_auto_resolve( - disputes: &[MarketDispute], + disputes: &[MarketDispute>], market: &MarketOf, ) -> Option { disputes.last().map(|last_dispute| { @@ -264,7 +261,7 @@ mod pallet { } fn remove_auto_resolve( - disputes: &[MarketDispute], + disputes: &[MarketDispute>], market_id: &MarketIdOf, market: &MarketOf, ) { @@ -320,14 +317,13 @@ mod pallet { let mut overall_imbalance = NegativeImbalanceOf::::zero(); - for (i, dispute) in disputes.iter().enumerate() { - let actual_bond = default_dispute_bond::(i); + for dispute in disputes.iter() { if dispute.outcome == resolved_outcome { T::AssetManager::unreserve_named( &Self::reserve_id(), Asset::Ztg, &dispute.by, - actual_bond, + dispute.bond.saturated_into::().saturated_into(), ); correct_reporters.push(dispute.by.clone()); @@ -335,7 +331,7 @@ mod pallet { let (imbalance, _) = CurrencyOf::::slash_reserved_named( &Self::reserve_id(), &dispute.by, - actual_bond.saturated_into::().saturated_into(), + dispute.bond.saturated_into::().saturated_into(), ); overall_imbalance.subsume(imbalance); } @@ -406,14 +402,8 @@ mod pallet { )?; } - for (index, MarketDispute { at: _, by, outcome }) in disputes.iter().enumerate() { - let dispute_bond = default_dispute_bond::(index); - T::GlobalDisputes::push_voting_outcome( - market_id, - outcome.clone(), - by, - dispute_bond, - )?; + for MarketDispute { at: _, by, outcome, bond } in disputes.iter() { + T::GlobalDisputes::push_voting_outcome(market_id, outcome.clone(), by, bond)?; } } Ok(()) @@ -427,12 +417,12 @@ mod pallet { // `Disputes` is emtpy unless the market is disputed, so this is just a defensive // check. if market.status == MarketStatus::Disputed { - for (index, dispute) in Disputes::::take(market_id).iter().enumerate() { + for dispute in Disputes::::take(market_id).iter() { T::AssetManager::unreserve_named( &Self::reserve_id(), Asset::Ztg, &dispute.by, - default_dispute_bond::(index), + dispute.bond.saturated_into::().saturated_into(), ); } } @@ -443,12 +433,12 @@ mod pallet { impl SimpleDisputesPalletApi for Pallet where T: Config {} // No-one can bound more than BalanceOf, therefore, this functions saturates - pub fn default_dispute_bond(n: usize) -> BalanceOf + pub fn default_outcome_bond(n: usize) -> BalanceOf where T: Config, { - T::DisputeBond::get().saturating_add( - T::DisputeFactor::get().saturating_mul(n.saturated_into::().into()), + T::OutcomeBond::get().saturating_add( + T::OutcomeFactor::get().saturating_mul(n.saturated_into::().into()), ) } } diff --git a/zrml/simple-disputes/src/mock.rs b/zrml/simple-disputes/src/mock.rs index 59ba06cb3..971039f95 100644 --- a/zrml/simple-disputes/src/mock.rs +++ b/zrml/simple-disputes/src/mock.rs @@ -30,7 +30,7 @@ use sp_runtime::{ }; use zeitgeist_primitives::{ constants::mock::{ - BlockHashCount, DisputeBond, DisputeFactor, ExistentialDeposits, GetNativeCurrencyId, + BlockHashCount, OutcomeBond, OutcomeFactor, ExistentialDeposits, GetNativeCurrencyId, MaxApprovals, MaxDisputes, MaxReserves, MinimumPeriod, PmPalletId, SimpleDisputesPalletId, TreasuryPalletId, }, @@ -129,8 +129,8 @@ impl DisputeResolutionApi for NoopResolution { impl crate::Config for Runtime { type AssetManager = AssetManager; type Event = (); - type DisputeBond = DisputeBond; - type DisputeFactor = DisputeFactor; + type OutcomeBond = OutcomeBond; + type OutcomeFactor = OutcomeFactor; type DisputeResolution = NoopResolution; #[cfg(feature = "with-global-disputes")] type GlobalDisputes = GlobalDisputes; diff --git a/zrml/simple-disputes/src/tests.rs b/zrml/simple-disputes/src/tests.rs index a62d21549..c479f84ee 100644 --- a/zrml/simple-disputes/src/tests.rs +++ b/zrml/simple-disputes/src/tests.rs @@ -23,6 +23,7 @@ use crate::{ }; use frame_support::{assert_noop, BoundedVec}; use zeitgeist_primitives::{ + constants::mock::{OutcomeBond, OutcomeFactor}, traits::DisputeApi, types::{ Deadlines, Market, MarketBonds, MarketCreation, MarketDispute, MarketDisputeMechanism, @@ -44,7 +45,7 @@ const DEFAULT_MARKET: MarketOf = Market { resolved_outcome: None, scoring_rule: ScoringRule::CPMM, status: MarketStatus::Disputed, - bonds: MarketBonds { creation: None, oracle: None }, + bonds: MarketBonds { creation: None, oracle: None, dispute: None }, }; #[test] @@ -78,8 +79,18 @@ fn on_resolution_sets_the_last_dispute_of_disputed_markets_as_the_canonical_outc market.status = MarketStatus::Disputed; let disputes = BoundedVec::try_from( [ - MarketDispute { at: 0, by: 0, outcome: OutcomeReport::Scalar(0) }, - MarketDispute { at: 0, by: 0, outcome: OutcomeReport::Scalar(20) }, + MarketDispute { + at: 0, + by: 0, + outcome: OutcomeReport::Scalar(0), + bond: OutcomeBond::get(), + }, + MarketDispute { + at: 0, + by: 0, + outcome: OutcomeReport::Scalar(20), + bond: OutcomeFactor::get() * OutcomeBond::get(), + }, ] .to_vec(), ) From 9448ab9cf29902028faaa2a35260ad233db66e9f Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Mon, 16 Jan 2023 18:30:05 +0100 Subject: [PATCH 11/58] mdm funds flow --- primitives/src/traits/dispute_api.rs | 15 ++++++- runtime/common/src/lib.rs | 1 - runtime/zeitgeist/src/parameters.rs | 2 +- zrml/authorized/src/lib.rs | 19 +++++++- zrml/authorized/src/tests.rs | 15 ++++--- zrml/court/src/lib.rs | 19 +++++++- zrml/court/src/tests.rs | 28 ++++++------ zrml/prediction-markets/src/lib.rs | 67 +++++++++++++++++++++++----- zrml/prediction-markets/src/mock.rs | 6 +-- zrml/prediction-markets/src/tests.rs | 40 +++++++++-------- zrml/simple-disputes/src/lib.rs | 33 +++++++++----- zrml/simple-disputes/src/mock.rs | 5 +-- zrml/simple-disputes/src/tests.rs | 8 ++-- 13 files changed, 179 insertions(+), 79 deletions(-) diff --git a/primitives/src/traits/dispute_api.rs b/primitives/src/traits/dispute_api.rs index d415be8d3..b7e576cd5 100644 --- a/primitives/src/traits/dispute_api.rs +++ b/primitives/src/traits/dispute_api.rs @@ -31,6 +31,7 @@ type MarketOfDisputeApi = Market< pub trait DisputeApi { type AccountId; type Balance; + type NegativeImbalance; type BlockNumber; type MarketId; type Moment; @@ -51,11 +52,23 @@ pub trait DisputeApi { /// /// Returns the dispute mechanism's report if available, otherwise `None`. If `None` is /// returned, this means that the dispute could not be resolved. - fn on_resolution( + fn get_resolution_outcome( market_id: &Self::MarketId, market: &MarketOfDisputeApi, ) -> Result, DispatchError>; + /// Allow the flow of funds to the market dispute mechanism. + /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. + /// + /// # Returns + /// Returns the negative imbalance which is meant to be used for the treasury. + fn maybe_pay( + market_id: &Self::MarketId, + market: &MarketOfDisputeApi, + resolved_outcome: &OutcomeReport, + overall_imbalance: Self::NegativeImbalance, + ) -> Result; + /// Query the future resolution block of a disputed market. /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. /// diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index d52f9189d..2d308a866 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -1052,7 +1052,6 @@ macro_rules! impl_config_traits { type MaxDisputes = MaxDisputes; type PalletId = SimpleDisputesPalletId; type PredictionMarketsPalletId = PmPalletId; - type Slash = Treasury; type WeightInfo = zrml_simple_disputes::weights::WeightInfo; } diff --git a/runtime/zeitgeist/src/parameters.rs b/runtime/zeitgeist/src/parameters.rs index acda8068d..3aa2a2cc2 100644 --- a/runtime/zeitgeist/src/parameters.rs +++ b/runtime/zeitgeist/src/parameters.rs @@ -151,7 +151,7 @@ parameter_types! { /// (Slashable) Bond that is provided for disputing the outcome. /// Unreserved in case the dispute was justified otherwise slashed. /// This is when the resolved outcome is different to the default (reported) outcome. - pub const DisputeBond: Balance = 5_000 * BASE; + pub const DisputeBond: Balance = 2_000 * BASE; /// Maximum Categories a prediciton market can have (excluding base asset). pub const MaxCategories: u16 = MAX_CATEGORIES; /// Maximum number of disputes. diff --git a/zrml/authorized/src/lib.rs b/zrml/authorized/src/lib.rs index 35e742264..00bcfd7c0 100644 --- a/zrml/authorized/src/lib.rs +++ b/zrml/authorized/src/lib.rs @@ -57,6 +57,8 @@ mod pallet { as Currency<::AccountId>>::Balance; pub(crate) type CurrencyOf = <::MarketCommons as MarketCommonsPalletApi>::Currency; + pub(crate) type NegativeImbalanceOf = + as Currency<::AccountId>>::NegativeImbalance; pub(crate) type MarketIdOf = <::MarketCommons as MarketCommonsPalletApi>::MarketId; pub(crate) type MomentOf = <::MarketCommons as MarketCommonsPalletApi>::Moment; @@ -195,6 +197,7 @@ mod pallet { { type AccountId = T::AccountId; type Balance = BalanceOf; + type NegativeImbalance = NegativeImbalanceOf; type BlockNumber = T::BlockNumber; type MarketId = MarketIdOf; type Moment = MomentOf; @@ -208,7 +211,7 @@ mod pallet { Ok(()) } - fn on_resolution( + fn get_resolution_outcome( market_id: &Self::MarketId, market: &MarketOf, ) -> Result, DispatchError> { @@ -220,6 +223,20 @@ mod pallet { Ok(report.map(|r| r.outcome)) } + fn maybe_pay( + _: &Self::MarketId, + market: &MarketOf, + _: &OutcomeReport, + overall_imbalance: NegativeImbalanceOf, + ) -> Result, DispatchError> { + ensure!( + market.dispute_mechanism == MarketDisputeMechanism::Authorized, + Error::::MarketDoesNotHaveDisputeMechanismAuthorized + ); + // all funds to treasury + Ok(overall_imbalance) + } + fn get_auto_resolve( market_id: &Self::MarketId, market: &MarketOf, diff --git a/zrml/authorized/src/tests.rs b/zrml/authorized/src/tests.rs index 4c5550000..a49095014 100644 --- a/zrml/authorized/src/tests.rs +++ b/zrml/authorized/src/tests.rs @@ -157,15 +157,15 @@ fn authorize_market_outcome_fails_on_unauthorized_account() { } #[test] -fn on_resolution_fails_if_no_report_was_submitted() { +fn get_resolution_outcome_fails_if_no_report_was_submitted() { ExtBuilder::default().build().execute_with(|| { - let report = Authorized::on_resolution(&0, &market_mock::()).unwrap(); + let report = Authorized::get_resolution_outcome(&0, &market_mock::()).unwrap(); assert!(report.is_none()); }); } #[test] -fn on_resolution_removes_stored_outcomes() { +fn get_resolution_outcome_removes_stored_outcomes() { ExtBuilder::default().build().execute_with(|| { let market = market_mock::(); Markets::::insert(0, &market); @@ -174,13 +174,13 @@ fn on_resolution_removes_stored_outcomes() { 0, OutcomeReport::Scalar(2) )); - assert_ok!(Authorized::on_resolution(&0, &market)); + assert_ok!(Authorized::get_resolution_outcome(&0, &market)); assert_eq!(AuthorizedOutcomeReports::::get(0), None); }); } #[test] -fn on_resolution_returns_the_reported_outcome() { +fn get_resolution_outcome_returns_the_reported_outcome() { ExtBuilder::default().build().execute_with(|| { let market = market_mock::(); Markets::::insert(0, &market); @@ -195,7 +195,10 @@ fn on_resolution_returns_the_reported_outcome() { 0, OutcomeReport::Scalar(2) )); - assert_eq!(Authorized::on_resolution(&0, &market).unwrap(), Some(OutcomeReport::Scalar(2))); + assert_eq!( + Authorized::get_resolution_outcome(&0, &market).unwrap(), + Some(OutcomeReport::Scalar(2)) + ); }); } diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index d67b3790e..1491481a4 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -86,6 +86,8 @@ mod pallet { as Currency<::AccountId>>::Balance; pub(crate) type CurrencyOf = <::MarketCommons as MarketCommonsPalletApi>::Currency; + pub(crate) type NegativeImbalanceOf = + as Currency<::AccountId>>::NegativeImbalance; pub(crate) type MarketIdOf = <::MarketCommons as MarketCommonsPalletApi>::MarketId; pub(crate) type MomentOf = <::MarketCommons as MarketCommonsPalletApi>::Moment; @@ -539,6 +541,7 @@ mod pallet { { type AccountId = T::AccountId; type Balance = BalanceOf; + type NegativeImbalance = NegativeImbalanceOf; type BlockNumber = T::BlockNumber; type MarketId = MarketIdOf; type Moment = MomentOf; @@ -557,7 +560,7 @@ mod pallet { // rewarded if sided on the most voted outcome but jurors that voted second most // voted outcome (winner of the losing majority) are placed as tardy instead of // being slashed. - fn on_resolution( + fn get_resolution_outcome( market_id: &Self::MarketId, market: &MarketOf, ) -> Result, DispatchError> { @@ -585,6 +588,20 @@ mod pallet { Ok(Some(first)) } + fn maybe_pay( + _: &Self::MarketId, + market: &MarketOf, + _: &OutcomeReport, + overall_imbalance: NegativeImbalanceOf, + ) -> Result, DispatchError> { + ensure!( + market.dispute_mechanism == MarketDisputeMechanism::Court, + Error::::MarketDoesNotHaveCourtMechanism + ); + // TODO all funds to treasury? + Ok(overall_imbalance) + } + fn get_auto_resolve( _: &Self::MarketId, market: &MarketOf, diff --git a/zrml/court/src/tests.rs b/zrml/court/src/tests.rs index 589434e98..dcdfac4e0 100644 --- a/zrml/court/src/tests.rs +++ b/zrml/court/src/tests.rs @@ -138,12 +138,12 @@ fn on_dispute_denies_non_court_markets() { } #[test] -fn on_resolution_denies_non_court_markets() { +fn get_resolution_outcome_denies_non_court_markets() { ExtBuilder::default().build().execute_with(|| { let mut market = DEFAULT_MARKET; market.dispute_mechanism = MarketDisputeMechanism::SimpleDisputes; assert_noop!( - Court::on_resolution(&0, &market), + Court::get_resolution_outcome(&0, &market), Error::::MarketDoesNotHaveCourtMechanism ); }); @@ -167,7 +167,7 @@ fn appeal_stores_jurors_that_should_vote() { // Alice is the winner, Bob is tardy and Charlie is the loser #[test] -fn on_resolution_awards_winners_and_slashes_losers() { +fn get_resolution_outcome_awards_winners_and_slashes_losers() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); Court::join_court(Origin::signed(ALICE)).unwrap(); @@ -178,7 +178,7 @@ fn on_resolution_awards_winners_and_slashes_losers() { Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(2)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(3)).unwrap(); - let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); + let _ = Court::get_resolution_outcome(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(Balances::free_balance(ALICE), 998 * BASE + 3 * BASE); assert_eq!(Balances::reserved_balance_named(&Court::reserve_id(), &ALICE), 2 * BASE); assert_eq!(Balances::free_balance(BOB), 996 * BASE); @@ -189,7 +189,7 @@ fn on_resolution_awards_winners_and_slashes_losers() { } #[test] -fn on_resolution_decides_market_outcome_based_on_the_majority() { +fn get_resolution_outcome_decides_market_outcome_based_on_the_majority() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); Court::join_court(Origin::signed(ALICE)).unwrap(); @@ -200,13 +200,13 @@ fn on_resolution_decides_market_outcome_based_on_the_majority() { Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); - let outcome = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); + let outcome = Court::get_resolution_outcome(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(outcome, Some(OutcomeReport::Scalar(1))); }); } #[test] -fn on_resolution_sets_late_jurors_as_tardy() { +fn get_resolution_outcome_sets_late_jurors_as_tardy() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); Court::join_court(Origin::signed(ALICE)).unwrap(); @@ -214,14 +214,14 @@ fn on_resolution_sets_late_jurors_as_tardy() { Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); Court::appeal(Origin::signed(ALICE), 0).unwrap(); - let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); + let _ = Court::get_resolution_outcome(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(Jurors::::get(ALICE).unwrap().status, JurorStatus::Ok); assert_eq!(Jurors::::get(BOB).unwrap().status, JurorStatus::Tardy); }); } #[test] -fn on_resolution_sets_jurors_that_voted_on_the_second_most_voted_outcome_as_tardy() { +fn get_resolution_outcome_sets_jurors_that_voted_on_the_second_most_voted_outcome_as_tardy() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); Court::join_court(Origin::signed(ALICE)).unwrap(); @@ -232,13 +232,13 @@ fn on_resolution_sets_jurors_that_voted_on_the_second_most_voted_outcome_as_tard Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); - let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); + let _ = Court::get_resolution_outcome(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(Jurors::::get(CHARLIE).unwrap().status, JurorStatus::Tardy); }); } #[test] -fn on_resolution_punishes_tardy_jurors_that_failed_to_vote_a_second_time() { +fn get_resolution_outcome_punishes_tardy_jurors_that_failed_to_vote_a_second_time() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); Court::join_court(Origin::signed(ALICE)).unwrap(); @@ -247,7 +247,7 @@ fn on_resolution_punishes_tardy_jurors_that_failed_to_vote_a_second_time() { Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); Court::appeal(Origin::signed(ALICE), 0).unwrap(); - let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); + let _ = Court::get_resolution_outcome(&0, &DEFAULT_MARKET).unwrap(); let join_court_stake = 40000000000; let slash = join_court_stake / 5; assert_eq!(Balances::free_balance(Court::treasury_account_id()), INITIAL_BALANCE + slash); @@ -257,7 +257,7 @@ fn on_resolution_punishes_tardy_jurors_that_failed_to_vote_a_second_time() { } #[test] -fn on_resolution_removes_requested_jurors_and_votes() { +fn get_resolution_outcome_removes_requested_jurors_and_votes() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); Court::join_court(Origin::signed(ALICE)).unwrap(); @@ -268,7 +268,7 @@ fn on_resolution_removes_requested_jurors_and_votes() { Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); - let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); + let _ = Court::get_resolution_outcome(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(RequestedJurors::::iter().count(), 0); assert_eq!(Votes::::iter().count(), 0); }); diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index d479cfab0..5285e2f0c 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -238,6 +238,11 @@ mod pallet { Self::slash_oracle_bond(&market_id, None)?; } } + if let Some(bond) = market.bonds.dispute { + if !bond.is_settled { + Self::unreserve_dispute_bond(&market_id)?; + } + } if market_status == MarketStatus::Proposed { MarketIdsForEdit::::remove(market_id); @@ -1387,6 +1392,7 @@ mod pallet { type Authorized: zrml_authorized::AuthorizedPalletApi< AccountId = Self::AccountId, Balance = BalanceOf, + NegativeImbalance = NegativeImbalanceOf, BlockNumber = Self::BlockNumber, MarketId = MarketIdOf, Moment = MomentOf, @@ -1400,6 +1406,7 @@ mod pallet { type Court: zrml_court::CourtPalletApi< AccountId = Self::AccountId, Balance = BalanceOf, + NegativeImbalance = NegativeImbalanceOf, BlockNumber = Self::BlockNumber, MarketId = MarketIdOf, Moment = MomentOf, @@ -1513,6 +1520,7 @@ mod pallet { type SimpleDisputes: DisputeApi< AccountId = Self::AccountId, Balance = BalanceOf, + NegativeImbalance = NegativeImbalanceOf, BlockNumber = Self::BlockNumber, MarketId = MarketIdOf, Moment = MomentOf, @@ -2334,11 +2342,13 @@ mod pallet { if resolved_outcome_option.is_none() { resolved_outcome_option = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { - T::Authorized::on_resolution(market_id, market)? + T::Authorized::get_resolution_outcome(market_id, market)? + } + MarketDisputeMechanism::Court => { + T::Court::get_resolution_outcome(market_id, market)? } - MarketDisputeMechanism::Court => T::Court::on_resolution(market_id, market)?, MarketDisputeMechanism::SimpleDisputes => { - T::SimpleDisputes::on_resolution(market_id, market)? + T::SimpleDisputes::get_resolution_outcome(market_id, market)? } }; } @@ -2346,25 +2356,58 @@ mod pallet { let resolved_outcome = resolved_outcome_option.unwrap_or_else(|| report.outcome.clone()); + let mut overall_imbalance = >::zero(); + // If the oracle reported right, return the OracleBond, otherwise slash it to // pay the correct reporters. if report.by == market.oracle && report.outcome == resolved_outcome { Self::unreserve_oracle_bond(market_id)?; } else { - let _imbalance = Self::slash_oracle_bond(market_id, None)?; - // TODO what should be done with the OracleBond imbalance? - // overall_imbalance.subsume(imbalance); + let imb = Self::slash_oracle_bond(market_id, None)?; + overall_imbalance.subsume(imb); + } + + let mut correct_disputor = None; + if let Some(bond) = market.bonds.dispute.clone() { + if !bond.is_settled { + if report.outcome != resolved_outcome { + // If the report outcome was wrong, the dispute was justified + Self::unreserve_dispute_bond(market_id)?; + correct_disputor = Some(bond.who); + } else { + let imb = Self::slash_dispute_bond(market_id, None)?; + overall_imbalance.subsume(imb); + } + } } - if report.outcome != resolved_outcome { - // If the report outcome was wrong, the dispute was justified - Self::unreserve_dispute_bond(market_id)?; + let mut imbalance_left = >::zero(); + if let Some(disputor) = correct_disputor { + CurrencyOf::::resolve_creating(&disputor, overall_imbalance); } else { - // TODO what should be done with the DisputeBond imbalance? - let _imbalance = Self::slash_dispute_bond(market_id, None)?; - // overall_imbalance.subsume(imbalance); + imbalance_left = overall_imbalance; } + let remainder = match market.dispute_mechanism { + MarketDisputeMechanism::Authorized => T::Authorized::maybe_pay( + market_id, + market, + &resolved_outcome, + imbalance_left, + )?, + MarketDisputeMechanism::Court => { + T::Court::maybe_pay(market_id, market, &resolved_outcome, imbalance_left)? + } + MarketDisputeMechanism::SimpleDisputes => T::SimpleDisputes::maybe_pay( + market_id, + market, + &resolved_outcome, + imbalance_left, + )?, + }; + + T::Slash::on_unbalanced(remainder); + Ok(resolved_outcome) } diff --git a/zrml/prediction-markets/src/mock.rs b/zrml/prediction-markets/src/mock.rs index 516a9ee5c..a209d8b49 100644 --- a/zrml/prediction-markets/src/mock.rs +++ b/zrml/prediction-markets/src/mock.rs @@ -315,7 +315,6 @@ impl zrml_simple_disputes::Config for Runtime { type MaxDisputes = MaxDisputes; type PalletId = SimpleDisputesPalletId; type PredictionMarketsPalletId = PmPalletId; - type Slash = Treasury; type WeightInfo = zrml_simple_disputes::weights::WeightInfo; } @@ -465,10 +464,7 @@ mod tests { ::OracleBond::get(), ::ValidityBond::get() ); - assert_ne!( - ::OracleBond::get(), - ::DisputeBond::get() - ); + assert_ne!(::OracleBond::get(), ::DisputeBond::get()); assert_ne!( ::ValidityBond::get(), ::DisputeBond::get() diff --git a/zrml/prediction-markets/src/tests.rs b/zrml/prediction-markets/src/tests.rs index b62e6cef4..5e11adaf5 100644 --- a/zrml/prediction-markets/src/tests.rs +++ b/zrml/prediction-markets/src/tests.rs @@ -19,9 +19,8 @@ #![allow(clippy::reversed_empty_ranges)] use crate::{ - mock::*, Config, Disputes, Error, Event, LastTimeFrame, MarketIdsForEdit, - MarketIdsPerCloseBlock, MarketIdsPerDisputeBlock, MarketIdsPerOpenBlock, - MarketIdsPerReportBlock, + mock::*, Config, Error, Event, LastTimeFrame, MarketIdsForEdit, MarketIdsPerCloseBlock, + MarketIdsPerDisputeBlock, MarketIdsPerOpenBlock, MarketIdsPerReportBlock, }; use core::ops::{Range, RangeInclusive}; use frame_support::{ @@ -34,7 +33,7 @@ use test_case::test_case; use orml_traits::MultiCurrency; use sp_runtime::traits::{AccountIdConversion, SaturatedConversion, Zero}; use zeitgeist_primitives::{ - constants::mock::{OutcomeFactor, BASE, CENT, MILLISECS_PER_BLOCK}, + constants::mock::{OutcomeBond, OutcomeFactor, BASE, CENT, MILLISECS_PER_BLOCK}, traits::Swaps as SwapsPalletApi, types::{ AccountIdTest, Asset, Balance, BlockNumber, Bond, Deadlines, Market, MarketBonds, @@ -475,13 +474,15 @@ fn admin_destroy_market_correctly_unreserves_dispute_bonds() { ); assert_eq!( Balances::free_balance(CHARLIE), - balance_free_before_charlie + zrml_simple_disputes::default_dispute_bond::(0) + balance_free_before_charlie + + DisputeBond::get() + + zrml_simple_disputes::default_outcome_bond::(0) ); assert_eq!( Balances::free_balance(DAVE), - balance_free_before_dave + zrml_simple_disputes::default_dispute_bond::(1), + balance_free_before_dave + zrml_simple_disputes::default_outcome_bond::(1), ); - assert!(Disputes::::get(market_id).is_empty()); + assert!(zrml_simple_disputes::Disputes::::get(market_id).is_empty()); }); } @@ -2214,6 +2215,12 @@ fn it_resolves_a_disputed_market() { assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); + let market = MarketCommons::market(&0).unwrap(); + assert_eq!(market.status, MarketStatus::Disputed); + + let charlie_reserved = Balances::reserved_balance(&CHARLIE); + assert_eq!(charlie_reserved, DisputeBond::get()); + let dispute_at_0 = report_at + 1; run_to_block(dispute_at_0); @@ -2246,13 +2253,13 @@ fn it_resolves_a_disputed_market() { // check everyone's deposits let charlie_reserved = Balances::reserved_balance(&CHARLIE); - assert_eq!(charlie_reserved, DisputeBond::get()); + assert_eq!(charlie_reserved, DisputeBond::get() + OutcomeBond::get()); let dave_reserved = Balances::reserved_balance(&DAVE); - assert_eq!(dave_reserved, DisputeBond::get() + DisputeFactor::get()); + assert_eq!(dave_reserved, OutcomeBond::get() + OutcomeFactor::get()); let eve_reserved = Balances::reserved_balance(&EVE); - assert_eq!(eve_reserved, DisputeBond::get() + 2 * DisputeFactor::get()); + assert_eq!(eve_reserved, OutcomeBond::get() + 2 * OutcomeFactor::get()); // check disputes length let disputes = zrml_simple_disputes::Disputes::::get(0); @@ -2286,12 +2293,12 @@ fn it_resolves_a_disputed_market() { // Make sure rewards are right: // // Slashed amounts: - // - Dave's reserve: DisputeBond::get() + DisputeFactor::get() + // - Dave's reserve: OutcomeBond::get() + OutcomeFactor::get() // - Alice's oracle bond: OracleBond::get() - // Total: OracleBond::get() + DisputeBond::get() + DisputeFactor::get() + // Total: OracleBond::get() + OutcomeBond::get() + OutcomeFactor::get() // // Charlie and Eve each receive half of the total slashed amount as bounty. - let dave_reserved = DisputeBond::get() + DisputeFactor::get(); + let dave_reserved = OutcomeBond::get() + OutcomeFactor::get(); let total_slashed = OracleBond::get() + dave_reserved; let charlie_balance = Balances::free_balance(&CHARLIE); @@ -2314,6 +2321,7 @@ fn it_resolves_a_disputed_market() { assert!(market_after.bonds.creation.unwrap().is_settled); assert!(market_after.bonds.oracle.unwrap().is_settled); + assert!(market_after.bonds.dispute.unwrap().is_settled); }); } @@ -3075,10 +3083,6 @@ fn authorized_correctly_resolves_disputed_market() { let charlie_reserved = Balances::reserved_balance(&CHARLIE); assert_eq!(charlie_reserved, DisputeBond::get()); - // check disputes length - let disputes = crate::Disputes::::get(0); - assert_eq!(disputes.len(), 1); - let market_ids_1 = MarketIdsPerDisputeBlock::::get( dispute_at + ::CorrectionPeriod::get(), ); @@ -3102,7 +3106,7 @@ fn authorized_correctly_resolves_disputed_market() { let market_after = MarketCommons::market(&0).unwrap(); assert_eq!(market_after.status, MarketStatus::Resolved); - let disputes = crate::Disputes::::get(0); + let disputes = zrml_simple_disputes::Disputes::::get(0); assert_eq!(disputes.len(), 0); assert_ok!(PredictionMarkets::redeem_shares(Origin::signed(CHARLIE), 0)); diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index bbd7b9b55..0bc3ec216 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -37,7 +37,7 @@ mod pallet { dispatch::DispatchResult, ensure, pallet_prelude::{Blake2_128Concat, DispatchResultWithPostInfo, StorageMap, ValueQuery}, - traits::{Currency, Get, Hooks, Imbalance, IsType, NamedReservableCurrency, OnUnbalanced}, + traits::{Currency, Get, Hooks, Imbalance, IsType, NamedReservableCurrency}, transactional, BoundedVec, PalletId, }; use frame_system::pallet_prelude::*; @@ -113,9 +113,6 @@ mod pallet { #[pallet::constant] type PredictionMarketsPalletId: Get; - /// Handler for slashed funds. - type Slash: OnUnbalanced>; - /// Weights generated by benchmarks type WeightInfo: WeightInfoZeitgeist; } @@ -280,6 +277,7 @@ mod pallet { { type AccountId = T::AccountId; type Balance = BalanceOf; + type NegativeImbalance = NegativeImbalanceOf; type BlockNumber = T::BlockNumber; type MarketId = MarketIdOf; type Moment = MomentOf; @@ -293,7 +291,7 @@ mod pallet { Ok(()) } - fn on_resolution( + fn get_resolution_outcome( market_id: &Self::MarketId, market: &MarketOf, ) -> Result, DispatchError> { @@ -311,14 +309,27 @@ mod pallet { None => return Ok(None), }; - let resolved_outcome = last_dispute.outcome.clone(); + Ok(Some(last_dispute.outcome.clone())) + } - let mut correct_reporters: Vec = Vec::new(); + fn maybe_pay( + market_id: &Self::MarketId, + market: &MarketOf, + resolved_outcome: &OutcomeReport, + mut overall_imbalance: NegativeImbalanceOf, + ) -> Result, DispatchError> { + ensure!( + market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, + Error::::MarketDoesNotHaveSimpleDisputesMechanism + ); + ensure!(market.status == MarketStatus::Disputed, Error::::InvalidMarketStatus); - let mut overall_imbalance = NegativeImbalanceOf::::zero(); + let disputes = Disputes::::get(market_id); + + let mut correct_reporters: Vec = Vec::new(); for dispute in disputes.iter() { - if dispute.outcome == resolved_outcome { + if &dispute.outcome == resolved_outcome { T::AssetManager::unreserve_named( &Self::reserve_id(), Asset::Ztg, @@ -350,11 +361,9 @@ mod pallet { } } - T::Slash::on_unbalanced(overall_imbalance); - Disputes::::remove(market_id); - Ok(Some(resolved_outcome)) + Ok(overall_imbalance) } fn get_auto_resolve( diff --git a/zrml/simple-disputes/src/mock.rs b/zrml/simple-disputes/src/mock.rs index 971039f95..e9872c558 100644 --- a/zrml/simple-disputes/src/mock.rs +++ b/zrml/simple-disputes/src/mock.rs @@ -30,8 +30,8 @@ use sp_runtime::{ }; use zeitgeist_primitives::{ constants::mock::{ - BlockHashCount, OutcomeBond, OutcomeFactor, ExistentialDeposits, GetNativeCurrencyId, - MaxApprovals, MaxDisputes, MaxReserves, MinimumPeriod, PmPalletId, SimpleDisputesPalletId, + BlockHashCount, ExistentialDeposits, GetNativeCurrencyId, MaxApprovals, MaxDisputes, + MaxReserves, MinimumPeriod, OutcomeBond, OutcomeFactor, PmPalletId, SimpleDisputesPalletId, TreasuryPalletId, }, traits::DisputeResolutionApi, @@ -138,7 +138,6 @@ impl crate::Config for Runtime { type MaxDisputes = MaxDisputes; type PalletId = SimpleDisputesPalletId; type PredictionMarketsPalletId = PmPalletId; - type Slash = Treasury; type WeightInfo = zrml_simple_disputes::weights::WeightInfo; } diff --git a/zrml/simple-disputes/src/tests.rs b/zrml/simple-disputes/src/tests.rs index c479f84ee..ff8a0170c 100644 --- a/zrml/simple-disputes/src/tests.rs +++ b/zrml/simple-disputes/src/tests.rs @@ -61,19 +61,19 @@ fn on_dispute_denies_non_simple_disputes_markets() { } #[test] -fn on_resolution_denies_non_simple_disputes_markets() { +fn get_resolution_outcome_denies_non_simple_disputes_markets() { ExtBuilder.build().execute_with(|| { let mut market = DEFAULT_MARKET; market.dispute_mechanism = MarketDisputeMechanism::Court; assert_noop!( - SimpleDisputes::on_resolution(&0, &market), + SimpleDisputes::get_resolution_outcome(&0, &market), Error::::MarketDoesNotHaveSimpleDisputesMechanism ); }); } #[test] -fn on_resolution_sets_the_last_dispute_of_disputed_markets_as_the_canonical_outcome() { +fn get_resolution_outcome_sets_the_last_dispute_of_disputed_markets_as_the_canonical_outcome() { ExtBuilder.build().execute_with(|| { let mut market = DEFAULT_MARKET; market.status = MarketStatus::Disputed; @@ -97,7 +97,7 @@ fn on_resolution_sets_the_last_dispute_of_disputed_markets_as_the_canonical_outc .unwrap(); Disputes::::insert(0, &disputes); assert_eq!( - &SimpleDisputes::on_resolution(&0, &market).unwrap().unwrap(), + &SimpleDisputes::get_resolution_outcome(&0, &market).unwrap().unwrap(), &disputes.last().unwrap().outcome ) }); From c46621e0d9e3b6e1bb763c4d964e1b891e6f0177 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Tue, 17 Jan 2023 10:39:09 +0100 Subject: [PATCH 12/58] fix clippy --- zrml/court/src/tests.rs | 14 +++++++------- zrml/prediction-markets/src/lib.rs | 9 +++------ zrml/prediction-markets/src/tests.rs | 12 +++++++----- zrml/simple-disputes/src/lib.rs | 13 +++++-------- 4 files changed, 22 insertions(+), 26 deletions(-) diff --git a/zrml/court/src/tests.rs b/zrml/court/src/tests.rs index dcdfac4e0..2cc17b65d 100644 --- a/zrml/court/src/tests.rs +++ b/zrml/court/src/tests.rs @@ -155,7 +155,7 @@ fn appeal_stores_jurors_that_should_vote() { setup_blocks(123); let _ = Court::join_court(Origin::signed(ALICE)); let _ = Court::join_court(Origin::signed(BOB)); - MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); + MarketCommons::push_market(DEFAULT_MARKET).unwrap(); Court::appeal(Origin::signed(ALICE), 0).unwrap(); assert_noop!( Court::join_court(Origin::signed(ALICE)), @@ -173,7 +173,7 @@ fn get_resolution_outcome_awards_winners_and_slashes_losers() { Court::join_court(Origin::signed(ALICE)).unwrap(); Court::join_court(Origin::signed(BOB)).unwrap(); Court::join_court(Origin::signed(CHARLIE)).unwrap(); - MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); + MarketCommons::push_market(DEFAULT_MARKET).unwrap(); Court::appeal(Origin::signed(ALICE), 0).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(2)).unwrap(); @@ -195,7 +195,7 @@ fn get_resolution_outcome_decides_market_outcome_based_on_the_majority() { Court::join_court(Origin::signed(ALICE)).unwrap(); Court::join_court(Origin::signed(BOB)).unwrap(); Court::join_court(Origin::signed(CHARLIE)).unwrap(); - MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); + MarketCommons::push_market(DEFAULT_MARKET).unwrap(); Court::appeal(Origin::signed(ALICE), 0).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); @@ -212,7 +212,7 @@ fn get_resolution_outcome_sets_late_jurors_as_tardy() { Court::join_court(Origin::signed(ALICE)).unwrap(); Court::join_court(Origin::signed(BOB)).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); - MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); + MarketCommons::push_market(DEFAULT_MARKET).unwrap(); Court::appeal(Origin::signed(ALICE), 0).unwrap(); let _ = Court::get_resolution_outcome(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(Jurors::::get(ALICE).unwrap().status, JurorStatus::Ok); @@ -227,7 +227,7 @@ fn get_resolution_outcome_sets_jurors_that_voted_on_the_second_most_voted_outcom Court::join_court(Origin::signed(ALICE)).unwrap(); Court::join_court(Origin::signed(BOB)).unwrap(); Court::join_court(Origin::signed(CHARLIE)).unwrap(); - MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); + MarketCommons::push_market(DEFAULT_MARKET).unwrap(); Court::appeal(Origin::signed(ALICE), 0).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); @@ -245,7 +245,7 @@ fn get_resolution_outcome_punishes_tardy_jurors_that_failed_to_vote_a_second_tim Court::join_court(Origin::signed(BOB)).unwrap(); Court::set_stored_juror_as_tardy(&BOB).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); - MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); + MarketCommons::push_market(DEFAULT_MARKET).unwrap(); Court::appeal(Origin::signed(ALICE), 0).unwrap(); let _ = Court::get_resolution_outcome(&0, &DEFAULT_MARKET).unwrap(); let join_court_stake = 40000000000; @@ -263,7 +263,7 @@ fn get_resolution_outcome_removes_requested_jurors_and_votes() { Court::join_court(Origin::signed(ALICE)).unwrap(); Court::join_court(Origin::signed(BOB)).unwrap(); Court::join_court(Origin::signed(CHARLIE)).unwrap(); - MarketCommons::push_market(DEFAULT_MARKET.clone()).unwrap(); + MarketCommons::push_market(DEFAULT_MARKET).unwrap(); Court::appeal(Origin::signed(ALICE), 0).unwrap(); Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 5285e2f0c..39fd9d0eb 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -2389,12 +2389,9 @@ mod pallet { } let remainder = match market.dispute_mechanism { - MarketDisputeMechanism::Authorized => T::Authorized::maybe_pay( - market_id, - market, - &resolved_outcome, - imbalance_left, - )?, + MarketDisputeMechanism::Authorized => { + T::Authorized::maybe_pay(market_id, market, &resolved_outcome, imbalance_left)? + } MarketDisputeMechanism::Court => { T::Court::maybe_pay(market_id, market, &resolved_outcome, imbalance_left)? } diff --git a/zrml/prediction-markets/src/tests.rs b/zrml/prediction-markets/src/tests.rs index 5e11adaf5..24a690d4e 100644 --- a/zrml/prediction-markets/src/tests.rs +++ b/zrml/prediction-markets/src/tests.rs @@ -2295,14 +2295,16 @@ fn it_resolves_a_disputed_market() { // Slashed amounts: // - Dave's reserve: OutcomeBond::get() + OutcomeFactor::get() // - Alice's oracle bond: OracleBond::get() - // Total: OracleBond::get() + OutcomeBond::get() + OutcomeFactor::get() + // simple-disputes reward: OutcomeBond::get() + OutcomeFactor::get() + // Charlie gets OracleBond, because the dispute was justified. + // A dispute is justified if the oracle's report is different to the final outcome. // - // Charlie and Eve each receive half of the total slashed amount as bounty. + // Charlie and Eve each receive half of the simple-disputes reward as bounty. let dave_reserved = OutcomeBond::get() + OutcomeFactor::get(); - let total_slashed = OracleBond::get() + dave_reserved; + let total_slashed = dave_reserved; let charlie_balance = Balances::free_balance(&CHARLIE); - assert_eq!(charlie_balance, 1_000 * BASE + total_slashed / 2); + assert_eq!(charlie_balance, 1_000 * BASE + OracleBond::get() + total_slashed / 2); let charlie_reserved_2 = Balances::reserved_balance(&CHARLIE); assert_eq!(charlie_reserved_2, 0); let eve_balance = Balances::free_balance(&EVE); @@ -2415,7 +2417,7 @@ fn start_global_dispute_works() { ); for i in 1..=::MaxDisputes::get() { let dispute_bond = - zrml_simple_disputes::default_dispute_bond::((i - 1).into()); + zrml_simple_disputes::default_outcome_bond::((i - 1).into()); assert_eq!( GlobalDisputes::get_voting_outcome_info( &market_id, diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index 0bc3ec216..5c8308654 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -117,7 +117,7 @@ mod pallet { type WeightInfo: WeightInfoZeitgeist; } - type BalanceOf = + pub(crate) type BalanceOf = as Currency<::AccountId>>::Balance; pub(crate) type CurrencyOf = <::MarketCommons as MarketCommonsPalletApi>::Currency; @@ -390,21 +390,18 @@ mod pallet { Ok(disputes.len() == T::MaxDisputes::get() as usize) } - fn on_global_dispute( - #[allow(dead_code, unused)] market_id: &Self::MarketId, - market: &MarketOf, - ) -> DispatchResult { + fn on_global_dispute(_market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { ensure!( market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, Error::::MarketDoesNotHaveSimpleDisputesMechanism ); #[cfg(feature = "with-global-disputes")] { - let disputes = >::get(market_id); + let disputes = >::get(_market_id); // add report outcome to voting choices if let Some(report) = &market.report { T::GlobalDisputes::push_voting_outcome( - market_id, + _market_id, report.outcome.clone(), &report.by, >::zero(), @@ -412,7 +409,7 @@ mod pallet { } for MarketDispute { at: _, by, outcome, bond } in disputes.iter() { - T::GlobalDisputes::push_voting_outcome(market_id, outcome.clone(), by, bond)?; + T::GlobalDisputes::push_voting_outcome(_market_id, outcome.clone(), by, *bond)?; } } Ok(()) From 2f12959b9feab778e9eb942ccc6232fba8df5d02 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Tue, 17 Jan 2023 12:08:51 +0100 Subject: [PATCH 13/58] fix pm benchmarks --- zrml/prediction-markets/src/benchmarks.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/zrml/prediction-markets/src/benchmarks.rs b/zrml/prediction-markets/src/benchmarks.rs index 622bad072..358b3a81e 100644 --- a/zrml/prediction-markets/src/benchmarks.rs +++ b/zrml/prediction-markets/src/benchmarks.rs @@ -250,6 +250,11 @@ benchmarks! { let pool_id = >::market_pool(&market_id)?; let disputor = account("disputor", 1, 0); + ::AssetManager::deposit( + Asset::Ztg, + &disputor, + u128::MAX.saturated_into(), + ).unwrap(); let _ = Pallet::::dispute(RawOrigin::Signed(disputor).into(), market_id)?; let market = >::market(&market_id)?; @@ -470,6 +475,11 @@ benchmarks! { let outcome = OutcomeReport::Scalar(0); let disputor = account("disputor", 1, 0); + ::AssetManager::deposit( + Asset::Ztg, + &disputor, + u128::MAX.saturated_into(), + ).unwrap(); Pallet::::dispute(RawOrigin::Signed(disputor).into(), market_id)?; let now = >::block_number(); @@ -515,6 +525,11 @@ benchmarks! { })?; let disputor = account("disputor", 1, 0); + ::AssetManager::deposit( + Asset::Ztg, + &disputor, + u128::MAX.saturated_into(), + ).unwrap(); Pallet::::dispute(RawOrigin::Signed(disputor).into(), market_id)?; // Authorize the outcome with the highest number of correct reporters to maximize the @@ -786,6 +801,11 @@ benchmarks! { } let disputor: T::AccountId = account("Disputor", 1, 0); + ::AssetManager::deposit( + Asset::Ztg, + &disputor, + u128::MAX.saturated_into(), + ).unwrap(); let _ = Call::::dispute { market_id, } From 6f10d96e2aecce83998dfb7cac26705ad2dc122a Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Tue, 17 Jan 2023 14:28:30 +0100 Subject: [PATCH 14/58] add migration --- runtime/common/src/lib.rs | 1 - zrml/prediction-markets/src/lib.rs | 2 - zrml/prediction-markets/src/migrations.rs | 203 +++++++++++++++++++++- zrml/prediction-markets/src/mock.rs | 1 - zrml/simple-disputes/src/lib.rs | 6 +- zrml/simple-disputes/src/mock.rs | 1 - 6 files changed, 204 insertions(+), 10 deletions(-) diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 84b717a55..d7801dc17 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -1051,7 +1051,6 @@ macro_rules! impl_config_traits { type MarketCommons = MarketCommons; type MaxDisputes = MaxDisputes; type PalletId = SimpleDisputesPalletId; - type PredictionMarketsPalletId = PmPalletId; type WeightInfo = zrml_simple_disputes::weights::WeightInfo; } diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 043b8f884..d05f66614 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -1591,8 +1591,6 @@ mod pallet { MarketStartTooSoon, /// The point in time when the market becomes active is too late. MarketStartTooLate, - /// The maximum number of disputes has been reached. - MaxDisputesReached, /// The market dispute mechanism has not failed. MarketDisputeMechanismNotFailed, /// Tried to settle missing bond. diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 49aee5ec3..4cf93a34e 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -430,7 +430,7 @@ mod tests { use alloc::string::ToString; use frame_support::{migration::storage_key_iter, Twox64Concat}; use frame_system::pallet_prelude::BlockNumberFor; -use sp_runtime::traits::Saturating; +use sp_runtime::{traits::Saturating, SaturatedConversion}; use zeitgeist_primitives::types::AuthorityReport; use zrml_authorized::Pallet as AuthorizedPallet; @@ -704,6 +704,207 @@ mod tests_authorized { } } +use frame_support::dispatch::EncodeLike; +use zeitgeist_primitives::types::{MarketDispute, OldMarketDispute}; + +const PREDICTION_MARKETS_REQUIRED_STORAGE_VERSION: u16 = 7; +const PREDICTION_MARKETS_NEXT_STORAGE_VERSION: u16 = 8; + +#[cfg(feature = "try-runtime")] +type OldDisputesOf = frame_support::BoundedVec< + OldMarketDispute< + ::AccountId, + ::BlockNumber, + >, + ::MaxDisputes, +>; + +pub struct MoveDataToSimpleDisputes(PhantomData); + +impl OnRuntimeUpgrade + for MoveDataToSimpleDisputes +where + ::MarketId: EncodeLike< + <::MarketCommons as MarketCommonsPalletApi>::MarketId, + >, +{ + fn on_runtime_upgrade() -> Weight { + use orml_traits::NamedMultiReservableCurrency; + use zeitgeist_primitives::types::Asset; + + let mut total_weight = T::DbWeight::get().reads(1); + let pm_version = StorageVersion::get::>(); + if pm_version != PREDICTION_MARKETS_REQUIRED_STORAGE_VERSION { + log::info!( + "MoveDataToSimpleDisputes: market-commons version is {:?}, but {:?} is required", + pm_version, + PREDICTION_MARKETS_REQUIRED_STORAGE_VERSION, + ); + return total_weight; + } + log::info!("MoveDataToSimpleDisputes: Starting..."); + + total_weight = total_weight.saturating_add(T::DbWeight::get().reads(1)); + + for (market_id, old_disputes) in crate::Disputes::::drain() { + total_weight = total_weight.saturating_add(T::DbWeight::get().writes(1)); + + total_weight = total_weight.saturating_add(T::DbWeight::get().reads(1)); + if let Ok(mut market) = >::market(&market_id) { + match market.dispute_mechanism { + MarketDisputeMechanism::Authorized => { + if let Some(first_dispute) = old_disputes.first() { + let OldMarketDispute { at: _, by, outcome: _ } = first_dispute; + market.bonds.dispute = + Some(Bond::new(by.clone(), T::DisputeBond::get())); + zrml_market_commons::Markets::::insert(market_id, market); + } else { + log::warn!( + "MoveDataToSimpleDisputes: Could not find first dispute for \ + market id {:?}", + market_id + ); + } + // for authorized use the first dispute as actual dispute caller + continue; + } + // for simple-disputes ignore who called the dispute the first time + // and just use the below code to fill Disputes inside simple-disputes + MarketDisputeMechanism::SimpleDisputes => (), + // ignore / delete all disputes for court markets + MarketDisputeMechanism::Court => continue, + } + } else { + log::warn!( + "MoveDataToSimpleDisputes: Could not find market with market id {:?}", + market_id + ); + } + let mut new_disputes = zrml_simple_disputes::Disputes::::get(market_id); + for (i, old_dispute) in old_disputes.iter().enumerate() { + let bond = zrml_simple_disputes::default_outcome_bond::(i); + let new_dispute = MarketDispute { + at: old_dispute.at, + by: old_dispute.by.clone(), + outcome: old_dispute.outcome.clone(), + bond, + }; + new_disputes.try_push(new_dispute).expect("Failed to push to bounded vector!"); + + // switch to new reserve identifier for simple disputes + let sd_pallet_id = zeitgeist_primitives::constants::SD_PALLET_ID; + let sd_reserve_id = sd_pallet_id.0; + let pm_pallet_id = zeitgeist_primitives::constants::PM_PALLET_ID; + let pm_reserve_id = pm_pallet_id.0; + ::AssetManager::unreserve_named( + &pm_reserve_id, + Asset::Ztg, + &old_dispute.by, + bond.saturated_into::().saturated_into(), + ); + ::AssetManager::reserve_named( + &sd_reserve_id, + Asset::Ztg, + &old_dispute.by, + bond.saturated_into::().saturated_into(), + ) + .expect("Failed to reserve ZTG for dispute bond"); + } + + total_weight = total_weight.saturating_add(T::DbWeight::get().writes(1)); + zrml_simple_disputes::Disputes::::insert(market_id, new_disputes); + } + + StorageVersion::new(PREDICTION_MARKETS_NEXT_STORAGE_VERSION).put::>(); + total_weight = total_weight.saturating_add(T::DbWeight::get().writes(1)); + log::info!("MoveDataToSimpleDisputes: Done!"); + total_weight + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result<(), &'static str> { + log::info!("MoveDataToSimpleDisputes: Start pre_upgrade!"); + + let old_disputes = crate::Disputes::::iter().collect::>(); + Self::set_temp_storage(old_disputes, "old_disputes"); + + Ok(()) + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade() -> Result<(), &'static str> { + let old_disputes: BTreeMap, OldDisputesOf> = + Self::get_temp_storage("old_disputes").unwrap(); + + log::info!("MoveDataToSimpleDisputes: (post_upgrade) Start first try-runtime part!"); + + for (market_id, o) in old_disputes.iter() { + let market = >::market(&market_id) + .expect(&format!("Market for market id {:?} not found", market_id)[..]); + match market.dispute_mechanism { + MarketDisputeMechanism::Authorized => { + let first_dispute = old_disputes + .first() + .expect(&format!("First dispute for market {:?} not found", market_id)[..]); + let disputor = first_dispute.by.clone(); + let bond = T::DisputeBond::get(); + assert_eq!( + market.bonds.dispute, + Some(Bond { who: disputor, value: bond, is_settled: false }), + ); + + let simple_disputes_count = + zrml_simple_disputes::Disputes::::get(market_id).iter().count(); + assert_eq!(simple_disputes_count, 0); + continue; + } + MarketDisputeMechanism::SimpleDisputes => { + let new_count = + zrml_simple_disputes::Disputes::::get(market_id).iter().count(); + let old_count = o.iter().count(); + assert_eq!(new_count, old_count); + } + MarketDisputeMechanism::Court => { + panic!("Court should not be contained at all.") + } + } + } + + log::info!("MoveDataToSimpleDisputes: (post_upgrade) Start second try-runtime part!"); + + assert!(crate::Disputes::::iter().count() == 0); + + for (market_id, new_disputes) in zrml_simple_disputes::Disputes::::iter() { + let old_disputes = old_disputes + .get(&market_id) + .expect(&format!("Disputes for market {:?} not found", market_id)[..]); + + let market = >::market(&market_id) + .expect(&format!("Market for market id {:?} not found", market_id)[..]); + match market.dispute_mechanism { + MarketDisputeMechanism::Authorized => { + panic!("Authorized should not be contained in simple disputes."); + } + MarketDisputeMechanism::SimpleDisputes => (), + MarketDisputeMechanism::Court => { + panic!("Court should not be contained in simple disputes."); + } + } + + for (i, new_dispute) in new_disputes.iter().enumerate() { + let old_dispute = + old_disputes.get(i).expect(&format!("Dispute at index {} not found", i)[..]); + assert_eq!(new_dispute.at, old_dispute.at); + assert_eq!(new_dispute.by, old_dispute.by); + assert_eq!(new_dispute.outcome, old_dispute.outcome); + assert_eq!(new_dispute.bond, zrml_simple_disputes::default_outcome_bond::(i)); + } + } + + Ok(()) + } +} + // We use these utilities to prevent having to make the swaps pallet a dependency of // prediciton-markets. The calls are based on the implementation of `StorageVersion`, found here: // https://github.com/paritytech/substrate/blob/bc7a1e6c19aec92bfa247d8ca68ec63e07061032/frame/support/src/traits/metadata.rs#L168-L230 diff --git a/zrml/prediction-markets/src/mock.rs b/zrml/prediction-markets/src/mock.rs index 9cfd75644..e9b15883c 100644 --- a/zrml/prediction-markets/src/mock.rs +++ b/zrml/prediction-markets/src/mock.rs @@ -314,7 +314,6 @@ impl zrml_simple_disputes::Config for Runtime { type MarketCommons = MarketCommons; type MaxDisputes = MaxDisputes; type PalletId = SimpleDisputesPalletId; - type PredictionMarketsPalletId = PmPalletId; type WeightInfo = zrml_simple_disputes::weights::WeightInfo; } diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index 5c8308654..89ba33201 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -110,9 +110,6 @@ mod pallet { #[pallet::constant] type PalletId: Get; - #[pallet::constant] - type PredictionMarketsPalletId: Get; - /// Weights generated by benchmarks type WeightInfo: WeightInfoZeitgeist; } @@ -169,6 +166,7 @@ mod pallet { OutcomeMismatch, CannotDisputeSameOutcome, MarketIsNotReported, + /// The maximum number of disputes has been reached. MaxDisputesReached, } @@ -225,7 +223,7 @@ mod pallet { impl Pallet { #[inline] pub fn reserve_id() -> [u8; 8] { - T::PredictionMarketsPalletId::get().0 + T::PalletId::get().0 } fn ensure_can_not_dispute_the_same_outcome( diff --git a/zrml/simple-disputes/src/mock.rs b/zrml/simple-disputes/src/mock.rs index e9872c558..e9219ddbb 100644 --- a/zrml/simple-disputes/src/mock.rs +++ b/zrml/simple-disputes/src/mock.rs @@ -137,7 +137,6 @@ impl crate::Config for Runtime { type MarketCommons = MarketCommons; type MaxDisputes = MaxDisputes; type PalletId = SimpleDisputesPalletId; - type PredictionMarketsPalletId = PmPalletId; type WeightInfo = zrml_simple_disputes::weights::WeightInfo; } From 9f002a40d023aa9d41c811a2136092b7ccfe4566 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Tue, 17 Jan 2023 16:31:57 +0100 Subject: [PATCH 15/58] simplify migration --- zrml/prediction-markets/src/migrations.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 4cf93a34e..8610a6586 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -839,8 +839,11 @@ where log::info!("MoveDataToSimpleDisputes: (post_upgrade) Start first try-runtime part!"); for (market_id, o) in old_disputes.iter() { - let market = >::market(&market_id) + let market = ::MarketCommons::market(market_id) .expect(&format!("Market for market id {:?} not found", market_id)[..]); + + let disputes = zrml_simple_disputes::Disputes::::get(market_id); + match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { let first_dispute = old_disputes @@ -853,14 +856,12 @@ where Some(Bond { who: disputor, value: bond, is_settled: false }), ); - let simple_disputes_count = - zrml_simple_disputes::Disputes::::get(market_id).iter().count(); + let simple_disputes_count = disputes.iter().count(); assert_eq!(simple_disputes_count, 0); continue; } MarketDisputeMechanism::SimpleDisputes => { - let new_count = - zrml_simple_disputes::Disputes::::get(market_id).iter().count(); + let new_count = disputes.iter().count(); let old_count = o.iter().count(); assert_eq!(new_count, old_count); } @@ -876,10 +877,10 @@ where for (market_id, new_disputes) in zrml_simple_disputes::Disputes::::iter() { let old_disputes = old_disputes - .get(&market_id) + .get(&market_id.saturated_into::().saturated_into()) .expect(&format!("Disputes for market {:?} not found", market_id)[..]); - let market = >::market(&market_id) + let market = ::MarketCommons::market(&market_id) .expect(&format!("Market for market id {:?} not found", market_id)[..]); match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { From 09730a0a233d2871351573c3619d298eb170991b Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Wed, 18 Jan 2023 08:06:55 +0100 Subject: [PATCH 16/58] correct migration --- zrml/prediction-markets/src/migrations.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 8610a6586..a255a552f 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -839,14 +839,15 @@ where log::info!("MoveDataToSimpleDisputes: (post_upgrade) Start first try-runtime part!"); for (market_id, o) in old_disputes.iter() { - let market = ::MarketCommons::market(market_id) + let market = >::market(market_id) .expect(&format!("Market for market id {:?} not found", market_id)[..]); - let disputes = zrml_simple_disputes::Disputes::::get(market_id); + // market id is a reference, but we need the raw value to encode with the where clause + let disputes = zrml_simple_disputes::Disputes::::get(*market_id); match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { - let first_dispute = old_disputes + let first_dispute = o .first() .expect(&format!("First dispute for market {:?} not found", market_id)[..]); let disputor = first_dispute.by.clone(); From f1347c3eaaf971af9c224913f19091c8ac9426c6 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Wed, 18 Jan 2023 09:16:53 +0100 Subject: [PATCH 17/58] migration fixes and call filter --- runtime/common/src/lib.rs | 2 +- runtime/zeitgeist/src/lib.rs | 1 + zrml/prediction-markets/src/migrations.rs | 54 +++++++++++++++++++++-- 3 files changed, 52 insertions(+), 5 deletions(-) diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index d7801dc17..df8fbdc6f 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -305,7 +305,7 @@ macro_rules! create_runtime { Court: zrml_court::{Call, Event, Pallet, Storage} = 52, LiquidityMining: zrml_liquidity_mining::{Call, Config, Event, Pallet, Storage} = 53, RikiddoSigmoidFeeMarketEma: zrml_rikiddo::::{Pallet, Storage} = 54, - SimpleDisputes: zrml_simple_disputes::{Event, Pallet, Storage} = 55, + SimpleDisputes: zrml_simple_disputes::{Call, Event, Pallet, Storage} = 55, Swaps: zrml_swaps::{Call, Event, Pallet, Storage} = 56, PredictionMarkets: zrml_prediction_markets::{Call, Event, Pallet, Storage} = 57, Styx: zrml_styx::{Call, Event, Pallet, Storage} = 58, diff --git a/runtime/zeitgeist/src/lib.rs b/runtime/zeitgeist/src/lib.rs index 745f6948e..c22fbc6a4 100644 --- a/runtime/zeitgeist/src/lib.rs +++ b/runtime/zeitgeist/src/lib.rs @@ -162,6 +162,7 @@ impl Contains for IsCallable { _ => true, } } + Call::SimpleDisputes(_) => false, Call::System(inner_call) => { match inner_call { // Some "waste" storage will never impact proper operation. diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index a255a552f..a6d9e2a19 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -753,10 +753,17 @@ where if let Ok(mut market) = >::market(&market_id) { match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { + // TODO Move this part of the migration (market mutation) + // TODO into the OutsiderBond migration (needs to run before this migration) + // TODO because it needs to iterate over all Disputes of the pm pallet + // TODO in this current migration we drain all Disputes of the pm pallet if let Some(first_dispute) = old_disputes.first() { let OldMarketDispute { at: _, by, outcome: _ } = first_dispute; market.bonds.dispute = Some(Bond::new(by.clone(), T::DisputeBond::get())); + + total_weight = + total_weight.saturating_add(T::DbWeight::get().writes(1)); zrml_market_commons::Markets::::insert(market_id, market); } else { log::warn!( @@ -780,6 +787,8 @@ where market_id ); } + + total_weight = total_weight.saturating_add(T::DbWeight::get().reads(1)); let mut new_disputes = zrml_simple_disputes::Disputes::::get(market_id); for (i, old_dispute) in old_disputes.iter().enumerate() { let bond = zrml_simple_disputes::default_outcome_bond::(i); @@ -789,26 +798,62 @@ where outcome: old_dispute.outcome.clone(), bond, }; - new_disputes.try_push(new_dispute).expect("Failed to push to bounded vector!"); + let res = new_disputes.try_push(new_dispute); + if res.is_err() { + log::error!( + "MoveDataToSimpleDisputes: Could not push dispute for market id {:?}", + market_id + ); + } // switch to new reserve identifier for simple disputes let sd_pallet_id = zeitgeist_primitives::constants::SD_PALLET_ID; let sd_reserve_id = sd_pallet_id.0; let pm_pallet_id = zeitgeist_primitives::constants::PM_PALLET_ID; let pm_reserve_id = pm_pallet_id.0; + + // charge weight defensivly for unreserve_named + // https://github.com/open-web3-stack/open-runtime-module-library/blob/24f0a8b6e04e1078f70d0437fb816337cdf4f64c/tokens/src/lib.rs#L1516-L1547 + total_weight = total_weight.saturating_add(T::DbWeight::get().reads_writes(4, 3)); + let reserved_balance = ::AssetManager::reserved_balance_named( + &pm_reserve_id, + Asset::Ztg, + &old_dispute.by, + ); + if reserved_balance < bond.saturated_into::().saturated_into() { + log::error!( + "MoveDataToSimpleDisputes: Could not unreserve {:?} for {:?} because \ + reserved balance is only {:?}. Market id: {:?}", + bond, + old_dispute.by, + reserved_balance, + market_id, + ); + } ::AssetManager::unreserve_named( &pm_reserve_id, Asset::Ztg, &old_dispute.by, bond.saturated_into::().saturated_into(), ); - ::AssetManager::reserve_named( + + // charge weight defensivly for reserve_named + // https://github.com/open-web3-stack/open-runtime-module-library/blob/24f0a8b6e04e1078f70d0437fb816337cdf4f64c/tokens/src/lib.rs#L1486-L1499 + total_weight = total_weight.saturating_add(T::DbWeight::get().reads_writes(3, 3)); + let res = ::AssetManager::reserve_named( &sd_reserve_id, Asset::Ztg, &old_dispute.by, bond.saturated_into::().saturated_into(), - ) - .expect("Failed to reserve ZTG for dispute bond"); + ); + if res.is_err() { + log::error!( + "MoveDataToSimpleDisputes: Could not reserve bond for dispute caller {:?} \ + and market id {:?}", + old_dispute.by, + market_id + ); + } } total_weight = total_weight.saturating_add(T::DbWeight::get().writes(1)); @@ -903,6 +948,7 @@ where } } + log::info!("MoveDataToSimpleDisputes: Done! (post_upgrade)"); Ok(()) } } From b42002c1292afbad80df931d1ac08ab82652eac8 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Wed, 18 Jan 2023 10:49:09 +0100 Subject: [PATCH 18/58] correct admin_destroy_market benchmark --- primitives/src/traits/dispute_api.rs | 1 - zrml/authorized/src/mock.rs | 2 - zrml/court/src/mock.rs | 1 - zrml/prediction-markets/src/benchmarks.rs | 20 ++++++---- zrml/prediction-markets/src/lib.rs | 5 +-- zrml/prediction-markets/src/weights.rs | 45 +++++++++++++---------- zrml/simple-disputes/src/mock.rs | 1 - 7 files changed, 39 insertions(+), 36 deletions(-) diff --git a/primitives/src/traits/dispute_api.rs b/primitives/src/traits/dispute_api.rs index b7e576cd5..880698a71 100644 --- a/primitives/src/traits/dispute_api.rs +++ b/primitives/src/traits/dispute_api.rs @@ -112,7 +112,6 @@ pub trait DisputeResolutionApi { type Balance; type BlockNumber; type MarketId; - type MaxDisputes; type Moment; /// Resolve a market. diff --git a/zrml/authorized/src/mock.rs b/zrml/authorized/src/mock.rs index adef4d071..8027749b8 100644 --- a/zrml/authorized/src/mock.rs +++ b/zrml/authorized/src/mock.rs @@ -66,7 +66,6 @@ construct_runtime!( ord_parameter_types! { pub const AuthorizedDisputeResolutionUser: AccountIdTest = ALICE; - pub const MaxDisputes: u32 = 64; } // MockResolution implements DisputeResolutionApi with no-ops. @@ -77,7 +76,6 @@ impl DisputeResolutionApi for MockResolution { type Balance = Balance; type BlockNumber = BlockNumber; type MarketId = MarketId; - type MaxDisputes = MaxDisputes; type Moment = Moment; fn resolve( diff --git a/zrml/court/src/mock.rs b/zrml/court/src/mock.rs index bc41187cf..88bb89d8a 100644 --- a/zrml/court/src/mock.rs +++ b/zrml/court/src/mock.rs @@ -74,7 +74,6 @@ impl DisputeResolutionApi for NoopResolution { type Balance = Balance; type BlockNumber = BlockNumber; type MarketId = MarketId; - type MaxDisputes = u32; type Moment = Moment; fn resolve( diff --git a/zrml/prediction-markets/src/benchmarks.rs b/zrml/prediction-markets/src/benchmarks.rs index 358b3a81e..67faa12a5 100644 --- a/zrml/prediction-markets/src/benchmarks.rs +++ b/zrml/prediction-markets/src/benchmarks.rs @@ -227,7 +227,7 @@ benchmarks! { From<::MarketId>, } - admin_destroy_disputed_market{ + admin_destroy_disputed_market { // The number of assets. let a in (T::MinCategories::get().into())..T::MaxCategories::get().into(); // The number of market ids per open time frame. @@ -265,16 +265,18 @@ benchmarks! { }; for i in 0..o { + // shift of 1 to avoid collisions with first market id 0 MarketIdsPerOpenTimeFrame::::try_mutate( Pallet::::calculate_time_frame_of_moment(range_start), - |ids| ids.try_push(i.into()), + |ids| ids.try_push((i + 1).into()), ).unwrap(); } for i in 0..c { + // shift of 65 to avoid collisions with `o` MarketIdsPerCloseTimeFrame::::try_mutate( Pallet::::calculate_time_frame_of_moment(range_end), - |ids| ids.try_push(i.into()), + |ids| ids.try_push((i + 65).into()), ).unwrap(); } @@ -287,9 +289,10 @@ benchmarks! { let now = >::block_number(); let resolves_at = now.saturating_add(::CorrectionPeriod::get()); for i in 0..r { + // shift of 129 to avoid collisions with `o` and `c` MarketIdsPerDisputeBlock::::try_mutate( resolves_at, - |ids| ids.try_push(i.into()), + |ids| ids.try_push((i + 129).into()), ).unwrap(); } @@ -326,25 +329,28 @@ benchmarks! { }; for i in 0..o { + // shift of 1 to avoid collisions with first market id 0 MarketIdsPerOpenTimeFrame::::try_mutate( Pallet::::calculate_time_frame_of_moment(range_start), - |ids| ids.try_push(i.into()), + |ids| ids.try_push((i + 1).into()), ).unwrap(); } for i in 0..c { + // shift of 65 to avoid collisions with `o` MarketIdsPerCloseTimeFrame::::try_mutate( Pallet::::calculate_time_frame_of_moment(range_end), - |ids| ids.try_push(i.into()), + |ids| ids.try_push((i + 65).into()), ).unwrap(); } let report_at = market.report.unwrap().at; let resolves_at = report_at.saturating_add(market.deadlines.dispute_duration); for i in 0..r { + // shift of 129 to avoid collisions with `o` and `c` MarketIdsPerReportBlock::::try_mutate( resolves_at, - |ids| ids.try_push(i.into()), + |ids| ids.try_push((i + 129).into()), ).unwrap(); } diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index d05f66614..296cd3021 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -205,7 +205,6 @@ mod pallet { ) .max(T::WeightInfo::admin_destroy_disputed_market( T::MaxCategories::get().into(), - T::MaxDisputes::get(), CacheSize::get(), CacheSize::get(), CacheSize::get(), @@ -265,7 +264,7 @@ mod pallet { let open_ids_len = Self::clear_auto_open(&market_id)?; let close_ids_len = Self::clear_auto_close(&market_id)?; - let (ids_len, disputes_len) = Self::clear_auto_resolve(&market_id)?; + let (ids_len, _) = Self::clear_auto_resolve(&market_id)?; Self::clear_dispute_mechanism(&market_id)?; >::remove_market(&market_id)?; @@ -288,7 +287,6 @@ mod pallet { Ok(( Some(T::WeightInfo::admin_destroy_disputed_market( category_count, - disputes_len, open_ids_len, close_ids_len, ids_len, @@ -2822,7 +2820,6 @@ mod pallet { type Balance = BalanceOf; type BlockNumber = T::BlockNumber; type MarketId = MarketIdOf; - type MaxDisputes = T::MaxDisputes; type Moment = MomentOf; fn resolve( diff --git a/zrml/prediction-markets/src/weights.rs b/zrml/prediction-markets/src/weights.rs index 496d959a4..153708e97 100644 --- a/zrml/prediction-markets/src/weights.rs +++ b/zrml/prediction-markets/src/weights.rs @@ -45,7 +45,7 @@ use frame_support::{traits::Get, weights::Weight}; /// Trait containing the required functions for weight retrival within /// zrml_prediction_markets (automatically generated) pub trait WeightInfoZeitgeist { - fn admin_destroy_disputed_market(a: u32, d: u32, o: u32, c: u32, r: u32) -> Weight; + fn admin_destroy_disputed_market(a: u32, o: u32, c: u32, r: u32) -> Weight; fn admin_destroy_reported_market(a: u32, o: u32, c: u32, r: u32) -> Weight; fn admin_move_market_to_closed(o: u32, c: u32) -> Weight; fn admin_move_market_to_resolved_scalar_reported(r: u32) -> Weight; @@ -83,25 +83,27 @@ pub trait WeightInfoZeitgeist { pub struct WeightInfo(PhantomData); impl WeightInfoZeitgeist for WeightInfo { // Storage: MarketCommons Markets (r:1 w:1) - // Storage: Balances Reserves (r:1 w:1) - // Storage: System Account (r:2 w:2) + // Storage: Balances Reserves (r:2 w:2) + // Storage: System Account (r:3 w:3) // Storage: MarketCommons MarketPool (r:1 w:1) // Storage: Swaps Pools (r:1 w:1) // Storage: Tokens Accounts (r:2 w:2) // Storage: Tokens TotalIssuance (r:2 w:2) - // Storage: PredictionMarkets Disputes (r:1 w:1) + // Storage: Authorized AuthorizedOutcomeReports (r:1 w:1) // Storage: PredictionMarkets MarketIdsPerDisputeBlock (r:1 w:1) - fn admin_destroy_disputed_market(a: u32, d: u32, o: u32, _c: u32, _r: u32) -> Weight { - (131_391_000 as Weight) - // Standard Error: 3_000 - .saturating_add((22_410_000 as Weight).saturating_mul(a as Weight)) - // Standard Error: 56_000 - .saturating_add((1_219_000 as Weight).saturating_mul(d as Weight)) - // Standard Error: 3_000 - .saturating_add((66_000 as Weight).saturating_mul(o as Weight)) - .saturating_add(T::DbWeight::get().reads(8 as Weight)) + fn admin_destroy_disputed_market(a: u32, o: u32, c: u32, r: u32) -> Weight { + (138_848_000 as Weight) + // Standard Error: 35_000 + .saturating_add((20_922_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 34_000 + .saturating_add((1_091_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 34_000 + .saturating_add((984_000 as Weight).saturating_mul(c as Weight)) + // Standard Error: 34_000 + .saturating_add((1_026_000 as Weight).saturating_mul(r as Weight)) + .saturating_add(T::DbWeight::get().reads(10 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(a as Weight))) - .saturating_add(T::DbWeight::get().writes(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(10 as Weight)) .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(a as Weight))) } // Storage: MarketCommons Markets (r:1 w:1) @@ -112,14 +114,17 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: Tokens Accounts (r:2 w:2) // Storage: Tokens TotalIssuance (r:2 w:2) // Storage: PredictionMarkets MarketIdsPerReportBlock (r:1 w:1) - // Storage: PredictionMarkets Disputes (r:0 w:1) - fn admin_destroy_reported_market(a: u32, _o: u32, _c: u32, _r: u32) -> Weight { - (148_923_000 as Weight) - // Standard Error: 4_000 - .saturating_add((22_300_000 as Weight).saturating_mul(a as Weight)) + fn admin_destroy_reported_market(a: u32, o: u32, c: u32, _r: u32) -> Weight { + (144_950_000 as Weight) + // Standard Error: 5_000 + .saturating_add((23_098_000 as Weight).saturating_mul(a as Weight)) + // Standard Error: 5_000 + .saturating_add((41_000 as Weight).saturating_mul(o as Weight)) + // Standard Error: 5_000 + .saturating_add((43_000 as Weight).saturating_mul(c as Weight)) .saturating_add(T::DbWeight::get().reads(7 as Weight)) .saturating_add(T::DbWeight::get().reads((2 as Weight).saturating_mul(a as Weight))) - .saturating_add(T::DbWeight::get().writes(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(7 as Weight)) .saturating_add(T::DbWeight::get().writes((2 as Weight).saturating_mul(a as Weight))) } // Storage: MarketCommons Markets (r:1 w:1) diff --git a/zrml/simple-disputes/src/mock.rs b/zrml/simple-disputes/src/mock.rs index e9219ddbb..b6ae69469 100644 --- a/zrml/simple-disputes/src/mock.rs +++ b/zrml/simple-disputes/src/mock.rs @@ -100,7 +100,6 @@ impl DisputeResolutionApi for NoopResolution { type Balance = Balance; type BlockNumber = BlockNumber; type MarketId = MarketId; - type MaxDisputes = u32; type Moment = Moment; fn resolve( From 80b3fa6bec13c93833758bdb99e1f5b76c7b0aed Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Wed, 18 Jan 2023 10:56:15 +0100 Subject: [PATCH 19/58] improve simple-disputes mock --- zrml/simple-disputes/src/mock.rs | 61 ++++++++++++++++++------------- zrml/simple-disputes/src/tests.rs | 8 ++-- 2 files changed, 40 insertions(+), 29 deletions(-) diff --git a/zrml/simple-disputes/src/mock.rs b/zrml/simple-disputes/src/mock.rs index b6ae69469..ddf72f35b 100644 --- a/zrml/simple-disputes/src/mock.rs +++ b/zrml/simple-disputes/src/mock.rs @@ -21,18 +21,16 @@ use crate::{self as zrml_simple_disputes}; use frame_support::{ construct_runtime, ord_parameter_types, pallet_prelude::{DispatchError, Weight}, - traits::{Everything, NeverEnsureOrigin}, + traits::Everything, }; -use frame_system::EnsureSignedBy; use sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, }; use zeitgeist_primitives::{ constants::mock::{ - BlockHashCount, ExistentialDeposits, GetNativeCurrencyId, MaxApprovals, MaxDisputes, - MaxReserves, MinimumPeriod, OutcomeBond, OutcomeFactor, PmPalletId, SimpleDisputesPalletId, - TreasuryPalletId, + BlockHashCount, ExistentialDeposits, GetNativeCurrencyId, MaxDisputes, MaxReserves, + MinimumPeriod, OutcomeBond, OutcomeFactor, PmPalletId, SimpleDisputesPalletId, BASE, }, traits::DisputeResolutionApi, types::{ @@ -47,8 +45,16 @@ use zeitgeist_primitives::constants::mock::{ MinOutcomeVoteAmount, RemoveKeysLimit, VotingOutcomeFee, }; +pub const ALICE: AccountIdTest = 0; +pub const BOB: AccountIdTest = 1; +pub const CHARLIE: AccountIdTest = 2; +pub const DAVE: AccountIdTest = 3; +pub const EVE: AccountIdTest = 4; +pub const FRED: AccountIdTest = 5; pub const SUDO: AccountIdTest = 69; +pub const INITIAL_BALANCE: u128 = 1_000 * BASE; + ord_parameter_types! { pub const Sudo: AccountIdTest = SUDO; } @@ -69,7 +75,6 @@ construct_runtime!( System: frame_system::{Call, Config, Event, Pallet, Storage}, Timestamp: pallet_timestamp::{Pallet}, Tokens: orml_tokens::{Config, Event, Pallet, Storage}, - Treasury: pallet_treasury::{Call, Event, Pallet, Storage}, } ); @@ -88,7 +93,6 @@ construct_runtime!( System: frame_system::{Call, Config, Event, Pallet, Storage}, Timestamp: pallet_timestamp::{Pallet}, Tokens: orml_tokens::{Config, Event, Pallet, Storage}, - Treasury: pallet_treasury::{Call, Event, Pallet, Storage}, } ); @@ -230,29 +234,34 @@ impl pallet_timestamp::Config for Runtime { type WeightInfo = (); } -impl pallet_treasury::Config for Runtime { - type ApproveOrigin = EnsureSignedBy; - type Burn = (); - type BurnDestination = (); - type Currency = Balances; - type Event = (); - type MaxApprovals = MaxApprovals; - type OnSlash = (); - type PalletId = TreasuryPalletId; - type ProposalBond = (); - type ProposalBondMinimum = (); - type ProposalBondMaximum = (); - type RejectOrigin = EnsureSignedBy; - type SpendFunds = (); - type SpendOrigin = NeverEnsureOrigin; - type SpendPeriod = (); - type WeightInfo = (); +pub struct ExtBuilder { + balances: Vec<(AccountIdTest, Balance)>, } -pub struct ExtBuilder; +impl Default for ExtBuilder { + fn default() -> Self { + Self { + balances: vec![ + (ALICE, INITIAL_BALANCE), + (BOB, INITIAL_BALANCE), + (CHARLIE, INITIAL_BALANCE), + (DAVE, INITIAL_BALANCE), + (EVE, INITIAL_BALANCE), + (FRED, INITIAL_BALANCE), + (SUDO, INITIAL_BALANCE), + ], + } + } +} impl ExtBuilder { pub fn build(self) -> sp_io::TestExternalities { - frame_system::GenesisConfig::default().build_storage::().unwrap().into() + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + pallet_balances::GenesisConfig:: { balances: self.balances } + .assimilate_storage(&mut t) + .unwrap(); + + t.into() } } diff --git a/zrml/simple-disputes/src/tests.rs b/zrml/simple-disputes/src/tests.rs index ff8a0170c..b1bc24304 100644 --- a/zrml/simple-disputes/src/tests.rs +++ b/zrml/simple-disputes/src/tests.rs @@ -50,7 +50,7 @@ const DEFAULT_MARKET: MarketOf = Market { #[test] fn on_dispute_denies_non_simple_disputes_markets() { - ExtBuilder.build().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { let mut market = DEFAULT_MARKET; market.dispute_mechanism = MarketDisputeMechanism::Court; assert_noop!( @@ -62,7 +62,7 @@ fn on_dispute_denies_non_simple_disputes_markets() { #[test] fn get_resolution_outcome_denies_non_simple_disputes_markets() { - ExtBuilder.build().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { let mut market = DEFAULT_MARKET; market.dispute_mechanism = MarketDisputeMechanism::Court; assert_noop!( @@ -74,7 +74,7 @@ fn get_resolution_outcome_denies_non_simple_disputes_markets() { #[test] fn get_resolution_outcome_sets_the_last_dispute_of_disputed_markets_as_the_canonical_outcome() { - ExtBuilder.build().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { let mut market = DEFAULT_MARKET; market.status = MarketStatus::Disputed; let disputes = BoundedVec::try_from( @@ -102,3 +102,5 @@ fn get_resolution_outcome_sets_the_last_dispute_of_disputed_markets_as_the_canon ) }); } + +// TODO test `reserve_outcome` functionality and API functionality From bd7c97d9c66867be496a93c4b272ffd761785a40 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 19 Jan 2023 11:12:58 +0100 Subject: [PATCH 20/58] benchmark reserve_outcome --- runtime/common/src/lib.rs | 2 + zrml/simple-disputes/src/benchmarks.rs | 69 +++++++++++++++++++++++++ zrml/simple-disputes/src/lib.rs | 70 ++++++++++++++++++++------ 3 files changed, 127 insertions(+), 14 deletions(-) create mode 100644 zrml/simple-disputes/src/benchmarks.rs diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index df8fbdc6f..8daf02710 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -1211,6 +1211,7 @@ macro_rules! create_runtime_api { list_benchmark!(list, extra, zrml_swaps, Swaps); list_benchmark!(list, extra, zrml_authorized, Authorized); list_benchmark!(list, extra, zrml_court, Court); + list_benchmark!(list, extra, zrml_simple_disputes, SimpleDisputes); #[cfg(feature = "with-global-disputes")] list_benchmark!(list, extra, zrml_global_disputes, GlobalDisputes); list_benchmark!(list, extra, zrml_prediction_markets, PredictionMarkets); @@ -1289,6 +1290,7 @@ macro_rules! create_runtime_api { add_benchmark!(params, batches, zrml_swaps, Swaps); add_benchmark!(params, batches, zrml_authorized, Authorized); add_benchmark!(params, batches, zrml_court, Court); + add_benchmark!(params, batches, zrml_simple_disputes, SimpleDisputes); #[cfg(feature = "with-global-disputes")] add_benchmark!(params, batches, zrml_global_disputes, GlobalDisputes); add_benchmark!(params, batches, zrml_prediction_markets, PredictionMarkets); diff --git a/zrml/simple-disputes/src/benchmarks.rs b/zrml/simple-disputes/src/benchmarks.rs new file mode 100644 index 000000000..a77238632 --- /dev/null +++ b/zrml/simple-disputes/src/benchmarks.rs @@ -0,0 +1,69 @@ +// Copyright 2021-2022 Zeitgeist PM LLC. +// +// This file is part of Zeitgeist. +// +// Zeitgeist is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the +// Free Software Foundation, either version 3 of the License, or (at +// your option) any later version. +// +// Zeitgeist is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Zeitgeist. If not, see . + +#![allow( + // Auto-generated code is a no man's land + clippy::integer_arithmetic +)] +#![allow(clippy::type_complexity)] +#![cfg(feature = "runtime-benchmarks")] + +use super::*; +use frame_benchmarking::{account, benchmarks, vec, whitelisted_caller}; + +benchmarks! { + reserve_outcome { + let d in 1..(T::MaxDisputes::get() - 1); + let e in 1..63; + + let caller: T::AccountId = whitelisted_caller(); + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market).unwrap(); + + let now = >::block_number(); + + for i in 0..d { + + } + let last_dispute = MarketDispute { + at: now, + by: caller.clone(), + outcome: OutcomeReport::Scalar(2), + bond: default_outcome_bond::(0usize), + }; + Disputes::::insert(market_id, last_dispute); + + + let dispute_duration_ends_at_block = + now.saturating_add(market.deadlines.dispute_duration); + for i in 0..e { + let id = T::MarketCommons::push_market(market_mock::()).unwrap(); + T::DisputeResolution::add_auto_resolve(&id, dispute_duration_ends_at_block).unwrap(); + } + + let outcome = OutcomeReport::Scalar(1); + let bond = default_outcome_bond::(0usize); + let _ = T::Currency::deposit_creating(&caller, bond); + }: _(RawOrigin::Signed(caller.clone()), market_id, outcome) + + impl_benchmark_test_suite!( + PredictionMarket, + crate::mock::ExtBuilder::default().build(), + crate::mock::Runtime, + ); +} diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index 89ba33201..4cbe1b1f9 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -20,6 +20,8 @@ extern crate alloc; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarks; mod mock; mod simple_disputes_pallet_api; mod tests; @@ -27,9 +29,16 @@ pub mod weights; pub use pallet::*; pub use simple_disputes_pallet_api::SimpleDisputesPalletApi; +use zeitgeist_primitives::{ + traits::{DisputeApi, DisputeResolutionApi, ZeitgeistAssetManager}, + types::{ + Asset, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, OutcomeReport, Report, + }, +}; #[frame_support::pallet] mod pallet { + use super::*; use crate::{weights::WeightInfoZeitgeist, SimpleDisputesPalletApi}; use alloc::vec::Vec; use core::marker::PhantomData; @@ -48,13 +57,7 @@ mod pallet { traits::{CheckedDiv, Saturating}, DispatchError, SaturatedConversion, }; - use zeitgeist_primitives::{ - traits::{DisputeApi, DisputeResolutionApi, ZeitgeistAssetManager}, - types::{ - Asset, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, OutcomeReport, - Report, - }, - }; + #[cfg(feature = "with-global-disputes")] use zrml_global_disputes::GlobalDisputesPalletApi; use zrml_market_commons::MarketCommonsPalletApi; @@ -128,6 +131,14 @@ mod pallet { ::BlockNumber, MomentOf, >; + pub(crate) type DisputesOf = BoundedVec< + MarketDispute< + ::AccountId, + ::BlockNumber, + BalanceOf, + >, + ::MaxDisputes, + >; #[pallet::pallet] pub struct Pallet(PhantomData); @@ -135,13 +146,8 @@ mod pallet { /// For each market, this holds the dispute information for each dispute that's /// been issued. #[pallet::storage] - pub type Disputes = StorageMap< - _, - Blake2_128Concat, - MarketIdOf, - BoundedVec>, T::MaxDisputes>, - ValueQuery, - >; + pub type Disputes = + StorageMap<_, Blake2_128Concat, MarketIdOf, DisputesOf, ValueQuery>; #[pallet::event] #[pallet::generate_deposit(fn deposit_event)] @@ -446,3 +452,39 @@ mod pallet { ) } } + +#[cfg(any(feature = "runtime-benchmarks", test))] +pub(crate) fn market_mock() +-> zeitgeist_primitives::types::Market, T::BlockNumber, MomentOf> +where + T: crate::Config, +{ + use frame_support::traits::Get; + use sp_runtime::{traits::AccountIdConversion, SaturatedConversion}; + use zeitgeist_primitives::types::{MarketBonds, ScoringRule}; + + zeitgeist_primitives::types::Market { + creation: zeitgeist_primitives::types::MarketCreation::Permissionless, + creator_fee: 0, + creator: T::PalletId::get().into_account_truncating(), + market_type: zeitgeist_primitives::types::MarketType::Scalar(0..=100), + dispute_mechanism: zeitgeist_primitives::types::MarketDisputeMechanism::SimpleDisputes, + metadata: Default::default(), + oracle: T::PalletId::get().into_account_truncating(), + period: zeitgeist_primitives::types::MarketPeriod::Block(Default::default()), + deadlines: zeitgeist_primitives::types::Deadlines { + grace_period: 1_u32.into(), + oracle_duration: 1_u32.into(), + dispute_duration: 42_u32.into(), + }, + report: Some(zeitgeist_primitives::types::Report { + outcome: OutcomeReport::Scalar(0), + at: 0u64.saturated_into(), + by: T::PalletId::get().into_account_truncating(), + }), + resolved_outcome: None, + scoring_rule: ScoringRule::CPMM, + status: zeitgeist_primitives::types::MarketStatus::Disputed, + bonds: MarketBonds::default(), + } +} From 355dad64820394bebafeca0e8bd7c0a53520a6f7 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 19 Jan 2023 13:39:09 +0100 Subject: [PATCH 21/58] benchmark reserve_outcome --- primitives/src/traits/dispute_api.rs | 3 +- zrml/authorized/src/lib.rs | 4 +- zrml/authorized/src/mock.rs | 4 +- zrml/court/src/lib.rs | 4 +- zrml/court/src/mock.rs | 4 +- zrml/prediction-markets/src/migrations.rs | 1 - zrml/simple-disputes/src/benchmarks.rs | 48 +++++++++++++++++------ zrml/simple-disputes/src/lib.rs | 27 ++++++++----- zrml/simple-disputes/src/mock.rs | 4 +- zrml/simple-disputes/src/weights.rs | 44 +++++++++++---------- 10 files changed, 89 insertions(+), 54 deletions(-) diff --git a/primitives/src/traits/dispute_api.rs b/primitives/src/traits/dispute_api.rs index d61635d6b..3ef91f806 100644 --- a/primitives/src/traits/dispute_api.rs +++ b/primitives/src/traits/dispute_api.rs @@ -16,11 +16,10 @@ // along with Zeitgeist. If not, see . use crate::{ - market::MarketDispute, outcome_report::OutcomeReport, types::{Asset, Market}, }; -use frame_support::{dispatch::DispatchResult, pallet_prelude::Weight, BoundedVec}; +use frame_support::{dispatch::DispatchResult, pallet_prelude::Weight}; use parity_scale_codec::MaxEncodedLen; use sp_runtime::DispatchError; diff --git a/zrml/authorized/src/lib.rs b/zrml/authorized/src/lib.rs index 41644901c..efdd3ae40 100644 --- a/zrml/authorized/src/lib.rs +++ b/zrml/authorized/src/lib.rs @@ -46,7 +46,9 @@ mod pallet { use sp_runtime::{traits::Saturating, DispatchError}; use zeitgeist_primitives::{ traits::{DisputeApi, DisputeResolutionApi}, - types::{Asset, AuthorityReport, Market, MarketDisputeMechanism, MarketStatus, OutcomeReport}, + types::{ + Asset, AuthorityReport, Market, MarketDisputeMechanism, MarketStatus, OutcomeReport, + }, }; use zrml_market_commons::MarketCommonsPalletApi; diff --git a/zrml/authorized/src/mock.rs b/zrml/authorized/src/mock.rs index 702d57522..892ad49ac 100644 --- a/zrml/authorized/src/mock.rs +++ b/zrml/authorized/src/mock.rs @@ -38,8 +38,8 @@ use zeitgeist_primitives::{ }, traits::DisputeResolutionApi, types::{ - AccountIdTest, Asset, Balance, BlockNumber, BlockTest, Hash, Index, Market, MarketId, Moment, - UncheckedExtrinsicTest, + AccountIdTest, Asset, Balance, BlockNumber, BlockTest, Hash, Index, Market, MarketId, + Moment, UncheckedExtrinsicTest, }, }; diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index ed7ca0e36..b6254ff28 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -66,7 +66,9 @@ mod pallet { }; use zeitgeist_primitives::{ traits::{DisputeApi, DisputeResolutionApi}, - types::{Asset, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, OutcomeReport}, + types::{ + Asset, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, OutcomeReport, + }, }; use zrml_market_commons::MarketCommonsPalletApi; diff --git a/zrml/court/src/mock.rs b/zrml/court/src/mock.rs index f06ea7002..79c6e2761 100644 --- a/zrml/court/src/mock.rs +++ b/zrml/court/src/mock.rs @@ -36,8 +36,8 @@ use zeitgeist_primitives::{ }, traits::DisputeResolutionApi, types::{ - AccountIdTest, Asset, Balance, BlockNumber, BlockTest, Hash, Index, Market, MarketId, Moment, - UncheckedExtrinsicTest, + AccountIdTest, Asset, Balance, BlockNumber, BlockTest, Hash, Index, Market, MarketId, + Moment, UncheckedExtrinsicTest, }, }; diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 998f35fef..da96ef3a7 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -749,7 +749,6 @@ where { fn on_runtime_upgrade() -> Weight { use orml_traits::NamedMultiReservableCurrency; - use zeitgeist_primitives::types::Asset; let mut total_weight = T::DbWeight::get().reads(1); let pm_version = StorageVersion::get::>(); diff --git a/zrml/simple-disputes/src/benchmarks.rs b/zrml/simple-disputes/src/benchmarks.rs index a77238632..dc97b753c 100644 --- a/zrml/simple-disputes/src/benchmarks.rs +++ b/zrml/simple-disputes/src/benchmarks.rs @@ -22,32 +22,54 @@ #![allow(clippy::type_complexity)] #![cfg(feature = "runtime-benchmarks")] +#[cfg(test)] +use crate::Pallet as SimpleDisputes; + use super::*; -use frame_benchmarking::{account, benchmarks, vec, whitelisted_caller}; +use frame_benchmarking::{account, benchmarks, whitelisted_caller, Vec}; +use frame_support::{dispatch::RawOrigin, traits::Get}; +use orml_traits::MultiCurrency; +use sp_runtime::traits::{One, Saturating}; +use zrml_market_commons::MarketCommonsPalletApi; benchmarks! { reserve_outcome { let d in 1..(T::MaxDisputes::get() - 1); + let r in 1..63; let e in 1..63; let caller: T::AccountId = whitelisted_caller(); let market_id = 0u32.into(); let market = market_mock::(); - T::MarketCommons::push_market(market).unwrap(); + T::MarketCommons::push_market(market.clone()).unwrap(); - let now = >::block_number(); + let mut now; + let mut disputes = Vec::new(); for i in 0..d { + now = >::block_number(); + let disputor = account("disputor", i, 0); + let last_dispute = MarketDispute { + at: now, + by: disputor, + outcome: OutcomeReport::Scalar((2 + i).into()), + bond: default_outcome_bond::(i as usize), + }; + disputes.push(last_dispute); + >::set_block_number(now.saturating_add(T::BlockNumber::one())); + } + let last_dispute = disputes.last().unwrap(); + let auto_resolve = last_dispute.at.saturating_add(market.deadlines.dispute_duration); + for i in 0..r { + let id = T::MarketCommons::push_market(market_mock::()).unwrap(); + T::DisputeResolution::add_auto_resolve(&id, auto_resolve).unwrap(); } - let last_dispute = MarketDispute { - at: now, - by: caller.clone(), - outcome: OutcomeReport::Scalar(2), - bond: default_outcome_bond::(0usize), - }; - Disputes::::insert(market_id, last_dispute); + let now = >::block_number(); + + let bounded_vec = >::try_from(disputes).unwrap(); + Disputes::::insert(market_id, bounded_vec); let dispute_duration_ends_at_block = now.saturating_add(market.deadlines.dispute_duration); @@ -57,12 +79,12 @@ benchmarks! { } let outcome = OutcomeReport::Scalar(1); - let bond = default_outcome_bond::(0usize); - let _ = T::Currency::deposit_creating(&caller, bond); + let bond = default_outcome_bond::(T::MaxDisputes::get() as usize); + T::AssetManager::deposit(Asset::Ztg, &caller, bond).unwrap(); }: _(RawOrigin::Signed(caller.clone()), market_id, outcome) impl_benchmark_test_suite!( - PredictionMarket, + SimpleDisputes, crate::mock::ExtBuilder::default().build(), crate::mock::Runtime, ); diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index 7832b1c31..3a496dbee 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -45,7 +45,9 @@ mod pallet { use frame_support::{ dispatch::DispatchResult, ensure, - pallet_prelude::{Blake2_128Concat, DispatchResultWithPostInfo, StorageMap, ValueQuery}, + pallet_prelude::{ + Blake2_128Concat, ConstU32, DispatchResultWithPostInfo, StorageMap, ValueQuery, + }, traits::{Currency, Get, Hooks, Imbalance, IsType, NamedReservableCurrency}, transactional, BoundedVec, PalletId, }; @@ -140,6 +142,7 @@ mod pallet { >, ::MaxDisputes, >; + pub type CacheSize = ConstU32<64>; #[pallet::pallet] pub struct Pallet(PhantomData); @@ -182,7 +185,11 @@ mod pallet { #[pallet::call] impl Pallet { - #[pallet::weight(5000)] + #[pallet::weight(T::WeightInfo::reserve_outcome( + T::MaxDisputes::get(), + CacheSize::get(), + CacheSize::get(), + ))] #[transactional] pub fn reserve_outcome( origin: OriginFor, @@ -216,14 +223,15 @@ mod pallet { })?; // each dispute resets dispute_duration - Self::remove_auto_resolve(disputes.as_slice(), &market_id, &market); + let r = Self::remove_auto_resolve(disputes.as_slice(), &market_id, &market); let dispute_duration_ends_at_block = now.saturating_add(market.deadlines.dispute_duration); - T::DisputeResolution::add_auto_resolve(&market_id, dispute_duration_ends_at_block)?; + let e = + T::DisputeResolution::add_auto_resolve(&market_id, dispute_duration_ends_at_block)?; Self::deposit_event(Event::OutcomeReserved { market_id, dispute: market_dispute }); - Ok((Some(5000)).into()) + Ok((Some(T::WeightInfo::reserve_outcome(num_disputes, r, e))).into()) } } @@ -266,13 +274,14 @@ mod pallet { disputes: &[MarketDispute>], market_id: &MarketIdOf, market: &MarketOf, - ) { + ) -> u32 { if let Some(dispute_duration_ends_at_block) = Self::get_auto_resolve(disputes, market) { - T::DisputeResolution::remove_auto_resolve( + return T::DisputeResolution::remove_auto_resolve( market_id, dispute_duration_ends_at_block, ); } + 0u32 } } @@ -455,8 +464,7 @@ mod pallet { } #[cfg(any(feature = "runtime-benchmarks", test))] -pub(crate) fn market_mock() --> zeitgeist_primitives::types::Market, T::BlockNumber, MomentOf> +pub(crate) fn market_mock() -> MarketOf where T: crate::Config, { @@ -465,6 +473,7 @@ where use zeitgeist_primitives::types::{MarketBonds, ScoringRule}; zeitgeist_primitives::types::Market { + base_asset: Asset::Ztg, creation: zeitgeist_primitives::types::MarketCreation::Permissionless, creator_fee: 0, creator: T::PalletId::get().into_account_truncating(), diff --git a/zrml/simple-disputes/src/mock.rs b/zrml/simple-disputes/src/mock.rs index 4ec9d6d9c..13a47032d 100644 --- a/zrml/simple-disputes/src/mock.rs +++ b/zrml/simple-disputes/src/mock.rs @@ -34,8 +34,8 @@ use zeitgeist_primitives::{ }, traits::DisputeResolutionApi, types::{ - AccountIdTest, Amount, Asset, Balance, BasicCurrencyAdapter, BlockNumber, BlockTest, CurrencyId, - Hash, Index, Market, MarketId, Moment, UncheckedExtrinsicTest, + AccountIdTest, Amount, Asset, Balance, BasicCurrencyAdapter, BlockNumber, BlockTest, + CurrencyId, Hash, Index, Market, MarketId, Moment, UncheckedExtrinsicTest, }, }; diff --git a/zrml/simple-disputes/src/weights.rs b/zrml/simple-disputes/src/weights.rs index 248c8f7e0..354a87e83 100644 --- a/zrml/simple-disputes/src/weights.rs +++ b/zrml/simple-disputes/src/weights.rs @@ -15,25 +15,25 @@ // You should have received a copy of the GNU General Public License // along with Zeitgeist. If not, see . -//! Autogenerated weights for zrml_prediction_markets +//! Autogenerated weights for zrml_simple_disputes //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2023-01-09, STEPS: `10`, REPEAT: 1000, LOW RANGE: `[]`, HIGH RANGE: `[]` -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 +//! DATE: 2023-01-19, STEPS: `10`, REPEAT: 10, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! EXECUTION: Some(Native), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 // Executed Command: -// ./target/release/zeitgeist +// ./target/debug/zeitgeist // benchmark // pallet // --chain=dev // --steps=10 -// --repeat=1000 -// --pallet=zrml_prediction_markets +// --repeat=10 +// --pallet=zrml_simple_disputes // --extrinsic=* -// --execution=wasm +// --execution=Native // --wasm-execution=compiled // --heap-pages=4096 -// --output=./zrml/prediction-markets/src/weights.rs +// --output=./zrml/simple-disputes/src/weights2.rs // --template=./misc/weight_template.hbs #![allow(unused_parens)] @@ -43,25 +43,27 @@ use core::marker::PhantomData; use frame_support::{traits::Get, weights::Weight}; /// Trait containing the required functions for weight retrival within -/// zrml_prediction_markets (automatically generated) +/// zrml_simple_disputes (automatically generated) pub trait WeightInfoZeitgeist { - fn start_global_dispute(m: u32, n: u32) -> Weight; + fn reserve_outcome(d: u32, r: u32, e: u32) -> Weight; } +/// Weight functions for zrml_simple_disputes (automatically generated) pub struct WeightInfo(PhantomData); impl WeightInfoZeitgeist for WeightInfo { // Storage: MarketCommons Markets (r:1 w:0) - // Storage: PredictionMarkets Disputes (r:1 w:0) - // Storage: GlobalDisputes Winners (r:1 w:1) - // Storage: GlobalDisputes Outcomes (r:7 w:7) + // Storage: SimpleDisputes Disputes (r:1 w:1) + // Storage: Balances Reserves (r:1 w:1) // Storage: PredictionMarkets MarketIdsPerDisputeBlock (r:2 w:2) - fn start_global_dispute(m: u32, n: u32) -> Weight { - (94_106_000 as Weight) - // Standard Error: 0 - .saturating_add((15_000 as Weight).saturating_mul(m as Weight)) - // Standard Error: 0 - .saturating_add((20_000 as Weight).saturating_mul(n as Weight)) - .saturating_add(T::DbWeight::get().reads(12 as Weight)) - .saturating_add(T::DbWeight::get().writes(10 as Weight)) + fn reserve_outcome(d: u32, r: u32, e: u32) -> Weight { + (400_160_000 as Weight) + // Standard Error: 1_302_000 + .saturating_add((3_511_000 as Weight).saturating_mul(d as Weight)) + // Standard Error: 69_000 + .saturating_add((324_000 as Weight).saturating_mul(r as Weight)) + // Standard Error: 69_000 + .saturating_add((311_000 as Weight).saturating_mul(e as Weight)) + .saturating_add(T::DbWeight::get().reads(5 as Weight)) + .saturating_add(T::DbWeight::get().writes(4 as Weight)) } } From ee2681a73de73be15a4914b7ba044c5527df747b Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Tue, 24 Jan 2023 08:52:31 +0100 Subject: [PATCH 22/58] fix weights file --- zrml/prediction-markets/src/weights.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/zrml/prediction-markets/src/weights.rs b/zrml/prediction-markets/src/weights.rs index c47450636..76a2a0110 100644 --- a/zrml/prediction-markets/src/weights.rs +++ b/zrml/prediction-markets/src/weights.rs @@ -106,7 +106,6 @@ impl WeightInfoZeitgeist for WeightInfo { .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(a.into()))) .saturating_add(T::DbWeight::get().writes(10)) .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(a.into()))) - .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(d.into()))) } // Storage: MarketCommons Markets (r:1 w:1) // Storage: Balances Reserves (r:1 w:1) From 06314bbc92909241477267a4e0f698412e658979 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Tue, 31 Jan 2023 12:19:30 +0100 Subject: [PATCH 23/58] fix after merge --- Cargo.lock | 2 +- runtime/common/src/lib.rs | 10 +- zrml/prediction-markets/src/lib.rs | 27 +-- zrml/prediction-markets/src/migrations.rs | 197 ++++++++++++---------- zrml/prediction-markets/src/tests.rs | 26 ++- 5 files changed, 145 insertions(+), 117 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 22e66ec78..d0684752d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -396,7 +396,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide", + "miniz_oxide 0.6.2", "object 0.30.3", "rustc-demangle", ] diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 56e7b4513..f65e3c7fc 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -58,7 +58,10 @@ macro_rules! decl_common_types { frame_system::ChainContext, Runtime, AllPalletsWithSystem, - zrml_prediction_markets::migrations::AddOutsiderBond, + ( + zrml_prediction_markets::migrations::AddOutsiderAndDisputeBond, + zrml_prediction_markets::migrations::MoveDataToSimpleDisputes, + ), >; #[cfg(not(feature = "parachain"))] @@ -68,7 +71,10 @@ macro_rules! decl_common_types { frame_system::ChainContext, Runtime, AllPalletsWithSystem, - zrml_prediction_markets::migrations::AddOutsiderBond, + ( + zrml_prediction_markets::migrations::AddOutsiderAndDisputeBond, + zrml_prediction_markets::migrations::MoveDataToSimpleDisputes, + ), >; pub type Header = generic::Header; diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index f57aecdbd..1db7adc0d 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -332,6 +332,10 @@ mod pallet { let market_status = market.status; let market_account = >::market_account(market_id); + if Self::is_dispute_bond_pending(&market_id, &market, false) { + Self::unreserve_dispute_bond(&market_id)?; + } + // Slash outstanding bonds; see // https://github.com/zeitgeistpm/runtime-audit-1/issues/34#issuecomment-1120187097 for // details. @@ -2055,9 +2059,6 @@ mod pallet { if Self::is_outsider_bond_pending(market_id, market, false) { Self::slash_outsider_bond(market_id, None)?; } - if Self::is_dispute_bond_pending(market_id, market, false) { - Self::slash_dispute_bond(market_id, None)?; - } Ok(()) } @@ -2523,8 +2524,6 @@ mod pallet { let resolved_outcome = resolved_outcome_option.unwrap_or_else(|| report.outcome.clone()); - let mut overall_imbalance = >::zero(); - // If the oracle reported right, return the OracleBond, otherwise slash it to // pay the correct reporters. let mut overall_imbalance = NegativeImbalanceOf::::zero(); @@ -2569,14 +2568,16 @@ mod pallet { } let mut correct_disputor = None; - if Self::is_dispute_bond_pending(market_id, market, false) { - if is_correct { - let imb = Self::slash_dispute_bond(market_id, None)?; - overall_imbalance.subsume(imb); - } else { - // If the report outcome was wrong, the dispute was justified - Self::unreserve_dispute_bond(market_id)?; - correct_disputor = Some(bond.who); + if let Some(bond) = market.bonds.dispute.clone() { + if !bond.is_settled { + if is_correct { + let imb = Self::slash_dispute_bond(market_id, None)?; + overall_imbalance.subsume(imb); + } else { + // If the report outcome was wrong, the dispute was justified + Self::unreserve_dispute_bond(market_id)?; + correct_disputor = Some(bond.who); + } } } diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index f3e2fe6ae..c9b1629f0 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -41,9 +41,7 @@ use zeitgeist_primitives::types::{ Asset, Bond, Deadlines, Market, MarketBonds, MarketCreation, MarketDisputeMechanism, MarketPeriod, MarketStatus, MarketType, OutcomeReport, Report, ScoringRule, }; -#[cfg(feature = "try-runtime")] -use zrml_market_commons::MarketCommonsPalletApi; -use zrml_market_commons::Pallet as MarketCommonsPallet; +use zrml_market_commons::{MarketCommonsPalletApi, Pallet as MarketCommonsPallet}; #[cfg(any(feature = "try-runtime", test))] const MARKET_COMMONS: &[u8] = b"MarketCommons"; @@ -111,35 +109,53 @@ impl OnRuntimeUpgrade for AddOutsiderAn log::info!("AddOutsiderAndDisputeBond: Starting..."); let mut translated = 0u64; - zrml_market_commons::Markets::::translate::, _>(|_key, old_market| { - translated.saturating_inc(); - - let new_market = Market { - base_asset: old_market.base_asset, - creator: old_market.creator, - creation: old_market.creation, - creator_fee: old_market.creator_fee, - oracle: old_market.oracle, - metadata: old_market.metadata, - market_type: old_market.market_type, - period: old_market.period, - scoring_rule: old_market.scoring_rule, - status: old_market.status, - report: old_market.report, - resolved_outcome: old_market.resolved_outcome, - dispute_mechanism: old_market.dispute_mechanism, - deadlines: old_market.deadlines, - bonds: MarketBonds { - creation: old_market.bonds.creation, - oracle: old_market.bonds.oracle, - outsider: None, - // TODO - dispute: None, - }, - }; - - Some(new_market) - }); + zrml_market_commons::Markets::::translate::, _>( + |market_id, old_market| { + translated.saturating_inc(); + + let mut dispute_bond = None; + // SimpleDisputes is regarded in the following migration `MoveDataToSimpleDisputes` + if let MarketDisputeMechanism::Authorized = old_market.dispute_mechanism { + total_weight = total_weight.saturating_add(T::DbWeight::get().reads(1)); + let old_disputes = crate::Disputes::::get(market_id); + if let Some(first_dispute) = old_disputes.first() { + let OldMarketDispute { at: _, by, outcome: _ } = first_dispute; + dispute_bond = Some(Bond::new(by.clone(), T::DisputeBond::get())); + } else { + log::warn!( + "MoveDataToSimpleDisputes: Could not find first dispute for market id \ + {:?}", + market_id + ); + } + } + + let new_market = Market { + base_asset: old_market.base_asset, + creator: old_market.creator, + creation: old_market.creation, + creator_fee: old_market.creator_fee, + oracle: old_market.oracle, + metadata: old_market.metadata, + market_type: old_market.market_type, + period: old_market.period, + scoring_rule: old_market.scoring_rule, + status: old_market.status, + report: old_market.report, + resolved_outcome: old_market.resolved_outcome, + dispute_mechanism: old_market.dispute_mechanism, + deadlines: old_market.deadlines, + bonds: MarketBonds { + creation: old_market.bonds.creation, + oracle: old_market.bonds.oracle, + outsider: None, + dispute: dispute_bond, + }, + }; + + Some(new_market) + }, + ); log::info!("AddOutsiderAndDisputeBond: Upgraded {} markets.", translated); total_weight = total_weight.saturating_add(T::DbWeight::get().reads_writes(translated, translated)); @@ -202,12 +218,31 @@ impl OnRuntimeUpgrade for AddOutsiderAn assert_eq!(new_market.dispute_mechanism, old_market.dispute_mechanism); assert_eq!(new_market.bonds.oracle, old_market.bonds.oracle); assert_eq!(new_market.bonds.creation, old_market.bonds.creation); - // new field + // new fields assert_eq!(new_market.bonds.outsider, None); - // TODO - assert_eq!(new_market.bonds.dispute, None); + // other dispute mechanisms are regarded in the migration after this migration + if let MarketDisputeMechanism::Authorized = new_market.dispute_mechanism { + let old_disputes = crate::Disputes::::get(market_id); + if let Some(first_dispute) = old_disputes.first() { + let OldMarketDispute { at: _, by, outcome: _ } = first_dispute; + assert_eq!( + new_market.bonds.dispute, + Some(Bond { + who: by.clone(), + value: T::DisputeBond::get(), + is_settled: false + }) + ); + } + } else { + assert_eq!(new_market.bonds.dispute, None); + } } - log::info!("AddOutsiderAndDisputeBond: Market Counter post-upgrade is {}!", new_market_count); + + log::info!( + "AddOutsiderAndDisputeBond: Market Counter post-upgrade is {}!", + new_market_count + ); assert!(new_market_count > 0); Ok(()) } @@ -217,7 +252,7 @@ impl OnRuntimeUpgrade for AddOutsiderAn mod tests { use super::*; use crate::{ - mock::{ExtBuilder, Runtime}, + mock::{DisputeBond, ExtBuilder, Runtime}, MarketIdOf, MarketOf, }; use frame_support::{ @@ -229,7 +264,7 @@ mod tests { fn on_runtime_upgrade_increments_the_storage_version() { ExtBuilder::default().build().execute_with(|| { set_up_version(); - AddOutsiderBond::::on_runtime_upgrade(); + AddOutsiderAndDisputeBond::::on_runtime_upgrade(); assert_eq!( StorageVersion::get::>(), MARKET_COMMONS_NEXT_STORAGE_VERSION @@ -241,29 +276,51 @@ mod tests { fn on_runtime_upgrade_is_noop_if_versions_are_not_correct() { ExtBuilder::default().build().execute_with(|| { // Don't set up chain to signal that storage is already up to date. - let (_, new_markets) = construct_old_new_tuple(); + let (_, new_markets) = construct_old_new_tuple(None); populate_test_data::, MarketOf>( MARKET_COMMONS, MARKETS, new_markets.clone(), ); - AddOutsiderBond::::on_runtime_upgrade(); + AddOutsiderAndDisputeBond::::on_runtime_upgrade(); let actual = >::market(&0u128).unwrap(); assert_eq!(actual, new_markets[0]); }); } #[test] - fn on_runtime_upgrade_correctly_updates_markets() { + fn on_runtime_upgrade_correctly_updates_markets_with_none_disputor() { ExtBuilder::default().build().execute_with(|| { set_up_version(); - let (old_markets, new_markets) = construct_old_new_tuple(); + let (old_markets, new_markets) = construct_old_new_tuple(None); populate_test_data::, OldMarketOf>( MARKET_COMMONS, MARKETS, old_markets, ); - AddOutsiderBond::::on_runtime_upgrade(); + AddOutsiderAndDisputeBond::::on_runtime_upgrade(); + let actual = >::market(&0u128).unwrap(); + assert_eq!(actual, new_markets[0]); + }); + } + + #[test] + fn on_runtime_upgrade_correctly_updates_markets_with_some_disputor() { + ExtBuilder::default().build().execute_with(|| { + set_up_version(); + let mut disputes = crate::Disputes::::get(0); + let disputor = crate::mock::EVE; + let dispute = + OldMarketDispute { at: 0, by: disputor, outcome: OutcomeReport::Categorical(0u16) }; + disputes.try_push(dispute).unwrap(); + crate::Disputes::::insert(0, disputes); + let (old_markets, new_markets) = construct_old_new_tuple(Some(disputor)); + populate_test_data::, OldMarketOf>( + MARKET_COMMONS, + MARKETS, + old_markets, + ); + AddOutsiderAndDisputeBond::::on_runtime_upgrade(); let actual = >::market(&0u128).unwrap(); assert_eq!(actual, new_markets[0]); }); @@ -274,7 +331,9 @@ mod tests { .put::>(); } - fn construct_old_new_tuple() -> (Vec>, Vec>) { + fn construct_old_new_tuple( + disputor: Option, + ) -> (Vec>, Vec>) { let base_asset = Asset::Ztg; let creator = 999; let creator_fee = 1; @@ -293,12 +352,12 @@ mod tests { creation: Some(Bond::new(creator, ::ValidityBond::get())), oracle: Some(Bond::new(creator, ::OracleBond::get())), }; + let dispute_bond = disputor.map(|disputor| Bond::new(disputor, DisputeBond::get())); let new_bonds = MarketBonds { creation: Some(Bond::new(creator, ::ValidityBond::get())), oracle: Some(Bond::new(creator, ::OracleBond::get())), outsider: None, - // TODO - dispute: None, + dispute: dispute_bond, }; let old_market = OldMarket { @@ -353,11 +412,8 @@ mod tests { } } -#[cfg(feature = "try-runtime")] -use alloc::string::ToString; -use zrml_market_commons::MarketCommonsPalletApi; -use sp_runtime::SaturatedConversion; use frame_support::dispatch::EncodeLike; +use sp_runtime::SaturatedConversion; use zeitgeist_primitives::types::{MarketDispute, OldMarketDispute}; const PREDICTION_MARKETS_REQUIRED_STORAGE_VERSION: u16 = 7; @@ -398,39 +454,16 @@ where total_weight = total_weight.saturating_add(T::DbWeight::get().reads(1)); + // important drain disputes storage item from prediction markets pallet for (market_id, old_disputes) in crate::Disputes::::drain() { total_weight = total_weight.saturating_add(T::DbWeight::get().writes(1)); total_weight = total_weight.saturating_add(T::DbWeight::get().reads(1)); - if let Ok(mut market) = >::market(&market_id) { + if let Ok(market) = >::market(&market_id) { match market.dispute_mechanism { - MarketDisputeMechanism::Authorized => { - // TODO Move this part of the migration (market mutation) - // TODO into the OutsiderBond migration (needs to run before this migration) - // TODO because it needs to iterate over all Disputes of the pm pallet - // TODO in this current migration we drain all Disputes of the pm pallet - if let Some(first_dispute) = old_disputes.first() { - let OldMarketDispute { at: _, by, outcome: _ } = first_dispute; - market.bonds.dispute = - Some(Bond::new(by.clone(), T::DisputeBond::get())); - - total_weight = - total_weight.saturating_add(T::DbWeight::get().writes(1)); - zrml_market_commons::Markets::::insert(market_id, market); - } else { - log::warn!( - "MoveDataToSimpleDisputes: Could not find first dispute for \ - market id {:?}", - market_id - ); - } - // for authorized use the first dispute as actual dispute caller - continue; - } - // for simple-disputes ignore who called the dispute the first time - // and just use the below code to fill Disputes inside simple-disputes + MarketDisputeMechanism::Authorized => continue, + // just transform SimpleDispute disputes MarketDisputeMechanism::SimpleDisputes => (), - // ignore / delete all disputes for court markets MarketDisputeMechanism::Court => continue, } } else { @@ -544,16 +577,6 @@ where match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { - let first_dispute = o - .first() - .expect(&format!("First dispute for market {:?} not found", market_id)[..]); - let disputor = first_dispute.by.clone(); - let bond = T::DisputeBond::get(); - assert_eq!( - market.bonds.dispute, - Some(Bond { who: disputor, value: bond, is_settled: false }), - ); - let simple_disputes_count = disputes.iter().count(); assert_eq!(simple_disputes_count, 0); continue; diff --git a/zrml/prediction-markets/src/tests.rs b/zrml/prediction-markets/src/tests.rs index 924e725e2..9f2a5e7b0 100644 --- a/zrml/prediction-markets/src/tests.rs +++ b/zrml/prediction-markets/src/tests.rs @@ -4250,24 +4250,21 @@ fn outsider_reports_wrong_outcome() { let dispute_at_0 = report_at + 1; run_to_block(dispute_at_0); - let eve_reserved = Balances::reserved_balance(&EVE); - - assert_ok!(PredictionMarkets::dispute( - Origin::signed(EVE), - 0, - )); + assert_ok!(PredictionMarkets::dispute(Origin::signed(EVE), 0,)); + check_reserve(&EVE, DisputeBond::get()); - assert_eq!(eve_reserved, DisputeBond::get()); - assert_ok!(SimpleDisputes::reserve_outcome( - Origin::signed(EVE), + Origin::signed(DAVE), 0, OutcomeReport::Categorical(0) )); - - assert_eq!(eve_reserved, DisputeBond::get() + zrml_simple_disputes::default_outcome_bond::(0)); + + let outcome_bond = zrml_simple_disputes::default_outcome_bond::(0); + + check_reserve(&DAVE, outcome_bond); let eve_balance_before = Balances::free_balance(&EVE); + let dave_balance_before = Balances::free_balance(&DAVE); // on_resolution called run_blocks(market.deadlines.dispute_duration); @@ -4277,12 +4274,13 @@ fn outsider_reports_wrong_outcome() { check_reserve(&outsider, 0); assert_eq!(Balances::free_balance(&outsider), outsider_balance_before); - let dispute_bond = crate::default_dispute_bond::(0usize); - // disputor EVE gets the OracleBond and OutsiderBond and dispute bond + // disputor EVE gets the OracleBond and OutsiderBond and DisputeBond assert_eq!( Balances::free_balance(&EVE), - eve_balance_before + dispute_bond + OutsiderBond::get() + OracleBond::get() + eve_balance_before + DisputeBond::get() + OutsiderBond::get() + OracleBond::get() ); + // DAVE gets his outcome bond back + assert_eq!(Balances::free_balance(&DAVE), dave_balance_before + outcome_bond); }; ExtBuilder::default().build().execute_with(|| { test(Asset::Ztg); From 78f0b0301dba795c5f2d6bc2e7b89bc2724168ad Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Tue, 31 Jan 2023 14:38:57 +0100 Subject: [PATCH 24/58] add migration tests --- zrml/prediction-markets/src/migrations.rs | 161 ++++++++++++++++++++++ 1 file changed, 161 insertions(+) diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index c9b1629f0..f75520be2 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -628,6 +628,167 @@ where } } +#[cfg(test)] +mod tests_simple_disputes_migration { + use super::*; + use crate::{ + mock::{DisputeBond, ExtBuilder, Runtime}, + MarketOf, + }; + use zrml_market_commons::MarketCommonsPalletApi; + + #[test] + fn on_runtime_upgrade_increments_the_storage_version() { + ExtBuilder::default().build().execute_with(|| { + set_up_version(); + MoveDataToSimpleDisputes::::on_runtime_upgrade(); + assert_eq!( + StorageVersion::get::>(), + PREDICTION_MARKETS_NEXT_STORAGE_VERSION + ); + }); + } + + #[test] + fn on_runtime_upgrade_is_noop_if_versions_are_not_correct() { + ExtBuilder::default().build().execute_with(|| { + // Don't set up chain to signal that storage is already up to date. + let market_id = 0u128; + let mut disputes = zrml_simple_disputes::Disputes::::get(market_id); + let dispute = MarketDispute { + at: 42u64, + by: 0u128, + outcome: OutcomeReport::Categorical(0u16), + bond: DisputeBond::get(), + }; + disputes.try_push(dispute.clone()).unwrap(); + zrml_simple_disputes::Disputes::::insert(market_id, disputes); + let market = get_market(MarketDisputeMechanism::SimpleDisputes); + >::push_market(market).unwrap(); + + MoveDataToSimpleDisputes::::on_runtime_upgrade(); + + let actual = zrml_simple_disputes::Disputes::::get(0); + assert_eq!(actual, vec![dispute]); + }); + } + + #[test] + fn on_runtime_upgrade_correctly_updates_simple_disputes() { + ExtBuilder::default().build().execute_with(|| { + set_up_version(); + let market_id = 0u128; + + let mut disputes = crate::Disputes::::get(0); + for i in 0..::MaxDisputes::get() { + let dispute = OldMarketDispute { + at: i as u64 + 42u64, + by: i as u128, + outcome: OutcomeReport::Categorical(i as u16), + }; + disputes.try_push(dispute).unwrap(); + } + crate::Disputes::::insert(market_id, disputes); + let market = get_market(MarketDisputeMechanism::SimpleDisputes); + >::push_market(market).unwrap(); + + MoveDataToSimpleDisputes::::on_runtime_upgrade(); + + let mut disputes = zrml_simple_disputes::Disputes::::get(market_id); + for i in 0..::MaxDisputes::get() { + let dispute = disputes.get_mut(i as usize).unwrap(); + + assert_eq!(dispute.at, i as u64 + 42u64); + assert_eq!(dispute.by, i as u128); + assert_eq!(dispute.outcome, OutcomeReport::Categorical(i as u16)); + + let bond = zrml_simple_disputes::default_outcome_bond::(i as usize); + assert_eq!(dispute.bond, bond); + } + }); + } + + #[test] + fn on_runtime_upgrade_correctly_updates_reserve_ids() { + ExtBuilder::default().build().execute_with(|| { + set_up_version(); + let market_id = 0u128; + + let mut disputes = crate::Disputes::::get(0); + for i in 0..::MaxDisputes::get() { + let dispute = OldMarketDispute { + at: i as u64 + 42u64, + by: i as u128, + outcome: OutcomeReport::Categorical(i as u16), + }; + disputes.try_push(dispute).unwrap(); + } + crate::Disputes::::insert(market_id, disputes); + let market = get_market(MarketDisputeMechanism::SimpleDisputes); + >::push_market(market).unwrap(); + + MoveDataToSimpleDisputes::::on_runtime_upgrade(); + + let mut disputes = zrml_simple_disputes::Disputes::::get(market_id); + for i in 0..::MaxDisputes::get() { + let dispute = disputes.get_mut(i as usize).unwrap(); + + assert_eq!(dispute.at, i as u64 + 42u64); + assert_eq!(dispute.by, i as u128); + assert_eq!(dispute.outcome, OutcomeReport::Categorical(i as u16)); + + let bond = zrml_simple_disputes::default_outcome_bond::(i as usize); + assert_eq!(dispute.bond, bond); + } + }); + } + + fn set_up_version() { + StorageVersion::new(PREDICTION_MARKETS_REQUIRED_STORAGE_VERSION) + .put::>(); + } + + fn get_market(dispute_mechanism: MarketDisputeMechanism) -> MarketOf { + let base_asset = Asset::Ztg; + let creator = 999; + let creator_fee = 1; + let oracle = 2; + let metadata = vec![3, 4, 5]; + let market_type = MarketType::Categorical(6); + let period = MarketPeriod::Block(7..8); + let scoring_rule = ScoringRule::CPMM; + let status = MarketStatus::Disputed; + let creation = MarketCreation::Permissionless; + let report = None; + let resolved_outcome = None; + let deadlines = Deadlines::default(); + let bonds = MarketBonds { + creation: Some(Bond::new(creator, ::ValidityBond::get())), + oracle: Some(Bond::new(creator, ::OracleBond::get())), + outsider: None, + dispute: None, + }; + + Market { + base_asset, + creator, + creation, + creator_fee, + oracle, + metadata, + market_type, + period, + scoring_rule, + status, + report, + resolved_outcome, + dispute_mechanism, + deadlines, + bonds, + } + } +} + // We use these utilities to prevent having to make the swaps pallet a dependency of // prediciton-markets. The calls are based on the implementation of `StorageVersion`, found here: // https://github.com/paritytech/substrate/blob/bc7a1e6c19aec92bfa247d8ca68ec63e07061032/frame/support/src/traits/metadata.rs#L168-L230 From 84bb0214ec2348342ed0f9c02f9699bb1e390d43 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Tue, 31 Jan 2023 16:53:52 +0100 Subject: [PATCH 25/58] add migration reserve id test --- zrml/prediction-markets/src/migrations.rs | 35 +++++++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index f75520be2..5c4507fbb 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -635,6 +635,7 @@ mod tests_simple_disputes_migration { mock::{DisputeBond, ExtBuilder, Runtime}, MarketOf, }; + use orml_traits::NamedMultiReservableCurrency; use zrml_market_commons::MarketCommonsPalletApi; #[test] @@ -721,6 +722,15 @@ mod tests_simple_disputes_migration { by: i as u128, outcome: OutcomeReport::Categorical(i as u16), }; + let bond = zrml_simple_disputes::default_outcome_bond::(i.into()); + let pm_reserve_id = crate::Pallet::::reserve_id(); + let res = ::AssetManager::reserve_named( + &pm_reserve_id, + Asset::Ztg, + &dispute.by, + bond.saturated_into::().saturated_into(), + ); + assert!(res.is_ok()); disputes.try_push(dispute).unwrap(); } crate::Disputes::::insert(market_id, disputes); @@ -733,12 +743,25 @@ mod tests_simple_disputes_migration { for i in 0..::MaxDisputes::get() { let dispute = disputes.get_mut(i as usize).unwrap(); - assert_eq!(dispute.at, i as u64 + 42u64); - assert_eq!(dispute.by, i as u128); - assert_eq!(dispute.outcome, OutcomeReport::Categorical(i as u16)); - - let bond = zrml_simple_disputes::default_outcome_bond::(i as usize); - assert_eq!(dispute.bond, bond); + let sd_reserve_id = zrml_simple_disputes::Pallet::::reserve_id(); + let reserved_balance = + ::AssetManager::reserved_balance_named( + &sd_reserve_id, + Asset::Ztg, + &dispute.by, + ); + let bond = zrml_simple_disputes::default_outcome_bond::(i.into()); + assert_eq!(reserved_balance, bond); + assert!(reserved_balance > 0); + + let pm_reserve_id = crate::Pallet::::reserve_id(); + let reserved_balance = + ::AssetManager::reserved_balance_named( + &pm_reserve_id, + Asset::Ztg, + &dispute.by, + ); + assert_eq!(reserved_balance, 0); } }); } From c3c5ca6baee310aa05a7c99758db614d372f988c Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 2 Mar 2023 10:52:16 +0100 Subject: [PATCH 26/58] apply review suggestions --- primitives/src/traits/dispute_api.rs | 14 ++++++++------ zrml/authorized/src/lib.rs | 4 ++-- zrml/authorized/src/tests.rs | 15 ++++++--------- zrml/court/src/lib.rs | 4 ++-- zrml/court/src/tests.rs | 28 ++++++++++++++-------------- zrml/prediction-markets/src/lib.rs | 16 ++++++---------- zrml/simple-disputes/src/lib.rs | 4 ++-- zrml/simple-disputes/src/tests.rs | 8 ++++---- 8 files changed, 44 insertions(+), 49 deletions(-) diff --git a/primitives/src/traits/dispute_api.rs b/primitives/src/traits/dispute_api.rs index 3ef91f806..adc6e763f 100644 --- a/primitives/src/traits/dispute_api.rs +++ b/primitives/src/traits/dispute_api.rs @@ -57,21 +57,22 @@ pub trait DisputeApi { /// /// Returns the dispute mechanism's report if available, otherwise `None`. If `None` is /// returned, this means that the dispute could not be resolved. - fn get_resolution_outcome( + fn on_resolution( market_id: &Self::MarketId, market: &MarketOfDisputeApi, ) -> Result, DispatchError>; - /// Allow the flow of funds to the market dispute mechanism. + /// Allow the transfer of funds from the API caller to the API consumer and back. + /// This can be based on the final resolution outcome of the market. /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. /// /// # Returns - /// Returns the negative imbalance which is meant to be used for the treasury. - fn maybe_pay( + /// Returns a negative imbalance back to the caller. + fn exchange( market_id: &Self::MarketId, market: &MarketOfDisputeApi, resolved_outcome: &OutcomeReport, - overall_imbalance: Self::NegativeImbalance, + amount: Self::NegativeImbalance, ) -> Result; /// Query the future resolution block of a disputed market. @@ -100,7 +101,8 @@ pub trait DisputeApi { market: &MarketOfDisputeApi, ) -> DispatchResult; - /// Called, when a market is destroyed. + /// Allow the API consumer to clear storage items of the dispute mechanism. + /// This may be called, when the dispute mechanism is no longer needed. /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. fn clear(market_id: &Self::MarketId, market: &MarketOfDisputeApi) -> DispatchResult; } diff --git a/zrml/authorized/src/lib.rs b/zrml/authorized/src/lib.rs index efdd3ae40..b47ebf31d 100644 --- a/zrml/authorized/src/lib.rs +++ b/zrml/authorized/src/lib.rs @@ -213,7 +213,7 @@ mod pallet { Ok(()) } - fn get_resolution_outcome( + fn on_resolution( market_id: &Self::MarketId, market: &MarketOf, ) -> Result, DispatchError> { @@ -225,7 +225,7 @@ mod pallet { Ok(report.map(|r| r.outcome)) } - fn maybe_pay( + fn exchange( _: &Self::MarketId, market: &MarketOf, _: &OutcomeReport, diff --git a/zrml/authorized/src/tests.rs b/zrml/authorized/src/tests.rs index a49095014..4c5550000 100644 --- a/zrml/authorized/src/tests.rs +++ b/zrml/authorized/src/tests.rs @@ -157,15 +157,15 @@ fn authorize_market_outcome_fails_on_unauthorized_account() { } #[test] -fn get_resolution_outcome_fails_if_no_report_was_submitted() { +fn on_resolution_fails_if_no_report_was_submitted() { ExtBuilder::default().build().execute_with(|| { - let report = Authorized::get_resolution_outcome(&0, &market_mock::()).unwrap(); + let report = Authorized::on_resolution(&0, &market_mock::()).unwrap(); assert!(report.is_none()); }); } #[test] -fn get_resolution_outcome_removes_stored_outcomes() { +fn on_resolution_removes_stored_outcomes() { ExtBuilder::default().build().execute_with(|| { let market = market_mock::(); Markets::::insert(0, &market); @@ -174,13 +174,13 @@ fn get_resolution_outcome_removes_stored_outcomes() { 0, OutcomeReport::Scalar(2) )); - assert_ok!(Authorized::get_resolution_outcome(&0, &market)); + assert_ok!(Authorized::on_resolution(&0, &market)); assert_eq!(AuthorizedOutcomeReports::::get(0), None); }); } #[test] -fn get_resolution_outcome_returns_the_reported_outcome() { +fn on_resolution_returns_the_reported_outcome() { ExtBuilder::default().build().execute_with(|| { let market = market_mock::(); Markets::::insert(0, &market); @@ -195,10 +195,7 @@ fn get_resolution_outcome_returns_the_reported_outcome() { 0, OutcomeReport::Scalar(2) )); - assert_eq!( - Authorized::get_resolution_outcome(&0, &market).unwrap(), - Some(OutcomeReport::Scalar(2)) - ); + assert_eq!(Authorized::on_resolution(&0, &market).unwrap(), Some(OutcomeReport::Scalar(2))); }); } diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index b6254ff28..46eb59206 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -563,7 +563,7 @@ mod pallet { // rewarded if sided on the most voted outcome but jurors that voted second most // voted outcome (winner of the losing majority) are placed as tardy instead of // being slashed. - fn get_resolution_outcome( + fn on_resolution( market_id: &Self::MarketId, market: &MarketOf, ) -> Result, DispatchError> { @@ -591,7 +591,7 @@ mod pallet { Ok(Some(first)) } - fn maybe_pay( + fn exchange( _: &Self::MarketId, market: &MarketOf, _: &OutcomeReport, diff --git a/zrml/court/src/tests.rs b/zrml/court/src/tests.rs index 72aeb6b30..1ac6b9d2a 100644 --- a/zrml/court/src/tests.rs +++ b/zrml/court/src/tests.rs @@ -139,12 +139,12 @@ fn on_dispute_denies_non_court_markets() { } #[test] -fn get_resolution_outcome_denies_non_court_markets() { +fn on_resolution_denies_non_court_markets() { ExtBuilder::default().build().execute_with(|| { let mut market = DEFAULT_MARKET; market.dispute_mechanism = MarketDisputeMechanism::SimpleDisputes; assert_noop!( - Court::get_resolution_outcome(&0, &market), + Court::on_resolution(&0, &market), Error::::MarketDoesNotHaveCourtMechanism ); }); @@ -168,7 +168,7 @@ fn appeal_stores_jurors_that_should_vote() { // Alice is the winner, Bob is tardy and Charlie is the loser #[test] -fn get_resolution_outcome_awards_winners_and_slashes_losers() { +fn on_resolution_awards_winners_and_slashes_losers() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); Court::join_court(Origin::signed(ALICE)).unwrap(); @@ -179,7 +179,7 @@ fn get_resolution_outcome_awards_winners_and_slashes_losers() { Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(2)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(3)).unwrap(); - let _ = Court::get_resolution_outcome(&0, &DEFAULT_MARKET).unwrap(); + let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(Balances::free_balance(ALICE), 998 * BASE + 3 * BASE); assert_eq!(Balances::reserved_balance_named(&Court::reserve_id(), &ALICE), 2 * BASE); assert_eq!(Balances::free_balance(BOB), 996 * BASE); @@ -190,7 +190,7 @@ fn get_resolution_outcome_awards_winners_and_slashes_losers() { } #[test] -fn get_resolution_outcome_decides_market_outcome_based_on_the_majority() { +fn on_resolution_decides_market_outcome_based_on_the_majority() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); Court::join_court(Origin::signed(ALICE)).unwrap(); @@ -201,13 +201,13 @@ fn get_resolution_outcome_decides_market_outcome_based_on_the_majority() { Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); - let outcome = Court::get_resolution_outcome(&0, &DEFAULT_MARKET).unwrap(); + let outcome = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(outcome, Some(OutcomeReport::Scalar(1))); }); } #[test] -fn get_resolution_outcome_sets_late_jurors_as_tardy() { +fn on_resolution_sets_late_jurors_as_tardy() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); Court::join_court(Origin::signed(ALICE)).unwrap(); @@ -215,14 +215,14 @@ fn get_resolution_outcome_sets_late_jurors_as_tardy() { Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); MarketCommons::push_market(DEFAULT_MARKET).unwrap(); Court::appeal(Origin::signed(ALICE), 0).unwrap(); - let _ = Court::get_resolution_outcome(&0, &DEFAULT_MARKET).unwrap(); + let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(Jurors::::get(ALICE).unwrap().status, JurorStatus::Ok); assert_eq!(Jurors::::get(BOB).unwrap().status, JurorStatus::Tardy); }); } #[test] -fn get_resolution_outcome_sets_jurors_that_voted_on_the_second_most_voted_outcome_as_tardy() { +fn on_resolution_sets_jurors_that_voted_on_the_second_most_voted_outcome_as_tardy() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); Court::join_court(Origin::signed(ALICE)).unwrap(); @@ -233,13 +233,13 @@ fn get_resolution_outcome_sets_jurors_that_voted_on_the_second_most_voted_outcom Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); - let _ = Court::get_resolution_outcome(&0, &DEFAULT_MARKET).unwrap(); + let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(Jurors::::get(CHARLIE).unwrap().status, JurorStatus::Tardy); }); } #[test] -fn get_resolution_outcome_punishes_tardy_jurors_that_failed_to_vote_a_second_time() { +fn on_resolution_punishes_tardy_jurors_that_failed_to_vote_a_second_time() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); Court::join_court(Origin::signed(ALICE)).unwrap(); @@ -248,7 +248,7 @@ fn get_resolution_outcome_punishes_tardy_jurors_that_failed_to_vote_a_second_tim Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); MarketCommons::push_market(DEFAULT_MARKET).unwrap(); Court::appeal(Origin::signed(ALICE), 0).unwrap(); - let _ = Court::get_resolution_outcome(&0, &DEFAULT_MARKET).unwrap(); + let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); let join_court_stake = 40000000000; let slash = join_court_stake / 5; assert_eq!(Balances::free_balance(Court::treasury_account_id()), INITIAL_BALANCE + slash); @@ -258,7 +258,7 @@ fn get_resolution_outcome_punishes_tardy_jurors_that_failed_to_vote_a_second_tim } #[test] -fn get_resolution_outcome_removes_requested_jurors_and_votes() { +fn on_resolution_removes_requested_jurors_and_votes() { ExtBuilder::default().build().execute_with(|| { setup_blocks(2); Court::join_court(Origin::signed(ALICE)).unwrap(); @@ -269,7 +269,7 @@ fn get_resolution_outcome_removes_requested_jurors_and_votes() { Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); - let _ = Court::get_resolution_outcome(&0, &DEFAULT_MARKET).unwrap(); + let _ = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); assert_eq!(RequestedJurors::::iter().count(), 0); assert_eq!(Votes::::iter().count(), 0); }); diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 1db7adc0d..ec04812e7 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -2510,13 +2510,11 @@ mod pallet { if resolved_outcome_option.is_none() { resolved_outcome_option = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { - T::Authorized::get_resolution_outcome(market_id, market)? - } - MarketDisputeMechanism::Court => { - T::Court::get_resolution_outcome(market_id, market)? + T::Authorized::on_resolution(market_id, market)? } + MarketDisputeMechanism::Court => T::Court::on_resolution(market_id, market)?, MarketDisputeMechanism::SimpleDisputes => { - T::SimpleDisputes::get_resolution_outcome(market_id, market)? + T::SimpleDisputes::on_resolution(market_id, market)? } }; } @@ -2583,21 +2581,19 @@ mod pallet { let mut imbalance_left = >::zero(); if let Some(disputor) = correct_disputor { - // TODO: The disputor gets at most the outsider and oracle bond. Is okay? CurrencyOf::::resolve_creating(&disputor, overall_imbalance); } else { - // TODO: The MDMs get at most the slashed dispute bond. Is okay? imbalance_left = overall_imbalance; } let remainder = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { - T::Authorized::maybe_pay(market_id, market, &resolved_outcome, imbalance_left)? + T::Authorized::exchange(market_id, market, &resolved_outcome, imbalance_left)? } MarketDisputeMechanism::Court => { - T::Court::maybe_pay(market_id, market, &resolved_outcome, imbalance_left)? + T::Court::exchange(market_id, market, &resolved_outcome, imbalance_left)? } - MarketDisputeMechanism::SimpleDisputes => T::SimpleDisputes::maybe_pay( + MarketDisputeMechanism::SimpleDisputes => T::SimpleDisputes::exchange( market_id, market, &resolved_outcome, diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index 3a496dbee..5c5fcecd2 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -305,7 +305,7 @@ mod pallet { Ok(()) } - fn get_resolution_outcome( + fn on_resolution( market_id: &Self::MarketId, market: &MarketOf, ) -> Result, DispatchError> { @@ -326,7 +326,7 @@ mod pallet { Ok(Some(last_dispute.outcome.clone())) } - fn maybe_pay( + fn exchange( market_id: &Self::MarketId, market: &MarketOf, resolved_outcome: &OutcomeReport, diff --git a/zrml/simple-disputes/src/tests.rs b/zrml/simple-disputes/src/tests.rs index 5480063b6..71b8d929e 100644 --- a/zrml/simple-disputes/src/tests.rs +++ b/zrml/simple-disputes/src/tests.rs @@ -62,19 +62,19 @@ fn on_dispute_denies_non_simple_disputes_markets() { } #[test] -fn get_resolution_outcome_denies_non_simple_disputes_markets() { +fn on_resolution_denies_non_simple_disputes_markets() { ExtBuilder::default().build().execute_with(|| { let mut market = DEFAULT_MARKET; market.dispute_mechanism = MarketDisputeMechanism::Court; assert_noop!( - SimpleDisputes::get_resolution_outcome(&0, &market), + SimpleDisputes::on_resolution(&0, &market), Error::::MarketDoesNotHaveSimpleDisputesMechanism ); }); } #[test] -fn get_resolution_outcome_sets_the_last_dispute_of_disputed_markets_as_the_canonical_outcome() { +fn on_resolution_sets_the_last_dispute_of_disputed_markets_as_the_canonical_outcome() { ExtBuilder::default().build().execute_with(|| { let mut market = DEFAULT_MARKET; market.status = MarketStatus::Disputed; @@ -98,7 +98,7 @@ fn get_resolution_outcome_sets_the_last_dispute_of_disputed_markets_as_the_canon .unwrap(); Disputes::::insert(0, &disputes); assert_eq!( - &SimpleDisputes::get_resolution_outcome(&0, &market).unwrap().unwrap(), + &SimpleDisputes::on_resolution(&0, &market).unwrap().unwrap(), &disputes.last().unwrap().outcome ) }); From 5d873d218d42005cfc97e18168da4d846ad55bf5 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 2 Mar 2023 11:05:09 +0100 Subject: [PATCH 27/58] rename reserve_outcome to suggest_outcome --- zrml/prediction-markets/src/benchmarks.rs | 2 +- zrml/prediction-markets/src/tests.rs | 38 +++++++++++------------ zrml/simple-disputes/src/benchmarks.rs | 2 +- zrml/simple-disputes/src/lib.rs | 6 ++-- zrml/simple-disputes/src/tests.rs | 2 +- zrml/simple-disputes/src/weights.rs | 4 +-- 6 files changed, 27 insertions(+), 27 deletions(-) diff --git a/zrml/prediction-markets/src/benchmarks.rs b/zrml/prediction-markets/src/benchmarks.rs index 3abf3d742..2e3a9c3b9 100644 --- a/zrml/prediction-markets/src/benchmarks.rs +++ b/zrml/prediction-markets/src/benchmarks.rs @@ -829,7 +829,7 @@ benchmarks! { let reserver: T::AccountId = account("Reserver", i, 0); ::AssetManager::deposit(Asset::Ztg, &reserver, (u128::MAX).saturated_into())?; let market_id_number: u128 = market_id.saturated_into::(); - let _ = zrml_simple_disputes::Call::::reserve_outcome { + let _ = zrml_simple_disputes::Call::::suggest_outcome { market_id: market_id_number.saturated_into(), outcome: OutcomeReport::Scalar(i.saturated_into()), }.dispatch_bypass_filter(RawOrigin::Signed(reserver.clone()).into())?; diff --git a/zrml/prediction-markets/src/tests.rs b/zrml/prediction-markets/src/tests.rs index 9f2a5e7b0..98fa1389c 100644 --- a/zrml/prediction-markets/src/tests.rs +++ b/zrml/prediction-markets/src/tests.rs @@ -639,12 +639,12 @@ fn admin_destroy_market_correctly_unreserves_dispute_bonds() { )); run_to_block(grace_period + 2); assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(0) )); - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(DAVE), 0, OutcomeReport::Categorical(1) @@ -2635,7 +2635,7 @@ fn it_allows_to_dispute_the_outcome_of_a_market() { run_to_block(dispute_at); assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(0) @@ -2828,7 +2828,7 @@ fn it_resolves_a_disputed_market() { let dispute_at_0 = report_at + 1; run_to_block(dispute_at_0); - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(1) @@ -2837,7 +2837,7 @@ fn it_resolves_a_disputed_market() { let dispute_at_1 = report_at + 2; run_to_block(dispute_at_1); - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(DAVE), 0, OutcomeReport::Categorical(0) @@ -2846,7 +2846,7 @@ fn it_resolves_a_disputed_market() { let dispute_at_2 = report_at + 3; run_to_block(dispute_at_2); - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(EVE), 0, OutcomeReport::Categorical(1) @@ -3002,7 +3002,7 @@ fn start_global_dispute_works() { Error::::MarketDisputeMechanismNotFailed ); - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(CHARLIE), market_id, OutcomeReport::Categorical(i.saturated_into()), @@ -3629,7 +3629,7 @@ fn full_scalar_market_lifecycle() { // dispute assert_ok!(PredictionMarkets::dispute(Origin::signed(DAVE), 0)); - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(DAVE), 0, OutcomeReport::Scalar(25) @@ -4253,7 +4253,7 @@ fn outsider_reports_wrong_outcome() { assert_ok!(PredictionMarkets::dispute(Origin::signed(EVE), 0,)); check_reserve(&EVE, DisputeBond::get()); - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(DAVE), 0, OutcomeReport::Categorical(0) @@ -4412,7 +4412,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark OutcomeReport::Categorical(0) )); assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(1) @@ -4463,7 +4463,7 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_approved_advised_ma OutcomeReport::Categorical(0) )); assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(1) @@ -4514,12 +4514,12 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark )); assert_ok!(PredictionMarkets::dispute(Origin::signed(EVE), 0,)); // EVE disputes with wrong outcome - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(EVE), 0, OutcomeReport::Categorical(1) )); - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(0) @@ -4574,12 +4574,12 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_advised_approved_ma )); assert_ok!(PredictionMarkets::dispute(Origin::signed(EVE), 0,)); // EVE disputes with wrong outcome - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(EVE), 0, OutcomeReport::Categorical(1) )); - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(CHARLIE), 0, OutcomeReport::Categorical(0) @@ -4639,12 +4639,12 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_permissionless_mark assert_ok!(PredictionMarkets::dispute(Origin::signed(EVE), 0,)); // EVE disputes with wrong outcome - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(EVE), 0, OutcomeReport::Categorical(1) )); - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(FRED), 0, OutcomeReport::Categorical(0) @@ -4710,12 +4710,12 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_advised_approved_ma assert_ok!(PredictionMarkets::dispute(Origin::signed(EVE), 0,)); // EVE disputes with wrong outcome - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(EVE), 0, OutcomeReport::Categorical(1) )); - assert_ok!(SimpleDisputes::reserve_outcome( + assert_ok!(SimpleDisputes::suggest_outcome( Origin::signed(FRED), 0, OutcomeReport::Categorical(0) diff --git a/zrml/simple-disputes/src/benchmarks.rs b/zrml/simple-disputes/src/benchmarks.rs index dc97b753c..1d2a9d5e3 100644 --- a/zrml/simple-disputes/src/benchmarks.rs +++ b/zrml/simple-disputes/src/benchmarks.rs @@ -33,7 +33,7 @@ use sp_runtime::traits::{One, Saturating}; use zrml_market_commons::MarketCommonsPalletApi; benchmarks! { - reserve_outcome { + suggest_outcome { let d in 1..(T::MaxDisputes::get() - 1); let r in 1..63; let e in 1..63; diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index 5c5fcecd2..a25e50294 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -185,13 +185,13 @@ mod pallet { #[pallet::call] impl Pallet { - #[pallet::weight(T::WeightInfo::reserve_outcome( + #[pallet::weight(T::WeightInfo::suggest_outcome( T::MaxDisputes::get(), CacheSize::get(), CacheSize::get(), ))] #[transactional] - pub fn reserve_outcome( + pub fn suggest_outcome( origin: OriginFor, #[pallet::compact] market_id: MarketIdOf, outcome: OutcomeReport, @@ -231,7 +231,7 @@ mod pallet { Self::deposit_event(Event::OutcomeReserved { market_id, dispute: market_dispute }); - Ok((Some(T::WeightInfo::reserve_outcome(num_disputes, r, e))).into()) + Ok((Some(T::WeightInfo::suggest_outcome(num_disputes, r, e))).into()) } } diff --git a/zrml/simple-disputes/src/tests.rs b/zrml/simple-disputes/src/tests.rs index 71b8d929e..6bb6d5457 100644 --- a/zrml/simple-disputes/src/tests.rs +++ b/zrml/simple-disputes/src/tests.rs @@ -104,4 +104,4 @@ fn on_resolution_sets_the_last_dispute_of_disputed_markets_as_the_canonical_outc }); } -// TODO test `reserve_outcome` functionality and API functionality +// TODO test `suggest_outcome` functionality and API functionality diff --git a/zrml/simple-disputes/src/weights.rs b/zrml/simple-disputes/src/weights.rs index c810c63cb..8d2851d61 100644 --- a/zrml/simple-disputes/src/weights.rs +++ b/zrml/simple-disputes/src/weights.rs @@ -45,7 +45,7 @@ use frame_support::{traits::Get, weights::Weight}; /// Trait containing the required functions for weight retrival within /// zrml_simple_disputes (automatically generated) pub trait WeightInfoZeitgeist { - fn reserve_outcome(d: u32, r: u32, e: u32) -> Weight; + fn suggest_outcome(d: u32, r: u32, e: u32) -> Weight; } /// Weight functions for zrml_simple_disputes (automatically generated) @@ -55,7 +55,7 @@ impl WeightInfoZeitgeist for WeightInfo { // Storage: SimpleDisputes Disputes (r:1 w:1) // Storage: Balances Reserves (r:1 w:1) // Storage: PredictionMarkets MarketIdsPerDisputeBlock (r:2 w:2) - fn reserve_outcome(d: u32, r: u32, e: u32) -> Weight { + fn suggest_outcome(d: u32, r: u32, e: u32) -> Weight { Weight::from_ref_time(400_160_000) // Standard Error: 1_302_000 .saturating_add(Weight::from_ref_time(3_511_000).saturating_mul(d.into())) From 88a43dd06b10656a46cee4ad02b560eb9090e50d Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 2 Mar 2023 11:45:29 +0100 Subject: [PATCH 28/58] separate resolve_disputed_market into parts --- zrml/prediction-markets/src/lib.rs | 68 +++++++++++++++++++----------- 1 file changed, 43 insertions(+), 25 deletions(-) diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index ec04812e7..72039cb92 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -2496,6 +2496,37 @@ mod pallet { market: &MarketOf, ) -> Result { let report = market.report.as_ref().ok_or(Error::::MarketIsNotReported)?; + + let resolved_outcome: OutcomeReport = + Self::get_resolved_outcome(market_id, market, &report.outcome)?; + + let imbalance_left = Self::settle_bonds(market_id, market, &resolved_outcome, report)?; + + let remainder = match market.dispute_mechanism { + MarketDisputeMechanism::Authorized => { + T::Authorized::exchange(market_id, market, &resolved_outcome, imbalance_left)? + } + MarketDisputeMechanism::Court => { + T::Court::exchange(market_id, market, &resolved_outcome, imbalance_left)? + } + MarketDisputeMechanism::SimpleDisputes => T::SimpleDisputes::exchange( + market_id, + market, + &resolved_outcome, + imbalance_left, + )?, + }; + + T::Slash::on_unbalanced(remainder); + + Ok(resolved_outcome) + } + + fn get_resolved_outcome( + market_id: &MarketIdOf, + market: &MarketOf, + reported_outcome: &OutcomeReport, + ) -> Result { let mut resolved_outcome_option = None; #[cfg(feature = "with-global-disputes")] @@ -2519,15 +2550,19 @@ mod pallet { }; } - let resolved_outcome = - resolved_outcome_option.unwrap_or_else(|| report.outcome.clone()); + Ok(resolved_outcome_option.unwrap_or_else(|| reported_outcome.clone())) + } - // If the oracle reported right, return the OracleBond, otherwise slash it to - // pay the correct reporters. + fn settle_bonds( + market_id: &MarketIdOf, + market: &MarketOf, + resolved_outcome: &OutcomeReport, + report: &Report, + ) -> Result, DispatchError> { let mut overall_imbalance = NegativeImbalanceOf::::zero(); let report_by_oracle = report.by == market.oracle; - let is_correct = report.outcome == resolved_outcome; + let is_correct = &report.outcome == resolved_outcome; let unreserve_outsider = || -> DispatchResult { if Self::is_outsider_bond_pending(market_id, market, true) { @@ -2566,7 +2601,7 @@ mod pallet { } let mut correct_disputor = None; - if let Some(bond) = market.bonds.dispute.clone() { + if let Some(bond) = &market.bonds.dispute { if !bond.is_settled { if is_correct { let imb = Self::slash_dispute_bond(market_id, None)?; @@ -2574,7 +2609,7 @@ mod pallet { } else { // If the report outcome was wrong, the dispute was justified Self::unreserve_dispute_bond(market_id)?; - correct_disputor = Some(bond.who); + correct_disputor = Some(bond.who.clone()); } } } @@ -2586,24 +2621,7 @@ mod pallet { imbalance_left = overall_imbalance; } - let remainder = match market.dispute_mechanism { - MarketDisputeMechanism::Authorized => { - T::Authorized::exchange(market_id, market, &resolved_outcome, imbalance_left)? - } - MarketDisputeMechanism::Court => { - T::Court::exchange(market_id, market, &resolved_outcome, imbalance_left)? - } - MarketDisputeMechanism::SimpleDisputes => T::SimpleDisputes::exchange( - market_id, - market, - &resolved_outcome, - imbalance_left, - )?, - }; - - T::Slash::on_unbalanced(remainder); - - Ok(resolved_outcome) + Ok(imbalance_left) } pub fn on_resolution( From b8cd91ae54d0217e05761094447a77c14ef29869 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Mon, 27 Mar 2023 12:42:18 +0200 Subject: [PATCH 29/58] edit exchange API documentation --- primitives/src/traits/dispute_api.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/primitives/src/traits/dispute_api.rs b/primitives/src/traits/dispute_api.rs index adc6e763f..93e961d46 100644 --- a/primitives/src/traits/dispute_api.rs +++ b/primitives/src/traits/dispute_api.rs @@ -66,8 +66,14 @@ pub trait DisputeApi { /// This can be based on the final resolution outcome of the market. /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. /// + /// # Arguments + /// * `market_id` - The identifier of the market. + /// * `market` - The market data. + /// * `resolved_outcome` - The final resolution outcome of the market. + /// * `amount` - The amount of funds transferred to the dispute mechanism. + /// /// # Returns - /// Returns a negative imbalance back to the caller. + /// Returns a negative imbalance in order to transfer funds back to the caller. fn exchange( market_id: &Self::MarketId, market: &MarketOfDisputeApi, From 5d6df7961b83d185a26b3e2b69a2f1f4b9005eb3 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Mon, 27 Mar 2023 12:50:51 +0200 Subject: [PATCH 30/58] slash dispute bond --- zrml/prediction-markets/src/lib.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 72039cb92..f722e8768 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -332,10 +332,6 @@ mod pallet { let market_status = market.status; let market_account = >::market_account(market_id); - if Self::is_dispute_bond_pending(&market_id, &market, false) { - Self::unreserve_dispute_bond(&market_id)?; - } - // Slash outstanding bonds; see // https://github.com/zeitgeistpm/runtime-audit-1/issues/34#issuecomment-1120187097 for // details. @@ -2059,6 +2055,9 @@ mod pallet { if Self::is_outsider_bond_pending(market_id, market, false) { Self::slash_outsider_bond(market_id, None)?; } + if Self::is_dispute_bond_pending(market_id, market, false) { + Self::slash_dispute_bond(market_id, None)?; + } Ok(()) } From ce13fd2ed8312973742388fc21443e431aa6f201 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Tue, 28 Mar 2023 09:56:43 +0200 Subject: [PATCH 31/58] add empty commit From 7b3ff21a74bb435f952bc9cb8a6735a44dbf5387 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Tue, 28 Mar 2023 10:08:03 +0200 Subject: [PATCH 32/58] correct admin_destroy_market test --- zrml/prediction-markets/src/tests.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/zrml/prediction-markets/src/tests.rs b/zrml/prediction-markets/src/tests.rs index 6bdd601aa..8d76e7e49 100644 --- a/zrml/prediction-markets/src/tests.rs +++ b/zrml/prediction-markets/src/tests.rs @@ -619,7 +619,7 @@ fn admin_destroy_market_correctly_slashes_permissionless_market_disputed() { } #[test] -fn admin_destroy_market_correctly_unreserves_dispute_bonds() { +fn admin_destroy_market_correctly_slashes_dispute_bonds() { ExtBuilder::default().build().execute_with(|| { let end = 2; simple_create_categorical_market( @@ -674,9 +674,7 @@ fn admin_destroy_market_correctly_unreserves_dispute_bonds() { ); assert_eq!( Balances::free_balance(CHARLIE), - balance_free_before_charlie - + DisputeBond::get() - + zrml_simple_disputes::default_outcome_bond::(0) + balance_free_before_charlie + zrml_simple_disputes::default_outcome_bond::(0) ); assert_eq!( Balances::free_balance(DAVE), From a052320c0dd22c6d8fe10c324ec5d60de6f6797e Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Tue, 28 Mar 2023 12:06:18 +0200 Subject: [PATCH 33/58] remove gd dependency from simple disputes --- Cargo.lock | 1 - primitives/src/traits/dispute_api.rs | 11 ++++++- runtime/common/src/lib.rs | 2 -- zrml/authorized/src/lib.rs | 8 ++++-- zrml/court/src/lib.rs | 7 +++-- zrml/prediction-markets/Cargo.toml | 1 - zrml/prediction-markets/src/lib.rs | 16 ++++++++++- zrml/prediction-markets/src/mock.rs | 2 -- zrml/simple-disputes/Cargo.toml | 4 --- zrml/simple-disputes/src/lib.rs | 39 +++++++------------------ zrml/simple-disputes/src/mock.rs | 43 ---------------------------- 11 files changed, 46 insertions(+), 88 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0684752d..1f904d5d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13118,7 +13118,6 @@ dependencies = [ "sp-io", "sp-runtime", "zeitgeist-primitives", - "zrml-global-disputes", "zrml-market-commons", ] diff --git a/primitives/src/traits/dispute_api.rs b/primitives/src/traits/dispute_api.rs index 2c2b058f4..bcb6734c1 100644 --- a/primitives/src/traits/dispute_api.rs +++ b/primitives/src/traits/dispute_api.rs @@ -16,10 +16,13 @@ // You should have received a copy of the GNU General Public License // along with Zeitgeist. If not, see . +extern crate alloc; + use crate::{ outcome_report::OutcomeReport, types::{Asset, Market}, }; +use alloc::vec::Vec; use frame_support::{dispatch::DispatchResult, pallet_prelude::Weight}; use parity_scale_codec::MaxEncodedLen; use sp_runtime::DispatchError; @@ -34,6 +37,9 @@ type MarketOfDisputeApi = Market< Asset<::MarketId>, >; +type GlobalDisputeItemOfDisputeApi = + (OutcomeReport, ::AccountId, ::Balance); + pub trait DisputeApi { type AccountId; type Balance; @@ -103,10 +109,13 @@ pub trait DisputeApi { /// Called, when a global dispute is started. /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. + /// + /// # Returns + /// Returns the initial vote outcomes with initial vote value and owner of the vote. fn on_global_dispute( market_id: &Self::MarketId, market: &MarketOfDisputeApi, - ) -> DispatchResult; + ) -> Result>, DispatchError>; /// Allow the API consumer to clear storage items of the dispute mechanism. /// This may be called, when the dispute mechanism is no longer needed. diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index 72c97f7e8..11891f7b9 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -1062,8 +1062,6 @@ macro_rules! impl_config_traits { type OutcomeFactor = OutcomeFactor; type DisputeResolution = zrml_prediction_markets::Pallet; type Event = Event; - #[cfg(feature = "with-global-disputes")] - type GlobalDisputes = GlobalDisputes; type MarketCommons = MarketCommons; type MaxDisputes = MaxDisputes; type PalletId = SimpleDisputesPalletId; diff --git a/zrml/authorized/src/lib.rs b/zrml/authorized/src/lib.rs index 31d16f095..3b6f231b5 100644 --- a/zrml/authorized/src/lib.rs +++ b/zrml/authorized/src/lib.rs @@ -35,6 +35,7 @@ pub use pallet::*; #[frame_support::pallet] mod pallet { use crate::{weights::WeightInfoZeitgeist, AuthorizedPalletApi}; + use alloc::vec::Vec; use core::marker::PhantomData; use frame_support::{ dispatch::{DispatchResult, DispatchResultWithPostInfo}, @@ -260,13 +261,16 @@ mod pallet { Ok(false) } - fn on_global_dispute(_: &Self::MarketId, market: &MarketOf) -> DispatchResult { + fn on_global_dispute( + _: &Self::MarketId, + market: &MarketOf, + ) -> Result, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Authorized, Error::::MarketDoesNotHaveDisputeMechanismAuthorized ); - Ok(()) + Ok(Vec::new()) } fn clear(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index 6dbe09312..86541a834 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -625,12 +625,15 @@ mod pallet { Ok(false) } - fn on_global_dispute(_: &Self::MarketId, market: &MarketOf) -> DispatchResult { + fn on_global_dispute( + _: &Self::MarketId, + market: &MarketOf, + ) -> Result, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, Error::::MarketDoesNotHaveCourtMechanism ); - Ok(()) + Ok(Vec::new()) } fn clear(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { diff --git a/zrml/prediction-markets/Cargo.toml b/zrml/prediction-markets/Cargo.toml index 9ee2be18b..f12cf796f 100644 --- a/zrml/prediction-markets/Cargo.toml +++ b/zrml/prediction-markets/Cargo.toml @@ -92,7 +92,6 @@ try-runtime = [ ] with-global-disputes = [ "zrml-global-disputes", - "zrml-simple-disputes/with-global-disputes", ] [package] diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index bafd1a1f5..940565e93 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -1435,6 +1435,8 @@ mod pallet { Error::::GlobalDisputeAlreadyStarted ); + let report = market.report.as_ref().ok_or(Error::::MarketIsNotReported)?; + let has_failed = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { T::Authorized::has_failed(&market_id, &market)? @@ -1446,7 +1448,7 @@ mod pallet { }; ensure!(has_failed, Error::::MarketDisputeMechanismNotFailed); - match market.dispute_mechanism { + let initial_vote_outcomes = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { T::Authorized::on_global_dispute(&market_id, &market)? } @@ -1458,6 +1460,18 @@ mod pallet { } }; + T::GlobalDisputes::push_voting_outcome( + &market_id, + report.outcome.clone(), + &report.by, + >::zero(), + )?; + + // push vote outcomes other than the report outcome + for (outcome, owner, bond) in initial_vote_outcomes { + T::GlobalDisputes::push_voting_outcome(&market_id, outcome, &owner, bond)?; + } + // TODO(#372): Allow court with global disputes. // ensure, that global disputes controls the resolution now // it does not end after the dispute period now, but after the global dispute end diff --git a/zrml/prediction-markets/src/mock.rs b/zrml/prediction-markets/src/mock.rs index 894ad790e..07fd46149 100644 --- a/zrml/prediction-markets/src/mock.rs +++ b/zrml/prediction-markets/src/mock.rs @@ -324,8 +324,6 @@ impl zrml_simple_disputes::Config for Runtime { type OutcomeBond = OutcomeBond; type OutcomeFactor = OutcomeFactor; type DisputeResolution = prediction_markets::Pallet; - #[cfg(feature = "with-global-disputes")] - type GlobalDisputes = GlobalDisputes; type MarketCommons = MarketCommons; type MaxDisputes = MaxDisputes; type PalletId = SimpleDisputesPalletId; diff --git a/zrml/simple-disputes/Cargo.toml b/zrml/simple-disputes/Cargo.toml index 465fb3fd8..e947cc9a8 100644 --- a/zrml/simple-disputes/Cargo.toml +++ b/zrml/simple-disputes/Cargo.toml @@ -7,7 +7,6 @@ parity-scale-codec = { default-features = false, features = ["derive", "max-enco scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } sp-runtime = { branch = "moonbeam-polkadot-v0.9.29", default-features = false, git = "https://github.com/zeitgeistpm/substrate" } zeitgeist-primitives = { default-features = false, path = "../../primitives" } -zrml-global-disputes = { default-features = false, path = "../global-disputes", optional = true } zrml-market-commons = { default-features = false, path = "../market-commons" } [dev-dependencies] @@ -37,9 +36,6 @@ std = [ try-runtime = [ "frame-support/try-runtime", ] -with-global-disputes = [ - "zrml-global-disputes", -] [package] authors = ["Zeitgeist PM "] diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index 96d8f199e..9028959b6 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -54,15 +54,11 @@ mod pallet { }; use frame_system::pallet_prelude::*; use orml_traits::currency::NamedMultiReservableCurrency; - #[cfg(feature = "with-global-disputes")] - use sp_runtime::traits::Zero; use sp_runtime::{ traits::{CheckedDiv, Saturating}, DispatchError, SaturatedConversion, }; - #[cfg(feature = "with-global-disputes")] - use zrml_global_disputes::GlobalDisputesPalletApi; use zrml_market_commons::MarketCommonsPalletApi; #[pallet::config] @@ -94,14 +90,6 @@ mod pallet { #[pallet::constant] type OutcomeFactor: Get>; - /// See [`GlobalDisputesPalletApi`]. - #[cfg(feature = "with-global-disputes")] - type GlobalDisputes: GlobalDisputesPalletApi< - MarketIdOf, - Self::AccountId, - BalanceOf, - >; - /// The identifier of individual markets. type MarketCommons: MarketCommonsPalletApi< AccountId = Self::AccountId, @@ -405,29 +393,22 @@ mod pallet { Ok(disputes.len() == T::MaxDisputes::get() as usize) } - fn on_global_dispute(_market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { + fn on_global_dispute( + market_id: &Self::MarketId, + market: &MarketOf, + ) -> Result, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, Error::::MarketDoesNotHaveSimpleDisputesMechanism ); - #[cfg(feature = "with-global-disputes")] - { - let disputes = >::get(_market_id); - // add report outcome to voting choices - if let Some(report) = &market.report { - T::GlobalDisputes::push_voting_outcome( - _market_id, - report.outcome.clone(), - &report.by, - >::zero(), - )?; - } - for MarketDispute { at: _, by, outcome, bond } in disputes.iter() { - T::GlobalDisputes::push_voting_outcome(_market_id, outcome.clone(), by, *bond)?; - } + let mut gd_outcomes: Vec<(OutcomeReport, Self::AccountId, Self::Balance)> = Vec::new(); + + for MarketDispute { at: _, by, outcome, bond } in >::get(market_id).iter() { + gd_outcomes.push((outcome.clone(), by.clone(), *bond)); } - Ok(()) + + Ok(gd_outcomes) } fn clear(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { diff --git a/zrml/simple-disputes/src/mock.rs b/zrml/simple-disputes/src/mock.rs index ed1408094..7fa175ab4 100644 --- a/zrml/simple-disputes/src/mock.rs +++ b/zrml/simple-disputes/src/mock.rs @@ -40,12 +40,6 @@ use zeitgeist_primitives::{ }, }; -#[cfg(feature = "with-global-disputes")] -use zeitgeist_primitives::constants::mock::{ - GlobalDisputeLockId, GlobalDisputesPalletId, MaxGlobalDisputeVotes, MaxOwners, - MinOutcomeVoteAmount, RemoveKeysLimit, VotingOutcomeFee, -}; - pub const ALICE: AccountIdTest = 0; pub const BOB: AccountIdTest = 1; pub const CHARLIE: AccountIdTest = 2; @@ -60,26 +54,6 @@ ord_parameter_types! { pub const Sudo: AccountIdTest = SUDO; } -#[cfg(feature = "with-global-disputes")] -construct_runtime!( - pub enum Runtime - where - Block = BlockTest, - NodeBlock = BlockTest, - UncheckedExtrinsic = UncheckedExtrinsicTest, - { - Balances: pallet_balances::{Call, Config, Event, Pallet, Storage}, - AssetManager: orml_currencies::{Call, Pallet, Storage}, - MarketCommons: zrml_market_commons::{Pallet, Storage}, - SimpleDisputes: zrml_simple_disputes::{Event, Pallet, Storage}, - GlobalDisputes: zrml_global_disputes::{Event, Pallet, Storage}, - System: frame_system::{Call, Config, Event, Pallet, Storage}, - Timestamp: pallet_timestamp::{Pallet}, - Tokens: orml_tokens::{Config, Event, Pallet, Storage}, - } -); - -#[cfg(not(feature = "with-global-disputes"))] construct_runtime!( pub enum Runtime where @@ -142,29 +116,12 @@ impl crate::Config for Runtime { type OutcomeBond = OutcomeBond; type OutcomeFactor = OutcomeFactor; type DisputeResolution = NoopResolution; - #[cfg(feature = "with-global-disputes")] - type GlobalDisputes = GlobalDisputes; type MarketCommons = MarketCommons; type MaxDisputes = MaxDisputes; type PalletId = SimpleDisputesPalletId; type WeightInfo = zrml_simple_disputes::weights::WeightInfo; } -#[cfg(feature = "with-global-disputes")] -impl zrml_global_disputes::Config for Runtime { - type Event = (); - type MarketCommons = MarketCommons; - type Currency = Balances; - type GlobalDisputeLockId = GlobalDisputeLockId; - type GlobalDisputesPalletId = GlobalDisputesPalletId; - type MaxGlobalDisputeVotes = MaxGlobalDisputeVotes; - type MaxOwners = MaxOwners; - type MinOutcomeVoteAmount = MinOutcomeVoteAmount; - type RemoveKeysLimit = RemoveKeysLimit; - type VotingOutcomeFee = VotingOutcomeFee; - type WeightInfo = zrml_global_disputes::weights::WeightInfo; -} - impl frame_system::Config for Runtime { type AccountData = pallet_balances::AccountData; type AccountId = AccountIdTest; From c3b61cb3b9c8e80177b1bdb9a154f9fe9245fa2a Mon Sep 17 00:00:00 2001 From: Chralt Date: Wed, 12 Apr 2023 13:28:36 +0200 Subject: [PATCH 34/58] Update zrml/simple-disputes/src/mock.rs Co-authored-by: Harald Heckmann --- zrml/simple-disputes/src/mock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zrml/simple-disputes/src/mock.rs b/zrml/simple-disputes/src/mock.rs index 7fa175ab4..bc46fdfe3 100644 --- a/zrml/simple-disputes/src/mock.rs +++ b/zrml/simple-disputes/src/mock.rs @@ -61,8 +61,8 @@ construct_runtime!( NodeBlock = BlockTest, UncheckedExtrinsic = UncheckedExtrinsicTest, { - Balances: pallet_balances::{Call, Config, Event, Pallet, Storage}, AssetManager: orml_currencies::{Call, Pallet, Storage}, + Balances: pallet_balances::{Call, Config, Event, Pallet, Storage}, MarketCommons: zrml_market_commons::{Pallet, Storage}, SimpleDisputes: zrml_simple_disputes::{Event, Pallet, Storage}, System: frame_system::{Call, Config, Event, Pallet, Storage}, From 11960ded8b198ceea71434198e0320eece9e4908 Mon Sep 17 00:00:00 2001 From: Chralt Date: Wed, 12 Apr 2023 13:28:47 +0200 Subject: [PATCH 35/58] Update zrml/simple-disputes/src/mock.rs Co-authored-by: Harald Heckmann --- zrml/simple-disputes/src/mock.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zrml/simple-disputes/src/mock.rs b/zrml/simple-disputes/src/mock.rs index bc46fdfe3..5119f1343 100644 --- a/zrml/simple-disputes/src/mock.rs +++ b/zrml/simple-disputes/src/mock.rs @@ -113,11 +113,11 @@ impl DisputeResolutionApi for NoopResolution { impl crate::Config for Runtime { type AssetManager = AssetManager; type Event = (); - type OutcomeBond = OutcomeBond; - type OutcomeFactor = OutcomeFactor; type DisputeResolution = NoopResolution; type MarketCommons = MarketCommons; type MaxDisputes = MaxDisputes; + type OutcomeBond = OutcomeBond; + type OutcomeFactor = OutcomeFactor; type PalletId = SimpleDisputesPalletId; type WeightInfo = zrml_simple_disputes::weights::WeightInfo; } From 6fc919763245d047f8eb60ff852c4088ca7dc551 Mon Sep 17 00:00:00 2001 From: Chralt Date: Wed, 12 Apr 2023 13:40:06 +0200 Subject: [PATCH 36/58] Update zrml/prediction-markets/src/lib.rs Co-authored-by: Harald Heckmann --- zrml/prediction-markets/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 940565e93..15e56c316 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -1809,7 +1809,7 @@ mod pallet { MarketInsufficientSubsidy(MarketIdOf, MarketStatus), /// A market has been closed \[market_id\] MarketClosed(MarketIdOf), - /// A market has been disputed \[market_id, new_market_status, new_outcome\] + /// A market has been disputed \[market_id, new_market_status\] MarketDisputed(MarketIdOf, MarketStatus), /// An advised market has ended before it was approved or rejected. \[market_id\] MarketExpired(MarketIdOf), From c6386796b529d77719c198107f2ca5265ea85af3 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Wed, 12 Apr 2023 13:42:24 +0200 Subject: [PATCH 37/58] add doc string --- zrml/prediction-markets/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 15e56c316..6b0ba23cc 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -2221,6 +2221,7 @@ mod pallet { Ok((ids_len, mdm_len)) } + /// The dispute mechanism is intended to clear its own storage here. fn clear_dispute_mechanism(market_id: &MarketIdOf) -> DispatchResult { let market = >::market(market_id)?; match market.dispute_mechanism { From 553e082af83ef27fd8cc008776159351f0228b02 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Wed, 12 Apr 2023 13:48:49 +0200 Subject: [PATCH 38/58] add doc strings --- zrml/prediction-markets/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 6b0ba23cc..de5ce1606 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -2486,6 +2486,8 @@ mod pallet { } } + /// Handle a market resolution, which is currently in the reported state. + /// Returns the resolved outcome of a market, which is the reported outcome. fn resolve_reported_market( market_id: &MarketIdOf, market: &MarketOf, @@ -2506,6 +2508,8 @@ mod pallet { Ok(report.outcome.clone()) } + /// Handle a market resolution, which is currently in the disputed state. + /// Returns the resolved outcome of a market. fn resolve_disputed_market( market_id: &MarketIdOf, market: &MarketOf, @@ -2537,6 +2541,7 @@ mod pallet { Ok(resolved_outcome) } + /// Get the outcome the market should resolve to. fn get_resolved_outcome( market_id: &MarketIdOf, market: &MarketOf, @@ -2568,6 +2573,7 @@ mod pallet { Ok(resolved_outcome_option.unwrap_or_else(|| reported_outcome.clone())) } + /// Manage the outstanding bonds (oracle, outsider, dispute) of the market. fn settle_bonds( market_id: &MarketIdOf, market: &MarketOf, From 55fdee0774285b5fc3358a74bf0f4108496205c1 Mon Sep 17 00:00:00 2001 From: Harald Heckmann Date: Mon, 3 Apr 2023 12:40:12 +0200 Subject: [PATCH 39/58] Reduce settle_bonds LOC --- zrml/prediction-markets/src/lib.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index de5ce1606..7c3a11338 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -2621,7 +2621,7 @@ mod pallet { } } - let mut correct_disputor = None; + if let Some(bond) = &market.bonds.dispute { if !bond.is_settled { if is_correct { @@ -2630,19 +2630,13 @@ mod pallet { } else { // If the report outcome was wrong, the dispute was justified Self::unreserve_dispute_bond(market_id)?; - correct_disputor = Some(bond.who.clone()); + CurrencyOf::::resolve_creating(&bond.who, overall_imbalance); + overall_imbalance = NegativeImbalanceOf::::zero(); } } } - let mut imbalance_left = >::zero(); - if let Some(disputor) = correct_disputor { - CurrencyOf::::resolve_creating(&disputor, overall_imbalance); - } else { - imbalance_left = overall_imbalance; - } - - Ok(imbalance_left) + Ok(overall_imbalance) } pub fn on_resolution( From 0efc405603c6cbf32b5ab022bfcce4527c3555fa Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Wed, 12 Apr 2023 14:00:15 +0200 Subject: [PATCH 40/58] cargo fmt --- zrml/prediction-markets/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 7c3a11338..4de5c08a9 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -2621,7 +2621,6 @@ mod pallet { } } - if let Some(bond) = &market.bonds.dispute { if !bond.is_settled { if is_correct { From aa09b01e1c1536cc7a23099a0c0a0d4a8b2afd7a Mon Sep 17 00:00:00 2001 From: Chralt Date: Wed, 12 Apr 2023 14:02:47 +0200 Subject: [PATCH 41/58] Update zrml/prediction-markets/src/migrations.rs Co-authored-by: Harald Heckmann --- zrml/prediction-markets/src/migrations.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 45bfca43e..aa2bb6cd9 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -457,9 +457,7 @@ where // important drain disputes storage item from prediction markets pallet for (market_id, old_disputes) in crate::Disputes::::drain() { - total_weight = total_weight.saturating_add(T::DbWeight::get().writes(1)); - - total_weight = total_weight.saturating_add(T::DbWeight::get().reads(1)); + total_weight = total_weight.saturating_add(T::DbWeight::get().reads_writes(1,1)); if let Ok(market) = >::market(&market_id) { match market.dispute_mechanism { MarketDisputeMechanism::Authorized => continue, From 2c15b969a2a9628f18dd871523b6f13fcef34436 Mon Sep 17 00:00:00 2001 From: Chralt Date: Wed, 12 Apr 2023 14:03:59 +0200 Subject: [PATCH 42/58] Update zrml/prediction-markets/src/migrations.rs Co-authored-by: Harald Heckmann --- zrml/prediction-markets/src/migrations.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index aa2bb6cd9..d52fd3cb8 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -491,10 +491,8 @@ where } // switch to new reserve identifier for simple disputes - let sd_pallet_id = zeitgeist_primitives::constants::SD_PALLET_ID; - let sd_reserve_id = sd_pallet_id.0; - let pm_pallet_id = zeitgeist_primitives::constants::PM_PALLET_ID; - let pm_reserve_id = pm_pallet_id.0; + let sd_reserve_id = >::reserve_id(); + let pm_reserve_id = >::reserve_id(); // charge weight defensivly for unreserve_named // https://github.com/open-web3-stack/open-runtime-module-library/blob/24f0a8b6e04e1078f70d0437fb816337cdf4f64c/tokens/src/lib.rs#L1516-L1547 From a71bb5c318fe0e2f37a8421b995c3a9fff5a32f9 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Wed, 12 Apr 2023 15:17:03 +0200 Subject: [PATCH 43/58] apply review suggestion --- primitives/src/market.rs | 11 +++++++++++ primitives/src/traits/dispute_api.rs | 4 ++-- zrml/authorized/src/lib.rs | 5 +++-- zrml/court/src/lib.rs | 5 +++-- zrml/prediction-markets/src/lib.rs | 17 +++++++++++------ zrml/prediction-markets/src/migrations.rs | 2 +- zrml/simple-disputes/src/lib.rs | 20 +++++++++++--------- 7 files changed, 42 insertions(+), 22 deletions(-) diff --git a/primitives/src/market.rs b/primitives/src/market.rs index 0c2c4386a..6eeb4e9ca 100644 --- a/primitives/src/market.rs +++ b/primitives/src/market.rs @@ -177,6 +177,17 @@ pub enum MarketCreation { Advised, } +/// Defines a global dispute item for the initialisation of a global dispute. +pub struct GlobalDisputeItem { + /// The account that already paid somehow for the outcome. + pub owner: AccountId, + /// The outcome that was already paid for + /// and should be added as vote outcome inside global disputes. + pub outcome: OutcomeReport, + /// The initial amount added in the global dispute vote system initially for the outcome. + pub initial_vote_amount: Balance, +} + // TODO to remove, when Disputes storage item is removed #[derive(Clone, Decode, Encode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] pub struct OldMarketDispute { diff --git a/primitives/src/traits/dispute_api.rs b/primitives/src/traits/dispute_api.rs index bcb6734c1..2a137f243 100644 --- a/primitives/src/traits/dispute_api.rs +++ b/primitives/src/traits/dispute_api.rs @@ -20,7 +20,7 @@ extern crate alloc; use crate::{ outcome_report::OutcomeReport, - types::{Asset, Market}, + types::{Asset, GlobalDisputeItem, Market}, }; use alloc::vec::Vec; use frame_support::{dispatch::DispatchResult, pallet_prelude::Weight}; @@ -38,7 +38,7 @@ type MarketOfDisputeApi = Market< >; type GlobalDisputeItemOfDisputeApi = - (OutcomeReport, ::AccountId, ::Balance); + GlobalDisputeItem<::AccountId, ::Balance>; pub trait DisputeApi { type AccountId; diff --git a/zrml/authorized/src/lib.rs b/zrml/authorized/src/lib.rs index 3b6f231b5..142a5cb1b 100644 --- a/zrml/authorized/src/lib.rs +++ b/zrml/authorized/src/lib.rs @@ -49,7 +49,8 @@ mod pallet { use zeitgeist_primitives::{ traits::{DisputeApi, DisputeResolutionApi}, types::{ - Asset, AuthorityReport, Market, MarketDisputeMechanism, MarketStatus, OutcomeReport, + Asset, AuthorityReport, GlobalDisputeItem, Market, MarketDisputeMechanism, + MarketStatus, OutcomeReport, }, }; use zrml_market_commons::MarketCommonsPalletApi; @@ -264,7 +265,7 @@ mod pallet { fn on_global_dispute( _: &Self::MarketId, market: &MarketOf, - ) -> Result, DispatchError> { + ) -> Result>, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Authorized, Error::::MarketDoesNotHaveDisputeMechanismAuthorized diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index 86541a834..e16c4f1fe 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -68,7 +68,8 @@ mod pallet { use zeitgeist_primitives::{ traits::{DisputeApi, DisputeResolutionApi}, types::{ - Asset, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, OutcomeReport, + Asset, GlobalDisputeItem, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, + OutcomeReport, }, }; use zrml_market_commons::MarketCommonsPalletApi; @@ -628,7 +629,7 @@ mod pallet { fn on_global_dispute( _: &Self::MarketId, market: &MarketOf, - ) -> Result, DispatchError> { + ) -> Result>, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, Error::::MarketDoesNotHaveCourtMechanism diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 4de5c08a9..4948976fe 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -64,9 +64,9 @@ mod pallet { constants::MILLISECS_PER_BLOCK, traits::{DisputeApi, DisputeResolutionApi, Swaps, ZeitgeistAssetManager}, types::{ - Asset, Bond, Deadlines, Market, MarketBonds, MarketCreation, MarketDisputeMechanism, - MarketPeriod, MarketStatus, MarketType, MultiHash, OldMarketDispute, OutcomeReport, - Report, ScalarPosition, ScoringRule, SubsidyUntil, + Asset, Bond, Deadlines, GlobalDisputeItem, Market, MarketBonds, MarketCreation, + MarketDisputeMechanism, MarketPeriod, MarketStatus, MarketType, MultiHash, + OldMarketDispute, OutcomeReport, Report, ScalarPosition, ScoringRule, SubsidyUntil, }, }; #[cfg(feature = "with-global-disputes")] @@ -1448,7 +1448,7 @@ mod pallet { }; ensure!(has_failed, Error::::MarketDisputeMechanismNotFailed); - let initial_vote_outcomes = match market.dispute_mechanism { + let gd_items = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { T::Authorized::on_global_dispute(&market_id, &market)? } @@ -1468,8 +1468,13 @@ mod pallet { )?; // push vote outcomes other than the report outcome - for (outcome, owner, bond) in initial_vote_outcomes { - T::GlobalDisputes::push_voting_outcome(&market_id, outcome, &owner, bond)?; + for GlobalDisputeItem { outcome, owner, initial_vote_amount } in gd_items { + T::GlobalDisputes::push_voting_outcome( + &market_id, + outcome, + &owner, + initial_vote_amount, + )?; } // TODO(#372): Allow court with global disputes. diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index d52fd3cb8..7e45d23c7 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -457,7 +457,7 @@ where // important drain disputes storage item from prediction markets pallet for (market_id, old_disputes) in crate::Disputes::::drain() { - total_weight = total_weight.saturating_add(T::DbWeight::get().reads_writes(1,1)); + total_weight = total_weight.saturating_add(T::DbWeight::get().reads_writes(1, 1)); if let Ok(market) = >::market(&market_id) { match market.dispute_mechanism { MarketDisputeMechanism::Authorized => continue, diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index 9028959b6..c649177aa 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -33,7 +33,8 @@ pub use simple_disputes_pallet_api::SimpleDisputesPalletApi; use zeitgeist_primitives::{ traits::{DisputeApi, DisputeResolutionApi, ZeitgeistAssetManager}, types::{ - Asset, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, OutcomeReport, Report, + Asset, GlobalDisputeItem, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, + OutcomeReport, Report, }, }; @@ -396,19 +397,20 @@ mod pallet { fn on_global_dispute( market_id: &Self::MarketId, market: &MarketOf, - ) -> Result, DispatchError> { + ) -> Result>, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, Error::::MarketDoesNotHaveSimpleDisputesMechanism ); - let mut gd_outcomes: Vec<(OutcomeReport, Self::AccountId, Self::Balance)> = Vec::new(); - - for MarketDispute { at: _, by, outcome, bond } in >::get(market_id).iter() { - gd_outcomes.push((outcome.clone(), by.clone(), *bond)); - } - - Ok(gd_outcomes) + Ok(>::get(market_id) + .iter() + .map(|dispute| GlobalDisputeItem { + outcome: dispute.outcome.clone(), + owner: dispute.by.clone(), + initial_vote_amount: dispute.bond, + }) + .collect()) } fn clear(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { From afd9d618a0eaaf5643733db0d092f68f809123e7 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Mon, 17 Apr 2023 08:23:00 +0200 Subject: [PATCH 44/58] add correct mdm benchmarking on_dispute --- primitives/src/traits/dispute_api.rs | 3 ++ zrml/authorized/src/benchmarks.rs | 14 +++++--- zrml/authorized/src/lib.rs | 7 +++- zrml/authorized/src/weights.rs | 4 +++ zrml/court/src/benchmarks.rs | 15 ++++++--- zrml/court/src/lib.rs | 38 +++++++++++++++++++++- zrml/court/src/weights.rs | 5 +++ zrml/prediction-markets/src/lib.rs | 44 +++++++++++++++++++------- zrml/simple-disputes/src/benchmarks.rs | 9 +++++- zrml/simple-disputes/src/lib.rs | 6 +++- zrml/simple-disputes/src/weights.rs | 5 +++ 11 files changed, 126 insertions(+), 24 deletions(-) diff --git a/primitives/src/traits/dispute_api.rs b/primitives/src/traits/dispute_api.rs index 2a137f243..a47f123c5 100644 --- a/primitives/src/traits/dispute_api.rs +++ b/primitives/src/traits/dispute_api.rs @@ -55,6 +55,9 @@ pub trait DisputeApi { /// associated pallet. **May** assume that `market.dispute_mechanism` refers to the calling dispute API. fn on_dispute(market_id: &Self::MarketId, market: &MarketOfDisputeApi) -> DispatchResult; + /// Return the weight of the `on_dispute` function. + fn on_dispute_weight() -> Weight; + /// Manage market resolution of a disputed market. /// /// **Should** only be called if the market was disputed before resolving. **May** assume that diff --git a/zrml/authorized/src/benchmarks.rs b/zrml/authorized/src/benchmarks.rs index d4f349161..cbab9b329 100644 --- a/zrml/authorized/src/benchmarks.rs +++ b/zrml/authorized/src/benchmarks.rs @@ -22,9 +22,7 @@ )] #![cfg(feature = "runtime-benchmarks")] -#[cfg(test)] -use crate::Pallet as Authorized; -use crate::{market_mock, AuthorizedOutcomeReports, Call, Config, Pallet}; +use crate::{market_mock, AuthorizedOutcomeReports, Call, Config, Pallet as Authorized, Pallet}; use frame_benchmarking::benchmarks; use frame_support::{ dispatch::UnfilteredDispatchable, @@ -32,7 +30,7 @@ use frame_support::{ }; use sp_runtime::traits::Saturating; use zeitgeist_primitives::{ - traits::DisputeResolutionApi, + traits::{DisputeApi, DisputeResolutionApi}, types::{AuthorityReport, OutcomeReport}, }; use zrml_market_commons::MarketCommonsPalletApi; @@ -96,6 +94,14 @@ benchmarks! { assert_eq!(AuthorizedOutcomeReports::::get(market_id).unwrap(), report); } + on_dispute_weight { + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market.clone()).unwrap(); + }: { + Authorized::::on_dispute(&market_id, &market).unwrap(); + } + impl_benchmark_test_suite!( Authorized, crate::mock::ExtBuilder::default().build(), diff --git a/zrml/authorized/src/lib.rs b/zrml/authorized/src/lib.rs index 142a5cb1b..33eb14f71 100644 --- a/zrml/authorized/src/lib.rs +++ b/zrml/authorized/src/lib.rs @@ -40,7 +40,7 @@ mod pallet { use frame_support::{ dispatch::{DispatchResult, DispatchResultWithPostInfo}, ensure, - pallet_prelude::{ConstU32, EnsureOrigin, OptionQuery, StorageMap}, + pallet_prelude::{ConstU32, EnsureOrigin, OptionQuery, StorageMap, Weight}, traits::{Currency, Get, Hooks, IsType, StorageVersion}, PalletId, Twox64Concat, }; @@ -216,6 +216,11 @@ mod pallet { Ok(()) } + fn on_dispute_weight() -> Weight { + // TODO T::WeightInfo::on_dispute_weight() + Weight::zero() + } + fn on_resolution( market_id: &Self::MarketId, market: &MarketOf, diff --git a/zrml/authorized/src/weights.rs b/zrml/authorized/src/weights.rs index 685066985..b27ee7161 100644 --- a/zrml/authorized/src/weights.rs +++ b/zrml/authorized/src/weights.rs @@ -48,6 +48,7 @@ use frame_support::{traits::Get, weights::Weight}; pub trait WeightInfoZeitgeist { fn authorize_market_outcome_first_report(m: u32) -> Weight; fn authorize_market_outcome_existing_report() -> Weight; + fn on_dispute_weight() -> Weight; } /// Weight functions for zrml_authorized (automatically generated) @@ -70,4 +71,7 @@ impl WeightInfoZeitgeist for WeightInfo { .saturating_add(T::DbWeight::get().reads(2)) .saturating_add(T::DbWeight::get().writes(1)) } + fn on_dispute_weight() -> Weight { + Weight::from_ref_time(0) + } } diff --git a/zrml/court/src/benchmarks.rs b/zrml/court/src/benchmarks.rs index d78f614d1..994ac8c2e 100644 --- a/zrml/court/src/benchmarks.rs +++ b/zrml/court/src/benchmarks.rs @@ -22,14 +22,13 @@ )] #![cfg(feature = "runtime-benchmarks")] -#[cfg(test)] -use crate::Pallet as Court; -use crate::{BalanceOf, Call, Config, CurrencyOf, Pallet}; +use crate::{market_mock, BalanceOf, Call, Config, CurrencyOf, Pallet as Court, Pallet}; use frame_benchmarking::{benchmarks, whitelisted_caller}; use frame_support::{dispatch::UnfilteredDispatchable, traits::Currency}; use frame_system::RawOrigin; use sp_runtime::traits::Bounded; -use zeitgeist_primitives::types::OutcomeReport; +use zeitgeist_primitives::{traits::DisputeApi, types::OutcomeReport}; +use zrml_market_commons::MarketCommonsPalletApi; fn deposit(caller: &T::AccountId) where @@ -66,6 +65,14 @@ benchmarks! { deposit_and_join_court::(&caller); }: _(RawOrigin::Signed(caller), market_id, outcome) + on_dispute_weight { + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market.clone()).unwrap(); + }: { + Court::::on_dispute(&market_id, &market).unwrap(); + } + impl_benchmark_test_suite!( Court, crate::mock::ExtBuilder::default().build(), diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index e16c4f1fe..920a5b38a 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -52,7 +52,7 @@ mod pallet { use frame_support::{ dispatch::DispatchResult, ensure, - pallet_prelude::{CountedStorageMap, StorageDoubleMap, StorageValue, ValueQuery}, + pallet_prelude::{CountedStorageMap, StorageDoubleMap, StorageValue, ValueQuery, Weight}, traits::{ BalanceStatus, Currency, Get, Hooks, IsType, NamedReservableCurrency, Randomness, StorageVersion, @@ -561,6 +561,10 @@ mod pallet { Ok(()) } + fn on_dispute_weight() -> Weight { + Weight::zero() + } + // Set jurors that sided on the second most voted outcome as tardy. Jurors are only // rewarded if sided on the most voted outcome but jurors that voted second most // voted outcome (winner of the losing majority) are placed as tardy instead of @@ -682,3 +686,35 @@ mod pallet { (T::BlockNumber, OutcomeReport), >; } + +#[cfg(any(feature = "runtime-benchmarks", test))] +pub(crate) fn market_mock() -> MarketOf +where + T: crate::Config, +{ + use frame_support::traits::Get; + use sp_runtime::traits::AccountIdConversion; + use zeitgeist_primitives::types::{Asset, MarketBonds, ScoringRule}; + + zeitgeist_primitives::types::Market { + base_asset: Asset::Ztg, + creation: zeitgeist_primitives::types::MarketCreation::Permissionless, + creator_fee: 0, + creator: T::PalletId::get().into_account_truncating(), + market_type: zeitgeist_primitives::types::MarketType::Scalar(0..=100), + dispute_mechanism: zeitgeist_primitives::types::MarketDisputeMechanism::Court, + metadata: Default::default(), + oracle: T::PalletId::get().into_account_truncating(), + period: zeitgeist_primitives::types::MarketPeriod::Block(Default::default()), + deadlines: zeitgeist_primitives::types::Deadlines { + grace_period: 1_u32.into(), + oracle_duration: 1_u32.into(), + dispute_duration: 1_u32.into(), + }, + report: None, + resolved_outcome: None, + scoring_rule: ScoringRule::CPMM, + status: zeitgeist_primitives::types::MarketStatus::Disputed, + bonds: MarketBonds::default(), + } +} diff --git a/zrml/court/src/weights.rs b/zrml/court/src/weights.rs index 96b5e68a9..eed9d2298 100644 --- a/zrml/court/src/weights.rs +++ b/zrml/court/src/weights.rs @@ -49,6 +49,7 @@ pub trait WeightInfoZeitgeist { fn exit_court() -> Weight; fn join_court() -> Weight; fn vote() -> Weight; + fn on_dispute_weight() -> Weight; } /// Weight functions for zrml_court (automatically generated) @@ -79,4 +80,8 @@ impl WeightInfoZeitgeist for WeightInfo { .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } + + fn on_dispute_weight() -> Weight { + Weight::from_ref_time(0) + } } diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 4948976fe..e07a54a90 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -64,13 +64,16 @@ mod pallet { constants::MILLISECS_PER_BLOCK, traits::{DisputeApi, DisputeResolutionApi, Swaps, ZeitgeistAssetManager}, types::{ - Asset, Bond, Deadlines, GlobalDisputeItem, Market, MarketBonds, MarketCreation, - MarketDisputeMechanism, MarketPeriod, MarketStatus, MarketType, MultiHash, - OldMarketDispute, OutcomeReport, Report, ScalarPosition, ScoringRule, SubsidyUntil, + Asset, Bond, Deadlines, Market, MarketBonds, MarketCreation, MarketDisputeMechanism, + MarketPeriod, MarketStatus, MarketType, MultiHash, OldMarketDispute, OutcomeReport, + Report, ScalarPosition, ScoringRule, SubsidyUntil, }, }; #[cfg(feature = "with-global-disputes")] - use zrml_global_disputes::GlobalDisputesPalletApi; + use { + zeitgeist_primitives::types::GlobalDisputeItem, + zrml_global_disputes::GlobalDisputesPalletApi, + }; use zrml_liquidity_mining::LiquidityMiningPalletApi; use zrml_market_commons::MarketCommonsPalletApi; @@ -613,7 +616,13 @@ mod pallet { /// # Weight /// /// Complexity: `O(n)`, where `n` is the number of outstanding disputes. - #[pallet::weight(T::WeightInfo::dispute_authorized())] + #[pallet::weight( + T::WeightInfo::dispute_authorized().saturating_add( + T::Court::on_dispute_weight().saturating_add( + T::SimpleDisputes::on_dispute_weight() + ) + ) + )] #[transactional] pub fn dispute( origin: OriginFor, @@ -624,16 +633,22 @@ mod pallet { let market = >::market(&market_id)?; ensure!(market.status == MarketStatus::Reported, Error::::InvalidMarketStatus); - // TODO(#782): use multiple benchmarks paths for different dispute mechanisms - match market.dispute_mechanism { + let overweight = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { - T::Authorized::on_dispute(&market_id, &market)? + T::Authorized::on_dispute(&market_id, &market)?; + T::Court::on_dispute_weight() + .saturating_add(T::SimpleDisputes::on_dispute_weight()) + } + MarketDisputeMechanism::Court => { + T::Court::on_dispute(&market_id, &market)?; + T::Authorized::on_dispute_weight() + .saturating_add(T::SimpleDisputes::on_dispute_weight()) } - MarketDisputeMechanism::Court => T::Court::on_dispute(&market_id, &market)?, MarketDisputeMechanism::SimpleDisputes => { - T::SimpleDisputes::on_dispute(&market_id, &market)? + T::SimpleDisputes::on_dispute(&market_id, &market)?; + T::Court::on_dispute_weight().saturating_add(T::Authorized::on_dispute_weight()) } - } + }; let dispute_bond = T::DisputeBond::get(); @@ -647,7 +662,12 @@ mod pallet { Self::deposit_event(Event::MarketDisputed(market_id, MarketStatus::Disputed)); - Ok((Some(T::WeightInfo::dispute_authorized())).into()) + let full_weight = T::WeightInfo::dispute_authorized().saturating_add( + T::Court::on_dispute_weight() + .saturating_add(T::SimpleDisputes::on_dispute_weight()), + ); + + Ok((Some(full_weight.saturating_sub(overweight))).into()) } /// Create a permissionless market, buy complete sets and deploy a pool with specified diff --git a/zrml/simple-disputes/src/benchmarks.rs b/zrml/simple-disputes/src/benchmarks.rs index 1d2a9d5e3..6fd425a0f 100644 --- a/zrml/simple-disputes/src/benchmarks.rs +++ b/zrml/simple-disputes/src/benchmarks.rs @@ -22,7 +22,6 @@ #![allow(clippy::type_complexity)] #![cfg(feature = "runtime-benchmarks")] -#[cfg(test)] use crate::Pallet as SimpleDisputes; use super::*; @@ -83,6 +82,14 @@ benchmarks! { T::AssetManager::deposit(Asset::Ztg, &caller, bond).unwrap(); }: _(RawOrigin::Signed(caller.clone()), market_id, outcome) + on_dispute_weight { + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market.clone()).unwrap(); + }: { + SimpleDisputes::::on_dispute(&market_id, &market).unwrap(); + } + impl_benchmark_test_suite!( SimpleDisputes, crate::mock::ExtBuilder::default().build(), diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index c649177aa..15f9e6427 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -48,7 +48,7 @@ mod pallet { dispatch::DispatchResult, ensure, pallet_prelude::{ - Blake2_128Concat, ConstU32, DispatchResultWithPostInfo, StorageMap, ValueQuery, + Blake2_128Concat, ConstU32, DispatchResultWithPostInfo, StorageMap, ValueQuery, Weight, }, traits::{Currency, Get, Hooks, Imbalance, IsType, NamedReservableCurrency}, transactional, BoundedVec, PalletId, @@ -295,6 +295,10 @@ mod pallet { Ok(()) } + fn on_dispute_weight() -> Weight { + Weight::zero() + } + fn on_resolution( market_id: &Self::MarketId, market: &MarketOf, diff --git a/zrml/simple-disputes/src/weights.rs b/zrml/simple-disputes/src/weights.rs index 8d2851d61..2143935cc 100644 --- a/zrml/simple-disputes/src/weights.rs +++ b/zrml/simple-disputes/src/weights.rs @@ -46,6 +46,7 @@ use frame_support::{traits::Get, weights::Weight}; /// zrml_simple_disputes (automatically generated) pub trait WeightInfoZeitgeist { fn suggest_outcome(d: u32, r: u32, e: u32) -> Weight; + fn on_dispute_weight() -> Weight; } /// Weight functions for zrml_simple_disputes (automatically generated) @@ -66,4 +67,8 @@ impl WeightInfoZeitgeist for WeightInfo { .saturating_add(T::DbWeight::get().reads(5)) .saturating_add(T::DbWeight::get().writes(4)) } + + fn on_dispute_weight() -> Weight { + Weight::from_ref_time(0) + } } From af0a25a94b6c744df7547e5fd1ed6c3c97ae108a Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Mon, 17 Apr 2023 08:25:34 +0200 Subject: [PATCH 45/58] use on_dispute_weight inside api --- zrml/authorized/src/lib.rs | 3 +-- zrml/court/src/lib.rs | 2 +- zrml/simple-disputes/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/zrml/authorized/src/lib.rs b/zrml/authorized/src/lib.rs index 33eb14f71..d98cba895 100644 --- a/zrml/authorized/src/lib.rs +++ b/zrml/authorized/src/lib.rs @@ -217,8 +217,7 @@ mod pallet { } fn on_dispute_weight() -> Weight { - // TODO T::WeightInfo::on_dispute_weight() - Weight::zero() + T::WeightInfo::on_dispute_weight() } fn on_resolution( diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index 920a5b38a..77ea0d9f3 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -562,7 +562,7 @@ mod pallet { } fn on_dispute_weight() -> Weight { - Weight::zero() + T::WeightInfo::on_dispute_weight() } // Set jurors that sided on the second most voted outcome as tardy. Jurors are only diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index 15f9e6427..303d11d2b 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -296,7 +296,7 @@ mod pallet { } fn on_dispute_weight() -> Weight { - Weight::zero() + T::WeightInfo::on_dispute_weight() } fn on_resolution( From b88aca43c8c4954d7fecae5aa61084e8f67a47fc Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Mon, 17 Apr 2023 12:53:32 +0200 Subject: [PATCH 46/58] improve mdm weight technique --- primitives/src/market.rs | 12 +++ primitives/src/traits/dispute_api.rs | 31 ++++++- zrml/authorized/src/benchmarks.rs | 78 +++++++++++++++- zrml/authorized/src/lib.rs | 36 +++++++- zrml/authorized/src/weights.rs | 24 +++++ zrml/court/src/lib.rs | 38 +++++++- zrml/court/src/weights.rs | 25 +++++- zrml/prediction-markets/src/lib.rs | 42 ++++++--- zrml/simple-disputes/src/benchmarks.rs | 120 ++++++++++++++++++++----- zrml/simple-disputes/src/lib.rs | 74 ++++++++++++++- zrml/simple-disputes/src/weights.rs | 58 ++++++++++++ 11 files changed, 492 insertions(+), 46 deletions(-) diff --git a/primitives/src/market.rs b/primitives/src/market.rs index 6eeb4e9ca..a7a6900d2 100644 --- a/primitives/src/market.rs +++ b/primitives/src/market.rs @@ -204,6 +204,18 @@ pub struct MarketDispute { pub bond: Balance, } +#[derive(Default)] +pub enum MDMWeight { + Authorized, + Court, + SimpleDisputes { + market_id: MarketId, + market: Market, + }, + #[default] + Default, +} + /// How a market should resolve disputes #[derive(Clone, Decode, Encode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] pub enum MarketDisputeMechanism { diff --git a/primitives/src/traits/dispute_api.rs b/primitives/src/traits/dispute_api.rs index a47f123c5..f67281e53 100644 --- a/primitives/src/traits/dispute_api.rs +++ b/primitives/src/traits/dispute_api.rs @@ -20,7 +20,7 @@ extern crate alloc; use crate::{ outcome_report::OutcomeReport, - types::{Asset, GlobalDisputeItem, Market}, + types::{Asset, GlobalDisputeItem, MDMWeight, Market}, }; use alloc::vec::Vec; use frame_support::{dispatch::DispatchResult, pallet_prelude::Weight}; @@ -37,6 +37,15 @@ type MarketOfDisputeApi = Market< Asset<::MarketId>, >; +type MDMWeightOf = MDMWeight< + ::MarketId, + ::AccountId, + ::Balance, + ::BlockNumber, + ::Moment, + Asset<::MarketId>, +>; + type GlobalDisputeItemOfDisputeApi = GlobalDisputeItem<::AccountId, ::Balance>; @@ -56,7 +65,7 @@ pub trait DisputeApi { fn on_dispute(market_id: &Self::MarketId, market: &MarketOfDisputeApi) -> DispatchResult; /// Return the weight of the `on_dispute` function. - fn on_dispute_weight() -> Weight; + fn on_dispute_weight(mdm_info: &MDMWeightOf) -> Weight; /// Manage market resolution of a disputed market. /// @@ -72,6 +81,9 @@ pub trait DisputeApi { market: &MarketOfDisputeApi, ) -> Result, DispatchError>; + /// Return the weight of the `on_resolution` function. + fn on_resolution_weight(mdm_info: &MDMWeightOf) -> Weight; + /// Allow the transfer of funds from the API caller to the API consumer and back. /// This can be based on the final resolution outcome of the market. /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. @@ -91,6 +103,9 @@ pub trait DisputeApi { amount: Self::NegativeImbalance, ) -> Result; + /// Return the weight of the `exchange` function. + fn exchange_weight(mdm_info: &MDMWeightOf) -> Weight; + /// Query the future resolution block of a disputed market. /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. /// @@ -102,6 +117,9 @@ pub trait DisputeApi { market: &MarketOfDisputeApi, ) -> Result, DispatchError>; + /// Return the weight of the `get_auto_resolve` function. + fn get_auto_resolve_weight(mdm_info: &MDMWeightOf) -> Weight; + /// Returns `true` if the market dispute mechanism /// was unable to come to a conclusion. /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. @@ -110,6 +128,9 @@ pub trait DisputeApi { market: &MarketOfDisputeApi, ) -> Result; + /// Return the weight of the `has_failed` function. + fn has_failed_weight(mdm_info: &MDMWeightOf) -> Weight; + /// Called, when a global dispute is started. /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. /// @@ -120,10 +141,16 @@ pub trait DisputeApi { market: &MarketOfDisputeApi, ) -> Result>, DispatchError>; + /// Return the weight of the `on_global_dispute` function. + fn on_global_dispute_weight(mdm_info: &MDMWeightOf) -> Weight; + /// Allow the API consumer to clear storage items of the dispute mechanism. /// This may be called, when the dispute mechanism is no longer needed. /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. fn clear(market_id: &Self::MarketId, market: &MarketOfDisputeApi) -> DispatchResult; + + /// Return the weight of the `clear` function. + fn clear_weight(mdm_info: &MDMWeightOf) -> Weight; } type MarketOfDisputeResolutionApi = Market< diff --git a/zrml/authorized/src/benchmarks.rs b/zrml/authorized/src/benchmarks.rs index cbab9b329..ff3cbd3f1 100644 --- a/zrml/authorized/src/benchmarks.rs +++ b/zrml/authorized/src/benchmarks.rs @@ -22,11 +22,14 @@ )] #![cfg(feature = "runtime-benchmarks")] -use crate::{market_mock, AuthorizedOutcomeReports, Call, Config, Pallet as Authorized, Pallet}; +use crate::{ + market_mock, AuthorizedOutcomeReports, Call, Config, NegativeImbalanceOf, Pallet as Authorized, + Pallet, +}; use frame_benchmarking::benchmarks; use frame_support::{ dispatch::UnfilteredDispatchable, - traits::{EnsureOrigin, Get}, + traits::{EnsureOrigin, Get, Imbalance}, }; use sp_runtime::traits::Saturating; use zeitgeist_primitives::{ @@ -102,6 +105,77 @@ benchmarks! { Authorized::::on_dispute(&market_id, &market).unwrap(); } + on_resolution_weight { + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market.clone()).unwrap(); + + frame_system::Pallet::::set_block_number(42u32.into()); + + let now = frame_system::Pallet::::block_number(); + let resolve_at = now.saturating_add(T::CorrectionPeriod::get()); + + let report = AuthorityReport { resolve_at, outcome: OutcomeReport::Scalar(0) }; + AuthorizedOutcomeReports::::insert(market_id, report); + }: { + Authorized::::on_resolution(&market_id, &market).unwrap(); + } + + exchange_weight { + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market.clone()).unwrap(); + + let outcome = OutcomeReport::Scalar(0); + let imb = NegativeImbalanceOf::::zero(); + }: { + Authorized::::exchange(&market_id, &market, &outcome, imb).unwrap(); + } + + get_auto_resolve_weight { + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market.clone()).unwrap(); + + let now = frame_system::Pallet::::block_number(); + let resolve_at = now.saturating_add(T::CorrectionPeriod::get()); + + let report = AuthorityReport { resolve_at, outcome: OutcomeReport::Scalar(0) }; + AuthorizedOutcomeReports::::insert(market_id, report); + }: { + Authorized::::get_auto_resolve(&market_id, &market).unwrap(); + } + + has_failed_weight { + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market.clone()).unwrap(); + }: { + Authorized::::has_failed(&market_id, &market).unwrap(); + } + + on_global_dispute_weight { + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market.clone()).unwrap(); + }: { + Authorized::::on_global_dispute(&market_id, &market).unwrap(); + } + + clear_weight { + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market.clone()).unwrap(); + + let now = frame_system::Pallet::::block_number(); + let resolve_at = now.saturating_add(T::CorrectionPeriod::get()); + + let report = AuthorityReport { resolve_at, outcome: OutcomeReport::Scalar(0) }; + AuthorizedOutcomeReports::::insert(market_id, report); + }: { + Authorized::::clear(&market_id, &market).unwrap(); + } + impl_benchmark_test_suite!( Authorized, crate::mock::ExtBuilder::default().build(), diff --git a/zrml/authorized/src/lib.rs b/zrml/authorized/src/lib.rs index d98cba895..55b26777c 100644 --- a/zrml/authorized/src/lib.rs +++ b/zrml/authorized/src/lib.rs @@ -49,7 +49,7 @@ mod pallet { use zeitgeist_primitives::{ traits::{DisputeApi, DisputeResolutionApi}, types::{ - Asset, AuthorityReport, GlobalDisputeItem, Market, MarketDisputeMechanism, + Asset, AuthorityReport, GlobalDisputeItem, MDMWeight, Market, MarketDisputeMechanism, MarketStatus, OutcomeReport, }, }; @@ -75,6 +75,14 @@ mod pallet { MomentOf, Asset>, >; + pub(crate) type MDMWeightOf = MDMWeight< + MarketIdOf, + ::AccountId, + BalanceOf, + ::BlockNumber, + MomentOf, + Asset>, + >; #[pallet::call] impl Pallet { @@ -216,7 +224,7 @@ mod pallet { Ok(()) } - fn on_dispute_weight() -> Weight { + fn on_dispute_weight(_mdm_info: &MDMWeightOf) -> Weight { T::WeightInfo::on_dispute_weight() } @@ -232,6 +240,10 @@ mod pallet { Ok(report.map(|r| r.outcome)) } + fn on_resolution_weight(_mdm_info: &MDMWeightOf) -> Weight { + T::WeightInfo::on_resolution_weight() + } + fn exchange( _: &Self::MarketId, market: &MarketOf, @@ -246,6 +258,10 @@ mod pallet { Ok(overall_imbalance) } + fn exchange_weight(_mdm_info: &MDMWeightOf) -> Weight { + T::WeightInfo::exchange_weight() + } + fn get_auto_resolve( market_id: &Self::MarketId, market: &MarketOf, @@ -257,6 +273,10 @@ mod pallet { Ok(Self::get_auto_resolve(market_id)) } + fn get_auto_resolve_weight(_mdm_info: &MDMWeightOf) -> Weight { + T::WeightInfo::get_auto_resolve_weight() + } + fn has_failed(_: &Self::MarketId, market: &MarketOf) -> Result { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Authorized, @@ -266,6 +286,10 @@ mod pallet { Ok(false) } + fn has_failed_weight(_mdm_info: &MDMWeightOf) -> Weight { + T::WeightInfo::has_failed_weight() + } + fn on_global_dispute( _: &Self::MarketId, market: &MarketOf, @@ -278,6 +302,10 @@ mod pallet { Ok(Vec::new()) } + fn on_global_dispute_weight(_mdm_info: &MDMWeightOf) -> Weight { + T::WeightInfo::on_global_dispute_weight() + } + fn clear(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Authorized, @@ -287,6 +315,10 @@ mod pallet { AuthorizedOutcomeReports::::remove(market_id); Ok(()) } + + fn clear_weight(_mdm_info: &MDMWeightOf) -> Weight { + T::WeightInfo::clear_weight() + } } impl AuthorizedPalletApi for Pallet where T: Config {} diff --git a/zrml/authorized/src/weights.rs b/zrml/authorized/src/weights.rs index b27ee7161..1754ea7c7 100644 --- a/zrml/authorized/src/weights.rs +++ b/zrml/authorized/src/weights.rs @@ -49,6 +49,12 @@ pub trait WeightInfoZeitgeist { fn authorize_market_outcome_first_report(m: u32) -> Weight; fn authorize_market_outcome_existing_report() -> Weight; fn on_dispute_weight() -> Weight; + fn on_resolution_weight() -> Weight; + fn exchange_weight() -> Weight; + fn get_auto_resolve_weight() -> Weight; + fn has_failed_weight() -> Weight; + fn on_global_dispute_weight() -> Weight; + fn clear_weight() -> Weight; } /// Weight functions for zrml_authorized (automatically generated) @@ -74,4 +80,22 @@ impl WeightInfoZeitgeist for WeightInfo { fn on_dispute_weight() -> Weight { Weight::from_ref_time(0) } + fn on_resolution_weight() -> Weight { + Weight::from_ref_time(0) + } + fn exchange_weight() -> Weight { + Weight::from_ref_time(0) + } + fn get_auto_resolve_weight() -> Weight { + Weight::from_ref_time(0) + } + fn has_failed_weight() -> Weight { + Weight::from_ref_time(0) + } + fn on_global_dispute_weight() -> Weight { + Weight::from_ref_time(0) + } + fn clear_weight() -> Weight { + Weight::from_ref_time(0) + } } diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index 77ea0d9f3..0e3816d1e 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -68,8 +68,8 @@ mod pallet { use zeitgeist_primitives::{ traits::{DisputeApi, DisputeResolutionApi}, types::{ - Asset, GlobalDisputeItem, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, - OutcomeReport, + Asset, GlobalDisputeItem, MDMWeight, Market, MarketDispute, MarketDisputeMechanism, + MarketStatus, OutcomeReport, }, }; use zrml_market_commons::MarketCommonsPalletApi; @@ -102,6 +102,14 @@ mod pallet { MomentOf, Asset>, >; + pub(crate) type MDMWeightOf = MDMWeight< + MarketIdOf, + ::AccountId, + BalanceOf, + ::BlockNumber, + MomentOf, + Asset>, + >; #[pallet::call] impl Pallet { @@ -561,7 +569,7 @@ mod pallet { Ok(()) } - fn on_dispute_weight() -> Weight { + fn on_dispute_weight(_mdm_info: &MDMWeightOf) -> Weight { T::WeightInfo::on_dispute_weight() } @@ -597,6 +605,10 @@ mod pallet { Ok(Some(first)) } + fn on_resolution_weight(_mdm_info: &MDMWeightOf) -> Weight { + T::WeightInfo::on_resolution_weight() + } + fn exchange( _: &Self::MarketId, market: &MarketOf, @@ -611,6 +623,10 @@ mod pallet { Ok(overall_imbalance) } + fn exchange_weight(_mdm_info: &MDMWeightOf) -> Weight { + T::WeightInfo::exchange_weight() + } + fn get_auto_resolve( _: &Self::MarketId, market: &MarketOf, @@ -622,6 +638,10 @@ mod pallet { Ok(None) } + fn get_auto_resolve_weight(_mdm_info: &MDMWeightOf) -> Weight { + T::WeightInfo::get_auto_resolve_weight() + } + fn has_failed(_: &Self::MarketId, market: &MarketOf) -> Result { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, @@ -630,6 +650,10 @@ mod pallet { Ok(false) } + fn has_failed_weight(_mdm_info: &MDMWeightOf) -> Weight { + T::WeightInfo::has_failed_weight() + } + fn on_global_dispute( _: &Self::MarketId, market: &MarketOf, @@ -641,6 +665,10 @@ mod pallet { Ok(Vec::new()) } + fn on_global_dispute_weight(_mdm_info: &MDMWeightOf) -> Weight { + T::WeightInfo::on_global_dispute_weight() + } + fn clear(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, @@ -650,6 +678,10 @@ mod pallet { let _ = RequestedJurors::::clear_prefix(market_id, u32::max_value(), None); Ok(()) } + + fn clear_weight(_mdm_info: &MDMWeightOf) -> Weight { + T::WeightInfo::clear_weight() + } } impl CourtPalletApi for Pallet where T: Config {} diff --git a/zrml/court/src/weights.rs b/zrml/court/src/weights.rs index eed9d2298..f50651eee 100644 --- a/zrml/court/src/weights.rs +++ b/zrml/court/src/weights.rs @@ -50,6 +50,12 @@ pub trait WeightInfoZeitgeist { fn join_court() -> Weight; fn vote() -> Weight; fn on_dispute_weight() -> Weight; + fn on_resolution_weight() -> Weight; + fn exchange_weight() -> Weight; + fn get_auto_resolve_weight() -> Weight; + fn has_failed_weight() -> Weight; + fn on_global_dispute_weight() -> Weight; + fn clear_weight() -> Weight; } /// Weight functions for zrml_court (automatically generated) @@ -80,8 +86,25 @@ impl WeightInfoZeitgeist for WeightInfo { .saturating_add(T::DbWeight::get().reads(1)) .saturating_add(T::DbWeight::get().writes(1)) } - fn on_dispute_weight() -> Weight { Weight::from_ref_time(0) } + fn on_resolution_weight() -> Weight { + Weight::from_ref_time(0) + } + fn exchange_weight() -> Weight { + Weight::from_ref_time(0) + } + fn get_auto_resolve_weight() -> Weight { + Weight::from_ref_time(0) + } + fn has_failed_weight() -> Weight { + Weight::from_ref_time(0) + } + fn on_global_dispute_weight() -> Weight { + Weight::from_ref_time(0) + } + fn clear_weight() -> Weight { + Weight::from_ref_time(0) + } } diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index e07a54a90..cdf73265b 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -64,9 +64,9 @@ mod pallet { constants::MILLISECS_PER_BLOCK, traits::{DisputeApi, DisputeResolutionApi, Swaps, ZeitgeistAssetManager}, types::{ - Asset, Bond, Deadlines, Market, MarketBonds, MarketCreation, MarketDisputeMechanism, - MarketPeriod, MarketStatus, MarketType, MultiHash, OldMarketDispute, OutcomeReport, - Report, ScalarPosition, ScoringRule, SubsidyUntil, + Asset, Bond, Deadlines, MDMWeight, Market, MarketBonds, MarketCreation, + MarketDisputeMechanism, MarketPeriod, MarketStatus, MarketType, MultiHash, + OldMarketDispute, OutcomeReport, Report, ScalarPosition, ScoringRule, SubsidyUntil, }, }; #[cfg(feature = "with-global-disputes")] @@ -618,8 +618,8 @@ mod pallet { /// Complexity: `O(n)`, where `n` is the number of outstanding disputes. #[pallet::weight( T::WeightInfo::dispute_authorized().saturating_add( - T::Court::on_dispute_weight().saturating_add( - T::SimpleDisputes::on_dispute_weight() + T::Court::on_dispute_weight(&MDMWeight::Default).saturating_add( + T::SimpleDisputes::on_dispute_weight(&MDMWeight::Default) ) ) )] @@ -636,17 +636,26 @@ mod pallet { let overweight = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { T::Authorized::on_dispute(&market_id, &market)?; - T::Court::on_dispute_weight() - .saturating_add(T::SimpleDisputes::on_dispute_weight()) + T::Court::on_dispute_weight(&MDMWeight::Court).saturating_add( + T::SimpleDisputes::on_dispute_weight(&MDMWeight::SimpleDisputes { + market_id, + market: market.clone(), + }), + ) } MarketDisputeMechanism::Court => { T::Court::on_dispute(&market_id, &market)?; - T::Authorized::on_dispute_weight() - .saturating_add(T::SimpleDisputes::on_dispute_weight()) + T::Authorized::on_dispute_weight(&MDMWeight::Authorized).saturating_add( + T::SimpleDisputes::on_dispute_weight(&MDMWeight::SimpleDisputes { + market_id, + market: market.clone(), + }), + ) } MarketDisputeMechanism::SimpleDisputes => { T::SimpleDisputes::on_dispute(&market_id, &market)?; - T::Court::on_dispute_weight().saturating_add(T::Authorized::on_dispute_weight()) + T::Court::on_dispute_weight(&MDMWeight::Court) + .saturating_add(T::Authorized::on_dispute_weight(&MDMWeight::Authorized)) } }; @@ -663,8 +672,12 @@ mod pallet { Self::deposit_event(Event::MarketDisputed(market_id, MarketStatus::Disputed)); let full_weight = T::WeightInfo::dispute_authorized().saturating_add( - T::Court::on_dispute_weight() - .saturating_add(T::SimpleDisputes::on_dispute_weight()), + T::Court::on_dispute_weight(&MDMWeight::Court).saturating_add( + T::SimpleDisputes::on_dispute_weight(&MDMWeight::SimpleDisputes { + market_id, + market, + }), + ), ); Ok((Some(full_weight.saturating_sub(overweight))).into()) @@ -1457,6 +1470,8 @@ mod pallet { let report = market.report.as_ref().ok_or(Error::::MarketIsNotReported)?; + // TODO(#782): use multiple benchmarks paths for different dispute mechanisms + let has_failed = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { T::Authorized::has_failed(&market_id, &market)? @@ -2249,6 +2264,8 @@ mod pallet { /// The dispute mechanism is intended to clear its own storage here. fn clear_dispute_mechanism(market_id: &MarketIdOf) -> DispatchResult { let market = >::market(market_id)?; + + // TODO(#782): use multiple benchmarks paths for different dispute mechanisms match market.dispute_mechanism { MarketDisputeMechanism::Authorized => T::Authorized::clear(market_id, &market)?, MarketDisputeMechanism::Court => T::Court::clear(market_id, &market)?, @@ -2546,6 +2563,7 @@ mod pallet { let imbalance_left = Self::settle_bonds(market_id, market, &resolved_outcome, report)?; + // TODO(#782): use multiple benchmarks paths for different dispute mechanisms let remainder = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { T::Authorized::exchange(market_id, market, &resolved_outcome, imbalance_left)? diff --git a/zrml/simple-disputes/src/benchmarks.rs b/zrml/simple-disputes/src/benchmarks.rs index 6fd425a0f..6f64cc8d7 100644 --- a/zrml/simple-disputes/src/benchmarks.rs +++ b/zrml/simple-disputes/src/benchmarks.rs @@ -25,12 +25,32 @@ use crate::Pallet as SimpleDisputes; use super::*; -use frame_benchmarking::{account, benchmarks, whitelisted_caller, Vec}; -use frame_support::{dispatch::RawOrigin, traits::Get}; +use frame_benchmarking::{account, benchmarks, whitelisted_caller}; +use frame_support::{ + dispatch::RawOrigin, + traits::{Get, Imbalance}, +}; use orml_traits::MultiCurrency; use sp_runtime::traits::{One, Saturating}; use zrml_market_commons::MarketCommonsPalletApi; +fn fill_disputes(market_id: MarketIdOf, d: u32) { + for i in 0..d { + let now = >::block_number(); + let disputor = account("disputor", i, 0); + let bond = default_outcome_bond::(i as usize); + T::AssetManager::deposit(Asset::Ztg, &disputor, bond).unwrap(); + let outcome = OutcomeReport::Scalar((2 + i).into()); + SimpleDisputes::::suggest_outcome( + RawOrigin::Signed(disputor).into(), + market_id, + outcome, + ) + .unwrap(); + >::set_block_number(now.saturating_add(T::BlockNumber::one())); + } +} + benchmarks! { suggest_outcome { let d in 1..(T::MaxDisputes::get() - 1); @@ -42,22 +62,8 @@ benchmarks! { let market = market_mock::(); T::MarketCommons::push_market(market.clone()).unwrap(); - let mut now; - - let mut disputes = Vec::new(); - for i in 0..d { - now = >::block_number(); - - let disputor = account("disputor", i, 0); - let last_dispute = MarketDispute { - at: now, - by: disputor, - outcome: OutcomeReport::Scalar((2 + i).into()), - bond: default_outcome_bond::(i as usize), - }; - disputes.push(last_dispute); - >::set_block_number(now.saturating_add(T::BlockNumber::one())); - } + fill_disputes::(market_id, d); + let disputes = Disputes::::get(market_id); let last_dispute = disputes.last().unwrap(); let auto_resolve = last_dispute.at.saturating_add(market.deadlines.dispute_duration); for i in 0..r { @@ -67,9 +73,6 @@ benchmarks! { let now = >::block_number(); - let bounded_vec = >::try_from(disputes).unwrap(); - Disputes::::insert(market_id, bounded_vec); - let dispute_duration_ends_at_block = now.saturating_add(market.deadlines.dispute_duration); for i in 0..e { @@ -90,6 +93,81 @@ benchmarks! { SimpleDisputes::::on_dispute(&market_id, &market).unwrap(); } + on_resolution_weight { + let d in 1..T::MaxDisputes::get(); + + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market.clone()).unwrap(); + + fill_disputes::(market_id, d); + }: { + SimpleDisputes::::on_resolution(&market_id, &market).unwrap(); + } + + exchange_weight { + let d in 1..T::MaxDisputes::get(); + + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market.clone()).unwrap(); + + fill_disputes::(market_id, d); + + let outcome = OutcomeReport::Scalar(1); + let imb = NegativeImbalanceOf::::zero(); + }: { + SimpleDisputes::::exchange(&market_id, &market, &outcome, imb).unwrap(); + } + + get_auto_resolve_weight { + let d in 1..T::MaxDisputes::get(); + + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market.clone()).unwrap(); + + fill_disputes::(market_id, d); + }: { + SimpleDisputes::::get_auto_resolve(&market_id, &market).unwrap(); + } + + has_failed_weight { + let d in 1..T::MaxDisputes::get(); + + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market.clone()).unwrap(); + + fill_disputes::(market_id, d); + }: { + SimpleDisputes::::has_failed(&market_id, &market).unwrap(); + } + + on_global_dispute_weight { + let d in 1..T::MaxDisputes::get(); + + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market.clone()).unwrap(); + + fill_disputes::(market_id, d); + }: { + SimpleDisputes::::on_global_dispute(&market_id, &market).unwrap(); + } + + clear_weight { + let d in 1..T::MaxDisputes::get(); + + let market_id = 0u32.into(); + let market = market_mock::(); + T::MarketCommons::push_market(market.clone()).unwrap(); + + fill_disputes::(market_id, d); + }: { + SimpleDisputes::::clear(&market_id, &market).unwrap(); + } + impl_benchmark_test_suite!( SimpleDisputes, crate::mock::ExtBuilder::default().build(), diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index 303d11d2b..d124d1721 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -33,8 +33,8 @@ pub use simple_disputes_pallet_api::SimpleDisputesPalletApi; use zeitgeist_primitives::{ traits::{DisputeApi, DisputeResolutionApi, ZeitgeistAssetManager}, types::{ - Asset, GlobalDisputeItem, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, - OutcomeReport, Report, + Asset, GlobalDisputeItem, MDMWeight, Market, MarketDispute, MarketDisputeMechanism, + MarketStatus, OutcomeReport, Report, }, }; @@ -124,6 +124,14 @@ mod pallet { MomentOf, Asset>, >; + pub(crate) type MDMWeightOf = MDMWeight< + MarketIdOf, + ::AccountId, + BalanceOf, + ::BlockNumber, + MomentOf, + Asset>, + >; pub(crate) type DisputesOf = BoundedVec< MarketDispute< ::AccountId, @@ -295,7 +303,7 @@ mod pallet { Ok(()) } - fn on_dispute_weight() -> Weight { + fn on_dispute_weight(_mdm_info: &MDMWeightOf) -> Weight { T::WeightInfo::on_dispute_weight() } @@ -320,6 +328,16 @@ mod pallet { Ok(Some(last_dispute.outcome.clone())) } + fn on_resolution_weight(mdm_info: &MDMWeightOf) -> Weight { + match mdm_info { + MDMWeight::SimpleDisputes { market_id, market: _ } => { + let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; + T::WeightInfo::on_resolution_weight(disputes_len) + } + _ => T::WeightInfo::on_resolution_weight(T::MaxDisputes::get()), + } + } + fn exchange( market_id: &Self::MarketId, market: &MarketOf, @@ -374,6 +392,16 @@ mod pallet { Ok(overall_imbalance) } + fn exchange_weight(mdm_info: &MDMWeightOf) -> Weight { + match mdm_info { + MDMWeight::SimpleDisputes { market_id, market: _ } => { + let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; + T::WeightInfo::exchange_weight(disputes_len) + } + _ => T::WeightInfo::exchange_weight(T::MaxDisputes::get()), + } + } + fn get_auto_resolve( market_id: &Self::MarketId, market: &MarketOf, @@ -386,6 +414,16 @@ mod pallet { Ok(Self::get_auto_resolve(disputes.as_slice(), market)) } + fn get_auto_resolve_weight(mdm_info: &MDMWeightOf) -> Weight { + match mdm_info { + MDMWeight::SimpleDisputes { market_id, market: _ } => { + let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; + T::WeightInfo::get_auto_resolve_weight(disputes_len) + } + _ => T::WeightInfo::get_auto_resolve_weight(T::MaxDisputes::get()), + } + } + fn has_failed( market_id: &Self::MarketId, market: &MarketOf, @@ -398,6 +436,16 @@ mod pallet { Ok(disputes.len() == T::MaxDisputes::get() as usize) } + fn has_failed_weight(mdm_info: &MDMWeightOf) -> Weight { + match mdm_info { + MDMWeight::SimpleDisputes { market_id, market: _ } => { + let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; + T::WeightInfo::has_failed_weight(disputes_len) + } + _ => T::WeightInfo::has_failed_weight(T::MaxDisputes::get()), + } + } + fn on_global_dispute( market_id: &Self::MarketId, market: &MarketOf, @@ -417,6 +465,16 @@ mod pallet { .collect()) } + fn on_global_dispute_weight(mdm_info: &MDMWeightOf) -> Weight { + match mdm_info { + MDMWeight::SimpleDisputes { market_id, market: _ } => { + let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; + T::WeightInfo::on_global_dispute_weight(disputes_len) + } + _ => T::WeightInfo::on_global_dispute_weight(T::MaxDisputes::get()), + } + } + fn clear(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { ensure!( market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, @@ -436,6 +494,16 @@ mod pallet { } Ok(()) } + + fn clear_weight(mdm_info: &MDMWeightOf) -> Weight { + match mdm_info { + MDMWeight::SimpleDisputes { market_id, market: _ } => { + let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; + T::WeightInfo::clear_weight(disputes_len) + } + _ => T::WeightInfo::clear_weight(T::MaxDisputes::get()), + } + } } impl SimpleDisputesPalletApi for Pallet where T: Config {} diff --git a/zrml/simple-disputes/src/weights.rs b/zrml/simple-disputes/src/weights.rs index 2143935cc..f4233871d 100644 --- a/zrml/simple-disputes/src/weights.rs +++ b/zrml/simple-disputes/src/weights.rs @@ -47,6 +47,12 @@ use frame_support::{traits::Get, weights::Weight}; pub trait WeightInfoZeitgeist { fn suggest_outcome(d: u32, r: u32, e: u32) -> Weight; fn on_dispute_weight() -> Weight; + fn on_resolution_weight(d: u32) -> Weight; + fn exchange_weight(d: u32) -> Weight; + fn get_auto_resolve_weight(d: u32) -> Weight; + fn has_failed_weight(d: u32) -> Weight; + fn on_global_dispute_weight(d: u32) -> Weight; + fn clear_weight(d: u32) -> Weight; } /// Weight functions for zrml_simple_disputes (automatically generated) @@ -71,4 +77,56 @@ impl WeightInfoZeitgeist for WeightInfo { fn on_dispute_weight() -> Weight { Weight::from_ref_time(0) } + // Storage: SimpleDisputes Disputes (r:1 w:0) + fn on_resolution_weight(d: u32) -> Weight { + Weight::from_ref_time(5_464_000) + // Standard Error: 3_000 + .saturating_add(Weight::from_ref_time(210_000).saturating_mul(d.into())) + .saturating_add(T::DbWeight::get().reads(1)) + } + // Storage: SimpleDisputes Disputes (r:1 w:1) + // Storage: Balances Reserves (r:1 w:1) + // Storage: System Account (r:1 w:1) + fn exchange_weight(d: u32) -> Weight { + Weight::from_ref_time(18_573_000) + // Standard Error: 14_000 + .saturating_add(Weight::from_ref_time(19_710_000).saturating_mul(d.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(d.into()))) + .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(d.into()))) + } + // Storage: SimpleDisputes Disputes (r:1 w:0) + fn get_auto_resolve_weight(d: u32) -> Weight { + Weight::from_ref_time(5_535_000) + // Standard Error: 3_000 + .saturating_add(Weight::from_ref_time(145_000).saturating_mul(d.into())) + .saturating_add(T::DbWeight::get().reads(1)) + } + // Storage: SimpleDisputes Disputes (r:1 w:0) + fn has_failed_weight(d: u32) -> Weight { + Weight::from_ref_time(5_685_000) + // Standard Error: 2_000 + .saturating_add(Weight::from_ref_time(117_000).saturating_mul(d.into())) + .saturating_add(T::DbWeight::get().reads(1)) + } + // Storage: SimpleDisputes Disputes (r:1 w:0) + fn on_global_dispute_weight(d: u32) -> Weight { + Weight::from_ref_time(5_815_000) + // Standard Error: 2_000 + .saturating_add(Weight::from_ref_time(66_000).saturating_mul(d.into())) + .saturating_add(T::DbWeight::get().reads(1)) + } + // Storage: SimpleDisputes Disputes (r:1 w:1) + // Storage: Balances Reserves (r:1 w:1) + // Storage: System Account (r:1 w:1) + fn clear_weight(d: u32) -> Weight { + Weight::from_ref_time(15_958_000) + // Standard Error: 17_000 + .saturating_add(Weight::from_ref_time(13_085_000).saturating_mul(d.into())) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(d.into()))) + .saturating_add(T::DbWeight::get().writes(1)) + .saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(d.into()))) + } } From f48a0a36a50d65173ea6bed439f4c038ba97af31 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Tue, 18 Apr 2023 10:42:58 +0200 Subject: [PATCH 47/58] add mdm weights to on_resolution --- primitives/src/traits/dispute_api.rs | 14 ++--- zrml/authorized/src/lib.rs | 14 ++--- zrml/court/src/lib.rs | 14 ++--- zrml/prediction-markets/src/lib.rs | 94 +++++++++++++++++++--------- zrml/simple-disputes/src/lib.rs | 14 ++--- 5 files changed, 94 insertions(+), 56 deletions(-) diff --git a/primitives/src/traits/dispute_api.rs b/primitives/src/traits/dispute_api.rs index f67281e53..edabaf2f7 100644 --- a/primitives/src/traits/dispute_api.rs +++ b/primitives/src/traits/dispute_api.rs @@ -65,7 +65,7 @@ pub trait DisputeApi { fn on_dispute(market_id: &Self::MarketId, market: &MarketOfDisputeApi) -> DispatchResult; /// Return the weight of the `on_dispute` function. - fn on_dispute_weight(mdm_info: &MDMWeightOf) -> Weight; + fn on_dispute_weight(mdm_info: MDMWeightOf) -> Weight; /// Manage market resolution of a disputed market. /// @@ -82,7 +82,7 @@ pub trait DisputeApi { ) -> Result, DispatchError>; /// Return the weight of the `on_resolution` function. - fn on_resolution_weight(mdm_info: &MDMWeightOf) -> Weight; + fn on_resolution_weight(mdm_info: MDMWeightOf) -> Weight; /// Allow the transfer of funds from the API caller to the API consumer and back. /// This can be based on the final resolution outcome of the market. @@ -104,7 +104,7 @@ pub trait DisputeApi { ) -> Result; /// Return the weight of the `exchange` function. - fn exchange_weight(mdm_info: &MDMWeightOf) -> Weight; + fn exchange_weight(mdm_info: MDMWeightOf) -> Weight; /// Query the future resolution block of a disputed market. /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. @@ -118,7 +118,7 @@ pub trait DisputeApi { ) -> Result, DispatchError>; /// Return the weight of the `get_auto_resolve` function. - fn get_auto_resolve_weight(mdm_info: &MDMWeightOf) -> Weight; + fn get_auto_resolve_weight(mdm_info: MDMWeightOf) -> Weight; /// Returns `true` if the market dispute mechanism /// was unable to come to a conclusion. @@ -129,7 +129,7 @@ pub trait DisputeApi { ) -> Result; /// Return the weight of the `has_failed` function. - fn has_failed_weight(mdm_info: &MDMWeightOf) -> Weight; + fn has_failed_weight(mdm_info: MDMWeightOf) -> Weight; /// Called, when a global dispute is started. /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. @@ -142,7 +142,7 @@ pub trait DisputeApi { ) -> Result>, DispatchError>; /// Return the weight of the `on_global_dispute` function. - fn on_global_dispute_weight(mdm_info: &MDMWeightOf) -> Weight; + fn on_global_dispute_weight(mdm_info: MDMWeightOf) -> Weight; /// Allow the API consumer to clear storage items of the dispute mechanism. /// This may be called, when the dispute mechanism is no longer needed. @@ -150,7 +150,7 @@ pub trait DisputeApi { fn clear(market_id: &Self::MarketId, market: &MarketOfDisputeApi) -> DispatchResult; /// Return the weight of the `clear` function. - fn clear_weight(mdm_info: &MDMWeightOf) -> Weight; + fn clear_weight(mdm_info: MDMWeightOf) -> Weight; } type MarketOfDisputeResolutionApi = Market< diff --git a/zrml/authorized/src/lib.rs b/zrml/authorized/src/lib.rs index 55b26777c..ac1929da8 100644 --- a/zrml/authorized/src/lib.rs +++ b/zrml/authorized/src/lib.rs @@ -224,7 +224,7 @@ mod pallet { Ok(()) } - fn on_dispute_weight(_mdm_info: &MDMWeightOf) -> Weight { + fn on_dispute_weight(_mdm_info: MDMWeightOf) -> Weight { T::WeightInfo::on_dispute_weight() } @@ -240,7 +240,7 @@ mod pallet { Ok(report.map(|r| r.outcome)) } - fn on_resolution_weight(_mdm_info: &MDMWeightOf) -> Weight { + fn on_resolution_weight(_mdm_info: MDMWeightOf) -> Weight { T::WeightInfo::on_resolution_weight() } @@ -258,7 +258,7 @@ mod pallet { Ok(overall_imbalance) } - fn exchange_weight(_mdm_info: &MDMWeightOf) -> Weight { + fn exchange_weight(_mdm_info: MDMWeightOf) -> Weight { T::WeightInfo::exchange_weight() } @@ -273,7 +273,7 @@ mod pallet { Ok(Self::get_auto_resolve(market_id)) } - fn get_auto_resolve_weight(_mdm_info: &MDMWeightOf) -> Weight { + fn get_auto_resolve_weight(_mdm_info: MDMWeightOf) -> Weight { T::WeightInfo::get_auto_resolve_weight() } @@ -286,7 +286,7 @@ mod pallet { Ok(false) } - fn has_failed_weight(_mdm_info: &MDMWeightOf) -> Weight { + fn has_failed_weight(_mdm_info: MDMWeightOf) -> Weight { T::WeightInfo::has_failed_weight() } @@ -302,7 +302,7 @@ mod pallet { Ok(Vec::new()) } - fn on_global_dispute_weight(_mdm_info: &MDMWeightOf) -> Weight { + fn on_global_dispute_weight(_mdm_info: MDMWeightOf) -> Weight { T::WeightInfo::on_global_dispute_weight() } @@ -316,7 +316,7 @@ mod pallet { Ok(()) } - fn clear_weight(_mdm_info: &MDMWeightOf) -> Weight { + fn clear_weight(_mdm_info: MDMWeightOf) -> Weight { T::WeightInfo::clear_weight() } } diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index 0e3816d1e..aca008ad3 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -569,7 +569,7 @@ mod pallet { Ok(()) } - fn on_dispute_weight(_mdm_info: &MDMWeightOf) -> Weight { + fn on_dispute_weight(_mdm_info: MDMWeightOf) -> Weight { T::WeightInfo::on_dispute_weight() } @@ -605,7 +605,7 @@ mod pallet { Ok(Some(first)) } - fn on_resolution_weight(_mdm_info: &MDMWeightOf) -> Weight { + fn on_resolution_weight(_mdm_info: MDMWeightOf) -> Weight { T::WeightInfo::on_resolution_weight() } @@ -623,7 +623,7 @@ mod pallet { Ok(overall_imbalance) } - fn exchange_weight(_mdm_info: &MDMWeightOf) -> Weight { + fn exchange_weight(_mdm_info: MDMWeightOf) -> Weight { T::WeightInfo::exchange_weight() } @@ -638,7 +638,7 @@ mod pallet { Ok(None) } - fn get_auto_resolve_weight(_mdm_info: &MDMWeightOf) -> Weight { + fn get_auto_resolve_weight(_mdm_info: MDMWeightOf) -> Weight { T::WeightInfo::get_auto_resolve_weight() } @@ -650,7 +650,7 @@ mod pallet { Ok(false) } - fn has_failed_weight(_mdm_info: &MDMWeightOf) -> Weight { + fn has_failed_weight(_mdm_info: MDMWeightOf) -> Weight { T::WeightInfo::has_failed_weight() } @@ -665,7 +665,7 @@ mod pallet { Ok(Vec::new()) } - fn on_global_dispute_weight(_mdm_info: &MDMWeightOf) -> Weight { + fn on_global_dispute_weight(_mdm_info: MDMWeightOf) -> Weight { T::WeightInfo::on_global_dispute_weight() } @@ -679,7 +679,7 @@ mod pallet { Ok(()) } - fn clear_weight(_mdm_info: &MDMWeightOf) -> Weight { + fn clear_weight(_mdm_info: MDMWeightOf) -> Weight { T::WeightInfo::clear_weight() } } diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index cdf73265b..7c11765b7 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -618,8 +618,8 @@ mod pallet { /// Complexity: `O(n)`, where `n` is the number of outstanding disputes. #[pallet::weight( T::WeightInfo::dispute_authorized().saturating_add( - T::Court::on_dispute_weight(&MDMWeight::Default).saturating_add( - T::SimpleDisputes::on_dispute_weight(&MDMWeight::Default) + T::Court::on_dispute_weight(MDMWeight::Default).saturating_add( + T::SimpleDisputes::on_dispute_weight(MDMWeight::Default) ) ) )] @@ -636,8 +636,8 @@ mod pallet { let overweight = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { T::Authorized::on_dispute(&market_id, &market)?; - T::Court::on_dispute_weight(&MDMWeight::Court).saturating_add( - T::SimpleDisputes::on_dispute_weight(&MDMWeight::SimpleDisputes { + T::Court::on_dispute_weight(MDMWeight::Court).saturating_add( + T::SimpleDisputes::on_dispute_weight(MDMWeight::SimpleDisputes { market_id, market: market.clone(), }), @@ -645,8 +645,8 @@ mod pallet { } MarketDisputeMechanism::Court => { T::Court::on_dispute(&market_id, &market)?; - T::Authorized::on_dispute_weight(&MDMWeight::Authorized).saturating_add( - T::SimpleDisputes::on_dispute_weight(&MDMWeight::SimpleDisputes { + T::Authorized::on_dispute_weight(MDMWeight::Authorized).saturating_add( + T::SimpleDisputes::on_dispute_weight(MDMWeight::SimpleDisputes { market_id, market: market.clone(), }), @@ -654,8 +654,8 @@ mod pallet { } MarketDisputeMechanism::SimpleDisputes => { T::SimpleDisputes::on_dispute(&market_id, &market)?; - T::Court::on_dispute_weight(&MDMWeight::Court) - .saturating_add(T::Authorized::on_dispute_weight(&MDMWeight::Authorized)) + T::Court::on_dispute_weight(MDMWeight::Court) + .saturating_add(T::Authorized::on_dispute_weight(MDMWeight::Authorized)) } }; @@ -672,8 +672,8 @@ mod pallet { Self::deposit_event(Event::MarketDisputed(market_id, MarketStatus::Disputed)); let full_weight = T::WeightInfo::dispute_authorized().saturating_add( - T::Court::on_dispute_weight(&MDMWeight::Court).saturating_add( - T::SimpleDisputes::on_dispute_weight(&MDMWeight::SimpleDisputes { + T::Court::on_dispute_weight(MDMWeight::Court).saturating_add( + T::SimpleDisputes::on_dispute_weight(MDMWeight::SimpleDisputes { market_id, market, }), @@ -2555,33 +2555,51 @@ mod pallet { fn resolve_disputed_market( market_id: &MarketIdOf, market: &MarketOf, - ) -> Result { + ) -> Result<(OutcomeReport, Weight), DispatchError> { let report = market.report.as_ref().ok_or(Error::::MarketIsNotReported)?; + let mut weight = Weight::zero(); - let resolved_outcome: OutcomeReport = + let (resolved_outcome, w): (OutcomeReport, Weight) = Self::get_resolved_outcome(market_id, market, &report.outcome)?; + weight = weight.saturating_add(w); let imbalance_left = Self::settle_bonds(market_id, market, &resolved_outcome, report)?; - // TODO(#782): use multiple benchmarks paths for different dispute mechanisms let remainder = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { - T::Authorized::exchange(market_id, market, &resolved_outcome, imbalance_left)? + let remainder = T::Authorized::exchange( + market_id, + market, + &resolved_outcome, + imbalance_left, + )?; + weight = weight + .saturating_add(T::Authorized::exchange_weight(MDMWeight::Authorized)); + remainder } MarketDisputeMechanism::Court => { - T::Court::exchange(market_id, market, &resolved_outcome, imbalance_left)? + let remainder = + T::Court::exchange(market_id, market, &resolved_outcome, imbalance_left)?; + weight = weight.saturating_add(T::Court::exchange_weight(MDMWeight::Court)); + remainder + } + MarketDisputeMechanism::SimpleDisputes => { + let remainder = T::SimpleDisputes::exchange( + market_id, + market, + &resolved_outcome, + imbalance_left, + )?; + weight = weight.saturating_add(T::SimpleDisputes::exchange_weight( + MDMWeight::SimpleDisputes { market_id: *market_id, market: market.clone() }, + )); + remainder } - MarketDisputeMechanism::SimpleDisputes => T::SimpleDisputes::exchange( - market_id, - market, - &resolved_outcome, - imbalance_left, - )?, }; T::Slash::on_unbalanced(remainder); - Ok(resolved_outcome) + Ok((resolved_outcome, weight)) } /// Get the outcome the market should resolve to. @@ -2589,31 +2607,46 @@ mod pallet { market_id: &MarketIdOf, market: &MarketOf, reported_outcome: &OutcomeReport, - ) -> Result { + ) -> Result<(OutcomeReport, Weight), DispatchError> { let mut resolved_outcome_option = None; + let mut weight = Weight::zero(); #[cfg(feature = "with-global-disputes")] if let Some(o) = T::GlobalDisputes::determine_voting_winner(market_id) { resolved_outcome_option = Some(o); } - // TODO(#782): use multiple benchmarks paths for different dispute mechanisms - // Try to get the outcome of the MDM. If the MDM failed to resolve, default to // the oracle's report. if resolved_outcome_option.is_none() { resolved_outcome_option = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { + weight = weight.saturating_add(T::Authorized::on_resolution_weight( + MDMWeight::Authorized, + )); T::Authorized::on_resolution(market_id, market)? } - MarketDisputeMechanism::Court => T::Court::on_resolution(market_id, market)?, + MarketDisputeMechanism::Court => { + weight = + weight.saturating_add(T::Court::on_resolution_weight(MDMWeight::Court)); + T::Court::on_resolution(market_id, market)? + } MarketDisputeMechanism::SimpleDisputes => { + weight = weight.saturating_add(T::SimpleDisputes::on_resolution_weight( + MDMWeight::SimpleDisputes { + market_id: *market_id, + market: market.clone(), + }, + )); T::SimpleDisputes::on_resolution(market_id, market)? } }; } - Ok(resolved_outcome_option.unwrap_or_else(|| reported_outcome.clone())) + let resolved_outcome = + resolved_outcome_option.unwrap_or_else(|| reported_outcome.clone()); + + Ok((resolved_outcome, weight)) } /// Manage the outstanding bonds (oracle, outsider, dispute) of the market. @@ -2693,7 +2726,12 @@ mod pallet { let resolved_outcome = match market.status { MarketStatus::Reported => Self::resolve_reported_market(market_id, market)?, - MarketStatus::Disputed => Self::resolve_disputed_market(market_id, market)?, + MarketStatus::Disputed => { + let (resolved_outcome, weight) = + Self::resolve_disputed_market(market_id, market)?; + total_weight = total_weight.saturating_add(weight); + resolved_outcome + } _ => return Err(Error::::InvalidMarketStatus.into()), }; let clean_up_weight = Self::clean_up_pool(market, market_id, &resolved_outcome)?; diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index d124d1721..c96ff8280 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -303,7 +303,7 @@ mod pallet { Ok(()) } - fn on_dispute_weight(_mdm_info: &MDMWeightOf) -> Weight { + fn on_dispute_weight(_mdm_info: MDMWeightOf) -> Weight { T::WeightInfo::on_dispute_weight() } @@ -328,7 +328,7 @@ mod pallet { Ok(Some(last_dispute.outcome.clone())) } - fn on_resolution_weight(mdm_info: &MDMWeightOf) -> Weight { + fn on_resolution_weight(mdm_info: MDMWeightOf) -> Weight { match mdm_info { MDMWeight::SimpleDisputes { market_id, market: _ } => { let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; @@ -392,7 +392,7 @@ mod pallet { Ok(overall_imbalance) } - fn exchange_weight(mdm_info: &MDMWeightOf) -> Weight { + fn exchange_weight(mdm_info: MDMWeightOf) -> Weight { match mdm_info { MDMWeight::SimpleDisputes { market_id, market: _ } => { let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; @@ -414,7 +414,7 @@ mod pallet { Ok(Self::get_auto_resolve(disputes.as_slice(), market)) } - fn get_auto_resolve_weight(mdm_info: &MDMWeightOf) -> Weight { + fn get_auto_resolve_weight(mdm_info: MDMWeightOf) -> Weight { match mdm_info { MDMWeight::SimpleDisputes { market_id, market: _ } => { let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; @@ -436,7 +436,7 @@ mod pallet { Ok(disputes.len() == T::MaxDisputes::get() as usize) } - fn has_failed_weight(mdm_info: &MDMWeightOf) -> Weight { + fn has_failed_weight(mdm_info: MDMWeightOf) -> Weight { match mdm_info { MDMWeight::SimpleDisputes { market_id, market: _ } => { let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; @@ -465,7 +465,7 @@ mod pallet { .collect()) } - fn on_global_dispute_weight(mdm_info: &MDMWeightOf) -> Weight { + fn on_global_dispute_weight(mdm_info: MDMWeightOf) -> Weight { match mdm_info { MDMWeight::SimpleDisputes { market_id, market: _ } => { let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; @@ -495,7 +495,7 @@ mod pallet { Ok(()) } - fn clear_weight(mdm_info: &MDMWeightOf) -> Weight { + fn clear_weight(mdm_info: MDMWeightOf) -> Weight { match mdm_info { MDMWeight::SimpleDisputes { market_id, market: _ } => { let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; From cbe528a5b795c6e98eef8dcfcd8fb4eaba52a285 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Tue, 18 Apr 2023 11:28:47 +0200 Subject: [PATCH 48/58] add tests for pm --- zrml/prediction-markets/src/lib.rs | 2 +- zrml/prediction-markets/src/tests.rs | 164 +++++++++++++++++++++++++++ 2 files changed, 165 insertions(+), 1 deletion(-) diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 7c11765b7..0ae48662b 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -2603,7 +2603,7 @@ mod pallet { } /// Get the outcome the market should resolve to. - fn get_resolved_outcome( + pub(crate) fn get_resolved_outcome( market_id: &MarketIdOf, market: &MarketOf, reported_outcome: &OutcomeReport, diff --git a/zrml/prediction-markets/src/tests.rs b/zrml/prediction-markets/src/tests.rs index 8d76e7e49..1068ad9b9 100644 --- a/zrml/prediction-markets/src/tests.rs +++ b/zrml/prediction-markets/src/tests.rs @@ -2697,6 +2697,170 @@ fn dispute_fails_disputed_already() { }); } +#[test] +fn dispute_fails_if_market_not_reported() { + ExtBuilder::default().build().execute_with(|| { + let end = 2; + assert_ok!(PredictionMarkets::create_market( + Origin::signed(ALICE), + Asset::Ztg, + BOB, + MarketPeriod::Block(0..end), + get_deadlines(), + gen_metadata(2), + MarketCreation::Permissionless, + MarketType::Categorical(::MinCategories::get()), + MarketDisputeMechanism::Authorized, + ScoringRule::CPMM, + )); + + // Run to the end of the trading phase. + let market = MarketCommons::market(&0).unwrap(); + let grace_period = end + market.deadlines.grace_period; + run_to_block(grace_period + 1); + + // no report happening here... + + let dispute_at = grace_period + 2; + run_to_block(dispute_at); + + assert_noop!( + PredictionMarkets::dispute(Origin::signed(CHARLIE), 0), + Error::::InvalidMarketStatus, + ); + }); +} + +#[test] +fn dispute_reserves_dispute_bond() { + ExtBuilder::default().build().execute_with(|| { + let end = 2; + assert_ok!(PredictionMarkets::create_market( + Origin::signed(ALICE), + Asset::Ztg, + BOB, + MarketPeriod::Block(0..end), + get_deadlines(), + gen_metadata(2), + MarketCreation::Permissionless, + MarketType::Categorical(::MinCategories::get()), + MarketDisputeMechanism::Authorized, + ScoringRule::CPMM, + )); + + // Run to the end of the trading phase. + let market = MarketCommons::market(&0).unwrap(); + let grace_period = end + market.deadlines.grace_period; + run_to_block(grace_period + 1); + + assert_ok!(PredictionMarkets::report( + Origin::signed(BOB), + 0, + OutcomeReport::Categorical(1) + )); + + let dispute_at = grace_period + 2; + run_to_block(dispute_at); + + let free_charlie_before = Balances::free_balance(CHARLIE); + let reserved_charlie = Balances::reserved_balance(CHARLIE); + assert_eq!(reserved_charlie, 0); + + assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); + + let free_charlie_after = Balances::free_balance(CHARLIE); + assert_eq!(free_charlie_before - free_charlie_after, DisputeBond::get()); + + let reserved_charlie = Balances::reserved_balance(CHARLIE); + assert_eq!(reserved_charlie, DisputeBond::get()); + }); +} + +#[test] +fn dispute_updates_market() { + ExtBuilder::default().build().execute_with(|| { + let end = 2; + assert_ok!(PredictionMarkets::create_market( + Origin::signed(ALICE), + Asset::Ztg, + BOB, + MarketPeriod::Block(0..end), + get_deadlines(), + gen_metadata(2), + MarketCreation::Permissionless, + MarketType::Categorical(::MinCategories::get()), + MarketDisputeMechanism::Authorized, + ScoringRule::CPMM, + )); + + // Run to the end of the trading phase. + let market = MarketCommons::market(&0).unwrap(); + let grace_period = end + market.deadlines.grace_period; + run_to_block(grace_period + 1); + + assert_ok!(PredictionMarkets::report( + Origin::signed(BOB), + 0, + OutcomeReport::Categorical(1) + )); + + let dispute_at = grace_period + 2; + run_to_block(dispute_at); + + let market = MarketCommons::market(&0).unwrap(); + assert_eq!(market.status, MarketStatus::Reported); + assert_eq!(market.bonds.dispute, None); + + assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); + + let market = MarketCommons::market(&0).unwrap(); + assert_eq!(market.status, MarketStatus::Disputed); + assert_eq!( + market.bonds.dispute, + Some(Bond { who: CHARLIE, value: DisputeBond::get(), is_settled: false }) + ); + }); +} + +#[test] +fn dispute_emits_event() { + ExtBuilder::default().build().execute_with(|| { + let end = 2; + assert_ok!(PredictionMarkets::create_market( + Origin::signed(ALICE), + Asset::Ztg, + BOB, + MarketPeriod::Block(0..end), + get_deadlines(), + gen_metadata(2), + MarketCreation::Permissionless, + MarketType::Categorical(::MinCategories::get()), + MarketDisputeMechanism::Authorized, + ScoringRule::CPMM, + )); + + // Run to the end of the trading phase. + let market = MarketCommons::market(&0).unwrap(); + let grace_period = end + market.deadlines.grace_period; + run_to_block(grace_period + 1); + + assert_ok!(PredictionMarkets::report( + Origin::signed(BOB), + 0, + OutcomeReport::Categorical(1) + )); + + let dispute_at = grace_period + 2; + run_to_block(dispute_at); + + assert_ok!(PredictionMarkets::dispute(Origin::signed(CHARLIE), 0,)); + + System::assert_last_event( + Event::MarketDisputed(0u32.into(), MarketStatus::Disputed).into(), + ); + }); +} + #[test] fn it_allows_anyone_to_report_an_unreported_market() { ExtBuilder::default().build().execute_with(|| { From 7ab62c48c39b380b6edcc51a747d4cd0490f9679 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Tue, 18 Apr 2023 14:33:37 +0200 Subject: [PATCH 49/58] modify migration logs, fix try-runtime --- zrml/prediction-markets/src/migrations.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 7e45d23c7..68f126e83 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -122,12 +122,6 @@ impl OnRuntimeUpgrade for AddOutsiderAn if let Some(first_dispute) = old_disputes.first() { let OldMarketDispute { at: _, by, outcome: _ } = first_dispute; dispute_bond = Some(Bond::new(by.clone(), T::DisputeBond::get())); - } else { - log::warn!( - "MoveDataToSimpleDisputes: Could not find first dispute for market id \ - {:?}", - market_id - ); } } @@ -417,8 +411,8 @@ use frame_support::dispatch::EncodeLike; use sp_runtime::SaturatedConversion; use zeitgeist_primitives::types::{MarketDispute, OldMarketDispute}; -const PREDICTION_MARKETS_REQUIRED_STORAGE_VERSION: u16 = 7; -const PREDICTION_MARKETS_NEXT_STORAGE_VERSION: u16 = 8; +const PREDICTION_MARKETS_REQUIRED_STORAGE_VERSION: u16 = 6; +const PREDICTION_MARKETS_NEXT_STORAGE_VERSION: u16 = 7; #[cfg(feature = "try-runtime")] type OldDisputesOf = frame_support::BoundedVec< @@ -503,7 +497,9 @@ where &old_dispute.by, ); if reserved_balance < bond.saturated_into::().saturated_into() { - log::error!( + // warns for battery station market id 386 + // https://discord.com/channels/737780518313000960/817041223201587230/958682619413934151 + log::warn!( "MoveDataToSimpleDisputes: Could not unreserve {:?} for {:?} because \ reserved balance is only {:?}. Market id: {:?}", bond, From 86bd97e43f63a7b43891c3fd984ed90f3421cb43 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 20 Apr 2023 07:31:37 +0200 Subject: [PATCH 50/58] little benchmark fix --- zrml/authorized/src/benchmarks.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/zrml/authorized/src/benchmarks.rs b/zrml/authorized/src/benchmarks.rs index ff3cbd3f1..714fcdf3c 100644 --- a/zrml/authorized/src/benchmarks.rs +++ b/zrml/authorized/src/benchmarks.rs @@ -110,12 +110,7 @@ benchmarks! { let market = market_mock::(); T::MarketCommons::push_market(market.clone()).unwrap(); - frame_system::Pallet::::set_block_number(42u32.into()); - - let now = frame_system::Pallet::::block_number(); - let resolve_at = now.saturating_add(T::CorrectionPeriod::get()); - - let report = AuthorityReport { resolve_at, outcome: OutcomeReport::Scalar(0) }; + let report = AuthorityReport { resolve_at: 0u32.into(), outcome: OutcomeReport::Scalar(0) }; AuthorizedOutcomeReports::::insert(market_id, report); }: { Authorized::::on_resolution(&market_id, &market).unwrap(); From af60129ced95718e1a2d136f8b0705e089f5da42 Mon Sep 17 00:00:00 2001 From: Chralt Date: Thu, 20 Apr 2023 07:32:38 +0200 Subject: [PATCH 51/58] Update zrml/authorized/src/benchmarks.rs Co-authored-by: Harald Heckmann --- zrml/authorized/src/benchmarks.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/zrml/authorized/src/benchmarks.rs b/zrml/authorized/src/benchmarks.rs index 714fcdf3c..74de5613c 100644 --- a/zrml/authorized/src/benchmarks.rs +++ b/zrml/authorized/src/benchmarks.rs @@ -131,11 +131,7 @@ benchmarks! { let market_id = 0u32.into(); let market = market_mock::(); T::MarketCommons::push_market(market.clone()).unwrap(); - - let now = frame_system::Pallet::::block_number(); - let resolve_at = now.saturating_add(T::CorrectionPeriod::get()); - - let report = AuthorityReport { resolve_at, outcome: OutcomeReport::Scalar(0) }; + let report = AuthorityReport { resolve_at: 0u32.into(), outcome: OutcomeReport::Scalar(0) }; AuthorizedOutcomeReports::::insert(market_id, report); }: { Authorized::::get_auto_resolve(&market_id, &market).unwrap(); From ddf14ffc9006d715b26a167f7e5e4f1dd8ffb693 Mon Sep 17 00:00:00 2001 From: Chralt Date: Thu, 20 Apr 2023 07:33:42 +0200 Subject: [PATCH 52/58] Update zrml/authorized/src/benchmarks.rs Co-authored-by: Harald Heckmann --- zrml/authorized/src/benchmarks.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/zrml/authorized/src/benchmarks.rs b/zrml/authorized/src/benchmarks.rs index 74de5613c..1ddf58cf8 100644 --- a/zrml/authorized/src/benchmarks.rs +++ b/zrml/authorized/src/benchmarks.rs @@ -157,11 +157,7 @@ benchmarks! { let market_id = 0u32.into(); let market = market_mock::(); T::MarketCommons::push_market(market.clone()).unwrap(); - - let now = frame_system::Pallet::::block_number(); - let resolve_at = now.saturating_add(T::CorrectionPeriod::get()); - - let report = AuthorityReport { resolve_at, outcome: OutcomeReport::Scalar(0) }; + let report = AuthorityReport { resolve_at: 0u32.into(), outcome: OutcomeReport::Scalar(0) }; AuthorizedOutcomeReports::::insert(market_id, report); }: { Authorized::::clear(&market_id, &market).unwrap(); From 85131915f06664f8c2d7857e8e6809760fca86a7 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Thu, 20 Apr 2023 07:58:11 +0200 Subject: [PATCH 53/58] use result with weight struct --- zrml/prediction-markets/src/lib.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 0ae48662b..3169da074 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -66,7 +66,8 @@ mod pallet { types::{ Asset, Bond, Deadlines, MDMWeight, Market, MarketBonds, MarketCreation, MarketDisputeMechanism, MarketPeriod, MarketStatus, MarketType, MultiHash, - OldMarketDispute, OutcomeReport, Report, ScalarPosition, ScoringRule, SubsidyUntil, + OldMarketDispute, OutcomeReport, Report, ResultWithWeightInfo, ScalarPosition, + ScoringRule, SubsidyUntil, }, }; #[cfg(feature = "with-global-disputes")] @@ -2555,13 +2556,14 @@ mod pallet { fn resolve_disputed_market( market_id: &MarketIdOf, market: &MarketOf, - ) -> Result<(OutcomeReport, Weight), DispatchError> { + ) -> Result, DispatchError> { let report = market.report.as_ref().ok_or(Error::::MarketIsNotReported)?; let mut weight = Weight::zero(); - let (resolved_outcome, w): (OutcomeReport, Weight) = + let res: ResultWithWeightInfo = Self::get_resolved_outcome(market_id, market, &report.outcome)?; - weight = weight.saturating_add(w); + let resolved_outcome = res.result; + weight = weight.saturating_add(res.weight); let imbalance_left = Self::settle_bonds(market_id, market, &resolved_outcome, report)?; @@ -2599,7 +2601,9 @@ mod pallet { T::Slash::on_unbalanced(remainder); - Ok((resolved_outcome, weight)) + let res = ResultWithWeightInfo { result: resolved_outcome, weight }; + + Ok(res) } /// Get the outcome the market should resolve to. @@ -2607,7 +2611,7 @@ mod pallet { market_id: &MarketIdOf, market: &MarketOf, reported_outcome: &OutcomeReport, - ) -> Result<(OutcomeReport, Weight), DispatchError> { + ) -> Result, DispatchError> { let mut resolved_outcome_option = None; let mut weight = Weight::zero(); @@ -2646,7 +2650,9 @@ mod pallet { let resolved_outcome = resolved_outcome_option.unwrap_or_else(|| reported_outcome.clone()); - Ok((resolved_outcome, weight)) + let res = ResultWithWeightInfo { result: resolved_outcome, weight }; + + Ok(res) } /// Manage the outstanding bonds (oracle, outsider, dispute) of the market. @@ -2727,10 +2733,9 @@ mod pallet { let resolved_outcome = match market.status { MarketStatus::Reported => Self::resolve_reported_market(market_id, market)?, MarketStatus::Disputed => { - let (resolved_outcome, weight) = - Self::resolve_disputed_market(market_id, market)?; - total_weight = total_weight.saturating_add(weight); - resolved_outcome + let res = Self::resolve_disputed_market(market_id, market)?; + total_weight = total_weight.saturating_add(res.weight); + res.result } _ => return Err(Error::::InvalidMarketStatus.into()), }; From 1e0fcbcfb2fb11128327cd66baf69c04c7612dbc Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Fri, 21 Apr 2023 12:56:21 +0200 Subject: [PATCH 54/58] improve dispute api weight system --- primitives/src/market.rs | 12 -- primitives/src/traits.rs | 2 +- primitives/src/traits/dispute_api.rs | 72 +++---- zrml/authorized/src/authorized_pallet_api.rs | 4 +- zrml/authorized/src/lib.rs | 135 +++++++----- zrml/authorized/src/tests.rs | 11 +- zrml/court/src/court_pallet_api.rs | 4 +- zrml/court/src/lib.rs | 134 ++++++++---- zrml/court/src/tests.rs | 2 +- zrml/prediction-markets/src/lib.rs | 113 +++++----- zrml/simple-disputes/src/lib.rs | 198 ++++++++++-------- .../src/simple_disputes_pallet_api.rs | 4 +- zrml/simple-disputes/src/tests.rs | 2 +- 13 files changed, 382 insertions(+), 311 deletions(-) diff --git a/primitives/src/market.rs b/primitives/src/market.rs index a7a6900d2..6eeb4e9ca 100644 --- a/primitives/src/market.rs +++ b/primitives/src/market.rs @@ -204,18 +204,6 @@ pub struct MarketDispute { pub bond: Balance, } -#[derive(Default)] -pub enum MDMWeight { - Authorized, - Court, - SimpleDisputes { - market_id: MarketId, - market: Market, - }, - #[default] - Default, -} - /// How a market should resolve disputes #[derive(Clone, Decode, Encode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)] pub enum MarketDisputeMechanism { diff --git a/primitives/src/traits.rs b/primitives/src/traits.rs index fe7ec219f..a1be3cd57 100644 --- a/primitives/src/traits.rs +++ b/primitives/src/traits.rs @@ -22,7 +22,7 @@ mod market_id; mod swaps; mod zeitgeist_multi_reservable_currency; -pub use dispute_api::{DisputeApi, DisputeResolutionApi}; +pub use dispute_api::{DisputeApi, DisputeMaxWeightApi, DisputeResolutionApi}; pub use market_commons_pallet_api::MarketCommonsPalletApi; pub use market_id::MarketId; pub use swaps::Swaps; diff --git a/primitives/src/traits/dispute_api.rs b/primitives/src/traits/dispute_api.rs index edabaf2f7..385bbd7de 100644 --- a/primitives/src/traits/dispute_api.rs +++ b/primitives/src/traits/dispute_api.rs @@ -20,10 +20,10 @@ extern crate alloc; use crate::{ outcome_report::OutcomeReport, - types::{Asset, GlobalDisputeItem, MDMWeight, Market}, + types::{Asset, GlobalDisputeItem, Market, ResultWithWeightInfo}, }; use alloc::vec::Vec; -use frame_support::{dispatch::DispatchResult, pallet_prelude::Weight}; +use frame_support::pallet_prelude::Weight; use parity_scale_codec::MaxEncodedLen; use sp_runtime::DispatchError; @@ -37,15 +37,6 @@ type MarketOfDisputeApi = Market< Asset<::MarketId>, >; -type MDMWeightOf = MDMWeight< - ::MarketId, - ::AccountId, - ::Balance, - ::BlockNumber, - ::Moment, - Asset<::MarketId>, ->; - type GlobalDisputeItemOfDisputeApi = GlobalDisputeItem<::AccountId, ::Balance>; @@ -62,10 +53,10 @@ pub trait DisputeApi { /// /// Further interaction with the dispute API (if necessary) **should** happen through an /// associated pallet. **May** assume that `market.dispute_mechanism` refers to the calling dispute API. - fn on_dispute(market_id: &Self::MarketId, market: &MarketOfDisputeApi) -> DispatchResult; - - /// Return the weight of the `on_dispute` function. - fn on_dispute_weight(mdm_info: MDMWeightOf) -> Weight; + fn on_dispute( + market_id: &Self::MarketId, + market: &MarketOfDisputeApi, + ) -> Result, DispatchError>; /// Manage market resolution of a disputed market. /// @@ -79,10 +70,7 @@ pub trait DisputeApi { fn on_resolution( market_id: &Self::MarketId, market: &MarketOfDisputeApi, - ) -> Result, DispatchError>; - - /// Return the weight of the `on_resolution` function. - fn on_resolution_weight(mdm_info: MDMWeightOf) -> Weight; + ) -> Result>, DispatchError>; /// Allow the transfer of funds from the API caller to the API consumer and back. /// This can be based on the final resolution outcome of the market. @@ -101,12 +89,7 @@ pub trait DisputeApi { market: &MarketOfDisputeApi, resolved_outcome: &OutcomeReport, amount: Self::NegativeImbalance, - ) -> Result; - - /// Return the weight of the `exchange` function. - fn exchange_weight(mdm_info: MDMWeightOf) -> Weight; - - /// Query the future resolution block of a disputed market. + ) -> Result, DispatchError>; /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. /// /// # Returns @@ -115,10 +98,7 @@ pub trait DisputeApi { fn get_auto_resolve( market_id: &Self::MarketId, market: &MarketOfDisputeApi, - ) -> Result, DispatchError>; - - /// Return the weight of the `get_auto_resolve` function. - fn get_auto_resolve_weight(mdm_info: MDMWeightOf) -> Weight; + ) -> Result>, DispatchError>; /// Returns `true` if the market dispute mechanism /// was unable to come to a conclusion. @@ -126,10 +106,7 @@ pub trait DisputeApi { fn has_failed( market_id: &Self::MarketId, market: &MarketOfDisputeApi, - ) -> Result; - - /// Return the weight of the `has_failed` function. - fn has_failed_weight(mdm_info: MDMWeightOf) -> Weight; + ) -> Result, DispatchError>; /// Called, when a global dispute is started. /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. @@ -139,18 +116,33 @@ pub trait DisputeApi { fn on_global_dispute( market_id: &Self::MarketId, market: &MarketOfDisputeApi, - ) -> Result>, DispatchError>; - - /// Return the weight of the `on_global_dispute` function. - fn on_global_dispute_weight(mdm_info: MDMWeightOf) -> Weight; + ) -> Result>>, DispatchError>; /// Allow the API consumer to clear storage items of the dispute mechanism. /// This may be called, when the dispute mechanism is no longer needed. /// **May** assume that `market.dispute_mechanism` refers to the calling dispute API. - fn clear(market_id: &Self::MarketId, market: &MarketOfDisputeApi) -> DispatchResult; + fn clear( + market_id: &Self::MarketId, + market: &MarketOfDisputeApi, + ) -> Result, DispatchError>; +} - /// Return the weight of the `clear` function. - fn clear_weight(mdm_info: MDMWeightOf) -> Weight; +pub trait DisputeMaxWeightApi { + /// Return the max weight of the `on_dispute` function. + fn on_dispute_max_weight() -> Weight; + /// Return the max weight of the `on_resolution` function. + fn on_resolution_max_weight() -> Weight; + /// Return the max weight of the `exchange` function. + fn exchange_max_weight() -> Weight; + /// Query the future resolution block of a disputed market. + /// Return the max weight of the `get_auto_resolve` function. + fn get_auto_resolve_max_weight() -> Weight; + /// Return the max weight of the `has_failed` function. + fn has_failed_max_weight() -> Weight; + /// Return the max weight of the `on_global_dispute` function. + fn on_global_dispute_max_weight() -> Weight; + /// Return the max weight of the `clear` function. + fn clear_max_weight() -> Weight; } type MarketOfDisputeResolutionApi = Market< diff --git a/zrml/authorized/src/authorized_pallet_api.rs b/zrml/authorized/src/authorized_pallet_api.rs index b9a1f4185..f9ac39c21 100644 --- a/zrml/authorized/src/authorized_pallet_api.rs +++ b/zrml/authorized/src/authorized_pallet_api.rs @@ -15,6 +15,6 @@ // You should have received a copy of the GNU General Public License // along with Zeitgeist. If not, see . -use zeitgeist_primitives::traits::DisputeApi; +use zeitgeist_primitives::traits::{DisputeApi, DisputeMaxWeightApi}; -pub trait AuthorizedPalletApi: DisputeApi {} +pub trait AuthorizedPalletApi: DisputeApi + DisputeMaxWeightApi {} diff --git a/zrml/authorized/src/lib.rs b/zrml/authorized/src/lib.rs index ac1929da8..675061058 100644 --- a/zrml/authorized/src/lib.rs +++ b/zrml/authorized/src/lib.rs @@ -38,7 +38,7 @@ mod pallet { use alloc::vec::Vec; use core::marker::PhantomData; use frame_support::{ - dispatch::{DispatchResult, DispatchResultWithPostInfo}, + dispatch::DispatchResultWithPostInfo, ensure, pallet_prelude::{ConstU32, EnsureOrigin, OptionQuery, StorageMap, Weight}, traits::{Currency, Get, Hooks, IsType, StorageVersion}, @@ -47,10 +47,10 @@ mod pallet { use frame_system::pallet_prelude::OriginFor; use sp_runtime::{traits::Saturating, DispatchError}; use zeitgeist_primitives::{ - traits::{DisputeApi, DisputeResolutionApi}, + traits::{DisputeApi, DisputeMaxWeightApi, DisputeResolutionApi}, types::{ - Asset, AuthorityReport, GlobalDisputeItem, MDMWeight, Market, MarketDisputeMechanism, - MarketStatus, OutcomeReport, + Asset, AuthorityReport, GlobalDisputeItem, Market, MarketDisputeMechanism, + MarketStatus, OutcomeReport, ResultWithWeightInfo, }, }; use zrml_market_commons::MarketCommonsPalletApi; @@ -75,14 +75,6 @@ mod pallet { MomentOf, Asset>, >; - pub(crate) type MDMWeightOf = MDMWeight< - MarketIdOf, - ::AccountId, - BalanceOf, - ::BlockNumber, - MomentOf, - Asset>, - >; #[pallet::call] impl Pallet { @@ -204,6 +196,39 @@ mod pallet { } } + impl DisputeMaxWeightApi for Pallet + where + T: Config, + { + fn on_dispute_max_weight() -> Weight { + T::WeightInfo::on_dispute_weight() + } + + fn on_resolution_max_weight() -> Weight { + T::WeightInfo::on_resolution_weight() + } + + fn exchange_max_weight() -> Weight { + T::WeightInfo::exchange_weight() + } + + fn get_auto_resolve_max_weight() -> Weight { + T::WeightInfo::get_auto_resolve_weight() + } + + fn has_failed_max_weight() -> Weight { + T::WeightInfo::has_failed_weight() + } + + fn on_global_dispute_max_weight() -> Weight { + T::WeightInfo::on_global_dispute_weight() + } + + fn clear_max_weight() -> Weight { + T::WeightInfo::clear_weight() + } + } + impl DisputeApi for Pallet where T: Config, @@ -216,32 +241,37 @@ mod pallet { type Moment = MomentOf; type Origin = T::Origin; - fn on_dispute(_: &Self::MarketId, market: &MarketOf) -> DispatchResult { + fn on_dispute( + _: &Self::MarketId, + market: &MarketOf, + ) -> Result, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Authorized, Error::::MarketDoesNotHaveDisputeMechanismAuthorized ); - Ok(()) - } - fn on_dispute_weight(_mdm_info: MDMWeightOf) -> Weight { - T::WeightInfo::on_dispute_weight() + let res = + ResultWithWeightInfo { result: (), weight: T::WeightInfo::on_dispute_weight() }; + + Ok(res) } fn on_resolution( market_id: &Self::MarketId, market: &MarketOf, - ) -> Result, DispatchError> { + ) -> Result>, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Authorized, Error::::MarketDoesNotHaveDisputeMechanismAuthorized ); let report = AuthorizedOutcomeReports::::take(market_id); - Ok(report.map(|r| r.outcome)) - } - fn on_resolution_weight(_mdm_info: MDMWeightOf) -> Weight { - T::WeightInfo::on_resolution_weight() + let res = ResultWithWeightInfo { + result: report.map(|r| r.outcome), + weight: T::WeightInfo::on_resolution_weight(), + }; + + Ok(res) } fn exchange( @@ -249,75 +279,86 @@ mod pallet { market: &MarketOf, _: &OutcomeReport, overall_imbalance: NegativeImbalanceOf, - ) -> Result, DispatchError> { + ) -> Result>, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Authorized, Error::::MarketDoesNotHaveDisputeMechanismAuthorized ); // all funds to treasury - Ok(overall_imbalance) - } + let res = ResultWithWeightInfo { + result: overall_imbalance, + weight: T::WeightInfo::exchange_weight(), + }; - fn exchange_weight(_mdm_info: MDMWeightOf) -> Weight { - T::WeightInfo::exchange_weight() + Ok(res) } fn get_auto_resolve( market_id: &Self::MarketId, market: &MarketOf, - ) -> Result, DispatchError> { + ) -> Result>, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Authorized, Error::::MarketDoesNotHaveDisputeMechanismAuthorized ); - Ok(Self::get_auto_resolve(market_id)) - } - fn get_auto_resolve_weight(_mdm_info: MDMWeightOf) -> Weight { - T::WeightInfo::get_auto_resolve_weight() + let res = ResultWithWeightInfo { + result: Self::get_auto_resolve(market_id), + weight: T::WeightInfo::get_auto_resolve_weight(), + }; + + Ok(res) } - fn has_failed(_: &Self::MarketId, market: &MarketOf) -> Result { + fn has_failed( + _: &Self::MarketId, + market: &MarketOf, + ) -> Result, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Authorized, Error::::MarketDoesNotHaveDisputeMechanismAuthorized ); - Ok(false) - } + let res = + ResultWithWeightInfo { result: false, weight: T::WeightInfo::has_failed_weight() }; - fn has_failed_weight(_mdm_info: MDMWeightOf) -> Weight { - T::WeightInfo::has_failed_weight() + Ok(res) } fn on_global_dispute( _: &Self::MarketId, market: &MarketOf, - ) -> Result>, DispatchError> { + ) -> Result< + ResultWithWeightInfo>>, + DispatchError, + > { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Authorized, Error::::MarketDoesNotHaveDisputeMechanismAuthorized ); - Ok(Vec::new()) - } + let res = ResultWithWeightInfo { + result: Vec::new(), + weight: T::WeightInfo::on_global_dispute_weight(), + }; - fn on_global_dispute_weight(_mdm_info: MDMWeightOf) -> Weight { - T::WeightInfo::on_global_dispute_weight() + Ok(res) } - fn clear(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { + fn clear( + market_id: &Self::MarketId, + market: &MarketOf, + ) -> Result, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Authorized, Error::::MarketDoesNotHaveDisputeMechanismAuthorized ); AuthorizedOutcomeReports::::remove(market_id); - Ok(()) - } - fn clear_weight(_mdm_info: MDMWeightOf) -> Weight { - T::WeightInfo::clear_weight() + let res = ResultWithWeightInfo { result: (), weight: T::WeightInfo::clear_weight() }; + + Ok(res) } } diff --git a/zrml/authorized/src/tests.rs b/zrml/authorized/src/tests.rs index 60cebd57d..515e656e2 100644 --- a/zrml/authorized/src/tests.rs +++ b/zrml/authorized/src/tests.rs @@ -160,7 +160,7 @@ fn authorize_market_outcome_fails_on_unauthorized_account() { #[test] fn on_resolution_fails_if_no_report_was_submitted() { ExtBuilder::default().build().execute_with(|| { - let report = Authorized::on_resolution(&0, &market_mock::()).unwrap(); + let report = Authorized::on_resolution(&0, &market_mock::()).unwrap().result; assert!(report.is_none()); }); } @@ -196,7 +196,10 @@ fn on_resolution_returns_the_reported_outcome() { 0, OutcomeReport::Scalar(2) )); - assert_eq!(Authorized::on_resolution(&0, &market).unwrap(), Some(OutcomeReport::Scalar(2))); + assert_eq!( + Authorized::on_resolution(&0, &market).unwrap().result, + Some(OutcomeReport::Scalar(2)) + ); }); } @@ -241,7 +244,7 @@ fn get_auto_resolve_works() { )); let now = frame_system::Pallet::::block_number(); let resolve_at = now + ::CorrectionPeriod::get(); - assert_eq!(Authorized::get_auto_resolve(&0, &market).unwrap(), Some(resolve_at),); + assert_eq!(Authorized::get_auto_resolve(&0, &market).unwrap().result, Some(resolve_at),); }); } @@ -249,6 +252,6 @@ fn get_auto_resolve_works() { fn get_auto_resolve_returns_none_without_market_storage() { ExtBuilder::default().build().execute_with(|| { let market = market_mock::(); - assert_eq!(Authorized::get_auto_resolve(&0, &market).unwrap(), None,); + assert_eq!(Authorized::get_auto_resolve(&0, &market).unwrap().result, None,); }); } diff --git a/zrml/court/src/court_pallet_api.rs b/zrml/court/src/court_pallet_api.rs index 73b9e2829..8d0535aa8 100644 --- a/zrml/court/src/court_pallet_api.rs +++ b/zrml/court/src/court_pallet_api.rs @@ -15,6 +15,6 @@ // You should have received a copy of the GNU General Public License // along with Zeitgeist. If not, see . -use zeitgeist_primitives::traits::DisputeApi; +use zeitgeist_primitives::traits::{DisputeApi, DisputeMaxWeightApi}; -pub trait CourtPalletApi: DisputeApi {} +pub trait CourtPalletApi: DisputeApi + DisputeMaxWeightApi {} diff --git a/zrml/court/src/lib.rs b/zrml/court/src/lib.rs index aca008ad3..7b7f049dc 100644 --- a/zrml/court/src/lib.rs +++ b/zrml/court/src/lib.rs @@ -66,10 +66,10 @@ mod pallet { ArithmeticError, DispatchError, SaturatedConversion, }; use zeitgeist_primitives::{ - traits::{DisputeApi, DisputeResolutionApi}, + traits::{DisputeApi, DisputeMaxWeightApi, DisputeResolutionApi}, types::{ - Asset, GlobalDisputeItem, MDMWeight, Market, MarketDispute, MarketDisputeMechanism, - MarketStatus, OutcomeReport, + Asset, GlobalDisputeItem, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, + OutcomeReport, ResultWithWeightInfo, }, }; use zrml_market_commons::MarketCommonsPalletApi; @@ -102,14 +102,6 @@ mod pallet { MomentOf, Asset>, >; - pub(crate) type MDMWeightOf = MDMWeight< - MarketIdOf, - ::AccountId, - BalanceOf, - ::BlockNumber, - MomentOf, - Asset>, - >; #[pallet::call] impl Pallet { @@ -548,6 +540,39 @@ mod pallet { } } + impl DisputeMaxWeightApi for Pallet + where + T: Config, + { + fn on_dispute_max_weight() -> Weight { + T::WeightInfo::on_dispute_weight() + } + + fn on_resolution_max_weight() -> Weight { + T::WeightInfo::on_resolution_weight() + } + + fn exchange_max_weight() -> Weight { + T::WeightInfo::exchange_weight() + } + + fn get_auto_resolve_max_weight() -> Weight { + T::WeightInfo::get_auto_resolve_weight() + } + + fn has_failed_max_weight() -> Weight { + T::WeightInfo::has_failed_weight() + } + + fn on_global_dispute_max_weight() -> Weight { + T::WeightInfo::on_global_dispute_weight() + } + + fn clear_max_weight() -> Weight { + T::WeightInfo::clear_weight() + } + } + impl DisputeApi for Pallet where T: Config, @@ -560,17 +585,19 @@ mod pallet { type Moment = MomentOf; type Origin = T::Origin; - fn on_dispute(_: &Self::MarketId, market: &MarketOf) -> DispatchResult { + fn on_dispute( + _: &Self::MarketId, + market: &MarketOf, + ) -> Result, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, Error::::MarketDoesNotHaveCourtMechanism ); - Ok(()) - } + let res = + ResultWithWeightInfo { result: (), weight: T::WeightInfo::on_dispute_weight() }; - fn on_dispute_weight(_mdm_info: MDMWeightOf) -> Weight { - T::WeightInfo::on_dispute_weight() + Ok(res) } // Set jurors that sided on the second most voted outcome as tardy. Jurors are only @@ -580,7 +607,7 @@ mod pallet { fn on_resolution( market_id: &Self::MarketId, market: &MarketOf, - ) -> Result, DispatchError> { + ) -> Result>, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, Error::::MarketDoesNotHaveCourtMechanism @@ -602,11 +629,13 @@ mod pallet { Self::slash_losers_to_award_winners(&valid_winners_and_losers, &first)?; let _ = Votes::::clear_prefix(market_id, u32::max_value(), None); let _ = RequestedJurors::::clear_prefix(market_id, u32::max_value(), None); - Ok(Some(first)) - } - fn on_resolution_weight(_mdm_info: MDMWeightOf) -> Weight { - T::WeightInfo::on_resolution_weight() + let res = ResultWithWeightInfo { + result: Some(first), + weight: T::WeightInfo::on_resolution_weight(), + }; + + Ok(res) } fn exchange( @@ -614,73 +643,86 @@ mod pallet { market: &MarketOf, _: &OutcomeReport, overall_imbalance: NegativeImbalanceOf, - ) -> Result, DispatchError> { + ) -> Result>, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, Error::::MarketDoesNotHaveCourtMechanism ); // TODO all funds to treasury? - Ok(overall_imbalance) - } - fn exchange_weight(_mdm_info: MDMWeightOf) -> Weight { - T::WeightInfo::exchange_weight() + let res = ResultWithWeightInfo { + result: overall_imbalance, + weight: T::WeightInfo::exchange_weight(), + }; + Ok(res) } fn get_auto_resolve( _: &Self::MarketId, market: &MarketOf, - ) -> Result, DispatchError> { + ) -> Result>, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, Error::::MarketDoesNotHaveCourtMechanism ); - Ok(None) - } - fn get_auto_resolve_weight(_mdm_info: MDMWeightOf) -> Weight { - T::WeightInfo::get_auto_resolve_weight() + let res = ResultWithWeightInfo { + result: None, + weight: T::WeightInfo::get_auto_resolve_weight(), + }; + + Ok(res) } - fn has_failed(_: &Self::MarketId, market: &MarketOf) -> Result { + fn has_failed( + _: &Self::MarketId, + market: &MarketOf, + ) -> Result, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, Error::::MarketDoesNotHaveCourtMechanism ); - Ok(false) - } - fn has_failed_weight(_mdm_info: MDMWeightOf) -> Weight { - T::WeightInfo::has_failed_weight() + let res = + ResultWithWeightInfo { result: false, weight: T::WeightInfo::has_failed_weight() }; + + Ok(res) } fn on_global_dispute( _: &Self::MarketId, market: &MarketOf, - ) -> Result>, DispatchError> { + ) -> Result< + ResultWithWeightInfo>>, + DispatchError, + > { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, Error::::MarketDoesNotHaveCourtMechanism ); - Ok(Vec::new()) - } - fn on_global_dispute_weight(_mdm_info: MDMWeightOf) -> Weight { - T::WeightInfo::on_global_dispute_weight() + let res = ResultWithWeightInfo { + result: Vec::new(), + weight: T::WeightInfo::on_global_dispute_weight(), + }; + + Ok(res) } - fn clear(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { + fn clear( + market_id: &Self::MarketId, + market: &MarketOf, + ) -> Result, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::Court, Error::::MarketDoesNotHaveCourtMechanism ); let _ = Votes::::clear_prefix(market_id, u32::max_value(), None); let _ = RequestedJurors::::clear_prefix(market_id, u32::max_value(), None); - Ok(()) - } - fn clear_weight(_mdm_info: MDMWeightOf) -> Weight { - T::WeightInfo::clear_weight() + let res = ResultWithWeightInfo { result: (), weight: T::WeightInfo::clear_weight() }; + + Ok(res) } } diff --git a/zrml/court/src/tests.rs b/zrml/court/src/tests.rs index a7ef0e046..0932af74b 100644 --- a/zrml/court/src/tests.rs +++ b/zrml/court/src/tests.rs @@ -202,7 +202,7 @@ fn on_resolution_decides_market_outcome_based_on_the_majority() { Court::vote(Origin::signed(ALICE), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(BOB), 0, OutcomeReport::Scalar(1)).unwrap(); Court::vote(Origin::signed(CHARLIE), 0, OutcomeReport::Scalar(2)).unwrap(); - let outcome = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap(); + let outcome = Court::on_resolution(&0, &DEFAULT_MARKET).unwrap().result; assert_eq!(outcome, Some(OutcomeReport::Scalar(1))); }); } diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 3169da074..5ba8036a0 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -64,10 +64,9 @@ mod pallet { constants::MILLISECS_PER_BLOCK, traits::{DisputeApi, DisputeResolutionApi, Swaps, ZeitgeistAssetManager}, types::{ - Asset, Bond, Deadlines, MDMWeight, Market, MarketBonds, MarketCreation, - MarketDisputeMechanism, MarketPeriod, MarketStatus, MarketType, MultiHash, - OldMarketDispute, OutcomeReport, Report, ResultWithWeightInfo, ScalarPosition, - ScoringRule, SubsidyUntil, + Asset, Bond, Deadlines, Market, MarketBonds, MarketCreation, MarketDisputeMechanism, + MarketPeriod, MarketStatus, MarketType, MultiHash, OldMarketDispute, OutcomeReport, + Report, ResultWithWeightInfo, ScalarPosition, ScoringRule, SubsidyUntil, }, }; #[cfg(feature = "with-global-disputes")] @@ -76,6 +75,7 @@ mod pallet { zrml_global_disputes::GlobalDisputesPalletApi, }; + use zeitgeist_primitives::traits::DisputeMaxWeightApi; use zrml_liquidity_mining::LiquidityMiningPalletApi; use zrml_market_commons::MarketCommonsPalletApi; @@ -619,8 +619,8 @@ mod pallet { /// Complexity: `O(n)`, where `n` is the number of outstanding disputes. #[pallet::weight( T::WeightInfo::dispute_authorized().saturating_add( - T::Court::on_dispute_weight(MDMWeight::Default).saturating_add( - T::SimpleDisputes::on_dispute_weight(MDMWeight::Default) + T::Court::on_dispute_max_weight().saturating_add( + T::SimpleDisputes::on_dispute_max_weight() ) ) )] @@ -637,26 +637,18 @@ mod pallet { let overweight = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { T::Authorized::on_dispute(&market_id, &market)?; - T::Court::on_dispute_weight(MDMWeight::Court).saturating_add( - T::SimpleDisputes::on_dispute_weight(MDMWeight::SimpleDisputes { - market_id, - market: market.clone(), - }), - ) + T::Court::on_dispute_max_weight() + .saturating_add(T::SimpleDisputes::on_dispute_max_weight()) } MarketDisputeMechanism::Court => { T::Court::on_dispute(&market_id, &market)?; - T::Authorized::on_dispute_weight(MDMWeight::Authorized).saturating_add( - T::SimpleDisputes::on_dispute_weight(MDMWeight::SimpleDisputes { - market_id, - market: market.clone(), - }), - ) + T::Authorized::on_dispute_max_weight() + .saturating_add(T::SimpleDisputes::on_dispute_max_weight()) } MarketDisputeMechanism::SimpleDisputes => { T::SimpleDisputes::on_dispute(&market_id, &market)?; - T::Court::on_dispute_weight(MDMWeight::Court) - .saturating_add(T::Authorized::on_dispute_weight(MDMWeight::Authorized)) + T::Court::on_dispute_max_weight() + .saturating_add(T::Authorized::on_dispute_max_weight()) } }; @@ -673,12 +665,8 @@ mod pallet { Self::deposit_event(Event::MarketDisputed(market_id, MarketStatus::Disputed)); let full_weight = T::WeightInfo::dispute_authorized().saturating_add( - T::Court::on_dispute_weight(MDMWeight::Court).saturating_add( - T::SimpleDisputes::on_dispute_weight(MDMWeight::SimpleDisputes { - market_id, - market, - }), - ), + T::Court::on_dispute_max_weight() + .saturating_add(T::SimpleDisputes::on_dispute_max_weight()), ); Ok((Some(full_weight.saturating_sub(overweight))).into()) @@ -1473,7 +1461,7 @@ mod pallet { // TODO(#782): use multiple benchmarks paths for different dispute mechanisms - let has_failed = match market.dispute_mechanism { + let res_0 = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { T::Authorized::has_failed(&market_id, &market)? } @@ -1482,9 +1470,10 @@ mod pallet { T::SimpleDisputes::has_failed(&market_id, &market)? } }; + let has_failed = res_0.result; ensure!(has_failed, Error::::MarketDisputeMechanismNotFailed); - let gd_items = match market.dispute_mechanism { + let res_1 = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { T::Authorized::on_global_dispute(&market_id, &market)? } @@ -1496,6 +1485,8 @@ mod pallet { } }; + let gd_items = res_1.result; + T::GlobalDisputes::push_voting_outcome( &market_id, report.outcome.clone(), @@ -1701,7 +1692,7 @@ mod pallet { type ResolveOrigin: EnsureOrigin; /// See [`DisputeApi`]. - type SimpleDisputes: DisputeApi< + type SimpleDisputes: zrml_simple_disputes::SimpleDisputesPalletApi< AccountId = Self::AccountId, Balance = BalanceOf, NegativeImbalance = NegativeImbalanceOf, @@ -2238,17 +2229,18 @@ mod pallet { } MarketStatus::Disputed => { // TODO(#782): use multiple benchmarks paths for different dispute mechanisms - let auto_resolve_block_opt = match market.dispute_mechanism { - MarketDisputeMechanism::Authorized => { - T::Authorized::get_auto_resolve(market_id, &market)? - } - MarketDisputeMechanism::Court => { - T::Court::get_auto_resolve(market_id, &market)? - } - MarketDisputeMechanism::SimpleDisputes => { - T::SimpleDisputes::get_auto_resolve(market_id, &market)? - } - }; + let ResultWithWeightInfo { result: auto_resolve_block_opt, weight: _ } = + match market.dispute_mechanism { + MarketDisputeMechanism::Authorized => { + T::Authorized::get_auto_resolve(market_id, &market)? + } + MarketDisputeMechanism::Court => { + T::Court::get_auto_resolve(market_id, &market)? + } + MarketDisputeMechanism::SimpleDisputes => { + T::SimpleDisputes::get_auto_resolve(market_id, &market)? + } + }; if let Some(auto_resolve_block) = auto_resolve_block_opt { let ids_len = remove_auto_resolve::(market_id, auto_resolve_block); (ids_len, 0u32) @@ -2569,32 +2561,32 @@ mod pallet { let remainder = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { - let remainder = T::Authorized::exchange( + let res = T::Authorized::exchange( market_id, market, &resolved_outcome, imbalance_left, )?; - weight = weight - .saturating_add(T::Authorized::exchange_weight(MDMWeight::Authorized)); + let remainder = res.result; + weight = weight.saturating_add(res.weight); remainder } MarketDisputeMechanism::Court => { - let remainder = + let res = T::Court::exchange(market_id, market, &resolved_outcome, imbalance_left)?; - weight = weight.saturating_add(T::Court::exchange_weight(MDMWeight::Court)); + let remainder = res.result; + weight = weight.saturating_add(res.weight); remainder } MarketDisputeMechanism::SimpleDisputes => { - let remainder = T::SimpleDisputes::exchange( + let res = T::SimpleDisputes::exchange( market_id, market, &resolved_outcome, imbalance_left, )?; - weight = weight.saturating_add(T::SimpleDisputes::exchange_weight( - MDMWeight::SimpleDisputes { market_id: *market_id, market: market.clone() }, - )); + let remainder = res.result; + weight = weight.saturating_add(res.weight); remainder } }; @@ -2625,24 +2617,19 @@ mod pallet { if resolved_outcome_option.is_none() { resolved_outcome_option = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { - weight = weight.saturating_add(T::Authorized::on_resolution_weight( - MDMWeight::Authorized, - )); - T::Authorized::on_resolution(market_id, market)? + let res = T::Authorized::on_resolution(market_id, market)?; + weight = weight.saturating_add(res.weight); + res.result } MarketDisputeMechanism::Court => { - weight = - weight.saturating_add(T::Court::on_resolution_weight(MDMWeight::Court)); - T::Court::on_resolution(market_id, market)? + let res = T::Court::on_resolution(market_id, market)?; + weight = weight.saturating_add(res.weight); + res.result } MarketDisputeMechanism::SimpleDisputes => { - weight = weight.saturating_add(T::SimpleDisputes::on_resolution_weight( - MDMWeight::SimpleDisputes { - market_id: *market_id, - market: market.clone(), - }, - )); - T::SimpleDisputes::on_resolution(market_id, market)? + let res = T::SimpleDisputes::on_resolution(market_id, market)?; + weight = weight.saturating_add(res.weight); + res.result } }; } diff --git a/zrml/simple-disputes/src/lib.rs b/zrml/simple-disputes/src/lib.rs index c96ff8280..aa60ff84b 100644 --- a/zrml/simple-disputes/src/lib.rs +++ b/zrml/simple-disputes/src/lib.rs @@ -31,10 +31,10 @@ pub mod weights; pub use pallet::*; pub use simple_disputes_pallet_api::SimpleDisputesPalletApi; use zeitgeist_primitives::{ - traits::{DisputeApi, DisputeResolutionApi, ZeitgeistAssetManager}, + traits::{DisputeApi, DisputeMaxWeightApi, DisputeResolutionApi, ZeitgeistAssetManager}, types::{ - Asset, GlobalDisputeItem, MDMWeight, Market, MarketDispute, MarketDisputeMechanism, - MarketStatus, OutcomeReport, Report, + Asset, GlobalDisputeItem, Market, MarketDispute, MarketDisputeMechanism, MarketStatus, + OutcomeReport, Report, ResultWithWeightInfo, }, }; @@ -124,14 +124,6 @@ mod pallet { MomentOf, Asset>, >; - pub(crate) type MDMWeightOf = MDMWeight< - MarketIdOf, - ::AccountId, - BalanceOf, - ::BlockNumber, - MomentOf, - Asset>, - >; pub(crate) type DisputesOf = BoundedVec< MarketDispute< ::AccountId, @@ -283,6 +275,39 @@ mod pallet { } } + impl DisputeMaxWeightApi for Pallet + where + T: Config, + { + fn on_dispute_max_weight() -> Weight { + T::WeightInfo::on_dispute_weight() + } + + fn on_resolution_max_weight() -> Weight { + T::WeightInfo::on_resolution_weight(T::MaxDisputes::get()) + } + + fn exchange_max_weight() -> Weight { + T::WeightInfo::exchange_weight(T::MaxDisputes::get()) + } + + fn get_auto_resolve_max_weight() -> Weight { + T::WeightInfo::get_auto_resolve_weight(T::MaxDisputes::get()) + } + + fn has_failed_max_weight() -> Weight { + T::WeightInfo::has_failed_weight(T::MaxDisputes::get()) + } + + fn on_global_dispute_max_weight() -> Weight { + T::WeightInfo::on_global_dispute_weight(T::MaxDisputes::get()) + } + + fn clear_max_weight() -> Weight { + T::WeightInfo::clear_weight(T::MaxDisputes::get()) + } + } + impl DisputeApi for Pallet where T: Config, @@ -295,22 +320,25 @@ mod pallet { type Moment = MomentOf; type Origin = T::Origin; - fn on_dispute(_: &Self::MarketId, market: &MarketOf) -> DispatchResult { + fn on_dispute( + _: &Self::MarketId, + market: &MarketOf, + ) -> Result, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, Error::::MarketDoesNotHaveSimpleDisputesMechanism ); - Ok(()) - } - fn on_dispute_weight(_mdm_info: MDMWeightOf) -> Weight { - T::WeightInfo::on_dispute_weight() + let res = + ResultWithWeightInfo { result: (), weight: T::WeightInfo::on_dispute_weight() }; + + Ok(res) } fn on_resolution( market_id: &Self::MarketId, market: &MarketOf, - ) -> Result, DispatchError> { + ) -> Result>, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, Error::::MarketDoesNotHaveSimpleDisputesMechanism @@ -322,20 +350,20 @@ mod pallet { let last_dispute = match disputes.last() { Some(l) => l, // if there are no disputes, then the market is resolved with the default report - None => return Ok(None), + None => { + return Ok(ResultWithWeightInfo { + result: None, + weight: T::WeightInfo::on_resolution_weight(disputes.len() as u32), + }); + } }; - Ok(Some(last_dispute.outcome.clone())) - } + let res = ResultWithWeightInfo { + result: Some(last_dispute.outcome.clone()), + weight: T::WeightInfo::on_resolution_weight(disputes.len() as u32), + }; - fn on_resolution_weight(mdm_info: MDMWeightOf) -> Weight { - match mdm_info { - MDMWeight::SimpleDisputes { market_id, market: _ } => { - let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; - T::WeightInfo::on_resolution_weight(disputes_len) - } - _ => T::WeightInfo::on_resolution_weight(T::MaxDisputes::get()), - } + Ok(res) } fn exchange( @@ -343,7 +371,7 @@ mod pallet { market: &MarketOf, resolved_outcome: &OutcomeReport, mut overall_imbalance: NegativeImbalanceOf, - ) -> Result, DispatchError> { + ) -> Result>, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, Error::::MarketDoesNotHaveSimpleDisputesMechanism @@ -389,100 +417,94 @@ mod pallet { Disputes::::remove(market_id); - Ok(overall_imbalance) - } + let res = ResultWithWeightInfo { + result: overall_imbalance, + weight: T::WeightInfo::exchange_weight(disputes.len() as u32), + }; - fn exchange_weight(mdm_info: MDMWeightOf) -> Weight { - match mdm_info { - MDMWeight::SimpleDisputes { market_id, market: _ } => { - let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; - T::WeightInfo::exchange_weight(disputes_len) - } - _ => T::WeightInfo::exchange_weight(T::MaxDisputes::get()), - } + Ok(res) } fn get_auto_resolve( market_id: &Self::MarketId, market: &MarketOf, - ) -> Result, DispatchError> { + ) -> Result>, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, Error::::MarketDoesNotHaveSimpleDisputesMechanism ); let disputes = Disputes::::get(market_id); - Ok(Self::get_auto_resolve(disputes.as_slice(), market)) - } - fn get_auto_resolve_weight(mdm_info: MDMWeightOf) -> Weight { - match mdm_info { - MDMWeight::SimpleDisputes { market_id, market: _ } => { - let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; - T::WeightInfo::get_auto_resolve_weight(disputes_len) - } - _ => T::WeightInfo::get_auto_resolve_weight(T::MaxDisputes::get()), - } + let res = ResultWithWeightInfo { + result: Self::get_auto_resolve(disputes.as_slice(), market), + weight: T::WeightInfo::get_auto_resolve_weight(disputes.len() as u32), + }; + + Ok(res) } fn has_failed( market_id: &Self::MarketId, market: &MarketOf, - ) -> Result { + ) -> Result, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, Error::::MarketDoesNotHaveSimpleDisputesMechanism ); let disputes = >::get(market_id); - Ok(disputes.len() == T::MaxDisputes::get() as usize) - } + let disputes_len = disputes.len() as u32; - fn has_failed_weight(mdm_info: MDMWeightOf) -> Weight { - match mdm_info { - MDMWeight::SimpleDisputes { market_id, market: _ } => { - let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; - T::WeightInfo::has_failed_weight(disputes_len) - } - _ => T::WeightInfo::has_failed_weight(T::MaxDisputes::get()), - } + let res = ResultWithWeightInfo { + result: disputes_len == T::MaxDisputes::get(), + weight: T::WeightInfo::has_failed_weight(disputes_len), + }; + + Ok(res) } fn on_global_dispute( market_id: &Self::MarketId, market: &MarketOf, - ) -> Result>, DispatchError> { + ) -> Result< + ResultWithWeightInfo>>, + DispatchError, + > { ensure!( market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, Error::::MarketDoesNotHaveSimpleDisputesMechanism ); - Ok(>::get(market_id) - .iter() - .map(|dispute| GlobalDisputeItem { - outcome: dispute.outcome.clone(), - owner: dispute.by.clone(), - initial_vote_amount: dispute.bond, - }) - .collect()) - } + let disputes_len = >::decode_len(market_id).unwrap_or(0) as u32; + + let res = ResultWithWeightInfo { + result: >::get(market_id) + .iter() + .map(|dispute| GlobalDisputeItem { + outcome: dispute.outcome.clone(), + owner: dispute.by.clone(), + initial_vote_amount: dispute.bond, + }) + .collect(), + weight: T::WeightInfo::on_global_dispute_weight(disputes_len), + }; - fn on_global_dispute_weight(mdm_info: MDMWeightOf) -> Weight { - match mdm_info { - MDMWeight::SimpleDisputes { market_id, market: _ } => { - let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; - T::WeightInfo::on_global_dispute_weight(disputes_len) - } - _ => T::WeightInfo::on_global_dispute_weight(T::MaxDisputes::get()), - } + Ok(res) } - fn clear(market_id: &Self::MarketId, market: &MarketOf) -> DispatchResult { + fn clear( + market_id: &Self::MarketId, + market: &MarketOf, + ) -> Result, DispatchError> { ensure!( market.dispute_mechanism == MarketDisputeMechanism::SimpleDisputes, Error::::MarketDoesNotHaveSimpleDisputesMechanism ); + + let mut disputes_len = 0u32; // `Disputes` is emtpy unless the market is disputed, so this is just a defensive // check. if market.status == MarketStatus::Disputed { + disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; for dispute in Disputes::::take(market_id).iter() { T::AssetManager::unreserve_named( &Self::reserve_id(), @@ -492,17 +514,13 @@ mod pallet { ); } } - Ok(()) - } - fn clear_weight(mdm_info: MDMWeightOf) -> Weight { - match mdm_info { - MDMWeight::SimpleDisputes { market_id, market: _ } => { - let disputes_len = Disputes::::decode_len(market_id).unwrap_or(0) as u32; - T::WeightInfo::clear_weight(disputes_len) - } - _ => T::WeightInfo::clear_weight(T::MaxDisputes::get()), - } + let res = ResultWithWeightInfo { + result: (), + weight: T::WeightInfo::clear_weight(disputes_len), + }; + + Ok(res) } } diff --git a/zrml/simple-disputes/src/simple_disputes_pallet_api.rs b/zrml/simple-disputes/src/simple_disputes_pallet_api.rs index 3c723b624..221193d0f 100644 --- a/zrml/simple-disputes/src/simple_disputes_pallet_api.rs +++ b/zrml/simple-disputes/src/simple_disputes_pallet_api.rs @@ -15,6 +15,6 @@ // You should have received a copy of the GNU General Public License // along with Zeitgeist. If not, see . -use zeitgeist_primitives::traits::DisputeApi; +use zeitgeist_primitives::traits::{DisputeApi, DisputeMaxWeightApi}; -pub trait SimpleDisputesPalletApi: DisputeApi {} +pub trait SimpleDisputesPalletApi: DisputeApi + DisputeMaxWeightApi {} diff --git a/zrml/simple-disputes/src/tests.rs b/zrml/simple-disputes/src/tests.rs index 19981e3b8..f5f35ba89 100644 --- a/zrml/simple-disputes/src/tests.rs +++ b/zrml/simple-disputes/src/tests.rs @@ -99,7 +99,7 @@ fn on_resolution_sets_the_last_dispute_of_disputed_markets_as_the_canonical_outc .unwrap(); Disputes::::insert(0, &disputes); assert_eq!( - &SimpleDisputes::on_resolution(&0, &market).unwrap().unwrap(), + &SimpleDisputes::on_resolution(&0, &market).unwrap().result.unwrap(), &disputes.last().unwrap().outcome ) }); From ae99d7fac32fc8aecab7fc51fb5d84098453d9f6 Mon Sep 17 00:00:00 2001 From: Harald Heckmann Date: Wed, 3 May 2023 12:13:39 +0200 Subject: [PATCH 55/58] Use accurate dispute weight instead of max --- zrml/prediction-markets/src/lib.rs | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 5ba8036a0..399f73b07 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -634,26 +634,26 @@ mod pallet { let market = >::market(&market_id)?; ensure!(market.status == MarketStatus::Reported, Error::::InvalidMarketStatus); - let overweight = match market.dispute_mechanism { + let weight = match market.dispute_mechanism { MarketDisputeMechanism::Authorized => { T::Authorized::on_dispute(&market_id, &market)?; - T::Court::on_dispute_max_weight() - .saturating_add(T::SimpleDisputes::on_dispute_max_weight()) + T::WeightInfo::dispute_authorized() } MarketDisputeMechanism::Court => { - T::Court::on_dispute(&market_id, &market)?; - T::Authorized::on_dispute_max_weight() - .saturating_add(T::SimpleDisputes::on_dispute_max_weight()) + let court_weight = T::Court::on_dispute(&market_id, &market)?.weight; + T::WeightInfo::dispute_authorized() + .saturating_sub(T::Authorized::on_dispute_max_weight()) + .saturating_add(court_weight) } MarketDisputeMechanism::SimpleDisputes => { - T::SimpleDisputes::on_dispute(&market_id, &market)?; - T::Court::on_dispute_max_weight() - .saturating_add(T::Authorized::on_dispute_max_weight()) + let sd_weight = T::SimpleDisputes::on_dispute(&market_id, &market)?.weight; + T::WeightInfo::dispute_authorized() + .saturating_sub(T::Authorized::on_dispute_max_weight()) + .saturating_add(sd_weight) } }; let dispute_bond = T::DisputeBond::get(); - T::AssetManager::reserve_named(&Self::reserve_id(), Asset::Ztg, &who, dispute_bond)?; >::mutate_market(&market_id, |m| { @@ -663,13 +663,7 @@ mod pallet { })?; Self::deposit_event(Event::MarketDisputed(market_id, MarketStatus::Disputed)); - - let full_weight = T::WeightInfo::dispute_authorized().saturating_add( - T::Court::on_dispute_max_weight() - .saturating_add(T::SimpleDisputes::on_dispute_max_weight()), - ); - - Ok((Some(full_weight.saturating_sub(overweight))).into()) + Ok((Some(weight)).into()) } /// Create a permissionless market, buy complete sets and deploy a pool with specified From 6025960822411d6e2283131539e8e8e2fc9fbe48 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Tue, 9 May 2023 10:04:11 +0200 Subject: [PATCH 56/58] fix clippy --- zrml/prediction-markets/src/mock.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zrml/prediction-markets/src/mock.rs b/zrml/prediction-markets/src/mock.rs index 1852fe593..4f0ef9f02 100644 --- a/zrml/prediction-markets/src/mock.rs +++ b/zrml/prediction-markets/src/mock.rs @@ -44,8 +44,8 @@ use zeitgeist_primitives::{ MaxDisputeDuration, MaxDisputes, MaxEditReasonLen, MaxGracePeriod, MaxInRatio, MaxMarketLifetime, MaxOracleDuration, MaxOutRatio, MaxRejectReasonLen, MaxReserves, MaxSubsidyPeriod, MaxSwapFee, MaxTotalWeight, MaxWeight, MinAssets, MinCategories, - MinDisputeDuration, MinLiquidity, MinOracleDuration, MinSubsidy, MinSubsidyPeriod, - MinWeight, MinimumPeriod, OutcomeBond, OutcomeFactor, OutsiderBond, PmPalletId, + MinDisputeDuration, MinOracleDuration, MinSubsidy, MinSubsidyPeriod, MinWeight, + MinimumPeriod, OutcomeBond, OutcomeFactor, OutsiderBond, PmPalletId, SimpleDisputesPalletId, StakeWeight, SwapsPalletId, TreasuryPalletId, BASE, CENT, MILLISECS_PER_BLOCK, }, From 99836e52d3c66abbdea3aa0d23810e05c9cd893d Mon Sep 17 00:00:00 2001 From: Chralt Date: Mon, 15 May 2023 08:49:08 +0200 Subject: [PATCH 57/58] Update zrml/prediction-markets/src/migrations.rs Co-authored-by: Malte Kliemann --- zrml/prediction-markets/src/migrations.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zrml/prediction-markets/src/migrations.rs b/zrml/prediction-markets/src/migrations.rs index 68f126e83..65950184c 100644 --- a/zrml/prediction-markets/src/migrations.rs +++ b/zrml/prediction-markets/src/migrations.rs @@ -439,7 +439,7 @@ where let pm_version = StorageVersion::get::>(); if pm_version != PREDICTION_MARKETS_REQUIRED_STORAGE_VERSION { log::info!( - "MoveDataToSimpleDisputes: market-commons version is {:?}, but {:?} is required", + "MoveDataToSimpleDisputes: prediction-markets version is {:?}, but {:?} is required", pm_version, PREDICTION_MARKETS_REQUIRED_STORAGE_VERSION, ); From 7aae6f1f08eab53b4f5687de94de0a27318fba90 Mon Sep 17 00:00:00 2001 From: Chralt98 Date: Mon, 15 May 2023 16:16:46 +0200 Subject: [PATCH 58/58] add copyrights --- zrml/authorized/src/authorized_pallet_api.rs | 1 + zrml/court/src/court_pallet_api.rs | 1 + zrml/simple-disputes/src/benchmarks.rs | 1 + zrml/simple-disputes/src/simple_disputes_pallet_api.rs | 1 + zrml/simple-disputes/src/weights.rs | 1 + 5 files changed, 5 insertions(+) diff --git a/zrml/authorized/src/authorized_pallet_api.rs b/zrml/authorized/src/authorized_pallet_api.rs index f9ac39c21..387fa6034 100644 --- a/zrml/authorized/src/authorized_pallet_api.rs +++ b/zrml/authorized/src/authorized_pallet_api.rs @@ -1,3 +1,4 @@ +// Copyright 2023 Forecasting Technologies LTD. // Copyright 2021-2022 Zeitgeist PM LLC. // // This file is part of Zeitgeist. diff --git a/zrml/court/src/court_pallet_api.rs b/zrml/court/src/court_pallet_api.rs index 8d0535aa8..feebd7c35 100644 --- a/zrml/court/src/court_pallet_api.rs +++ b/zrml/court/src/court_pallet_api.rs @@ -1,3 +1,4 @@ +// Copyright 2023 Forecasting Technologies LTD. // Copyright 2021-2022 Zeitgeist PM LLC. // // This file is part of Zeitgeist. diff --git a/zrml/simple-disputes/src/benchmarks.rs b/zrml/simple-disputes/src/benchmarks.rs index 6f64cc8d7..d4b324630 100644 --- a/zrml/simple-disputes/src/benchmarks.rs +++ b/zrml/simple-disputes/src/benchmarks.rs @@ -1,3 +1,4 @@ +// Copyright 2023 Forecasting Technologies LTD. // Copyright 2021-2022 Zeitgeist PM LLC. // // This file is part of Zeitgeist. diff --git a/zrml/simple-disputes/src/simple_disputes_pallet_api.rs b/zrml/simple-disputes/src/simple_disputes_pallet_api.rs index 221193d0f..f01588aaa 100644 --- a/zrml/simple-disputes/src/simple_disputes_pallet_api.rs +++ b/zrml/simple-disputes/src/simple_disputes_pallet_api.rs @@ -1,3 +1,4 @@ +// Copyright 2023 Forecasting Technologies LTD. // Copyright 2021-2022 Zeitgeist PM LLC. // // This file is part of Zeitgeist. diff --git a/zrml/simple-disputes/src/weights.rs b/zrml/simple-disputes/src/weights.rs index f4233871d..bfbc6cc8c 100644 --- a/zrml/simple-disputes/src/weights.rs +++ b/zrml/simple-disputes/src/weights.rs @@ -1,3 +1,4 @@ +// Copyright 2023 Forecasting Technologies LTD. // Copyright 2021-2022 Zeitgeist PM LLC. // // This file is part of Zeitgeist.