From ed94372a0e5d5b685b8141bc4bd938cf68ad0d9b Mon Sep 17 00:00:00 2001 From: Luca Giussani Date: Tue, 25 Nov 2025 16:02:02 +0100 Subject: [PATCH 1/4] Add deliveryFee method to xcm precompile --- Cargo.lock | 179 ++++++++++++++++-- Cargo.toml | 2 + runtime/common/src/xcm_teleport.rs | 145 ++++++++++++-- runtime/vflow/Cargo.toml | 3 + .../src/tests/xcm_teleport_integration.rs | 123 +++++++++++- 5 files changed, 419 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da5fd8b..5b2550a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -159,15 +159,33 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "alloy" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e2a5d689ccd182f1d138a61f081841b905034e0089f5278f6c200f2bcdab00a" +dependencies = [ + "alloy-core", +] + +[[package]] +name = "alloy-core" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca96214615ec8cf3fa2a54b32f486eb49100ca7fe7eb0b8c1137cd316e7250a" +dependencies = [ + "alloy-primitives 1.4.1", +] + [[package]] name = "alloy-dyn-abi" version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf69d3061e2e908a4370bda5d8d6529d5080232776975489eec0b49ce971027e" dependencies = [ - "alloy-json-abi", + "alloy-json-abi 0.8.26", "alloy-primitives 0.8.26", - "alloy-sol-type-parser", + "alloy-sol-type-parser 0.8.26", "alloy-sol-types 0.8.26", "const-hex", "itoa", @@ -183,7 +201,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4584e3641181ff073e9d5bec5b3b8f78f9749d9fb108a1cfbc4399a4a139c72a" dependencies = [ "alloy-primitives 0.8.26", - "alloy-sol-type-parser", + "alloy-sol-type-parser 0.8.26", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-json-abi" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5513d5e6bd1cba6bdcf5373470f559f320c05c8c59493b6e98912fbe6733943f" +dependencies = [ + "alloy-primitives 1.4.1", + "alloy-sol-type-parser 1.4.1", "serde", "serde_json", ] @@ -257,6 +287,33 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "alloy-primitives" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "355bf68a433e0fd7f7d33d5a9fc2583fde70bf5c530f63b80845f8da5505cf28" +dependencies = [ + "alloy-rlp", + "bytes", + "cfg-if", + "const-hex", + "derive_more 2.0.1", + "foldhash 0.2.0", + "hashbrown 0.16.0", + "indexmap 2.11.0", + "itoa", + "k256", + "keccak-asm", + "paste", + "proptest", + "rand 0.9.2", + "ruint", + "rustc-hash 2.1.1", + "serde", + "sha3", + "tiny-keccak", +] + [[package]] name = "alloy-rlp" version = "0.3.12" @@ -312,6 +369,20 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "alloy-sol-macro" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3ce480400051b5217f19d6e9a82d9010cdde20f1ae9c00d53591e4a1afbb312" +dependencies = [ + "alloy-sol-macro-expander 1.4.1", + "alloy-sol-macro-input 1.4.1", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "alloy-sol-macro-expander" version = "0.7.7" @@ -348,6 +419,24 @@ dependencies = [ "tiny-keccak", ] +[[package]] +name = "alloy-sol-macro-expander" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d792e205ed3b72f795a8044c52877d2e6b6e9b1d13f431478121d8d4eaa9028" +dependencies = [ + "alloy-sol-macro-input 1.4.1", + "const-hex", + "heck 0.5.0", + "indexmap 2.11.0", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.106", + "syn-solidity 1.4.1", + "tiny-keccak", +] + [[package]] name = "alloy-sol-macro-input" version = "0.7.7" @@ -379,6 +468,22 @@ dependencies = [ "syn-solidity 0.8.26", ] +[[package]] +name = "alloy-sol-macro-input" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bd1247a8f90b465ef3f1207627547ec16940c35597875cdc09c49d58b19693c" +dependencies = [ + "const-hex", + "dunce", + "heck 0.5.0", + "macro-string", + "proc-macro2", + "quote", + "syn 2.0.106", + "syn-solidity 1.4.1", +] + [[package]] name = "alloy-sol-type-parser" version = "0.8.26" @@ -389,6 +494,16 @@ dependencies = [ "winnow", ] +[[package]] +name = "alloy-sol-type-parser" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "954d1b2533b9b2c7959652df3076954ecb1122a28cc740aa84e7b0a49f6ac0a9" +dependencies = [ + "serde", + "winnow", +] + [[package]] name = "alloy-sol-types" version = "0.4.2" @@ -418,13 +533,25 @@ version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e960c4b52508ef2ae1e37cae5058e905e9ae099b107900067a503f8c454036f" dependencies = [ - "alloy-json-abi", + "alloy-json-abi 0.8.26", "alloy-primitives 0.8.26", "alloy-sol-macro 0.8.26", "const-hex", "serde", ] +[[package]] +name = "alloy-sol-types" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70319350969a3af119da6fb3e9bddb1bce66c9ea933600cb297c8b1850ad2a3c" +dependencies = [ + "alloy-json-abi 1.4.1", + "alloy-primitives 1.4.1", + "alloy-sol-macro 1.4.1", + "serde", +] + [[package]] name = "always-assert" version = "0.1.3" @@ -4521,7 +4648,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -6198,6 +6325,16 @@ dependencies = [ "serde", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +dependencies = [ + "foldhash 0.2.0", + "serde", +] + [[package]] name = "hashlink" version = "0.8.4" @@ -7618,7 +7755,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.53.3", ] [[package]] @@ -9435,7 +9572,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" dependencies = [ - "proc-macro-crate 1.1.3", + "proc-macro-crate 3.3.0", "proc-macro2", "quote", "syn 2.0.106", @@ -14577,7 +14714,7 @@ version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "itertools 0.14.0", "log", "multimap", @@ -14779,7 +14916,7 @@ dependencies = [ "once_cell", "socket2 0.6.0", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -14823,6 +14960,7 @@ checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", + "serde", ] [[package]] @@ -14861,6 +14999,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" dependencies = [ "getrandom 0.3.3", + "serde", ] [[package]] @@ -15725,7 +15864,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.9.4", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -18199,7 +18338,7 @@ version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "syn 2.0.106", @@ -20340,6 +20479,18 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "syn-solidity" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff790eb176cc81bb8936aed0f7b9f14fc4670069a2d371b3e3b0ecce908b2cb3" +dependencies = [ + "paste", + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "synstructure" version = "0.12.6" @@ -20412,7 +20563,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix 1.0.8", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -21418,6 +21569,8 @@ dependencies = [ name = "vflow-runtime" version = "1.0.0" dependencies = [ + "alloy", + "alloy-sol-types 1.4.1", "cfg-if", "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", @@ -22380,7 +22533,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.60.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 80bfcb7..4c30ce0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -181,6 +181,8 @@ xcm-primitives = {git = "https://github.com/moonbeam-foundation/moonbeam/", tag # Other rstest = {version = "0.26"} tokio = {version = "1.13"} +alloy = { version = "1", default-features = false } +alloy-sol-types = { version = "1" } [workspace.metadata.cargo-machete] ignored = ["num_enum"] diff --git a/runtime/common/src/xcm_teleport.rs b/runtime/common/src/xcm_teleport.rs index a444eab..cc6f16f 100644 --- a/runtime/common/src/xcm_teleport.rs +++ b/runtime/common/src/xcm_teleport.rs @@ -13,17 +13,35 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::alloc::borrow::ToOwned; use frame_support::dispatch::{DispatchInfo, PostDispatchInfo}; use pallet_evm::AddressMapping; use precompile_utils::prelude::*; use sp_core::{H256, U256}; use sp_runtime::traits::{Dispatchable, Get}; use sp_std::{boxed::Box, marker::PhantomData, vec}; -use xcm::v5::{Asset, AssetId, Assets, Fungibility, Junction, Location}; -use xcm::{VersionedAssets, VersionedLocation}; +use xcm::{ + v5::{ + Asset, + AssetFilter::Wild, + AssetId, Assets, Fungibility, + Instruction::{BuyExecution, ClearOrigin, DepositAsset, ReceiveTeleportedAsset}, + Junction, Location, Reanchorable, WeightLimit, + WildAsset::AllCounted, + Xcm, + }, + VersionedAssets, VersionedLocation, VersionedXcm, +}; pub struct XcmTeleportPrecompile(PhantomData<(R, O, C, L, A)>); +struct TeleportCallParams { + destination: Location, + beneficiary: Location, + assets: Assets, + fee_asset_item: u32, +} + #[precompile_utils::precompile] impl XcmTeleportPrecompile where @@ -55,35 +73,126 @@ where ::AddressMapping::into_account_id(handle.context().caller); let origin: O = frame_system::RawOrigin::Signed(account_id).into(); - let destination = VersionedLocation::V5(L::get()); + let TeleportCallParams { + destination, + beneficiary, + assets, + fee_asset_item, + } = Self::build_teleport_params(destination_account, amount)?; - let beneficiary = VersionedLocation::V5(Location::new( + let call: C = pallet_xcm::Call::::teleport_assets { + dest: Box::new(VersionedLocation::V5(destination)), + beneficiary: Box::new(VersionedLocation::V5(beneficiary)), + assets: Box::new(VersionedAssets::V5(assets)), + fee_asset_item, + } + .into(); + + RuntimeHelper::::try_dispatch::(handle, origin, call, 0)?; + + Ok(()) + } + + #[precompile::public("deliveryFee(bytes32,uint256)")] + fn delivery_fee( + handle: &mut impl PrecompileHandle, + destination_account: H256, + amount: U256, + ) -> EvmResult { + // No benchmarks availabe yet for precompiles, so charge some arbitrary gas as a spam + // prevention mechanism. + handle.record_cost(1000)?; + + let TeleportCallParams { + destination, + beneficiary, + assets, + fee_asset_item, + } = Self::build_teleport_params(destination_account, amount)?; + + let program = Self::teleport_assets_program( + destination.clone().into(), + beneficiary.into(), + assets.into(), + fee_asset_item, + )?; + + let versioned_fees = pallet_xcm::Pallet::::query_delivery_fees( + VersionedLocation::V5(destination), + VersionedXcm::V5(program), + ) + .map_err(|_| revert("cannot query delivery fees"))?; + + let fees: Assets = versioned_fees.try_into().unwrap(); + match { &fees.get(fee_asset_item as usize).unwrap().fun } { + Fungibility::Fungible(amount) => Ok(U256::from(*amount)), + _ => unreachable!(), + } + } + + fn teleport_assets_program( + dest: Location, + beneficiary: Location, + assets: Assets, + fee_asset_item: u32, + ) -> EvmResult> { + let fees = assets + .get(fee_asset_item as usize) + .ok_or_else(|| RevertReason::read_out_of_bounds("fees"))? + .to_owned(); + let max_assets = assets.len() as u32; + let context = R::UniversalLocation::get(); + let reanchored_assets = assets + .reanchored(&dest, &context) + .map_err(|_| revert("cannot reanchor assets"))?; + let reanchored_fees = fees + .reanchored(&dest, &context) + .map_err(|_| revert("cannot reanchor fees"))?; + + Ok(Xcm(vec![ + ReceiveTeleportedAsset(reanchored_assets), + ClearOrigin, + BuyExecution { + fees: reanchored_fees, + weight_limit: WeightLimit::Unlimited, + }, + DepositAsset { + assets: Wild(AllCounted(max_assets)), + beneficiary, + }, + ])) + } + + fn build_teleport_params( + destination_account: H256, + amount: U256, + ) -> EvmResult { + let destination = L::get(); + + let beneficiary = Location::new( 0, [Junction::AccountId32 { network: None, id: destination_account.into(), }], - )); + ); - let amount_u128: u128 = amount.try_into().map_err(|_| revert("Amount too large"))?; + let amount_u128 = amount + .try_into() + .map_err(|_| RevertReason::value_is_too_large("amount"))?; - let assets = VersionedAssets::V5(Assets::from(vec![Asset { + let assets = Assets::from(vec![Asset { id: A::get(), fun: Fungibility::Fungible(amount_u128), - }])); + }]); let fee_asset_item = 0; - let call: C = pallet_xcm::Call::::teleport_assets { - dest: Box::new(destination), - beneficiary: Box::new(beneficiary), - assets: Box::new(assets), + Ok(TeleportCallParams { + destination, + beneficiary, + assets, fee_asset_item, - } - .into(); - - RuntimeHelper::::try_dispatch::(handle, origin, call, 0)?; - - Ok(()) + }) } } diff --git a/runtime/vflow/Cargo.toml b/runtime/vflow/Cargo.toml index c954a28..01eee3a 100644 --- a/runtime/vflow/Cargo.toml +++ b/runtime/vflow/Cargo.toml @@ -105,9 +105,12 @@ xcm-primitives = {workspace = true} substrate-wasm-builder = {workspace = true} [dev-dependencies] +alloy = {workspace = true} +alloy-sol-types = {workspace = true} ethereum = {workspace = true} hex = {workspace = true, features = ["std"]} rstest = {workspace = true} +serde_json = {workspace = true} [features] default = [ "std" ] diff --git a/runtime/vflow/src/tests/xcm_teleport_integration.rs b/runtime/vflow/src/tests/xcm_teleport_integration.rs index 8ad025a..fffc505 100644 --- a/runtime/vflow/src/tests/xcm_teleport_integration.rs +++ b/runtime/vflow/src/tests/xcm_teleport_integration.rs @@ -1,10 +1,16 @@ use crate::{ configs::xcm::{NativeAssetId, RelayLocation}, - currency::VFY, + constants::currency::VFY, tests::ALICE, - AccountId, Runtime, RuntimeOrigin, ZKVXcm, + AccountId, Runtime, RuntimeCall, RuntimeOrigin, ZKVXcm, U256, }; +use alloy::primitives::U256 as Uint256; +use alloy_sol_types::{sol, SolCall, SolValue}; +use fp_evm::CallInfo; +use fp_rpc::runtime_decl_for_ethereum_runtime_rpc_api::EthereumRuntimeRPCApiV5; use frame_support::assert_ok; +use precompile_utils::precompile_set::AddressU64; +use sp_core::Get; use sp_runtime::BuildStorage; use xcm::v5::{Asset, Assets, Fungibility, Junction, Location, WeightLimit}; use xcm::{VersionedAssets, VersionedLocation}; @@ -77,3 +83,116 @@ fn can_teleport_vfy_to_relay() { )); }); } + +#[test] +fn xcm_teleport_precompile_delivery_fee_computation_is_correct() { + new_test_ext().execute_with(|| { + let from = ALICE; + let to = [0x42u8; 32]; + let amount = 1 * VFY; + + let fees_from_precompile = compute_teleport_delivery_fees_via_precompile(from, to, amount); + let fees_from_dry_run = compute_teleport_delivery_fees_via_dry_run(from, to, amount); + + assert_eq!(fees_from_precompile, fees_from_dry_run); + }); +} + +fn compute_teleport_delivery_fees_via_precompile( + from: [u8; 20], + account: [u8; 32], + amount: u128, +) -> u128 { + sol! { + contract IXcmTeleportPrecompile { + function deliveryFee(bytes32 id, uint256 amount) external returns (uint256); + } + } + + let precompile_address = AddressU64::<2060>::get(); + let calldata = IXcmTeleportPrecompile::deliveryFeeCall { + id: account.into(), + amount: Uint256::from(amount), + } + .abi_encode(); + + let CallInfo { value, .. } = Runtime::call( + from.into(), + precompile_address, + calldata, + U256::zero(), + U256::from(1_000_000), + None, + None, + None, + false, + None, + ) + .unwrap(); + + Uint256::abi_decode(&value).unwrap().to() +} + +fn compute_teleport_delivery_fees_via_dry_run( + from: [u8; 20], + account: [u8; 32], + amount: u128, +) -> u128 { + let destination = VersionedLocation::V5(RelayLocation::get()); + + let beneficiary = VersionedLocation::V5(Location::new( + 0, + [Junction::AccountId32 { + network: None, + id: account, + }], + )); + + let assets = VersionedAssets::V5(Assets::from(vec![Asset { + id: NativeAssetId::get(), + fun: Fungibility::Fungible(amount), + }])); + + let call = pallet_xcm::Call::::teleport_assets { + dest: Box::new(destination.clone()), + beneficiary: Box::new(beneficiary.clone()), + assets: Box::new(assets.clone()), + fee_asset_item: 0, + } + .into(); + + compute_delivery_fees_for_call( + RuntimeOrigin::signed(from.into()), + call, + destination.clone(), + ) +} + +fn compute_delivery_fees_for_call( + origin: RuntimeOrigin, + call: RuntimeCall, + destination: VersionedLocation, +) -> u128 { + ZKVXcm::dry_run_call::< + Runtime, + ::XcmRouter, + ::RuntimeOrigin, + ::RuntimeCall, + >(origin, call, 5) + .unwrap() + .forwarded_xcms + .into_iter() + .filter(|(location, _xcms)| location == &destination) + .flat_map(|(_location, xcms)| xcms.into_iter()) + .map(|xcm| -> Assets { + pallet_xcm::Pallet::::query_delivery_fees(destination.clone(), xcm) + .unwrap() + .try_into() + .unwrap() + }) + .flat_map(|assets| assets.into_inner()) + .fold(0, |acc, asset: Asset| match asset.fun { + Fungibility::Fungible(amount) => acc + amount, + Fungibility::NonFungible(_) => acc, + }) +} From 49cf10c66e4374e24cb1c859212fc4a96fc10357 Mon Sep 17 00:00:00 2001 From: Luca Giussani Date: Tue, 25 Nov 2025 17:13:59 +0100 Subject: [PATCH 2/4] Linter fixes --- Cargo.lock | 332 +++++++++++++++++- runtime/common/src/xcm_teleport.rs | 8 +- runtime/vflow/Cargo.toml | 1 + .../src/tests/xcm_teleport_integration.rs | 2 +- 4 files changed, 334 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b2550a..3ce7064 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -165,7 +165,36 @@ version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e2a5d689ccd182f1d138a61f081841b905034e0089f5278f6c200f2bcdab00a" dependencies = [ + "alloy-consensus", "alloy-core", + "alloy-eips", + "alloy-genesis", + "alloy-serde", + "alloy-trie", +] + +[[package]] +name = "alloy-consensus" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d213580c17d239ae83c0d897ac3315db7cda83d2d4936a9823cc3517552f2e24" +dependencies = [ + "alloy-eips", + "alloy-primitives 1.4.1", + "alloy-rlp", + "alloy-serde", + "alloy-trie", + "alloy-tx-macros", + "auto_impl", + "c-kzg", + "derive_more 2.0.1", + "either", + "k256", + "once_cell", + "secp256k1 0.30.0", + "serde", + "serde_with", + "thiserror 2.0.16", ] [[package]] @@ -174,7 +203,11 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca96214615ec8cf3fa2a54b32f486eb49100ca7fe7eb0b8c1137cd316e7250a" dependencies = [ + "alloy-dyn-abi 1.4.1", + "alloy-json-abi 1.4.1", "alloy-primitives 1.4.1", + "alloy-rlp", + "alloy-sol-types 1.4.1", ] [[package]] @@ -194,6 +227,96 @@ dependencies = [ "winnow", ] +[[package]] +name = "alloy-dyn-abi" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdff496dd4e98a81f4861e66f7eaf5f2488971848bb42d9c892f871730245c8" +dependencies = [ + "alloy-json-abi 1.4.1", + "alloy-primitives 1.4.1", + "alloy-sol-type-parser 1.4.1", + "alloy-sol-types 1.4.1", + "itoa", + "serde", + "serde_json", + "winnow", +] + +[[package]] +name = "alloy-eip2124" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "741bdd7499908b3aa0b159bba11e71c8cddd009a2c2eb7a06e825f1ec87900a5" +dependencies = [ + "alloy-primitives 1.4.1", + "alloy-rlp", + "crc", + "serde", + "thiserror 2.0.16", +] + +[[package]] +name = "alloy-eip2930" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9441120fa82df73e8959ae0e4ab8ade03de2aaae61be313fbf5746277847ce25" +dependencies = [ + "alloy-primitives 1.4.1", + "alloy-rlp", + "borsh", + "serde", +] + +[[package]] +name = "alloy-eip7702" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2919c5a56a1007492da313e7a3b6d45ef5edc5d33416fdec63c0d7a2702a0d20" +dependencies = [ + "alloy-primitives 1.4.1", + "alloy-rlp", + "borsh", + "serde", + "thiserror 2.0.16", +] + +[[package]] +name = "alloy-eips" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a15b4b0f6bab47aae017d52bb5a739bda381553c09fb9918b7172721ef5f5de" +dependencies = [ + "alloy-eip2124", + "alloy-eip2930", + "alloy-eip7702", + "alloy-primitives 1.4.1", + "alloy-rlp", + "alloy-serde", + "auto_impl", + "c-kzg", + "derive_more 2.0.1", + "either", + "serde", + "serde_with", + "sha2 0.10.9", + "thiserror 2.0.16", +] + +[[package]] +name = "alloy-genesis" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ba1cbc25a07e0142e8875fcbe80e1fdb02be8160ae186b90f4b9a69a72ed2b" +dependencies = [ + "alloy-eips", + "alloy-primitives 1.4.1", + "alloy-serde", + "alloy-trie", + "serde", + "serde_with", +] + [[package]] name = "alloy-json-abi" version = "0.8.26" @@ -320,10 +443,33 @@ version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f70d83b765fdc080dbcd4f4db70d8d23fe4761f2f02ebfa9146b833900634b4" dependencies = [ + "alloy-rlp-derive", "arrayvec 0.7.6", "bytes", ] +[[package]] +name = "alloy-rlp-derive" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64b728d511962dda67c1bc7ea7c03736ec275ed2cf4c35d9585298ac9ccf3b73" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "alloy-serde" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b3b1078b8775077525bc9fe9f6577e815ceaecd6c412a4f3b4d8aa2836e8f6" +dependencies = [ + "alloy-primitives 1.4.1", + "serde", + "serde_json", +] + [[package]] name = "alloy-sol-macro" version = "0.4.2" @@ -552,6 +698,34 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-trie" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3412d52bb97c6c6cc27ccc28d4e6e8cf605469101193b50b0bd5813b1f990b5" +dependencies = [ + "alloy-primitives 1.4.1", + "alloy-rlp", + "arrayvec 0.7.6", + "derive_more 2.0.1", + "nybbles", + "serde", + "smallvec", + "tracing", +] + +[[package]] +name = "alloy-tx-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ccf423f6de62e8ce1d6c7a11fb7508ae3536d02e0d68aaeb05c8669337d0937" +dependencies = [ + "darling 0.21.3", + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "always-assert" version = "0.1.3" @@ -1858,7 +2032,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43d193de1f7487df1914d3a568b772458861d33f9c54249612cc2893d6915054" dependencies = [ - "bitcoin_hashes", + "bitcoin_hashes 0.13.0", "serde", "unicode-normalization", ] @@ -1884,6 +2058,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" +[[package]] +name = "bitcoin-io" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" + [[package]] name = "bitcoin_hashes" version = "0.13.0" @@ -1891,7 +2071,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" dependencies = [ "bitcoin-internals", - "hex-conservative", + "hex-conservative 0.1.2", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io", + "hex-conservative 0.2.1", ] [[package]] @@ -2022,6 +2212,18 @@ dependencies = [ "piper", ] +[[package]] +name = "blst" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcdb4c7013139a150f9fc55d123186dbfaba0d912817466282c73ac49e71fb45" +dependencies = [ + "cc", + "glob", + "threadpool", + "zeroize", +] + [[package]] name = "borsh" version = "1.5.7" @@ -2432,6 +2634,21 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "c-kzg" +version = "2.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e00bf4b112b07b505472dbefd19e37e53307e2bfed5a79e0cc161d58ccd0e687" +dependencies = [ + "blst", + "cc", + "glob", + "hex", + "libc", + "once_cell", + "serde", +] + [[package]] name = "c2-chacha" version = "0.3.3" @@ -4002,6 +4219,16 @@ dependencies = [ "darling_macro 0.20.11", ] +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core 0.21.3", + "darling_macro 0.21.3", +] + [[package]] name = "darling_core" version = "0.14.4" @@ -4030,6 +4257,20 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.11.1", + "syn 2.0.106", +] + [[package]] name = "darling_macro" version = "0.14.4" @@ -4052,6 +4293,17 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core 0.21.3", + "quote", + "syn 2.0.106", +] + [[package]] name = "dashmap" version = "5.5.3" @@ -4151,6 +4403,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -6386,6 +6639,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec 0.7.6", +] + [[package]] name = "hex-literal" version = "0.4.1" @@ -9578,6 +9840,20 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "nybbles" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa11e84403164a9f12982ab728f3c67c6fd4ab5b5f0254ffc217bdbd3b28ab0" +dependencies = [ + "alloy-rlp", + "cfg-if", + "proptest", + "ruint", + "serde", + "smallvec", +] + [[package]] name = "objc" version = "0.2.7" @@ -11064,7 +11340,7 @@ name = "pallet-hyperbridge-aggregations" version = "0.1.0" source = "git+https://github.com/zkVerify/zkVerify.git?tag=1.0.0-1.0.0#e6ac3c7242f12aa04dd3b9d0704969f4ab6393a6" dependencies = [ - "alloy-dyn-abi", + "alloy-dyn-abi 0.8.26", "alloy-primitives 0.8.26", "anyhow", "frame-benchmarking", @@ -12422,7 +12698,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e69bf016dc406eff7d53a7d3f7cf1c2e72c82b9088aac1118591e36dd2cd3e9" dependencies = [ - "bitcoin_hashes", + "bitcoin_hashes 0.13.0", "rand 0.8.5", "rand_core 0.6.4", "serde", @@ -17554,6 +17830,30 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + [[package]] name = "schnellru" version = "0.2.4" @@ -17670,6 +17970,17 @@ dependencies = [ "secp256k1-sys 0.9.2", ] +[[package]] +name = "secp256k1" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b50c5943d326858130af85e049f2661ba3c78b26589b8ab98e65e80ae44a1252" +dependencies = [ + "bitcoin_hashes 0.14.0", + "rand 0.8.5", + "secp256k1-sys 0.10.1", +] + [[package]] name = "secp256k1-sys" version = "0.8.2" @@ -17688,6 +17999,15 @@ dependencies = [ "cc", ] +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + [[package]] name = "secrecy" version = "0.8.0" @@ -17864,6 +18184,10 @@ dependencies = [ "base64 0.22.1", "chrono", "hex", + "indexmap 1.9.3", + "indexmap 2.11.0", + "schemars 0.9.0", + "schemars 1.1.0", "serde", "serde_derive", "serde_json", diff --git a/runtime/common/src/xcm_teleport.rs b/runtime/common/src/xcm_teleport.rs index cc6f16f..5d0460e 100644 --- a/runtime/common/src/xcm_teleport.rs +++ b/runtime/common/src/xcm_teleport.rs @@ -111,9 +111,9 @@ where } = Self::build_teleport_params(destination_account, amount)?; let program = Self::teleport_assets_program( - destination.clone().into(), - beneficiary.into(), - assets.into(), + destination.clone(), + beneficiary, + assets, fee_asset_item, )?; @@ -124,7 +124,7 @@ where .map_err(|_| revert("cannot query delivery fees"))?; let fees: Assets = versioned_fees.try_into().unwrap(); - match { &fees.get(fee_asset_item as usize).unwrap().fun } { + match &fees.get(fee_asset_item as usize).unwrap().fun { Fungibility::Fungible(amount) => Ok(U256::from(*amount)), _ => unreachable!(), } diff --git a/runtime/vflow/Cargo.toml b/runtime/vflow/Cargo.toml index 01eee3a..c687f55 100644 --- a/runtime/vflow/Cargo.toml +++ b/runtime/vflow/Cargo.toml @@ -115,6 +115,7 @@ serde_json = {workspace = true} [features] default = [ "std" ] std = [ + "alloy/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-parachain-system/std", "cumulus-pallet-session-benchmarking/std", diff --git a/runtime/vflow/src/tests/xcm_teleport_integration.rs b/runtime/vflow/src/tests/xcm_teleport_integration.rs index fffc505..c5d0c2c 100644 --- a/runtime/vflow/src/tests/xcm_teleport_integration.rs +++ b/runtime/vflow/src/tests/xcm_teleport_integration.rs @@ -89,7 +89,7 @@ fn xcm_teleport_precompile_delivery_fee_computation_is_correct() { new_test_ext().execute_with(|| { let from = ALICE; let to = [0x42u8; 32]; - let amount = 1 * VFY; + let amount = VFY; let fees_from_precompile = compute_teleport_delivery_fees_via_precompile(from, to, amount); let fees_from_dry_run = compute_teleport_delivery_fees_via_dry_run(from, to, amount); From 5bbae9072fa82aff18f4d234f80e786a64e0ac29 Mon Sep 17 00:00:00 2001 From: Luca Giussani Date: Wed, 10 Dec 2025 18:41:57 +0100 Subject: [PATCH 3/4] Avoid unwraps in precompile --- runtime/common/src/xcm_teleport.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/runtime/common/src/xcm_teleport.rs b/runtime/common/src/xcm_teleport.rs index 5d0460e..e81ffdb 100644 --- a/runtime/common/src/xcm_teleport.rs +++ b/runtime/common/src/xcm_teleport.rs @@ -123,10 +123,16 @@ where ) .map_err(|_| revert("cannot query delivery fees"))?; - let fees: Assets = versioned_fees.try_into().unwrap(); - match &fees.get(fee_asset_item as usize).unwrap().fun { - Fungibility::Fungible(amount) => Ok(U256::from(*amount)), - _ => unreachable!(), + let fees: Assets = versioned_fees + .try_into() + .map_err(|_| RevertReason::custom("xcm conversion error"))?; + match fees + .get(fee_asset_item as usize) + .ok_or_else(|| RevertReason::read_out_of_bounds("fees"))? + .fun + { + Fungibility::Fungible(amount) => Ok(U256::from(amount)), + Fungibility::NonFungible(_asset_instance) => Ok(U256::zero()), } } From e086b27b5100b08e3d7de4f1d8132e5672d3c748 Mon Sep 17 00:00:00 2001 From: Luca Giussani Date: Fri, 12 Dec 2025 11:21:57 +0100 Subject: [PATCH 4/4] Return error if delivery fee is not fungible --- runtime/common/src/xcm_teleport.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/runtime/common/src/xcm_teleport.rs b/runtime/common/src/xcm_teleport.rs index e81ffdb..0634850 100644 --- a/runtime/common/src/xcm_teleport.rs +++ b/runtime/common/src/xcm_teleport.rs @@ -132,7 +132,9 @@ where .fun { Fungibility::Fungible(amount) => Ok(U256::from(amount)), - Fungibility::NonFungible(_asset_instance) => Ok(U256::zero()), + Fungibility::NonFungible(_asset_instance) => { + Err(RevertReason::custom("delivery fee is not fungible"))? + } } }