diff --git a/pallets/vsbond-auction/src/lib.rs b/pallets/vsbond-auction/src/lib.rs index 8b0c6d6058..5ad55761c3 100644 --- a/pallets/vsbond-auction/src/lib.rs +++ b/pallets/vsbond-auction/src/lib.rs @@ -102,6 +102,9 @@ pub mod module { pub enum Error { NotEnoughSupply, NotFindOrderInfo, + NotEnoughBalanceToUnreserve, + NotEnoughBalanceToReserve, + CantPayThePrice, ForbidRevokeOrderNotInTrade, ForbidRevokeOrderWithoutOwnership, ForbidClinchOrderNotInTrade, @@ -179,7 +182,10 @@ pub mod module { CurrencyId::VSBond(*T::InvoicingCurrency::get(), index, first_slot, last_slot); // Check the balance of vsbond - T::MultiCurrency::ensure_can_withdraw(vsbond, &owner, supply)?; + ensure!( + T::MultiCurrency::can_reserve(vsbond, &owner, supply), + Error::::NotEnoughBalanceToReserve + ); let order_in_trade_amount = { if let Some(sets) = Self::in_trade_order_ids(&owner) { @@ -205,9 +211,8 @@ pub mod module { order_state: OrderState::InTrade, }; - // Lock the balance of vsbond_type - let lock_iden = order_id.to_be_bytes(); - T::MultiCurrency::set_lock(lock_iden, vsbond, &owner, supply)?; + // Reserve the balance of vsbond_type + T::MultiCurrency::reserve(vsbond, &owner, supply)?; // Insert OrderInfo to Storage TotalOrderInfos::::insert(order_id, order_info.clone()); @@ -249,9 +254,11 @@ pub mod module { // Check OrderOwner ensure!(order_info.owner == from, Error::::ForbidRevokeOrderWithoutOwnership); - // Unlock the vsbond - let lock_iden = order_info.order_id.to_be_bytes(); - T::MultiCurrency::remove_lock(lock_iden, order_info.vsbond, &from)?; + // Unreserve the vsbond + let reserved_balance = + T::MultiCurrency::reserved_balance(order_info.vsbond, &order_info.owner); + ensure!(reserved_balance >= order_info.remain, Error::::NotEnoughBalanceToUnreserve); + T::MultiCurrency::unreserve(order_info.vsbond, &order_info.owner, order_info.remain); // Revoke order TotalOrderInfos::::insert( @@ -334,6 +341,10 @@ pub mod module { .checked_mul(&order_info.unit_price) .ok_or(Error::::Overflow)?; + // Check the balance of buyer + T::MultiCurrency::ensure_can_withdraw(T::InvoicingCurrency::get(), &buyer, total_price) + .map_err(|_| Error::::CantPayThePrice)?; + // Get the new OrderInfo let new_order_info = if quantity_clinchd == order_info.remain { OrderInfo { remain: Zero::zero(), order_state: OrderState::Clinchd, ..order_info } @@ -344,17 +355,16 @@ pub mod module { } }; - // Decrease the locked amount of vsbond - let lock_iden = order_id.to_be_bytes(); - T::MultiCurrency::remove_lock(lock_iden, new_order_info.vsbond, &new_order_info.owner)?; - T::MultiCurrency::set_lock( - lock_iden, + // Unreserve the balance of vsbond to transfer + let reserved_balance = + T::MultiCurrency::reserved_balance(new_order_info.vsbond, &new_order_info.owner); + ensure!(reserved_balance >= quantity_clinchd, Error::::NotEnoughBalanceToUnreserve); + T::MultiCurrency::unreserve( new_order_info.vsbond, &new_order_info.owner, - new_order_info.remain, - )?; + quantity_clinchd, + ); - // TODO: Maybe fail if double lock? // Exchange: Transfer vsbond from owner to buyer T::MultiCurrency::transfer( new_order_info.vsbond, diff --git a/pallets/vsbond-auction/src/mock.rs b/pallets/vsbond-auction/src/mock.rs index 8fdd4bf1db..8e5091f11a 100644 --- a/pallets/vsbond-auction/src/mock.rs +++ b/pallets/vsbond-auction/src/mock.rs @@ -25,7 +25,6 @@ use sp_runtime::{ generic, traits::{BlakeTwo256, IdentityLookup}, }; -use vsbond_auction::*; use crate as vsbond_auction; @@ -41,8 +40,8 @@ construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system::{Pallet, Call, Config, Storage, Event}, - OrmlAssets: orml_tokens::{Pallet, Call, Storage, Event}, - VSBondAuction: vsbond_auction::{Pallet, Call, Storage, Event}, + Tokens: orml_tokens::{Pallet, Call, Storage, Event}, + Auction: vsbond_auction::{Pallet, Call, Storage, Event}, } ); @@ -119,10 +118,10 @@ pub(crate) fn new_test_ext() -> sp_io::TestExternalities { orml_tokens::GenesisConfig:: { balances: vec![ - (ACCOUNT_ALICE, TOKEN, BALANCE_TOKEN), - (ACCOUNT_ALICE, VSBOND, BALANCE_VSBOND), - (ACCOUNT_BRUCE, TOKEN, BALANCE_TOKEN), - (ACCOUNT_BRUCE, VSBOND, BALANCE_VSBOND), + (ALICE, TOKEN, 100), + (ALICE, VSBOND, 100), + (BRUCE, TOKEN, 100), + (BRUCE, VSBOND, 100), ], } .assimilate_storage(&mut fs_gc) @@ -131,14 +130,7 @@ pub(crate) fn new_test_ext() -> sp_io::TestExternalities { fs_gc.into() } +pub(crate) const ALICE: AccountId = 1; +pub(crate) const BRUCE: AccountId = 2; pub(crate) const TOKEN: CurrencyId = CurrencyId::Token(TokenSymbol::KSM); -pub(crate) const PARA_ID: ParaId = 3000; -pub(crate) const FIRST_SLOT: LeasePeriod = 0; -pub(crate) const LAST_SLOT: LeasePeriod = 100; -pub(crate) const VSBOND: CurrencyId = - CurrencyId::VSBond(TokenSymbol::KSM, PARA_ID, FIRST_SLOT, LAST_SLOT); -pub(crate) const ACCOUNT_ALICE: AccountId = 1; -pub(crate) const ACCOUNT_BRUCE: AccountId = 2; -pub(crate) const BALANCE_VSBOND: Balance = 1_000; -pub(crate) const BALANCE_TOKEN: Balance = 1_000; -pub(crate) const UNIT_PRICE: Balance = 1; +pub(crate) const VSBOND: CurrencyId = CurrencyId::VSBond(TokenSymbol::KSM, 3000, 13, 20); diff --git a/pallets/vsbond-auction/src/tests.rs b/pallets/vsbond-auction/src/tests.rs index e1e5bf2aea..3ca917f083 100644 --- a/pallets/vsbond-auction/src/tests.rs +++ b/pallets/vsbond-auction/src/tests.rs @@ -18,30 +18,53 @@ #![cfg(test)] -use frame_support::{assert_noop, assert_ok, dispatch::DispatchError}; -use orml_traits::{MultiCurrency, MultiLockableCurrency}; +use frame_support::{assert_noop, assert_ok, dispatch::DispatchError, traits::BalanceStatus}; +use orml_traits::{LockIdentifier, MultiLockableCurrency}; use crate::{mock::*, *}; #[test] fn create_order_should_work() { - let _ = new_test_ext().execute_with(|| -> DispatchResultWithPostInfo { - assert_ok!(VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - BALANCE_VSBOND, - UNIT_PRICE, - )); + new_test_ext().execute_with(|| { + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 100, 1)); - // Check storage - let in_trade_order_ids = - VSBondAuction::in_trade_order_ids(ACCOUNT_ALICE).ok_or(Error::::Unexpected)?; + assert_eq!(Auction::order_id(), 1); + + let in_trade_order_ids = Auction::in_trade_order_ids(ALICE).unwrap(); assert!(in_trade_order_ids.contains(&0)); - assert_eq!(in_trade_order_ids.len(), 1); - Ok(().into()) + assert!(Auction::revoked_order_ids(ALICE).is_none()); + assert!(Auction::clinchd_order_ids(ALICE).is_none()); + + assert!(Auction::order_info(&0).is_some()); + + assert_eq!(Tokens::accounts(ALICE, VSBOND).free, 0); + assert_eq!(Tokens::accounts(ALICE, VSBOND).frozen, 0); + assert_eq!(Tokens::accounts(ALICE, VSBOND).reserved, 100); + }); +} + +#[test] +fn double_create_order_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 50, 1)); + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 50, 1)); + + assert_eq!(Auction::order_id(), 2); + + let in_trade_order_ids = Auction::in_trade_order_ids(ALICE).unwrap(); + assert!(in_trade_order_ids.contains(&0)); + assert!(in_trade_order_ids.contains(&1)); + + assert!(Auction::revoked_order_ids(ALICE).is_none()); + assert!(Auction::clinchd_order_ids(ALICE).is_none()); + + assert!(Auction::order_info(&0).is_some()); + assert!(Auction::order_info(&1).is_some()); + + assert_eq!(Tokens::accounts(ALICE, VSBOND).free, 0); + assert_eq!(Tokens::accounts(ALICE, VSBOND).frozen, 0); + assert_eq!(Tokens::accounts(ALICE, VSBOND).reserved, 100); }); } @@ -49,403 +72,296 @@ fn create_order_should_work() { fn create_order_by_origin_illegal_should_fail() { new_test_ext().execute_with(|| { assert_noop!( - VSBondAuction::create_order( - Origin::root(), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - BALANCE_VSBOND, - UNIT_PRICE, - ), - DispatchError::BadOrigin, + Auction::create_order(Origin::root(), 3000, 13, 20, 100, 1), + DispatchError::BadOrigin ); assert_noop!( - VSBondAuction::create_order( - Origin::none(), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - BALANCE_VSBOND, - UNIT_PRICE, - ), - DispatchError::BadOrigin, + Auction::create_order(Origin::none(), 3000, 13, 20, 100, 1), + DispatchError::BadOrigin ); }); } #[test] -fn create_order_without_enough_currency_should_fail() { +fn create_order_under_minimum_supply_should_fail() { new_test_ext().execute_with(|| { assert_noop!( - VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - BALANCE_VSBOND + 1, - UNIT_PRICE, - ), - orml_tokens::Error::::BalanceTooLow, + Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 0, 1), + Error::::NotEnoughSupply ); }); } #[test] -fn create_order_with_enough_currency_under_lock_should_fail() { +fn create_order_without_enough_vsbond_should_fail() { new_test_ext().execute_with(|| { - assert_ok!(OrmlAssets::extend_lock( - 1u64.to_be_bytes(), - VSBOND, - &ACCOUNT_ALICE, - BALANCE_VSBOND - )); - assert_noop!( - VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - BALANCE_VSBOND, - UNIT_PRICE, - ), - orml_tokens::Error::::LiquidityRestrictions, + Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 1000, 1), + Error::::NotEnoughBalanceToReserve, ); - }); -} -#[test] -fn create_order_should_increase_order_id() { - new_test_ext().execute_with(|| { - for i in 0 .. MaximumOrderInTrade::get() { - assert_ok!(VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - 1, - UNIT_PRICE, - )); - - assert_eq!(VSBondAuction::order_id(), i as u64 + 1); - } + const LOCK_ID: LockIdentifier = 0u64.to_be_bytes(); + assert_ok!(Tokens::set_lock(LOCK_ID, VSBOND, &ALICE, 50)); + assert_noop!( + Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 51, 1), + Error::::NotEnoughBalanceToReserve, + ); }); } #[test] fn create_order_exceed_maximum_order_in_trade_should_fail() { - let _ = new_test_ext().execute_with(|| -> DispatchResultWithPostInfo { + new_test_ext().execute_with(|| { for _ in 0 .. MaximumOrderInTrade::get() { - assert_ok!(VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - 1, - UNIT_PRICE, - )); + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 1, 1)); } assert_noop!( - VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - 1, - UNIT_PRICE, - ), + Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 1, 1), Error::::ExceedMaximumOrderInTrade, ); - - Ok(().into()) }); } #[test] -fn create_order_should_lock_vsbond() { +fn revoke_order_should_work() { new_test_ext().execute_with(|| { - assert_ok!(VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - BALANCE_VSBOND, - UNIT_PRICE, - )); + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 100, 1)); + assert_ok!(Auction::revoke_order(Some(ALICE).into(), 0)); - assert_noop!( - OrmlAssets::ensure_can_withdraw(VSBOND, &ACCOUNT_ALICE, BALANCE_VSBOND), - orml_tokens::Error::::LiquidityRestrictions - ); + assert_eq!(Auction::order_id(), 1); + + let in_trade_order_ids = Auction::in_trade_order_ids(ALICE).unwrap(); + assert!(in_trade_order_ids.is_empty()); + + let revoked_order_ids = Auction::revoked_order_ids(ALICE).unwrap(); + assert!(revoked_order_ids.contains(&0)); + + assert!(Auction::clinchd_order_ids(ALICE).is_none()); + + let order_info = Auction::order_info(0).unwrap(); + assert_eq!(order_info.order_state, OrderState::Revoked); + + assert_eq!(Tokens::accounts(ALICE, VSBOND).free, 100); + assert_eq!(Tokens::accounts(ALICE, VSBOND).frozen, 0); + assert_eq!(Tokens::accounts(ALICE, VSBOND).reserved, 0); }); } #[test] -fn revoke_order_should_work() { - let _ = new_test_ext().execute_with(|| -> DispatchResultWithPostInfo { - assert_ok!(VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - BALANCE_VSBOND, - UNIT_PRICE, - )); +fn revoke_order_which_be_partial_clinchd_should_work() { + new_test_ext().execute_with(|| { + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 50, 1)); + assert_ok!(Auction::partial_clinch_order(Some(BRUCE).into(), 0, 25)); + assert_ok!(Auction::revoke_order(Some(ALICE).into(), 0)); + + assert_eq!(Auction::order_id(), 1); + + let in_trade_order_ids = Auction::in_trade_order_ids(ALICE).unwrap(); + assert!(in_trade_order_ids.is_empty()); - assert_ok!(VSBondAuction::revoke_order(Origin::signed(ACCOUNT_ALICE), 0,)); + let revoked_order_ids = Auction::revoked_order_ids(ALICE).unwrap(); + assert!(revoked_order_ids.contains(&0)); - let in_trade_order_ids = - VSBondAuction::in_trade_order_ids(ACCOUNT_ALICE).ok_or(Error::::Unexpected)?; - assert!(in_trade_order_ids.len() == 0); - let revoked_order_ids = - VSBondAuction::revoked_order_ids(ACCOUNT_ALICE).ok_or(Error::::Unexpected)?; - assert!(revoked_order_ids.len() == 1 && revoked_order_ids.contains(&0)); + assert!(Auction::clinchd_order_ids(ALICE).is_none()); - Ok(().into()) + let order_info = Auction::order_info(0).unwrap(); + assert_eq!(order_info.order_state, OrderState::Revoked); + assert_eq!(order_info.remain, 25); + + assert_eq!(Tokens::accounts(ALICE, VSBOND).free, 75); + assert_eq!(Tokens::accounts(ALICE, VSBOND).frozen, 0); + assert_eq!(Tokens::accounts(ALICE, VSBOND).reserved, 0); }); } #[test] fn revoke_order_not_exist_should_fail() { new_test_ext().execute_with(|| { + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 50, 1)); assert_noop!( - VSBondAuction::revoke_order(Origin::signed(ACCOUNT_ALICE), 0,), - Error::::NotFindOrderInfo, + Auction::partial_clinch_order(Some(BRUCE).into(), 1, 25), + Error::::NotFindOrderInfo ); }); } #[test] -fn revoke_order_by_origin_illegal_should_fail() { +fn revoke_order_without_enough_reserved_vsbond_should_fail() { new_test_ext().execute_with(|| { - assert_ok!(VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - BALANCE_VSBOND, - UNIT_PRICE, + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 50, 1)); + assert_ok!(Tokens::repatriate_reserved( + VSBOND, + &ALICE, + &BRUCE, + 25, + BalanceStatus::Reserved )); + assert_noop!( + Auction::revoke_order(Some(ALICE).into(), 0), + Error::::NotEnoughBalanceToUnreserve + ); + }); +} - assert_noop!(VSBondAuction::revoke_order(Origin::root(), 0), DispatchError::BadOrigin,); +#[test] +fn revoke_order_by_origin_illegal_should_fail() { + new_test_ext().execute_with(|| { + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 50, 1)); assert_noop!( - VSBondAuction::revoke_order(Origin::signed(ACCOUNT_BRUCE), 0), - Error::::ForbidRevokeOrderWithoutOwnership, + Auction::revoke_order(Some(BRUCE).into(), 0), + Error::::ForbidRevokeOrderWithoutOwnership ); - assert_noop!(VSBondAuction::revoke_order(Origin::none(), 0), DispatchError::BadOrigin,); + assert_noop!(Auction::revoke_order(Origin::root(), 0), DispatchError::BadOrigin); + assert_noop!(Auction::revoke_order(Origin::none(), 0), DispatchError::BadOrigin); }); } #[test] fn revoke_order_not_in_trade_should_fail() { new_test_ext().execute_with(|| { - assert_ok!(VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - BALANCE_VSBOND / 2, - UNIT_PRICE, - )); - - assert_ok!(VSBondAuction::revoke_order(Origin::signed(ACCOUNT_ALICE), 0),); + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 50, 1)); + assert_ok!(Auction::revoke_order(Some(ALICE).into(), 0)); assert_noop!( - VSBondAuction::revoke_order(Origin::signed(ACCOUNT_ALICE), 0), - Error::::ForbidRevokeOrderNotInTrade, + Auction::revoke_order(Some(ALICE).into(), 0), + Error::::ForbidRevokeOrderNotInTrade ); - assert_ok!(VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - BALANCE_VSBOND / 2, - UNIT_PRICE, - )); - - assert_ok!(VSBondAuction::clinch_order(Origin::signed(ACCOUNT_BRUCE), 1,)); + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 50, 1)); + assert_ok!(Auction::clinch_order(Some(BRUCE).into(), 1)); assert_noop!( - VSBondAuction::revoke_order(Origin::signed(ACCOUNT_ALICE), 1), - Error::::ForbidRevokeOrderNotInTrade, + Auction::revoke_order(Some(ALICE).into(), 1), + Error::::ForbidRevokeOrderNotInTrade ); }); } #[test] -fn revoke_order_should_unlock_vsbond() { +fn partial_clinch_order_should_work() { new_test_ext().execute_with(|| { - assert_ok!(VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - BALANCE_VSBOND, - UNIT_PRICE, - )); - assert_ok!(VSBondAuction::revoke_order(Origin::signed(ACCOUNT_ALICE), 0,)); + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 100, 1)); + assert_ok!(Auction::partial_clinch_order(Some(BRUCE).into(), 0, 25)); - assert_ok!(OrmlAssets::ensure_can_withdraw(VSBOND, &ACCOUNT_ALICE, BALANCE_VSBOND),); - }); -} + assert_eq!(Auction::order_id(), 1); -#[test] -fn clinch_order_should_work() { - let _ = new_test_ext().execute_with(|| -> DispatchResultWithPostInfo { - assert_ok!(VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - BALANCE_VSBOND, - UNIT_PRICE, - )); + let in_trade_order_ids = Auction::in_trade_order_ids(ALICE).unwrap(); + assert!(in_trade_order_ids.contains(&0)); - assert_ok!(VSBondAuction::partial_clinch_order( - Origin::signed(ACCOUNT_BRUCE), - 0, - BALANCE_VSBOND / 2, - )); + assert!(Auction::revoked_order_ids(ALICE).is_none()); + assert!(Auction::clinchd_order_ids(ALICE).is_none()); - // Check remain - let order_info = VSBondAuction::order_info(0).ok_or(Error::::Unexpected)?; - assert_eq!(order_info.remain, BALANCE_VSBOND / 2); + let order_info = Auction::order_info(0).unwrap(); + assert_eq!(order_info.remain, 75); assert_eq!(order_info.order_state, OrderState::InTrade); - assert_ok!(VSBondAuction::clinch_order(Origin::signed(ACCOUNT_BRUCE), 0,)); + assert_eq!(Tokens::accounts(ALICE, VSBOND).free, 0); + assert_eq!(Tokens::accounts(ALICE, VSBOND).frozen, 0); + assert_eq!(Tokens::accounts(ALICE, VSBOND).reserved, 75); - // Check balance - assert_eq!( - OrmlAssets::free_balance(TOKEN, &ACCOUNT_ALICE), - BALANCE_TOKEN.saturating_mul(2) - ); - assert_eq!( - OrmlAssets::free_balance(VSBOND, &ACCOUNT_BRUCE), - BALANCE_VSBOND.saturating_mul(2) - ); + assert_eq!(Tokens::accounts(ALICE, TOKEN).free, 125); + assert_eq!(Tokens::accounts(ALICE, TOKEN).frozen, 0); + assert_eq!(Tokens::accounts(ALICE, TOKEN).reserved, 0); - // Check storage - let order_info = VSBondAuction::order_info(0).ok_or(Error::::Unexpected)?; - assert_eq!(order_info.order_state, OrderState::Clinchd); + assert_eq!(Tokens::accounts(BRUCE, VSBOND).free, 125); + assert_eq!(Tokens::accounts(BRUCE, VSBOND).frozen, 0); + assert_eq!(Tokens::accounts(BRUCE, VSBOND).reserved, 0); + + assert_eq!(Tokens::accounts(BRUCE, TOKEN).free, 75); + assert_eq!(Tokens::accounts(BRUCE, TOKEN).frozen, 0); + assert_eq!(Tokens::accounts(BRUCE, TOKEN).reserved, 0); + + assert_ok!(Auction::partial_clinch_order(Some(BRUCE).into(), 0, 9999999)); + + let in_trade_order_ids = Auction::in_trade_order_ids(ALICE).unwrap(); + assert!(in_trade_order_ids.is_empty()); + + assert!(Auction::revoked_order_ids(ALICE).is_none()); - let in_trade_order_ids = - VSBondAuction::in_trade_order_ids(ACCOUNT_ALICE).ok_or(Error::::Unexpected)?; - assert_eq!(in_trade_order_ids.len(), 0); - let clinchd_order_ids = - VSBondAuction::clinchd_order_ids(ACCOUNT_ALICE).ok_or(Error::::Unexpected)?; - assert_eq!(clinchd_order_ids.len(), 1); + let clinchd_order_ids = Auction::clinchd_order_ids(ALICE).unwrap(); assert!(clinchd_order_ids.contains(&0)); - Ok(().into()) + let order_info = Auction::order_info(0).unwrap(); + assert_eq!(order_info.remain, 0); + assert_eq!(order_info.order_state, OrderState::Clinchd); + + assert_eq!(Tokens::accounts(ALICE, VSBOND).free, 0); + assert_eq!(Tokens::accounts(ALICE, VSBOND).frozen, 0); + assert_eq!(Tokens::accounts(ALICE, VSBOND).reserved, 0); + + assert_eq!(Tokens::accounts(ALICE, TOKEN).free, 200); + assert_eq!(Tokens::accounts(ALICE, TOKEN).frozen, 0); + assert_eq!(Tokens::accounts(ALICE, TOKEN).reserved, 0); + + assert_eq!(Tokens::accounts(BRUCE, VSBOND).free, 200); + assert_eq!(Tokens::accounts(BRUCE, VSBOND).frozen, 0); + assert_eq!(Tokens::accounts(BRUCE, VSBOND).reserved, 0); + + assert_eq!(Tokens::accounts(BRUCE, TOKEN).free, 0); + assert_eq!(Tokens::accounts(BRUCE, TOKEN).frozen, 0); + assert_eq!(Tokens::accounts(BRUCE, TOKEN).reserved, 0); }); } #[test] -fn clinch_order_not_exist_should_fail() { +fn partial_clinch_order_not_exist_should_fail() { new_test_ext().execute_with(|| { + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 100, 1)); + assert_noop!(Auction::clinch_order(Some(BRUCE).into(), 1), Error::::NotFindOrderInfo); assert_noop!( - VSBondAuction::partial_clinch_order( - Origin::signed(ACCOUNT_BRUCE), - 0, - BALANCE_VSBOND / 2, - ), - Error::::NotFindOrderInfo, - ); - - assert_noop!( - VSBondAuction::clinch_order(Origin::signed(ACCOUNT_BRUCE), 0,), - Error::::NotFindOrderInfo, + Auction::partial_clinch_order(Some(BRUCE).into(), 1, 50), + Error::::NotFindOrderInfo ); }); } #[test] -fn clinck_order_by_origin_illegal_should_fail() { +fn clinch_order_by_origin_illegal_should_fail() { new_test_ext().execute_with(|| { - assert_ok!(VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - BALANCE_VSBOND, - UNIT_PRICE, - )); - + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 100, 1)); assert_noop!( - VSBondAuction::partial_clinch_order(Origin::root(), 0, BALANCE_VSBOND / 2), - DispatchError::BadOrigin + Auction::clinch_order(Some(ALICE).into(), 0), + Error::::ForbidClinchOrderWithinOwnership ); assert_noop!( - VSBondAuction::partial_clinch_order( - Origin::signed(ACCOUNT_ALICE), - 0, - BALANCE_VSBOND / 2 - ), + Auction::partial_clinch_order(Some(ALICE).into(), 0, 50), Error::::ForbidClinchOrderWithinOwnership ); + assert_noop!( - VSBondAuction::partial_clinch_order(Origin::none(), 0, BALANCE_VSBOND / 2), - DispatchError::BadOrigin + Auction::partial_clinch_order(Origin::root(), 0, 50), + DispatchError::BadOrigin, ); - - assert_noop!(VSBondAuction::clinch_order(Origin::root(), 0), DispatchError::BadOrigin); assert_noop!( - VSBondAuction::clinch_order(Origin::signed(ACCOUNT_ALICE), 0,), - Error::::ForbidClinchOrderWithinOwnership + Auction::partial_clinch_order(Origin::none(), 0, 50), + DispatchError::BadOrigin, ); - assert_noop!(VSBondAuction::clinch_order(Origin::none(), 0), DispatchError::BadOrigin); }); } #[test] fn clinch_order_not_in_trade_should_fail() { new_test_ext().execute_with(|| { - assert_ok!(VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - BALANCE_VSBOND / 2, - UNIT_PRICE, - )); - assert_ok!(VSBondAuction::revoke_order(Origin::signed(ACCOUNT_ALICE), 0,)); + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 100, 1)); + assert_ok!(Auction::revoke_order(Some(ALICE).into(), 0)); assert_noop!( - VSBondAuction::clinch_order(Origin::signed(ACCOUNT_BRUCE), 0), + Auction::partial_clinch_order(Some(BRUCE).into(), 0, 50), Error::::ForbidClinchOrderNotInTrade ); - assert_ok!(VSBondAuction::create_order( - Origin::signed(ACCOUNT_ALICE), - PARA_ID, - FIRST_SLOT, - LAST_SLOT, - BALANCE_VSBOND / 2, - UNIT_PRICE, - )); - assert_ok!(VSBondAuction::clinch_order(Origin::signed(ACCOUNT_BRUCE), 1,)); + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 100, 1)); + assert_ok!(Auction::clinch_order(Some(BRUCE).into(), 1)); assert_noop!( - VSBondAuction::clinch_order(Origin::signed(ACCOUNT_BRUCE), 1), + Auction::partial_clinch_order(Some(BRUCE).into(), 1, 50), Error::::ForbidClinchOrderNotInTrade ); }); } -// TODO: Weird Err?? -// #[test] -// fn clinch_order_without_enough_currency_expected_should_fail() { -// new_test_ext().execute_with(|| { -// assert_ok!(VSBondAuction::create_order( -// Origin::signed(ACCOUNT_ALICE), -// PARA_ID, -// FIRST_SLOT, -// LAST_SLOT, -// BALANCE_VSBOND, -// UNIT_PRICE + 1, -// )); -// -// assert_noop!( -// VSBondAuction::clinch_order(Origin::signed(ACCOUNT_BRUCE), 0), -// orml_tokens::Error::::BalanceTooLow, -// ); -// }); -// } +#[test] +fn clinch_order_without_enough_token_should_fail() { + new_test_ext().execute_with(|| { + assert_ok!(Auction::create_order(Some(ALICE).into(), 3000, 13, 20, 100, 2)); + assert_ok!(Auction::partial_clinch_order(Some(BRUCE).into(), 0, 50)); + assert_noop!(Auction::clinch_order(Some(BRUCE).into(), 0), Error::::CantPayThePrice); + }); +}