Skip to content

Commit

Permalink
✅ New decimal-aware price system - Part 6: Fix auction tests (#266)
Browse files Browse the repository at this point in the history
Main info on #260 

- This PR focuses on fixing the auction tests
  • Loading branch information
JuaniRios authored Apr 30, 2024
1 parent ef9a3ee commit 9b80e26
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 28 deletions.
5 changes: 3 additions & 2 deletions pallets/funding/src/instantiator/calculations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,11 @@ impl<
for (bid, price) in self.get_actual_price_charged_for_bucketed_bids(bids, project_metadata, maybe_bucket) {
let funding_asset_id = bid.asset.to_assethub_id();
let funding_asset_decimals = self.execute(|| T::FundingCurrency::decimals(funding_asset_id));
let funding_asset_usd_price =
let funding_asset_usd_price = self.execute(|| {
T::PriceProvider::get_decimals_aware_price(funding_asset_id, USD_DECIMALS, funding_asset_decimals)
.ok_or(Error::<T>::PriceNotFound)
.unwrap();
.unwrap()
});
let usd_ticket_size = price.saturating_mul_int(bid.amount);
let funding_asset_spent = funding_asset_usd_price.reciprocal().unwrap().saturating_mul_int(usd_ticket_size);
output.push(UserToForeignAssets::<T>::new(
Expand Down
1 change: 1 addition & 0 deletions pallets/funding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ pub type MultiplierOf<T> = <T as Config>::Multiplier;

pub type BalanceOf<T> = <T as Config>::Balance;
pub type PriceOf<T> = <T as Config>::Price;
pub type PriceProviderOf<T> = <T as Config>::PriceProvider;
pub type StringLimitOf<T> = <T as Config>::StringLimit;
pub type AssetIdOf<T> =
<<T as Config>::FundingCurrency as fungibles::Inspect<<T as frame_system::Config>::AccountId>>::AssetId;
Expand Down
104 changes: 78 additions & 26 deletions pallets/funding/src/tests/3_auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ mod round_flow {
let bounded_name = bounded_name();
let bounded_symbol = bounded_symbol();
let metadata_hash = ipfs_hash();
let normalized_price = PriceOf::<TestRuntime>::from_float(10.0);
let decimal_aware_price = PriceProviderOf::<TestRuntime>::calculate_decimals_aware_price(
normalized_price,
USD_DECIMALS,
CT_DECIMALS,
)
.unwrap();
let project_metadata = ProjectMetadata {
token_information: CurrencyMetadata {
name: bounded_name,
Expand All @@ -61,7 +68,7 @@ mod round_flow {
mainnet_token_max_supply: 8_000_000 * CT_UNIT,
total_allocation_size: 100_000 * CT_UNIT,
auction_round_allocation_percentage: Percent::from_percent(50u8),
minimum_price: PriceOf::<TestRuntime>::from_float(10.0),
minimum_price: decimal_aware_price,
bidding_ticket_sizes: BiddingTicketSizes {
professional: TicketSize::new(Some(5000 * USD_UNIT), None),
institutional: TicketSize::new(Some(5000 * USD_UNIT), None),
Expand Down Expand Up @@ -109,12 +116,17 @@ mod round_flow {

inst.start_community_funding(project_id).unwrap();

let token_price =
inst.get_project_details(project_id).weighted_average_price.unwrap().saturating_mul_int(CT_UNIT);

let desired_price = PriceOf::<TestRuntime>::from_float(11.1818f64).saturating_mul_int(CT_UNIT);
let token_price = inst.get_project_details(project_id).weighted_average_price.unwrap();
let normalized_wap =
PriceProviderOf::<TestRuntime>::convert_back_to_normal_price(token_price, USD_DECIMALS, CT_DECIMALS)
.unwrap();
let desired_price = PriceOf::<TestRuntime>::from_float(11.1818f64);

assert_close_enough!(token_price, desired_price, Perquintill::from_float(0.99));
assert_close_enough!(
normalized_wap.saturating_mul_int(CT_UNIT),
desired_price.saturating_mul_int(CT_UNIT),
Perquintill::from_float(0.99)
);
}

#[test]
Expand All @@ -136,11 +148,18 @@ mod round_flow {
let second_bucket_bid = (BIDDER_6, 500 * CT_UNIT).into();
bids.push(second_bucket_bid);

let project_id = inst.create_community_contributing_project(project_metadata, issuer, evaluations, bids);
let project_id =
inst.create_community_contributing_project(project_metadata.clone(), issuer, evaluations, bids);
let bidder_5_bid =
inst.execute(|| Bids::<TestRuntime>::iter_prefix_values((project_id, BIDDER_6)).next().unwrap());
let wabgp = inst.get_project_details(project_id).weighted_average_price.unwrap();
assert_eq!(bidder_5_bid.original_ct_usd_price.to_float(), 11.0);
let price_normalized = <TestRuntime as Config>::PriceProvider::convert_back_to_normal_price(
bidder_5_bid.original_ct_usd_price,
USD_DECIMALS,
project_metadata.token_information.decimals,
)
.unwrap();
assert_eq!(price_normalized.to_float(), 11.0);
assert_eq!(bidder_5_bid.final_ct_usd_price, wabgp);
}

Expand Down Expand Up @@ -459,7 +478,7 @@ mod round_flow {
.iter()
.map(|acc| UserToForeignAssets {
account: acc.clone(),
asset_amount: CT_UNIT * 1_000_000,
asset_amount: USDT_UNIT * 1_000_000,
asset_id: fundings.next().unwrap().to_assethub_id(),
})
.collect_vec();
Expand All @@ -481,12 +500,18 @@ mod round_flow {

inst.start_community_funding(project_id).unwrap();

let token_price =
inst.get_project_details(project_id).weighted_average_price.unwrap().saturating_mul_int(CT_UNIT);
let token_price = inst.get_project_details(project_id).weighted_average_price.unwrap();
let normalized_wap =
PriceProviderOf::<TestRuntime>::convert_back_to_normal_price(token_price, USD_DECIMALS, CT_DECIMALS)
.unwrap();

let desired_price = PriceOf::<TestRuntime>::from_float(11.1818f64).saturating_mul_int(CT_UNIT);
let desired_price = PriceOf::<TestRuntime>::from_float(11.1818f64);

assert_close_enough!(token_price, desired_price, Perquintill::from_float(0.99));
assert_close_enough!(
normalized_wap.saturating_mul_int(USD_UNIT),
desired_price.saturating_mul_int(USD_UNIT),
Perquintill::from_float(0.99)
);
}
}

Expand Down Expand Up @@ -924,7 +949,12 @@ mod bid_extrinsic {
let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext())));

let mut project_metadata = default_project_metadata(ISSUER_1);
project_metadata.minimum_price = PriceOf::<TestRuntime>::from_float(1.0);
project_metadata.minimum_price = PriceProviderOf::<TestRuntime>::calculate_decimals_aware_price(
PriceOf::<TestRuntime>::from_float(1.0),
USD_DECIMALS,
project_metadata.clone().token_information.decimals,
)
.unwrap();
project_metadata.auction_round_allocation_percentage = Percent::from_percent(50u8);

let evaluations = default_evaluations();
Expand Down Expand Up @@ -978,32 +1008,43 @@ mod bid_extrinsic {
// 40% + 10% + 5% + 5% + 3% = 5 total bids
assert_eq!(stored_bids.len(), 5);

assert_eq!(stored_bids[1].original_ct_usd_price, PriceOf::<TestRuntime>::from_float(1.0));
let normalize_price = |decimal_aware_price| {
PriceProviderOf::<TestRuntime>::convert_back_to_normal_price(
decimal_aware_price,
USD_DECIMALS,
project_metadata.clone().token_information.decimals,
)
.unwrap()
};
assert_eq!(normalize_price(stored_bids[1].original_ct_usd_price), PriceOf::<TestRuntime>::from_float(1.0));
assert_eq!(
stored_bids[1].original_ct_amount,
Percent::from_percent(10) * project_metadata.total_allocation_size
);
assert_eq!(stored_bids[2].original_ct_usd_price, PriceOf::<TestRuntime>::from_rational(11, 10));
assert_eq!(
normalize_price(stored_bids[2].original_ct_usd_price),
PriceOf::<TestRuntime>::from_rational(11, 10)
);
assert_eq!(
stored_bids[2].original_ct_amount,
Percent::from_percent(5) * project_metadata.total_allocation_size
);

assert_eq!(stored_bids[3].original_ct_usd_price, PriceOf::<TestRuntime>::from_float(1.2));
assert_eq!(normalize_price(stored_bids[3].original_ct_usd_price), PriceOf::<TestRuntime>::from_float(1.2));
assert_eq!(
stored_bids[3].original_ct_amount,
Percent::from_percent(5) * project_metadata.total_allocation_size
);

assert_eq!(stored_bids[4].original_ct_usd_price, PriceOf::<TestRuntime>::from_float(1.3));
assert_eq!(normalize_price(stored_bids[4].original_ct_usd_price), PriceOf::<TestRuntime>::from_float(1.3));
assert_eq!(
stored_bids[4].original_ct_amount,
Percent::from_percent(3) * project_metadata.total_allocation_size
);
let current_bucket = inst.execute(|| Buckets::<TestRuntime>::get(project_id)).unwrap();
assert_eq!(current_bucket.current_price, PriceOf::<TestRuntime>::from_float(1.3));
assert_eq!(normalize_price(current_bucket.current_price), PriceOf::<TestRuntime>::from_float(1.3));
assert_eq!(current_bucket.amount_left, Percent::from_percent(2) * project_metadata.total_allocation_size);
assert_eq!(current_bucket.delta_price, PriceOf::<TestRuntime>::from_float(0.1));
assert_eq!(normalize_price(current_bucket.delta_price), PriceOf::<TestRuntime>::from_float(0.1));
}
}

Expand Down Expand Up @@ -1394,7 +1435,12 @@ mod bid_extrinsic {
institutional: TicketSize::new(Some(20_000 * USD_UNIT), None),
phantom: Default::default(),
};
project_metadata.minimum_price = PriceOf::<TestRuntime>::from_float(1.0);
project_metadata.minimum_price = PriceProviderOf::<TestRuntime>::calculate_decimals_aware_price(
PriceOf::<TestRuntime>::from_float(1.0),
USD_DECIMALS,
project_metadata.clone().token_information.decimals,
)
.unwrap();

let evaluations = default_evaluations();

Expand All @@ -1406,17 +1452,23 @@ mod bid_extrinsic {
(BIDDER_3, 200_000 * PLMC).into(),
]);
inst.mint_foreign_asset_to(vec![
(BIDDER_1, 200_000 * CT_UNIT).into(),
(BIDDER_2, 200_000 * CT_UNIT).into(),
(BIDDER_3, 200_000 * CT_UNIT).into(),
(BIDDER_1, 200_000 * USDT_UNIT).into(),
(BIDDER_2, 200_000 * USDT_UNIT).into(),
(BIDDER_3, 200_000 * USDT_UNIT).into(),
]);

// First bucket is covered by one bidder
let big_bid: BidParams<TestRuntime> = (BIDDER_1, 50_000 * CT_UNIT).into();
inst.bid_for_users(project_id, vec![big_bid.clone()]).unwrap();

// A bid at the min price of 1 should require a min of 8k CT, but with a new price of 1.1, we can now bid with less
let smallest_ct_amount_at_8k_usd = PriceOf::<TestRuntime>::from_float(1.1)
let bucket_increase_price = PriceProviderOf::<TestRuntime>::calculate_decimals_aware_price(
PriceOf::<TestRuntime>::from_float(1.1),
USD_DECIMALS,
project_metadata.clone().token_information.decimals,
)
.unwrap();
let smallest_ct_amount_at_8k_usd = bucket_increase_price
.reciprocal()
.unwrap()
.checked_mul_int(8000 * USD_UNIT)
Expand All @@ -1435,7 +1487,7 @@ mod bid_extrinsic {
project_metadata.clone().policy_ipfs_cid.unwrap(),
));
});
let smallest_ct_amount_at_20k_usd = PriceOf::<TestRuntime>::from_float(1.1)
let smallest_ct_amount_at_20k_usd = bucket_increase_price
.reciprocal()
.unwrap()
.checked_mul_int(20_000 * USD_UNIT)
Expand Down

0 comments on commit 9b80e26

Please sign in to comment.