Skip to content

Commit

Permalink
API tests (#422)
Browse files Browse the repository at this point in the history
## What?
- Forgot to push the test
  • Loading branch information
JuaniRios authored Oct 17, 2024
1 parent ee93b3a commit 904e5d7
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 9 deletions.
4 changes: 2 additions & 2 deletions integration-tests/src/tests/otm_edge_cases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ fn otm_fee_below_min_amount_reverts() {
assert!(min_usdt_contribution_otm_fee < usdt_min_balance);

let ct_for_min_usdt_contribution =
PolimecFunding::funding_asset_to_ct_amount(project_id, AcceptedFundingAsset::USDT, min_usdt_contribution);
PolimecFunding::funding_asset_to_ct_amount_classic(project_id, AcceptedFundingAsset::USDT, min_usdt_contribution);

let jwt = get_mock_jwt_with_cid(
bobert.clone(),
Expand Down Expand Up @@ -153,7 +153,7 @@ fn after_otm_fee_user_goes_under_ed_reverts() {
let usdt_otm_fee = usdt_price.reciprocal().unwrap().saturating_mul_int(usd_otm_fee);

let ct_for_contribution =
PolimecFunding::funding_asset_to_ct_amount(project_id, AcceptedFundingAsset::USDT, usdt_contribution);
PolimecFunding::funding_asset_to_ct_amount_classic(project_id, AcceptedFundingAsset::USDT, usdt_contribution);
let jwt = get_mock_jwt_with_cid(
bobert.clone(),
InvestorType::Retail,
Expand Down
2 changes: 1 addition & 1 deletion pallets/funding/src/functions/1_application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ impl<T: Config> Pallet<T> {
migration_type: None,
};

let bucket: BucketOf<T> = Self::create_bucket_from_metadata(&project_metadata)?;
let bucket: BucketOf<T> = Self::create_bucket_from_metadata(project_metadata)?;

Ok((project_details, bucket))
}
Expand Down
2 changes: 1 addition & 1 deletion pallets/funding/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ impl Config for TestRuntime {

parameter_types! {
// Means a USD Ticket fee of 1.5%, since the FeePercentage is applied on the PLMC bond with multiplier 5.
pub FeePercentage: Perbill = Perbill::from_rational(75u32, 100u32);
pub FeePercentage: Perbill = Perbill::from_rational(75u32, 1000u32);
pub const FeeRecipient: AccountId = 80085;
pub const RootId: PalletId = PalletId(*b"treasury");
}
Expand Down
8 changes: 4 additions & 4 deletions pallets/funding/src/runtime_api.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
#[allow(clippy::wildcard_imports)]
use crate::*;
use crate::{traits::BondingRequirementCalculation, HoldReason::Participation};
use crate::{traits::BondingRequirementCalculation};
use alloc::collections::BTreeMap;
use frame_support::traits::fungibles::{Inspect, InspectEnumerable};
use itertools::Itertools;
use parity_scale_codec::{Decode, Encode};
use polimec_common::{credentials::InvestorType, ProvideAssetPrice, USD_DECIMALS};
use scale_info::TypeInfo;
use sp_arithmetic::Perquintill;
use sp_core::Get;
use sp_runtime::traits::Zero;

Expand Down Expand Up @@ -192,9 +191,10 @@ impl<T: Config> Pallet<T> {
let funding_asset_usd_price =
Pallet::<T>::get_decimals_aware_funding_asset_price(&funding_asset).expect("Price not found");
let otm_multiplier = ParticipationMode::OTM.multiplier();
let otm_fee_percentage = <T as pallet_proxy_bonding::Config>::FeePercentage::get() / otm_multiplier;
let otm_fee_plmc_percentage = <T as pallet_proxy_bonding::Config>::FeePercentage::get();
let otm_fee_usd_percentage = otm_fee_plmc_percentage / otm_multiplier;

let divisor = FixedU128::from_perbill(otm_fee_percentage) + FixedU128::one();
let divisor = FixedU128::from_perbill(otm_fee_usd_percentage) + FixedU128::from_rational(1,1);
let participating_funding_asset_amount =
divisor.reciprocal().unwrap().saturating_mul_int(total_funding_asset_amount);
let fee_funding_asset_amount = total_funding_asset_amount.saturating_sub(participating_funding_asset_amount);
Expand Down
159 changes: 158 additions & 1 deletion pallets/funding/src/tests/runtime_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ fn contribution_tokens() {
}

#[test]
fn funding_asset_to_ct_amount() {
fn funding_asset_to_ct_amount_classic() {
let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext())));

// We want to use a funding asset that is not equal to 1 USD
Expand Down Expand Up @@ -467,6 +467,163 @@ fn funding_asset_to_ct_amount() {
});
}

#[test]
fn funding_asset_to_ct_amount_otm() {
let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext())));

// We want to use a funding asset that is not equal to 1 USD
// Sanity check
assert_eq!(
PriceProviderOf::<TestRuntime>::get_price(AcceptedFundingAsset::DOT.id()).unwrap(),
PriceOf::<TestRuntime>::from_float(69.0f64)
);

let dot_participation_amount: u128 = 1350_0_000_000_000;
// USD Ticket = 93_150 USD
let dot_fee_amount = FixedU128::from_float(0.015f64).saturating_mul_int(dot_participation_amount);

// Easy case, wap is already calculated, we want to know how many tokens at wap we can buy with `x` USDT
let project_metadata_1 = default_project_metadata(ISSUER_1);
let project_id_1 = inst.create_community_contributing_project(
project_metadata_1.clone(),
ISSUER_1,
None,
default_evaluations(),
vec![],
);
let wap = project_metadata_1.minimum_price;
assert_eq!(inst.get_project_details(project_id_1).weighted_average_price.unwrap(), wap);

// Price of ct is min price = 10 USD/CT
let expected_ct_amount_contribution = 9_315 * CT_UNIT;
inst.execute(|| {
let block_hash = System::block_hash(System::block_number());
let (ct_amount, fee_amount) = TestRuntime::funding_asset_to_ct_amount_otm(
&TestRuntime,
block_hash,
project_id_1,
AcceptedFundingAsset::DOT,
dot_participation_amount + dot_fee_amount,
)
.unwrap();
assert_close_enough!(ct_amount, expected_ct_amount_contribution, Perquintill::from_float(0.9999));
assert_close_enough!(fee_amount, dot_fee_amount, Perquintill::from_float(0.9999));
});

// Medium case, contribution at a wap that is not the minimum price.
let project_metadata_2 = default_project_metadata(ISSUER_2);
let new_price = PriceOf::<TestRuntime>::from_float(16.3f64);
let decimal_aware_price =
PriceProviderOf::<TestRuntime>::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, 420, |acc| acc + 1);
let project_id_2 = inst.create_community_contributing_project(
project_metadata_2.clone(),
ISSUER_2,
None,
default_evaluations(),
bids,
);
// Sanity check
let project_details = inst.get_project_details(project_id_2);
assert_eq!(project_details.weighted_average_price.unwrap(), decimal_aware_price);

// 5'714.72... rounded down
let expected_ct_amount_contribution = 5_714_720_000_000_000_000;
inst.execute(|| {
let block_hash = System::block_hash(System::block_number());
let (ct_amount, fee_amount) = TestRuntime::funding_asset_to_ct_amount_otm(
&TestRuntime,
block_hash,
project_id_2,
AcceptedFundingAsset::DOT,
dot_participation_amount + dot_fee_amount,
)
.unwrap();
assert_close_enough!(ct_amount, expected_ct_amount_contribution, Perquintill::from_float(0.9999f64));
assert_close_enough!(fee_amount, dot_fee_amount, Perquintill::from_float(0.9999f64));
});

// Medium case, a bid goes over part of a bucket (bucket after the first one)
let project_metadata_3 = default_project_metadata(ISSUER_3);
let project_id_3 =
inst.create_auctioning_project(project_metadata_3.clone(), ISSUER_3, None, default_evaluations());
let mut bucket = inst.execute(|| Buckets::<TestRuntime>::get(project_id_3)).unwrap();

// We want a full bucket after filling 6 buckets. (first bucket has full allocation and initial price)
// Price should be at 16 USD/CT
bucket.current_price = bucket.initial_price + bucket.delta_price * FixedU128::from_float(6.0f64);
bucket.amount_left = bucket.delta_amount;
let bids = inst.generate_bids_from_bucket(
project_metadata_3.clone(),
bucket,
420,
|acc| acc + 1,
AcceptedFundingAsset::USDT,
);
let necessary_plmc =
inst.calculate_auction_plmc_charged_from_all_bids_made_or_with_bucket(&bids, project_metadata_3.clone(), None);
let necessary_usdt = inst.calculate_auction_funding_asset_charged_from_all_bids_made_or_with_bucket(
&bids,
project_metadata_3.clone(),
None,
);
inst.mint_plmc_to(necessary_plmc);
inst.mint_funding_asset_to(necessary_usdt);
inst.bid_for_users(project_id_3, bids).unwrap();

// Sanity check
let expected_price = PriceOf::<TestRuntime>::from_float(16.0f64);
let decimal_aware_expected_price =
PriceProviderOf::<TestRuntime>::calculate_decimals_aware_price(expected_price, USD_DECIMALS, CT_DECIMALS)
.unwrap();
let current_bucket = inst.execute(|| Buckets::<TestRuntime>::get(project_id_3).unwrap());
assert_eq!(current_bucket.current_price, decimal_aware_expected_price);

let dot_participation_amount: u128 = 217_0_000_000_000;
let dot_fee_amount = FixedU128::from_float(0.015f64).saturating_mul_int(dot_participation_amount);
let expected_ct_amount: u128 = 935_812_500_000_000_000;

inst.execute(|| {
let block_hash = System::block_hash(System::block_number());
let (ct_amount, fee_amount) = TestRuntime::funding_asset_to_ct_amount_otm(
&TestRuntime,
block_hash,
project_id_3,
AcceptedFundingAsset::DOT,
dot_participation_amount + dot_fee_amount,
)
.unwrap();
assert_close_enough!(ct_amount, expected_ct_amount, Perquintill::from_float(0.9999));
assert_close_enough!(fee_amount, dot_fee_amount, Perquintill::from_float(0.9999));
});

// Hard case, a bid goes over multiple buckets
// We take the same project from before, and we add a bid that goes over 3 buckets.
// Bucket size is 50k CTs, and current price is 16 USD/CT
// We need to buy 50k at 16 , 50k at 17, and 13.5k at 18 = 1893k USD

// Amount needed to spend 1893k USD through several buckets with DOT at 69 USD/DOT
let dot_participation_amount = 27_434_7_826_086_956u128;
let dot_fee_amount = FixedU128::from_float(0.015f64).saturating_mul_int(dot_participation_amount);
let expected_ct_amount = 113_500 * CT_UNIT;

inst.execute(|| {
let block_hash = System::block_hash(System::block_number());
let (ct_amount, fee_amount) = TestRuntime::funding_asset_to_ct_amount_otm(
&TestRuntime,
block_hash,
project_id_3,
AcceptedFundingAsset::DOT,
dot_participation_amount + dot_fee_amount,
)
.unwrap();
assert_close_enough!(ct_amount, expected_ct_amount, Perquintill::from_float(0.9999));
assert_close_enough!(fee_amount, dot_fee_amount, Perquintill::from_float(0.9999));
});
}

#[test]
fn get_next_vesting_schedule_merge_candidates() {
let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext())));
Expand Down

0 comments on commit 904e5d7

Please sign in to comment.