From 45701a61a1291d9f9c0a6a6c47fa7fcbc4954dfc Mon Sep 17 00:00:00 2001 From: Malte Kliemann Date: Mon, 8 Apr 2024 16:35:10 +0200 Subject: [PATCH] Fix prediction-markets tests, I (#1265) * Test `admin_move_market_to_resolved` with disputed market * Fix formatting * Move court integration test to `integration.rs` * Test that `approve_market` fails in invalid states * Use `ApproveOrigin` instead of `SUDO` * Fix formatting * Use `RejectOrigin` instead of `SUDO` * Use `CloseMarketEarlyOrigin` instead of `SUDO` * Use `CloseOrigin` instead of `SUDO` * Remove `DestroyOrigin` * Use `RequestEditOrigin` to replace `SUDO` * Use `ResolveOrigin` to replace `SUDO` * Fix benchmarks and tests * Remove solved TODO * Add `buy_complete_set` tests * Add missing `close_trusted_market` tests * Add missing tests for `create_market` * Fix naming in `benchmarks.rs` * Apply suggestions from code review Co-authored-by: Harald Heckmann --------- Co-authored-by: Harald Heckmann Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- runtime/common/src/lib.rs | 7 - zrml/neo-swaps/src/mock.rs | 1 - zrml/prediction-markets/src/benchmarks.rs | 24 +- zrml/prediction-markets/src/lib.rs | 3 - zrml/prediction-markets/src/mock.rs | 28 +- .../src/tests/admin_move_market_to_closed.rs | 19 +- .../tests/admin_move_market_to_resolved.rs | 77 +++- .../src/tests/approve_market.rs | 54 ++- .../src/tests/buy_complete_set.rs | 12 +- .../src/tests/close_market.rs | 47 +- .../src/tests/create_market.rs | 85 +++- zrml/prediction-markets/src/tests/dispute.rs | 33 +- .../src/tests/dispute_early_close.rs | 19 +- .../src/tests/edit_market.rs | 24 +- .../src/tests/integration.rs | 248 +++++++++- zrml/prediction-markets/src/tests/mod.rs | 2 +- .../src/tests/on_market_close.rs | 2 +- .../src/tests/on_resolution.rs | 429 +----------------- .../src/tests/reject_early_close.rs | 44 +- .../src/tests/reject_market.rs | 49 +- .../src/tests/request_edit.rs | 10 +- .../src/tests/schedule_early_close.rs | 19 +- 22 files changed, 699 insertions(+), 537 deletions(-) diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index c8709d7ce..5f624f20f 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -172,12 +172,6 @@ macro_rules! decl_common_types { EnsureProportionAtLeast, >; - // At least 100% - type EnsureRootOrAllAdvisoryCommittee = EitherOfDiverse< - EnsureRoot, - EnsureProportionAtLeast, - >; - #[cfg(feature = "std")] /// The version information used to identify this runtime when compiled natively. pub fn native_version() -> NativeVersion { @@ -1274,7 +1268,6 @@ macro_rules! impl_config_traits { type CloseEarlyProtectionTimeFramePeriod = CloseEarlyProtectionTimeFramePeriod; type CloseEarlyProtectionBlockPeriod = CloseEarlyProtectionBlockPeriod; type CloseEarlyRequestBond = CloseEarlyRequestBond; - type DestroyOrigin = EnsureRootOrAllAdvisoryCommittee; type DeployPool = NeoSwaps; type DisputeBond = DisputeBond; type RuntimeEvent = RuntimeEvent; diff --git a/zrml/neo-swaps/src/mock.rs b/zrml/neo-swaps/src/mock.rs index 28de6bf34..2bef966c7 100644 --- a/zrml/neo-swaps/src/mock.rs +++ b/zrml/neo-swaps/src/mock.rs @@ -340,7 +340,6 @@ impl zrml_prediction_markets::Config for Runtime { type Court = Court; type Currency = Balances; type DeployPool = DeployPoolNoop; - type DestroyOrigin = EnsureSignedBy; type DisputeBond = DisputeBond; type RuntimeEvent = RuntimeEvent; type GlobalDisputes = GlobalDisputes; diff --git a/zrml/prediction-markets/src/benchmarks.rs b/zrml/prediction-markets/src/benchmarks.rs index eb19904b4..c0c137bb1 100644 --- a/zrml/prediction-markets/src/benchmarks.rs +++ b/zrml/prediction-markets/src/benchmarks.rs @@ -280,10 +280,10 @@ benchmarks! { ).unwrap(); } - let close_origin = T::CloseOrigin::try_successful_origin().unwrap(); + let resolve_origin = T::ResolveOrigin::try_successful_origin().unwrap(); let call = Call::::admin_move_market_to_resolved { market_id }; }: { - call.dispatch_bypass_filter(close_origin)? + call.dispatch_bypass_filter(resolve_origin)? } verify { assert_last_event::(Event::MarketResolved::( market_id, @@ -316,10 +316,10 @@ benchmarks! { ).unwrap(); } - let close_origin = T::CloseOrigin::try_successful_origin().unwrap(); + let resolve_origin = T::ResolveOrigin::try_successful_origin().unwrap(); let call = Call::::admin_move_market_to_resolved { market_id }; }: { - call.dispatch_bypass_filter(close_origin)? + call.dispatch_bypass_filter(resolve_origin)? } verify { assert_last_event::(Event::MarketResolved::( market_id, @@ -368,10 +368,10 @@ benchmarks! { ).unwrap(); } - let close_origin = T::CloseOrigin::try_successful_origin().unwrap(); + let resolve_origin = T::ResolveOrigin::try_successful_origin().unwrap(); let call = Call::::admin_move_market_to_resolved { market_id }; }: { - call.dispatch_bypass_filter(close_origin)? + call.dispatch_bypass_filter(resolve_origin)? } verify { assert_last_event::(Event::MarketResolved::( market_id, @@ -421,10 +421,10 @@ benchmarks! { ).unwrap(); } - let close_origin = T::CloseOrigin::try_successful_origin().unwrap(); + let resolve_origin = T::ResolveOrigin::try_successful_origin().unwrap(); let call = Call::::admin_move_market_to_resolved { market_id }; }: { - call.dispatch_bypass_filter(close_origin)? + call.dispatch_bypass_filter(resolve_origin)? } verify { assert_last_event::(Event::MarketResolved::( market_id, @@ -456,10 +456,10 @@ benchmarks! { Some(MarketDisputeMechanism::Court), )?; - let approve_origin = T::ApproveOrigin::try_successful_origin().unwrap(); + let request_edit_origin = T::RequestEditOrigin::try_successful_origin().unwrap(); let edit_reason = vec![0_u8; r as usize]; let call = Call::::request_edit{ market_id, edit_reason }; - }: { call.dispatch_bypass_filter(approve_origin)? } verify {} + }: { call.dispatch_bypass_filter(request_edit_origin)? } verify {} buy_complete_set { let a in (T::MinCategories::get().into())..T::MaxCategories::get().into(); @@ -529,10 +529,10 @@ benchmarks! { .dispatch_bypass_filter(RawOrigin::Signed(caller.clone()).into())?; let market_id = zrml_market_commons::Pallet::::latest_market_id()?; - let approve_origin = T::ApproveOrigin::try_successful_origin().unwrap(); + let request_edit_origin = T::RequestEditOrigin::try_successful_origin().unwrap(); let edit_reason = vec![0_u8; 1024]; Call::::request_edit{ market_id, edit_reason } - .dispatch_bypass_filter(approve_origin)?; + .dispatch_bypass_filter(request_edit_origin)?; for i in 0..m { MarketIdsPerCloseTimeFrame::::try_mutate( diff --git a/zrml/prediction-markets/src/lib.rs b/zrml/prediction-markets/src/lib.rs index 59694b7e7..0552a2c80 100644 --- a/zrml/prediction-markets/src/lib.rs +++ b/zrml/prediction-markets/src/lib.rs @@ -1628,9 +1628,6 @@ mod pallet { MarketId = MarketIdOf, >; - /// 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>; diff --git a/zrml/prediction-markets/src/mock.rs b/zrml/prediction-markets/src/mock.rs index 3f0ef4230..5ef90a100 100644 --- a/zrml/prediction-markets/src/mock.rs +++ b/zrml/prediction-markets/src/mock.rs @@ -44,6 +44,8 @@ use sp_runtime::{ DispatchError, DispatchResult, }; use std::cell::RefCell; +#[cfg(feature = "parachain")] +use zeitgeist_primitives::types::XcmAsset; use zeitgeist_primitives::{ constants::mock::{ AddOutcomePeriod, AggregationPeriod, AppealBond, AppealPeriod, AssetsAccountDeposit, @@ -68,7 +70,6 @@ use zeitgeist_primitives::{ AccountIdTest, Amount, Assets, Balance, BasicCurrencyAdapter, BlockNumber, BlockTest, CampaignAsset, CampaignAssetClass, CampaignAssetId, Currencies, CustomAsset, CustomAssetId, Hash, Index, MarketAsset, MarketId, Moment, ResultWithWeightInfo, UncheckedExtrinsicTest, - XcmAsset, }, }; @@ -86,6 +87,12 @@ pub const DAVE: AccountIdTest = 3; pub const EVE: AccountIdTest = 4; pub const FRED: AccountIdTest = 5; pub const SUDO: AccountIdTest = 69; +pub const APPROVE_ORIGIN: AccountIdTest = 70; +pub const REJECT_ORIGIN: AccountIdTest = 71; +pub const CLOSE_MARKET_EARLY_ORIGIN: AccountIdTest = 72; +pub const CLOSE_ORIGIN: AccountIdTest = 73; +pub const REQUEST_EDIT_ORIGIN: AccountIdTest = 74; +pub const RESOLVE_ORIGIN: AccountIdTest = 75; pub const INITIAL_BALANCE: u128 = 1_000 * BASE; @@ -191,6 +198,12 @@ impl DeployPoolMock { ord_parameter_types! { pub const Sudo: AccountIdTest = SUDO; + pub const ApproveOrigin: AccountIdTest = APPROVE_ORIGIN; + pub const RejectOrigin: AccountIdTest = REJECT_ORIGIN; + pub const CloseMarketEarlyOrigin: AccountIdTest = CLOSE_MARKET_EARLY_ORIGIN; + pub const CloseOrigin: AccountIdTest = CLOSE_ORIGIN; + pub const RequestEditOrigin: AccountIdTest = REQUEST_EDIT_ORIGIN; + pub const ResolveOrigin: AccountIdTest = RESOLVE_ORIGIN; } parameter_types! { pub const AdvisoryBond: Balance = 11 * CENT; @@ -235,7 +248,7 @@ construct_runtime!( impl crate::Config for Runtime { type AdvisoryBond = AdvisoryBond; type AdvisoryBondSlashPercentage = AdvisoryBondSlashPercentage; - type ApproveOrigin = EnsureSignedBy; + type ApproveOrigin = EnsureSignedBy; type AssetCreator = AssetRouter; type AssetDestroyer = AssetRouter; type AssetManager = AssetManager; @@ -243,15 +256,14 @@ impl crate::Config for Runtime { type AssetRegistry = MockRegistry; type Authorized = Authorized; type CloseEarlyDisputeBond = CloseEarlyDisputeBond; - type CloseMarketEarlyOrigin = EnsureSignedBy; + type CloseMarketEarlyOrigin = EnsureSignedBy; type CloseEarlyProtectionTimeFramePeriod = CloseEarlyProtectionTimeFramePeriod; type CloseEarlyProtectionBlockPeriod = CloseEarlyProtectionBlockPeriod; type CloseEarlyRequestBond = CloseEarlyRequestBond; - type CloseOrigin = EnsureSignedBy; + type CloseOrigin = EnsureSignedBy; type Currency = Balances; type MaxCreatorFee = MaxCreatorFee; type Court = Court; - type DestroyOrigin = EnsureSignedBy; type DeployPool = DeployPoolMock; type DisputeBond = DisputeBond; type RuntimeEvent = RuntimeEvent; @@ -274,9 +286,9 @@ impl crate::Config for Runtime { type PalletId = PmPalletId; type CloseEarlyBlockPeriod = CloseEarlyBlockPeriod; type CloseEarlyTimeFramePeriod = CloseEarlyTimeFramePeriod; - type RejectOrigin = EnsureSignedBy; - type RequestEditOrigin = EnsureSignedBy; - type ResolveOrigin = EnsureSignedBy; + type RejectOrigin = EnsureSignedBy; + type RequestEditOrigin = EnsureSignedBy; + type ResolveOrigin = EnsureSignedBy; type SimpleDisputes = SimpleDisputes; type Slash = Treasury; type ValidityBond = ValidityBond; diff --git a/zrml/prediction-markets/src/tests/admin_move_market_to_closed.rs b/zrml/prediction-markets/src/tests/admin_move_market_to_closed.rs index 5cc92b88c..8fbef6fe2 100644 --- a/zrml/prediction-markets/src/tests/admin_move_market_to_closed.rs +++ b/zrml/prediction-markets/src/tests/admin_move_market_to_closed.rs @@ -36,7 +36,7 @@ fn admin_move_market_to_closed_successfully_closes_market_and_sets_end_blocknumb run_blocks(3); let market_id = 0; assert_ok!(PredictionMarkets::admin_move_market_to_closed( - RuntimeOrigin::signed(SUDO), + RuntimeOrigin::signed(CloseOrigin::get()), market_id )); let market = MarketCommons::market(&market_id).unwrap(); @@ -81,7 +81,7 @@ fn admin_move_market_to_closed_successfully_closes_market_and_sets_end_timestamp run_blocks(shift_blocks); assert_ok!(PredictionMarkets::admin_move_market_to_closed( - RuntimeOrigin::signed(SUDO), + RuntimeOrigin::signed(CloseOrigin::get()), market_id )); let market = MarketCommons::market(&market_id).unwrap(); @@ -97,7 +97,10 @@ fn admin_move_market_to_closed_successfully_closes_market_and_sets_end_timestamp fn admin_move_market_to_closed_fails_if_market_does_not_exist() { ExtBuilder::default().build().execute_with(|| { assert_noop!( - PredictionMarkets::admin_move_market_to_closed(RuntimeOrigin::signed(SUDO), 0), + PredictionMarkets::admin_move_market_to_closed( + RuntimeOrigin::signed(CloseOrigin::get()), + 0 + ), zrml_market_commons::Error::::MarketDoesNotExist ); }); @@ -122,7 +125,10 @@ fn admin_move_market_to_closed_fails_if_market_is_not_active(market_status: Mark Ok(()) })); assert_noop!( - PredictionMarkets::admin_move_market_to_closed(RuntimeOrigin::signed(SUDO), market_id), + PredictionMarkets::admin_move_market_to_closed( + RuntimeOrigin::signed(CloseOrigin::get()), + market_id + ), Error::::MarketIsNotActive, ); }); @@ -158,7 +164,10 @@ fn admin_move_market_to_closed_correctly_clears_auto_close_blocks() { Some(MarketDisputeMechanism::SimpleDisputes), ScoringRule::Lmsr, )); - assert_ok!(PredictionMarkets::admin_move_market_to_closed(RuntimeOrigin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::admin_move_market_to_closed( + RuntimeOrigin::signed(CloseOrigin::get()), + 0 + )); let auto_close = MarketIdsPerCloseBlock::::get(66).into_inner(); assert_eq!(auto_close, vec![1]); diff --git a/zrml/prediction-markets/src/tests/admin_move_market_to_resolved.rs b/zrml/prediction-markets/src/tests/admin_move_market_to_resolved.rs index 1d1826093..a82c5f89e 100644 --- a/zrml/prediction-markets/src/tests/admin_move_market_to_resolved.rs +++ b/zrml/prediction-markets/src/tests/admin_move_market_to_resolved.rs @@ -57,7 +57,7 @@ fn admin_move_market_to_resolved_resolves_reported_market() { outcome_report.clone() )); assert_ok!(PredictionMarkets::admin_move_market_to_resolved( - RuntimeOrigin::signed(SUDO), + RuntimeOrigin::signed(ResolveOrigin::get()), market_id )); @@ -94,7 +94,78 @@ fn admin_move_market_to_resolved_resolves_reported_market() { }); } -// TODO(#1239) resolves disputed market +#[test] +fn admin_move_market_to_resolved_resolves_disputed_market() { + // NOTE: Bonds are always in ZTG, irrespective of base_asset. + let test = |base_asset: BaseAsset| { + let end = 33; + simple_create_categorical_market( + base_asset, + MarketCreation::Permissionless, + 0..end, + ScoringRule::Lmsr, + ); + let market_id = 0; + + // Give ALICE `SENTINEL_AMOUNT` free and reserved ZTG; we record the free balance to check + // that the correct bonds are unreserved! + assert_ok!(AssetManager::deposit(Asset::Ztg, &ALICE, 2 * SENTINEL_AMOUNT)); + assert_ok!(Balances::reserve_named( + &PredictionMarkets::reserve_id(), + &ALICE, + SENTINEL_AMOUNT + )); + let balance_free_before = Balances::free_balance(ALICE); + let balance_reserved_before = + Balances::reserved_balance_named(&PredictionMarkets::reserve_id(), &ALICE); + + let market = MarketCommons::market(&0).unwrap(); + let grace_period = end + market.deadlines.grace_period; + run_to_block(grace_period + 1); + let category = 1; + let outcome_report = OutcomeReport::Categorical(category); + assert_ok!(PredictionMarkets::report( + RuntimeOrigin::signed(BOB), + market_id, + OutcomeReport::Categorical(0), + )); + assert_ok!(PredictionMarkets::dispute(RuntimeOrigin::signed(CHARLIE), market_id)); + assert_ok!(Authorized::authorize_market_outcome( + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), + market_id, + outcome_report.clone(), + )); + assert_ok!(PredictionMarkets::admin_move_market_to_resolved( + RuntimeOrigin::signed(ResolveOrigin::get()), + market_id + )); + + let market = MarketCommons::market(&market_id).unwrap(); + assert_eq!(market.status, MarketStatus::Resolved); + assert_eq!(market.resolved_outcome.unwrap(), outcome_report); + System::assert_last_event( + Event::MarketResolved(market_id, MarketStatus::Resolved, outcome_report).into(), + ); + + assert_eq!( + Balances::reserved_balance_named(&PredictionMarkets::reserve_id(), &ALICE), + balance_reserved_before + - ::OracleBond::get() + - ::ValidityBond::get() + ); + assert_eq!( + Balances::free_balance(ALICE), + balance_free_before + ::ValidityBond::get() + ); + }; + ExtBuilder::default().build().execute_with(|| { + test(BaseAsset::Ztg); + }); + #[cfg(feature = "parachain")] + ExtBuilder::default().build().execute_with(|| { + test(BaseAsset::ForeignAsset(100)); + }); +} #[test_case(MarketStatus::Active)] #[test_case(MarketStatus::Closed)] @@ -116,7 +187,7 @@ fn admin_move_market_to_resolved_fails_if_market_is_not_reported_or_disputed( })); assert_noop!( PredictionMarkets::admin_move_market_to_resolved( - RuntimeOrigin::signed(SUDO), + RuntimeOrigin::signed(ResolveOrigin::get()), market_id, ), Error::::InvalidMarketStatus, diff --git a/zrml/prediction-markets/src/tests/approve_market.rs b/zrml/prediction-markets/src/tests/approve_market.rs index c2bf82081..c3c603f21 100644 --- a/zrml/prediction-markets/src/tests/approve_market.rs +++ b/zrml/prediction-markets/src/tests/approve_market.rs @@ -17,12 +17,38 @@ // along with Zeitgeist. If not, see . use super::*; +use test_case::test_case; use crate::MarketIdsForEdit; use sp_runtime::DispatchError; -// TODO(#1239) Be more granular with regards to origins -// TODO(#1239) Approve fails if market status is not proposed +#[test_case(MarketStatus::Active)] +#[test_case(MarketStatus::Closed)] +#[test_case(MarketStatus::Reported)] +#[test_case(MarketStatus::Disputed)] +#[test_case(MarketStatus::Resolved)] +fn fails_if_market_status_is_not_proposed(market_status: MarketStatus) { + ExtBuilder::default().build().execute_with(|| { + simple_create_categorical_market( + BaseAsset::Ztg, + MarketCreation::Advised, + 0..2, + ScoringRule::Lmsr, + ); + let market_id = 0; + assert_ok!(MarketCommons::mutate_market(&market_id, |market| { + market.status = market_status; + Ok(()) + })); + assert_noop!( + PredictionMarkets::approve_market( + RuntimeOrigin::signed(ApproveOrigin::get()), + market_id + ), + Error::::MarketIsNotProposed + ); + }); +} #[test] fn it_allows_advisory_origin_to_approve_markets() { @@ -43,8 +69,10 @@ fn it_allows_advisory_origin_to_approve_markets() { DispatchError::BadOrigin ); - // Now it should work from SUDO - assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market( + RuntimeOrigin::signed(ApproveOrigin::get()), + 0 + )); let after_market = MarketCommons::market(&0); assert_eq!(after_market.unwrap().status, MarketStatus::Active); @@ -68,11 +96,15 @@ fn market_with_edit_request_cannot_be_approved() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; - assert_ok!(PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), 0, edit_reason)); + assert_ok!(PredictionMarkets::request_edit( + RuntimeOrigin::signed(RequestEditOrigin::get()), + 0, + edit_reason + )); assert!(MarketIdsForEdit::::contains_key(0)); assert_noop!( - PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0), + PredictionMarkets::approve_market(RuntimeOrigin::signed(ApproveOrigin::get()), 0), Error::::MarketEditRequestAlreadyInProgress ); }); @@ -99,7 +131,10 @@ fn approve_market_correctly_unreserves_advisory_bond() { let market_id = 0; let alice_balance_before = Balances::free_balance(ALICE); check_reserve(&ALICE, AdvisoryBond::get() + OracleBond::get()); - assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), market_id)); + assert_ok!(PredictionMarkets::approve_market( + RuntimeOrigin::signed(ApproveOrigin::get()), + market_id + )); check_reserve(&ALICE, OracleBond::get()); assert_eq!(Balances::free_balance(ALICE), alice_balance_before + AdvisoryBond::get()); let market = MarketCommons::market(&market_id).unwrap(); @@ -127,7 +162,10 @@ fn does_trigger_market_transition_api() { 1..2, ScoringRule::Lmsr, ); - assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market( + RuntimeOrigin::signed(ApproveOrigin::get()), + 0 + )); assert!(StateTransitionMock::on_activation_triggered()); }); } diff --git a/zrml/prediction-markets/src/tests/buy_complete_set.rs b/zrml/prediction-markets/src/tests/buy_complete_set.rs index 8a5ee2140..ba327d8a2 100644 --- a/zrml/prediction-markets/src/tests/buy_complete_set.rs +++ b/zrml/prediction-markets/src/tests/buy_complete_set.rs @@ -19,8 +19,6 @@ use super::*; use test_case::test_case; -// TODO(#1239) buy_complete_set fails if market doesn't exist - #[test] fn buy_complete_set_works() { let test = |base_asset: BaseAsset| { @@ -151,3 +149,13 @@ fn buy_complete_set_fails_if_market_has_wrong_scoring_rule(scoring_rule: Scoring ); }); } + +#[test] +fn fails_if_market_is_not_found() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(FRED), 0, 1), + zrml_market_commons::Error::::MarketDoesNotExist, + ); + }); +} diff --git a/zrml/prediction-markets/src/tests/close_market.rs b/zrml/prediction-markets/src/tests/close_market.rs index 9e666d01a..448cf2861 100644 --- a/zrml/prediction-markets/src/tests/close_market.rs +++ b/zrml/prediction-markets/src/tests/close_market.rs @@ -22,8 +22,6 @@ use test_case::test_case; use crate::MarketIdsPerCloseBlock; use sp_runtime::traits::Zero; -// TODO(#1239) MarketDoesNotExist - // TODO(#1239) Split test #[test] fn close_trusted_market_works() { @@ -62,11 +60,6 @@ fn close_trusted_market_works() { let auto_closes = MarketIdsPerCloseBlock::::get(end); assert_eq!(auto_closes.first().cloned().unwrap(), market_id); - assert_noop!( - PredictionMarkets::close_trusted_market(RuntimeOrigin::signed(BOB), market_id), - Error::::CallerNotMarketCreator - ); - assert_ok!(PredictionMarkets::close_trusted_market( RuntimeOrigin::signed(market_creator), market_id @@ -80,6 +73,36 @@ fn close_trusted_market_works() { }); } +#[test] +fn fails_if_caller_is_not_market_creator() { + ExtBuilder::default().build().execute_with(|| { + let end = 10; + let market_creator = ALICE; + assert_ok!(PredictionMarkets::create_market( + RuntimeOrigin::signed(market_creator), + BaseAsset::Ztg, + Perbill::zero(), + BOB, + MarketPeriod::Block(0..end), + Deadlines { + grace_period: 0, + oracle_duration: ::MinOracleDuration::get(), + dispute_duration: Zero::zero(), + }, + gen_metadata(0x99), + MarketCreation::Permissionless, + MarketType::Categorical(3), + None, + ScoringRule::Lmsr, + )); + run_to_block(end - 1); + assert_noop!( + PredictionMarkets::close_trusted_market(RuntimeOrigin::signed(BOB), 0), + Error::::CallerNotMarketCreator + ); + }); +} + #[test] fn close_trusted_market_fails_if_not_trusted() { ExtBuilder::default().build().execute_with(|| { @@ -165,6 +188,16 @@ fn close_trusted_market_fails_if_invalid_market_state(status: MarketStatus) { }); } +#[test] +fn fails_if_market_is_not_found() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + PredictionMarkets::close_trusted_market(RuntimeOrigin::signed(ALICE), 3), + zrml_market_commons::Error::::MarketDoesNotExist + ); + }); +} + #[test] fn does_trigger_market_transition_api_permissionless() { ExtBuilder::default().build().execute_with(|| { diff --git a/zrml/prediction-markets/src/tests/create_market.rs b/zrml/prediction-markets/src/tests/create_market.rs index a59aa0fa6..70b1c6355 100644 --- a/zrml/prediction-markets/src/tests/create_market.rs +++ b/zrml/prediction-markets/src/tests/create_market.rs @@ -26,9 +26,88 @@ use zeitgeist_primitives::{ types::{BlockNumber, Bond, MarketBonds, Moment}, }; -// TODO(#1239) FeeTooHigh not verified -// TODO(#1239) InvalidMultihash not verified -// TODO(#1239) Creation fails if user can't afford the bonds +#[test_case( + MarketCreation::Advised, + ::AdvisoryBond::get() + ::OracleBond::get() - 1 +)] +#[test_case( + MarketCreation::Permissionless, + ::ValidityBond::get() + ::OracleBond::get() - 1 +)] +fn fails_if_user_cannot_afford_bonds_advised( + market_creation: MarketCreation, + balance: BalanceOf, +) { + ExtBuilder::default().build().execute_with(|| { + let creator = 999; + assert_ok!(AssetManager::deposit(Asset::Ztg, &creator, balance)); + assert_noop!( + PredictionMarkets::create_market( + RuntimeOrigin::signed(creator), + BaseAsset::Ztg, + ::MaxCreatorFee::get(), + BOB, + MarketPeriod::Block(123..456), + get_deadlines(), + gen_metadata(2), + market_creation, + MarketType::Scalar(0..=1), + Some(MarketDisputeMechanism::SimpleDisputes), + ScoringRule::Lmsr, + ), + pallet_balances::Error::::InsufficientBalance + ); + }); +} + +#[test] +fn fails_on_fee_too_high() { + ExtBuilder::default().build().execute_with(|| { + let one_billionth = Perbill::from_rational(1u128, 1_000_000_000u128); + assert_noop!( + PredictionMarkets::create_market( + RuntimeOrigin::signed(ALICE), + BaseAsset::Ztg, + ::MaxCreatorFee::get() + one_billionth, + BOB, + MarketPeriod::Block(123..456), + get_deadlines(), + gen_metadata(2), + MarketCreation::Permissionless, + MarketType::Scalar(0..=1), + Some(MarketDisputeMechanism::SimpleDisputes), + ScoringRule::Lmsr, + ), + Error::::FeeTooHigh + ); + }); +} + +#[test] +fn fails_on_invalid_multihash() { + ExtBuilder::default().build().execute_with(|| { + let mut metadata = [0xff; 50]; + metadata[0] = 0x15; + metadata[1] = 0x29; + let multihash = MultiHash::Sha3_384(metadata); + assert_noop!( + PredictionMarkets::create_market( + RuntimeOrigin::signed(ALICE), + BaseAsset::Ztg, + ::MaxCreatorFee::get(), + BOB, + MarketPeriod::Block(123..456), + get_deadlines(), + multihash, + MarketCreation::Permissionless, + MarketType::Scalar(0..=1), + Some(MarketDisputeMechanism::SimpleDisputes), + ScoringRule::Lmsr, + ), + Error::::InvalidMultihash + ); + }); +} #[test_case(std::ops::RangeInclusive::new(7, 6); "empty range")] #[test_case(555..=555; "one element as range")] diff --git a/zrml/prediction-markets/src/tests/dispute.rs b/zrml/prediction-markets/src/tests/dispute.rs index b06000d78..8dc16635b 100644 --- a/zrml/prediction-markets/src/tests/dispute.rs +++ b/zrml/prediction-markets/src/tests/dispute.rs @@ -36,39 +36,34 @@ fn it_allows_to_dispute_the_outcome_of_a_market() { 0..end, ScoringRule::Lmsr, ); + let market_id = 0; // Run to the end of the trading phase. - let market = MarketCommons::market(&0).unwrap(); + let market = MarketCommons::market(&market_id).unwrap(); let grace_period = end + market.deadlines.grace_period; run_to_block(grace_period + 1); assert_ok!(PredictionMarkets::report( RuntimeOrigin::signed(BOB), - 0, + market_id, OutcomeReport::Categorical(1) )); let dispute_at = grace_period + 2; run_to_block(dispute_at); - assert_ok!(PredictionMarkets::dispute(RuntimeOrigin::signed(CHARLIE), 0,)); - assert_ok!(SimpleDisputes::suggest_outcome( - RuntimeOrigin::signed(CHARLIE), - 0, - OutcomeReport::Categorical(0) - )); - - let market = MarketCommons::market(&0).unwrap(); + assert_ok!(PredictionMarkets::dispute(RuntimeOrigin::signed(CHARLIE), 0)); + let market = MarketCommons::market(&market_id).unwrap(); assert_eq!(market.status, MarketStatus::Disputed); - let disputes = zrml_simple_disputes::Disputes::::get(0); - assert_eq!(disputes.len(), 1); - let dispute = &disputes[0]; - assert_eq!(dispute.at, dispute_at); - assert_eq!(dispute.by, CHARLIE); - assert_eq!(dispute.outcome, OutcomeReport::Categorical(0)); - - let dispute_ends_at = dispute_at + market.deadlines.dispute_duration; + // Ensure that the MDM interacts correctly with auto resolution. + assert_ok!(Authorized::authorize_market_outcome( + RuntimeOrigin::signed(AuthorizedDisputeResolutionUser::get()), + market_id, + OutcomeReport::Categorical(0), + )); + let dispute_ends_at = + dispute_at + ::CorrectionPeriod::get(); let market_ids = MarketIdsPerDisputeBlock::::get(dispute_ends_at); assert_eq!(market_ids.len(), 1); assert_eq!(market_ids[0], 0); @@ -107,7 +102,7 @@ fn dispute_fails_disputed_already() { let dispute_at = grace_period + 2; run_to_block(dispute_at); - assert_ok!(PredictionMarkets::dispute(RuntimeOrigin::signed(CHARLIE), 0,)); + assert_ok!(PredictionMarkets::dispute(RuntimeOrigin::signed(CHARLIE), 0)); assert_noop!( PredictionMarkets::dispute(RuntimeOrigin::signed(CHARLIE), 0), diff --git a/zrml/prediction-markets/src/tests/dispute_early_close.rs b/zrml/prediction-markets/src/tests/dispute_early_close.rs index 074b10012..8ed76eee4 100644 --- a/zrml/prediction-markets/src/tests/dispute_early_close.rs +++ b/zrml/prediction-markets/src/tests/dispute_early_close.rs @@ -142,9 +142,10 @@ fn dispute_early_close_fails_if_scheduled_as_sudo() { )); let market_id = 0; - assert_ok!( - PredictionMarkets::schedule_early_close(RuntimeOrigin::signed(SUDO), market_id,) - ); + assert_ok!(PredictionMarkets::schedule_early_close( + RuntimeOrigin::signed(CloseMarketEarlyOrigin::get()), + market_id + )); run_blocks(1); @@ -221,7 +222,10 @@ fn dispute_early_close_fails_if_already_rejected() { assert_ok!(PredictionMarkets::dispute_early_close(RuntimeOrigin::signed(BOB), market_id,)); - assert_ok!(PredictionMarkets::reject_early_close(RuntimeOrigin::signed(SUDO), market_id,)); + assert_ok!(PredictionMarkets::reject_early_close( + RuntimeOrigin::signed(CloseMarketEarlyOrigin::get()), + market_id + )); let market = MarketCommons::market(&market_id).unwrap(); assert_eq!(market.early_close.unwrap().state, EarlyCloseState::Rejected); @@ -377,9 +381,10 @@ fn schedule_early_close_disputed_sudo_schedule_and_settle_bonds() { let free_bob = Balances::free_balance(BOB); let free_alice = Balances::free_balance(ALICE); - assert_ok!( - PredictionMarkets::schedule_early_close(RuntimeOrigin::signed(SUDO), market_id,) - ); + assert_ok!(PredictionMarkets::schedule_early_close( + RuntimeOrigin::signed(CloseMarketEarlyOrigin::get()), + market_id + )); let reserved_bob_after = Balances::reserved_balance(BOB); let reserved_alice_after = Balances::reserved_balance(ALICE); diff --git a/zrml/prediction-markets/src/tests/edit_market.rs b/zrml/prediction-markets/src/tests/edit_market.rs index 7bc90dc9f..0dbb0e077 100644 --- a/zrml/prediction-markets/src/tests/edit_market.rs +++ b/zrml/prediction-markets/src/tests/edit_market.rs @@ -41,8 +41,12 @@ fn only_creator_can_edit_market() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; - // Now it should work from SUDO - assert_ok!(PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), 0, edit_reason)); + // Now it should work for the designated origin. + assert_ok!(PredictionMarkets::request_edit( + RuntimeOrigin::signed(RequestEditOrigin::get()), + 0, + edit_reason + )); assert!(MarketIdsForEdit::::contains_key(0)); @@ -80,8 +84,12 @@ fn edit_cycle_for_proposed_markets() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; - // Now it should work from SUDO - assert_ok!(PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), 0, edit_reason)); + // Now it should work for the designated origin. + assert_ok!(PredictionMarkets::request_edit( + RuntimeOrigin::signed(RequestEditOrigin::get()), + 0, + edit_reason + )); assert!(MarketIdsForEdit::::contains_key(0)); @@ -126,8 +134,12 @@ fn edit_market_with_foreign_asset() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; - // Now it should work from SUDO - assert_ok!(PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), 0, edit_reason)); + // Now it should work for the designated origin. + assert_ok!(PredictionMarkets::request_edit( + RuntimeOrigin::signed(RequestEditOrigin::get()), + 0, + edit_reason + )); assert!(MarketIdsForEdit::::contains_key(0)); diff --git a/zrml/prediction-markets/src/tests/integration.rs b/zrml/prediction-markets/src/tests/integration.rs index a303f6bc4..3599495df 100644 --- a/zrml/prediction-markets/src/tests/integration.rs +++ b/zrml/prediction-markets/src/tests/integration.rs @@ -17,13 +17,15 @@ // along with Zeitgeist. If not, see . use super::*; - -use alloc::collections::BTreeMap; -use zeitgeist_primitives::types::OutcomeReport; - use crate::MarketIdsPerDisputeBlock; +use alloc::collections::BTreeMap; use orml_traits::MultiReservableCurrency; -use zeitgeist_primitives::{constants::MILLISECS_PER_BLOCK, types::ScalarPosition}; +use sp_runtime::Perquintill; +use zeitgeist_primitives::{ + constants::MILLISECS_PER_BLOCK, + types::{OutcomeReport, ScalarPosition}, +}; +use zrml_court::types::{CourtStatus, Draw, Vote}; use zrml_global_disputes::{ types::{OutcomeInfo, Possession}, GlobalDisputesPalletApi, Outcomes, PossessionOf, @@ -479,6 +481,242 @@ fn authorized_correctly_resolves_disputed_market() { }); } +#[test] +fn it_resolves_a_disputed_court_market() { + let test = |base_asset: BaseAsset| { + let juror_0 = 1000; + let juror_1 = 1001; + let juror_2 = 1002; + let juror_3 = 1003; + let juror_4 = 1004; + let juror_5 = 1005; + + for j in &[juror_0, juror_1, juror_2, juror_3, juror_4, juror_5] { + let amount = ::MinJurorStake::get() + *j; + assert_ok!(AssetManager::deposit(Asset::Ztg, j, amount + SENTINEL_AMOUNT)); + assert_ok!(Court::join_court(RuntimeOrigin::signed(*j), amount)); + } + + // just to have enough jurors for the dispute + for j in 1006..(1006 + Court::necessary_draws_weight(0usize) as u32) { + let juror = j as u128; + let amount = ::MinJurorStake::get() + juror; + assert_ok!(AssetManager::deposit(Asset::Ztg, &juror, amount + SENTINEL_AMOUNT)); + assert_ok!(Court::join_court(RuntimeOrigin::signed(juror), amount)); + } + + let end = 2; + assert_ok!(PredictionMarkets::create_market( + RuntimeOrigin::signed(ALICE), + base_asset, + Perbill::zero(), + BOB, + MarketPeriod::Block(0..end), + get_deadlines(), + gen_metadata(2), + MarketCreation::Permissionless, + MarketType::Categorical(::MinCategories::get()), + Some(MarketDisputeMechanism::Court), + ScoringRule::Lmsr, + )); + + let market_id = 0; + let market = MarketCommons::market(&0).unwrap(); + + let report_at = end + market.deadlines.grace_period + 1; + run_to_block(report_at); + + assert_ok!(PredictionMarkets::report( + RuntimeOrigin::signed(BOB), + market_id, + OutcomeReport::Categorical(0) + )); + + assert_ok!(PredictionMarkets::dispute(RuntimeOrigin::signed(CHARLIE), market_id,)); + + let court = zrml_court::Courts::::get(market_id).unwrap(); + let vote_start = court.round_ends.pre_vote + 1; + + run_to_block(vote_start); + + // overwrite draws to disregard randomness + zrml_court::SelectedDraws::::remove(market_id); + let mut draws = zrml_court::SelectedDraws::::get(market_id); + for juror in &[juror_0, juror_1, juror_2, juror_3, juror_4, juror_5] { + let draw = Draw { + court_participant: *juror, + weight: 1, + vote: Vote::Drawn, + slashable: ::MinJurorStake::get(), + }; + let index = draws + .binary_search_by_key(juror, |draw| draw.court_participant) + .unwrap_or_else(|j| j); + draws.try_insert(index, draw).unwrap(); + } + let old_draws = draws.clone(); + zrml_court::SelectedDraws::::insert(market_id, draws); + + let salt = ::Hash::default(); + + // outcome_0 is the plurality decision => right outcome + let outcome_0 = OutcomeReport::Categorical(0); + let vote_item_0 = VoteItem::Outcome(outcome_0.clone()); + // outcome_1 is the wrong outcome + let outcome_1 = OutcomeReport::Categorical(1); + let vote_item_1 = VoteItem::Outcome(outcome_1); + + let commitment_0 = BlakeTwo256::hash_of(&(juror_0, vote_item_0.clone(), salt)); + assert_ok!(Court::vote(RuntimeOrigin::signed(juror_0), market_id, commitment_0)); + + // juror_1 votes for non-plurality outcome => slashed later + let commitment_1 = BlakeTwo256::hash_of(&(juror_1, vote_item_1.clone(), salt)); + assert_ok!(Court::vote(RuntimeOrigin::signed(juror_1), market_id, commitment_1)); + + let commitment_2 = BlakeTwo256::hash_of(&(juror_2, vote_item_0.clone(), salt)); + assert_ok!(Court::vote(RuntimeOrigin::signed(juror_2), market_id, commitment_2)); + + let commitment_3 = BlakeTwo256::hash_of(&(juror_3, vote_item_0.clone(), salt)); + assert_ok!(Court::vote(RuntimeOrigin::signed(juror_3), market_id, commitment_3)); + + // juror_4 fails to vote in time + + let commitment_5 = BlakeTwo256::hash_of(&(juror_5, vote_item_0.clone(), salt)); + assert_ok!(Court::vote(RuntimeOrigin::signed(juror_5), market_id, commitment_5)); + + // juror_3 is denounced by juror_0 => slashed later + assert_ok!(Court::denounce_vote( + RuntimeOrigin::signed(juror_0), + market_id, + juror_3, + vote_item_0.clone(), + salt + )); + + let aggregation_start = court.round_ends.vote + 1; + run_to_block(aggregation_start); + + assert_ok!(Court::reveal_vote( + RuntimeOrigin::signed(juror_0), + market_id, + vote_item_0.clone(), + salt + )); + assert_ok!(Court::reveal_vote( + RuntimeOrigin::signed(juror_1), + market_id, + vote_item_1, + salt + )); + + let wrong_salt = BlakeTwo256::hash_of(&69); + assert_noop!( + Court::reveal_vote( + RuntimeOrigin::signed(juror_2), + market_id, + vote_item_0.clone(), + wrong_salt + ), + zrml_court::Error::::CommitmentHashMismatch + ); + assert_ok!(Court::reveal_vote( + RuntimeOrigin::signed(juror_2), + market_id, + vote_item_0.clone(), + salt + )); + + assert_noop!( + Court::reveal_vote( + RuntimeOrigin::signed(juror_3), + market_id, + vote_item_0.clone(), + salt + ), + zrml_court::Error::::VoteAlreadyDenounced + ); + + assert_noop!( + Court::reveal_vote( + RuntimeOrigin::signed(juror_4), + market_id, + vote_item_0.clone(), + salt + ), + zrml_court::Error::::JurorDidNotVote + ); + + // juror_5 fails to reveal in time + + let resolve_at = court.round_ends.appeal; + let market_ids = MarketIdsPerDisputeBlock::::get(resolve_at); + assert_eq!(market_ids.len(), 1); + + run_blocks(resolve_at); + + let market_after = MarketCommons::market(&0).unwrap(); + assert_eq!(market_after.status, MarketStatus::Resolved); + assert_eq!(market_after.resolved_outcome, Some(outcome_0)); + let court_after = zrml_court::Courts::::get(market_id).unwrap(); + assert_eq!(court_after.status, CourtStatus::Closed { winner: vote_item_0 }); + + let free_juror_0_before = Balances::free_balance(juror_0); + let free_juror_1_before = Balances::free_balance(juror_1); + let free_juror_2_before = Balances::free_balance(juror_2); + let free_juror_3_before = Balances::free_balance(juror_3); + let free_juror_4_before = Balances::free_balance(juror_4); + let free_juror_5_before = Balances::free_balance(juror_5); + + assert_ok!(Court::reassign_court_stakes(RuntimeOrigin::signed(juror_0), market_id)); + + let free_juror_0_after = Balances::free_balance(juror_0); + let slashable_juror_0 = + old_draws.iter().find(|draw| draw.court_participant == juror_0).unwrap().slashable; + let free_juror_1_after = Balances::free_balance(juror_1); + let slashable_juror_1 = + old_draws.iter().find(|draw| draw.court_participant == juror_1).unwrap().slashable; + let free_juror_2_after = Balances::free_balance(juror_2); + let slashable_juror_2 = + old_draws.iter().find(|draw| draw.court_participant == juror_2).unwrap().slashable; + let free_juror_3_after = Balances::free_balance(juror_3); + let slashable_juror_3 = + old_draws.iter().find(|draw| draw.court_participant == juror_3).unwrap().slashable; + let free_juror_4_after = Balances::free_balance(juror_4); + let slashable_juror_4 = + old_draws.iter().find(|draw| draw.court_participant == juror_4).unwrap().slashable; + let free_juror_5_after = Balances::free_balance(juror_5); + let slashable_juror_5 = + old_draws.iter().find(|draw| draw.court_participant == juror_5).unwrap().slashable; + + let mut total_slashed = 0; + // juror_1 voted for the wrong outcome => slashed + assert_eq!(free_juror_1_before - free_juror_1_after, slashable_juror_1); + total_slashed += slashable_juror_1; + // juror_3 was denounced by juror_0 => slashed + assert_eq!(free_juror_3_before - free_juror_3_after, slashable_juror_3); + total_slashed += slashable_juror_3; + // juror_4 failed to vote => slashed + assert_eq!(free_juror_4_before - free_juror_4_after, slashable_juror_4); + total_slashed += slashable_juror_4; + // juror_5 failed to reveal => slashed + assert_eq!(free_juror_5_before - free_juror_5_after, slashable_juror_5); + total_slashed += slashable_juror_5; + // juror_0 and juror_2 voted for the right outcome => rewarded + let total_winner_stake = slashable_juror_0 + slashable_juror_2; + let juror_0_share = Perquintill::from_rational(slashable_juror_0, total_winner_stake); + assert_eq!(free_juror_0_after, free_juror_0_before + juror_0_share * total_slashed); + let juror_2_share = Perquintill::from_rational(slashable_juror_2, total_winner_stake); + assert_eq!(free_juror_2_after, free_juror_2_before + juror_2_share * total_slashed); + }; + ExtBuilder::default().build().execute_with(|| { + test(BaseAsset::Ztg); + }); + #[cfg(feature = "parachain")] + ExtBuilder::default().build().execute_with(|| { + test(BaseAsset::ForeignAsset(100)); + }); +} + #[test] fn outsider_reports_wrong_outcome() { // NOTE: Bonds are always in ZTG, irrespective of base_asset. diff --git a/zrml/prediction-markets/src/tests/mod.rs b/zrml/prediction-markets/src/tests/mod.rs index e4d159553..662ff84f8 100644 --- a/zrml/prediction-markets/src/tests/mod.rs +++ b/zrml/prediction-markets/src/tests/mod.rs @@ -122,7 +122,7 @@ fn simple_create_categorical_market( gen_metadata(2), creation, MarketType::Categorical(::MinCategories::get()), - Some(MarketDisputeMechanism::SimpleDisputes), + Some(MarketDisputeMechanism::Authorized), scoring_rule )); } diff --git a/zrml/prediction-markets/src/tests/on_market_close.rs b/zrml/prediction-markets/src/tests/on_market_close.rs index ae8762b21..f5189bd3c 100644 --- a/zrml/prediction-markets/src/tests/on_market_close.rs +++ b/zrml/prediction-markets/src/tests/on_market_close.rs @@ -101,7 +101,7 @@ fn on_market_close_auto_rejects_expired_advised_market_with_edit_request() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; assert_ok!(PredictionMarkets::request_edit( - RuntimeOrigin::signed(SUDO), + RuntimeOrigin::signed(RequestEditOrigin::get()), market_id, edit_reason )); diff --git a/zrml/prediction-markets/src/tests/on_resolution.rs b/zrml/prediction-markets/src/tests/on_resolution.rs index 4f640ed33..a7a9672da 100644 --- a/zrml/prediction-markets/src/tests/on_resolution.rs +++ b/zrml/prediction-markets/src/tests/on_resolution.rs @@ -19,12 +19,8 @@ use super::*; use crate::{MarketIdsPerDisputeBlock, MarketIdsPerReportBlock}; -use sp_runtime::{ - traits::{BlakeTwo256, Hash, Zero}, - Perquintill, -}; +use sp_runtime::traits::Zero; use zeitgeist_primitives::types::{Bond, OutcomeReport, Report}; -use zrml_court::types::{CourtStatus, Draw, Vote, VoteItem}; #[test] fn it_correctly_resolves_a_market_that_was_reported_on() { @@ -84,404 +80,6 @@ fn it_correctly_resolves_a_market_that_was_reported_on() { }); } -#[test] -fn it_resolves_a_disputed_market() { - let test = |base_asset: BaseAsset| { - let end = 2; - simple_create_categorical_market( - base_asset, - MarketCreation::Permissionless, - 0..end, - ScoringRule::Lmsr, - ); - - assert_ok!(PredictionMarkets::buy_complete_set(RuntimeOrigin::signed(CHARLIE), 0, CENT)); - let market = MarketCommons::market(&0).unwrap(); - - let report_at = end + market.deadlines.grace_period + 1; - run_to_block(report_at); - - assert_ok!(PredictionMarkets::report( - RuntimeOrigin::signed(BOB), - 0, - OutcomeReport::Categorical(0) - )); - - assert_ok!(PredictionMarkets::dispute(RuntimeOrigin::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); - - assert_ok!(SimpleDisputes::suggest_outcome( - RuntimeOrigin::signed(CHARLIE), - 0, - OutcomeReport::Categorical(1) - )); - - let dispute_at_1 = report_at + 2; - run_to_block(dispute_at_1); - - assert_ok!(SimpleDisputes::suggest_outcome( - RuntimeOrigin::signed(DAVE), - 0, - OutcomeReport::Categorical(0) - )); - - let dispute_at_2 = report_at + 3; - run_to_block(dispute_at_2); - - assert_ok!(SimpleDisputes::suggest_outcome( - RuntimeOrigin::signed(EVE), - 0, - OutcomeReport::Categorical(1) - )); - - let market = MarketCommons::market(&0).unwrap(); - assert_eq!(market.status, MarketStatus::Disputed); - - // check everyone's deposits - let charlie_reserved = Balances::reserved_balance(CHARLIE); - assert_eq!( - charlie_reserved, - DisputeBond::get() + ::OutcomeBond::get() - ); - - let dave_reserved = Balances::reserved_balance(DAVE); - assert_eq!( - dave_reserved, - ::OutcomeBond::get() - + ::OutcomeFactor::get() - ); - - let eve_reserved = Balances::reserved_balance(EVE); - assert_eq!( - eve_reserved, - ::OutcomeBond::get() - + 2 * ::OutcomeFactor::get() - ); - - // check disputes length - 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 - let market_ids_1 = MarketIdsPerDisputeBlock::::get( - dispute_at_0 + market.deadlines.dispute_duration, - ); - assert_eq!(market_ids_1.len(), 0); - - let market_ids_2 = MarketIdsPerDisputeBlock::::get( - dispute_at_1 + market.deadlines.dispute_duration, - ); - assert_eq!(market_ids_2.len(), 0); - - let market_ids_3 = MarketIdsPerDisputeBlock::::get( - dispute_at_2 + market.deadlines.dispute_duration, - ); - assert_eq!(market_ids_3.len(), 1); - - run_blocks(market.deadlines.dispute_duration); - - let market_after = MarketCommons::market(&0).unwrap(); - assert_eq!(market_after.status, MarketStatus::Resolved); - let disputes = zrml_simple_disputes::Disputes::::get(0); - assert_eq!(disputes.len(), 0); - - assert_ok!(PredictionMarkets::redeem_shares(RuntimeOrigin::signed(CHARLIE), 0)); - - // Make sure rewards are right: - // - // Slashed amounts: - // - Dave's reserve: ::OutcomeBond::get() + ::OutcomeFactor::get() - // - Alice's oracle bond: OracleBond::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 simple-disputes reward as bounty. - let dave_reserved = ::OutcomeBond::get() - + ::OutcomeFactor::get(); - let total_slashed = dave_reserved; - - let charlie_balance = Balances::free_balance(CHARLIE); - 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); - assert_eq!(eve_balance, 1_000 * BASE + total_slashed / 2); - - let dave_balance = Balances::free_balance(DAVE); - assert_eq!(dave_balance, 1_000 * BASE - dave_reserved); - - let alice_balance = Balances::free_balance(ALICE); - assert_eq!(alice_balance, 1_000 * BASE - OracleBond::get()); - - // bob kinda gets away scot-free since Alice is held responsible - // for her designated reporter - let bob_balance = Balances::free_balance(BOB); - assert_eq!(bob_balance, 1_000 * BASE); - - assert!(market_after.bonds.creation.unwrap().is_settled); - assert!(market_after.bonds.oracle.unwrap().is_settled); - assert!(market_after.bonds.dispute.unwrap().is_settled); - }; - ExtBuilder::default().build().execute_with(|| { - test(BaseAsset::CampaignAsset(100)); - }); - ExtBuilder::default().build().execute_with(|| { - test(BaseAsset::Ztg); - }); - #[cfg(feature = "parachain")] - ExtBuilder::default().build().execute_with(|| { - test(BaseAsset::ForeignAsset(100)); - }); -} - -#[test] -fn it_resolves_a_disputed_court_market() { - let test = |base_asset: BaseAsset| { - let juror_0 = 1000; - let juror_1 = 1001; - let juror_2 = 1002; - let juror_3 = 1003; - let juror_4 = 1004; - let juror_5 = 1005; - - for j in &[juror_0, juror_1, juror_2, juror_3, juror_4, juror_5] { - let amount = ::MinJurorStake::get() + *j; - assert_ok!(AssetManager::deposit(Asset::Ztg, j, amount + SENTINEL_AMOUNT)); - assert_ok!(Court::join_court(RuntimeOrigin::signed(*j), amount)); - } - - // just to have enough jurors for the dispute - for j in 1006..(1006 + Court::necessary_draws_weight(0usize) as u32) { - let juror = j as u128; - let amount = ::MinJurorStake::get() + juror; - assert_ok!(AssetManager::deposit(Asset::Ztg, &juror, amount + SENTINEL_AMOUNT)); - assert_ok!(Court::join_court(RuntimeOrigin::signed(juror), amount)); - } - - let end = 2; - assert_ok!(PredictionMarkets::create_market( - RuntimeOrigin::signed(ALICE), - base_asset, - Perbill::zero(), - BOB, - MarketPeriod::Block(0..end), - get_deadlines(), - gen_metadata(2), - MarketCreation::Permissionless, - MarketType::Categorical(::MinCategories::get()), - Some(MarketDisputeMechanism::Court), - ScoringRule::Lmsr, - )); - - let market_id = 0; - let market = MarketCommons::market(&0).unwrap(); - - let report_at = end + market.deadlines.grace_period + 1; - run_to_block(report_at); - - assert_ok!(PredictionMarkets::report( - RuntimeOrigin::signed(BOB), - market_id, - OutcomeReport::Categorical(0) - )); - - assert_ok!(PredictionMarkets::dispute(RuntimeOrigin::signed(CHARLIE), market_id,)); - - let court = zrml_court::Courts::::get(market_id).unwrap(); - let vote_start = court.round_ends.pre_vote + 1; - - run_to_block(vote_start); - - // overwrite draws to disregard randomness - zrml_court::SelectedDraws::::remove(market_id); - let mut draws = zrml_court::SelectedDraws::::get(market_id); - for juror in &[juror_0, juror_1, juror_2, juror_3, juror_4, juror_5] { - let draw = Draw { - court_participant: *juror, - weight: 1, - vote: Vote::Drawn, - slashable: ::MinJurorStake::get(), - }; - let index = draws - .binary_search_by_key(juror, |draw| draw.court_participant) - .unwrap_or_else(|j| j); - draws.try_insert(index, draw).unwrap(); - } - let old_draws = draws.clone(); - zrml_court::SelectedDraws::::insert(market_id, draws); - - let salt = ::Hash::default(); - - // outcome_0 is the plurality decision => right outcome - let outcome_0 = OutcomeReport::Categorical(0); - let vote_item_0 = VoteItem::Outcome(outcome_0.clone()); - // outcome_1 is the wrong outcome - let outcome_1 = OutcomeReport::Categorical(1); - let vote_item_1 = VoteItem::Outcome(outcome_1); - - let commitment_0 = BlakeTwo256::hash_of(&(juror_0, vote_item_0.clone(), salt)); - assert_ok!(Court::vote(RuntimeOrigin::signed(juror_0), market_id, commitment_0)); - - // juror_1 votes for non-plurality outcome => slashed later - let commitment_1 = BlakeTwo256::hash_of(&(juror_1, vote_item_1.clone(), salt)); - assert_ok!(Court::vote(RuntimeOrigin::signed(juror_1), market_id, commitment_1)); - - let commitment_2 = BlakeTwo256::hash_of(&(juror_2, vote_item_0.clone(), salt)); - assert_ok!(Court::vote(RuntimeOrigin::signed(juror_2), market_id, commitment_2)); - - let commitment_3 = BlakeTwo256::hash_of(&(juror_3, vote_item_0.clone(), salt)); - assert_ok!(Court::vote(RuntimeOrigin::signed(juror_3), market_id, commitment_3)); - - // juror_4 fails to vote in time - - let commitment_5 = BlakeTwo256::hash_of(&(juror_5, vote_item_0.clone(), salt)); - assert_ok!(Court::vote(RuntimeOrigin::signed(juror_5), market_id, commitment_5)); - - // juror_3 is denounced by juror_0 => slashed later - assert_ok!(Court::denounce_vote( - RuntimeOrigin::signed(juror_0), - market_id, - juror_3, - vote_item_0.clone(), - salt - )); - - let aggregation_start = court.round_ends.vote + 1; - run_to_block(aggregation_start); - - assert_ok!(Court::reveal_vote( - RuntimeOrigin::signed(juror_0), - market_id, - vote_item_0.clone(), - salt - )); - assert_ok!(Court::reveal_vote( - RuntimeOrigin::signed(juror_1), - market_id, - vote_item_1, - salt - )); - - let wrong_salt = BlakeTwo256::hash_of(&69); - assert_noop!( - Court::reveal_vote( - RuntimeOrigin::signed(juror_2), - market_id, - vote_item_0.clone(), - wrong_salt - ), - zrml_court::Error::::CommitmentHashMismatch - ); - assert_ok!(Court::reveal_vote( - RuntimeOrigin::signed(juror_2), - market_id, - vote_item_0.clone(), - salt - )); - - assert_noop!( - Court::reveal_vote( - RuntimeOrigin::signed(juror_3), - market_id, - vote_item_0.clone(), - salt - ), - zrml_court::Error::::VoteAlreadyDenounced - ); - - assert_noop!( - Court::reveal_vote( - RuntimeOrigin::signed(juror_4), - market_id, - vote_item_0.clone(), - salt - ), - zrml_court::Error::::JurorDidNotVote - ); - - // juror_5 fails to reveal in time - - let resolve_at = court.round_ends.appeal; - let market_ids = MarketIdsPerDisputeBlock::::get(resolve_at); - assert_eq!(market_ids.len(), 1); - - run_blocks(resolve_at); - - let market_after = MarketCommons::market(&0).unwrap(); - assert_eq!(market_after.status, MarketStatus::Resolved); - assert_eq!(market_after.resolved_outcome, Some(outcome_0)); - let court_after = zrml_court::Courts::::get(market_id).unwrap(); - assert_eq!(court_after.status, CourtStatus::Closed { winner: vote_item_0 }); - - let free_juror_0_before = Balances::free_balance(juror_0); - let free_juror_1_before = Balances::free_balance(juror_1); - let free_juror_2_before = Balances::free_balance(juror_2); - let free_juror_3_before = Balances::free_balance(juror_3); - let free_juror_4_before = Balances::free_balance(juror_4); - let free_juror_5_before = Balances::free_balance(juror_5); - - assert_ok!(Court::reassign_court_stakes(RuntimeOrigin::signed(juror_0), market_id)); - - let free_juror_0_after = Balances::free_balance(juror_0); - let slashable_juror_0 = - old_draws.iter().find(|draw| draw.court_participant == juror_0).unwrap().slashable; - let free_juror_1_after = Balances::free_balance(juror_1); - let slashable_juror_1 = - old_draws.iter().find(|draw| draw.court_participant == juror_1).unwrap().slashable; - let free_juror_2_after = Balances::free_balance(juror_2); - let slashable_juror_2 = - old_draws.iter().find(|draw| draw.court_participant == juror_2).unwrap().slashable; - let free_juror_3_after = Balances::free_balance(juror_3); - let slashable_juror_3 = - old_draws.iter().find(|draw| draw.court_participant == juror_3).unwrap().slashable; - let free_juror_4_after = Balances::free_balance(juror_4); - let slashable_juror_4 = - old_draws.iter().find(|draw| draw.court_participant == juror_4).unwrap().slashable; - let free_juror_5_after = Balances::free_balance(juror_5); - let slashable_juror_5 = - old_draws.iter().find(|draw| draw.court_participant == juror_5).unwrap().slashable; - - let mut total_slashed = 0; - // juror_1 voted for the wrong outcome => slashed - assert_eq!(free_juror_1_before - free_juror_1_after, slashable_juror_1); - total_slashed += slashable_juror_1; - // juror_3 was denounced by juror_0 => slashed - assert_eq!(free_juror_3_before - free_juror_3_after, slashable_juror_3); - total_slashed += slashable_juror_3; - // juror_4 failed to vote => slashed - assert_eq!(free_juror_4_before - free_juror_4_after, slashable_juror_4); - total_slashed += slashable_juror_4; - // juror_5 failed to reveal => slashed - assert_eq!(free_juror_5_before - free_juror_5_after, slashable_juror_5); - total_slashed += slashable_juror_5; - // juror_0 and juror_2 voted for the right outcome => rewarded - let total_winner_stake = slashable_juror_0 + slashable_juror_2; - let juror_0_share = Perquintill::from_rational(slashable_juror_0, total_winner_stake); - assert_eq!(free_juror_0_after, free_juror_0_before + juror_0_share * total_slashed); - let juror_2_share = Perquintill::from_rational(slashable_juror_2, total_winner_stake); - assert_eq!(free_juror_2_after, free_juror_2_before + juror_2_share * total_slashed); - }; - ExtBuilder::default().build().execute_with(|| { - test(BaseAsset::CampaignAsset(100)); - }); - ExtBuilder::default().build().execute_with(|| { - test(BaseAsset::Ztg); - }); - #[cfg(feature = "parachain")] - ExtBuilder::default().build().execute_with(|| { - test(BaseAsset::ForeignAsset(100)); - }); -} - #[test] fn on_resolution_correctly_reserves_and_unreserves_bonds_for_approved_advised_market_on_oracle_report() { @@ -502,7 +100,10 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_approved_advised_ma Some(MarketDisputeMechanism::SimpleDisputes), ScoringRule::Lmsr, )); - assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market( + RuntimeOrigin::signed(ApproveOrigin::get()), + 0 + )); let alice_balance_before = Balances::free_balance(ALICE); check_reserve(&ALICE, OracleBond::get()); let market = MarketCommons::market(&0).unwrap(); @@ -551,7 +152,10 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_approved_advised_ma Some(MarketDisputeMechanism::SimpleDisputes), ScoringRule::Lmsr, )); - assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market( + RuntimeOrigin::signed(ApproveOrigin::get()), + 0 + )); let alice_balance_before = Balances::free_balance(ALICE); check_reserve(&ALICE, OracleBond::get()); let market = MarketCommons::market(&0).unwrap(); @@ -655,7 +259,10 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_approved_advised_ma Some(MarketDisputeMechanism::SimpleDisputes), ScoringRule::Lmsr, )); - assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market( + RuntimeOrigin::signed(ApproveOrigin::get()), + 0 + )); let alice_balance_before = Balances::free_balance(ALICE); check_reserve(&ALICE, OracleBond::get()); let market = MarketCommons::market(&0).unwrap(); @@ -773,7 +380,10 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_advised_approved_ma Some(MarketDisputeMechanism::SimpleDisputes), ScoringRule::Lmsr, )); - assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market( + RuntimeOrigin::signed(ApproveOrigin::get()), + 0 + )); let alice_balance_before = Balances::free_balance(ALICE); check_reserve(&ALICE, OracleBond::get()); let market = MarketCommons::market(&0).unwrap(); @@ -912,7 +522,10 @@ fn on_resolution_correctly_reserves_and_unreserves_bonds_for_advised_approved_ma let outsider = CHARLIE; - assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market( + RuntimeOrigin::signed(ApproveOrigin::get()), + 0 + )); let alice_balance_before = Balances::free_balance(ALICE); check_reserve(&ALICE, OracleBond::get()); let market = MarketCommons::market(&0).unwrap(); diff --git a/zrml/prediction-markets/src/tests/reject_early_close.rs b/zrml/prediction-markets/src/tests/reject_early_close.rs index 2a61054ad..0a99c5b87 100644 --- a/zrml/prediction-markets/src/tests/reject_early_close.rs +++ b/zrml/prediction-markets/src/tests/reject_early_close.rs @@ -44,7 +44,10 @@ fn reject_early_close_emits_event() { assert_ok!(PredictionMarkets::dispute_early_close(RuntimeOrigin::signed(BOB), market_id,)); - assert_ok!(PredictionMarkets::reject_early_close(RuntimeOrigin::signed(SUDO), market_id,)); + assert_ok!(PredictionMarkets::reject_early_close( + RuntimeOrigin::signed(CloseMarketEarlyOrigin::get()), + market_id + )); System::assert_last_event(Event::MarketEarlyCloseRejected { market_id }.into()); }); @@ -72,7 +75,10 @@ fn reject_early_close_fails_if_state_is_scheduled_as_market_creator() { )); assert_noop!( - PredictionMarkets::reject_early_close(RuntimeOrigin::signed(SUDO), market_id,), + PredictionMarkets::reject_early_close( + RuntimeOrigin::signed(CloseMarketEarlyOrigin::get()), + market_id + ), Error::::InvalidEarlyCloseState ); }); @@ -94,14 +100,21 @@ fn reject_early_close_fails_if_state_is_rejected() { let market_id = 0; - assert_ok!( - PredictionMarkets::schedule_early_close(RuntimeOrigin::signed(SUDO), market_id,) - ); + assert_ok!(PredictionMarkets::schedule_early_close( + RuntimeOrigin::signed(CloseMarketEarlyOrigin::get()), + market_id + )); - assert_ok!(PredictionMarkets::reject_early_close(RuntimeOrigin::signed(SUDO), market_id,)); + assert_ok!(PredictionMarkets::reject_early_close( + RuntimeOrigin::signed(CloseMarketEarlyOrigin::get()), + market_id + )); assert_noop!( - PredictionMarkets::reject_early_close(RuntimeOrigin::signed(SUDO), market_id,), + PredictionMarkets::reject_early_close( + RuntimeOrigin::signed(CloseMarketEarlyOrigin::get()), + market_id + ), Error::::InvalidEarlyCloseState ); }); @@ -126,9 +139,10 @@ fn reject_early_close_resets_to_old_market_period() { )); let market_id = 0; - assert_ok!( - PredictionMarkets::schedule_early_close(RuntimeOrigin::signed(SUDO), market_id,) - ); + assert_ok!(PredictionMarkets::schedule_early_close( + RuntimeOrigin::signed(CloseMarketEarlyOrigin::get()), + market_id + )); let now = >::block_number(); let new_end = now + ::CloseEarlyProtectionBlockPeriod::get(); @@ -137,7 +151,10 @@ fn reject_early_close_resets_to_old_market_period() { run_blocks(1); - assert_ok!(PredictionMarkets::reject_early_close(RuntimeOrigin::signed(SUDO), market_id,)); + assert_ok!(PredictionMarkets::reject_early_close( + RuntimeOrigin::signed(CloseMarketEarlyOrigin::get()), + market_id + )); let market_ids_at_new_end = >::get(new_end); assert!(market_ids_at_new_end.is_empty()); @@ -180,7 +197,10 @@ fn reject_early_close_settles_bonds() { let free_bob = Balances::free_balance(BOB); let free_alice = Balances::free_balance(ALICE); - assert_ok!(PredictionMarkets::reject_early_close(RuntimeOrigin::signed(SUDO), market_id,)); + assert_ok!(PredictionMarkets::reject_early_close( + RuntimeOrigin::signed(CloseMarketEarlyOrigin::get()), + market_id + )); let market = MarketCommons::market(&market_id).unwrap(); assert_eq!(market.early_close.unwrap().state, EarlyCloseState::Rejected); diff --git a/zrml/prediction-markets/src/tests/reject_market.rs b/zrml/prediction-markets/src/tests/reject_market.rs index 02e0b979d..96bf08052 100644 --- a/zrml/prediction-markets/src/tests/reject_market.rs +++ b/zrml/prediction-markets/src/tests/reject_market.rs @@ -39,7 +39,7 @@ fn it_allows_the_advisory_origin_to_reject_markets() { let reject_reason: Vec = vec![0; ::MaxRejectReasonLen::get() as usize]; assert_ok!(PredictionMarkets::reject_market( - RuntimeOrigin::signed(SUDO), + RuntimeOrigin::signed(RejectOrigin::get()), 0, reject_reason.clone() )); @@ -71,7 +71,11 @@ fn reject_errors_if_reject_reason_is_too_long() { let reject_reason: Vec = vec![0; ::MaxRejectReasonLen::get() as usize + 1]; assert_noop!( - PredictionMarkets::reject_market(RuntimeOrigin::signed(SUDO), 0, reject_reason), + PredictionMarkets::reject_market( + RuntimeOrigin::signed(RejectOrigin::get()), + 0, + reject_reason + ), Error::::RejectReasonLengthExceedsMaxRejectReasonLen ); }); @@ -95,9 +99,17 @@ fn it_allows_the_advisory_origin_to_reject_markets_with_edit_request() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize]; let reject_reason = vec![0_u8; ::MaxRejectReasonLen::get() as usize]; - assert_ok!(PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), 0, edit_reason)); + assert_ok!(PredictionMarkets::request_edit( + RuntimeOrigin::signed(RequestEditOrigin::get()), + 0, + edit_reason + )); assert!(MarketIdsForEdit::::contains_key(0)); - assert_ok!(PredictionMarkets::reject_market(RuntimeOrigin::signed(SUDO), 0, reject_reason)); + assert_ok!(PredictionMarkets::reject_market( + RuntimeOrigin::signed(RejectOrigin::get()), + 0, + reject_reason + )); assert!(!MarketIdsForEdit::::contains_key(0)); assert_noop!( @@ -134,7 +146,11 @@ fn reject_market_unreserves_oracle_bond_and_slashes_advisory_bond() { let reject_reason: Vec = vec![0; ::MaxRejectReasonLen::get() as usize]; - assert_ok!(PredictionMarkets::reject_market(RuntimeOrigin::signed(SUDO), 0, reject_reason)); + assert_ok!(PredictionMarkets::reject_market( + RuntimeOrigin::signed(RejectOrigin::get()), + 0, + reject_reason + )); // AdvisoryBond gets slashed after reject_market // OracleBond gets unreserved after reject_market @@ -199,7 +215,11 @@ fn reject_market_clears_auto_close_blocks() { ); let reject_reason: Vec = vec![0; ::MaxRejectReasonLen::get() as usize]; - assert_ok!(PredictionMarkets::reject_market(RuntimeOrigin::signed(SUDO), 0, reject_reason)); + assert_ok!(PredictionMarkets::reject_market( + RuntimeOrigin::signed(RejectOrigin::get()), + 0, + reject_reason + )); let auto_close = MarketIdsPerCloseBlock::::get(66); assert_eq!(auto_close.len(), 1); @@ -220,7 +240,11 @@ fn reject_market_fails_on_permissionless_market() { let reject_reason: Vec = vec![0; ::MaxRejectReasonLen::get() as usize]; assert_noop!( - PredictionMarkets::reject_market(RuntimeOrigin::signed(SUDO), 0, reject_reason), + PredictionMarkets::reject_market( + RuntimeOrigin::signed(RejectOrigin::get()), + 0, + reject_reason + ), Error::::InvalidMarketStatus ); }); @@ -236,11 +260,18 @@ fn reject_market_fails_on_approved_market() { 0..2, ScoringRule::Lmsr, ); - assert_ok!(PredictionMarkets::approve_market(RuntimeOrigin::signed(SUDO), 0)); + assert_ok!(PredictionMarkets::approve_market( + RuntimeOrigin::signed(ApproveOrigin::get()), + 0 + )); let reject_reason: Vec = vec![0; ::MaxRejectReasonLen::get() as usize]; assert_noop!( - PredictionMarkets::reject_market(RuntimeOrigin::signed(SUDO), 0, reject_reason), + PredictionMarkets::reject_market( + RuntimeOrigin::signed(RejectOrigin::get()), + 0, + reject_reason + ), Error::::InvalidMarketStatus ); }); diff --git a/zrml/prediction-markets/src/tests/request_edit.rs b/zrml/prediction-markets/src/tests/request_edit.rs index 31c4e022b..beadb4940 100644 --- a/zrml/prediction-markets/src/tests/request_edit.rs +++ b/zrml/prediction-markets/src/tests/request_edit.rs @@ -44,9 +44,9 @@ fn it_allows_request_edit_origin_to_request_edits_for_markets() { DispatchError::BadOrigin ); - // Now it should work from SUDO + // Now it should work for the designated origin. assert_ok!(PredictionMarkets::request_edit( - RuntimeOrigin::signed(SUDO), + RuntimeOrigin::signed(RequestEditOrigin::get()), 0, edit_reason.clone() )); @@ -104,7 +104,11 @@ fn edit_request_fails_if_edit_reason_is_too_long() { let edit_reason = vec![0_u8; ::MaxEditReasonLen::get() as usize + 1]; assert_noop!( - PredictionMarkets::request_edit(RuntimeOrigin::signed(SUDO), 0, edit_reason), + PredictionMarkets::request_edit( + RuntimeOrigin::signed(RequestEditOrigin::get()), + 0, + edit_reason + ), Error::::EditReasonLengthExceedsMaxEditReasonLen ); }); diff --git a/zrml/prediction-markets/src/tests/schedule_early_close.rs b/zrml/prediction-markets/src/tests/schedule_early_close.rs index d29ca7f8f..bbc2c740b 100644 --- a/zrml/prediction-markets/src/tests/schedule_early_close.rs +++ b/zrml/prediction-markets/src/tests/schedule_early_close.rs @@ -44,7 +44,10 @@ fn schedule_early_close_emits_event() { let market_id = 0; - assert_ok!(PredictionMarkets::schedule_early_close(RuntimeOrigin::signed(SUDO), market_id)); + assert_ok!(PredictionMarkets::schedule_early_close( + RuntimeOrigin::signed(CloseMarketEarlyOrigin::get()), + market_id + )); let now = >::block_number(); let new_end = now + ::CloseEarlyProtectionBlockPeriod::get(); @@ -89,9 +92,10 @@ fn sudo_schedule_early_close_at_block_works() { assert_eq!(market_ids_to_close.1.into_inner(), vec![market_id]); assert!(market.early_close.is_none()); - assert_ok!( - PredictionMarkets::schedule_early_close(RuntimeOrigin::signed(SUDO), market_id,) - ); + assert_ok!(PredictionMarkets::schedule_early_close( + RuntimeOrigin::signed(CloseMarketEarlyOrigin::get()), + market_id + )); let now = >::block_number(); let new_end = now + ::CloseEarlyProtectionBlockPeriod::get(); @@ -162,9 +166,10 @@ fn sudo_schedule_early_close_at_timeframe_works() { assert_eq!(first.1.clone().into_inner(), vec![market_id]); assert!(market.early_close.is_none()); - assert_ok!( - PredictionMarkets::schedule_early_close(RuntimeOrigin::signed(SUDO), market_id,) - ); + assert_ok!(PredictionMarkets::schedule_early_close( + RuntimeOrigin::signed(CloseMarketEarlyOrigin::get()), + market_id + )); let now = >::now(); let new_end = now + ::CloseEarlyProtectionTimeFramePeriod::get();