Skip to content

Commit

Permalink
358 handle delegation of brz token to automation pallet in xcm config (
Browse files Browse the repository at this point in the history
…#365)

* Update LICENSE (#354)

* second iteration on xcm intercept

* listen to ReserveAssetDeposited instruction instead of WithdrawAsset. Mock Moonbeam transfer of asset. Implement custom barrier for other runtimes

* fixes, format

* move integration test BRZ from moonbeam into pendulum

* remove mock BRZ asset moonriver, moonbase

* re-add test macro

* extracting a fee from handled asset

* use custom asset transactor to handle automation pallet call

* use if let with tuple

* refactor to use MultiCurrencyAdapter as a wrapped AssetTransactor
  • Loading branch information
gianfra-t authored Dec 22, 2023
1 parent 4c44828 commit fbb86dc
Show file tree
Hide file tree
Showing 11 changed files with 264 additions and 17 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

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

4 changes: 4 additions & 0 deletions runtime/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-f
sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.40" }

xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.40" }
xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.40" }

orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.40" }
orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.40" }
orml-xcm-support = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.40" }

dia-oracle = { git = "https://github.com/pendulum-chain/oracle-pallet", default-features = false, branch = "polkadot-v0.9.40" }
zenlink-protocol = { git = "https://github.com/pendulum-chain/Zenlink-DEX-Module", default-features = false, branch = "polkadot-v0.9.40-protocol" }
Expand All @@ -49,9 +51,11 @@ std = [
"sp-consensus-aura/std",
"sp-core/std",
"xcm/std",
"xcm-executor/std",
"orml-traits/std",
"dia-oracle/std",
"orml-asset-registry/std",
"orml-xcm-support/std",
"zenlink-protocol/std",
"spacewalk-primitives/std",
]
Expand Down
74 changes: 74 additions & 0 deletions runtime/common/src/custom_transactor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use sp_runtime::{
codec::FullCodec,
traits::{Convert, MaybeSerializeDeserialize, SaturatedConversion},
};
use sp_std::{
cmp::{Eq, PartialEq},
fmt::Debug,
marker::PhantomData,
prelude::*,
result,
};

use orml_xcm_support::{OnDepositFail, UnknownAsset as UnknownAssetT};
use xcm::v3::{prelude::*, Error as XcmError, MultiAsset, MultiLocation, Result};
use xcm_executor::{
traits::{Convert as MoreConvert, MatchesFungible, TransactAsset},
Assets,
};

pub struct AssetData {
pub length: u8,
pub data: [u8; 32],
}

pub trait AutomationPalletConfig {
fn matches_asset(asset: &MultiAsset) -> Option<u128>;
fn matches_beneficiary(beneficiary_location: &MultiLocation) -> Option<AssetData>;
fn callback(length: u8, data: [u8; 32], amount: u128) -> Result;
}

pub struct CustomTransactorInterceptor<WrappedTransactor, AutomationPalletConfigT>(
PhantomData<(WrappedTransactor, AutomationPalletConfigT)>,
);

impl<WrappedTransactor: TransactAsset, AutomationPalletConfigT: AutomationPalletConfig>
TransactAsset for CustomTransactorInterceptor<WrappedTransactor, AutomationPalletConfigT>
{
fn deposit_asset(
asset: &MultiAsset,
location: &MultiLocation,
_context: &XcmContext,
) -> Result {
if let (Some(amount_deposited), Some(asset_data)) = (
AutomationPalletConfigT::matches_asset(asset),
AutomationPalletConfigT::matches_beneficiary(location),
) {
AutomationPalletConfigT::callback(
asset_data.length,
asset_data.data,
amount_deposited,
)?;
return Ok(())
}

WrappedTransactor::deposit_asset(asset, location, _context)
}

fn withdraw_asset(
asset: &MultiAsset,
location: &MultiLocation,
_maybe_context: Option<&XcmContext>,
) -> result::Result<Assets, XcmError> {
WrappedTransactor::withdraw_asset(asset, location, _maybe_context)
}

fn transfer_asset(
asset: &MultiAsset,
from: &MultiLocation,
to: &MultiLocation,
_context: &XcmContext,
) -> result::Result<Assets, XcmError> {
WrappedTransactor::transfer_asset(asset, from, to, _context)
}
}
1 change: 1 addition & 0 deletions runtime/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use sp_runtime::{

pub mod asset_registry;
pub mod chain_ext;
pub mod custom_transactor;
mod proxy_type;
pub mod stellar;
pub mod zenlink;
Expand Down
2 changes: 1 addition & 1 deletion runtime/foucoco/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ runtime-benchmarks = [
"replace/runtime-benchmarks",
"stellar-relay/runtime-benchmarks",
"vault-registry/runtime-benchmarks",

"oracle/testing-utils",
"runtime-common/runtime-benchmarks",
"orml-currencies-allowance-extension/runtime-benchmarks",
"orml-tokens-management-extension/runtime-benchmarks"
Expand Down
3 changes: 2 additions & 1 deletion runtime/integration-tests/src/amplitude_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use crate::{
mock::{kusama_relay_ext, para_ext, ParachainType, USDT_ASSET_ID},
sibling,
test_macros::{
parachain1_transfer_asset_to_parachain2, parachain1_transfer_asset_to_parachain2_and_back,
moonbeam_transfers_token_and_handle_automation, parachain1_transfer_asset_to_parachain2,
parachain1_transfer_asset_to_parachain2_and_back,
parachain1_transfer_incorrect_asset_to_parachain2_should_fail,
transfer_10_relay_token_from_parachain_to_relay_chain,
transfer_20_relay_token_from_relay_chain_to_parachain,
Expand Down
19 changes: 19 additions & 0 deletions runtime/integration-tests/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use sp_io::TestExternalities;
use sp_runtime::traits::AccountIdConversion;
use xcm_emulator::Weight;

use runtime_common::parachains::polkadot::moonbeam::PARA_ID as MOONBEAM_PARA_ID;
use statemine_runtime as kusama_asset_hub_runtime;
use statemint_runtime as polkadot_asset_hub_runtime;

Expand Down Expand Up @@ -116,6 +117,7 @@ pub enum ParachainType {
Pendulum,
Amplitude,
Sibling,
Moonbeam,
}

pub struct ExtBuilderParachain<Currency> {
Expand Down Expand Up @@ -189,6 +191,7 @@ pub fn para_ext(chain: ParachainType) -> sp_io::TestExternalities {
ParachainType::Amplitude =>
ExtBuilderParachain::amplitude_default().balances(vec![]).build(),
ParachainType::Sibling => ExtBuilderParachain::sibling_default().balances(vec![]).build(),
ParachainType::Moonbeam => ExtBuilderParachain::moonbeam_default().balances(vec![]).build(),
}
}

Expand All @@ -200,6 +203,7 @@ impl<Currency> ExtBuilderParachain<Currency> {
ParachainType::Pendulum => PENDULUM_ID,
ParachainType::Sibling => SIBLING_ID,
ParachainType::Amplitude => AMPLITUDE_ID,
ParachainType::Moonbeam => MOONBEAM_PARA_ID,
}
}
}
Expand Down Expand Up @@ -255,6 +259,10 @@ impl ExtBuilderParachain<SiblingCurrencyId> {
pub fn sibling_default() -> Self {
Self { balances: vec![], chain: ParachainType::Sibling }
}

pub fn moonbeam_default() -> Self {
Self { balances: vec![], chain: ParachainType::Moonbeam }
}
}

impl Builder<SiblingCurrencyId> for ExtBuilderParachain<SiblingCurrencyId> {
Expand All @@ -276,6 +284,17 @@ impl Builder<SiblingCurrencyId> for ExtBuilderParachain<SiblingCurrencyId> {
SiblingCurrencyId
)
},
ParachainType::Moonbeam => {
use sibling::{Runtime, System};
build_parachain_with_orml!(
self,
Runtime,
System,
NATIVE_INITIAL_BALANCE,
ORML_INITIAL_BALANCE,
SiblingCurrencyId
)
},
_ => panic!("cannot use this chain to build"),
}
}
Expand Down
28 changes: 27 additions & 1 deletion runtime/integration-tests/src/pendulum_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use crate::{
mock::{para_ext, polkadot_relay_ext, ParachainType, USDT_ASSET_ID},
sibling,
test_macros::{
parachain1_transfer_asset_to_parachain2, parachain1_transfer_asset_to_parachain2_and_back,
moonbeam_transfers_token_and_handle_automation, parachain1_transfer_asset_to_parachain2,
parachain1_transfer_asset_to_parachain2_and_back,
parachain1_transfer_incorrect_asset_to_parachain2_should_fail,
transfer_10_relay_token_from_parachain_to_relay_chain,
transfer_20_relay_token_from_relay_chain_to_parachain,
Expand All @@ -12,6 +13,7 @@ use crate::{
};

use frame_support::assert_ok;
use runtime_common::parachains::polkadot::moonbeam::PARA_ID as MOONBEAM_PARA_ID;
use statemint_runtime as polkadot_asset_hub_runtime;
use xcm::latest::NetworkId;
use xcm_emulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain, TestExt};
Expand Down Expand Up @@ -56,12 +58,23 @@ decl_test_parachain! {
}
}

decl_test_parachain! {
pub struct MoonbeamParachain {
Runtime = sibling::Runtime,
RuntimeOrigin = sibling::RuntimeOrigin,
XcmpMessageHandler = sibling::XcmpQueue,
DmpMessageHandler = sibling::DmpQueue,
new_ext = para_ext(ParachainType::Moonbeam),
}
}

decl_test_network! {
pub struct PolkadotMockNet {
relay_chain = PolkadotRelay,
parachains = vec![
(1000, AssetHubParachain),
(2094, PendulumParachain),
(2004, MoonbeamParachain),
(9999, SiblingParachain),
],
}
Expand Down Expand Up @@ -142,3 +155,16 @@ fn transfer_native_token_from_pendulum_to_sibling_parachain_and_back() {
SIBLING_ID
);
}

#[test]
fn moonbeam_transfers_token_and_handle_automation() {
moonbeam_transfers_token_and_handle_automation!(
PolkadotMockNet,
pendulum_runtime,
PendulumParachain,
sibling,
MoonbeamParachain,
PENDULUM_ID,
MOONBEAM_PARA_ID
);
}
5 changes: 5 additions & 0 deletions runtime/integration-tests/src/sibling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ use xcm_builder::{

use crate::{AMPLITUDE_ID, ASSETHUB_ID, PENDULUM_ID};

use runtime_common::parachains::polkadot::moonbeam::BRZ_location;

const XCM_ASSET_RELAY_DOT: u8 = 0;
const XCM_ASSET_ASSETHUB_USDT: u8 = 1;

Expand Down Expand Up @@ -92,6 +94,7 @@ pub enum CurrencyId {
Amplitude,
Native,
XCM(u8),
Token,
}

// Convert from u32 parachain id to CurrencyId
Expand Down Expand Up @@ -127,6 +130,7 @@ impl Convert<CurrencyId, Option<MultiLocation>> for CurrencyIdConvert {
Some(MultiLocation::new(1, X2(Parachain(PENDULUM_ID), PalletInstance(10)))),
CurrencyId::Amplitude =>
Some(MultiLocation::new(1, X2(Parachain(AMPLITUDE_ID), PalletInstance(10)))),
CurrencyId::Token => Some(BRZ_location()),
CurrencyId::XCM(f) => match f {
XCM_ASSET_RELAY_DOT => Some(MultiLocation::parent()),
// Handles both Kusama and Polkadot asset hub
Expand Down Expand Up @@ -155,6 +159,7 @@ impl Convert<MultiLocation, Option<CurrencyId>> for CurrencyIdConvert {
Some(CurrencyId::XCM(XCM_ASSET_ASSETHUB_USDT)),
MultiLocation { parents: 1, interior: Here } =>
Some(CurrencyId::XCM(XCM_ASSET_RELAY_DOT)),
loc if loc == BRZ_location() => Some(CurrencyId::Token),
_ => None,
}
}
Expand Down
73 changes: 73 additions & 0 deletions runtime/integration-tests/src/test_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,10 @@ macro_rules! transfer_native_token_from_parachain1_to_parachain2_and_back {
// Verify BOB's balance on parachain2 after receiving
// Should increase by the transfer amount
$parachain2::execute_with(|| {
use $parachain2_runtime::{RuntimeEvent, System, XTokens};
for i in System::events().iter() {
println!("para 2 events {}: {:?}\n", stringify!($para2_runtime), i);
}
assert_eq!(
$parachain2_runtime::Tokens::balance(para1_native_currency_on_para2, &BOB.into()),
transfer_amount
Expand Down Expand Up @@ -591,6 +595,10 @@ macro_rules! transfer_native_token_from_parachain1_to_parachain2_and_back {
// Verify ALICE's balance on parachain1 after receiving
// Should become the same amount as initial balance before both transfers
$parachain1::execute_with(|| {
use $parachain1_runtime::System;
for i in System::events().iter() {
println!("para 1 events {}: {:?}\n", stringify!($para2_runtime), i);
}
assert_eq!(
$parachain1_runtime::Currencies::free_balance(Parachain1CurrencyId::Native, &ALICE.into()),
native_tokens_before
Expand All @@ -599,7 +607,72 @@ macro_rules! transfer_native_token_from_parachain1_to_parachain2_and_back {
}};
}

macro_rules! moonbeam_transfers_token_and_handle_automation {
(
$mocknet:ident,
$parachain1_runtime:ident,
$parachain1:ident,
$parachain2_runtime:ident,
$parachain2:ident,
$parachain1_id:ident,
$parachain2_id:ident
) => {{
use crate::mock::{units, ALICE};
use polkadot_core_primitives::Balance;
use xcm::latest::{
Junction, Junction::{ GeneralKey, PalletInstance}, Junctions::{X1,X2, X3}, MultiLocation, WeightLimit,
};
use $parachain2_runtime::CurrencyId as Parachain2CurrencyId;

$mocknet::reset();

let transfer_amount: Balance = units(10);
// We mock parachain 2 as beeing moonriver in this case.
// Sending "Token" variant which is equivalent to BRZ mock token Multilocation
// in the sibling definition
$parachain2::execute_with(|| {
use $parachain2_runtime::{XTokens, Tokens,RuntimeOrigin, System};

assert_ok!(Tokens::set_balance(RuntimeOrigin::root().into(), ALICE.clone().into(), Parachain2CurrencyId::Token,transfer_amount, 0));

// We must ensure that the destination Multilocation is of the structure
// the intercept excepts so it calls automation pallet

// TODO replace instance 99 with automation pallet index when added
assert_ok!(XTokens::transfer(
$parachain2_runtime::RuntimeOrigin::signed(ALICE.into()),
Parachain2CurrencyId::Token,
transfer_amount,
Box::new(
MultiLocation::new(
1,
X3(
Junction::Parachain($parachain1_id),
PalletInstance(99),
GeneralKey {length:32 , data:[1u8;32]}
)
)
.into()
),
WeightLimit::Unlimited
));
});

$parachain1::execute_with(|| {
use $parachain1_runtime::{RuntimeEvent, System, Tokens};
// given the configuration in pendulum's xcm_config, we expect the callback (in this case a Remark)
// to be executed
assert!(System::events().iter().any(|r| matches!(
r.event,
RuntimeEvent::System(frame_system::Event::Remarked { .. })
)));


});
}};
}
// macros defined at the bottom of this file to prevent unresolved imports
pub(super) use moonbeam_transfers_token_and_handle_automation;
pub(super) use parachain1_transfer_asset_to_parachain2;
pub(super) use parachain1_transfer_asset_to_parachain2_and_back;
pub(super) use parachain1_transfer_incorrect_asset_to_parachain2_should_fail;
Expand Down
Loading

0 comments on commit fbb86dc

Please sign in to comment.