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

Commit

Permalink
Use relay token as fee asset
Browse files Browse the repository at this point in the history
  • Loading branch information
yrong committed Aug 22, 2024
1 parent 9d900b2 commit 33ea85e
Show file tree
Hide file tree
Showing 4 changed files with 190 additions and 16 deletions.
6 changes: 2 additions & 4 deletions bridges/snowbridge/pallets/inbound-queue/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,8 @@ pub mod pallet {
fee
);

if fee > BalanceOf::<T>::zero() {
// Burning fees for teleport
Self::burn_fees(channel.para_id, fee)?;
}
// Burning fees for teleport
Self::burn_fees(channel.para_id, fee)?;

// Attempt to send XCM to a dest parachain
let message_id = Self::send_xcm(xcm, channel.para_id)?;
Expand Down
7 changes: 4 additions & 3 deletions bridges/snowbridge/primitives/router/src/inbound/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ where
}
.ok_or(ConvertMessageError::InvalidDestination)?;

let fee_asset: Asset = (Location::here(), destination_fee).into();
let fee_asset: Asset = (Location::parent(), destination_fee).into();

let versioned_asset_id =
ConvertAssetId::convert(&token_id).ok_or(ConvertMessageError::InvalidToken)?;
Expand All @@ -392,16 +392,17 @@ where
let inbound_queue_pallet_index = InboundQueuePalletInstance::get();

let instructions = vec![
ReceiveTeleportedAsset(fee_asset.clone().into()),
BuyExecution { fees: fee_asset, weight_limit: Unlimited },
DescendOrigin(PalletInstance(inbound_queue_pallet_index).into()),
UniversalOrigin(GlobalConsensus(network)),
WithdrawAsset(assets),
BuyExecution { fees: fee_asset, weight_limit: Unlimited },
ClearOrigin,
DepositAsset { assets: AllCounted(2).into(), beneficiary },
SetTopic(message_id.into()),
];

Ok((instructions.into(), Balance::zero()))
Ok((instructions.into(), destination_fee.into()))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ use bridge_hub_westend_runtime::EthereumInboundQueue;
use codec::{Decode, Encode};
use frame_support::pallet_prelude::TypeInfo;
use hex_literal::hex;
use snowbridge_core::{outbound::OperatingMode, AssetRegistrarMetadata};
use snowbridge_core::{outbound::OperatingMode, AssetRegistrarMetadata, TokenIdOf};
use snowbridge_router_primitives::inbound::{
Command, ConvertMessage, Destination, MessageV1, VersionedMessage,
Command, ConvertMessage, Destination, GlobalConsensusEthereumConvertsFor, MessageV1,
VersionedMessage,
};
use sp_core::H256;
use testnet_parachains_constants::westend::snowbridge::EthereumNetwork;
use xcm_executor::traits::ConvertLocation;

const INITIAL_FUND: u128 = 5_000_000_000_000;
pub const CHAIN_ID: u64 = 11155111;
Expand Down Expand Up @@ -70,7 +72,7 @@ fn register_weth_token_from_ethereum_to_asset_hub() {
command: Command::RegisterToken { token: WETH.into(), fee: XCM_FEE },
});
let (xcm, _) = Converter::convert(message_id, message).unwrap();
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubRococo::para_id().into()).unwrap();
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubWestend::para_id().into()).unwrap();

assert_expected_events!(
BridgeHubWestend,
Expand Down Expand Up @@ -328,10 +330,7 @@ fn register_relay_token() {
let sudo_origin = <Westend as Chain>::RuntimeOrigin::root();
let destination = Westend::child_location_of(BridgeHubWestend::para_id()).into();

let asset_id: Location = Location {
parents: 1,
interior: [GlobalConsensus(Westend), Parachain(AssetHubWestend::para_id().into())].into(),
};
let asset_id: Location = Location { parents: 1, interior: [GlobalConsensus(Westend)].into() };

// construct ForceRegisterToken call
let register_relay_token_call = SnowbridgeControl::Control(ControlCall::ForceRegisterToken {
Expand Down Expand Up @@ -387,3 +386,163 @@ fn register_relay_token() {
);
});
}

#[test]
fn send_relay_token_to_ethereum() {
let assethub_location = BridgeHubWestend::sibling_location_of(AssetHubWestend::para_id());
let assethub_sovereign = BridgeHubWestend::sovereign_account_id_of(assethub_location);

AssetHubWestend::force_default_xcm_version(Some(XCM_VERSION));
BridgeHubWestend::force_default_xcm_version(Some(XCM_VERSION));
AssetHubWestend::force_xcm_version(
Location::new(2, [GlobalConsensus(Ethereum { chain_id: CHAIN_ID })]),
XCM_VERSION,
);

BridgeHubWestend::fund_accounts(vec![(assethub_sovereign.clone(), INITIAL_FUND)]);

let asset_id: Location = Location { parents: 1, interior: [GlobalConsensus(Westend)].into() };
let token_id = TokenIdOf::convert_location(&asset_id).unwrap();

// create token
BridgeHubWestend::execute_with(|| {
type Runtime = <BridgeHubWestend as Chain>::Runtime;

snowbridge_pallet_system::Tokens::<Runtime>::insert(
token_id,
VersionedLocation::from(asset_id),
);
});

const TOKEN_AMOUNT: u128 = 100_000_000_000;

// Send relay token to Ethereum
AssetHubWestend::execute_with(|| {
type RuntimeOrigin = <AssetHubWestend as Chain>::RuntimeOrigin;
type RuntimeEvent = <AssetHubWestend as Chain>::RuntimeEvent;

let assets = vec![Asset { id: AssetId(Location::parent()), fun: Fungible(TOKEN_AMOUNT) }];
let multi_assets = VersionedAssets::V4(Assets::from(assets));

let destination = VersionedLocation::V4(Location::new(
2,
[GlobalConsensus(Ethereum { chain_id: CHAIN_ID })],
));

let beneficiary = VersionedLocation::V4(Location::new(
0,
[AccountKey20 { network: None, key: ETHEREUM_DESTINATION_ADDRESS.into() }],
));

assert_ok!(<AssetHubWestend as AssetHubWestendPallet>::PolkadotXcm::limited_reserve_transfer_assets(
RuntimeOrigin::signed(AssetHubWestendSender::get()),
Box::new(destination),
Box::new(beneficiary),
Box::new(multi_assets),
0,
Unlimited,
));

let events = AssetHubWestend::events();
// Check that the native asset transferred to some reserved account(sovereign of Ethereum)
assert!(
events.iter().any(|event| matches!(
event,
RuntimeEvent::Balances(pallet_balances::Event::Transfer { amount, ..})
if *amount == TOKEN_AMOUNT,
)),
"native token reserved to Ethereum sovereign account."
);
});

BridgeHubWestend::execute_with(|| {
type RuntimeEvent = <BridgeHubWestend as Chain>::RuntimeEvent;
// Check that the transfer token back to Ethereum message was queue in the Ethereum
// Outbound Queue
assert_expected_events!(
BridgeHubWestend,
vec![
RuntimeEvent::EthereumOutboundQueue(snowbridge_pallet_outbound_queue::Event::MessageQueued
{..}) => {}, ]
);
});
}

#[test]
fn send_relay_token_from_ethereum() {
let asset_id: Location = Location { parents: 1, interior: [GlobalConsensus(Westend)].into() };
let token_id = TokenIdOf::convert_location(&asset_id).unwrap();

const TOKEN_AMOUNT: u128 = 100_000_000_000;

let ethereum_sovereign = GlobalConsensusEthereumConvertsFor::<[u8; 32]>::convert_location(
&Location::new(2, [GlobalConsensus(EthereumNetwork::get())]),
)
.unwrap();

AssetHubWestend::fund_accounts(vec![(ethereum_sovereign.into(), INITIAL_FUND)]);

BridgeHubWestend::execute_with(|| {
type Runtime = <BridgeHubWestend as Chain>::Runtime;

type RuntimeEvent = <BridgeHubWestend as Chain>::RuntimeEvent;

// create token
snowbridge_pallet_system::Tokens::<Runtime>::insert(
token_id,
VersionedLocation::from(asset_id),
);

// Send relay token back to AH
let message_id: H256 = [0; 32].into();
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::SendNativeToken {
token_id,
destination: Destination::ForeignAccountId32 {
para_id: AssetHubWestend::para_id().into(),
id: AssetHubWestendReceiver::get().into(),
fee: XCM_FEE,
},
amount: TOKEN_AMOUNT,
},
});
// Convert the message to XCM
let (xcm, _) = EthereumInboundQueue::do_convert(message_id, message).unwrap();
// Send the XCM
let _ = EthereumInboundQueue::send_xcm(xcm, AssetHubWestend::para_id().into()).unwrap();

assert_expected_events!(
BridgeHubWestend,
vec![
RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
]
);
});

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

let events = AssetHubWestend::events();

// Check that the native token burnt from some reserved account
assert!(
events.iter().any(|event| matches!(
event,
RuntimeEvent::Balances(pallet_balances::Event::Burned { amount, ..})
if *amount == TOKEN_AMOUNT,
)),
"native token burnt from Ethereum sovereign account."
);

// Check that the token was minted to beneficiary
assert!(
events.iter().any(|event| matches!(
event,
RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount })
if *amount == TOKEN_AMOUNT && *who == AssetHubWestendReceiver::get()
)),
"Token minted to beneficiary."
);
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ parameter_types! {
pub StakingPot: AccountId = CollatorSelection::account_id();
pub TreasuryAccount: AccountId = TREASURY_PALLET_ID.into_account_truncating();
pub RelayTreasuryLocation: Location = (Parent, PalletInstance(westend_runtime_constants::TREASURY_PALLET_ID)).into();
pub GlobalWestendLocation: Location = Location::new(1,[GlobalConsensus(Westend)]);
}

/// Type for specifying how a `Location` can be converted into an `AccountId`. This is used
Expand All @@ -106,6 +107,20 @@ pub type LocationToAccountId = (
GlobalConsensusEthereumConvertsFor<AccountId>,
);

/// Means for transacting the native currency on this chain.
pub type GlobalFungibleTransactor = FungibleAdapter<
// Use this currency:
Balances,
// Use this currency when it is a fungible asset matching the given location or name:
IsConcrete<GlobalWestendLocation>,
// Convert an XCM Location into a local account id:
LocationToAccountId,
// Our chain's account ID type (we can't get away without mentioning it explicitly):
AccountId,
// We don't track any teleports of `Balances`.
(),
>;

/// Means for transacting the native currency on this chain.
pub type FungibleTransactor = FungibleAdapter<
// Use this currency:
Expand Down Expand Up @@ -217,6 +232,7 @@ pub type PoolFungiblesTransactor = FungiblesAdapter<
/// Means for transacting assets on this chain.
pub type AssetTransactors = (
FungibleTransactor,
GlobalFungibleTransactor,
FungiblesTransactor,
ForeignFungiblesTransactor,
PoolFungiblesTransactor,
Expand Down Expand Up @@ -646,8 +662,8 @@ pub mod bridging {

pub mod to_ethereum {
use super::*;
use assets_common::matching::FromNetwork;
use alloc::collections::btree_set::BTreeSet;
use assets_common::matching::FromNetwork;
use testnet_parachains_constants::westend::snowbridge::{
EthereumNetwork, INBOUND_QUEUE_PALLET_INDEX,
};
Expand All @@ -657,7 +673,7 @@ pub mod bridging {
/// (initially was calculated by test `OutboundQueue::calculate_fees` - ETH/ROC 1/400 and fee_per_gas 20 GWEI = 2200698000000 + *25%)
/// Needs to be more than fee calculated from DefaultFeeConfig FeeConfigRecord in snowbridge:parachain/pallets/outbound-queue/src/lib.rs
/// Polkadot uses 10 decimals, Kusama and Rococo 12 decimals.
pub const DefaultBridgeHubEthereumBaseFee: Balance = 2_750_872_500_000;
pub const DefaultBridgeHubEthereumBaseFee: Balance = 3_200_000_000_000;
pub storage BridgeHubEthereumBaseFee: Balance = DefaultBridgeHubEthereumBaseFee::get();
pub SiblingBridgeHubWithEthereumInboundQueueInstance: Location = Location::new(
1,
Expand Down

0 comments on commit 33ea85e

Please sign in to comment.