From 16877adb60f8fb3b65ae503cf710996f9b3a8f49 Mon Sep 17 00:00:00 2001 From: Juan Ignacio Rios Date: Thu, 19 Sep 2024 12:28:00 +0200 Subject: [PATCH] otm_funding_tests --- Cargo.lock | 1 + integration-tests/src/tests/defaults.rs | 4 +- pallets/funding/src/benchmarking.rs | 51 +-- .../funding/src/instantiator/calculations.rs | 64 ++-- pallets/funding/src/instantiator/tests.rs | 28 +- pallets/funding/src/instantiator/types.rs | 47 +-- pallets/funding/src/tests/2_evaluation.rs | 2 +- pallets/funding/src/tests/3_auction.rs | 133 ++++---- pallets/funding/src/tests/4_contribution.rs | 299 +++++++++++++++++- pallets/funding/src/tests/6_settlement.rs | 41 +-- pallets/funding/src/tests/misc.rs | 30 +- pallets/funding/src/tests/mod.rs | 56 ++-- pallets/funding/src/tests/runtime_api.rs | 16 +- pallets/proxy-bonding/Cargo.toml | 1 + 14 files changed, 527 insertions(+), 246 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aa0bafbe8..a17c304ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7772,6 +7772,7 @@ dependencies = [ "polimec-common", "scale-info", "serde", + "sp-core", "sp-io", "sp-runtime", ] diff --git a/integration-tests/src/tests/defaults.rs b/integration-tests/src/tests/defaults.rs index 3153edce3..c51b86ddf 100644 --- a/integration-tests/src/tests/defaults.rs +++ b/integration-tests/src/tests/defaults.rs @@ -54,7 +54,7 @@ pub fn ipfs_hash() -> BoundedVec> { pub fn default_weights() -> Vec { vec![20u8, 15u8, 10u8, 25u8, 30u8] } -pub fn default_bidder_multipliers() -> Vec { +pub fn default_bidder_modes() -> Vec { vec![1u8, 6u8, 10u8, 8u8, 3u8] } pub fn default_contributor_multipliers() -> Vec { @@ -113,7 +113,7 @@ pub fn default_bids() -> Vec> { default_metadata.minimum_price, default_weights(), default_bidders(), - default_bidder_multipliers(), + default_bidder_modes(), ) } diff --git a/pallets/funding/src/benchmarking.rs b/pallets/funding/src/benchmarking.rs index 59c4f1ebb..10bbbb328 100644 --- a/pallets/funding/src/benchmarking.rs +++ b/pallets/funding/src/benchmarking.rs @@ -126,7 +126,7 @@ where default_project_metadata.minimum_price, default_weights(), default_bidders::(), - default_bidder_multipliers(), + default_bidder_modes(), ) } @@ -145,7 +145,7 @@ where default_project.minimum_price, default_weights(), default_bidders::(), - default_bidder_multipliers(), + default_bidder_modes(), ) } @@ -170,7 +170,7 @@ where default_project_metadata.minimum_price, default_weights(), default_community_contributors::(), - default_community_contributor_multipliers(), + default_community_contributor_modes(), ) } @@ -195,7 +195,7 @@ where 10u128.into(), default_weights(), default_remainder_contributors::(), - default_remainder_contributor_multipliers(), + default_remainder_contributor_modes(), ) } @@ -241,14 +241,17 @@ pub fn default_remainder_contributors() -> Vec> { ] } -pub fn default_bidder_multipliers() -> Vec { - vec![10u8, 3u8, 1u8, 7u8, 4u8] +pub fn default_bidder_modes() -> Vec { + use ParticipationMode::{Classic, OTM}; + vec![Classic(10u8), Classic(3u8), OTM, OTM, Classic(4u8)] } -pub fn default_community_contributor_multipliers() -> Vec { - vec![2u8, 1u8, 3u8, 1u8, 1u8] +pub fn default_community_contributor_modes() -> Vec { + use ParticipationMode::{Classic, OTM}; + vec![Classic(2u8), Classic(1u8), Classic(3u8), OTM, OTM] } -pub fn default_remainder_contributor_multipliers() -> Vec { - vec![1u8, 11u8, 1u8, 1u8, 1u8] +pub fn default_remainder_contributor_modes() -> Vec { + use ParticipationMode::{Classic, OTM}; + vec![Classic(1u8), OTM, Classic(1u8), OTM, Classic(1u8)] } /// Grab an account, seeded by a name and index. @@ -665,7 +668,7 @@ mod benchmarks { let project_id = inst.create_auctioning_project(project_metadata.clone(), issuer, None, evaluations); - let existing_bid = BidParams::new(bidder.clone(), (50 * CT_UNIT).into(), 5u8, AcceptedFundingAsset::USDT); + let existing_bid = BidParams::new(bidder.clone(), (50 * CT_UNIT).into(), ParticipationMode::Classic(5u8), AcceptedFundingAsset::USDT); let existing_bids = vec![existing_bid; x as usize]; let existing_bids_post_bucketing = @@ -708,7 +711,7 @@ mod benchmarks { let current_bucket = Buckets::::get(project_id).unwrap(); // first lets bring the bucket to almost its limit with another bidder: assert!(new_bidder.clone() != bidder.clone()); - let bid_params = BidParams::new(new_bidder, current_bucket.amount_left, 1u8, AcceptedFundingAsset::USDT); + let bid_params = BidParams::new(new_bidder, current_bucket.amount_left, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT); maybe_filler_bid = Some(bid_params.clone()); let plmc_for_new_bidder = inst.calculate_auction_plmc_charged_with_given_price( &vec![bid_params.clone()], @@ -733,7 +736,7 @@ mod benchmarks { ct_amount = bucket_size * (y as u128); usdt_for_filler_bidder = usdt_for_new_bidder; } - let extrinsic_bid = BidParams::new(bidder.clone(), ct_amount, 1u8, AcceptedFundingAsset::USDT); + let extrinsic_bid = BidParams::new(bidder.clone(), ct_amount, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT); let original_extrinsic_bid = extrinsic_bid.clone(); let current_bucket = Buckets::::get(project_id).unwrap(); // we need to call this after bidding `x` amount of times, to get the latest bucket from storage @@ -786,7 +789,7 @@ mod benchmarks { jwt, project_id, original_extrinsic_bid.amount, - original_extrinsic_bid.multiplier, + original_extrinsic_bid.mode, original_extrinsic_bid.asset, ); @@ -803,7 +806,7 @@ mod benchmarks { original_ct_usd_price: Some(price), funding_asset: Some(AcceptedFundingAsset::USDT), funding_asset_amount_locked: None, - multiplier: Some(bid_params.multiplier), + mode: Some(bid_params.mode), plmc_bond: None, when: None, }; @@ -862,11 +865,11 @@ mod benchmarks { Event::::Bid { project_id, ct_amount, - multiplier, .. + mode, .. }, project_id == project_id, ct_amount == bid_params.amount, - multiplier == bid_params.multiplier + mode == bid_params.mode }; assert!(maybe_event.is_some(), "Event not found"); } @@ -917,7 +920,7 @@ mod benchmarks { BidParams::::new( account::>("bidder", 0, i), (min_bid_amount * CT_UNIT).into(), - 1u8, + ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT, ) }) @@ -929,7 +932,7 @@ mod benchmarks { let last_rejected_bid = BidParams::::new( account::>("bidder", 0, 420), auction_allocation - (min_bid_amount * CT_UNIT * (y as u128 - 1u128)), - 1u8, + ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT, ); all_bids.push(last_rejected_bid.clone()); @@ -939,7 +942,7 @@ mod benchmarks { let allocation_bid = BidParams::::new( account::>("bidder", 0, y), auction_allocation, - 1u8, + ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT, ); all_bids.push(allocation_bid); @@ -954,7 +957,7 @@ mod benchmarks { BidParams::::new( account::>("bidder", 0, i), (min_bid_amount * CT_UNIT).into(), - 1u8, + ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT, ) }) @@ -1501,7 +1504,7 @@ mod benchmarks { .map(|_| UserToUSDBalance::new(participant.clone(), (100 * USD_UNIT).into())) .collect_vec(); let participant_bids = (0..max_bids) - .map(|_| BidParams::new(participant.clone(), (500 * CT_UNIT).into(), 1u8, AcceptedFundingAsset::USDT)) + .map(|_| BidParams::new(participant.clone(), (500 * CT_UNIT).into(), ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT)) .collect_vec(); let participant_contributions = (0..max_contributions) .map(|_| { @@ -1843,7 +1846,7 @@ mod benchmarks { .map(|_| UserToUSDBalance::new(participant.clone(), (100 * USD_UNIT).into())) .collect_vec(); let participant_bids = (0..max_bids) - .map(|_| BidParams::new(participant.clone(), (500 * CT_UNIT).into(), 1u8, AcceptedFundingAsset::USDT)) + .map(|_| BidParams::new(participant.clone(), (500 * CT_UNIT).into(), ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT)) .collect_vec(); let participant_contributions = (0..max_contributions) .map(|_| { @@ -1934,7 +1937,7 @@ mod benchmarks { .map(|_| UserToUSDBalance::new(participant.clone(), (100 * USD_UNIT).into())) .collect_vec(); let participant_bids = (0..max_bids) - .map(|_| BidParams::new(participant.clone(), (500 * CT_UNIT).into(), 1u8, AcceptedFundingAsset::USDT)) + .map(|_| BidParams::new(participant.clone(), (500 * CT_UNIT).into(), ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT)) .collect_vec(); let participant_contributions = (0..max_contributions) .map(|_| { diff --git a/pallets/funding/src/instantiator/calculations.rs b/pallets/funding/src/instantiator/calculations.rs index 2eb3cef00..79ea7cde9 100644 --- a/pallets/funding/src/instantiator/calculations.rs +++ b/pallets/funding/src/instantiator/calculations.rs @@ -15,6 +15,10 @@ impl< T::ExistentialDeposit::get() } + pub fn get_funding_asset_ed(&mut self, asset_id: AssetIdOf) -> Balance { + self.execute(|| T::FundingCurrency::minimum_balance(asset_id)) + } + pub fn get_ct_account_deposit(&self) -> Balance { ::ContributionTokenCurrency::deposit_required(One::one()) } @@ -61,7 +65,7 @@ impl< BidParams { bidder: bid.bidder.clone(), amount: bid_amount, - multiplier: bid.multiplier, + mode: bid.mode, asset: bid.asset, }, bucket.current_price, @@ -86,7 +90,8 @@ impl< let mut output = Vec::new(); for bid in bids { let usd_ticket_size = ct_price.saturating_mul_int(bid.amount); - let usd_bond = bid.multiplier.calculate_bonding_requirement::(usd_ticket_size).unwrap(); + let multiplier: MultiplierOf = bid.mode.multiplier().try_into().ok().unwrap(); + let usd_bond = multiplier.calculate_bonding_requirement::(usd_ticket_size).unwrap(); let mut plmc_bond = plmc_usd_price.reciprocal().unwrap().saturating_mul_int(usd_bond); if with_ed { plmc_bond = plmc_bond.saturating_add(self.get_ed()); @@ -111,7 +116,8 @@ impl< for (bid, price) in self.get_actual_price_charged_for_bucketed_bids(bids, project_metadata, maybe_bucket) { let usd_ticket_size = price.saturating_mul_int(bid.amount); - let usd_bond = bid.multiplier.calculate_bonding_requirement::(usd_ticket_size).unwrap(); + let multiplier: MultiplierOf = bid.mode.multiplier().try_into().ok().unwrap(); + let usd_bond = multiplier.calculate_bonding_requirement::(usd_ticket_size).unwrap(); let mut plmc_bond = plmc_usd_price.reciprocal().unwrap().saturating_mul_int(usd_bond); if with_ed { plmc_bond = plmc_bond.saturating_add(self.get_ed()); @@ -147,8 +153,8 @@ impl< for (price_charged, bids) in grouped_by_price_bids { for bid in bids { let charged_usd_ticket_size = price_charged.saturating_mul_int(bid.amount); - let charged_usd_bond = - bid.multiplier.calculate_bonding_requirement::(charged_usd_ticket_size).unwrap(); + let multiplier: MultiplierOf = bid.mode.multiplier().try_into().ok().unwrap(); + let charged_usd_bond = multiplier.calculate_bonding_requirement::(charged_usd_ticket_size).unwrap(); let charged_plmc_bond = plmc_usd_price.reciprocal().unwrap().saturating_mul_int(charged_usd_bond); if remaining_cts <= Zero::zero() { @@ -163,8 +169,9 @@ impl< if weighted_average_price > price_charged { price_charged } else { weighted_average_price }; let actual_usd_ticket_size = final_price.saturating_mul_int(bought_cts); - let actual_usd_bond = - bid.multiplier.calculate_bonding_requirement::(actual_usd_ticket_size).unwrap(); + + let multiplier: MultiplierOf = bid.mode.multiplier().try_into().ok().unwrap(); + let actual_usd_bond = multiplier.calculate_bonding_requirement::(actual_usd_ticket_size).unwrap(); let actual_plmc_bond = plmc_usd_price.reciprocal().unwrap().saturating_mul_int(actual_usd_bond); let returned_plmc_bond = charged_plmc_bond - actual_plmc_bond; @@ -336,7 +343,7 @@ impl< filtered_bids.push(BidParams { bidder: bid.bidder.clone(), amount: total_cts_left, - multiplier: bid.multiplier, + mode: bid.mode, asset: bid.asset, }); total_cts_left = Zero::zero(); @@ -433,7 +440,14 @@ impl< .unwrap() }); let usd_ticket_size = token_usd_price.saturating_mul_int(cont.amount); - let funding_asset_spent = funding_asset_usd_price.reciprocal().unwrap().saturating_mul_int(usd_ticket_size); + let mut funding_asset_spent = + funding_asset_usd_price.reciprocal().unwrap().saturating_mul_int(usd_ticket_size); + if cont.mode == ParticipationMode::OTM { + let multiplier: MultiplierOf = cont.mode.multiplier().try_into().ok().unwrap(); + let plmc_bond = multiplier.calculate_bonding_requirement::(usd_ticket_size).unwrap(); + let otm_fee = >::calculate_fee(plmc_bond, funding_asset_id).unwrap(); + funding_asset_spent += otm_fee; + } output.push(UserToFundingAsset::new(cont.contributor, funding_asset_spent, cont.asset.id())); } output @@ -547,16 +561,16 @@ impl< min_price: PriceOf, weights: Vec, bidders: Vec>, - multipliers: Vec, + modes: Vec, ) -> Vec> { assert_eq!(weights.len(), bidders.len(), "Should have enough weights for all the bidders"); - zip(zip(weights, bidders), multipliers) - .map(|((weight, bidder), multiplier)| { + zip(zip(weights, bidders), modes) + .map(|((weight, bidder), mode)| { let ticket_size = Percent::from_percent(weight) * usd_amount; let token_amount = min_price.reciprocal().unwrap().saturating_mul_int(ticket_size); - BidParams::new(bidder, token_amount, multiplier, AcceptedFundingAsset::USDT) + BidParams::new(bidder, token_amount, mode, AcceptedFundingAsset::USDT) }) .collect() } @@ -567,17 +581,17 @@ impl< percent_funding: u8, weights: Vec, bidders: Vec>, - multipliers: Vec, + modes: Vec, ) -> Vec> { let total_allocation_size = project_metadata.total_allocation_size; let total_ct_bid = Percent::from_percent(percent_funding) * total_allocation_size; assert_eq!(weights.len(), bidders.len(), "Should have enough weights for all the bidders"); - zip(zip(weights, bidders), multipliers) - .map(|((weight, bidder), multiplier)| { + zip(zip(weights, bidders), modes) + .map(|((weight, bidder), mode)| { let token_amount = Percent::from_percent(weight) * total_ct_bid; - BidParams::new(bidder, token_amount, multiplier, AcceptedFundingAsset::USDT) + BidParams::new(bidder, token_amount, mode, AcceptedFundingAsset::USDT) }) .collect() } @@ -588,17 +602,17 @@ impl< final_price: PriceOf, weights: Vec, contributors: Vec>, - multipliers: Vec, + modes: Vec, ) -> Vec> { - zip(zip(weights, contributors), multipliers) - .map(|((weight, bidder), multiplier)| { + zip(zip(weights, contributors), modes) + .map(|((weight, bidder), mode)| { let ticket_size = Percent::from_percent(weight) * usd_amount; let token_amount = final_price.reciprocal().unwrap().saturating_mul_int(ticket_size); ContributionParams::new( bidder, token_amount, - ParticipationMode::Classic(multiplier), + mode, AcceptedFundingAsset::USDT, ) }) @@ -611,20 +625,20 @@ impl< percent_funding: u8, weights: Vec, contributors: Vec>, - multipliers: Vec, + modes: Vec, ) -> Vec> { let total_allocation_size = project_metadata.total_allocation_size; let total_ct_bought = Percent::from_percent(percent_funding) * total_allocation_size; assert_eq!(weights.len(), contributors.len(), "Should have enough weights for all the bidders"); - zip(zip(weights, contributors), multipliers) - .map(|((weight, contributor), multiplier)| { + zip(zip(weights, contributors), modes) + .map(|((weight, contributor), mode)| { let token_amount = Percent::from_percent(weight) * total_ct_bought; ContributionParams::new( contributor, token_amount, - ParticipationMode::Classic(multiplier), + mode, AcceptedFundingAsset::USDT, ) }) diff --git a/pallets/funding/src/instantiator/tests.rs b/pallets/funding/src/instantiator/tests.rs index 91bd80edd..51a88b987 100644 --- a/pallets/funding/src/instantiator/tests.rs +++ b/pallets/funding/src/instantiator/tests.rs @@ -16,12 +16,12 @@ use sp_arithmetic::Percent; fn dry_run_wap() { let mut inst = tests::MockInstantiator::new(Some(RefCell::new(new_test_ext()))); - const ADAM: u32 = 60; - const TOM: u32 = 61; - const SOFIA: u32 = 62; - const FRED: u32 = 63; - const ANNA: u32 = 64; - const DAMIAN: u32 = 65; + const ADAM: AccountIdOf = 60; + const TOM: AccountIdOf = 61; + const SOFIA: AccountIdOf = 62; + const FRED: AccountIdOf = 63; + const ANNA: AccountIdOf = 64; + const DAMIAN: AccountIdOf = 65; let accounts = vec![ADAM, TOM, SOFIA, FRED, ANNA, DAMIAN]; @@ -50,7 +50,7 @@ fn dry_run_wap() { phantom: Default::default(), }, participation_currencies: vec![AcceptedFundingAsset::USDT].try_into().unwrap(), - funding_destination_account: 0u32, + funding_destination_account: 0, policy_ipfs_cid: Some(metadata_hash), }; @@ -98,12 +98,12 @@ fn dry_run_wap() { fn find_bucket_for_wap() { let mut inst = tests::MockInstantiator::new(Some(RefCell::new(new_test_ext()))); - const ADAM: u32 = 60; - const TOM: u32 = 61; - const SOFIA: u32 = 62; - const FRED: u32 = 63; - const ANNA: u32 = 64; - const DAMIAN: u32 = 65; + const ADAM: AccountIdOf = 60; + const TOM: AccountIdOf = 61; + const SOFIA: AccountIdOf = 62; + const FRED: AccountIdOf = 63; + const ANNA: AccountIdOf = 64; + const DAMIAN: AccountIdOf = 65; let accounts = vec![ADAM, TOM, SOFIA, FRED, ANNA, DAMIAN]; @@ -132,7 +132,7 @@ fn find_bucket_for_wap() { phantom: Default::default(), }, participation_currencies: vec![AcceptedFundingAsset::USDT].try_into().unwrap(), - funding_destination_account: 0u32, + funding_destination_account: 0, policy_ipfs_cid: Some(metadata_hash), }; diff --git a/pallets/funding/src/instantiator/types.rs b/pallets/funding/src/instantiator/types.rs index cfe33f5a6..36dafc4ff 100644 --- a/pallets/funding/src/instantiator/types.rs +++ b/pallets/funding/src/instantiator/types.rs @@ -246,57 +246,32 @@ pub struct BidParams { pub asset: AcceptedFundingAsset, } impl BidParams { - pub fn new(bidder: AccountIdOf, amount: Balance, multiplier: u8, asset: AcceptedFundingAsset) -> Self { - Self { bidder, amount, multiplier: multiplier.try_into().map_err(|_| ()).unwrap(), asset } + pub fn new(bidder: AccountIdOf, amount: Balance, mode: ParticipationMode, asset: AcceptedFundingAsset) -> Self { + Self { bidder, amount, mode, asset } } pub fn new_with_defaults(bidder: AccountIdOf, amount: Balance) -> Self { - Self { - bidder, - amount, - multiplier: 1u8.try_into().unwrap_or_else(|_| panic!("multiplier could not be created from 1u8")), - asset: AcceptedFundingAsset::USDT, - } + Self { bidder, amount, mode: ParticipationMode::Classic(1u8), asset: AcceptedFundingAsset::USDT } } } impl From<(AccountIdOf, Balance)> for BidParams { fn from((bidder, amount): (AccountIdOf, Balance)) -> Self { - Self { - bidder, - amount, - multiplier: 1u8.try_into().unwrap_or_else(|_| panic!("multiplier could not be created from 1u8")), - asset: AcceptedFundingAsset::USDT, - } + Self { bidder, amount, mode: ParticipationMode::Classic(1u8), asset: AcceptedFundingAsset::USDT } } } -impl From<(AccountIdOf, Balance, u8)> for BidParams { - fn from((bidder, amount, multiplier): (AccountIdOf, Balance, u8)) -> Self { - Self { - bidder, - amount, - multiplier: multiplier.try_into().unwrap_or_else(|_| panic!("Failed to create multiplier")), - asset: AcceptedFundingAsset::USDT, - } +impl From<(AccountIdOf, Balance, ParticipationMode)> for BidParams { + fn from((bidder, amount, mode): (AccountIdOf, Balance, ParticipationMode)) -> Self { + Self { bidder, amount, mode, asset: AcceptedFundingAsset::USDT } } } -impl From<(AccountIdOf, Balance, u8, AcceptedFundingAsset)> for BidParams { - fn from((bidder, amount, multiplier, asset): (AccountIdOf, Balance, u8, AcceptedFundingAsset)) -> Self { - Self { - bidder, - amount, - multiplier: multiplier.try_into().unwrap_or_else(|_| panic!("Failed to create multiplier")), - asset, - } +impl From<(AccountIdOf, Balance, ParticipationMode, AcceptedFundingAsset)> for BidParams { + fn from((bidder, amount, mode, asset): (AccountIdOf, Balance, ParticipationMode, AcceptedFundingAsset)) -> Self { + Self { bidder, amount, mode, asset } } } impl From<(AccountIdOf, Balance, AcceptedFundingAsset)> for BidParams { fn from((bidder, amount, asset): (AccountIdOf, Balance, AcceptedFundingAsset)) -> Self { - Self { - bidder, - amount, - multiplier: 1u8.try_into().unwrap_or_else(|_| panic!("multiplier could not be created from 1u8")), - asset, - } + Self { bidder, amount, mode: ParticipationMode::Classic(1u8), asset } } } diff --git a/pallets/funding/src/tests/2_evaluation.rs b/pallets/funding/src/tests/2_evaluation.rs index 98c8e9f53..df16a6ede 100644 --- a/pallets/funding/src/tests/2_evaluation.rs +++ b/pallets/funding/src/tests/2_evaluation.rs @@ -764,7 +764,7 @@ mod evaluate_extrinsic { let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext()))); let project_metadata = default_project_metadata(ISSUER_1); let evaluations = (0u32..::MaxEvaluationsPerProject::get()) - .map(|i| UserToUSDBalance::::new(i as u32 + 420u32, (100u128 * CT_UNIT).into())) + .map(|i| UserToUSDBalance::::new(i as u64 + 420, (100u128 * CT_UNIT).into())) .collect_vec(); let failing_evaluation = UserToUSDBalance::new(EVALUATOR_1, 1000 * CT_UNIT); diff --git a/pallets/funding/src/tests/3_auction.rs b/pallets/funding/src/tests/3_auction.rs index 48c9b5521..43fae7825 100644 --- a/pallets/funding/src/tests/3_auction.rs +++ b/pallets/funding/src/tests/3_auction.rs @@ -223,7 +223,7 @@ mod round_flow { ), project_id, min_professional_bid_ct, - 1u8.try_into().unwrap(), + ParticipationMode::Classic(1u8), funding_asset, ))); @@ -262,7 +262,7 @@ mod round_flow { let max_bids_per_project: u32 = ::MaxBidsPerProject::get(); let big_bid: BidParams = (BIDDER_1, total_allocation).into(); let small_bids: Vec> = - (0..max_bids_per_project - 1).map(|i| (i + BIDDER_1, min_bid_ct).into()).collect(); + (0..max_bids_per_project - 1).map(|i| (i as u64 + BIDDER_1, min_bid_ct).into()).collect(); let all_bids = vec![vec![big_bid.clone()], small_bids.clone()].into_iter().flatten().collect_vec(); let mut project_metadata = default_project_metadata(ISSUER_1); @@ -362,7 +362,7 @@ mod bid_extrinsic { let mut evaluations = default_evaluations(); let evaluator_bidder = 69; let evaluation_amount = 420 * USD_UNIT; - let evaluator_bid = BidParams::new(evaluator_bidder, 600 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT); + let evaluator_bid = BidParams::new(evaluator_bidder, 600 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT); evaluations.push((evaluator_bidder, evaluation_amount).into()); let project_id = inst.create_auctioning_project(project_metadata.clone(), issuer, None, evaluations); @@ -436,9 +436,9 @@ mod bid_extrinsic { let evaluations = default_evaluations(); - let usdt_bid = BidParams::new(BIDDER_1, 10_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT); - let usdc_bid = BidParams::new(BIDDER_1, 10_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDC); - let dot_bid = BidParams::new(BIDDER_1, 10_000 * CT_UNIT, 1u8, AcceptedFundingAsset::DOT); + let usdt_bid = BidParams::new(BIDDER_1, 10_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT); + let usdc_bid = BidParams::new(BIDDER_1, 10_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDC); + let dot_bid = BidParams::new(BIDDER_1, 10_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::DOT); let plmc_fundings = inst.calculate_auction_plmc_charged_with_given_price( &vec![usdt_bid.clone(), usdc_bid.clone(), dot_bid.clone()], @@ -514,13 +514,13 @@ mod bid_extrinsic { project_policy, ); let amount = 1000 * CT_UNIT; - let multiplier = Multiplier::force_new(u8_multiplier); + let mode = ParticipationMode::Classic(u8_multiplier); if u8_multiplier > 0 { let bid = BidParams:: { bidder: bidder.clone(), amount, - multiplier, + mode, asset: AcceptedFundingAsset::USDT, }; let min_price = inst.get_project_metadata(project_id).minimum_price; @@ -538,7 +538,7 @@ mod bid_extrinsic { jwt, project_id, amount, - multiplier, + mode, AcceptedFundingAsset::USDT, ) }) @@ -608,7 +608,7 @@ mod bid_extrinsic { 40u8, vec![100], vec![BIDDER_1], - vec![8u8], + vec![ParticipationMode::Classic(8u8)], ); // Note: 5% of total CTs is one bucket, i.e 10% of the auction allocation @@ -620,7 +620,7 @@ mod bid_extrinsic { 23u8, vec![100], vec![BIDDER_2], - vec![7u8], + vec![ParticipationMode::Classic(7u8)], ); let all_bids = vec![bid_40_percent[0].clone(), bid_23_percent[0].clone()]; @@ -696,7 +696,7 @@ mod bid_extrinsic { let project_id = inst.create_auctioning_project(project_metadata.clone(), issuer, None, default_evaluations()); - let bid = BidParams::new(BIDDER_4, 500 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT); + let bid = BidParams::new(BIDDER_4, 500 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT); let plmc_required = inst.calculate_auction_plmc_charged_from_all_bids_made_or_with_bucket( &vec![bid.clone()], project_metadata.clone(), @@ -738,7 +738,7 @@ mod bid_extrinsic { ), project_id, bid.amount, - bid.multiplier, + bid.mode, bid.asset )); }); @@ -777,7 +777,7 @@ mod bid_extrinsic { let project_id = inst.create_auctioning_project(project_metadata.clone(), issuer, None, default_evaluations()); - let bid = BidParams::new(BIDDER_4, 500 * CT_UNIT, 5u8, AcceptedFundingAsset::USDT); + let bid = BidParams::new(BIDDER_4, 500 * CT_UNIT, ParticipationMode::Classic(5u8), AcceptedFundingAsset::USDT); let plmc_required = inst.calculate_auction_plmc_charged_from_all_bids_made_or_with_bucket( &vec![bid.clone()], project_metadata.clone(), @@ -819,7 +819,7 @@ mod bid_extrinsic { ), project_id, bid.amount, - bid.multiplier, + bid.mode, bid.asset )); }); @@ -832,7 +832,7 @@ mod bid_extrinsic { 90u8, default_weights(), default_community_contributors(), - default_multipliers(), + default_modes(), ); let plmc_required = inst.calculate_contributed_plmc_spent(contributions.clone(), wap, false); let plmc_existential_deposits = plmc_required.accounts().existential_deposits(); @@ -900,7 +900,7 @@ mod bid_extrinsic { let mut evaluations = default_evaluations(); let evaluator_bidder = 69; let evaluation_amount = 420 * USD_UNIT; - let evaluator_bid = BidParams::new(evaluator_bidder, 600 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT); + let evaluator_bid = BidParams::new(evaluator_bidder, 600 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT); evaluations.push((evaluator_bidder, evaluation_amount).into()); let project_id = inst.create_auctioning_project(project_metadata.clone(), issuer, None, evaluations); @@ -929,7 +929,7 @@ mod bid_extrinsic { let evaluator_bidder = 69; let evaluation_amount = 420 * USD_UNIT; - let evaluator_bid = BidParams::new(evaluator_bidder, 600 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT); + let evaluator_bid = BidParams::new(evaluator_bidder, 600 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT); evaluations_1.push((evaluator_bidder, evaluation_amount).into()); let _project_id_1 = @@ -971,7 +971,7 @@ mod bid_extrinsic { ), project_id_2, evaluator_bid.amount, - evaluator_bid.multiplier, + evaluator_bid.mode, evaluator_bid.asset ), Error::::ParticipantNotEnoughFunds @@ -993,7 +993,7 @@ mod bid_extrinsic { bidder: BIDDER_2, project_id: 0, ct_amount: 1, - mode: 1u8.try_into().unwrap(), + mode: ParticipationMode::Classic(1u8), funding_asset: AcceptedFundingAsset::USDT, did, investor_type, @@ -1014,8 +1014,7 @@ mod bid_extrinsic { let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), vec![EVALUATOR_1], vec![100u8]); let max_bids_per_project: u32 = ::MaxBidsPerProject::get(); - let bids = - (0u32..max_bids_per_project - 1).map(|i| (i as u32 + 420u32, 5000 * CT_UNIT).into()).collect_vec(); + let bids = (0u32..max_bids_per_project - 1).map(|i| (i as u64 + 420, 5000 * CT_UNIT).into()).collect_vec(); let project_id = inst.create_auctioning_project(project_metadata.clone(), ISSUER_1, None, evaluations); @@ -1038,7 +1037,7 @@ mod bid_extrinsic { // This bid should be split in 2, but the second one should fail, making the whole extrinsic fail and roll back storage let failing_bid = - BidParams::::new(BIDDER_1, remaining_ct + 5000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT); + BidParams::::new(BIDDER_1, remaining_ct + 5000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT); let plmc_for_failing_bid = inst.calculate_auction_plmc_charged_from_all_bids_made_or_with_bucket( &vec![failing_bid.clone()], project_metadata.clone(), @@ -1067,7 +1066,7 @@ mod bid_extrinsic { ), project_id, failing_bid.amount, - failing_bid.multiplier, + failing_bid.mode, failing_bid.asset ), Error::::TooManyProjectParticipations @@ -1086,7 +1085,7 @@ mod bid_extrinsic { ), project_id, remaining_ct, - failing_bid.multiplier, + failing_bid.mode, failing_bid.asset )); }); @@ -1102,7 +1101,7 @@ mod bid_extrinsic { ), project_id, 5000 * CT_UNIT, - failing_bid.multiplier, + failing_bid.mode, failing_bid.asset ), Error::::TooManyProjectParticipations @@ -1143,7 +1142,7 @@ mod bid_extrinsic { // This bid should be split in 2, but the second one should fail, making the whole extrinsic fail and roll back storage let failing_bid = - BidParams::::new(BIDDER_1, remaining_ct + 5000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT); + BidParams::::new(BIDDER_1, remaining_ct + 5000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT); let plmc_for_failing_bid = inst.calculate_auction_plmc_charged_from_all_bids_made_or_with_bucket( &vec![failing_bid.clone()], project_metadata.clone(), @@ -1170,7 +1169,7 @@ mod bid_extrinsic { ), project_id, failing_bid.amount, - failing_bid.multiplier, + failing_bid.mode, failing_bid.asset ), Error::::TooManyUserParticipations @@ -1189,7 +1188,7 @@ mod bid_extrinsic { ), project_id, remaining_ct, - failing_bid.multiplier, + failing_bid.mode, failing_bid.asset )); }); @@ -1205,7 +1204,7 @@ mod bid_extrinsic { ), project_id, 5000 * CT_UNIT, - failing_bid.multiplier, + failing_bid.mode, failing_bid.asset ), Error::::TooManyUserParticipations @@ -1243,7 +1242,7 @@ mod bid_extrinsic { bidder: BIDDER_1, project_id, ct_amount: 799 * CT_UNIT, - mode: 1u8.try_into().unwrap(), + mode: ParticipationMode::Classic(1u8), funding_asset: AcceptedFundingAsset::USDT, did: generate_did_from_account(BIDDER_1), investor_type: InvestorType::Professional, @@ -1259,7 +1258,7 @@ mod bid_extrinsic { bidder: BIDDER_2, project_id, ct_amount: 1999 * CT_UNIT, - mode: 1u8.try_into().unwrap(), + mode: ParticipationMode::Classic(1u8), funding_asset: AcceptedFundingAsset::USDT, did: generate_did_from_account(BIDDER_1), investor_type: InvestorType::Institutional, @@ -1326,7 +1325,7 @@ mod bid_extrinsic { bidder: BIDDER_2, project_id, ct_amount: smallest_ct_amount_at_8k_usd, - mode: 1u8.try_into().unwrap(), + mode: ParticipationMode::Classic(1u8), funding_asset: AcceptedFundingAsset::USDT, did: generate_did_from_account(BIDDER_1), investor_type: InvestorType::Professional, @@ -1345,7 +1344,7 @@ mod bid_extrinsic { bidder: BIDDER_3, project_id, ct_amount: smallest_ct_amount_at_20k_usd, - mode: 1u8.try_into().unwrap(), + mode: ParticipationMode::Classic(1u8), funding_asset: AcceptedFundingAsset::USDT, did: generate_did_from_account(BIDDER_1), investor_type: InvestorType::Institutional, @@ -1407,7 +1406,7 @@ mod bid_extrinsic { bidder_1_jwt, project_id, 8000 * CT_UNIT, - 1u8.try_into().unwrap(), + ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT, )); }); @@ -1418,7 +1417,7 @@ mod bid_extrinsic { bidder_2_jwt_same_did.clone(), project_id, 3000 * CT_UNIT, - 1u8.try_into().unwrap(), + ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT ), Error::::TooHigh @@ -1431,7 +1430,7 @@ mod bid_extrinsic { bidder_2_jwt_same_did, project_id, 2000 * CT_UNIT, - 1u8.try_into().unwrap(), + ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT, )); }); @@ -1455,7 +1454,7 @@ mod bid_extrinsic { bidder_3_jwt, project_id, 40_000 * CT_UNIT, - 1u8.try_into().unwrap(), + ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT, )); }); @@ -1466,7 +1465,7 @@ mod bid_extrinsic { bidder_4_jwt_same_did.clone(), project_id, 11_000 * CT_UNIT, - 1u8.try_into().unwrap(), + ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT, ), Error::::TooHigh @@ -1479,7 +1478,7 @@ mod bid_extrinsic { bidder_4_jwt_same_did, project_id, 10_000 * CT_UNIT, - 1u8.try_into().unwrap(), + ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT, )); }); @@ -1496,7 +1495,7 @@ mod bid_extrinsic { bidder: ISSUER_1, project_id, ct_amount: 5000 * CT_UNIT, - mode: 1u8.try_into().unwrap(), + mode: ParticipationMode::Classic(1u8), funding_asset: AcceptedFundingAsset::USDT, did: generate_did_from_account(ISSUER_1), investor_type: InvestorType::Professional, @@ -1512,7 +1511,7 @@ mod bid_extrinsic { let project_metadata = default_project_metadata(ISSUER_1); let project_id = inst.create_auctioning_project(project_metadata.clone(), ISSUER_1, None, default_evaluations()); - let bids = vec![BidParams::::new(BIDDER_1, 10_000, 1u8, AcceptedFundingAsset::USDC)]; + let bids = vec![BidParams::::new(BIDDER_1, 10_000, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDC)]; let did = generate_did_from_account(bids[0].bidder); let investor_type = InvestorType::Institutional; @@ -1522,7 +1521,7 @@ mod bid_extrinsic { bidder: bids[0].bidder, project_id, ct_amount: bids[0].amount, - mode: bids[0].multiplier, + mode: bids[0].mode, funding_asset: bids[0].asset, did, investor_type, @@ -1551,7 +1550,7 @@ mod bid_extrinsic { ), project_id, 5000 * CT_UNIT, - 1u8.try_into().unwrap(), + ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT ), Error::::PolicyMismatch @@ -1574,12 +1573,12 @@ mod end_auction_extrinsic { // From the knowledge hub: https://hub.polimec.org/learn/calculation-example#auction-round-calculation-example let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext()))); - const ADAM: u32 = 60; - const TOM: u32 = 61; - const SOFIA: u32 = 62; - const FRED: u32 = 63; - const ANNA: u32 = 64; - const DAMIAN: u32 = 65; + const ADAM: AccountIdOf = 60; + const TOM: AccountIdOf = 61; + const SOFIA: AccountIdOf = 62; + const FRED: AccountIdOf = 63; + const ANNA: AccountIdOf = 64; + const DAMIAN: AccountIdOf = 65; let accounts = vec![ADAM, TOM, SOFIA, FRED, ANNA, DAMIAN]; @@ -1688,11 +1687,11 @@ mod end_auction_extrinsic { // We use multiplier > 1 so after settlement, only the refunds defined above are done. The rest will be done // through the linear release pallet - let bid_1 = BidParams::new(BIDDER_1, 5000 * CT_UNIT, 5u8, AcceptedFundingAsset::USDT); - let bid_2 = BidParams::new(BIDDER_2, 40_000 * CT_UNIT, 5u8, AcceptedFundingAsset::USDC); - let bid_3 = BidParams::new(BIDDER_1, 10_000 * CT_UNIT, 5u8, AcceptedFundingAsset::DOT); - let bid_4 = BidParams::new(BIDDER_3, 6000 * CT_UNIT, 5u8, AcceptedFundingAsset::USDT); - let bid_5 = BidParams::new(BIDDER_4, 2000 * CT_UNIT, 5u8, AcceptedFundingAsset::DOT); + let bid_1 = BidParams::new(BIDDER_1, 5000 * CT_UNIT, ParticipationMode::Classic(5u8), AcceptedFundingAsset::USDT); + let bid_2 = BidParams::new(BIDDER_2, 40_000 * CT_UNIT, ParticipationMode::Classic(5u8), AcceptedFundingAsset::USDC); + let bid_3 = BidParams::new(BIDDER_1, 10_000 * CT_UNIT, ParticipationMode::Classic(5u8), AcceptedFundingAsset::DOT); + let bid_4 = BidParams::new(BIDDER_3, 6000 * CT_UNIT, ParticipationMode::Classic(5u8), AcceptedFundingAsset::USDT); + let bid_5 = BidParams::new(BIDDER_4, 2000 * CT_UNIT, ParticipationMode::Classic(5u8), AcceptedFundingAsset::DOT); // post bucketing, the bids look like this: // (BIDDER_1, 5k) - (BIDDER_2, 40k) - (BIDDER_1, 5k) - (BIDDER_1, 5k) - (BIDDER_3 - 5k) - (BIDDER_3 - 1k) - (BIDDER_4 - 2k) // | -------------------- 10USD ----------------------|---- 11 USD ---|---- 12 USD ----|----------- 13 USD -------------| @@ -1801,12 +1800,12 @@ mod end_auction_extrinsic { // From the knowledge hub: https://hub.polimec.org/learn/calculation-example#auction-round-calculation-example let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext()))); - const ADAM: u32 = 60; - const TOM: u32 = 61; - const SOFIA: u32 = 62; - const FRED: u32 = 63; - const ANNA: u32 = 64; - const DAMIAN: u32 = 65; + const ADAM: AccountIdOf = 60; + const TOM: AccountIdOf = 61; + const SOFIA: AccountIdOf = 62; + const FRED: AccountIdOf = 63; + const ANNA: AccountIdOf = 64; + const DAMIAN: AccountIdOf = 65; let accounts = vec![ADAM, TOM, SOFIA, FRED, ANNA, DAMIAN]; let mut project_metadata = default_project_metadata(ISSUER_1); @@ -1840,12 +1839,12 @@ mod end_auction_extrinsic { let project_id = inst.create_auctioning_project(project_metadata, ISSUER_1, None, default_evaluations()); let bids = vec![ - (ADAM, 10_000 * CT_UNIT, 1, AcceptedFundingAsset::USDT).into(), - (TOM, 20_000 * CT_UNIT, 1, AcceptedFundingAsset::USDC).into(), - (SOFIA, 20_000 * CT_UNIT, 1, AcceptedFundingAsset::DOT).into(), - (FRED, 10_000 * CT_UNIT, 1, AcceptedFundingAsset::USDT).into(), - (ANNA, 5_000 * CT_UNIT, 1, AcceptedFundingAsset::USDC).into(), - (DAMIAN, 5_000 * CT_UNIT, 1, AcceptedFundingAsset::DOT).into(), + (ADAM, 10_000 * CT_UNIT, ParticipationMode::Classic(1), AcceptedFundingAsset::USDT).into(), + (TOM, 20_000 * CT_UNIT, ParticipationMode::Classic(1), AcceptedFundingAsset::USDC).into(), + (SOFIA, 20_000 * CT_UNIT, ParticipationMode::Classic(1), AcceptedFundingAsset::DOT).into(), + (FRED, 10_000 * CT_UNIT, ParticipationMode::Classic(1), AcceptedFundingAsset::USDT).into(), + (ANNA, 5_000 * CT_UNIT, ParticipationMode::Classic(1), AcceptedFundingAsset::USDC).into(), + (DAMIAN, 5_000 * CT_UNIT, ParticipationMode::Classic(1), AcceptedFundingAsset::DOT).into(), ]; inst.bid_for_users(project_id, bids).unwrap(); diff --git a/pallets/funding/src/tests/4_contribution.rs b/pallets/funding/src/tests/4_contribution.rs index 983ed0c1e..27d7da0dc 100644 --- a/pallets/funding/src/tests/4_contribution.rs +++ b/pallets/funding/src/tests/4_contribution.rs @@ -332,6 +332,7 @@ mod contribute_extrinsic { #[cfg(test)] mod success { use super::*; + use crate::traits::BondingRequirementCalculation; use frame_support::{dispatch::DispatchResultWithPostInfo, traits::fungible::InspectFreeze}; #[test] @@ -662,7 +663,7 @@ mod contribute_extrinsic { 50, default_weights(), default_bidders(), - default_multipliers(), + default_modes(), ); let project_id = inst.create_community_contributing_project(project_metadata.clone(), ISSUER_1, None, evaluations, bids); @@ -739,8 +740,8 @@ mod contribute_extrinsic { evaluations.push((BIDDER_4, 1337 * USD_UNIT).into()); let successful_bids = vec![ - BidParams::new(BIDDER_1, 400_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), - BidParams::new(BIDDER_2, 100_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_1, 400_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_2, 100_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), ]; // This bids should fill the first bucket. @@ -1005,12 +1006,12 @@ mod contribute_extrinsic { fn participant_was_evaluator_and_bidder() { let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext()))); let issuer = ISSUER_1; - let participant = 42069u32; + let participant = 42069; let project_metadata = default_project_metadata(issuer); let mut evaluations = default_evaluations(); evaluations.push((participant, 100 * USD_UNIT).into()); let mut bids = default_bids(); - bids.push(BidParams::new(participant, 1000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT)); + bids.push(BidParams::new(participant, 1000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT)); let community_contributions = default_community_contributions(); let mut remainder_contributions = default_remainder_contributions(); remainder_contributions.push(ContributionParams::new( @@ -1030,6 +1031,288 @@ mod contribute_extrinsic { remainder_contributions, ); } + + #[test] + fn one_token_mode_contribution_funding_success() { + let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext()))); + let issuer = ISSUER_1; + + let mut project_metadata = default_project_metadata(issuer); + project_metadata.mainnet_token_max_supply = 50_000 * CT_UNIT; + project_metadata.total_allocation_size = 5_000 * CT_UNIT; + project_metadata.minimum_price = ::PriceProvider::calculate_decimals_aware_price( + PriceOf::::from_float(1.0), + USD_DECIMALS, + CT_DECIMALS, + ) + .unwrap(); + + let evaluations = + inst.generate_successful_evaluations(project_metadata.clone(), default_evaluators(), default_weights()); + + let project_id = + inst.create_community_contributing_project(project_metadata.clone(), issuer, None, evaluations, vec![]); + let wap = inst.get_project_details(project_id).weighted_average_price.unwrap(); + let otm_multiplier: MultiplierOf = + ParticipationMode::OTM.multiplier().try_into().ok().unwrap(); + let otm_duration = otm_multiplier.calculate_vesting_duration::(); + + const USDT_ID: u32 = AcceptedFundingAsset::USDT.id(); + const USDT_PARTICIPATION: u128 = 3000 * USDT_UNIT; + + const OTM_USDT_FEE: u128 = 30 * USDT_UNIT; + let usdt_ed = inst.get_funding_asset_ed(AcceptedFundingAsset::USDT.id()); + let required_usdt = UserToFundingAsset::new(BUYER_1, USDT_PARTICIPATION + OTM_USDT_FEE + usdt_ed, USDT_ID); + inst.mint_funding_asset_to(vec![required_usdt.clone()]); + + let ct_participation = inst.execute(|| { + >::funding_asset_to_ct_amount( + project_id, + AcceptedFundingAsset::USDT, + USDT_PARTICIPATION, + ) + }); + /// USDT has the same decimals and price as our baseline USD + let expected_plmc_bond = >::calculate_plmc_bond(USDT_PARTICIPATION, otm_multiplier).unwrap(); + dbg!(&expected_plmc_bond); + let otm_lock_time = otm_multiplier.calculate_vesting_duration::(); + + let otm_escrow_account = + ::RootId::get().into_sub_account_truncating(project_id); + let otm_treasury_account = ::Treasury::get(); + let otm_fee_recipient_account = ::FeeRecipient::get(); + let funding_project_escrow = PolimecFunding::fund_account_id(project_id); + + assert!(funding_project_escrow != otm_escrow_account); + + let pre_participation_treasury_free_plmc = inst.get_free_plmc_balance_for(otm_treasury_account); + let pre_participation_otm_escrow_held_plmc = + inst.get_reserved_plmc_balance_for(otm_escrow_account, HoldReason::Participation.into()); + let pre_participation_otm_escrow_usdt = + inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + let pre_participation_otm_fee_recipient_usdt = + inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); + let pre_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BUYER_1); + + inst.execute(|| { + assert_ok!(PolimecFunding::contribute( + RuntimeOrigin::signed(BUYER_1), + get_mock_jwt_with_cid( + BUYER_1, + InvestorType::Retail, + generate_did_from_account(BUYER_1), + project_metadata.clone().policy_ipfs_cid.unwrap() + ), + project_id, + ct_participation, + ParticipationMode::OTM, + AcceptedFundingAsset::USDT + )); + }); + + let post_participation_treasury_free_plmc = inst.get_free_plmc_balance_for(otm_treasury_account); + let post_participation_otm_escrow_held_plmc = + inst.get_reserved_plmc_balance_for(otm_escrow_account, HoldReason::Participation.into()); + let post_participation_otm_escrow_usdt = + inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + let post_participation_otm_fee_recipient_usdt = + inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); + let post_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BUYER_1); + + assert_eq!( + post_participation_treasury_free_plmc, + pre_participation_treasury_free_plmc - expected_plmc_bond - inst.get_ed() + ); + assert_eq!( + post_participation_otm_escrow_held_plmc, + pre_participation_otm_escrow_held_plmc + expected_plmc_bond + ); + assert_eq!(post_participation_otm_escrow_usdt, pre_participation_otm_escrow_usdt + OTM_USDT_FEE); + assert_eq!(post_participation_otm_fee_recipient_usdt, pre_participation_otm_fee_recipient_usdt); + assert_eq!(post_participation_buyer_usdt, pre_participation_buyer_usdt - USDT_PARTICIPATION - OTM_USDT_FEE); + + assert_eq!(inst.go_to_next_state(project_id), ProjectStatus::FundingSuccessful); + assert_eq!(inst.go_to_next_state(project_id), ProjectStatus::SettlementStarted(FundingOutcome::Success)); + inst.settle_project(project_id, true); + + inst.execute(|| { + assert_ok!(>::transfer_fees_to_recipient( + RuntimeOrigin::signed(BUYER_1), + project_id, + HoldReason::Participation.into(), + USDT_ID + )); + assert_noop!( + >::transfer_bonds_back_to_treasury( + RuntimeOrigin::signed(BUYER_1), + project_id, + HoldReason::Participation.into() + ), + pallet_proxy_bonding::Error::::TooEarlyToUnlock + ); + }); + let now = inst.current_block(); + inst.jump_to_block(otm_duration + now); + inst.execute(|| { + assert_ok!(>::transfer_bonds_back_to_treasury( + RuntimeOrigin::signed(BUYER_1), + project_id, + HoldReason::Participation.into() + )); + }); + + let post_settlement_treasury_free_plmc = inst.get_free_plmc_balance_for(otm_treasury_account); + let post_settlement_otm_escrow_held_plmc = inst.get_free_plmc_balance_for(otm_escrow_account); + let post_settlement_otm_escrow_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + let post_settlement_otm_fee_recipient_usdt = + inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); + let post_settlement_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BUYER_1); + let issuer_funding_account = inst.get_free_funding_asset_balance_for(USDT_ID, issuer); + + assert_eq!(post_settlement_treasury_free_plmc, post_participation_treasury_free_plmc + expected_plmc_bond); + assert_eq!(post_settlement_otm_escrow_held_plmc, inst.get_ed()); + assert_eq!(post_settlement_otm_escrow_usdt, Zero::zero()); + assert_eq!(post_settlement_otm_fee_recipient_usdt, OTM_USDT_FEE); + assert_eq!(post_settlement_buyer_usdt, usdt_ed); + assert_eq!(issuer_funding_account, USDT_PARTICIPATION); + } + + #[test] + fn one_token_mode_contribution_funding_failed() { + let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext()))); + let issuer = ISSUER_1; + + let mut project_metadata = default_project_metadata(issuer); + project_metadata.mainnet_token_max_supply = 50_000 * CT_UNIT; + project_metadata.total_allocation_size = 20_000 * CT_UNIT; + project_metadata.minimum_price = ::PriceProvider::calculate_decimals_aware_price( + PriceOf::::from_float(1.0), + USD_DECIMALS, + CT_DECIMALS, + ) + .unwrap(); + + let evaluations = + inst.generate_successful_evaluations(project_metadata.clone(), default_evaluators(), default_weights()); + + let project_id = + inst.create_community_contributing_project(project_metadata.clone(), issuer, None, evaluations, vec![]); + let wap = inst.get_project_details(project_id).weighted_average_price.unwrap(); + let otm_multiplier: MultiplierOf = + ParticipationMode::OTM.multiplier().try_into().ok().unwrap(); + let otm_duration = otm_multiplier.calculate_vesting_duration::(); + + const USDT_ID: u32 = AcceptedFundingAsset::USDT.id(); + const USDT_PARTICIPATION: u128 = 3000 * USDT_UNIT; + + const OTM_USDT_FEE: u128 = 30 * USDT_UNIT; + let usdt_ed = inst.get_funding_asset_ed(AcceptedFundingAsset::USDT.id()); + let required_usdt = UserToFundingAsset::new(BUYER_1, USDT_PARTICIPATION + OTM_USDT_FEE + usdt_ed, USDT_ID); + inst.mint_funding_asset_to(vec![required_usdt.clone()]); + + let ct_participation = inst.execute(|| { + >::funding_asset_to_ct_amount( + project_id, + AcceptedFundingAsset::USDT, + USDT_PARTICIPATION, + ) + }); + /// USDT has the same decimals and price as our baseline USD + let expected_plmc_bond = >::calculate_plmc_bond(USDT_PARTICIPATION, otm_multiplier).unwrap(); + dbg!(&expected_plmc_bond); + let otm_lock_time = otm_multiplier.calculate_vesting_duration::(); + + let otm_escrow_account = + ::RootId::get().into_sub_account_truncating(project_id); + let otm_treasury_account = ::Treasury::get(); + let otm_fee_recipient_account = ::FeeRecipient::get(); + let funding_project_escrow = PolimecFunding::fund_account_id(project_id); + + assert!(funding_project_escrow != otm_escrow_account); + + let pre_participation_treasury_free_plmc = inst.get_free_plmc_balance_for(otm_treasury_account); + let pre_participation_otm_escrow_held_plmc = + inst.get_reserved_plmc_balance_for(otm_escrow_account, HoldReason::Participation.into()); + let pre_participation_otm_escrow_usdt = + inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + let pre_participation_otm_fee_recipient_usdt = + inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); + let pre_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BUYER_1); + + inst.execute(|| { + assert_ok!(PolimecFunding::contribute( + RuntimeOrigin::signed(BUYER_1), + get_mock_jwt_with_cid( + BUYER_1, + InvestorType::Retail, + generate_did_from_account(BUYER_1), + project_metadata.clone().policy_ipfs_cid.unwrap() + ), + project_id, + ct_participation, + ParticipationMode::OTM, + AcceptedFundingAsset::USDT + )); + }); + + let post_participation_treasury_free_plmc = inst.get_free_plmc_balance_for(otm_treasury_account); + let post_participation_otm_escrow_held_plmc = + inst.get_reserved_plmc_balance_for(otm_escrow_account, HoldReason::Participation.into()); + let post_participation_otm_escrow_usdt = + inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + let post_participation_otm_fee_recipient_usdt = + inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); + let post_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BUYER_1); + + assert_eq!( + post_participation_treasury_free_plmc, + pre_participation_treasury_free_plmc - expected_plmc_bond - inst.get_ed() + ); + assert_eq!( + post_participation_otm_escrow_held_plmc, + pre_participation_otm_escrow_held_plmc + expected_plmc_bond + ); + assert_eq!(post_participation_otm_escrow_usdt, pre_participation_otm_escrow_usdt + OTM_USDT_FEE); + assert_eq!(post_participation_otm_fee_recipient_usdt, pre_participation_otm_fee_recipient_usdt); + assert_eq!(post_participation_buyer_usdt, pre_participation_buyer_usdt - USDT_PARTICIPATION - OTM_USDT_FEE); + + assert_eq!(inst.go_to_next_state(project_id), ProjectStatus::FundingFailed); + assert_eq!(inst.go_to_next_state(project_id), ProjectStatus::SettlementStarted(FundingOutcome::Failure)); + inst.settle_project(project_id, true); + + inst.execute(|| { + assert_noop!( + >::transfer_fees_to_recipient( + RuntimeOrigin::signed(BUYER_1), + project_id, + HoldReason::Participation.into(), + USDT_ID + ), + pallet_proxy_bonding::Error::::FeeToRecipientDisallowed + ); + + assert_ok!(>::transfer_bonds_back_to_treasury( + RuntimeOrigin::signed(BUYER_1), + project_id, + HoldReason::Participation.into() + )); + }); + + let post_settlement_treasury_free_plmc = inst.get_free_plmc_balance_for(otm_treasury_account); + let post_settlement_otm_escrow_held_plmc = inst.get_free_plmc_balance_for(otm_escrow_account); + let post_settlement_otm_escrow_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + let post_settlement_otm_fee_recipient_usdt = + inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); + let post_settlement_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BUYER_1); + let issuer_funding_account = inst.get_free_funding_asset_balance_for(USDT_ID, issuer); + + assert_eq!(post_settlement_treasury_free_plmc, post_participation_treasury_free_plmc + expected_plmc_bond); + assert_eq!(post_settlement_otm_escrow_held_plmc, inst.get_ed()); + assert_eq!(post_settlement_otm_escrow_usdt, Zero::zero()); + assert_eq!(post_settlement_otm_fee_recipient_usdt, Zero::zero()); + assert_eq!(post_settlement_buyer_usdt, usdt_ed + USDT_PARTICIPATION + OTM_USDT_FEE); + assert_eq!(issuer_funding_account, Zero::zero()); + } } #[cfg(test)] @@ -1155,10 +1438,10 @@ mod contribute_extrinsic { let mut evaluations = default_evaluations(); evaluations.push((BIDDER_2, 1337 * USD_UNIT).into()); let bids = vec![ - BidParams::new(BIDDER_1, 400_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), - BidParams::new(BIDDER_2, 50_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_1, 400_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_2, 50_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), // Partially accepted bid. Only the 50k of the second bid will be accepted. - BidParams::new(BIDDER_3, 100_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_3, 100_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), ]; let project_id = inst.create_community_contributing_project( diff --git a/pallets/funding/src/tests/6_settlement.rs b/pallets/funding/src/tests/6_settlement.rs index a0727710b..0f6f52a61 100644 --- a/pallets/funding/src/tests/6_settlement.rs +++ b/pallets/funding/src/tests/6_settlement.rs @@ -171,14 +171,14 @@ mod settle_evaluation_extrinsic { 50, default_weights(), default_bidders(), - default_multipliers(), + default_modes(), ), inst.generate_contributions_from_total_ct_percent( project_metadata.clone(), 50, default_weights(), default_community_contributors(), - default_community_contributor_multipliers(), + default_community_contributor_modes(), ), vec![], ); @@ -255,7 +255,7 @@ mod settle_evaluation_extrinsic { RuntimeOrigin::signed(evaluator), project_id, evaluator, - evaluator - 21 // The First evaluation index is 0, the first evaluator account is 21 + (evaluator - 21) as u32 // The First evaluation index is 0, the first evaluator account is 21 ))); let ct_rewarded = inst.get_ct_asset_balance_for(project_id, evaluator); assert_close_enough!(ct_rewarded, expected_reward, Perquintill::from_float(0.9999)); @@ -396,8 +396,8 @@ mod settle_bid_extrinsic { let auction_allocation = project_metadata.auction_round_allocation_percentage * project_metadata.total_allocation_size; let partial_amount_bid_params = - BidParams::new(BIDDER_1, auction_allocation, 3u8, AcceptedFundingAsset::USDT); - let lower_price_bid_params = BidParams::new(BIDDER_2, 2000 * CT_UNIT, 5u8, AcceptedFundingAsset::DOT); + BidParams::new(BIDDER_1, auction_allocation, ParticipationMode::Classic(3u8), AcceptedFundingAsset::USDT); + let lower_price_bid_params = BidParams::new(BIDDER_2, 2000 * CT_UNIT, ParticipationMode::Classic(5u8), AcceptedFundingAsset::DOT); let bids = vec![partial_amount_bid_params.clone(), lower_price_bid_params.clone()]; let project_id = inst.create_finished_project( @@ -504,7 +504,8 @@ mod settle_bid_extrinsic { inst.assert_migration(project_id, BIDDER_2, 2000 * CT_UNIT, 1, ParticipationType::Bid, true); // Multiplier 5 should be unbonded no earlier than after 8.67 weeks (i.e. 436'867 blocks) - let vesting_time = lower_price_bid_params.multiplier.calculate_vesting_duration::(); + let multiplier: MultiplierOf = lower_price_bid_params.mode.multiplier().try_into().ok().unwrap(); + let vesting_time = multiplier.calculate_vesting_duration::(); // Sanity check, 5 blocks should not be enough inst.advance_time(5u64); @@ -531,7 +532,7 @@ mod settle_bid_extrinsic { let auction_allocation = project_metadata.auction_round_allocation_percentage * project_metadata.total_allocation_size; let no_refund_bid_params = - BidParams::new(BIDDER_1, auction_allocation / 2, 16u8, AcceptedFundingAsset::USDT); + BidParams::new(BIDDER_1, auction_allocation / 2, ParticipationMode::Classic(16u8), AcceptedFundingAsset::USDT); let project_id = inst.create_finished_project( project_metadata.clone(), @@ -572,8 +573,8 @@ mod settle_bid_extrinsic { inst.assert_migration(project_id, BIDDER_1, auction_allocation / 2, 0, ParticipationType::Bid, true); let hold_reason: RuntimeHoldReason = HoldReason::Participation.into(); - - let vesting_time = no_refund_bid_params.multiplier.calculate_vesting_duration::(); + let multiplier: MultiplierOf = no_refund_bid_params.mode.multiplier().try_into().ok().unwrap(); + let vesting_time = multiplier.calculate_vesting_duration::(); // Sanity check, 5 blocks should not be enough inst.advance_time(5u64); @@ -598,8 +599,8 @@ mod settle_bid_extrinsic { let auction_allocation = project_metadata.auction_round_allocation_percentage * project_metadata.total_allocation_size; let partial_amount_bid_params = - BidParams::new(BIDDER_1, auction_allocation, 1u8, AcceptedFundingAsset::USDC); - let lower_price_bid_params = BidParams::new(BIDDER_2, 2000 * CT_UNIT, 5u8, AcceptedFundingAsset::DOT); + BidParams::new(BIDDER_1, auction_allocation, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDC); + let lower_price_bid_params = BidParams::new(BIDDER_2, 2000 * CT_UNIT, ParticipationMode::Classic(5u8), AcceptedFundingAsset::DOT); let bids = vec![partial_amount_bid_params.clone(), lower_price_bid_params.clone()]; let project_id = inst.create_finished_project( @@ -695,7 +696,7 @@ mod settle_bid_extrinsic { let mut project_metadata = default_project_metadata(ISSUER_1); project_metadata.participation_currencies = bounded_vec![AcceptedFundingAsset::USDT, AcceptedFundingAsset::DOT]; - let no_refund_bid_params = BidParams::new(BIDDER_1, 500 * CT_UNIT, 16u8, AcceptedFundingAsset::USDT); + let no_refund_bid_params = BidParams::new(BIDDER_1, 500 * CT_UNIT, ParticipationMode::Classic(16u8), AcceptedFundingAsset::USDT); let project_id = inst.create_finished_project( project_metadata.clone(), @@ -753,8 +754,8 @@ mod settle_bid_extrinsic { bounded_vec![AcceptedFundingAsset::USDT, AcceptedFundingAsset::DOT]; let auction_allocation = project_metadata.auction_round_allocation_percentage * project_metadata.total_allocation_size; - let rejected_bid_params = BidParams::new(BIDDER_1, auction_allocation, 4u8, AcceptedFundingAsset::USDT); - let accepted_bid_params = BidParams::new(BIDDER_2, auction_allocation, 1u8, AcceptedFundingAsset::DOT); + let rejected_bid_params = BidParams::new(BIDDER_1, auction_allocation, ParticipationMode::Classic(4u8), AcceptedFundingAsset::USDT); + let accepted_bid_params = BidParams::new(BIDDER_2, auction_allocation, ParticipationMode::Classic(1u8), AcceptedFundingAsset::DOT); let bids = vec![rejected_bid_params.clone(), accepted_bid_params.clone()]; let project_id = inst.create_community_contributing_project( @@ -810,8 +811,8 @@ mod settle_bid_extrinsic { bounded_vec![AcceptedFundingAsset::USDT, AcceptedFundingAsset::DOT]; let auction_allocation = project_metadata.auction_round_allocation_percentage * project_metadata.total_allocation_size; - let rejected_bid_params = BidParams::new(BIDDER_1, auction_allocation, 4u8, AcceptedFundingAsset::USDT); - let accepted_bid_params = BidParams::new(BIDDER_2, auction_allocation, 1u8, AcceptedFundingAsset::DOT); + let rejected_bid_params = BidParams::new(BIDDER_1, auction_allocation, ParticipationMode::Classic(4u8), AcceptedFundingAsset::USDT); + let accepted_bid_params = BidParams::new(BIDDER_2, auction_allocation, ParticipationMode::Classic(1u8), AcceptedFundingAsset::DOT); let bids = vec![rejected_bid_params.clone(), accepted_bid_params.clone()]; let project_id = inst.create_finished_project( @@ -871,8 +872,8 @@ mod settle_bid_extrinsic { project_metadata.auction_round_allocation_percentage = Percent::from_percent(10); let auction_allocation = project_metadata.auction_round_allocation_percentage * project_metadata.total_allocation_size; - let rejected_bid_params = BidParams::new(BIDDER_1, auction_allocation, 4u8, AcceptedFundingAsset::USDT); - let accepted_bid_params = BidParams::new(BIDDER_2, auction_allocation, 1u8, AcceptedFundingAsset::DOT); + let rejected_bid_params = BidParams::new(BIDDER_1, auction_allocation, ParticipationMode::Classic(4u8), AcceptedFundingAsset::USDT); + let accepted_bid_params = BidParams::new(BIDDER_2, auction_allocation, ParticipationMode::Classic(1u8), AcceptedFundingAsset::DOT); let bids = vec![rejected_bid_params.clone(), accepted_bid_params.clone()]; let project_id = inst.create_finished_project( @@ -1066,14 +1067,14 @@ mod settle_contribution_extrinsic { 10, default_weights(), default_bidders(), - default_multipliers(), + default_modes(), ); let mut community_contributions = inst.generate_contributions_from_total_ct_percent( project_metadata.clone(), 10, default_weights(), default_community_contributors(), - default_community_contributor_multipliers(), + default_community_contributor_modes(), ); let contribution_mul_1 = ContributionParams::::new( diff --git a/pallets/funding/src/tests/misc.rs b/pallets/funding/src/tests/misc.rs index 6594d36ba..7d91f5840 100644 --- a/pallets/funding/src/tests/misc.rs +++ b/pallets/funding/src/tests/misc.rs @@ -66,23 +66,23 @@ mod helper_functions { #[test] fn calculate_evaluation_plmc_spent() { let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext()))); - const EVALUATOR_1: AccountIdOf = 1u32; + const EVALUATOR_1: AccountIdOf = 1; const USD_AMOUNT_1: Balance = 150_000 * USD_UNIT; const EXPECTED_PLMC_AMOUNT_1: f64 = 17_857.1428571428f64; - const EVALUATOR_2: AccountIdOf = 2u32; + const EVALUATOR_2: AccountIdOf = 2; const USD_AMOUNT_2: Balance = 50_000 * USD_UNIT; const EXPECTED_PLMC_AMOUNT_2: f64 = 5_952.3809523809f64; - const EVALUATOR_3: AccountIdOf = 3u32; + const EVALUATOR_3: AccountIdOf = 3; const USD_AMOUNT_3: Balance = 75_000 * USD_UNIT; const EXPECTED_PLMC_AMOUNT_3: f64 = 8_928.5714285714f64; - const EVALUATOR_4: AccountIdOf = 4u32; + const EVALUATOR_4: AccountIdOf = 4; const USD_AMOUNT_4: Balance = 100 * USD_UNIT; const EXPECTED_PLMC_AMOUNT_4: f64 = 11.9047619047f64; - const EVALUATOR_5: AccountIdOf = 5u32; + const EVALUATOR_5: AccountIdOf = 5; // 123.7 USD const USD_AMOUNT_5: Balance = 1237 * USD_UNIT / 10; @@ -139,11 +139,11 @@ mod helper_functions { const CT_AMOUNT_4: u128 = 6000 * CT_UNIT; const CT_AMOUNT_5: u128 = 2000 * CT_UNIT; - let bid_1 = BidParams::new(BIDDER_1, CT_AMOUNT_1, 1u8, AcceptedFundingAsset::USDT); - let bid_2 = BidParams::new(BIDDER_2, CT_AMOUNT_2, 1u8, AcceptedFundingAsset::USDT); - let bid_3 = BidParams::new(BIDDER_1, CT_AMOUNT_3, 1u8, AcceptedFundingAsset::USDT); - let bid_4 = BidParams::new(BIDDER_3, CT_AMOUNT_4, 1u8, AcceptedFundingAsset::USDT); - let bid_5 = BidParams::new(BIDDER_4, CT_AMOUNT_5, 1u8, AcceptedFundingAsset::USDT); + let bid_1 = BidParams::new(BIDDER_1, CT_AMOUNT_1, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT); + let bid_2 = BidParams::new(BIDDER_2, CT_AMOUNT_2, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT); + let bid_3 = BidParams::new(BIDDER_1, CT_AMOUNT_3, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT); + let bid_4 = BidParams::new(BIDDER_3, CT_AMOUNT_4, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT); + let bid_5 = BidParams::new(BIDDER_4, CT_AMOUNT_5, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT); // post bucketing, the bids look like this: // (BIDDER_1, 5k) - (BIDDER_2, 40k) - (BIDDER_1, 5k) - (BIDDER_1, 5k) - (BIDDER_3 - 5k) - (BIDDER_3 - 1k) - (BIDDER_4 - 2k) @@ -246,31 +246,31 @@ mod helper_functions { const PLMC_PRICE: f64 = 8.4f64; const CT_PRICE: f64 = 16.32f64; - const CONTRIBUTOR_1: AccountIdOf = 1u32; + const CONTRIBUTOR_1: AccountIdOf = 1; const TOKEN_AMOUNT_1: u128 = 120 * CT_UNIT; const MULTIPLIER_1: u8 = 1u8; const _TICKET_SIZE_USD_1: u128 = 1_958_4_000_000_000_u128; const EXPECTED_PLMC_AMOUNT_1: f64 = 233.1_428_571_428f64; - const CONTRIBUTOR_2: AccountIdOf = 2u32; + const CONTRIBUTOR_2: AccountIdOf = 2; const TOKEN_AMOUNT_2: u128 = 5023 * CT_UNIT; const MULTIPLIER_2: u8 = 2u8; const _TICKET_SIZE_USD_2: u128 = 81_975_3_600_000_000_u128; const EXPECTED_PLMC_AMOUNT_2: f64 = 4_879.4_857_142_857f64; - const CONTRIBUTOR_3: AccountIdOf = 3u32; + const CONTRIBUTOR_3: AccountIdOf = 3; const TOKEN_AMOUNT_3: u128 = 20_000 * CT_UNIT; const MULTIPLIER_3: u8 = 17u8; const _TICKET_SIZE_USD_3: u128 = 326_400_0_000_000_000_u128; const EXPECTED_PLMC_AMOUNT_3: f64 = 2_285.7_142_857_142f64; - const CONTRIBUTOR_4: AccountIdOf = 4u32; + const CONTRIBUTOR_4: AccountIdOf = 4; const TOKEN_AMOUNT_4: u128 = 1_000_000 * CT_UNIT; const MULTIPLIER_4: u8 = 25u8; const _TICKET_SIZE_4: u128 = 16_320_000_0_000_000_000_u128; const EXPECTED_PLMC_AMOUNT_4: f64 = 77_714.2_857_142_857f64; - const CONTRIBUTOR_5: AccountIdOf = 5u32; + const CONTRIBUTOR_5: AccountIdOf = 5; // 0.1233 CTs const TOKEN_AMOUNT_5: u128 = 1_233 * CT_UNIT / 10_000; const MULTIPLIER_5: u8 = 10u8; diff --git a/pallets/funding/src/tests/mod.rs b/pallets/funding/src/tests/mod.rs index 9aacdbac2..6e67b0a0a 100644 --- a/pallets/funding/src/tests/mod.rs +++ b/pallets/funding/src/tests/mod.rs @@ -198,20 +198,20 @@ pub mod defaults { pub fn default_bids() -> Vec> { vec![ - BidParams::new(BIDDER_1, 400_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), - BidParams::new(BIDDER_2, 50_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_1, 400_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_2, 50_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), ] } pub fn knowledge_hub_bids() -> Vec> { // This should reflect the bidding currency, which currently is USDT vec![ - BidParams::new(BIDDER_1, 10_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), - BidParams::new(BIDDER_2, 20_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), - BidParams::new(BIDDER_3, 20_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), - BidParams::new(BIDDER_4, 10_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), - BidParams::new(BIDDER_5, 5_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), - BidParams::new(BIDDER_6, 5_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_1, 10_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_2, 20_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_3, 20_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_4, 10_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_5, 5_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_6, 5_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), ] } @@ -340,17 +340,21 @@ pub mod defaults { pub fn default_bidders() -> Vec { vec![BIDDER_1, BIDDER_2, BIDDER_3, BIDDER_4, BIDDER_5] } - pub fn default_multipliers() -> Vec { - vec![1u8, 1u8, 1u8, 1u8, 1u8] + pub fn default_modes() -> Vec { + use ParticipationMode::{Classic, OTM}; + vec![Classic(1u8), Classic(1u8), Classic(1u8), OTM, OTM] } - pub fn default_bidder_multipliers() -> Vec { - vec![10u8, 3u8, 8u8, 1u8, 4u8] + pub fn default_bidder_modes() -> Vec { + use ParticipationMode::{Classic, OTM}; + vec![Classic(10u8), OTM, Classic(8u8), OTM, Classic(4u8)] } - pub fn default_community_contributor_multipliers() -> Vec { - vec![1u8, 1u8, 1u8, 1u8, 1u8] + pub fn default_community_contributor_modes() -> Vec { + use ParticipationMode::{Classic, OTM}; + vec![Classic(1u8), Classic(1u8), OTM, Classic(1u8), OTM] } - pub fn default_remainder_contributor_multipliers() -> Vec { - vec![1u8, 1u8, 1u8, 1u8, 1u8] + pub fn default_remainder_contributor_modes() -> Vec { + use ParticipationMode::{Classic, OTM}; + vec![Classic(1u8), Classic(1u8), Classic(1u8), OTM, Classic(1u8)] } pub fn default_community_contributors() -> Vec { @@ -385,14 +389,14 @@ pub mod defaults { min_price, default_weights(), default_bidders(), - default_multipliers(), + default_modes(), ); let contributions = instantiator.generate_contributions_from_total_usd( Percent::from_percent(50u8) * usd_to_reach, min_price, default_weights(), default_community_contributors(), - default_multipliers(), + default_modes(), ); instantiator.create_finished_project(project_metadata, ISSUER_1, None, evaluations, bids, contributions, vec![]) } @@ -406,7 +410,7 @@ pub mod defaults { percent, default_weights(), default_bidders(), - default_bidder_multipliers(), + default_bidder_modes(), ) } @@ -419,7 +423,7 @@ pub mod defaults { percent, default_weights(), default_community_contributors(), - default_community_contributor_multipliers(), + default_community_contributor_modes(), ) } @@ -432,7 +436,7 @@ pub mod defaults { percent, default_weights(), default_remainder_contributors(), - default_remainder_contributor_multipliers(), + default_remainder_contributor_modes(), ) } } @@ -452,14 +456,14 @@ pub fn create_project_with_funding_percentage( min_price, default_weights(), default_bidders(), - default_multipliers(), + default_modes(), ); let contributions = inst.generate_contributions_from_total_usd( Percent::from_percent(50u8) * percentage_funded_usd, min_price, default_weights(), default_community_contributors(), - default_multipliers(), + default_modes(), ); let project_id = inst.create_finished_project(project_metadata, ISSUER_1, None, evaluations, bids, contributions, vec![]); @@ -482,7 +486,7 @@ pub fn create_finished_project_with_usd_raised( usd_raised: Balance, usd_target: Balance, ) -> (MockInstantiator, ProjectId) { - let issuer = inst.get_new_nonce() as u32; + let issuer = inst.get_new_nonce(); let mut project_metadata = default_project_metadata(issuer); project_metadata.total_allocation_size = project_metadata.minimum_price.reciprocal().unwrap().saturating_mul_int(usd_target); @@ -505,7 +509,7 @@ pub fn create_finished_project_with_usd_raised( let evaluations = default_evaluations(); - let bids = inst.generate_bids_that_take_price_to(project_metadata.clone(), required_price, 420, |acc| acc + 1u32); + let bids = inst.generate_bids_that_take_price_to(project_metadata.clone(), required_price, 420, |acc| acc + 1); let project_id = inst.create_community_contributing_project(project_metadata, issuer, None, evaluations, bids); @@ -520,7 +524,7 @@ pub fn create_finished_project_with_usd_raised( wap, default_weights(), default_community_contributors(), - default_multipliers(), + default_modes(), ); let plmc_required = inst.calculate_contributed_plmc_spent(community_contributions.clone(), required_price, true); let usdt_required = inst.calculate_contributed_funding_asset_spent(community_contributions.clone(), required_price); diff --git a/pallets/funding/src/tests/runtime_api.rs b/pallets/funding/src/tests/runtime_api.rs index a2d10a05d..716756be8 100644 --- a/pallets/funding/src/tests/runtime_api.rs +++ b/pallets/funding/src/tests/runtime_api.rs @@ -363,7 +363,7 @@ fn funding_asset_to_ct_amount() { PriceProviderOf::::calculate_decimals_aware_price(new_price, USD_DECIMALS, CT_DECIMALS).unwrap(); let bids = - inst.generate_bids_that_take_price_to(project_metadata_2.clone(), decimal_aware_price, 420u32, |acc| acc + 1); + inst.generate_bids_that_take_price_to(project_metadata_2.clone(), decimal_aware_price, 420, |acc| acc + 1); let project_id_2 = inst.create_community_contributing_project( project_metadata_2.clone(), ISSUER_2, @@ -403,7 +403,7 @@ fn funding_asset_to_ct_amount() { let bids = inst.generate_bids_from_bucket( project_metadata_3.clone(), bucket, - 420u32, + 420, |acc| acc + 1, AcceptedFundingAsset::USDT, ); @@ -478,9 +478,9 @@ fn get_next_vesting_schedule_merge_candidates() { UserToUSDBalance::new(BIDDER_1, 320_000 * USD_UNIT), ]; let bids = vec![ - BidParams::new(BIDDER_1, 50_000 * CT_UNIT, 10u8, AcceptedFundingAsset::USDT), - BidParams::new(BIDDER_1, 400_000 * CT_UNIT, 5u8, AcceptedFundingAsset::USDT), - BidParams::new(BIDDER_2, 50_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_1, 50_000 * CT_UNIT, ParticipationMode::Classic(10u8), AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_1, 400_000 * CT_UNIT, ParticipationMode::Classic(5u8), AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_2, 50_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), ]; let remaining_contributions = vec![ ContributionParams::new(BIDDER_1, 1_000 * CT_UNIT, ParticipationMode::Classic(5u8), AcceptedFundingAsset::USDT), @@ -564,8 +564,8 @@ fn all_project_participations_by_did() { UserToUSDBalance::new(EVALUATOR_3, 320_000 * USD_UNIT), ]; let bids = vec![ - BidParams::new(BIDDER_1, 400_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), - BidParams::new(BIDDER_2, 50_000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_1, 400_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), + BidParams::new(BIDDER_2, 50_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), ]; let community_contributions = vec![ ContributionParams::new(BUYER_1, 50_000 * CT_UNIT, ParticipationMode::Classic(1u8), AcceptedFundingAsset::USDT), @@ -662,7 +662,7 @@ fn all_project_participations_by_did() { jwt, project_id, bid.amount, - bid.multiplier, + bid.mode, bid.asset, ) .unwrap(); diff --git a/pallets/proxy-bonding/Cargo.toml b/pallets/proxy-bonding/Cargo.toml index f7b262e14..b025c7855 100644 --- a/pallets/proxy-bonding/Cargo.toml +++ b/pallets/proxy-bonding/Cargo.toml @@ -21,6 +21,7 @@ polimec-common.workspace = true parity-scale-codec.workspace = true scale-info.workspace = true serde = { workspace = true, features = ["derive"] } +sp-core.workspace = true [dev-dependencies] sp-io.workspace = true