-
Notifications
You must be signed in to change notification settings - Fork 300
feat: asset registry #728
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
feat: asset registry #728
Conversation
I think we should still require some basic fields like name, symbol, decimals. otherwise the js sdk still need specialized code to handle it for different parachains. |
Codecov Report
@@ Coverage Diff @@
## master paritytech/polkadot#728 +/- ##
==========================================
- Coverage 77.68% 77.67% -0.01%
==========================================
Files 92 100 +8
Lines 9069 9598 +529
==========================================
+ Hits 7045 7455 +410
- Misses 2024 2143 +119
📣 Codecov can now indicate which changes are the most critical in Pull Requests. Learn more |
I agree with xlc - that some basic information can be already part of the pallet ( name,symbol, decimals). personally, i would not require |
Sure, I added name, symbol, decimals and multilocation.
When I added default fields, I also added the (multi)location. Are you opposed to this? Do you think it should be an optional item? Or should it be removed as a default field altogether? |
I might be wrong here - but i think, if you set a location for asset and then xcm config is set to map asset and locations - that will make the asset automatically transferable. which is probably fine, that's why you add foreign assets in first place. but not all assets need location, and not all asset are transferable. For example - in HydraDX's xyk pool - we use asset registry to register 'share asset' for each subpool as another asset in the system. However, this asset does not need location nor it can be transferred somewhere else. |
Thank you for the clarification, that makes sense indeed. I changed the location to be a |
What about existential deposit / min balance ? I believe this could be one of the required fields too. i think that it would be useful if you could also plug asset registry to eg. orml_tokens's config Eg. in our asset-registry here. |
Agreed, added. |
I cleaned the code up a bit and added some tests, including some that show that it can be used in xcm transfers. From my PoV, this PR is ready to be reviewed. There is one thing that I still need address: the default weights. For the other pallets, the default weights are generated with One more note on the |
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.
not 100% sure if we want all the XCM weight related code in this pallet. I guess we don't really want another crate just for that so it is probably fine.
|
||
#[pallet::pallet] | ||
#[pallet::generate_store(pub(super) trait Store)] | ||
#[pallet::without_storage_info] |
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.
should use bonded types, but that can happen in later PR
other than nits it is good for a V1 |
pub struct MyFixedConversionRateProvider; | ||
impl FixedConversionRateProvider for MyFixedConversionRateProvider { | ||
fn get_fee_per_second(location: &MultiLocation) -> Option<u128> { | ||
let metadata = AssetRegistry::fetch_metadata_by_location(location)?; | ||
Some(metadata.additional.fee_per_second) | ||
} | ||
} |
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.
Can this move to impl.rs, I think this is a common implementation.
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 can't - the fee_per_second is part of the custom metadata rather than the default metadata.
Edit: unless we make the impl generic over some callback Fn(Metadata) -> Option<Balance>
- should we?
asset-registry/src/impls.rs
Outdated
let new_weight = existing_weight.saturating_add(weight); | ||
|
||
if let Some(amount) = W::convert_weight_to_fee(location, new_weight) { | ||
let fee_increase = amount.saturating_sub(existing_fee); |
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 might miss something, but not sure why adding weight to existing to get new_weight
first, then convert to fee and subtract. Simply converting weight
to fee should have the same result no?
And the embedded if
/if let
checks could be flattened for readability, such as:
if let Some(amount) = W::convert_weight_to_fee(location, new_weight) {
-->
let amount = W::convert_weight_to_fee(location, new_weight).ok_or(XcmError::TooExpensive)?;
// ...
Also
if fee_increase == 0 {
return Ok(payment);
} else if let Ok(unused) = payment.clone().checked_sub((asset.clone(), fee_increase).into()) {
-->
if fee_increase == 0 {
return Ok(payment);
}
let unused = payment.clone().checked_sub((asset.clone(), fee_increase).into()).ok_or(XcmError::TooExpensive)?;
// ...
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 might miss something, but not sure why adding weight to existing to get new_weight first, then convert to fee and subtract. Simply converting weight to fee should have the same result no?
It's equivalent only when convert_weight_to_fee
is a linear function, which it is not guaranteed to be. Though maybe I'm overcomplicating things - I don't expect to see non-linear functions being used in practice..
And the embedded if/if let checks could be flattened for readability, such as:
if let Some(amount) = W::convert_weight_to_fee(location, new_weight) {
-->
let amount = W::convert_weight_to_fee(location, new_weight).ok_or(XcmError::TooExpensive)?;
That would stop the iteration over the assets in payment.fungible
. The same applies for the last refactoring you suggest
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 don't see non-linear functions being used either. AFAIK ppl are all using fixed rate conversions, specifically the fixed rate weight traders implemented in Polkadot repo.
IMO we can simply aim for the same impl to provide a fixed rate trader. It's easier to use and maintain.
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 suggest to change update_asset
dispatchable call signature to
pub fn update_asset(
origin: OriginFor<T>,
asset_id: T::AssetId,
decimals: Option<u32>,
name: Option<Vec<u8>>,
// ... rest fields wrapped in `Option`
) -> DispatchResult
The impl checks every field and update it if Some
. Note location
needs to be Option<Option<VersionedMultiLocation>>
.
The rationale behind it is that in most cases, only one field will be updated, but the current call requires to copy all existing unchanged ones, which is unnecessary and prone to mistakes. Additionally, set_asset_location
call can be merged into this one.
I think I've addressed all comments - PR should be ready for final review pass & merging |
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. A few more trivial issues and I think we are good to go.
asset-registry/src/impls.rs
Outdated
let new_weight = existing_weight.saturating_add(weight); | ||
|
||
if let Some(amount) = W::convert_weight_to_fee(location, new_weight) { | ||
let fee_increase = amount.saturating_sub(existing_fee); |
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 don't see non-linear functions being used either. AFAIK ppl are all using fixed rate conversions, specifically the fixed rate weight traders implemented in Polkadot repo.
IMO we can simply aim for the same impl to provide a fixed rate trader. It's easier to use and maintain.
Fixed the last comments and rebased (and squashed) the branch. |
This is meant to address #721.
This PR will need cleanup, tests, etc, but I'm opening this as a draft now to get some feedback regarding the direction. Some things to note about the implementation:
WeightTrader::refund_weight
allows only a single asset to be refunded, the default implementation does not support paying with different assets. That is, it can pay with any asset in the registry, but only one asset per xcm message. I opened WeightTrader refund limitations paritytech/polkadot-sdk#836 to see ifrefund_weight
can refund multiple assets in the future.An example of usage:
I would love to get some feedback on this. I'm out of office until tuesday though so might not be able to address any comments until then.