Asset Conversion release to westmint (#2148)

* 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 <5252494+jsidorenko@users.noreply.github.com>

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

Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com>

* Update parachains/common/src/impls.rs

Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com>

* 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 <25483142+joepetrowski@users.noreply.github.com>

* add benchmarks for new assets pallet

* revert common/src changes

* need a concrete id

* more fixes

* lock

---------

Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com>
Co-authored-by: joepetrowski <joe@parity.io>
Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
This commit is contained in:
Squirrel
2023-06-23 21:31:50 +01:00
committed by GitHub
parent eb76e109c8
commit 5487ce7687
18 changed files with 1719 additions and 243 deletions
@@ -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" }
@@ -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::{
@@ -15,5 +15,6 @@
// along with Cumulus. If not, see <http://www.gnu.org/licenses/>.
mod reserve_transfer;
mod swap;
mod teleport;
mod transact;
@@ -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(),
));
});
}