Skip to content

Commit

Permalink
otm_funding_tests
Browse files Browse the repository at this point in the history
  • Loading branch information
JuaniRios committed Sep 20, 2024
1 parent 7b27337 commit 086bca3
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 59 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.

13 changes: 12 additions & 1 deletion pallets/funding/src/instantiator/calculations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ impl<
T::ExistentialDeposit::get()
}

pub fn get_funding_asset_ed(&mut self, asset_id: AssetIdOf<T>) -> Balance {
self.execute(|| T::FundingCurrency::minimum_balance(asset_id))
}

pub fn get_ct_account_deposit(&self) -> Balance {
<T as crate::Config>::ContributionTokenCurrency::deposit_required(One::one())
}
Expand Down Expand Up @@ -433,7 +437,14 @@ impl<
.unwrap()
});
let usd_ticket_size = token_usd_price.saturating_mul_int(cont.amount);
let funding_asset_spent = funding_asset_usd_price.reciprocal().unwrap().saturating_mul_int(usd_ticket_size);
let mut funding_asset_spent =
funding_asset_usd_price.reciprocal().unwrap().saturating_mul_int(usd_ticket_size);
if cont.mode == ParticipationMode::OTM {
let multiplier: MultiplierOf<T> = cont.mode.multiplier().try_into().ok().unwrap();
let plmc_bond = multiplier.calculate_bonding_requirement::<T>(usd_ticket_size).unwrap();
let otm_fee = <pallet_proxy_bonding::Pallet<T>>::calculate_fee(plmc_bond, funding_asset_id).unwrap();
funding_asset_spent += otm_fee;
}
output.push(UserToFundingAsset::new(cont.contributor, funding_asset_spent, cont.asset.id()));
}
output
Expand Down
28 changes: 14 additions & 14 deletions pallets/funding/src/instantiator/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ use sp_arithmetic::Percent;
fn dry_run_wap() {
let mut inst = tests::MockInstantiator::new(Some(RefCell::new(new_test_ext())));

const ADAM: u32 = 60;
const TOM: u32 = 61;
const SOFIA: u32 = 62;
const FRED: u32 = 63;
const ANNA: u32 = 64;
const DAMIAN: u32 = 65;
const ADAM: AccountIdOf<TestRuntime> = 60;
const TOM: AccountIdOf<TestRuntime> = 61;
const SOFIA: AccountIdOf<TestRuntime> = 62;
const FRED: AccountIdOf<TestRuntime> = 63;
const ANNA: AccountIdOf<TestRuntime> = 64;
const DAMIAN: AccountIdOf<TestRuntime> = 65;

let accounts = vec![ADAM, TOM, SOFIA, FRED, ANNA, DAMIAN];

Expand Down Expand Up @@ -50,7 +50,7 @@ fn dry_run_wap() {
phantom: Default::default(),
},
participation_currencies: vec![AcceptedFundingAsset::USDT].try_into().unwrap(),
funding_destination_account: 0u32,
funding_destination_account: 0,
policy_ipfs_cid: Some(metadata_hash),
};

Expand Down Expand Up @@ -98,12 +98,12 @@ fn dry_run_wap() {
fn find_bucket_for_wap() {
let mut inst = tests::MockInstantiator::new(Some(RefCell::new(new_test_ext())));

const ADAM: u32 = 60;
const TOM: u32 = 61;
const SOFIA: u32 = 62;
const FRED: u32 = 63;
const ANNA: u32 = 64;
const DAMIAN: u32 = 65;
const ADAM: AccountIdOf<TestRuntime> = 60;
const TOM: AccountIdOf<TestRuntime> = 61;
const SOFIA: AccountIdOf<TestRuntime> = 62;
const FRED: AccountIdOf<TestRuntime> = 63;
const ANNA: AccountIdOf<TestRuntime> = 64;
const DAMIAN: AccountIdOf<TestRuntime> = 65;

let accounts = vec![ADAM, TOM, SOFIA, FRED, ANNA, DAMIAN];

Expand Down Expand Up @@ -132,7 +132,7 @@ fn find_bucket_for_wap() {
phantom: Default::default(),
},
participation_currencies: vec![AcceptedFundingAsset::USDT].try_into().unwrap(),
funding_destination_account: 0u32,
funding_destination_account: 0,
policy_ipfs_cid: Some(metadata_hash),
};

Expand Down
26 changes: 14 additions & 12 deletions pallets/funding/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub const MILLI_PLMC: Balance = PLMC / 10u128.pow(3);
pub const MICRO_PLMC: Balance = PLMC / 10u128.pow(6);
pub const EXISTENTIAL_DEPOSIT: Balance = 10 * MILLI_PLMC;
pub type Block = frame_system::mocking::MockBlock<TestRuntime>;
pub type AccountId = u32;
pub type AccountId = u64;
pub type BlockNumber = u64;
pub type Identifier = u32;
pub type Price = FixedU128;
Expand All @@ -71,7 +71,7 @@ pub const fn free_deposit() -> Balance {

pub struct SignedToAccountIndex<RuntimeOrigin, AccountId, Network>(PhantomData<(RuntimeOrigin, AccountId, Network)>);

impl<RuntimeOrigin: OriginTrait + Clone, AccountId: Into<u32>, Network: Get<Option<NetworkId>>>
impl<RuntimeOrigin: OriginTrait + Clone, AccountId: Into<u64>, Network: Get<Option<NetworkId>>>
TryConvert<RuntimeOrigin, Location> for SignedToAccountIndex<RuntimeOrigin, AccountId, Network>
where
RuntimeOrigin::PalletsOrigin:
Expand All @@ -80,7 +80,7 @@ where
fn try_convert(o: RuntimeOrigin) -> Result<Location, RuntimeOrigin> {
o.try_with_caller(|caller| match caller.try_into() {
Ok(SystemRawOrigin::Signed(who)) =>
Ok(Junction::AccountIndex64 { network: Network::get(), index: Into::<u32>::into(who).into() }.into()),
Ok(Junction::AccountIndex64 { network: Network::get(), index: Into::<u64>::into(who).into() }.into()),
Ok(other) => Err(other.into()),
Err(other) => Err(other),
})
Expand Down Expand Up @@ -296,7 +296,7 @@ parameter_types! {
pub const CommunityRoundDuration: BlockNumber = 18u64;
pub const RemainderRoundDuration: BlockNumber = 6u64;

pub const FundingPalletId: PalletId = PalletId(*b"py/cfund");
pub const FundingPalletId: PalletId = PalletId(*b"plmc-fun");
pub FeeBrackets: Vec<(Percent, Balance)> = vec![
(Percent::from_percent(10), 1_000_000 * USD_UNIT),
(Percent::from_percent(8), 4_000_000 * USD_UNIT),
Expand Down Expand Up @@ -353,14 +353,14 @@ pub struct DummyConverter;
impl sp_runtime::traits::Convert<AccountId, [u8; 32]> for DummyConverter {
fn convert(a: AccountId) -> [u8; 32] {
let mut account: [u8; 32] = [0u8; 32];
account[0..4].copy_from_slice(a.to_le_bytes().as_slice());
account[0..8].copy_from_slice(a.to_le_bytes().as_slice());
account
}
}
impl ConvertBack<AccountId, [u8; 32]> for DummyConverter {
fn convert_back(bytes: [u8; 32]) -> AccountId {
let account: [u8; 4] = bytes[0..3].try_into().unwrap();
u32::from_le_bytes(account)
let account: [u8; 8] = bytes[0..7].try_into().unwrap();
u64::from_le_bytes(account)
}
}
thread_local! {
Expand Down Expand Up @@ -437,7 +437,7 @@ impl Config for TestRuntime {

parameter_types! {
pub const FeePercentage: Perbill = Perbill::from_percent(5);
pub const FeeRecipient: AccountId = 80085u32;
pub const FeeRecipient: AccountId = 80085;
pub const RootId: PalletId = PalletId(*b"treasury");
}
impl pallet_proxy_bonding::Config for TestRuntime {
Expand Down Expand Up @@ -482,27 +482,29 @@ pub fn new_test_ext() -> sp_io::TestExternalities {
balances: vec![
(<TestRuntime as Config>::PalletId::get().into_account_truncating(), ed),
(<TestRuntime as Config>::ContributionTreasury::get(), ed),
(<TestRuntime as Config>::BlockchainOperationTreasury::get(), ed),
/// Treasury account needs PLMC for the One Token Model participations
(<TestRuntime as Config>::BlockchainOperationTreasury::get(), 1_000_000 * PLMC),
],
},
foreign_assets: ForeignAssetsConfig {
assets: vec![
(
AcceptedFundingAsset::USDT.id(),
<TestRuntime as Config>::PalletId::get().into_account_truncating(),
false,
// asset is sufficient, i.e. participants can hold only this asset to participate with OTM
true,
10,
),
(
AcceptedFundingAsset::USDC.id(),
<TestRuntime as Config>::PalletId::get().into_account_truncating(),
false,
true,
10,
),
(
AcceptedFundingAsset::DOT.id(),
<TestRuntime as Config>::PalletId::get().into_account_truncating(),
false,
true,
10,
),
],
Expand Down
2 changes: 1 addition & 1 deletion pallets/funding/src/tests/2_evaluation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@ mod evaluate_extrinsic {
let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext())));
let project_metadata = default_project_metadata(ISSUER_1);
let evaluations = (0u32..<TestRuntime as Config>::MaxEvaluationsPerProject::get())
.map(|i| UserToUSDBalance::<TestRuntime>::new(i as u32 + 420u32, (100u128 * CT_UNIT).into()))
.map(|i| UserToUSDBalance::<TestRuntime>::new(i as u64 + 420, (100u128 * CT_UNIT).into()))
.collect_vec();
let failing_evaluation = UserToUSDBalance::new(EVALUATOR_1, 1000 * CT_UNIT);

Expand Down
29 changes: 14 additions & 15 deletions pallets/funding/src/tests/3_auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ mod round_flow {
let max_bids_per_project: u32 = <TestRuntime as Config>::MaxBidsPerProject::get();
let big_bid: BidParams<TestRuntime> = (BIDDER_1, total_allocation).into();
let small_bids: Vec<BidParams<TestRuntime>> =
(0..max_bids_per_project - 1).map(|i| (i + BIDDER_1, min_bid_ct).into()).collect();
(0..max_bids_per_project - 1).map(|i| (i as u64 + BIDDER_1, min_bid_ct).into()).collect();
let all_bids = vec![vec![big_bid.clone()], small_bids.clone()].into_iter().flatten().collect_vec();

let mut project_metadata = default_project_metadata(ISSUER_1);
Expand Down Expand Up @@ -1014,8 +1014,7 @@ mod bid_extrinsic {
let evaluations =
inst.generate_successful_evaluations(project_metadata.clone(), vec![EVALUATOR_1], vec![100u8]);
let max_bids_per_project: u32 = <TestRuntime as Config>::MaxBidsPerProject::get();
let bids =
(0u32..max_bids_per_project - 1).map(|i| (i as u32 + 420u32, 5000 * CT_UNIT).into()).collect_vec();
let bids = (0u32..max_bids_per_project - 1).map(|i| (i as u64 + 420, 5000 * CT_UNIT).into()).collect_vec();

let project_id = inst.create_auctioning_project(project_metadata.clone(), ISSUER_1, None, evaluations);

Expand Down Expand Up @@ -1574,12 +1573,12 @@ mod end_auction_extrinsic {
// From the knowledge hub: https://hub.polimec.org/learn/calculation-example#auction-round-calculation-example
let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext())));

const ADAM: u32 = 60;
const TOM: u32 = 61;
const SOFIA: u32 = 62;
const FRED: u32 = 63;
const ANNA: u32 = 64;
const DAMIAN: u32 = 65;
const ADAM: AccountIdOf<TestRuntime> = 60;
const TOM: AccountIdOf<TestRuntime> = 61;
const SOFIA: AccountIdOf<TestRuntime> = 62;
const FRED: AccountIdOf<TestRuntime> = 63;
const ANNA: AccountIdOf<TestRuntime> = 64;
const DAMIAN: AccountIdOf<TestRuntime> = 65;

let accounts = vec![ADAM, TOM, SOFIA, FRED, ANNA, DAMIAN];

Expand Down Expand Up @@ -1801,12 +1800,12 @@ mod end_auction_extrinsic {
// From the knowledge hub: https://hub.polimec.org/learn/calculation-example#auction-round-calculation-example
let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext())));

const ADAM: u32 = 60;
const TOM: u32 = 61;
const SOFIA: u32 = 62;
const FRED: u32 = 63;
const ANNA: u32 = 64;
const DAMIAN: u32 = 65;
const ADAM: AccountIdOf<TestRuntime> = 60;
const TOM: AccountIdOf<TestRuntime> = 61;
const SOFIA: AccountIdOf<TestRuntime> = 62;
const FRED: AccountIdOf<TestRuntime> = 63;
const ANNA: AccountIdOf<TestRuntime> = 64;
const DAMIAN: AccountIdOf<TestRuntime> = 65;

let accounts = vec![ADAM, TOM, SOFIA, FRED, ANNA, DAMIAN];
let mut project_metadata = default_project_metadata(ISSUER_1);
Expand Down
114 changes: 113 additions & 1 deletion pallets/funding/src/tests/4_contribution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ mod contribute_extrinsic {
#[cfg(test)]
mod success {
use super::*;
use crate::traits::BondingRequirementCalculation;
use frame_support::{dispatch::DispatchResultWithPostInfo, traits::fungible::InspectFreeze};

#[test]
Expand Down Expand Up @@ -1005,7 +1006,7 @@ mod contribute_extrinsic {
fn participant_was_evaluator_and_bidder() {
let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext())));
let issuer = ISSUER_1;
let participant = 42069u32;
let participant = 42069;
let project_metadata = default_project_metadata(issuer);
let mut evaluations = default_evaluations();
evaluations.push((participant, 100 * USD_UNIT).into());
Expand All @@ -1030,6 +1031,117 @@ mod contribute_extrinsic {
remainder_contributions,
);
}

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

let mut project_metadata = default_project_metadata(issuer);
project_metadata.mainnet_token_max_supply = 50_000 * CT_UNIT;
project_metadata.total_allocation_size = 5_000 * CT_UNIT;
project_metadata.minimum_price = <TestRuntime as Config>::PriceProvider::calculate_decimals_aware_price(
PriceOf::<TestRuntime>::from_float(1.0),
USD_DECIMALS,
CT_DECIMALS,
)
.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, None, evaluations, vec![]);
let wap = inst.get_project_details(project_id).weighted_average_price.unwrap();
let otm_multiplier: MultiplierOf<TestRuntime> =
ParticipationMode::OTM.multiplier().try_into().ok().unwrap();

const USDT_ID: u32 = AcceptedFundingAsset::USDT.id();
const USDT_PARTICIPATION: u128 = 3000 * USDT_UNIT;

const OTM_USDT_FEE: u128 = 30 * USDT_UNIT;
let usdt_ed = inst.get_funding_asset_ed(AcceptedFundingAsset::USDT.id());
let required_usdt = UserToFundingAsset::new(BUYER_1, USDT_PARTICIPATION + OTM_USDT_FEE + usdt_ed, USDT_ID);
inst.mint_funding_asset_to(vec![required_usdt.clone()]);

let ct_participation = inst.execute(|| {
<Pallet<TestRuntime>>::funding_asset_to_ct_amount(
project_id,
AcceptedFundingAsset::USDT,
USDT_PARTICIPATION,
)
});
/// USDT has the same decimals and price as our baseline USD
let expected_plmc_bond = <Pallet<TestRuntime>>::calculate_plmc_bond(USDT_PARTICIPATION, otm_multiplier).unwrap();
dbg!(&expected_plmc_bond);
let otm_lock_time = otm_multiplier.calculate_vesting_duration::<TestRuntime>();

let otm_escrow_account =
<TestRuntime as pallet_proxy_bonding::Config>::RootId::get().into_sub_account_truncating(project_id);
let otm_treasury_account = <TestRuntime as pallet_proxy_bonding::Config>::Treasury::get();
let otm_fee_recipient_account = <TestRuntime as pallet_proxy_bonding::Config>::FeeRecipient::get();
let funding_project_escrow = PolimecFunding::fund_account_id(project_id);

assert!(funding_project_escrow != otm_escrow_account);

let pre_participation_treasury_free_plmc = inst.get_free_plmc_balance_for(otm_treasury_account);
let pre_participation_otm_escrow_held_plmc =
inst.get_reserved_plmc_balance_for(otm_escrow_account, HoldReason::Participation.into());
let pre_participation_otm_escrow_usdt =
inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account);
let pre_participation_otm_fee_recipient_usdt =
inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account);
let pre_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BUYER_1);

inst.execute(|| {
assert_ok!(PolimecFunding::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,
ct_participation,
ParticipationMode::OTM,
AcceptedFundingAsset::USDT
));
});

let post_participation_treasury_free_plmc = inst.get_free_plmc_balance_for(otm_treasury_account);
let post_participation_otm_escrow_held_plmc =
inst.get_reserved_plmc_balance_for(otm_escrow_account, HoldReason::Participation.into());
let post_participation_otm_escrow_usdt =
inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account);
let post_participation_otm_fee_recipient_usdt =
inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account);
let post_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BUYER_1);

assert_eq!(
post_participation_treasury_free_plmc,
pre_participation_treasury_free_plmc - expected_plmc_bond - inst.get_ed()
);
assert_eq!(
post_participation_otm_escrow_held_plmc,
pre_participation_otm_escrow_held_plmc + expected_plmc_bond
);
assert_eq!(post_participation_otm_escrow_usdt, pre_participation_otm_escrow_usdt + OTM_USDT_FEE);
assert_eq!(post_participation_otm_fee_recipient_usdt, pre_participation_otm_fee_recipient_usdt);
assert_eq!(post_participation_buyer_usdt, pre_participation_buyer_usdt - USDT_PARTICIPATION - OTM_USDT_FEE);

assert_eq!(inst.go_to_next_state(project_id), ProjectStatus::FundingSuccessful);
assert_eq!(inst.go_to_next_state(project_id), ProjectStatus::SettlementStarted(FundingOutcome::Success));
inst.settle_project(project_id, true);

// let post_settlement_treasury_free_plmc = inst.get_free_plmc_balance_for(otm_treasury_account);
// let post_settlement_otm_escrow_held_plmc = inst.get_free_plmc_balance_for(otm_escrow_account);
// let post_settlement_otm_escrow_usdt = inst.get_free_funding_asset_balance_for(otm_escrow_account, AcceptedFundingAsset::USDT);
// let post_settlement_otm_fee_recipient_usdt = inst.get_free_funding_asset_balance_for(otm_fee_recipient_account, AcceptedFundingAsset::USDT);
// let post_settlement_buyer_usdt = inst.get_free_funding_asset_balance_for(BUYER_1, AcceptedFundingAsset::USDT);

// assert_eq!(post_settlement_treasury_free_plmc, post_participation_treasury_free_plmc);
}
}

#[cfg(test)]
Expand Down
2 changes: 1 addition & 1 deletion pallets/funding/src/tests/6_settlement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ mod settle_evaluation_extrinsic {
RuntimeOrigin::signed(evaluator),
project_id,
evaluator,
evaluator - 21 // The First evaluation index is 0, the first evaluator account is 21
(evaluator - 21) as u32 // The First evaluation index is 0, the first evaluator account is 21
)));
let ct_rewarded = inst.get_ct_asset_balance_for(project_id, evaluator);
assert_close_enough!(ct_rewarded, expected_reward, Perquintill::from_float(0.9999));
Expand Down
Loading

0 comments on commit 086bca3

Please sign in to comment.