Integrate token swap pallet into Millau runtime (#1099)

* integrate token swap pallet into Millau runtime

* set OnDeliveryConfirmed callback in Millau runtime
This commit is contained in:
Svyatoslav Nikolsky
2021-09-15 15:08:27 +03:00
committed by Bastian Köcher
parent 71080f94df
commit 24bd2d6c51
11 changed files with 214 additions and 122 deletions
+2
View File
@@ -23,6 +23,7 @@ bridge-runtime-common = { path = "../../runtime-common", default-features = fals
pallet-bridge-dispatch = { path = "../../../modules/dispatch", default-features = false } pallet-bridge-dispatch = { path = "../../../modules/dispatch", default-features = false }
pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false } pallet-bridge-grandpa = { path = "../../../modules/grandpa", default-features = false }
pallet-bridge-messages = { path = "../../../modules/messages", default-features = false } pallet-bridge-messages = { path = "../../../modules/messages", default-features = false }
pallet-bridge-token-swap = { path = "../../../modules/token-swap", default-features = false }
pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false } pallet-shift-session-manager = { path = "../../../modules/shift-session-manager", default-features = false }
# Substrate Dependencies # Substrate Dependencies
@@ -77,6 +78,7 @@ std = [
"pallet-bridge-dispatch/std", "pallet-bridge-dispatch/std",
"pallet-bridge-grandpa/std", "pallet-bridge-grandpa/std",
"pallet-bridge-messages/std", "pallet-bridge-messages/std",
"pallet-bridge-token-swap/std",
"pallet-grandpa/std", "pallet-grandpa/std",
"pallet-randomness-collective-flip/std", "pallet-randomness-collective-flip/std",
"pallet-session/std", "pallet-session/std",
+41 -11
View File
@@ -362,7 +362,7 @@ parameter_types! {
pub const GetDeliveryConfirmationTransactionFee: Balance = pub const GetDeliveryConfirmationTransactionFee: Balance =
bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _; bp_millau::MAX_SINGLE_MESSAGE_DELIVERY_CONFIRMATION_TX_WEIGHT as _;
pub const RootAccountForPayments: Option<AccountId> = None; pub const RootAccountForPayments: Option<AccountId> = None;
pub const BridgedChainId: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID; pub const RialtoChainId: bp_runtime::ChainId = bp_runtime::RIALTO_CHAIN_ID;
} }
/// Instance of the messages pallet used to relay messages to/from Rialto chain. /// Instance of the messages pallet used to relay messages to/from Rialto chain.
@@ -394,11 +394,31 @@ impl pallet_bridge_messages::Config<WithRialtoMessagesInstance> for Runtime {
GetDeliveryConfirmationTransactionFee, GetDeliveryConfirmationTransactionFee,
RootAccountForPayments, RootAccountForPayments,
>; >;
type OnDeliveryConfirmed = (); type OnDeliveryConfirmed = pallet_bridge_token_swap::Pallet<Runtime, WithRialtoTokenSwapInstance>;
type SourceHeaderChain = crate::rialto_messages::Rialto; type SourceHeaderChain = crate::rialto_messages::Rialto;
type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch; type MessageDispatch = crate::rialto_messages::FromRialtoMessageDispatch;
type BridgedChainId = BridgedChainId; type BridgedChainId = RialtoChainId;
}
parameter_types! {
pub const TokenSwapMessagesLane: bp_messages::LaneId = *b"swap";
}
/// Instance of the with-Rialto token swap pallet.
pub type WithRialtoTokenSwapInstance = ();
impl pallet_bridge_token_swap::Config<WithRialtoTokenSwapInstance> for Runtime {
type Event = Event;
type BridgedChainId = RialtoChainId;
type OutboundMessageLaneId = TokenSwapMessagesLane;
type MessagesBridge = pallet_bridge_messages::Pallet<Runtime, WithRialtoMessagesInstance>;
type ThisCurrency = pallet_balances::Pallet<Runtime>;
type FromSwapToThisAccountIdConverter = bp_rialto::AccountIdConverter;
type BridgedChain = bp_rialto::Rialto;
type FromBridgedToThisAccountIdConverter = bp_millau::AccountIdConverter;
} }
construct_runtime!( construct_runtime!(
@@ -407,20 +427,30 @@ construct_runtime!(
NodeBlock = opaque::Block, NodeBlock = opaque::Block,
UncheckedExtrinsic = UncheckedExtrinsic UncheckedExtrinsic = UncheckedExtrinsic
{ {
BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event<T>, Config<T>},
BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event<T>},
BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage},
BridgeWestendGrandpa: pallet_bridge_grandpa::<Instance1>::{Pallet, Call, Config<T>, Storage},
System: frame_system::{Pallet, Call, Config, Storage, Event<T>}, System: frame_system::{Pallet, Call, Config, Storage, Event<T>},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage}, Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
// Must be before session.
Aura: pallet_aura::{Pallet, Config<T>}, Aura: pallet_aura::{Pallet, Config<T>},
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event},
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>}, Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
TransactionPayment: pallet_transaction_payment::{Pallet, Storage}, TransactionPayment: pallet_transaction_payment::{Pallet, Storage},
Sudo: pallet_sudo::{Pallet, Call, Config<T>, Storage, Event<T>},
// Consensus support.
Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>}, Session: pallet_session::{Pallet, Call, Storage, Event, Config<T>},
Grandpa: pallet_grandpa::{Pallet, Call, Storage, Config, Event},
ShiftSessionManager: pallet_shift_session_manager::{Pallet}, ShiftSessionManager: pallet_shift_session_manager::{Pallet},
RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Pallet, Storage},
// Rialto bridge modules.
BridgeRialtoGrandpa: pallet_bridge_grandpa::{Pallet, Call, Storage},
BridgeDispatch: pallet_bridge_dispatch::{Pallet, Event<T>},
BridgeRialtoMessages: pallet_bridge_messages::{Pallet, Call, Storage, Event<T>, Config<T>},
BridgeRialtoTokenSwap: pallet_bridge_token_swap::{Pallet, Call, Storage, Event<T>},
// Westend bridge modules.
BridgeWestendGrandpa: pallet_bridge_grandpa::<Instance1>::{Pallet, Call, Config<T>, Storage},
} }
); );
@@ -108,7 +108,7 @@ impl messages::ThisChainWithMessages for Millau {
type Call = crate::Call; type Call = crate::Call;
fn is_outbound_lane_enabled(lane: &LaneId) -> bool { fn is_outbound_lane_enabled(lane: &LaneId) -> bool {
*lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] || *lane == crate::TokenSwapMessagesLane::get()
} }
fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { fn maximal_pending_messages_at_outbound_lane() -> MessageNonce {
+131 -88
View File
@@ -56,7 +56,11 @@ use bp_messages::{
}; };
use bp_runtime::{ChainId, Size}; use bp_runtime::{ChainId, Size};
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use frame_support::{fail, traits::Get, weights::PostDispatchInfo}; use frame_support::{
fail,
traits::Get,
weights::{Pays, PostDispatchInfo},
};
use frame_system::RawOrigin; use frame_system::RawOrigin;
use num_traits::{SaturatingAdd, Zero}; use num_traits::{SaturatingAdd, Zero};
use sp_runtime::traits::BadOrigin; use sp_runtime::traits::BadOrigin;
@@ -241,94 +245,13 @@ pub mod pallet {
payload: T::OutboundPayload, payload: T::OutboundPayload,
delivery_and_dispatch_fee: T::OutboundMessageFee, delivery_and_dispatch_fee: T::OutboundMessageFee,
) -> DispatchResultWithPostInfo { ) -> DispatchResultWithPostInfo {
ensure_normal_operating_mode::<T, I>()?; crate::send_message::<T, I>(
let submitter = origin.into().map_err(|_| BadOrigin)?; origin.into().map_err(|_| BadOrigin)?,
// initially, actual (post-dispatch) weight is equal to pre-dispatch weight
let mut actual_weight = T::WeightInfo::send_message_weight(&payload);
// let's first check if message can be delivered to target chain
T::TargetHeaderChain::verify_message(&payload).map_err(|err| {
log::trace!(
target: "runtime::bridge-messages",
"Message to lane {:?} is rejected by target chain: {:?}",
lane_id,
err,
);
Error::<T, I>::MessageRejectedByChainVerifier
})?;
// now let's enforce any additional lane rules
let mut lane = outbound_lane::<T, I>(lane_id);
T::LaneMessageVerifier::verify_message(
&submitter,
&delivery_and_dispatch_fee,
&lane_id,
&lane.data(),
&payload,
)
.map_err(|err| {
log::trace!(
target: "runtime::bridge-messages",
"Message to lane {:?} is rejected by lane verifier: {:?}",
lane_id,
err,
);
Error::<T, I>::MessageRejectedByLaneVerifier
})?;
// let's withdraw delivery and dispatch fee from submitter
T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee(
&submitter,
&delivery_and_dispatch_fee,
&Self::relayer_fund_account_id(),
)
.map_err(|err| {
log::trace!(
target: "runtime::bridge-messages",
"Message to lane {:?} is rejected because submitter {:?} is unable to pay fee {:?}: {:?}",
lane_id,
submitter,
delivery_and_dispatch_fee,
err,
);
Error::<T, I>::FailedToWithdrawMessageFee
})?;
// finally, save message in outbound storage and emit event
let encoded_payload = payload.encode();
let encoded_payload_len = encoded_payload.len();
let nonce = lane.send_message(MessageData {
payload: encoded_payload,
fee: delivery_and_dispatch_fee,
});
// message sender pays for pruning at most `MaxMessagesToPruneAtOnce` messages
// the cost of pruning every message is roughly single db write
// => lets refund sender if less than `MaxMessagesToPruneAtOnce` messages pruned
let max_messages_to_prune = T::MaxMessagesToPruneAtOnce::get();
let pruned_messages = lane.prune_messages(max_messages_to_prune);
if let Some(extra_messages) = max_messages_to_prune.checked_sub(pruned_messages) {
actual_weight = actual_weight.saturating_sub(T::DbWeight::get().writes(extra_messages));
}
log::trace!(
target: "runtime::bridge-messages",
"Accepted message {} to lane {:?}. Message size: {:?}",
nonce,
lane_id, lane_id,
encoded_payload_len, payload,
); delivery_and_dispatch_fee,
)
Self::deposit_event(Event::MessageAccepted(lane_id, nonce)); .map(|sent_message| sent_message.post_dispatch_info)
Ok(PostDispatchInfo {
actual_weight: Some(actual_weight),
pays_fee: Pays::Yes,
})
} }
/// Pay additional fee for the message. /// Pay additional fee for the message.
@@ -899,6 +822,126 @@ pub mod storage_keys {
} }
} }
impl<T, I> bp_messages::source_chain::MessagesBridge<T::AccountId, T::OutboundMessageFee, T::OutboundPayload>
for Pallet<T, I>
where
T: Config<I>,
I: 'static,
{
type Error = sp_runtime::DispatchErrorWithPostInfo<PostDispatchInfo>;
fn send_message(
sender: bp_messages::source_chain::Sender<T::AccountId>,
lane: LaneId,
message: T::OutboundPayload,
delivery_and_dispatch_fee: T::OutboundMessageFee,
) -> Result<MessageNonce, Self::Error> {
crate::send_message::<T, I>(sender, lane, message, delivery_and_dispatch_fee)
.map(|sent_message| sent_message.nonce)
}
}
/// Message that has been sent.
struct SentMessage {
/// Nonce of the message.
pub nonce: MessageNonce,
/// Post-dispatch call info.
pub post_dispatch_info: PostDispatchInfo,
}
/// Function that actually sends message.
fn send_message<T: Config<I>, I: 'static>(
submitter: bp_messages::source_chain::Sender<T::AccountId>,
lane_id: LaneId,
payload: T::OutboundPayload,
delivery_and_dispatch_fee: T::OutboundMessageFee,
) -> sp_std::result::Result<SentMessage, sp_runtime::DispatchErrorWithPostInfo<PostDispatchInfo>> {
ensure_normal_operating_mode::<T, I>()?;
// initially, actual (post-dispatch) weight is equal to pre-dispatch weight
let mut actual_weight = T::WeightInfo::send_message_weight(&payload);
// let's first check if message can be delivered to target chain
T::TargetHeaderChain::verify_message(&payload).map_err(|err| {
log::trace!(
target: "runtime::bridge-messages",
"Message to lane {:?} is rejected by target chain: {:?}",
lane_id,
err,
);
Error::<T, I>::MessageRejectedByChainVerifier
})?;
// now let's enforce any additional lane rules
let mut lane = outbound_lane::<T, I>(lane_id);
T::LaneMessageVerifier::verify_message(&submitter, &delivery_and_dispatch_fee, &lane_id, &lane.data(), &payload)
.map_err(|err| {
log::trace!(
target: "runtime::bridge-messages",
"Message to lane {:?} is rejected by lane verifier: {:?}",
lane_id,
err,
);
Error::<T, I>::MessageRejectedByLaneVerifier
})?;
// let's withdraw delivery and dispatch fee from submitter
T::MessageDeliveryAndDispatchPayment::pay_delivery_and_dispatch_fee(
&submitter,
&delivery_and_dispatch_fee,
&Pallet::<T, I>::relayer_fund_account_id(),
)
.map_err(|err| {
log::trace!(
target: "runtime::bridge-messages",
"Message to lane {:?} is rejected because submitter {:?} is unable to pay fee {:?}: {:?}",
lane_id,
submitter,
delivery_and_dispatch_fee,
err,
);
Error::<T, I>::FailedToWithdrawMessageFee
})?;
// finally, save message in outbound storage and emit event
let encoded_payload = payload.encode();
let encoded_payload_len = encoded_payload.len();
let nonce = lane.send_message(MessageData {
payload: encoded_payload,
fee: delivery_and_dispatch_fee,
});
// message sender pays for pruning at most `MaxMessagesToPruneAtOnce` messages
// the cost of pruning every message is roughly single db write
// => lets refund sender if less than `MaxMessagesToPruneAtOnce` messages pruned
let max_messages_to_prune = T::MaxMessagesToPruneAtOnce::get();
let pruned_messages = lane.prune_messages(max_messages_to_prune);
if let Some(extra_messages) = max_messages_to_prune.checked_sub(pruned_messages) {
actual_weight = actual_weight.saturating_sub(T::DbWeight::get().writes(extra_messages));
}
log::trace!(
target: "runtime::bridge-messages",
"Accepted message {} to lane {:?}. Message size: {:?}",
nonce,
lane_id,
encoded_payload_len,
);
Pallet::<T, I>::deposit_event(Event::MessageAccepted(lane_id, nonce));
Ok(SentMessage {
nonce,
post_dispatch_info: PostDispatchInfo {
actual_weight: Some(actual_weight),
pays_fee: Pays::Yes,
},
})
}
/// Ensure that the origin is either root, or `PalletOwner`. /// Ensure that the origin is either root, or `PalletOwner`.
fn ensure_owner_or_root<T: Config<I>, I: 'static>(origin: T::Origin) -> Result<(), BadOrigin> { fn ensure_owner_or_root<T: Config<I>, I: 'static>(origin: T::Origin) -> Result<(), BadOrigin> {
match origin.into() { match origin.into() {
+1 -1
View File
@@ -26,7 +26,7 @@ frame-system = { git = "https://github.com/paritytech/substrate", branch = "mast
sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-core = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-io = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-io = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } sp-std = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false }
[dev-dependencies] [dev-dependencies]
pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" }
+26 -11
View File
@@ -49,6 +49,8 @@
//! While swap is pending, the `source_balance_at_this_chain` tokens are owned by the special //! While swap is pending, the `source_balance_at_this_chain` tokens are owned by the special
//! temporary `swap_account_at_this_chain` account. It is destroyed upon swap completion. //! temporary `swap_account_at_this_chain` account. It is destroyed upon swap completion.
#![cfg_attr(not(feature = "std"), no_std)]
use bp_messages::{ use bp_messages::{
source_chain::{MessagesBridge, OnDeliveryConfirmed}, source_chain::{MessagesBridge, OnDeliveryConfirmed},
DeliveredMessages, LaneId, MessageNonce, DeliveredMessages, LaneId, MessageNonce,
@@ -64,6 +66,7 @@ use frame_support::{
use sp_core::H256; use sp_core::H256;
use sp_io::hashing::blake2_256; use sp_io::hashing::blake2_256;
use sp_runtime::traits::{Convert, Saturating}; use sp_runtime::traits::{Convert, Saturating};
use sp_std::vec::Vec;
#[cfg(test)] #[cfg(test)]
mod mock; mod mock;
@@ -98,7 +101,7 @@ pub mod pallet {
type Event: From<Event<Self, I>> + IsType<<Self as frame_system::Config>::Event>; type Event: From<Event<Self, I>> + IsType<<Self as frame_system::Config>::Event>;
/// Id of the bridge with the Bridged chain. /// Id of the bridge with the Bridged chain.
type BridgeChainId: Get<ChainId>; type BridgedChainId: Get<ChainId>;
/// The identifier of outbound message lane on This chain used to send token transfer /// The identifier of outbound message lane on This chain used to send token transfer
/// messages to the Bridged chain. /// messages to the Bridged chain.
/// ///
@@ -114,8 +117,6 @@ pub mod pallet {
<Self::ThisCurrency as Currency<Self::AccountId>>::Balance, <Self::ThisCurrency as Currency<Self::AccountId>>::Balance,
MessagePayloadOf<Self, I>, MessagePayloadOf<Self, I>,
>; >;
/// Message delivery and dispatch fee for the tokens transfer message heading to the Bridged chain.
type MessageDeliveryAndDispatchFee: Get<<Self::ThisCurrency as Currency<Self::AccountId>>::Balance>;
/// This chain Currency used in the tokens swap. /// This chain Currency used in the tokens swap.
type ThisCurrency: Currency<Self::AccountId>; type ThisCurrency: Currency<Self::AccountId>;
@@ -128,6 +129,10 @@ pub mod pallet {
type FromBridgedToThisAccountIdConverter: Convert<H256, Self::AccountId>; type FromBridgedToThisAccountIdConverter: Convert<H256, Self::AccountId>;
} }
/// Tokens balance at This chain.
pub type ThisChainBalance<T, I> =
<<T as Config<I>>::ThisCurrency as Currency<<T as frame_system::Config>::AccountId>>::Balance;
/// Type of the Bridged chain. /// Type of the Bridged chain.
pub type BridgedChainOf<T, I> = <T as Config<I>>::BridgedChain; pub type BridgedChainOf<T, I> = <T as Config<I>>::BridgedChain;
/// Tokens balance type at the Bridged chain. /// Tokens balance type at the Bridged chain.
@@ -151,7 +156,7 @@ pub mod pallet {
/// Type of `TokenSwap` used by the pallet. /// Type of `TokenSwap` used by the pallet.
pub type TokenSwapOf<T, I> = TokenSwap< pub type TokenSwapOf<T, I> = TokenSwap<
BlockNumberFor<T>, BlockNumberFor<T>,
<<T as Config<I>>::ThisCurrency as Currency<<T as frame_system::Config>::AccountId>>::Balance, ThisChainBalance<T, I>,
<T as frame_system::Config>::AccountId, <T as frame_system::Config>::AccountId,
BridgedBalanceOf<T, I>, BridgedBalanceOf<T, I>,
BridgedAccountIdOf<T, I>, BridgedAccountIdOf<T, I>,
@@ -203,6 +208,7 @@ pub mod pallet {
origin: OriginFor<T>, origin: OriginFor<T>,
swap: TokenSwapOf<T, I>, swap: TokenSwapOf<T, I>,
target_public_at_bridged_chain: BridgedAccountPublicOf<T, I>, target_public_at_bridged_chain: BridgedAccountPublicOf<T, I>,
swap_delivery_and_dispatch_fee: ThisChainBalance<T, I>,
bridged_chain_spec_version: u32, bridged_chain_spec_version: u32,
bridged_currency_transfer: RawBridgedTransferCall, bridged_currency_transfer: RawBridgedTransferCall,
bridged_currency_transfer_weight: Weight, bridged_currency_transfer_weight: Weight,
@@ -239,13 +245,12 @@ pub mod pallet {
let swap_account = swap_account_id::<T, I>(&swap); let swap_account = swap_account_id::<T, I>(&swap);
frame_support::storage::with_transaction(|| { frame_support::storage::with_transaction(|| {
// funds are transferred from This account to the temporary Swap account // funds are transferred from This account to the temporary Swap account
let message_delivery_and_dispatch_fee = T::MessageDeliveryAndDispatchFee::get();
let transfer_result = T::ThisCurrency::transfer( let transfer_result = T::ThisCurrency::transfer(
&swap.source_account_at_this_chain, &swap.source_account_at_this_chain,
&swap_account, &swap_account,
// saturating_add is ok, or we have the chain where single holder owns all tokens // saturating_add is ok, or we have the chain where single holder owns all tokens
swap.source_balance_at_this_chain swap.source_balance_at_this_chain
.saturating_add(message_delivery_and_dispatch_fee), .saturating_add(swap_delivery_and_dispatch_fee),
// if we'll allow account to die, then he'll be unable to `cancel_claim` // if we'll allow account to die, then he'll be unable to `cancel_claim`
// if something won't work // if something won't work
ExistenceRequirement::KeepAlive, ExistenceRequirement::KeepAlive,
@@ -268,7 +273,7 @@ pub mod pallet {
// `Currency::transfer` call on the bridged chain, but no checks are made - it is // `Currency::transfer` call on the bridged chain, but no checks are made - it is
// the transaction submitter to ensure it is valid. // the transaction submitter to ensure it is valid.
let send_message_result = T::MessagesBridge::send_message( let send_message_result = T::MessagesBridge::send_message(
swap_account.clone(), bp_messages::source_chain::Sender::from(Some(swap_account.clone())),
T::OutboundMessageLaneId::get(), T::OutboundMessageLaneId::get(),
bp_message_dispatch::MessagePayload { bp_message_dispatch::MessagePayload {
spec_version: bridged_chain_spec_version, spec_version: bridged_chain_spec_version,
@@ -281,7 +286,7 @@ pub mod pallet {
dispatch_fee_payment: DispatchFeePayment::AtTargetChain, dispatch_fee_payment: DispatchFeePayment::AtTargetChain,
call: bridged_currency_transfer, call: bridged_currency_transfer,
}, },
message_delivery_and_dispatch_fee, swap_delivery_and_dispatch_fee,
); );
let transfer_message_nonce = match send_message_result { let transfer_message_nonce = match send_message_result {
Ok(transfer_message_nonce) => transfer_message_nonce, Ok(transfer_message_nonce) => transfer_message_nonce,
@@ -493,7 +498,7 @@ pub mod pallet {
/// Expected target account representation on This chain (aka `target_account_at_this_chain`). /// Expected target account representation on This chain (aka `target_account_at_this_chain`).
pub(crate) fn target_account_at_this_chain<T: Config<I>, I: 'static>(swap: &TokenSwapOf<T, I>) -> T::AccountId { pub(crate) fn target_account_at_this_chain<T: Config<I>, I: 'static>(swap: &TokenSwapOf<T, I>) -> T::AccountId {
T::FromBridgedToThisAccountIdConverter::convert(bp_runtime::derive_account_id( T::FromBridgedToThisAccountIdConverter::convert(bp_runtime::derive_account_id(
T::BridgeChainId::get(), T::BridgedChainId::get(),
bp_runtime::SourceAccount::Account(swap.target_account_at_bridged_chain.clone()), bp_runtime::SourceAccount::Account(swap.target_account_at_bridged_chain.clone()),
)) ))
} }
@@ -584,6 +589,7 @@ mod tests {
Origin::signed(THIS_CHAIN_ACCOUNT), Origin::signed(THIS_CHAIN_ACCOUNT),
test_swap(), test_swap(),
bridged_chain_account_public(), bridged_chain_account_public(),
SWAP_DELIVERY_AND_DISPATCH_FEE,
BRIDGED_CHAIN_SPEC_VERSION, BRIDGED_CHAIN_SPEC_VERSION,
test_transfer(), test_transfer(),
BRIDGED_CHAIN_CALL_WEIGHT, BRIDGED_CHAIN_CALL_WEIGHT,
@@ -606,6 +612,7 @@ mod tests {
Origin::signed(THIS_CHAIN_ACCOUNT + 1), Origin::signed(THIS_CHAIN_ACCOUNT + 1),
test_swap(), test_swap(),
bridged_chain_account_public(), bridged_chain_account_public(),
SWAP_DELIVERY_AND_DISPATCH_FEE,
BRIDGED_CHAIN_SPEC_VERSION, BRIDGED_CHAIN_SPEC_VERSION,
test_transfer(), test_transfer(),
BRIDGED_CHAIN_CALL_WEIGHT, BRIDGED_CHAIN_CALL_WEIGHT,
@@ -626,6 +633,7 @@ mod tests {
Origin::signed(THIS_CHAIN_ACCOUNT), Origin::signed(THIS_CHAIN_ACCOUNT),
swap, swap,
bridged_chain_account_public(), bridged_chain_account_public(),
SWAP_DELIVERY_AND_DISPATCH_FEE,
BRIDGED_CHAIN_SPEC_VERSION, BRIDGED_CHAIN_SPEC_VERSION,
test_transfer(), test_transfer(),
BRIDGED_CHAIN_CALL_WEIGHT, BRIDGED_CHAIN_CALL_WEIGHT,
@@ -646,6 +654,7 @@ mod tests {
Origin::signed(THIS_CHAIN_ACCOUNT), Origin::signed(THIS_CHAIN_ACCOUNT),
swap, swap,
bridged_chain_account_public(), bridged_chain_account_public(),
SWAP_DELIVERY_AND_DISPATCH_FEE,
BRIDGED_CHAIN_SPEC_VERSION, BRIDGED_CHAIN_SPEC_VERSION,
test_transfer(), test_transfer(),
BRIDGED_CHAIN_CALL_WEIGHT, BRIDGED_CHAIN_CALL_WEIGHT,
@@ -666,6 +675,7 @@ mod tests {
Origin::signed(THIS_CHAIN_ACCOUNT), Origin::signed(THIS_CHAIN_ACCOUNT),
test_swap(), test_swap(),
bridged_chain_account_public(), bridged_chain_account_public(),
SWAP_DELIVERY_AND_DISPATCH_FEE,
BRIDGED_CHAIN_SPEC_VERSION, BRIDGED_CHAIN_SPEC_VERSION,
transfer, transfer,
BRIDGED_CHAIN_CALL_WEIGHT, BRIDGED_CHAIN_CALL_WEIGHT,
@@ -683,6 +693,7 @@ mod tests {
Origin::signed(THIS_CHAIN_ACCOUNT), Origin::signed(THIS_CHAIN_ACCOUNT),
test_swap(), test_swap(),
bridged_chain_account_public(), bridged_chain_account_public(),
SWAP_DELIVERY_AND_DISPATCH_FEE,
BRIDGED_CHAIN_SPEC_VERSION, BRIDGED_CHAIN_SPEC_VERSION,
test_transfer(), test_transfer(),
BRIDGED_CHAIN_CALL_WEIGHT, BRIDGED_CHAIN_CALL_WEIGHT,
@@ -694,6 +705,7 @@ mod tests {
Origin::signed(THIS_CHAIN_ACCOUNT), Origin::signed(THIS_CHAIN_ACCOUNT),
test_swap(), test_swap(),
bridged_chain_account_public(), bridged_chain_account_public(),
SWAP_DELIVERY_AND_DISPATCH_FEE,
BRIDGED_CHAIN_SPEC_VERSION, BRIDGED_CHAIN_SPEC_VERSION,
test_transfer(), test_transfer(),
BRIDGED_CHAIN_CALL_WEIGHT, BRIDGED_CHAIN_CALL_WEIGHT,
@@ -713,6 +725,7 @@ mod tests {
Origin::signed(THIS_CHAIN_ACCOUNT), Origin::signed(THIS_CHAIN_ACCOUNT),
test_swap(), test_swap(),
bridged_chain_account_public(), bridged_chain_account_public(),
SWAP_DELIVERY_AND_DISPATCH_FEE,
BRIDGED_CHAIN_SPEC_VERSION, BRIDGED_CHAIN_SPEC_VERSION,
test_transfer(), test_transfer(),
BRIDGED_CHAIN_CALL_WEIGHT, BRIDGED_CHAIN_CALL_WEIGHT,
@@ -731,6 +744,7 @@ mod tests {
Origin::signed(THIS_CHAIN_ACCOUNT), Origin::signed(THIS_CHAIN_ACCOUNT),
test_swap(), test_swap(),
bridged_chain_account_public(), bridged_chain_account_public(),
SWAP_DELIVERY_AND_DISPATCH_FEE,
BRIDGED_CHAIN_SPEC_VERSION, BRIDGED_CHAIN_SPEC_VERSION,
test_transfer(), test_transfer(),
BRIDGED_CHAIN_CALL_WEIGHT, BRIDGED_CHAIN_CALL_WEIGHT,
@@ -749,6 +763,7 @@ mod tests {
Origin::signed(THIS_CHAIN_ACCOUNT), Origin::signed(THIS_CHAIN_ACCOUNT),
test_swap(), test_swap(),
bridged_chain_account_public(), bridged_chain_account_public(),
SWAP_DELIVERY_AND_DISPATCH_FEE,
BRIDGED_CHAIN_SPEC_VERSION, BRIDGED_CHAIN_SPEC_VERSION,
test_transfer(), test_transfer(),
BRIDGED_CHAIN_CALL_WEIGHT, BRIDGED_CHAIN_CALL_WEIGHT,
@@ -763,7 +778,7 @@ mod tests {
assert_eq!(PendingMessages::<TestRuntime>::get(MESSAGE_NONCE), Some(swap_hash)); assert_eq!(PendingMessages::<TestRuntime>::get(MESSAGE_NONCE), Some(swap_hash));
assert_eq!( assert_eq!(
pallet_balances::Pallet::<TestRuntime>::free_balance(&swap_account_id::<TestRuntime, ()>(&test_swap())), pallet_balances::Pallet::<TestRuntime>::free_balance(&swap_account_id::<TestRuntime, ()>(&test_swap())),
test_swap().source_balance_at_this_chain + MessageDeliveryAndDispatchFee::get(), test_swap().source_balance_at_this_chain + SWAP_DELIVERY_AND_DISPATCH_FEE,
); );
assert!( assert!(
frame_system::Pallet::<TestRuntime>::events() frame_system::Pallet::<TestRuntime>::events()
@@ -989,7 +1004,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
pallet_balances::Pallet::<TestRuntime>::free_balance(&THIS_CHAIN_ACCOUNT), pallet_balances::Pallet::<TestRuntime>::free_balance(&THIS_CHAIN_ACCOUNT),
THIS_CHAIN_ACCOUNT_BALANCE - MessageDeliveryAndDispatchFee::get(), THIS_CHAIN_ACCOUNT_BALANCE - SWAP_DELIVERY_AND_DISPATCH_FEE,
); );
assert!( assert!(
frame_system::Pallet::<TestRuntime>::events() frame_system::Pallet::<TestRuntime>::events()
+7 -7
View File
@@ -43,6 +43,8 @@ pub const MESSAGE_NONCE: MessageNonce = 3;
pub const THIS_CHAIN_ACCOUNT: AccountId = 1; pub const THIS_CHAIN_ACCOUNT: AccountId = 1;
pub const THIS_CHAIN_ACCOUNT_BALANCE: Balance = 100_000; pub const THIS_CHAIN_ACCOUNT_BALANCE: Balance = 100_000;
pub const SWAP_DELIVERY_AND_DISPATCH_FEE: Balance = 1;
frame_support::construct_runtime! { frame_support::construct_runtime! {
pub enum TestRuntime where pub enum TestRuntime where
Block = Block, Block = Block,
@@ -106,18 +108,16 @@ impl pallet_balances::Config for TestRuntime {
} }
frame_support::parameter_types! { frame_support::parameter_types! {
pub const BridgeChainId: ChainId = *b"inst"; pub const BridgedChainId: ChainId = *b"inst";
pub const OutboundMessageLaneId: LaneId = *b"lane"; pub const OutboundMessageLaneId: LaneId = *b"lane";
pub const MessageDeliveryAndDispatchFee: Balance = 1;
} }
impl pallet_bridge_token_swap::Config for TestRuntime { impl pallet_bridge_token_swap::Config for TestRuntime {
type Event = Event; type Event = Event;
type BridgeChainId = BridgeChainId; type BridgedChainId = BridgedChainId;
type OutboundMessageLaneId = OutboundMessageLaneId; type OutboundMessageLaneId = OutboundMessageLaneId;
type MessagesBridge = TestMessagesBridge; type MessagesBridge = TestMessagesBridge;
type MessageDeliveryAndDispatchFee = MessageDeliveryAndDispatchFee;
type ThisCurrency = pallet_balances::Pallet<TestRuntime>; type ThisCurrency = pallet_balances::Pallet<TestRuntime>;
type FromSwapToThisAccountIdConverter = TestAccountConverter; type FromSwapToThisAccountIdConverter = TestAccountConverter;
@@ -146,14 +146,14 @@ impl MessagesBridge<AccountId, Balance, MessagePayloadOf<TestRuntime, ()>> for T
type Error = (); type Error = ();
fn send_message( fn send_message(
sender: AccountId, sender: frame_system::RawOrigin<AccountId>,
lane: LaneId, lane: LaneId,
message: MessagePayloadOf<TestRuntime, ()>, message: MessagePayloadOf<TestRuntime, ()>,
delivery_and_dispatch_fee: Balance, delivery_and_dispatch_fee: Balance,
) -> Result<MessageNonce, Self::Error> { ) -> Result<MessageNonce, Self::Error> {
assert_ne!(sender, THIS_CHAIN_ACCOUNT); assert_ne!(sender, frame_system::RawOrigin::Signed(THIS_CHAIN_ACCOUNT));
assert_eq!(lane, OutboundMessageLaneId::get()); assert_eq!(lane, OutboundMessageLaneId::get());
assert_eq!(delivery_and_dispatch_fee, MessageDeliveryAndDispatchFee::get()); assert_eq!(delivery_and_dispatch_fee, SWAP_DELIVERY_AND_DISPATCH_FEE);
match message.call[0] { match message.call[0] {
OK_TRANSFER_CALL => Ok(MESSAGE_NONCE), OK_TRANSFER_CALL => Ok(MESSAGE_NONCE),
BAD_TRANSFER_CALL => Err(()), BAD_TRANSFER_CALL => Err(()),
@@ -136,7 +136,7 @@ pub trait MessagesBridge<AccountId, Balance, Payload> {
/// ///
/// Returns unique message nonce or error if send has failed. /// Returns unique message nonce or error if send has failed.
fn send_message( fn send_message(
sender: AccountId, sender: Sender<AccountId>,
lane: LaneId, lane: LaneId,
message: Payload, message: Payload,
delivery_and_dispatch_fee: Balance, delivery_and_dispatch_fee: Balance,
+2
View File
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>. // along with Parity Bridges Common. If not, see <http://www.gnu.org/licenses/>.
#![cfg_attr(not(feature = "std"), no_std)]
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use frame_support::RuntimeDebug; use frame_support::RuntimeDebug;
use sp_core::U256; use sp_core::U256;
@@ -102,6 +102,6 @@ mod tests {
let hex = encode_message.encode().unwrap(); let hex = encode_message.encode().unwrap();
// then // then
assert_eq!(format!("{:?}", hex), "0x01000000b0d60f000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c040130000000000000000000000000"); assert_eq!(format!("{:?}", hex), "0x01000000b0d60f000000000002d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d003c000130000000000000000000000000");
} }
} }
@@ -323,7 +323,7 @@ mod tests {
weight: 1038000, weight: 1038000,
origin: CallOrigin::SourceAccount(sp_keyring::AccountKeyring::Alice.to_account_id()), origin: CallOrigin::SourceAccount(sp_keyring::AccountKeyring::Alice.to_account_id()),
dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain, dispatch_fee_payment: bp_runtime::messages::DispatchFeePayment::AtSourceChain,
call: hex!("0401081234").to_vec(), call: hex!("0001081234").to_vec(),
} }
); );
} }