diff --git a/Cargo.lock b/Cargo.lock
index 20e8691b4..16d57ca15 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -8262,6 +8262,7 @@ dependencies = [
"serde",
"sp-runtime",
"sp-std",
+ "staging-xcm",
]
[[package]]
diff --git a/integration-tests/penpal/src/lib.rs b/integration-tests/penpal/src/lib.rs
index 1ae1b7f11..970b66109 100644
--- a/integration-tests/penpal/src/lib.rs
+++ b/integration-tests/penpal/src/lib.rs
@@ -82,7 +82,6 @@ use parachains_common::{
};
use sp_runtime::traits::Convert;
use xcm::latest::prelude::BodyId;
-use xcm_executor::XcmExecutor;
/// Balance of an account.
pub type Balance = u128;
diff --git a/integration-tests/penpal/src/weights/mod.rs b/integration-tests/penpal/src/weights/mod.rs
index ed0b4dbcd..ef1ab0d1a 100644
--- a/integration-tests/penpal/src/weights/mod.rs
+++ b/integration-tests/penpal/src/weights/mod.rs
@@ -24,5 +24,4 @@ pub mod rocksdb_weights;
pub use block_weights::constants::BlockExecutionWeight;
pub use extrinsic_weights::constants::ExtrinsicBaseWeight;
-pub use paritydb_weights::constants::ParityDbWeight;
pub use rocksdb_weights::constants::RocksDbWeight;
diff --git a/integration-tests/src/tests/ct_migration.rs b/integration-tests/src/tests/ct_migration.rs
index 403e695cf..9407e592e 100644
--- a/integration-tests/src/tests/ct_migration.rs
+++ b/integration-tests/src/tests/ct_migration.rs
@@ -15,22 +15,13 @@
// along with this program. If not, see .
use crate::*;
-use pallet_funding::{
- assert_close_enough, traits::VestingDurationCalculation, BidStatus, EvaluatorsOutcome, MigrationStatus, Multiplier,
- ProjectId, ProjectsToUpdate, RewardOrSlash,
-};
-use polimec_common::migration_types::{Migration, MigrationInfo, MigrationOrigin, Migrations, ParticipationType};
+use pallet_funding::{assert_close_enough, ProjectId};
+use polimec_common::migration_types::{MigrationStatus, Migrations};
use politest_runtime::Funding;
-use sp_runtime::{traits::Convert, FixedPointNumber, Perquintill};
+use sp_runtime::Perquintill;
use std::collections::HashMap;
use tests::defaults::*;
-fn execute_cleaner(inst: &mut IntegrationInstantiator) {
- PolitestNet::execute_with(|| {
- dbg!(::SuccessToSettlementTime::get() + 25u32);
- inst.advance_time(::SuccessToSettlementTime::get() + 25u32).unwrap();
- });
-}
fn mock_hrmp_establishment(project_id: u32) {
PolitestNet::execute_with(|| {
assert_ok!(Funding::do_set_para_id_for_project(&ISSUER.into(), project_id, ParaId::from(6969u32)));
@@ -46,10 +37,8 @@ fn mock_hrmp_establishment(project_id: u32) {
assert_ok!(Funding::do_handle_channel_accepted(channel_accepted_message));
});
- PenNet::execute_with(|| {
- println!("penpal events:");
- dbg!(PenNet::events());
- });
+ // Required for passing migration ready check.
+ PenNet::execute_with(|| {});
}
fn assert_migration_is_ready(project_id: u32) {
@@ -59,437 +48,143 @@ fn assert_migration_is_ready(project_id: u32) {
});
}
-fn send_migrations(project_id: ProjectId, accounts: Vec) -> HashMap {
- let mut output = HashMap::new();
+fn get_migrations_for_participants(
+ project_id: ProjectId,
+ participants: Vec,
+) -> HashMap {
+ let mut user_migrations = HashMap::new();
PolitestNet::execute_with(|| {
- for account in accounts {
- assert_ok!(Funding::migrate_one_participant(
- PolitestOrigin::signed(account.clone()),
- project_id,
- account.clone()
- ));
-
- let user_evaluations =
- pallet_funding::Evaluations::::iter_prefix_values((project_id, account.clone()));
- let user_bids = pallet_funding::Bids::::iter_prefix_values((project_id, account.clone()))
- .filter(|bid| matches!(bid.status, BidStatus::Accepted | BidStatus::PartiallyAccepted(..)));
- let user_contributions =
- pallet_funding::Contributions::::iter_prefix_values((project_id, account.clone()));
-
- let evaluation_migrations = user_evaluations.map(|evaluation| {
- let evaluator_bytes = ::AccountId32Conversion::convert(
- evaluation.evaluator.clone(),
- );
- assert!(
- matches!(evaluation.ct_migration_status, MigrationStatus::Sent(_)),
- "{:?}'s evaluation was not sent {:?}",
- names()[&evaluator_bytes],
- evaluation
- );
- if let Some(RewardOrSlash::Reward(amount)) = evaluation.rewarded_or_slashed {
- Migration {
- info: MigrationInfo {
- contribution_token_amount: amount,
- vesting_time: Multiplier::new(1u8)
- .unwrap()
- .calculate_vesting_duration::()
- .into(),
- },
- origin: MigrationOrigin {
- user: account.clone().into(),
- id: evaluation.id,
- participation_type: ParticipationType::Evaluation,
- },
- }
- } else {
- panic!("should be rewarded")
- }
- });
- let bid_migrations = user_bids.map(|bid| {
- assert!(matches!(bid.ct_migration_status, MigrationStatus::Sent(_)));
- Migration {
- info: MigrationInfo {
- contribution_token_amount: bid.final_ct_amount,
- vesting_time: bid.multiplier.calculate_vesting_duration::().into(),
- },
- origin: MigrationOrigin {
- user: account.clone().into(),
- id: bid.id,
- participation_type: ParticipationType::Bid,
- },
- }
- });
- let contribution_migrations = user_contributions.map(|contribution| {
- assert!(matches!(contribution.ct_migration_status, MigrationStatus::Sent(_)));
- Migration {
- info: MigrationInfo {
- contribution_token_amount: contribution.ct_amount,
- vesting_time: contribution.multiplier.calculate_vesting_duration::().into(),
- },
- origin: MigrationOrigin {
- user: account.clone().into(),
- id: contribution.id,
- participation_type: ParticipationType::Contribution,
- },
- }
- });
-
- let migrations =
- evaluation_migrations.chain(bid_migrations).chain(contribution_migrations).collect::();
-
- if migrations.clone().inner().is_empty() {
- panic!("no migrations for account: {:?}", account)
- }
- output.insert(account.clone(), migrations);
+ for participant in participants {
+ let (status, migrations) =
+ pallet_funding::UserMigrations::::get(project_id, participant.clone()).unwrap();
+ user_migrations.insert(participant, (status, Migrations::from(migrations.into())));
}
});
- output
+ user_migrations
}
-fn migrations_are_executed(grouped_migrations: Vec) {
- let all_migrations =
- grouped_migrations.iter().flat_map(|migrations| migrations.clone().inner()).collect::>();
- PenNet::execute_with(|| {
- assert_expected_events!(
- PenNet,
- vec![
- PenpalEvent::PolimecReceiver(polimec_receiver::Event::MigrationExecuted{migration}) => {
- migration: all_migrations.contains(&migration),
- },
- ]
- );
- });
-
- // since current way to migrate is by bundling each user's migrations into one, we can assume that all migrations in a group are from the same user
- for migration_group in grouped_migrations {
- let user = migration_group.clone().inner()[0].origin.user;
- assert!(migration_group.origins().iter().all(|origin| origin.user == user));
-
- let user_info = PenNet::account_data_of(user.into());
- assert_close_enough!(user_info.free, migration_group.total_ct_amount(), Perquintill::from_float(0.99));
-
- let vest_scheduled_cts = migration_group
- .inner()
- .iter()
- .filter_map(|migration| {
- if migration.info.vesting_time > 1 {
- Some(migration.info.contribution_token_amount)
- } else {
- None
- }
- })
- .sum::();
+fn send_migrations(project_id: ProjectId, accounts: Vec) {
+ for user in accounts.into_iter() {
+ PolitestNet::execute_with(|| {
+ assert_ok!(Funding::migrate_one_participant(
+ PolitestOrigin::signed(user.clone()),
+ project_id,
+ user.clone()
+ ));
+ });
+ }
+}
- assert_close_enough!(user_info.frozen, vest_scheduled_cts, Perquintill::from_float(0.99));
+fn migrations_are_executed(project_id: ProjectId, accounts: Vec) {
+ let user_migrations = get_migrations_for_participants(project_id, accounts.clone());
+ for account in accounts.into_iter() {
+ let user_info = PenNet::account_data_of(account.clone());
+ PenNet::execute_with(|| {
+ let (_, migrations) = user_migrations.get(&account).unwrap();
+
+ assert_close_enough!(user_info.free, migrations.total_ct_amount(), Perquintill::from_float(0.99));
+
+ let vest_scheduled_cts = migrations
+ .clone()
+ .inner()
+ .iter()
+ .filter_map(|migration| {
+ if migration.info.vesting_time > 1 {
+ Some(migration.info.contribution_token_amount)
+ } else {
+ None
+ }
+ })
+ .sum::();
+ assert_close_enough!(user_info.frozen, vest_scheduled_cts, Perquintill::from_float(0.99));
+ });
}
}
-fn migrations_are_confirmed(project_id: u32, grouped_migrations: Vec) {
- let ordered_grouped_origins = grouped_migrations
- .clone()
- .into_iter()
- .map(|group| {
- let mut origins = group.origins();
- origins.sort();
- origins
- })
- .collect::>();
+fn migrations_are_confirmed(project_id: u32, accounts: Vec) {
+ let user_migrations = get_migrations_for_participants(project_id, accounts.clone());
PolitestNet::execute_with(|| {
- assert_expected_events!(
- PolitestNet,
- vec![
- PolitestEvent::Funding(pallet_funding::Event::MigrationsConfirmed{project_id, migration_origins}) => {
- project_id: project_id == project_id,
- migration_origins: {
- let mut migration_origins = migration_origins.to_vec();
- migration_origins.sort();
- ordered_grouped_origins.contains(&migration_origins)
- },
- },
- ]
- );
- let all_migration_origins =
- grouped_migrations.iter().flat_map(|migrations| migrations.clone().origins()).collect::>();
- for migration_origin in all_migration_origins {
- match migration_origin.participation_type {
- ParticipationType::Evaluation => {
- let evaluation = pallet_funding::Evaluations::::get((
- project_id,
- AccountId::from(migration_origin.user),
- migration_origin.id,
- ))
- .unwrap();
- assert_eq!(evaluation.ct_migration_status, MigrationStatus::Confirmed);
- },
- ParticipationType::Bid => {
- let bid = pallet_funding::Bids::::get((
- project_id,
- AccountId::from(migration_origin.user),
- migration_origin.id,
- ))
- .unwrap();
- assert_eq!(bid.ct_migration_status, MigrationStatus::Confirmed);
- },
- ParticipationType::Contribution => {
- let contribution = pallet_funding::Contributions::::get((
- project_id,
- AccountId::from(migration_origin.user),
- migration_origin.id,
- ))
- .unwrap();
- assert_eq!(contribution.ct_migration_status, MigrationStatus::Confirmed);
- },
- }
+ for user in accounts.iter() {
+ let (current_status, _) = user_migrations.get(user).unwrap();
+ assert_eq!(current_status, &MigrationStatus::Confirmed);
}
});
}
-fn vest_migrations(grouped_migrations: Vec) {
- let biggest_time = grouped_migrations.iter().map(|migrations| migrations.biggest_vesting_time()).max().unwrap();
+fn vest_migrations(project_id: u32, accounts: Vec) {
+ let user_migrations = get_migrations_for_participants(project_id, accounts.clone());
+ let biggest_time =
+ user_migrations.iter().map(|(_, (_, migrations))| migrations.biggest_vesting_time()).max().unwrap();
+
PenNet::execute_with(|| {
PenpalSystem::set_block_number(biggest_time as u32 + 1u32);
});
- for migration_group in grouped_migrations {
- let user = migration_group.clone().inner()[0].origin.user;
- assert!(migration_group.origins().iter().all(|origin| origin.user == user));
- // check if any vesting_time is bigger than 1, which means the balance was actually frozen
- let has_frozen_balance = migration_group.inner().iter().any(|migration| migration.info.vesting_time > 1);
- if has_frozen_balance {
- PenNet::execute_with(|| {
- assert_ok!(pallet_vesting::Pallet::::vest(PenpalOrigin::signed(user.into())));
- });
- }
+ for account in accounts {
+ let user_info = PenNet::account_data_of(account.clone());
+ PenNet::execute_with(|| {
+ if user_info.frozen > 0 {
+ assert_ok!(pallet_vesting::Pallet::::vest(PenpalOrigin::signed(account)));
+ }
+ });
}
}
-fn migrations_are_vested(grouped_migrations: Vec) {
- for migration_group in grouped_migrations {
- let user = migration_group.clone().inner()[0].origin.user;
- assert!(migration_group.origins().iter().all(|origin| origin.user == user));
- let user_info = PenNet::account_data_of(user.into());
+fn migrations_are_vested(project_id: u32, accounts: Vec) {
+ let user_migrations = get_migrations_for_participants(project_id, accounts.clone());
+ user_migrations.iter().for_each(|(user, (_, migrations))| {
+ let user_info = PenNet::account_data_of(user.clone());
assert_eq!(user_info.frozen, 0);
- assert_eq!(user_info.free, migration_group.total_ct_amount());
- }
-}
-
-#[test]
-fn migration_check() {
- let mut inst = IntegrationInstantiator::new(None);
- let project_id = PolitestNet::execute_with(|| {
- let project_id = inst.create_finished_project(
- default_project_metadata(0, ISSUER.into()),
- ISSUER.into(),
- default_evaluations(),
- default_bids(),
- default_community_contributions(),
- vec![],
- );
-
- inst.advance_time(::SuccessToSettlementTime::get() + 1u32).unwrap();
- project_id
+ assert_eq!(user_info.free, migrations.clone().total_ct_amount());
});
-
- mock_hrmp_establishment(project_id);
-
- assert_migration_is_ready(project_id);
}
-#[test]
-fn migration_is_sent() {
+fn create_settled_project() -> (ProjectId, Vec) {
let mut inst = IntegrationInstantiator::new(None);
- let participants =
- vec![EVAL_1, EVAL_2, EVAL_3, BIDDER_1, BIDDER_2, BIDDER_3, BIDDER_4, BUYER_1, BUYER_2, BUYER_3, BUYER_4]
- .into_iter()
- .map(|x| AccountId::from(x))
- .collect::>();
- let project_id = PolitestNet::execute_with(|| {
- inst.create_finished_project(
- default_project_metadata(0, ISSUER.into()),
- ISSUER.into(),
- default_evaluations(),
- default_bids(),
- default_community_contributions(),
- default_remainder_contributions(),
- )
- });
-
PolitestNet::execute_with(|| {
- dbg!(PolimecSystem::block_number());
- dbg!(ProjectsToUpdate::::iter().collect::>());
- });
-
- execute_cleaner(&mut inst);
-
- mock_hrmp_establishment(project_id);
-
- assert_migration_is_ready(project_id);
-
- send_migrations(project_id, participants);
-}
-
-#[test]
-fn migration_is_executed_on_project_and_confirmed_on_polimec() {
- let mut inst = IntegrationInstantiator::new(None);
- let participants =
- vec![EVAL_1, EVAL_2, EVAL_3, BIDDER_2, BIDDER_3, BIDDER_4, BIDDER_5, BUYER_2, BUYER_3, BUYER_4, BUYER_5]
- .into_iter()
- .map(|x| AccountId::from(x))
- .collect::>();
- let project_id = PolitestNet::execute_with(|| {
- inst.create_finished_project(
+ let project_id = inst.create_finished_project(
default_project_metadata(0, ISSUER.into()),
ISSUER.into(),
default_evaluations(),
default_bids(),
default_community_contributions(),
default_remainder_contributions(),
- )
- });
- execute_cleaner(&mut inst);
-
- mock_hrmp_establishment(project_id);
-
- assert_migration_is_ready(project_id);
-
- let migrations_map = send_migrations(project_id, participants);
- let grouped_migrations = migrations_map.values().cloned().collect::>();
-
- migrations_are_executed(grouped_migrations.clone());
-
- migrations_are_confirmed(project_id, grouped_migrations.clone());
-}
-
-#[test]
-fn vesting_over_several_blocks_on_project() {
- let mut inst = IntegrationInstantiator::new(None);
- let participants = vec![EVAL_1, EVAL_2, EVAL_3, BIDDER_1, BIDDER_2, BUYER_1, BUYER_2]
- .into_iter()
- .map(|x| AccountId::from(x))
- .collect::>();
-
- let bids = default_bids();
- let community_contributions = default_community_contributions();
- let remainder_contributions = default_remainder_contributions();
-
- let project_id = PolitestNet::execute_with(|| {
- inst.create_finished_project(
- default_project_metadata(0, ISSUER.into()),
- ISSUER.into(),
- default_evaluations(),
- bids,
- community_contributions,
- remainder_contributions,
- )
- });
- execute_cleaner(&mut inst);
-
- mock_hrmp_establishment(project_id);
-
- assert_migration_is_ready(project_id);
-
- // Migrate is sent
- let user_migrations = send_migrations(project_id, participants);
- let grouped_migrations = user_migrations.values().cloned().collect::>();
-
- migrations_are_executed(grouped_migrations.clone());
-
- migrations_are_confirmed(project_id, grouped_migrations.clone());
-
- vest_migrations(grouped_migrations.clone());
-
- migrations_are_vested(grouped_migrations.clone());
+ );
+ inst.advance_time(::SuccessToSettlementTime::get()).unwrap();
+ let mut participants: Vec =
+ pallet_funding::Evaluations::::iter_prefix_values((project_id,))
+ .map(|eval| eval.evaluator)
+ .chain(pallet_funding::Bids::::iter_prefix_values((project_id,)).map(|bid| bid.bidder))
+ .chain(
+ pallet_funding::Contributions::::iter_prefix_values((project_id,))
+ .map(|contribution| contribution.contributor),
+ )
+ .collect();
+ participants.sort();
+ participants.dedup();
+
+ inst.settle_project(project_id).unwrap();
+ (project_id, participants)
+ })
}
#[test]
-fn disallow_duplicated_migrations_on_receiver_pallet() {
- let mut inst = IntegrationInstantiator::new(None);
-
- let project_id = PolitestNet::execute_with(|| {
- inst.create_finished_project(
- default_project_metadata(0, ISSUER.into()),
- ISSUER.into(),
- default_evaluations(),
- default_bids(),
- default_community_contributions(),
- default_remainder_contributions(),
- )
- });
-
- let project_details = PolitestNet::execute_with(|| inst.get_project_details(project_id));
- if let EvaluatorsOutcome::Rewarded(info) = project_details.evaluation_round_info.evaluators_outcome {
- println!("rewarded: {:?}", info);
- } else {
- panic!("should be rewarded")
- }
-
- let participants = vec![
- EVAL_1, EVAL_2, EVAL_3, EVAL_4, BIDDER_1, BIDDER_2, BIDDER_3, BIDDER_4, BIDDER_5, BIDDER_6, BUYER_1, BUYER_2,
- BUYER_3, BUYER_4, BUYER_5, BUYER_6,
- ]
- .into_iter()
- .map(|x| AccountId::from(x))
- .collect::>();
+fn full_migration_test() {
+ let (project_id, participants) = create_settled_project();
- execute_cleaner(&mut inst);
+ dbg!(get_migrations_for_participants(project_id, participants.clone()));
mock_hrmp_establishment(project_id);
assert_migration_is_ready(project_id);
// Migrate is sent
- let user_migrations = send_migrations(project_id, participants);
- let grouped_migrations = user_migrations.values().cloned().collect::>();
-
- migrations_are_executed(grouped_migrations.clone());
-
- migrations_are_confirmed(project_id, grouped_migrations.clone());
+ send_migrations(project_id, participants.clone());
- vest_migrations(grouped_migrations.clone());
+ migrations_are_executed(project_id, participants.clone());
- migrations_are_vested(grouped_migrations.clone());
+ migrations_are_confirmed(project_id, participants.clone());
- // just any number that lets us execute our xcm's
- for migrations in grouped_migrations.clone() {
- for (_, xcm) in PolitestFundingPallet::construct_migration_xcm_messages(migrations) {
- let _call: ::RuntimeCall =
- pallet_funding::Call::confirm_migrations { query_id: Default::default(), response: Default::default() }
- .into();
-
- let max_weight = Weight::from_parts(700_000_000, 10_000);
- let mut instructions = xcm.into_inner();
- instructions.push(ReportTransactStatus(QueryResponseInfo {
- destination: ParentThen(X1(Parachain(PolitestNet::para_id().into()))).into(),
- query_id: 69,
- max_weight,
- }));
- let xcm = Xcm(instructions);
- let project_multilocation = MultiLocation { parents: 1, interior: X1(Parachain(PenNet::para_id().into())) };
-
- PolitestNet::execute_with(|| {
- PolitestXcmPallet::send_xcm(Here, project_multilocation, xcm).unwrap();
- });
- }
- }
+ vest_migrations(project_id, participants.clone());
- // each duplicated migration was skipped (in this case we duplicated all of them)
- let all_migrations =
- grouped_migrations.iter().flat_map(|migrations| migrations.clone().inner()).collect::>();
- PenNet::execute_with(|| {
- assert_expected_events!(
- PenNet,
- vec![
- PenpalEvent::PolimecReceiver(polimec_receiver::Event::DuplicatedMigrationSkipped{migration}) => {
- migration: all_migrations.contains(&migration),
- },
- ]
- );
- });
-
- migrations_are_vested(grouped_migrations.clone());
-}
-
-#[ignore]
-#[test]
-fn failing_bid_doesnt_get_migrated() {
- todo!();
+ migrations_are_vested(project_id, participants.clone());
}
diff --git a/integration-tests/src/tests/e2e.rs b/integration-tests/src/tests/e2e.rs
index 65ce2a8ee..cd134543c 100644
--- a/integration-tests/src/tests/e2e.rs
+++ b/integration-tests/src/tests/e2e.rs
@@ -398,7 +398,7 @@ fn ct_minted() {
let mut inst = IntegrationInstantiator::new(None);
PolitestNet::execute_with(|| {
- let _ = inst.create_finished_project(
+ let project_id = inst.create_finished_project(
excel_project(0),
ISSUER.into(),
excel_evaluators(),
@@ -408,7 +408,7 @@ fn ct_minted() {
);
inst.advance_time(::SuccessToSettlementTime::get()).unwrap();
- inst.advance_time(10).unwrap();
+ inst.settle_project(project_id).unwrap();
for (contributor, expected_amount, project_id) in excel_ct_amounts() {
let minted = inst
@@ -433,7 +433,7 @@ fn ct_migrated() {
);
inst.advance_time(::SuccessToSettlementTime::get()).unwrap();
- inst.advance_time(10).unwrap();
+ inst.settle_project(project_id).unwrap();
for (contributor, expected_amount, project_id) in excel_ct_amounts() {
let minted = inst
diff --git a/pallets/funding/src/benchmarking.rs b/pallets/funding/src/benchmarking.rs
index 2047b8469..b957b8c35 100644
--- a/pallets/funding/src/benchmarking.rs
+++ b/pallets/funding/src/benchmarking.rs
@@ -736,21 +736,16 @@ mod benchmarks {
.last()
.unwrap();
- match stored_evaluation {
- EvaluationInfo {
- project_id,
- evaluator,
- original_plmc_bond,
- current_plmc_bond,
- rewarded_or_slashed,
- ..
- } if project_id == project_id &&
- evaluator == evaluation.account.clone() &&
- original_plmc_bond == extrinsic_plmc_bonded &&
- current_plmc_bond == extrinsic_plmc_bonded &&
- rewarded_or_slashed.is_none() => {},
- _ => assert!(false, "Evaluation is not stored correctly"),
- }
+ let correct = match stored_evaluation {
+ EvaluationInfo { project_id, evaluator, original_plmc_bond, current_plmc_bond, .. }
+ if project_id == project_id &&
+ evaluator == evaluation.account.clone() &&
+ original_plmc_bond == extrinsic_plmc_bonded &&
+ current_plmc_bond == extrinsic_plmc_bonded =>
+ true,
+ _ => false,
+ };
+ assert!(correct, "Evaluation is not stored correctly");
// Balances
let bonded_plmc = inst.get_reserved_plmc_balances_for(
@@ -1031,10 +1026,7 @@ mod benchmarks {
funding_asset_amount_locked: None,
multiplier: Some(bid_params.multiplier),
plmc_bond: None,
- plmc_vesting_info: Some(None),
when: None,
- funds_released: Some(false),
- ct_minted: Some(false),
};
Bids::::iter_prefix_values((project_id, bidder.clone()))
.find(|stored_bid| bid_filter.matches_bid(stored_bid))
@@ -1458,255 +1450,36 @@ mod benchmarks {
}
#[benchmark]
- fn evaluation_unbond_for() {
- // setup
- let mut inst = BenchInstantiator::::new(None);
-
- // real benchmark starts at block 0, and we can't call `events()` at block 0
- inst.advance_time(1u32.into()).unwrap();
-
- let issuer = account::>("issuer", 0, 0);
- let evaluations = default_evaluations::();
- let evaluator = evaluations[0].account.clone();
- whitelist_account!(evaluator);
-
- let project_id = inst.create_finished_project(
- default_project::(inst.get_new_nonce(), issuer.clone()),
- issuer,
- evaluations,
- default_bids::(),
- default_community_contributions::(),
- vec![],
- );
-
- run_blocks_to_execute_next_transition(project_id, UpdateType::StartSettlement, &mut inst);
-
- assert_eq!(inst.get_project_details(project_id).status, ProjectStatus::FundingSuccessful);
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Success(CleanerState::Initialized(PhantomData))
- );
-
- let evaluation_to_unbond =
- inst.execute(|| Evaluations::::iter_prefix_values((project_id, evaluator.clone())).next().unwrap());
-
- inst.execute(|| {
- PalletFunding::::evaluation_reward_payout_for(
- ::RuntimeOrigin::signed(evaluator.clone().into()),
- project_id,
- evaluator.clone(),
- evaluation_to_unbond.id,
- )
- .expect("")
- });
-
- #[extrinsic_call]
- evaluation_unbond_for(
- RawOrigin::Signed(evaluator.clone()),
- project_id,
- evaluator.clone(),
- evaluation_to_unbond.id,
- );
-
- // * validity checks *
- // Balance
- let bonded_plmc = inst
- .get_reserved_plmc_balances_for(vec![evaluator.clone()], HoldReason::Evaluation(project_id).into())[0]
- .plmc_amount;
- assert_eq!(bonded_plmc, 0.into());
-
- // Events
- frame_system::Pallet::::assert_last_event(
- Event::BondReleased {
- project_id,
- amount: evaluation_to_unbond.current_plmc_bond,
- bonder: evaluator.clone(),
- releaser: evaluator,
- }
- .into(),
- );
- }
-
- #[benchmark]
- fn evaluation_reward_payout_for_with_ct_account_creation() {
- // setup
- let mut inst = BenchInstantiator::::new(None);
-
- // real benchmark starts at block 0, and we can't call `events()` at block 0
- inst.advance_time(1u32.into()).unwrap();
-
- let issuer = account::>("issuer", 0, 0);
- let evaluations: Vec> = default_evaluations::();
- let evaluator: AccountIdOf = evaluations[0].account.clone();
- whitelist_account!(evaluator);
-
- let project_id = inst.create_finished_project(
- default_project::(inst.get_new_nonce(), issuer.clone()),
- issuer,
- evaluations,
- default_bids::(),
- default_community_contributions::(),
- vec![],
- );
-
- run_blocks_to_execute_next_transition(project_id, UpdateType::StartSettlement, &mut inst);
-
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Success(CleanerState::Initialized(PhantomData))
- );
-
- let evaluation_to_unbond =
- inst.execute(|| Evaluations::::iter_prefix_values((project_id, evaluator.clone())).next().unwrap());
-
- #[extrinsic_call]
- evaluation_reward_payout_for(
- RawOrigin::Signed(evaluator.clone()),
- project_id,
- evaluator.clone(),
- evaluation_to_unbond.id,
- );
-
- // * validity checks *
- // Storage
- let stored_evaluation =
- Evaluations::::get((project_id, evaluator.clone(), evaluation_to_unbond.id)).unwrap();
- assert!(stored_evaluation.rewarded_or_slashed.is_some());
-
- // Balances
- let project_details = ProjectsDetails::::get(project_id).unwrap();
- let reward_info = match project_details.evaluation_round_info.evaluators_outcome {
- EvaluatorsOutcome::Rewarded(reward_info) => reward_info,
- _ => panic!("EvaluatorsOutcome should be Rewarded"),
- };
- let total_reward =
- BenchInstantiator::::calculate_total_reward_for_evaluation(stored_evaluation.clone(), reward_info);
- let ct_amount = inst.get_ct_asset_balances_for(project_id, vec![evaluator.clone()])[0];
- assert_eq!(ct_amount, total_reward);
-
- // Events
- frame_system::Pallet::::assert_last_event(
- Event::EvaluationRewarded {
- project_id,
- evaluator: evaluator.clone(),
- id: stored_evaluation.id,
- amount: total_reward,
- caller: evaluator,
- }
- .into(),
- );
- }
-
- #[benchmark]
- fn evaluation_reward_payout_for_no_ct_account_creation() {
+ fn decide_project_outcome(
+ // Insertion attempts in add_to_update_store. Total amount of storage items iterated through in `ProjectsToUpdate`. Leave one free to make the extrinsic pass
+ x: Linear<1, { ::MaxProjectsToUpdateInsertionAttempts::get() - 1 }>,
+ ) {
// setup
let mut inst = BenchInstantiator::::new(None);
- // real benchmark starts at block 0, and we can't call `events()` at block 0
- inst.advance_time(1u32.into()).unwrap();
-
- let issuer = account::>("issuer", 0, 0);
- let mut evaluations = default_evaluations::();
- let evaluator: AccountIdOf = evaluations[0].account.clone();
- evaluations[1].account = evaluator.clone();
- whitelist_account!(evaluator);
-
- let project_id = inst.create_finished_project(
- default_project::(inst.get_new_nonce(), issuer.clone()),
- issuer,
- evaluations,
- default_bids::(),
- default_community_contributions::(),
- vec![],
- );
-
- run_blocks_to_execute_next_transition(project_id, UpdateType::StartSettlement, &mut inst);
-
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Success(CleanerState::Initialized(PhantomData))
- );
-
- let mut evaluations_to_unbond =
- inst.execute(|| Evaluations::::iter_prefix_values((project_id, evaluator.clone())));
-
- let pre_evaluation = evaluations_to_unbond.next().unwrap();
- let bench_evaluation = evaluations_to_unbond.next().unwrap();
-
- Pallet::::evaluation_reward_payout_for(
- RawOrigin::Signed(evaluator.clone()).into(),
- project_id,
- evaluator.clone(),
- pre_evaluation.id,
- )
- .unwrap();
-
- #[extrinsic_call]
- evaluation_reward_payout_for(
- RawOrigin::Signed(evaluator.clone()),
- project_id,
- evaluator.clone(),
- bench_evaluation.id,
- );
-
- // * validity checks *
- // Storage
- let stored_evaluation = Evaluations::::get((project_id, evaluator.clone(), bench_evaluation.id)).unwrap();
- assert!(stored_evaluation.rewarded_or_slashed.is_some());
-
- // Balances
- let project_details = ProjectsDetails::::get(project_id).unwrap();
- let reward_info = match project_details.evaluation_round_info.evaluators_outcome {
- EvaluatorsOutcome::Rewarded(reward_info) => reward_info,
- _ => panic!("EvaluatorsOutcome should be Rewarded"),
- };
-
- let pre_reward =
- BenchInstantiator::::calculate_total_reward_for_evaluation(pre_evaluation.clone(), reward_info.clone());
- let bench_reward =
- BenchInstantiator::::calculate_total_reward_for_evaluation(bench_evaluation.clone(), reward_info);
- let ct_amount = inst.get_ct_asset_balances_for(project_id, vec![evaluator.clone()])[0];
- assert_eq!(ct_amount, pre_reward + bench_reward);
-
- // Events
- frame_system::Pallet::::assert_last_event(
- Event::EvaluationRewarded {
- project_id,
- evaluator: evaluator.clone(),
- id: stored_evaluation.id,
- amount: bench_reward,
- caller: evaluator,
- }
- .into(),
- );
- }
-
- #[benchmark]
- fn evaluation_slash_for() {
- // setup
- let mut inst = BenchInstantiator::::new(None);
+ // We need to leave enough block numbers to fill `ProjectsToUpdate` before our project insertion
- // real benchmark starts at block 0, and we can't call `events()` at block 0
- inst.advance_time(1u32.into()).unwrap();
+ let time_advance: u32 = x + 2;
+ frame_system::Pallet::::set_block_number(time_advance.into());
let issuer = account::>("issuer", 0, 0);
- let evaluations = default_evaluations::();
- let evaluator = evaluations[0].account.clone();
- whitelist_account!(evaluator);
+ whitelist_account!(issuer);
let project_metadata = default_project::(inst.get_new_nonce(), issuer.clone());
let target_funding_amount: BalanceOf =
project_metadata.minimum_price.saturating_mul_int(project_metadata.total_allocation_size);
+ let evaluations = default_evaluations::();
let bids = BenchInstantiator::generate_bids_from_total_usd(
- Percent::from_percent(15) * target_funding_amount,
- 10u128.into(),
+ Percent::from_percent(30) * target_funding_amount,
+ project_metadata.minimum_price,
default_weights(),
default_bidders::(),
default_bidder_multipliers(),
);
+
let contributions = BenchInstantiator::generate_contributions_from_total_usd(
- Percent::from_percent(10) * target_funding_amount,
+ Percent::from_percent(40) * target_funding_amount,
project_metadata.minimum_price,
default_weights(),
default_community_contributors::(),
@@ -1714,59 +1487,33 @@ mod benchmarks {
);
let project_id =
- inst.create_finished_project(project_metadata, issuer, evaluations, bids, contributions, vec![]);
+ inst.create_finished_project(project_metadata, issuer.clone(), evaluations, bids, contributions, vec![]);
inst.advance_time(One::one()).unwrap();
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Failure(CleanerState::Initialized(PhantomData))
- );
- let evaluation_to_unbond =
- inst.execute(|| Evaluations::::iter_prefix_values((project_id, evaluator.clone())).next().unwrap());
+ let current_block = inst.current_block();
+ let insertion_block_number: BlockNumberFor = current_block + One::one();
+
+ fill_projects_to_update::(x, insertion_block_number);
+ let jwt = get_mock_jwt(issuer.clone(), InvestorType::Institutional, generate_did_from_account(issuer.clone()));
#[extrinsic_call]
- evaluation_slash_for(
- RawOrigin::Signed(evaluator.clone()),
- project_id,
- evaluator.clone(),
- evaluation_to_unbond.id,
- );
+ decide_project_outcome(RawOrigin::Signed(issuer), jwt, project_id, FundingOutcomeDecision::AcceptFunding);
// * validity checks *
// Storage
- let stored_evaluation =
- Evaluations::::get((project_id, evaluator.clone(), evaluation_to_unbond.id)).unwrap();
- assert!(stored_evaluation.rewarded_or_slashed.is_some());
- let slashed_amount = T::EvaluatorSlash::get() * evaluation_to_unbond.original_plmc_bond;
- let current_plmc_bond = evaluation_to_unbond.current_plmc_bond.saturating_sub(slashed_amount);
- assert_eq!(stored_evaluation.current_plmc_bond, current_plmc_bond);
-
- // Balance
- let treasury_account = T::ProtocolGrowthTreasury::get();
- let bonded_plmc = inst
- .get_reserved_plmc_balances_for(vec![evaluator.clone()], HoldReason::Evaluation(project_id).into())[0]
- .plmc_amount;
- assert_eq!(bonded_plmc, stored_evaluation.current_plmc_bond);
- let free_treasury_plmc = inst.get_free_plmc_balances_for(vec![treasury_account])[0].plmc_amount;
- let ed = BenchInstantiator::::get_ed();
- assert_eq!(free_treasury_plmc, slashed_amount + ed);
+ let maybe_transition =
+ inst.get_update_block(project_id, &UpdateType::ProjectDecision(FundingOutcomeDecision::AcceptFunding));
+ assert!(maybe_transition.is_some());
// Events
frame_system::Pallet::::assert_last_event(
- Event::EvaluationSlashed {
- project_id,
- evaluator: evaluator.clone(),
- id: stored_evaluation.id,
- amount: slashed_amount,
- caller: evaluator,
- }
- .into(),
+ Event::ProjectOutcomeDecided { project_id, decision: FundingOutcomeDecision::AcceptFunding }.into(),
);
}
#[benchmark]
- fn bid_ct_mint_for_with_ct_account_creation() {
+ fn settle_successful_evaluation() {
// setup
let mut inst = BenchInstantiator::::new(None);
@@ -1774,511 +1521,86 @@ mod benchmarks {
inst.advance_time(1u32.into()).unwrap();
let issuer = account::>("issuer", 0, 0);
- let bids = default_bids::();
- let bidder = bids[0].bidder.clone();
- whitelist_account!(bidder);
+ let evaluations: Vec> = default_evaluations::();
+ let evaluator: AccountIdOf = evaluations[0].account.clone();
+ whitelist_account!(evaluator);
let project_id = inst.create_finished_project(
default_project::(inst.get_new_nonce(), issuer.clone()),
issuer,
- default_evaluations::(),
- bids,
+ evaluations,
+ default_bids::(),
default_community_contributions::(),
vec![],
);
run_blocks_to_execute_next_transition(project_id, UpdateType::StartSettlement, &mut inst);
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Success(CleanerState::Initialized(PhantomData))
- );
-
- let bid_to_mint_ct =
- inst.execute(|| Bids::::iter_prefix_values((project_id, bidder.clone())).next().unwrap());
+ let evaluation_to_settle =
+ inst.execute(|| Evaluations::::iter_prefix_values((project_id, evaluator.clone())).next().unwrap());
#[extrinsic_call]
- bid_ct_mint_for(RawOrigin::Signed(bidder.clone()), project_id, bidder.clone(), bid_to_mint_ct.id);
+ settle_successful_evaluation(
+ RawOrigin::Signed(evaluator.clone()),
+ project_id,
+ evaluator.clone(),
+ evaluation_to_settle.id,
+ );
// * validity checks *
- // Storage
- let stored_bid = Bids::::get((project_id, bidder.clone(), bid_to_mint_ct.id)).unwrap();
- assert!(stored_bid.ct_minted);
+ // Evaluation should be removed
+ assert!(Evaluations::::get((project_id, evaluator.clone(), evaluation_to_settle.id)).is_none());
// Balances
- let ct_amount = inst.get_ct_asset_balances_for(project_id, vec![bidder.clone()])[0];
- assert_eq!(stored_bid.final_ct_amount, ct_amount);
-
- // Events
- frame_system::Pallet::::assert_last_event(
- Event::ContributionTokenMinted { releaser: bidder.clone(), project_id, claimer: bidder, amount: ct_amount }
- .into(),
- );
- }
-
- #[benchmark]
- fn bid_ct_mint_for_no_ct_account_creation() {
- // setup
- let mut inst = BenchInstantiator::::new(None);
-
- // real benchmark starts at block 0, and we can't call `events()` at block 0
- inst.advance_time(1u32.into()).unwrap();
-
- let issuer = account::>("issuer", 0, 0);
- let bids: Vec> = default_bids::();
- let bidder = bids[0].bidder.clone();
- whitelist_account!(bidder);
-
- let project_id = inst.create_finished_project(
- default_project::(inst.get_new_nonce(), issuer.clone()),
- issuer,
- default_evaluations::(),
- bids,
- default_community_contributions::(),
- vec![],
- );
-
- run_blocks_to_execute_next_transition(project_id, UpdateType::StartSettlement, &mut inst);
-
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Success(CleanerState::Initialized(PhantomData))
- );
-
- let mut bids_to_mint_ct = inst.execute(|| Bids::::iter_prefix_values((project_id, bidder.clone())));
-
- let bench_bid_to_mint_ct = bids_to_mint_ct.next().unwrap();
-
- #[extrinsic_call]
- bid_ct_mint_for(RawOrigin::Signed(bidder.clone()), project_id, bidder.clone(), bench_bid_to_mint_ct.id);
-
- // * validity checks *
- // Storage
- let stored_bid = Bids::::get((project_id, bidder.clone(), bench_bid_to_mint_ct.id)).unwrap();
- assert!(stored_bid.ct_minted);
-
- // Balances
- let ct_amount = inst.get_ct_asset_balances_for(project_id, vec![bidder.clone()])[0];
- assert_eq!(ct_amount, stored_bid.final_ct_amount);
-
- // Events
- frame_system::Pallet::::assert_last_event(
- Event::ContributionTokenMinted {
- releaser: bidder.clone(),
- project_id,
- claimer: bidder,
- amount: bench_bid_to_mint_ct.final_ct_amount,
- }
- .into(),
- );
- }
-
- #[benchmark]
- fn contribution_ct_mint_for_with_ct_account_creation() {
- // setup
- let mut inst = BenchInstantiator::::new(None);
-
- // real benchmark starts at block 0, and we can't call `events()` at block 0
- inst.advance_time(1u32.into()).unwrap();
-
- let issuer = account::>("issuer", 0, 0);
- let contributions = default_community_contributions::();
- let contributor = contributions[0].contributor.clone();
- whitelist_account!(contributor);
-
- let project_id = inst.create_finished_project(
- default_project::(inst.get_new_nonce(), issuer.clone()),
- issuer,
- default_evaluations::(),
- default_bids::(),
- contributions,
- vec![],
- );
-
- run_blocks_to_execute_next_transition(project_id, UpdateType::StartSettlement, &mut inst);
-
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Success(CleanerState::Initialized(PhantomData))
- );
-
- let contribution_to_mint_ct =
- inst.execute(|| Contributions::::iter_prefix_values((project_id, contributor.clone())).next().unwrap());
-
- #[extrinsic_call]
- contribution_ct_mint_for(
- RawOrigin::Signed(contributor.clone()),
- project_id,
- contributor.clone(),
- contribution_to_mint_ct.id,
- );
-
- // * validity checks *
- // Storage
- let stored_contribution =
- Contributions::::get((project_id, contributor.clone(), contribution_to_mint_ct.id)).unwrap();
- assert!(stored_contribution.ct_minted);
-
- // Balances
- let ct_amount = inst.get_ct_asset_balances_for(project_id, vec![contributor.clone()])[0];
- assert_eq!(stored_contribution.ct_amount, ct_amount);
-
- // Events
- frame_system::Pallet::::assert_last_event(
- Event::ContributionTokenMinted {
- releaser: contributor.clone(),
- project_id,
- claimer: contributor,
- amount: ct_amount,
- }
- .into(),
- );
- }
-
- #[benchmark]
- fn contribution_ct_mint_for_no_ct_account_creation() {
- // setup
- let mut inst = BenchInstantiator::::new(None);
-
- // real benchmark starts at block 0, and we can't call `events()` at block 0
- inst.advance_time(1u32.into()).unwrap();
-
- let issuer = account::>("issuer", 0, 0);
- let mut contributions: Vec> = default_community_contributions::();
- let contributor = contributions[0].contributor.clone();
- contributions[1].contributor = contributor.clone();
- whitelist_account!(contributor);
-
- let project_id = inst.create_finished_project(
- default_project::(inst.get_new_nonce(), issuer.clone()),
- issuer,
- default_evaluations::(),
- default_bids::(),
- contributions,
- vec![],
- );
-
- run_blocks_to_execute_next_transition(project_id, UpdateType::StartSettlement, &mut inst);
-
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Success(CleanerState::Initialized(PhantomData))
- );
-
- let mut contributions_to_mint_ct =
- inst.execute(|| Contributions::::iter_prefix_values((project_id, contributor.clone())));
-
- let pre_contribution_to_mint_ct = contributions_to_mint_ct.next().unwrap();
- let bench_contribution_to_mint_ct = contributions_to_mint_ct.next().unwrap();
-
- Pallet::::contribution_ct_mint_for(
- RawOrigin::Signed(contributor.clone()).into(),
- project_id,
- contributor.clone(),
- pre_contribution_to_mint_ct.id,
- )
- .unwrap();
-
- #[extrinsic_call]
- contribution_ct_mint_for(
- RawOrigin::Signed(contributor.clone()),
- project_id,
- contributor.clone(),
- bench_contribution_to_mint_ct.id,
- );
-
- // * validity checks *
- // Storage
- let stored_contribution =
- Contributions::::get((project_id, contributor.clone(), bench_contribution_to_mint_ct.id)).unwrap();
- assert!(stored_contribution.ct_minted);
-
- // Balances
- let ct_amount = inst.get_ct_asset_balances_for(project_id, vec![contributor.clone()])[0];
- assert_eq!(ct_amount, pre_contribution_to_mint_ct.ct_amount + bench_contribution_to_mint_ct.ct_amount);
-
- // Events
- frame_system::Pallet::::assert_last_event(
- Event::ContributionTokenMinted {
- releaser: contributor.clone(),
- project_id,
- claimer: contributor,
- amount: bench_contribution_to_mint_ct.ct_amount,
- }
- .into(),
- );
- }
-
- #[benchmark]
- fn start_bid_vesting_schedule_for() {
- // setup
- let mut inst = BenchInstantiator::::new(None);
-
- // real benchmark starts at block 0, and we can't call `events()` at block 0
- inst.advance_time(1u32.into()).unwrap();
-
- let issuer = account::>("issuer", 0, 0);
- let bids = default_bids::();
- let bidder = bids[0].bidder.clone();
- whitelist_account!(bidder);
-
- let project_id = inst.create_finished_project(
- default_project::(inst.get_new_nonce(), issuer.clone()),
- issuer,
- default_evaluations::(),
- bids,
- default_community_contributions::(),
- vec![],
- );
-
- run_blocks_to_execute_next_transition(project_id, UpdateType::StartSettlement, &mut inst);
-
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Success(CleanerState::Initialized(PhantomData))
- );
-
- let bid_to_vest = inst.execute(|| Bids::::iter_prefix_values((project_id, bidder.clone())).next().unwrap());
-
- #[extrinsic_call]
- start_bid_vesting_schedule_for(RawOrigin::Signed(bidder.clone()), project_id, bidder.clone(), bid_to_vest.id);
-
- // * validity checks *
- // Storage
- let stored_bid = Bids::::get((project_id, bidder.clone(), bid_to_vest.id)).unwrap();
- assert!(stored_bid.plmc_vesting_info.is_some());
- let vest_info = stored_bid.plmc_vesting_info.unwrap();
- let total_vested =
- T::Vesting::total_scheduled_amount(&bidder, HoldReason::Participation(project_id).into()).unwrap();
- assert_eq!(vest_info.total_amount, total_vested);
-
- // Events
- frame_system::Pallet::::assert_last_event(
- Event::BidPlmcVestingScheduled {
- project_id,
- bidder: bidder.clone(),
- id: stored_bid.id,
- amount: vest_info.total_amount,
- caller: bidder,
- }
- .into(),
- );
- }
-
- #[benchmark]
- fn start_contribution_vesting_schedule_for() {
- // setup
- let mut inst = BenchInstantiator::::new(None);
-
- // real benchmark starts at block 0, and we can't call `events()` at block 0
- inst.advance_time(1u32.into()).unwrap();
-
- let issuer = account::>("issuer", 0, 0);
- let contributions = default_community_contributions::();
- let contributor = contributions[0].contributor.clone();
- whitelist_account!(contributor);
-
- let project_id = inst.create_finished_project(
- default_project::(inst.get_new_nonce(), issuer.clone()),
- issuer,
- default_evaluations::(),
- default_bids::(),
- contributions,
- vec![],
- );
-
- run_blocks_to_execute_next_transition(project_id, UpdateType::StartSettlement, &mut inst);
-
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Success(CleanerState::Initialized(PhantomData))
- );
-
- let contribution_to_vest =
- inst.execute(|| Contributions::::iter_prefix_values((project_id, contributor.clone())).next().unwrap());
-
- #[extrinsic_call]
- start_contribution_vesting_schedule_for(
- RawOrigin::Signed(contributor.clone()),
- project_id,
- contributor.clone(),
- contribution_to_vest.id,
- );
-
- // * validity checks *
- // Storage
- let stored_contribution =
- Contributions::::get((project_id, contributor.clone(), contribution_to_vest.id)).unwrap();
- assert!(stored_contribution.plmc_vesting_info.is_some());
- let vest_info = stored_contribution.plmc_vesting_info.unwrap();
- let total_vested =
- T::Vesting::total_scheduled_amount(&contributor, HoldReason::Participation(project_id).into()).unwrap();
- assert_eq!(vest_info.total_amount, total_vested);
-
- // Events
- frame_system::Pallet::::assert_last_event(
- Event::ContributionPlmcVestingScheduled {
- project_id,
- contributor: contributor.clone(),
- id: stored_contribution.id,
- amount: vest_info.total_amount,
- caller: contributor,
- }
- .into(),
- );
- }
-
- #[benchmark]
- fn payout_bid_funds_for() {
- // setup
- let mut inst = BenchInstantiator::::new(None);
-
- // real benchmark starts at block 0, and we can't call `events()` at block 0
- inst.advance_time(1u32.into()).unwrap();
-
- let issuer = account::>("issuer", 0, 0);
- let bids = default_bids::();
- let bidder = bids[0].bidder.clone();
- whitelist_account!(bidder);
-
- let project_id = inst.create_finished_project(
- default_project::(inst.get_new_nonce(), issuer.clone()),
- issuer.clone(),
- default_evaluations::(),
- bids,
- default_community_contributions::(),
- vec![],
- );
-
- run_blocks_to_execute_next_transition(project_id, UpdateType::StartSettlement, &mut inst);
-
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Success(CleanerState::Initialized(PhantomData))
- );
-
- let bid_to_payout =
- inst.execute(|| Bids::::iter_prefix_values((project_id, bidder.clone())).next().unwrap());
-
- #[extrinsic_call]
- payout_bid_funds_for(RawOrigin::Signed(issuer.clone()), project_id, bidder.clone(), bid_to_payout.id);
-
- // * validity checks *
- // Storage
- let stored_bid = Bids::::get((project_id, bidder.clone(), bid_to_payout.id)).unwrap();
- assert!(stored_bid.funds_released);
-
- // Balances
- let asset = stored_bid.funding_asset.to_assethub_id();
let project_details = ProjectsDetails::::get(project_id).unwrap();
- let free_assets =
- inst.get_free_foreign_asset_balances_for(asset, vec![project_details.issuer_account])[0].asset_amount;
- assert_eq!(free_assets, stored_bid.funding_asset_amount_locked);
-
- // Events
- frame_system::Pallet::::assert_last_event(
- Event::BidFundingPaidOut { project_id, bidder, id: stored_bid.id, amount: free_assets, caller: issuer }
- .into(),
- );
- }
-
- #[benchmark]
- fn payout_contribution_funds_for() {
- // setup
- let mut inst = BenchInstantiator::::new(None);
-
- // real benchmark starts at block 0, and we can't call `events()` at block 0
- inst.advance_time(1u32.into()).unwrap();
-
- let issuer = account::>("issuer", 0, 0);
- let contributions = default_community_contributions::();
- let contributor = contributions[0].contributor.clone();
- whitelist_account!(contributor);
-
- let project_id = inst.create_finished_project(
- default_project::(inst.get_new_nonce(), issuer.clone()),
- issuer.clone(),
- default_evaluations::(),
- default_bids::(),
- contributions,
- vec![],
- );
-
- run_blocks_to_execute_next_transition(project_id, UpdateType::StartSettlement, &mut inst);
-
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Success(CleanerState::Initialized(PhantomData))
- );
-
- let contribution_to_payout =
- inst.execute(|| Contributions::::iter_prefix_values((project_id, contributor.clone())).next().unwrap());
-
- #[extrinsic_call]
- payout_contribution_funds_for(
- RawOrigin::Signed(issuer.clone()),
- project_id,
- contributor.clone(),
- contribution_to_payout.id,
- );
-
- // * validity checks *
- // Storage
- let stored_contribution =
- Contributions::::get((project_id, contributor.clone(), contribution_to_payout.id)).unwrap();
- assert!(stored_contribution.funds_released);
+ let reward_info = match project_details.evaluation_round_info.evaluators_outcome {
+ EvaluatorsOutcome::Rewarded(reward_info) => reward_info,
+ _ => panic!("EvaluatorsOutcome should be Rewarded"),
+ };
+ let reward = Pallet::::calculate_evaluator_reward(&evaluation_to_settle, &reward_info);
- // Balances
- let asset = stored_contribution.funding_asset.to_assethub_id();
- let project_details = ProjectsDetails::::get(project_id).unwrap();
- let free_assets =
- inst.get_free_foreign_asset_balances_for(asset, vec![project_details.issuer_account])[0].asset_amount;
- assert_eq!(free_assets, stored_contribution.funding_asset_amount);
+ let ct_amount = inst.get_ct_asset_balances_for(project_id, vec![evaluator.clone()])[0];
+ assert_eq!(ct_amount, reward);
// Events
frame_system::Pallet::::assert_last_event(
- Event::ContributionFundingPaidOut {
+ Event::EvaluationSettled {
project_id,
- contributor,
- id: stored_contribution.id,
- amount: free_assets,
- caller: issuer,
+ account: evaluator.clone(),
+ id: evaluation_to_settle.id,
+ ct_amount: reward,
+ slashed_amount: 0.into(),
}
.into(),
);
}
#[benchmark]
- fn decide_project_outcome(
- // Insertion attempts in add_to_update_store. Total amount of storage items iterated through in `ProjectsToUpdate`. Leave one free to make the extrinsic pass
- x: Linear<1, { ::MaxProjectsToUpdateInsertionAttempts::get() - 1 }>,
- ) {
+ fn settle_failed_evaluation() {
// setup
let mut inst = BenchInstantiator::::new(None);
- // We need to leave enough block numbers to fill `ProjectsToUpdate` before our project insertion
-
- let time_advance: u32 = x + 2;
- frame_system::Pallet::::set_block_number(time_advance.into());
+ // real benchmark starts at block 0, and we can't call `events()` at block 0
+ inst.advance_time(1u32.into()).unwrap();
let issuer = account::>("issuer", 0, 0);
- whitelist_account!(issuer);
+ let evaluations = default_evaluations::();
+ let evaluator = evaluations[0].account.clone();
+ whitelist_account!(evaluator);
let project_metadata = default_project::(inst.get_new_nonce(), issuer.clone());
let target_funding_amount: BalanceOf =
project_metadata.minimum_price.saturating_mul_int(project_metadata.total_allocation_size);
- let evaluations = default_evaluations::();
let bids = BenchInstantiator::generate_bids_from_total_usd(
- Percent::from_percent(30) * target_funding_amount,
- project_metadata.minimum_price,
+ Percent::from_percent(15) * target_funding_amount,
+ 10u128.into(),
default_weights(),
default_bidders::(),
default_bidder_multipliers(),
);
-
let contributions = BenchInstantiator::generate_contributions_from_total_usd(
- Percent::from_percent(40) * target_funding_amount,
+ Percent::from_percent(10) * target_funding_amount,
project_metadata.minimum_price,
default_weights(),
default_community_contributors::(),
@@ -2286,33 +1608,53 @@ mod benchmarks {
);
let project_id =
- inst.create_finished_project(project_metadata, issuer.clone(), evaluations, bids, contributions, vec![]);
+ inst.create_finished_project(project_metadata, issuer, evaluations, bids, contributions, vec![]);
inst.advance_time(One::one()).unwrap();
+ assert_eq!(inst.get_project_details(project_id).status, ProjectStatus::FundingFailed);
- let current_block = inst.current_block();
- let insertion_block_number: BlockNumberFor = current_block + One::one();
-
- fill_projects_to_update::(x, insertion_block_number);
- let jwt = get_mock_jwt(issuer.clone(), InvestorType::Institutional, generate_did_from_account(issuer.clone()));
+ let evaluation_to_settle =
+ inst.execute(|| Evaluations::::iter_prefix_values((project_id, evaluator.clone())).next().unwrap());
#[extrinsic_call]
- decide_project_outcome(RawOrigin::Signed(issuer), jwt, project_id, FundingOutcomeDecision::AcceptFunding);
+ settle_failed_evaluation(
+ RawOrigin::Signed(evaluator.clone()),
+ project_id,
+ evaluator.clone(),
+ evaluation_to_settle.id,
+ );
// * validity checks *
// Storage
- let maybe_transition =
- inst.get_update_block(project_id, &UpdateType::ProjectDecision(FundingOutcomeDecision::AcceptFunding));
- assert!(maybe_transition.is_some());
+ // Evaluation should be removed
+ assert!(Evaluations::::get((project_id, evaluator.clone(), evaluation_to_settle.id)).is_none());
+ let slashed_amount = T::EvaluatorSlash::get() * evaluation_to_settle.original_plmc_bond;
+
+ let reserved_plmc = inst
+ .get_reserved_plmc_balances_for(vec![evaluator.clone()], HoldReason::Evaluation(project_id).into())[0]
+ .plmc_amount;
+ assert_eq!(reserved_plmc, 0.into());
+
+ let treasury_account = T::ProtocolGrowthTreasury::get();
+ let free_treasury_plmc = inst.get_free_plmc_balances_for(vec![treasury_account])[0].plmc_amount;
+ let ed = BenchInstantiator::::get_ed();
+ assert_eq!(free_treasury_plmc, slashed_amount + ed);
// Events
frame_system::Pallet::::assert_last_event(
- Event::ProjectOutcomeDecided { project_id, decision: FundingOutcomeDecision::AcceptFunding }.into(),
+ Event::EvaluationSettled {
+ project_id,
+ account: evaluator.clone(),
+ id: evaluation_to_settle.id,
+ ct_amount: 0.into(),
+ slashed_amount,
+ }
+ .into(),
);
}
#[benchmark]
- fn release_bid_funds_for() {
+ fn settle_successful_bid() {
// setup
let mut inst = BenchInstantiator::::new(None);
@@ -2320,69 +1662,45 @@ mod benchmarks {
inst.advance_time(1u32.into()).unwrap();
let issuer = account::>("issuer", 0, 0);
- let evaluations = default_evaluations::();
-
- let project_metadata = default_project::(inst.get_new_nonce(), issuer.clone());
- let target_funding_amount: BalanceOf =
- project_metadata.minimum_price.saturating_mul_int(project_metadata.total_allocation_size);
-
- let bids: Vec> = BenchInstantiator::generate_bids_from_total_usd(
- Percent::from_percent(15) * target_funding_amount,
- 10u128.into(),
- default_weights(),
- default_bidders::(),
- default_bidder_multipliers(),
- );
+ let bids = default_bids::();
let bidder = bids[0].bidder.clone();
whitelist_account!(bidder);
- let contributions = BenchInstantiator::generate_contributions_from_total_usd(
- Percent::from_percent(10) * target_funding_amount,
- project_metadata.minimum_price,
- default_weights(),
- default_community_contributors::(),
- default_community_contributor_multipliers(),
+
+ let project_id = inst.create_finished_project(
+ default_project::(inst.get_new_nonce(), issuer.clone()),
+ issuer,
+ default_evaluations::(),
+ bids,
+ default_community_contributions::(),
+ vec![],
);
- let project_id =
- inst.create_finished_project(project_metadata, issuer.clone(), evaluations, bids, contributions, vec![]);
+ run_blocks_to_execute_next_transition(project_id, UpdateType::StartSettlement, &mut inst);
- inst.advance_time(One::one()).unwrap();
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Failure(CleanerState::Initialized(PhantomData))
- );
+ assert_eq!(inst.get_project_details(project_id).status, ProjectStatus::FundingSuccessful);
- let bid_to_payout =
+ let bid_to_settle =
inst.execute(|| Bids::::iter_prefix_values((project_id, bidder.clone())).next().unwrap());
- let asset = bid_to_payout.funding_asset.to_assethub_id();
- let free_assets_before = inst.get_free_foreign_asset_balances_for(asset, vec![bidder.clone()])[0].asset_amount;
+
#[extrinsic_call]
- release_bid_funds_for(RawOrigin::Signed(issuer.clone()), project_id, bidder.clone(), bid_to_payout.id);
+ settle_successful_bid(RawOrigin::Signed(bidder.clone()), project_id, bidder.clone(), bid_to_settle.id);
// * validity checks *
// Storage
- let stored_bid = Bids::::get((project_id, bidder.clone(), bid_to_payout.id)).unwrap();
- assert!(stored_bid.funds_released);
+ assert!(Bids::::get((project_id, bidder.clone(), bid_to_settle.id)).is_none());
// Balances
- let free_assets = inst.get_free_foreign_asset_balances_for(asset, vec![bidder.clone()])[0].asset_amount;
- assert_eq!(free_assets, stored_bid.funding_asset_amount_locked + free_assets_before);
+ let ct_amount = inst.get_ct_asset_balances_for(project_id, vec![bidder.clone()])[0];
+ assert_eq!(bid_to_settle.final_ct_amount, ct_amount);
// Events
frame_system::Pallet::::assert_last_event(
- Event::BidFundingReleased {
- project_id,
- bidder,
- id: stored_bid.id,
- amount: stored_bid.funding_asset_amount_locked,
- caller: issuer,
- }
- .into(),
+ Event::BidSettled { project_id, account: bidder.clone(), id: bid_to_settle.id, ct_amount }.into(),
);
}
#[benchmark]
- fn release_contribution_funds_for() {
+ fn settle_failed_bid() {
// setup
let mut inst = BenchInstantiator::::new(None);
@@ -2398,69 +1716,50 @@ mod benchmarks {
let bids: Vec> = BenchInstantiator::generate_bids_from_total_usd(
Percent::from_percent(15) * target_funding_amount,
- project_metadata.minimum_price,
+ 10u128.into(),
default_weights(),
default_bidders::(),
default_bidder_multipliers(),
);
- let contributions: Vec> = BenchInstantiator::generate_contributions_from_total_usd(
+ let bidder = bids[0].bidder.clone();
+ whitelist_account!(bidder);
+ let contributions = BenchInstantiator::generate_contributions_from_total_usd(
Percent::from_percent(10) * target_funding_amount,
project_metadata.minimum_price,
default_weights(),
default_community_contributors::(),
default_community_contributor_multipliers(),
);
- let contributor = contributions[0].contributor.clone();
- whitelist_account!(contributor);
let project_id =
- inst.create_finished_project(project_metadata, issuer, evaluations, bids, contributions, vec![]);
+ inst.create_finished_project(project_metadata, issuer.clone(), evaluations, bids, contributions, vec![]);
inst.advance_time(One::one()).unwrap();
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Failure(CleanerState::Initialized(PhantomData))
- );
-
- let contribution_to_payout =
- inst.execute(|| Contributions::::iter_prefix_values((project_id, contributor.clone())).next().unwrap());
+ assert_eq!(inst.get_project_details(project_id).status, ProjectStatus::FundingFailed);
- let asset = contribution_to_payout.funding_asset.to_assethub_id();
- let free_assets_before =
- inst.get_free_foreign_asset_balances_for(asset, vec![contributor.clone()])[0].asset_amount;
+ let bid_to_settle =
+ inst.execute(|| Bids::::iter_prefix_values((project_id, bidder.clone())).next().unwrap());
+ let asset = bid_to_settle.funding_asset.to_assethub_id();
+ let free_assets_before = inst.get_free_foreign_asset_balances_for(asset, vec![bidder.clone()])[0].asset_amount;
#[extrinsic_call]
- release_contribution_funds_for(
- RawOrigin::Signed(contributor.clone()),
- project_id,
- contributor.clone(),
- contribution_to_payout.id,
- );
+ settle_failed_bid(RawOrigin::Signed(issuer.clone()), project_id, bidder.clone(), bid_to_settle.id);
// * validity checks *
// Storage
- let stored_contribution =
- Contributions::::get((project_id, contributor.clone(), contribution_to_payout.id)).unwrap();
- assert!(stored_contribution.funds_released);
+ assert!(Bids::::get((project_id, bidder.clone(), bid_to_settle.id)).is_none());
// Balances
- let free_assets = inst.get_free_foreign_asset_balances_for(asset, vec![contributor.clone()])[0].asset_amount;
- assert_eq!(free_assets, stored_contribution.funding_asset_amount + free_assets_before);
+ let free_assets = inst.get_free_foreign_asset_balances_for(asset, vec![bidder.clone()])[0].asset_amount;
+ assert_eq!(free_assets, bid_to_settle.funding_asset_amount_locked + free_assets_before);
// Events
frame_system::Pallet::::assert_last_event(
- Event::ContributionFundingReleased {
- project_id,
- contributor: contributor.clone(),
- id: stored_contribution.id,
- amount: stored_contribution.funding_asset_amount,
- caller: contributor,
- }
- .into(),
+ Event::BidSettled { project_id, account: bidder.clone(), id: bid_to_settle.id, ct_amount: 0.into() }.into(),
);
}
#[benchmark]
- fn bid_unbond_for() {
+ fn settle_successful_contribution() {
// setup
let mut inst = BenchInstantiator::::new(None);
@@ -2468,71 +1767,56 @@ mod benchmarks {
inst.advance_time(1u32.into()).unwrap();
let issuer = account::>("issuer", 0, 0);
- let evaluations = default_evaluations::();
-
- let project_metadata = default_project::(inst.get_new_nonce(), issuer.clone());
- let target_funding_amount: BalanceOf =
- project_metadata.minimum_price.saturating_mul_int(project_metadata.total_allocation_size);
+ let contributions = default_community_contributions::();
+ let contributor = contributions[0].contributor.clone();
+ whitelist_account!(contributor);
- let bids: Vec> = BenchInstantiator::generate_bids_from_total_usd(
- Percent::from_percent(15) * target_funding_amount,
- 10u128.into(),
- default_weights(),
- default_bidders::(),
- default_bidder_multipliers(),
- );
- let bidder = bids[0].bidder.clone();
- whitelist_account!(bidder);
- let contributions = BenchInstantiator::generate_contributions_from_total_usd(
- Percent::from_percent(10) * target_funding_amount,
- project_metadata.minimum_price,
- default_weights(),
- default_community_contributors::(),
- default_community_contributor_multipliers(),
+ let project_id = inst.create_finished_project(
+ default_project::(inst.get_new_nonce(), issuer.clone()),
+ issuer,
+ default_evaluations::(),
+ default_bids::(),
+ contributions,
+ vec![],
);
- let project_id =
- inst.create_finished_project(project_metadata, issuer, evaluations, bids, contributions, vec![]);
-
- inst.advance_time(One::one()).unwrap();
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Failure(CleanerState::Initialized(PhantomData))
- );
+ run_blocks_to_execute_next_transition(project_id, UpdateType::StartSettlement, &mut inst);
- let stored_bid = inst.execute(|| Bids::::iter_prefix_values((project_id, bidder.clone())).next().unwrap());
+ assert_eq!(inst.get_project_details(project_id).status, ProjectStatus::FundingSuccessful);
- inst.execute(|| {
- PalletFunding::::release_bid_funds_for(
- ::RuntimeOrigin::signed(bidder.clone().into()),
- project_id,
- bidder.clone(),
- stored_bid.id,
- )
- .expect("Funds are released")
- });
+ let contribution_to_settle =
+ inst.execute(|| Contributions::::iter_prefix_values((project_id, contributor.clone())).next().unwrap());
#[extrinsic_call]
- bid_unbond_for(RawOrigin::Signed(bidder.clone()), project_id, bidder.clone(), stored_bid.id);
+ settle_successful_contribution(
+ RawOrigin::Signed(contributor.clone()),
+ project_id,
+ contributor.clone(),
+ contribution_to_settle.id,
+ );
// * validity checks *
// Storage
- assert!(!Bids::::contains_key((project_id, bidder.clone(), stored_bid.id)));
+ assert!(Contributions::::get((project_id, contributor.clone(), contribution_to_settle.id)).is_none());
+
// Balances
- let reserved_plmc = inst
- .get_reserved_plmc_balances_for(vec![bidder.clone()], HoldReason::Participation(project_id).into())[0]
- .plmc_amount;
- assert_eq!(reserved_plmc, 0.into());
+ let ct_amount = inst.get_ct_asset_balances_for(project_id, vec![contributor.clone()])[0];
+ assert_eq!(contribution_to_settle.ct_amount, ct_amount);
// Events
frame_system::Pallet::::assert_last_event(
- Event::BondReleased { project_id, amount: stored_bid.plmc_bond, bonder: bidder.clone(), releaser: bidder }
- .into(),
+ Event::ContributionSettled {
+ project_id,
+ account: contributor.clone(),
+ id: contribution_to_settle.id,
+ ct_amount,
+ }
+ .into(),
);
}
#[benchmark]
- fn contribution_unbond_for() {
+ fn settle_failed_contribution() {
// setup
let mut inst = BenchInstantiator::::new(None);
@@ -2564,60 +1848,45 @@ mod benchmarks {
whitelist_account!(contributor);
let project_id =
- inst.create_finished_project(project_metadata, issuer.clone(), evaluations, bids, contributions, vec![]);
+ inst.create_finished_project(project_metadata, issuer, evaluations, bids, contributions, vec![]);
inst.advance_time(One::one()).unwrap();
- assert_eq!(
- inst.get_project_details(project_id).cleanup,
- Cleaner::Failure(CleanerState::Initialized(PhantomData))
- );
+ assert_eq!(inst.get_project_details(project_id).status, ProjectStatus::FundingFailed);
- let stored_contribution =
+ let contribution_to_settle =
inst.execute(|| Contributions::