Skip to content

Commit

Permalink
feat(222): starting to write test for <= 33 funding. Need first a new…
Browse files Browse the repository at this point in the history
… PR for FinishedFunding being also a failed project
  • Loading branch information
JuaniRios committed Jul 24, 2023
1 parent 16fe844 commit 0cf9b79
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 16 deletions.
59 changes: 45 additions & 14 deletions polimec-skeleton/pallets/funding/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use super::*;

use crate::traits::{BondingRequirementCalculation, ProvideStatemintPrice};
use frame_support::dispatch::DispatchResult;
use frame_support::traits::fungible::InspectHold;
use frame_support::traits::tokens::{Precision, Preservation};
use frame_support::{
Expand All @@ -32,7 +33,6 @@ use frame_support::{
Get,
},
};
use frame_support::dispatch::DispatchResult;

use sp_arithmetic::Perquintill;

Expand Down Expand Up @@ -655,25 +655,38 @@ impl<T: Config> Pallet<T> {
if funding_ratio <= Perquintill::from_percent(33u64) {
project_details.evaluation_round_info.evaluators_outcome = EvaluatorsOutcome::Slashed(vec![]);
Self::make_project_funding_fail(project_id, project_details, FailureReason::TargetNotReached)

} else if funding_ratio <= Perquintill::from_percent(75u64) {
project_details.evaluation_round_info.evaluators_outcome = EvaluatorsOutcome::Slashed(vec![]);
project_details.status = ProjectStatus::AwaitingProjectDecision;
ProjectsDetails::<T>::insert(project_id, project_details);
Ok(())

} else if funding_ratio < Perquintill::from_percent(90u64) {
project_details.evaluation_round_info.evaluators_outcome = EvaluatorsOutcome::Unchanged;
project_details.status = ProjectStatus::AwaitingProjectDecision;
ProjectsDetails::<T>::insert(project_id, project_details);
Ok(())

} else {
let reward_info = Self::generate_evaluator_rewards_info(project_id)?;
project_details.evaluation_round_info.evaluators_outcome = EvaluatorsOutcome::Rewarded(reward_info);
Self::make_project_funding_successful(project_id, project_details, SuccessReason::ReachedTarget)
}
}

pub fn do_project_decision(project_id: T::ProjectIdentifier, decision: FundingOutcomeDecision) -> DispatchResult {
// * Get variables *
let project_details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectInfoNotFound)?;

// * Update storage *
match decision {
FundingOutcomeDecision::AcceptFunding => {
Self::make_project_funding_successful(project_id, project_details, SuccessReason::ProjectDecision)?;
}
FundingOutcomeDecision::RejectFunding => {
Self::make_project_funding_fail(project_id, project_details, FailureReason::ProjectDecision)?;
}
}

Ok(())
}

/// Called manually by a user extrinsic
Expand Down Expand Up @@ -1173,8 +1186,25 @@ impl<T: Config> Pallet<T> {
Ok(())
}

pub fn do_decide_project_outcome(issuer: AccountIdOf<T>, project_id: T::ProjectIdentifier) -> {
pub fn do_decide_project_outcome(
issuer: AccountIdOf<T>, project_id: T::ProjectIdentifier, decision: FundingOutcomeDecision,
) -> DispatchResult {
// * Get variables *
let project_details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectInfoNotFound)?;
let now = <frame_system::Pallet<T>>::block_number();

// * Validity checks *
ensure!(project_details.issuer == issuer, Error::<T>::NotAllowed);
ensure!(
project_details.status == ProjectStatus::AwaitingProjectDecision,
Error::<T>::NotAllowed
);

// * Update storage *
Self::remove_from_update_store(&project_id)?;
Self::add_to_update_store(now + 1u32.into(), (&project_id, UpdateType::ProjectDecision(decision)));

Ok(())
}

/// Unbond some plmc from a successful bid, after a step in the vesting period has passed.
Expand Down Expand Up @@ -2110,9 +2140,7 @@ impl<T: Config> Pallet<T> {

pub fn generate_evaluator_rewards_info(
project_id: <T as Config>::ProjectIdentifier,
) -> Result<RewardInfoOf<T>,
DispatchError,
> {
) -> Result<RewardInfoOf<T>, DispatchError> {
let project_details = ProjectsDetails::<T>::get(project_id).ok_or(Error::<T>::ProjectNotFound)?;
let evaluation_usd_amounts = Evaluations::<T>::iter_prefix(project_id)
.map(|(evaluator, evaluations)| {
Expand Down Expand Up @@ -2150,7 +2178,8 @@ impl<T: Config> Pallet<T> {
let late_evaluator_total_bonded_usd = evaluation_usd_amounts
.iter()
.fold(BalanceOf::<T>::zero(), |acc, (_, (_, late))| acc.saturating_add(*late));
let normal_evaluator_total_bonded_usd = early_evaluator_total_bonded_usd.saturating_add(late_evaluator_total_bonded_usd);
let normal_evaluator_total_bonded_usd =
early_evaluator_total_bonded_usd.saturating_add(late_evaluator_total_bonded_usd);
Ok(RewardInfo {
early_evaluator_reward_pot_usd,
normal_evaluator_reward_pot_usd,
Expand All @@ -2159,7 +2188,9 @@ impl<T: Config> Pallet<T> {
})
}

pub fn make_project_funding_successful(project_id: T::ProjectIdentifier, mut project_details: ProjectDetailsOf<T>, reason: SuccessReason) -> DispatchResult {
pub fn make_project_funding_successful(
project_id: T::ProjectIdentifier, mut project_details: ProjectDetailsOf<T>, reason: SuccessReason,
) -> DispatchResult {
let project_metadata = ProjectsMetadata::<T>::get(project_id).ok_or(Error::<T>::ProjectNotFound)?;
let token_information = project_metadata.token_information;

Expand All @@ -2176,7 +2207,7 @@ impl<T: Config> Pallet<T> {
token_information.symbol.into(),
token_information.decimals,
)
.map_err(|_| Error::<T>::AssetMetadataUpdateFailed)?;
.map_err(|_| Error::<T>::AssetMetadataUpdateFailed)?;

Self::deposit_event(Event::<T>::FundingEnded {
project_id,
Expand All @@ -2186,7 +2217,9 @@ impl<T: Config> Pallet<T> {
Ok(())
}

pub fn make_project_funding_fail(project_id: T::ProjectIdentifier, mut project_details: ProjectDetailsOf<T>, reason: FailureReason) -> DispatchResult {
pub fn make_project_funding_fail(
project_id: T::ProjectIdentifier, mut project_details: ProjectDetailsOf<T>, reason: FailureReason,
) -> DispatchResult {
project_details.status = ProjectStatus::FundingFailed;
project_details.cleanup = ProjectCleanup::Ready(ProjectFinalizer::Failure(Default::default()));

Expand All @@ -2198,6 +2231,4 @@ impl<T: Config> Pallet<T> {
});
Ok(())
}


}
6 changes: 5 additions & 1 deletion polimec-skeleton/pallets/funding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,9 @@
// we add more without this limit.
#![cfg_attr(feature = "runtime-benchmarks", recursion_limit = "512")]

pub mod functions;
pub mod types;
pub mod weights;
pub mod functions;

#[cfg(test)]
pub mod mock;
Expand Down Expand Up @@ -912,6 +912,10 @@ pub mod pallet {
UpdateType::FundingEnd => {
unwrap_result_or_skip!(Self::do_end_funding(project_id), project_id)
}

UpdateType::ProjectDecision(decision) => {
unwrap_result_or_skip!(Self::do_project_decision(project_id, decision), project_id)
}
}
}
// TODO: PLMC-127. Set a proper weight
Expand Down
60 changes: 60 additions & 0 deletions polimec-skeleton/pallets/funding/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ const BIDDER_1: AccountId = 30;
const BIDDER_2: AccountId = 31;
const BIDDER_3: AccountId = 32;
const BIDDER_4: AccountId = 33;
const BIDDER_5: AccountId = 34;
const BUYER_1: AccountId = 40;
const BUYER_2: AccountId = 41;
const BUYER_3: AccountId = 42;
Expand Down Expand Up @@ -1305,6 +1306,7 @@ mod defaults {
pub mod helper_functions {
use super::*;
use sp_arithmetic::traits::Zero;
use sp_arithmetic::Percent;
use sp_core::H256;
use std::collections::BTreeMap;

Expand Down Expand Up @@ -1625,6 +1627,38 @@ pub mod helper_functions {
_ => Ok(()),
}
}

pub fn generate_bids_from_total_usd(
usd_amount: BalanceOf<TestRuntime>, min_price: PriceOf<TestRuntime>,
) -> TestBids {
const WEIGHTS: [u8; 5] = [30u8, 20u8, 15u8, 10u8, 25u8];
const BIDDERS: [AccountIdOf<TestRuntime>; 5] = [BUYER_1, BUYER_2, BUYER_3, BUYER_4, BUYER_5];

zip(WEIGHTS, BIDDERS)
.map(|(weight, bidder)| {
let ticket_size = Percent::from_percent(weight) * usd_amount;
let token_amount = min_price.reciprocal().unwrap().saturating_mul_int(ticket_size);

TestBid::new(bidder, token_amount, min_price, None, AcceptedFundingAsset::USDT)
})
.collect()
}

pub fn generate_contributions_from_total_usd(
usd_amount: BalanceOf<TestRuntime>, final_price: PriceOf<TestRuntime>,
) -> TestContributions {
const WEIGHTS: [u8; 5] = [30u8, 20u8, 15u8, 10u8, 25u8];
const BIDDERS: [AccountIdOf<TestRuntime>; 5] = [BIDDER_1, BIDDER_2, BIDDER_3, BIDDER_4, BIDDER_5];

zip(WEIGHTS, BIDDERS)
.map(|(weight, bidder)| {
let ticket_size = Percent::from_percent(weight) * usd_amount;
let token_amount = final_price.reciprocal().unwrap().saturating_mul_int(ticket_size);

TestContribution::new(bidder, token_amount, None, AcceptedFundingAsset::USDT)
})
.collect()
}
}

#[cfg(test)]
Expand Down Expand Up @@ -3844,6 +3878,32 @@ mod remainder_round_success {
}
}

#[cfg(test)]
mod funding_end {
use super::*;
use sp_arithmetic::{Percent, Perquintill};

#[test]
fn automatic_fail_less_eq_33_percent() {
let test_env = TestEnvironment::new();
let project_metadata = default_project(test_env.get_new_nonce());
let min_price = project_metadata.minimum_price;
let twenty_percent_funding_usd = Perquintill::from_percent(20u64)
* (project_metadata
.minimum_price
.checked_mul_int(project_metadata.total_allocation_size)
.unwrap());
let evaluations = default_evaluations();
let bids = generate_bids_from_total_usd(Percent::from_percent(10u8) * twenty_percent_funding_usd, min_price);
let contributions =
generate_contributions_from_total_usd(Percent::from_percent(10u8) * twenty_percent_funding_usd, min_price);
let remainder_project =
RemainderFundingProject::new_with(&test_env, project_metadata, ISSUER, evaluations, bids, contributions);

remainder_project.end_funding();
}
}

#[cfg(test)]
mod purchased_vesting {
use super::*;
Expand Down
10 changes: 9 additions & 1 deletion polimec-skeleton/pallets/funding/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,14 +140,15 @@ pub mod storage_types {
}

/// Tells on_initialize what to do with the project
#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Copy, Ord, PartialOrd)]
#[derive(Clone, Copy, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
pub enum UpdateType {
EvaluationEnd,
EnglishAuctionStart,
CandleAuctionStart,
CommunityFundingStart,
RemainderFundingStart,
FundingEnd,
ProjectDecision(FundingOutcomeDecision),
}

#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Ord, PartialOrd)]
Expand Down Expand Up @@ -480,6 +481,7 @@ pub mod inner_types {
pub enum SuccessReason {
SoldOut,
ReachedTarget,
ProjectDecision,
}

#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
Expand Down Expand Up @@ -555,4 +557,10 @@ pub mod inner_types {
pub early_evaluator_total_bonded_usd: Balance,
pub normal_evaluator_total_bonded_usd: Balance,
}

#[derive(Clone, Copy, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
pub enum FundingOutcomeDecision {
AcceptFunding,
RejectFunding,
}
}

0 comments on commit 0cf9b79

Please sign in to comment.