Skip to content

Commit

Permalink
ZIP-0 Part II (#938)
Browse files Browse the repository at this point in the history
* move disputes to simple-disputes

* move more to simple-disputes

* wip

* wip

* some mock preparation

* wip

* fix tests

* taplo fmt

* update court authorized mdms

* add dispute bond to market storage

* mdm funds flow

* fix clippy

* fix pm benchmarks

* add migration

* simplify migration

* correct migration

* migration fixes and call filter

* correct admin_destroy_market benchmark

* improve simple-disputes mock

* benchmark reserve_outcome

* benchmark reserve_outcome

* fix weights file

* fix after merge

* add migration tests

* add migration reserve id test

* apply review suggestions

* rename reserve_outcome to suggest_outcome

* separate resolve_disputed_market into parts

* edit exchange API documentation

* slash dispute bond

* add empty commit

* correct admin_destroy_market test

* remove gd dependency from simple disputes

* Update zrml/simple-disputes/src/mock.rs

Co-authored-by: Harald Heckmann <[email protected]>

* Update zrml/simple-disputes/src/mock.rs

Co-authored-by: Harald Heckmann <[email protected]>

* Update zrml/prediction-markets/src/lib.rs

Co-authored-by: Harald Heckmann <[email protected]>

* add doc string

* add doc strings

* Reduce settle_bonds LOC

* cargo fmt

* Update zrml/prediction-markets/src/migrations.rs

Co-authored-by: Harald Heckmann <[email protected]>

* Update zrml/prediction-markets/src/migrations.rs

Co-authored-by: Harald Heckmann <[email protected]>

* apply review suggestion

* add correct mdm benchmarking on_dispute

* use on_dispute_weight inside api

* improve mdm weight technique

* add mdm weights to on_resolution

* add tests for pm

* modify migration logs, fix try-runtime

* little benchmark fix

* Update zrml/authorized/src/benchmarks.rs

Co-authored-by: Harald Heckmann <[email protected]>

* Update zrml/authorized/src/benchmarks.rs

Co-authored-by: Harald Heckmann <[email protected]>

* use result with weight struct

* improve dispute api weight system

* Use accurate dispute weight instead of max

* fix clippy

* Update zrml/prediction-markets/src/migrations.rs

Co-authored-by: Malte Kliemann <[email protected]>

* add copyrights

---------

Co-authored-by: Harald Heckmann <[email protected]>
Co-authored-by: Malte Kliemann <[email protected]>
  • Loading branch information
3 people authored May 16, 2023
1 parent af86377 commit fddeb1b
Show file tree
Hide file tree
Showing 36 changed files with 2,594 additions and 701 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions primitives/src/constants/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,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 MaxDisputeDuration: BlockNumber = 50;
Expand All @@ -85,6 +84,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
Expand Down
26 changes: 24 additions & 2 deletions primitives/src/market.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ pub struct MarketBonds<AI, BA> {
pub creation: Option<Bond<AI, BA>>,
pub oracle: Option<Bond<AI, BA>>,
pub outsider: Option<Bond<AI, BA>>,
pub dispute: Option<Bond<AI, BA>>,
}

impl<AI: Ord, BA: frame_support::traits::tokens::Balance> MarketBonds<AI, BA> {
Expand All @@ -100,13 +101,14 @@ impl<AI: Ord, BA: frame_support::traits::tokens::Balance> MarketBonds<AI, BA> {
value_or_default(&self.creation)
.saturating_add(value_or_default(&self.oracle))
.saturating_add(value_or_default(&self.outsider))
.saturating_add(value_or_default(&self.dispute))
}
}

// Used primarily for testing purposes.
impl<AI, BA> Default for MarketBonds<AI, BA> {
fn default() -> Self {
MarketBonds { creation: None, oracle: None, outsider: None }
MarketBonds { creation: None, oracle: None, outsider: None, dispute: None }
}
}

Expand Down Expand Up @@ -175,11 +177,31 @@ pub enum MarketCreation {
Advised,
}

/// Defines a global dispute item for the initialisation of a global dispute.
pub struct GlobalDisputeItem<AccountId, Balance> {
/// 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<AccountId, BlockNumber> {
pub at: BlockNumber,
pub by: AccountId,
pub outcome: OutcomeReport,
}

#[derive(Clone, Decode, Encode, Eq, MaxEncodedLen, PartialEq, RuntimeDebug, TypeInfo)]
pub struct MarketDispute<AccountId, BlockNumber> {
pub struct MarketDispute<AccountId, BlockNumber, Balance> {
pub at: BlockNumber,
pub by: AccountId,
pub outcome: OutcomeReport,
pub bond: Balance,
}

/// How a market should resolve disputes
Expand Down
2 changes: 1 addition & 1 deletion primitives/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
85 changes: 67 additions & 18 deletions primitives/src/traits/dispute_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
// You should have received a copy of the GNU General Public License
// along with Zeitgeist. If not, see <https://www.gnu.org/licenses/>.

extern crate alloc;

use crate::{
market::MarketDispute,
outcome_report::OutcomeReport,
types::{Asset, Market},
types::{Asset, GlobalDisputeItem, Market, ResultWithWeightInfo},
};
use frame_support::{dispatch::DispatchResult, pallet_prelude::Weight, BoundedVec};
use alloc::vec::Vec;
use frame_support::pallet_prelude::Weight;
use parity_scale_codec::MaxEncodedLen;
use sp_runtime::DispatchError;

Expand All @@ -35,9 +37,13 @@ type MarketOfDisputeApi<T> = Market<
Asset<<T as DisputeApi>::MarketId>,
>;

type GlobalDisputeItemOfDisputeApi<T> =
GlobalDisputeItem<<T as DisputeApi>::AccountId, <T as DisputeApi>::Balance>;

pub trait DisputeApi {
type AccountId;
type Balance;
type NegativeImbalance;
type BlockNumber;
type MarketId: MaxEncodedLen;
type Moment;
Expand All @@ -48,10 +54,9 @@ 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<Self::AccountId, Self::BlockNumber>],
market_id: &Self::MarketId,
market: &MarketOfDisputeApi<Self>,
) -> DispatchResult;
) -> Result<ResultWithWeightInfo<()>, DispatchError>;

/// Manage market resolution of a disputed market.
///
Expand All @@ -63,31 +68,81 @@ 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<Self::AccountId, Self::BlockNumber>],
market_id: &Self::MarketId,
market: &MarketOfDisputeApi<Self>,
) -> Result<Option<OutcomeReport>, DispatchError>;
) -> Result<ResultWithWeightInfo<Option<OutcomeReport>>, DispatchError>;

/// Query the future resolution block of a disputed market.
/// 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.
///
/// # 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 in order to transfer funds back to the caller.
fn exchange(
market_id: &Self::MarketId,
market: &MarketOfDisputeApi<Self>,
resolved_outcome: &OutcomeReport,
amount: Self::NegativeImbalance,
) -> Result<ResultWithWeightInfo<Self::NegativeImbalance>, DispatchError>;
/// **May** assume that `market.dispute_mechanism` refers to the calling dispute API.
///
/// # Returns
///
/// Returns the future resolution block if available, otherwise `None`.
fn get_auto_resolve(
disputes: &[MarketDispute<Self::AccountId, Self::BlockNumber>],
market_id: &Self::MarketId,
market: &MarketOfDisputeApi<Self>,
) -> Result<Option<Self::BlockNumber>, DispatchError>;
) -> Result<ResultWithWeightInfo<Option<Self::BlockNumber>>, DispatchError>;

/// 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.
fn has_failed(
disputes: &[MarketDispute<Self::AccountId, Self::BlockNumber>],
market_id: &Self::MarketId,
market: &MarketOfDisputeApi<Self>,
) -> Result<bool, DispatchError>;
) -> Result<ResultWithWeightInfo<bool>, DispatchError>;

/// 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<Self>,
) -> Result<ResultWithWeightInfo<Vec<GlobalDisputeItemOfDisputeApi<Self>>>, 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<Self>,
) -> Result<ResultWithWeightInfo<()>, DispatchError>;
}

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<T> = Market<
Expand All @@ -103,7 +158,6 @@ pub trait DisputeResolutionApi {
type Balance;
type BlockNumber;
type MarketId: MaxEncodedLen;
type MaxDisputes;
type Moment;

/// Resolve a market.
Expand Down Expand Up @@ -142,9 +196,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<MarketDispute<Self::AccountId, Self::BlockNumber>, Self::MaxDisputes>;
}
14 changes: 9 additions & 5 deletions runtime/battery-station/src/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,9 @@ parameter_types! {
/// The percentage of the advisory bond that gets slashed when a market is rejected.
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 block period for a dispute.
Expand Down Expand Up @@ -224,6 +222,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
Expand Down
15 changes: 12 additions & 3 deletions runtime/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ macro_rules! decl_common_types {
frame_system::ChainContext<Runtime>,
Runtime,
AllPalletsWithSystem,
zrml_prediction_markets::migrations::AddOutsiderBond<Runtime>,
(
zrml_prediction_markets::migrations::AddOutsiderAndDisputeBond<Runtime>,
zrml_prediction_markets::migrations::MoveDataToSimpleDisputes<Runtime>,
),
>;

pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
Expand Down Expand Up @@ -300,7 +303,7 @@ macro_rules! create_runtime {
Court: zrml_court::{Call, Event<T>, Pallet, Storage} = 52,
LiquidityMining: zrml_liquidity_mining::{Call, Config<T>, Event<T>, Pallet, Storage} = 53,
RikiddoSigmoidFeeMarketEma: zrml_rikiddo::<Instance1>::{Pallet, Storage} = 54,
SimpleDisputes: zrml_simple_disputes::{Event<T>, Pallet, Storage} = 55,
SimpleDisputes: zrml_simple_disputes::{Call, Event<T>, Pallet, Storage} = 55,
Swaps: zrml_swaps::{Call, Event<T>, Pallet, Storage} = 56,
PredictionMarkets: zrml_prediction_markets::{Call, Event<T>, Pallet, Storage} = 57,
Styx: zrml_styx::{Call, Event<T>, Pallet, Storage} = 58,
Expand Down Expand Up @@ -986,7 +989,6 @@ macro_rules! impl_config_traits {
type CloseOrigin = EnsureRoot<AccountId>;
type DestroyOrigin = EnsureRootOrAllAdvisoryCommittee;
type DisputeBond = DisputeBond;
type DisputeFactor = DisputeFactor;
type Event = Event;
#[cfg(feature = "with-global-disputes")]
type GlobalDisputes = GlobalDisputes;
Expand Down Expand Up @@ -1041,10 +1043,15 @@ macro_rules! impl_config_traits {
}

impl zrml_simple_disputes::Config for Runtime {
type AssetManager = AssetManager;
type OutcomeBond = OutcomeBond;
type OutcomeFactor = OutcomeFactor;
type DisputeResolution = zrml_prediction_markets::Pallet<Runtime>;
type Event = Event;
type MarketCommons = MarketCommons;
type MaxDisputes = MaxDisputes;
type PalletId = SimpleDisputesPalletId;
type WeightInfo = zrml_simple_disputes::weights::WeightInfo<Runtime>;
}

#[cfg(feature = "with-global-disputes")]
Expand Down Expand Up @@ -1195,6 +1202,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);
#[cfg(not(feature = "parachain"))]
Expand Down Expand Up @@ -1273,6 +1281,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);
#[cfg(not(feature = "parachain"))]
Expand Down
1 change: 1 addition & 0 deletions runtime/zeitgeist/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ impl Contains<Call> for IsCallable {
_ => true,
}
}
Call::SimpleDisputes(_) => false,
Call::System(inner_call) => {
match inner_call {
// Some "waste" storage will never impact proper operation.
Expand Down
12 changes: 8 additions & 4 deletions runtime/zeitgeist/src/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,9 @@ parameter_types! {
/// The percentage of the advisory bond that gets slashed when a market is rejected.
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.
/// 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 = 2_000 * BASE;
/// `DisputeBond` is increased by this factor after every dispute.
pub const DisputeFactor: Balance = 2 * BASE;
/// Maximum Categories a prediciton market can have (excluding base asset).
pub const MaxCategories: u16 = MAX_CATEGORIES;
/// Maximum block period for a dispute.
Expand Down Expand Up @@ -224,6 +222,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
Expand Down
5 changes: 3 additions & 2 deletions zrml/authorized/src/authorized_pallet_api.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Copyright 2023 Forecasting Technologies LTD.
// Copyright 2021-2022 Zeitgeist PM LLC.
//
// This file is part of Zeitgeist.
Expand All @@ -15,6 +16,6 @@
// You should have received a copy of the GNU General Public License
// along with Zeitgeist. If not, see <https://www.gnu.org/licenses/>.

use zeitgeist_primitives::traits::DisputeApi;
use zeitgeist_primitives::traits::{DisputeApi, DisputeMaxWeightApi};

pub trait AuthorizedPalletApi: DisputeApi {}
pub trait AuthorizedPalletApi: DisputeApi + DisputeMaxWeightApi {}
Loading

0 comments on commit fddeb1b

Please sign in to comment.