Skip to content

Commit

Permalink
additional changes
Browse files Browse the repository at this point in the history
  • Loading branch information
JuaniRios committed Jul 22, 2024
1 parent 68df862 commit 33e38d6
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 171 deletions.
17 changes: 9 additions & 8 deletions pallets/funding/src/functions/2_evaluation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ impl<T: Config> Pallet<T> {
// * Get variables *
let project_metadata = ProjectsMetadata::<T>::get(project_id).ok_or(Error::<T>::ProjectMetadataNotFound)?;
let mut project_details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectDetailsNotFound)?;

// * Validity checks *
ensure!(project_details.issuer_account == caller, Error::<T>::NotIssuer);
ensure!(!project_details.is_frozen, Error::<T>::ProjectAlreadyFrozen);
ensure!(project_metadata.policy_ipfs_cid.is_some(), Error::<T>::CidNotProvided);

// * Update storage *
project_details.is_frozen = true;

// * Transition Round *
Self::transition_project(
project_id,
Expand Down Expand Up @@ -77,7 +77,8 @@ impl<T: Config> Pallet<T> {

// * Calculate new variables *
let usd_total_amount_bonded = project_details.evaluation_round_info.total_bonded_usd;
let evaluation_target_usd = <T as Config>::EvaluationSuccessThreshold::get() * project_details.fundraising_target_usd;
let evaluation_target_usd =
<T as Config>::EvaluationSuccessThreshold::get() * project_details.fundraising_target_usd;

// Check which logic path to follow
let is_funded = usd_total_amount_bonded >= evaluation_target_usd;
Expand All @@ -86,10 +87,10 @@ impl<T: Config> Pallet<T> {
// Successful path
if is_funded {
return Self::transition_project(
project_id,
project_details,
ProjectStatus::EvaluationRound,
ProjectStatus::AuctionInitializePeriod,
project_id,
project_details,
ProjectStatus::EvaluationRound,
ProjectStatus::AuctionInitializePeriod,
T::AuctionInitializePeriodDuration::get(),
false,
)
Expand Down
15 changes: 6 additions & 9 deletions pallets/funding/src/functions/3_auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ impl<T: Config> Pallet<T> {
// * Get variables *
let project_details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectDetailsNotFound)?;
let project_metadata = ProjectsMetadata::<T>::get(project_id).ok_or(Error::<T>::ProjectMetadataNotFound)?;
let bucket = Buckets::<T>::get(project_id).ok_or(Error::<T>::BucketNotFound)?;
let bucket = Buckets::<T>::get(project_id).ok_or(Error::<T>::BucketNotFound)?;

// * Calculate WAP *
let auction_allocation_size = project_metadata.auction_round_allocation_percentage * project_metadata.total_allocation_size;
let auction_allocation_size =
project_metadata.auction_round_allocation_percentage * project_metadata.total_allocation_size;
let weighted_token_price = bucket.calculate_wap(auction_allocation_size);

// * Update Storage *
Expand Down Expand Up @@ -150,10 +151,7 @@ impl<T: Config> Pallet<T> {

ensure!(ct_amount > Zero::zero(), Error::<T>::TooLow);
ensure!(did != project_details.issuer_did, Error::<T>::ParticipationToOwnProject);
ensure!(
matches!(project_details.status, ProjectStatus::Auction),
Error::<T>::IncorrectRound
);
ensure!(matches!(project_details.status, ProjectStatus::Auction), Error::<T>::IncorrectRound);
ensure!(
project_metadata.participation_currencies.contains(&funding_asset),
Error::<T>::FundingAssetNotAccepted
Expand Down Expand Up @@ -241,8 +239,7 @@ impl<T: Config> Pallet<T> {
ensure!(total_bids_for_project < T::MaxBidsPerProject::get(), Error::<T>::TooManyProjectParticipations);

// * Calculate new variables *
let plmc_bond =
Self::calculate_plmc_bond(ticket_size, multiplier).map_err(|_| Error::<T>::BadMath)?;
let plmc_bond = Self::calculate_plmc_bond(ticket_size, multiplier).map_err(|_| Error::<T>::BadMath)?;
let funding_asset_amount_locked = Self::calculate_funding_asset_amount(ticket_size, funding_asset)?;

let new_bid = BidInfoOf::<T> {
Expand Down
13 changes: 8 additions & 5 deletions pallets/funding/src/functions/4_contribution.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use super::*;

impl<T: Config> Pallet<T> {

/// Buy tokens in the Community Round at the price set in the Bidding Round
///
/// # Arguments
Expand All @@ -24,14 +23,14 @@ impl<T: Config> Pallet<T> {
) -> DispatchResultWithPostInfo {
let mut project_details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectDetailsNotFound)?;
let did_has_winning_bid = DidWithWinningBids::<T>::get(project_id, did.clone());

let remainder_start = match project_details.status {
ProjectStatus::CommunityRound(remainder_start) => remainder_start,
_ => return Err(Error::<T>::IncorrectRound.into()),
};

let now = <frame_system::Pallet<T>>::block_number();
let remainder_started = now > remainder_start;
let remainder_started = now >= remainder_start;
let round_end = project_details.round_duration.end().ok_or(Error::<T>::ImpossibleState)?;
ensure!(!did_has_winning_bid || remainder_started, Error::<T>::UserHasWinningBid);
ensure!(now < round_end, Error::<T>::TooLateForRound);
Expand Down Expand Up @@ -104,7 +103,11 @@ impl<T: Config> Pallet<T> {
caller_existing_contributions.len() < T::MaxContributionsPerUser::get() as usize,
Error::<T>::TooManyUserParticipations
);
ensure!(contributor_ticket_size.usd_ticket_above_minimum_per_participation(ticket_size) || project_details.remaining_contribution_tokens.is_zero(), Error::<T>::TooLow);
ensure!(
contributor_ticket_size.usd_ticket_above_minimum_per_participation(ticket_size) ||
project_details.remaining_contribution_tokens.is_zero(),
Error::<T>::TooLow
);
ensure!(
contributor_ticket_size.usd_ticket_below_maximum_per_did(total_usd_bought_by_did + ticket_size),
Error::<T>::TooHigh
Expand Down
30 changes: 13 additions & 17 deletions pallets/funding/src/functions/5_funding_end.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,29 +65,25 @@ impl<T: Config> Pallet<T> {
};

project_details.evaluation_round_info.evaluators_outcome = evaluator_outcome;

let (next_status, duration, actual_weight) = if funding_ratio <= T::FundingSuccessThreshold::get() {
(
ProjectStatus::FundingFailed,
1u32.into(),
WeightInfoOf::<T>::end_funding_automatically_rejected_evaluators_slashed(1)
)
} else {
(
ProjectStatus::FundingSuccessful,
T::SuccessToSettlementTime::get(),
WeightInfoOf::<T>::end_funding_automatically_accepted_evaluators_rewarded(1,1)
)
(
ProjectStatus::FundingFailed,
1u32.into(),
WeightInfoOf::<T>::end_funding_automatically_rejected_evaluators_slashed(1),
)
} else {
(
ProjectStatus::FundingSuccessful,
T::SuccessToSettlementTime::get(),
WeightInfoOf::<T>::end_funding_automatically_accepted_evaluators_rewarded(1, 1),
)
};

let round_end = now.saturating_add(duration).saturating_sub(One::one());
project_details.round_duration.update(Some(now), Some(round_end));
project_details.status = next_status;

Ok(PostDispatchInfo {
actual_weight: Some(actual_weight),
pays_fee: Pays::Yes,
})
Ok(PostDispatchInfo { actual_weight: Some(actual_weight), pays_fee: Pays::Yes })
}

}
24 changes: 15 additions & 9 deletions pallets/funding/src/functions/6_settlement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use frame_support::{
dispatch::DispatchResult,
ensure,
traits::{
fungible::{MutateHold as FungibleMutateHold, Inspect as FungibleInspect},
fungible::{Inspect as FungibleInspect, MutateHold as FungibleMutateHold},
fungibles::{Inspect, Mutate as FungiblesMutate},
tokens::{Fortitude, Precision, Preservation, Restriction, Provenance, DepositConsequence},
tokens::{DepositConsequence, Fortitude, Precision, Preservation, Provenance, Restriction},
Get,
},
};
Expand Down Expand Up @@ -192,7 +192,7 @@ impl<T: Config> Pallet<T> {
ensure!(T::ContributionTokenCurrency::asset_exists(project_id), Error::<T>::TooEarlyForRound);

let (refund_plmc, refund_funding_asset) = Self::calculate_refund(&bid)?;

let bidder = bid.bidder;
// Calculate the vesting info and add the release schedule
let funding_end_block = project_details.funding_end_block.ok_or(Error::<T>::ImpossibleState)?;
Expand Down Expand Up @@ -222,7 +222,7 @@ impl<T: Config> Pallet<T> {

let new_funding_asset_amount_locked = bid.funding_asset_amount_locked.saturating_sub(refund_funding_asset);
if refund_funding_asset > Zero::zero() {
Self::release_funding_asset(project_id, &bidder, refund_funding_asset , bid.funding_asset)?;
Self::release_funding_asset(project_id, &bidder, refund_funding_asset, bid.funding_asset)?;
}

// Payout the bid funding asset amount to the project account
Expand Down Expand Up @@ -257,14 +257,19 @@ impl<T: Config> Pallet<T> {
/// Calculate the amount of funds the biider should receive back based on the original bid
/// amount and price compared to the final bid amount and price.
fn calculate_refund(bid: &BidInfoOf<T>) -> Result<(BalanceOf<T>, BalanceOf<T>), DispatchError> {
let new_ticket_size =
bid.final_ct_usd_price.checked_mul_int(bid.final_ct_amount).ok_or(Error::<T>::BadMath)?;

let new_ticket_size = bid.final_ct_usd_price.checked_mul_int(bid.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 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);
if T::FundingCurrency::can_deposit(bid.funding_asset.to_assethub_id(), &bid.bidder, refund_funding_asset, Provenance::Extant) != DepositConsequence::Success {
if T::FundingCurrency::can_deposit(
bid.funding_asset.to_assethub_id(),
&bid.bidder,
refund_funding_asset,
Provenance::Extant,
) != DepositConsequence::Success
{
refund_funding_asset = Zero::zero();
}
if T::NativeCurrency::can_deposit(&bid.bidder, refund_plmc, Provenance::Extant) != DepositConsequence::Success {
Expand All @@ -277,7 +282,8 @@ impl<T: Config> Pallet<T> {
pub fn do_settle_failed_bid(bid: BidInfoOf<T>, project_id: ProjectId) -> DispatchResult {
let project_details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectDetailsNotFound)?;
ensure!(
matches!(project_details.status, ProjectStatus::SettlementStarted(FundingOutcome::FundingFailed)) || bid.status == BidStatus::Rejected,
matches!(project_details.status, ProjectStatus::SettlementStarted(FundingOutcome::FundingFailed)) ||
bid.status == BidStatus::Rejected,
Error::<T>::FundingFailedSettlementNotStarted
);

Expand Down
62 changes: 33 additions & 29 deletions pallets/funding/src/functions/misc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ impl<T: Config> Pallet<T> {
T::PalletId::get().into_sub_account_truncating(index.saturating_add(One::one()))
}


pub fn create_bucket_from_metadata(metadata: &ProjectMetadataOf<T>) -> Result<BucketOf<T>, DispatchError> {
let auction_allocation_size = metadata.auction_round_allocation_percentage * metadata.total_allocation_size;
let bucket_delta_amount = Percent::from_percent(10) * auction_allocation_size;
Expand All @@ -36,7 +35,11 @@ impl<T: Config> Pallet<T> {
let plmc_usd_price = T::PriceProvider::get_decimals_aware_price(PLMC_FOREIGN_ID, USD_DECIMALS, PLMC_DECIMALS)
.ok_or(Error::<T>::PriceNotFound)?;
let usd_bond = multiplier.calculate_bonding_requirement::<T>(ticket_size).map_err(|_| Error::<T>::BadMath)?;
plmc_usd_price.reciprocal().ok_or(Error::<T>::BadMath)?.checked_mul_int(usd_bond).ok_or(Error::<T>::BadMath.into())
plmc_usd_price
.reciprocal()
.ok_or(Error::<T>::BadMath)?
.checked_mul_int(usd_bond)
.ok_or(Error::<T>::BadMath.into())
}

pub fn calculate_funding_asset_amount(
Expand All @@ -45,13 +48,12 @@ impl<T: Config> Pallet<T> {
) -> Result<BalanceOf<T>, DispatchError> {
let asset_id = asset_id.to_assethub_id();
let asset_decimals = T::FundingCurrency::decimals(asset_id);
let asset_usd_price =
T::PriceProvider::get_decimals_aware_price(asset_id, USD_DECIMALS, asset_decimals)
.ok_or(Error::<T>::PriceNotFound)?;
let asset_usd_price = T::PriceProvider::get_decimals_aware_price(asset_id, USD_DECIMALS, asset_decimals)
.ok_or(Error::<T>::PriceNotFound)?;
asset_usd_price
.reciprocal()
.and_then(|recip| recip.checked_mul_int(ticket_size))
.ok_or(Error::<T>::BadMath.into())
.reciprocal()
.and_then(|recip| recip.checked_mul_int(ticket_size))
.ok_or(Error::<T>::BadMath.into())
}

// Based on the amount of tokens and price to buy, a desired multiplier, and the type of investor the caller is,
Expand Down Expand Up @@ -113,13 +115,12 @@ impl<T: Config> Pallet<T> {
.partition(|bid| matches!(bid.status, BidStatus::Accepted | BidStatus::PartiallyAccepted(..)));

let accepted_bid_len = accepted_bids.len() as u32;
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)
)
}
).ok_or(Error::<T>::BadMath)?;
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))
})
.ok_or(Error::<T>::BadMath)?;

ProjectsDetails::<T>::mutate(project_id, |maybe_info| -> DispatchResult {
if let Some(info) = maybe_info {
Expand All @@ -134,7 +135,6 @@ impl<T: Config> Pallet<T> {
Ok((accepted_bid_len, rejected_bids.len() as u32))
}


pub fn try_plmc_participation_lock(
who: &T::AccountId,
project_id: ProjectId,
Expand Down Expand Up @@ -248,10 +248,13 @@ impl<T: Config> Pallet<T> {
let project_details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectDetailsNotFound)?;
let total_fee_allocation = Self::calculate_fee_allocation(project_id)?;

// Calculate the percentage of target funding based on available documentation.
// A.K.A variable "Y" in the documentation. We mean it to saturate to 1 even if the ratio is above 1 when funding raised
// is above the target.
let percentage_of_target_funding = Perquintill::from_rational(project_details.funding_amount_reached_usd, project_details.fundraising_target_usd);
// Calculate the percentage of target funding based on available documentation.
// A.K.A variable "Y" in the documentation. We mean it to saturate to 1 even if the ratio is above 1 when funding raised
// is above the target.
let percentage_of_target_funding = Perquintill::from_rational(
project_details.funding_amount_reached_usd,
project_details.fundraising_target_usd,
);

// Calculate rewards.
let evaluator_rewards = percentage_of_target_funding * Perquintill::from_percent(30) * total_fee_allocation;
Expand All @@ -263,7 +266,8 @@ impl<T: Config> Pallet<T> {
let normal_evaluator_total_bonded_usd = project_details.evaluation_round_info.total_bonded_usd;
let early_evaluation_reward_threshold_usd =
T::EvaluationSuccessThreshold::get() * project_details.fundraising_target_usd;
let early_evaluator_total_bonded_usd = normal_evaluator_total_bonded_usd.min(early_evaluation_reward_threshold_usd);
let early_evaluator_total_bonded_usd =
normal_evaluator_total_bonded_usd.min(early_evaluation_reward_threshold_usd);

// Construct the reward information object.
let reward_info = RewardInfo {
Expand All @@ -282,10 +286,11 @@ impl<T: Config> Pallet<T> {
let details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectDetailsNotFound)?;
let total_fee_allocation = Self::calculate_fee_allocation(project_id)?;

// Calculate the percentage of target funding based on available documentation.
// A.K.A variable "Y" in the documentation. We mean it to saturate to 1 even if the ratio is above 1 when funding raised
// is above the target.
let percentage_of_target_funding = Perquintill::from_rational(details.funding_amount_reached_usd, details.fundraising_target_usd);
// Calculate the percentage of target funding based on available documentation.
// A.K.A variable "Y" in the documentation. We mean it to saturate to 1 even if the ratio is above 1 when funding raised
// is above the target.
let percentage_of_target_funding =
Perquintill::from_rational(details.funding_amount_reached_usd, details.fundraising_target_usd);
let inverse_percentage_of_target_funding = Perquintill::from_percent(100) - percentage_of_target_funding;

let liquidity_pools_percentage = Perquintill::from_percent(50);
Expand Down Expand Up @@ -409,15 +414,14 @@ impl<T: Config> Pallet<T> {
let now = <frame_system::Pallet<T>>::block_number();
ensure!(project_details.round_duration.ended(now) || skip_end_check, Error::<T>::TooEarlyForRound);
ensure!(project_details.status == current_round, Error::<T>::IncorrectRound);



let round_end = now.saturating_add(round_duration).saturating_sub(One::one());
project_details.round_duration.update(Some(now), Some(round_end));
project_details.status = next_round;

// * Update storage *
ProjectsDetails::<T>::insert(project_id, project_details);

// TODO: FIX event transmition by either doing it outside function or map ProjectStatus
// -> ProjectPhase
// * Emit events *
Expand Down
12 changes: 2 additions & 10 deletions pallets/funding/src/instantiator/chain_interactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,11 +283,7 @@ impl<
});
}

pub fn creation_assertions(
&mut self,
project_id: ProjectId,
expected_metadata: ProjectMetadataOf<T>,
) {
pub fn creation_assertions(&mut self, project_id: ProjectId, expected_metadata: ProjectMetadataOf<T>) {
let metadata = self.get_project_metadata(project_id);
let details = self.get_project_details(project_id);
let expected_details = ProjectDetailsOf::<T> {
Expand Down Expand Up @@ -675,11 +671,7 @@ impl<
self.advance_time(1u32.into()).unwrap();
let project_details = self.get_project_details(project_id);
assert!(
matches!(
project_details.status,
ProjectStatus::FundingSuccessful |
ProjectStatus::FundingFailed
),
matches!(project_details.status, ProjectStatus::FundingSuccessful | ProjectStatus::FundingFailed),
"Project should be in Finished status"
);
Ok(())
Expand Down
Loading

0 comments on commit 33e38d6

Please sign in to comment.