Asset Conversion release to westmint (#2148)

* Dex and payment by dex in westmint

* Wrap U256 type for now

(to support required traits.)

* cargo fmt

* We can now use U256

* Rename PromotedBalance

* name change

* Updating the code to master.

TODO: handle dust!

* cargo fmt

* Minimising changes and step towards getting benchmarks compiling

(still a From<u32> bound in the pallet)

* minimise diff

* Update parachains/runtimes/assets/westmint/src/lib.rs

Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com>

* Update parachains/runtimes/assets/westmint/src/lib.rs

Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com>

* Update parachains/common/src/impls.rs

Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com>

* Fix benchmark build

* Add in AssetConversionAPI

* Handle dust

* cargo fmt

* Don't need to be explicit that it's AccountId32

* remove pool setup fee

(Asset deposit fees are a sufficient anti-spam measure)

* More natural way to specify native

* cargo fmt

* Update parachains/runtimes/assets/westmint/src/lib.rs

* Additional required impls

* either form of multilocation should be acceptable.

* add call filter exclusion

* Fix typo & try_convert now fails if native is converted

* merge master fixup

* Fix: HoldReason should be there.

* Box MultiAssetId

Otherwise it blows out the Call enum memory size.

* cargo fmt

* update lock file

* add std feature, update lock file

* need to turn on std on common

* adding in westmint tests

* WeightToFee must be from the destination chain.

* cargo fmt

* account for higher ED on westmint

* type removed as not used

* cargo fmt

* remove unused import

* minimising diff

* import needed only with feature enabled

* use multilocation contains

* move the impls to separate file

* simplify on conversion

* simplify on reverse conversion also.

* rename var

* clippy

* removed dead code

* cargo fmt

* Use pay by swap

* review suggestions

* cargo fmt

* Update parachains/runtimes/assets/asset-hub-westend/src/lib.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* add benchmarks for new assets pallet

* revert common/src changes

* need a concrete id

* more fixes

* lock

---------

Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com>
Co-authored-by: joepetrowski <joe@parity.io>
Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
This commit is contained in:
Squirrel
2023-06-23 21:31:50 +01:00
committed by GitHub
parent eb76e109c8
commit 5487ce7687
18 changed files with 1719 additions and 243 deletions
+245 -194
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -11,6 +11,7 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"], default-features = false }
scale-info = { version = "2.8.0", default-features = false, features = ["derive"] }
num-traits = { version = "0.2", default-features = false}
# Substrate
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
@@ -33,6 +34,7 @@ xcm-executor = { git = "https://github.com/paritytech/polkadot", default-feature
# Cumulus
pallet-collator-selection = { path = "../../pallets/collator-selection", default-features = false }
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
cumulus-primitives-utility = { path = "../../primitives/utility", default-features = false }
[dev-dependencies]
@@ -47,7 +49,6 @@ default = ["std"]
std = [
"frame-support/std",
"frame-system/std",
"pallet-asset-tx-payment/std",
"pallet-assets/std",
"pallet-authorship/std",
"pallet-balances/std",
@@ -56,6 +57,7 @@ std = [
"sp-io/std",
"sp-std/std",
"pallet-collator-selection/std",
"cumulus-primitives-core/std",
"cumulus-primitives-utility/std",
"xcm/std",
"xcm-executor/std",
@@ -16,6 +16,7 @@ sp-core = { default-features = false, git = "https://github.com/paritytech/subst
sp-weights = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-assets = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-asset-conversion = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
# Polkadot
polkadot-core-primitives = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
@@ -26,7 +26,8 @@ pub use integration_tests_common::{
},
AccountId, AssetHubWestend, AssetHubWestendPallet, AssetHubWestendReceiver,
AssetHubWestendSender, Collectives, CollectivesPallet, CollectivesReceiver, CollectivesSender,
PenpalWestend, Westend, WestendPallet, WestendReceiver, WestendSender,
PenpalWestend, PenpalWestendPallet, PenpalWestendReceiver, PenpalWestendSender, Westend,
WestendPallet, WestendReceiver, WestendSender,
};
pub use polkadot_core_primitives::InboundDownwardMessage;
pub use xcm::{
@@ -15,5 +15,6 @@
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
mod reserve_transfer;
mod swap;
mod teleport;
mod transact;
@@ -0,0 +1,307 @@
use crate::*;
use frame_support::{instances::Instance2, BoundedVec};
use xcm_emulator::Parachain;
#[test]
fn swap_locally_on_chain_using_local_assets() {
const ASSET_ID: u32 = 1;
let asset_native = Box::new(MultiLocation { parents: 0, interior: Here });
let asset_one = Box::new(MultiLocation {
parents: 0,
interior: X2(PalletInstance(50), GeneralIndex(ASSET_ID.into())),
});
AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Parachain>::RuntimeEvent;
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::Assets::create(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
ASSET_ID.into(),
AssetHubWestendSender::get().into(),
1000,
));
assert!(<AssetHubWestend as AssetHubWestendPallet>::Assets::asset_exists(ASSET_ID));
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::Assets::mint(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
ASSET_ID.into(),
AssetHubWestendSender::get().into(),
3_000_000_000_000,
));
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::create_pool(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native.clone(),
asset_one.clone(),
));
assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::PoolCreated { .. }) => {},
]
);
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::add_liquidity(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native.clone(),
asset_one.clone(),
1_000_000_000_000,
2_000_000_000_000,
0,
0,
AssetHubWestendSender::get().into()
));
assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::LiquidityAdded {lp_token_minted, .. }) => { lp_token_minted: *lp_token_minted == 1414213562273, },
]
);
let path = BoundedVec::<_, _>::truncate_from(vec![asset_native.clone(), asset_one.clone()]);
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::swap_exact_tokens_for_tokens(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
path,
100,
1,
AssetHubWestendSender::get().into(),
true
));
assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. }) => {
amount_in: *amount_in == 100,
amount_out: *amount_out == 199,
},
]
);
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::remove_liquidity(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native,
asset_one,
1414213562273 - 2_000_000_000, // all but the 2 EDs can't be retrieved.
0,
0,
AssetHubWestendSender::get().into(),
));
});
}
#[test]
fn swap_locally_on_chain_using_foreign_assets() {
use frame_support::weights::WeightToFee;
const ASSET_ID: u32 = 1;
let asset_native = Box::new(MultiLocation { parents: 0, interior: Here });
let foreign_asset1_at_asset_hub_westend = Box::new(MultiLocation {
parents: 1,
interior: X3(
Parachain(PenpalWestend::para_id().into()),
PalletInstance(50),
GeneralIndex(ASSET_ID.into()),
),
});
let assets_para_destination: VersionedMultiLocation =
MultiLocation { parents: 1, interior: X1(Parachain(AssetHubWestend::para_id().into())) }
.into();
let penpal_location =
MultiLocation { parents: 1, interior: X1(Parachain(PenpalWestend::para_id().into())) };
// 1. Create asset on penpal:
PenpalWestend::execute_with(|| {
assert_ok!(<PenpalWestend as PenpalWestendPallet>::Assets::create(
<PenpalWestend as Parachain>::RuntimeOrigin::signed(PenpalWestendSender::get()),
ASSET_ID.into(),
PenpalWestendSender::get().into(),
1000,
));
assert!(<PenpalWestend as PenpalWestendPallet>::Assets::asset_exists(ASSET_ID));
});
// 2. Create foreign asset on asset_hub_westend:
let require_weight_at_most = Weight::from_parts(1_100_000_000_000, 30_000);
let origin_kind = OriginKind::Xcm;
let sov_penpal_on_asset_hub_westend = AssetHubWestend::sovereign_account_id_of(penpal_location);
AssetHubWestend::fund_accounts(vec![
(AssetHubWestendSender::get(), 5_000_000), // An account to swap dot for something else.
(sov_penpal_on_asset_hub_westend.clone(), 1000_000_000_000_000_000),
]);
let sov_penpal_on_asset_hub_westend_as_location: MultiLocation = MultiLocation {
parents: 0,
interior: X1(AccountId32 {
network: None,
id: sov_penpal_on_asset_hub_westend.clone().into(),
}),
};
let call_foreign_assets_create =
<AssetHubWestend as Para>::RuntimeCall::ForeignAssets(pallet_assets::Call::<
<AssetHubWestend as Para>::Runtime,
Instance2,
>::create {
id: *foreign_asset1_at_asset_hub_westend,
min_balance: 1000,
admin: sov_penpal_on_asset_hub_westend.clone().into(),
})
.encode()
.into();
let buy_execution_fee_amount =
asset_hub_westend_runtime::constants::fee::WeightToFee::weight_to_fee(&Weight::from_parts(
10_100_000_000_000,
300_000,
));
let buy_execution_fee = MultiAsset {
id: Concrete(MultiLocation { parents: 1, interior: Here }),
fun: Fungible(buy_execution_fee_amount),
};
let xcm = VersionedXcm::from(Xcm(vec![
WithdrawAsset { 0: vec![buy_execution_fee.clone()].into() },
BuyExecution { fees: buy_execution_fee.clone(), weight_limit: Unlimited },
Transact { require_weight_at_most, origin_kind, call: call_foreign_assets_create },
RefundSurplus,
DepositAsset {
assets: All.into(),
beneficiary: sov_penpal_on_asset_hub_westend_as_location,
},
]));
// Send XCM message from penpal => asset_hub_westend
let sudo_penpal_origin = <PenpalWestend as Parachain>::RuntimeOrigin::root();
PenpalWestend::execute_with(|| {
assert_ok!(<PenpalWestend as PenpalWestendPallet>::PolkadotXcm::send(
sudo_penpal_origin.clone(),
bx!(assets_para_destination.clone()),
bx!(xcm),
));
type RuntimeEvent = <PenpalWestend as Parachain>::RuntimeEvent;
assert_expected_events!(
PenpalWestend,
vec![
RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {},
]
);
});
// Receive XCM message in Assets Parachain
AssetHubWestend::execute_with(|| {
assert!(<AssetHubWestend as AssetHubWestendPallet>::ForeignAssets::asset_exists(
*foreign_asset1_at_asset_hub_westend
));
// 3: Mint foreign asset on asset_hub_westend:
//
// (While it might be nice to use batch,
// currently that's disabled due to safe call filters.)
type RuntimeEvent = <AssetHubWestend as Parachain>::RuntimeEvent;
// 3. Mint foreign asset (in reality this should be a teleport or some such)
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::ForeignAssets::mint(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(
sov_penpal_on_asset_hub_westend.clone().into()
),
*foreign_asset1_at_asset_hub_westend,
sov_penpal_on_asset_hub_westend.clone().into(),
3_000_000_000_000,
));
assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { .. }) => {},
]
);
// 4. Create pool:
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::create_pool(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native.clone(),
foreign_asset1_at_asset_hub_westend.clone(),
));
assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::PoolCreated { .. }) => {},
]
);
// 5. Add liquidity:
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::add_liquidity(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(
sov_penpal_on_asset_hub_westend.clone()
),
asset_native.clone(),
foreign_asset1_at_asset_hub_westend.clone(),
1_000_000_000_000,
2_000_000_000_000,
0,
0,
sov_penpal_on_asset_hub_westend.clone().into()
));
assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::LiquidityAdded {lp_token_minted, .. }) => {
lp_token_minted: *lp_token_minted == 1414213562273,
},
]
);
// 6. Swap!
let path = BoundedVec::<_, _>::truncate_from(vec![
asset_native.clone(),
foreign_asset1_at_asset_hub_westend.clone(),
]);
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::swap_exact_tokens_for_tokens(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
path,
100000,
1000,
AssetHubWestendSender::get().into(),
true
));
assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. },) => {
amount_in: *amount_in == 100000,
amount_out: *amount_out == 199399,
},
]
);
// 7. Remove liquidity
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::remove_liquidity(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(
sov_penpal_on_asset_hub_westend.clone()
),
asset_native,
foreign_asset1_at_asset_hub_westend,
1414213562273 - 2_000_000_000, // all but the 2 EDs can't be retrieved.
0,
0,
sov_penpal_on_asset_hub_westend.clone().into(),
));
});
}
@@ -98,6 +98,7 @@ decl_test_parachains! {
PolkadotXcm: asset_hub_westend_runtime::PolkadotXcm,
Assets: asset_hub_westend_runtime::Assets,
ForeignAssets: asset_hub_westend_runtime::ForeignAssets,
AssetConversion: asset_hub_westend_runtime::AssetConversion,
}
},
// Polkadot
@@ -20,8 +20,9 @@ frame-system = { git = "https://github.com/paritytech/substrate", default-featur
frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", optional = true, default-features = false, branch = "master" }
frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "master" }
pallet-asset-tx-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-asset-conversion-tx-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-assets = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-asset-conversion = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
@@ -47,6 +48,8 @@ sp-session = { git = "https://github.com/paritytech/substrate", default-features
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
# num-traits feature needed for dex integer sq root:
primitive-types = { version = "0.12.0", default-features = false, features = ["codec", "scale-info", "num-traits"] }
# Polkadot
pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
@@ -90,6 +93,7 @@ runtime-benchmarks = [
"frame-system-benchmarking/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-assets/runtime-benchmarks",
"pallet-asset-conversion/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-multisig/runtime-benchmarks",
"pallet-nft-fractionalization/runtime-benchmarks",
@@ -117,8 +121,9 @@ try-runtime = [
"frame-executive/try-runtime",
"frame-system/try-runtime",
"frame-try-runtime/try-runtime",
"pallet-asset-tx-payment/try-runtime",
"pallet-asset-conversion-tx-payment/try-runtime",
"pallet-assets/try-runtime",
"pallet-asset-conversion/try-runtime",
"pallet-aura/try-runtime",
"pallet-authorship/try-runtime",
"pallet-balances/try-runtime",
@@ -143,8 +148,9 @@ std = [
"frame-support/std",
"frame-system-rpc-runtime-api/std",
"frame-system/std",
"pallet-asset-tx-payment/std",
"pallet-asset-conversion-tx-payment/std",
"pallet-assets/std",
"pallet-asset-conversion/std",
"pallet-aura/std",
"pallet-authorship/std",
"pallet-balances/std",
@@ -28,49 +28,51 @@ pub mod constants;
mod weights;
pub mod xcm_config;
use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases;
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, ConvertInto, Verify},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult,
};
use sp_std::prelude::*;
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
use crate::xcm_config::{TrustBackedAssetsPalletLocation, UniversalLocation};
use assets_common::local_and_foreign_assets::{LocalAndForeignAssets, MultiLocationConverter};
use codec::{Decode, Encode, MaxEncodedLen};
use constants::{currency::*, fee::WeightToFee};
use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases;
use frame_support::{
construct_runtime,
dispatch::DispatchClass,
parameter_types,
ord_parameter_types, parameter_types,
traits::{
tokens::nonfungibles_v2::Inspect, AsEnsureOriginWithArg, ConstBool, ConstU32, ConstU64,
ConstU8, InstanceFilter,
tokens::nonfungibles_v2::Inspect, AsEnsureOriginWithArg, ConstBool, ConstU128, ConstU32,
ConstU64, ConstU8, InstanceFilter,
},
weights::{ConstantMultiplier, Weight},
BoundedVec, PalletId, RuntimeDebug,
};
use frame_system::{
limits::{BlockLength, BlockWeights},
EnsureRoot, EnsureSigned,
EnsureRoot, EnsureSigned, EnsureSignedBy,
};
use pallet_asset_conversion_tx_payment::AssetConversionAdapter;
use pallet_nfts::PalletFeatures;
pub use parachains_common as common;
use parachains_common::{
impls::{AssetsToBlockAuthor, DealWithFees},
opaque, AccountId, AssetIdForTrustBackedAssets, AuraId, Balance, BlockNumber, Hash, Header,
Index, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT,
NORMAL_DISPATCH_RATIO, SLOT_DURATION,
impls::DealWithFees, opaque, AccountId, AssetIdForTrustBackedAssets, AuraId, Balance,
BlockNumber, Hash, Header, Index, Signature, AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS,
MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION,
};
use sp_api::impl_runtime_apis;
use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
use sp_runtime::{
create_runtime_str, generic, impl_opaque_keys,
traits::{AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, Verify},
transaction_validity::{TransactionSource, TransactionValidity},
ApplyExtrinsicResult, Permill,
};
use sp_std::prelude::*;
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
use xcm::opaque::v3::MultiLocation;
use xcm_config::{
ForeignAssetsConvertedConcreteId, TrustBackedAssetsConvertedConcreteId, WestendLocation,
XcmConfig, XcmOriginToTransactDispatchOrigin,
ForeignAssetsConvertedConcreteId, PoolAssetsConvertedConcreteId,
TrustBackedAssetsConvertedConcreteId, WestendLocation, XcmConfig,
XcmOriginToTransactDispatchOrigin,
};
#[cfg(any(feature = "std", test))]
@@ -251,11 +253,77 @@ impl pallet_assets::Config<TrustBackedAssetsInstance> for Runtime {
type WeightInfo = weights::pallet_assets_local::WeightInfo<Runtime>;
type CallbackHandle = ();
type AssetAccountDeposit = AssetAccountDeposit;
type RemoveItemsLimit = frame_support::traits::ConstU32<1000>;
type RemoveItemsLimit = ConstU32<1000>;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = ();
}
parameter_types! {
pub const AssetConversionPalletId: PalletId = PalletId(*b"py/ascon");
pub storage AllowMultiAssetPools: bool = false;
// should be non-zero if AllowMultiAssetPools is true, otherwise can be zero
pub storage LiquidityWithdrawalFee: Permill = Permill::from_percent(0);
}
ord_parameter_types! {
pub const AssetConversionOrigin: sp_runtime::AccountId32 = AccountIdConversion::<sp_runtime::AccountId32>::into_account_truncating(&AssetConversionPalletId::get());
}
pub type PoolAssetsInstance = pallet_assets::Instance3;
impl pallet_assets::Config<PoolAssetsInstance> for Runtime {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
type RemoveItemsLimit = ConstU32<1000>;
type AssetId = u32;
type AssetIdParameter = u32;
type Currency = Balances;
type CreateOrigin =
AsEnsureOriginWithArg<EnsureSignedBy<AssetConversionOrigin, sp_runtime::AccountId32>>;
type ForceOrigin = AssetsForceOrigin;
type AssetDeposit = ConstU128<0>;
type AssetAccountDeposit = ConstU128<0>;
type MetadataDepositBase = ConstU128<0>;
type MetadataDepositPerByte = ConstU128<0>;
type ApprovalDeposit = ConstU128<0>;
type StringLimit = ConstU32<50>;
type Freezer = ();
type Extra = ();
type WeightInfo = weights::pallet_assets_pool::WeightInfo<Runtime>;
type CallbackHandle = ();
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = ();
}
impl pallet_asset_conversion::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Balance = Balance;
type HigherPrecisionBalance = sp_core::U256;
type Currency = Balances;
type AssetBalance = <Self as pallet_balances::Config>::Balance;
type AssetId = MultiLocation;
type Assets = LocalAndForeignAssets<Assets, ForeignAssets, TrustBackedAssetsPalletLocation>;
type PoolAssets = PoolAssets;
type PoolAssetId = u32;
type PoolSetupFee = ConstU128<0>; // Asset class deposit fees are sufficient to prevent spam
type PoolSetupFeeReceiver = AssetConversionOrigin;
type LiquidityWithdrawalFee = LiquidityWithdrawalFee; // should be non-zero if AllowMultiAssetPools is true, otherwise can be zero.
type LPFee = ConstU32<3>;
type PalletId = AssetConversionPalletId;
type AllowMultiAssetPools = AllowMultiAssetPools;
type MaxSwapPathLength = ConstU32<4>;
type MultiAssetId = Box<MultiLocation>;
type MultiAssetIdConverter = MultiLocationConverter<Balances, UniversalLocation>;
type MintMinLiquidity = ConstU128<100>;
type WeightInfo = ();
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper =
crate::xcm_config::BenchmarkMultiLocationConverter<parachain_info::Pallet<Runtime>>;
}
parameter_types! {
// we just reuse the same deposits
pub const ForeignAssetsAssetDeposit: Balance = AssetDeposit::get();
@@ -587,18 +655,10 @@ impl pallet_collator_selection::Config for Runtime {
type WeightInfo = weights::pallet_collator_selection::WeightInfo<Runtime>;
}
impl pallet_asset_tx_payment::Config for Runtime {
impl pallet_asset_conversion_tx_payment::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type Fungibles = Assets;
type OnChargeAssetTransaction = pallet_asset_tx_payment::FungiblesAdapter<
pallet_assets::BalanceToAssetBalance<
Balances,
Runtime,
ConvertInto,
TrustBackedAssetsInstance,
>,
AssetsToBlockAuthor<Runtime, TrustBackedAssetsInstance>,
>;
type Fungibles = LocalAndForeignAssets<Assets, ForeignAssets, TrustBackedAssetsPalletLocation>;
type OnChargeAssetTransaction = AssetConversionAdapter<Balances, AssetConversion>;
}
parameter_types! {
@@ -715,7 +775,8 @@ construct_runtime!(
// Monetary stuff.
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>} = 10,
TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event<T>} = 11,
AssetTxPayment: pallet_asset_tx_payment::{Pallet, Event<T>} = 12,
// AssetTxPayment: pallet_asset_tx_payment::{Pallet, Event<T>} = 12,
AssetTxPayment: pallet_asset_conversion_tx_payment::{Pallet, Event<T>} = 13,
// Collator support. the order of these 5 are important and shall not change.
Authorship: pallet_authorship::{Pallet, Storage} = 20,
@@ -741,6 +802,8 @@ construct_runtime!(
Nfts: pallet_nfts::{Pallet, Call, Storage, Event<T>} = 52,
ForeignAssets: pallet_assets::<Instance2>::{Pallet, Call, Storage, Event<T>} = 53,
NftFractionalization: pallet_nft_fractionalization::{Pallet, Call, Storage, Event<T>, HoldReason} = 54,
PoolAssets: pallet_assets::<Instance3>::{Pallet, Call, Storage, Event<T>} = 55,
AssetConversion: pallet_asset_conversion::{Pallet, Call, Storage, Event<T>} = 56,
}
);
@@ -761,7 +824,7 @@ pub type SignedExtra = (
frame_system::CheckEra<Runtime>,
frame_system::CheckNonce<Runtime>,
frame_system::CheckWeight<Runtime>,
pallet_asset_tx_payment::ChargeAssetTxPayment<Runtime>,
pallet_asset_conversion_tx_payment::ChargeAssetTxPayment<Runtime>,
);
/// Unchecked extrinsic type as expected by this runtime.
pub type UncheckedExtrinsic =
@@ -795,6 +858,8 @@ mod benches {
[frame_system, SystemBench::<Runtime>]
[pallet_assets, Local]
[pallet_assets, Foreign]
[pallet_assets, PoolAssets]
[pallet_asset_conversion, AssetConversion]
[pallet_balances, Balances]
[pallet_multisig, Multisig]
[pallet_nft_fractionalization, NftFractionalization]
@@ -952,6 +1017,26 @@ impl_runtime_apis! {
}
}
impl pallet_asset_conversion::AssetConversionApi<
Block,
Balance,
u128,
Box<MultiLocation>,
> for Runtime
{
fn quote_price_exact_tokens_for_tokens(asset1: Box<MultiLocation>, asset2: Box<MultiLocation>, amount: u128, include_fee: bool) -> Option<Balance> {
AssetConversion::quote_price_exact_tokens_for_tokens(asset1, asset2, amount, include_fee)
}
fn quote_price_tokens_for_exact_tokens(asset1: Box<MultiLocation>, asset2: Box<MultiLocation>, amount: u128, include_fee: bool) -> Option<Balance> {
AssetConversion::quote_price_tokens_for_exact_tokens(asset1, asset2, amount, include_fee)
}
fn get_reserves(asset1: Box<MultiLocation>, asset2: Box<MultiLocation>) -> Option<(Balance, Balance)> {
AssetConversion::get_reserves(&asset1, &asset2).ok()
}
}
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<Block, Balance> for Runtime {
fn query_info(
uxt: <Block as BlockT>::Extrinsic,
@@ -1021,7 +1106,13 @@ impl_runtime_apis! {
)?,
// collect pallet_assets (ForeignAssets)
convert::<_, _, _, _, ForeignAssetsConvertedConcreteId>(
ForeignAssets::account_balances(account)
ForeignAssets::account_balances(account.clone())
.iter()
.filter(|(_, balance)| balance > &0)
)?,
// collect pallet_assets (PoolAssets)
convert::<_, _, _, _, PoolAssetsConvertedConcreteId>(
PoolAssets::account_balances(account)
.iter()
.filter(|(_, balance)| balance > &0)
)?,
@@ -1078,6 +1169,7 @@ impl_runtime_apis! {
// `pallet_assets_local.rs / pallet_assets_foreign.rs`.
type Local = pallet_assets::Pallet::<Runtime, TrustBackedAssetsInstance>;
type Foreign = pallet_assets::Pallet::<Runtime, ForeignAssetsInstance>;
type Pool = pallet_assets::Pallet::<Runtime, PoolAssetsInstance>;
let mut list = Vec::<BenchmarkList>::new();
list_benchmarks!(list, extra);
@@ -1215,6 +1307,7 @@ impl_runtime_apis! {
type Local = pallet_assets::Pallet::<Runtime, TrustBackedAssetsInstance>;
type Foreign = pallet_assets::Pallet::<Runtime, ForeignAssetsInstance>;
type Pool = pallet_assets::Pallet::<Runtime, PoolAssetsInstance>;
let whitelist: Vec<TrackedStorageKey> = vec![
// Block Number
@@ -4,6 +4,7 @@ pub mod extrinsic_weights;
pub mod frame_system;
pub mod pallet_assets_foreign;
pub mod pallet_assets_local;
pub mod pallet_assets_pool;
pub mod pallet_balances;
pub mod pallet_collator_selection;
pub mod pallet_multisig;
@@ -0,0 +1,534 @@
// Copyright Parity Technologies (UK) Ltd.
// This file is part of Cumulus.
// Cumulus is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Cumulus is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
//! Autogenerated weights for `pallet_assets`
//!
//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
//! DATE: 2023-06-20, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]`
//! WORST CASE MAP SIZE: `1000000`
//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz`
//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("asset-hub-westend-dev"), DB CACHE: 1024
// Executed Command:
// target/production/polkadot-parachain
// benchmark
// pallet
// --steps=50
// --repeat=20
// --extrinsic=*
// --execution=wasm
// --wasm-execution=compiled
// --heap-pages=4096
// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/cumulus/.git/.artifacts/bench.json
// --pallet=pallet_assets
// --chain=asset-hub-westend-dev
// --header=./file_header.txt
// --output=./parachains/runtimes/assets/asset-hub-westend/src/weights/
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(missing_docs)]
use frame_support::{traits::Get, weights::Weight};
use core::marker::PhantomData;
/// Weight functions for `pallet_assets`.
pub struct WeightInfo<T>(PhantomData<T>);
impl<T: frame_system::Config> pallet_assets::WeightInfo for WeightInfo<T> {
/// Storage: ParachainInfo ParachainId (r:1 w:0)
/// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen)
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: System Account (r:1 w:1)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
fn create() -> Weight {
// Proof Size summary in bytes:
// Measured: `107`
// Estimated: `4273`
// Minimum execution time: 31_477_000 picoseconds.
Weight::from_parts(32_036_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(3))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
fn force_create() -> Weight {
// Proof Size summary in bytes:
// Measured: `4`
// Estimated: `4273`
// Minimum execution time: 13_084_000 picoseconds.
Weight::from_parts(13_591_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
fn start_destroy() -> Weight {
// Proof Size summary in bytes:
// Measured: `276`
// Estimated: `4273`
// Minimum execution time: 15_413_000 picoseconds.
Weight::from_parts(16_009_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Account (r:1001 w:1000)
/// Proof: ForeignAssets Account (max_values: None, max_size: Some(732), added: 3207, mode: MaxEncodedLen)
/// Storage: System Account (r:1000 w:1000)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
/// The range of component `c` is `[0, 1000]`.
/// The range of component `c` is `[0, 1000]`.
fn destroy_accounts(c: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `0 + c * (208 ±0)`
// Estimated: `4273 + c * (3207 ±0)`
// Minimum execution time: 18_503_000 picoseconds.
Weight::from_parts(18_705_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
// Standard Error: 5_073
.saturating_add(Weight::from_parts(12_123_380, 0).saturating_mul(c.into()))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().reads((2_u64).saturating_mul(c.into())))
.saturating_add(T::DbWeight::get().writes(1))
.saturating_add(T::DbWeight::get().writes((2_u64).saturating_mul(c.into())))
.saturating_add(Weight::from_parts(0, 3207).saturating_mul(c.into()))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Approvals (r:1001 w:1000)
/// Proof: ForeignAssets Approvals (max_values: None, max_size: Some(746), added: 3221, mode: MaxEncodedLen)
/// The range of component `a` is `[0, 1000]`.
/// The range of component `a` is `[0, 1000]`.
fn destroy_approvals(a: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `413 + a * (86 ±0)`
// Estimated: `4273 + a * (3221 ±0)`
// Minimum execution time: 19_736_000 picoseconds.
Weight::from_parts(20_044_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
// Standard Error: 3_446
.saturating_add(Weight::from_parts(14_117_950, 0).saturating_mul(a.into()))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().reads((1_u64).saturating_mul(a.into())))
.saturating_add(T::DbWeight::get().writes(1))
.saturating_add(T::DbWeight::get().writes((1_u64).saturating_mul(a.into())))
.saturating_add(Weight::from_parts(0, 3221).saturating_mul(a.into()))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Metadata (r:1 w:0)
/// Proof: ForeignAssets Metadata (max_values: None, max_size: Some(738), added: 3213, mode: MaxEncodedLen)
fn finish_destroy() -> Weight {
// Proof Size summary in bytes:
// Measured: `242`
// Estimated: `4273`
// Minimum execution time: 15_520_000 picoseconds.
Weight::from_parts(16_042_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Account (r:1 w:1)
/// Proof: ForeignAssets Account (max_values: None, max_size: Some(732), added: 3207, mode: MaxEncodedLen)
fn mint() -> Weight {
// Proof Size summary in bytes:
// Measured: `242`
// Estimated: `4273`
// Minimum execution time: 27_380_000 picoseconds.
Weight::from_parts(27_731_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Account (r:1 w:1)
/// Proof: ForeignAssets Account (max_values: None, max_size: Some(732), added: 3207, mode: MaxEncodedLen)
fn burn() -> Weight {
// Proof Size summary in bytes:
// Measured: `350`
// Estimated: `4273`
// Minimum execution time: 33_762_000 picoseconds.
Weight::from_parts(34_201_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Account (r:2 w:2)
/// Proof: ForeignAssets Account (max_values: None, max_size: Some(732), added: 3207, mode: MaxEncodedLen)
/// Storage: System Account (r:1 w:1)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
fn transfer() -> Weight {
// Proof Size summary in bytes:
// Measured: `350`
// Estimated: `7404`
// Minimum execution time: 45_731_000 picoseconds.
Weight::from_parts(46_587_000, 0)
.saturating_add(Weight::from_parts(0, 7404))
.saturating_add(T::DbWeight::get().reads(4))
.saturating_add(T::DbWeight::get().writes(4))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Account (r:2 w:2)
/// Proof: ForeignAssets Account (max_values: None, max_size: Some(732), added: 3207, mode: MaxEncodedLen)
/// Storage: System Account (r:1 w:1)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
fn transfer_keep_alive() -> Weight {
// Proof Size summary in bytes:
// Measured: `350`
// Estimated: `7404`
// Minimum execution time: 40_758_000 picoseconds.
Weight::from_parts(41_283_000, 0)
.saturating_add(Weight::from_parts(0, 7404))
.saturating_add(T::DbWeight::get().reads(4))
.saturating_add(T::DbWeight::get().writes(4))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Account (r:2 w:2)
/// Proof: ForeignAssets Account (max_values: None, max_size: Some(732), added: 3207, mode: MaxEncodedLen)
/// Storage: System Account (r:1 w:1)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
fn force_transfer() -> Weight {
// Proof Size summary in bytes:
// Measured: `350`
// Estimated: `7404`
// Minimum execution time: 46_265_000 picoseconds.
Weight::from_parts(47_105_000, 0)
.saturating_add(Weight::from_parts(0, 7404))
.saturating_add(T::DbWeight::get().reads(4))
.saturating_add(T::DbWeight::get().writes(4))
}
/// Storage: ForeignAssets Asset (r:1 w:0)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Account (r:1 w:1)
/// Proof: ForeignAssets Account (max_values: None, max_size: Some(732), added: 3207, mode: MaxEncodedLen)
fn freeze() -> Weight {
// Proof Size summary in bytes:
// Measured: `350`
// Estimated: `4273`
// Minimum execution time: 19_186_000 picoseconds.
Weight::from_parts(19_697_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: ForeignAssets Asset (r:1 w:0)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Account (r:1 w:1)
/// Proof: ForeignAssets Account (max_values: None, max_size: Some(732), added: 3207, mode: MaxEncodedLen)
fn thaw() -> Weight {
// Proof Size summary in bytes:
// Measured: `350`
// Estimated: `4273`
// Minimum execution time: 18_930_000 picoseconds.
Weight::from_parts(19_378_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
fn freeze_asset() -> Weight {
// Proof Size summary in bytes:
// Measured: `276`
// Estimated: `4273`
// Minimum execution time: 15_091_000 picoseconds.
Weight::from_parts(15_429_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
fn thaw_asset() -> Weight {
// Proof Size summary in bytes:
// Measured: `276`
// Estimated: `4273`
// Minimum execution time: 14_820_000 picoseconds.
Weight::from_parts(15_227_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Metadata (r:1 w:0)
/// Proof: ForeignAssets Metadata (max_values: None, max_size: Some(738), added: 3213, mode: MaxEncodedLen)
fn transfer_ownership() -> Weight {
// Proof Size summary in bytes:
// Measured: `242`
// Estimated: `4273`
// Minimum execution time: 16_832_000 picoseconds.
Weight::from_parts(17_104_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
fn set_team() -> Weight {
// Proof Size summary in bytes:
// Measured: `242`
// Estimated: `4273`
// Minimum execution time: 15_212_000 picoseconds.
Weight::from_parts(15_819_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: ForeignAssets Asset (r:1 w:0)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Metadata (r:1 w:1)
/// Proof: ForeignAssets Metadata (max_values: None, max_size: Some(738), added: 3213, mode: MaxEncodedLen)
/// The range of component `n` is `[0, 50]`.
/// The range of component `s` is `[0, 50]`.
/// The range of component `n` is `[0, 50]`.
/// The range of component `s` is `[0, 50]`.
fn set_metadata(n: u32, s: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `242`
// Estimated: `4273`
// Minimum execution time: 30_119_000 picoseconds.
Weight::from_parts(30_931_884, 0)
.saturating_add(Weight::from_parts(0, 4273))
// Standard Error: 2_734
.saturating_add(Weight::from_parts(2_665, 0).saturating_mul(n.into()))
// Standard Error: 2_734
.saturating_add(Weight::from_parts(725, 0).saturating_mul(s.into()))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: ForeignAssets Asset (r:1 w:0)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Metadata (r:1 w:1)
/// Proof: ForeignAssets Metadata (max_values: None, max_size: Some(738), added: 3213, mode: MaxEncodedLen)
fn clear_metadata() -> Weight {
// Proof Size summary in bytes:
// Measured: `406`
// Estimated: `4273`
// Minimum execution time: 30_740_000 picoseconds.
Weight::from_parts(31_699_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: ForeignAssets Asset (r:1 w:0)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Metadata (r:1 w:1)
/// Proof: ForeignAssets Metadata (max_values: None, max_size: Some(738), added: 3213, mode: MaxEncodedLen)
/// The range of component `n` is `[0, 50]`.
/// The range of component `s` is `[0, 50]`.
/// The range of component `n` is `[0, 50]`.
/// The range of component `s` is `[0, 50]`.
fn force_set_metadata(n: u32, s: u32, ) -> Weight {
// Proof Size summary in bytes:
// Measured: `81`
// Estimated: `4273`
// Minimum execution time: 14_270_000 picoseconds.
Weight::from_parts(14_791_008, 0)
.saturating_add(Weight::from_parts(0, 4273))
// Standard Error: 1_649
.saturating_add(Weight::from_parts(227, 0).saturating_mul(n.into()))
// Standard Error: 1_649
.saturating_add(Weight::from_parts(4_436, 0).saturating_mul(s.into()))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: ForeignAssets Asset (r:1 w:0)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Metadata (r:1 w:1)
/// Proof: ForeignAssets Metadata (max_values: None, max_size: Some(738), added: 3213, mode: MaxEncodedLen)
fn force_clear_metadata() -> Weight {
// Proof Size summary in bytes:
// Measured: `406`
// Estimated: `4273`
// Minimum execution time: 29_653_000 picoseconds.
Weight::from_parts(30_256_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
fn force_asset_status() -> Weight {
// Proof Size summary in bytes:
// Measured: `242`
// Estimated: `4273`
// Minimum execution time: 13_914_000 picoseconds.
Weight::from_parts(14_372_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Approvals (r:1 w:1)
/// Proof: ForeignAssets Approvals (max_values: None, max_size: Some(746), added: 3221, mode: MaxEncodedLen)
fn approve_transfer() -> Weight {
// Proof Size summary in bytes:
// Measured: `276`
// Estimated: `4273`
// Minimum execution time: 33_615_000 picoseconds.
Weight::from_parts(34_064_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Approvals (r:1 w:1)
/// Proof: ForeignAssets Approvals (max_values: None, max_size: Some(746), added: 3221, mode: MaxEncodedLen)
/// Storage: ForeignAssets Account (r:2 w:2)
/// Proof: ForeignAssets Account (max_values: None, max_size: Some(732), added: 3207, mode: MaxEncodedLen)
/// Storage: System Account (r:1 w:1)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
fn transfer_approved() -> Weight {
// Proof Size summary in bytes:
// Measured: `520`
// Estimated: `7404`
// Minimum execution time: 64_837_000 picoseconds.
Weight::from_parts(65_668_000, 0)
.saturating_add(Weight::from_parts(0, 7404))
.saturating_add(T::DbWeight::get().reads(5))
.saturating_add(T::DbWeight::get().writes(5))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Approvals (r:1 w:1)
/// Proof: ForeignAssets Approvals (max_values: None, max_size: Some(746), added: 3221, mode: MaxEncodedLen)
fn cancel_approval() -> Weight {
// Proof Size summary in bytes:
// Measured: `446`
// Estimated: `4273`
// Minimum execution time: 35_648_000 picoseconds.
Weight::from_parts(36_163_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Approvals (r:1 w:1)
/// Proof: ForeignAssets Approvals (max_values: None, max_size: Some(746), added: 3221, mode: MaxEncodedLen)
fn force_cancel_approval() -> Weight {
// Proof Size summary in bytes:
// Measured: `446`
// Estimated: `4273`
// Minimum execution time: 36_452_000 picoseconds.
Weight::from_parts(36_885_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
fn set_min_balance() -> Weight {
// Proof Size summary in bytes:
// Measured: `242`
// Estimated: `4273`
// Minimum execution time: 15_963_000 picoseconds.
Weight::from_parts(16_345_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(1))
.saturating_add(T::DbWeight::get().writes(1))
}
/// Storage: ForeignAssets Account (r:1 w:1)
/// Proof: ForeignAssets Account (max_values: None, max_size: Some(732), added: 3207, mode: MaxEncodedLen)
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: System Account (r:1 w:1)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
fn touch() -> Weight {
// Proof Size summary in bytes:
// Measured: `345`
// Estimated: `4273`
// Minimum execution time: 35_359_000 picoseconds.
Weight::from_parts(36_006_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(3))
.saturating_add(T::DbWeight::get().writes(3))
}
/// Storage: ForeignAssets Account (r:1 w:1)
/// Proof: ForeignAssets Account (max_values: None, max_size: Some(732), added: 3207, mode: MaxEncodedLen)
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
fn touch_other() -> Weight {
// Proof Size summary in bytes:
// Measured: `242`
// Estimated: `4273`
// Minimum execution time: 33_524_000 picoseconds.
Weight::from_parts(34_090_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: ForeignAssets Account (r:1 w:1)
/// Proof: ForeignAssets Account (max_values: None, max_size: Some(732), added: 3207, mode: MaxEncodedLen)
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: System Account (r:1 w:1)
/// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen)
fn refund() -> Weight {
// Proof Size summary in bytes:
// Measured: `471`
// Estimated: `4273`
// Minimum execution time: 31_777_000 picoseconds.
Weight::from_parts(32_319_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(3))
.saturating_add(T::DbWeight::get().writes(3))
}
/// Storage: ForeignAssets Account (r:1 w:1)
/// Proof: ForeignAssets Account (max_values: None, max_size: Some(732), added: 3207, mode: MaxEncodedLen)
/// Storage: ForeignAssets Asset (r:1 w:1)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
fn refund_other() -> Weight {
// Proof Size summary in bytes:
// Measured: `401`
// Estimated: `4273`
// Minimum execution time: 30_160_000 picoseconds.
Weight::from_parts(30_665_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(2))
}
/// Storage: ForeignAssets Asset (r:1 w:0)
/// Proof: ForeignAssets Asset (max_values: None, max_size: Some(808), added: 3283, mode: MaxEncodedLen)
/// Storage: ForeignAssets Account (r:1 w:1)
/// Proof: ForeignAssets Account (max_values: None, max_size: Some(732), added: 3207, mode: MaxEncodedLen)
fn block() -> Weight {
// Proof Size summary in bytes:
// Measured: `350`
// Estimated: `4273`
// Minimum execution time: 19_011_000 picoseconds.
Weight::from_parts(19_491_000, 0)
.saturating_add(Weight::from_parts(0, 4273))
.saturating_add(T::DbWeight::get().reads(2))
.saturating_add(T::DbWeight::get().writes(1))
}
}
@@ -15,7 +15,7 @@
use super::{
AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, ParachainInfo,
ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
ParachainSystem, PolkadotXcm, PoolAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin,
TrustBackedAssetsInstance, WeightToFee, XcmpQueue,
};
use crate::ForeignAssets;
@@ -43,6 +43,9 @@ use xcm_builder::{
};
use xcm_executor::{traits::WithOriginFilter, XcmExecutor};
#[cfg(feature = "runtime-benchmarks")]
use {cumulus_primitives_core::ParaId, sp_core::Get};
parameter_types! {
pub const WestendLocation: MultiLocation = MultiLocation::parent();
pub RelayNetwork: Option<NetworkId> = Some(NetworkId::Westend);
@@ -52,6 +55,10 @@ parameter_types! {
pub UniversalLocationNetworkId: NetworkId = UniversalLocation::get().global_consensus().unwrap();
pub TrustBackedAssetsPalletLocation: MultiLocation =
PalletInstance(<Assets as PalletInfoAccess>::index() as u8).into();
pub ForeignAssetsPalletLocation: MultiLocation =
PalletInstance(<ForeignAssets as PalletInfoAccess>::index() as u8).into();
pub PoolAssetsPalletLocation: MultiLocation =
PalletInstance(<PoolAssets as PalletInfoAccess>::index() as u8).into();
pub CheckingAccount: AccountId = PolkadotXcm::check_account();
}
@@ -131,8 +138,30 @@ pub type ForeignFungiblesTransactor = FungiblesAdapter<
CheckingAccount,
>;
/// `AssetId/Balance` converter for `PoolAssets`
pub type PoolAssetsConvertedConcreteId =
assets_common::PoolAssetsConvertedConcreteId<PoolAssetsPalletLocation, Balance>;
/// Means for transacting asset conversion pool assets on this chain.
pub type PoolFungiblesTransactor = FungiblesAdapter<
// Use this fungibles implementation:
PoolAssets,
// Use this currency when it is a fungible asset matching the given location or name:
PoolAssetsConvertedConcreteId,
// Convert an XCM MultiLocation into a local account id:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We only want to allow teleports of known assets. We use non-zero issuance as an indication
// that this asset is known.
LocalMint<parachains_common::impls::NonZeroIssuance<AccountId, PoolAssets>>,
// The account to use for tracking teleports.
CheckingAccount,
>;
/// Means for transacting assets on this chain.
pub type AssetTransactors = (CurrencyTransactor, FungiblesTransactor, ForeignFungiblesTransactor);
pub type AssetTransactors =
(CurrencyTransactor, FungiblesTransactor, ForeignFungiblesTransactor, PoolFungiblesTransactor);
/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance,
/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can
@@ -269,6 +298,12 @@ impl Contains<RuntimeCall> for SafeCallFilter {
pallet_assets::Call::transfer_approved { .. } |
pallet_assets::Call::touch { .. } |
pallet_assets::Call::refund { .. },
) | RuntimeCall::AssetConversion(
pallet_asset_conversion::Call::create_pool { .. } |
pallet_asset_conversion::Call::add_liquidity { .. } |
pallet_asset_conversion::Call::remove_liquidity { .. } |
pallet_asset_conversion::Call::swap_tokens_for_exact_tokens { .. } |
pallet_asset_conversion::Call::swap_exact_tokens_for_tokens { .. },
) | RuntimeCall::NftFractionalization(
pallet_nft_fractionalization::Call::fractionalize { .. } |
pallet_nft_fractionalization::Call::unify { .. },
@@ -364,6 +399,11 @@ pub type Barrier = TrailingSetTopicAsId<
>,
>;
// TODO: This calls into the Assets pallet's default `BalanceToAssetBalance` implementation, which
// uses the ratio of minimum balances and requires asset sufficiency. This means that purchasing
// weight within XCM programs will still use the old way, and paying fees via asset conversion will
// only be possible when transacting locally. We should add an impl of this trait that does asset
// conversion.
pub type AssetFeeAsExistentialDepositMultiplierFeeCharger = AssetFeeAsExistentialDepositMultiplier<
Runtime,
WeightToFee,
@@ -493,3 +533,26 @@ impl pallet_assets::BenchmarkHelper<MultiLocation> for XcmBenchmarkHelper {
MultiLocation { parents: 1, interior: X1(Parachain(id)) }
}
}
#[cfg(feature = "runtime-benchmarks")]
pub struct BenchmarkMultiLocationConverter<SelfParaId> {
_phantom: sp_std::marker::PhantomData<SelfParaId>,
}
#[cfg(feature = "runtime-benchmarks")]
impl<SelfParaId> pallet_asset_conversion::BenchmarkHelper<MultiLocation>
for BenchmarkMultiLocationConverter<SelfParaId>
where
SelfParaId: Get<ParaId>,
{
fn asset_id(asset_id: u32) -> MultiLocation {
MultiLocation {
parents: 1,
interior: X3(
Parachain(SelfParaId::get().into()),
PalletInstance(<Assets as PalletInfoAccess>::index() as u8),
GeneralIndex(asset_id.into()),
),
}
}
}
@@ -15,6 +15,8 @@ frame-support = { git = "https://github.com/paritytech/substrate", default-featu
sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" }
pallet-asset-conversion = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
pallet-asset-tx-payment = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
# Polkadot
pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" }
@@ -35,6 +37,8 @@ std = [
"codec/std",
"log/std",
"frame-support/std",
"pallet-asset-conversion/std",
"pallet-asset-tx-payment/std",
"parachains-common/std",
"cumulus-primitives-core/std",
"sp-api/std",
@@ -17,6 +17,7 @@
pub mod foreign_creators;
pub mod fungible_conversion;
pub mod local_and_foreign_assets;
pub mod matching;
pub mod runtime_api;
@@ -76,6 +77,20 @@ pub type ForeignAssetsConvertedConcreteId<AdditionalMultiLocationExclusionFilter
Balance,
>;
type AssetIdForPoolAssets = u32;
/// `MultiLocation` vs `AssetIdForPoolAssets` converter for `PoolAssets`.
pub type AssetIdForPoolAssetsConvert<PoolAssetsPalletLocation> =
AsPrefixedGeneralIndex<PoolAssetsPalletLocation, AssetIdForPoolAssets, JustTry>;
/// [`MatchedConvertedConcreteId`] converter dedicated for `PoolAssets`
pub type PoolAssetsConvertedConcreteId<PoolAssetsPalletLocation, Balance> =
MatchedConvertedConcreteId<
AssetIdForPoolAssets,
Balance,
StartsWith<PoolAssetsPalletLocation>,
AssetIdForPoolAssetsConvert<PoolAssetsPalletLocation>,
JustTry,
>;
#[cfg(test)]
mod tests {
use super::*;
@@ -0,0 +1,394 @@
// Copyright (C) 2021 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::local_and_foreign_assets::fungibles::Inspect;
use cumulus_primitives_core::InteriorMultiLocation;
use frame_support::{
pallet_prelude::DispatchError,
traits::{
fungibles::{
self, Balanced, Create, HandleImbalanceDrop, Mutate as MutateFungible, Unbalanced,
},
tokens::{DepositConsequence, Fortitude, Preservation, Provenance, WithdrawConsequence},
AccountTouch, ContainsPair, Get, PalletInfoAccess,
},
};
use pallet_asset_conversion::MultiAssetIdConverter;
use parachains_common::{AccountId, AssetIdForTrustBackedAssets};
use sp_runtime::{traits::MaybeEquivalence, DispatchResult};
use sp_std::{boxed::Box, marker::PhantomData};
use xcm::{latest::MultiLocation, opaque::lts::Junctions::Here};
use xcm_builder::AsPrefixedGeneralIndex;
use xcm_executor::traits::JustTry;
/// Whether the multilocation refers to an asset in the local assets pallet or not,
/// and if return the asset id.
fn is_local<TrustBackedAssetsPalletLocation: Get<MultiLocation>>(
multilocation: MultiLocation,
) -> Option<u32> {
AsPrefixedGeneralIndex::<TrustBackedAssetsPalletLocation, AssetIdForTrustBackedAssets, JustTry>::convert(&multilocation)
}
pub struct MultiLocationConverter<Balances, ParachainLocation: Get<InteriorMultiLocation>> {
_phantom: PhantomData<(Balances, ParachainLocation)>,
}
impl<Balances, ParachainLocation> MultiAssetIdConverter<Box<MultiLocation>, MultiLocation>
for MultiLocationConverter<Balances, ParachainLocation>
where
Balances: PalletInfoAccess,
ParachainLocation: Get<InteriorMultiLocation>,
{
fn get_native() -> Box<MultiLocation> {
Box::new(MultiLocation { parents: 0, interior: Here })
}
fn is_native(asset_id: &Box<MultiLocation>) -> bool {
let mut asset_id = asset_id.clone();
asset_id.simplify(&ParachainLocation::get());
*asset_id == *Self::get_native()
}
fn try_convert(asset_id: &Box<MultiLocation>) -> Result<MultiLocation, ()> {
let mut asset_id = asset_id.clone();
asset_id.simplify(&ParachainLocation::get());
if Self::is_native(&asset_id) {
// Otherwise it will try and touch the asset to create an account.
return Err(())
}
// Return simplified MultiLocation:
Ok(*asset_id)
}
fn into_multiasset_id(asset_id: &MultiLocation) -> Box<MultiLocation> {
let mut asset_id = *asset_id;
asset_id.simplify(&ParachainLocation::get());
Box::new(asset_id)
}
}
pub struct LocalAndForeignAssets<Assets, ForeignAssets, Location> {
_phantom: PhantomData<(Assets, ForeignAssets, Location)>,
}
impl<Assets, ForeignAssets, Location> Unbalanced<AccountId>
for LocalAndForeignAssets<Assets, ForeignAssets, Location>
where
Location: Get<MultiLocation>,
ForeignAssets: Inspect<AccountId, Balance = u128, AssetId = MultiLocation>
+ Unbalanced<AccountId>
+ Balanced<AccountId>,
Assets: Inspect<AccountId, Balance = u128, AssetId = u32>
+ Unbalanced<AccountId>
+ Balanced<AccountId>
+ PalletInfoAccess,
{
fn handle_dust(dust: frame_support::traits::fungibles::Dust<AccountId, Self>) {
let credit = dust.into_credit();
if let Some(asset) = is_local::<Location>(credit.asset()) {
Assets::handle_raw_dust(asset, credit.peek());
} else {
ForeignAssets::handle_raw_dust(credit.asset(), credit.peek());
}
// As we have already handled the dust, we must stop credit's drop from happening:
sp_std::mem::forget(credit);
}
fn write_balance(
asset: <Self as frame_support::traits::fungibles::Inspect<AccountId>>::AssetId,
who: &AccountId,
amount: <Self as frame_support::traits::fungibles::Inspect<AccountId>>::Balance,
) -> Result<
Option<<Self as frame_support::traits::fungibles::Inspect<AccountId>>::Balance>,
sp_runtime::DispatchError,
> {
if let Some(asset) = is_local::<Location>(asset) {
Assets::write_balance(asset, who, amount)
} else {
ForeignAssets::write_balance(asset, who, amount)
}
}
/// Set the total issuance of `asset` to `amount`.
fn set_total_issuance(asset: Self::AssetId, amount: Self::Balance) {
if let Some(asset) = is_local::<Location>(asset) {
Assets::set_total_issuance(asset, amount)
} else {
ForeignAssets::set_total_issuance(asset, amount)
}
}
}
impl<Assets, ForeignAssets, Location> Inspect<AccountId>
for LocalAndForeignAssets<Assets, ForeignAssets, Location>
where
Location: Get<MultiLocation>,
ForeignAssets: Inspect<AccountId, Balance = u128, AssetId = MultiLocation>,
Assets: Inspect<AccountId, Balance = u128, AssetId = u32>,
{
type AssetId = MultiLocation;
type Balance = u128;
/// The total amount of issuance in the system.
fn total_issuance(asset: Self::AssetId) -> Self::Balance {
if let Some(asset) = is_local::<Location>(asset) {
Assets::total_issuance(asset)
} else {
ForeignAssets::total_issuance(asset)
}
}
/// The minimum balance any single account may have.
fn minimum_balance(asset: Self::AssetId) -> Self::Balance {
if let Some(asset) = is_local::<Location>(asset) {
Assets::minimum_balance(asset)
} else {
ForeignAssets::minimum_balance(asset)
}
}
/// Get the `asset` balance of `who`.
fn balance(asset: Self::AssetId, who: &AccountId) -> Self::Balance {
if let Some(asset) = is_local::<Location>(asset) {
Assets::balance(asset, who)
} else {
ForeignAssets::balance(asset, who)
}
}
/// Get the maximum amount of `asset` that `who` can withdraw/transfer successfully.
fn reducible_balance(
asset: Self::AssetId,
who: &AccountId,
presevation: Preservation,
fortitude: Fortitude,
) -> Self::Balance {
if let Some(asset) = is_local::<Location>(asset) {
Assets::reducible_balance(asset, who, presevation, fortitude)
} else {
ForeignAssets::reducible_balance(asset, who, presevation, fortitude)
}
}
/// Returns `true` if the `asset` balance of `who` may be increased by `amount`.
///
/// - `asset`: The asset that should be deposited.
/// - `who`: The account of which the balance should be increased by `amount`.
/// - `amount`: How much should the balance be increased?
/// - `mint`: Will `amount` be minted to deposit it into `account`?
fn can_deposit(
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance,
mint: Provenance,
) -> DepositConsequence {
if let Some(asset) = is_local::<Location>(asset) {
Assets::can_deposit(asset, who, amount, mint)
} else {
ForeignAssets::can_deposit(asset, who, amount, mint)
}
}
/// Returns `Failed` if the `asset` balance of `who` may not be decreased by `amount`, otherwise
/// the consequence.
fn can_withdraw(
asset: Self::AssetId,
who: &AccountId,
amount: Self::Balance,
) -> WithdrawConsequence<Self::Balance> {
if let Some(asset) = is_local::<Location>(asset) {
Assets::can_withdraw(asset, who, amount)
} else {
ForeignAssets::can_withdraw(asset, who, amount)
}
}
/// Returns `true` if an `asset` exists.
fn asset_exists(asset: Self::AssetId) -> bool {
if let Some(asset) = is_local::<Location>(asset) {
Assets::asset_exists(asset)
} else {
ForeignAssets::asset_exists(asset)
}
}
fn total_balance(
asset: <Self as frame_support::traits::fungibles::Inspect<AccountId>>::AssetId,
account: &AccountId,
) -> <Self as frame_support::traits::fungibles::Inspect<AccountId>>::Balance {
if let Some(asset) = is_local::<Location>(asset) {
Assets::total_balance(asset, account)
} else {
ForeignAssets::total_balance(asset, account)
}
}
}
impl<Assets, ForeignAssets, Location> MutateFungible<AccountId>
for LocalAndForeignAssets<Assets, ForeignAssets, Location>
where
Location: Get<MultiLocation>,
ForeignAssets: MutateFungible<AccountId, Balance = u128>
+ Inspect<AccountId, Balance = u128, AssetId = MultiLocation>
+ Balanced<AccountId>,
Assets: MutateFungible<AccountId>
+ Inspect<AccountId, Balance = u128, AssetId = u32>
+ Balanced<AccountId>
+ PalletInfoAccess,
{
/// Transfer funds from one account into another.
fn transfer(
asset: MultiLocation,
source: &AccountId,
dest: &AccountId,
amount: Self::Balance,
keep_alive: Preservation,
) -> Result<Self::Balance, DispatchError> {
if let Some(asset_id) = is_local::<Location>(asset) {
Assets::transfer(asset_id, source, dest, amount, keep_alive)
} else {
ForeignAssets::transfer(asset, source, dest, amount, keep_alive)
}
}
}
impl<Assets, ForeignAssets, Location> Create<AccountId>
for LocalAndForeignAssets<Assets, ForeignAssets, Location>
where
Location: Get<MultiLocation>,
ForeignAssets: Create<AccountId> + Inspect<AccountId, Balance = u128, AssetId = MultiLocation>,
Assets: Create<AccountId> + Inspect<AccountId, Balance = u128, AssetId = u32>,
{
/// Create a new fungible asset.
fn create(
asset_id: Self::AssetId,
admin: AccountId,
is_sufficient: bool,
min_balance: Self::Balance,
) -> DispatchResult {
if let Some(asset_id) = is_local::<Location>(asset_id) {
Assets::create(asset_id, admin, is_sufficient, min_balance)
} else {
ForeignAssets::create(asset_id, admin, is_sufficient, min_balance)
}
}
}
impl<Assets, ForeignAssets, Location> AccountTouch<MultiLocation, AccountId>
for LocalAndForeignAssets<Assets, ForeignAssets, Location>
where
Location: Get<MultiLocation>,
ForeignAssets: AccountTouch<MultiLocation, AccountId, Balance = u128>,
Assets: AccountTouch<u32, AccountId, Balance = u128>,
{
type Balance = u128;
fn deposit_required(
asset_id: MultiLocation,
) -> <Self as AccountTouch<MultiLocation, AccountId>>::Balance {
if let Some(asset_id) = is_local::<Location>(asset_id) {
Assets::deposit_required(asset_id)
} else {
ForeignAssets::deposit_required(asset_id)
}
}
fn touch(
asset_id: MultiLocation,
who: AccountId,
depositor: AccountId,
) -> Result<(), sp_runtime::DispatchError> {
if let Some(asset_id) = is_local::<Location>(asset_id) {
Assets::touch(asset_id, who, depositor)
} else {
ForeignAssets::touch(asset_id, who, depositor)
}
}
}
/// Implements [`ContainsPair`] trait for a pair of asset and account IDs.
impl<Assets, ForeignAssets, Location> ContainsPair<MultiLocation, AccountId>
for LocalAndForeignAssets<Assets, ForeignAssets, Location>
where
Location: Get<MultiLocation>,
ForeignAssets: ContainsPair<MultiLocation, AccountId>,
Assets: PalletInfoAccess + ContainsPair<u32, AccountId>,
{
/// Check if an account with the given asset ID and account address exists.
fn contains(asset_id: &MultiLocation, who: &AccountId) -> bool {
if let Some(asset_id) = is_local::<Location>(*asset_id) {
Assets::contains(&asset_id, &who)
} else {
ForeignAssets::contains(&asset_id, &who)
}
}
}
impl<Assets, ForeignAssets, Location> Balanced<AccountId>
for LocalAndForeignAssets<Assets, ForeignAssets, Location>
where
Location: Get<MultiLocation>,
ForeignAssets:
Balanced<AccountId> + Inspect<AccountId, Balance = u128, AssetId = MultiLocation>,
Assets:
Balanced<AccountId> + Inspect<AccountId, Balance = u128, AssetId = u32> + PalletInfoAccess,
{
type OnDropDebt = DebtDropIndirection<Assets, ForeignAssets, Location>;
type OnDropCredit = CreditDropIndirection<Assets, ForeignAssets, Location>;
}
pub struct DebtDropIndirection<Assets, ForeignAssets, Location> {
_phantom: PhantomData<LocalAndForeignAssets<Assets, ForeignAssets, Location>>,
}
impl<Assets, ForeignAssets, Location> HandleImbalanceDrop<MultiLocation, u128>
for DebtDropIndirection<Assets, ForeignAssets, Location>
where
Location: Get<MultiLocation>,
ForeignAssets:
Balanced<AccountId> + Inspect<AccountId, Balance = u128, AssetId = MultiLocation>,
Assets: Balanced<AccountId> + Inspect<AccountId, Balance = u128, AssetId = u32>,
{
fn handle(asset: MultiLocation, amount: u128) {
if let Some(asset_id) = is_local::<Location>(asset) {
Assets::OnDropDebt::handle(asset_id, amount);
} else {
ForeignAssets::OnDropDebt::handle(asset, amount);
}
}
}
pub struct CreditDropIndirection<Assets, ForeignAssets, Location> {
_phantom: PhantomData<LocalAndForeignAssets<Assets, ForeignAssets, Location>>,
}
impl<Assets, ForeignAssets, Location> HandleImbalanceDrop<MultiLocation, u128>
for CreditDropIndirection<Assets, ForeignAssets, Location>
where
Location: Get<MultiLocation>,
ForeignAssets:
Balanced<AccountId> + Inspect<AccountId, Balance = u128, AssetId = MultiLocation>,
Assets: Balanced<AccountId> + Inspect<AccountId, Balance = u128, AssetId = u32>,
{
fn handle(asset: MultiLocation, amount: u128) {
if let Some(asset_id) = is_local::<Location>(asset) {
Assets::OnDropCredit::handle(asset_id, amount);
} else {
ForeignAssets::OnDropCredit::handle(asset, amount);
}
}
}
@@ -17,8 +17,8 @@
use codec::{Codec, Decode, Encode};
use frame_support::RuntimeDebug;
use sp_std::vec::Vec;
use xcm::latest::MultiAsset;
#[cfg(feature = "std")]
use {sp_std::vec::Vec, xcm::latest::MultiAsset};
/// The possible errors that can happen querying the storage of assets.
#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug, scale_info::TypeInfo)]
@@ -108,6 +108,7 @@ std = [
"pallet-xcm/std",
"polkadot-primitives/std",
"parachain-info/std",
"parachains-common/std",
"polkadot-parachain/std",
"polkadot-runtime-common/std",
"sp-api/std",
+1
View File
@@ -49,6 +49,7 @@ std = [
"frame-system/std",
"pallet-balances/std",
"pallet-sudo/std",
"pallet-glutton/std",
"pallet-timestamp/std",
"pallet-transaction-payment/std",
"pallet-glutton/std",