Lines
83.87 %
Functions
6.02 %
Branches
100 %
// Copyright (C) Moondance Labs Ltd.
// This file is part of Tanssi.
// Tanssi is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Tanssi is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Tanssi. If not, see <http://www.gnu.org/licenses/>
use {
alloc::vec,
core::marker::PhantomData,
cumulus_primitives_core::ParaId,
frame_support::traits::Get,
xcm::{
latest::{Location, NetworkId},
prelude::*,
},
xcm_builder::InspectMessageQueues,
SendError::*,
};
// We check if the destination is ETH
fn is_ethereum_location(loc: &Location, ethereum_network: NetworkId) -> bool {
matches!(
loc,
Location {
parents: 2,
interior: Junctions::X1(juncs)
} if juncs[0] == GlobalConsensus(ethereum_network)
)
}
pub struct SovereignPaidRemoteExporter<
Router,
UniversalLocation,
EthereumNetwork,
ExecutionFee,
SelfParaId,
>(
PhantomData<(
)>,
);
impl<
Router: SendXcm,
UniversalLocation: Get<InteriorLocation>,
> SendXcm
for SovereignPaidRemoteExporter<
>
where
EthereumNetwork: Get<NetworkId>,
ExecutionFee: Get<u128>,
SelfParaId: Get<ParaId>,
{
type Ticket = Router::Ticket;
fn validate(
dest: &mut Option<Location>,
msg: &mut Option<Xcm<()>>,
) -> SendResult<Router::Ticket> {
log::trace!(target: "xcm::sovereign_paid_remote_exporter", "validate params: dest={dest:?}, msg={msg:?}");
let d = dest.as_ref().ok_or(MissingArgument)?;
let xcm = msg.take().ok_or(MissingArgument)?;
// Check if the destination is an Ethereum location
if !is_ethereum_location(&d.clone(), EthereumNetwork::get()) {
return Err(NotApplicable);
// `xcm` should already end with `SetTopic` - if it does, then extract and derive into
// an onward topic ID.
let maybe_forward_id = match xcm.last() {
Some(SetTopic(t)) => Some(*t),
_ => None,
let export_instruction = ExportMessage {
network: EthereumNetwork::get(),
destination: Here,
xcm: xcm.clone(),
// For now hardcoding fees, but later it should be converted from fixed Tanssi relay amount
let fees = Asset {
id: AssetId(Location::here()),
fun: Fungible(ExecutionFee::get()),
let container_location = Location::new(0, Parachain(SelfParaId::get().into()));
// Prepare the message to send
let mut message = Xcm(vec![
WithdrawAsset(fees.clone().into()),
BuyExecution {
fees,
weight_limit: Unlimited,
SetAppendix(Xcm(vec![DepositAsset {
assets: AllCounted(1).into(),
beneficiary: container_location,
}])),
export_instruction,
]);
let tanssi_location = Location {
parents: 1,
interior: Here,
if let Some(forward_id) = maybe_forward_id {
message.0.push(SetTopic(forward_id));
let (v, cost) = validate_send::<Router>(tanssi_location, message).inspect_err(|err| {
if let NotApplicable = err {
*msg = Some(xcm);
})?;
Ok((v, cost))
fn deliver(ticket: Router::Ticket) -> Result<XcmHash, SendError> {
Router::deliver(ticket)
> InspectMessageQueues
fn clear_messages() {}
fn get_messages() -> vec::Vec<(VersionedLocation, vec::Vec<VersionedXcm<()>>)> {
vec::Vec::new()