Closed xlc closed 1 month ago
Hello, with the migration to the polkadot-sdk single project, are there any updates relative to the ability to estimate XCM fees?
@xlc gentle nudge
Don’t nudge me, I am the one asking question and hoping someone else will answer me as well.
CC @franciscoaguirre
@bkchr - would be great if someone from Dev Fellowship could comment on this and let interested parties know if and when this might be addressed.
We see this as a limitation to the Dynamic fee mechanism on Moonbeam and should XCM continue to get traction, this will prove to be a problem for others.
If you are not the right person to ping on this, is there a better way to get someone from the fellowship to take a look and provide some guidance?
Thanks in advance
I’m also aware of this behaviour, but am unsure what the best solution would be. Can you elaborate on the desired/ideal UX, and we can work backwards from that to fix/improve fee handling?
We can take a look at this in the next XCM retreat, but in the meantime if you have any specific proposal for improvement, perhaps you can put it in an RFC.
What about multi-hop XCMs? For example, going through a reserve chain C for transferring TokenC
from A to B, or going over a bridge.
Runtime API to dry run XCM and returns outcome and fees and weights. If all the fees are deducted from fee register, then it is simply calculate how much is deducted from it.
Having this ^ would allow UIs to call into each runtime for every hop to query fees, but they'd be "guessing" what the intermediary XCMs look like. Probably we'd need to provide these intermediaries too as part of the dry-run. As in: Dry-run this XCM, you get back execution cost/weight, delivery cost to first hop, first hop location, and XCM to be sent to first hop, then you repeat dry-runs with new intermediary XCMs for each hop to destination.
But I'm secretly hoping there's a better/smarter way to do it..
Unfortunately, it is most likely that you will need to query multiple chains for a multi hop XCM execution. I just cannot see any way around it. But at least someone could build an SDK to abstract all those complex logics. and with light clients and the new polkadot-api (which I don't know what it is because there are zero docs exists), it should be possible to make the consumer side relatively easy.
There is BuyExecution { fees: Asset, weight_limit: WeightLimit }
, user can set the asset id to be used from registry and the weight limit. But no separate fee registry.
And there is a runtime api to query a weight and an estimated fee for for a call - link.
It would be nice to hear what we need on top of it.
Part of https://github.com/paritytech/polkadot-sdk/issues/3434#issuecomment-1961353598:
Current proposal is to provide runtime apis (callable from on-chain or off-chain) to effectively "dry-run" an XCM program, providing info on things like:
The same runtime API can then be called off-chain recursively on [intermediary, +] destination chains dry-running the XCMs got in 2. from previous hop.
This way a wallet/dapp can dry-run the e2e path and get fees for each step.
This runtime API can be later genericized/replaced with a new XCQ mechanism to get the same info (and more) using generic chain-agnostic queries (rather than chain-specific runtime api calls).
Further, ideas were also discussed for some mechanism to actively lock-in the fee-price, to avoid synchronization issues between querying and executing.
Now that we have the XCM fee payment runtime API, we need a higher level runtime API UIs can use to estimate fees for the most common operations users do, starting with reserve asset transfers and teleports. These would need to fit well with pallet-xcm's transfer_assets
and xtokens' transfer
at a minimum.
I see two options, either we create a runtime API that returns the fees needed to be paid for each transfer type, or one that just returns the message that will be executed and the message that would be sent. I lean towards the second one. Given those messages, the UI could call the lower level API for getting the fees. This has the benefit we don't need to replicate the weight and valid assets thing on the higher level API. The downside is UIs would have to call two APIs instead of one, but they could cache the response of one of them for some time if that's a problem.
Ongoing conversation happening in https://github.com/paritytech/polkadot-sdk/pull/3872
Cross-posting here as well:
I was discussing something similar with @franciscoaguirre, exploring something similar:
pub struct XcmDryRunEffects {
forwarded_xcms: Vec<(Location, Xcm<()>)>,
fees_spent_locally: MultiAssets,
// maybe more?
}
pub trait DryRunXcmApi {
/// query side effects for executing extrinsic
fn query_xcm_for_extrinsic(
xt: <Block as BlockT>::Extrinsic, // extrinsic to dry-run
query_side_effects: FnMut(), // optional closure to implement any custom logic
// for custom querying dry-run side-effects
// (balances changes, any particular storage changes)
) -> Result<XcmDryRunEffects, /* ErrT */>;
/// query side effects for executing (incoming) XCM
fn query_execute_xcm(
xcm: Xcm<()>,
using_origin: Location,
query_side_effects: FnMut(),
) -> Result<XcmDryRunEffects, /* ErrT */>;
}
We want to:
Runtime
before fn is done and temp db layer with side effects is dropped.Would this be enough to cover all needs?
(Changed title to clarify this issue is now specialized on the ability to estimate total fees across multiple chains for cross-chain messages)
The other side of the problem, namely how transport fees are actually charged in the executor is being tracked and discussed in https://github.com/paritytech/polkadot-sdk/issues/3434
Now that the XcmDryRunApi was merged. There are still some next steps:
https://github.com/paritytech/polkadot/blob/543462890784d6cd17b6c6f58b73c94d3b32a65d/xcm/xcm-executor/src/lib.rs#L242-L251
Right now it withdraw the fee from origin account directly. This is just bad.
UI will have hard time to estimate the actual fee. User have no way to limit the fee amount.
I don't think right now it is possible to estimate fee of a XCM. We can estimate weight and therefore there is no reason we can't estimate fee. We need some traits and runtime calls to allow frontend to do estimation.
Also I would like to see that fees should only be withdrawn from a fee register, which are prefilled with an instruction to withdraw assets into fee register. This way, user can specify the max fee to avoid unexpected charge.