Skip to content

Commit

Permalink
Preserve origin with AliasOrigin
Browse files Browse the repository at this point in the history
  • Loading branch information
yrong committed Oct 29, 2024
1 parent 67c6e79 commit f40656c
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 62 deletions.
59 changes: 26 additions & 33 deletions bridges/snowbridge/primitives/router/src/outbound/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use snowbridge_core::{
AgentId, TokenId, TokenIdOf,
};
use sp_core::{H160, H256};
use sp_runtime::traits::MaybeEquivalence;
use sp_runtime::traits::{BlakeTwo256, Hash, MaybeEquivalence};
use sp_std::{iter::Peekable, marker::PhantomData, prelude::*};
use xcm::prelude::*;
use xcm_builder::{CreateMatcher, ExporterFor, MatchXcm};
Expand Down Expand Up @@ -112,13 +112,13 @@ where
SendError::MissingArgument
})?;

// Inspect ExpectAsset as V2 message
// Inspect AliasOrigin as V2 message
let mut instructions = message.clone().0;
let result = instructions.matcher().match_next_inst_while(
|_| true,
|inst| {
return match inst {
ExpectAsset(..) => Err(ProcessMessageError::Yield),
AliasOrigin(..) => Err(ProcessMessageError::Yield),
_ => Ok(ControlFlow::Continue(())),
}
},
Expand Down Expand Up @@ -180,6 +180,7 @@ enum XcmConverterError {
InvalidAsset,
UnexpectedInstruction,
TooManyCommands,
AliasOriginExpected,
}

macro_rules! match_expression {
Expand Down Expand Up @@ -229,6 +230,14 @@ where
Ok(result)
}

/// Convert the xcm for Ethereum-native token from AH into the Command
/// To match transfers of Ethereum-native tokens, we expect an input of the form:
/// # WithdrawAsset(WETH_FEE)
/// # PayFees(WETH_FEE)
/// # WithdrawAsset(WETH)
/// # AliasOrigin(origin)
/// # DepositAsset(WETH)
/// # SetTopic
fn send_tokens_message(&mut self) -> Result<Message, XcmConverterError> {
use XcmConverterError::*;

Expand All @@ -239,15 +248,9 @@ where
match_expression!(self.next()?, WithdrawAsset(reserve_assets), reserve_assets)
.ok_or(WithdrawAssetExpected)?;

// Check if clear origin exists and skip over it.
if match_expression!(self.peek(), Ok(ClearOrigin), ()).is_some() {
let _ = self.next();
}

// Check if ExpectAsset exists and skip over it.
if match_expression!(self.peek(), Ok(ExpectAsset { .. }), ()).is_some() {
let _ = self.next();
}
// Check AliasOrigin.
let origin = match_expression!(self.next()?, AliasOrigin(origin), origin)
.ok_or(AliasOriginExpected)?;

let (deposit_assets, beneficiary) = match_expression!(
self.next()?,
Expand Down Expand Up @@ -298,8 +301,7 @@ where

let message = Message {
id: (*topic_id).into(),
// Todo: from XCMV5 AliasOrigin
origin: H256::zero(),
origin: BlakeTwo256::hash_of(origin),
fee: fee_amount,
commands: BoundedVec::try_from(vec![Command::UnlockNativeToken {
agent_id: self.agent_id,
Expand All @@ -317,10 +319,6 @@ where
self.iter.next().ok_or(XcmConverterError::UnexpectedEndOfXcm)
}

fn peek(&mut self) -> Result<&&'a Instruction<Call>, XcmConverterError> {
self.iter.peek().ok_or(XcmConverterError::UnexpectedEndOfXcm)
}

fn network_matches(&self, network: &Option<NetworkId>) -> bool {
if let Some(network) = network {
*network == self.ethereum_network
Expand All @@ -331,10 +329,11 @@ where

/// Convert the xcm for Polkadot-native token from AH into the Command
/// To match transfers of Polkadot-native tokens, we expect an input of the form:
/// # ReserveAssetDeposited
/// # ClearOrigin
/// # BuyExecution
/// # DepositAsset
/// # WithdrawAsset(WETH)
/// # PayFees(WETH)
/// # ReserveAssetDeposited(DOT)
/// # AliasOrigin(origin)
/// # DepositAsset(DOT)
/// # SetTopic
fn send_native_tokens_message(&mut self) -> Result<Message, XcmConverterError> {
use XcmConverterError::*;
Expand All @@ -346,15 +345,9 @@ where
match_expression!(self.next()?, ReserveAssetDeposited(reserve_assets), reserve_assets)
.ok_or(ReserveAssetDepositedExpected)?;

// Check if clear origin exists and skip over it.
if match_expression!(self.peek(), Ok(ClearOrigin), ()).is_some() {
let _ = self.next();
}

// Check if ExpectAsset exists and skip over it.
if match_expression!(self.peek(), Ok(ExpectAsset { .. }), ()).is_some() {
let _ = self.next();
}
// Check AliasOrigin.
let origin = match_expression!(self.next()?, AliasOrigin(origin), origin)
.ok_or(AliasOriginExpected)?;

let (deposit_assets, beneficiary) = match_expression!(
self.next()?,
Expand Down Expand Up @@ -406,7 +399,7 @@ where
let topic_id = match_expression!(self.next()?, SetTopic(id), id).ok_or(SetTopicExpected)?;

let message = Message {
origin: H256::zero(),
origin: BlakeTwo256::hash_of(origin),
fee: fee_amount,
id: (*topic_id).into(),
commands: BoundedVec::try_from(vec![Command::MintForeignToken {
Expand Down Expand Up @@ -472,7 +465,7 @@ impl Contains<Xcm<()>> for XcmForSnowbridgeV2 {
|_| true,
|inst| {
return match inst {
ExpectAsset(..) => Err(ProcessMessageError::Yield),
AliasOrigin(..) => Err(ProcessMessageError::Yield),
_ => Ok(ControlFlow::Continue(())),
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::imports::*;
use asset_hub_westend_runtime::xcm_config::bridging::to_ethereum::DefaultBridgeHubEthereumBaseFee;
use bridge_hub_westend_runtime::EthereumInboundQueue;
use codec::{Decode, Encode};
use emulated_integration_tests_common::RESERVABLE_ASSET_ID;
use frame_support::pallet_prelude::TypeInfo;
use hex_literal::hex;
use rococo_westend_system_emulated_network::asset_hub_westend_emulated_chain::genesis::AssetHubWestendAssetOwner;
use snowbridge_core::{outbound::OperatingMode, AssetMetadata, TokenIdOf};
use snowbridge_core::{AssetMetadata, TokenIdOf};
use snowbridge_router_primitives::inbound::{
v1::{Command, Destination, MessageV1, VersionedMessage},
GlobalConsensusEthereumConvertsFor,
};
use sp_core::H256;
use sp_runtime::MultiAddress;
use testnet_parachains_constants::westend::snowbridge::EthereumNetwork;
use xcm::v5::AssetTransferFilter;
Expand Down Expand Up @@ -121,12 +115,7 @@ fn send_weth_from_asset_hub_to_ethereum() {
[AccountKey20 { network: None, key: ETHEREUM_DESTINATION_ADDRESS.into() }],
);

// Internal xcm of InitiateReserveWithdraw, WithdrawAssets + ClearOrigin instructions will
// be appended to the front of the list by the xcm executor
let xcm_on_bh = Xcm(vec![
ExpectAsset(vec![remote_fee_asset.clone()].into()),
DepositAsset { assets: Wild(AllCounted(2)), beneficiary },
]);
let xcm_on_bh = Xcm(vec![DepositAsset { assets: Wild(AllCounted(2)), beneficiary }]);

let xcms = VersionedXcm::from(Xcm(vec![
WithdrawAsset(assets.clone().into()),
Expand All @@ -136,6 +125,7 @@ fn send_weth_from_asset_hub_to_ethereum() {
remote_fees: Some(AssetTransferFilter::ReserveWithdraw(Definite(
remote_fee_asset.clone().into(),
))),
preserve_origin: true,
assets: vec![AssetTransferFilter::ReserveWithdraw(Definite(
reserve_asset.clone().into(),
))],
Expand All @@ -153,7 +143,6 @@ fn send_weth_from_asset_hub_to_ethereum() {
});

BridgeHubWestend::execute_with(|| {
use bridge_hub_westend_runtime::xcm_config::TreasuryAccount;
type RuntimeEvent = <BridgeHubWestend as Chain>::RuntimeEvent;
// Check that the transfer token back to Ethereum message was queue in the Ethereum
// Outbound Queue
Expand Down Expand Up @@ -185,8 +174,6 @@ fn transfer_relay_token() {
let expected_asset_id: Location =
Location { parents: 1, interior: [GlobalConsensus(Westend)].into() };

let expected_token_id = TokenIdOf::convert_location(&expected_asset_id).unwrap();

let ethereum_sovereign: AccountId =
GlobalConsensusEthereumConvertsFor::<[u8; 32]>::convert_location(&Location::new(
2,
Expand Down Expand Up @@ -274,10 +261,7 @@ fn transfer_relay_token() {
[AccountKey20 { network: None, key: ETHEREUM_DESTINATION_ADDRESS.into() }],
);

let xcm_on_bh = Xcm(vec![
ExpectAsset(vec![remote_fee_asset.clone()].into()),
DepositAsset { assets: Wild(AllCounted(2)), beneficiary },
]);
let xcm_on_bh = Xcm(vec![DepositAsset { assets: Wild(AllCounted(2)), beneficiary }]);

let xcms = VersionedXcm::from(Xcm(vec![
WithdrawAsset(assets.clone().into()),
Expand All @@ -287,6 +271,7 @@ fn transfer_relay_token() {
remote_fees: Some(AssetTransferFilter::ReserveWithdraw(Definite(
remote_fee_asset.clone().into(),
))),
preserve_origin: true,
assets: vec![AssetTransferFilter::ReserveDeposit(Definite(
Asset { id: AssetId(Location::parent()), fun: Fungible(TOKEN_AMOUNT) }.into(),
))],
Expand All @@ -302,16 +287,16 @@ fn transfer_relay_token() {
)
.unwrap();

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 { to, ..})
// if *to == ethereum_sovereign.clone(),
// )),
// "native token reserved to Ethereum sovereign account."
// );
let events = AssetHubWestend::events();
assert!(
events.iter().any(|event| matches!(
event,
RuntimeEvent::Balances(pallet_balances::Event::Minted { who, amount})
if *who == ethereum_sovereign.clone() && *amount == TOKEN_AMOUNT,
)),
"native token reserved to Ethereum sovereign account."
);
});

BridgeHubWestend::execute_with(|| {
Expand Down

0 comments on commit f40656c

Please sign in to comment.