Holding Register Modifiers
Most of the XCM instructions alter the Holding Register. We already have seen instructions that
alter the Holding Register, like the WithdrawAsset
or DepositAsset
instructions. In this chapter
we go over more instructions that alter the holding register, namely:
- BurnAsset
- ExchangeAsset
BurnAsset
BurnAsset(MultiAssets)
The BurnAsset
instruction allows for the reduction of assets in the Holding Register by up to the
specified assets. The execution of the instruction does not throw an error if the Holding Register
does not contain the assets (to make this an error, use ExpectAsset
prior).
Example
For the full example, check the repo.
The Scenario of the example is as follows: Parachain A withdraws 10 units from its sovereign account
on the relay chain and burns 4 of them. The relay chain then reports back the status of the Holding
Register to Parachain A. We expect the Holding Register to hold 6 units. Note: If we would have
added more then 10 units worth of assets in the BurnAsset
instruction, we would have burned all
assets in the Holding Register and the execution would succeed.
let message = Xcm(vec![
WithdrawAsset((Here, 10 * CENTS).into()),
BuyExecution { fees: (Here, CENTS).into(), weight_limit: WeightLimit::Unlimited },
BurnAsset((Here, 4 * CENTS).into()),
ReportHolding {
response_info: QueryResponseInfo {
destination: Parachain(1).into(),
query_id: QUERY_ID,
max_weight: Weight::from_parts(1_000_000_000, 64*64) },
assets: All.into()
}
]);
We expect the following response:
Response::Assets((Parent, 6 * CENTS).into())
ExchangeAsset
ExchangeAsset { give: MultiAssetFilter, want: MultiAssets, maximal: bool }
The ExchangeAsset
instruction allows us to remove asset(s) (give
) from the Holding Register and
replace them with alternative assets (want
). The ExchangeAsset
instruction has three fields.
The give
field indicates the maximum number of assets that can be removed from the Holding
register.
The want
field indicates the minimum amount of assets which give
should be exchanged for. We
should at a minimum get the assets in want
for the execution of the instruction not to fail.
If the maximal
field is true
, then we prefer to give as much as possible up to the limit of
give
and receive accordingly more assets then stated in want
. If the maximal
field is false
,
then we prefer to give as little as possible in order to receive as little as possible while
receiving at least want
.
Example
The full example can be found in the repo.
The scenario for the example is this: Scenario: The relay chain sends an XCM to Parachain A that: .1 Withdraws some native assets .2 Exchanges these assets for relay chain derivative tokens, with maximal set to true. .3 Deposit all the assets that are in the Holding in the account of Alice.
NOTE: The implementation of the AssetExchanger is simple and in this case swaps all the assets in
the exchange for the assets in give
. Depending on the implementation of AssetExchanger, the test
results could differ.
The Assets in the exchange in Parachain(1). This is a custom exchange implementation just for testing purposes.
let assets_in_exchange = vec![(Parent, 10 * CENTS).into()];
parachain::set_exchange_assets(assets_in_exchange);
The message that is send:
let message = Xcm(vec![
WithdrawAsset((Here, 10 * CENTS).into()),
BuyExecution { fees: (Here, CENTS).into(), weight_limit: WeightLimit::Unlimited },
// Maximal field set to true.
ExchangeAsset {
give: Definite((Here, 5 * CENTS).into()),
want: (Parent, 5 * CENTS).into(),
maximal: true,
},
DepositAsset {
assets: AllCounted(2).into(),
beneficiary: AccountId32 {
network: Some(parachain::RelayNetwork::get()),
id: ALICE.into(),
}
.into(),
},
]);
Alice receives 5 CENTS
worth of native assets (Here
) and 5 CENTS
worth of relay chain
derivative assets (Parent
).