feat: initialize Kurdistan SDK - independent fork of Polkadot SDK

This commit is contained in:
2025-12-13 15:44:15 +03:00
commit 286de54384
6841 changed files with 1848356 additions and 0 deletions
@@ -0,0 +1,85 @@
[package]
name = "pallet-xcm-precompiles"
version = "0.1.0"
authors.workspace = true
edition.workspace = true
license = "Apache-2.0"
homepage.workspace = true
repository.workspace = true
description = "Provides precompiles for `pallet-xcm`"
[lints]
workspace = true
[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
codec = { features = ["derive"], workspace = true }
tracing = { workspace = true }
frame-support = { workspace = true }
pallet-revive = { workspace = true }
pallet-xcm = { workspace = true }
xcm = { workspace = true }
xcm-executor = { workspace = true }
[dev-dependencies]
frame-system = { workspace = true, default-features = true }
pallet-assets = { workspace = true, default-features = true }
pallet-balances = { workspace = true, default-features = true }
pallet-timestamp = { workspace = true, default-features = true }
pezkuwi-teyrchain-primitives = { workspace = true, default-features = true }
scale-info = { workspace = true, default-features = true }
sp-io = { workspace = true, default-features = true }
sp-runtime = { workspace = true, default-features = true }
xcm-builder = { workspace = true, default-features = true }
xcm-simulator = { workspace = true, default-features = true }
[features]
default = ["std"]
std = [
"codec/std",
"frame-support/std",
"frame-system/std",
"pallet-assets/std",
"pallet-balances/std",
"pallet-revive/std",
"pallet-timestamp/std",
"pallet-xcm/std",
"pezkuwi-teyrchain-primitives/std",
"scale-info/std",
"sp-io/std",
"sp-runtime/std",
"tracing/std",
"xcm-builder/std",
"xcm-executor/std",
"xcm/std",
]
runtime-benchmarks = [
"frame-support/runtime-benchmarks",
"frame-system/runtime-benchmarks",
"pallet-assets/runtime-benchmarks",
"pallet-balances/runtime-benchmarks",
"pallet-revive/runtime-benchmarks",
"pallet-timestamp/runtime-benchmarks",
"pallet-xcm/runtime-benchmarks",
"pezkuwi-teyrchain-primitives/runtime-benchmarks",
"sp-io/runtime-benchmarks",
"sp-runtime/runtime-benchmarks",
"xcm-builder/runtime-benchmarks",
"xcm-executor/runtime-benchmarks",
"xcm-simulator/runtime-benchmarks",
"xcm/runtime-benchmarks",
]
try-runtime = [
"frame-support/try-runtime",
"frame-system/try-runtime",
"pallet-assets/try-runtime",
"pallet-balances/try-runtime",
"pallet-revive/try-runtime",
"pallet-timestamp/try-runtime",
"pallet-xcm/try-runtime",
"sp-runtime/try-runtime",
]
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/// @dev The on-chain address of the XCM (Cross-Consensus Messaging) precompile.
address constant XCM_PRECOMPILE_ADDRESS = address(0xA0000);
/// @title XCM Precompile Interface
/// @notice A low-level interface for interacting with `pallet_xcm`.
/// It forwards calls directly to the corresponding dispatchable functions,
/// providing access to XCM execution and message passing.
/// @dev Documentation:
/// @dev - XCM: https://docs.pezkuwichain.io/develop/interoperability
/// @dev - SCALE codec: https://docs.pezkuwichain.io/polkadot-protocol/parachain-basics/data-encoding
/// @dev - Weights: https://docs.pezkuwichain.io/polkadot-protocol/parachain-basics/blocks-transactions-fees/fees/#transactions-weights-and-fees
interface IXcm {
/// @notice Weight v2 used for measurement for an XCM execution
struct Weight {
/// @custom:property The computational time used to execute some logic based on reference hardware.
uint64 refTime;
/// @custom:property The size of the proof needed to execute some logic.
uint64 proofSize;
}
/// @notice Executes an XCM message locally on the current chain with the caller's origin.
/// @dev Internally calls `pallet_xcm::execute`.
/// @param message A SCALE-encoded Versioned XCM message.
/// @param weight The maximum allowed `Weight` for execution.
/// @dev Call @custom:function weighMessage(message) to ensure sufficient weight allocation.
function execute(bytes calldata message, Weight calldata weight) external;
/// @notice Sends an XCM message to another parachain or consensus system.
/// @dev Internally calls `pallet_xcm::send`.
/// @param destination SCALE-encoded destination MultiLocation.
/// @param message SCALE-encoded Versioned XCM message.
function send(bytes calldata destination, bytes calldata message) external;
/// @notice Estimates the `Weight` required to execute a given XCM message.
/// @param message SCALE-encoded Versioned XCM message to analyze.
/// @return weight Struct containing estimated `refTime` and `proofSize`.
function weighMessage(bytes calldata message) external view returns (Weight memory weight);
}
@@ -0,0 +1,182 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Pezkuwi.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Ensure we're `no_std` when compiling for Wasm.
#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
use alloc::vec::Vec;
use codec::{DecodeAll, DecodeLimit};
use core::{fmt, marker::PhantomData, num::NonZero};
use frame_support::dispatch::RawOrigin;
use pallet_revive::{
precompiles::{
alloy::{self, sol_types::SolValue},
AddressMatcher, Error, Ext, Precompile,
},
DispatchInfo, ExecOrigin as Origin, Weight,
};
use pallet_xcm::{Config, WeightInfo};
use tracing::error;
use xcm::{v5, IdentifyVersion, VersionedLocation, VersionedXcm, MAX_XCM_DECODE_DEPTH};
use xcm_executor::traits::WeightBounds;
alloy::sol!("src/interface/IXcm.sol");
use IXcm::IXcmCalls;
#[cfg(test)]
mod mock;
#[cfg(test)]
mod tests;
const LOG_TARGET: &str = "xcm::precompiles";
fn revert(error: &impl fmt::Debug, message: &str) -> Error {
error!(target: LOG_TARGET, ?error, "{}", message);
Error::Revert(message.into())
}
// We don't allow XCM versions older than 5.
fn ensure_xcm_version<V: IdentifyVersion>(input: &V) -> Result<(), Error> {
let version = input.identify_version();
if version < v5::VERSION {
return Err(Error::Revert("Only XCM version 5 and onwards are supported.".into()));
}
Ok(())
}
pub struct XcmPrecompile<T>(PhantomData<T>);
impl<Runtime> Precompile for XcmPrecompile<Runtime>
where
Runtime: crate::Config + pallet_revive::Config,
{
type T = Runtime;
const MATCHER: AddressMatcher = AddressMatcher::Fixed(NonZero::new(10).unwrap());
const HAS_CONTRACT_INFO: bool = false;
type Interface = IXcm::IXcmCalls;
fn call(
_address: &[u8; 20],
input: &Self::Interface,
env: &mut impl Ext<T = Self::T>,
) -> Result<Vec<u8>, Error> {
let origin = env.caller();
let frame_origin = match origin {
Origin::Root => RawOrigin::Root.into(),
Origin::Signed(account_id) => RawOrigin::Signed(account_id.clone()).into(),
};
match input {
IXcmCalls::send(_) | IXcmCalls::execute(_) if env.is_read_only() =>
Err(Error::Error(pallet_revive::Error::<Self::T>::StateChangeDenied.into())),
IXcmCalls::send(IXcm::sendCall { destination, message }) => {
let _ = env.charge(<Runtime as Config>::WeightInfo::send())?;
let final_destination = VersionedLocation::decode_all(&mut &destination[..])
.map_err(|error| {
revert(&error, "XCM send failed: Invalid destination format")
})?;
ensure_xcm_version(&final_destination)?;
let final_message = VersionedXcm::<()>::decode_all_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut &message[..],
)
.map_err(|error| revert(&error, "XCM send failed: Invalid message format"))?;
ensure_xcm_version(&final_message)?;
pallet_xcm::Pallet::<Runtime>::send(
frame_origin,
final_destination.into(),
final_message.into(),
)
.map(|_| Vec::new())
.map_err(|error| {
revert(
&error,
"XCM send failed: destination or message format may be incompatible",
)
})
},
IXcmCalls::execute(IXcm::executeCall { message, weight }) => {
let max_weight = Weight::from_parts(weight.refTime, weight.proofSize);
let weight_to_charge =
max_weight.saturating_add(<Runtime as Config>::WeightInfo::execute());
let charged_amount = env.charge(weight_to_charge)?;
let final_message = VersionedXcm::decode_all_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut &message[..],
)
.map_err(|error| revert(&error, "XCM execute failed: Invalid message format"))?;
ensure_xcm_version(&final_message)?;
let result = pallet_xcm::Pallet::<Runtime>::execute(
frame_origin,
final_message.into(),
max_weight,
);
let pre = DispatchInfo {
call_weight: weight_to_charge,
extension_weight: Weight::zero(),
..Default::default()
};
// Adjust gas using actual weight or fallback to initially charged weight
let actual_weight = frame_support::dispatch::extract_actual_weight(&result, &pre);
env.adjust_gas(charged_amount, actual_weight);
result.map(|_| Vec::new()).map_err(|error| {
revert(
&error,
"XCM execute failed: message may be invalid or execution constraints not satisfied"
)
})
},
IXcmCalls::weighMessage(IXcm::weighMessageCall { message }) => {
let _ = env.charge(<Runtime as Config>::WeightInfo::weigh_message())?;
let converted_message = VersionedXcm::decode_all_with_depth_limit(
MAX_XCM_DECODE_DEPTH,
&mut &message[..],
)
.map_err(|error| revert(&error, "XCM weightMessage: Invalid message format"))?;
ensure_xcm_version(&converted_message)?;
let mut final_message = converted_message.try_into().map_err(|error| {
revert(&error, "XCM weightMessage: Conversion to Xcm failed")
})?;
let weight = <<Runtime>::Weigher>::weight(&mut final_message, Weight::MAX)
.map_err(|error| {
revert(&error, "XCM weightMessage: Failed to calculate weight")
})?;
let final_weight =
IXcm::Weight { proofSize: weight.proof_size(), refTime: weight.ref_time() };
Ok(final_weight.abi_encode())
},
}
}
}
@@ -0,0 +1,343 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Pezkuwi.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
pub use core::cell::RefCell;
use frame_support::{
derive_impl, parameter_types,
traits::{
fungible::HoldConsideration, AsEnsureOriginWithArg, ConstU32, Equals, Everything,
EverythingBut, Footprint, Nothing,
},
weights::Weight,
};
use frame_system::EnsureRoot;
use pezkuwi_teyrchain_primitives::primitives::Id as ParaId;
use sp_runtime::{
traits::{Convert, IdentityLookup},
AccountId32, BuildStorage,
};
use xcm::prelude::*;
use xcm_builder::{
AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom,
AllowTopLevelPaidExecutionFrom, ChildTeyrchainConvertsVia, DescribeAllTerminal,
EnsureDecodableXcm, FixedWeightBounds, FungibleAdapter, FungiblesAdapter, HashedDescription,
IsConcrete, MatchedConvertedConcreteId, NoChecking, TakeWeightCredit,
};
use xcm_executor::{
traits::{Identity, JustTry},
XcmExecutor,
};
use xcm_simulator::helpers::derive_topic_id;
use crate::XcmPrecompile;
pub type AccountId = AccountId32;
pub type Balance = u128;
type Block = frame_system::mocking::MockBlock<Test>;
pub const ALICE: AccountId32 = AccountId::new([0u8; 32]);
parameter_types! {
pub const MinimumPeriod: u64 = 1;
}
impl pallet_timestamp::Config for Test {
type Moment = u64;
type OnTimestampSet = ();
type MinimumPeriod = MinimumPeriod;
type WeightInfo = ();
}
frame_support::construct_runtime!(
pub enum Test
{
System: frame_system,
AssetsPallet: pallet_assets,
Balances: pallet_balances,
XcmPallet: pallet_xcm,
Revive: pallet_revive,
Timestamp: pallet_timestamp,
}
);
thread_local! {
pub static SENT_XCM: RefCell<Vec<(Location, Xcm<()>)>> = RefCell::new(Vec::new());
pub static FAIL_SEND_XCM: RefCell<bool> = RefCell::new(false);
}
pub(crate) fn sent_xcm() -> Vec<(Location, Xcm<()>)> {
SENT_XCM.with(|q| (*q.borrow()).clone())
}
/// Sender that never returns error.
pub struct TestSendXcm;
impl SendXcm for TestSendXcm {
type Ticket = (Location, Xcm<()>);
fn validate(
dest: &mut Option<Location>,
msg: &mut Option<Xcm<()>>,
) -> SendResult<(Location, Xcm<()>)> {
if FAIL_SEND_XCM.with(|q| *q.borrow()) {
return Err(SendError::Transport("Intentional send failure used in tests"));
}
let pair = (dest.take().unwrap(), msg.take().unwrap());
Ok((pair, Assets::new()))
}
fn deliver(pair: (Location, Xcm<()>)) -> Result<XcmHash, SendError> {
let message = pair.1.clone();
if message
.iter()
.any(|instr| matches!(instr, ExpectError(Some((1, XcmError::Unimplemented)))))
{
return Err(SendError::Transport("Intentional deliver failure used in tests".into()));
}
let hash = derive_topic_id(&message);
SENT_XCM.with(|q| q.borrow_mut().push(pair));
Ok(hash)
}
}
/// Sender that returns error if `X8` junction and stops routing
pub struct TestSendXcmErrX8;
impl SendXcm for TestSendXcmErrX8 {
type Ticket = (Location, Xcm<()>);
fn validate(
dest: &mut Option<Location>,
_: &mut Option<Xcm<()>>,
) -> SendResult<(Location, Xcm<()>)> {
if dest.as_ref().unwrap().len() == 8 {
dest.take();
Err(SendError::Transport("Destination location full"))
} else {
Err(SendError::NotApplicable)
}
}
fn deliver(pair: (Location, Xcm<()>)) -> Result<XcmHash, SendError> {
let hash = derive_topic_id(&pair.1);
SENT_XCM.with(|q| q.borrow_mut().push(pair));
Ok(hash)
}
}
#[derive_impl(frame_system::config_preludes::TestDefaultConfig)]
impl frame_system::Config for Test {
type AccountId = AccountId;
type Lookup = IdentityLookup<Self::AccountId>;
type Block = Block;
type AccountData = pallet_balances::AccountData<Balance>;
}
parameter_types! {
pub ExistentialDeposit: Balance = 1;
}
#[derive_impl(pallet_balances::config_preludes::TestDefaultConfig)]
impl pallet_balances::Config for Test {
type Balance = Balance;
type ExistentialDeposit = ExistentialDeposit;
type AccountStore = System;
}
#[cfg(feature = "runtime-benchmarks")]
/// Simple conversion of `u32` into an `AssetId` for use in benchmarking.
pub struct XcmBenchmarkHelper;
#[cfg(feature = "runtime-benchmarks")]
impl pallet_assets::BenchmarkHelper<Location, ()> for XcmBenchmarkHelper {
fn create_asset_id_parameter(id: u32) -> Location {
Location::new(1, [Teyrchain(id)])
}
fn create_reserve_id_parameter(_: u32) {}
}
#[derive_impl(pallet_assets::config_preludes::TestDefaultConfig)]
impl pallet_assets::Config for Test {
type Balance = Balance;
type AssetId = Location;
type AssetIdParameter = Location;
type Currency = Balances;
type CreateOrigin = AsEnsureOriginWithArg<frame_system::EnsureSigned<AccountId>>;
type ForceOrigin = EnsureRoot<AccountId>;
#[cfg(feature = "runtime-benchmarks")]
type BenchmarkHelper = XcmBenchmarkHelper;
}
// This child teyrchain is not configured as trusted reserve or teleport location for any assets.
pub const SOME_PARA_ID: u32 = 2009;
parameter_types! {
pub const RelayLocation: Location = Here.into_location();
pub const AnyNetwork: Option<NetworkId> = None;
pub const BaseXcmWeight: Weight = Weight::from_parts(1_000, 1_000);
pub const MaxInstructions: u32 = 100;
pub const MaxAssetsIntoHolding: u32 = 64;
pub UniversalLocation: InteriorLocation = GlobalConsensus(ByGenesis([0; 32])).into();
pub CheckingAccount: AccountId = XcmPallet::check_account();
}
pub type SovereignAccountOf = (
ChildTeyrchainConvertsVia<ParaId, AccountId>,
AccountId32Aliases<AnyNetwork, AccountId>,
HashedDescription<AccountId, DescribeAllTerminal>,
);
pub type ForeignAssetsConvertedConcreteId = MatchedConvertedConcreteId<
Location,
Balance,
// Excludes relay/parent chain currency
EverythingBut<(Equals<RelayLocation>,)>,
Identity,
JustTry,
>;
pub type AssetTransactors = (
FungibleAdapter<Balances, IsConcrete<RelayLocation>, SovereignAccountOf, AccountId, ()>,
FungiblesAdapter<
AssetsPallet,
ForeignAssetsConvertedConcreteId,
SovereignAccountOf,
AccountId,
NoChecking,
CheckingAccount,
>,
);
pub type Barrier = (
TakeWeightCredit,
AllowTopLevelPaidExecutionFrom<Everything>,
AllowKnownQueryResponses<XcmPallet>,
AllowSubscriptionsFrom<Everything>,
);
pub type XcmRouter = EnsureDecodableXcm<(TestSendXcmErrX8, TestSendXcm)>;
pub struct XcmConfig;
impl xcm_executor::Config for XcmConfig {
type RuntimeCall = RuntimeCall;
type XcmSender = XcmRouter;
type AssetTransactor = AssetTransactors;
type OriginConverter = ();
type IsReserve = ();
type IsTeleporter = ();
type UniversalLocation = UniversalLocation;
type Barrier = Barrier;
type Weigher = FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>;
type Trader = ();
type ResponseHandler = XcmPallet;
type AssetTrap = XcmPallet;
type AssetLocker = ();
type AssetExchanger = ();
type AssetClaims = XcmPallet;
type SubscriptionService = XcmPallet;
type PalletInstancesInfo = AllPalletsWithSystem;
type MaxAssetsIntoHolding = MaxAssetsIntoHolding;
type FeeManager = ();
type MessageExporter = ();
type UniversalAliases = Nothing;
type CallDispatcher = RuntimeCall;
type SafeCallFilter = Everything;
type Aliasers = Nothing;
type TransactionalProcessor = xcm_builder::FrameTransactionalProcessor;
type HrmpNewChannelOpenRequestHandler = ();
type HrmpChannelAcceptedHandler = ();
type HrmpChannelClosingHandler = ();
type XcmRecorder = XcmPallet;
type XcmEventEmitter = XcmPallet;
}
pub type LocalOriginToLocation = xcm_builder::SignedToAccountId32<RuntimeOrigin, AccountId, ()>;
parameter_types! {
pub static AdvertisedXcmVersion: xcm::prelude::XcmVersion = 4;
pub const AuthorizeAliasHoldReason: RuntimeHoldReason = RuntimeHoldReason::XcmPallet(pallet_xcm::HoldReason::AuthorizeAlias);
}
pub struct ConvertDeposit;
impl Convert<Footprint, u128> for ConvertDeposit {
fn convert(a: Footprint) -> u128 {
(a.count * 2 + a.size) as u128
}
}
impl pallet_xcm::Config for Test {
type RuntimeEvent = RuntimeEvent;
type SendXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
type XcmRouter = XcmRouter;
type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin<RuntimeOrigin, LocalOriginToLocation>;
type XcmExecuteFilter = Everything;
type XcmExecutor = XcmExecutor<XcmConfig>;
type XcmTeleportFilter = Nothing;
type XcmReserveTransferFilter = Everything;
type Weigher = FixedWeightBounds<BaseXcmWeight, RuntimeCall, MaxInstructions>;
type UniversalLocation = UniversalLocation;
type RuntimeOrigin = RuntimeOrigin;
type RuntimeCall = RuntimeCall;
const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100;
type AdvertisedXcmVersion = AdvertisedXcmVersion;
type Currency = Balances;
type CurrencyMatcher = ();
type TrustedLockers = ();
type SovereignAccountOf = ();
type MaxLockers = ConstU32<8>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
type WeightInfo = pallet_xcm::TestWeightInfo;
type AdminOrigin = EnsureRoot<AccountId>;
type AuthorizedAliasConsideration =
HoldConsideration<AccountId, Balances, AuthorizeAliasHoldReason, ConvertDeposit>;
}
#[derive_impl(pallet_revive::config_preludes::TestDefaultConfig)]
impl pallet_revive::Config for Test {
type AddressMapper = pallet_revive::AccountId32Mapper<Self>;
type Balance = Balance;
type Currency = Balances;
type Precompiles = (XcmPrecompile<Self>,);
type Time = Timestamp;
type UploadOrigin = frame_system::EnsureSigned<AccountId>;
type InstantiateOrigin = frame_system::EnsureSigned<AccountId>;
}
pub(crate) fn buy_execution<C>(fees: impl Into<Asset>) -> Instruction<C> {
use xcm::latest::prelude::*;
BuyExecution { fees: fees.into(), weight_limit: Unlimited }
}
pub(crate) fn new_test_ext_with_balances(
balances: Vec<(AccountId, Balance)>,
) -> sp_io::TestExternalities {
new_test_ext_with_balances_and_xcm_version(balances, Some(XCM_VERSION), vec![])
}
pub fn new_test_ext_with_balances_and_xcm_version(
balances: Vec<(AccountId, Balance)>,
safe_xcm_version: Option<XcmVersion>,
supported_version: Vec<(Location, XcmVersion)>,
) -> sp_io::TestExternalities {
let mut t = frame_system::GenesisConfig::<Test>::default().build_storage().unwrap();
pallet_balances::GenesisConfig::<Test> { balances, ..Default::default() }
.assimilate_storage(&mut t)
.unwrap();
pallet_xcm::GenesisConfig::<Test> { safe_xcm_version, supported_version, ..Default::default() }
.assimilate_storage(&mut t)
.unwrap();
pallet_revive::GenesisConfig::<Test> { mapped_accounts: vec![ALICE], ..Default::default() }
.assimilate_storage(&mut t)
.unwrap();
let mut ext = sp_io::TestExternalities::new(t);
ext.execute_with(|| System::set_block_number(1));
ext
}
@@ -0,0 +1,713 @@
// Copyright (C) Parity Technologies (UK) Ltd.
// This file is part of Pezkuwi.
// SPDX-License-Identifier: Apache-2.0
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use super::*;
use crate::{
mock::*,
IXcm::{self, weighMessageCall},
VersionedLocation, VersionedXcm,
};
use frame_support::traits::Currency;
use pallet_revive::{
precompiles::{
alloy::{
hex,
sol_types::{SolInterface, SolValue},
},
H160,
},
ExecConfig, U256,
};
use pezkuwi_teyrchain_primitives::primitives::Id as ParaId;
use sp_runtime::traits::AccountIdConversion;
use xcm::{prelude::*, v3, v4};
const BOB: AccountId = AccountId::new([1u8; 32]);
const CHARLIE: AccountId = AccountId::new([2u8; 32]);
const SEND_AMOUNT: u128 = 10;
const CUSTOM_INITIAL_BALANCE: u128 = 100_000_000_000u128;
#[test]
fn test_xcm_send_precompile_works() {
use codec::Encode;
let balances = vec![
(ALICE, CUSTOM_INITIAL_BALANCE),
(ParaId::from(SOME_PARA_ID).into_account_truncating(), CUSTOM_INITIAL_BALANCE),
];
new_test_ext_with_balances(balances).execute_with(|| {
let xcm_precompile_addr = H160::from(
hex::const_decode_to_array(b"00000000000000000000000000000000000A0000").unwrap(),
);
let sender: Location = AccountId32 { network: None, id: ALICE.into() }.into();
let message = Xcm(vec![
ReserveAssetDeposited((Parent, SEND_AMOUNT).into()),
ClearOrigin,
buy_execution((Parent, SEND_AMOUNT)),
DepositAsset { assets: AllCounted(1).into(), beneficiary: sender.clone() },
]);
let versioned_dest: VersionedLocation = RelayLocation::get().into();
let versioned_message: VersionedXcm<()> = VersionedXcm::from(message.clone());
let xcm_send_params = IXcm::sendCall {
destination: versioned_dest.encode().into(),
message: versioned_message.encode().into(),
};
let call = IXcm::IXcmCalls::send(xcm_send_params);
let encoded_call = call.abi_encode();
let result = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_call,
ExecConfig::new_substrate_tx(),
);
assert!(result.result.is_ok());
let sent_message = Xcm(Some(DescendOrigin(sender.clone().try_into().unwrap()))
.into_iter()
.chain(message.0.clone().into_iter())
.collect());
assert_eq!(sent_xcm(), vec![(Here.into(), sent_message)]);
});
}
#[test]
fn test_xcm_send_precompile_to_teyrchain() {
use codec::Encode;
let balances = vec![
(ALICE, CUSTOM_INITIAL_BALANCE),
(ParaId::from(SOME_PARA_ID).into_account_truncating(), CUSTOM_INITIAL_BALANCE),
];
new_test_ext_with_balances(balances).execute_with(|| {
let xcm_precompile_addr = H160::from(
hex::const_decode_to_array(b"00000000000000000000000000000000000A0000").unwrap(),
);
let sender: Location = AccountId32 { network: None, id: ALICE.into() }.into();
let message = Xcm(vec![
ReserveAssetDeposited((Parent, SEND_AMOUNT).into()),
ClearOrigin,
buy_execution((Parent, SEND_AMOUNT)),
DepositAsset { assets: AllCounted(1).into(), beneficiary: sender.clone() },
]);
let destination: VersionedLocation = Teyrchain(SOME_PARA_ID).into();
let versioned_message: VersionedXcm<()> = VersionedXcm::from(message.clone());
let xcm_send_params = IXcm::sendCall {
destination: destination.encode().into(),
message: versioned_message.encode().into(),
};
let call = IXcm::IXcmCalls::send(xcm_send_params);
let encoded_call = call.abi_encode();
let result = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_call,
ExecConfig::new_substrate_tx(),
);
assert!(result.result.is_ok());
let sent_message = Xcm(Some(DescendOrigin(sender.clone().try_into().unwrap()))
.into_iter()
.chain(message.0.clone().into_iter())
.collect());
assert_eq!(sent_xcm(), vec![(Teyrchain(SOME_PARA_ID).into(), sent_message)]);
});
}
#[test]
fn test_xcm_send_precompile_fails() {
use codec::Encode;
let balances = vec![
(ALICE, CUSTOM_INITIAL_BALANCE),
(ParaId::from(SOME_PARA_ID).into_account_truncating(), CUSTOM_INITIAL_BALANCE),
];
new_test_ext_with_balances(balances).execute_with(|| {
let xcm_precompile_addr = H160::from(
hex::const_decode_to_array(b"00000000000000000000000000000000000A0000").unwrap(),
);
let sender: Location = AccountId32 { network: None, id: ALICE.into() }.into();
let message = Xcm(vec![
ReserveAssetDeposited((Parent, SEND_AMOUNT).into()),
buy_execution((Parent, SEND_AMOUNT)),
DepositAsset { assets: AllCounted(1).into(), beneficiary: sender },
]);
let destination: VersionedLocation = VersionedLocation::from(Location::ancestor(8));
let versioned_message: VersionedXcm<()> = VersionedXcm::from(message.clone());
let xcm_send_params = IXcm::sendCall {
destination: destination.encode().into(),
message: versioned_message.encode().into(),
};
let call = IXcm::IXcmCalls::send(xcm_send_params);
let encoded_call = call.abi_encode();
let result = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_call,
ExecConfig::new_substrate_tx(),
);
let return_value = match result.result {
Ok(value) => value,
Err(err) => panic!("XcmSendPrecompile call failed with error: {err:?}"),
};
assert!(return_value.did_revert());
});
}
#[test]
fn send_fails_on_old_location_version() {
use codec::Encode;
let balances = vec![
(ALICE, CUSTOM_INITIAL_BALANCE),
(ParaId::from(SOME_PARA_ID).into_account_truncating(), CUSTOM_INITIAL_BALANCE),
];
new_test_ext_with_balances(balances).execute_with(|| {
let xcm_precompile_addr = H160::from(
hex::const_decode_to_array(b"00000000000000000000000000000000000A0000").unwrap(),
);
let sender: Location = AccountId32 { network: None, id: ALICE.into() }.into();
let message = Xcm(vec![
ReserveAssetDeposited((Parent, SEND_AMOUNT).into()),
ClearOrigin,
buy_execution((Parent, SEND_AMOUNT)),
DepositAsset { assets: AllCounted(1).into(), beneficiary: sender.clone() },
]);
// V4 location is old and will fail.
let destination: VersionedLocation =
VersionedLocation::V4(v4::Junction::Teyrchain(SOME_PARA_ID).into());
let versioned_message: VersionedXcm<RuntimeCall> = VersionedXcm::from(message.clone());
let xcm_send_params = IXcm::sendCall {
destination: destination.encode().into(),
message: versioned_message.encode().into(),
};
let call = IXcm::IXcmCalls::send(xcm_send_params);
let encoded_call = call.abi_encode();
let result = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_call,
ExecConfig::new_substrate_tx(),
);
let return_value = match result.result {
Ok(value) => value,
Err(err) => panic!("XcmSendPrecompile call failed with error: {err:?}"),
};
assert!(return_value.did_revert());
// V3 also fails.
let destination: VersionedLocation =
VersionedLocation::V3(v3::Junction::Teyrchain(SOME_PARA_ID).into());
let versioned_message: VersionedXcm<RuntimeCall> = VersionedXcm::from(message);
let xcm_send_params = IXcm::sendCall {
destination: destination.encode().into(),
message: versioned_message.encode().into(),
};
let call = IXcm::IXcmCalls::send(xcm_send_params);
let encoded_call = call.abi_encode();
let result = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_call,
ExecConfig::new_substrate_tx(),
);
let return_value = match result.result {
Ok(value) => value,
Err(err) => panic!("XcmSendPrecompile call failed with error: {err:?}"),
};
assert!(return_value.did_revert());
});
}
#[test]
fn send_fails_on_old_xcm_version() {
use codec::Encode;
let balances = vec![
(ALICE, CUSTOM_INITIAL_BALANCE),
(ParaId::from(SOME_PARA_ID).into_account_truncating(), CUSTOM_INITIAL_BALANCE),
];
new_test_ext_with_balances(balances).execute_with(|| {
let xcm_precompile_addr = H160::from(
hex::const_decode_to_array(b"00000000000000000000000000000000000A0000").unwrap(),
);
let sender: Location = AccountId32 { network: None, id: ALICE.into() }.into();
let message = Xcm(vec![
ReserveAssetDeposited((Parent, SEND_AMOUNT).into()),
ClearOrigin,
buy_execution((Parent, SEND_AMOUNT)),
DepositAsset { assets: AllCounted(1).into(), beneficiary: sender.clone() },
]);
// V4 is old and fails.
let v4_message: v4::Xcm<RuntimeCall> = message.try_into().unwrap();
let destination: VersionedLocation = Teyrchain(SOME_PARA_ID).into();
let versioned_message: VersionedXcm<RuntimeCall> = VersionedXcm::V4(v4_message.clone());
let xcm_send_params = IXcm::sendCall {
destination: destination.encode().into(),
message: versioned_message.encode().into(),
};
let call = IXcm::IXcmCalls::send(xcm_send_params);
let encoded_call = call.abi_encode();
let result = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_call,
ExecConfig::new_substrate_tx(),
);
let return_value = match result.result {
Ok(value) => value,
Err(err) => panic!("XcmSendPrecompile call failed with error: {err:?}"),
};
assert!(return_value.did_revert());
// With V3 it also fails.
let v3_message: v3::Xcm<RuntimeCall> = v4_message.try_into().unwrap();
let destination: VersionedLocation = Teyrchain(SOME_PARA_ID).into();
let versioned_message: VersionedXcm<RuntimeCall> = VersionedXcm::V3(v3_message);
let xcm_send_params = IXcm::sendCall {
destination: destination.encode().into(),
message: versioned_message.encode().into(),
};
let call = IXcm::IXcmCalls::send(xcm_send_params);
let encoded_call = call.abi_encode();
let result = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_call,
ExecConfig::new_substrate_tx(),
);
let return_value = match result.result {
Ok(value) => value,
Err(err) => panic!("XcmSendPrecompile call failed with error: {err:?}"),
};
assert!(return_value.did_revert());
});
}
#[test]
fn test_xcm_execute_precompile_works() {
use codec::Encode;
let balances = vec![
(ALICE, CUSTOM_INITIAL_BALANCE),
(ParaId::from(SOME_PARA_ID).into_account_truncating(), CUSTOM_INITIAL_BALANCE),
];
new_test_ext_with_balances(balances).execute_with(|| {
let xcm_precompile_addr = H160::from(
hex::const_decode_to_array(b"00000000000000000000000000000000000A0000").unwrap(),
);
let dest: Location = Junction::AccountId32 { network: None, id: BOB.into() }.into();
assert_eq!(Balances::total_balance(&ALICE), CUSTOM_INITIAL_BALANCE);
let message: VersionedXcm<RuntimeCall> = VersionedXcm::from(Xcm(vec![
WithdrawAsset((Here, SEND_AMOUNT).into()),
buy_execution((Here, SEND_AMOUNT)),
DepositAsset { assets: AllCounted(1).into(), beneficiary: dest },
]));
let weight_params = weighMessageCall { message: message.encode().into() };
let weight_call = IXcm::IXcmCalls::weighMessage(weight_params);
let encoded_weight_call = weight_call.abi_encode();
let xcm_weight_results = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_weight_call,
ExecConfig::new_substrate_tx(),
);
let weight_result = match xcm_weight_results.result {
Ok(value) => value,
Err(err) => panic!("XcmExecutePrecompile Failed to decode weight with error {err:?}"),
};
let weight: IXcm::Weight = IXcm::Weight::abi_decode(&weight_result.data[..])
.expect("XcmExecutePrecompile Failed to decode weight");
let xcm_execute_params = IXcm::executeCall { message: message.encode().into(), weight };
let call = IXcm::IXcmCalls::execute(xcm_execute_params);
let encoded_call = call.abi_encode();
let result = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_call,
ExecConfig::new_substrate_tx(),
);
assert!(result.result.is_ok());
assert_eq!(Balances::total_balance(&ALICE), CUSTOM_INITIAL_BALANCE - SEND_AMOUNT);
assert_eq!(Balances::total_balance(&BOB), SEND_AMOUNT);
});
}
#[test]
fn test_xcm_execute_precompile_different_beneficiary() {
use codec::Encode;
let balances = vec![(ALICE, CUSTOM_INITIAL_BALANCE), (CHARLIE, CUSTOM_INITIAL_BALANCE)];
new_test_ext_with_balances(balances).execute_with(|| {
let xcm_precompile_addr = H160::from(
hex::const_decode_to_array(b"00000000000000000000000000000000000A0000").unwrap(),
);
let dest: Location = Junction::AccountId32 { network: None, id: CHARLIE.into() }.into();
assert_eq!(Balances::total_balance(&ALICE), CUSTOM_INITIAL_BALANCE);
let message: VersionedXcm<RuntimeCall> = VersionedXcm::from(Xcm(vec![
WithdrawAsset((Here, SEND_AMOUNT).into()),
buy_execution((Here, SEND_AMOUNT)),
DepositAsset { assets: AllCounted(1).into(), beneficiary: dest },
]));
let weight_params = weighMessageCall { message: message.encode().into() };
let weight_call = IXcm::IXcmCalls::weighMessage(weight_params);
let encoded_weight_call = weight_call.abi_encode();
let xcm_weight_results = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_weight_call,
ExecConfig::new_substrate_tx(),
);
let weight_result = match xcm_weight_results.result {
Ok(value) => value,
Err(err) => panic!("XcmExecutePrecompile Failed to decode weight with error: {err:?}"),
};
let weight: IXcm::Weight = IXcm::Weight::abi_decode(&weight_result.data[..])
.expect("XcmExecutePrecompile Failed to decode weight");
let xcm_execute_params = IXcm::executeCall { message: message.encode().into(), weight };
let call = IXcm::IXcmCalls::execute(xcm_execute_params);
let encoded_call = call.abi_encode();
let result = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_call,
ExecConfig::new_substrate_tx(),
);
let return_value = match result.result {
Ok(value) => value,
Err(err) => panic!("XcmExecutePrecompile call failed with error: {err:?}"),
};
assert!(!return_value.did_revert());
assert_eq!(Balances::total_balance(&ALICE), CUSTOM_INITIAL_BALANCE - SEND_AMOUNT);
assert_eq!(Balances::total_balance(&CHARLIE), CUSTOM_INITIAL_BALANCE + SEND_AMOUNT);
});
}
#[test]
fn test_xcm_execute_precompile_fails() {
use codec::Encode;
let balances = vec![(ALICE, CUSTOM_INITIAL_BALANCE), (BOB, CUSTOM_INITIAL_BALANCE)];
new_test_ext_with_balances(balances).execute_with(|| {
let xcm_precompile_addr = H160::from(
hex::const_decode_to_array(b"00000000000000000000000000000000000A0000").unwrap(),
);
let dest: Location = Junction::AccountId32 { network: None, id: BOB.into() }.into();
assert_eq!(Balances::total_balance(&ALICE), CUSTOM_INITIAL_BALANCE);
let amount_to_send = CUSTOM_INITIAL_BALANCE - ExistentialDeposit::get();
let assets: Assets = (Here, amount_to_send).into();
let message: VersionedXcm<RuntimeCall> = VersionedXcm::from(Xcm(vec![
WithdrawAsset(assets.clone()),
buy_execution(assets.inner()[0].clone()),
DepositAsset { assets: assets.clone().into(), beneficiary: dest },
WithdrawAsset(assets),
]));
let weight_params = weighMessageCall { message: message.encode().into() };
let weight_call = IXcm::IXcmCalls::weighMessage(weight_params);
let encoded_weight_call = weight_call.abi_encode();
let xcm_weight_results = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_weight_call,
ExecConfig::new_substrate_tx(),
);
let weight_result = match xcm_weight_results.result {
Ok(value) => value,
Err(err) => panic!("XcmExecutePrecompile Failed to decode weight with error: {err:?}"),
};
let weight: IXcm::Weight = IXcm::Weight::abi_decode(&weight_result.data[..])
.expect("XcmExecutePrecompile Failed to decode weight");
let xcm_execute_params = IXcm::executeCall { message: message.encode().into(), weight };
let call = IXcm::IXcmCalls::execute(xcm_execute_params);
let encoded_call = call.abi_encode();
let result = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_call,
ExecConfig::new_substrate_tx(),
);
let return_value = match result.result {
Ok(value) => value,
Err(err) => panic!("XcmExecutePrecompile call failed with error: {err:?}"),
};
assert!(return_value.did_revert());
assert_eq!(Balances::total_balance(&ALICE), CUSTOM_INITIAL_BALANCE);
assert_eq!(Balances::total_balance(&BOB), CUSTOM_INITIAL_BALANCE);
});
}
#[test]
fn execute_fails_on_old_version() {
use codec::Encode;
let balances = vec![
(ALICE, CUSTOM_INITIAL_BALANCE),
(ParaId::from(SOME_PARA_ID).into_account_truncating(), CUSTOM_INITIAL_BALANCE),
];
new_test_ext_with_balances(balances).execute_with(|| {
let xcm_precompile_addr = H160::from(
hex::const_decode_to_array(b"00000000000000000000000000000000000A0000").unwrap(),
);
let dest: Location = Junction::AccountId32 { network: None, id: BOB.into() }.into();
assert_eq!(Balances::total_balance(&ALICE), CUSTOM_INITIAL_BALANCE);
let message = Xcm(vec![
WithdrawAsset((Here, SEND_AMOUNT).into()),
buy_execution((Here, SEND_AMOUNT)),
DepositAsset { assets: AllCounted(1).into(), beneficiary: dest },
]);
let versioned_message = VersionedXcm::from(message.clone());
let weight_params = weighMessageCall { message: versioned_message.encode().into() };
let weight_call = IXcm::IXcmCalls::weighMessage(weight_params);
let encoded_weight_call = weight_call.abi_encode();
let xcm_weight_results = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_weight_call,
ExecConfig::new_substrate_tx(),
);
let weight_result = match xcm_weight_results.result {
Ok(value) => value,
Err(err) => panic!("XcmExecutePrecompile Failed to decode weight with error {err:?}"),
};
let weight: IXcm::Weight = IXcm::Weight::abi_decode(&weight_result.data[..])
.expect("XcmExecutePrecompile Failed to decode weight");
// Using a V4 message to check that it fails.
let v4_message: v4::Xcm<RuntimeCall> = message.clone().try_into().unwrap();
let versioned_message = VersionedXcm::V4(v4_message.clone());
let xcm_execute_params = IXcm::executeCall {
message: versioned_message.encode().into(),
weight: weight.clone(),
};
let call = IXcm::IXcmCalls::execute(xcm_execute_params);
let encoded_call = call.abi_encode();
let result = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_call,
ExecConfig::new_substrate_tx(),
);
let return_value = match result.result {
Ok(value) => value,
Err(err) => panic!("XcmExecutePrecompile call failed with error: {err:?}"),
};
assert!(return_value.did_revert());
assert_eq!(Balances::total_balance(&ALICE), CUSTOM_INITIAL_BALANCE);
assert_eq!(Balances::total_balance(&BOB), 0);
// Now using a V3 message.
let v3_message: v3::Xcm<RuntimeCall> = v4_message.try_into().unwrap();
let versioned_message = VersionedXcm::V3(v3_message);
let xcm_execute_params =
IXcm::executeCall { message: versioned_message.encode().into(), weight };
let call = IXcm::IXcmCalls::execute(xcm_execute_params);
let encoded_call = call.abi_encode();
let result = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_call,
ExecConfig::new_substrate_tx(),
);
let return_value = match result.result {
Ok(value) => value,
Err(err) => panic!("XcmExecutePrecompile call failed with error: {err:?}"),
};
assert!(return_value.did_revert());
assert_eq!(Balances::total_balance(&ALICE), CUSTOM_INITIAL_BALANCE);
assert_eq!(Balances::total_balance(&BOB), 0);
});
}
#[test]
fn weight_fails_on_old_version() {
use codec::Encode;
let balances = vec![
(ALICE, CUSTOM_INITIAL_BALANCE),
(ParaId::from(SOME_PARA_ID).into_account_truncating(), CUSTOM_INITIAL_BALANCE),
];
new_test_ext_with_balances(balances).execute_with(|| {
let xcm_precompile_addr = H160::from(
hex::const_decode_to_array(b"00000000000000000000000000000000000A0000").unwrap(),
);
let dest: Location = Junction::AccountId32 { network: None, id: BOB.into() }.into();
assert_eq!(Balances::total_balance(&ALICE), CUSTOM_INITIAL_BALANCE);
let message: Xcm<RuntimeCall> = Xcm(vec![
WithdrawAsset((Here, SEND_AMOUNT).into()),
buy_execution((Here, SEND_AMOUNT)),
DepositAsset { assets: AllCounted(1).into(), beneficiary: dest },
]);
// V4 version is old, fails.
let v4_message: v4::Xcm<RuntimeCall> = message.try_into().unwrap();
let versioned_message = VersionedXcm::V4(v4_message.clone());
let weight_params = weighMessageCall { message: versioned_message.encode().into() };
let weight_call = IXcm::IXcmCalls::weighMessage(weight_params);
let encoded_weight_call = weight_call.abi_encode();
let xcm_weight_results = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_weight_call,
ExecConfig::new_substrate_tx(),
);
let result = match xcm_weight_results.result {
Ok(value) => value,
Err(err) => panic!("XcmExecutePrecompile Failed to decode weight with error {err:?}"),
};
assert!(result.did_revert());
// Now we also try V3.
let v3_message: v3::Xcm<RuntimeCall> = v4_message.try_into().unwrap();
let versioned_message = VersionedXcm::V3(v3_message);
let weight_params = weighMessageCall { message: versioned_message.encode().into() };
let weight_call = IXcm::IXcmCalls::weighMessage(weight_params);
let encoded_weight_call = weight_call.abi_encode();
let xcm_weight_results = pallet_revive::Pallet::<Test>::bare_call(
RuntimeOrigin::signed(ALICE),
xcm_precompile_addr,
U256::zero(),
Weight::MAX,
u128::MAX,
encoded_weight_call,
ExecConfig::new_substrate_tx(),
);
let result = match xcm_weight_results.result {
Ok(value) => value,
Err(err) => panic!("XcmExecutePrecompile Failed to decode weight with error {err:?}"),
};
assert!(result.did_revert());
});
}