diff --git a/pallets/funding/src/benchmarking.rs b/pallets/funding/src/benchmarking.rs index 6a6e3cab5..b1b87c20e 100644 --- a/pallets/funding/src/benchmarking.rs +++ b/pallets/funding/src/benchmarking.rs @@ -2623,9 +2623,6 @@ mod benchmarks { vec![], ); - // let issuer_mint = UserToPLMCBalance::::new(issuer.clone(), (100 * ASSET_UNIT).into()); - // inst.mint_plmc_to(vec![issuer_mint]); - #[block] { Pallet::::do_start_settlement(project_id).unwrap(); @@ -2685,6 +2682,218 @@ mod benchmarks { assert_eq!(project_details.status, ProjectStatus::SettlementStarted(FundingOutcome::FundingFailed)); } + #[benchmark] + fn start_pallet_migration() { + // setup + let mut inst = BenchInstantiator::::new(None); + ::SetPrices::set_prices(); + + let issuer = account::>("issuer", 0, 0); + + let project_metadata = default_project_metadata::(issuer.clone()); + let project_id = inst.create_finished_project( + project_metadata.clone(), + issuer.clone(), + default_evaluations::(), + default_bids::(), + default_community_contributions::(), + vec![], + ); + + let settlement_block = inst.get_update_block(project_id, &UpdateType::StartSettlement).unwrap(); + inst.jump_to_block(settlement_block); + + inst.settle_project(project_id).unwrap(); + + let jwt = get_mock_jwt_with_cid( + issuer.clone(), + InvestorType::Institutional, + generate_did_from_account(issuer.clone()), + project_metadata.clone().policy_ipfs_cid.unwrap(), + ); + + #[extrinsic_call] + start_pallet_migration(RawOrigin::Signed(issuer), jwt, project_id, ParaId::from(6969)); + + // * validity checks * + let project_details = inst.get_project_details(project_id); + assert_eq!(project_details.status, ProjectStatus::CTMigrationStarted); + assert_eq!(project_details.migration_type, Some(MigrationType::Pallet(PalletMigrationInfo { + parachain_id: ParaId::from(6969), + hrmp_channel_status: HRMPChannelStatus { project_to_polimec: ChannelStatus::Closed, polimec_to_project: ChannelStatus::Closed }, + migration_readiness_check: None, + remaining_participants: 13, + }))) + } + + #[benchmark] + fn start_offchain_migration() { + // setup + let mut inst = BenchInstantiator::::new(None); + ::SetPrices::set_prices(); + + let issuer = account::>("issuer", 0, 0); + + let project_metadata = default_project_metadata::(issuer.clone()); + let project_id = inst.create_finished_project( + project_metadata.clone(), + issuer.clone(), + default_evaluations::(), + default_bids::(), + default_community_contributions::(), + vec![], + ); + + let settlement_block = inst.get_update_block(project_id, &UpdateType::StartSettlement).unwrap(); + inst.jump_to_block(settlement_block); + + inst.settle_project(project_id).unwrap(); + + let jwt = get_mock_jwt_with_cid( + issuer.clone(), + InvestorType::Institutional, + generate_did_from_account(issuer.clone()), + project_metadata.clone().policy_ipfs_cid.unwrap(), + ); + + #[extrinsic_call] + start_offchain_migration(RawOrigin::Signed(issuer), jwt, project_id); + + // * validity checks * + let project_details = inst.get_project_details(project_id); + assert_eq!(project_details.status, ProjectStatus::CTMigrationStarted); + assert_eq!(project_details.migration_type, Some(MigrationType::Offchain(OffchainMigrationInfo{ remaining_participants: 13 }))); + } + + #[benchmark] + fn confirm_offchain_migration( + // Amount of migrations to confirm for a single user + x: Linear<1, { MaxParticipationsPerUser::::get() }>, + ) { + // setup + let mut inst = BenchInstantiator::::new(None); + ::SetPrices::set_prices(); + + let issuer = account::>("issuer", 0, 0); + let participant = account::>("test_participant", 0, 0); + + let max_evaluations = (x/3).min(::MaxEvaluationsPerUser::get()); + let max_bids = ((x-max_evaluations)/2).min(::MaxBidsPerUser::get()); + let max_contributions = x-max_evaluations-max_bids; + + let participant_evaluations = (0..max_evaluations).map(|_| UserToUSDBalance::new( + participant.clone(), + (100 * USD_UNIT).into(), + )).collect_vec(); + let participant_bids = (0..max_bids).map(|_| BidParams::new( + participant.clone(), + (500 * CT_UNIT).into(), + 1u8, + AcceptedFundingAsset::USDT)).collect_vec(); + let participant_contributions = (0..max_contributions).map(|_| ContributionParams::new( + participant.clone(), + (10 * CT_UNIT).into(), + 1u8, + AcceptedFundingAsset::USDT)).collect_vec(); + + let mut evaluations = default_evaluations::(); + evaluations.extend(participant_evaluations); + + let mut bids = default_bids::(); + bids.extend(participant_bids); + + let project_metadata = default_project_metadata::(issuer.clone()); + let project_id = inst.create_finished_project( + project_metadata.clone(), + issuer.clone(), + default_evaluations::(), + default_bids::(), + default_community_contributions::(), + vec![], + ); + + + let settlement_block = inst.get_update_block(project_id, &UpdateType::StartSettlement).unwrap(); + inst.jump_to_block(settlement_block); + + inst.settle_project(project_id).unwrap(); + + let jwt = get_mock_jwt_with_cid( + issuer.clone(), + InvestorType::Institutional, + generate_did_from_account(issuer.clone()), + project_metadata.clone().policy_ipfs_cid.unwrap(), + ); + + + crate::Pallet::::start_offchain_migration(RawOrigin::Signed(issuer.clone()).into(), jwt.clone(), project_id).unwrap(); + + let participant_migrations_len = UserMigrations::::get((project_id, participant)).unwrap().1.len(); + assert_eq!(participant_migrations_len as u32, MaxParticipationsPerUser::::get()); + + #[extrinsic_call] + confirm_offchain_migration(RawOrigin::Signed(issuer), project_id, participant); + + // * validity checks * + let project_details = inst.get_project_details(project_id); + assert_eq!(project_details.status, ProjectStatus::CTMigrationStarted); + assert_eq!(project_details.migration_type, Some(MigrationType::Offchain(OffchainMigrationInfo{ remaining_participants: 13 }))); + } + + // We use the `count` built-in method of `CountedStorageNMap`, so this extrinsic's weight is a constant + #[benchmark] + fn mark_project_migration_as_finished() { + // setup + let mut inst = BenchInstantiator::::new(None); + ::SetPrices::set_prices(); + + let issuer = account::>("issuer", 0, 0); + + let project_metadata = default_project_metadata::(issuer.clone()); + let project_id = inst.create_finished_project( + project_metadata.clone(), + issuer.clone(), + evaluations, + bids, + default_community_contributions::(), + participant_contributions, + ); + + + let settlement_block = inst.get_update_block(project_id, &UpdateType::StartSettlement).unwrap(); + inst.jump_to_block(settlement_block); + + inst.settle_project(project_id).unwrap(); + + let jwt = get_mock_jwt_with_cid( + issuer.clone(), + InvestorType::Institutional, + generate_did_from_account(issuer.clone()), + project_metadata.clone().policy_ipfs_cid.unwrap(), + ); + + + crate::Pallet::::start_offchain_migration(RawOrigin::Signed(issuer.clone()).into(), jwt.clone(), project_id).unwrap(); + + let participants = UserMigrations::::iter_key_prefix((project_id,)).collect_vec(); + for participant in participants { + >::confirm_offchain_migration(RawOrigin::Signed(issuer), project_id, participant).unwrap() + } + + + #[extrinsic_call] + mark_project_migration_as_finished(RawOrigin::Signed(issuer), project_id, issuer); + + // * validity checks * + let project_details = inst.get_project_details(project_id); + assert_eq!(project_details.status, ProjectStatus::CTMigrationFinished); + assert_eq!(project_details.migration_type, Some(MigrationType::Offchain(OffchainMigrationInfo{ remaining_participants: 0 }))); + assert_eq!(UserMigrations::::count()); + } + + + + #[cfg(test)] mod tests { use super::*; @@ -2886,5 +3095,26 @@ mod benchmarks { assert_ok!(PalletFunding::::test_end_funding_awaiting_decision_evaluators_slashed()); }); } + + #[test] + fn bench_start_pallet_migration() { + new_test_ext().execute_with(|| { + assert_ok!(PalletFunding::::test_start_pallet_migration()); + }); + } + + #[test] + fn bench_start_offchain_migration() { + new_test_ext().execute_with(|| { + assert_ok!(PalletFunding::::test_start_offchain_migration()); + }); + } + + #[test] + fn bench_confirm_offchain_migration() { + new_test_ext().execute_with(|| { + assert_ok!(PalletFunding::::test_confirm_offchain_migration()); + }); + } } } diff --git a/pallets/funding/src/instantiator/chain_interactions.rs b/pallets/funding/src/instantiator/chain_interactions.rs index 377ca31ab..7f28eafd0 100644 --- a/pallets/funding/src/instantiator/chain_interactions.rs +++ b/pallets/funding/src/instantiator/chain_interactions.rs @@ -1041,7 +1041,6 @@ impl< }, _ => {}, }; - let ct_price = self.get_project_details(project_id).weighted_average_price.unwrap(); let contributors = remainder_contributions.accounts(); let asset_id = remainder_contributions[0].asset.to_assethub_id(); @@ -1055,8 +1054,14 @@ impl< let plmc_remainder_contribution_deposits = self.calculate_contributed_plmc_spent(remainder_contributions.clone(), ct_price, false); + let reducible_evaluator_balances = self.slash_evaluator_balances(plmc_evaluation_deposits); + let remaining_reducible_evaluator_balances = self.generic_map_operation( + vec![reducible_evaluator_balances, plmc_bid_deposits.clone()], + MergeOperation::Subtract, + ); + let necessary_plmc_mint = self.generic_map_operation( - vec![plmc_remainder_contribution_deposits.clone(), plmc_evaluation_deposits], + vec![plmc_remainder_contribution_deposits.clone(), remaining_reducible_evaluator_balances], MergeOperation::Subtract, ); let total_plmc_participation_locked = self.generic_map_operation( @@ -1088,7 +1093,7 @@ impl< HoldReason::Participation(project_id).into(), ); self.do_contribution_transferred_foreign_asset_assertions( - funding_asset_deposits.merge_accounts(MergeOperation::Add), + funding_asset_deposits, project_id, ); self.do_free_plmc_assertions(expected_free_plmc_balances.merge_accounts(MergeOperation::Add)); diff --git a/pallets/funding/src/tests/5_remainder.rs b/pallets/funding/src/tests/5_remainder.rs index 6cda38c95..62880486b 100644 --- a/pallets/funding/src/tests/5_remainder.rs +++ b/pallets/funding/src/tests/5_remainder.rs @@ -1165,6 +1165,35 @@ mod remaining_contribute_extrinsic { }; assert_eq!(account_data, expected_account_data); } + + #[test] + 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 project_metadata = default_project_metadata(issuer); + let mut evaluations = default_evaluations(); + evaluations.push((participant, 100 * USD_UNIT).into()); + let mut bids = default_bids(); + bids.push(BidParams::new(participant, 1000 * CT_UNIT, 1u8, AcceptedFundingAsset::USDT)); + let community_contributions = default_community_buys(); + let mut remainder_contributions = default_remainder_buys(); + remainder_contributions.push(ContributionParams::new( + participant, + 10 * CT_UNIT, + 1u8, + AcceptedFundingAsset::USDT, + )); + + let _project_id = inst.create_finished_project( + project_metadata.clone(), + issuer, + evaluations, + bids, + community_contributions, + remainder_contributions, + ); + } } #[cfg(test)]