From 75c005f4ec162d32925d7571859de91968967f1e Mon Sep 17 00:00:00 2001 From: Juan Ignacio Rios Date: Tue, 30 Jul 2024 12:58:23 +0200 Subject: [PATCH] Remove unnecessary bid fields --- pallets/funding/src/functions/2_evaluation.rs | 9 ------ pallets/funding/src/functions/3_auction.rs | 2 -- .../funding/src/functions/4_contribution.rs | 12 ++------ pallets/funding/src/functions/6_settlement.rs | 29 ++++++++++++++----- pallets/funding/src/functions/misc.rs | 15 +++++----- .../src/instantiator/chain_interactions.rs | 7 ++++- pallets/funding/src/instantiator/types.rs | 6 ---- pallets/funding/src/lib.rs | 7 ++--- pallets/funding/src/runtime_api.rs | 17 ++++++++++- pallets/funding/src/types.rs | 13 +-------- 10 files changed, 56 insertions(+), 61 deletions(-) diff --git a/pallets/funding/src/functions/2_evaluation.rs b/pallets/funding/src/functions/2_evaluation.rs index 76cad32b8..8d811d94d 100644 --- a/pallets/funding/src/functions/2_evaluation.rs +++ b/pallets/funding/src/functions/2_evaluation.rs @@ -142,15 +142,6 @@ impl Pallet { ensure!(total_evaluations_count < T::MaxEvaluationsPerProject::get(), Error::::TooManyProjectParticipations); ensure!(user_evaluations_count < T::MaxEvaluationsPerUser::get(), Error::::TooManyUserParticipations); - // * Calculate new variables * - if investor_type == InvestorType::Retail { - RetailParticipations::::mutate(&did, |project_participations| { - if project_participations.contains(&project_id).not() { - // We don't care if it fails, since it means the user already has access to the max multiplier - let _ = project_participations.try_push(project_id); - } - }); - } let plmc_bond = plmc_usd_price .reciprocal() .ok_or(Error::::BadMath)? diff --git a/pallets/funding/src/functions/3_auction.rs b/pallets/funding/src/functions/3_auction.rs index 664a2e816..f6209527f 100644 --- a/pallets/funding/src/functions/3_auction.rs +++ b/pallets/funding/src/functions/3_auction.rs @@ -252,8 +252,6 @@ impl Pallet { status: BidStatus::YetUnknown, original_ct_amount: ct_amount, original_ct_usd_price: ct_usd_price, - final_ct_amount: ct_amount, - final_ct_usd_price: ct_usd_price, funding_asset, funding_asset_amount_locked, multiplier, diff --git a/pallets/funding/src/functions/4_contribution.rs b/pallets/funding/src/functions/4_contribution.rs index d106353dc..f0e5b0d2b 100644 --- a/pallets/funding/src/functions/4_contribution.rs +++ b/pallets/funding/src/functions/4_contribution.rs @@ -78,19 +78,11 @@ impl Pallet { InvestorType::Retail => project_metadata.contributing_ticket_sizes.retail, }; let max_multiplier = match investor_type { - InvestorType::Retail => { - RetailParticipations::::mutate(&did, |project_participations| { - if project_participations.contains(&project_id).not() { - // We don't care if it fails, since it means the user already has access to the max multiplier - let _ = project_participations.try_push(project_id); - } - retail_max_multiplier_for_participations(project_participations.len() as u8) - }) - }, - + InvestorType::Retail => RETAIL_MAX_MULTIPLIER, InvestorType::Professional => PROFESSIONAL_MAX_MULTIPLIER, InvestorType::Institutional => INSTITUTIONAL_MAX_MULTIPLIER, }; + // * Validity checks * ensure!(project_policy == whitelisted_policy, Error::::PolicyMismatch); ensure!(multiplier.into() <= max_multiplier && multiplier.into() > 0u8, Error::::ForbiddenMultiplier); diff --git a/pallets/funding/src/functions/6_settlement.rs b/pallets/funding/src/functions/6_settlement.rs index 0adfecaf1..6435062a7 100644 --- a/pallets/funding/src/functions/6_settlement.rs +++ b/pallets/funding/src/functions/6_settlement.rs @@ -146,13 +146,16 @@ impl Pallet { ProjectStatus::SettlementStarted(FundingOutcome::Success) => true, _ => false, }; + let wap = project_details.weighted_average_price.ok_or(Error::::ImpossibleState)?; + ensure!( matches!(project_details.status, ProjectStatus::SettlementStarted(..)) || bid.status == BidStatus::Rejected, Error::::SettlementNotStarted ); // Return either the full amount to refund if bid is rejected/project failed, or a partial amount when the wap > paid price - let (refunded_plmc, refunded_funding_asset_amount) = Self::calculate_refund(&bid, funding_success)?; + let (final_ct_price, final_ct_amount, refunded_plmc, refunded_funding_asset_amount) = + Self::calculate_refund(&bid, funding_success, wap)?; Self::release_participation_bond(project_id, &bid.bidder, refunded_plmc)?; Self::release_funding_asset(project_id, &bid.bidder, refunded_funding_asset_amount, bid.funding_asset)?; @@ -172,14 +175,14 @@ impl Pallet { HoldReason::Participation(project_id).into(), )?; - Self::mint_contribution_tokens(project_id, &bid.bidder, bid.final_ct_amount)?; + Self::mint_contribution_tokens(project_id, &bid.bidder, final_ct_amount)?; Self::create_migration( project_id, &bid.bidder, bid.id, ParticipationType::Bid, - bid.final_ct_amount, + final_ct_amount, plmc_vesting_info.duration, )?; @@ -197,7 +200,8 @@ impl Pallet { project_id, account: bid.bidder, id: bid.id, - ct_amount: bid.final_ct_amount, + final_ct_amount, + final_ct_price }); Ok(()) @@ -208,18 +212,27 @@ impl Pallet { fn calculate_refund( bid: &BidInfoOf, funding_success: bool, - ) -> Result<(BalanceOf, BalanceOf), DispatchError> { + wap: PriceOf, + ) -> Result<(PriceOf, BalanceOf, BalanceOf, BalanceOf), DispatchError> { + let final_ct_usd_price = if bid.original_ct_usd_price > wap { wap } else { bid.original_ct_usd_price }; + if bid.status == BidStatus::Rejected || !funding_success { - return Ok((bid.plmc_bond, bid.funding_asset_amount_locked)); + return Ok((final_ct_usd_price, Zero::zero(), bid.plmc_bond, bid.funding_asset_amount_locked)); } - let new_ticket_size = bid.final_ct_usd_price.checked_mul_int(bid.final_ct_amount).ok_or(Error::::BadMath)?; + let final_ct_amount = match bid.status { + BidStatus::Accepted => bid.original_ct_amount, + BidStatus::PartiallyAccepted(amount) => amount, + _ => Zero::zero(), + }; + + let new_ticket_size = final_ct_usd_price.checked_mul_int(final_ct_amount).ok_or(Error::::BadMath)?; let new_plmc_bond = Self::calculate_plmc_bond(new_ticket_size, bid.multiplier)?; let new_funding_asset_amount = Self::calculate_funding_asset_amount(new_ticket_size, bid.funding_asset)?; let mut refund_plmc = bid.plmc_bond.saturating_sub(new_plmc_bond); let mut refund_funding_asset = bid.funding_asset_amount_locked.saturating_sub(new_funding_asset_amount); - Ok((refund_plmc, refund_funding_asset)) + Ok((final_ct_usd_price, final_ct_amount, refund_plmc, refund_funding_asset)) } pub fn do_settle_contribution(contribution: ContributionInfoOf, project_id: ProjectId) -> DispatchResult { diff --git a/pallets/funding/src/functions/misc.rs b/pallets/funding/src/functions/misc.rs index c5edae12d..d39bb4d85 100644 --- a/pallets/funding/src/functions/misc.rs +++ b/pallets/funding/src/functions/misc.rs @@ -90,20 +90,14 @@ impl Pallet { let buyable_amount = auction_allocation_size.saturating_sub(bid_token_amount_sum); if buyable_amount.is_zero() { bid.status = BidStatus::Rejected; - bid.final_ct_amount = Zero::zero(); } else if bid.original_ct_amount <= buyable_amount { - if bid.final_ct_usd_price > wap { - bid.final_ct_usd_price = wap; - } bid_token_amount_sum.saturating_accrue(bid.original_ct_amount); - bid.final_ct_amount = bid.original_ct_amount; bid.status = BidStatus::Accepted; DidWithWinningBids::::mutate(project_id, bid.did.clone(), |flag| { *flag = true; }); } else { bid_token_amount_sum.saturating_accrue(buyable_amount); - bid.final_ct_amount = buyable_amount; bid.status = BidStatus::PartiallyAccepted(buyable_amount); DidWithWinningBids::::mutate(project_id, bid.did.clone(), |flag| { *flag = true; @@ -118,7 +112,14 @@ impl Pallet { let total_auction_allocation_usd: BalanceOf = accepted_bids .into_iter() .try_fold(Zero::zero(), |acc: BalanceOf, bid: BidInfoOf| { - bid.final_ct_usd_price.checked_mul_int(bid.final_ct_amount).and_then(|ticket| acc.checked_add(&ticket)) + let final_ct_usd_price = if bid.original_ct_usd_price > wap { wap } else { bid.original_ct_usd_price }; + let final_ct_amount = match bid.status { + BidStatus::Accepted => bid.original_ct_amount, + BidStatus::PartiallyAccepted(amount) => amount, + _ => Zero::zero(), + }; + + final_ct_usd_price.checked_mul_int(final_ct_amount).and_then(|usd_ticket| acc.checked_add(&usd_ticket)) }) .ok_or(Error::::BadMath)?; diff --git a/pallets/funding/src/instantiator/chain_interactions.rs b/pallets/funding/src/instantiator/chain_interactions.rs index dd0d90198..d820e7280 100644 --- a/pallets/funding/src/instantiator/chain_interactions.rs +++ b/pallets/funding/src/instantiator/chain_interactions.rs @@ -818,7 +818,12 @@ impl< for bid in bids { let account = bid.bidder.clone(); assert_eq!(self.execute(|| { Bids::::iter_prefix_values((&project_id, &account)).count() }), 0); - let amount: BalanceOf = if is_successful { bid.final_ct_amount } else { 0u64.into() }; + let amount: BalanceOf = match bid.status { + BidStatus::Accepted => bid.original_ct_amount, + BidStatus::PartiallyAccepted(amount) => amount, + BidStatus::Rejected => 0u64.into(), + BidStatus::YetUnknown => {panic!("Bid should have a different status than YetUnknown")} + }; self.assert_migration(project_id, account, amount, bid.id, ParticipationType::Bid, is_successful); } } diff --git a/pallets/funding/src/instantiator/types.rs b/pallets/funding/src/instantiator/types.rs index 738c8a720..6ffe55041 100644 --- a/pallets/funding/src/instantiator/types.rs +++ b/pallets/funding/src/instantiator/types.rs @@ -399,12 +399,6 @@ impl BidInfoFilter { if self.original_ct_usd_price.is_some() && self.original_ct_usd_price.unwrap() != bid.original_ct_usd_price { return false; } - if self.final_ct_amount.is_some() && self.final_ct_amount.unwrap() != bid.final_ct_amount { - return false; - } - if self.final_ct_usd_price.is_some() && self.final_ct_usd_price.unwrap() != bid.final_ct_usd_price { - return false; - } if self.funding_asset.is_some() && self.funding_asset.unwrap() != bid.funding_asset { return false; } diff --git a/pallets/funding/src/lib.rs b/pallets/funding/src/lib.rs index 9bf816ca0..6330029c0 100644 --- a/pallets/funding/src/lib.rs +++ b/pallets/funding/src/lib.rs @@ -522,10 +522,6 @@ pub mod pallet { BalanceOf, ValueQuery, >; - #[pallet::storage] - // After 25 participations, the retail user has access to the max multiplier of 10x, so no need to keep tracking it - pub type RetailParticipations = - StorageMap<_, Blake2_128Concat, Did, BoundedVec, ValueQuery>; #[pallet::storage] pub type UserMigrations = StorageNMap< @@ -630,7 +626,8 @@ pub mod pallet { project_id: ProjectId, account: AccountIdOf, id: u32, - ct_amount: BalanceOf, + final_ct_amount: BalanceOf, + final_ct_price: PriceOf, }, ContributionSettled { project_id: ProjectId, diff --git a/pallets/funding/src/runtime_api.rs b/pallets/funding/src/runtime_api.rs index b3627a544..49041f1aa 100644 --- a/pallets/funding/src/runtime_api.rs +++ b/pallets/funding/src/runtime_api.rs @@ -70,7 +70,22 @@ impl Pallet { pub fn top_bids(project_id: ProjectId, amount: u32) -> Vec> { Bids::::iter_prefix_values((project_id,)) - .sorted_by(|a, b| b.final_ct_amount.cmp(&a.final_ct_amount)) + .sorted_by(|a, b| { + let a_final_ct_amount = match a.status { + BidStatus::YetUnknown => {panic!("Something on-chain went very wrong")} + BidStatus::Accepted => {a.original_ct_amount} + BidStatus::Rejected => {Zero::zero()} + BidStatus::PartiallyAccepted(amount) => {amount} + } ; + + let b_final_ct_amount = match b.status { + BidStatus::YetUnknown => {panic!("Something on-chain went very wrong")} + BidStatus::Accepted => {b.original_ct_amount} + BidStatus::Rejected => {Zero::zero()} + BidStatus::PartiallyAccepted(amount) => {amount} + } ; + b_final_ct_amount.cmp(&a_final_ct_amount) + }) .take(amount as usize) .collect_vec() } diff --git a/pallets/funding/src/types.rs b/pallets/funding/src/types.rs index 15aa6f2c2..bc5fe5e8d 100644 --- a/pallets/funding/src/types.rs +++ b/pallets/funding/src/types.rs @@ -149,16 +149,7 @@ pub mod config_types { } } - pub type MaxParticipationsForMaxMultiplier = ConstU32<25>; - pub const fn retail_max_multiplier_for_participations(participations: u8) -> u8 { - match participations { - 0..=2 => 1, - 3..=4 => 2, - 5..=9 => 4, - 10..=24 => 7, - 25..=u8::MAX => 10, - } - } + pub const RETAIL_MAX_MULTIPLIER: u8 = 5u8; pub const PROFESSIONAL_MAX_MULTIPLIER: u8 = 10u8; pub const INSTITUTIONAL_MAX_MULTIPLIER: u8 = 25u8; } @@ -383,8 +374,6 @@ pub mod storage_types { #[codec(compact)] pub original_ct_amount: Balance, pub original_ct_usd_price: Price, - pub final_ct_amount: Balance, - pub final_ct_usd_price: Price, pub funding_asset: AcceptedFundingAsset, pub funding_asset_amount_locked: Balance, pub multiplier: Multiplier,