Skip to content
This repository has been archived by the owner on May 21, 2024. It is now read-only.

Withdraw derivative on origin #275

Merged
merged 9 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pallets/withdraw-teleport/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ frame-support = { workspace = true }
frame-system = { workspace = true }
pallet-xcm = { workspace = true }
xcm = { workspace = true }
xcm-executor = { workspace = true }
sp-io = { workspace = true }


Expand Down
40 changes: 22 additions & 18 deletions pallets/withdraw-teleport/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@
type BaseXcm<T> = pallet_xcm::Pallet<T>;
use frame_support::{
dispatch::DispatchResult,
ensure,
ensure, log,
traits::{Contains, EnsureOrigin, Get},
weights::Weight,
};
use frame_system::pallet_prelude::OriginFor;
pub use pallet::*;
Expand All @@ -36,6 +35,7 @@ pub use xcm::{
latest::prelude::*, VersionedMultiAssets, VersionedMultiLocation, VersionedResponse,
VersionedXcm,
};
use xcm_executor::traits::WeightBounds;

// #[cfg(test)]
// mod mock;
Expand Down Expand Up @@ -170,10 +170,6 @@ impl<T: Config> Pallet<T> {
.reanchored(&dest, context)
.map_err(|_| pallet_xcm::Error::<T>::CannotReanchor)?;

// TODO: Define if Withdrawn fee assets are deposited or trapped.
// Check if there is no vulnerability through RefundSurplus
// let max_assets = (assets.len() as u32).checked_add(1).ok_or(Error::<T>::TooManyAssets)?;

// DISCLAIMER: Splitting the instructions to be executed on origin and destination is
// discouraged. Due to current limitations, we need to generate a message
// to be executed on origin and another message to be sent to be executed on destination in
Expand All @@ -185,29 +181,37 @@ impl<T: Config> Pallet<T> {

//Build the message to execute on origin.
let assets: MultiAssets = assets.into();
let message: Xcm<<T as frame_system::Config>::RuntimeCall> =
Xcm(vec![WithdrawAsset(assets.clone()), BurnAsset(assets)]);
let mut message: Xcm<<T as frame_system::Config>::RuntimeCall> = Xcm(vec![
WithdrawAsset(assets.clone()),
SetFeesMode { jit_withdraw: true },
// Burn the native asset.
BurnAsset(assets),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should actually burn the amount that's left after buying execution.
You could estimate this via the same mechanism that's used to turn weight into assets.

The actual amount used to pay for the weight is stored in the Trader in the XCM config.
You could use that to assert your calculation is right.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, and this also applies for the amount to be minted on AH on the sent ReceiveTeleportedAsset as stated on the known issue here.

Will dig into this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: Fixed with SetFeesMode, fees are paid from origin on-chain account funds so amount withdrawn is amount to be burned and minted on destination.

// Burn the fee asset derivative.
WithdrawAsset(fee_asset.clone()),
BurnAsset(fee_asset.clone()),
]);

// Build the message to send to be executed.
// Set WeightLimit
// TODO: Implement weight_limit calculation with final instructions.
let weight_limit: WeightLimit = Unlimited;
let fee_asset_id: AssetId = fee_asset.get(0).ok_or(pallet_xcm::Error::<T>::Empty)?.id;
let xcm_to_send: Xcm<()> = Xcm(vec![
// There are currently no limitations on the amount of fee assets to withdraw.
// Since funds are withdrawn from the Sovereign Account of the origin, chains must be
// aware of this and implement a mechanism to prevent draining.
WithdrawAsset(fee_asset),
// User must have the derivative of fee_asset on origin.
WithdrawAsset(fee_asset.clone()),
BuyExecution { fees, weight_limit },
ReceiveTeleportedAsset(foreign_assets.clone()),
// Intentionally trap ROC to avoid exploit of draining Sovereing Account
// by depositing withdrawn ROC on beneficiary.
// We can deposit funds since they were both withdrawn on origin.
DepositAsset { assets: MultiAssetFilter::Definite(foreign_assets), beneficiary },
RefundSurplus,
DepositAsset {
assets: Wild(AllOf { id: fee_asset_id, fun: WildFungibility::Fungible }),
beneficiary,
},
]);

// Temporarly hardcode weight.
// TODO: Replace for Weigher.
let weight: Weight = Weight::from_parts(1_000_000_000, 100_000);
// T::Weigher::weight(&mut message).map_err(|()| Error::<T>::UnweighableMessage)?;
let weight = T::Weigher::weight(&mut message)
.map_err(|()| pallet_xcm::Error::<T>::UnweighableMessage)?;

// Execute Withdraw for trapping assets on origin.
let hash = message.using_encoded(sp_io::hashing::blake2_256);
Expand Down
2 changes: 1 addition & 1 deletion runtime/trappist/src/xcm_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ parameter_types! {
0u128
);
/// Roc = 7 RUSD
pub RocPerSecond: (xcm::v3::AssetId, u128,u128) = (MultiLocation::parent().into(), default_fee_per_second() * 70, 0u128);
pub RocPerSecond: (xcm::v3::AssetId, u128, u128) = (MultiLocation::new(1, Here).into(), default_fee_per_second() * 70, 0u128);
}

parameter_types! {
Expand Down