Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Transact from eth to sub #114

Open
wants to merge 50 commits into
base: bridge-next-gen
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
d68c3d6
Fix for unit test
yrong Feb 14, 2024
307ecd6
Update for transact
yrong Feb 14, 2024
7c493bd
Penpal config for transact
yrong Feb 13, 2024
e55cfd1
Fix import
yrong Feb 14, 2024
45c3372
Fix taplo
yrong Feb 14, 2024
26df807
Fix for breaking emulated tests
yrong Feb 14, 2024
c4fe031
Remove unused
yrong Feb 14, 2024
51b76fe
Tranfer fees to BH for transact
yrong Feb 14, 2024
3ed7260
Remove the teleport config
yrong Feb 15, 2024
772fa46
Enable create agent/channel by xcm
yrong Feb 15, 2024
540a791
Refund surplus
yrong Feb 16, 2024
051b3b6
Fix format
yrong Feb 16, 2024
e523185
Replace hardcode value
yrong Feb 16, 2024
a8b8435
Leave to user to prefund sovereign account on the destination chain t…
yrong Feb 19, 2024
b10d19e
Update import path
yrong Feb 19, 2024
cbd2e19
Merge branch 'snowbridge' into transact-from-eth-to-sub
yrong Feb 20, 2024
e363918
Unit test for transact
yrong Feb 20, 2024
13217f1
DescendOrigin to inbound-queue first
yrong Feb 22, 2024
257e75d
Fix breaking test
yrong Feb 22, 2024
e03942a
First match RegisterToken or SendToken
yrong Feb 22, 2024
698a9e9
Remove deprecated
yrong Feb 22, 2024
9968a37
Use SetAppendix and refund surplus when transact fail
yrong Feb 22, 2024
40ea01a
Ignore parents which is meaningless for GlobalConsensus locations
yrong Feb 22, 2024
004afd2
Reuse weight type
yrong Feb 23, 2024
85d2c03
Update sender consistent with smoke test
yrong Feb 23, 2024
626ec76
Update Cargo.toml
yrong Feb 26, 2024
0686fcd
Fix breaking test
yrong Feb 26, 2024
7cc0d59
Improve tests
yrong Feb 26, 2024
050585c
Merge branch 'snowbridge' into transact-from-eth-to-sub
yrong Feb 28, 2024
ece8a96
Merge branch 'snowbridge' into transact-from-eth-to-sub
yrong Mar 6, 2024
7b916e5
Add TransactFeeMode
yrong Mar 6, 2024
15759a4
Improve convert logic
yrong Mar 6, 2024
04a339e
Fix UniversalLocation
yrong Mar 7, 2024
c18f771
AllowUnpaidExecutionFromSnowBridgeWithFeeChecked
yrong Mar 7, 2024
e49f077
Merge branch 'snowbridge' into transact-from-eth-to-sub
yrong Mar 19, 2024
362e414
Remove feeMode and fully charge all cost on Ethereum
yrong Mar 19, 2024
6fb78fe
Merge branch 'snowbridge' into transact-from-eth-to-sub
yrong Apr 11, 2024
9d0af91
Fix build error
yrong Apr 11, 2024
68abf04
Make network specific types as storage which can be changed
yrong Apr 11, 2024
76b01b2
Remove the fund steps unnecessary
yrong Apr 11, 2024
87ed097
Move Transact after Origin operations
yrong Apr 11, 2024
0ea24a4
Fix breaking test
yrong Apr 11, 2024
b85e362
Merge branch 'bridge-next-gen' into transact-from-eth-to-sub
yrong Apr 16, 2024
cd7a64a
Fix compile error
yrong Apr 16, 2024
966abdf
Use native token of destination chain to pay fee from a pre-funded so…
yrong Apr 17, 2024
1cab94c
Use native token or DOT based on whether its a system parachain or not
yrong Apr 22, 2024
5a22972
Make fee asset as configuration parameter of the Channel
yrong Apr 26, 2024
9829de7
Zero fee for transact
yrong Apr 28, 2024
2f30d46
Remove unused
yrong Apr 29, 2024
ee6bdc5
Deposit any left over fees back into the pre-funded account
yrong May 3, 2024
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: 2 additions & 0 deletions Cargo.lock

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

49 changes: 37 additions & 12 deletions bridges/snowbridge/pallets/inbound-queue/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,8 @@ use snowbridge_core::{
sibling_sovereign_account, BasicOperatingMode, Channel, ChannelId, ParaId, PricingParameters,
StaticLookup,
};
use snowbridge_router_primitives::{
inbound,
inbound::{ConvertMessage, ConvertMessageError},
use snowbridge_router_primitives::inbound::{
Command, ConvertMessage, ConvertMessageError, MessageV1, VersionedMessage,
};
use sp_runtime::{traits::Saturating, SaturatedConversion, TokenError};

Expand Down Expand Up @@ -139,6 +138,9 @@ pub mod pallet {

/// To withdraw and deposit an asset.
type AssetTransactor: TransactAsset;

/// Returns the parachain ID we are running with.
type SelfParaId: Get<ParaId>;
vgeddes marked this conversation as resolved.
Show resolved Hide resolved
}

#[pallet::hooks]
Expand Down Expand Up @@ -268,8 +270,8 @@ pub mod pallet {
T::Token::transfer(&sovereign_account, &who, delivery_cost, Preservation::Preserve)?;

// Decode message into XCM
let (xcm, fee) =
match inbound::VersionedMessage::decode_all(&mut envelope.payload.as_ref()) {
let (xcm, fee, message) =
match VersionedMessage::decode_all(&mut envelope.payload.as_ref()) {
Ok(message) => Self::do_convert(envelope.message_id, message)?,
Err(_) => return Err(Error::<T>::InvalidPayload.into()),
};
Expand All @@ -281,8 +283,13 @@ pub mod pallet {
fee
);

// Burning fees for teleport
Self::burn_fees(channel.para_id, fee)?;
let _ = match message {
// Transfer fees to BH for transact
VersionedMessage::V1(MessageV1 { command: Command::Transact { .. }, .. }) =>
Self::transfer_fees(channel.para_id, fee),
// Burning fees for teleport
_ => Self::burn_fees(channel.para_id, fee),
}?;

// Attempt to send XCM to a dest parachain
let message_id = Self::send_xcm(xcm, channel.para_id)?;
Expand Down Expand Up @@ -314,13 +321,13 @@ pub mod pallet {
impl<T: Config> Pallet<T> {
pub fn do_convert(
message_id: H256,
message: inbound::VersionedMessage,
) -> Result<(Xcm<()>, BalanceOf<T>), Error<T>> {
let (mut xcm, fee) =
T::MessageConverter::convert(message).map_err(|e| Error::<T>::ConvertMessage(e))?;
message: VersionedMessage,
) -> Result<(Xcm<()>, BalanceOf<T>, VersionedMessage), Error<T>> {
let (mut xcm, fee) = T::MessageConverter::convert(message.clone())
.map_err(|e| Error::<T>::ConvertMessage(e))?;
// Append the message id as an XCM topic
xcm.inner_mut().extend(vec![SetTopic(message_id.into())]);
Ok((xcm, fee))
Ok((xcm, fee, message))
}

pub fn send_xcm(xcm: Xcm<()>, dest: ParaId) -> Result<XcmHash, Error<T>> {
Expand Down Expand Up @@ -360,6 +367,24 @@ pub mod pallet {
})?;
Ok(())
}

pub fn transfer_fees(para_id: ParaId, fee: BalanceOf<T>) -> DispatchResult {
let dummy_context =
XcmContext { origin: None, message_id: Default::default(), topic: None };
let from = Location::new(1, [Parachain(para_id.into())]);
let to = Location::new(1, [Parachain(T::SelfParaId::get().into())]);
let fees = (Location::parent(), fee.saturated_into::<u128>()).into();
T::AssetTransactor::transfer_asset(&fees, &from, &to, &dummy_context).map_err(
|error| {
log::error!(
target: LOG_TARGET,
"XCM asset transfer failed with error {:?}", error
);
TokenError::FundsUnavailable
},
)?;
Ok(())
}
}

/// API for accessing the delivery cost of a message
Expand Down
2 changes: 1 addition & 1 deletion bridges/snowbridge/pallets/inbound-queue/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ impl pallet_balances::Config for Test {
type MaxFreezes = ();
type RuntimeHoldReason = ();
type RuntimeFreezeReason = ();
type MaxHolds = ();
}

parameter_types! {
Expand Down Expand Up @@ -258,6 +257,7 @@ impl inbound_queue::Config for Test {
type LengthToFee = IdentityFee<u128>;
type MaxMessageSize = ConstU32<1024>;
type AssetTransactor = SuccessfulTransactor;
type SelfParaId = OwnParaId;
}

pub fn last_events(n: usize) -> Vec<RuntimeEvent> {
Expand Down
2 changes: 0 additions & 2 deletions bridges/snowbridge/pallets/system/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ use xcm_executor::traits::ConvertLocation;
#[cfg(feature = "runtime-benchmarks")]
use frame_support::traits::OriginTrait;

pub use pallet::*;

pub type BalanceOf<T> =
<<T as pallet::Config>::Token as Inspect<<T as frame_system::Config>::AccountId>>::Balance;
pub type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
Expand Down
1 change: 0 additions & 1 deletion bridges/snowbridge/pallets/system/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,6 @@ impl pallet_balances::Config for Test {
type MaxFreezes = ();
type RuntimeHoldReason = ();
type RuntimeFreezeReason = ();
type MaxHolds = ();
}

impl pallet_xcm_origin::Config for Test {
Expand Down
61 changes: 61 additions & 0 deletions bridges/snowbridge/primitives/router/src/inbound/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,21 @@ pub enum Command {
/// XCM execution fee on AssetHub
fee: u128,
},
/// call arbitrary transact on dest chain
Transact {
/// The address of the sender
sender: H160,
/// OriginKind
origin_kind: OriginKind,
/// XCM execution fee on dest chain
fee: u128,
/// The ref_time part of weight_at_most
weight_ref_time: u64,
/// The proof_size part of weight_at_most
weight_proof_size: u64,
yrong marked this conversation as resolved.
Show resolved Hide resolved
/// The payload of the transact
payload: Vec<u8>,
},
}

/// Destination for bridged tokens
Expand Down Expand Up @@ -146,6 +161,19 @@ impl<CreateAssetCall, CreateAssetDeposit, InboundQueuePalletInstance, AccountId,
Ok(Self::convert_register_token(chain_id, token, fee)),
V1(MessageV1 { chain_id, command: SendToken { token, destination, amount, fee } }) =>
Ok(Self::convert_send_token(chain_id, token, destination, amount, fee)),
V1(MessageV1 {
chain_id,
command:
Transact { sender, origin_kind, fee, weight_ref_time, weight_proof_size, payload },
}) => Ok(Self::convert_transact(
chain_id,
sender,
origin_kind,
fee,
weight_ref_time,
weight_proof_size,
payload,
)),
}
}
}
Expand Down Expand Up @@ -289,6 +317,39 @@ where
[GlobalConsensus(network), AccountKey20 { network: None, key: token.into() }],
)
}

fn convert_transact(
chain_id: u64,
sender: H160,
origin_kind: OriginKind,
fee: u128,
weight_ref_time: u64,
weight_proof_size: u64,
payload: Vec<u8>,
) -> (Xcm<()>, Balance) {
let xcm_fee: Asset = (Location::parent(), fee).into();

let xcm: Xcm<()> = vec![
// Teleport required fees.
WithdrawAsset(xcm_fee.clone().into()),
// Pay for execution.
BuyExecution { fees: xcm_fee.clone(), weight_limit: Unlimited },
// Change origin to the bridge.
UniversalOrigin(GlobalConsensus(Ethereum { chain_id })),
// DescendOrigin to the sender.
DescendOrigin(AccountKey20 { network: None, key: sender.into() }.into()),
// Transact on dest chain.
Transact {
origin_kind,
require_weight_at_most: Weight::from_parts(weight_ref_time, weight_proof_size),
call: payload.into(),
},
ExpectTransactStatus(MaybeErrorCode::Success),
vgeddes marked this conversation as resolved.
Show resolved Hide resolved
]
.into();

(xcm, fee.into())
yrong marked this conversation as resolved.
Show resolved Hide resolved
}
}

pub struct GlobalConsensusEthereumConvertsFor<AccountId>(PhantomData<AccountId>);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ hex-literal = "0.4.1"
# Substrate
sp-core = { path = "../../../../../../../substrate/primitives/core", default-features = false }
frame-support = { path = "../../../../../../../substrate/frame/support", default-features = false }
frame-system = { path = "../../../../../../../substrate/frame/system", default-features = false }
pallet-assets = { path = "../../../../../../../substrate/frame/assets", default-features = false }
pallet-asset-conversion = { path = "../../../../../../../substrate/frame/asset-conversion", default-features = false }
pallet-balances = { path = "../../../../../../../substrate/frame/balances", default-features = false }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ use snowbridge_pallet_inbound_queue_fixtures::{
InboundQueueFixture,
};
use snowbridge_pallet_system;
use snowbridge_router_primitives::inbound::GlobalConsensusEthereumConvertsFor;
use snowbridge_router_primitives::inbound::{
Command, GlobalConsensusEthereumConvertsFor, MessageV1, VersionedMessage,
};
use sp_core::H256;
use sp_runtime::{ArithmeticError::Underflow, DispatchError::Arithmetic};
use testnet_parachains_constants::rococo::snowbridge::EthereumNetwork;
Expand All @@ -38,6 +40,7 @@ const TREASURY_ACCOUNT: [u8; 32] =
hex!("6d6f646c70792f74727372790000000000000000000000000000000000000000");
const WETH: [u8; 20] = hex!("87d1f7fdfEe7f651FaBc8bFCB6E086C278b77A7d");
const ETHEREUM_DESTINATION_ADDRESS: [u8; 20] = hex!("44a57ee2f2FCcb85FDa2B0B18EBD0D8D2333700e");
const XCM_FEE: u128 = 40_000_000_000;

#[derive(Encode, Decode, Debug, PartialEq, Eq, Clone, TypeInfo)]
pub enum ControlCall {
Expand Down Expand Up @@ -320,6 +323,51 @@ fn send_token_from_ethereum_to_penpal() {
});
}

#[test]
fn transact_from_ethereum_to_penpal() {
// Fund BridgeHub sovereign account on penpal so that it can pay execution fees.
PenpalA::fund_para_sovereign(BridgeHubRococo::para_id().into(), INITIAL_FUND);

BridgeHubRococo::execute_with(|| {
type RuntimeEvent = <BridgeHubRococo as Chain>::RuntimeEvent;

let message_id: H256 = [1; 32].into();
let message = VersionedMessage::V1(MessageV1 {
chain_id: CHAIN_ID,
command: Command::Transact {
sender: hex!("ee9170abfbf9421ad6dd07f6bdec9d89f2b581e0").into(),
fee: XCM_FEE,
weight_ref_time: 40_000_000,
weight_proof_size: 8_000,
origin_kind: OriginKind::SovereignAccount,
payload: hex!("00071468656c6c6f").to_vec(),
},
});
// Convert the message to XCM
let (xcm, _, _) = EthereumInboundQueue::do_convert(message_id, message).unwrap();
// Send the XCM
let _ = EthereumInboundQueue::send_xcm(xcm, PenpalA::para_id().into()).unwrap();

assert_expected_events!(
BridgeHubRococo,
vec![
RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {},
]
);
});

PenpalA::execute_with(|| {
type RuntimeEvent = <PenpalA as Chain>::RuntimeEvent;
// Check that system event remarked on PenPal
assert_expected_events!(
PenpalA,
vec![
RuntimeEvent::System(frame_system::Event::Remarked { .. }) => {},
]
);
});
}

/// Tests the registering of a token as an asset on AssetHub, and then subsequently sending
/// a token from Ethereum to AssetHub.
#[test]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,7 @@ impl snowbridge_pallet_inbound_queue::Config for Runtime {
type WeightInfo = weights::snowbridge_pallet_inbound_queue::WeightInfo<Runtime>;
type PricingParameters = EthereumSystem;
type AssetTransactor = <xcm_config::XcmConfig as xcm_executor::Config>::AssetTransactor;
type SelfParaId = parachain_info::Pallet<Runtime>;
}

impl snowbridge_pallet_outbound_queue::Config for Runtime {
Expand Down
2 changes: 2 additions & 0 deletions cumulus/parachains/runtimes/testing/penpal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ sp-api = { path = "../../../../../substrate/primitives/api", default-features =
sp-block-builder = { path = "../../../../../substrate/primitives/block-builder", default-features = false }
sp-consensus-aura = { path = "../../../../../substrate/primitives/consensus/aura", default-features = false }
sp-core = { path = "../../../../../substrate/primitives/core", default-features = false }
sp-io = { path = "../../../../../substrate/primitives/io", default-features = false }
sp-genesis-builder = { path = "../../../../../substrate/primitives/genesis-builder", default-features = false }
sp-inherents = { path = "../../../../../substrate/primitives/inherents", default-features = false }
sp-offchain = { path = "../../../../../substrate/primitives/offchain", default-features = false }
Expand Down Expand Up @@ -125,6 +126,7 @@ std = [
"sp-core/std",
"sp-genesis-builder/std",
"sp-inherents/std",
"sp-io/std",
"sp-offchain/std",
"sp-runtime/std",
"sp-session/std",
Expand Down
Loading
Loading