Skip to content
Closed
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
6c702f3
update: initial commit
sphamjoli Apr 8, 2025
7da970b
update: revert file changes
sphamjoli Apr 8, 2025
77c90ad
update: fix function
sphamjoli Apr 9, 2025
2cd3f77
update: add documentation and fixed proof_size issue
sphamjoli Apr 13, 2025
cfddbbd
update: fix unverified commit
sphamjoli Apr 14, 2025
5da9f96
update: test commit
sphamjoli Apr 14, 2025
8a4b9ab
update: revert changes to pallet xcm for weights
sphamjoli Apr 16, 2025
63a7939
update: fix tests
sphamjoli Apr 19, 2025
f81110f
Merge branch 'master' into spha/xcm_precompile
sphamjoli Apr 28, 2025
7dfc036
update: implement precompile using framework
sphamjoli May 2, 2025
12a6b45
update: remove alloy type crate
sphamjoli May 5, 2025
5637a44
Merge branch 'master' into spha/xcm_precompile
sphamjoli May 6, 2025
d1e9fc4
update: remove unnecessary import
sphamjoli May 6, 2025
df3f49f
update: add the XCM precompile to WAH's runtime
tiagobndr May 7, 2025
8c61877
update: remove trace logs, revert changes to AH
sphamjoli May 8, 2025
884dc92
update: fix tests
sphamjoli May 8, 2025
80647e1
Merge branch 'master' into spha/xcm_precompile
sphamjoli May 8, 2025
a1f0dc3
fix: PR comments
sphamjoli May 9, 2025
ee39c21
Merge branch 'master' into spha/xcm_precompile
sphamjoli May 9, 2025
66bfe96
fix: PR comments
sphamjoli May 10, 2025
ad6fb82
Merge branch 'master' into spha/xcm_precompile
sphamjoli May 12, 2025
5c55ab9
Merge branch 'spha/xcm_precompile' of https://github.com/paritytech/p…
sphamjoli May 12, 2025
fa35ded
fix: PR comments
sphamjoli May 12, 2025
2628b96
Merge branch 'master' into spha/xcm_precompile
sphamjoli May 12, 2025
2bae436
fix: revert messages
sphamjoli May 12, 2025
35d3c0e
Merge branch 'spha/xcm_precompile' of https://github.com/paritytech/p…
sphamjoli May 12, 2025
1b09ec4
update: remove weight info
sphamjoli May 13, 2025
a13b50a
fix: PR comments
sphamjoli May 13, 2025
e1f66a1
update: rm formatting
sphamjoli May 13, 2025
60abf42
fix: PR comments
sphamjoli May 13, 2025
24c0d9a
fix: PR comments
sphamjoli May 13, 2025
dcf7375
fix: param name in interface
sphamjoli May 13, 2025
49628d0
update: use correct abi encoded results for messageWeight
sphamjoli May 13, 2025
a814da7
Merge branch 'master' into spha/xcm_precompile
sphamjoli May 14, 2025
fe317bb
Merge branch 'master' into spha/xcm_precompile
sphamjoli May 14, 2025
eb6d839
Update from github-actions[bot] running command 'fmt'
github-actions[bot] May 14, 2025
63b163c
Merge branch 'master' into spha/xcm_precompile
franciscoaguirre May 14, 2025
98874b4
Merge branch 'master' into spha/xcm_precompile
sphamjoli May 14, 2025
231457a
fix: PR comments
sphamjoli May 14, 2025
6856f6d
Merge branch 'spha/xcm_precompile' of https://github.com/paritytech/p…
sphamjoli May 14, 2025
9da7cef
fix: change CallRuntime to CallXcmExecute for xcm execute
sphamjoli May 14, 2025
3bfec03
Merge branch 'master' into spha/xcm_precompile
sphamjoli May 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion substrate/frame/revive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -149,4 +149,4 @@ try-runtime = [
"pallet-transaction-payment/try-runtime",
"pallet-utility/try-runtime",
"sp-runtime/try-runtime",
]
]
3 changes: 2 additions & 1 deletion substrate/frame/revive/mock-network/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ pub mod mocks;
pub mod parachain;
pub mod primitives;
pub mod relay_chain;

pub mod weight_info;
pub mod utils;
#[cfg(test)]
mod tests;

Expand Down
8 changes: 4 additions & 4 deletions substrate/frame/revive/mock-network/src/parachain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
mod contracts_config;
use crate::{
mocks::msg_queue::pallet as mock_msg_queue,
primitives::{AccountId, AssetIdForAssets, Balance},
primitives::{AccountId, AssetIdForAssets, Balance}, weight_info::ReviveTestWeightInfo,
};
use core::marker::PhantomData;
use frame_support::{
Expand Down Expand Up @@ -176,8 +176,8 @@ pub fn estimate_weight(number_of_instructions: u64) -> Weight {
pub fn estimate_fee_for_weight(weight: Weight) -> u128 {
let (_, units_per_second, units_per_mb) = TokensPerSecondPerMegabyte::get();

units_per_second * (weight.ref_time() as u128) / (WEIGHT_REF_TIME_PER_SECOND as u128) +
units_per_mb * (weight.proof_size() as u128) / (WEIGHT_PROOF_SIZE_PER_MB as u128)
units_per_second * (weight.ref_time() as u128) / (WEIGHT_REF_TIME_PER_SECOND as u128)
+ units_per_mb * (weight.proof_size() as u128) / (WEIGHT_PROOF_SIZE_PER_MB as u128)
}

pub type LocalBalancesTransactor =
Expand Down Expand Up @@ -324,7 +324,7 @@ impl pallet_xcm::Config for Runtime {
type MaxLockers = ConstU32<8>;
type MaxRemoteLockConsumers = ConstU32<0>;
type RemoteLockConsumerIdentifier = ();
type WeightInfo = pallet_xcm::TestWeightInfo;
type WeightInfo = ReviveTestWeightInfo;
type AdminOrigin = EnsureRoot<AccountId>;
// Aliasing is disabled: xcm_executor::Config::Aliasers is set to `Nothing`.
type AuthorizedAliasConsideration = Disabled;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
use super::{Balances, Runtime, RuntimeCall, RuntimeEvent};
use crate::parachain::RuntimeHoldReason;
use frame_support::derive_impl;
use pallet_revive::precompiles::custom::XcmPrecompile;

#[derive_impl(pallet_revive::config_preludes::TestDefaultConfig)]
impl pallet_revive::Config for Runtime {
type AddressMapper = pallet_revive::AccountId32Mapper<Self>;
type Currency = Balances;
type Time = super::Timestamp;
type Xcm = pallet_xcm::Pallet<Self>;
}
type Precompiles = (XcmPrecompile<Self>,);
}
237 changes: 231 additions & 6 deletions substrate/frame/revive/mock-network/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,27 @@
// limitations under the License.

use crate::{
parachain, parachain_account_sovereign_account_id, primitives::CENTS, relay_chain, MockNet,
ParaA, ParachainBalances, Relay, ALICE, BOB, INITIAL_BALANCE,
parachain, parachain_account_sovereign_account_id, primitives::CENTS, relay_chain,
utils::to_fixed_non_zero, MockNet, ParaA, ParachainBalances, Relay, ALICE, BOB,
INITIAL_BALANCE,
};
use codec::{Decode, Encode};
use frame_support::traits::{fungibles::Mutate, Currency};
use frame_system::RawOrigin;
use pallet_revive::precompiles::custom::IXcm;
use pallet_revive::{
precompiles::alloy::sol_types::SolInterface,
test_utils::{self, builder::*},
Code, DepositLimit,
Code, DepositLimit, ExecReturnValue,
};
use pallet_revive_fixtures::compile_module;
use pallet_revive_uapi::ReturnErrorCode;
use pallet_revive_uapi::{ReturnErrorCode, ReturnFlags};
use sp_core::H160;
use xcm::{v4::prelude::*, VersionedLocation, VersionedXcm};
use xcm_simulator::TestExt;

macro_rules! assert_return_code {
( $x:expr , $y:expr $(,)? ) => {{
($x:expr, $y:expr $(,)?) => {{
assert_eq!(u32::from_le_bytes($x.data[..].try_into().unwrap()), $y as u32);
}};
}
Expand Down Expand Up @@ -148,7 +151,6 @@ fn test_xcm_execute_reentrant_call() {
value: 0u128,
});

// The XCM used to transfer funds to Bob.
let message: Xcm<parachain::RuntimeCall> = Xcm::builder_unsafe()
.transact(OriginKind::Native, 1_000_000_000, transact_call.encode())
.expect_transact_status(MaybeErrorCode::Success)
Expand Down Expand Up @@ -202,3 +204,226 @@ fn test_xcm_send() {
assert_eq!(INITIAL_BALANCE + amount - fee, relay_chain::Balances::free_balance(ALICE));
});
}

#[test]
fn test_xcm_execute_reentrant_call_via_precompile() {
MockNet::reset();

ParaA::execute_with(|| {
let initial_bob_balance = ParachainBalances::free_balance(BOB);

let transact_call = parachain::RuntimeCall::Contracts(pallet_revive::Call::call {
dest: to_fixed_non_zero(10),
gas_limit: 1_000_000.into(),
storage_deposit_limit: test_utils::deposit_limit::<parachain::Runtime>(),
data: vec![],
value: 0u128,
});

let message: Xcm<parachain::RuntimeCall> = Xcm::builder_unsafe()
.transact(OriginKind::Native, 1_000_000_000, transact_call.encode())
.expect_transact_status(MaybeErrorCode::Success)
.build();

let xcm_execute_params =
IXcm::xcmExecuteCall { message: VersionedXcm::V4(message).encode().into() };

let call = IXcm::IXcmCalls::xcmExecute(xcm_execute_params);
let encoded_call = call.abi_encode();
let results = bare_call(to_fixed_non_zero(10)).data(encoded_call).build();
let result = match results.result {
Ok(value) => value,
Err(_) => ExecReturnValue { flags: ReturnFlags::REVERT, data: Vec::new() },
};

let final_bob_balance = ParachainBalances::free_balance(BOB);

assert_eq!(
result.flags,
ReturnFlags::REVERT,
"Expected transaction to revert due to reentrant call"
);
assert_eq!(final_bob_balance, initial_bob_balance, "Bob's balance should remain unchanged");
});
}

#[test]
fn test_xcm_execute_incomplete_call_via_precompile() {
MockNet::reset();
let amount = 10 * CENTS;

ParaA::execute_with(|| {
let initial_bob_balance = ParachainBalances::free_balance(BOB);
let initial_alice_balance = ParachainBalances::free_balance(ALICE);

let assets: Asset = (Here, amount).into();
let beneficiary = AccountId32 { network: None, id: BOB.clone().into() };

let message: Xcm<()> = Xcm::builder_unsafe()
.withdraw_asset(assets.clone())
// This will fail as the contract does not have enough balance to complete both
// withdrawals.
.withdraw_asset((Here, INITIAL_BALANCE))
.buy_execution(assets.clone(), Unlimited)
.deposit_asset(assets, beneficiary)
.build();

let xcm_execute_params =
IXcm::xcmExecuteCall { message: VersionedXcm::V4(message).encode().into() };

let call = IXcm::IXcmCalls::xcmExecute(xcm_execute_params);
let encoded_call = call.abi_encode();
bare_call(to_fixed_non_zero(10)).data(encoded_call).build();

let final_bob_balance = ParachainBalances::free_balance(BOB);
let final_alice_balance = ParachainBalances::free_balance(ALICE);

assert_eq!(final_bob_balance, initial_bob_balance, "Bob's balance should remain unchanged");
assert_eq!(
final_alice_balance, initial_alice_balance,
"Alice's balance should remain unchanged"
);
});
}

#[test]
fn test_xcm_execute_precompile() {
MockNet::reset();
let amount: u128 = 10 * CENTS;

ParaA::execute_with(|| {
let initial_alice_balance = ParachainBalances::free_balance(ALICE);
let initial_bob_balance = ParachainBalances::free_balance(BOB);

let assets: Asset = (Here, amount).into();
let beneficiary = AccountId32 { network: None, id: BOB.clone().into() };

let message: Xcm<()> = Xcm::builder_unsafe()
.withdraw_asset(assets.clone())
.deposit_asset(assets, beneficiary)
.build();

let xcm_execute_params =
IXcm::xcmExecuteCall { message: VersionedXcm::V4(message).encode().into() };

let call = IXcm::IXcmCalls::xcmExecute(xcm_execute_params);
let encoded_call = call.abi_encode();

bare_call(to_fixed_non_zero(10)).data(encoded_call).build();

let final_alice_balance = ParachainBalances::free_balance(ALICE);
let final_bob_balance = ParachainBalances::free_balance(BOB);

assert_eq!(
final_bob_balance,
initial_bob_balance + amount,
"Bob's balance should increase by the specified amount"
);
assert_eq!(
final_alice_balance,
initial_alice_balance - amount,
"Alice's balance should decrease by the specified amount"
);
});
}

#[test]
fn test_xcm_send_precompile() {
MockNet::reset();
let amount = 1_000 * CENTS;
let fee: u128 = parachain::estimate_message_fee(4);

let sovereign_account_id = ParaA::execute_with(|| {
let sovereign_account_id = parachain_account_sovereign_account_id(1, ALICE.clone());
let initial_sovereign_balance =
Relay::execute_with(|| relay_chain::Balances::free_balance(&sovereign_account_id));

let initial_alice_relay_balance =
Relay::execute_with(|| relay_chain::Balances::free_balance(ALICE));

let dest = VersionedLocation::V4(Parent.into());
let assets: Asset = (Here, amount).into();
let beneficiary = AccountId32 { network: None, id: ALICE.clone().into() };

let message: Xcm<()> = Xcm::builder()
.withdraw_asset(assets.clone())
.buy_execution((Here, fee), Unlimited)
.deposit_asset(assets, beneficiary)
.build();

let xcm_send_params = IXcm::xcmSendCall {
destination: dest.encode().into(),
message: VersionedXcm::V4(message).encode().into(),
};

let call = IXcm::IXcmCalls::xcmSend(xcm_send_params);
let encoded_call = call.abi_encode();
let results = bare_call(to_fixed_non_zero(10)).data(encoded_call).build();
let result = results.result.expect("Transaction should succeed");
let mut data = &result.data[..];
XcmHash::decode(&mut data).expect("Failed to decode xcm_send message_id");
(sovereign_account_id, initial_sovereign_balance, initial_alice_relay_balance)
});

Relay::execute_with(|| {
let (sovereign_account_id, initial_sovereign_balance, initial_alice_relay_balance) =
sovereign_account_id;

let final_sovereign_balance = relay_chain::Balances::free_balance(&sovereign_account_id);
assert_eq!(
final_sovereign_balance,
initial_sovereign_balance - amount,
"Sovereign account balance should decrease by the amount sent"
);

let final_alice_balance = relay_chain::Balances::free_balance(ALICE);
assert_eq!(
final_alice_balance,
initial_alice_relay_balance + amount - fee,
"Alice's balance should increase by amount minus fee"
);
});
}

#[test]
fn test_xcm_send_precompile_via_fixture() {
MockNet::reset();
let amount = 1_000 * CENTS;
let fee: u128 = parachain::estimate_message_fee(4);
let Contract { addr, .. } = instantiate_test_contract("call_and_return");

ParaA::execute_with(|| {
let dest = VersionedLocation::V4(Parent.into());
let assets: Asset = (Here, amount).into();
let beneficiary = AccountId32 { network: None, id: ALICE.clone().into() };

let message: Xcm<()> = Xcm::builder()
.withdraw_asset(assets.clone())
.buy_execution((Here, fee), Unlimited)
.deposit_asset(assets, beneficiary)
.build();

let xcm_send_params = IXcm::xcmSendCall {
destination: dest.encode().into(),
message: VersionedXcm::V4(message).encode().into(),
};

let call = IXcm::IXcmCalls::xcmSend(xcm_send_params);
let encoded_call = call.abi_encode();
let result = bare_call(addr)
.data(
(to_fixed_non_zero(10), 5000u64)
.encode()
.into_iter()
.chain(encoded_call)
.collect::<Vec<_>>(),
)
.build_and_unwrap_result();
let mut data = &result.data[..];
XcmHash::decode(&mut data).expect("Failed to decode xcm_send message_id");
});

Relay::execute_with(|| {
assert_eq!(INITIAL_BALANCE + amount - fee, relay_chain::Balances::free_balance(ALICE));
});
}
25 changes: 25 additions & 0 deletions substrate/frame/revive/mock-network/src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// 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 sp_core::H160;

pub fn to_fixed_non_zero(precompile_id: u16) -> H160 {
let mut address = [0u8; 20];
address[16] = (precompile_id >> 8) as u8;
address[17] = (precompile_id & 0xFF) as u8;

H160::from(address)
}
Loading
Loading