Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement market creator incentives #1057

Merged
merged 43 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
5f2845d
Integrate creator_fee in config and market & pool creation
sea212 Jul 30, 2023
81dfb59
Merge branch 'main' into sea212-implement-market-creator-incentives
sea212 Aug 24, 2023
d98ba65
Make creator_fee decideable by market creator
sea212 Aug 24, 2023
9804a21
Finalize adjustable creator fee changes
sea212 Aug 24, 2023
0aacfc3
Plan helper function
sea212 Aug 25, 2023
449e199
Partially implement market creator fees
sea212 Aug 28, 2023
a6d0d94
Implement market fees for swap_exact_amount_in
sea212 Aug 28, 2023
d34aab9
Add tests for swap_exact_amount_in fees (WIP)
sea212 Aug 28, 2023
1a22b6b
Finalize creator fee for swap_exact_amount_in
sea212 Aug 29, 2023
87f40dc
Merge branch 'main' into sea212-implement-market-creator-incentives
sea212 Aug 29, 2023
0028490
Fix bugs
sea212 Aug 30, 2023
ad8ffdc
Finalize fee handling logic
sea212 Aug 31, 2023
af56138
Use BASET_ASSET constant in tests
sea212 Aug 31, 2023
56f8e93
Use const for pool and market id
sea212 Aug 31, 2023
6df65da
Add swap_in tests
sea212 Aug 31, 2023
750fd18
Complete swap_in with creator fee tests
sea212 Sep 1, 2023
f4a7ca5
Use const for default weights
sea212 Sep 1, 2023
2406b97
Use imported Error instead of absolute path
sea212 Sep 1, 2023
09e2b95
Implement limit tests when using creator fee
sea212 Sep 1, 2023
5db1090
Implement max price tests when using creator fee
sea212 Sep 1, 2023
025cf7b
Complete swap_out with creator fee tests
sea212 Sep 1, 2023
55f059e
Fix no-base<->no-base swap out creato fee test
sea212 Sep 1, 2023
31010ae
Implement limit tests with swap_out when using creator fee
sea212 Sep 1, 2023
239fd4e
Implement max price tests for swap_out when using creator fee
sea212 Sep 1, 2023
b0302d4
Implement test to verify swap out amount is correct
sea212 Sep 1, 2023
b1bb837
Add test that verifies fee boundaries during pool creation
sea212 Sep 1, 2023
24393ad
Add creator_fee migration
sea212 Sep 4, 2023
13d8ac3
Adjust all tests to new create_market call
sea212 Sep 4, 2023
65bf66e
Format
sea212 Sep 4, 2023
225c967
Update changelog
sea212 Sep 4, 2023
ad315af
Update changelog
sea212 Sep 4, 2023
1542ada
Fix invalid test
sea212 Sep 4, 2023
3f5be5d
Add fee limit test in prediction markets crate
sea212 Sep 4, 2023
7a40603
Fix swaps benchmarks (invalid market id)
sea212 Sep 4, 2023
97f0a87
Update license headers
sea212 Sep 4, 2023
761dbef
Satisfy clippy
sea212 Sep 4, 2023
00f75e3
Repair fuzz tests
sea212 Sep 4, 2023
266aae7
Fix swaps fuzz tests (invalid market id)
sea212 Sep 7, 2023
3544b76
Add market parameter test for create_cpmm_market_and_deploy_assets
sea212 Sep 7, 2023
f483b80
Adjust swap benchmarks to use worst-case execution
sea212 Sep 8, 2023
9101013
Make handle_creator_fees infallible
sea212 Sep 8, 2023
8d9f099
Add ED tests for creator fees
sea212 Sep 8, 2023
17855e5
Update copyright
sea212 Sep 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.

21 changes: 21 additions & 0 deletions docs/changelog_for_devs.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,27 @@ All things about Global Disputes Fix ⚠️ :

### Added

- Add market creator incentives.
- The following dispatchable calls within the prediction markets pallet now
expect a market creator fee denoted as type `Perbill` after the `base_asset`
parameter. The fee is bounded by the pallet's `Config` parameter
`MaxCreatorFee`:
- `create_market`
- `create_cpmm_market_and_deploy_assets`
- The market type now holds an additional field `creator_fee` using the type
`Perbill` after the `creation` field.
- The swaps pallet's `Config` parameter `MaxSwapFee` now is a boundary for the
sum of all fees, currently the liqudity provider fee and the market creator
fee. It is checked during the execution of the public function
`create_pool`.
- Fees are always transferred from the trader's account to the market
creator's account either before or after the trade. The base asset is always
preferred to pay fees. If the trade does not include the base asset, the
pallet will try to convert the outcome asset to the base asset by executing
a swap.
- A new event `MarketCreatorFeesPaid` is emitted by the swaps pallet after
successful payment of fees to the market creator. It contains the fields
`\[payer, payee, amount, asset\]`.
- ⚠️ Add court production implementation ([#976]). Dispatchable calls are:
- `join_court` - Join the court with a stake to become a juror in order to get
the stake-weighted chance to be selected for decision making.
Expand Down
1 change: 1 addition & 0 deletions primitives/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ orml-traits = { workspace = true }
parity-scale-codec = { workspace = true, features = ["derive", "max-encoded-len"] }
scale-info = { workspace = true, features = ["derive"] }
serde = { workspace = true, features = ["derive"], optional = true }
sp-arithmetic = { workspace = true }
sp-core = { workspace = true }
sp-runtime = { workspace = true }

Expand Down
2 changes: 2 additions & 0 deletions primitives/src/constants/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use crate::{
};
use frame_support::{parameter_types, traits::LockIdentifier, PalletId};
use orml_traits::parameter_type_with_key;
use sp_arithmetic::Perbill;

// Authorized
parameter_types! {
Expand Down Expand Up @@ -75,6 +76,7 @@ parameter_types! {
pub const DisputeBond: Balance = 5 * BASE;
pub const DisputeFactor: Balance = 2 * BASE;
pub const MaxCategories: u16 = 10;
pub const MaxCreatorFee: Perbill = Perbill::from_percent(1);
pub const MaxDisputeDuration: BlockNumber = 50;
pub const MaxDisputes: u16 = 6;
pub const MaxEditReasonLen: u32 = 1024;
Expand Down
11 changes: 6 additions & 5 deletions primitives/src/market.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ use alloc::vec::Vec;
use core::ops::{Range, RangeInclusive};
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_arithmetic::per_things::Perbill;
use sp_runtime::RuntimeDebug;

/// Types
///
/// * `AI`: Account id
/// * `BA`: Balance type for bonds
/// * `BA`: Balance type
/// * `BN`: Block number
/// * `M`: Moment (time moment)
/// * `A`: Asset
Expand All @@ -38,8 +39,8 @@ pub struct Market<AI, BA, BN, M, A> {
pub creator: AI,
/// Creation type.
pub creation: MarketCreation,
/// The fee the creator gets from each winning share.
pub creator_fee: u8,
/// A fee that is charged each trade and given to the market creator.
pub creator_fee: Perbill,
/// Oracle that reports the outcome of this market.
pub oracle: AI,
/// Metadata for the market, usually a content address of IPFS
Expand Down Expand Up @@ -150,7 +151,7 @@ where
AI::max_encoded_len()
.saturating_add(A::max_encoded_len())
.saturating_add(MarketCreation::max_encoded_len())
.saturating_add(u8::max_encoded_len())
.saturating_add(Perbill::max_encoded_len())
.saturating_add(AI::max_encoded_len())
// We assume that at max. a 512 bit hash function is used
.saturating_add(u8::max_encoded_len().saturating_mul(68))
Expand Down Expand Up @@ -378,7 +379,7 @@ mod tests {
base_asset: Asset::Ztg,
creator: 1,
creation: MarketCreation::Permissionless,
creator_fee: 2,
creator_fee: Default::default(),
oracle: 3,
metadata: vec![4u8; 5],
market_type, // : MarketType::Categorical(6),
Expand Down
7 changes: 7 additions & 0 deletions primitives/src/traits/swaps.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 Down Expand Up @@ -152,6 +153,8 @@ pub trait Swaps<AccountId> {
/// * `asset_out`: Asset leaving the pool.
/// * `min_asset_amount_out`: Minimum asset amount that can leave the pool.
/// * `max_price`: Market price must be equal or less than the provided value.
/// * `handle_fees`: Whether additional fees are handled or not (sets LP fee to 0)
#[allow(clippy::too_many_arguments)]
fn swap_exact_amount_in(
who: AccountId,
pool_id: PoolId,
Expand All @@ -160,6 +163,7 @@ pub trait Swaps<AccountId> {
asset_out: Asset<Self::MarketId>,
min_asset_amount_out: Option<Self::Balance>,
max_price: Option<Self::Balance>,
handle_fees: bool,
) -> Result<Weight, DispatchError>;

/// Swap - Exact amount out
Expand All @@ -175,6 +179,8 @@ pub trait Swaps<AccountId> {
/// * `asset_out`: Asset leaving the pool.
/// * `asset_amount_out`: Amount that will be transferred from the pool to the provider.
/// * `max_price`: Market price must be equal or less than the provided value.
/// * `handle_fees`: Whether additional fees are handled or not (sets LP fee to 0)
#[allow(clippy::too_many_arguments)]
fn swap_exact_amount_out(
who: AccountId,
pool_id: PoolId,
Expand All @@ -183,5 +189,6 @@ pub trait Swaps<AccountId> {
asset_out: Asset<Self::MarketId>,
asset_amount_out: Self::Balance,
max_price: Option<Self::Balance>,
handle_fees: bool,
) -> Result<Weight, DispatchError>;
}
2 changes: 2 additions & 0 deletions runtime/battery-station/src/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ parameter_types! {
pub const DisputeBond: Balance = 25 * BASE;
/// Maximum Categories a prediciton market can have (excluding base asset).
pub const MaxCategories: u16 = MAX_CATEGORIES;
/// Max creator fee, bounds the fraction per trade volume that is moved to the market creator.
pub const MaxCreatorFee: Perbill = Perbill::from_percent(1);
/// Maximum block period for a dispute.
pub const MaxDisputeDuration: BlockNumber = MAX_DISPUTE_DURATION;
/// Maximum number of disputes.
Expand Down
9 changes: 5 additions & 4 deletions runtime/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,17 @@ macro_rules! decl_common_types {
orml_asset_registry::Migration<Runtime>,
orml_unknown_tokens::Migration<Runtime>,
pallet_xcm::migration::v1::MigrateToV1<Runtime>,
// IMPORTANT that AddDisputeBond comes before MoveDataToSimpleDisputes!!!
zrml_prediction_markets::migrations::AddDisputeBond<Runtime>,
// IMPORTANT that AddDisputeBondAndConvertCreatorFee comes before MoveDataToSimpleDisputes!!!
zrml_prediction_markets::migrations::AddDisputeBondAndConvertCreatorFee<Runtime>,
zrml_prediction_markets::migrations::MoveDataToSimpleDisputes<Runtime>,
zrml_global_disputes::migrations::ModifyGlobalDisputesStructures<Runtime>,
);

#[cfg(not(feature = "parachain"))]
type Migrations = (
pallet_grandpa::migrations::CleanupSetIdSessionMap<Runtime>,
// IMPORTANT that AddDisputeBond comes before MoveDataToSimpleDisputes!!!
zrml_prediction_markets::migrations::AddDisputeBond<Runtime>,
// IMPORTANT that AddDisputeBondAndConvertCreatorFee comes before MoveDataToSimpleDisputes!!!
zrml_prediction_markets::migrations::AddDisputeBondAndConvertCreatorFee<Runtime>,
zrml_prediction_markets::migrations::MoveDataToSimpleDisputes<Runtime>,
zrml_global_disputes::migrations::ModifyGlobalDisputesStructures<Runtime>,
);
Expand Down Expand Up @@ -1126,6 +1126,7 @@ macro_rules! impl_config_traits {
type LiquidityMining = NoopLiquidityMining;
// type LiquidityMining = LiquidityMining;
type MaxCategories = MaxCategories;
type MaxCreatorFee = MaxCreatorFee;
type MaxDisputes = MaxDisputes;
type MaxMarketLifetime = MaxMarketLifetime;
type MinDisputeDuration = MinDisputeDuration;
Expand Down
2 changes: 2 additions & 0 deletions runtime/zeitgeist/src/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ parameter_types! {
pub const DisputeBond: Balance = 2_000 * BASE;
/// Maximum Categories a prediciton market can have (excluding base asset).
pub const MaxCategories: u16 = MAX_CATEGORIES;
/// Max creator fee, bounds the fraction per trade volume that is moved to the market creator.
pub const MaxCreatorFee: Perbill = Perbill::from_percent(1);
/// Maximum block period for a dispute.
pub const MaxDisputeDuration: BlockNumber = MAX_DISPUTE_DURATION;
/// Maximum number of disputes.
Expand Down
2 changes: 1 addition & 1 deletion zrml/authorized/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ where
zeitgeist_primitives::types::Market {
base_asset: Asset::Ztg,
creation: zeitgeist_primitives::types::MarketCreation::Permissionless,
creator_fee: 0,
creator_fee: sp_runtime::Perbill::zero(),
creator: T::PalletId::get().into_account_truncating(),
market_type: zeitgeist_primitives::types::MarketType::Scalar(0..=100),
dispute_mechanism: zeitgeist_primitives::types::MarketDisputeMechanism::Authorized,
Expand Down
2 changes: 1 addition & 1 deletion zrml/court/src/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ where
Market {
base_asset: Asset::Ztg,
creation: MarketCreation::Permissionless,
creator_fee: 0,
creator_fee: sp_runtime::Perbill::zero(),
creator: account("creator", 0, 0),
market_type: MarketType::Scalar(0..=100),
dispute_mechanism: MarketDisputeMechanism::Court,
Expand Down
2 changes: 1 addition & 1 deletion zrml/court/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const ORACLE_REPORT: OutcomeReport = OutcomeReport::Scalar(u128::MAX);
const DEFAULT_MARKET: MarketOf<Runtime> = Market {
base_asset: Asset::Ztg,
creation: MarketCreation::Permissionless,
creator_fee: 0,
creator_fee: sp_runtime::Perbill::zero(),
creator: 0,
market_type: MarketType::Scalar(0..=100),
dispute_mechanism: MarketDisputeMechanism::Court,
Expand Down
2 changes: 1 addition & 1 deletion zrml/global-disputes/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ where
zeitgeist_primitives::types::Market {
base_asset: zeitgeist_primitives::types::Asset::Ztg,
creation: zeitgeist_primitives::types::MarketCreation::Permissionless,
creator_fee: 0,
creator_fee: sp_runtime::Perbill::zero(),
creator: T::GlobalDisputesPalletId::get().into_account_truncating(),
market_type: zeitgeist_primitives::types::MarketType::Scalar(0..=u128::MAX),
dispute_mechanism: zeitgeist_primitives::types::MarketDisputeMechanism::SimpleDisputes,
Expand Down
2 changes: 1 addition & 1 deletion zrml/liquidity-mining/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ fn create_default_market(market_id: u128, period: Range<u64>) {
Market {
base_asset: Asset::Ztg,
creation: MarketCreation::Permissionless,
creator_fee: 0,
creator_fee: sp_runtime::Perbill::zero(),
creator: 0,
market_type: MarketType::Categorical(0),
dispute_mechanism: MarketDisputeMechanism::SimpleDisputes,
Expand Down
4 changes: 2 additions & 2 deletions zrml/market-commons/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::{
MarketCounter, Markets,
};
use frame_support::{assert_err, assert_noop, assert_ok};
use sp_runtime::DispatchError;
use sp_runtime::{DispatchError, Perbill};
use zeitgeist_primitives::{
traits::MarketCommonsPalletApi,
types::{
Expand All @@ -36,7 +36,7 @@ use zeitgeist_primitives::{
const MARKET_DUMMY: Market<AccountIdTest, Balance, BlockNumber, Moment, Asset<MarketId>> = Market {
base_asset: Asset::Ztg,
creation: MarketCreation::Permissionless,
creator_fee: 0,
creator_fee: Perbill::zero(),
creator: 0,
market_type: MarketType::Scalar(0..=100),
dispute_mechanism: MarketDisputeMechanism::Authorized,
Expand Down
1 change: 1 addition & 0 deletions zrml/prediction-markets/fuzz/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ test = false
arbitrary = { workspace = true, features = ["derive"] }
frame-support = { workspace = true, features = ["default"] }
libfuzzer-sys = { workspace = true }
sp-arithmetic = { workspace = true, features = ["default"] }
zeitgeist-primitives = { workspace = true, features = ["arbitrary", "mock", "default"] }
zrml-prediction-markets = { workspace = true, features = ["mock", "default"] }
zrml-simple-disputes = { workspace = true, features = ["default"] }
Expand Down
15 changes: 12 additions & 3 deletions zrml/prediction-markets/fuzz/pm_full_workflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@ use arbitrary::Arbitrary;
use core::ops::{Range, RangeInclusive};
use frame_support::traits::Hooks;
use libfuzzer_sys::fuzz_target;
use zeitgeist_primitives::types::{
Asset, Deadlines, MarketCreation, MarketDisputeMechanism, MarketPeriod, MarketType, MultiHash,
OutcomeReport, ScoringRule,
use sp_arithmetic::Perbill;
use zeitgeist_primitives::{
constants::mock::MaxCreatorFee,
types::{
Asset, Deadlines, MarketCreation, MarketDisputeMechanism, MarketPeriod, MarketType,
MultiHash, OutcomeReport, ScoringRule,
},
};
use zrml_prediction_markets::mock::{ExtBuilder, PredictionMarkets, RuntimeOrigin, System};

Expand All @@ -39,9 +43,13 @@ fuzz_target!(|data: Data| {
oracle_duration: 1_u32.into(),
dispute_duration: 3_u32.into(),
};
let max_parts_per_bill = MaxCreatorFee::get().deconstruct();
let bounded_parts = data.create_scalar_market_fee % max_parts_per_bill as u128;
let fee = Perbill::from_parts(bounded_parts.try_into().unwrap());
let _ = PredictionMarkets::create_market(
RuntimeOrigin::signed(data.create_scalar_market_origin.into()),
Asset::Ztg,
fee,
data.create_scalar_market_oracle.into(),
MarketPeriod::Block(data.create_scalar_market_period),
deadlines,
Expand Down Expand Up @@ -95,6 +103,7 @@ fuzz_target!(|data: Data| {
struct Data {
create_scalar_market_origin: u8,
create_scalar_market_oracle: u8,
create_scalar_market_fee: u128,
create_scalar_market_period: Range<u64>,
create_scalar_market_metadata: MultiHash,
create_scalar_market_creation: u8,
Expand Down
9 changes: 8 additions & 1 deletion zrml/prediction-markets/src/benchmarks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ use frame_support::{
};
use frame_system::RawOrigin;
use orml_traits::MultiCurrency;
use sp_runtime::traits::{One, SaturatedConversion, Saturating, Zero};
use sp_runtime::{
traits::{One, SaturatedConversion, Saturating, Zero},
Perbill,
};
use zeitgeist_primitives::{
constants::mock::{MaxSwapFee, MinWeight, BASE, MILLISECS_PER_BLOCK},
traits::{DisputeApi, Swaps},
Expand Down Expand Up @@ -89,11 +92,13 @@ fn create_market_common<T: Config + pallet_timestamp::Config>(
pallet_timestamp::Pallet::<T>::set_timestamp(0u32.into());
let range_start: MomentOf<T> = 100_000u64.saturated_into();
let range_end: MomentOf<T> = 1_000_000u64.saturated_into();
let creator_fee: Perbill = Perbill::zero();
let period = period.unwrap_or(MarketPeriod::Timestamp(range_start..range_end));
let (caller, oracle, deadlines, metadata, creation) =
create_market_common_parameters::<T>(permission)?;
Call::<T>::create_market {
base_asset: Asset::Ztg,
creator_fee,
oracle,
period,
deadlines,
Expand Down Expand Up @@ -625,6 +630,7 @@ benchmarks! {
}: _(
RawOrigin::Signed(caller),
Asset::Ztg,
Perbill::zero(),
oracle,
period,
deadlines,
Expand All @@ -648,6 +654,7 @@ benchmarks! {
create_market_common_parameters::<T>(MarketCreation::Advised)?;
Call::<T>::create_market {
base_asset: Asset::Ztg,
creator_fee: Perbill::zero(),
oracle: oracle.clone(),
period: period.clone(),
deadlines,
Expand Down
Loading
Loading