Skip to content

Commit

Permalink
refacot the forwarder
Browse files Browse the repository at this point in the history
  • Loading branch information
Freddy Li authored and Freddy Li committed Jan 18, 2024
1 parent e0971fc commit 5446b05
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 64 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions bridge-forwarder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ license = "LGPL-3.0"
[dependencies]
codec = { package = "parity-scale-codec", version = "3.6.1", default-features = false, features = ["derive", "max-encoded-len"] }
scale-info = { version = "2.5.0", default-features = false, features = ["derive", "serde", "decode"] }
hex-literal = { version = "0.3", default-features = false }

# Substrate
frame-support = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.1.0", default-features = false }
frame-system = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.1.0", default-features = false }
sp-std = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.1.0", default-features = false }
sp-io = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.1.0", default-features = false }

# Polkadot
xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.1.0", default-features = false }
Expand All @@ -35,6 +37,7 @@ frame-system = { git = "https://github.com/paritytech/polkadot-sdk.git", branch
pallet-balances = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.1.0" }
pallet-assets = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.1.0" }

# Local
sygma-traits = { path = "../traits" }

[features]
Expand All @@ -45,6 +48,7 @@ std = [
"frame-support/std",
"frame-system/std",
"sp-std/std",
"sp-io/std",
"xcm/std",
"xcm-builder/std",
"xcm-executor/std",
Expand Down
27 changes: 26 additions & 1 deletion bridge-forwarder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@

pub use self::pallet::*;

pub mod xcm_asset_transactor;

#[frame_support::pallet]
pub mod pallet {
use cumulus_primitives_core::ParaId;
use frame_support::pallet_prelude::*;
use frame_support::traits::StorageVersion;
use xcm::latest::{MultiAsset, MultiLocation, Junction};
use xcm::prelude::{Concrete, Fungible, Parachain, X1};

use sygma_traits::{Bridge, TransactorForwarder};
use sygma_traits::{AssetTypeIdentifier, Bridge, TransactorForwarder};

const STORAGE_VERSION: StorageVersion = StorageVersion::new(0);

Expand Down Expand Up @@ -76,4 +80,25 @@ pub mod pallet {
Ok(())
}
}

pub struct NativeAssetTypeIdentifier<T>(PhantomData<T>);
impl<T: Get<ParaId>> AssetTypeIdentifier for NativeAssetTypeIdentifier<T> {
/// check if the given MultiAsset is a native asset
fn is_native_asset(asset: &MultiAsset) -> bool {
// currently there are two multilocations are considered as native asset:
// 1. integrated parachain native asset(MultiLocation::here())
// 2. other parachain native asset(MultiLocation::new(1, X1(Parachain(T::get().into()))))
let native_locations = [
MultiLocation::here(),
MultiLocation::new(1, X1(Parachain(T::get().into()))),
];

match (&asset.id, &asset.fun) {
(Concrete(ref id), Fungible(_)) => {
native_locations.contains(id)
}
_ => false,
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use hex_literal::hex;
use sygma_traits::{AssetTypeIdentifier, TransactorForwarder};

pub struct XCMAssetTransactor<CurrencyTransactor, FungiblesTransactor, AssetTypeChecker, Forwarder>(PhantomData<(CurrencyTransactor, FungiblesTransactor, AssetTypeChecker, Forwarder)>);

impl<CurrencyTransactor: TransactAsset, FungiblesTransactor: TransactAsset, AssetTypeChecker: AssetTypeIdentifier, Forwarder: TransactorForwarder> TransactAsset for XCMAssetTransactor<CurrencyTransactor, FungiblesTransactor, AssetTypeChecker, Forwarder> {
// deposit_asset implements the TransactAsset deposit_asset method and contains the logic to classify
// the asset recipient location:
Expand Down
2 changes: 1 addition & 1 deletion bridge/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ xcm = { package = "staging-xcm", git = "https://github.com/paritytech/polkadot-s
xcm-builder = { package = "staging-xcm-builder", git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.1.0" }
xcm-executor = { package = "staging-xcm-executor", git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.1.0" }
polkadot-parachain-primitives = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.1.0"}

parachains-common = { git = "https://github.com/paritytech/polkadot-sdk.git", branch = "release-polkadot-v1.1.0" }

# Local
sygma-basic-feehandler = { path = "../basic-fee-handler" }
sygma-traits = { path = "../traits" }

Expand Down
24 changes: 1 addition & 23 deletions bridge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,12 @@ mod encode;

#[cfg(test)]
mod mock;
mod xcm_asset_transactor;

#[allow(unused_variables)]
#[allow(clippy::large_enum_variant)]
#[frame_support::pallet]
pub mod pallet {
use codec::{Decode, Encode};
use cumulus_primitives_core::ParaId;
use ethabi::{encode as abi_encode, token::Token};
use frame_support::{
dispatch::DispatchResult,
Expand All @@ -49,7 +47,7 @@ pub mod pallet {
use xcm::latest::{MultiLocation, prelude::*};
use xcm_executor::traits::TransactAsset;

use sygma_traits::{AssetTypeIdentifier, Bridge, ChainID, DecimalConverter, DepositNonce, DomainID, ExtractDestinationData, FeeHandler, MpcAddress, ResourceId, TransferType, VerifyingContractAddress};
use sygma_traits::{Bridge, ChainID, DecimalConverter, DepositNonce, DomainID, ExtractDestinationData, FeeHandler, MpcAddress, ResourceId, TransferType, VerifyingContractAddress};

use crate::eip712;
use crate::encode::{abi::encode_packed, SolidityDataType};
Expand Down Expand Up @@ -683,26 +681,6 @@ pub mod pallet {
}
}

impl<T: Get<ParaId>> AssetTypeIdentifier for Pallet<T> {
/// check if the given MultiAsset is a native asset
fn is_native_asset(asset: &MultiAsset) -> bool {
// currently there are two multilocations are considered as native asset:
// 1. integrated parachain native asset(MultiLocation::here())
// 2. other parachain native asset(MultiLocation::new(1, X1(Parachain(T::get().into()))))
let native_locations = [
MultiLocation::here(),
MultiLocation::new(1, X1(Parachain(T::get().into()))),
];

match (&asset.id, &asset.fun) {
(Concrete(ref id), Fungible(_)) => {
native_locations.contains(id)
}
_ => false,
}
}
}

impl<T: Config> Bridge for Pallet<T> where
<T as frame_system::Config>::AccountId: From<[u8; 32]> + Into<[u8; 32]>,
{
Expand Down
10 changes: 2 additions & 8 deletions bridge/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,8 @@ use sygma_traits::{
VerifyingContractAddress,
};
use xcm::latest::{prelude::*, AssetId as XcmAssetId, MultiLocation};
use xcm_builder::{
AccountId32Aliases, CurrencyAdapter, FungiblesAdapter, IsConcrete, NoChecking, ParentIsPreset,
SiblingParachainConvertsVia,
};
use xcm_builder::{AccountId32Aliases, CurrencyAdapter, FungiblesAdapter, IsConcrete, NoChecking, ParentIsPreset, SiblingParachainConvertsVia};
use xcm_executor::traits::{Error as ExecutionError, MatchesFungibles};
use crate::xcm_asset_transactor::XCMAssetTransactor;

type Block = frame_system::mocking::MockBlock<Runtime>;

Expand All @@ -48,8 +44,6 @@ frame_support::construct_runtime!(
SygmaBridge: sygma_bridge::{Pallet, Call, Storage, Event<T>} = 6,
SygmaPercentageFeeHandler: sygma_percentage_feehandler::{Pallet, Call, Storage, Event<T>} = 7,
SygmaFeeHandlerRouter: sygma_fee_handler_router::{Pallet, Call, Storage, Event<T>} = 8,
SygmaBridgeForwarder: sygma_bridge_forwarder::{Pallet, Event<T>} = 9,
SygmaXcmBridge: sygma_xcm_bridge::{Pallet, Event<T>} = 10,
}
);

Expand Down Expand Up @@ -485,7 +479,7 @@ impl sygma_bridge::Config for Runtime {
type EIP712ChainID = EIP712ChainID;
type DestVerifyingContractAddress = DestVerifyingContractAddress;
type FeeHandler = SygmaFeeHandlerRouter;
type AssetTransactor = XCMAssetTransactor<CurrencyTransactor, FungiblesTransactor, SygmaXcmBridge, SygmaBridgeForwarder, >;
type AssetTransactor = AssetTransactors;
type ResourcePairs = ResourcePairs;
type IsReserve = ReserveChecker;
type ExtractDestData = DestinationDataParser;
Expand Down
36 changes: 28 additions & 8 deletions xcm-bridge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,13 @@ pub mod pallet {

type XcmExecutor: ExecuteXcm<Self::RuntimeCall>;

type UniversalLocation: Get<InteriorMultiLocation>;

#[pallet::constant]
type SelfLocation: Get<MultiLocation>;

/// Minimum xcm execution fee paid on destination chain.
type MinXcmFee: Get<Vec<(AssetId, u128)>>;
}

pub enum TransferKind {
Expand Down Expand Up @@ -65,6 +70,7 @@ pub mod pallet {
InvalidDestination,
UnknownTransferType,
CannotReanchor,
NoXcmMiNFeeSet,
}

#[derive(PartialEq, Eq, Clone, Encode, Decode)]
Expand Down Expand Up @@ -159,9 +165,21 @@ pub mod pallet {
let (dest_location, recipient) =
Pallet::<T>::extract_dest(&dest).ok_or(Error::<T>::InvalidDestination)?;

ensure!(
T::MinXcmFee::get().iter().position(|a| a.0 == asset.id).map(|idx| {
T::MinXcmFee::get()[idx].1
}).is_some(),
Error::<T>::NoXcmMiNFeeSet
);
let fee_per_asset = T::MinXcmFee::get().iter().position(|a| a.0 == asset.id).map(|idx| {
T::MinXcmFee::get()[idx].1
}).unwrap();

let fee_to_dest: MultiAsset = (asset.id, fee_per_asset).into();

let xcm = XcmObject::<T> {
asset: asset.clone(),
fee: asset.clone(), // TODO: fee is asset?
fee: fee_to_dest,
origin: origin_location.clone(),
dest: dest_location,
recipient,
Expand All @@ -186,8 +204,6 @@ pub mod pallet {
/// extract the dest_location, recipient_location
pub fn extract_dest(dest: &MultiLocation) -> Option<(MultiLocation, MultiLocation)> {
match (dest.parents, dest.first_interior()) {
// parents must be 1 here because only parents as 1 can be forwarded to xcm bridge logic
// parachains
(1, Some(Parachain(id))) => Some((
MultiLocation::new(1, X1(Parachain(*id))),
MultiLocation::new(0, dest.interior().clone().split_first().0),
Expand Down Expand Up @@ -336,10 +352,13 @@ pub mod pallet {
fn test_transfer_self_reserve_asset_to_parachain() {
TestNet::reset();

// sending native asset from parachain A to parachain B
ParaA::execute_with(|| {
assert_eq!(ParaBalances::free_balance(&ALICE), ENDOWED_BALANCE);

// transfer parachain A native asset from Alice to parachain B on Bob
assert_ok!(BridgeImpl::<Runtime>::transfer(ALICE.into(),
(Concrete(MultiLocation::new(0, Here)), Fungible(10u128)).into(),
(Concrete(MultiLocation::new(0, Here)), Fungible(10_000_000_000_000u128)).into(),
MultiLocation::new(
1,
X2(
Expand All @@ -350,11 +369,11 @@ pub mod pallet {
},
),
)
));
assert_eq!(ParaBalances::free_balance(&ALICE), ENDOWED_BALANCE - 10);
));
assert_eq!(ParaBalances::free_balance(&ALICE), ENDOWED_BALANCE - 10_000_000_000_000u128);

assert_events(vec![RuntimeEvent::SygmaXcmBridge(SygmaXcmBridgeEvent::XCMTransferSend {
asset: (Concrete(MultiLocation::new(0, Here)), Fungible(10u128)).into(),
asset: (Concrete(MultiLocation::new(0, Here)), Fungible(10_000_000_000_000u128)).into(),
origin: Junction::AccountId32 {
network: None,
id: ALICE.into(),
Expand All @@ -373,7 +392,8 @@ pub mod pallet {
});

ParaB::execute_with(|| {
assert_eq!(ParaAssets::balance(0u32.into(), &BOB), 0);
assert_eq!(ParaAssets::balance(1u32.into(), &ALICE), ENDOWED_BALANCE);
assert_eq!(ParaAssets::balance(1u32.into(), &BOB), 9_000_000_000_000u128);
});
}

Expand Down
11 changes: 7 additions & 4 deletions xcm-bridge/src/mock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub mod para;

pub const ALICE: AccountId32 = AccountId32::new([0u8; 32]);
pub const BOB: AccountId32 = AccountId32::new([1u8; 32]);
pub const ENDOWED_BALANCE: u128 = 100_000_000;
pub const ENDOWED_BALANCE: u128 = 100_000_000_000_000_000_000;

pub type ParaBalances = pallet_balances::Pallet<para::Runtime>;
pub type ParaAssets = pallet_assets::Pallet<para::Runtime>;
Expand Down Expand Up @@ -72,6 +72,7 @@ pub fn para_ext(para_id: u32) -> TestExternalities {
};
parachain_info_config.assimilate_storage(&mut t).unwrap();

// set Alice and Bob with ENDOWED_BALANCE amount of native asset on every parachain
pallet_balances::GenesisConfig::<Runtime> {
balances: vec![
(ALICE, ENDOWED_BALANCE),
Expand All @@ -81,10 +82,11 @@ pub fn para_ext(para_id: u32) -> TestExternalities {
.assimilate_storage(&mut t)
.unwrap();

// set Alice with ENDOWED_BALANCE amount of USDT asset on every parachain
pallet_assets::GenesisConfig::<Runtime> {
assets: vec![(0, ALICE, false, 1)],
metadata: vec![(0, "USDT".into(), "USDT".into(), 6)],
accounts: vec![(0, ALICE, ENDOWED_BALANCE)],
assets: vec![(1, ALICE, false, 1)],
metadata: vec![(1, "USDT".into(), "USDT".into(), 6)],
accounts: vec![(1, ALICE, ENDOWED_BALANCE)],
}
.assimilate_storage(&mut t)
.unwrap();
Expand All @@ -101,6 +103,7 @@ pub fn relay_ext() -> sp_io::TestExternalities {
.build_storage()
.unwrap();

// set Alice with ENDOWED_BALANCE amount of native asset on relay chain
pallet_balances::GenesisConfig::<Runtime> {
balances: vec![(ALICE, ENDOWED_BALANCE)],
}
Expand Down
Loading

0 comments on commit 5446b05

Please sign in to comment.