@@ -25,7 +25,7 @@ pub use crate::backend::{Account, Log, Vicinity, Backend};
25
25
26
26
use sp_std:: { vec:: Vec , marker:: PhantomData } ;
27
27
use frame_support:: { ensure, decl_module, decl_storage, decl_event, decl_error} ;
28
- use frame_support:: weights:: { Weight , WeighData , ClassifyDispatch , DispatchClass , PaysFee } ;
28
+ use frame_support:: weights:: { Weight , DispatchClass , FunctionOf } ;
29
29
use frame_support:: traits:: { Currency , WithdrawReason , ExistenceRequirement } ;
30
30
use frame_system:: { self as system, ensure_signed} ;
31
31
use sp_runtime:: ModuleId ;
@@ -34,6 +34,7 @@ use sp_core::{U256, H256, H160, Hasher};
34
34
use sp_runtime:: {
35
35
DispatchResult , traits:: { UniqueSaturatedInto , AccountIdConversion , SaturatedConversion } ,
36
36
} ;
37
+ use sha3:: { Digest , Keccak256 } ;
37
38
use evm:: { ExitReason , ExitSucceed , ExitError } ;
38
39
use evm:: executor:: StackExecutor ;
39
40
use evm:: backend:: ApplyBackend ;
@@ -115,38 +116,6 @@ impl Precompiles for () {
115
116
}
116
117
}
117
118
118
- struct WeightForCallCreate ;
119
-
120
- impl WeighData < ( & H160 , & Vec < u8 > , & U256 , & u32 , & U256 , & Option < U256 > ) > for WeightForCallCreate {
121
- fn weigh_data (
122
- & self ,
123
- ( _, _, _, gas_provided, gas_price, _) : ( & H160 , & Vec < u8 > , & U256 , & u32 , & U256 , & Option < U256 > )
124
- ) -> Weight {
125
- ( * gas_price) . saturated_into :: < Weight > ( ) . saturating_mul ( * gas_provided)
126
- }
127
- }
128
-
129
- impl WeighData < ( & Vec < u8 > , & U256 , & u32 , & U256 , & Option < U256 > ) > for WeightForCallCreate {
130
- fn weigh_data (
131
- & self ,
132
- ( _, _, gas_provided, gas_price, _) : ( & Vec < u8 > , & U256 , & u32 , & U256 , & Option < U256 > )
133
- ) -> Weight {
134
- ( * gas_price) . saturated_into :: < Weight > ( ) . saturating_mul ( * gas_provided)
135
- }
136
- }
137
-
138
- impl < T > ClassifyDispatch < T > for WeightForCallCreate {
139
- fn classify_dispatch ( & self , _: T ) -> DispatchClass {
140
- DispatchClass :: Normal
141
- }
142
- }
143
-
144
- impl < T > PaysFee < T > for WeightForCallCreate {
145
- fn pays_fee ( & self , _: T ) -> bool {
146
- true
147
- }
148
- }
149
-
150
119
/// EVM module trait
151
120
pub trait Trait : frame_system:: Trait + pallet_timestamp:: Trait {
152
121
/// Calculator for current gas price.
@@ -252,7 +221,7 @@ decl_module! {
252
221
}
253
222
254
223
/// Issue an EVM call operation. This is similar to a message call transaction in Ethereum.
255
- #[ weight = WeightForCallCreate ]
224
+ #[ weight = FunctionOf ( | ( _ , _ , _ , gas_limit , gas_price , _ ) : ( & H160 , & Vec < u8 > , & U256 , & u32 , & U256 , & Option < U256 > ) | ( * gas_price ) . saturated_into :: < Weight > ( ) . saturating_mul ( * gas_limit ) , DispatchClass :: Normal , true ) ]
256
225
fn call(
257
226
origin,
258
227
target: H160 ,
@@ -315,7 +284,7 @@ decl_module! {
315
284
316
285
/// Issue an EVM create operation. This is similar to a contract creation transaction in
317
286
/// Ethereum.
318
- #[ weight = WeightForCallCreate ]
287
+ #[ weight = FunctionOf ( | ( _ , _ , gas_limit , gas_price , _ ) : ( & Vec < u8 > , & U256 , & u32 , & U256 , & Option < U256 > ) | ( * gas_price ) . saturated_into :: < Weight > ( ) . saturating_mul ( * gas_limit ) , DispatchClass :: Normal , true ) ]
319
288
fn create(
320
289
origin,
321
290
init: Vec <u8 >,
@@ -353,7 +322,9 @@ decl_module! {
353
322
ensure!( source_account. nonce == nonce, Error :: <T >:: InvalidNonce ) ;
354
323
}
355
324
356
- let create_address = executor. create_address( source, evm:: CreateScheme :: Dynamic ) ;
325
+ let create_address = executor. create_address(
326
+ evm:: CreateScheme :: Legacy { caller: source }
327
+ ) ;
357
328
let reason = executor. transact_create(
358
329
source,
359
330
value,
@@ -378,6 +349,76 @@ decl_module! {
378
349
379
350
ret. map_err( Into :: into)
380
351
}
352
+
353
+ /// Issue an EVM create2 operation.
354
+ #[ weight = FunctionOf ( |( _, _, _, gas_limit, gas_price, _) : ( & Vec <u8 >, & H256 , & U256 , & u32 , & U256 , & Option <U256 >) | ( * gas_price) . saturated_into:: <Weight >( ) . saturating_mul( * gas_limit) , DispatchClass :: Normal , true ) ]
355
+ fn create2(
356
+ origin,
357
+ init: Vec <u8 >,
358
+ salt: H256 ,
359
+ value: U256 ,
360
+ gas_limit: u32 ,
361
+ gas_price: U256 ,
362
+ nonce: Option <U256 >,
363
+ ) -> DispatchResult {
364
+ let sender = ensure_signed( origin) ?;
365
+ ensure!( gas_price >= T :: FeeCalculator :: min_gas_price( ) , Error :: <T >:: GasPriceTooLow ) ;
366
+
367
+ let source = T :: ConvertAccountId :: convert_account_id( & sender) ;
368
+
369
+ let vicinity = Vicinity {
370
+ gas_price,
371
+ origin: source,
372
+ } ;
373
+
374
+ let mut backend = Backend :: <T >:: new( & vicinity) ;
375
+ let mut executor = StackExecutor :: new_with_precompile(
376
+ & backend,
377
+ gas_limit as usize ,
378
+ & backend:: GASOMETER_CONFIG ,
379
+ T :: Precompiles :: execute,
380
+ ) ;
381
+
382
+ let total_fee = gas_price. checked_mul( U256 :: from( gas_limit) )
383
+ . ok_or( Error :: <T >:: FeeOverflow ) ?;
384
+ let total_payment = value. checked_add( total_fee) . ok_or( Error :: <T >:: PaymentOverflow ) ?;
385
+ let source_account = Accounts :: get( & source) ;
386
+ ensure!( source_account. balance >= total_payment, Error :: <T >:: BalanceLow ) ;
387
+ executor. withdraw( source, total_fee) . map_err( |_| Error :: <T >:: WithdrawFailed ) ?;
388
+
389
+ if let Some ( nonce) = nonce {
390
+ ensure!( source_account. nonce == nonce, Error :: <T >:: InvalidNonce ) ;
391
+ }
392
+
393
+ let code_hash = H256 :: from_slice( Keccak256 :: digest( & init) . as_slice( ) ) ;
394
+ let create_address = executor. create_address(
395
+ evm:: CreateScheme :: Create2 { caller: source, code_hash, salt }
396
+ ) ;
397
+ let reason = executor. transact_create2(
398
+ source,
399
+ value,
400
+ init,
401
+ salt,
402
+ gas_limit as usize ,
403
+ ) ;
404
+
405
+ let ret = match reason {
406
+ ExitReason :: Succeed ( _) => {
407
+ Module :: <T >:: deposit_event( Event :: Created ( create_address) ) ;
408
+ Ok ( ( ) )
409
+ } ,
410
+ ExitReason :: Error ( _) => Err ( Error :: <T >:: ExitReasonFailed ) ,
411
+ ExitReason :: Revert ( _) => Err ( Error :: <T >:: ExitReasonRevert ) ,
412
+ ExitReason :: Fatal ( _) => Err ( Error :: <T >:: ExitReasonFatal ) ,
413
+ } ;
414
+ let actual_fee = executor. fee( gas_price) ;
415
+ executor. deposit( source, total_fee. saturating_sub( actual_fee) ) ;
416
+
417
+ let ( values, logs) = executor. deconstruct( ) ;
418
+ backend. apply( values, logs, true ) ;
419
+
420
+ ret. map_err( Into :: into)
421
+ }
381
422
}
382
423
}
383
424
0 commit comments