@@ -54,7 +54,7 @@ type CallOf<T> = <T as frame_system::Config>::RuntimeCall;
54
54
/// - Not too high, ensuring the gas value is large enough (at least 7 digits) to encode the
55
55
/// ref_time, proof_size, and deposit into the less significant (6 lower) digits of the gas value.
56
56
/// - Not too low, enabling users to adjust the gas price to define a tip.
57
- pub const GAS_PRICE : u32 = 100_000u32 ;
57
+ pub const GAS_PRICE : u32 = 1_000u32 ;
58
58
59
59
/// Convert a `Balance` into a gas value, using the fixed `GAS_PRICE`.
60
60
/// The gas is calculated as `balance / GAS_PRICE`, rounded up to the nearest integer.
@@ -324,6 +324,11 @@ pub trait EthExtra {
324
324
let GenericTransaction { nonce, chain_id, to, value, input, gas, gas_price, .. } =
325
325
GenericTransaction :: from_signed ( tx, None ) ;
326
326
327
+ let Some ( gas) = gas else {
328
+ log:: debug!( target: LOG_TARGET , "No gas provided" ) ;
329
+ return Err ( InvalidTransaction :: Call ) ;
330
+ } ;
331
+
327
332
if chain_id. unwrap_or_default ( ) != <Self :: Config as Config >:: ChainId :: get ( ) . into ( ) {
328
333
log:: debug!( target: LOG_TARGET , "Invalid chain_id {chain_id:?}" ) ;
329
334
return Err ( InvalidTransaction :: Call ) ;
@@ -337,13 +342,11 @@ pub trait EthExtra {
337
342
338
343
let data = input. unwrap_or_default ( ) . 0 ;
339
344
340
- let ( gas_limit, storage_deposit_limit) = <Self :: Config as Config >:: EthGasEncoder :: decode (
341
- gas. unwrap_or_default ( ) ,
342
- )
343
- . ok_or_else ( || {
344
- log:: debug!( target: LOG_TARGET , "Failed to decode gas: {gas:?}" ) ;
345
- InvalidTransaction :: Call
346
- } ) ?;
345
+ let ( gas_limit, storage_deposit_limit) =
346
+ <Self :: Config as Config >:: EthGasEncoder :: decode ( gas) . ok_or_else ( || {
347
+ log:: debug!( target: LOG_TARGET , "Failed to decode gas: {gas:?}" ) ;
348
+ InvalidTransaction :: Call
349
+ } ) ?;
347
350
348
351
let call = if let Some ( dest) = to {
349
352
crate :: Call :: call:: < Self :: Config > {
@@ -380,13 +383,13 @@ pub trait EthExtra {
380
383
// Fees calculated with the fixed `GAS_PRICE`
381
384
// When we dry-run the transaction, we set the gas to `Fee / GAS_PRICE`
382
385
let eth_fee_no_tip = U256 :: from ( GAS_PRICE )
383
- . saturating_mul ( gas. unwrap_or_default ( ) )
386
+ . saturating_mul ( gas)
384
387
. try_into ( )
385
388
. map_err ( |_| InvalidTransaction :: Call ) ?;
386
389
387
390
// Fees with the actual gas_price from the transaction.
388
391
let eth_fee: BalanceOf < Self :: Config > = U256 :: from ( gas_price. unwrap_or_default ( ) )
389
- . saturating_mul ( gas. unwrap_or_default ( ) )
392
+ . saturating_mul ( gas)
390
393
. try_into ( )
391
394
. map_err ( |_| InvalidTransaction :: Call ) ?;
392
395
@@ -411,7 +414,8 @@ pub trait EthExtra {
411
414
}
412
415
413
416
if eth_fee_no_tip > actual_fee. saturating_mul ( 2u32 . into ( ) ) {
414
- log:: debug!( target: LOG_TARGET , "actual fees: {actual_fee:?} too high, base eth fees: {eth_fee_no_tip:?}" ) ;
417
+ log:: debug!( target: LOG_TARGET , "actual fees: {actual_fee:?} too high, base eth fees:
418
+ {eth_fee_no_tip:?}" ) ;
415
419
return Err ( InvalidTransaction :: Call . into ( ) )
416
420
}
417
421
@@ -473,8 +477,6 @@ mod test {
473
477
#[ derive( Clone ) ]
474
478
struct UncheckedExtrinsicBuilder {
475
479
tx : GenericTransaction ,
476
- gas_limit : Weight ,
477
- storage_deposit_limit : BalanceOf < Test > ,
478
480
before_validate : Option < std:: sync:: Arc < dyn Fn ( ) + Send + Sync > > ,
479
481
}
480
482
@@ -488,8 +490,6 @@ mod test {
488
490
gas_price : Some ( U256 :: from ( GAS_PRICE ) ) ,
489
491
..Default :: default ( )
490
492
} ,
491
- gas_limit : Weight :: zero ( ) ,
492
- storage_deposit_limit : 0 ,
493
493
before_validate : None ,
494
494
}
495
495
}
@@ -506,11 +506,6 @@ mod test {
506
506
Ok ( dry_run) => {
507
507
log:: debug!( target: LOG_TARGET , "Estimated gas: {:?}" , dry_run. eth_gas) ;
508
508
self . tx . gas = Some ( dry_run. eth_gas ) ;
509
- let ( gas_limit, deposit) =
510
- <<Test as Config >:: EthGasEncoder as GasEncoder < _ > >:: decode ( dry_run. eth_gas )
511
- . unwrap ( ) ;
512
- self . gas_limit = gas_limit;
513
- self . storage_deposit_limit = deposit;
514
509
} ,
515
510
Err ( err) => {
516
511
log:: debug!( target: LOG_TARGET , "Failed to estimate gas: {:?}" , err) ;
@@ -522,31 +517,35 @@ mod test {
522
517
fn call_with ( dest : H160 ) -> Self {
523
518
let mut builder = Self :: new ( ) ;
524
519
builder. tx . to = Some ( dest) ;
525
- ExtBuilder :: default ( ) . build ( ) . execute_with ( || builder. estimate_gas ( ) ) ;
526
520
builder
527
521
}
528
522
529
523
/// Create a new builder with an instantiate call.
530
524
fn instantiate_with ( code : Vec < u8 > , data : Vec < u8 > ) -> Self {
531
525
let mut builder = Self :: new ( ) ;
532
526
builder. tx . input = Some ( Bytes ( code. into_iter ( ) . chain ( data. into_iter ( ) ) . collect ( ) ) ) ;
533
- ExtBuilder :: default ( ) . build ( ) . execute_with ( || builder. estimate_gas ( ) ) ;
534
527
builder
535
528
}
536
529
537
- /// Update the transaction with the given function.
538
- fn update ( mut self , f : impl FnOnce ( & mut GenericTransaction ) -> ( ) ) -> Self {
539
- f ( & mut self . tx ) ;
540
- self
541
- }
542
530
/// Set before_validate function.
543
531
fn before_validate ( mut self , f : impl Fn ( ) + Send + Sync + ' static ) -> Self {
544
532
self . before_validate = Some ( std:: sync:: Arc :: new ( f) ) ;
545
533
self
546
534
}
547
535
536
+ fn check (
537
+ self ,
538
+ ) -> Result < ( RuntimeCall , SignedExtra , GenericTransaction ) , TransactionValidityError > {
539
+ self . mutate_estimate_and_check ( Box :: new ( |_| ( ) ) )
540
+ }
541
+
548
542
/// Call `check` on the unchecked extrinsic, and `pre_dispatch` on the signed extension.
549
- fn check ( & self ) -> Result < ( RuntimeCall , SignedExtra ) , TransactionValidityError > {
543
+ fn mutate_estimate_and_check (
544
+ mut self ,
545
+ f : Box < dyn FnOnce ( & mut GenericTransaction ) -> ( ) > ,
546
+ ) -> Result < ( RuntimeCall , SignedExtra , GenericTransaction ) , TransactionValidityError > {
547
+ ExtBuilder :: default ( ) . build ( ) . execute_with ( || self . estimate_gas ( ) ) ;
548
+ f ( & mut self . tx ) ;
550
549
ExtBuilder :: default ( ) . build ( ) . execute_with ( || {
551
550
let UncheckedExtrinsicBuilder { tx, before_validate, .. } = self . clone ( ) ;
552
551
@@ -557,8 +556,9 @@ mod test {
557
556
100_000_000_000_000 ,
558
557
) ;
559
558
560
- let payload =
561
- account. sign_transaction ( tx. try_into_unsigned ( ) . unwrap ( ) ) . signed_payload ( ) ;
559
+ let payload = account
560
+ . sign_transaction ( tx. clone ( ) . try_into_unsigned ( ) . unwrap ( ) )
561
+ . signed_payload ( ) ;
562
562
let call = RuntimeCall :: Contracts ( crate :: Call :: eth_transact { payload } ) ;
563
563
564
564
let encoded_len = call. encoded_size ( ) ;
@@ -578,22 +578,26 @@ mod test {
578
578
0 ,
579
579
) ?;
580
580
581
- Ok ( ( result. function , extra) )
581
+ Ok ( ( result. function , extra, tx ) )
582
582
} )
583
583
}
584
584
}
585
585
586
586
#[ test]
587
587
fn check_eth_transact_call_works ( ) {
588
588
let builder = UncheckedExtrinsicBuilder :: call_with ( H160 :: from ( [ 1u8 ; 20 ] ) ) ;
589
+ let ( call, _, tx) = builder. check ( ) . unwrap ( ) ;
590
+ let ( gas_limit, storage_deposit_limit) =
591
+ <<Test as Config >:: EthGasEncoder as GasEncoder < _ > >:: decode ( tx. gas . unwrap ( ) ) . unwrap ( ) ;
592
+
589
593
assert_eq ! (
590
- builder . check ( ) . unwrap ( ) . 0 ,
594
+ call ,
591
595
crate :: Call :: call:: <Test > {
592
- dest: builder . tx. to. unwrap( ) ,
593
- value: builder . tx. value. unwrap_or_default( ) . as_u64( ) ,
594
- gas_limit : builder . gas_limit ,
595
- storage_deposit_limit : builder . storage_deposit_limit ,
596
- data : builder . tx . input . unwrap_or_default ( ) . 0
596
+ dest: tx. to. unwrap( ) ,
597
+ value: tx. value. unwrap_or_default( ) . as_u64( ) ,
598
+ data : tx . input . unwrap_or_default ( ) . 0 ,
599
+ gas_limit ,
600
+ storage_deposit_limit
597
601
}
598
602
. into( )
599
603
) ;
@@ -604,28 +608,30 @@ mod test {
604
608
let ( code, _) = compile_module ( "dummy" ) . unwrap ( ) ;
605
609
let data = vec ! [ ] ;
606
610
let builder = UncheckedExtrinsicBuilder :: instantiate_with ( code. clone ( ) , data. clone ( ) ) ;
611
+ let ( call, _, tx) = builder. check ( ) . unwrap ( ) ;
612
+ let ( gas_limit, storage_deposit_limit) =
613
+ <<Test as Config >:: EthGasEncoder as GasEncoder < _ > >:: decode ( tx. gas . unwrap ( ) ) . unwrap ( ) ;
607
614
608
615
assert_eq ! (
609
- builder . check ( ) . unwrap ( ) . 0 ,
616
+ call ,
610
617
crate :: Call :: instantiate_with_code:: <Test > {
611
- value: builder. tx. value. unwrap_or_default( ) . as_u64( ) ,
612
- gas_limit: builder. gas_limit,
613
- storage_deposit_limit: builder. storage_deposit_limit,
618
+ value: tx. value. unwrap_or_default( ) . as_u64( ) ,
614
619
code,
615
620
data,
616
- salt: None
621
+ salt: None ,
622
+ gas_limit,
623
+ storage_deposit_limit
617
624
}
618
625
. into( )
619
626
) ;
620
627
}
621
628
622
629
#[ test]
623
630
fn check_eth_transact_nonce_works ( ) {
624
- let builder = UncheckedExtrinsicBuilder :: call_with ( H160 :: from ( [ 1u8 ; 20 ] ) )
625
- . update ( |tx| tx. nonce = Some ( 1u32 . into ( ) ) ) ;
631
+ let builder = UncheckedExtrinsicBuilder :: call_with ( H160 :: from ( [ 1u8 ; 20 ] ) ) ;
626
632
627
633
assert_eq ! (
628
- builder. check ( ) ,
634
+ builder. mutate_estimate_and_check ( Box :: new ( |tx| tx . nonce = Some ( 1u32 . into ( ) ) ) ) ,
629
635
Err ( TransactionValidityError :: Invalid ( InvalidTransaction :: Future ) )
630
636
) ;
631
637
@@ -642,11 +648,10 @@ mod test {
642
648
643
649
#[ test]
644
650
fn check_eth_transact_chain_id_works ( ) {
645
- let builder = UncheckedExtrinsicBuilder :: call_with ( H160 :: from ( [ 1u8 ; 20 ] ) )
646
- . update ( |tx| tx. chain_id = Some ( 42 . into ( ) ) ) ;
651
+ let builder = UncheckedExtrinsicBuilder :: call_with ( H160 :: from ( [ 1u8 ; 20 ] ) ) ;
647
652
648
653
assert_eq ! (
649
- builder. check ( ) ,
654
+ builder. mutate_estimate_and_check ( Box :: new ( |tx| tx . chain_id = Some ( 42 . into ( ) ) ) ) ,
650
655
Err ( TransactionValidityError :: Invalid ( InvalidTransaction :: Call ) )
651
656
) ;
652
657
}
@@ -659,7 +664,7 @@ mod test {
659
664
660
665
// Fail because the tx input fail to get the blob length
661
666
assert_eq ! (
662
- builder. clone ( ) . update ( |tx| tx. input = Some ( Bytes ( vec![ 1 , 2 , 3 ] ) ) ) . check ( ) ,
667
+ builder. mutate_estimate_and_check ( Box :: new ( |tx| tx. input = Some ( Bytes ( vec![ 1 , 2 , 3 ] ) ) ) ) ,
663
668
Err ( TransactionValidityError :: Invalid ( InvalidTransaction :: Call ) )
664
669
) ;
665
670
}
@@ -691,27 +696,27 @@ mod test {
691
696
] ;
692
697
693
698
for ( msg, update_tx, err) in scenarios {
694
- let builder =
695
- UncheckedExtrinsicBuilder :: call_with ( H160 :: from ( [ 1u8 ; 20 ] ) ) . update ( update_tx) ;
699
+ let res = UncheckedExtrinsicBuilder :: call_with ( H160 :: from ( [ 1u8 ; 20 ] ) )
700
+ . mutate_estimate_and_check ( update_tx) ;
696
701
697
- assert_eq ! ( builder . check ( ) , Err ( TransactionValidityError :: Invalid ( err) ) , "{}" , msg) ;
702
+ assert_eq ! ( res , Err ( TransactionValidityError :: Invalid ( err) ) , "{}" , msg) ;
698
703
}
699
704
}
700
705
701
706
#[ test]
702
707
fn check_transaction_tip ( ) {
703
708
let ( code, _) = compile_module ( "dummy" ) . unwrap ( ) ;
704
709
let data = vec ! [ ] ;
705
- let builder = UncheckedExtrinsicBuilder :: instantiate_with ( code. clone ( ) , data. clone ( ) )
706
- . update ( |tx| {
707
- tx. gas_price = Some ( tx. gas_price . unwrap ( ) * 103 / 100 ) ;
708
- log:: debug!( target: LOG_TARGET , "Gas price: {:?}" , tx. gas_price) ;
709
- } ) ;
710
+ let ( _, extra, tx) =
711
+ UncheckedExtrinsicBuilder :: instantiate_with ( code. clone ( ) , data. clone ( ) )
712
+ . mutate_estimate_and_check ( Box :: new ( |tx| {
713
+ tx. gas_price = Some ( tx. gas_price . unwrap ( ) * 103 / 100 ) ;
714
+ log:: debug!( target: LOG_TARGET , "Gas price: {:?}" , tx. gas_price) ;
715
+ } ) )
716
+ . unwrap ( ) ;
710
717
711
- let tx = & builder. tx ;
712
718
let expected_tip =
713
719
tx. gas_price . unwrap ( ) * tx. gas . unwrap ( ) - U256 :: from ( GAS_PRICE ) * tx. gas . unwrap ( ) ;
714
- let ( _, extra) = builder. check ( ) . unwrap ( ) ;
715
720
assert_eq ! ( U256 :: from( extra. 1 . tip( ) ) , expected_tip) ;
716
721
}
717
722
}
0 commit comments