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

✅ New decimals community test #277

Merged
merged 1 commit into from
May 2, 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
5 changes: 3 additions & 2 deletions pallets/funding/src/instantiator/chain_interactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,11 +538,12 @@ impl<
evaluations: Vec<UserToUSDBalance<T>>,
bids: Vec<BidParams<T>>,
) -> ProjectId {
let project_id = self.create_auctioning_project(project_metadata.clone(), issuer, evaluations.clone());
if bids.is_empty() {
panic!("Cannot start community funding without bids")
self.start_community_funding(project_id).unwrap();
return project_id
}

let project_id = self.create_auctioning_project(project_metadata.clone(), issuer, evaluations.clone());
let bidders = bids.accounts();
let asset_id = bids[0].asset.to_assethub_id();
let prev_plmc_balances = self.get_free_plmc_balances_for(bidders.clone());
Expand Down
154 changes: 154 additions & 0 deletions pallets/funding/src/tests/4_community.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ mod round_flow {
#[cfg(test)]
mod success {
use super::*;
use frame_support::traits::fungibles::metadata::Inspect;
use sp_runtime::bounded_vec;
use std::collections::HashSet;

#[test]
fn community_round_completed() {
Expand Down Expand Up @@ -151,6 +154,157 @@ mod round_flow {

assert_eq!(inst.get_project_details(project_id).remaining_contribution_tokens, 0);
}

#[test]
fn different_decimals_ct_works_as_expected() {
// Setup some base values to compare different decimals
let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext())));
let ed = inst.get_ed();
let default_project_metadata = default_project_metadata(ISSUER_1);
let original_decimal_aware_price = default_project_metadata.minimum_price;
let original_price = <TestRuntime as Config>::PriceProvider::convert_back_to_normal_price(
original_decimal_aware_price,
USD_DECIMALS,
default_project_metadata.token_information.decimals,
)
.unwrap();
let usable_plmc_price = inst.execute(|| {
<TestRuntime as Config>::PriceProvider::get_decimals_aware_price(
PLMC_FOREIGN_ID,
USD_DECIMALS,
PLMC_DECIMALS,
)
.unwrap()
});
let usdt_price = inst.execute(|| {
<TestRuntime as Config>::PriceProvider::get_decimals_aware_price(
AcceptedFundingAsset::USDT.to_assethub_id(),
USD_DECIMALS,
ForeignAssets::decimals(AcceptedFundingAsset::USDT.to_assethub_id()),
)
.unwrap()
});
let usdc_price = inst.execute(|| {
<TestRuntime as Config>::PriceProvider::get_decimals_aware_price(
AcceptedFundingAsset::USDC.to_assethub_id(),
USD_DECIMALS,
ForeignAssets::decimals(AcceptedFundingAsset::USDC.to_assethub_id()),
)
.unwrap()
});
let dot_price = inst.execute(|| {
<TestRuntime as Config>::PriceProvider::get_decimals_aware_price(
AcceptedFundingAsset::DOT.to_assethub_id(),
USD_DECIMALS,
ForeignAssets::decimals(AcceptedFundingAsset::DOT.to_assethub_id()),
)
.unwrap()
});

let mut funding_assets_cycle =
vec![AcceptedFundingAsset::USDT, AcceptedFundingAsset::USDC, AcceptedFundingAsset::DOT]
.into_iter()
.cycle();

let mut total_fundings_ct = Vec::new();
let mut total_fundings_usd = Vec::new();
let mut total_fundings_plmc = Vec::new();

let mut decimal_test = |decimals: u8| {
let funding_asset = funding_assets_cycle.next().unwrap();
let funding_asset_usd_price = match funding_asset {
AcceptedFundingAsset::USDT => usdt_price,
AcceptedFundingAsset::USDC => usdc_price,
AcceptedFundingAsset::DOT => dot_price,
};

let mut project_metadata = default_project_metadata.clone();
project_metadata.token_information.decimals = decimals;
project_metadata.minimum_price =
<TestRuntime as Config>::PriceProvider::calculate_decimals_aware_price(
original_price,
USD_DECIMALS,
decimals,
)
.unwrap();

project_metadata.total_allocation_size = 1_000_000 * 10u128.pow(decimals as u32);
project_metadata.mainnet_token_max_supply = project_metadata.total_allocation_size;
project_metadata.participation_currencies = bounded_vec!(funding_asset);

let issuer: AccountIdOf<TestRuntime> = (10_000 + inst.get_new_nonce()).try_into().unwrap();
let evaluations = inst.generate_successful_evaluations(
project_metadata.clone(),
default_evaluators(),
default_weights(),
);
let project_id =
inst.create_community_contributing_project(project_metadata.clone(), issuer, evaluations, vec![]);

let total_funding_ct = project_metadata.total_allocation_size;
let total_funding_usd = project_metadata.minimum_price.saturating_mul_int(total_funding_ct);
let total_funding_plmc = usable_plmc_price.reciprocal().unwrap().saturating_mul_int(total_funding_usd);
let total_funding_funding_asset =
funding_asset_usd_price.reciprocal().unwrap().saturating_mul_int(total_funding_usd);

total_fundings_ct.push(total_funding_ct);
total_fundings_usd.push(total_funding_usd);
total_fundings_plmc.push(total_funding_plmc);

// Every project should want to raise 10MM USD
assert_eq!(total_funding_usd, 10_000_000 * USD_UNIT);

// Every project should produce the same PLMC bond when having the full funding at multiplier 1.
assert_close_enough!(total_funding_plmc, 1_190_476 * PLMC, Perquintill::from_float(0.999));

// Every project should have a different amount of CTs to raise, depending on their decimals
assert_eq!(total_funding_ct, 1_000_000 * 10u128.pow(decimals as u32));

// Buying all the remaining tokens. This is a fixed USD value, but the extrinsic amount depends on CT decimals.
inst.mint_plmc_to(vec![UserToPLMCBalance::new(BUYER_1, total_funding_plmc + ed)]);
inst.mint_foreign_asset_to(vec![UserToForeignAssets::new(
BUYER_1,
total_funding_funding_asset,
funding_asset.to_assethub_id(),
)]);

assert_ok!(inst.execute(|| PolimecFunding::community_contribute(
RuntimeOrigin::signed(BUYER_1),
get_mock_jwt_with_cid(
BUYER_1,
InvestorType::Retail,
generate_did_from_account(BUYER_1),
project_metadata.clone().policy_ipfs_cid.unwrap()
),
project_id,
total_funding_ct,
1u8.try_into().unwrap(),
funding_asset,
)));

// the remaining tokens should be zero
assert_eq!(inst.get_project_details(project_id).remaining_contribution_tokens, 0);

// We can successfully finish the project
inst.finish_funding(project_id).unwrap();
};

for decimals in 0..25 {
decimal_test(decimals);
}

// Since we use the same original price and allocation size and adjust for decimals,
// the USD and PLMC amounts should be the same
assert!(total_fundings_usd.iter().all(|x| *x == total_fundings_usd[0]));
assert!(total_fundings_plmc.iter().all(|x| *x == total_fundings_plmc[0]));

// CT amounts however should be different from each other
let mut hash_set_1 = HashSet::new();
for amount in total_fundings_ct {
assert!(!hash_set_1.contains(&amount));
hash_set_1.insert(amount);
}
}
}
}

Expand Down