diff --git a/benchmarked-extrinsics.rs b/benchmarked-extrinsics.rs
new file mode 100644
index 000000000..62c9be435
--- /dev/null
+++ b/benchmarked-extrinsics.rs
@@ -0,0 +1,153 @@
+// Polimec Blockchain – https://www.polimec.org/
+// Copyright (C) Polimec 2022. All rights reserved.
+
+// The Polimec Blockchain is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// The Polimec Blockchain is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+// If you feel like getting in touch with us, you can do so at info@polimec.org
+
+
+//! Autogenerated weights for `pallet_funding`
+//!
+//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 39.0.0
+//! DATE: 2025-01-29, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
+//! WORST CASE MAP SIZE: `1000000`
+//! HOSTNAME: `Mac.home`, CPU: ``
+//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("polimec-paseo-local")`, DB CACHE: `1024`
+
+// Executed Command:
+// target/production/polimec-node
+// benchmark
+// pallet
+// --chain=polimec-paseo-local
+// --steps=50
+// --repeat=20
+// --pallet=pallet-funding
+// --no-storage-info
+// --no-median-slopes
+// --no-min-squares
+// --extrinsic=bid
+// --wasm-execution=compiled
+// --heap-pages=4096
+// --output=benchmarked-extrinsics.rs
+// --template=./.maintain/frame-weight-template.hbs
+
+#![cfg_attr(rustfmt, rustfmt_skip)]
+#![allow(unused_parens)]
+#![allow(unused_imports)]
+#![allow(missing_docs)]
+
+use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
+use core::marker::PhantomData;
+
+/// Weight functions needed for `pallet_funding`.
+pub trait WeightInfo {
+ fn bid(x: u32, ) -> Weight;
+}
+
+/// Weights for `pallet_funding` using the Substrate node and recommended hardware.
+pub struct SubstrateWeight(PhantomData);
+impl WeightInfo for SubstrateWeight {
+ /// Storage: `Timestamp::Now` (r:1 w:0)
+ /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::ProjectsMetadata` (r:1 w:0)
+ /// Proof: `Funding::ProjectsMetadata` (`max_values`: None, `max_size`: Some(437), added: 2912, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::ProjectsDetails` (r:1 w:0)
+ /// Proof: `Funding::ProjectsDetails` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::Buckets` (r:1 w:1)
+ /// Proof: `Funding::Buckets` (`max_values`: None, `max_size`: Some(100), added: 2575, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::NextBidId` (r:1 w:1)
+ /// Proof: `Funding::NextBidId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::BidBucketBounds` (r:11 w:10)
+ /// Proof: `Funding::BidBucketBounds` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::AuctionBoughtUSD` (r:1 w:1)
+ /// Proof: `Funding::AuctionBoughtUSD` (`max_values`: None, `max_size`: Some(118), added: 2593, mode: `MaxEncodedLen`)
+ /// Storage: `Oracle::Values` (r:2 w:0)
+ /// Proof: `Oracle::Values` (`max_values`: None, `max_size`: Some(634), added: 3109, mode: `MaxEncodedLen`)
+ /// Storage: `ForeignAssets::Metadata` (r:1 w:0)
+ /// Proof: `ForeignAssets::Metadata` (`max_values`: None, `max_size`: Some(738), added: 3213, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::Evaluations` (r:1 w:0)
+ /// Proof: `Funding::Evaluations` (`max_values`: None, `max_size`: Some(337), added: 2812, mode: `MaxEncodedLen`)
+ /// Storage: `Balances::Holds` (r:1 w:1)
+ /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`)
+ /// Storage: `ForeignAssets::Asset` (r:1 w:1)
+ /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`)
+ /// Storage: `ForeignAssets::Account` (r:2 w:2)
+ /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::OutbidBidsCutoff` (r:1 w:1)
+ /// Proof: `Funding::OutbidBidsCutoff` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::Bids` (r:999 w:19)
+ /// Proof: `Funding::Bids` (`max_values`: None, `max_size`: Some(341), added: 2816, mode: `MaxEncodedLen`)
+ /// The range of component `x` is `[1, 1000]`.
+ fn bid(x: u32, ) -> Weight {
+ // Proof Size summary in bytes:
+ // Measured: `4850 + x * (226 ±0)`
+ // Estimated: `28875 + x * (2816 ±0)`
+ // Minimum execution time: 829_000_000 picoseconds.
+ Weight::from_parts(767_882_619, 28875)
+ // Standard Error: 8_838
+ .saturating_add(Weight::from_parts(5_852_038, 0).saturating_mul(x.into()))
+ .saturating_add(T::DbWeight::get().reads(26_u64))
+ .saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(x.into())))
+ .saturating_add(T::DbWeight::get().writes(36_u64))
+ .saturating_add(Weight::from_parts(0, 2816).saturating_mul(x.into()))
+ }
+}
+
+// For backwards compatibility and tests.
+impl WeightInfo for () {
+ /// Storage: `Timestamp::Now` (r:1 w:0)
+ /// Proof: `Timestamp::Now` (`max_values`: Some(1), `max_size`: Some(8), added: 503, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::ProjectsMetadata` (r:1 w:0)
+ /// Proof: `Funding::ProjectsMetadata` (`max_values`: None, `max_size`: Some(437), added: 2912, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::ProjectsDetails` (r:1 w:0)
+ /// Proof: `Funding::ProjectsDetails` (`max_values`: None, `max_size`: Some(347), added: 2822, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::Buckets` (r:1 w:1)
+ /// Proof: `Funding::Buckets` (`max_values`: None, `max_size`: Some(100), added: 2575, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::NextBidId` (r:1 w:1)
+ /// Proof: `Funding::NextBidId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::BidBucketBounds` (r:11 w:10)
+ /// Proof: `Funding::BidBucketBounds` (`max_values`: None, `max_size`: Some(60), added: 2535, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::AuctionBoughtUSD` (r:1 w:1)
+ /// Proof: `Funding::AuctionBoughtUSD` (`max_values`: None, `max_size`: Some(118), added: 2593, mode: `MaxEncodedLen`)
+ /// Storage: `Oracle::Values` (r:2 w:0)
+ /// Proof: `Oracle::Values` (`max_values`: None, `max_size`: Some(634), added: 3109, mode: `MaxEncodedLen`)
+ /// Storage: `ForeignAssets::Metadata` (r:1 w:0)
+ /// Proof: `ForeignAssets::Metadata` (`max_values`: None, `max_size`: Some(738), added: 3213, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::Evaluations` (r:1 w:0)
+ /// Proof: `Funding::Evaluations` (`max_values`: None, `max_size`: Some(337), added: 2812, mode: `MaxEncodedLen`)
+ /// Storage: `Balances::Holds` (r:1 w:1)
+ /// Proof: `Balances::Holds` (`max_values`: None, `max_size`: Some(175), added: 2650, mode: `MaxEncodedLen`)
+ /// Storage: `ForeignAssets::Asset` (r:1 w:1)
+ /// Proof: `ForeignAssets::Asset` (`max_values`: None, `max_size`: Some(808), added: 3283, mode: `MaxEncodedLen`)
+ /// Storage: `ForeignAssets::Account` (r:2 w:2)
+ /// Proof: `ForeignAssets::Account` (`max_values`: None, `max_size`: Some(732), added: 3207, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::OutbidBidsCutoff` (r:1 w:1)
+ /// Proof: `Funding::OutbidBidsCutoff` (`max_values`: None, `max_size`: Some(40), added: 2515, mode: `MaxEncodedLen`)
+ /// Storage: `Funding::Bids` (r:999 w:19)
+ /// Proof: `Funding::Bids` (`max_values`: None, `max_size`: Some(341), added: 2816, mode: `MaxEncodedLen`)
+ /// The range of component `x` is `[1, 1000]`.
+ fn bid(x: u32, ) -> Weight {
+ // Proof Size summary in bytes:
+ // Measured: `4850 + x * (226 ±0)`
+ // Estimated: `28875 + x * (2816 ±0)`
+ // Minimum execution time: 829_000_000 picoseconds.
+ Weight::from_parts(767_882_619, 28875)
+ // Standard Error: 8_838
+ .saturating_add(Weight::from_parts(5_852_038, 0).saturating_mul(x.into()))
+ .saturating_add(RocksDbWeight::get().reads(26_u64))
+ .saturating_add(RocksDbWeight::get().reads((1_u64).saturating_mul(x.into())))
+ .saturating_add(RocksDbWeight::get().writes(36_u64))
+ .saturating_add(Weight::from_parts(0, 2816).saturating_mul(x.into()))
+ }
+}
\ No newline at end of file
diff --git a/integration-tests/src/tests/ct_migration.rs b/integration-tests/src/tests/ct_migration.rs
index 3159c835c..226553cf8 100644
--- a/integration-tests/src/tests/ct_migration.rs
+++ b/integration-tests/src/tests/ct_migration.rs
@@ -14,6 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
+use frame_support::WeakBoundedVec;
use crate::{constants::PricesBuilder, *};
use frame_support::traits::{fungible::Mutate, fungibles::Inspect};
use itertools::Itertools;
@@ -70,7 +71,7 @@ fn get_migrations_for_participants(
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())));
+ user_migrations.insert(participant, (status, Migrations::from(migrations.to_vec())));
}
});
user_migrations
@@ -159,8 +160,8 @@ fn create_settled_project() -> (ProjectId, Vec) {
let mut inst = IntegrationInstantiator::new(None);
let project_metadata = default_project_metadata(ISSUER.into());
- let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 5);
- let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 95, 8);
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+ let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 95, 30);
PolimecNet::execute_with(|| {
let project_id = inst.create_finished_project(project_metadata, ISSUER.into(), None, evaluations, bids);
assert_eq!(
@@ -207,8 +208,8 @@ fn create_project_with_unsettled_participation(participation_type: Participation
let mut inst = IntegrationInstantiator::new(None);
PolimecNet::execute_with(|| {
let project_metadata = default_project_metadata(ISSUER.into());
- let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 5);
- let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 95, 8);
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+ let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 95, 30);
let project_id = inst.create_finished_project(project_metadata, ISSUER.into(), None, evaluations, bids);
assert_eq!(
@@ -217,12 +218,12 @@ fn create_project_with_unsettled_participation(participation_type: Participation
);
let evaluations_to_settle =
pallet_funding::Evaluations::::iter_prefix_values((project_id,)).collect_vec();
- let bids_to_settle = PolimecFunding::get_ordered_bid_settlements(project_id);
+ let bids_to_settle = inst.get_bids(project_id);
let mut participants: Vec = evaluations_to_settle
.iter()
.map(|eval| eval.evaluator.clone())
- .chain(bids_to_settle.iter().map(|x| x.1.clone()))
+ .chain(bids_to_settle.iter().map(|x| x.bidder.clone()))
.collect();
participants.sort();
participants.dedup();
@@ -240,8 +241,8 @@ fn create_project_with_unsettled_participation(participation_type: Participation
let proposed_start = if participation_type == ParticipationType::Bid { 1 } else { 0 };
let end = if proposed_start == 1 { bids_to_settle.len() - 1 } else { bids_to_settle.len() };
- for (project_id, bidder, id) in bids_to_settle[..end].iter() {
- PolimecFunding::settle_bid(RuntimeOrigin::signed(alice()), *project_id, bidder.clone(), *id).unwrap()
+ for bid in bids_to_settle[..end].iter() {
+ PolimecFunding::settle_bid(RuntimeOrigin::signed(alice()), project_id, bid.original_ct_usd_price, bid.id).unwrap()
}
let evaluations =
diff --git a/integration-tests/src/tests/defaults.rs b/integration-tests/src/tests/defaults.rs
index 3ad2b3037..362e2c2ae 100644
--- a/integration-tests/src/tests/defaults.rs
+++ b/integration-tests/src/tests/defaults.rs
@@ -68,7 +68,7 @@ pub fn default_project_metadata(issuer: AccountId) -> ProjectMetadataOf::get((project_id, user.clone(), participation_id));
- // dbg!(&stored_bid);
- assert!(stored_bid.is_some());
}
let post_participation_free_plmc = PolimecBalances::free_balance(user.clone());
@@ -425,10 +422,11 @@ fn e2e_test() {
let prev_treasury_usdt_balance = PolimecForeignAssets::balance(USDT.id(), otm_project_sub_account.clone());
let prev_escrow_usdt_balance = PolimecForeignAssets::balance(USDT.id(), funding_escrow_account.clone());
+ let rejected_bidder_bid = inst.get_bid(rejected_bid_id);
PolimecFunding::settle_bid(
PolimecOrigin::signed(rejected_bidder.clone()),
project_id,
- rejected_bidder.clone(),
+ rejected_bidder_bid.original_ct_usd_price,
rejected_bid_id,
)
.unwrap();
@@ -663,3 +661,23 @@ fn e2e_test() {
}
});
}
+
+#[test]
+fn sandbox() {
+ fn bid(x: u32, ) -> Weight {
+ // Proof Size summary in bytes:
+ // Measured: `4850 + x * (226 ±0)`
+ // Estimated: `28875 + x * (2816 ±0)`
+ // Minimum execution time: 829_000_000 picoseconds.
+ Weight::from_parts(767_882_619, 28875)
+ // Standard Error: 8_838
+ .saturating_add(Weight::from_parts(5_852_038, 0).saturating_mul(x.into()))
+ .saturating_add(::DbWeight::get().reads(26_u64))
+ .saturating_add(::DbWeight::get().reads((1_u64).saturating_mul(x.into())))
+ .saturating_add(::DbWeight::get().writes(36_u64))
+ .saturating_add(Weight::from_parts(0, 2816).saturating_mul(x.into()))
+ }
+
+ let max_weight = bid(1000);
+ dbg!(max_weight);
+}
diff --git a/integration-tests/src/tests/oracle.rs b/integration-tests/src/tests/oracle.rs
index c4564bb37..42c3a5485 100644
--- a/integration-tests/src/tests/oracle.rs
+++ b/integration-tests/src/tests/oracle.rs
@@ -131,8 +131,8 @@ fn pallet_funding_works() {
assert_ok!(Oracle::feed_values(RuntimeOrigin::signed(charlie.clone()), values([4.84, 1.0, 1.0, 2500.0, 0.4])));
let project_metadata = default_project_metadata(ISSUER.into());
- let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 5);
- let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 95, 8);
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+ let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 95, 30);
let _project_id = inst.create_finished_project(project_metadata, ISSUER.into(), None, evaluations, bids);
});
}
diff --git a/justfile b/justfile
index 8ba10b791..babf2428e 100644
--- a/justfile
+++ b/justfile
@@ -99,8 +99,8 @@ benchmark-pallet chain="polimec-paseo-local" pallet="pallet-dispenser":
benchmark-extrinsics pallet="pallet-funding" extrinsics="*" :
cargo run --features runtime-benchmarks --profile=production -p polimec-node benchmark pallet \
--chain=polimec-paseo-local \
- --steps=10 \
- --repeat=5 \
+ --steps=50 \
+ --repeat=20 \
--pallet={{ pallet }} \
--no-storage-info \
--no-median-slopes \
diff --git a/pallets/funding/src/benchmarking.rs b/pallets/funding/src/benchmarking.rs
index 2c400181f..4b0f0bf5d 100644
--- a/pallets/funding/src/benchmarking.rs
+++ b/pallets/funding/src/benchmarking.rs
@@ -72,9 +72,9 @@ where
.unwrap(),
bidding_ticket_sizes: BiddingTicketSizes {
- professional: TicketSize::new(10u128 * USD_UNIT, None),
- institutional: TicketSize::new(10u128 * USD_UNIT, None),
- retail: TicketSize::new(10u128 * USD_UNIT, None),
+ professional: TicketSize::new(100u128 * USD_UNIT, None),
+ institutional: TicketSize::new(100u128 * USD_UNIT, None),
+ retail: TicketSize::new(100u128 * USD_UNIT, None),
phantom: Default::default(),
},
participation_currencies: vec![USDT, USDC, DOT, WETH].try_into().unwrap(),
@@ -84,90 +84,6 @@ where
}
}
-pub fn default_evaluations() -> Vec>
-where
- ::Price: From,
- T::Hash: From,
-{
- let threshold = ::EvaluationSuccessThreshold::get();
- let default_project_metadata: ProjectMetadataOf =
- default_project_metadata::(account::>("issuer", 0, 0));
- let funding_target =
- default_project_metadata.minimum_price.saturating_mul_int(default_project_metadata.total_allocation_size);
- let evaluation_target = threshold * funding_target;
-
- vec![
- EvaluationParams::from((
- account::>("evaluator_1", 0, 0),
- Percent::from_percent(35) * evaluation_target,
- )),
- EvaluationParams::from((
- account::>("evaluator_2", 0, 0),
- Percent::from_percent(35) * evaluation_target,
- )),
- EvaluationParams::from((
- account::>("evaluator_3", 0, 0),
- Percent::from_percent(35) * evaluation_target,
- )),
- ]
-}
-
-pub fn default_bids() -> Vec>
-where
- ::Price: From,
- T::Hash: From,
-{
- let default_project_metadata = default_project_metadata::(account::>("issuer", 0, 0));
- let auction_funding_target =
- default_project_metadata.minimum_price.saturating_mul_int(default_project_metadata.total_allocation_size);
- let inst = BenchInstantiator::::new(None);
-
- inst.generate_bids_from_total_usd(
- default_project_metadata.clone(),
- Percent::from_percent(95) * auction_funding_target,
- 5,
- )
-}
-
-pub fn full_bids() -> Vec>
-where
- T: Config,
- ::Price: From,
- T::Hash: From,
-{
- let inst = BenchInstantiator::::new(None);
- let default_project = default_project_metadata::(account::>("issuer", 0, 0));
- let total_ct_for_bids = default_project.total_allocation_size;
- let total_usd_for_bids = default_project.minimum_price.checked_mul_int(total_ct_for_bids).unwrap();
- inst.generate_bids_from_total_usd(default_project.clone(), total_usd_for_bids, 5)
-}
-
-pub fn default_weights() -> Vec {
- vec![20u8, 15u8, 10u8, 25u8, 30u8]
-}
-
-pub fn default_evaluators() -> Vec> {
- vec![
- account::>("evaluator_1", 0, 0),
- account::>("evaluator_2", 0, 0),
- account::>("evaluator_3", 0, 0),
- account::>("evaluator_4", 0, 0),
- account::>("evaluator_5", 0, 0),
- ]
-}
-pub fn default_bidders() -> Vec> {
- vec![
- account::>("bidder_1", 0, 0),
- account::>("bidder_2", 0, 0),
- account::>("bidder_3", 0, 0),
- account::>("bidder_4", 0, 0),
- account::>("bidder_5", 0, 0),
- ]
-}
-
-pub fn default_bidder_modes() -> Vec {
- vec![Classic(10u8), Classic(3u8), OTM, OTM, Classic(4u8)]
-}
/// Grab an account, seeded by a name and index.
pub fn string_account(
name: scale_info::prelude::string::String,
@@ -314,7 +230,7 @@ mod benchmarks {
bidding_ticket_sizes: BiddingTicketSizes {
professional: TicketSize::new(5000 * USD_UNIT, Some(10_000 * USD_UNIT)),
institutional: TicketSize::new(5000 * USD_UNIT, Some(10_000 * USD_UNIT)),
- retail: TicketSize::new(10 * USD_UNIT, Some(10_000 * USD_UNIT)),
+ retail: TicketSize::new(100 * USD_UNIT, Some(10_000 * USD_UNIT)),
phantom: Default::default(),
},
participation_currencies: vec![AcceptedFundingAsset::USDT, AcceptedFundingAsset::USDC].try_into().unwrap(),
@@ -393,15 +309,13 @@ mod benchmarks {
}
#[benchmark]
- fn evaluate(
- // How many other evaluations the user did for that same project
- x: Linear<0, { T::MaxEvaluationsPerUser::get() - 1 }>,
- ) {
+ fn evaluate() {
// setup
let mut inst = BenchInstantiator::::new(None);
::SetPrices::set_prices();
- // We can't see events at block 0 inst.advance_time(1u32.into());
+ // We can't see events at block 0
+ inst.advance_time(1u32.into());
let issuer = account::>("issuer", 0, 0);
let test_evaluator = account::>("evaluator", 0, 0);
@@ -410,25 +324,16 @@ mod benchmarks {
let project_metadata = default_project_metadata::(issuer.clone());
let project_id = inst.create_evaluating_project(project_metadata.clone(), issuer, None);
- let existing_evaluation = EvaluationParams::from((test_evaluator.clone(), (200 * USD_UNIT).into()));
let extrinsic_evaluation = EvaluationParams::from((test_evaluator.clone(), (1_000 * USD_UNIT).into()));
- let existing_evaluations = vec![existing_evaluation; x as usize];
- let plmc_for_existing_evaluations = inst.calculate_evaluation_plmc_spent(existing_evaluations.clone());
let plmc_for_extrinsic_evaluation = inst.calculate_evaluation_plmc_spent(vec![extrinsic_evaluation.clone()]);
let existential_plmc: Vec> =
plmc_for_extrinsic_evaluation.accounts().existential_deposits();
inst.mint_plmc_to(existential_plmc);
- inst.mint_plmc_to(plmc_for_existing_evaluations.clone());
inst.mint_plmc_to(plmc_for_extrinsic_evaluation.clone());
- // do "x" evaluations for this user
- inst.evaluate_for_users(project_id, existing_evaluations).expect("All evaluations are accepted");
-
let extrinsic_plmc_bonded = plmc_for_extrinsic_evaluation[0].plmc_amount;
- let total_expected_plmc_bonded = inst
- .sum_balance_mappings(vec![plmc_for_existing_evaluations.clone(), plmc_for_extrinsic_evaluation.clone()]);
let jwt = get_mock_jwt_with_cid(
extrinsic_evaluation.account.clone(),
@@ -468,7 +373,7 @@ mod benchmarks {
let bonded_plmc = inst
.get_reserved_plmc_balances_for(vec![extrinsic_evaluation.account.clone()], HoldReason::Evaluation.into())[0]
.plmc_amount;
- assert_eq!(bonded_plmc, total_expected_plmc_bonded);
+ assert_eq!(bonded_plmc, extrinsic_plmc_bonded);
// Events
frame_system::Pallet::::assert_last_event(
@@ -544,10 +449,8 @@ mod benchmarks {
#[benchmark]
fn bid(
- // amount of already made bids by the same user. Leave 10 bids available to make the extrinsic pass in case y = max (10)
- x: Linear<0, { T::MaxBidsPerUser::get() - 10 }>,
- // amount of times when `perform_bid` is called (i.e. into how many buckets the bid is spread)
- y: Linear<0, 10>,
+ // Amount of bids that are outbid by this one.
+ x: Linear<1, 1000>,
) {
// * setup *
let mut inst = BenchInstantiator::::new(None);
@@ -561,10 +464,10 @@ mod benchmarks {
whitelist_account!(bidder);
let mut project_metadata = default_project_metadata::(issuer.clone());
- project_metadata.mainnet_token_max_supply = 100_000 * CT_UNIT;
- project_metadata.total_allocation_size = 100_000 * CT_UNIT;
+ project_metadata.mainnet_token_max_supply = 40_000 * CT_UNIT;
+ project_metadata.total_allocation_size = 40_000 * CT_UNIT;
project_metadata.minimum_price = PriceProviderOf::::calculate_decimals_aware_price(
- PriceOf::::checked_from_rational(100, 1).unwrap(),
+ PriceOf::::checked_from_rational(10, 1).unwrap(),
USD_DECIMALS,
CT_DECIMALS,
)
@@ -574,145 +477,75 @@ mod benchmarks {
let project_id = inst.create_auctioning_project(project_metadata.clone(), issuer, None, evaluations);
- let existing_bid = BidParams::from((
- bidder.clone(),
- Institutional,
- (50 * CT_UNIT).into(),
- ParticipationMode::Classic(5u8),
- AcceptedFundingAsset::USDT,
- ));
+ let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 100, x);
+ let total_ct_bid = project_metadata.total_allocation_size;
- let existing_bids = vec![existing_bid; x as usize];
- let existing_bids_post_bucketing =
- inst.get_actual_price_charged_for_bucketed_bids(&existing_bids, project_metadata.clone(), None);
- let plmc_for_existing_bids = inst.calculate_auction_plmc_charged_from_all_bids_made_or_with_bucket(
- &existing_bids,
+ let bids_plmc = inst.calculate_auction_plmc_charged_from_all_bids_made_or_with_bucket(
+ &bids,
+ project_metadata.clone(),
+ None,
+ );
+ let bids_funding_assets = inst.calculate_auction_funding_asset_charged_from_all_bids_made_or_with_bucket(
+ &bids,
project_metadata.clone(),
None,
);
- let usdt_for_existing_bids: Vec> = inst
- .calculate_auction_funding_asset_charged_from_all_bids_made_or_with_bucket(
- &existing_bids,
- project_metadata.clone(),
- None,
- );
- let escrow_account = Pallet::::fund_account_id(project_id);
- let prev_total_escrow_usdt_locked =
- inst.get_free_funding_asset_balances_for(vec![(escrow_account.clone(), usdt_id())]);
-
- inst.mint_plmc_ed_if_required(plmc_for_existing_bids.accounts());
- inst.mint_plmc_to(plmc_for_existing_bids.clone());
- inst.mint_funding_asset_ed_if_required(usdt_for_existing_bids.to_account_asset_map());
- inst.mint_funding_asset_to(usdt_for_existing_bids.clone());
-
- // do "x" contributions for this user
- inst.bid_for_users(project_id, existing_bids.clone()).unwrap();
-
- // to call do_perform_bid several times, we need the bucket to reach its limit. You can only bid over 10 buckets
- // in a single bid, since the increase delta is 10% of the total allocation, and you cannot bid more than the allocation.
- let mut ct_amount = (50 * CT_UNIT).into();
- let mut maybe_filler_bid = None;
- let new_bidder = account::>("new_bidder", 0, 0);
-
- let mut usdt_for_filler_bidder =
- vec![UserToFundingAsset::::new(new_bidder.clone(), Zero::zero(), AcceptedFundingAsset::USDT.id())];
- if y > 0 {
- let current_bucket = Buckets::::get(project_id).unwrap();
- // first lets bring the bucket to almost its limit with another bidder:
- assert!(new_bidder.clone() != bidder.clone());
- let bid_params = BidParams::from((
- new_bidder.clone(),
- Institutional,
- current_bucket.amount_left,
- ParticipationMode::Classic(1u8),
- AcceptedFundingAsset::USDT,
- ));
- maybe_filler_bid = Some(bid_params.clone());
- let plmc_for_new_bidder = inst.calculate_auction_plmc_charged_with_given_price(
- &vec![bid_params.clone()],
- current_bucket.current_price,
- );
- let usdt_for_new_bidder = inst.calculate_auction_funding_asset_charged_with_given_price(
- &vec![bid_params.clone()],
- current_bucket.current_price,
- );
-
- inst.mint_plmc_ed_if_required(vec![(new_bidder.clone())]);
- inst.mint_plmc_to(plmc_for_new_bidder);
-
- inst.mint_funding_asset_ed_if_required(vec![(new_bidder, AcceptedFundingAsset::USDT.id())]);
- inst.mint_funding_asset_to(usdt_for_new_bidder.clone());
-
- inst.bid_for_users(project_id, vec![bid_params]).unwrap();
-
- let auction_allocation = project_metadata.total_allocation_size;
- let bucket_size = Percent::from_percent(10) * auction_allocation;
- ct_amount = bucket_size * (y as u128);
- usdt_for_filler_bidder = usdt_for_new_bidder;
- }
+ inst.mint_plmc_ed_if_required(bids.accounts());
+ inst.mint_plmc_to(bids_plmc);
+
+ inst.mint_funding_asset_ed_if_required(bids.to_account_asset_map());
+ inst.mint_funding_asset_to(bids_funding_assets);
+
+ inst.bid_for_users(project_id, bids).unwrap();
+
+ let current_bucket = Buckets::::get(project_id).unwrap();
let extrinsic_bid = BidParams::from((
bidder.clone(),
Institutional,
- ct_amount,
+ total_ct_bid,
ParticipationMode::Classic(1u8),
AcceptedFundingAsset::USDT,
));
- let original_extrinsic_bid = extrinsic_bid.clone();
- let current_bucket = Buckets::::get(project_id).unwrap();
- // we need to call this after bidding `x` amount of times, to get the latest bucket from storage
- let extrinsic_bids_post_bucketing = inst.get_actual_price_charged_for_bucketed_bids(
+
+ let extrinsic_bid_plmc = inst.calculate_auction_plmc_charged_from_all_bids_made_or_with_bucket(
+ &vec![extrinsic_bid.clone()],
+ project_metadata.clone(),
+ Some(current_bucket),
+ );
+ let extrinsic_bid_funding_asset = inst.calculate_auction_funding_asset_charged_from_all_bids_made_or_with_bucket(
&vec![extrinsic_bid.clone()],
project_metadata.clone(),
Some(current_bucket),
);
- assert_eq!(extrinsic_bids_post_bucketing.len(), (y as usize).max(1usize));
-
- let plmc_for_extrinsic_bids: Vec> = inst
- .calculate_auction_plmc_charged_from_all_bids_made_or_with_bucket(
- &vec![extrinsic_bid.clone()],
- project_metadata.clone(),
- Some(current_bucket),
- );
- let usdt_for_extrinsic_bids: Vec> = inst
- .calculate_auction_funding_asset_charged_from_all_bids_made_or_with_bucket(
- &vec![extrinsic_bid],
- project_metadata.clone(),
- Some(current_bucket),
- );
- inst.mint_plmc_ed_if_required(plmc_for_extrinsic_bids.accounts());
- inst.mint_plmc_to(plmc_for_extrinsic_bids.clone());
- inst.mint_funding_asset_ed_if_required(usdt_for_extrinsic_bids.to_account_asset_map());
- inst.mint_funding_asset_to(usdt_for_extrinsic_bids.clone());
-
- let total_free_plmc = inst.get_ed();
- let total_plmc_participation_bonded =
- inst.sum_balance_mappings(vec![plmc_for_extrinsic_bids.clone(), plmc_for_existing_bids.clone()]);
- let total_free_usdt = inst.get_funding_asset_ed(AcceptedFundingAsset::USDT.id());
- let total_escrow_usdt_locked = inst.sum_funding_asset_mappings(vec![
- prev_total_escrow_usdt_locked.clone(),
- usdt_for_extrinsic_bids.clone(),
- usdt_for_existing_bids.clone(),
- usdt_for_filler_bidder.clone(),
- ])[0]
- .1;
+ inst.mint_plmc_ed_if_required(extrinsic_bid_plmc.accounts());
+ inst.mint_plmc_to(extrinsic_bid_plmc.clone());
+ inst.mint_funding_asset_ed_if_required(extrinsic_bid_funding_asset.to_account_asset_map());
+ inst.mint_funding_asset_to(extrinsic_bid_funding_asset.clone());
+
+ let extrinsic_bids_post_bucketing = inst.get_actual_price_charged_for_bucketed_bids(
+ &vec![extrinsic_bid.clone()],
+ project_metadata.clone(),
+ Some(current_bucket),
+ );
+ dbg!(extrinsic_bids_post_bucketing.len());
let jwt = get_mock_jwt_with_cid(
- original_extrinsic_bid.bidder.clone(),
+ bidder.clone(),
InvestorType::Institutional,
- generate_did_from_account(original_extrinsic_bid.bidder.clone()),
+ generate_did_from_account(bidder.clone()),
project_metadata.clone().policy_ipfs_cid.unwrap(),
);
#[extrinsic_call]
bid(
- RawOrigin::Signed(original_extrinsic_bid.bidder.clone()),
+ RawOrigin::Signed(bidder.clone()),
jwt,
project_id,
- original_extrinsic_bid.amount,
- original_extrinsic_bid.mode,
- original_extrinsic_bid.asset,
+ extrinsic_bid.amount,
+ extrinsic_bid.mode,
+ extrinsic_bid.asset,
);
// * validity checks *
@@ -732,66 +565,15 @@ mod benchmarks {
plmc_bond: None,
when: None,
};
- Bids::::iter_prefix_values((project_id, bidder.clone()))
+ Bids::::iter_prefix_values((project_id,))
.find(|stored_bid| bid_filter.matches_bid(stored_bid))
.expect("bid not found");
}
- // Bucket Storage Check
- let bucket_delta_amount = Percent::from_percent(10) * project_metadata.total_allocation_size;
- let ten_percent_in_price: ::Price =
- PriceOf::::checked_from_rational(1, 10).unwrap() * project_metadata.minimum_price;
+ let cutoff = OutbidBidsCutoff::::get(project_id).unwrap();
- let mut expected_bucket = Bucket::new(
- project_metadata.total_allocation_size,
- project_metadata.minimum_price,
- ten_percent_in_price,
- bucket_delta_amount,
- );
-
- for (bid_params, _price_) in existing_bids_post_bucketing.clone() {
- expected_bucket.update(bid_params.amount);
- }
- if let Some(bid_params) = maybe_filler_bid {
- expected_bucket.update(bid_params.amount);
- }
- for (bid_params, _price_) in extrinsic_bids_post_bucketing.clone() {
- expected_bucket.update(bid_params.amount);
- }
-
- let current_bucket = Buckets::::get(project_id).unwrap();
- assert_eq!(current_bucket, expected_bucket);
-
- // Balances
- let bonded_plmc =
- inst.get_reserved_plmc_balances_for(vec![bidder.clone()], HoldReason::Participation.into())[0].plmc_amount;
- assert_eq!(bonded_plmc, total_plmc_participation_bonded);
-
- let free_plmc = inst.get_free_plmc_balances_for(vec![bidder.clone()])[0].plmc_amount;
- assert_eq!(free_plmc, total_free_plmc);
-
- let escrow_account = Pallet::::fund_account_id(project_id);
- let locked_usdt = inst.get_free_funding_asset_balance_for(usdt_id(), escrow_account.clone());
- assert_eq!(locked_usdt, total_escrow_usdt_locked);
-
- let free_usdt = inst.get_free_funding_asset_balance_for(usdt_id(), bidder);
- assert_eq!(free_usdt, total_free_usdt);
-
- // Events
- for (bid_params, _price_) in extrinsic_bids_post_bucketing {
- let maybe_event = find_event! {
- T,
- Event::::Bid {
- project_id,
- ct_amount,
- mode, ..
- },
- project_id == project_id,
- ct_amount == bid_params.amount,
- mode == bid_params.mode
- };
- assert!(maybe_event.is_some(), "Event not found");
- }
+ // First bucket with whole allocation should be outbid.
+ assert_eq!(cutoff, (project_metadata.minimum_price, 0));
}
// end_funding has 2 logic paths:
@@ -868,13 +650,10 @@ mod benchmarks {
let issuer = account::>("issuer", 0, 0);
whitelist_account!(anyone);
- let project_id = inst.create_finished_project(
- default_project_metadata::(issuer.clone()),
- issuer,
- None,
- default_evaluations::(),
- default_bids::(),
- );
+ let project_metadata = default_project_metadata::(issuer.clone());
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+ let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 95, 30);
+ let project_id = inst.create_finished_project(project_metadata, issuer, None, evaluations, bids);
#[extrinsic_call]
start_settlement(RawOrigin::Signed(anyone), project_id);
@@ -900,16 +679,19 @@ mod benchmarks {
inst.advance_time(1u32.into());
let issuer = account::>("issuer", 0, 0);
- let evaluations: Vec> = default_evaluations::();
+ let project_metadata = default_project_metadata::(issuer.clone());
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
let evaluator: AccountIdOf = evaluations[0].account.clone();
whitelist_account!(evaluator);
+ let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 95, 30);
+
let project_id = inst.create_finished_project(
default_project_metadata::(issuer.clone()),
issuer,
None,
evaluations,
- default_bids::(),
+ bids,
);
let evaluation_to_settle =
@@ -961,53 +743,48 @@ mod benchmarks {
inst.advance_time(1u32.into());
let issuer = account::>("issuer", 0, 0);
- let mut bidder_accounts = default_bidders::().into_iter();
let project_metadata = default_project_metadata::(issuer.clone());
- // let target_wap = project_metadata.minimum_price + project_metadata.minimum_price * >::saturating_from_rational(1, 10);
- let mut target_bucket = >::create_bucket_from_metadata(&project_metadata.clone()).unwrap();
- target_bucket.update(target_bucket.amount_left);
- target_bucket.update(target_bucket.amount_left);
+ let increase = project_metadata.minimum_price * PriceOf::::saturating_from_rational(5, 10);
+ let target_wap = project_metadata.minimum_price + increase;
- let bids = inst.generate_bids_from_bucket(
- project_metadata.clone(),
- target_bucket,
- bidder_accounts.next().unwrap(),
- |_| bidder_accounts.next().unwrap(),
- AcceptedFundingAsset::USDT,
- );
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+ let bids = inst.generate_bids_that_take_price_to(project_metadata.clone(), target_wap);
- let project_id = inst.create_finished_project(
- project_metadata.clone(),
- issuer,
- None,
- default_evaluations::(),
- bids.clone(),
- );
+ let project_id =
+ inst.create_finished_project(project_metadata.clone(), issuer, None, evaluations, bids.clone());
let wap = inst.get_project_details(project_id).weighted_average_price.unwrap();
- let bidder = bids.last().unwrap().bidder.clone();
- whitelist_account!(bidder);
-
assert_ok!(>::do_start_settlement(project_id));
- let bid_to_settle =
- inst.execute(|| Bids::::iter_prefix_values((project_id, bidder.clone())).next().unwrap());
+ let bid_to_settle = inst.execute(|| {
+ let mut bids_iter = Bids::::iter_prefix_values((project_id,));
+ bids_iter.find(|b| matches!(b.status, BidStatus::PartiallyAccepted(_))).unwrap()
+ });
+
+ let bidder = bid_to_settle.bidder.clone();
+ whitelist_account!(bidder);
- // Make sure a refund has to happen
- assert!(bid_to_settle.original_ct_usd_price > wap);
+ let BidStatus::PartiallyAccepted(expected_ct_amount) = bid_to_settle.status else {
+ unreachable!();
+ };
#[extrinsic_call]
- settle_bid(RawOrigin::Signed(bidder.clone()), project_id, bidder.clone(), bid_to_settle.id);
+ settle_bid(
+ RawOrigin::Signed(bidder.clone()),
+ project_id,
+ bid_to_settle.original_ct_usd_price,
+ bid_to_settle.id,
+ );
// * validity checks *
// Storage
- assert!(Bids::::get((project_id, bidder.clone(), bid_to_settle.id)).is_none());
+ assert!(Bids::::get((project_id, bid_to_settle.original_ct_usd_price, bid_to_settle.id)).is_none());
// Balances
let ct_amount = inst.get_ct_asset_balances_for(project_id, vec![bidder.clone()])[0];
- assert_eq!(bid_to_settle.original_ct_amount, ct_amount);
+ assert_eq!(expected_ct_amount, ct_amount);
// Events
frame_system::Pallet::::assert_last_event(
@@ -1015,9 +792,9 @@ mod benchmarks {
project_id,
account: bidder.clone(),
id: bid_to_settle.id,
- status: BidStatus::Accepted,
- final_ct_amount: bid_to_settle.original_ct_amount,
- final_ct_usd_price: wap,
+ status: bid_to_settle.status,
+ final_ct_amount: expected_ct_amount,
+ final_ct_usd_price: bid_to_settle.original_ct_usd_price,
}
.into(),
);
@@ -1034,14 +811,11 @@ mod benchmarks {
whitelist_account!(anyone);
let project_metadata = default_project_metadata::(issuer.clone());
- let project_id = inst.create_settled_project(
- project_metadata.clone(),
- issuer.clone(),
- None,
- default_evaluations::(),
- default_bids::(),
- false,
- );
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+ let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 95, 30);
+
+ let project_id =
+ inst.create_settled_project(project_metadata.clone(), issuer.clone(), None, evaluations, bids, false);
#[extrinsic_call]
mark_project_as_settled(RawOrigin::Signed(anyone), project_id);
@@ -1060,8 +834,8 @@ mod benchmarks {
let issuer = account::>("issuer", 0, 0);
let project_metadata = default_project_metadata::(issuer.clone());
- let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 1);
- let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 34, 1);
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+ let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 34, 30);
let project_id =
inst.create_settled_project(project_metadata.clone(), issuer.clone(), None, evaluations, bids, true);
@@ -1078,13 +852,13 @@ mod benchmarks {
// * validity checks *
let project_details = inst.get_project_details(project_id);
assert_eq!(project_details.status, ProjectStatus::CTMigrationStarted);
- assert_eq!(UnmigratedCounter::::get(project_id), 2);
+ assert_eq!(UnmigratedCounter::::get(project_id), 40);
}
#[benchmark]
fn confirm_offchain_migration(
// Amount of migrations to confirm for a single user
- x: Linear<1, { <::MaxBidsPerUser>::get() }>,
+ x: Linear<1, 100>,
) {
// setup
let mut inst = BenchInstantiator::::new(None);
@@ -1093,6 +867,11 @@ mod benchmarks {
let issuer = account::>("issuer", 0, 0);
let participant = account::>("test_participant", 0, 0);
+ let project_metadata = default_project_metadata::(issuer.clone());
+
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+
+ let mut bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 34, 50);
let max_bids = x;
let participant_bids = (0..max_bids)
.map(|_| {
@@ -1105,12 +884,6 @@ mod benchmarks {
))
})
.collect_vec();
-
- let project_metadata = default_project_metadata::(issuer.clone());
-
- let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 1);
-
- let mut bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 34, 1);
bids.extend(participant_bids);
let project_id =
@@ -1141,8 +914,8 @@ mod benchmarks {
// * validity checks *
let project_details = inst.get_project_details(project_id);
assert_eq!(project_details.status, ProjectStatus::CTMigrationStarted);
- // Evaluations and Bids had 1 each where it was a different account that the one we just confirmed.
- assert_eq!(UnmigratedCounter::::get(project_id), 2);
+
+ assert_eq!(UnmigratedCounter::::get(project_id), 10 + 50);
}
#[benchmark]
@@ -1154,14 +927,10 @@ mod benchmarks {
let issuer = account::>("issuer", 0, 0);
let project_metadata = default_project_metadata::(issuer.clone());
- let project_id = inst.create_settled_project(
- project_metadata.clone(),
- issuer.clone(),
- None,
- default_evaluations::(),
- default_bids::(),
- true,
- );
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+ let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 34, 30);
+ let project_id =
+ inst.create_settled_project(project_metadata.clone(), issuer.clone(), None, evaluations, bids, true);
let jwt = get_mock_jwt_with_cid(
issuer.clone(),
@@ -1198,14 +967,10 @@ mod benchmarks {
let issuer = account::>("issuer", 0, 0);
let project_metadata = default_project_metadata::(issuer.clone());
- let project_id = inst.create_settled_project(
- project_metadata.clone(),
- issuer.clone(),
- None,
- default_evaluations::(),
- default_bids::(),
- true,
- );
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+ let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 34, 30);
+ let project_id =
+ inst.create_settled_project(project_metadata.clone(), issuer.clone(), None, evaluations, bids, true);
let jwt = get_mock_jwt_with_cid(
issuer.clone(),
@@ -1255,14 +1020,10 @@ mod benchmarks {
let issuer = account::>("issuer", 0, 0);
let project_metadata = default_project_metadata::(issuer.clone());
- let project_id = inst.create_settled_project(
- project_metadata.clone(),
- issuer.clone(),
- None,
- default_evaluations::(),
- default_bids::(),
- true,
- );
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+ let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 34, 30);
+ let project_id =
+ inst.create_settled_project(project_metadata.clone(), issuer.clone(), None, evaluations, bids, true);
let jwt = get_mock_jwt_with_cid(
issuer.clone(),
@@ -1329,14 +1090,10 @@ mod benchmarks {
let issuer = account::>("issuer", 0, 0);
let project_metadata = default_project_metadata::(issuer.clone());
- let project_id = inst.create_settled_project(
- project_metadata.clone(),
- issuer.clone(),
- None,
- default_evaluations::(),
- default_bids::(),
- true,
- );
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+ let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 34, 30);
+ let project_id =
+ inst.create_settled_project(project_metadata.clone(), issuer.clone(), None, evaluations, bids, true);
let jwt = get_mock_jwt_with_cid(
issuer.clone(),
@@ -1409,7 +1166,7 @@ mod benchmarks {
#[benchmark]
fn send_pallet_migration_for(
// Amount of migrations to confirm for a single user
- x: Linear<1, { ::MaxBidsPerUser::get() }>,
+ x: Linear<1, 100>,
) {
// setup
let mut inst = BenchInstantiator::::new(None);
@@ -1425,7 +1182,7 @@ mod benchmarks {
BidParams::from((
participant.clone(),
Institutional,
- (500 * CT_UNIT).into(),
+ (50 * CT_UNIT).into(),
ParticipationMode::Classic(1u8),
AcceptedFundingAsset::USDT,
))
@@ -1433,8 +1190,8 @@ mod benchmarks {
.collect_vec();
let project_metadata = default_project_metadata::(issuer.clone());
- let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 5);
- let mut bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 34, 1);
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+ let mut bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 34, 40);
bids.extend(participant_bids);
let project_id =
@@ -1481,9 +1238,9 @@ mod benchmarks {
}
#[benchmark]
- fn confirm_pallet_migrations(
+ fn confirm_pallet_migration(
// Amount of migrations to confirm for a single user
- x: Linear<1, { ::MaxBidsPerUser::get() }>,
+ x: Linear<1, 100>,
) {
// setup
let mut inst = BenchInstantiator::::new(None);
@@ -1499,7 +1256,7 @@ mod benchmarks {
BidParams::from((
participant.clone(),
Institutional,
- (500 * CT_UNIT).into(),
+ (50 * CT_UNIT).into(),
ParticipationMode::Classic(1u8),
AcceptedFundingAsset::USDT,
))
@@ -1507,9 +1264,10 @@ mod benchmarks {
.collect_vec();
let project_metadata = default_project_metadata::(issuer.clone());
- let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 1);
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+
+ let mut bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 34, 50);
- let mut bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 34, 1);
bids.extend(participant_bids);
let project_id =
@@ -1572,14 +1330,10 @@ mod benchmarks {
let issuer = account::>("issuer", 0, 0);
let project_metadata = default_project_metadata::(issuer.clone());
- let project_id = inst.create_settled_project(
- project_metadata.clone(),
- issuer.clone(),
- None,
- default_evaluations::(),
- default_bids::(),
- true,
- );
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+ let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 34, 30);
+ let project_id =
+ inst.create_settled_project(project_metadata.clone(), issuer.clone(), None, evaluations, bids, true);
let jwt = get_mock_jwt_with_cid(
issuer.clone(),
@@ -1611,14 +1365,10 @@ mod benchmarks {
let issuer = account::>("issuer", 0, 0);
let project_metadata = default_project_metadata::(issuer.clone());
- let project_id = inst.create_settled_project(
- project_metadata.clone(),
- issuer.clone(),
- None,
- default_evaluations::(),
- default_bids::(),
- true,
- );
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+ let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 34, 30);
+ let project_id =
+ inst.create_settled_project(project_metadata.clone(), issuer.clone(), None, evaluations, bids, true);
let jwt = get_mock_jwt_with_cid(
issuer.clone(),
@@ -1652,14 +1402,10 @@ mod benchmarks {
let issuer = account::>("issuer", 0, 0);
let project_metadata = default_project_metadata::(issuer.clone());
- let project_id = inst.create_settled_project(
- project_metadata.clone(),
- issuer.clone(),
- None,
- default_evaluations::(),
- default_bids::(),
- true,
- );
+ let evaluations = inst.generate_successful_evaluations(project_metadata.clone(), 10);
+ let bids = inst.generate_bids_from_total_ct_percent(project_metadata.clone(), 34, 30);
+ let project_id =
+ inst.create_settled_project(project_metadata.clone(), issuer.clone(), None, evaluations, bids, true);
let jwt = get_mock_jwt_with_cid(
issuer.clone(),
diff --git a/pallets/funding/src/functions/2_evaluation.rs b/pallets/funding/src/functions/2_evaluation.rs
index a859dc519..a83366ff0 100644
--- a/pallets/funding/src/functions/2_evaluation.rs
+++ b/pallets/funding/src/functions/2_evaluation.rs
@@ -76,7 +76,7 @@ impl Pallet {
did: Did,
whitelisted_policy: Cid,
receiving_account: Junction,
- ) -> DispatchResultWithPostInfo {
+ ) -> DispatchResult {
// * Get variables *
let project_metadata = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectMetadataNotFound)?;
let mut project_details = ProjectsDetails::::get(project_id).ok_or(Error::::ProjectDetailsNotFound)?;
@@ -88,8 +88,6 @@ impl Pallet {
let early_evaluation_reward_threshold_usd =
T::EvaluationSuccessThreshold::get() * project_details.fundraising_target_usd;
let evaluation_round_info = &mut project_details.evaluation_round_info;
- let total_evaluations_count = EvaluationCounts::::get(project_id);
- let user_evaluations_count = Evaluations::::iter_prefix((project_id, evaluator)).count() as u32;
let project_policy = project_metadata.policy_ipfs_cid.ok_or(Error::::ImpossibleState)?;
let project_metadata = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectDetailsNotFound)?;
@@ -102,8 +100,6 @@ impl Pallet {
project_details.round_duration.started(now) && !project_details.round_duration.ended(now),
Error::::IncorrectRound
);
- ensure!(total_evaluations_count < T::MaxEvaluationsPerProject::get(), Error::::TooManyProjectParticipations);
- ensure!(user_evaluations_count < T::MaxEvaluationsPerUser::get(), Error::::TooManyUserParticipations);
ensure!(
project_metadata.participants_account_type.junction_is_supported(&receiving_account),
Error::::UnsupportedReceiverAccountJunction
@@ -146,7 +142,6 @@ impl Pallet {
evaluation_round_info.total_bonded_usd = evaluation_round_info.total_bonded_usd.saturating_add(usd_amount);
evaluation_round_info.total_bonded_plmc = evaluation_round_info.total_bonded_plmc.saturating_add(plmc_bond);
ProjectsDetails::::insert(project_id, project_details);
- EvaluationCounts::::mutate(project_id, |c| *c = c.saturating_add(1));
// * Emit events *
Self::deposit_event(Event::Evaluation {
@@ -156,9 +151,6 @@ impl Pallet {
plmc_amount: plmc_bond,
});
- Ok(PostDispatchInfo {
- actual_weight: Some(WeightInfoOf::::evaluate(user_evaluations_count)),
- pays_fee: Pays::No,
- })
+ Ok(())
}
}
diff --git a/pallets/funding/src/functions/3_auction.rs b/pallets/funding/src/functions/3_auction.rs
index 80a02ea4c..131006c0c 100644
--- a/pallets/funding/src/functions/3_auction.rs
+++ b/pallets/funding/src/functions/3_auction.rs
@@ -3,7 +3,7 @@ use super::*;
impl Pallet {
#[transactional]
- pub fn do_bid(params: DoBidParams) -> DispatchResultWithPostInfo {
+ pub fn do_bid(params: DoBidParams) -> DispatchResult {
// * Get variables *
let DoBidParams {
bidder,
@@ -23,7 +23,6 @@ impl Pallet {
let mut current_bucket = Buckets::::get(project_id).ok_or(Error::::BucketNotFound)?;
let now = >::block_number();
let mut amount_to_bid = ct_amount;
- let total_bids_for_project = BidCounts::::get(project_id);
let project_policy = project_metadata.policy_ipfs_cid.ok_or(Error::::ImpossibleState)?;
// User will spend at least this amount of USD for his bid(s). More if the bid gets split into different buckets
@@ -32,9 +31,6 @@ impl Pallet {
// weight return variables
let mut perform_bid_calls = 0;
- let existing_bids = Bids::::iter_prefix_values((project_id, bidder.clone())).collect::>();
- let existing_bids_amount = existing_bids.len() as u32;
-
let metadata_ticket_size_bounds = match investor_type {
InvestorType::Institutional => project_metadata.bidding_ticket_sizes.institutional,
InvestorType::Professional => project_metadata.bidding_ticket_sizes.professional,
@@ -64,11 +60,11 @@ impl Pallet {
metadata_ticket_size_bounds.usd_ticket_above_minimum_per_participation(min_total_ticket_size),
Error::::TooLow
);
+ ensure!(min_total_ticket_size <= MAX_USD_TICKET_PER_BID_EXTRINSIC, Error::::TooHigh);
ensure!(mode.multiplier() <= max_multiplier && mode.multiplier() > 0u8, Error::::ForbiddenMultiplier);
// Note: We limit the CT Amount to the auction allocation size, to avoid long-running loops.
ensure!(ct_amount <= project_metadata.total_allocation_size, Error::::TooHigh);
- ensure!(existing_bids.len() < T::MaxBidsPerUser::get() as usize, Error::::TooManyUserParticipations);
ensure!(
project_metadata.participants_account_type.junction_is_supported(&receiving_account),
Error::::UnsupportedReceiverAccountJunction
@@ -84,6 +80,7 @@ impl Pallet {
current_bucket.amount_left
};
let bid_id = NextBidId::::get();
+ let auction_oversubscribed = current_bucket.current_price > current_bucket.initial_price;
let perform_params = DoPerformBidParams {
bidder: bidder.clone(),
@@ -96,22 +93,22 @@ impl Pallet {
now,
did: did.clone(),
metadata_ticket_size_bounds,
- total_bids_by_bidder: existing_bids_amount.saturating_add(perform_bid_calls),
- total_bids_for_project: total_bids_for_project.saturating_add(perform_bid_calls),
receiving_account,
+ auction_oversubscribed,
};
- let bid_info = Self::do_perform_bid(perform_params)?;
- let bid_index = bid_info.id;
- BidsSettlementOrder::::mutate(project_id, current_bucket.current_price, |maybe_indexes| {
+ BidBucketBounds::::mutate(project_id, current_bucket.current_price, |maybe_indexes| {
if let Some((i, j)) = maybe_indexes {
// TODO: remove the debug_assert before the PR is merged.
- debug_assert!(bid_index == *j + 1);
- *maybe_indexes = Some((*i, bid_index));
+ debug_assert!(bid_id == *j + 1);
+ *maybe_indexes = Some((*i, bid_id));
} else {
- *maybe_indexes = Some((bid_index, bid_index));
+ *maybe_indexes = Some((bid_id, bid_id));
}
});
+
+ Self::do_perform_bid(perform_params)?;
+
perform_bid_calls = perform_bid_calls.saturating_add(1);
// Update the current bucket and reduce the amount to bid by the amount we just bid
@@ -122,10 +119,7 @@ impl Pallet {
// Note: If the bucket has been exhausted, the 'update' function has already made the 'current_bucket' point to the next one.
Buckets::::insert(project_id, current_bucket);
- Ok(PostDispatchInfo {
- actual_weight: Some(WeightInfoOf::::bid(existing_bids_amount, perform_bid_calls)),
- pays_fee: Pays::No,
- })
+ Ok(())
}
#[transactional]
@@ -141,26 +135,23 @@ impl Pallet {
now,
did,
metadata_ticket_size_bounds,
- total_bids_by_bidder,
- total_bids_for_project,
receiving_account,
+ auction_oversubscribed,
} = do_perform_bid_params;
- let ticket_size = ct_usd_price.checked_mul_int(ct_amount).ok_or(Error::::BadMath)?;
+ let usd_ticket_size = ct_usd_price.checked_mul_int(ct_amount).ok_or(Error::::BadMath)?;
let total_usd_bid_by_did = AuctionBoughtUSD::::get((project_id, did.clone()));
let multiplier: MultiplierOf = mode.multiplier().try_into().map_err(|_| Error::::BadMath)?;
ensure!(
metadata_ticket_size_bounds
- .usd_ticket_below_maximum_per_did(total_usd_bid_by_did.saturating_add(ticket_size)),
+ .usd_ticket_below_maximum_per_did(total_usd_bid_by_did.saturating_add(usd_ticket_size)),
Error::::TooHigh
);
- ensure!(total_bids_by_bidder < T::MaxBidsPerUser::get(), Error::::TooManyUserParticipations);
- ensure!(total_bids_for_project < T::MaxBidsPerProject::get(), Error::::TooManyProjectParticipations);
// * Calculate new variables *
- let plmc_bond = Self::calculate_plmc_bond(ticket_size, multiplier).map_err(|_| Error::::BadMath)?;
- let funding_asset_amount_locked = Self::calculate_funding_asset_amount(ticket_size, funding_asset)?;
+ let plmc_bond = Self::calculate_plmc_bond(usd_ticket_size, multiplier).map_err(|_| Error::::BadMath)?;
+ let funding_asset_amount_locked = Self::calculate_funding_asset_amount(usd_ticket_size, funding_asset)?;
let new_bid = BidInfoOf:: {
id: bid_id,
@@ -181,10 +172,13 @@ impl Pallet {
Self::bond_plmc_with_mode(&bidder, project_id, plmc_bond, mode, funding_asset)?;
Self::try_funding_asset_hold(&bidder, project_id, funding_asset_amount_locked, funding_asset.id())?;
- Bids::::insert((project_id, bidder.clone(), bid_id), &new_bid);
+ Bids::::insert((project_id, ct_usd_price, bid_id), &new_bid);
NextBidId::::set(bid_id.saturating_add(One::one()));
- BidCounts::::mutate(project_id, |c| *c = c.saturating_add(1));
- AuctionBoughtUSD::::mutate((project_id, did), |amount| *amount = amount.saturating_add(ticket_size));
+ AuctionBoughtUSD::::mutate((project_id, did), |amount| *amount = amount.saturating_add(usd_ticket_size));
+
+ if auction_oversubscribed {
+ Self::update_outbid_bids_cutoff(project_id, ct_amount)?;
+ }
Self::deposit_event(Event::Bid {
project_id,
@@ -200,4 +194,76 @@ impl Pallet {
Ok(new_bid)
}
+
+ fn update_outbid_bids_cutoff(project_id: ProjectId, ct_amount: Balance) -> DispatchResult {
+ let project_metadata = ProjectsMetadata::::get(project_id).ok_or(Error::::ProjectMetadataNotFound)?;
+ let bucket = Buckets::::get(project_id).ok_or(Error::::BucketNotFound)?;
+ let maybe_current_cutoff = OutbidBidsCutoff::::get(project_id);
+ let mut current_cutoff: (PriceOf, u32);
+ let mut remaining_ct_amount = ct_amount;
+
+ // Adjust initial cutoff if necessary
+ if let Some((price, index)) = maybe_current_cutoff {
+ let bid = Bids::::get((project_id, price, index)).ok_or(Error::::ImpossibleState)?;
+ if !matches!(bid.status, BidStatus::PartiallyAccepted(_)) {
+ let (new_price, new_index) = Self::get_next_cutoff(project_id, bucket.delta_price, price, index)?;
+ current_cutoff = (new_price, new_index);
+ } else {
+ current_cutoff = (price, index);
+ }
+ } else {
+ // Initialize to the first bucket
+ let first_price = project_metadata.minimum_price;
+ let first_bucket_bounds =
+ BidBucketBounds::::get(project_id, first_price).ok_or(Error::::ImpossibleState)?;
+ current_cutoff = (first_price, first_bucket_bounds.1);
+ }
+
+ while remaining_ct_amount > Zero::zero() {
+ let (price, index) = current_cutoff;
+
+ let mut bid = Bids::