Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
Asset Conversion release to westmint (#2148)
Browse files Browse the repository at this point in the history
* Dex and payment by dex in westmint

* Wrap U256 type for now

(to support required traits.)

* cargo fmt

* We can now use U256

* Rename PromotedBalance

* name change

* Updating the code to master.

TODO: handle dust!

* cargo fmt

* Minimising changes and step towards getting benchmarks compiling

(still a From<u32> bound in the pallet)

* minimise diff

* Update parachains/runtimes/assets/westmint/src/lib.rs

Co-authored-by: Jegor Sidorenko <[email protected]>

* Update parachains/runtimes/assets/westmint/src/lib.rs

Co-authored-by: Jegor Sidorenko <[email protected]>

* Update parachains/common/src/impls.rs

Co-authored-by: Jegor Sidorenko <[email protected]>

* Fix benchmark build

* Add in AssetConversionAPI

* Handle dust

* cargo fmt

* Don't need to be explicit that it's AccountId32

* remove pool setup fee

(Asset deposit fees are a sufficient anti-spam measure)

* More natural way to specify native

* cargo fmt

* Update parachains/runtimes/assets/westmint/src/lib.rs

* Additional required impls

* either form of multilocation should be acceptable.

* add call filter exclusion

* Fix typo & try_convert now fails if native is converted

* merge master fixup

* Fix: HoldReason should be there.

* Box MultiAssetId

Otherwise it blows out the Call enum memory size.

* cargo fmt

* update lock file

* add std feature, update lock file

* need to turn on std on common

* adding in westmint tests

* WeightToFee must be from the destination chain.

* cargo fmt

* account for higher ED on westmint

* type removed as not used

* cargo fmt

* remove unused import

* minimising diff

* import needed only with feature enabled

* use multilocation contains

* move the impls to separate file

* simplify on conversion

* simplify on reverse conversion also.

* rename var

* clippy

* removed dead code

* cargo fmt

* Use pay by swap

* review suggestions

* cargo fmt

* Update parachains/runtimes/assets/asset-hub-westend/src/lib.rs

Co-authored-by: joe petrowski <[email protected]>

* add benchmarks for new assets pallet

* revert common/src changes

* need a concrete id

* more fixes

* lock

---------

Co-authored-by: Jegor Sidorenko <[email protected]>
Co-authored-by: joepetrowski <[email protected]>
Co-authored-by: joe petrowski <[email protected]>
  • Loading branch information
4 people authored Jun 23, 2023
1 parent 3137e73 commit 50494b2
Show file tree
Hide file tree
Showing 18 changed files with 1,719 additions and 243 deletions.
439 changes: 245 additions & 194 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion parachains/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"], default-features = false }
scale-info = { version = "2.8.0", default-features = false, features = ["derive"] }
num-traits = { version = "0.2", default-features = false}

# Substrate
frame-support = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" }
Expand All @@ -33,6 +34,7 @@ xcm-executor = { git = "https://github.com/paritytech/polkadot", default-feature

# Cumulus
pallet-collator-selection = { path = "../../pallets/collator-selection", default-features = false }
cumulus-primitives-core = { path = "../../primitives/core", default-features = false }
cumulus-primitives-utility = { path = "../../primitives/utility", default-features = false }

[dev-dependencies]
Expand All @@ -47,7 +49,6 @@ default = ["std"]
std = [
"frame-support/std",
"frame-system/std",
"pallet-asset-tx-payment/std",
"pallet-assets/std",
"pallet-authorship/std",
"pallet-balances/std",
Expand All @@ -56,6 +57,7 @@ std = [
"sp-io/std",
"sp-std/std",
"pallet-collator-selection/std",
"cumulus-primitives-core/std",
"cumulus-primitives-utility/std",
"xcm/std",
"xcm-executor/std",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ sp-core = { default-features = false, git = "https://github.com/paritytech/subst
sp-weights = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-assets = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }
pallet-asset-conversion = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" }

# Polkadot
polkadot-core-primitives = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ pub use integration_tests_common::{
},
AccountId, AssetHubWestend, AssetHubWestendPallet, AssetHubWestendReceiver,
AssetHubWestendSender, Collectives, CollectivesPallet, CollectivesReceiver, CollectivesSender,
PenpalWestend, Westend, WestendPallet, WestendReceiver, WestendSender,
PenpalWestend, PenpalWestendPallet, PenpalWestendReceiver, PenpalWestendSender, Westend,
WestendPallet, WestendReceiver, WestendSender,
};
pub use polkadot_core_primitives::InboundDownwardMessage;
pub use xcm::{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.

mod reserve_transfer;
mod swap;
mod teleport;
mod transact;
Original file line number Diff line number Diff line change
@@ -0,0 +1,307 @@
use crate::*;
use frame_support::{instances::Instance2, BoundedVec};
use xcm_emulator::Parachain;

#[test]
fn swap_locally_on_chain_using_local_assets() {
const ASSET_ID: u32 = 1;

let asset_native = Box::new(MultiLocation { parents: 0, interior: Here });
let asset_one = Box::new(MultiLocation {
parents: 0,
interior: X2(PalletInstance(50), GeneralIndex(ASSET_ID.into())),
});

AssetHubWestend::execute_with(|| {
type RuntimeEvent = <AssetHubWestend as Parachain>::RuntimeEvent;

assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::Assets::create(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
ASSET_ID.into(),
AssetHubWestendSender::get().into(),
1000,
));
assert!(<AssetHubWestend as AssetHubWestendPallet>::Assets::asset_exists(ASSET_ID));

assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::Assets::mint(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
ASSET_ID.into(),
AssetHubWestendSender::get().into(),
3_000_000_000_000,
));

assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::create_pool(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native.clone(),
asset_one.clone(),
));

assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::PoolCreated { .. }) => {},
]
);

assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::add_liquidity(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native.clone(),
asset_one.clone(),
1_000_000_000_000,
2_000_000_000_000,
0,
0,
AssetHubWestendSender::get().into()
));

assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::LiquidityAdded {lp_token_minted, .. }) => { lp_token_minted: *lp_token_minted == 1414213562273, },
]
);

let path = BoundedVec::<_, _>::truncate_from(vec![asset_native.clone(), asset_one.clone()]);

assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::swap_exact_tokens_for_tokens(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
path,
100,
1,
AssetHubWestendSender::get().into(),
true
));

assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. }) => {
amount_in: *amount_in == 100,
amount_out: *amount_out == 199,
},
]
);

assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::remove_liquidity(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native,
asset_one,
1414213562273 - 2_000_000_000, // all but the 2 EDs can't be retrieved.
0,
0,
AssetHubWestendSender::get().into(),
));
});
}

#[test]
fn swap_locally_on_chain_using_foreign_assets() {
use frame_support::weights::WeightToFee;

const ASSET_ID: u32 = 1;
let asset_native = Box::new(MultiLocation { parents: 0, interior: Here });

let foreign_asset1_at_asset_hub_westend = Box::new(MultiLocation {
parents: 1,
interior: X3(
Parachain(PenpalWestend::para_id().into()),
PalletInstance(50),
GeneralIndex(ASSET_ID.into()),
),
});

let assets_para_destination: VersionedMultiLocation =
MultiLocation { parents: 1, interior: X1(Parachain(AssetHubWestend::para_id().into())) }
.into();

let penpal_location =
MultiLocation { parents: 1, interior: X1(Parachain(PenpalWestend::para_id().into())) };

// 1. Create asset on penpal:
PenpalWestend::execute_with(|| {
assert_ok!(<PenpalWestend as PenpalWestendPallet>::Assets::create(
<PenpalWestend as Parachain>::RuntimeOrigin::signed(PenpalWestendSender::get()),
ASSET_ID.into(),
PenpalWestendSender::get().into(),
1000,
));

assert!(<PenpalWestend as PenpalWestendPallet>::Assets::asset_exists(ASSET_ID));
});

// 2. Create foreign asset on asset_hub_westend:

let require_weight_at_most = Weight::from_parts(1_100_000_000_000, 30_000);
let origin_kind = OriginKind::Xcm;
let sov_penpal_on_asset_hub_westend = AssetHubWestend::sovereign_account_id_of(penpal_location);

AssetHubWestend::fund_accounts(vec![
(AssetHubWestendSender::get(), 5_000_000), // An account to swap dot for something else.
(sov_penpal_on_asset_hub_westend.clone(), 1000_000_000_000_000_000),
]);

let sov_penpal_on_asset_hub_westend_as_location: MultiLocation = MultiLocation {
parents: 0,
interior: X1(AccountId32 {
network: None,
id: sov_penpal_on_asset_hub_westend.clone().into(),
}),
};

let call_foreign_assets_create =
<AssetHubWestend as Para>::RuntimeCall::ForeignAssets(pallet_assets::Call::<
<AssetHubWestend as Para>::Runtime,
Instance2,
>::create {
id: *foreign_asset1_at_asset_hub_westend,
min_balance: 1000,
admin: sov_penpal_on_asset_hub_westend.clone().into(),
})
.encode()
.into();

let buy_execution_fee_amount =
asset_hub_westend_runtime::constants::fee::WeightToFee::weight_to_fee(&Weight::from_parts(
10_100_000_000_000,
300_000,
));
let buy_execution_fee = MultiAsset {
id: Concrete(MultiLocation { parents: 1, interior: Here }),
fun: Fungible(buy_execution_fee_amount),
};

let xcm = VersionedXcm::from(Xcm(vec![
WithdrawAsset { 0: vec![buy_execution_fee.clone()].into() },
BuyExecution { fees: buy_execution_fee.clone(), weight_limit: Unlimited },
Transact { require_weight_at_most, origin_kind, call: call_foreign_assets_create },
RefundSurplus,
DepositAsset {
assets: All.into(),
beneficiary: sov_penpal_on_asset_hub_westend_as_location,
},
]));

// Send XCM message from penpal => asset_hub_westend
let sudo_penpal_origin = <PenpalWestend as Parachain>::RuntimeOrigin::root();
PenpalWestend::execute_with(|| {
assert_ok!(<PenpalWestend as PenpalWestendPallet>::PolkadotXcm::send(
sudo_penpal_origin.clone(),
bx!(assets_para_destination.clone()),
bx!(xcm),
));

type RuntimeEvent = <PenpalWestend as Parachain>::RuntimeEvent;

assert_expected_events!(
PenpalWestend,
vec![
RuntimeEvent::PolkadotXcm(pallet_xcm::Event::Sent { .. }) => {},
]
);
});

// Receive XCM message in Assets Parachain
AssetHubWestend::execute_with(|| {
assert!(<AssetHubWestend as AssetHubWestendPallet>::ForeignAssets::asset_exists(
*foreign_asset1_at_asset_hub_westend
));

// 3: Mint foreign asset on asset_hub_westend:
//
// (While it might be nice to use batch,
// currently that's disabled due to safe call filters.)

type RuntimeEvent = <AssetHubWestend as Parachain>::RuntimeEvent;
// 3. Mint foreign asset (in reality this should be a teleport or some such)
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::ForeignAssets::mint(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(
sov_penpal_on_asset_hub_westend.clone().into()
),
*foreign_asset1_at_asset_hub_westend,
sov_penpal_on_asset_hub_westend.clone().into(),
3_000_000_000_000,
));

assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::ForeignAssets(pallet_assets::Event::Issued { .. }) => {},
]
);

// 4. Create pool:
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::create_pool(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
asset_native.clone(),
foreign_asset1_at_asset_hub_westend.clone(),
));

assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::PoolCreated { .. }) => {},
]
);

// 5. Add liquidity:
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::add_liquidity(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(
sov_penpal_on_asset_hub_westend.clone()
),
asset_native.clone(),
foreign_asset1_at_asset_hub_westend.clone(),
1_000_000_000_000,
2_000_000_000_000,
0,
0,
sov_penpal_on_asset_hub_westend.clone().into()
));

assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::LiquidityAdded {lp_token_minted, .. }) => {
lp_token_minted: *lp_token_minted == 1414213562273,
},
]
);

// 6. Swap!
let path = BoundedVec::<_, _>::truncate_from(vec![
asset_native.clone(),
foreign_asset1_at_asset_hub_westend.clone(),
]);

assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::swap_exact_tokens_for_tokens(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(AssetHubWestendSender::get()),
path,
100000,
1000,
AssetHubWestendSender::get().into(),
true
));

assert_expected_events!(
AssetHubWestend,
vec![
RuntimeEvent::AssetConversion(pallet_asset_conversion::Event::SwapExecuted { amount_in, amount_out, .. },) => {
amount_in: *amount_in == 100000,
amount_out: *amount_out == 199399,
},
]
);

// 7. Remove liquidity
assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::AssetConversion::remove_liquidity(
<AssetHubWestend as Parachain>::RuntimeOrigin::signed(
sov_penpal_on_asset_hub_westend.clone()
),
asset_native,
foreign_asset1_at_asset_hub_westend,
1414213562273 - 2_000_000_000, // all but the 2 EDs can't be retrieved.
0,
0,
sov_penpal_on_asset_hub_westend.clone().into(),
));
});
}
1 change: 1 addition & 0 deletions parachains/integration-tests/emulated/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ decl_test_parachains! {
PolkadotXcm: asset_hub_westend_runtime::PolkadotXcm,
Assets: asset_hub_westend_runtime::Assets,
ForeignAssets: asset_hub_westend_runtime::ForeignAssets,
AssetConversion: asset_hub_westend_runtime::AssetConversion,
}
},
// Polkadot
Expand Down
Loading

0 comments on commit 50494b2

Please sign in to comment.