diff --git a/Cargo.lock b/Cargo.lock index 78c79c687..c93e8a84c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4587,6 +4587,7 @@ name = "integration-tests" version = "0.9.0" dependencies = [ "asset-hub-polkadot-runtime", + "assets-common", "cumulus-pallet-xcm", "cumulus-primitives-core", "frame-metadata-hash-extension", @@ -7304,7 +7305,6 @@ dependencies = [ "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", - "variant_count", ] [[package]] @@ -7743,6 +7743,7 @@ dependencies = [ "serde", "sp-io", "sp-runtime", + "staging-xcm", ] [[package]] @@ -8682,6 +8683,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "hex-literal", "jwt-compact", "pallet-timestamp", "parity-scale-codec", @@ -8690,6 +8692,7 @@ dependencies = [ "sp-runtime", "sp-std", "staging-xcm", + "variant_count", ] [[package]] @@ -8729,6 +8732,7 @@ dependencies = [ "log", "pallet-funding", "pallet-transaction-payment-rpc", + "polimec-common", "polimec-runtime", "polkadot-cli", "polkadot-primitives", diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index 595aa0149..cc5d552e6 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -50,7 +50,6 @@ polkadot-parachain-primitives.workspace = true pallet-collective.workspace = true pallet-elections-phragmen.workspace = true pallet-message-queue.workspace = true - cumulus-primitives-core.workspace = true cumulus-pallet-xcm.workspace = true @@ -84,6 +83,7 @@ pallet-skip-feeless-payment.workspace = true xcm-fee-payment-runtime-api.workspace = true hex-literal.workspace = true hex.workspace = true +assets-common.workspace = true # Runtimes polkadot-runtime.workspace = true diff --git a/integration-tests/src/constants.rs b/integration-tests/src/constants.rs index 160e89c11..6b054d28d 100644 --- a/integration-tests/src/constants.rs +++ b/integration-tests/src/constants.rs @@ -18,6 +18,7 @@ use frame_support::BoundedVec; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use pallet_parachain_staking::inflation::{perbill_annual_to_perbill_round, BLOCKS_PER_YEAR}; pub use parachains_common::{AccountId, AssetHubPolkadotAuraId, AuraId, Balance, BlockNumber}; +use polimec_common::assets::AcceptedFundingAsset; use polimec_runtime::{pallet_parachain_staking::Range, PLMC}; use polkadot_primitives::{AssignmentId, ValidatorId}; pub use polkadot_runtime_parachains::configuration::HostConfiguration; @@ -436,9 +437,8 @@ pub mod penpal { pub mod polimec { use super::*; use crate::{PolimecNet, PolimecOrigin, PolimecRuntime}; - use pallet_funding::AcceptedFundingAsset; use polimec_runtime::{BlockchainOperationTreasury, TreasuryAccount}; - use xcm::v4::Parent; + use xcm::v4::{Location, Parent}; use xcm_emulator::TestExt; pub const PARA_ID: u32 = 3344; @@ -454,10 +454,10 @@ pub mod polimec { let dot = (AcceptedFundingAsset::DOT.id(), prices.dot); let usdc = (AcceptedFundingAsset::USDC.id(), prices.usdc); let usdt = (AcceptedFundingAsset::USDT.id(), prices.usdt); - let plmc = (polimec_common::PLMC_FOREIGN_ID, prices.plmc); + let plmc = (Location::here(), prices.plmc); let weth = (AcceptedFundingAsset::WETH.id(), prices.weth); - let values: BoundedVec<(u32, FixedU128), ::MaxFeedValues> = + let values: BoundedVec<(Location, FixedU128), ::MaxFeedValues> = vec![dot, usdc, usdt, plmc, weth].try_into().expect("benchmarks can panic"); let alice: [u8; 32] = [ 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, @@ -524,15 +524,15 @@ pub mod polimec { contribution_tokens: Default::default(), foreign_assets: polimec_runtime::ForeignAssetsConfig { assets: vec![ - (dot_asset_id, alice_account.clone(), true, 100_000_000), - (usdt_asset_id, alice_account.clone(), true, 70_000), - (usdc_asset_id, alice_account.clone(), true, 70_000), + (dot_asset_id.clone(), alice_account.clone(), true, 100_000_000), + (usdt_asset_id.clone(), alice_account.clone(), true, 70_000), + (usdc_asset_id.clone(), alice_account.clone(), true, 70_000), (weth_asset_id, alice_account.clone(), true, 0_000_041_000_000_000_000), ], metadata: vec![ (dot_asset_id, "Local DOT".as_bytes().to_vec(), "DOT".as_bytes().to_vec(), 10), (usdt_asset_id, "Local USDT".as_bytes().to_vec(), "USDT".as_bytes().to_vec(), 6), - (usdc_asset_id, "Local USDC".as_bytes().to_vec(), "USDC".as_bytes().to_vec(), 6), + (usdc_asset_id.clone(), "Local USDC".as_bytes().to_vec(), "USDC".as_bytes().to_vec(), 6), (usdc_asset_id, "Local WETH".as_bytes().to_vec(), "WETH".as_bytes().to_vec(), 18), ], accounts: vec![], diff --git a/integration-tests/src/lib.rs b/integration-tests/src/lib.rs index 7f7d5bd59..be3949ecd 100644 --- a/integration-tests/src/lib.rs +++ b/integration-tests/src/lib.rs @@ -151,6 +151,7 @@ pub mod shortcuts { pub type PenpalAssets = ::Assets; pub type AssetHubAssets = ::LocalAssets; + pub type AssetHubForeignAssets = ::ForeignAssets; pub type PolimecForeignAssets = ::ForeignAssets; pub type PolkadotOrigin = ::RuntimeOrigin; diff --git a/integration-tests/src/tests/defaults.rs b/integration-tests/src/tests/defaults.rs index 2def4b508..6b2aed4af 100644 --- a/integration-tests/src/tests/defaults.rs +++ b/integration-tests/src/tests/defaults.rs @@ -17,13 +17,13 @@ use crate::PolimecRuntime; use frame_support::BoundedVec; pub use pallet_funding::instantiator::{BidParams, ContributionParams, EvaluationParams}; use pallet_funding::{ - AcceptedFundingAsset, BiddingTicketSizes, ContributingTicketSizes, CurrencyMetadata, ParticipantsAccountType, - ParticipationMode, PriceProviderOf, ProjectMetadata, ProjectMetadataOf, TicketSize, + BiddingTicketSizes, ContributingTicketSizes, CurrencyMetadata, ParticipantsAccountType, ParticipationMode, + PriceProviderOf, ProjectMetadata, ProjectMetadataOf, TicketSize, }; use sp_arithmetic::{FixedPointNumber, Percent}; use macros::generate_accounts; -use polimec_common::{ProvideAssetPrice, USD_DECIMALS, USD_UNIT}; +use polimec_common::{assets::AcceptedFundingAsset, ProvideAssetPrice, USD_DECIMALS, USD_UNIT}; use polimec_runtime::{AccountId, PLMC}; use sp_runtime::{traits::ConstU32, Perquintill}; use ParticipationMode::{Classic, OTM}; diff --git a/integration-tests/src/tests/e2e.rs b/integration-tests/src/tests/e2e.rs index 9b8d6111e..0c94f7891 100644 --- a/integration-tests/src/tests/e2e.rs +++ b/integration-tests/src/tests/e2e.rs @@ -27,6 +27,10 @@ use itertools::Itertools; use macros::generate_accounts; use pallet_funding::{traits::VestingDurationCalculation, *}; use polimec_common::{ + assets::{ + AcceptedFundingAsset, + AcceptedFundingAsset::{DOT, USDC, USDT}, + }, credentials::InvestorType, migration_types::{MigrationStatus, ParticipationType}, ProvideAssetPrice, USD_DECIMALS, USD_UNIT, @@ -35,7 +39,6 @@ use polimec_common_test_utils::{generate_did_from_account, get_mock_jwt, get_moc use polimec_runtime::PLMC; use sp_arithmetic::{FixedPointNumber, Percent, Perquintill}; use sp_runtime::FixedU128; -use AcceptedFundingAsset::{DOT, USDC, USDT}; use InvestorType::{Institutional, Professional, Retail}; use ParticipationMode::{Classic, OTM}; diff --git a/integration-tests/src/tests/oracle.rs b/integration-tests/src/tests/oracle.rs index 15c6617fd..e7eb478cd 100644 --- a/integration-tests/src/tests/oracle.rs +++ b/integration-tests/src/tests/oracle.rs @@ -15,27 +15,27 @@ // along with this program. If not, see . use crate::*; -use pallet_funding::AcceptedFundingAsset; /// Tests for the oracle pallet integration. /// Alice, Bob, Charlie are members of the OracleProvidersMembers. /// Only members should be able to feed data into the oracle. use parity_scale_codec::alloc::collections::HashMap; -use polimec_common::PLMC_FOREIGN_ID; +use polimec_common::assets::AcceptedFundingAsset; use polimec_runtime::{Oracle, RuntimeOrigin}; use sp_runtime::{bounded_vec, BoundedVec, FixedU128}; +use std::collections::BTreeMap; use tests::defaults::*; use AcceptedFundingAsset::{DOT, USDC, USDT, WETH}; fn values( values: [f64; 5], -) -> BoundedVec<(u32, FixedU128), >::MaxFeedValues> { +) -> BoundedVec<(Location, FixedU128), >::MaxFeedValues> { let [dot, usdc, usdt, weth, plmc] = values; bounded_vec![ (DOT.id(), FixedU128::from_float(dot)), (USDC.id(), FixedU128::from_float(usdc)), (USDT.id(), FixedU128::from_float(usdt)), (WETH.id(), FixedU128::from_float(weth)), - (PLMC_FOREIGN_ID, FixedU128::from_float(plmc)) + (Location::here(), FixedU128::from_float(plmc)) ] } @@ -55,12 +55,12 @@ fn members_can_feed_data() { let charlie = PolimecNet::account_id_of(CHARLIE); assert_ok!(Oracle::feed_values(RuntimeOrigin::signed(charlie.clone()), values([4.84, 1.0, 1.0, 2500.0, 0.4]))); - let expected_values = HashMap::from([ + let expected_values = BTreeMap::from([ (DOT.id(), FixedU128::from_float(4.84)), (USDC.id(), FixedU128::from_float(1.0)), (USDT.id(), FixedU128::from_float(1.0)), (WETH.id(), FixedU128::from_float(2500.0)), - (PLMC_FOREIGN_ID, FixedU128::from_float(0.4)), + (Location::here(), FixedU128::from_float(0.4)), ]); for (key, value) in Oracle::get_all_values() { @@ -101,12 +101,12 @@ fn data_is_correctly_combined() { )); // Default CombineData implementation is the median value - let expected_values = HashMap::from([ + let expected_values = BTreeMap::from([ (DOT.id(), FixedU128::from_float(2.0)), (USDC.id(), FixedU128::from_float(1.0)), (USDT.id(), FixedU128::from_float(1.1)), (WETH.id(), FixedU128::from_float(2500.0)), - (PLMC_FOREIGN_ID, FixedU128::from_float(0.22222)), + (Location::here(), FixedU128::from_float(0.22222)), ]); for (key, value) in Oracle::get_all_values() { diff --git a/integration-tests/src/tests/otm_edge_cases.rs b/integration-tests/src/tests/otm_edge_cases.rs index 9b70d63a1..b02769463 100644 --- a/integration-tests/src/tests/otm_edge_cases.rs +++ b/integration-tests/src/tests/otm_edge_cases.rs @@ -5,8 +5,10 @@ use crate::{ }; use frame_support::traits::fungibles::Inspect; use macros::generate_accounts; -use pallet_funding::{traits::BondingRequirementCalculation, AcceptedFundingAsset, MultiplierOf, ParticipationMode}; -use polimec_common::{credentials::InvestorType, ProvideAssetPrice, PLMC_DECIMALS, PLMC_FOREIGN_ID, USD_UNIT}; +use pallet_funding::{traits::BondingRequirementCalculation, MultiplierOf, ParticipationMode}; +use polimec_common::{ + assets::AcceptedFundingAsset, credentials::InvestorType, ProvideAssetPrice, PLMC_DECIMALS, USD_UNIT, +}; use polimec_common_test_utils::{generate_did_from_account, get_mock_jwt_with_cid}; use sp_arithmetic::{FixedPointNumber, FixedU128}; use sp_core::bounded_vec; @@ -42,7 +44,7 @@ fn otm_fee_below_min_amount_reverts() { .unwrap(); let plmc_price = ::PriceProvider::get_decimals_aware_price( - PLMC_FOREIGN_ID, + Location::here(), 6, PLMC_DECIMALS, ) @@ -132,7 +134,7 @@ fn after_otm_fee_user_goes_under_ed_reverts() { ); let plmc_price = ::PriceProvider::get_decimals_aware_price( - PLMC_FOREIGN_ID, + Location::here(), 6, PLMC_DECIMALS, ) diff --git a/integration-tests/src/tests/reserve_backed_transfers.rs b/integration-tests/src/tests/reserve_backed_transfers.rs index 71740de5b..ef8856dd4 100644 --- a/integration-tests/src/tests/reserve_backed_transfers.rs +++ b/integration-tests/src/tests/reserve_backed_transfers.rs @@ -17,12 +17,13 @@ use crate::*; use frame_support::{ traits::{ - fungible::{Inspect as FungibleInspect, Unbalanced}, + fungible::{Inspect as FungibleInspect, Mutate as FMutate, Unbalanced}, fungibles::{Inspect, Mutate}, PalletInfoAccess, }, weights::WeightToFee, }; +use polimec_common::assets::AcceptedFundingAsset; use sp_runtime::DispatchError; use xcm_emulator::Parachain; @@ -30,96 +31,118 @@ const RESERVE_TRANSFER_AMOUNT: u128 = 10_0_000_000_000; // 10 DOT const MAX_REF_TIME: u64 = 5_000_000_000; const MAX_PROOF_SIZE: u64 = 200_000; -fn create_asset_on_asset_hub(asset_id: u32) { - if asset_id == 10 { - return; - } +fn create_asset_on_asset_hub(asset: Location) { let admin_account = AssetNet::account_id_of(FERDIE); - AssetNet::execute_with(|| { - assert_ok!(AssetHubAssets::force_create( - AssetHubOrigin::root(), - asset_id.into(), - sp_runtime::MultiAddress::Id(admin_account.clone()), - true, - 0_0_010_000_000u128 - )); - }); + AssetNet::execute_with(|| match asset.unpack() { + (1, [Parachain(1000), PalletInstance(50), GeneralIndex(id)]) => { + assert_ok!(AssetHubAssets::force_create( + AssetHubOrigin::root(), + (*id as u32).into(), + sp_runtime::MultiAddress::Id(admin_account.clone()), + true, + 0_0_010_000_000u128 + )); + }, + weth if weth == AcceptedFundingAsset::WETH.id().unpack() => { + assert_ok!(AssetHubForeignAssets::force_create( + AssetHubOrigin::root(), + asset.try_into().unwrap(), + sp_runtime::MultiAddress::Id(admin_account.clone()), + true, + 0_000_041_000_000_000_000 + )); + }, + (1, []) => {}, + _ => unreachable!("Unexpected Asset"), + }) } -fn mint_asset_on_asset_hub_to(asset_id: u32, recipient: &AssetHubAccountId, amount: u128) { - AssetNet::execute_with(|| { - match asset_id { - 10 => { - assert_ok!(AssetHubBalances::write_balance(recipient, amount)); - }, - _ => { - assert_ok!(AssetHubAssets::mint_into(asset_id, recipient, amount)); - }, - } - AssetHubSystem::reset_events(); - }); +fn mint_asset_on_asset_hub_to(asset: Location, recipient: &AssetHubAccountId, amount: u128) { + AssetNet::execute_with(|| match asset.unpack() { + (1, [Parachain(1000), PalletInstance(50), GeneralIndex(id)]) => { + assert_ok!(AssetHubAssets::mint_into(*id as u32, recipient, amount)); + }, + weth if weth == AcceptedFundingAsset::WETH.id().unpack() => { + assert_ok!(AssetHubForeignAssets::mint_into(asset.try_into().unwrap(), recipient, amount)); + }, + (1, []) => { + assert_ok!(AssetHubBalances::mint_into(recipient, amount)); + }, + _ => unreachable!("Unexpected Asset"), + }) } -fn get_polimec_balances(asset_id: u32, user_account: AccountId) -> (u128, u128, u128, u128) { +fn get_polimec_balances(asset: Location, user_account: AccountId) -> (u128, u128, u128, u128) { PolimecNet::execute_with(|| { ( - PolimecForeignAssets::balance(asset_id, user_account.clone()), + PolimecForeignAssets::balance(asset.clone(), user_account.clone()), PolimecBalances::balance(&user_account.clone()), - PolimecForeignAssets::total_issuance(asset_id), + PolimecForeignAssets::total_issuance(asset), PolimecBalances::total_issuance(), ) }) } -fn get_asset_hub_balances(asset_id: u32, user_account: AccountId, polimec_account: AccountId) -> (u128, u128, u128) { - AssetNet::execute_with(|| { - match asset_id { - // Asset id 10 equals Dot - 10 => ( - AssetHubBalances::balance(&user_account), - AssetHubBalances::balance(&polimec_account), - AssetHubBalances::total_issuance(), - ), - _ => ( - AssetHubAssets::balance(asset_id, user_account.clone()), - AssetHubAssets::balance(asset_id, polimec_account.clone()), - AssetHubAssets::total_issuance(asset_id), - ), - } +fn get_asset_hub_balances(asset: Location, user_account: AccountId, polimec_account: AccountId) -> (u128, u128, u128) { + AssetNet::execute_with(|| match asset.unpack() { + (1, [Parachain(1000), PalletInstance(50), GeneralIndex(id)]) => { + let id = *id as u32; + ( + AssetHubAssets::balance(id, user_account.clone()), + AssetHubAssets::balance(id, polimec_account.clone()), + AssetHubAssets::total_issuance(id), + ) + }, + weth if weth == AcceptedFundingAsset::WETH.id().unpack() => { + let multilocation = asset.try_into().unwrap(); + ( + AssetHubForeignAssets::balance(multilocation, user_account.clone()), + AssetHubForeignAssets::balance(multilocation, polimec_account.clone()), + AssetHubForeignAssets::total_issuance(multilocation), + ) + }, + (1, []) => ( + AssetHubBalances::balance(&user_account), + AssetHubBalances::balance(&polimec_account), + AssetHubBalances::total_issuance(), + ), + _ => unreachable!("Asset unsupported"), }) } /// Test the reserve based transfer from asset_hub to Polimec. Depending of the asset_id we /// transfer either USDT, USDC and DOT. -fn test_reserve_to_polimec(asset_id: u32) { - create_asset_on_asset_hub(asset_id); - let asset_hub_asset_id: Location = match asset_id { - 10 => Parent.into(), - _ => (PalletInstance(AssetHubAssets::index() as u8), GeneralIndex(asset_id as u128)).into(), - }; +fn test_reserve_to_polimec(asset: Location) { + create_asset_on_asset_hub(asset.clone()); let alice_account = PolimecNet::account_id_of(ALICE); let polimec_sibling_account = AssetNet::sovereign_account_id_of((Parent, Parachain(PolimecNet::para_id().into())).into()); let max_weight = Weight::from_parts(MAX_REF_TIME, MAX_PROOF_SIZE); - mint_asset_on_asset_hub_to(asset_id, &alice_account, 100_0_000_000_000); + mint_asset_on_asset_hub_to(asset.clone(), &alice_account, 100_0_000_000_000); let ( polimec_prev_alice_asset_balance, polimec_prev_alice_plmc_balance, polimec_prev_asset_issuance, polimec_prev_plmc_issuance, - ) = get_polimec_balances(asset_id, alice_account.clone()); + ) = get_polimec_balances(asset.clone(), alice_account.clone()); // check AssetHub's pre transfer balances and issuance let (asset_hub_prev_alice_asset_balance, asset_hub_prev_polimec_asset_balance, asset_hub_prev_asset_issuance) = - get_asset_hub_balances(asset_id, alice_account.clone(), polimec_sibling_account.clone()); + get_asset_hub_balances(asset.clone(), alice_account.clone(), polimec_sibling_account.clone()); AssetNet::execute_with(|| { - let asset_transfer: Asset = (asset_hub_asset_id, RESERVE_TRANSFER_AMOUNT).into(); + let mut local_asset = asset.clone(); + + local_asset = asset + .clone() + .reanchored(&(Parent, Parachain(1000)).into(), &[GlobalConsensus(NetworkId::Polkadot)].into()) + .unwrap(); + let asset_transfer: Asset = (local_asset.clone(), RESERVE_TRANSFER_AMOUNT).into(); let origin = AssetHubOrigin::signed(alice_account.clone()); - let dest: VersionedLocation = ParentThen((Parachain(PolimecNet::para_id().into())).into()).into(); + let dest: VersionedLocation = ParentThen(Parachain(PolimecNet::para_id().into()).into()).into(); let beneficiary: VersionedLocation = AccountId32 { network: None, id: alice_account.clone().into() }.into(); let assets: VersionedAssets = asset_transfer.into(); let fee_asset_item = 0; @@ -151,10 +174,10 @@ fn test_reserve_to_polimec(asset_id: u32) { polimec_post_alice_plmc_balance, polimec_post_asset_issuance, polimec_post_plmc_issuance, - ) = get_polimec_balances(asset_id, alice_account.clone()); + ) = get_polimec_balances(asset.clone(), alice_account.clone()); let (asset_hub_post_alice_asset_balance, asset_hub_post_polimec_asset_balance, asset_hub_post_asset_issuance) = - get_asset_hub_balances(asset_id, alice_account.clone(), polimec_sibling_account.clone()); + get_asset_hub_balances(asset, alice_account.clone(), polimec_sibling_account.clone()); let polimec_delta_alice_asset_balance = polimec_post_alice_asset_balance.abs_diff(polimec_prev_alice_asset_balance); let polimec_delta_alice_plmc_balance = polimec_post_alice_plmc_balance.abs_diff(polimec_prev_alice_plmc_balance); @@ -206,31 +229,19 @@ fn test_reserve_to_polimec(asset_id: u32) { assert_eq!(polimec_delta_plmc_issuance, 0, "Polimec PLMC issuance should not have changed"); } -fn test_polimec_to_reserve(asset_id: u32) { - create_asset_on_asset_hub(asset_id); - let asset_hub_asset_id: Location = match asset_id { - 10 => Parent.into(), - _ => ParentThen( - ( - Parachain(AssetNet::para_id().into()), - PalletInstance(AssetHubAssets::index() as u8), - GeneralIndex(asset_id as u128), - ) - .into(), - ) - .into(), - }; +fn test_polimec_to_reserve(asset: Location) { + create_asset_on_asset_hub(asset.clone()); let alice_account = PolimecNet::account_id_of(ALICE); let polimec_sibling_account = AssetNet::sovereign_account_id_of((Parent, Parachain(PolimecNet::para_id().into())).into()); let max_weight = Weight::from_parts(MAX_REF_TIME, MAX_PROOF_SIZE); - mint_asset_on_asset_hub_to(asset_id, &polimec_sibling_account, RESERVE_TRANSFER_AMOUNT + 1_0_000_000_000); + mint_asset_on_asset_hub_to(asset.clone(), &polimec_sibling_account, RESERVE_TRANSFER_AMOUNT + 1_0_000_000_000); PolimecNet::execute_with(|| { assert_ok!(PolimecForeignAssets::mint_into( - asset_id, + asset.clone(), &alice_account, RESERVE_TRANSFER_AMOUNT + 1_0_000_000_000 )); @@ -241,14 +252,14 @@ fn test_polimec_to_reserve(asset_id: u32) { polimec_prev_alice_plmc_balance, polimec_prev_asset_issuance, polimec_prev_plmc_issuance, - ) = get_polimec_balances(asset_id, alice_account.clone()); + ) = get_polimec_balances(asset.clone(), alice_account.clone()); // check AssetHub's pre transfer balances and issuance let (asset_hub_prev_alice_asset_balance, asset_hub_prev_polimec_asset_balance, asset_hub_prev_asset_issuance) = - get_asset_hub_balances(asset_id, alice_account.clone(), polimec_sibling_account.clone()); + get_asset_hub_balances(asset.clone(), alice_account.clone(), polimec_sibling_account.clone()); PolimecNet::execute_with(|| { - let asset_transfer: Asset = (asset_hub_asset_id, RESERVE_TRANSFER_AMOUNT + 1_0_000_000_000).into(); + let asset_transfer: Asset = (asset.clone(), RESERVE_TRANSFER_AMOUNT + 1_0_000_000_000).into(); let origin = PolimecOrigin::signed(alice_account.clone()); let dest: VersionedLocation = ParentThen((Parachain(AssetNet::para_id().into())).into()).into(); @@ -283,10 +294,10 @@ fn test_polimec_to_reserve(asset_id: u32) { polimec_post_alice_plmc_balance, polimec_post_asset_issuance, polimec_post_plmc_issuance, - ) = get_polimec_balances(asset_id, alice_account.clone()); + ) = get_polimec_balances(asset.clone(), alice_account.clone()); let (asset_hub_post_alice_asset_balance, asset_hub_post_polimec_asset_balance, asset_hub_post_asset_issuance) = - get_asset_hub_balances(asset_id, alice_account.clone(), polimec_sibling_account.clone()); + get_asset_hub_balances(asset, alice_account.clone(), polimec_sibling_account.clone()); let polimec_delta_alice_asset_balance = polimec_post_alice_asset_balance.abs_diff(polimec_prev_alice_asset_balance); let polimec_delta_alice_plmc_balance = polimec_post_alice_plmc_balance.abs_diff(polimec_prev_alice_plmc_balance); @@ -335,61 +346,63 @@ fn test_polimec_to_reserve(asset_id: u32) { /// Test reserve based transfer of USDT from AssetHub to Polimec. #[test] fn reserve_usdt_to_polimec() { - let asset_id = 1984; - test_reserve_to_polimec(asset_id); + let asset = AcceptedFundingAsset::USDT.id(); + test_reserve_to_polimec(asset); } /// Test reserve based transfer of USDC from AssetHub to Polimec. #[test] fn reserve_usdc_to_polimec() { - let asset_id = 1337; - test_reserve_to_polimec(asset_id); + let asset = AcceptedFundingAsset::USDC.id(); + test_reserve_to_polimec(asset); } /// Test reserve based transfer of DOT from AssetHub to Polimec. #[test] fn reserve_dot_to_polimec() { - let asset_id = 10; - test_reserve_to_polimec(asset_id); + let asset = AcceptedFundingAsset::DOT.id(); + test_reserve_to_polimec(asset); } /// Test that reserve based transfer of random asset from AssetHub to Polimec fails. #[test] #[should_panic] fn reserve_random_asset_to_polimec() { - let asset_id = 69; - test_reserve_to_polimec(asset_id); + let asset: Location = (Parent, Parachain(1000), PalletInstance(50), GeneralIndex(420)).into(); + test_reserve_to_polimec(asset); } /// Test transfer of reserve-based DOT from Polimec back to AssetHub. #[test] fn polimec_usdt_to_reserve() { - let asset_id = 1984; - test_polimec_to_reserve(asset_id); + let asset = AcceptedFundingAsset::USDT.id(); + test_polimec_to_reserve(asset); } /// Test transfer of reserve-based DOT from Polimec back to AssetHub. #[test] fn polimec_usdc_to_reserve() { - let asset_id = 1337; - test_polimec_to_reserve(asset_id); + let asset = AcceptedFundingAsset::USDC.id(); + test_polimec_to_reserve(asset); } /// Test transfer of reserve-based DOT from Polimec back to AssetHub. #[test] fn polimec_dot_to_reserve() { - let asset_id = 10; - test_polimec_to_reserve(asset_id); + let asset = AcceptedFundingAsset::DOT.id(); + test_polimec_to_reserve(asset); } #[test] fn test_user_cannot_create_foreign_asset_on_polimec() { + let asset: Location = (Parent, Parachain(1000), PalletInstance(50), GeneralIndex(420)).into(); + PolimecNet::execute_with(|| { let admin = AssetNet::account_id_of(ALICE); assert_noop!( PolimecForeignAssets::create( PolimecOrigin::signed(admin.clone()), - 69.into(), + asset.into(), sp_runtime::MultiAddress::Id(admin), 0_0_010_000_000u128, ), diff --git a/integration-tests/src/tests/runtime_apis.rs b/integration-tests/src/tests/runtime_apis.rs index c097b2158..e293de066 100644 --- a/integration-tests/src/tests/runtime_apis.rs +++ b/integration-tests/src/tests/runtime_apis.rs @@ -1,30 +1,27 @@ use crate::{constants::*, *}; - +use assets_common::runtime_api::runtime_decl_for_fungibles_api::FungiblesApiV2; +use frame_support::traits::{fungible::Inspect, fungibles::Mutate}; +use polimec_common::assets::AcceptedFundingAsset; +use sp_arithmetic::FixedU128; +use xcm::v4::Junctions::X3; +use xcm_fee_payment_runtime_api::fees::runtime_decl_for_xcm_payment_api::XcmPaymentApiV1; mod xcm_payment_api { use super::*; - use sp_arithmetic::FixedU128; - use xcm::v4::Junctions::X3; - use xcm_fee_payment_runtime_api::fees::runtime_decl_for_xcm_payment_api::XcmPaymentApiV1; + use itertools::Itertools; #[test] fn query_acceptable_payment_assets() { PolimecNet::execute_with(|| { let accepted_payment_assets = PolimecRuntime::query_acceptable_payment_assets(4u32).unwrap(); - assert_eq!( - accepted_payment_assets, - vec![ - VersionedAssetId::V4(AssetId(Location { parents: 0, interior: Here },),), - VersionedAssetId::V4(AssetId(Location { parents: 1, interior: Here },),), - VersionedAssetId::V4(AssetId(Location { - parents: 1, - interior: X3([Parachain(1000,), PalletInstance(50,), GeneralIndex(1984,),].into(),), - },),), - VersionedAssetId::V4(AssetId(Location { - parents: 1, - interior: X3([Parachain(1000,), PalletInstance(50,), GeneralIndex(1337,),].into(),), - },),), - ] - ); + let versioned_funding_assets = AcceptedFundingAsset::all_ids() + .into_iter() + .map(|loc| AssetId::from(loc)) + .map(|a| VersionedAssetId::from(a)) + .collect_vec(); + + for asset in versioned_funding_assets { + assert!(accepted_payment_assets.contains(&asset)); + } }); } @@ -70,3 +67,30 @@ mod xcm_payment_api { }); } } + +mod fungibles_api { + use super::*; + + #[test] + fn query_account_assets() { + PolimecNet::execute_with(|| { + let alice_account = PolimecNet::account_id_of(accounts::ALICE); + + assert_ok!(PolimecForeignAssets::mint_into( + AcceptedFundingAsset::DOT.id(), + &alice_account, + 100_0_000_000_000 + )); + assert_ok!(PolimecForeignAssets::mint_into(AcceptedFundingAsset::USDT.id(), &alice_account, 100_000)); + assert_ok!(PolimecForeignAssets::mint_into(AcceptedFundingAsset::USDC.id(), &alice_account, 100_000)); + assert_ok!(PolimecForeignAssets::mint_into( + AcceptedFundingAsset::WETH.id(), + &alice_account, + 100_000_000_000_000 + )); + + let alice_assets = PolimecRuntime::query_account_balances(alice_account); + dbg!(alice_assets).unwrap(); + }); + } +} diff --git a/integration-tests/src/tests/transaction_payment.rs b/integration-tests/src/tests/transaction_payment.rs index 7813a3ffc..a3a8929bc 100644 --- a/integration-tests/src/tests/transaction_payment.rs +++ b/integration-tests/src/tests/transaction_payment.rs @@ -7,10 +7,10 @@ use frame_support::{ traits::{fungible::Mutate as FungibleMutate, fungibles, fungibles::Mutate as FungiblesMutate}, }; use macros::generate_accounts; -use pallet_funding::{AcceptedFundingAsset, PriceProviderOf}; +use pallet_funding::PriceProviderOf; use pallet_transaction_payment::FeeDetails; use parity_scale_codec::Encode; -use polimec_common::{ProvideAssetPrice, PLMC_DECIMALS, PLMC_FOREIGN_ID, USD_DECIMALS}; +use polimec_common::{assets::AcceptedFundingAsset, ProvideAssetPrice, PLMC_DECIMALS, USD_DECIMALS}; use polimec_runtime::Header; use sp_arithmetic::{FixedPointNumber, FixedU128}; use sp_core::H256; @@ -21,7 +21,11 @@ use sp_runtime::{ use xcm_emulator::TestExt; generate_accounts!(ALICE, AUTHOR); use frame_support::traits::fungible::Inspect; -use xcm::v3::{Junction::*, Junctions::*, MultiLocation}; +use xcm::{ + v3::{Junction::*, Junctions::*, MultiLocation}, + v4::Location, +}; + // Setup code inspired by pallet-authorship tests fn seal_header(mut header: Header, aura_index: u64) -> Header { { @@ -62,16 +66,17 @@ fn fee_paid_with_foreign_assets() { let usdt_id = AcceptedFundingAsset::USDT.id(); let usdt_multilocation = MultiLocation { parents: 1, interior: X3(Parachain(1000), PalletInstance(50), GeneralIndex(1984)) }; - let usdt_decimals = >::decimals(usdt_id); + let usdt_decimals = + >::decimals(usdt_id.clone()); let usdt_unit = 10u128.pow(usdt_decimals as u32); let plmc_decimals = PLMC_DECIMALS; let plmc_unit = 10u128.pow(plmc_decimals as u32); PolimecBalances::set_balance(&alice, 0u128); - PolimecForeignAssets::set_balance(usdt_id, &alice, 100 * usdt_unit); + PolimecForeignAssets::set_balance(usdt_id.clone(), &alice, 100 * usdt_unit); // Fees are usually very small, so we need to give the treasury an ED. PolimecForeignAssets::set_balance( - usdt_id, + usdt_id.clone(), &polimec_runtime::BlockchainOperationTreasury::get(), 100 * usdt_unit, ); @@ -98,20 +103,20 @@ fn fee_paid_with_foreign_assets() { let expected_plmc_tip = tip; let plmc_price_decimal_aware = - >::get_decimals_aware_price(PLMC_FOREIGN_ID, USD_DECIMALS, plmc_decimals) + >::get_decimals_aware_price(Location::here(), USD_DECIMALS, plmc_decimals) .expect("Price irretrievable"); // USDT should be configured with the same decimals as our underlying USD unit, and we set the price to 1USD at the beginning of this test. let expected_usd_fee = plmc_price_decimal_aware.saturating_mul_int(expected_plmc_fee); let expected_usd_tip = plmc_price_decimal_aware.saturating_mul_int(expected_plmc_tip); - let prev_alice_usdt_balance = PolimecForeignAssets::balance(usdt_id, alice.clone()); + let prev_alice_usdt_balance = PolimecForeignAssets::balance(usdt_id.clone(), alice.clone()); let prev_alice_plmc_balance = PolimecBalances::balance(&alice); let prev_blockchain_operation_treasury_usdt_balance = - PolimecForeignAssets::balance(usdt_id, polimec_runtime::BlockchainOperationTreasury::get()); + PolimecForeignAssets::balance(usdt_id.clone(), polimec_runtime::BlockchainOperationTreasury::get()); let prev_blockchain_operation_treasury_plmc_balance = PolimecBalances::balance(&polimec_runtime::BlockchainOperationTreasury::get()); - let prev_block_author_usdt_balance = PolimecForeignAssets::balance(usdt_id, block_author.clone()); + let prev_block_author_usdt_balance = PolimecForeignAssets::balance(usdt_id.clone(), block_author.clone()); let prev_block_author_plmc_balance = PolimecBalances::balance(&block_author.clone()); // Executes the `pre_dispatch` check for the transaction using the signed extension. @@ -123,13 +128,13 @@ fn fee_paid_with_foreign_assets() { TxPaymentExtension::post_dispatch(Some(pre), &dispatch_info, &post_info, paid_call_len, &Ok(())).unwrap(); - let post_alice_usdt_balance = PolimecForeignAssets::balance(usdt_id, alice.clone()); + let post_alice_usdt_balance = PolimecForeignAssets::balance(usdt_id.clone(), alice.clone()); let post_alice_plmc_balance = PolimecBalances::balance(&alice); let post_blockchain_operation_treasury_usdt_balance = - PolimecForeignAssets::balance(usdt_id, polimec_runtime::BlockchainOperationTreasury::get()); + PolimecForeignAssets::balance(usdt_id.clone(), polimec_runtime::BlockchainOperationTreasury::get()); let post_blockchain_operation_treasury_plmc_balance = PolimecBalances::balance(&polimec_runtime::BlockchainOperationTreasury::get()); - let post_block_author_usdt_balance = PolimecForeignAssets::balance(usdt_id, block_author.clone()); + let post_block_author_usdt_balance = PolimecForeignAssets::balance(usdt_id.clone(), block_author.clone()); let post_block_author_plmc_balance = PolimecBalances::balance(&block_author.clone()); assert_eq!(prev_alice_usdt_balance - post_alice_usdt_balance, expected_usd_fee + expected_usd_tip); @@ -144,7 +149,7 @@ fn fee_paid_with_foreign_assets() { // * Now we check if the same behavior but using PLMC as a fee asset, produces the same results. (2plmc=1usdt) * PolimecBalances::set_balance(&alice, 100 * plmc_unit); - PolimecForeignAssets::set_balance(usdt_id, &alice, 0u128); + PolimecForeignAssets::set_balance(usdt_id.clone(), &alice, 0u128); // Fees are usually very small, so we need to give the treasury an ED. PolimecBalances::set_balance(&polimec_runtime::BlockchainOperationTreasury::get(), 100 * plmc_unit); // Block author doesn't need to have any balance, as the tip is bigger than ED. @@ -153,13 +158,13 @@ fn fee_paid_with_foreign_assets() { let signed_extension = pallet_asset_tx_payment::ChargeAssetTxPayment::::from(10 * plmc_unit, None); - let prev_alice_usdt_balance = PolimecForeignAssets::balance(usdt_id, alice.clone()); + let prev_alice_usdt_balance = PolimecForeignAssets::balance(usdt_id.clone(), alice.clone()); let prev_alice_plmc_balance = PolimecBalances::balance(&alice); let prev_blockchain_operation_treasury_usdt_balance = - PolimecForeignAssets::balance(usdt_id, polimec_runtime::BlockchainOperationTreasury::get()); + PolimecForeignAssets::balance(usdt_id.clone(), polimec_runtime::BlockchainOperationTreasury::get()); let prev_blockchain_operation_treasury_plmc_balance = PolimecBalances::balance(&polimec_runtime::BlockchainOperationTreasury::get()); - let prev_block_author_usdt_balance = PolimecForeignAssets::balance(usdt_id, block_author.clone()); + let prev_block_author_usdt_balance = PolimecForeignAssets::balance(usdt_id.clone(), block_author.clone()); let prev_block_author_plmc_balance = PolimecBalances::balance(&block_author.clone()); let pre = signed_extension.pre_dispatch(&alice, &paid_call, &dispatch_info, paid_call_len).unwrap(); @@ -167,10 +172,10 @@ fn fee_paid_with_foreign_assets() { TxPaymentExtension::post_dispatch(Some(pre), &dispatch_info, &post_info, paid_call_len, &Ok(())).unwrap(); - let post_alice_usdt_balance = PolimecForeignAssets::balance(usdt_id, alice.clone()); + let post_alice_usdt_balance = PolimecForeignAssets::balance(usdt_id.clone(), alice.clone()); let post_alice_plmc_balance = PolimecBalances::balance(&alice); let post_blockchain_operation_treasury_usdt_balance = - PolimecForeignAssets::balance(usdt_id, polimec_runtime::BlockchainOperationTreasury::get()); + PolimecForeignAssets::balance(usdt_id.clone(), polimec_runtime::BlockchainOperationTreasury::get()); let post_blockchain_operation_treasury_plmc_balance = PolimecBalances::balance(&polimec_runtime::BlockchainOperationTreasury::get()); let post_block_author_usdt_balance = PolimecForeignAssets::balance(usdt_id, block_author.clone()); diff --git a/integration-tests/src/tests/xcm_config.rs b/integration-tests/src/tests/xcm_config.rs index bb85e806f..a45aa860a 100644 --- a/integration-tests/src/tests/xcm_config.rs +++ b/integration-tests/src/tests/xcm_config.rs @@ -23,8 +23,7 @@ fn execution_fees_go_to_treasury() { let beneficiary: PolimecAccountId = [0u8; 32].into(); let assert_reserve_asset_fee_goes_to_treasury = |asset: Asset| { - let asset_location = asset.id.0.clone(); - let asset_id = SupportedAssets::convert(&asset_location).unwrap(); + let asset_id = asset.id.0.clone(); let asset_amount = if let Fungible(amount) = asset.fun { amount } else { unreachable!() }; let xcm = Xcm::(vec![ @@ -37,8 +36,8 @@ fn execution_fees_go_to_treasury() { }, ]); PolimecNet::execute_with(|| { - let prev_treasury_balance = PolimecForeignAssets::balance(asset_id, TreasuryAccount::get()); - let prev_beneficiary_balance = PolimecForeignAssets::balance(asset_id, beneficiary.clone()); + let prev_treasury_balance = PolimecForeignAssets::balance(asset_id.clone(), TreasuryAccount::get()); + let prev_beneficiary_balance = PolimecForeignAssets::balance(asset_id.clone(), beneficiary.clone()); let outcome = ::XcmExecutor::prepare_and_execute( Location::new(1, [Parachain(1000)]), @@ -49,7 +48,7 @@ fn execution_fees_go_to_treasury() { ); assert!(outcome.ensure_complete().is_ok()); - let post_treasury_balance = PolimecForeignAssets::balance(asset_id, TreasuryAccount::get()); + let post_treasury_balance = PolimecForeignAssets::balance(asset_id.clone(), TreasuryAccount::get()); let post_beneficiary_balance = PolimecForeignAssets::balance(asset_id, beneficiary.clone()); let net_treasury_balance = post_treasury_balance - prev_treasury_balance; diff --git a/nodes/parachain/Cargo.toml b/nodes/parachain/Cargo.toml index 5e0640ff1..3770a12f1 100644 --- a/nodes/parachain/Cargo.toml +++ b/nodes/parachain/Cargo.toml @@ -28,6 +28,7 @@ futures.workspace = true # Local polimec-runtime.workspace = true pallet-funding.workspace = true +polimec-common.workspace = true # Substrate frame-benchmarking.workspace = true diff --git a/nodes/parachain/src/chain_spec/common.rs b/nodes/parachain/src/chain_spec/common.rs index 06e53ef94..6c436386e 100644 --- a/nodes/parachain/src/chain_spec/common.rs +++ b/nodes/parachain/src/chain_spec/common.rs @@ -2,6 +2,7 @@ use crate::chain_spec::{get_account_id_from_seed, Extensions}; use cumulus_primitives_core::ParaId; #[cfg(not(feature = "runtime-benchmarks"))] use itertools::Itertools; +use polimec_common::assets::AcceptedFundingAsset; #[cfg(not(feature = "runtime-benchmarks"))] use polimec_runtime::MinCandidateStk; use polimec_runtime::{ @@ -17,7 +18,6 @@ use sp_core::{ sr25519, }; use sp_runtime::{traits::AccountIdConversion, Perbill, Percent}; - pub type ChainSpec = sc_service::GenericChainSpec; /// The default XCM version to set in genesis config. @@ -110,9 +110,9 @@ pub fn genesis_config(genesis_config_params: GenesisConfigParams) -> serde_json: #[cfg(feature = "runtime-benchmarks")] let staking_candidates: Vec<(AccountId, Balance)> = vec![]; - let usdt_id = pallet_funding::types::AcceptedFundingAsset::USDT.id(); - let usdc_id = pallet_funding::types::AcceptedFundingAsset::USDC.id(); - let dot_id = pallet_funding::types::AcceptedFundingAsset::DOT.id(); + let usdt_id = AcceptedFundingAsset::USDT.id(); + let usdc_id = AcceptedFundingAsset::USDC.id(); + let dot_id = AcceptedFundingAsset::DOT.id(); serde_json::json!({ "balances": { @@ -123,28 +123,28 @@ pub fn genesis_config(genesis_config_params: GenesisConfigParams) -> serde_json: }, "foreignAssets": { "assets": vec![( - pallet_funding::types::AcceptedFundingAsset::USDT.id(), + AcceptedFundingAsset::USDT.id(), &AccountIdConversion::::into_account_truncating(&::PalletId::get()), true, 70000, ), ( - pallet_funding::types::AcceptedFundingAsset::USDC.id(), + AcceptedFundingAsset::USDC.id(), &AccountIdConversion::::into_account_truncating(&::PalletId::get()), true, 70000, ), ( - pallet_funding::types::AcceptedFundingAsset::DOT.id(), + AcceptedFundingAsset::DOT.id(), &AccountIdConversion::::into_account_truncating(&::PalletId::get()), true, 70000, )], // (id, name, symbol, decimals) "metadata": vec![ - (usdt_id, b"Local USDT", b"USDT", 6), - (usdc_id, b"Local USDC", b"USDC", 6), - (dot_id, b"Local DOT ", b"DOT ", 10) + (usdt_id.clone(), b"Local USDT", b"USDT", 6), + (usdc_id.clone(), b"Local USDC", b"USDC", 6), + (dot_id.clone(), b"Local DOT ", b"DOT ", 10) ], // (id, account_id, amount) "accounts": vec![ diff --git a/pallets/funding/Cargo.toml b/pallets/funding/Cargo.toml index a0bcad723..cb87d7466 100644 --- a/pallets/funding/Cargo.toml +++ b/pallets/funding/Cargo.toml @@ -22,7 +22,6 @@ scale-info = { workspace = true, default-features = false, features = [ "derive", ] } log.workspace = true -variant_count = "1.1.0" pallet-linear-release.workspace = true on-slash-vesting.workspace = true diff --git a/pallets/funding/src/benchmarking.rs b/pallets/funding/src/benchmarking.rs index 710042f6c..d68985a00 100644 --- a/pallets/funding/src/benchmarking.rs +++ b/pallets/funding/src/benchmarking.rs @@ -20,6 +20,7 @@ use super::*; use crate::{instantiator::*, traits::SetPrices}; +use polimec_common::assets::AcceptedFundingAsset; use ParticipationMode::{Classic, OTM}; use frame_benchmarking::v2::*; @@ -47,7 +48,7 @@ const CT_DECIMALS: u8 = 17; const CT_UNIT: u128 = 10u128.pow(CT_DECIMALS as u32); type BenchInstantiator = Instantiator::AllPalletsWithoutSystem, ::RuntimeEvent>; -pub fn usdt_id() -> u32 { +pub fn usdt_id() -> Location { AcceptedFundingAsset::USDT.id() } diff --git a/pallets/funding/src/functions/2_evaluation.rs b/pallets/funding/src/functions/2_evaluation.rs index 2b450984f..dff54a127 100644 --- a/pallets/funding/src/functions/2_evaluation.rs +++ b/pallets/funding/src/functions/2_evaluation.rs @@ -81,7 +81,7 @@ impl Pallet { let now = >::block_number(); let evaluation_id = NextEvaluationId::::get(); let plmc_usd_price = - >::get_decimals_aware_price(PLMC_FOREIGN_ID, USD_DECIMALS, PLMC_DECIMALS) + >::get_decimals_aware_price(Location::here(), USD_DECIMALS, PLMC_DECIMALS) .ok_or(Error::::PriceNotFound)?; let early_evaluation_reward_threshold_usd = T::EvaluationSuccessThreshold::get() * project_details.fundraising_target_usd; diff --git a/pallets/funding/src/functions/6_settlement.rs b/pallets/funding/src/functions/6_settlement.rs index d864675cf..814f2c42e 100644 --- a/pallets/funding/src/functions/6_settlement.rs +++ b/pallets/funding/src/functions/6_settlement.rs @@ -14,6 +14,7 @@ use frame_support::{ use on_slash_vesting::OnSlash; use pallet_proxy_bonding::ReleaseType; use polimec_common::{ + assets::AcceptedFundingAsset, migration_types::{MigrationInfo, MigrationOrigin, MigrationStatus, ParticipationType}, ReleaseSchedule, }; diff --git a/pallets/funding/src/functions/misc.rs b/pallets/funding/src/functions/misc.rs index a2095f6bd..a440538fc 100644 --- a/pallets/funding/src/functions/misc.rs +++ b/pallets/funding/src/functions/misc.rs @@ -1,7 +1,7 @@ #[allow(clippy::wildcard_imports)] use super::*; use alloc::string::{String, ToString}; -use polimec_common::ProvideAssetPrice; +use polimec_common::{assets::AcceptedFundingAsset, ProvideAssetPrice}; use sp_core::{ ecdsa::{Public as EcdsaPublic, Signature as EcdsaSignature}, keccak_256, @@ -38,7 +38,7 @@ impl Pallet { pub fn calculate_plmc_bond(ticket_size: Balance, multiplier: MultiplierOf) -> Result { let plmc_usd_price = - >::get_decimals_aware_price(PLMC_FOREIGN_ID, USD_DECIMALS, PLMC_DECIMALS) + >::get_decimals_aware_price(Location::here(), USD_DECIMALS, PLMC_DECIMALS) .ok_or(Error::::PriceNotFound)?; let usd_bond = multiplier.calculate_usd_bonding_requirement::(ticket_size).ok_or(Error::::BadMath)?; plmc_usd_price @@ -53,7 +53,7 @@ impl Pallet { asset_id: AcceptedFundingAsset, ) -> Result { let asset_id = asset_id.id(); - let asset_decimals = T::FundingCurrency::decimals(asset_id); + let asset_decimals = T::FundingCurrency::decimals(asset_id.clone()); let asset_usd_price = >::get_decimals_aware_price(asset_id, USD_DECIMALS, asset_decimals) .ok_or(Error::::PriceNotFound)?; asset_usd_price @@ -517,7 +517,7 @@ impl Pallet { pub fn get_decimals_aware_funding_asset_price(funding_asset: &AcceptedFundingAsset) -> Option> { let funding_asset_id = funding_asset.id(); - let funding_asset_decimals = T::FundingCurrency::decimals(funding_asset_id); + let funding_asset_decimals = T::FundingCurrency::decimals(funding_asset_id.clone()); >::get_decimals_aware_price(funding_asset_id, USD_DECIMALS, funding_asset_decimals) } } diff --git a/pallets/funding/src/instantiator/calculations.rs b/pallets/funding/src/instantiator/calculations.rs index 5963c8f90..373d9a70f 100644 --- a/pallets/funding/src/instantiator/calculations.rs +++ b/pallets/funding/src/instantiator/calculations.rs @@ -1,8 +1,9 @@ -#[allow(clippy::wildcard_imports)] use super::*; use crate::{MultiplierOf, ParticipationMode}; use core::cmp::Ordering; use itertools::GroupBy; +#[allow(clippy::wildcard_imports)] +use polimec_common::assets::AcceptedFundingAsset; use polimec_common::{ProvideAssetPrice, USD_DECIMALS}; use sp_core::{ecdsa, hexdisplay::AsBytesRef, keccak_256, sr25519, Pair}; @@ -36,7 +37,7 @@ impl< evaluations: Vec>, ) -> Vec> { let plmc_usd_price = self.execute(|| { - >::get_decimals_aware_price(PLMC_FOREIGN_ID, USD_DECIMALS, PLMC_DECIMALS).unwrap() + >::get_decimals_aware_price(Location::here(), USD_DECIMALS, PLMC_DECIMALS).unwrap() }); let mut output = Vec::new(); @@ -412,7 +413,7 @@ impl< ) { let multiplier: MultiplierOf = ParticipationMode::OTM.multiplier().try_into().ok().unwrap(); let plmc_usd_price = self.execute(|| { - >::get_decimals_aware_price(PLMC_FOREIGN_ID, USD_DECIMALS, PLMC_DECIMALS).unwrap() + >::get_decimals_aware_price(Location::here(), USD_DECIMALS, PLMC_DECIMALS).unwrap() }); let usd_bond = multiplier.calculate_usd_bonding_requirement::(usd_ticket_size).unwrap(); let plmc_bond = plmc_usd_price.reciprocal().unwrap().saturating_mul_int(usd_bond); @@ -425,7 +426,7 @@ impl< let multiplier: MultiplierOf = multiplier.try_into().ok().unwrap(); let usd_bond = multiplier.calculate_usd_bonding_requirement::(usd_ticket_size).unwrap(); let plmc_usd_price = self.execute(|| { - >::get_decimals_aware_price(PLMC_FOREIGN_ID, USD_DECIMALS, PLMC_DECIMALS).unwrap() + >::get_decimals_aware_price(Location::here(), USD_DECIMALS, PLMC_DECIMALS).unwrap() }); let plmc_bond = plmc_usd_price.reciprocal().unwrap().saturating_mul_int(usd_bond); *balance += plmc_bond; @@ -516,7 +517,7 @@ impl< #[allow(clippy::type_complexity)] let asset_lists: GroupBy, _, fn(&UserToFundingAsset) -> AssetIdOf> = - ordered_list.into_iter().group_by(|item| item.asset_id); + ordered_list.into_iter().group_by(|item| item.asset_id.clone()); let mut output = Vec::new(); diff --git a/pallets/funding/src/instantiator/chain_interactions.rs b/pallets/funding/src/instantiator/chain_interactions.rs index 646f3b72d..1a83e3701 100644 --- a/pallets/funding/src/instantiator/chain_interactions.rs +++ b/pallets/funding/src/instantiator/chain_interactions.rs @@ -2,6 +2,7 @@ #[allow(clippy::wildcard_imports)] use super::*; +use polimec_common::assets::AcceptedFundingAsset; // general chain interactions impl< @@ -79,7 +80,7 @@ impl< self.execute(|| { let mut balances: Vec> = Vec::new(); for (account, asset_id) in list { - let asset_amount = ::FundingCurrency::balance(asset_id, &account); + let asset_amount = ::FundingCurrency::balance(asset_id.clone(), &account); balances.push(UserToFundingAsset { account, asset_amount, asset_id }); } balances.sort_by(|a, b| a.account.cmp(&b.account)); @@ -120,7 +121,8 @@ impl< } pub fn get_all_free_funding_asset_balances(&mut self, asset_id: AssetIdOf) -> Vec> { - let user_keys = self.execute(|| frame_system::Account::::iter_keys().map(|a| (a, asset_id)).collect()); + let user_keys = + self.execute(|| frame_system::Account::::iter_keys().map(|a| (a, asset_id.clone())).collect()); self.get_free_funding_asset_balances_for(user_keys) } @@ -225,9 +227,9 @@ impl< pub fn mint_funding_asset_ed_if_required(&mut self, list: Vec<(AccountIdOf, AssetIdOf)>) { for (account, asset_id) in list { - let ed = self.get_funding_asset_ed(asset_id); + let ed = self.get_funding_asset_ed(asset_id.clone()); self.execute(|| { - if ::FundingCurrency::balance(asset_id, &account) < ed { + if ::FundingCurrency::balance(asset_id.clone(), &account) < ed { ::FundingCurrency::mint_into(asset_id, &account, ed).expect("Minting should work"); } }); diff --git a/pallets/funding/src/instantiator/tests.rs b/pallets/funding/src/instantiator/tests.rs index 2a00ca4f6..d2fd1280a 100644 --- a/pallets/funding/src/instantiator/tests.rs +++ b/pallets/funding/src/instantiator/tests.rs @@ -9,7 +9,7 @@ use crate::{ }; use core::cell::RefCell; use itertools::Itertools; -use polimec_common::{ProvideAssetPrice, USD_DECIMALS, USD_UNIT}; +use polimec_common::{assets::AcceptedFundingAsset, ProvideAssetPrice, USD_DECIMALS, USD_UNIT}; use sp_arithmetic::Percent; #[test] diff --git a/pallets/funding/src/instantiator/types.rs b/pallets/funding/src/instantiator/types.rs index 167a7c0b8..befd7612f 100644 --- a/pallets/funding/src/instantiator/types.rs +++ b/pallets/funding/src/instantiator/types.rs @@ -2,6 +2,7 @@ use super::*; use crate::ParticipationMode; use frame_support::{Deserialize, Serialize}; +use polimec_common::assets::AcceptedFundingAsset; pub type RuntimeOriginOf = ::RuntimeOrigin; pub struct BoxToFunction(pub Box); @@ -252,7 +253,7 @@ impl AccountMerge for Vec> { } btree .into_iter() - .map(|((account, asset_id), asset_amount)| UserToFundingAsset::new(account, asset_amount, *asset_id)) + .map(|((account, asset_id), asset_amount)| UserToFundingAsset::new(account, asset_amount, asset_id.clone())) .collect() } @@ -277,7 +278,7 @@ impl Totals for Vec> { let mut btree = BTreeMap::new(); for UserToFundingAsset { account: _, asset_amount, asset_id } in self.iter() { btree - .entry(*asset_id) + .entry(asset_id.clone()) .and_modify(|e: &mut Balance| *e = e.saturating_add(*asset_amount)) .or_insert(*asset_amount); } @@ -291,7 +292,7 @@ impl Conversions for Vec> { fn to_account_asset_map(&self) -> Vec<(Self::AccountId, Self::AssetId)> { let mut btree = BTreeSet::new(); for UserToFundingAsset { account, asset_id, .. } in self.iter() { - btree.insert((account.clone(), *asset_id)); + btree.insert((account.clone(), asset_id.clone())); } btree.into_iter().collect_vec() } diff --git a/pallets/funding/src/lib.rs b/pallets/funding/src/lib.rs index f8610d8e2..aa0b82d64 100644 --- a/pallets/funding/src/lib.rs +++ b/pallets/funding/src/lib.rs @@ -91,7 +91,7 @@ use pallet_xcm::ensure_response; use polimec_common::{ credentials::{Cid, Did, EnsureOriginWithCredentials, InvestorType, UntrustedToken}, migration_types::{Migration, MigrationStatus}, - PLMC_DECIMALS, PLMC_FOREIGN_ID, USD_DECIMALS, + PLMC_DECIMALS, USD_DECIMALS, }; use polkadot_parachain_primitives::primitives::Id as ParaId; use sp_arithmetic::traits::{One, Saturating}; @@ -160,7 +160,7 @@ pub mod pallet { }; use frame_system::pallet_prelude::*; use on_slash_vesting::OnSlash; - use polimec_common::ProvideAssetPrice; + use polimec_common::{assets::AcceptedFundingAsset, ProvideAssetPrice}; use sp_arithmetic::Percent; use sp_runtime::{ traits::{ConstU8, Convert, ConvertBack, Get}, @@ -187,7 +187,7 @@ pub mod pallet { RuntimeHoldReason = RuntimeHoldReasonOf, BondingToken = Self::NativeCurrency, BondingTokenDecimals = ConstU8, - BondingTokenId = ConstU32, + BondingTokenId = HereLocationGetter, UsdDecimals = ConstU8, FeeToken = Self::FundingCurrency, PriceProvider = PriceProviderOf, @@ -218,7 +218,7 @@ pub mod pallet { + fungibles::InspectEnumerable< AccountIdOf, Balance = Balance, - AssetsIterator = KeyPrefixIterator>, + AssetsIterator = KeyPrefixIterator, > + fungibles::metadata::Inspect> + fungibles::metadata::Mutate> + fungibles::metadata::MetadataDeposit @@ -251,9 +251,9 @@ pub mod pallet { type FeeBrackets: Get>; /// The currency used for funding projects in bids and contributions - type FundingCurrency: fungibles::InspectEnumerable, Balance = Balance, AssetId = u32> - + fungibles::metadata::Inspect, AssetId = u32> - + fungibles::metadata::Mutate, AssetId = u32> + type FundingCurrency: fungibles::InspectEnumerable, Balance = Balance, AssetId = Location> + + fungibles::metadata::Inspect, AssetId = Location> + + fungibles::metadata::Mutate, AssetId = Location> + fungibles::Mutate, Balance = Balance>; type FundingSuccessThreshold: Get; @@ -321,7 +321,7 @@ pub mod pallet { type Price: FixedPointNumber + Parameter + Copy + MaxEncodedLen + MaybeSerializeDeserialize; /// Method to get the price of an asset like USDT or PLMC. Likely to come from an oracle - type PriceProvider: ProvideAssetPrice; + type PriceProvider: ProvideAssetPrice, Price = Self::Price>; /// The length (expressed in number of blocks) of the Remainder Round. #[pallet::constant] diff --git a/pallets/funding/src/mock.rs b/pallets/funding/src/mock.rs index c133bea69..05b9c8098 100644 --- a/pallets/funding/src/mock.rs +++ b/pallets/funding/src/mock.rs @@ -34,7 +34,7 @@ use frame_support::{ }; use frame_system as system; use frame_system::{EnsureRoot, RawOrigin as SystemRawOrigin}; -use polimec_common::{credentials::EnsureInvestor, ProvideAssetPrice, USD_UNIT}; +use polimec_common::{assets::AcceptedFundingAsset, credentials::EnsureInvestor, ProvideAssetPrice, USD_UNIT}; use polimec_common_test_utils::DummyXcmSender; use polkadot_parachain_primitives::primitives::Sibling; use sp_arithmetic::{Perbill, Percent}; @@ -210,15 +210,21 @@ impl pallet_assets::Config for TestRuntime { type WeightInfo = (); } +pub struct PalletAssetsBenchmarkHelper; +impl pallet_assets::BenchmarkHelper for PalletAssetsBenchmarkHelper { + fn create_asset_id_parameter(id: u32) -> Location { + (Parent, Parachain(id)).into() + } +} impl pallet_assets::Config for TestRuntime { type ApprovalDeposit = ApprovalDeposit; type AssetAccountDeposit = AssetAccountDeposit; type AssetDeposit = AssetDeposit; - type AssetId = AssetId; - type AssetIdParameter = parity_scale_codec::Compact; + type AssetId = Location; + type AssetIdParameter = Location; type Balance = Balance; #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); + type BenchmarkHelper = PalletAssetsBenchmarkHelper; type CallbackHandle = (); type CreateOrigin = AsEnsureOriginWithArg>; type Currency = Balances; @@ -358,20 +364,20 @@ impl ConvertBack for DummyConverter { } } thread_local! { - pub static PRICE_MAP: RefCell> = RefCell::new(BTreeMap::from_iter(vec![ + pub static PRICE_MAP: RefCell> = RefCell::new(BTreeMap::from_iter(vec![ (AcceptedFundingAsset::DOT.id(), FixedU128::from_float(69f64)), // DOT (AcceptedFundingAsset::USDC.id(), FixedU128::from_float(0.97f64)), // USDC (AcceptedFundingAsset::USDT.id(), FixedU128::from_float(1.0f64)), // USDT (AcceptedFundingAsset::WETH.id(), FixedU128::from_float(3619.451f64)), // WETH - (PLMC_FOREIGN_ID, FixedU128::from_float(8.4f64)), // PLMC + (Location::here(), FixedU128::from_float(8.4f64)), // PLMC ])); } pub struct ConstPriceProvider; impl ProvideAssetPrice for ConstPriceProvider { - type AssetId = AssetId; + type AssetId = Location; type Price = Price; - fn get_price(asset_id: AssetId) -> Option { + fn get_price(asset_id: Location) -> Option { PRICE_MAP.with(|price_map| price_map.borrow().get(&asset_id).cloned()) } } @@ -386,7 +392,7 @@ impl Convert for SS58Converter { } impl ConstPriceProvider { - pub fn set_price(asset_id: AssetId, price: Price) { + pub fn set_price(asset_id: Location, price: Price) { PRICE_MAP.with(|price_map| { price_map.borrow_mut().insert(asset_id, price); }); @@ -447,7 +453,7 @@ parameter_types! { impl pallet_proxy_bonding::Config for TestRuntime { type BondingToken = Balances; type BondingTokenDecimals = ConstU8; - type BondingTokenId = ConstU32; + type BondingTokenId = HereLocationGetter; type FeePercentage = FeePercentage; type FeeRecipient = FeeRecipient; type FeeToken = ForeignAssets; diff --git a/pallets/funding/src/runtime_api.rs b/pallets/funding/src/runtime_api.rs index e99789261..9bb64157f 100644 --- a/pallets/funding/src/runtime_api.rs +++ b/pallets/funding/src/runtime_api.rs @@ -1,10 +1,12 @@ use crate::traits::BondingRequirementCalculation; #[allow(clippy::wildcard_imports)] -use crate::*; + +use crate::{traits::BondingRequirementCalculation, *}; use alloc::{collections::BTreeMap, string::String}; use frame_support::traits::fungibles::{Inspect, InspectEnumerable}; use itertools::Itertools; use parity_scale_codec::{Decode, Encode}; +use polimec_common::assets::AcceptedFundingAsset; use polimec_common::{credentials::InvestorType, ProvideAssetPrice, USD_DECIMALS}; use scale_info::TypeInfo; use sp_core::Get; @@ -269,7 +271,7 @@ impl Pallet { } pub fn calculate_otm_fee(funding_asset: AcceptedFundingAsset, funding_asset_amount: Balance) -> Option { - let plmc_price = >::get_decimals_aware_price(PLMC_FOREIGN_ID, USD_DECIMALS, PLMC_DECIMALS) + let plmc_price = >::get_decimals_aware_price(Location::here(), USD_DECIMALS, PLMC_DECIMALS) .expect("Price not found"); let funding_asset_usd_price = Pallet::::get_decimals_aware_funding_asset_price(&funding_asset).unwrap(); let usd_amount = funding_asset_usd_price.saturating_mul_int(funding_asset_amount); diff --git a/pallets/funding/src/tests/1_application.rs b/pallets/funding/src/tests/1_application.rs index ffdc19d7e..04911a365 100644 --- a/pallets/funding/src/tests/1_application.rs +++ b/pallets/funding/src/tests/1_application.rs @@ -1,5 +1,5 @@ use super::*; -use polimec_common::credentials::InvestorType; +use polimec_common::{assets::AcceptedFundingAsset, credentials::InvestorType}; use polimec_common_test_utils::{generate_did_from_account, get_mock_jwt_with_cid}; #[cfg(test)] diff --git a/pallets/funding/src/tests/2_evaluation.rs b/pallets/funding/src/tests/2_evaluation.rs index d83f34fcc..88b0c4137 100644 --- a/pallets/funding/src/tests/2_evaluation.rs +++ b/pallets/funding/src/tests/2_evaluation.rs @@ -53,8 +53,8 @@ mod round_flow { let project_id = inst.create_evaluating_project(project_metadata.clone(), ISSUER_1, None); inst.evaluate_for_users(project_id, evaluations.clone()).unwrap(); - let old_price = ::PriceProvider::get_price(PLMC_FOREIGN_ID).unwrap(); - PRICE_MAP.with_borrow_mut(|map| map.insert(PLMC_FOREIGN_ID, old_price / 2.into())); + let old_price = ::PriceProvider::get_price(Location::here()).unwrap(); + PRICE_MAP.with_borrow_mut(|map| map.insert(Location::here(), old_price / 2.into())); assert_eq!(inst.go_to_next_state(project_id), ProjectStatus::AuctionRound); @@ -66,8 +66,8 @@ mod round_flow { let project_id = inst.create_evaluating_project(project_metadata.clone(), ISSUER_2, None); inst.evaluate_for_users(project_id, evaluations.clone()).unwrap(); - let old_price = ::PriceProvider::get_price(PLMC_FOREIGN_ID).unwrap(); - PRICE_MAP.with_borrow_mut(|map| map.insert(PLMC_FOREIGN_ID, old_price * 2.into())); + let old_price = ::PriceProvider::get_price(Location::here()).unwrap(); + PRICE_MAP.with_borrow_mut(|map| map.insert(Location::here(), old_price * 2.into())); assert_eq!(inst.go_to_next_state(project_id), ProjectStatus::FundingFailed); assert_eq!(inst.go_to_next_state(project_id), ProjectStatus::SettlementStarted(FundingOutcome::Failure)); @@ -88,10 +88,10 @@ mod round_flow { .unwrap(); let min_evaluation_amount_usd = ::MinUsdPerEvaluation::get(); let stored_plmc_price = - inst.execute(|| ::PriceProvider::get_price(PLMC_FOREIGN_ID).unwrap()); + inst.execute(|| ::PriceProvider::get_price(Location::here()).unwrap()); let usable_plmc_price = inst.execute(|| { ::PriceProvider::get_decimals_aware_price( - PLMC_FOREIGN_ID, + Location::here(), USD_DECIMALS, PLMC_DECIMALS, ) diff --git a/pallets/funding/src/tests/3_auction.rs b/pallets/funding/src/tests/3_auction.rs index 9e2aa7965..84c2140bc 100644 --- a/pallets/funding/src/tests/3_auction.rs +++ b/pallets/funding/src/tests/3_auction.rs @@ -1,5 +1,6 @@ use super::*; use frame_support::traits::{fungible::InspectFreeze, fungibles::metadata::Inspect}; +use polimec_common::assets::{AcceptedFundingAsset, AcceptedFundingAsset::USDT}; use sp_core::bounded_vec; use sp_runtime::traits::Convert; use std::collections::HashSet; @@ -115,7 +116,7 @@ mod round_flow { .unwrap(); let usable_plmc_price = inst.execute(|| { ::PriceProvider::get_decimals_aware_price( - PLMC_FOREIGN_ID, + Location::here(), USD_DECIMALS, PLMC_DECIMALS, ) @@ -342,7 +343,6 @@ mod bid_extrinsic { #[cfg(test)] mod success { use super::*; - use crate::AcceptedFundingAsset::USDT; use frame_support::pallet_prelude::DispatchResultWithPostInfo; #[test] @@ -908,13 +908,14 @@ mod bid_extrinsic { ParticipationMode::OTM.multiplier().try_into().ok().unwrap(); let otm_duration = otm_multiplier.calculate_vesting_duration::(); - const USDT_ID: u32 = AcceptedFundingAsset::USDT.id(); + let usdt_id = AcceptedFundingAsset::USDT.id(); const USDT_PARTICIPATION: u128 = 5000 * USDT_UNIT; let otm_usdt_fee: u128 = (FeePercentage::get() / ParticipationMode::OTM.multiplier()) * USDT_PARTICIPATION; let usdt_ed = inst.get_funding_asset_ed(AcceptedFundingAsset::USDT.id()); - let required_usdt = UserToFundingAsset::new(BIDDER_1, USDT_PARTICIPATION + otm_usdt_fee + usdt_ed, USDT_ID); + let required_usdt = + UserToFundingAsset::new(BIDDER_1, USDT_PARTICIPATION + otm_usdt_fee + usdt_ed, usdt_id.clone()); inst.mint_funding_asset_to(vec![required_usdt.clone()]); let ct_participation = inst.execute(|| { @@ -940,10 +941,10 @@ mod bid_extrinsic { let pre_participation_otm_escrow_held_plmc = inst.get_reserved_plmc_balance_for(otm_escrow_account, HoldReason::Participation.into()); let pre_participation_otm_escrow_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_escrow_account); let pre_participation_otm_fee_recipient_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); - let pre_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BIDDER_1); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_fee_recipient_account); + let pre_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(usdt_id.clone(), BIDDER_1); inst.execute(|| { assert_ok!(PolimecFunding::bid( @@ -965,10 +966,10 @@ mod bid_extrinsic { let post_participation_otm_escrow_held_plmc = inst.get_reserved_plmc_balance_for(otm_escrow_account, HoldReason::Participation.into()); let post_participation_otm_escrow_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_escrow_account); let post_participation_otm_fee_recipient_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); - let post_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BIDDER_1); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_fee_recipient_account); + let post_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(usdt_id.clone(), BIDDER_1); assert_eq!( post_participation_treasury_free_plmc, @@ -1004,7 +1005,7 @@ mod bid_extrinsic { RuntimeOrigin::signed(BIDDER_1), project_id, HoldReason::Participation.into(), - USDT_ID + usdt_id.clone() )); assert_noop!( >::transfer_bonds_back_to_treasury( @@ -1027,11 +1028,12 @@ mod bid_extrinsic { let post_settlement_treasury_free_plmc = inst.get_free_plmc_balance_for(otm_treasury_account); let post_settlement_otm_escrow_held_plmc = inst.get_free_plmc_balance_for(otm_escrow_account); - let post_settlement_otm_escrow_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + let post_settlement_otm_escrow_usdt = + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_escrow_account); let post_settlement_otm_fee_recipient_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); - let post_settlement_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BIDDER_1); - let issuer_funding_account = inst.get_free_funding_asset_balance_for(USDT_ID, issuer); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_fee_recipient_account); + let post_settlement_buyer_usdt = inst.get_free_funding_asset_balance_for(usdt_id.clone(), BIDDER_1); + let issuer_funding_account = inst.get_free_funding_asset_balance_for(usdt_id, issuer); assert_eq!(post_settlement_treasury_free_plmc, post_participation_treasury_free_plmc + expected_plmc_bond); assert_eq!(post_settlement_otm_escrow_held_plmc, inst.get_ed()); @@ -1063,12 +1065,13 @@ mod bid_extrinsic { let otm_multiplier: MultiplierOf = ParticipationMode::OTM.multiplier().try_into().ok().unwrap(); - const USDT_ID: u32 = AcceptedFundingAsset::USDT.id(); + let usdt_id = AcceptedFundingAsset::USDT.id(); const USDT_PARTICIPATION: u128 = 5000 * USDT_UNIT; let otm_usdt_fee: u128 = (FeePercentage::get() / ParticipationMode::OTM.multiplier()) * USDT_PARTICIPATION; let usdt_ed = inst.get_funding_asset_ed(AcceptedFundingAsset::USDT.id()); - let required_usdt = UserToFundingAsset::new(BIDDER_1, USDT_PARTICIPATION + otm_usdt_fee + usdt_ed, USDT_ID); + let required_usdt = + UserToFundingAsset::new(BIDDER_1, USDT_PARTICIPATION + otm_usdt_fee + usdt_ed, usdt_id.clone()); inst.mint_funding_asset_to(vec![required_usdt.clone()]); let ct_participation = inst.execute(|| { @@ -1094,10 +1097,10 @@ mod bid_extrinsic { let pre_participation_otm_escrow_held_plmc = inst.get_reserved_plmc_balance_for(otm_escrow_account, HoldReason::Participation.into()); let pre_participation_otm_escrow_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_escrow_account); let pre_participation_otm_fee_recipient_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); - let pre_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BIDDER_1); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_fee_recipient_account); + let pre_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(usdt_id.clone(), BIDDER_1); inst.execute(|| { assert_ok!(PolimecFunding::bid( @@ -1119,10 +1122,10 @@ mod bid_extrinsic { let post_participation_otm_escrow_held_plmc = inst.get_reserved_plmc_balance_for(otm_escrow_account, HoldReason::Participation.into()); let post_participation_otm_escrow_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_escrow_account); let post_participation_otm_fee_recipient_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); - let post_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BIDDER_1); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_fee_recipient_account); + let post_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(usdt_id.clone(), BIDDER_1); assert_eq!( post_participation_treasury_free_plmc, @@ -1159,7 +1162,7 @@ mod bid_extrinsic { RuntimeOrigin::signed(BIDDER_1), project_id, HoldReason::Participation.into(), - USDT_ID + usdt_id.clone() ), pallet_proxy_bonding::Error::::FeeToRecipientDisallowed ); @@ -1173,11 +1176,12 @@ mod bid_extrinsic { let post_settlement_treasury_free_plmc = inst.get_free_plmc_balance_for(otm_treasury_account); let post_settlement_otm_escrow_held_plmc = inst.get_free_plmc_balance_for(otm_escrow_account); - let post_settlement_otm_escrow_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + let post_settlement_otm_escrow_usdt = + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_escrow_account); let post_settlement_otm_fee_recipient_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); - let post_settlement_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BIDDER_1); - let issuer_funding_account = inst.get_free_funding_asset_balance_for(USDT_ID, issuer); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_fee_recipient_account); + let post_settlement_buyer_usdt = inst.get_free_funding_asset_balance_for(usdt_id.clone(), BIDDER_1); + let issuer_funding_account = inst.get_free_funding_asset_balance_for(usdt_id, issuer); assert_eq!(post_settlement_treasury_free_plmc, post_participation_treasury_free_plmc + expected_plmc_bond); assert_eq!(post_settlement_otm_escrow_held_plmc, inst.get_ed()); @@ -2297,7 +2301,8 @@ mod end_auction_extrinsic { .map(|acc| { let accepted_asset = fundings.next().unwrap(); let asset_id = accepted_asset.id(); - let asset_decimals = inst.execute(|| ::FundingCurrency::decimals(asset_id)); + let asset_decimals = + inst.execute(|| ::FundingCurrency::decimals(asset_id.clone())); let asset_unit = 10u128.checked_pow(asset_decimals.into()).unwrap(); UserToFundingAsset { account: *acc, asset_amount: asset_unit * 1_000_000, asset_id } }) diff --git a/pallets/funding/src/tests/4_contribution.rs b/pallets/funding/src/tests/4_contribution.rs index f76b698f3..4aa980bde 100644 --- a/pallets/funding/src/tests/4_contribution.rs +++ b/pallets/funding/src/tests/4_contribution.rs @@ -1,4 +1,5 @@ use super::*; +use polimec_common::assets::AcceptedFundingAsset::{self, DOT, USDC, USDT}; #[cfg(test)] mod round_flow { @@ -179,7 +180,7 @@ mod round_flow { .unwrap(); let usable_plmc_price = inst.execute(|| { ::PriceProvider::get_decimals_aware_price( - PLMC_FOREIGN_ID, + Location::here(), USD_DECIMALS, PLMC_DECIMALS, ) @@ -317,7 +318,6 @@ mod contribute_extrinsic { #[cfg(test)] mod success { use super::*; - use crate::AcceptedFundingAsset::{DOT, USDC, USDT}; use frame_support::{dispatch::DispatchResultWithPostInfo, traits::fungible::InspectFreeze}; #[test] @@ -342,7 +342,7 @@ mod contribute_extrinsic { ); let ct_price = inst.get_project_details(project_id).weighted_average_price.unwrap(); let plmc_price = ::PriceProvider::get_decimals_aware_price( - PLMC_FOREIGN_ID, + Location::here(), USD_DECIMALS, PLMC_DECIMALS, ) @@ -433,7 +433,7 @@ mod contribute_extrinsic { evaluations.push(bob_evaluation); let plmc_price = ::PriceProvider::get_decimals_aware_price( - PLMC_FOREIGN_ID, + Location::here(), USD_DECIMALS, PLMC_DECIMALS, ) @@ -1057,12 +1057,13 @@ mod contribute_extrinsic { ParticipationMode::OTM.multiplier().try_into().ok().unwrap(); let otm_duration = otm_multiplier.calculate_vesting_duration::(); - const USDT_ID: u32 = AcceptedFundingAsset::USDT.id(); + let usdt_id = AcceptedFundingAsset::USDT.id(); const USDT_PARTICIPATION: u128 = 3000 * USDT_UNIT; let otm_usdt_fee: u128 = (FeePercentage::get() / ParticipationMode::OTM.multiplier()) * USDT_PARTICIPATION; let usdt_ed = inst.get_funding_asset_ed(AcceptedFundingAsset::USDT.id()); - let required_usdt = UserToFundingAsset::new(BUYER_1, USDT_PARTICIPATION + otm_usdt_fee + usdt_ed, USDT_ID); + let required_usdt = + UserToFundingAsset::new(BUYER_1, USDT_PARTICIPATION + otm_usdt_fee + usdt_ed, usdt_id.clone()); inst.mint_funding_asset_to(vec![required_usdt.clone()]); let ct_participation = inst.execute(|| { @@ -1088,10 +1089,10 @@ mod contribute_extrinsic { let pre_participation_otm_escrow_held_plmc = inst.get_reserved_plmc_balance_for(otm_escrow_account, HoldReason::Participation.into()); let pre_participation_otm_escrow_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_escrow_account); let pre_participation_otm_fee_recipient_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); - let pre_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BUYER_1); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_fee_recipient_account); + let pre_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(usdt_id.clone(), BUYER_1); inst.execute(|| { assert_ok!(PolimecFunding::contribute( @@ -1113,10 +1114,10 @@ mod contribute_extrinsic { let post_participation_otm_escrow_held_plmc = inst.get_reserved_plmc_balance_for(otm_escrow_account, HoldReason::Participation.into()); let post_participation_otm_escrow_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_escrow_account); let post_participation_otm_fee_recipient_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); - let post_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BUYER_1); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_fee_recipient_account); + let post_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(usdt_id.clone(), BUYER_1); assert_eq!( post_participation_treasury_free_plmc, @@ -1151,7 +1152,7 @@ mod contribute_extrinsic { RuntimeOrigin::signed(BUYER_1), project_id, HoldReason::Participation.into(), - USDT_ID + usdt_id.clone() )); assert_noop!( >::transfer_bonds_back_to_treasury( @@ -1174,11 +1175,12 @@ mod contribute_extrinsic { let post_settlement_treasury_free_plmc = inst.get_free_plmc_balance_for(otm_treasury_account); let post_settlement_otm_escrow_held_plmc = inst.get_free_plmc_balance_for(otm_escrow_account); - let post_settlement_otm_escrow_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + let post_settlement_otm_escrow_usdt = + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_escrow_account); let post_settlement_otm_fee_recipient_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); - let post_settlement_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BUYER_1); - let issuer_funding_account = inst.get_free_funding_asset_balance_for(USDT_ID, issuer); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_fee_recipient_account); + let post_settlement_buyer_usdt = inst.get_free_funding_asset_balance_for(usdt_id.clone(), BUYER_1); + let issuer_funding_account = inst.get_free_funding_asset_balance_for(usdt_id, issuer); assert_eq!(post_settlement_treasury_free_plmc, post_participation_treasury_free_plmc + expected_plmc_bond); assert_eq!(post_settlement_otm_escrow_held_plmc, inst.get_ed()); @@ -1211,12 +1213,13 @@ mod contribute_extrinsic { let otm_multiplier: MultiplierOf = ParticipationMode::OTM.multiplier().try_into().ok().unwrap(); - const USDT_ID: u32 = AcceptedFundingAsset::USDT.id(); + let usdt_id = AcceptedFundingAsset::USDT.id(); const USDT_PARTICIPATION: u128 = 3000 * USDT_UNIT; let otm_usdt_fee: u128 = (FeePercentage::get() / ParticipationMode::OTM.multiplier()) * USDT_PARTICIPATION; let usdt_ed = inst.get_funding_asset_ed(AcceptedFundingAsset::USDT.id()); - let required_usdt = UserToFundingAsset::new(BUYER_1, USDT_PARTICIPATION + otm_usdt_fee + usdt_ed, USDT_ID); + let required_usdt = + UserToFundingAsset::new(BUYER_1, USDT_PARTICIPATION + otm_usdt_fee + usdt_ed, usdt_id.clone()); inst.mint_funding_asset_to(vec![required_usdt.clone()]); let ct_participation = inst.execute(|| { @@ -1242,10 +1245,10 @@ mod contribute_extrinsic { let pre_participation_otm_escrow_held_plmc = inst.get_reserved_plmc_balance_for(otm_escrow_account, HoldReason::Participation.into()); let pre_participation_otm_escrow_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_escrow_account); let pre_participation_otm_fee_recipient_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); - let pre_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BUYER_1); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_fee_recipient_account); + let pre_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(usdt_id.clone(), BUYER_1); inst.execute(|| { assert_ok!(PolimecFunding::contribute( @@ -1267,10 +1270,10 @@ mod contribute_extrinsic { let post_participation_otm_escrow_held_plmc = inst.get_reserved_plmc_balance_for(otm_escrow_account, HoldReason::Participation.into()); let post_participation_otm_escrow_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_escrow_account); let post_participation_otm_fee_recipient_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); - let post_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BUYER_1); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_fee_recipient_account); + let post_participation_buyer_usdt = inst.get_free_funding_asset_balance_for(usdt_id.clone(), BUYER_1); assert_eq!( post_participation_treasury_free_plmc, @@ -1306,7 +1309,7 @@ mod contribute_extrinsic { RuntimeOrigin::signed(BUYER_1), project_id, HoldReason::Participation.into(), - USDT_ID + usdt_id.clone() ), pallet_proxy_bonding::Error::::FeeToRecipientDisallowed ); @@ -1320,11 +1323,12 @@ mod contribute_extrinsic { let post_settlement_treasury_free_plmc = inst.get_free_plmc_balance_for(otm_treasury_account); let post_settlement_otm_escrow_held_plmc = inst.get_free_plmc_balance_for(otm_escrow_account); - let post_settlement_otm_escrow_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, otm_escrow_account); + let post_settlement_otm_escrow_usdt = + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_escrow_account); let post_settlement_otm_fee_recipient_usdt = - inst.get_free_funding_asset_balance_for(USDT_ID, otm_fee_recipient_account); - let post_settlement_buyer_usdt = inst.get_free_funding_asset_balance_for(USDT_ID, BUYER_1); - let issuer_funding_account = inst.get_free_funding_asset_balance_for(USDT_ID, issuer); + inst.get_free_funding_asset_balance_for(usdt_id.clone(), otm_fee_recipient_account); + let post_settlement_buyer_usdt = inst.get_free_funding_asset_balance_for(usdt_id.clone(), BUYER_1); + let issuer_funding_account = inst.get_free_funding_asset_balance_for(usdt_id, issuer); assert_eq!(post_settlement_treasury_free_plmc, post_participation_treasury_free_plmc + expected_plmc_bond); assert_eq!(post_settlement_otm_escrow_held_plmc, inst.get_ed()); diff --git a/pallets/funding/src/tests/6_settlement.rs b/pallets/funding/src/tests/6_settlement.rs index 6155a3614..b97068cac 100644 --- a/pallets/funding/src/tests/6_settlement.rs +++ b/pallets/funding/src/tests/6_settlement.rs @@ -1,5 +1,6 @@ use super::*; use frame_support::traits::fungibles::Inspect; +use polimec_common::assets::AcceptedFundingAsset; use sp_runtime::bounded_vec; #[cfg(test)] diff --git a/pallets/funding/src/tests/misc.rs b/pallets/funding/src/tests/misc.rs index 8c32056e0..016da01b3 100644 --- a/pallets/funding/src/tests/misc.rs +++ b/pallets/funding/src/tests/misc.rs @@ -1,4 +1,5 @@ use super::*; +use polimec_common::assets::AcceptedFundingAsset; // check that functions created to facilitate testing return the expected results mod helper_functions { @@ -91,7 +92,7 @@ mod helper_functions { const PLMC_PRICE: f64 = 8.4f64; assert_eq!( - ::PriceProvider::get_price(PLMC_FOREIGN_ID).unwrap(), + ::PriceProvider::get_price(Location::here()).unwrap(), PriceOf::::from_float(PLMC_PRICE) ); @@ -284,7 +285,7 @@ mod helper_functions { const EXPECTED_PLMC_AMOUNT_5: f64 = 0.0_239_554_285f64; assert_eq!( - ::PriceProvider::get_price(PLMC_FOREIGN_ID).unwrap(), + ::PriceProvider::get_price(Location::here()).unwrap(), PriceOf::::from_float(PLMC_PRICE) ); diff --git a/pallets/funding/src/tests/mod.rs b/pallets/funding/src/tests/mod.rs index e34bd83a9..5f25156c4 100644 --- a/pallets/funding/src/tests/mod.rs +++ b/pallets/funding/src/tests/mod.rs @@ -72,6 +72,7 @@ const BUYER_7: AccountId = 47; pub mod defaults { use super::*; + use polimec_common::assets::AcceptedFundingAsset; pub fn default_token_information() -> CurrencyMetadata>> { CurrencyMetadata { name: bounded_name(), symbol: bounded_symbol(), decimals: CT_DECIMALS } diff --git a/pallets/funding/src/tests/runtime_api.rs b/pallets/funding/src/tests/runtime_api.rs index c1efc993b..9c625776e 100644 --- a/pallets/funding/src/tests/runtime_api.rs +++ b/pallets/funding/src/tests/runtime_api.rs @@ -1,7 +1,9 @@ use super::*; use crate::runtime_api::{ExtrinsicHelpers, Leaderboards, ProjectInformation, UserInformation}; use frame_support::traits::fungibles::{metadata::Inspect, Mutate}; +use polimec_common::assets::AcceptedFundingAsset; use sp_runtime::bounded_vec; + #[test] fn top_evaluations() { let mut inst = MockInstantiator::new(Some(RefCell::new(new_test_ext()))); @@ -739,10 +741,10 @@ fn calculate_otm_fee() { project_metadata.participation_currencies = bounded_vec![AcceptedFundingAsset::DOT]; let dot_id = AcceptedFundingAsset::DOT.id(); - let dot_decimals = inst.execute(|| ForeignAssets::decimals(dot_id)); + let dot_decimals = inst.execute(|| ForeignAssets::decimals(dot_id.clone())); let dot_unit = 10u128.pow(dot_decimals as u32); let dot_ticket = 10_000 * dot_unit; - let dot_ed = inst.get_funding_asset_ed(dot_id); + let dot_ed = inst.get_funding_asset_ed(dot_id.clone()); let block_hash = inst.execute(|| System::block_hash(System::block_number())); let calculated_fee = inst.execute(|| { @@ -765,7 +767,7 @@ fn calculate_otm_fee() { }) .unwrap(); - inst.execute(|| ForeignAssets::set_balance(dot_id, &BIDDER_1, dot_ticket + calculated_fee + dot_ed)); + inst.execute(|| ForeignAssets::set_balance(dot_id.clone(), &BIDDER_1, dot_ticket + calculated_fee + dot_ed)); let jwt = get_mock_jwt_with_cid( BIDDER_1, @@ -797,7 +799,7 @@ fn get_funding_asset_min_max_amounts() { ConstPriceProvider::set_price(AcceptedFundingAsset::USDT.id(), PriceOf::::from_float(1.0f64)); ConstPriceProvider::set_price(AcceptedFundingAsset::USDC.id(), PriceOf::::from_float(1.0f64)); ConstPriceProvider::set_price(AcceptedFundingAsset::DOT.id(), PriceOf::::from_float(10.0f64)); - ConstPriceProvider::set_price(PLMC_FOREIGN_ID, PriceOf::::from_float(0.5f64)); + ConstPriceProvider::set_price(Location::here(), PriceOf::::from_float(0.5f64)); const DOT_UNIT: u128 = 10u128.pow(10u32); // We test the following cases: diff --git a/pallets/funding/src/types.rs b/pallets/funding/src/types.rs index 2091ce136..ffa0b1e3f 100644 --- a/pallets/funding/src/types.rs +++ b/pallets/funding/src/types.rs @@ -35,12 +35,15 @@ pub use storage::*; use crate::{traits::VestingDurationCalculation, Config}; +use polimec_common::assets::AcceptedFundingAsset; use sp_runtime::traits::Zero; pub mod config { #[allow(clippy::wildcard_imports)] use super::*; use crate::Balance; + use sp_core::parameter_types; + use xcm::v4::Location; #[derive( Clone, @@ -149,6 +152,10 @@ pub mod config { pub const RETAIL_MAX_MULTIPLIER: u8 = 5u8; pub const PROFESSIONAL_MAX_MULTIPLIER: u8 = 10u8; pub const INSTITUTIONAL_MAX_MULTIPLIER: u8 = 25u8; + + parameter_types! { + pub HereLocationGetter: Location = Location::here(); + } } pub mod storage { @@ -488,7 +495,6 @@ pub mod inner { #[allow(clippy::wildcard_imports)] use super::*; use crate::Balance; - use variant_count::VariantCount; use xcm::v4::{Junction, QueryId}; pub enum MetadataError { @@ -629,43 +635,6 @@ pub mod inner { } } - #[derive( - VariantCount, - Clone, - Copy, - Encode, - Decode, - Eq, - PartialEq, - PartialOrd, - Ord, - RuntimeDebug, - TypeInfo, - MaxEncodedLen, - Serialize, - Deserialize, - )] - pub enum AcceptedFundingAsset { - #[codec(index = 0)] - USDT, - #[codec(index = 1)] - USDC, - #[codec(index = 2)] - DOT, - #[codec(index = 3)] - WETH, - } - impl AcceptedFundingAsset { - pub const fn id(&self) -> u32 { - match self { - AcceptedFundingAsset::USDT => 1984, - AcceptedFundingAsset::DOT => 10, - AcceptedFundingAsset::USDC => 1337, - AcceptedFundingAsset::WETH => 10_000, - } - } - } - #[derive( Default, Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen, Serialize, Deserialize, )] @@ -848,10 +817,8 @@ pub mod inner { } pub mod extrinsic { - use crate::{ - AcceptedFundingAsset, AccountIdOf, Balance, Config, ParticipationMode, PriceOf, ProjectDetailsOf, ProjectId, - TicketSize, - }; + use super::*; + use crate::{AccountIdOf, Balance, Config, ParticipationMode, PriceOf, ProjectDetailsOf, ProjectId, TicketSize}; use frame_system::pallet_prelude::BlockNumberFor; use polimec_common::credentials::{Cid, Did, InvestorType}; use xcm::v4::Junction; diff --git a/pallets/oracle-ocw/src/mock.rs b/pallets/oracle-ocw/src/mock.rs index 4a5211b51..bc8e41cfd 100644 --- a/pallets/oracle-ocw/src/mock.rs +++ b/pallets/oracle-ocw/src/mock.rs @@ -266,20 +266,28 @@ pub fn assert_close_enough(a: FixedU128, b: FixedU128) { } pub(crate) const KRAKEN_RESPONSES: &[(&str, &[u8])] = - &[("USDTZUSD", KRAKEN_USDT_CORRECT), ("USDCUSD", KRAKEN_USDC_CORRECT), ("DOTUSD", KRAKEN_DOT_CORRECT), ("XETHZUSD", KRAKEN_WETH_CORRECT)]; + &[("USDTZUSD", KRAKEN_USDT_CORRECT), ("USDCUSD", KRAKEN_USDC_CORRECT), ("DOTUSD", KRAKEN_DOT_CORRECT)]; const KRAKEN_USDT_CORRECT: &[u8] = br#"{"error":[],"result":{"USDTZUSD":[[1701877920,"1.00009","1.00011","1.00008","1.00009","1.00010","58759.32214931",36],[1701877980,"1.00009","1.00011","1.00009","1.00010","1.00010","17156.51835679",18],[1701878040,"1.00011","1.00011","1.00010","1.00010","1.00010","231514.66903930",13],[1701878100,"1.00010","1.00015","1.00010","1.00014","1.00012","10577.17236868",27],[1701878160,"1.00015","1.00020","1.00015","1.00019","1.00017","1026827.06857105",67],[1701878220,"1.00019","1.00019","1.00018","1.00019","1.00018","44228.73461655",28],[1701878280,"1.00018","1.00018","1.00015","1.00015","1.00016","41144.63245059",23],[1701878340,"1.00014","1.00015","1.00013","1.00013","1.00013","252283.11050904",67],[1701878400,"1.00014","1.00014","1.00012","1.00014","1.00012","34519.85524461",23],[1701878460,"1.00013","1.00013","1.00008","1.00009","1.00010","49702.48469208",40],[1701878520,"1.00009","1.00016","1.00009","1.00016","1.00012","83532.48937609",43],[1701878580,"1.00016","1.00018","1.00015","1.00018","1.00017","340329.29664927",27],[1701878640,"1.00018","1.00018","1.00015","1.00015","1.00016","125875.61559451",33],[1701878700,"1.00015","1.00015","1.00010","1.00011","1.00012","63925.70403795",32],[1701878760,"1.00010","1.00010","1.00008","1.00008","1.00009","53316.20999461",26]],"last":1699977300}}"#; const KRAKEN_USDC_CORRECT: &[u8] = br#"{"error":[],"result":{"USDCUSD":[[1701878040,"1.0001","1.0001","1.0000","1.0000","1.0000","2210.00000000",2],[1701878100,"1.0002","1.0002","1.0002","1.0002","1.0002","999.00000000",1],[1701878160,"1.0001","1.0002","1.0001","1.0002","1.0001","7201.85053234",9],[1701878220,"1.0001","1.0001","1.0001","1.0001","1.0001","15.71930681",1],[1701878280,"1.0000","1.0001","1.0000","1.0001","1.0000","102108.24129487",5],[1701878340,"1.0001","1.0001","1.0001","1.0001","0.0000","0.00000000",0],[1701878400,"1.0001","1.0001","1.0001","1.0001","1.0001","1451.37880000",1],[1701878460,"1.0001","1.0001","1.0000","1.0000","1.0000","11005.00000000",2],[1701878520,"1.0001","1.0001","1.0000","1.0000","1.0000","6760.93865300",3],[1701878580,"1.0000","1.0000","1.0000","1.0000","0.0000","0.00000000",0],[1701878640,"1.0000","1.0001","1.0000","1.0001","1.0000","1290.84392400",4],[1701878700,"1.0000","1.0001","1.0000","1.0001","1.0000","53.03306930",2],[1701878760,"1.0000","1.0000","1.0000","1.0000","1.0000","16711.33870874",7],[1701878820,"1.0000","1.0000","1.0000","1.0000","1.0000","10007.53328427",2],[1701878880,"0.9999","0.9999","0.9999","0.9999","0.9999","1000.00000000",1]],"last":1699977300}}"#; const KRAKEN_DOT_CORRECT: &[u8] = br#"{"error":[],"result":{"DOTUSD":[[1701878100,"6.1473","6.1474","6.1473","6.1474","6.1473","102.00000000",2],[1701878160,"6.1446","6.1446","6.1378","6.1409","6.1399","56.11963595",4],[1701878220,"6.1251","6.1473","6.1233","6.1473","6.1268","992.18112927",12],[1701878280,"6.1468","6.1500","6.1383","6.1383","6.1463","365.21179340",29],[1701878340,"6.1401","6.1401","6.1378","6.1378","6.1393","57.06050109",5],[1701878400,"6.1298","6.1380","6.1279","6.1380","6.1361","968.44275786",8],[1701878460,"6.1403","6.1407","6.1390","6.1390","6.1400","507.81565634",8],[1701878520,"6.1391","6.1500","6.1385","6.1500","6.1422","344.07407967",5],[1701878580,"6.1499","6.1573","6.1473","6.1573","6.1491","3563.21894841",32],[1701878640,"6.1594","6.1602","6.1552","6.1552","6.1591","1461.51440086",22],[1701878700,"6.1612","6.1622","6.1544","6.1544","6.1598","447.90016651",9],[1701878760,"6.1452","6.1452","6.1407","6.1407","6.1421","225.30037904",6],[1701878820,"6.1192","6.1192","6.1044","6.1044","6.1145","154.45052403",8],[1701878880,"6.1111","6.1126","6.1082","6.1124","6.1116","186.62943447",4],[1701878940,"6.1126","6.1199","6.1124","6.1197","6.1160","145.34596966",7]],"last":1699977300}}"#; const KRAKEN_WETH_CORRECT: &[u8] = br#"{"error":[],"result":{"XETHZUSD":[[1733097540,"3711.50","3712.78","3711.50","3712.60","3712.53","1.77755193",9],[1733097600,"3712.61","3714.28","3710.66","3714.28","3712.59","0.90987356",12],[1733097660,"3712.79","3712.79","3710.66","3710.66","3712.57","1.28841862",8],[1733097720,"3711.65","3711.65","3711.05","3711.05","3711.16","0.01669697",2],[1733097780,"3711.05","3714.28","3708.96","3714.28","3709.46","31.19426417",13],[1733097840,"3713.85","3713.85","3713.85","3713.85","3713.85","0.01965026",1],[1733097900,"3712.86","3712.86","3706.58","3707.40","3707.00","3.05832962",8],[1733097960,"3709.40","3710.37","3707.66","3707.66","3708.71","4.71410736",16],[1733098020,"3708.42","3709.36","3707.40","3707.41","3707.77","6.91011633",14],[1733098080,"3707.41","3707.41","3707.40","3707.40","3707.40","3.38888907",9],[1733098140,"3709.36","3711.83","3709.36","3710.48","3710.99","1.71648433",13],[1733098200,"3710.48","3712.97","3710.48","3711.00","3712.27","0.65391452",7],[1733098260,"3711.02","3711.60","3711.01","3711.01","3711.39","2.19165665",11],[1733098320,"3712.03","3714.91","3712.03","3714.91","3712.60","0.62750623",7],[1733098380,"3715.61","3715.61","3713.47","3713.70","3714.89","4.60012455",15],[1733098440,"3713.70","3713.70","3710.16","3712.46","3712.22","1.41298079",11],[1733098500,"3710.89","3710.89","3709.44","3709.77","3710.11","1.50535337",5],[1733098560,"3709.63","3710.29","3709.43","3709.43","3710.03","0.39015893",9],[1733098620,"3710.63","3711.93","3709.67","3710.98","3709.92","2.80273267",6],[1733098680,"3711.92","3711.92","3707.55","3709.00","3710.79","4.99878483",10],[1733098740,"3709.63","3709.63","3707.53","3707.85","3709.24","12.92705570",11],[1733098800,"3711.46","3715.75","3711.46","3715.41","3713.19","0.18304800",10],[1733098860,"3715.75","3715.75","3714.36","3714.36","3714.38","7.67826291",8],[1733098920,"3710.37","3714.80","3710.37","3714.11","3713.05","0.12573380",6],[1733098980,"3713.14","3713.21","3711.86","3712.38","3712.96","0.44787485",6],[1733099040,"3713.48","3715.74","3713.48","3715.68","3714.93","2.40902895",6],[1733099100,"3714.66","3714.66","3712.52","3712.52","3714.12","3.24249086",10],[1733099160,"3711.62","3712.81","3711.62","3712.64","3712.44","2.60025607",8],[1733099220,"3712.48","3712.48","3708.50","3708.50","3709.55","0.26668812",4],[1733099280,"3708.93","3710.67","3707.95","3709.47","3708.36","2.47649558",8],[1733099340,"3709.55","3714.48","3709.55","3714.48","3711.35","0.07527418",8],[1733099400,"3713.08","3714.75","3710.41","3714.42","3712.32","2.70555586",18],[1733099460,"3711.43","3712.38","3711.43","3712.38","3712.36","1.82643610",3],[1733099520,"3712.39","3720.31","3712.39","3720.31","3715.86","2.61350617",24],[1733099580,"3721.66","3722.16","3719.76","3719.77","3721.13","3.32603971",13],[1733099640,"3719.43","3719.43","3717.37","3717.37","3717.57","1.71956027",6],[1733099700,"3717.37","3717.37","3715.06","3715.06","3716.31","10.52527502",9],[1733099760,"3713.52","3717.38","3713.18","3717.38","3714.10","1.50482534",5],[1733099820,"3717.31","3717.31","3713.83","3713.83","3717.05","0.32989751",3],[1733099880,"3715.99","3718.21","3715.99","3718.00","3717.78","1.39215757",11],[1733099940,"3718.65","3718.65","3715.11","3715.11","3716.59","0.97830532",8],[1733100000,"3714.87","3714.87","3714.87","3714.87","3714.87","0.04509939",3],[1733100060,"3714.86","3714.87","3714.86","3714.87","3714.86","1.10306853",10],[1733100120,"3714.87","3714.87","3712.00","3712.00","3714.84","17.20954626",10],[1733100180,"3712.74","3712.74","3710.32","3710.32","3712.06","1.18025036",9],[1733100240,"3710.33","3712.61","3710.33","3712.61","3711.55","3.24513279",8],[1733100300,"3711.64","3711.64","3710.88","3710.88","3711.34","0.24509336",5],[1733100360,"3711.30","3711.48","3709.95","3709.95","3710.38","5.55639738",9],[1733100420,"3709.94","3709.95","3709.94","3709.95","3709.94","1.01665485",7],[1733100480,"3709.95","3709.95","3706.43","3706.43","3707.76","4.54863132",12],[1733100540,"3706.42","3706.42","3701.11","3701.12","3706.07","7.29863099",30],[1733100600,"3701.10","3701.56","3700.00","3700.00","3700.01","9.76957061",21],[1733100660,"3700.00","3704.51","3698.26","3702.61","3701.98","600.93675138",101],[1733100720,"3701.02","3703.88","3701.00","3703.88","3701.04","4.02347718",14],[1733100780,"3703.67","3704.53","3702.96","3703.91","3703.95","7.64678219",13],[1733100840,"3703.90","3703.90","3699.64","3699.81","3700.96","45.21687930",30],[1733100900,"3699.28","3699.28","3698.20","3698.20","3698.27","1.92997174",6],[1733100960,"3698.20","3703.69","3698.20","3703.69","3702.83","2.34000640",16],[1733101020,"3703.70","3705.68","3703.69","3705.68","3704.10","10.21676292",11],[1733101080,"3705.68","3708.25","3705.68","3708.25","3706.31","5.09574781",17],[1733101140,"3707.97","3708.33","3705.79","3705.79","3705.81","5.39037138",8],[1733101200,"3705.79","3705.79","3704.66","3704.66","3705.37","4.01434338",21],[1733101260,"3704.67","3705.29","3703.57","3704.05","3703.71","3.35525022",13],[1733101320,"3702.80","3703.16","3701.67","3702.40","3701.96","1.50089868",6],[1733101380,"3704.00","3706.91","3702.96","3706.91","3705.09","17.68472839",17],[1733101440,"3706.92","3713.78","3706.92","3713.51","3712.15","1.95010276",26],[1733101500,"3713.89","3718.37","3713.31","3715.98","3714.35","2.67541481",37],[1733101560,"3717.06","3717.07","3717.06","3717.07","3717.06","0.95054264",10],[1733101620,"3717.07","3717.07","3715.84","3715.93","3716.73","5.19063126",15],[1733101680,"3716.29","3716.30","3715.98","3715.98","3716.28","1.07922204",11],[1733101740,"3715.94","3715.94","3710.62","3711.35","3714.52","5.53133214",12],[1733101800,"3712.51","3712.61","3711.25","3711.68","3712.15","1.12343299",5],[1733101860,"3712.62","3712.74","3710.47","3710.47","3711.67","2.31901853",10],[1733101920,"3710.20","3710.60","3710.00","3710.59","3710.05","2.74183739",10],[1733101980,"3712.30","3712.45","3712.30","3712.38","3712.37","0.36717243",4],[1733102040,"3711.87","3711.87","3708.93","3708.93","3709.74","2.29561443",10],[1733102100,"3707.66","3714.40","3707.66","3714.40","3710.82","0.19015597",10],[1733102160,"3714.39","3714.40","3712.77","3712.77","3712.84","1.10859749",4],[1733102220,"3714.38","3714.39","3713.40","3713.46","3713.76","17.07006619",19],[1733102280,"3713.46","3713.46","3708.26","3708.58","3713.29","4.79918781",6],[1733102340,"3709.31","3712.64","3709.30","3712.64","3711.37","4.12036219",17],[1733102400,"3713.12","3713.47","3712.20","3712.20","3713.40","0.23775198",7],[1733102460,"3713.26","3719.65","3713.26","3719.65","3718.96","58.22920711",36],[1733102520,"3719.66","3724.07","3719.66","3724.07","3721.22","1.43147807",14],[1733102580,"3724.07","3728.01","3724.06","3727.85","3727.19","33.57560840",42],[1733102640,"3727.84","3727.85","3725.18","3727.85","3727.61","3.33522847",13],[1733102700,"3727.85","3729.85","3727.79","3729.84","3728.64","7.11120795",35],[1733102760,"3730.12","3737.27","3730.12","3735.11","3736.15","114.51505036",52],[1733102820,"3736.70","3736.93","3735.66","3736.42","3736.68","1.54320892",6],[1733102880,"3737.74","3737.74","3729.96","3733.81","3734.74","1187.52329149",121],[1733102940,"3733.85","3736.39","3733.35","3735.76","3736.18","32.37596821",20],[1733103000,"3735.78","3737.93","3734.70","3734.70","3736.70","2.57508835",15],[1733103060,"3734.20","3734.62","3731.42","3734.62","3732.58","0.93813050",5],[1733103120,"3733.94","3733.94","3729.60","3729.60","3733.01","8.98385056",18],[1733103180,"3728.56","3732.00","3728.56","3732.00","3730.05","6.36599185",16],[1733103240,"3730.63","3733.16","3725.07","3725.40","3727.53","2.44408690",26],[1733103300,"3725.28","3727.21","3724.71","3725.27","3725.72","5.84262455",16],[1733103360,"3726.69","3732.41","3726.69","3732.18","3731.96","0.84927076",11],[1733103420,"3732.95","3738.64","3732.95","3738.64","3734.22","2.03992009",17],[1733103480,"3738.41","3740.61","3733.35","3733.82","3737.46","6.89492953",18],[1733103540,"3732.45","3736.59","3731.96","3736.59","3732.71","1.87635421",8],[1733103600,"3735.91","3735.91","3732.63","3732.63","3734.58","21.67483428",8],[1733103660,"3731.96","3731.96","3726.68","3726.68","3728.35","3.58613709",15],[1733103720,"3726.69","3726.70","3726.69","3726.70","3726.69","1.04001621",5],[1733103780,"3726.69","3726.69","3721.93","3724.64","3724.59","20.48137459",12],[1733103840,"3724.13","3726.71","3724.13","3726.71","3726.07","0.16390055",8],[1733103900,"3726.70","3728.24","3726.70","3728.23","3728.19","3.57611611",11],[1733103960,"3723.69","3727.69","3723.69","3727.69","3727.61","15.93352163",7],[1733104020,"3727.70","3731.82","3727.70","3731.82","3731.40","2.53467570",10],[1733104080,"3731.93","3731.93","3731.47","3731.47","3731.80","2.05169649",2],[1733104140,"3729.49","3731.53","3729.49","3731.53","3729.61","1.34596538",4],[1733104200,"3730.42","3731.63","3730.42","3730.47","3730.55","22.34096121",22],[1733104260,"3727.69","3730.66","3727.69","3730.49","3729.99","3.51798569",9],[1733104320,"3730.78","3732.33","3730.78","3730.85","3730.89","5.03262138",10],[1733104380,"3730.49","3731.71","3730.48","3731.71","3731.01","0.61044865",6],[1733104440,"3731.02","3731.13","3730.48","3730.83","3730.56","0.82809577",9],[1733104500,"3730.78","3731.92","3730.78","3731.92","3731.25","0.22809483",6],[1733104560,"3731.93","3732.00","3730.61","3732.00","3731.84","0.50641455",9],[1733104620,"3731.62","3731.99","3731.62","3731.99","3731.63","0.54775684",2],[1733104680,"3732.00","3732.00","3732.00","3732.00","3732.00","0.09468305",2],[1733104740,"3731.04","3732.00","3731.04","3732.00","3731.79","4.18138852",10],[1733104800,"3731.99","3735.66","3731.99","3734.90","3734.13","4.76216415",23],[1733104860,"3734.90","3734.90","3734.79","3734.80","3734.81","0.97646891",12],[1733104920,"3734.81","3735.00","3732.74","3732.79","3734.27","1.85136936",17],[1733104980,"3732.82","3734.77","3732.82","3733.68","3733.31","4.26487124",15],[1733105040,"3734.78","3740.27","3734.78","3739.19","3738.06","1.73811756",38],[1733105100,"3736.93","3737.28","3734.78","3735.22","3735.73","1.61002020",8],[1733105160,"3734.80","3735.44","3731.99","3731.99","3734.80","2.22291000",13],[1733105220,"3734.37","3736.41","3734.37","3736.41","3736.30","21.12889989",27],[1733105280,"3736.40","3737.93","3735.38","3735.38","3737.06","5.48038433",14],[1733105340,"3735.89","3736.02","3733.11","3733.76","3734.32","0.82557490",12],[1733105400,"3733.60","3734.14","3730.61","3730.61","3733.46","65.67101196",21],[1733105460,"3730.49","3731.31","3728.07","3731.31","3729.12","8.88904548",25],[1733105520,"3731.73","3731.73","3731.72","3731.72","3731.72","0.06718685",2],[1733105580,"3730.82","3730.82","3728.82","3728.82","3728.90","1.00776283",5],[1733105640,"3728.81","3728.81","3725.75","3725.75","3725.93","1.50634335",12],[1733105700,"3724.97","3725.96","3720.00","3720.00","3724.43","24.46932225",25],[1733105760,"3717.27","3717.27","3711.96","3711.96","3713.63","0.01903047",5],[1733105820,"3711.65","3713.26","3711.65","3712.56","3713.06","3.47557518",16],[1733105880,"3713.28","3713.28","3711.65","3711.76","3711.77","5.17282550",9],[1733105940,"3713.19","3713.19","3713.18","3713.18","3713.18","0.90137233",7],[1733106000,"3713.18","3713.18","3710.00","3710.01","3711.07","18.71360575",29],[1733106060,"3710.00","3712.76","3708.97","3711.39","3711.80","8.77180995",23],[1733106120,"3711.39","3713.23","3711.36","3713.23","3712.05","0.89881581",9],[1733106180,"3713.27","3713.27","3713.26","3713.27","3713.26","2.65097026",7],[1733106240,"3712.35","3716.79","3712.35","3713.27","3713.29","8.27768262",21],[1733106300,"3713.26","3714.75","3713.26","3714.75","3714.64","1.61473142",5],[1733106360,"3714.76","3716.08","3714.75","3715.82","3714.84","12.19437685",13],[1733106420,"3716.58","3718.95","3716.17","3716.17","3718.14","2.47686829",11],[1733106480,"3716.16","3718.54","3715.77","3718.50","3718.24","2.61396118",7],[1733106540,"3718.45","3721.55","3718.45","3718.45","3719.16","590.09302667",54],[1733106600,"3718.44","3718.45","3718.41","3718.41","3718.43","6.55360577",11],[1733106660,"3716.92","3716.92","3715.78","3715.78","3716.90","3.19560806",10],[1733106720,"3715.77","3715.77","3715.02","3715.02","3715.66","0.28449900",5],[1733106780,"3715.92","3717.63","3714.00","3714.00","3715.78","1.94428975",10],[1733106840,"3714.00","3714.00","3711.03","3713.14","3712.15","157.28720382",34],[1733106900,"3714.49","3715.23","3713.67","3713.78","3714.40","0.41309790",9],[1733106960,"3713.71","3714.69","3713.71","3714.54","3714.40","30.69203258",7],[1733107020,"3715.73","3716.29","3714.27","3714.33","3714.85","0.83299615",6],[1733107080,"3713.94","3713.94","3711.79","3711.82","3711.94","14.08306561",10],[1733107140,"3711.66","3711.76","3711.66","3711.76","3711.74","0.02236976",2],[1733107200,"3714.25","3714.53","3714.07","3714.52","3714.51","52.91718803",15],[1733107260,"3714.52","3714.53","3714.52","3714.53","3714.52","0.61779140",6],[1733107320,"3714.53","3716.03","3714.53","3714.73","3715.39","1.05229050",9],[1733107380,"3715.88","3716.54","3715.16","3715.30","3716.08","0.43676791",12],[1733107440,"3715.54","3715.54","3715.13","3715.13","3715.36","3.68058189",8],[1733107500,"3714.68","3714.68","3711.52","3711.52","3713.68","11.69297765",16],[1733107560,"3711.84","3716.74","3711.60","3716.74","3713.97","600.49558784",67],[1733107620,"3716.75","3719.55","3716.75","3718.95","3718.75","54.03069047",21],[1733107680,"3718.87","3718.92","3718.30","3718.92","3718.90","3.66612803",5],[1733107740,"3719.51","3719.51","3719.51","3719.51","3719.51","0.20185992",1],[1733107800,"3719.56","3719.67","3717.76","3717.93","3719.44","0.75865036",10],[1733107860,"3718.63","3718.63","3718.62","3718.62","3718.62","0.56931127",5],[1733107920,"3718.63","3722.76","3718.63","3721.23","3720.68","9.66881328",26],[1733107980,"3720.55","3720.55","3718.94","3718.94","3720.00","0.99045517",3],[1733108040,"3719.91","3720.95","3719.91","3720.95","3720.02","0.16947448",6],[1733108100,"3721.49","3725.45","3721.49","3725.45","3723.23","0.11455885",21],[1733108160,"3725.79","3726.09","3725.79","3726.09","3726.04","0.06632802",3],[1733108220,"3726.20","3730.92","3726.20","3730.92","3728.21","1.64704086",30],[1733108280,"3730.92","3737.99","3730.92","3737.85","3733.79","1.62871808",18],[1733108340,"3736.86","3740.21","3736.86","3740.21","3738.41","4.89516870",29],[1733108400,"3740.51","3748.41","3740.34","3748.41","3743.11","13.81244228",83],[1733108460,"3748.39","3752.00","3747.95","3751.99","3750.13","148.67248027",130],[1733108520,"3752.00","3755.78","3752.00","3754.00","3753.62","27.14886466",66],[1733108580,"3752.69","3762.00","3752.69","3756.75","3759.01","34.99405027",102],[1733108640,"3758.26","3759.86","3752.29","3755.20","3754.20","10.80499290",32],[1733108700,"3755.20","3760.78","3755.20","3758.97","3759.35","4.88193990",36],[1733108760,"3760.07","3762.46","3757.62","3758.50","3762.30","30.08501576",34],[1733108820,"3756.48","3756.48","3751.21","3751.98","3754.73","3.60454425",10],[1733108880,"3751.98","3751.98","3743.37","3749.79","3746.81","606.64345921",88],[1733108940,"3748.68","3749.79","3748.68","3749.57","3749.72","1.42647850",9],[1733109000,"3748.56","3750.74","3748.53","3750.74","3749.52","5.23562212",7],[1733109060,"3751.00","3754.43","3751.00","3751.17","3751.37","1.12565280",8],[1733109120,"3751.08","3751.08","3749.89","3749.89","3750.98","2.77972409",9],[1733109180,"3749.89","3749.90","3741.32","3742.95","3743.95","617.09067274",60],[1733109240,"3742.53","3745.93","3742.53","3743.92","3743.55","1.54180829",13],[1733109300,"3743.87","3745.51","3740.53","3741.00","3741.82","9.20271782",30],[1733109360,"3740.77","3745.14","3738.87","3744.23","3739.91","3.40532723",11],[1733109420,"3744.13","3749.91","3743.09","3746.29","3745.88","2.45623524",17],[1733109480,"3744.94","3744.94","3742.85","3744.38","3744.07","1.36271335",13],[1733109540,"3746.63","3747.01","3744.37","3744.94","3744.77","2.07718865",13],[1733109600,"3746.16","3749.90","3746.16","3749.90","3746.99","51.96432819",16],[1733109660,"3749.91","3750.00","3749.91","3750.00","3749.99","2.43336277",7],[1733109720,"3750.54","3750.55","3749.91","3749.91","3750.50","37.03691213",14],[1733109780,"3748.07","3750.99","3746.30","3750.99","3748.10","1.50992204",16],[1733109840,"3750.99","3751.00","3750.94","3750.99","3750.98","5.60800335",11],[1733109900,"3751.00","3751.00","3747.80","3748.80","3749.63","1.30208242",11],[1733109960,"3749.10","3750.01","3748.68","3748.68","3749.94","3.01379069",8],[1733110020,"3748.68","3748.68","3745.91","3745.92","3748.38","3.86997931",13],[1733110080,"3745.57","3747.32","3745.57","3747.13","3747.13","17.75442377",10],[1733110140,"3746.35","3746.35","3743.73","3743.73","3744.13","6.25543832",9],[1733110200,"3743.49","3743.49","3741.27","3741.27","3743.39","2.17415821",8],[1733110260,"3739.56","3739.56","3733.60","3733.60","3735.27","2.64516719",37],[1733110320,"3733.59","3733.60","3733.19","3733.19","3733.58","0.57866359",5],[1733110380,"3732.55","3733.03","3732.10","3732.90","3732.84","2.55944209",12],[1733110440,"3733.42","3735.96","3733.42","3735.26","3733.44","4.01539093",7],[1733110500,"3733.29","3736.65","3732.74","3736.65","3732.96","1.16068946",6],[1733110560,"3732.81","3732.81","3731.93","3731.98","3731.93","1.90208153",7],[1733110620,"3731.92","3731.92","3730.70","3730.70","3730.90","1.21522024",7],[1733110680,"3730.65","3730.65","3727.41","3727.64","3728.32","126.80353549",14],[1733110740,"3727.09","3727.09","3726.68","3726.68","3726.86","0.06778342",5],[1733110800,"3726.68","3726.68","3723.53","3725.86","3725.14","11.08895264",21],[1733110860,"3726.29","3726.29","3724.38","3725.48","3725.73","2.87873086",14],[1733110920,"3723.88","3723.88","3721.69","3721.69","3722.43","0.36695824",10],[1733110980,"3721.87","3721.87","3719.16","3719.16","3721.03","5.05288572",10],[1733111040,"3717.90","3717.90","3713.94","3713.95","3715.45","11.05218052",18],[1733111100,"3714.75","3715.72","3714.39","3715.72","3715.13","1.90904325",10],[1733111160,"3715.71","3719.90","3714.71","3714.71","3717.60","646.50096829",76],[1733111220,"3717.58","3721.31","3716.60","3718.90","3719.08","632.28030491",53],[1733111280,"3720.40","3722.31","3719.99","3719.99","3720.20","2.07107894",11],[1733111340,"3719.99","3719.99","3714.60","3714.60","3716.79","10.29398413",11],[1733111400,"3713.94","3713.95","3708.06","3708.06","3710.15","19.67318096",46],[1733111460,"3708.03","3708.32","3706.22","3706.22","3707.48","15.20409903",28],[1733111520,"3706.22","3706.23","3706.22","3706.23","3706.22","0.10100048",5],[1733111580,"3706.23","3706.24","3701.83","3702.55","3704.75","30.34488141",40],[1733111640,"3702.44","3702.45","3699.37","3700.28","3699.73","10.78970492",23],[1733111700,"3698.99","3703.33","3697.95","3697.95","3700.99","64.09466072",49],[1733111760,"3697.95","3697.96","3690.00","3690.00","3692.44","17.15980298",62],[1733111820,"3690.00","3690.00","3680.06","3683.41","3684.58","53.49020228",57],[1733111880,"3689.25","3694.94","3688.89","3692.47","3691.73","30.97551014",35],[1733111940,"3692.43","3694.30","3688.97","3690.54","3692.26","1.19194122",9],[1733112000,"3688.42","3693.60","3686.60","3692.94","3688.66","54.70290317",61],[1733112060,"3692.95","3692.95","3689.84","3692.95","3691.09","1.34409470",15],[1733112120,"3692.94","3696.84","3692.94","3696.51","3695.93","23.30863189",23],[1733112180,"3696.51","3696.51","3692.57","3692.98","3694.29","2.92452262",11],[1733112240,"3692.45","3692.45","3689.57","3689.57","3690.83","0.07770615",5],[1733112300,"3691.72","3695.45","3685.17","3685.17","3689.42","414.10633560",41],[1733112360,"3684.81","3684.81","3680.53","3681.23","3683.18","33.30483679",20],[1733112420,"3680.05","3680.05","3666.68","3668.59","3670.51","120.02731584",118],[1733112480,"3669.34","3673.82","3663.50","3673.56","3668.97","77.59998701",34],[1733112540,"3673.20","3673.20","3671.20","3673.20","3672.33","2.10567611",13],[1733112600,"3673.20","3674.29","3666.21","3674.29","3670.73","46.00404715",24],[1733112660,"3673.18","3673.18","3667.36","3667.37","3669.00","2.76140870",10],[1733112720,"3671.29","3671.29","3663.75","3668.44","3665.72","439.73010498",50],[1733112780,"3667.38","3669.54","3667.37","3669.54","3667.38","1.43324356",10],[1733112840,"3669.54","3669.54","3667.37","3667.37","3667.38","15.69024386",12],[1733112900,"3667.38","3667.38","3661.99","3663.01","3666.29","10.84720189",24],[1733112960,"3665.59","3670.85","3665.59","3670.85","3668.30","2.31660891",13],[1733113020,"3670.84","3672.42","3667.80","3668.60","3669.51","9.17243732",13],[1733113080,"3668.01","3668.01","3668.00","3668.00","3668.00","0.02645376",2],[1733113140,"3666.61","3668.57","3661.98","3661.98","3662.66","8.30448327",11],[1733113200,"3663.86","3665.57","3662.12","3662.12","3663.40","0.22947588",6],[1733113260,"3661.98","3661.98","3654.91","3657.23","3658.06","54.13949250",70],[1733113320,"3655.81","3656.77","3653.99","3656.04","3655.65","60.77418689",31],[1733113380,"3656.03","3660.63","3655.35","3660.63","3656.31","27.02402577",19],[1733113440,"3661.65","3666.52","3661.13","3666.52","3661.99","0.88086267",13],[1733113500,"3666.64","3670.00","3666.64","3668.27","3667.00","0.82227417",9],[1733113560,"3670.07","3671.45","3668.36","3671.45","3670.14","3.99516068",21],[1733113620,"3670.28","3672.25","3670.28","3672.25","3672.01","0.91550529",6],[1733113680,"3672.27","3672.27","3672.27","3672.27","3672.27","0.03968734",2],[1733113740,"3672.57","3676.54","3672.57","3675.48","3675.25","2.06308410",18],[1733113800,"3675.27","3675.28","3675.27","3675.28","3675.27","0.64878414",5],[1733113860,"3675.28","3677.32","3675.28","3677.32","3676.88","51.31786865",20],[1733113920,"3677.38","3682.44","3677.38","3679.39","3679.52","18.01225408",31],[1733113980,"3679.09","3679.09","3678.45","3679.09","3679.06","2.54781952",10],[1733114040,"3679.08","3679.79","3679.08","3679.79","3679.09","21.33804694",4],[1733114100,"3679.95","3684.84","3679.95","3684.79","3684.70","54.09572571",18],[1733114160,"3683.77","3683.77","3682.65","3682.65","3682.94","6.76452165",4],[1733114220,"3680.68","3683.02","3680.68","3683.02","3681.74","0.78283925",12],[1733114280,"3684.26","3684.26","3684.26","3684.26","3684.26","2.15234170",6],[1733114340,"3684.27","3685.98","3684.27","3685.01","3685.73","30.37085526",9],[1733114400,"3685.00","3687.45","3684.50","3687.45","3686.26","4.67797364",20],[1733114460,"3687.60","3689.77","3687.60","3689.50","3689.59","14.37532162",26],[1733114520,"3687.60","3692.55","3687.60","3692.55","3691.89","1.10468296",16],[1733114580,"3692.64","3692.82","3689.50","3689.50","3690.05","13.30133497",10],[1733114640,"3689.95","3689.95","3689.95","3689.95","3689.95","0.02970297",2],[1733114700,"3689.32","3689.87","3689.32","3689.87","3689.83","2.77299430",7],[1733114760,"3689.87","3689.87","3685.48","3685.58","3687.53","2.41119393",7],[1733114820,"3685.47","3687.42","3683.49","3687.42","3685.63","3.52547055",10],[1733114880,"3685.91","3685.91","3684.15","3685.19","3685.29","152.76147269",13],[1733114940,"3684.89","3684.89","3682.86","3682.99","3683.19","1.22306129",8],[1733115000,"3685.74","3686.83","3685.16","3686.03","3685.99","0.73522808",8],[1733115060,"3684.98","3684.98","3684.66","3684.79","3684.83","1.40218663",4],[1733115120,"3684.93","3686.72","3684.93","3686.72","3685.08","3.01878103",7],[1733115180,"3686.73","3688.85","3686.73","3687.98","3688.02","0.23050162",7],[1733115240,"3688.49","3688.49","3687.48","3687.52","3688.11","4.92420915",7],[1733115300,"3687.93","3690.41","3687.74","3690.36","3690.37","34.17063466",12],[1733115360,"3689.40","3691.92","3689.40","3691.70","3691.70","0.97688424",16],[1733115420,"3692.33","3693.17","3691.38","3691.38","3693.07","0.16049081",7],[1733115480,"3691.76","3693.41","3691.76","3693.01","3693.33","11.41965812",16],[1733115540,"3693.01","3694.40","3693.01","3694.07","3694.33","16.45453799",14],[1733115600,"3694.07","3694.07","3692.59","3693.00","3692.62","4.87075228",9],[1733115660,"3690.01","3690.35","3690.01","3690.35","3690.26","0.12087354",5],[1733115720,"3690.82","3691.56","3690.00","3690.87","3691.01","1.36706396",11],[1733115780,"3690.88","3690.88","3690.87","3690.88","3690.87","6.35702340",7],[1733115840,"3690.88","3693.05","3689.57","3689.57","3692.08","1.87717810",15],[1733115900,"3690.47","3690.80","3690.47","3690.80","3690.62","0.66712573",8],[1733115960,"3690.80","3698.60","3690.80","3698.60","3692.92","2.60909291",44],[1733116020,"3698.76","3700.00","3698.76","3700.00","3699.53","2.88391984",24],[1733116080,"3700.00","3700.00","3699.99","3700.00","3699.99","0.17103637",12],[1733116140,"3699.99","3699.99","3699.16","3699.16","3699.55","0.67800000",2],[1733116200,"3700.00","3700.00","3699.99","3700.00","3699.99","2.39856622",5],[1733116260,"3700.00","3704.30","3700.00","3704.30","3700.19","5.80982130",25],[1733116320,"3704.32","3704.32","3702.44","3702.44","3704.29","0.27438423",3],[1733116380,"3701.19","3702.10","3701.19","3701.70","3701.69","3.02701502",4],[1733116440,"3701.93","3702.22","3701.53","3701.82","3701.70","0.95237861",6],[1733116500,"3702.23","3704.27","3702.23","3703.69","3703.71","0.21097162",5],[1733116560,"3701.37","3702.24","3701.37","3702.23","3701.78","1.47890900",10],[1733116620,"3702.24","3702.24","3702.24","3702.24","3702.24","0.10856382",3],[1733116680,"3702.23","3706.62","3702.23","3705.38","3703.89","10.14837097",23],[1733116740,"3706.62","3708.92","3705.98","3708.36","3707.49","28.50488200",21],[1733116800,"3709.09","3709.79","3708.44","3708.44","3708.90","2.37487599",8],[1733116860,"3708.44","3710.39","3708.35","3708.35","3708.46","57.49465455",16],[1733116920,"3704.85","3706.62","3702.77","3702.77","3705.24","23.89357877",16],[1733116980,"3702.76","3704.23","3702.76","3704.23","3703.50","50.79466085",5],[1733117040,"3706.06","3706.07","3704.79","3705.53","3705.44","0.68657979",8],[1733117100,"3706.01","3706.37","3703.96","3704.51","3705.16","16.79401014",11],[1733117160,"3704.78","3704.80","3704.78","3704.80","3704.78","0.23451329",4],[1733117220,"3704.81","3705.35","3704.78","3705.35","3704.79","1.35900162",6],[1733117280,"3705.37","3705.75","3704.78","3704.78","3705.12","1.44033535",9],[1733117340,"3703.28","3703.28","3701.77","3702.00","3702.34","0.32833183",10],[1733117400,"3702.01","3702.01","3699.99","3699.99","3700.18","0.97232822",13],[1733117460,"3699.99","3700.00","3699.27","3699.27","3699.70","1.93342130",8],[1733117520,"3699.77","3699.77","3699.14","3699.15","3699.40","8.23367084",9],[1733117580,"3699.48","3699.93","3699.47","3699.48","3699.73","1.37470521",6],[1733117640,"3699.48","3700.74","3699.47","3700.22","3700.54","0.63684798",4],[1733117700,"3700.00","3700.00","3695.29","3695.30","3697.14","2.07422600",12],[1733117760,"3695.30","3695.30","3691.80","3694.35","3694.74","4.56382554",15],[1733117820,"3695.60","3695.94","3695.60","3695.94","3695.80","0.06674969",6],[1733117880,"3695.93","3695.94","3695.93","3695.93","3695.93","13.59419320",6],[1733117940,"3695.93","3695.93","3695.93","3695.93","0.00","0.00000000",0],[1733118000,"3695.93","3695.93","3694.66","3694.66","3695.30","7.97025961",5],[1733118060,"3695.94","3696.26","3695.49","3695.49","3695.92","0.95618130",5],[1733118120,"3694.64","3694.64","3694.63","3694.63","3694.63","1.71774091",4],[1733118180,"3694.64","3694.64","3688.26","3688.26","3690.55","2.06895129",11],[1733118240,"3688.51","3689.99","3688.51","3689.99","3688.86","2.19349145",7],[1733118300,"3689.99","3689.99","3688.99","3689.00","3689.01","2.38638283",6],[1733118360,"3688.99","3688.99","3687.00","3687.00","3687.72","1.38470446",7],[1733118420,"3687.01","3687.01","3685.01","3685.01","3685.59","5.29168807",9],[1733118480,"3685.00","3685.00","3682.68","3682.68","3682.78","22.84754978",10],[1733118540,"3682.68","3682.68","3682.68","3682.68","3682.68","0.00685914",1],[1733118600,"3682.67","3682.67","3680.02","3680.02","3680.64","2.40649525",9],[1733118660,"3680.03","3680.03","3678.56","3678.56","3680.01","2.12418585",11],[1733118720,"3678.75","3678.75","3678.37","3678.37","3678.74","1.82047494",6],[1733118780,"3678.37","3678.37","3673.83","3674.99","3674.47","32.04325152",84],[1733118840,"3675.00","3677.40","3675.00","3677.40","3677.16","16.60645771",8],[1733118900,"3677.41","3678.07","3677.41","3678.07","3677.96","1.81080282",6],[1733118960,"3677.31","3679.50","3677.31","3679.50","3677.44","13.01481299",14],[1733119020,"3679.50","3681.78","3679.50","3681.61","3680.89","4.62196263",12],[1733119080,"3680.62","3680.62","3677.98","3677.98","3680.07","3.75235529",14],[1733119140,"3677.98","3678.65","3677.98","3678.50","3678.23","0.07356708",3],[1733119200,"3678.50","3678.50","3676.41","3676.41","3677.24","0.57904837",7],[1733119260,"3677.09","3677.09","3675.20","3675.20","3675.79","1.63196156",10],[1733119320,"3675.19","3675.19","3673.17","3673.49","3673.86","6.89517465",14],[1733119380,"3673.85","3673.85","3673.17","3673.17","3673.77","28.08356449",8],[1733119440,"3673.18","3673.18","3673.17","3673.17","3673.17","1.01294984",4],[1733119500,"3673.18","3673.18","3673.17","3673.18","3673.17","7.56500781",10],[1733119560,"3673.18","3673.18","3672.86","3672.86","3673.17","35.13992886",6],[1733119620,"3672.86","3672.86","3669.98","3669.98","3670.08","2.05075781",8],[1733119680,"3669.98","3669.98","3669.98","3669.98","0.00","0.00000000",0],[1733119740,"3669.97","3669.97","3669.52","3669.53","3669.53","0.53047452",10],[1733119800,"3669.52","3669.52","3664.23","3669.52","3667.81","92.16069189",49],[1733119860,"3669.53","3671.27","3668.85","3668.85","3670.50","1.41267811",14],[1733119920,"3668.29","3671.24","3668.29","3671.24","3668.33","9.74809587",10],[1733119980,"3672.31","3672.91","3672.31","3672.90","3672.76","0.09921546",8],[1733120040,"3670.26","3670.58","3670.26","3670.58","3670.43","0.68478523",4],[1733120100,"3672.31","3673.15","3672.31","3673.15","3672.96","0.01729194",4],[1733120160,"3673.17","3678.78","3673.17","3677.23","3677.03","1.81843816",44],[1733120220,"3677.28","3678.55","3677.28","3678.55","3677.92","0.14299156",6],[1733120280,"3678.55","3678.55","3674.85","3674.85","3678.37","23.15380036",12],[1733120340,"3673.83","3676.01","3673.51","3676.01","3675.15","1.07684912",6],[1733120400,"3676.42","3676.48","3675.60","3675.60","3676.38","24.40881027",6],[1733120460,"3676.65","3676.65","3675.83","3675.83","3675.99","0.14774000",2],[1733120520,"3675.83","3675.92","3675.82","3675.92","3675.82","1.30425290",8],[1733120580,"3673.36","3673.36","3673.18","3673.18","3673.27","0.14398556",10],[1733120640,"3673.17","3673.17","3664.98","3664.98","3667.19","27.04984244",11],[1733120700,"3663.80","3664.48","3659.10","3664.48","3662.18","4.72197447",27],[1733120760,"3663.79","3667.39","3662.99","3667.27","3663.40","84.81281725",11],[1733120820,"3665.89","3665.89","3664.10","3665.71","3664.21","0.99993982",5],[1733120880,"3665.71","3671.61","3665.71","3671.43","3667.21","7.48859870",6],[1733120940,"3671.18","3672.00","3669.33","3671.85","3671.18","9.71721168",24],[1733121000,"3671.99","3672.59","3671.99","3672.59","3672.26","11.47236389",15],[1733121060,"3672.59","3681.58","3672.59","3681.57","3677.86","5.84579717",45],[1733121120,"3679.39","3680.00","3679.39","3679.96","3679.96","54.98596614",10],[1733121180,"3679.65","3679.65","3676.19","3676.19","3678.11","17.01139802",18],[1733121240,"3676.10","3676.93","3674.67","3676.93","3676.12","5.03308436",13],[1733121300,"3676.79","3677.81","3669.21","3670.53","3675.19","0.49004659",10],[1733121360,"3670.01","3673.49","3670.01","3673.49","3672.64","5.29860522",7],[1733121420,"3673.20","3678.31","3673.20","3677.89","3675.49","1.85010403",12],[1733121480,"3677.50","3677.50","3677.50","3677.50","3677.50","0.29711217",1],[1733121540,"3678.34","3679.84","3678.34","3679.84","3678.48","1.39460625",8],[1733121600,"3679.84","3679.84","3679.83","3679.83","3679.83","0.25839266",4],[1733121660,"3679.83","3681.55","3679.83","3681.37","3679.86","16.84264099",25],[1733121720,"3681.56","3681.56","3680.65","3680.94","3680.85","7.16738077",8],[1733121780,"3680.02","3680.37","3676.90","3677.27","3677.41","3.28546413",7],[1733121840,"3676.80","3679.59","3676.80","3679.59","3677.33","0.08931058",4],[1733121900,"3679.65","3679.65","3678.24","3678.24","3678.79","0.27389097",3],[1733121960,"3678.89","3681.50","3678.89","3681.50","3680.26","12.05893847",22],[1733122020,"3681.23","3681.56","3681.23","3681.56","3681.55","0.66759479",14],[1733122080,"3681.56","3684.15","3681.55","3683.94","3683.03","4.41859345",19],[1733122140,"3683.73","3683.73","3682.11","3682.11","3682.63","0.06141612",3],[1733122200,"3681.58","3684.86","3681.58","3684.86","3682.04","3.21581691",17],[1733122260,"3685.33","3685.86","3685.28","3685.29","3685.29","50.68576249",11],[1733122320,"3685.28","3685.28","3682.16","3683.01","3683.92","5.41500809",17],[1733122380,"3683.42","3683.53","3683.42","3683.53","3683.42","0.04775001",2],[1733122440,"3683.52","3685.37","3683.52","3684.63","3684.53","0.39202891",19],[1733122500,"3684.25","3686.06","3684.25","3685.22","3685.29","8.95421616",16],[1733122560,"3684.98","3684.98","3684.98","3684.98","3684.98","0.42360343",3],[1733122620,"3683.48","3683.48","3683.19","3683.19","3683.46","0.08698395",3],[1733122680,"3683.18","3683.18","3680.00","3680.00","3680.86","1.78690567",10],[1733122740,"3680.00","3682.10","3680.00","3681.90","3680.55","1.53266807",11],[1733122800,"3682.02","3684.27","3682.02","3682.96","3683.24","0.89211989",18],[1733122860,"3683.64","3683.64","3683.63","3683.64","3683.63","2.54414649",7],[1733122920,"3683.64","3687.58","3683.64","3685.25","3685.75","4.93644398",25],[1733122980,"3684.83","3685.03","3684.83","3685.03","3684.88","2.02850000",8],[1733123040,"3684.29","3684.53","3682.15","3682.15","3683.53","3.09131346",16],[1733123100,"3681.48","3682.80","3681.48","3682.79","3682.43","4.14472568",16],[1733123160,"3682.80","3682.80","3682.12","3682.12","3682.13","3.65567327",3],[1733123220,"3682.33","3682.39","3682.33","3682.39","3682.38","1.06710000",3],[1733123280,"3682.80","3684.40","3682.80","3684.39","3683.33","1.00734846",12],[1733123340,"3684.40","3684.60","3684.40","3684.60","3684.52","0.33608371",6],[1733123400,"3684.60","3685.59","3684.60","3685.59","3684.97","1.70217982",16],[1733123460,"3685.60","3685.60","3685.60","3685.60","3685.60","0.18484512",2],[1733123520,"3685.59","3685.60","3685.59","3685.60","3685.59","0.12379263",5],[1733123580,"3685.60","3685.60","3685.59","3685.59","3685.59","0.54692616",5],[1733123640,"3685.59","3685.59","3680.00","3680.00","3685.01","3.62741420",11],[1733123700,"3680.01","3680.01","3676.82","3676.82","3678.39","10.75353471",64],[1733123760,"3675.20","3675.20","3675.20","3675.20","3675.20","0.03439656",1],[1733123820,"3674.88","3674.89","3674.88","3674.88","3674.88","0.12711796",4],[1733123880,"3674.01","3674.01","3670.00","3670.00","3671.80","6.12876961",12],[1733123940,"3670.00","3670.00","3668.07","3668.96","3668.15","8.87328344",15],[1733124000,"3668.37","3668.43","3665.00","3665.00","3667.92","9.95590589",17],[1733124060,"3665.01","3665.01","3664.09","3664.09","3664.99","3.17951958",8],[1733124120,"3666.81","3666.81","3664.09","3664.09","3665.00","0.89366053",4],[1733124180,"3664.70","3664.70","3657.69","3657.69","3659.18","16.90729201",23],[1733124240,"3657.06","3657.06","3657.00","3657.00","3657.01","0.23393927",7],[1733124300,"3657.01","3664.67","3657.01","3664.67","3661.27","26.29323546",18],[1733124360,"3664.72","3666.46","3664.72","3666.07","3665.91","0.92039344",6],[1733124420,"3665.78","3666.46","3664.00","3664.00","3666.13","1.35371968",6],[1733124480,"3664.01","3664.01","3657.01","3657.01","3662.99","3.85176630",23],[1733124540,"3657.60","3659.03","3657.60","3659.03","3658.39","0.27183433",7],[1733124600,"3660.51","3664.26","3660.51","3662.03","3662.42","0.22421902",12],[1733124660,"3661.63","3662.37","3658.38","3662.37","3660.92","5.89165330",16],[1733124720,"3660.50","3665.35","3660.50","3665.35","3663.68","6.97420217",16],[1733124780,"3664.57","3670.78","3664.57","3670.78","3667.86","12.31302816",27],[1733124840,"3671.03","3671.03","3666.47","3666.47","3668.16","1.84471814",5],[1733124900,"3666.47","3667.68","3666.47","3666.47","3666.93","2.66374176",8],[1733124960,"3665.92","3665.93","3662.09","3662.09","3664.55","3.66139131",7],[1733125020,"3662.09","3662.09","3662.09","3662.09","0.00","0.00000000",0],[1733125080,"3660.21","3661.51","3659.99","3661.51","3660.02","3.32349664",15],[1733125140,"3661.51","3663.44","3661.51","3663.44","3663.38","100.02250387",9],[1733125200,"3664.26","3664.26","3663.89","3664.26","3664.24","0.16832674",4],[1733125260,"3664.27","3668.28","3664.27","3668.28","3668.15","73.53592774",15],[1733125320,"3668.28","3668.28","3667.85","3668.28","3667.93","0.93619770",4],[1733125380,"3668.29","3668.95","3668.02","3668.04","3668.04","1.57012996",9],[1733125440,"3668.11","3668.65","3668.00","3668.01","3668.05","1.75045712",13],[1733125500,"3668.00","3668.01","3668.00","3668.01","3668.00","0.10673053",2],[1733125560,"3668.01","3671.90","3668.01","3671.20","3671.03","8.25428836",15],[1733125620,"3669.98","3670.30","3669.18","3669.95","3669.65","2.04980059",14],[1733125680,"3667.72","3667.72","3666.30","3666.44","3666.43","0.63481830",3],[1733125740,"3668.07","3670.29","3668.07","3670.29","3669.37","0.08677484",5],[1733125800,"3669.78","3671.41","3669.78","3671.41","3671.38","2.75584512",5],[1733125860,"3671.84","3671.84","3671.84","3671.84","3671.84","0.01000000",1],[1733125920,"3672.20","3672.64","3670.85","3671.11","3671.37","0.55174824",15],[1733125980,"3670.86","3670.86","3670.86","3670.86","3670.86","0.04849000",1],[1733126040,"3669.98","3669.98","3668.60","3668.60","3668.83","1.20700000",6],[1733126100,"3669.68","3669.68","3669.59","3669.59","3669.67","0.10413882",2],[1733126160,"3670.24","3670.33","3670.24","3670.33","3670.30","4.14100946",7],[1733126220,"3670.24","3670.34","3669.07","3669.07","3670.02","4.44886076",5],[1733126280,"3668.78","3668.91","3668.60","3668.60","3668.85","0.41443086",3],[1733126340,"3669.09","3669.09","3669.09","3669.09","3669.09","0.00655000",1],[1733126400,"3668.79","3668.79","3664.50","3664.50","3668.05","9.80404223",14],[1733126460,"3664.49","3664.49","3660.45","3661.20","3660.95","3.94403732",11],[1733126520,"3663.40","3663.96","3662.80","3662.80","3663.06","0.15007795",5],[1733126580,"3664.51","3664.51","3664.50","3664.51","3664.50","0.52825930",4],[1733126640,"3664.89","3667.15","3664.12","3664.13","3664.54","2.35750508",14],[1733126700,"3662.96","3665.64","3662.96","3663.01","3663.11","0.37259050",4],[1733126760,"3663.01","3663.43","3660.24","3660.24","3662.98","14.60738753",19],[1733126820,"3662.50","3662.50","3660.01","3660.01","3662.25","2.01310000",2],[1733126880,"3660.70","3662.24","3660.01","3662.24","3661.34","68.58482248",10],[1733126940,"3662.24","3667.50","3662.24","3667.50","3662.75","3.66475517",10],[1733127000,"3667.50","3667.50","3667.49","3667.49","3667.49","0.11704927",4],[1733127060,"3667.50","3673.09","3667.50","3673.09","3670.49","0.58183221",22],[1733127120,"3672.38","3673.07","3672.38","3673.07","3673.02","11.48948852",9],[1733127180,"3673.06","3673.06","3670.18","3670.18","3670.31","0.14537951",4],[1733127240,"3670.17","3670.17","3663.47","3663.47","3667.66","2.53236674",18],[1733127300,"3663.64","3664.27","3663.64","3664.27","3663.76","8.84817306",6],[1733127360,"3664.03","3664.03","3660.01","3660.01","3663.00","6.64019089",14],[1733127420,"3660.00","3660.01","3657.00","3657.00","3659.56","2.32171337",7],[1733127480,"3656.66","3656.66","3641.29","3641.89","3646.08","173.44592351",226],[1733127540,"3641.88","3643.22","3638.16","3639.95","3639.50","36.64225064",64],[1733127600,"3639.81","3639.81","3611.54","3617.64","3622.19","108.04399632",308],[1733127660,"3621.11","3631.23","3621.11","3631.23","3624.14","15.51583372",20],[1733127720,"3629.57","3631.33","3627.80","3629.69","3627.86","11.48613821",9],[1733127780,"3626.96","3626.96","3621.79","3621.85","3624.45","3.75294460",13],[1733127840,"3623.18","3624.61","3621.68","3622.26","3621.79","12.19719674",17],[1733127900,"3623.39","3623.79","3618.81","3623.39","3619.71","5.73807091",23],[1733127960,"3621.54","3621.54","3619.63","3619.63","3620.22","6.27167863",15],[1733128020,"3618.58","3621.39","3611.36","3612.34","3613.78","75.41206447",44],[1733128080,"3612.17","3616.55","3611.00","3612.99","3616.29","73.10158507",44],[1733128140,"3616.56","3623.01","3616.30","3616.30","3622.71","74.15931054",22],[1733128200,"3616.31","3622.00","3616.31","3618.55","3618.94","78.43583366",28],[1733128260,"3622.03","3622.03","3619.94","3620.39","3621.91","1.71988875",8],[1733128320,"3620.47","3630.21","3620.47","3630.01","3625.10","25.26707446",15],[1733128380,"3630.01","3630.01","3624.22","3625.54","3629.09","0.27735247",5],[1733128440,"3623.16","3624.08","3619.88","3621.69","3621.51","0.24694343",9],[1733128500,"3621.70","3626.68","3621.70","3625.90","3625.88","1.17220248",12],[1733128560,"3626.69","3627.04","3622.00","3622.01","3624.55","295.01840147",64],[1733128620,"3622.00","3622.00","3612.95","3613.41","3617.95","1.94925179",24],[1733128680,"3613.41","3614.29","3611.00","3611.00","3613.00","3.45803286",23],[1733128740,"3611.55","3611.55","3606.64","3606.64","3609.12","64.73204832",53],[1733128800,"3606.64","3606.64","3588.00","3588.88","3595.63","328.71358640",267],[1733128860,"3589.19","3601.38","3589.19","3598.27","3596.63","38.91827855",63],[1733128920,"3598.01","3609.45","3598.01","3607.81","3602.61","20.26306319",29],[1733128980,"3608.52","3611.73","3605.49","3606.58","3609.38","198.07252474",40],[1733129040,"3606.08","3609.99","3602.44","3605.50","3605.46","11.80793006",20],[1733129100,"3603.63","3603.91","3594.97","3596.24","3596.08","87.07490902",48],[1733129160,"3595.77","3595.77","3588.00","3590.30","3591.13","24.84599448",28],[1733129220,"3590.97","3595.77","3588.29","3595.00","3591.21","52.86153917",30],[1733129280,"3594.99","3596.25","3594.96","3596.25","3595.22","41.79263170",79],[1733129340,"3598.87","3601.53","3596.58","3601.53","3598.79","238.83696986",133],[1733129400,"3602.20","3610.61","3602.20","3610.61","3607.15","11.61228815",139],[1733129460,"3610.61","3611.74","3610.61","3611.19","3611.18","3.03675656",8],[1733129520,"3611.72","3616.20","3611.72","3616.20","3614.26","1.61152422",16],[1733129580,"3615.96","3615.97","3612.66","3612.68","3615.95","13.72839043",10],[1733129640,"3611.99","3611.99","3605.99","3605.99","3609.16","5.20184042",24],[1733129700,"3606.23","3606.23","3600.98","3600.98","3601.34","2.32910909",10],[1733129760,"3600.99","3605.29","3600.99","3602.33","3604.44","0.58380018",9],[1733129820,"3603.80","3607.72","3602.92","3607.72","3605.80","0.26541052",13],[1733129880,"3606.72","3608.59","3606.72","3608.59","3607.63","0.02428547",5],[1733129940,"3609.88","3609.88","3603.72","3603.72","3605.87","13.43147167",16],[1733130000,"3603.09","3604.01","3603.09","3604.00","3603.92","0.75632114",17],[1733130060,"3605.52","3605.52","3600.98","3602.93","3603.99","14.23185854",11],[1733130120,"3602.93","3605.53","3602.93","3605.00","3604.99","50.27341454",13],[1733130180,"3601.15","3601.15","3597.53","3597.53","3599.79","1.93550813",16],[1733130240,"3595.20","3601.18","3595.16","3601.18","3597.82","2.55851025",9],[1733130300,"3604.03","3605.50","3599.99","3604.59","3601.39","26.41185905",43],[1733130360,"3604.60","3610.15","3604.60","3609.18","3606.55","4.71972179",39],[1733130420,"3608.71","3610.38","3607.13","3610.13","3609.60","5.40855792",16],[1733130480,"3609.68","3610.50","3609.17","3610.49","3609.99","22.81100000",18],[1733130540,"3610.50","3611.99","3609.00","3611.99","3609.87","5.01578959",23],[1733130600,"3612.00","3615.97","3612.00","3615.97","3613.37","1.04978444",15],[1733130660,"3615.96","3617.36","3615.96","3616.64","3616.56","2.86222876",19],[1733130720,"3616.64","3617.42","3616.64","3617.42","3616.65","5.33947426",9],[1733130780,"3617.42","3618.20","3617.42","3618.20","3618.15","2.40192282",8],[1733130840,"3618.21","3618.88","3617.42","3618.00","3617.99","4.98184189",15],[1733130900,"3617.43","3617.96","3617.43","3617.96","3617.88","3.50274759",7],[1733130960,"3618.01","3620.78","3618.01","3620.77","3619.93","11.00549042",19],[1733131020,"3620.48","3622.55","3619.72","3622.55","3622.47","31.18623163",22],[1733131080,"3621.32","3621.75","3620.13","3620.13","3621.74","7.60324709",3],[1733131140,"3617.43","3617.43","3610.00","3611.22","3616.68","14.61682114",19],[1733131200,"3611.51","3613.18","3611.51","3613.18","3611.69","0.29794013",5],[1733131260,"3613.19","3616.40","3613.19","3614.17","3615.34","2.59644480",10],[1733131320,"3614.07","3619.93","3614.07","3617.93","3619.35","1.40637852",12],[1733131380,"3617.93","3617.93","3616.43","3616.43","3616.63","1.51665826",9],[1733131440,"3616.42","3616.42","3614.01","3614.02","3614.99","1.72620677",7],[1733131500,"3614.02","3614.67","3614.02","3614.67","3614.36","0.94255210",8],[1733131560,"3614.68","3617.51","3614.68","3617.50","3617.02","1.82921928",13],[1733131620,"3617.51","3620.52","3617.51","3619.75","3619.63","2.54973340",16],[1733131680,"3617.83","3621.15","3617.82","3620.74","3619.34","6.05306604",10],[1733131740,"3620.74","3620.74","3617.83","3617.83","3619.01","0.37350089",6],[1733131800,"3617.82","3618.43","3617.82","3618.43","3617.98","30.14170862",11],[1733131860,"3619.53","3619.77","3618.87","3619.77","3619.25","0.28288380",4],[1733131920,"3620.20","3620.55","3617.82","3617.82","3618.12","2.87851444",11],[1733131980,"3617.83","3617.83","3617.01","3617.01","3617.27","0.92332023",5],[1733132040,"3617.01","3617.53","3617.01","3617.53","3617.45","10.26009079",9],[1733132100,"3617.84","3618.14","3617.00","3618.14","3617.02","27.30783008",9],[1733132160,"3617.01","3617.01","3617.00","3617.00","3617.00","2.00250000",3],[1733132220,"3617.00","3617.00","3614.42","3614.42","3615.49","0.38868964",8],[1733132280,"3614.43","3614.43","3611.40","3611.40","3611.66","13.85609338",11],[1733132340,"3611.67","3614.44","3611.67","3614.44","3613.83","2.80155594",11],[1733132400,"3614.44","3614.44","3614.44","3614.44","0.00","0.00000000",0],[1733132460,"3614.88","3615.07","3614.18","3614.19","3614.50","0.48846719",7],[1733132520,"3612.14","3612.14","3612.14","3612.14","3612.14","0.01383991",1],[1733132580,"3611.39","3611.39","3610.00","3610.00","3610.73","0.09575198",7],[1733132640,"3610.00","3610.00","3606.99","3607.00","3609.22","3.93631685",15],[1733132700,"3607.00","3607.39","3606.99","3607.38","3607.00","210.08668824",11],[1733132760,"3606.70","3609.49","3603.84","3609.49","3606.66","2.30678876",13],[1733132820,"3609.51","3611.51","3609.51","3611.50","3611.41","6.21114588",9],[1733132880,"3611.51","3612.65","3610.59","3612.65","3610.82","1.21540343",8],[1733132940,"3610.36","3611.02","3610.10","3611.02","3610.96","1.08384210",4],[1733133000,"3611.86","3613.98","3611.86","3613.98","3612.66","0.64394758",11],[1733133060,"3614.51","3615.09","3613.81","3615.09","3614.70","2.78657787",123],[1733133120,"3614.20","3614.59","3614.08","3614.59","3614.52","1.08382226",41],[1733133180,"3615.10","3616.83","3615.10","3616.83","3616.77","1.09919753",7],[1733133240,"3616.60","3616.63","3615.77","3616.63","3616.54","0.77118553",5],[1733133300,"3616.94","3619.24","3616.94","3619.24","3618.98","0.17636205",6],[1733133360,"3619.24","3623.91","3619.24","3623.00","3623.66","102.15727298",25],[1733133420,"3622.68","3622.68","3621.98","3621.98","3622.04","0.92094307",2],[1733133480,"3622.27","3622.27","3622.22","3622.22","3622.22","1.09151639",5],[1733133540,"3622.78","3622.89","3622.55","3622.55","3622.76","2.18459831",6],[1733133600,"3622.46","3622.74","3622.00","3622.01","3622.58","0.35274157",7],[1733133660,"3622.00","3622.00","3617.66","3617.66","3621.82","22.77744416",6],[1733133720,"3617.85","3617.85","3616.92","3616.92","3617.52","57.52949814",4],[1733133780,"3615.81","3615.81","3615.80","3615.80","3615.80","2.46610797",7],[1733133840,"3615.80","3615.80","3612.38","3612.54","3615.68","4.47041513",13],[1733133900,"3612.44","3612.44","3608.92","3610.09","3609.94","2.90529257",41],[1733133960,"3610.09","3611.00","3610.09","3611.00","3610.09","5.62429450",118],[1733134020,"3610.46","3610.46","3609.22","3609.98","3610.02","0.38191171",6],[1733134080,"3610.20","3610.20","3605.22","3605.22","3607.96","301.10130669",71],[1733134140,"3605.21","3605.94","3603.56","3603.57","3604.73","7.18149557",23],[1733134200,"3604.92","3605.50","3604.25","3604.25","3604.89","5.78195835",40],[1733134260,"3604.42","3604.43","3603.45","3604.42","3604.37","1.13448084",4],[1733134320,"3603.90","3605.06","3603.90","3605.06","3604.44","3.83588948",9],[1733134380,"3603.94","3603.94","3600.00","3600.00","3602.71","2.25265487",10],[1733134440,"3600.00","3601.57","3600.00","3601.57","3600.70","4.59844578",12],[1733134500,"3602.89","3602.89","3601.85","3601.85","3602.52","0.59913148",5],[1733134560,"3601.85","3601.85","3600.02","3601.56","3601.43","2.23367055",9],[1733134620,"3600.67","3601.18","3600.02","3600.02","3600.29","1.35652925",7],[1733134680,"3598.05","3602.15","3598.05","3601.06","3600.42","7.15700259",26],[1733134740,"3600.67","3600.67","3596.87","3597.28","3597.11","1.93341720",6],[1733134800,"3597.08","3602.54","3597.08","3602.32","3601.26","6.27894183",17],[1733134860,"3602.32","3603.18","3602.06","3603.17","3602.29","0.77114537",5],[1733134920,"3602.01","3603.04","3602.01","3603.04","3602.38","0.74557312",5],[1733134980,"3603.03","3603.03","3597.10","3597.10","3602.49","8.67942937",11],[1733135040,"3596.63","3596.63","3596.63","3596.63","3596.63","0.05319335",1],[1733135100,"3596.16","3598.38","3596.08","3598.38","3596.47","1.56872129",10],[1733135160,"3598.39","3598.87","3596.09","3596.09","3598.61","125.93921170",15],[1733135220,"3598.26","3599.23","3598.26","3599.23","3598.69","0.01273734",2],[1733135280,"3597.99","3597.99","3596.27","3596.27","3597.27","0.29083220",10],[1733135340,"3596.45","3596.45","3596.45","3596.45","3596.45","2.75972155",1],[1733135400,"3596.34","3596.41","3593.15","3593.15","3596.05","9.56149538",26],[1733135460,"3593.15","3593.15","3592.86","3592.86","3593.08","0.10134421",5],[1733135520,"3593.13","3593.13","3593.13","3593.13","3593.13","0.32831015",4],[1733135580,"3592.86","3592.86","3590.80","3590.80","3591.08","1.90036903",9],[1733135640,"3590.84","3593.14","3590.84","3591.49","3591.47","0.95000331",8],[1733135700,"3590.84","3590.84","3588.00","3588.15","3589.06","9.53007922",22],[1733135760,"3588.14","3588.30","3588.14","3588.14","3588.14","8.13890561",7],[1733135820,"3588.15","3588.15","3575.70","3575.71","3584.39","48.98068001",120],[1733135880,"3575.71","3585.94","3575.71","3585.94","3577.20","14.82050285",16],[1733135940,"3585.94","3585.94","3580.99","3580.99","3582.43","1.46245360",11],[1733136000,"3580.21","3580.51","3577.90","3577.90","3578.16","1.72666804",7],[1733136060,"3581.56","3584.92","3581.22","3581.55","3581.62","5.83620182",28],[1733136120,"3581.55","3583.55","3580.60","3580.60","3581.71","0.27866291",6],[1733136180,"3581.64","3581.88","3579.90","3579.90","3580.08","1.91581344",10],[1733136240,"3581.24","3581.24","3578.41","3578.48","3579.90","0.26635600",4],[1733136300,"3575.70","3575.71","3575.70","3575.71","3575.70","0.21539158",2],[1733136360,"3575.94","3575.94","3575.09","3575.09","3575.45","1.41015813",8],[1733136420,"3575.09","3582.07","3575.08","3582.07","3575.14","17.67700831",6],[1733136480,"3582.08","3584.06","3582.08","3583.36","3582.86","9.31321675",7],[1733136540,"3584.44","3588.13","3584.44","3587.79","3586.03","3.10441274",11],[1733136600,"3588.01","3588.52","3588.01","3588.38","3588.47","0.48659484",6],[1733136660,"3588.01","3589.79","3588.01","3588.86","3588.41","1.62832987",13],[1733136720,"3588.00","3588.00","3584.06","3584.06","3584.15","13.00802163",6],[1733136780,"3580.83","3580.83","3577.29","3578.37","3577.56","0.06904541",7],[1733136840,"3577.53","3580.71","3577.45","3580.66","3578.83","0.60196197",9],[1733136900,"3580.84","3582.00","3576.31","3576.79","3578.16","6.78134200",20],[1733136960,"3576.78","3576.78","3576.00","3576.44","3576.73","2.14811146",6],[1733137020,"3576.79","3576.79","3576.00","3576.00","3576.62","1.43180308",7],[1733137080,"3575.01","3575.51","3575.00","3575.51","3575.10","0.40618325",5],[1733137140,"3575.00","3577.81","3575.00","3577.81","3575.61","4.83289969",15],[1733137200,"3577.81","3580.00","3576.41","3578.13","3577.48","68.35292801",25],[1733137260,"3577.00","3577.62","3577.00","3577.62","3577.14","0.44674963",5],[1733137320,"3580.00","3583.32","3579.25","3583.32","3581.79","48.58071063",41],[1733137380,"3583.91","3585.34","3580.60","3580.60","3582.63","3.66170989",13],[1733137440,"3576.66","3580.03","3576.66","3580.03","3576.69","25.89602674",77],[1733137500,"3580.61","3581.39","3580.61","3581.39","3580.63","0.30201448",4],[1733137560,"3581.39","3585.94","3581.39","3585.94","3585.61","2.16222438",13],[1733137620,"3585.26","3585.84","3583.94","3585.84","3585.79","1.04602848",4],[1733137680,"3582.68","3582.68","3577.17","3577.17","3580.62","41.40833209",13],[1733137740,"3578.40","3578.40","3575.36","3575.36","3576.30","4.98414658",11],[1733137800,"3576.37","3576.37","3575.00","3575.00","3575.48","0.53160000",6],[1733137860,"3575.01","3575.01","3570.02","3571.95","3571.10","82.44404834",69],[1733137920,"3571.95","3579.43","3571.95","3579.43","3576.09","5.50549027",31],[1733137980,"3579.43","3579.96","3579.43","3579.96","3579.95","0.36702237",3],[1733138040,"3579.97","3582.47","3579.97","3582.47","3580.14","1.69087648",8],[1733138100,"3582.47","3587.22","3582.47","3587.22","3584.78","10.22446184",24],[1733138160,"3587.23","3587.75","3587.23","3587.74","3587.73","8.22127188",7],[1733138220,"3587.75","3589.62","3587.75","3588.70","3588.79","1.91356156",11],[1733138280,"3589.68","3590.47","3588.62","3588.83","3589.59","2.42700952",14],[1733138340,"3588.61","3588.61","3586.18","3587.30","3586.93","16.24343347",7],[1733138400,"3587.32","3591.94","3587.32","3591.94","3588.47","0.15103536",8],[1733138460,"3592.24","3595.65","3592.24","3595.65","3593.29","0.60475566",8],[1733138520,"3596.04","3596.04","3595.55","3595.74","3595.79","0.75365739",5],[1733138580,"3595.52","3595.52","3592.01","3592.01","3592.63","3.29673235",6],[1733138640,"3592.00","3592.46","3591.45","3592.46","3591.88","2.18470226",5],[1733138700,"3591.50","3593.52","3591.50","3593.52","3592.22","1.41863868",3],[1733138760,"3593.53","3593.53","3593.53","3593.53","3593.53","0.00819017",1],[1733138820,"3593.97","3593.97","3592.90","3592.95","3593.91","2.22370389",5],[1733138880,"3593.11","3596.76","3593.11","3596.76","3596.33","4.69030120",9],[1733138940,"3596.97","3596.98","3596.97","3596.98","3596.97","0.07833327",4],[1733139000,"3596.98","3596.98","3594.79","3594.79","3596.96","5.84922316",7],[1733139060,"3595.23","3595.23","3594.74","3594.74","3594.94","4.83866479",4],[1733139120,"3596.40","3596.76","3596.40","3596.41","3596.52","1.70232986",4],[1733139180,"3596.40","3596.40","3593.05","3595.20","3594.72","2.85486733",8],[1733139240,"3595.67","3595.67","3594.92","3594.92","3595.48","0.05248173",2],[1733139300,"3591.30","3591.31","3591.30","3591.31","3591.30","0.04527910",2],[1733139360,"3591.13","3593.67","3591.13","3593.67","3591.47","0.26038571",3],[1733139420,"3592.32","3592.32","3592.32","3592.32","3592.32","9.99670087",4],[1733139480,"3592.13","3592.60","3590.59","3592.28","3590.96","1.16339289",6],[1733139540,"3592.28","3592.28","3592.28","3592.28","0.00","0.00000000",0],[1733139600,"3590.59","3590.59","3590.59","3590.59","3590.59","0.02485976",2],[1733139660,"3590.59","3590.59","3590.59","3590.59","3590.59","0.25000000",2],[1733139720,"3590.58","3592.01","3590.58","3592.01","3591.38","6.76081672",15],[1733139780,"3592.51","3592.51","3592.51","3592.51","3592.51","0.01999994",1],[1733139840,"3592.01","3592.01","3591.10","3591.25","3591.64","6.86044104",7],[1733139900,"3591.25","3591.25","3590.00","3590.00","3590.11","4.56371700",6],[1733139960,"3587.76","3590.33","3587.76","3589.94","3589.16","0.35176310",6],[1733140020,"3588.60","3588.60","3587.67","3587.67","3587.96","0.17593638",4],[1733140080,"3585.01","3585.01","3581.72","3581.72","3584.64","0.26279882",4],[1733140140,"3581.70","3582.88","3581.37","3582.88","3581.89","0.86044551",6],[1733140200,"3581.36","3581.75","3580.23","3581.45","3581.42","0.68409098",9],[1733140260,"3581.48","3581.98","3580.99","3580.99","3581.10","1.40470161",9],[1733140320,"3581.99","3585.00","3581.99","3582.76","3583.97","5.00451258",13],[1733140380,"3582.16","3584.08","3581.95","3581.99","3582.63","44.35087545",10],[1733140440,"3580.27","3580.27","3580.27","3580.27","3580.27","0.03349313",1],[1733140500,"3581.30","3584.99","3581.30","3584.99","3581.92","0.12100210",8],[1733140560,"3585.00","3586.35","3585.00","3586.35","3585.13","0.56934677",8],[1733140620,"3591.24","3594.01","3591.24","3594.01","3593.61","0.19635472",10],[1733140680,"3592.01","3592.01","3591.25","3591.25","3591.94","0.20729535",4]],"last":1733140620}}"#; -pub(crate) const BITFINEX_RESPONSES: &[(&str, &[u8])] = - &[("USTUSD", BITFINEX_USDT_CORRECT), ("UDCUSD", BITFINEX_USDC_CORRECT), ("DOTUSD", BITFINEX_DOT_CORRECT), ("ETHUSD", BITFINEX_ETH_CORRECT)]; +pub(crate) const BITFINEX_RESPONSES: &[(&str, &[u8])] = &[ + ("USTUSD", BITFINEX_USDT_CORRECT), + ("UDCUSD", BITFINEX_USDC_CORRECT), + ("DOTUSD", BITFINEX_DOT_CORRECT), + ("ETHUSD", BITFINEX_ETH_CORRECT), +]; const BITFINEX_USDT_CORRECT: &[u8] = br#"[[1701878700000,1.0005,1.0006,1.0006,1.0005,338.36072124],[1701878640000,1.0007,1.0005,1.0007,1.0005,63517.500237629996],[1701878580000,1.0007,1.0006,1.0007,1.0006,2007.06330507],[1701878520000,1.0007,1.0007,1.0007,1.0006,9546.62273159],[1701878460000,1.0008,1.0007,1.0008,1.0006,132234.98119663],[1701878400000,1.0008,1.0007,1.0008,1.0007,10224.08007082],[1701878340000,1.0008,1.0008,1.0008,1.0007,8716.53280425],[1701878280000,1.0008,1.0008,1.0008,1.0007,37436.46172385],[1701878220000,1.0007,1.0008,1.0008,1.0007,13436.41180859],[1701878160000,1.0008,1.0007,1.0008,1.0007,17947.59874696],[1701878100000,1.0008,1.0008,1.0008,1.0008,8238.112989],[1701878040000,1.0007,1.0008,1.0008,1.0007,4367.83340022],[1701877980000,1.0007,1.0007,1.0008,1.0007,2848.19766728],[1701877920000,1.0008,1.0008,1.0009,1.0008,171039.30620532],[1701877860000,1.0008,1.0008,1.0008,1.0007,184640.26643653]]"#; const BITFINEX_USDC_CORRECT: &[u8] = br#"[[1701878160000,1.0008,1.0008,1.0008,1.0008,119.85145068],[1701877020000,1.0004,1.0004,1.0004,1.0004,9637.55201485],[1701876660000,1.0005,0.99958,1.0005,0.99958,79514.655813],[1701876480000,1.0006,1.0006,1.0006,1.0006,17539.09],[1701876420000,1.0006,1.0006,1.0006,1.0006,2448.91],[1701876300000,1.0005,1.0005,1.0005,1.0005,144.71014286],[1701875940000,1.0002,1.0002,1.0002,1.0002,692.470892],[1701875700000,1.0002,1.0001,1.0002,1.0001,21000],[1701874920000,1,1,1,1,82.43673123],[1701874020000,1,0.99993,1,0.99993,10990],[1701873840000,1.0003,1.0003,1.0003,1.0003,154.23081876],[1701869880000,1.0003,1.0003,1.0003,1.0003,93.78810427],[1701869220000,1.0003,1.0003,1.0003,1.0003,182.41150567],[1701866580000,0.99988,0.99988,0.99988,0.99988,80.20076041],[1701866040000,0.99982,0.99982,0.99982,0.99982,5000]]"#; const BITFINEX_DOT_CORRECT: &[u8] = br#"[[1701878460000,6.1441,6.144,6.1441,6.144,8.4],[1701878400000,6.1377,6.1405,6.1405,6.1377,77.36041884],[1701878220000,6.1239,6.1239,6.1239,6.1239,5],[1701878160000,6.1546,6.1546,6.1546,6.1546,72.54925],[1701878100000,6.1574,6.1586,6.1586,6.1574,534.96073475],[1701878040000,6.1602,6.1602,6.1602,6.1602,26.5],[1701877920000,6.1454,6.1454,6.1454,6.1454,3.5],[1701877860000,6.1401,6.1401,6.1401,6.1401,59.49967],[1701877680000,6.118,6.118,6.118,6.118,0.5],[1701877620000,6.1416,6.1416,6.1416,6.1416,72.75138],[1701877020000,6.125,6.125,6.125,6.125,72.89985],[1701876900000,6.1426,6.1426,6.1426,6.1426,33.46011493],[1701876720000,6.1207,6.1207,6.1207,6.1207,4.5],[1701876540000,6.1033,6.1033,6.1033,6.1033,3.9],[1701876480000,6.1098,6.1067,6.1098,6.1067,53]]"#; const BITFINEX_ETH_CORRECT: &[u8] = br#"[[1733146260000,3619.8,3615.2,3619.8,3614.3,3.6731362400000003],[1733146200000,3617,3619.1,3619.1,3616.7,2.64361877],[1733146140000,3619.7,3618.8,3619.9,3618.7,5.87317269],[1733146080000,3619.3,3619.6,3619.6,3617.8,0.69071781],[1733146020000,3619,3618.6,3619.5,3617.2,8.14588395],[1733145960000,3617.8,3619.5,3619.7,3617.3,2.87764637],[1733145900000,3614.7,3617.6,3617.6,3614.7,1.91300089],[1733145840000,3616.8,3613.3,3616.8,3613.2,4.48436704],[1733145780000,3616.2,3616.8,3619,3614.8,9.13522865],[1733145720000,3614.3,3616.4,3616.7,3614.3,2.7752301200000002],[1733145660000,3613.2,3615.1,3615.1,3613.2,3.57605956],[1733145600000,3613.4,3612.8,3613.4,3612.3,1.17649605],[1733145540000,3614.3,3614.7,3615.8,3614.3,0.8682064899999999],[1733145480000,3615.6,3614.8,3616.7,3614.7,1.69914594],[1733145420000,3616.4,3615.5,3616.4,3615.5,0.9208798]]"#; -pub(crate) const BITSTAMP_RESPONSES: &[(&str, &[u8])] = - &[("usdtusd", BITSTAMP_USDT_CORRECT), ("usdcusd", BITSTAMP_USDC_CORRECT), ("dotusd", BITSTAMP_DOT_CORRECT), ("ethusd", BITSTAMP_ETH_CORRECT)]; +pub(crate) const BITSTAMP_RESPONSES: &[(&str, &[u8])] = &[ + ("usdtusd", BITSTAMP_USDT_CORRECT), + ("usdcusd", BITSTAMP_USDC_CORRECT), + ("dotusd", BITSTAMP_DOT_CORRECT), + ("ethusd", BITSTAMP_ETH_CORRECT), +]; const BITSTAMP_USDT_CORRECT: &[u8] = br#"{"data": {"ohlc": [{"close": "1.00010", "high": "1.00010", "low": "1.00010", "open": "1.00010", "timestamp": "1701877320", "volume": "44595.11593"}, {"close": "1.00008", "high": "1.00012", "low": "1.00008", "open": "1.00012", "timestamp": "1701877380", "volume": "4919.14926"}, {"close": "1.00008", "high": "1.00008", "low": "1.00008", "open": "1.00008", "timestamp": "1701877440", "volume": "4211.12929"}, {"close": "1.00009", "high": "1.00009", "low": "1.00009", "open": "1.00009", "timestamp": "1701877500", "volume": "4166.66667"}, {"close": "1.00010", "high": "1.00010", "low": "1.00010", "open": "1.00010", "timestamp": "1701877560", "volume": "4166.66667"}, {"close": "1.00011", "high": "1.00011", "low": "1.00009", "open": "1.00009", "timestamp": "1701877620", "volume": "4217.35212"}, {"close": "1.00011", "high": "1.00011", "low": "1.00011", "open": "1.00011", "timestamp": "1701877680", "volume": "4166.66667"}, {"close": "1.00011", "high": "1.00011", "low": "1.00011", "open": "1.00011", "timestamp": "1701877740", "volume": "4166.66667"}, {"close": "1.00010", "high": "1.00010", "low": "1.00010", "open": "1.00010", "timestamp": "1701877800", "volume": "4166.66666"}, {"close": "1.00009", "high": "1.00009", "low": "1.00008", "open": "1.00008", "timestamp": "1701877860", "volume": "4443.33076"}, {"close": "1.00009", "high": "1.00010", "low": "1.00008", "open": "1.00010", "timestamp": "1701877920", "volume": "4191.94439"}, {"close": "1.00009", "high": "1.00009", "low": "1.00007", "open": "1.00007", "timestamp": "1701877980", "volume": "4166.66666"}, {"close": "1.00009", "high": "1.00009", "low": "1.00009", "open": "1.00009", "timestamp": "1701878040", "volume": "4340.19105"}, {"close": "1.00010", "high": "1.00010", "low": "1.00009", "open": "1.00009", "timestamp": "1701878100", "volume": "6293.29493"}, {"close": "1.00010", "high": "1.00010", "low": "1.00010", "open": "1.00010", "timestamp": "1701878160", "volume": "0.00000"}], "pair": "USDT/USD"}}"#; const BITSTAMP_USDC_CORRECT: &[u8] = br#"{"data": {"ohlc": [{"close": "1.00000", "high": "1.00000", "low": "1.00000", "open": "1.00000", "timestamp": "1701877380", "volume": "46.46040"}, {"close": "1.00001", "high": "1.00001", "low": "1.00001", "open": "1.00001", "timestamp": "1701877440", "volume": "87.71000"}, {"close": "1.00001", "high": "1.00001", "low": "1.00001", "open": "1.00001", "timestamp": "1701877500", "volume": "0.00000"}, {"close": "1.00001", "high": "1.00001", "low": "1.00001", "open": "1.00001", "timestamp": "1701877560", "volume": "0.00000"}, {"close": "1.00001", "high": "1.00001", "low": "1.00001", "open": "1.00001", "timestamp": "1701877620", "volume": "0.00000"}, {"close": "1.00001", "high": "1.00001", "low": "1.00001", "open": "1.00001", "timestamp": "1701877680", "volume": "0.00000"}, {"close": "1.00001", "high": "1.00001", "low": "1.00001", "open": "1.00001", "timestamp": "1701877740", "volume": "0.00000"}, {"close": "1.00001", "high": "1.00001", "low": "1.00001", "open": "1.00001", "timestamp": "1701877800", "volume": "0.00000"}, {"close": "1.00001", "high": "1.00001", "low": "1.00001", "open": "1.00001", "timestamp": "1701877860", "volume": "0.00000"}, {"close": "1.00001", "high": "1.00001", "low": "1.00001", "open": "1.00001", "timestamp": "1701877920", "volume": "0.00000"}, {"close": "1.00001", "high": "1.00001", "low": "1.00001", "open": "1.00001", "timestamp": "1701877980", "volume": "0.00000"}, {"close": "1.00001", "high": "1.00001", "low": "1.00001", "open": "1.00001", "timestamp": "1701878040", "volume": "0.00000"}, {"close": "1.00001", "high": "1.00001", "low": "1.00001", "open": "1.00001", "timestamp": "1701878100", "volume": "0.00000"}, {"close": "1.00001", "high": "1.00001", "low": "1.00001", "open": "1.00001", "timestamp": "1701878160", "volume": "0.00000"}, {"close": "1.00001", "high": "1.00001", "low": "1.00001", "open": "1.00001", "timestamp": "1701878220", "volume": "0.00000"}], "pair": "USDC/USD"}}"#; const BITSTAMP_DOT_CORRECT: &[u8] = br#"{"data": {"ohlc": [{"close": "6.075", "high": "6.075", "low": "6.075", "open": "6.075", "timestamp": "1701877440", "volume": "0.00"}, {"close": "6.075", "high": "6.075", "low": "6.075", "open": "6.075", "timestamp": "1701877500", "volume": "0.00"}, {"close": "6.075", "high": "6.075", "low": "6.075", "open": "6.075", "timestamp": "1701877560", "volume": "0.00"}, {"close": "6.075", "high": "6.075", "low": "6.075", "open": "6.075", "timestamp": "1701877620", "volume": "0.00"}, {"close": "6.075", "high": "6.075", "low": "6.075", "open": "6.075", "timestamp": "1701877680", "volume": "0.00"}, {"close": "6.075", "high": "6.075", "low": "6.075", "open": "6.075", "timestamp": "1701877740", "volume": "0.00"}, {"close": "6.075", "high": "6.075", "low": "6.075", "open": "6.075", "timestamp": "1701877800", "volume": "0.00"}, {"close": "6.075", "high": "6.075", "low": "6.075", "open": "6.075", "timestamp": "1701877860", "volume": "0.00"}, {"close": "6.075", "high": "6.075", "low": "6.075", "open": "6.075", "timestamp": "1701877920", "volume": "0.00"}, {"close": "6.075", "high": "6.075", "low": "6.075", "open": "6.075", "timestamp": "1701877980", "volume": "0.00"}, {"close": "6.075", "high": "6.075", "low": "6.075", "open": "6.075", "timestamp": "1701878040", "volume": "0.00"}, {"close": "6.075", "high": "6.075", "low": "6.075", "open": "6.075", "timestamp": "1701878100", "volume": "0.00"}, {"close": "6.075", "high": "6.075", "low": "6.075", "open": "6.075", "timestamp": "1701878160", "volume": "0.00"}, {"close": "6.075", "high": "6.075", "low": "6.075", "open": "6.075", "timestamp": "1701878220", "volume": "0.00"}, {"close": "6.075", "high": "6.075", "low": "6.075", "open": "6.075", "timestamp": "1701878280", "volume": "0.00"}], "pair": "DOT/USD"}}"#; diff --git a/pallets/proxy-bonding/Cargo.toml b/pallets/proxy-bonding/Cargo.toml index d43abb5be..2df9f4290 100644 --- a/pallets/proxy-bonding/Cargo.toml +++ b/pallets/proxy-bonding/Cargo.toml @@ -21,6 +21,7 @@ polimec-common.workspace = true parity-scale-codec.workspace = true scale-info.workspace = true serde = { workspace = true, features = ["derive"] } +xcm.workspace = true [dev-dependencies] sp-io.workspace = true diff --git a/pallets/proxy-bonding/src/functions.rs b/pallets/proxy-bonding/src/functions.rs index 08e37e66e..c45cd823f 100644 --- a/pallets/proxy-bonding/src/functions.rs +++ b/pallets/proxy-bonding/src/functions.rs @@ -25,7 +25,8 @@ impl Pallet { ) .ok_or(Error::::PriceNotAvailable)?; - let fee_asset_decimals = >>::decimals(fee_asset); + let fee_asset_decimals = + >>::decimals(fee_asset.clone()); let fee_token_price = >::get_decimals_aware_price(fee_asset, T::UsdDecimals::get(), fee_asset_decimals) .ok_or(Error::::PriceNotAvailable)?; @@ -56,7 +57,7 @@ impl Pallet { let bonding_account: AccountIdOf = Self::get_bonding_account(derivation_path); let existential_deposit = >::minimum_balance(); - let fee_in_fee_asset = Self::calculate_fee(bond_amount, fee_asset)?; + let fee_in_fee_asset = Self::calculate_fee(bond_amount, fee_asset.clone())?; // Pay the fee from the user to the bonding account. It awaits either a full transfer to the T::FeeRecipient, or a refund to each user T::FeeToken::transfer(fee_asset, &account, &bonding_account, fee_in_fee_asset, Preservation::Preserve)?; @@ -102,7 +103,7 @@ impl Pallet { fee_asset: AssetId, ) -> Result<(), DispatchError> { let bonding_account = Self::get_bonding_account(derivation_path); - let fee_in_fee_asset = Self::calculate_fee(bond_amount, fee_asset)?; + let fee_in_fee_asset = Self::calculate_fee(bond_amount, fee_asset.clone())?; // We know this fee token account is existing thanks to the provider reference of the ED of the native asset, so we can fully move all the funds. // FYI same cannot be said of the `account`. We assume they only hold the fee token so their fee asset balance must not go below the min_balance. diff --git a/pallets/proxy-bonding/src/lib.rs b/pallets/proxy-bonding/src/lib.rs index 7902f0d5f..4263e340a 100644 --- a/pallets/proxy-bonding/src/lib.rs +++ b/pallets/proxy-bonding/src/lib.rs @@ -42,7 +42,7 @@ pub mod pallet { use polimec_common::ProvideAssetPrice; use sp_runtime::{Perbill, TypeId}; - pub type AssetId = u32; + pub type AssetId = xcm::v4::prelude::Location; pub type BalanceOf = <::BondingToken as fungible::Inspect>>::Balance; pub type AccountIdOf = ::AccountId; pub type HoldReasonOf = <::BondingToken as fungible::InspectHold>>::Reason; @@ -84,7 +84,7 @@ pub mod pallet { type FeePercentage: Get; /// Method to get the price of an asset like USDT or PLMC. Likely to come from an oracle - type PriceProvider: ProvideAssetPrice; + type PriceProvider: ProvideAssetPrice; /// The account holding the tokens to be bonded. Normally the treasury #[pallet::constant] @@ -200,8 +200,14 @@ pub mod pallet { let release_type = Releases::::get(derivation_path, hold_reason).ok_or(Error::::ReleaseTypeNotSet)?; ensure!(release_type != ReleaseType::Refunded, Error::::FeeToRecipientDisallowed); - let fees_balance = T::FeeToken::balance(fee_asset, &bonding_account); - T::FeeToken::transfer(fee_asset, &bonding_account, &fee_recipient, fees_balance, Preservation::Expendable)?; + let fees_balance = T::FeeToken::balance(fee_asset.clone(), &bonding_account); + T::FeeToken::transfer( + fee_asset.clone(), + &bonding_account, + &fee_recipient, + fees_balance, + Preservation::Expendable, + )?; Self::deposit_event(Event::FeesTransferredToFeeRecipient { fee_asset, fee_amount: fees_balance }); diff --git a/pallets/proxy-bonding/src/mock.rs b/pallets/proxy-bonding/src/mock.rs index 05a70af86..8e74c70f6 100644 --- a/pallets/proxy-bonding/src/mock.rs +++ b/pallets/proxy-bonding/src/mock.rs @@ -11,15 +11,22 @@ use scale_info::TypeInfo; use serde::{Deserialize, Serialize}; use sp_runtime::{ app_crypto::sp_core::MaxEncodedLen, - traits::{parameter_types, ConstU32, ConstU64, ConstU8, Identity, IdentityLookup}, + traits::{parameter_types, ConstU64, ConstU8, Identity, IdentityLookup}, BuildStorage, FixedU128, Perbill, }; use std::{cell::RefCell, collections::BTreeMap}; +use xcm::{ + prelude::Parachain, + v4::{Location, Parent}, +}; + pub const NATIVE_DECIMALS: u8 = 10; pub const NATIVE_UNIT: u64 = 1 * 10u64.pow(NATIVE_DECIMALS as u32); pub const MILLI_NATIVE_UNIT: u64 = NATIVE_UNIT / 1_000; -pub const MOCK_FEE_ASSET_ID: u32 = 1337; +pub fn mock_fee_asset_id() -> Location { + (Parent, Parachain(0)).into() +} pub const MOCK_FEE_ASSET_DECIMALS: u8 = 6; pub const MOCK_FEE_ASSET_UNIT: u64 = 1 * 10u64.pow(MOCK_FEE_ASSET_DECIMALS as u32); @@ -71,9 +78,18 @@ impl pallet_balances::Config for TestRuntime { type RuntimeHoldReason = MockRuntimeHoldReason; } +pub struct PalletAssetsBenchmarkHelper; +impl pallet_assets::BenchmarkHelper for PalletAssetsBenchmarkHelper { + fn create_asset_id_parameter(id: u32) -> Location { + (Parent, Parachain(id)).into() + } +} #[derive_impl(pallet_assets::config_preludes::TestDefaultConfig)] impl pallet_assets::Config for TestRuntime { + type AssetId = Location; + type AssetIdParameter = Location; type Balance = ::Balance; + type BenchmarkHelper = PalletAssetsBenchmarkHelper; type CreateOrigin = AsEnsureOriginWithArg>; type Currency = Balances; type ForceOrigin = frame_system::EnsureRoot; @@ -109,23 +125,23 @@ parameter_types! { } thread_local! { - pub static PRICE_MAP: RefCell> = RefCell::new(BTreeMap::from_iter(vec![ - (3344, FixedU128::from_float(0.5f64)), // Native Token - (1337, FixedU128::from_float(1f64)), // Fee Asset + pub static PRICE_MAP: RefCell> = RefCell::new(BTreeMap::from_iter(vec![ + (Location::here(), FixedU128::from_float(0.5f64)), // Native Token + ((Parent, Parachain(0)).into(), FixedU128::from_float(1f64)), // Fee Asset ])); } pub struct ConstPriceProvider; impl ProvideAssetPrice for ConstPriceProvider { - type AssetId = u32; + type AssetId = Location; type Price = FixedU128; - fn get_price(asset_id: u32) -> Option { + fn get_price(asset_id: Location) -> Option { PRICE_MAP.with(|price_map| price_map.borrow().get(&asset_id).cloned()) } } impl ConstPriceProvider { - pub fn set_price(asset_id: u32, price: FixedU128) { + pub fn set_price(asset_id: Location, price: FixedU128) { PRICE_MAP.with(|price_map| { price_map.borrow_mut().insert(asset_id, price); }); @@ -155,10 +171,13 @@ impl VariantCount for MockRuntimeHoldReason { const VARIANT_COUNT: u32 = 2; } +parameter_types! { + pub HereLocationGetter: Location = Location::here(); +} impl crate::Config for TestRuntime { type BondingToken = Balances; type BondingTokenDecimals = ConstU8; - type BondingTokenId = ConstU32<3344>; + type BondingTokenId = HereLocationGetter; type FeePercentage = FeePercentage; type FeeRecipient = FeeRecipient; type FeeToken = Assets; @@ -176,9 +195,9 @@ pub fn new_test_ext() -> sp_io::TestExternalities { let mut storage = GenesisConfig::::default().build_storage().unwrap(); RuntimeGenesisConfig { assets: AssetsConfig { - assets: vec![(MOCK_FEE_ASSET_ID, 1, true, 100)], + assets: vec![(mock_fee_asset_id(), 1, true, 100)], metadata: vec![( - MOCK_FEE_ASSET_ID, + mock_fee_asset_id(), "Tether USD".to_string().into_bytes(), "USDT".to_string().into_bytes(), MOCK_FEE_ASSET_DECIMALS, diff --git a/pallets/proxy-bonding/src/tests.rs b/pallets/proxy-bonding/src/tests.rs index e704b2f4a..46df1a7ba 100644 --- a/pallets/proxy-bonding/src/tests.rs +++ b/pallets/proxy-bonding/src/tests.rs @@ -24,7 +24,7 @@ fn locked_outcome() { let expected_fee = 5 * MOCK_FEE_ASSET_UNIT; // User decides to pay the fee with asset 1337 - let fee_asset = MOCK_FEE_ASSET_ID; + let fee_asset = mock_fee_asset_id(); let hold_reason = MockRuntimeHoldReason::Reason; @@ -49,17 +49,17 @@ fn locked_outcome() { // ) // .unwrap(); // User should have enough fee tokens to pay the fee, but also some amount for the ED, which is defined above as `min_balance` - >::mint_into(fee_asset, &user, expected_fee + 100).unwrap(); + >::mint_into(fee_asset.clone(), &user, expected_fee + 100).unwrap(); // The user requests the proxy bond - ProxyBonding::bond_on_behalf_of(derivation_path, user, bond_amount, fee_asset, hold_reason).unwrap(); + ProxyBonding::bond_on_behalf_of(derivation_path, user, bond_amount, fee_asset.clone(), hold_reason).unwrap(); // The user has locked 100 native tokens on sub-account 0 let sub_account_0: AccountIdOf = RootId::get().into_sub_account_truncating(0); assert_eq!(>::balance(&treasury), ed); assert_eq!(>::balance_on_hold(&hold_reason, &sub_account_0), bond_amount); - assert_eq!(>::balance(fee_asset, &sub_account_0), expected_fee); - assert_eq!(>::balance(fee_asset, &user), 100); + assert_eq!(>::balance(fee_asset.clone(), &sub_account_0), expected_fee); + assert_eq!(>::balance(fee_asset.clone(), &user), 100); // Mark the release type as Locked, which sends the fee to the fee_recipient, and the bond to the treasury after the inner block number is passed ProxyBonding::set_release_type(derivation_path, hold_reason, ReleaseType::Locked(10)); @@ -72,7 +72,7 @@ fn locked_outcome() { RuntimeOrigin::signed(1), derivation_path, hold_reason, - fee_asset + fee_asset.clone() )); assert_eq!(>::balance(fee_asset, &fee_recipient), expected_fee); @@ -101,8 +101,7 @@ fn refunded_outcome() { let bond_amount = 200 * NATIVE_UNIT; let expected_fee = 5 * MOCK_FEE_ASSET_UNIT; - // User decides to pay the fee with asset 1337 - let fee_asset = MOCK_FEE_ASSET_ID; + let fee_asset = mock_fee_asset_id(); let hold_reason = MockRuntimeHoldReason::Reason; @@ -114,17 +113,17 @@ fn refunded_outcome() { >::set_balance(&fee_recipient, ed); // User should have enough fee tokens to pay the fee, but also some amount for the ED, which is defined above as `min_balance` - >::mint_into(fee_asset, &user, expected_fee + 100).unwrap(); + >::mint_into(fee_asset.clone(), &user, expected_fee + 100).unwrap(); // The user requests the proxy bond - ProxyBonding::bond_on_behalf_of(derivation_path, user, bond_amount, fee_asset, hold_reason).unwrap(); + ProxyBonding::bond_on_behalf_of(derivation_path, user, bond_amount, fee_asset.clone(), hold_reason).unwrap(); // The user has locked 100 native tokens on sub-account 0 let sub_account_0: AccountIdOf = RootId::get().into_sub_account_truncating(0); assert_eq!(>::balance(&treasury), ed); assert_eq!(>::balance_on_hold(&hold_reason, &sub_account_0), bond_amount); - assert_eq!(>::balance(fee_asset, &sub_account_0), expected_fee); - assert_eq!(>::balance(fee_asset, &user), 100); + assert_eq!(>::balance(fee_asset.clone(), &sub_account_0), expected_fee); + assert_eq!(>::balance(fee_asset.clone(), &user), 100); // Mark the release type as Refunded, which leaves the fee to subsequent `refund_fee` calls, and allows to send the bond immediately the treasury. ProxyBonding::set_release_type(derivation_path, hold_reason, ReleaseType::Refunded); @@ -136,11 +135,16 @@ fn refunded_outcome() { ),); assert_eq!(>::balance(&treasury), ed + bond_amount); assert_noop!( - ProxyBonding::transfer_fees_to_recipient(RuntimeOrigin::signed(1), derivation_path, hold_reason, fee_asset), + ProxyBonding::transfer_fees_to_recipient( + RuntimeOrigin::signed(1), + derivation_path, + hold_reason, + fee_asset.clone() + ), Error::::FeeToRecipientDisallowed ); - assert_ok!(ProxyBonding::refund_fee(derivation_path, &user, bond_amount, fee_asset)); + assert_ok!(ProxyBonding::refund_fee(derivation_path, &user, bond_amount, fee_asset.clone())); assert_eq!(>::balance(fee_asset, &user), 100 + expected_fee); }); } diff --git a/polimec-common/common/Cargo.toml b/polimec-common/common/Cargo.toml index d64c530ce..e68b62f4a 100644 --- a/polimec-common/common/Cargo.toml +++ b/polimec-common/common/Cargo.toml @@ -18,6 +18,7 @@ parity-scale-codec = { workspace = true, features = ["derive"] } scale-info = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] } jwt-compact = { workspace = true, features = ["ed25519-dalek"] } +variant_count = "1.1.0" frame-benchmarking = { workspace = true, optional = true } frame-support.workspace = true @@ -26,7 +27,7 @@ pallet-timestamp.workspace = true sp-std.workspace = true sp-runtime.workspace = true xcm.workspace = true - +hex-literal.workspace = true [features] default = [ "std" ] std = [ diff --git a/polimec-common/common/src/assets.rs b/polimec-common/common/src/assets.rs new file mode 100644 index 000000000..5a15a8f4e --- /dev/null +++ b/polimec-common/common/src/assets.rs @@ -0,0 +1,59 @@ +use serde::{Deserialize, Serialize}; +use xcm::{ + prelude::Parachain, + v4::prelude::{AccountKey20, Ethereum, GeneralIndex, GlobalConsensus, Location, PalletInstance}, +}; + +use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use sp_runtime::RuntimeDebug; +use variant_count::VariantCount; +extern crate alloc; +use alloc::{vec, vec::*}; + +#[derive( + VariantCount, + Clone, + Copy, + Encode, + Decode, + Eq, + PartialEq, + PartialOrd, + Ord, + RuntimeDebug, + TypeInfo, + MaxEncodedLen, + Serialize, + Deserialize, +)] +pub enum AcceptedFundingAsset { + #[codec(index = 0)] + USDT, + #[codec(index = 1)] + USDC, + #[codec(index = 2)] + DOT, + #[codec(index = 3)] + WETH, +} +impl AcceptedFundingAsset { + pub fn id(&self) -> Location { + match self { + AcceptedFundingAsset::USDT => Location::new(1, [Parachain(1000), PalletInstance(50), GeneralIndex(1984)]), + AcceptedFundingAsset::DOT => Location::parent(), + AcceptedFundingAsset::USDC => Location::new(1, [Parachain(1000), PalletInstance(50), GeneralIndex(1337)]), + AcceptedFundingAsset::WETH => Location::new( + 2, + [ + GlobalConsensus(Ethereum { chain_id: 1 }), + AccountKey20 { network: None, key: hex_literal::hex!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2") }, + ], + ), + } + } + + pub fn all_ids() -> Vec { + vec![Self::USDT.id(), Self::DOT.id(), Self::USDC.id(), Self::WETH.id()] + } +} diff --git a/polimec-common/common/src/lib.rs b/polimec-common/common/src/lib.rs index a86093a05..36e3a5eb2 100644 --- a/polimec-common/common/src/lib.rs +++ b/polimec-common/common/src/lib.rs @@ -24,6 +24,7 @@ use sp_runtime::{ use sp_std::prelude::*; pub use xcm::v4::{opaque::Xcm, Assets, Location, QueryId, SendError, SendResult, SendXcm, XcmHash}; +pub mod assets; pub mod credentials; /// A release schedule over a fungible. This allows a particular fungible to have release limits @@ -226,7 +227,6 @@ pub mod migration_types { pub const USD_DECIMALS: u8 = 6; pub const USD_UNIT: u128 = 10u128.pow(USD_DECIMALS as u32); pub const PLMC_DECIMALS: u8 = 10; -pub const PLMC_FOREIGN_ID: u32 = 3344; pub trait ProvideAssetPrice { type AssetId; diff --git a/runtimes/polimec/src/benchmark_helpers.rs b/runtimes/polimec/src/benchmark_helpers.rs index c4f812b95..32cd49849 100644 --- a/runtimes/polimec/src/benchmark_helpers.rs +++ b/runtimes/polimec/src/benchmark_helpers.rs @@ -2,9 +2,10 @@ extern crate alloc; use crate::{Oracle, Runtime, RuntimeOrigin}; use alloc::vec; -use pallet_funding::{traits::SetPrices, AcceptedFundingAsset}; -use polimec_common::PLMC_FOREIGN_ID; +use pallet_funding::traits::SetPrices; +use polimec_common::assets::AcceptedFundingAsset; use sp_runtime::{BoundedVec, FixedU128}; +use xcm::v4::Location; pub struct SetOraclePrices; impl SetPrices for SetOraclePrices { @@ -12,9 +13,9 @@ impl SetPrices for SetOraclePrices { let dot = (AcceptedFundingAsset::DOT.id(), FixedU128::from_rational(69, 1)); let usdc = (AcceptedFundingAsset::USDC.id(), FixedU128::from_rational(1, 1)); let usdt = (AcceptedFundingAsset::USDT.id(), FixedU128::from_rational(1, 1)); - let plmc = (PLMC_FOREIGN_ID, FixedU128::from_rational(840, 100)); + let plmc = (Location::here(), FixedU128::from_rational(840, 100)); - let values: BoundedVec<(u32, FixedU128), ::MaxFeedValues> = + let values: BoundedVec<(Location, FixedU128), ::MaxFeedValues> = vec![dot, usdc, usdt, plmc].try_into().expect("benchmarks can panic"); let alice: [u8; 32] = [ 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, diff --git a/runtimes/polimec/src/lib.rs b/runtimes/polimec/src/lib.rs index d01ab2430..4e1e11c61 100644 --- a/runtimes/polimec/src/lib.rs +++ b/runtimes/polimec/src/lib.rs @@ -21,7 +21,6 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); extern crate alloc; -use assets_common::fungible_conversion::{convert, convert_balance}; use core::ops::RangeInclusive; use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; @@ -43,16 +42,16 @@ use frame_system::{EnsureRoot, EnsureRootWithSuccess, EnsureSigned, EnsureSigned use pallet_aura::Authorities; use pallet_democracy::GetElectorate; use pallet_funding::{ - runtime_api::ProjectParticipationIds, types::AcceptedFundingAsset, BidInfoOf, ContributionInfoOf, DaysToBlocks, - EvaluationInfoOf, PriceProviderOf, ProjectDetailsOf, ProjectId, ProjectMetadataOf, + runtime_api::ProjectParticipationIds, BidInfoOf, ContributionInfoOf, DaysToBlocks, EvaluationInfoOf, + HereLocationGetter, PriceProviderOf, ProjectDetailsOf, ProjectId, ProjectMetadataOf, }; use parachains_common::{ impls::AssetsToBlockAuthor, message_queue::{NarrowOriginToSibling, ParaIdToSibling}, - AssetIdForTrustBackedAssets as AssetId, }; use parity_scale_codec::Encode; use polimec_common::{ + assets::AcceptedFundingAsset, credentials::{Did, EnsureInvestor, InvestorType}, ProvideAssetPrice, USD_UNIT, }; @@ -73,14 +72,7 @@ use sp_std::{cmp::Ordering, prelude::*}; use sp_version::RuntimeVersion; // XCM Imports -use xcm::{ - v3::{ - Junction::{GeneralIndex, PalletInstance, Parachain}, - Junctions::{Here, X3}, - MultiLocation, - }, - VersionedAssets, VersionedLocation, VersionedXcm, -}; +use xcm::{v3::MultiLocation, VersionedAssets, VersionedLocation, VersionedXcm}; use xcm_config::{PriceForSiblingParachainDelivery, XcmOriginToTransactDispatchOrigin}; use xcm_fee_payment_runtime_api::{ dry_run::{CallDryRunEffects, Error as XcmDryRunApiError, XcmDryRunEffects}, @@ -105,7 +97,11 @@ use alloc::string::String; use sp_core::crypto::Ss58Codec; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; -use xcm::VersionedAssetId; +use xcm::{ + v4::{Location}, + VersionedAssetId, +}; + #[cfg(feature = "runtime-benchmarks")] mod benchmark_helpers; mod custom_migrations; @@ -442,15 +438,23 @@ impl pallet_transaction_payment::Config for Runtime { pub type ForeignAssetsInstance = pallet_assets::Instance2; +#[cfg(feature = "runtime-benchmarks")] +pub struct PalletAssetsBenchmarkHelper; +#[cfg(feature = "runtime-benchmarks")] +impl pallet_assets::BenchmarkHelper for PalletAssetsBenchmarkHelper { + fn create_asset_id_parameter(id: u32) -> Location { + (Parent, Parachain(id)).into() + } +} impl pallet_assets::Config for Runtime { type ApprovalDeposit = ExistentialDeposit; type AssetAccountDeposit = AssetAccountDeposit; type AssetDeposit = AssetDeposit; - type AssetId = AssetId; - type AssetIdParameter = parity_scale_codec::Compact; + type AssetId = Location; + type AssetIdParameter = Location; type Balance = Balance; #[cfg(feature = "runtime-benchmarks")] - type BenchmarkHelper = (); + type BenchmarkHelper = PalletAssetsBenchmarkHelper; type CallbackHandle = (); // Only Root (aka Governance) can create a new asset. type CreateOrigin = AsEnsureOriginWithArg>; @@ -848,7 +852,7 @@ impl orml_oracle::Config for Runtime { type MaxHasDispatchedSize = MaxHasDispatchedSize; type Members = OracleProvidersMembership; type OnNewData = (); - type OracleKey = AssetId; + type OracleKey = Location; type OracleValue = Price; type RootOperatorAccountId = RootOperatorAccountId; type RuntimeEvent = RuntimeEvent; @@ -897,7 +901,7 @@ where use sp_runtime::traits::StaticLookup; // take the biggest period possible. let period = BlockHashCount::get().checked_next_power_of_two().map(|c| c / 2).unwrap_or(2) as u64; - log::warn!("Attempted call: {:?}", call); + let current_block = System::block_number() .saturated_into::() // The `System::block_number` is initialized with `n+1`, @@ -922,7 +926,6 @@ where frame_metadata_hash_extension::CheckMetadataHash::::new(true), #[cfg(not(feature = "metadata-hash"))] frame_metadata_hash_extension::CheckMetadataHash::::new(false), - ); let raw_payload = generic::SignedPayload::new(call, extra) .map_err(|e| { @@ -1006,8 +1009,8 @@ impl pallet_assets::Config for Runtime { type ApprovalDeposit = ExistentialDeposit; type AssetAccountDeposit = ZeroDeposit; type AssetDeposit = AssetDeposit; - type AssetId = AssetId; - type AssetIdParameter = parity_scale_codec::Compact; + type AssetId = u32; + type AssetIdParameter = parity_scale_codec::Compact; type Balance = Balance; #[cfg(feature = "runtime-benchmarks")] type BenchmarkHelper = (); @@ -1087,7 +1090,7 @@ impl pallet_funding::Config for Runtime { type OnSlash = Vesting; type PalletId = FundingPalletId; type Price = Price; - type PriceProvider = OraclePriceProvider; + type PriceProvider = OraclePriceProvider; type RemainderRoundDuration = RemainderRoundDuration; type RequiredMaxCapacity = RequiredMaxCapacity; type RequiredMaxMessageSize = RequiredMaxMessageSize; @@ -1103,7 +1106,7 @@ impl pallet_funding::Config for Runtime { type WeightInfo = weights::pallet_funding::WeightInfo; } -use polimec_common::{PLMC_DECIMALS, PLMC_FOREIGN_ID, USD_DECIMALS}; +use polimec_common::{PLMC_DECIMALS, USD_DECIMALS}; parameter_types! { // Fee is defined as 1.5% of the usd_amount. Since fee is applied to the plmc amount, and that is always 5 times @@ -1116,12 +1119,12 @@ parameter_types! { impl pallet_proxy_bonding::Config for Runtime { type BondingToken = Balances; type BondingTokenDecimals = ConstU8; - type BondingTokenId = ConstU32; + type BondingTokenId = HereLocationGetter; type FeePercentage = FeePercentage; type FeeRecipient = FeeRecipient; type FeeToken = ForeignAssets; type Id = PalletId; - type PriceProvider = OraclePriceProvider; + type PriceProvider = OraclePriceProvider; type RootId = TreasuryId; type RuntimeEvent = RuntimeEvent; type RuntimeHoldReason = RuntimeHoldReason; @@ -1168,28 +1171,16 @@ impl pallet_dispenser::Config for Runtime { type WeightInfo = weights::pallet_dispenser::WeightInfo; type WhitelistedPolicy = DispenserWhitelistedPolicy; } - -pub struct ConvertMultilocationToAssetId; -impl Convert for ConvertMultilocationToAssetId { - fn convert(location: MultiLocation) -> AssetId { - match location { - MultiLocation { parents: 1, interior: Here } => 10, - MultiLocation { parents: 1, interior: X3(Parachain(1000), PalletInstance(50), GeneralIndex(1337)) } => 1337, - MultiLocation { parents: 1, interior: X3(Parachain(1000), PalletInstance(50), GeneralIndex(1984)) } => 1984, - // Since the asset with `AssetId` 0 does not exist and has no price, it is invalid. - _ => 0, - } - } -} pub struct PLMCToFundingAssetBalance; -impl ConversionToAssetBalance for PLMCToFundingAssetBalance { +impl ConversionToAssetBalance for PLMCToFundingAssetBalance { type Error = InvalidTransaction; - fn to_asset_balance(plmc_balance: Balance, asset_id: AssetId) -> Result { + fn to_asset_balance(plmc_balance: Balance, asset_id: Location) -> Result { let plmc_price = - >::get_decimals_aware_price(PLMC_FOREIGN_ID, USD_DECIMALS, PLMC_DECIMALS) + >::get_decimals_aware_price(Location::here(), USD_DECIMALS, PLMC_DECIMALS) .ok_or(InvalidTransaction::Payment)?; - let funding_asset_decimals = >::decimals(asset_id); + let funding_asset_decimals = + >::decimals(asset_id.clone()); let funding_asset_price = >::get_decimals_aware_price(asset_id, USD_DECIMALS, funding_asset_decimals) .ok_or(InvalidTransaction::Payment)?; @@ -1203,7 +1194,6 @@ impl pallet_asset_tx_payment::Config for Runtime { type Fungibles = ForeignAssets; type OnChargeAssetTransaction = TxFeeFungiblesAdapter< PLMCToFundingAssetBalance, - ConvertMultilocationToAssetId, CreditFungiblesToAccount, AssetsToBlockAuthor, >; @@ -1325,29 +1315,30 @@ mod benches { impl_runtime_apis! { impl assets_common::runtime_api::FungiblesApi for Runtime{ fn query_account_balances(account: AccountId) -> Result { - Ok([ - // collect pallet_balance - { - let balance = Balances::balance(&account); - if balance > 0 { - vec![convert_balance::(balance)?] - } else { - vec![] - } - }, - // collect pallet_assets (ContributionTokens) - convert::<_, _, _, _, xcm_config::ContributionTokensConvertedConcreteId>( - ContributionTokens::account_balances(account.clone()) - .iter() - .filter(|(_, balance)| balance > &0) - )?, - // collect pallet_assets (ForeignAssets) - convert::<_, _, _, _, xcm_config::ForeignAssetsConvertedConcreteId>( - ForeignAssets::account_balances(account) - .iter() - .filter(|(_, balance)| balance > &0) - )?, - ].concat().into()) + // Ok([ + // // collect pallet_balance + // { + // let balance = Balances::balance(&account); + // if balance > 0 { + // vec![convert_balance::(balance)?] + // } else { + // vec![] + // } + // }, + // // collect pallet_assets (ContributionTokens) + // convert::<_, _, _, _, xcm_config::ContributionTokensConvertedConcreteId>( + // ContributionTokens::account_balances(account.clone()) + // .iter() + // .filter(|(_, balance)| balance > &0) + // )?, + // // collect pallet_assets (ForeignAssets) + // convert::<_, _, _, _, xcm_config::ForeignAssetsConvertedConcreteId>( + // ForeignAssets::account_balances(account) + // .iter() + // .filter(|(_, balance)| balance > &0) + // )?, + // ].concat().into()) + Ok(vec![].into()) } } @@ -1710,31 +1701,21 @@ impl_runtime_apis! { impl xcm_fee_payment_runtime_api::fees::XcmPaymentApi for Runtime { fn query_acceptable_payment_assets(xcm_version: xcm::Version) -> Result, XcmPaymentApiError> { - let acceptable_assets = vec![ - xcm_config::HereLocation::get().into(), - xcm_config::DOTLocation::get().into(), - xcm_config::USDTLocation::get().into(), - xcm_config::USDCLocation::get().into() - ]; + let mut acceptable_assets = AcceptedFundingAsset::all_ids(); + acceptable_assets.push(Location::here()); + let acceptable_assets = acceptable_assets.into_iter().map(|a| a.into()).collect::>(); PolkadotXcm::query_acceptable_payment_assets(xcm_version, acceptable_assets) } fn query_weight_to_asset_fee(weight: Weight, asset: VersionedAssetId) -> Result { - match xcm::v3::AssetId::try_from(asset) { - Ok(xcm::v3::AssetId::Concrete(multilocation)) if multilocation == MultiLocation::here() => { - // for native token - Ok(TransactionPayment::weight_to_fee(weight)) - }, - Ok(xcm::v3::AssetId::Concrete(multilocation)) => { - let native_fee = TransactionPayment::weight_to_fee(weight); - let converted_asset_id = ConvertMultilocationToAssetId::convert(multilocation); - PLMCToFundingAssetBalance::to_asset_balance(native_fee, converted_asset_id).map_err(|_| XcmPaymentApiError::AssetNotFound) - }, - _ => { - Err(XcmPaymentApiError::VersionedConversionFailed) - } + let location: Location = xcm::v4::AssetId::try_from(asset).map_err(|_| XcmPaymentApiError::VersionedConversionFailed)?.0; + let native_fee = TransactionPayment::weight_to_fee(weight); + if location == Location::here() { + return Ok(native_fee) } + PLMCToFundingAssetBalance::to_asset_balance(native_fee, location).map_err(|_| XcmPaymentApiError::AssetNotFound) + } fn query_xcm_weight(message: VersionedXcm<()>) -> Result { diff --git a/runtimes/polimec/src/xcm_config.rs b/runtimes/polimec/src/xcm_config.rs index 8be691602..10285bfc1 100644 --- a/runtimes/polimec/src/xcm_config.rs +++ b/runtimes/polimec/src/xcm_config.rs @@ -16,9 +16,9 @@ extern crate alloc; use super::{ - AccountId, AllPalletsWithSystem, AssetId as AssetIdPalletAssets, Balance, Balances, ContributionTokens, EnsureRoot, - ForeignAssets, Funding, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, - RuntimeOrigin, ToTreasury, TreasuryAccount, Vec, WeightToFee, + AccountId, AllPalletsWithSystem, Balance, Balances, ContributionTokens, EnsureRoot, ForeignAssets, Funding, + ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, ToTreasury, + TreasuryAccount, Vec, WeightToFee, }; use core::marker::PhantomData; use cumulus_primitives_core::ParaId; @@ -30,20 +30,13 @@ use frame_support::{ weights::Weight, }; use pallet_xcm::XcmPassthrough; +use polimec_common::assets::AcceptedFundingAsset; #[cfg(feature = "runtime-benchmarks")] use polimec_common_test_utils::DummyXcmSender; use polkadot_parachain_primitives::primitives::Sibling; use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery; -use sp_runtime::traits::MaybeEquivalence; use xcm::v4::prelude::*; -use xcm_builder::{ - AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, - AllowTopLevelPaidExecutionFrom, CreateMatcher, DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, - FixedRateOfFungible, FixedWeightBounds, FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter, IsConcrete, - MatchXcm, MatchedConvertedConcreteId, MintLocation, NoChecking, ParentIsPreset, RelayChainAsNative, - SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, -}; +use xcm_builder::{AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, CreateMatcher, DenyReserveTransferToRelayChain, DenyThenTry, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, FrameTransactionalProcessor, FungibleAdapter, FungiblesAdapter, IsConcrete, MatchXcm, MatchedConvertedConcreteId, MintLocation, NoChecking, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, StartsWith, StartsWithExplicitGlobalConsensus, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, WithComputedOrigin}; use xcm_executor::{ traits::{JustTry, Properties, ShouldExecute}, XcmExecutor, @@ -61,8 +54,6 @@ const USDT_PER_MB_PROOF: u128 = 1_000_000; // 1 USDT per Megabyte of proof size const USDC_PER_SECOND_EXECUTION: u128 = 1_000_000; // 1 USDC per second of execution time const USDC_PER_MB_PROOF: u128 = 1_000_000; // 1 USDC per Megabyte of proof size -pub const WETH_ADDRESS: [u8; 20] = hex_literal::hex!("c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"); - parameter_types! { pub const RelayLocation: Location = Location::parent(); pub const RelayNetwork: Option = None; @@ -71,6 +62,7 @@ parameter_types! { GlobalConsensus(Polkadot), Parachain(ParachainInfo::parachain_id().into()), ).into(); + pub UniversalLocationNetworkId: NetworkId = UniversalLocation::get().global_consensus().unwrap(); pub const HereLocation: Location = Location::here(); pub AssetHubLocation: Location = (Parent, Parachain(1000)).into(); pub CheckAccount: AccountId = PolkadotXcm::check_account(); @@ -83,33 +75,11 @@ parameter_types! { pub ContributionTokensPalletIndex: u8 = ::index() as u8; pub ContributionTokensPalletLocation: Location = PalletInstance(ContributionTokensPalletIndex::get()).into(); - pub DOTLocation: Location = Location::new(DOT_PARENTS, DOT_JUNCTIONS); - pub USDTLocation: Location = Location::new(USDT_PARENTS, USDT_JUNCTIONS); - pub USDCLocation: Location = Location::new(USDC_PARENTS, USDC_JUNCTIONS); - pub WETHLocation: Location = Location::new(WETH_PARENTS, WETH_JUNCTIONS); - - pub DotTraderParams: (AssetId, u128, u128) = (DOTLocation::get().into(), DOT_PER_SECOND_EXECUTION, DOT_PER_MB_PROOF); - pub UsdtTraderParams: (AssetId, u128, u128) = (USDTLocation::get().into(), USDT_PER_SECOND_EXECUTION, USDT_PER_MB_PROOF); - pub UsdcTraderParams: (AssetId, u128, u128) = (USDCLocation::get().into(), USDC_PER_SECOND_EXECUTION, USDC_PER_MB_PROOF); + pub DotTraderParams: (AssetId, u128, u128) = (AcceptedFundingAsset::DOT.id().into(), DOT_PER_SECOND_EXECUTION, DOT_PER_MB_PROOF); + pub UsdtTraderParams: (AssetId, u128, u128) = (AcceptedFundingAsset::USDT.id().into(), USDT_PER_SECOND_EXECUTION, USDT_PER_MB_PROOF); + pub UsdcTraderParams: (AssetId, u128, u128) = (AcceptedFundingAsset::USDC.id().into(), USDC_PER_SECOND_EXECUTION, USDC_PER_MB_PROOF); } -const DOT_PARENTS: u8 = 1; -const DOT_JUNCTIONS: [Junction; 0] = []; -const DOT_UNPACKED: (u8, &[Junction]) = (DOT_PARENTS, &DOT_JUNCTIONS); - -const USDT_PARENTS: u8 = 1; -const USDT_JUNCTIONS: [Junction; 3] = [Parachain(1000), PalletInstance(50), GeneralIndex(1984)]; -const USDT_UNPACKED: (u8, &[Junction]) = (USDT_PARENTS, &USDT_JUNCTIONS); - -const USDC_PARENTS: u8 = 1; -const USDC_JUNCTIONS: [Junction; 3] = [Parachain(1000), PalletInstance(50), GeneralIndex(1337)]; -const USDC_UNPACKED: (u8, &[Junction]) = (USDC_PARENTS, &USDC_JUNCTIONS); - -const WETH_PARENTS: u8 = 2; -const WETH_JUNCTIONS: [Junction; 2] = - [GlobalConsensus(Ethereum { chain_id: 1 }), AccountKey20 { network: None, key: WETH_ADDRESS }]; -const WETH_UNPACKED: (u8, &[Junction]) = (WETH_PARENTS, &WETH_JUNCTIONS); - /// Type for specifying how a `Location` can be converted into an `AccountId`. This is used /// when determining ownership of accounts for asset transacting and when attempting to use XCM /// `Transact` in order to determine the dispatch Origin. @@ -137,8 +107,20 @@ pub type FungibleTransactor = FungibleAdapter< >; /// `AssetId`/`Balance` converter for `ForeignAssets`. -pub type ForeignAssetsConvertedConcreteId = - assets_common::TrustBackedAssetsConvertedConcreteId; +pub type ForeignAssetsConvertedConcreteId = assets_common::ForeignAssetsConvertedConcreteId< + ( + // Ignore `TrustBackedAssets` explicitly + StartsWith, + // Ignore assets that start explicitly with our `GlobalConsensus(NetworkId)`, means: + // - foreign assets from our consensus should be: `Location {parents: 1, X*(Parachain(xyz), + // ..)}` + // - foreign assets outside our consensus with the same `GlobalConsensus(NetworkId)` won't + // be accepted here + StartsWithExplicitGlobalConsensus, + ), + Balance, + xcm::v4::Location, +>; /// `AssetId`/`Balance` converter for `ContributionTokens`. pub type ContributionTokensConvertedConcreteId = @@ -149,40 +131,18 @@ pub type ContributionTokensConvertedConcreteId = pub struct SupportedAssets; impl frame_support::traits::Contains for SupportedAssets { fn contains(l: &Location) -> bool { - let funding_assets = [DOTLocation::get(), USDTLocation::get(), USDCLocation::get(), WETHLocation::get()]; + let funding_assets = AcceptedFundingAsset::all_ids(); funding_assets.contains(l) } } -impl MaybeEquivalence for SupportedAssets { - fn convert(asset_id: &Location) -> Option { - match asset_id.unpack() { - DOT_UNPACKED => Some(10), - USDT_UNPACKED => Some(1984), - USDC_UNPACKED => Some(1337), - WETH_UNPACKED => Some(10_000), - _ => None, - } - } - - fn convert_back(asset_id: &AssetIdPalletAssets) -> Option { - match asset_id { - 10 => Some(DOTLocation::get()), - 1337 => Some(USDCLocation::get()), - 1984 => Some(USDTLocation::get()), - 10_000 => Some(WETHLocation::get()), - _ => None, - } - } -} - /// Foreign assets adapter for supporting assets from other chains. Currently the only /// supported assets are DOT, USDT, and USDC. pub type ForeignAssetsAdapter = FungiblesAdapter< // Use this fungibles implementation: ForeignAssets, // Use this currency when it is a fungible asset matching the given location or name: - MatchedConvertedConcreteId, + MatchedConvertedConcreteId, // Convert an XCM Location into a local account id: LocationToAccountId, // Our chain's account ID type (we can't get away without mentioning it explicitly): diff --git a/runtimes/shared-configuration/src/currency.rs b/runtimes/shared-configuration/src/currency.rs index 4d45defbf..3e5f56be5 100644 --- a/runtimes/shared-configuration/src/currency.rs +++ b/runtimes/shared-configuration/src/currency.rs @@ -16,11 +16,10 @@ use crate::Balance; use frame_support::parameter_types; -use pallet_funding::AcceptedFundingAsset; use pallet_oracle_ocw::types::AssetName; -use parachains_common::AssetIdForTrustBackedAssets as AssetId; -use polimec_common::PLMC_FOREIGN_ID; +use polimec_common::assets::AcceptedFundingAsset; use sp_runtime::{traits::Convert, FixedU128}; +use xcm::v4::Location; /// One PLMC pub const PLMC: Balance = 10u128.pow(10); @@ -83,13 +82,13 @@ pub type Price = FixedU128; pub type Moment = u64; pub struct AssetPriceConverter; -impl Convert<(AssetName, FixedU128), (AssetId, Price)> for AssetPriceConverter { - fn convert((asset, price): (AssetName, FixedU128)) -> (AssetId, Price) { +impl Convert<(AssetName, FixedU128), (Location, Price)> for AssetPriceConverter { + fn convert((asset, price): (AssetName, FixedU128)) -> (Location, Price) { match asset { AssetName::DOT => (AcceptedFundingAsset::DOT.id(), price), AssetName::USDC => (AcceptedFundingAsset::USDC.id(), price), AssetName::USDT => (AcceptedFundingAsset::USDT.id(), price), - AssetName::PLMC => (PLMC_FOREIGN_ID, price), + AssetName::PLMC => (Location::here(), price), AssetName::WETH => (AcceptedFundingAsset::WETH.id(), price), } } diff --git a/runtimes/shared-configuration/src/fee.rs b/runtimes/shared-configuration/src/fee.rs index 265afdd8f..aa80a8cef 100644 --- a/runtimes/shared-configuration/src/fee.rs +++ b/runtimes/shared-configuration/src/fee.rs @@ -15,10 +15,10 @@ // along with this program. If not, see . extern crate alloc; use crate::{currency::MILLI_PLMC, Balance, StakingPalletId}; -use core::{fmt::Debug, marker::PhantomData}; +use core::marker::PhantomData; use frame_support::{ ord_parameter_types, - pallet_prelude::{MaybeSerializeDeserialize, Weight}, + pallet_prelude::Weight, parameter_types, sp_runtime::traits::AccountIdConversion, traits::{ @@ -38,15 +38,14 @@ use frame_support::{ use pallet_asset_tx_payment::{HandleCredit, OnChargeAssetTransaction}; use pallet_transaction_payment::OnChargeTransaction; use parachains_common::{impls::AccountIdOf, AccountId, SLOT_DURATION}; -use parity_scale_codec::FullCodec; -use scale_info::{prelude::vec, TypeInfo}; +use scale_info::prelude::vec; use smallvec::smallvec; use sp_arithmetic::Perbill; use sp_runtime::{ - traits::{Convert, DispatchInfoOf, Get, One, PostDispatchInfoOf, Zero}, + traits::{DispatchInfoOf, Get, One, PostDispatchInfoOf, Zero}, transaction_validity::{InvalidTransaction, TransactionValidityError}, }; -use xcm::v3::MultiLocation; +use xcm::v4::Location; #[allow(clippy::module_name_repetitions)] pub struct WeightToFee; @@ -172,24 +171,23 @@ type AssetBalanceOf = /// [`ConversionToAssetBalance`]) and 2 credit handlers (implementing [`HandleCredit`]). /// /// First handler does the fee, second the tip. -pub struct TxFeeFungiblesAdapter( - PhantomData<(Converter, MultiLocationToAssetId, FeeCreditor, TipCreditor)>, +pub struct TxFeeFungiblesAdapter( + PhantomData<(Converter, FeeCreditor, TipCreditor)>, ); /// Default implementation for a runtime instantiating this pallet, a balance to asset converter and /// a credit handler. -impl OnChargeAssetTransaction - for TxFeeFungiblesAdapter +impl OnChargeAssetTransaction + for TxFeeFungiblesAdapter where Runtime: pallet_asset_tx_payment::Config, - MultiLocationToAssetId: Convert>, + Runtime::Fungibles: Inspect, AssetId = xcm::v4::Location>, Converter: ConversionToAssetBalance, AssetIdOf, AssetBalanceOf>, FeeCreditor: HandleCredit, TipCreditor: HandleCredit, - AssetIdOf: FullCodec + Copy + MaybeSerializeDeserialize + Debug + Default + Eq + TypeInfo, { // Note: We stick to `v3::MultiLocation`` because `v4::Location`` doesn't implement `Copy`. - type AssetId = MultiLocation; + type AssetId = xcm::v3::MultiLocation; type Balance = BalanceOf; type LiquidityInfo = fungibles::Credit; @@ -205,13 +203,14 @@ where // We don't know the precision of the underlying asset. Because the converted fee could be // less than one (e.g. 0.5) but gets rounded down by integer division we introduce a minimum // fee. - let asset_id = MultiLocationToAssetId::convert(asset_id); + let asset_id: Location = + asset_id.try_into().map_err(|_| TransactionValidityError::Invalid(InvalidTransaction::Payment))?; let min_converted_fee = if fee.is_zero() { Zero::zero() } else { One::one() }; - let converted_fee = Converter::to_asset_balance(fee, asset_id) + let converted_fee = Converter::to_asset_balance(fee, asset_id.clone()) .map_err(|_| TransactionValidityError::from(InvalidTransaction::Payment))? .max(min_converted_fee); let can_withdraw = - >::can_withdraw(asset_id, who, converted_fee); + >::can_withdraw(asset_id.clone(), who, converted_fee); if can_withdraw != WithdrawConsequence::Success { return Err(InvalidTransaction::Payment.into()) } diff --git a/runtimes/shared-configuration/src/funding.rs b/runtimes/shared-configuration/src/funding.rs index 8d8d9e827..58713141f 100644 --- a/runtimes/shared-configuration/src/funding.rs +++ b/runtimes/shared-configuration/src/funding.rs @@ -16,12 +16,11 @@ use crate::{Balance, BlockNumber}; use frame_support::{parameter_types, PalletId}; -use pallet_funding::types::AcceptedFundingAsset; -use parachains_common::AssetIdForTrustBackedAssets; -use polimec_common::{PLMC_FOREIGN_ID, USD_UNIT}; +use polimec_common::{assets::AcceptedFundingAsset, USD_UNIT}; use sp_arithmetic::{FixedU128, Percent}; use sp_runtime::Perquintill; use sp_std::{collections::btree_map::BTreeMap, vec, vec::Vec}; +use xcm::v4::Location; #[cfg(feature = "instant-mode")] pub const EVALUATION_ROUND_DURATION: BlockNumber = 7; @@ -59,11 +58,11 @@ parameter_types! { pub const CommunityRoundDuration: BlockNumber = COMMUNITY_ROUND_DURATION; pub const RemainderRoundDuration: BlockNumber = REMAINDER_ROUND_DURATION; pub const FundingPalletId: PalletId = PalletId(*b"plmc/fun"); - pub PriceMap: BTreeMap = BTreeMap::from_iter(vec![ + pub PriceMap: BTreeMap = BTreeMap::from_iter(vec![ (AcceptedFundingAsset::DOT.id(), FixedU128::from_rational(69, 1)), // DOT (AcceptedFundingAsset::USDC.id(), FixedU128::from_rational(100, 100)), // USDC (AcceptedFundingAsset::USDT.id(), FixedU128::from_rational(100, 100)), // USDT - (PLMC_FOREIGN_ID, FixedU128::from_rational(840, 100)), // PLMC + (Location::here(), FixedU128::from_rational(840, 100)), // PLMC ]); pub FeeBrackets: Vec<(Percent, Balance)> = vec![ (Percent::from_percent(10), 1_000_000 * USD_UNIT),