Skip to content

Commit

Permalink
otm_funding_tests
Browse files Browse the repository at this point in the history
  • Loading branch information
JuaniRios committed Oct 3, 2024
1 parent 70e3fed commit 63506b0
Show file tree
Hide file tree
Showing 32 changed files with 1,294 additions and 453 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 7 additions & 5 deletions integration-tests/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ pub mod polimec {
let dot = (AcceptedFundingAsset::DOT.id(), prices.dot);
let usdc = (AcceptedFundingAsset::USDC.id(), prices.usdc);
let usdt = (AcceptedFundingAsset::USDT.id(), prices.usdt);
let plmc = (pallet_funding::PLMC_FOREIGN_ID, prices.plmc);
let plmc = (polimec_common::PLMC_FOREIGN_ID, prices.plmc);

let values: BoundedVec<(u32, FixedU128), <PolimecRuntime as orml_oracle::Config>::MaxFeedValues> =
vec![dot, usdc, usdt, plmc].try_into().expect("benchmarks can panic");
Expand Down Expand Up @@ -501,18 +501,20 @@ pub mod polimec {

funded_accounts.extend(accounts::init_balances().iter().cloned().map(|k| (k, INITIAL_DEPOSIT)));
funded_accounts.extend(collators::initial_authorities().iter().cloned().map(|(acc, _)| (acc, 20_005 * PLMC)));
funded_accounts.push((TreasuryAccount::get(), 20_005 * PLMC));
funded_accounts.push((TreasuryAccount::get(), 20_000_000 * PLMC));
funded_accounts.push((BlockchainOperationTreasury::get(), 20_005 * PLMC));
/// Treasury account needs PLMC for the One Token Model participations
funded_accounts.push((polimec_runtime::FeeRecipient::get(), INITIAL_DEPOSIT));

let genesis_config = polimec_runtime::RuntimeGenesisConfig {
system: Default::default(),
balances: polimec_runtime::BalancesConfig { balances: funded_accounts },
contribution_tokens: Default::default(),
foreign_assets: polimec_runtime::ForeignAssetsConfig {
assets: vec![
(dot_asset_id, alice_account.clone(), true, 0_0_010_000_000u128),
(usdt_asset_id, alice_account.clone(), true, 0_0_010_000_000u128),
(usdc_asset_id, alice_account.clone(), true, 0_0_010_000_000u128),
(dot_asset_id, alice_account.clone(), true, 70_000),
(usdt_asset_id, alice_account.clone(), true, 70_000),
(usdc_asset_id, alice_account.clone(), true, 70_000),
],
metadata: vec![
(dot_asset_id, "Local DOT".as_bytes().to_vec(), "DOT".as_bytes().to_vec(), 10),
Expand Down
1 change: 1 addition & 0 deletions integration-tests/src/tests/credentials.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use crate::*;
use frame_support::{assert_err, assert_ok, dispatch::GetDispatchInfo, traits::tokens::currency::VestingSchedule};
use macros::generate_accounts;
use pallet_funding::ParticipationMode::{Classic, OTM};
use polimec_common::credentials::{Did, InvestorType};
use polimec_common_test_utils::{get_fake_jwt, get_mock_jwt_with_cid, get_test_jwt};
use polimec_runtime::PLMC;
Expand Down
19 changes: 10 additions & 9 deletions integration-tests/src/tests/defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ use crate::PolimecRuntime;
use frame_support::BoundedVec;
pub use pallet_funding::instantiator::{BidParams, ContributionParams, UserToUSDBalance};
use pallet_funding::{
AcceptedFundingAsset, BiddingTicketSizes, ContributingTicketSizes, CurrencyMetadata, PriceProviderOf,
ProjectMetadata, ProjectMetadataOf, TicketSize,
AcceptedFundingAsset, BiddingTicketSizes, ContributingTicketSizes, CurrencyMetadata, ParticipationMode,
PriceProviderOf, ProjectMetadata, ProjectMetadataOf, TicketSize,
};
use sp_arithmetic::{FixedPointNumber, Percent};

use macros::generate_accounts;
use polimec_common::{ProvideAssetPrice, USD_DECIMALS, USD_UNIT};
use polimec_runtime::{AccountId, PLMC};
use sp_runtime::{traits::ConstU32, Perquintill};
use ParticipationMode::{Classic, OTM};

pub const IPFS_CID: &str = "QmeuJ24ffwLAZppQcgcggJs3n689bewednYkuc8Bx5Gngz";
pub const CT_DECIMALS: u8 = 18;
Expand Down Expand Up @@ -54,11 +55,11 @@ pub fn ipfs_hash() -> BoundedVec<u8, ConstU32<96>> {
pub fn default_weights() -> Vec<u8> {
vec![20u8, 15u8, 10u8, 25u8, 30u8]
}
pub fn default_bidder_multipliers() -> Vec<u8> {
vec![1u8, 6u8, 10u8, 8u8, 3u8]
pub fn default_bidder_modes() -> Vec<ParticipationMode> {
vec![Classic(1u8), Classic(6u8), OTM, OTM, Classic(3u8)]
}
pub fn default_contributor_multipliers() -> Vec<u8> {
vec![1u8, 1u8, 1u8, 1u8, 1u8]
pub fn default_contributor_modes() -> Vec<ParticipationMode> {
vec![Classic(1u8), Classic(1u8), OTM, OTM, Classic(3u8)]
}

pub fn default_project_metadata(issuer: AccountId) -> ProjectMetadataOf<polimec_runtime::Runtime> {
Expand Down Expand Up @@ -113,7 +114,7 @@ pub fn default_bids() -> Vec<BidParams<PolimecRuntime>> {
default_metadata.minimum_price,
default_weights(),
default_bidders(),
default_bidder_multipliers(),
default_bidder_modes(),
)
}

Expand All @@ -134,7 +135,7 @@ pub fn default_community_contributions() -> Vec<ContributionParams<PolimecRuntim
default_metadata.minimum_price,
default_weights(),
default_community_contributors(),
default_contributor_multipliers(),
default_contributor_modes(),
)
}

Expand All @@ -157,7 +158,7 @@ pub fn default_remainder_contributions() -> Vec<ContributionParams<PolimecRuntim
default_metadata.minimum_price,
vec![20u8, 15u8, 10u8, 25u8, 23u8, 7u8],
default_remainder_contributors(),
vec![1u8, 1u8, 1u8, 1u8, 1u8, 1u8],
default_contributor_modes(),
)
}
pub fn default_community_contributors() -> Vec<AccountId> {
Expand Down
1 change: 1 addition & 0 deletions integration-tests/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ mod e2e;
mod evaluator_slash_sideffects;
mod governance;
mod oracle;
mod otm_edge_cases;
mod reserve_backed_transfers;
mod vest;
mod xcm_config;
189 changes: 189 additions & 0 deletions integration-tests/src/tests/otm_edge_cases.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
use crate::{
constants::PricesBuilder,
tests::defaults::{default_evaluations, default_project_metadata, ipfs_hash, IntegrationInstantiator},
*,
};
use frame_support::traits::fungibles::Inspect;
use macros::generate_accounts;
use pallet_funding::{AcceptedFundingAsset, ParticipationMode, PriceProviderOf};
use polimec_common::{credentials::InvestorType, ProvideAssetPrice, USD_UNIT};
use polimec_common_test_utils::{generate_did_from_account, get_mock_jwt_with_cid};
use polimec_runtime::OraclePriceProvider;
use sp_arithmetic::{FixedPointNumber, FixedU128};
use sp_core::bounded_vec;
use sp_runtime::TokenError;
generate_accounts!(ISSUER, BOBERT);

#[test]
fn cannot_have_otm_fee_below_min_amount() {
let mut inst = IntegrationInstantiator::new(None);
let issuer: PolimecAccountId = ISSUER.into();
let bobert: PolimecAccountId = BOBERT.into();

let prices = PricesBuilder::new()
.plmc(FixedU128::from_float(0.17f64))
.usdt(FixedU128::from_float(0.9999f64))
.usdc(FixedU128::from_float(1.0001f64))
.dot(FixedU128::from_float(4.0f64))
.build();

polimec::set_prices(prices);

PolimecNet::execute_with(|| {
let mut project_metadata = default_project_metadata(issuer.clone());
project_metadata.participation_currencies = bounded_vec![
AcceptedFundingAsset::USDT,
AcceptedFundingAsset::USDC,
AcceptedFundingAsset::DOT,
];

let usdt_price = <PolimecRuntime as pallet_funding::Config>::PriceProvider::get_decimals_aware_price(
AcceptedFundingAsset::USDT.id(),
6,
6,
)
.unwrap();
let usdc_price = <PolimecRuntime as pallet_funding::Config>::PriceProvider::get_decimals_aware_price(
AcceptedFundingAsset::USDC.id(),
6,
6,
)
.unwrap();
let dot_price = <PolimecRuntime as pallet_funding::Config>::PriceProvider::get_decimals_aware_price(
AcceptedFundingAsset::USDC.id(),
6,
10,
)
.unwrap();

let project_id = inst.create_community_contributing_project(
project_metadata.clone(),
issuer.clone(),
None,
default_evaluations(),
vec![],
);

let plmc_ed = inst.get_ed();

let min_usd_contribution = USD_UNIT;

let mut min_usdt_contribution = usdt_price.reciprocal().unwrap().saturating_mul_int(min_usd_contribution);
while usdt_price.saturating_mul_int(min_usdt_contribution) < min_usd_contribution {
min_usdt_contribution += 1;
}

let mut min_usdc_contribution = usdc_price.reciprocal().unwrap().saturating_mul_int(min_usd_contribution);
while usdc_price.saturating_mul_int(min_usdc_contribution) < min_usd_contribution {
min_usdc_contribution += 1;
}

let mut min_dot_contribution = dot_price.reciprocal().unwrap().saturating_mul_int(min_usd_contribution);
while dot_price.saturating_mul_int(min_dot_contribution) < min_usd_contribution {
min_dot_contribution += 1;
}

let min_usdt_contribution_otm_fee = polimec_runtime::FeePercentage::get() * min_usdt_contribution;
let min_usdc_contribution_otm_fee = polimec_runtime::FeePercentage::get() * min_usdc_contribution;
let min_dot_contribution_otm_fee = polimec_runtime::FeePercentage::get() * min_dot_contribution;

let usdt_min_balance = inst.execute(|| PolimecForeignAssets::minimum_balance(AcceptedFundingAsset::USDT.id()));
let usdc_min_balance = inst.execute(|| PolimecForeignAssets::minimum_balance(AcceptedFundingAsset::USDC.id()));
let dot_min_balance = inst.execute(|| PolimecForeignAssets::minimum_balance(AcceptedFundingAsset::DOT.id()));

assert!(min_usdt_contribution_otm_fee > usdt_min_balance);
assert!(min_usdc_contribution_otm_fee > usdc_min_balance);
assert!(min_dot_contribution_otm_fee > dot_min_balance);

let ct_for_min_usdt_contribution =
PolimecFunding::funding_asset_to_ct_amount(project_id, AcceptedFundingAsset::USDT, min_usdt_contribution);
let ct_for_min_usdc_contribution =
PolimecFunding::funding_asset_to_ct_amount(project_id, AcceptedFundingAsset::USDC, min_usdc_contribution);
let ct_for_min_dot_contribution =
PolimecFunding::funding_asset_to_ct_amount(project_id, AcceptedFundingAsset::DOT, min_dot_contribution);

let jwt = get_mock_jwt_with_cid(
bobert.clone(),
InvestorType::Retail,
generate_did_from_account(bobert.clone()),
ipfs_hash(),
);

inst.mint_plmc_to(vec![(bobert.clone(), plmc_ed).into()]);
inst.mint_funding_asset_to(vec![
(bobert.clone(), min_usdt_contribution + min_usdt_contribution_otm_fee, AcceptedFundingAsset::USDT.id())
.into(),
(bobert.clone(), min_usdc_contribution + min_usdc_contribution_otm_fee, AcceptedFundingAsset::USDC.id())
.into(),
(bobert.clone(), min_dot_contribution + min_dot_contribution_otm_fee, AcceptedFundingAsset::DOT.id())
.into(),
]);

let contribute_is_ok_with = |asset, ct_amount| {
assert_ok!(PolimecFunding::contribute(
PolimecOrigin::signed(bobert.clone()),
jwt.clone(),
project_id,
ct_amount,
ParticipationMode::OTM,
asset
));
};
contribute_is_ok_with(AcceptedFundingAsset::USDT, ct_for_min_usdt_contribution);
contribute_is_ok_with(AcceptedFundingAsset::USDC, ct_for_min_usdc_contribution);
contribute_is_ok_with(AcceptedFundingAsset::DOT, ct_for_min_dot_contribution);
});
}

#[test]
fn after_otm_fee_user_goes_under_ed() {
let mut inst = IntegrationInstantiator::new(None);
let issuer: PolimecAccountId = ISSUER.into();
let bobert: PolimecAccountId = BOBERT.into();

polimec::set_prices(PricesBuilder::default());
PolimecNet::execute_with(|| {
let mut project_metadata = default_project_metadata(issuer.clone());

let project_id = inst.create_community_contributing_project(
project_metadata.clone(),
issuer.clone(),
None,
default_evaluations(),
vec![],
);

// default price of usdt = 1usd
let usdt_contribution = 100 * USD_UNIT;
let contribution_otm_fee = polimec_runtime::FeePercentage::get() * usdt_contribution;

let usdt_min_balance = inst.execute(|| PolimecForeignAssets::minimum_balance(AcceptedFundingAsset::USDT.id()));
assert!(contribution_otm_fee > usdt_min_balance);

let ct_for_contribution =
PolimecFunding::funding_asset_to_ct_amount(project_id, AcceptedFundingAsset::USDT, usdt_contribution);
let jwt = get_mock_jwt_with_cid(
bobert.clone(),
InvestorType::Retail,
generate_did_from_account(bobert.clone()),
ipfs_hash(),
);

let usdt_mint = usdt_contribution + contribution_otm_fee;
inst.mint_funding_asset_to(vec![(bobert.clone(), usdt_mint, AcceptedFundingAsset::USDT.id()).into()]);

assert_ok!(PolimecFunding::contribute(
PolimecOrigin::signed(bobert.clone()),
jwt.clone(),
project_id,
ct_for_contribution,
ParticipationMode::OTM,
AcceptedFundingAsset::USDT,
));

// Somehow still exists because sufficients = 1
assert!(PolimecSystem::account_exists(&bobert));
dbg!(PolimecSystem::account(&bobert));

});
}
15 changes: 9 additions & 6 deletions nodes/parachain/src/chain_spec/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ use polimec_runtime::{
inflation::{perbill_annual_to_perbill_round, BLOCKS_PER_YEAR},
InflationInfo, Range,
},
AccountId, AuraId as AuthorityId, Balance, OracleProvidersMembershipConfig, Runtime, PLMC,
AccountId, AuraId as AuthorityId, Balance, BlockchainOperationTreasury, ContributionTreasuryAccount,
ExistentialDeposit, FeeRecipient, OracleProvidersMembershipConfig, Runtime, TreasuryAccount, PLMC,
};
use sp_core::{crypto::UncheckedInto, sr25519};
use sp_runtime::{traits::AccountIdConversion, Perbill, Percent};

pub type ChainSpec = sc_service::GenericChainSpec<Extensions>;

/// The default XCM version to set in genesis config.
Expand Down Expand Up @@ -86,13 +88,14 @@ pub fn genesis_config(genesis_config_params: GenesisConfigParams) -> serde_json:
id,
} = genesis_config_params;

let ed = ExistentialDeposit::get();
let system_accounts = vec![
(
<Runtime as pallet_funding::Config>::ContributionTreasury::get(),
<Runtime as pallet_funding::Config>::NativeCurrency::minimum_balance(),
),
(ContributionTreasuryAccount::get(), ed),
(FeeRecipient::get(), ed),
// Need this to have enough for staking rewards
(<Runtime as pallet_parachain_staking::Config>::PayMaster::get(), 10_000_000 * PLMC),
(BlockchainOperationTreasury::get(), 10_000_000 * PLMC),
// Need this to have enough for proxy bonding
(TreasuryAccount::get(), 10_000_000 * PLMC),
];
endowed_accounts.append(&mut system_accounts.clone());

Expand Down
Loading

0 comments on commit 63506b0

Please sign in to comment.