@@ -21,10 +21,11 @@ use super::*;
2121use evm:: { ExitReason , ExitRevert , ExitSucceed } ;
2222use fp_ethereum:: { TransactionData , ValidatedTransaction } ;
2323use frame_support:: {
24- dispatch:: { DispatchClass , GetDispatchInfo } ,
24+ dispatch:: { DispatchClass , GetDispatchInfo , Pays , PostDispatchInfo } ,
2525 weights:: Weight ,
2626} ;
2727use pallet_evm:: AddressMapping ;
28+ use sp_runtime:: { DispatchError , DispatchErrorWithPostInfo , ModuleError } ;
2829
2930fn legacy_erc20_creation_unsigned_transaction ( ) -> LegacyUnsignedTransaction {
3031 LegacyUnsignedTransaction {
@@ -41,6 +42,21 @@ fn legacy_erc20_creation_transaction(account: &AccountInfo) -> Transaction {
4142 legacy_erc20_creation_unsigned_transaction ( ) . sign ( & account. private_key )
4243}
4344
45+ fn legacy_foo_bar_contract_creation_unsigned_transaction ( ) -> LegacyUnsignedTransaction {
46+ LegacyUnsignedTransaction {
47+ nonce : U256 :: zero ( ) ,
48+ gas_price : U256 :: from ( 1 ) ,
49+ gas_limit : U256 :: from ( 0x100000 ) ,
50+ action : ethereum:: TransactionAction :: Create ,
51+ value : U256 :: zero ( ) ,
52+ input : hex:: decode ( FOO_BAR_CONTRACT_CREATOR_BYTECODE . trim_end ( ) ) . unwrap ( ) ,
53+ }
54+ }
55+
56+ fn legacy_foo_bar_contract_creation_transaction ( account : & AccountInfo ) -> Transaction {
57+ legacy_foo_bar_contract_creation_unsigned_transaction ( ) . sign ( & account. private_key )
58+ }
59+
4460#[ test]
4561fn transaction_should_increment_nonce ( ) {
4662 let ( pairs, mut ext) = new_test_ext ( 1 ) ;
@@ -273,6 +289,138 @@ fn transaction_should_generate_correct_gas_used() {
273289 } ) ;
274290}
275291
292+ #[ test]
293+ fn contract_creation_succeeds_with_allowed_address ( ) {
294+ let ( pairs, mut ext) = new_test_ext ( 1 ) ;
295+ let alice = & pairs[ 0 ] ;
296+
297+ ext. execute_with ( || {
298+ // Alice can deploy contracts
299+ let t = LegacyUnsignedTransaction {
300+ nonce : U256 :: zero ( ) ,
301+ gas_price : U256 :: from ( 1 ) ,
302+ gas_limit : U256 :: from ( 0x100000 ) ,
303+ action : ethereum:: TransactionAction :: Create ,
304+ value : U256 :: zero ( ) ,
305+ input : hex:: decode ( TEST_CONTRACT_CODE ) . unwrap ( ) ,
306+ }
307+ . sign ( & alice. private_key ) ;
308+ assert_ok ! ( Ethereum :: execute( alice. address, & t, None , ) ) ;
309+ } ) ;
310+ }
311+
312+ #[ test]
313+ fn contract_creation_fails_with_not_allowed_address ( ) {
314+ let ( pairs, mut ext) = new_test_ext ( 2 ) ;
315+ let bob = & pairs[ 1 ] ;
316+
317+ ext. execute_with ( || {
318+ // Bob can't deploy contracts
319+ let t = LegacyUnsignedTransaction {
320+ nonce : U256 :: zero ( ) ,
321+ gas_price : U256 :: from ( 1 ) ,
322+ gas_limit : U256 :: from ( 0x100000 ) ,
323+ action : ethereum:: TransactionAction :: Create ,
324+ value : U256 :: zero ( ) ,
325+ input : hex:: decode ( TEST_CONTRACT_CODE ) . unwrap ( ) ,
326+ }
327+ . sign ( & bob. private_key ) ;
328+
329+ let result = Ethereum :: execute ( bob. address , & t, None ) ;
330+ assert ! ( result. is_err( ) ) ;
331+
332+ // Note: assert_err! macro doesn't work here because we receive 'None' as
333+ // 'actual_weight' using assert_err instead of Some(Weight::default()),
334+ // but the error is the same "CreateOriginNotAllowed".
335+ assert_eq ! (
336+ result,
337+ Err ( DispatchErrorWithPostInfo {
338+ post_info: PostDispatchInfo {
339+ actual_weight: Some ( Weight :: default ( ) ) ,
340+ pays_fee: Pays :: Yes
341+ } ,
342+ error: DispatchError :: Module ( ModuleError {
343+ index: 3 ,
344+ error: [ 14 , 0 , 0 , 0 ] ,
345+ message: Some ( "CreateOriginNotAllowed" )
346+ } )
347+ } )
348+ ) ;
349+ } ) ;
350+ }
351+
352+ #[ test]
353+ fn inner_contract_creation_succeeds_with_allowed_address ( ) {
354+ let ( pairs, mut ext) = new_test_ext ( 1 ) ;
355+ let alice = & pairs[ 0 ] ;
356+
357+ ext. execute_with ( || {
358+ let t = legacy_foo_bar_contract_creation_transaction ( alice) ;
359+ assert_ok ! ( Ethereum :: execute( alice. address, & t, None , ) ) ;
360+
361+ let contract_address = hex:: decode ( "32dcab0ef3fb2de2fce1d2e0799d36239671f04a" ) . unwrap ( ) ;
362+ let new_bar = hex:: decode ( "2fc11060" ) . unwrap ( ) ;
363+
364+ // Alice is allowed to deploy contracts via inner calls.
365+ let new_bar_inner_creation_tx = LegacyUnsignedTransaction {
366+ nonce : U256 :: from ( 1 ) ,
367+ gas_price : U256 :: from ( 1 ) ,
368+ gas_limit : U256 :: from ( 0x100000 ) ,
369+ action : TransactionAction :: Call ( H160 :: from_slice ( & contract_address) ) ,
370+ value : U256 :: zero ( ) ,
371+ input : new_bar,
372+ }
373+ . sign ( & alice. private_key ) ;
374+
375+ let ( _, _, info) =
376+ Ethereum :: execute ( alice. address , & new_bar_inner_creation_tx, None ) . unwrap ( ) ;
377+
378+ assert ! ( Ethereum :: execute( alice. address, & new_bar_inner_creation_tx, None ) . is_ok( ) ) ;
379+ match info {
380+ CallOrCreateInfo :: Call ( info) => {
381+ assert_eq ! ( info. exit_reason, ExitReason :: Succeed ( ExitSucceed :: Returned ) ) ;
382+ }
383+ CallOrCreateInfo :: Create ( _) => panic ! ( "expected call info" ) ,
384+ }
385+ } ) ;
386+ }
387+
388+ #[ test]
389+ fn inner_contract_creation_reverts_with_not_allowed_address ( ) {
390+ let ( pairs, mut ext) = new_test_ext ( 2 ) ;
391+ let alice = & pairs[ 0 ] ;
392+ let bob = & pairs[ 1 ] ;
393+
394+ ext. execute_with ( || {
395+ let t = legacy_foo_bar_contract_creation_transaction ( alice) ;
396+ assert_ok ! ( Ethereum :: execute( alice. address, & t, None , ) ) ;
397+
398+ let contract_address = hex:: decode ( "32dcab0ef3fb2de2fce1d2e0799d36239671f04a" ) . unwrap ( ) ;
399+ let new_bar = hex:: decode ( "2fc11060" ) . unwrap ( ) ;
400+
401+ // Bob is not allowed to deploy contracts via inner calls.
402+ let new_bar_inner_creation_tx = LegacyUnsignedTransaction {
403+ nonce : U256 :: from ( 1 ) ,
404+ gas_price : U256 :: from ( 1 ) ,
405+ gas_limit : U256 :: from ( 0x100000 ) ,
406+ action : TransactionAction :: Call ( H160 :: from_slice ( & contract_address) ) ,
407+ value : U256 :: zero ( ) ,
408+ input : new_bar,
409+ }
410+ . sign ( & bob. private_key ) ;
411+
412+ let ( _, _, info) =
413+ Ethereum :: execute ( bob. address , & new_bar_inner_creation_tx, None ) . unwrap ( ) ;
414+
415+ match info {
416+ CallOrCreateInfo :: Call ( info) => {
417+ assert_eq ! ( info. exit_reason, ExitReason :: Revert ( ExitRevert :: Reverted ) ) ;
418+ }
419+ CallOrCreateInfo :: Create ( _) => panic ! ( "expected call info" ) ,
420+ }
421+ } ) ;
422+ }
423+
276424#[ test]
277425fn call_should_handle_errors ( ) {
278426 let ( pairs, mut ext) = new_test_ext ( 1 ) ;
0 commit comments