Configuring FeeManager enforces the boundary Into<[u8; 32]> for the AccountId type.
Here is how it works currently:
Configuration:
type FeeManager = XcmFeeManagerFromComponents<
IsChildSystemParachain<primitives::Id>,
XcmFeeToAccount<Self::AssetTransactor, AccountId, TreasuryAccount>,
>;
XcmToFeeAccount struct:
/// A `HandleFee` implementation that simply deposits the fees into a specific on-chain
/// `ReceiverAccount`.
///
/// It reuses the `AssetTransactor` configured on the XCM executor to deposit fee assets. If
/// the `AssetTransactor` returns an error while calling `deposit_asset`, then a warning will be
/// logged and the fee burned.
pub struct XcmFeeToAccount<AssetTransactor, AccountId, ReceiverAccount>(
PhantomData<(AssetTransactor, AccountId, ReceiverAccount)>,
);
impl<
AssetTransactor: TransactAsset,
AccountId: Clone + Into<[u8; 32]>,
ReceiverAccount: Get<AccountId>,
> HandleFee for XcmFeeToAccount<AssetTransactor, AccountId, ReceiverAccount>
{
fn handle_fee(fee: Assets, context: Option<&XcmContext>, _reason: FeeReason) -> Assets {
deposit_or_burn_fee::<AssetTransactor, _>(fee, context, ReceiverAccount::get());
Assets::new()
}
}
deposit_or_burn_fee() function:
/// Try to deposit the given fee in the specified account.
/// Burns the fee in case of a failure.
pub fn deposit_or_burn_fee<AssetTransactor: TransactAsset, AccountId: Clone + Into<[u8; 32]>>(
fee: Assets,
context: Option<&XcmContext>,
receiver: AccountId,
) {
let dest = AccountId32 { network: None, id: receiver.into() }.into();
for asset in fee.into_inner() {
if let Err(e) = AssetTransactor::deposit_asset(&asset, &dest, context) {
log::trace!(
target: "xcm::fees",
"`AssetTransactor::deposit_asset` returned error: {:?}. Burning fee: {:?}. \
They might be burned.",
e, asset,
);
}
}
}
In order to use anotherAccountId type (for example, 20 byte addresses for compatibility with Ethereum or Bitcoin), one has to duplicate the code as the following (roughly changing every 32 to 20):
/// A `HandleFee` implementation that simply deposits the fees into a specific on-chain
/// `ReceiverAccount`.
///
/// It reuses the `AssetTransactor` configured on the XCM executor to deposit fee assets. If
/// the `AssetTransactor` returns an error while calling `deposit_asset`, then a warning will be
/// logged and the fee burned.
pub struct XcmFeeToAccount<AssetTransactor, AccountId, ReceiverAccount>(
PhantomData<(AssetTransactor, AccountId, ReceiverAccount)>,
);
impl<
AssetTransactor: TransactAsset,
AccountId: Clone + Into<[u8; 20]>,
ReceiverAccount: Get<AccountId>,
> HandleFee for XcmFeeToAccount<AssetTransactor, AccountId, ReceiverAccount>
{
fn handle_fee(fee: XcmAssets, context: Option<&XcmContext>, _reason: FeeReason) -> XcmAssets {
deposit_or_burn_fee::<AssetTransactor, _>(fee, context, ReceiverAccount::get());
XcmAssets::new()
}
}
pub fn deposit_or_burn_fee<AssetTransactor: TransactAsset, AccountId: Clone + Into<[u8; 20]>>(
fee: XcmAssets,
context: Option<&XcmContext>,
receiver: AccountId,
) {
let dest = AccountKey20 { network: None, key: receiver.into() }.into();
for asset in fee.into_inner() {
if let Err(e) = AssetTransactor::deposit_asset(&asset, &dest, context) {
log::trace!(
target: "xcm::fees",
"`AssetTransactor::deposit_asset` returned error: {:?}. Burning fee: {:?}. \
They might be burned.",
e, asset,
);
}
}
}
This results in code duplication, and it is not an elegant solution.
When this change is released in the next polkadot-sdk version:
AccountId20 should also implement From trait to Location in order to allow frontier users to easily configure FeeManager.
Motivation
Configuring
FeeManager
enforces the boundaryInto<[u8; 32]>
for theAccountId
type.Here is how it works currently:
Configuration:
XcmToFeeAccount
struct:deposit_or_burn_fee()
function:In order to use another
AccountId
type (for example, 20 byte addresses for compatibility with Ethereum or Bitcoin), one has to duplicate the code as the following (roughly changing every32
to20
):This results in code duplication, and it is not an elegant solution.
I submitted and merged https://github.com/paritytech/polkadot-sdk/pull/4959 which relaxed the trait bound for
XcmFeeToAccount
, and now it accepts everything that implementsGet<Location>
.When this change is released in the next
polkadot-sdk
version:AccountId20
should also implementFrom
trait toLocation
in order to allowfrontier
users to easily configureFeeManager
.