@@ -58,6 +58,7 @@ pub type FromMillauEncodedCall = messages::target::FromBridgedChainEncodedMessag
5858pub type FromMillauMessageDispatch = messages:: target:: FromBridgedChainMessageDispatch <
5959 WithMillauMessageBridge ,
6060 crate :: Runtime ,
61+ pallet_balances:: Pallet < Runtime > ,
6162 pallet_bridge_dispatch:: DefaultInstance ,
6263> ;
6364
@@ -172,6 +173,7 @@ impl messages::BridgedChainWithMessages for Millau {
172173
173174 fn estimate_delivery_transaction (
174175 message_payload : & [ u8 ] ,
176+ include_pay_dispatch_fee_cost : bool ,
175177 message_dispatch_weight : Weight ,
176178 ) -> MessageTransaction < Weight > {
177179 let message_payload_len = u32:: try_from ( message_payload. len ( ) ) . unwrap_or ( u32:: MAX ) ;
@@ -182,6 +184,11 @@ impl messages::BridgedChainWithMessages for Millau {
182184 dispatch_weight : extra_bytes_in_payload
183185 . saturating_mul ( bp_millau:: ADDITIONAL_MESSAGE_BYTE_DELIVERY_WEIGHT )
184186 . saturating_add ( bp_millau:: DEFAULT_MESSAGE_DELIVERY_TX_WEIGHT )
187+ . saturating_sub ( if include_pay_dispatch_fee_cost {
188+ 0
189+ } else {
190+ bp_millau:: PAY_INBOUND_DISPATCH_FEE_WEIGHT
191+ } )
185192 . saturating_add ( message_dispatch_weight) ,
186193 size : message_payload_len
187194 . saturating_add ( bp_rialto:: EXTRA_STORAGE_PROOF_SIZE )
@@ -258,3 +265,87 @@ impl MessagesParameter for RialtoToMillauMessagesParameter {
258265 }
259266 }
260267}
268+
269+ #[ cfg( test) ]
270+ mod tests {
271+ use super :: * ;
272+ use crate :: { AccountId , Call , ExistentialDeposit , Runtime , SystemCall , SystemConfig , VERSION } ;
273+ use bp_message_dispatch:: CallOrigin ;
274+ use bp_messages:: {
275+ target_chain:: { DispatchMessage , DispatchMessageData , MessageDispatch } ,
276+ MessageKey ,
277+ } ;
278+ use bp_runtime:: { derive_account_id, messages:: DispatchFeePayment , SourceAccount } ;
279+ use bridge_runtime_common:: messages:: target:: { FromBridgedChainEncodedMessageCall , FromBridgedChainMessagePayload } ;
280+ use frame_support:: {
281+ traits:: Currency ,
282+ weights:: { GetDispatchInfo , WeightToFeePolynomial } ,
283+ } ;
284+ use sp_runtime:: traits:: Convert ;
285+
286+ #[ test]
287+ fn transfer_happens_when_dispatch_fee_is_paid_at_target_chain ( ) {
288+ // this test actually belongs to the `bridge-runtime-common` crate, but there we have no
289+ // mock runtime. Making another one there just for this test, given that both crates
290+ // live n single repo is an overkill
291+ let mut ext: sp_io:: TestExternalities = SystemConfig :: default ( ) . build_storage :: < Runtime > ( ) . unwrap ( ) . into ( ) ;
292+ ext. execute_with ( || {
293+ let bridge = MILLAU_CHAIN_ID ;
294+ let call: Call = SystemCall :: remark ( vec ! [ ] ) . into ( ) ;
295+ let dispatch_weight = call. get_dispatch_info ( ) . weight ;
296+ let dispatch_fee = <Runtime as pallet_transaction_payment:: Config >:: WeightToFee :: calc ( & dispatch_weight) ;
297+ assert ! ( dispatch_fee > 0 ) ;
298+
299+ // create relayer account with minimal balance
300+ let relayer_account: AccountId = [ 1u8 ; 32 ] . into ( ) ;
301+ let initial_amount = ExistentialDeposit :: get ( ) ;
302+ let _ = <pallet_balances:: Pallet < Runtime > as Currency < AccountId > >:: deposit_creating (
303+ & relayer_account,
304+ initial_amount,
305+ ) ;
306+
307+ // create dispatch account with minimal balance + dispatch fee
308+ let dispatch_account = derive_account_id :: < <Runtime as pallet_bridge_dispatch:: Config >:: SourceChainAccountId > (
309+ bridge,
310+ SourceAccount :: Root ,
311+ ) ;
312+ let dispatch_account =
313+ <Runtime as pallet_bridge_dispatch:: Config >:: AccountIdConverter :: convert ( dispatch_account) ;
314+ let _ = <pallet_balances:: Pallet < Runtime > as Currency < AccountId > >:: deposit_creating (
315+ & dispatch_account,
316+ initial_amount + dispatch_fee,
317+ ) ;
318+
319+ // dispatch message with intention to pay dispatch fee at the target chain
320+ FromMillauMessageDispatch :: dispatch (
321+ & relayer_account,
322+ DispatchMessage {
323+ key : MessageKey {
324+ lane_id : Default :: default ( ) ,
325+ nonce : 0 ,
326+ } ,
327+ data : DispatchMessageData {
328+ payload : Ok ( FromBridgedChainMessagePayload :: < WithMillauMessageBridge > {
329+ spec_version : VERSION . spec_version ,
330+ weight : dispatch_weight,
331+ origin : CallOrigin :: SourceRoot ,
332+ dispatch_fee_payment : DispatchFeePayment :: AtTargetChain ,
333+ call : FromBridgedChainEncodedMessageCall :: new ( call. encode ( ) ) ,
334+ } ) ,
335+ fee : 1 ,
336+ } ,
337+ } ,
338+ ) ;
339+
340+ // ensure that fee has been transferred from dispatch to relayer account
341+ assert_eq ! (
342+ <pallet_balances:: Pallet <Runtime > as Currency <AccountId >>:: free_balance( & relayer_account) ,
343+ initial_amount + dispatch_fee,
344+ ) ;
345+ assert_eq ! (
346+ <pallet_balances:: Pallet <Runtime > as Currency <AccountId >>:: free_balance( & dispatch_account) ,
347+ initial_amount,
348+ ) ;
349+ } ) ;
350+ }
351+ }
0 commit comments