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 Parimutuel markets #1138

Merged
merged 105 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
105 commits
Select commit Hold shift + click to select a range
db142ad
wip
Chralt98 Oct 6, 2023
89bdd20
remove market commons currency
Chralt98 Oct 9, 2023
efda14e
update mocks, fix clippy
Chralt98 Oct 9, 2023
b08be12
use unambiguous balance type
Chralt98 Oct 9, 2023
c387d95
Update zrml/prediction-markets/src/lib.rs
Chralt98 Oct 9, 2023
4006cef
Update zrml/prediction-markets/src/lib.rs
Chralt98 Oct 9, 2023
65aad8e
Update zrml/prediction-markets/src/lib.rs
Chralt98 Oct 9, 2023
d7a00e2
fix benchmarks
Chralt98 Oct 9, 2023
facfa95
fix copyrights
Chralt98 Oct 9, 2023
266cdd5
Merge branch 'chralt98-unambigious-balances' into chralt98-parimutuel
Chralt98 Oct 9, 2023
ea0e4e0
wip
Chralt98 Oct 9, 2023
ded078a
restructure outcome asset type
Chralt98 Oct 9, 2023
e6f2330
Merge branch 'chralt98-restructure-outcome-type' into chralt98-parimu…
Chralt98 Oct 9, 2023
fd971e5
wip
Chralt98 Oct 9, 2023
9ee710d
wip
Chralt98 Oct 10, 2023
70e0fcc
Implement categorical and scalar claims
Chralt98 Oct 10, 2023
2d20c04
outsource into functions
Chralt98 Oct 10, 2023
22887b9
add refund_pot extrinsic
Chralt98 Oct 11, 2023
929a836
prepare tests
Chralt98 Oct 11, 2023
0633d0a
Merge branch 'main' into chralt98-parimutuel
Chralt98 Oct 12, 2023
b6e58e4
fmt
Chralt98 Oct 12, 2023
b4eac00
Merge branch 'main' into chralt98-restructure-outcome-type
Chralt98 Oct 12, 2023
ab8a06c
fix after merge
Chralt98 Oct 12, 2023
a669da3
Merge branch 'chralt98-restructure-outcome-type' into chralt98-parimu…
Chralt98 Oct 12, 2023
2f15491
Merge branch 'main' into chralt98-unambigious-balances
Chralt98 Oct 12, 2023
7d2c850
fix mock of neo-swaps
Chralt98 Oct 12, 2023
2f4a4da
apply review suggestions
Chralt98 Oct 12, 2023
96d680a
delete parimutuel
Chralt98 Oct 12, 2023
cc2fa56
Merge branch 'chralt98-unambigious-balances' into chralt98-parimutuel
Chralt98 Oct 12, 2023
4d0362f
add tests
Chralt98 Oct 12, 2023
a932566
impl bench, add comments
Chralt98 Oct 13, 2023
960475c
integrate Parimutuel into runtime
Chralt98 Oct 13, 2023
dfd89af
add parimutuel weights
Chralt98 Oct 13, 2023
64868e9
remove scalar for parimutuels
Chralt98 Oct 16, 2023
b92420f
revert outcome type changes in favour of dev speed
Chralt98 Oct 16, 2023
877e590
Merge branch 'chralt98-restructure-outcome-type' into chralt98-parimu…
Chralt98 Oct 16, 2023
8206ae5
revert outcome type in parimutuels
Chralt98 Oct 16, 2023
ca9800b
Merge branch 'main' into chralt98-parimutuel
Chralt98 Oct 17, 2023
b085b06
add resolution mechanism
Chralt98 Oct 17, 2023
e3382f3
modify copyrights
Chralt98 Oct 17, 2023
a82dc98
taplo fmt
Chralt98 Oct 17, 2023
dbb79bd
remove not existent Outcome type
Chralt98 Oct 17, 2023
38c72a9
Merge branch 'main' into chralt98-parimutuel
Chralt98 Oct 18, 2023
fcb33ce
avoid storage migration
Chralt98 Oct 18, 2023
b84da93
decrease parimutuel existential deposits
Chralt98 Oct 18, 2023
4b3832e
impl resolution_mechanism
Chralt98 Oct 18, 2023
f7ed9f3
remove MaxCategories from parimutuel
Chralt98 Oct 18, 2023
5df1f9a
Update zrml/parimutuel/Cargo.toml
Chralt98 Oct 18, 2023
491864b
rename benchmark module
Chralt98 Oct 18, 2023
c04ba8c
remove MaxCategories from parimutuel config
Chralt98 Oct 18, 2023
449c37c
remove unused block run methods
Chralt98 Oct 18, 2023
5f7ecbc
move market mock to utils file
Chralt98 Oct 18, 2023
6afe7b9
use default market type categorical
Chralt98 Oct 18, 2023
df4833b
remove unnecessary debug assert
Chralt98 Oct 18, 2023
42b43b8
implement is_redeemable
Chralt98 Oct 18, 2023
2865828
update config comments
Chralt98 Oct 18, 2023
0284e1d
add inconsistent state error
Chralt98 Oct 18, 2023
9842b8d
update comment
Chralt98 Oct 18, 2023
6c97b25
update collateral to be base asset
Chralt98 Oct 18, 2023
25c18c3
remove unused scalar market storage item
Chralt98 Oct 18, 2023
f818f1f
use do function style
Chralt98 Oct 18, 2023
1d9b550
order config trait
Chralt98 Oct 18, 2023
134ce53
change copyright
Chralt98 Oct 18, 2023
18f9fb3
update copyrights
Chralt98 Oct 18, 2023
cf73bcf
impl market assets contains fn
Chralt98 Oct 18, 2023
be6cbcf
improve comments
Chralt98 Oct 19, 2023
bb006e5
reduce indentation
Chralt98 Oct 19, 2023
7d9eb3f
correct error
Chralt98 Oct 19, 2023
65b0657
fmt
Chralt98 Oct 19, 2023
3ea7e52
delete review jerk comment
Chralt98 Oct 19, 2023
9db88a2
use bmul_floor and bdiv_floor
Chralt98 Oct 19, 2023
f3d0b73
add not categorical error
Chralt98 Oct 19, 2023
3b796ee
remove trailing commas
Chralt98 Oct 19, 2023
4be0898
use test_case for parimutuel
Chralt98 Oct 19, 2023
c2281ea
rename refund_pot to claim_refunds
Chralt98 Oct 19, 2023
14a33e5
Update zrml/parimutuel/README.md
Chralt98 Oct 19, 2023
730a893
use test cases for market status
Chralt98 Oct 19, 2023
2630315
add test cases for invalid scoring rule
Chralt98 Oct 19, 2023
a970687
improve test readibility
Chralt98 Oct 19, 2023
6bfde0d
improve test cases
Chralt98 Oct 19, 2023
ea62e63
add docs
Chralt98 Oct 19, 2023
72452a3
add invalid scoring rule tests
Chralt98 Oct 19, 2023
7028066
add redeem shares test
Chralt98 Oct 19, 2023
4151ff8
extend to non-trivial winner rewarding
Chralt98 Oct 19, 2023
f6685ba
add copyright
Chralt98 Oct 19, 2023
b62ef3a
revert unsupported currency
Chralt98 Oct 24, 2023
55c7cb2
Update zrml/prediction-markets/src/tests.rs
Chralt98 Oct 24, 2023
78ebfa1
remove import
Chralt98 Oct 24, 2023
3295f57
use log
Chralt98 Oct 24, 2023
0ea5090
fmt
Chralt98 Oct 24, 2023
06eb5af
Update zrml/prediction-markets/src/tests.rs
Chralt98 Oct 24, 2023
d462180
improve event readability
Chralt98 Oct 24, 2023
10194ba
rename impl_distribute to do_distribute
Chralt98 Oct 24, 2023
35c75c1
Update zrml/parimutuel/src/lib.rs
Chralt98 Oct 24, 2023
ecb1801
use logs
Chralt98 Oct 24, 2023
b2954e7
use log for optimized builds
Chralt98 Oct 24, 2023
6235d22
separate tests
Chralt98 Oct 24, 2023
1e80853
outsource shared code
Chralt98 Oct 24, 2023
e1c9f5c
outsource get_winning_asset
Chralt98 Oct 24, 2023
d49ac0b
add log
Chralt98 Oct 24, 2023
38bfe9c
use withdraw instead of slash
Chralt98 Oct 24, 2023
098f17f
use withdraw instead of slash
Chralt98 Oct 24, 2023
2e2ee54
Update runtime/battery-station/src/parameters.rs
Chralt98 Oct 25, 2023
2cdd654
Update runtime/zeitgeist/src/parameters.rs
Chralt98 Oct 25, 2023
82d3ffc
use creator parameter in mock
Chralt98 Oct 25, 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
23 changes: 23 additions & 0 deletions Cargo.lock

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

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ default-members = [
"zrml/market-commons",
"zrml/neo-swaps",
"zrml/orderbook-v1",
"zrml/parimutuel",
"zrml/prediction-markets",
"zrml/prediction-markets/runtime-api",
"zrml/rikiddo",
Expand All @@ -35,6 +36,7 @@ members = [
"zrml/neo-swaps",
"zrml/orderbook-v1",
"zrml/orderbook-v1/fuzz",
"zrml/parimutuel",
"zrml/prediction-markets",
"zrml/prediction-markets/fuzz",
"zrml/prediction-markets/runtime-api",
Expand Down Expand Up @@ -233,6 +235,7 @@ zrml-liquidity-mining = { path = "zrml/liquidity-mining", default-features = fal
zrml-market-commons = { path = "zrml/market-commons", default-features = false }
zrml-neo-swaps = { path = "zrml/neo-swaps", default-features = false }
zrml-orderbook-v1 = { path = "zrml/orderbook-v1", default-features = false }
zrml-parimutuel = { path = "zrml/parimutuel", default-features = false }
zrml-prediction-markets = { path = "zrml/prediction-markets", default-features = false }
zrml-prediction-markets-runtime-api = { path = "zrml/prediction-markets/runtime-api", default-features = false }
zrml-rikiddo = { path = "zrml/rikiddo", default-features = false }
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ _anything_.
- [orderbook-v1](./zrml/orderbook-v1) - A naive orderbook implementation that's
only part of Zeitgeist's PoC. Will be replaced by a v2 orderbook that uses
0x-style hybrid on-chain and off-chain trading.
- [parimutuel](./zrml/parimutuel) - A straightforward parimutuel market maker
for categorical markets.
- [prediction-markets](./zrml/prediction-markets) - The core implementation of
the prediction market logic for creating and resolving markets.
- [simple-disputes](./zrml-simple-disputes) - Simple disputes selects the last
Expand Down
21 changes: 21 additions & 0 deletions docs/changelog_for_devs.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,27 @@ APIs/RPC interface.
## v0.4.2

[#1148]: https://github.com/zeitgeistpm/zeitgeist/pull/1148
[#1138]: https://github.com/zeitgeistpm/zeitgeist/pull/1138

### Added

- Implement parimutuel market ([#1138]) maker to allow markets without liquidity
provision. The new pallet has the following dispatchables:

- `buy`: Buy outcome tokens.
- `claim_rewards`: Claim the winner outcome tokens.
- `claim_refunds`: Claim the refunds in case there was no winner.

The new pallet has the following events:

- `OutcomeBought { market_id, buyer, asset, amount_minus_fees, fees }`:
Informant bought a position.
- `RewardsClaimed { market_id, asset, balance, actual_payoff, sender }`:
Informant claimed rewards.
- `RefundsClaimed { market_id, asset, refunded_balance, sender }`: Informant
claimed refunds.

For details, please refer to the `README.md` and the in-file documentation.

### Changed

Expand Down
3 changes: 2 additions & 1 deletion primitives/src/asset.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2022 Forecasting Technologies LTD.
// Copyright 2022-2023 Forecasting Technologies LTD.
// Copyright 2021-2022 Zeitgeist PM LLC.
//
// This file is part of Zeitgeist.
Expand Down Expand Up @@ -50,6 +50,7 @@ pub enum Asset<MI: MaxEncodedLen> {
#[default]
Ztg,
ForeignAsset(u32),
ParimutuelShare(MI, CategoryIndex),
}

/// In a scalar market, users can either choose a `Long` position,
Expand Down
3 changes: 3 additions & 0 deletions primitives/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ pub const SWAPS_PALLET_ID: PalletId = PalletId(*b"zge/swap");
// Orderbook
pub const ORDERBOOK_PALLET_ID: PalletId = PalletId(*b"zge/ordb");

// Parimutuel
pub const PARIMUTUEL_PALLET_ID: PalletId = PalletId(*b"zge/prmt");

// Treasury
/// Pallet identifier, used to derive treasury account
pub const TREASURY_PALLET_ID: PalletId = PalletId(*b"zge/tsry");
6 changes: 6 additions & 0 deletions primitives/src/constants/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ parameter_types! {
pub const OrderbookPalletId: PalletId = PalletId(*b"zge/ordb");
}

// Parimutuel parameters
parameter_types! {
pub const ParimutuelPalletId: PalletId = PalletId(*b"zge/prmt");
pub const MinBetSize: Balance = BASE;
}

// Shared within tests
// Balance
parameter_types! {
Expand Down
21 changes: 21 additions & 0 deletions primitives/src/market.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,22 @@ pub struct Market<AI, BA, BN, M, A> {
pub bonds: MarketBonds<AI, BA>,
}

impl<AI, BA, BN, M, A> Market<AI, BA, BN, M, A> {
pub fn resolution_mechanism(&self) -> ResolutionMechanism {
match self.scoring_rule {
ScoringRule::CPMM
| ScoringRule::Lmsr
| ScoringRule::Orderbook
| ScoringRule::RikiddoSigmoidFeeMarketEma => ResolutionMechanism::RedeemTokens,
ScoringRule::Parimutuel => ResolutionMechanism::Noop,
}
}

pub fn is_redeemable(&self) -> bool {
matches!(self.resolution_mechanism(), ResolutionMechanism::RedeemTokens)
}
}

/// Tracks the status of a bond.
#[derive(Clone, Decode, Encode, MaxEncodedLen, PartialEq, Eq, RuntimeDebug, TypeInfo)]
pub struct Bond<AI, BA> {
Expand Down Expand Up @@ -303,6 +319,11 @@ pub struct AuthorityReport<BlockNumber> {
pub outcome: OutcomeReport,
}

pub enum ResolutionMechanism {
RedeemTokens,
Noop,
}

/// Contains a market id and the market period.
///
/// * `BN`: Block Number
Expand Down
24 changes: 24 additions & 0 deletions primitives/src/math/fixed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,24 @@ pub fn bmul(a: u128, b: u128) -> Result<u128, DispatchError> {
c1.check_div_rslt(&BASE)
}

pub fn bmul_floor(a: u128, b: u128) -> Result<u128, DispatchError> {
// checked_mul already rounds down
let c0 = a.check_mul_rslt(&b)?;
c0.check_div_rslt(&BASE)
}

pub fn bdiv(a: u128, b: u128) -> Result<u128, DispatchError> {
let c0 = a.check_mul_rslt(&BASE)?;
let c1 = c0.check_add_rslt(&b.check_div_rslt(&2)?)?;
c1.check_div_rslt(&b)
}

pub fn bdiv_floor(a: u128, b: u128) -> Result<u128, DispatchError> {
let c0 = a.check_mul_rslt(&BASE)?;
// checked_div already rounds down
c0.check_div_rslt(&b)
}

pub fn bpowi(a: u128, n: u128) -> Result<u128, DispatchError> {
let mut z = if n % 2 != 0 { a } else { BASE };

Expand Down Expand Up @@ -353,6 +365,18 @@ mod tests {
};
}

#[test]
fn bmul_rounding_behaviours() {
assert_eq!(bmul(3u128, 33_333_333_333u128).unwrap(), 10u128);
assert_eq!(bmul_floor(3u128, 33_333_333_333u128).unwrap(), 9u128);
}

#[test]
fn bdiv_rounding_behaviors() {
assert_eq!(bdiv(14u128, 3u128).unwrap(), 46_666_666_667u128);
assert_eq!(bdiv_floor(14u128, 3u128).unwrap(), 46_666_666_666u128);
}

#[test]
fn bdiv_has_minimum_set_of_correct_values() {
create_tests!(
Expand Down
1 change: 1 addition & 0 deletions primitives/src/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,5 @@ pub enum ScoringRule {
RikiddoSigmoidFeeMarketEma,
Lmsr,
Orderbook,
Parimutuel,
}
2 changes: 2 additions & 0 deletions primitives/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
mod complete_set_operations_api;
mod deploy_pool_api;
mod dispute_api;
mod distribute_fees;
mod market_commons_pallet_api;
mod market_id;
mod swaps;
Expand All @@ -27,6 +28,7 @@ mod zeitgeist_multi_reservable_currency;
pub use complete_set_operations_api::CompleteSetOperationsApi;
pub use deploy_pool_api::DeployPoolApi;
pub use dispute_api::{DisputeApi, DisputeMaxWeightApi, DisputeResolutionApi};
pub use distribute_fees::DistributeFees;
pub use market_commons_pallet_api::MarketCommonsPalletApi;
pub use market_id::MarketId;
pub use swaps::Swaps;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub trait DistributeFees {
fn distribute(
market_id: Self::MarketId,
asset: Self::Asset,
account: Self::AccountId,
account: &Self::AccountId,
maltekliemann marked this conversation as resolved.
Show resolved Hide resolved
amount: Self::Balance,
) -> Self::Balance;
}
4 changes: 4 additions & 0 deletions runtime/battery-station/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ zrml-liquidity-mining = { workspace = true }
zrml-market-commons = { workspace = true }
zrml-neo-swaps = { workspace = true }
zrml-orderbook-v1 = { workspace = true }
zrml-parimutuel = { workspace = true }
zrml-prediction-markets = { workspace = true }
zrml-rikiddo = { workspace = true }
zrml-simple-disputes = { workspace = true }
Expand Down Expand Up @@ -211,6 +212,7 @@ runtime-benchmarks = [
"zrml-court/runtime-benchmarks",
"zrml-liquidity-mining/runtime-benchmarks",
"zrml-neo-swaps/runtime-benchmarks",
"zrml-parimutuel/runtime-benchmarks",
"zrml-prediction-markets/runtime-benchmarks",
"zrml-simple-disputes/runtime-benchmarks",
"zrml-global-disputes/runtime-benchmarks",
Expand Down Expand Up @@ -325,6 +327,7 @@ std = [
"zrml-liquidity-mining/std",
"zrml-market-commons/std",
"zrml-neo-swaps/std",
"zrml-parimutuel/std",
"zrml-prediction-markets/std",
"zrml-rikiddo/std",
"zrml-simple-disputes/std",
Expand Down Expand Up @@ -380,6 +383,7 @@ try-runtime = [
"zrml-liquidity-mining/try-runtime",
"zrml-market-commons/try-runtime",
"zrml-neo-swaps/try-runtime",
"zrml-parimutuel/try-runtime",
"zrml-prediction-markets/try-runtime",
"zrml-rikiddo/try-runtime",
"zrml-simple-disputes/try-runtime",
Expand Down
5 changes: 1 addition & 4 deletions runtime/battery-station/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,7 @@ use frame_support::{
use frame_system::{EnsureRoot, EnsureWithSuccess};
use orml_currencies::Call::transfer;
use pallet_collective::{EnsureProportionAtLeast, PrimeDefaultVote};
use sp_runtime::{
traits::{AccountIdConversion, AccountIdLookup, BlakeTwo256},
DispatchError,
};
use sp_runtime::traits::{AccountIdConversion, AccountIdLookup, BlakeTwo256};
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use substrate_fixed::{types::extra::U33, FixedI128, FixedU128};
Expand Down
5 changes: 5 additions & 0 deletions runtime/battery-station/src/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ parameter_types! {
// Orderbook parameters
pub const OrderbookPalletId: PalletId = ORDERBOOK_PALLET_ID;

// Parimutuel parameters
pub const MinBetSize: Balance = 100 * ExistentialDeposit::get();
pub const ParimutuelPalletId: PalletId = PARIMUTUEL_PALLET_ID;

// System
pub const BlockHashCount: u64 = 250;
pub const SS58Prefix: u8 = 73;
Expand Down Expand Up @@ -466,6 +470,7 @@ parameter_type_with_key! {
#[cfg(not(feature = "parachain"))]
Asset::ForeignAsset(_) => ExistentialDeposit::get(),
Asset::Ztg => ExistentialDeposit::get(),
Asset::ParimutuelShare(_,_) => ExistentialDeposit::get(),
}
};
}
Expand Down
47 changes: 47 additions & 0 deletions runtime/common/src/fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,53 @@ macro_rules! impl_foreign_fees {
};
}

#[macro_export]
macro_rules! impl_market_creator_fees {
() => {
pub struct MarketCreatorFee;

/// Uses the `creator_fee` field defined by the specified market to deduct a fee for the market's
/// creator. Calling `distribute` is noop if the market doesn't exist or the transfer fails for any
/// reason.
impl DistributeFees for MarketCreatorFee {
type Asset = Asset<MarketId>;
type AccountId = AccountId;
type Balance = Balance;
type MarketId = MarketId;

fn distribute(
market_id: Self::MarketId,
asset: Self::Asset,
account: &Self::AccountId,
amount: Self::Balance,
) -> Self::Balance {
Self::do_distribute(market_id, asset, account, amount)
.unwrap_or_else(|_| 0u8.saturated_into())
}
}

impl MarketCreatorFee {
fn do_distribute(
market_id: MarketId,
asset: Asset<MarketId>,
account: &AccountId,
amount: Balance,
) -> Result<Balance, DispatchError> {
let market = MarketCommons::market(&market_id)?; // Should never fail
let fee_amount = market.creator_fee.mul_floor(amount);
// Might fail if the transaction is too small
<AssetManager as MultiCurrency<_>>::transfer(
asset,
account,
&market.creator,
fee_amount,
)?;
Ok(fee_amount)
}
}
};
}

#[macro_export]
macro_rules! fee_tests {
() => {
Expand Down
Loading
Loading