Skip to content

Commit

Permalink
inbound progress
Browse files Browse the repository at this point in the history
  • Loading branch information
claravanstaden committed Nov 6, 2024
1 parent d81affc commit 1638660
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 43 deletions.
13 changes: 7 additions & 6 deletions bridges/snowbridge/pallets/inbound-queue-v2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,33 +44,33 @@ use scale_info::TypeInfo;
use sp_core::H160;
use sp_std::vec;
use xcm::{
prelude::{send_xcm, Junction::*, Location, SendError as XcmpSendError, SendXcm, Xcm},
VersionedXcm, MAX_XCM_DECODE_DEPTH,
prelude::{send_xcm, Junction::*, Location, SendError as XcmpSendError, SendXcm},
};

use snowbridge_core::{
inbound::{Message, VerificationError, Verifier},
BasicOperatingMode,
};
use snowbridge_router_primitives::inbound::v2::Message as MessageV2;
use snowbridge_router_primitives::inbound::v2::ConvertMessage;

pub use weights::WeightInfo;

#[cfg(feature = "runtime-benchmarks")]
use snowbridge_beacon_primitives::BeaconHeader;

use snowbridge_router_primitives::inbound::v2::ConvertMessageError;

pub use pallet::*;

pub const LOG_TARGET: &str = "snowbridge-inbound-queue:v2";

#[frame_support::pallet]
pub mod pallet {
use super::*;
use codec::DecodeLimit;

use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use sp_core::H256;

#[pallet::pallet]
pub struct Pallet<T>(_);
Expand All @@ -97,6 +97,7 @@ pub mod pallet {
type WeightInfo: WeightInfo;
/// AssetHub parachain ID
type AssetHubParaId: Get<u32>;
type MessageConverter: ConvertMessage;
#[cfg(feature = "runtime-benchmarks")]
type Helper: BenchmarkHelper<Self>;
}
Expand Down Expand Up @@ -207,7 +208,7 @@ pub mod pallet {
let message = MessageV2::decode_all(&mut envelope.payload.as_ref())
.map_err(|_| Error::<T>::InvalidPayload)?;

let xcm = convert_message(message)?;
let xcm = T::MessageConverter::convert(message).map_err(|e| Error::<T>::ConvertMessage(e))?;

// Todo: Deposit fee(in Ether) to RewardLeger which should cover all of:
// T::RewardLeger::deposit(who, envelope.fee.into())?;
Expand All @@ -218,7 +219,7 @@ pub mod pallet {
// e. The reward

// Attempt to forward XCM to AH
let dest = Location::new(1, [Parachain(T::AssetHubParaId)]);
let dest = Location::new(1, [Parachain(T::AssetHubParaId::get())]);
let (message_id, _) = send_xcm::<T::XcmSender>(dest, xcm).map_err(Error::<T>::from)?;

Self::deposit_event(Event::MessageReceived { nonce: envelope.nonce, message_id });
Expand Down
29 changes: 14 additions & 15 deletions bridges/snowbridge/pallets/inbound-queue-v2/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use sp_runtime::{
};
use sp_std::{convert::From, default::Default};
use xcm::{latest::SendXcm, prelude::*};

use snowbridge_router_primitives::inbound::v2::MessageToXcm;
use crate::{self as inbound_queue};

type Block = frame_system::mocking::MockBlock<Test>;
Expand Down Expand Up @@ -100,20 +100,6 @@ impl Verifier for MockVerifier {

const GATEWAY_ADDRESS: [u8; 20] = hex!["eda338e4dc46038493b885327842fd3e301cab39"];

parameter_types! {
pub const EthereumNetwork: xcm::v3::NetworkId = xcm::v3::NetworkId::Ethereum { chain_id: 11155111 };
pub const GatewayAddress: H160 = H160(GATEWAY_ADDRESS);
pub const CreateAssetCall: [u8;2] = [53, 0];
pub const CreateAssetExecutionFee: u128 = 2_000_000_000;
pub const CreateAssetDeposit: u128 = 100_000_000_000;
pub const SendTokenExecutionFee: u128 = 1_000_000_000;
pub const InitialFund: u128 = 1_000_000_000_000;
pub const InboundQueuePalletInstance: u8 = 80;
pub UniversalLocation: InteriorLocation =
[GlobalConsensus(Westend), Parachain(1002)].into();
pub AssetHubFromEthereum: Location = Location::new(1,[GlobalConsensus(Westend),Parachain(1000)]);
}

#[cfg(feature = "runtime-benchmarks")]
impl<T: snowbridge_pallet_ethereum_client::Config> BenchmarkHelper<T> for Test {
// not implemented since the MockVerifier is used for tests
Expand Down Expand Up @@ -158,12 +144,25 @@ impl MaybeEquivalence<TokenId, Location> for MockTokenIdConvert {
}
}

parameter_types! {
pub const EthereumNetwork: xcm::v5::NetworkId = xcm::v5::NetworkId::Ethereum { chain_id: 11155111 };
pub const GatewayAddress: H160 = H160(GATEWAY_ADDRESS);
pub const InboundQueuePalletInstance: u8 = 80;
pub AssetHubLocation: InteriorLocation = Parachain(1000).into();
}

impl inbound_queue::Config for Test {
type RuntimeEvent = RuntimeEvent;
type Verifier = MockVerifier;
type XcmSender = MockXcmSender;
type WeightInfo = ();
type GatewayAddress = GatewayAddress;
type AssetHubParaId = ConstU32<1000>;
type MessageConverter = MessageToXcm<
EthereumNetwork,
AssetHubLocation,
InboundQueuePalletInstance,
>;
#[cfg(feature = "runtime-benchmarks")]
type Helper = Test;
}
Expand Down
9 changes: 5 additions & 4 deletions bridges/snowbridge/pallets/inbound-queue-v2/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,16 @@ use sp_runtime::DispatchError;

use crate::{mock::*, Error, Event as InboundQueueEvent};
use codec::DecodeLimit;
use snowbridge_router_primitives::inbound::v2::Asset as InboundAsset;
use snowbridge_router_primitives::inbound::v2::InboundAsset;
use sp_core::H256;
use xcm::opaque::latest::{
prelude::{ClearOrigin, ReceiveTeleportedAsset},
Asset, AssetId, Assets,
};
use xcm::VersionedXcm;
use xcm::MAX_XCM_DECODE_DEPTH;
use snowbridge_router_primitives::inbound::v2::ConvertMessage;
use xcm::prelude::{Junction::AccountKey20, *};

#[test]
fn test_submit_happy_path() {
Expand Down Expand Up @@ -246,9 +250,6 @@ fn test_register_token_inbound_message_with_xcm_and_claimer() {
}
};

let total_fee_asset: Asset = (Location::parent(), 1_000_000_000).into();
let first_instruction = ReceiveTeleportedAsset(total_fee_asset.into());

let mut decoded_instructions = decoded_instructions.into_iter();
let decoded_first = decoded_instructions.next().take();
assert!(decoded_first.is_some());
Expand Down
76 changes: 58 additions & 18 deletions bridges/snowbridge/primitives/router/src/inbound/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@ use codec::{Decode, Encode};
use core::marker::PhantomData;
use frame_support::PalletError;
use scale_info::TypeInfo;
use snowbridge_core::TokenId;
use sp_core::{Get, RuntimeDebug, H160, H256};
use sp_runtime::MultiAddress;
use sp_std::prelude::*;
use xcm::prelude::{Junction::AccountKey20, *};
use xcm::MAX_XCM_DECODE_DEPTH;
use codec::DecodeLimit;

const MINIMUM_DEPOSIT: u128 = 1;
const LOG_TARGET: &str = "snowbridge-router-primitives";

/// Messages from Ethereum are versioned. This is because in future,
Expand All @@ -32,23 +29,23 @@ pub struct Message {
/// The origin address
pub origin: H160,
/// The assets
pub assets: Vec<Asset>,
pub assets: Vec<InboundAsset>,
// The command originating from the Gateway contract
pub xcm: Vec<u8>,
// The claimer in the case that funds get trapped.
pub claimer: Option<Vec<u8>>,
}

#[derive(Clone, Encode, Decode, RuntimeDebug)]
pub enum Asset {
pub enum InboundAsset {
NativeTokenERC20 {
/// The token ID, native or foreign
/// The native token ID
token_id: H160,
/// The monetary value of the asset
value: u128
},
ForeignTokenERC20 {
/// The token ID, native or foreign
/// The foreign token ID
token_id: H256,
/// The monetary value of the asset
value: u128
Expand All @@ -71,29 +68,35 @@ pub trait ConvertMessage {
}

pub struct MessageToXcm<
EthereumUniversalLocation,
EthereumNetwork,
AssetHubLocation,
InboundQueuePalletInstance,
> where
EthereumUniversalLocation: Get<InteriorLocation>,
EthereumNetwork: Get<NetworkId>,
AssetHubLocation: Get<InteriorLocation>,
InboundQueuePalletInstance: Get<u8>,
{
_phantom: PhantomData<(
EthereumUniversalLocation,
EthereumNetwork,
AssetHubLocation,
InboundQueuePalletInstance,
)>,
}

impl<
EthereumUniversalLocation,
EthereumNetwork,
AssetHubLocation,
InboundQueuePalletInstance,
> ConvertMessage
for MessageToXcm<
EthereumUniversalLocation,
EthereumNetwork,
AssetHubLocation,
InboundQueuePalletInstance,
>
where
EthereumUniversalLocation: Get<InteriorLocation>,
EthereumNetwork: Get<NetworkId>,
AssetHubLocation: Get<InteriorLocation>,
InboundQueuePalletInstance: Get<u8>,
{
fn convert(message: Message) -> Result<Xcm<()>, ConvertMessageError> {
// Decode xcm
Expand All @@ -105,17 +108,54 @@ for MessageToXcm<

log::debug!(target: LOG_TARGET,"xcm decoded as {:?}", message_xcm);

let origin_location: Location = Location::new(2, [EthereumUniversalLocation::get().into(), Junction::AccountKey20{ key: message.origin.into(), network: None}.into()]);
let instructions = vec![
AliasOrigin(origin_location),
let network = EthereumNetwork::get();

let mut origin_location = Location::new(2, GlobalConsensus(network)).push_interior(AccountKey20 {
key: message.origin.into(), network: None
}).map_err(|_| ConvertMessageError::InvalidXCM)?;

let network = EthereumNetwork::get();

let fee_asset = Location::new(1, Here);
let fee_value = 1_000_000_000u128; // TODO configure
let fee: Asset = (fee_asset, fee_value).into();
let mut instructions = vec![
ReceiveTeleportedAsset(fee.clone().into()),
BuyExecution{fees: fee, weight_limit: Unlimited},
DescendOrigin(PalletInstance(InboundQueuePalletInstance::get()).into()),
UniversalOrigin(GlobalConsensus(network)),
AliasOrigin(origin_location.into()),
];

for asset in &message.assets {
match asset {
InboundAsset::NativeTokenERC20 { token_id, value } => {
let token_location: Location = Location::new(2, [GlobalConsensus(EthereumNetwork::get()), AccountKey20{network: None, key: (*token_id).into()}]);
instructions.push(ReserveAssetDeposited((token_location, *value).into()));
}
InboundAsset::ForeignTokenERC20 { token_id, value } => {
// TODO check how token is represented as H256 on AH, assets pallet?
let token_location: Location = Location::new(0, [AccountId32 {network: None, id: (*token_id).into()}]);
// TODO Is this token always on AH? Would probably need to distinguish between tokens on other parachains eventually
instructions.push(WithdrawAsset((token_location, *value).into()));
}
}
}

if let Some(claimer) = message.claimer {
let claimer = MultiAddress::decode(&mut claimer.as_ref()).map_err(|_| ConvertMessageError::InvalidClaimer)?;
let claimer_location: Location = Location::new(1, [AssetHubLocation::get().into(), claimer.into()]);
let claimer = Junction::decode(&mut claimer.as_ref()).map_err(|_| ConvertMessageError::InvalidClaimer)?;
let claimer_location: Location = Location::new(0, [claimer.into()]);
instructions.push(SetAssetClaimer { location: claimer_location });
}

// TODO not sure this is correct, should the junction be prefixed with GlobalConsensus(EthereumNetwork::get()?
instructions.push(DescendOrigin(AccountKey20 {
key: message.origin.into(), network: None
}.into()));

// Add the XCM the user specified to the end of the XCM
instructions.extend(message_xcm.0);

Ok(instructions.into())
}
}
Expand Down

0 comments on commit 1638660

Please sign in to comment.