-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Treasury Spend Detects Relative Locations of Native Asset #233
Treasury Spend Detects Relative Locations of Native Asset #233
Conversation
V3 { location, asset_id } => (location.try_into()?, asset_id.try_into()?), | ||
V4 { location, asset_id } => (location, asset_id), | ||
}; | ||
if asset_id.0.contains_parents_only(1) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the Relay Chain, wouldn't this be contains_parents_only(0)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
asset_id
will be relative to the parachain, this is why it's only parent 1
when I tried (0, here) on Asset Hub, it was not recognised as native asset, only (1, here)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, this is checking a message from AH, and it hasn't been reanchored.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Treasury pallet receives the locatable asset as
VersionedLocatableAsset: {
`location`: (0, Parachain(1000)),
`asset_id`: (1, Here),
}
and it should know it's a native asset
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated the PR description to include the example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should add it to this type's (or impl's) doc comment as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few questions, mostly about origins/locations.
...ation-tests/emulated/tests/collectives/collectives-polkadot/src/tests/fellowship_treasury.rs
Outdated
Show resolved
Hide resolved
as_origin: bx!(OriginCaller::system(RawOrigin::Signed(treasury_account))), | ||
call: bx!(RuntimeCall::XcmPallet(pallet_xcm::Call::<Runtime>::teleport_assets { | ||
dest: bx!(VersionedLocation::V4(asset_hub_location.clone())), | ||
beneficiary: bx!(VersionedLocation::V4(treasury_location_on_asset_hub)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting that the beneficiary is actually the Location
of the Relay's Treasury pallet and not the converted local Account ID.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the implementation Pay
trait which used to execute the spend uses xcm TransferAsset
instruction, we can use the pallet's location from which the xcm-executor will derive the account id.
// Dispatched from Root to `despatch_as` `Signed(treasury_account)`. | ||
assert_ok!(teleport_call.dispatch(root)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We allow Treasurer
to send messages. Could we just do a referendum to teleport_assets
on the Treasurer track?
https://github.com/polkadot-fellows/runtimes/blob/ba359a4/relay/polkadot/src/xcm_config.rs#L286
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the type SovereignAccountOf
we will need to associate a Treasurer Origin with Treasury::account_id(). Not sure if this is right, I think pallet's location account id can be Treasury::account_id(). And also it would mean that Treasurer Origin can spend any amount from Treasury.
let treasury_origin: RuntimeOrigin = | ||
polkadot_runtime::governance::pallet_custom_origins::Origin::Treasurer.into(); | ||
let fellowship_treasury_location: Location = | ||
Location::new(1, [Parachain(1001), PalletInstance(65)]); | ||
let asset_hub_location: Location = [Parachain(1000)].into(); | ||
let native_asset_on_asset_hub = Location::parent(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
treasury_origin
is on the Relay Chain, but all the others are defined from the perspective of Asset Hub. Got a bit confused with this. Perhaps a comment to clarify?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
asset_kind = {
location - or destination, from the perspective of Relay Chain,
asset_id - from the perspective of asset_kind.location
}
beneficiary - from the perspective of asset_kind.location
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add that as a comment in the code maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have all this documented in the functions' docs.
Co-authored-by: joe petrowski <[email protected]>
integration-tests/emulated/tests/collectives/collectives-polkadot/src/lib.rs
Outdated
Show resolved
Hide resolved
{ | ||
Ok(balance) | ||
} else { | ||
I::from_asset_balance(balance, asset_kind).map_err(|_| ()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This hinders debuggability. Can you please log the error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this particular case, upstream we do not really care about type of error and there is only one reason for error.
But for a general implementation I will add the log.
{ | ||
Ok(balance) | ||
} else { | ||
I::from_asset_balance(balance, asset_kind).map_err(|_| ()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
system-parachains/collectives/collectives-polkadot/src/impls.rs
Outdated
Show resolved
Hide resolved
{ | ||
Ok(balance) | ||
} else { | ||
I::from_asset_balance(balance, asset_kind).map_err(|_| ()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dont understand enough of the code, so please consider further review before merging.
…achain-for-asset-rate
@acatangiu can you please check this PR |
@bkchr can you please check this PR |
system-parachains/collectives/collectives-polkadot/src/impls.rs
Outdated
Show resolved
Hide resolved
Co-authored-by: Branislav Kontur <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The whole LocatableAsset
thing seems very convoluted, it'd be good to simplify it in the future.
It looks like it works though
integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/treasury.rs
Show resolved
Hide resolved
integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/treasury.rs
Outdated
Show resolved
Hide resolved
integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/treasury.rs
Outdated
Show resolved
Hide resolved
|
||
let native_asset = Location::here(); | ||
let asset_hub_location: Location = [Parachain(1000)].into(); | ||
let treasury_location_on_asset_hub: Location = (Parent, PalletInstance(18)).into(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name is confusing. Previous variables are relative to the relay, this one starts with Parent
but says on_asset_hub
, leading to believe that it should be relative to the relay as well.
Looks like you want the relay's treasury sovereign account. I'd probably name it relay_treasury_location
and add a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I try to avoid a prefix relay for the treasury. We have only one the Treasury, or the Polkadot/Kusama Treasury, which eventually will move from Relay chain. I rename it to treasury_location
.
integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/treasury.rs
Outdated
Show resolved
Hide resolved
|
||
let native_asset = Location::here(); | ||
let asset_hub_location: Location = [Parachain(1000)].into(); | ||
let treasury_location_on_asset_hub: Location = (Parent, PalletInstance(19)).into(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pallet index is different, should this be called collectives_treasury_location
?
Also, maybe add a constant for the magic number 19 or even get it from the pallet itself with PalletAccessInfo
, that'd be great
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's different, because this is polkadot's treasury
let treasury_origin: RuntimeOrigin = | ||
polkadot_runtime::governance::pallet_custom_origins::Origin::Treasurer.into(); | ||
let fellowship_treasury_location: Location = | ||
Location::new(1, [Parachain(1001), PalletInstance(65)]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I definitely think we should try to access the actual pallet's index for these locations
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not have that strong opinion about this. When I use literals, I want this test fail if for some reason pallet's index changes.
let treasury_origin: RuntimeOrigin = | ||
polkadot_runtime::governance::pallet_custom_origins::Origin::Treasurer.into(); | ||
let fellowship_treasury_location: Location = | ||
Location::new(1, [Parachain(1001), PalletInstance(65)]); | ||
let asset_hub_location: Location = [Parachain(1000)].into(); | ||
let native_asset_on_asset_hub = Location::parent(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add that as a comment in the code maybe?
V3 { location, asset_id } => (location.try_into()?, asset_id.try_into()?), | ||
V4 { location, asset_id } => (location, asset_id), | ||
}; | ||
if asset_id.0.contains_parents_only(1) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should add it to this type's (or impl's) doc comment as well
Do you have an idea how? The origin for the current structure comes from this type - https://github.com/paritytech/polkadot-sdk/blob/430ad2f5610dc3d53b4708c651617e34affa97f7/polkadot/xcm/xcm-builder/src/pay.rs#L193 |
system-parachains/collectives/collectives-polkadot/src/fellowship/mod.rs
Outdated
Show resolved
Hide resolved
system-parachains/collectives/collectives-polkadot/src/fellowship/mod.rs
Outdated
Show resolved
Hide resolved
system-parachains/collectives/collectives-polkadot/src/fellowship/mod.rs
Outdated
Show resolved
Hide resolved
integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/treasury.rs
Outdated
Show resolved
Hide resolved
integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/treasury.rs
Outdated
Show resolved
Hide resolved
integration-tests/emulated/tests/assets/asset-hub-kusama/src/tests/treasury.rs
Outdated
Show resolved
Hide resolved
Co-authored-by: Branislav Kontur <[email protected]>
Co-authored-by: Branislav Kontur <[email protected]>
pub struct NativeOnSystemParachain<I>(PhantomData<I>); | ||
impl<I> ConversionFromAssetBalance<Balance, VersionedLocatableAsset, Balance> | ||
for NativeOnSystemParachain<I> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub struct NativeOnSystemParachain<I>(PhantomData<I>); | |
impl<I> ConversionFromAssetBalance<Balance, VersionedLocatableAsset, Balance> | |
for NativeOnSystemParachain<I> | |
pub struct NativeOnSystemParachainElseConvertWith<I>(PhantomData<I>); | |
impl<I> ConversionFromAssetBalance<Balance, VersionedLocatableAsset, Balance> | |
for NativeOnSystemParachainElseConvertWith<I> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like my version more, I personally prefer short and laconic names with docs, instead long names.
But if you get one more vote for your rename suggestion, I rename
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well, I don't mind longer names if they are self-describing :)
e.g. NativeOnSiblingParachain does not mention in the docs that it filters just system parachains, so I think at least NativeOnSystemParachain or NativeOnSiblingSystemParachain is better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well, I don't mind longer names if they are self-describing :) e.g. NativeOnSiblingParachain does not mention in the docs that it filters just system parachains, so I think at least NativeOnSystemParachain or NativeOnSiblingSystemParachain is better
@muharem to avoid any confusions (e.g. NativeOnSibling, can be ACA or whatever), why not to just rename all of NativeOnSiblingParachain
and NativeOnSystemParachain
to the final UnityOrOuterConversion
temporary with several impls here? When we do polkadot-sdk bump with paritytech/polkadot-sdk#3659, it wil just "change imports"
pub struct NativeOnSystemParachain<I>(PhantomData<I>); | ||
impl<I> ConversionFromAssetBalance<Balance, VersionedLocatableAsset, Balance> | ||
for NativeOnSystemParachain<I> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub struct NativeOnSystemParachain<I>(PhantomData<I>); | |
impl<I> ConversionFromAssetBalance<Balance, VersionedLocatableAsset, Balance> | |
for NativeOnSystemParachain<I> | |
pub struct NativeOnSystemParachainElseConvertWith<I>(PhantomData<I>); | |
impl<I> ConversionFromAssetBalance<Balance, VersionedLocatableAsset, Balance> | |
for NativeOnSystemParachainElseConvertWith<I> |
pub struct NativeOnSiblingParachain<I, SelfParaId>(PhantomData<(I, SelfParaId)>); | ||
impl<I, SelfParaId> ConversionFromAssetBalance<Balance, VersionedLocatableAsset, Balance> | ||
for NativeOnSiblingParachain<I, SelfParaId> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pub struct NativeOnSiblingParachain<I, SelfParaId>(PhantomData<(I, SelfParaId)>); | |
impl<I, SelfParaId> ConversionFromAssetBalance<Balance, VersionedLocatableAsset, Balance> | |
for NativeOnSiblingParachain<I, SelfParaId> | |
pub struct NativeOnSystemParachainElseConvertWith<I, SelfParaId>(PhantomData<(I, SelfParaId)>); | |
impl<I, SelfParaId> ConversionFromAssetBalance<Balance, VersionedLocatableAsset, Balance> | |
for NativeOnSystemParachainElseConvertWith<I, SelfParaId> |
if asset_id.0.contains_parents_only(1) && | ||
IsSiblingSystemParachain::<ParaId, SelfParaId>::contains(&location) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the NativeOnSiblingParachain
for collectives and NativeOnSystemParachain
for relays are "almost" the same implementation and differ only with the different ::contains(&location)
implementation for matching system parachains.
I'm also not sure about the same asset_id.0.contains_parents_only(1)
in both implementations, but regardless of that, they are exactly the same. I would suggest creating just one generic implementation and placing it in the polkadot-sdk
repository somewhere. As a temporary solution, with a TODO, it could be placed in the system-parachains-constants
repository. Yes, it may be ugly, but it serves the purpose. Alternatively, you could copy the exact same generic implementation where needed and remove it later.
Suggested generic implementation:
pub struct NativeOnSystemParachainElseConvertWith<I, N, IsSystemParachain>(PhantomData<(I, N, IsSystemParachain)>);
impl<I, N, IsSystemParachain> ConversionFromAssetBalance<Balance, VersionedLocatableAsset, Balance>
for NativeOnSystemParachainElseConvertWith<I, N, IsSystemParachain>
where
I: ConversionFromAssetBalance<Balance, VersionedLocatableAsset, Balance>,
IsNativeAsset: Contains<Location> // <-- or maybe Contains<AssetId>?, we have already matchers for Contains<Location>
IsSystemParachain: Contains<Location>,
{
type Error = ();
fn from_asset_balance(
balance: Balance,
asset_kind: VersionedLocatableAsset,
) -> Result<Balance, Self::Error> {
use VersionedLocatableAsset::*;
let (location, asset_id) = match asset_kind.clone() {
V3 { location, asset_id } => (location.try_into()?, asset_id.try_into()?),
V4 { location, asset_id } => (location, asset_id),
};
if IsNativeAsset::contains(asset_id.0) && IsSystemParachain::contains(&location)
{
Ok(balance)
} else {
I::from_asset_balance(balance, asset_kind).map_err(|_| ())
}
}
#[cfg(feature = "runtime-benchmarks")]
fn ensure_successful(asset_kind: VersionedLocatableAsset) {
I::ensure_successful(asset_kind)
}
}
so with this one generic implementation, it can be used for both:
// for collectives
type BalanceConverter = NativeOnSystemParachainElseConvertWith<
AssetRate,
Equals<xcm_config::DotLocation>
IsSiblingSystemParachain<ParaId, ParachainInfo>,
>;
// for relays
type BalanceConverter = NativeOnSystemParachainElseConvertWith<
AssetRate,
(
Equals<DotLocation>
Equals<DotLocationWithParent1> // <- kind of OR matching
),
IsChildSystemParachain::<ParaId>,
>;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR description referes to polkadot-sdk version - paritytech/polkadot-sdk#3659
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR description referes to polkadot-sdk version - paritytech/polkadot-sdk#3659
ahaaa, ok, I see, looks like it does exactly the same even more generic way, cool :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm, as it will be changed later by paritytech/polkadot-sdk#3659
@ordian can you please check this PR |
/merge |
/merge |
Enabled Available commands
For more information see the documentation |
3ae3d29
into
polkadot-fellows:main
Introduce teleport and whitelist call tests for Polkadot Collectives. Based on #233 - [x] Does not require a CHANGELOG entry --------- Co-authored-by: joe petrowski <[email protected]> Co-authored-by: Branislav Kontur <[email protected]>
Treasury Spend detects the relative locations of native asset to compare origin's spend limits.
When a spend is approved for a native asset located on Asset Hub, the AssetRate pallet instance does not recognize the location (parent: 1, here) as a native asset. Therefore, it requires the asset rate to be set in advance to the rate of
1
. To address this issue in this PR, we introduce new types to wrap theAssetRate
implementation of balance conversion. These types match the native asset's relative locations and result in a 1:1 balance conversion in such cases.In addition we provide integration tests to cover these cases.
Examples:
Treasury pallet on Relay Chain accepts the spend of the native asset on Asset Hub with it's ID presented as
VersionedLocatableAsset
typeand it's balance should be converted 1:1 by treasury pallet's
BalanceConverter
type.Note: I plan to introduce a similar but configurable implementation in the polkadot-sdk and utilize it here. However, to get this change in the next release, I open this PR first.
Frame version: paritytech/polkadot-sdk#3659