Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🗑️ Remove unnecessary bid fields #367

Merged
merged 1 commit into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions pallets/funding/src/functions/2_evaluation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ impl<T: Config> Pallet<T> {
project_id: ProjectId,
usd_amount: BalanceOf<T>,
did: Did,
investor_type: InvestorType,
whitelisted_policy: Cid,
) -> DispatchResultWithPostInfo {
// * Get variables *
Expand All @@ -142,15 +141,6 @@ impl<T: Config> Pallet<T> {
ensure!(total_evaluations_count < T::MaxEvaluationsPerProject::get(), Error::<T>::TooManyProjectParticipations);
ensure!(user_evaluations_count < T::MaxEvaluationsPerUser::get(), Error::<T>::TooManyUserParticipations);

// * Calculate new variables *
if investor_type == InvestorType::Retail {
RetailParticipations::<T>::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::<T>::BadMath)?
Expand Down
2 changes: 0 additions & 2 deletions pallets/funding/src/functions/3_auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,6 @@ impl<T: Config> Pallet<T> {
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,
Expand Down
12 changes: 2 additions & 10 deletions pallets/funding/src/functions/4_contribution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,11 @@ impl<T: Config> Pallet<T> {
InvestorType::Retail => project_metadata.contributing_ticket_sizes.retail,
};
let max_multiplier = match investor_type {
InvestorType::Retail => {
RetailParticipations::<T>::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::<T>::PolicyMismatch);
ensure!(multiplier.into() <= max_multiplier && multiplier.into() > 0u8, Error::<T>::ForbiddenMultiplier);
Expand Down
25 changes: 17 additions & 8 deletions pallets/funding/src/functions/6_settlement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,14 +146,17 @@ impl<T: Config> Pallet<T> {
ProjectStatus::SettlementStarted(FundingOutcome::Success) => true,
_ => false,
};
let wap = project_details.weighted_average_price.ok_or(Error::<T>::ImpossibleState)?;

ensure!(
matches!(project_details.status, ProjectStatus::SettlementStarted(..)) || bid.status == BidStatus::Rejected,
Error::<T>::SettlementNotStarted
);

// Return either the full amount to refund if bid is rejected/project failed,
// or a partial amount when the wap > paid price/bid is partially accepted
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)?;
Expand All @@ -173,14 +176,14 @@ impl<T: Config> Pallet<T> {
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,
)?;

Expand All @@ -198,7 +201,8 @@ impl<T: Config> Pallet<T> {
project_id,
account: bid.bidder,
id: bid.id,
ct_amount: bid.final_ct_amount,
final_ct_amount,
final_ct_price,
});

Ok(())
Expand All @@ -209,18 +213,23 @@ impl<T: Config> Pallet<T> {
fn calculate_refund(
bid: &BidInfoOf<T>,
funding_success: bool,
) -> Result<(BalanceOf<T>, BalanceOf<T>), DispatchError> {
wap: PriceOf<T>,
) -> Result<(PriceOf<T>, BalanceOf<T>, BalanceOf<T>, BalanceOf<T>), 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::<T>::BadMath)?;
let final_ct_amount = bid.final_ct_amount();

let new_ticket_size = final_ct_usd_price.checked_mul_int(final_ct_amount).ok_or(Error::<T>::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 refund_plmc = bid.plmc_bond.saturating_sub(new_plmc_bond);
let 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<T>, project_id: ProjectId) -> DispatchResult {
Expand Down
10 changes: 3 additions & 7 deletions pallets/funding/src/functions/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,20 +90,14 @@ impl<T: Config> Pallet<T> {
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::<T>::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::<T>::mutate(project_id, bid.did.clone(), |flag| {
*flag = true;
Expand All @@ -118,7 +112,9 @@ impl<T: Config> Pallet<T> {
let total_auction_allocation_usd: BalanceOf<T> = accepted_bids
.into_iter()
.try_fold(Zero::zero(), |acc: BalanceOf<T>, bid: BidInfoOf<T>| {
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 = bid.final_ct_amount();
final_ct_usd_price.checked_mul_int(final_ct_amount).and_then(|usd_ticket| acc.checked_add(&usd_ticket))
})
.ok_or(Error::<T>::BadMath)?;

Expand Down
3 changes: 1 addition & 2 deletions pallets/funding/src/instantiator/chain_interactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,6 @@ impl<
project_id,
usd_amount,
generate_did_from_account(account),
InvestorType::Professional,
project_policy.clone(),
)
})?;
Expand Down Expand Up @@ -816,7 +815,7 @@ impl<
for bid in bids {
let account = bid.bidder.clone();
assert_eq!(self.execute(|| { Bids::<T>::iter_prefix_values((&project_id, &account)).count() }), 0);
let amount: BalanceOf<T> = if is_successful { bid.final_ct_amount } else { 0u64.into() };
let amount: BalanceOf<T> = bid.final_ct_amount();
self.assert_migration(project_id, account, amount, bid.id, ParticipationType::Bid, is_successful);
}
}
Expand Down
6 changes: 0 additions & 6 deletions pallets/funding/src/instantiator/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -399,12 +399,6 @@ impl<T: Config> BidInfoFilter<T> {
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;
}
Expand Down
11 changes: 4 additions & 7 deletions pallets/funding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -521,10 +521,6 @@ pub mod pallet {
BalanceOf<T>,
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<T: Config> =
StorageMap<_, Blake2_128Concat, Did, BoundedVec<ProjectId, MaxParticipationsForMaxMultiplier>, ValueQuery>;

#[pallet::storage]
pub type UserMigrations<T: Config> = StorageNMap<
Expand Down Expand Up @@ -629,7 +625,8 @@ pub mod pallet {
project_id: ProjectId,
account: AccountIdOf<T>,
id: u32,
ct_amount: BalanceOf<T>,
final_ct_amount: BalanceOf<T>,
final_ct_price: PriceOf<T>,
},
ContributionSettled {
project_id: ProjectId,
Expand Down Expand Up @@ -869,10 +866,10 @@ pub mod pallet {
project_id: ProjectId,
#[pallet::compact] usd_amount: BalanceOf<T>,
) -> DispatchResultWithPostInfo {
let (account, did, investor_type, whitelisted_policy) =
let (account, did, _investor_type, whitelisted_policy) =
T::InvestorOrigin::ensure_origin(origin, &jwt, T::VerifierPublicKey::get())?;

Self::do_evaluate(&account, project_id, usd_amount, did, investor_type, whitelisted_policy)
Self::do_evaluate(&account, project_id, usd_amount, did, whitelisted_policy)
}

#[pallet::call_index(5)]
Expand Down
2 changes: 1 addition & 1 deletion pallets/funding/src/runtime_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ impl<T: Config> Pallet<T> {

pub fn top_bids(project_id: ProjectId, amount: u32) -> Vec<BidInfoOf<T>> {
Bids::<T>::iter_prefix_values((project_id,))
.sorted_by(|a, b| b.final_ct_amount.cmp(&a.final_ct_amount))
.sorted_by(|a, b| b.final_ct_amount().cmp(&a.final_ct_amount()))
.take(amount as usize)
.collect_vec()
}
Expand Down
25 changes: 13 additions & 12 deletions pallets/funding/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,22 +149,14 @@ 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;
}

pub mod storage_types {
use super::*;
use sp_runtime::traits::Zero;

#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo, Serialize, Deserialize)]
pub struct ProjectMetadata<BoundedString, Balance: PartialOrd + Copy, Price: FixedPointNumber, AccountId, Cid> {
Expand Down Expand Up @@ -383,14 +375,23 @@ 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,
pub plmc_bond: Balance,
pub when: BlockNumber,
}
impl<ProjectId, Did, Balance: BalanceT, Price: FixedPointNumber, AccountId, BlockNumber, Multiplier>
BidInfo<ProjectId, Did, Balance, Price, AccountId, BlockNumber, Multiplier>
{
pub fn final_ct_amount(&self) -> Balance {
match self.status {
BidStatus::Accepted => self.original_ct_amount,
BidStatus::PartiallyAccepted(amount) => amount,
_ => Zero::zero(),
}
}
}

impl<
ProjectId: Eq,
Expand Down