2020-09-22 14:53:52 +02:00
// Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of OpenEthereum.
2016-02-05 13:40:41 +01:00
2020-09-22 14:53:52 +02:00
// OpenEthereum is free software: you can redistribute it and/or modify
2016-02-05 13:40:41 +01:00
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
2020-09-22 14:53:52 +02:00
// OpenEthereum is distributed in the hope that it will be useful,
2016-02-05 13:40:41 +01:00
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
2020-09-22 14:53:52 +02:00
// along with OpenEthereum. If not, see <http://www.gnu.org/licenses/>.
2016-02-05 13:40:41 +01:00
2016-01-11 02:42:02 +01:00
//! Transaction Execution environment.
2017-09-06 20:47:45 +02:00
use bytes ::{ Bytes , BytesRef } ;
2017-02-21 12:35:21 +01:00
use ethereum_types ::{ Address , H256 , U256 , U512 } ;
use evm ::{ CallType , FinalizationResult , Finalize } ;
2019-01-04 14:05:46 +01:00
use executed ::ExecutionError ;
2018-02-19 12:27:42 +01:00
pub use executed ::{ Executed , ExecutionResult } ;
2016-01-15 14:22:46 +01:00
use externalities ::* ;
2018-10-02 16:33:19 +02:00
use factory ::VmFactory ;
2017-08-30 19:18:28 +02:00
use hash ::keccak ;
2018-07-23 15:48:01 +02:00
use machine ::EthereumMachine as Machine ;
2017-02-21 12:35:21 +01:00
use state ::{ Backend as StateBackend , CleanupMode , State , Substate } ;
2017-07-29 21:56:42 +02:00
use std ::{ cmp , sync ::Arc } ;
2017-10-20 15:40:25 +02:00
use trace ::{ self , Tracer , VMTracer } ;
2019-01-04 14:05:46 +01:00
use transaction_ext ::Transaction ;
2017-07-12 13:09:17 +02:00
use types ::transaction ::{ Action , SignedTransaction } ;
2018-02-19 12:27:42 +01:00
use vm ::{
2020-11-04 19:11:05 +01:00
self , AccessList , ActionParams , ActionValue , CleanDustMode , CreateContractAddress , EnvInfo ,
ResumeCall , ResumeCreate , ReturnData , Schedule , TrapError ,
2020-08-05 06:08:03 +02:00
} ;
2016-05-16 18:33:32 +02:00
2020-09-10 08:04:14 +02:00
#[ cfg(any(test, feature = " test-helpers " )) ]
/// Precompile that can never be prunned from state trie (0x3, only in tests)
const UNPRUNABLE_PRECOMPILE_ADDRESS : Option < Address > = Some ( ethereum_types ::H160 ( [
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 3 ,
] ) ) ;
#[ cfg(not(any(test, feature = " test-helpers " ))) ]
/// Precompile that can never be prunned from state trie (none)
const UNPRUNABLE_PRECOMPILE_ADDRESS : Option < Address > = None ;
2017-04-19 14:30:00 +02:00
/// Returns new address created from address, nonce, and code hash
2017-06-30 11:30:32 +02:00
pub fn contract_address (
address_scheme : CreateContractAddress ,
sender : & Address ,
nonce : & U256 ,
code : & [ u8 ] ,
) -> ( Address , Option < H256 > ) {
2017-03-20 19:14:29 +01:00
use rlp ::RlpStream ;
2020-08-05 06:08:03 +02:00
2017-04-19 14:30:00 +02:00
match address_scheme {
CreateContractAddress ::FromSenderAndNonce = > {
let mut stream = RlpStream ::new_list ( 2 ) ;
stream . append ( sender ) ;
stream . append ( nonce ) ;
2017-08-30 19:18:28 +02:00
( From ::from ( keccak ( stream . as_raw ( ) ) ) , None )
2017-04-19 14:30:00 +02:00
}
2018-08-01 13:17:04 +02:00
CreateContractAddress ::FromSenderSaltAndCodeHash ( salt ) = > {
2017-08-30 19:18:28 +02:00
let code_hash = keccak ( code ) ;
2018-08-31 17:43:51 +02:00
let mut buffer = [ 0 u8 ; 1 + 20 + 32 + 32 ] ;
buffer [ 0 ] = 0xff ;
& mut buffer [ 1 .. ( 1 + 20 ) ] . copy_from_slice ( & sender [ .. ] ) ;
& mut buffer [ ( 1 + 20 ) .. ( 1 + 20 + 32 ) ] . copy_from_slice ( & salt [ .. ] ) ;
& mut buffer [ ( 1 + 20 + 32 ) .. ] . copy_from_slice ( & code_hash [ .. ] ) ;
2017-08-30 19:18:28 +02:00
( From ::from ( keccak ( & buffer [ .. ] ) ) , Some ( code_hash ) )
2017-04-19 14:30:00 +02:00
}
CreateContractAddress ::FromSenderAndCodeHash = > {
2017-08-30 19:18:28 +02:00
let code_hash = keccak ( code ) ;
2017-04-19 14:30:00 +02:00
let mut buffer = [ 0 u8 ; 20 + 32 ] ;
& mut buffer [ .. 20 ] . copy_from_slice ( & sender [ .. ] ) ;
& mut buffer [ 20 .. ] . copy_from_slice ( & code_hash [ .. ] ) ;
2017-08-30 19:18:28 +02:00
( From ::from ( keccak ( & buffer [ .. ] ) ) , Some ( code_hash ) )
2017-04-19 14:30:00 +02:00
}
}
2016-01-07 23:33:54 +01:00
}
2016-01-07 19:05:44 +01:00
2018-10-02 16:33:19 +02:00
/// Convert a finalization result into a VM message call result.
pub fn into_message_call_result ( result : vm ::Result < FinalizationResult > ) -> vm ::MessageCallResult {
match result {
Ok ( FinalizationResult {
gas_left ,
return_data ,
apply_state : true ,
} ) = > vm ::MessageCallResult ::Success ( gas_left , return_data ) ,
Ok ( FinalizationResult {
gas_left ,
return_data ,
apply_state : false ,
} ) = > vm ::MessageCallResult ::Reverted ( gas_left , return_data ) ,
_ = > vm ::MessageCallResult ::Failed ,
}
}
/// Convert a finalization result into a VM contract create result.
pub fn into_contract_create_result (
result : vm ::Result < FinalizationResult > ,
address : & Address ,
substate : & mut Substate ,
) -> vm ::ContractCreateResult {
match result {
Ok ( FinalizationResult {
gas_left ,
apply_state : true ,
..
} ) = > {
substate . contracts_created . push ( address . clone ( ) ) ;
vm ::ContractCreateResult ::Created ( address . clone ( ) , gas_left )
}
Ok ( FinalizationResult {
gas_left ,
apply_state : false ,
return_data ,
} ) = > vm ::ContractCreateResult ::Reverted ( gas_left , return_data ) ,
_ = > vm ::ContractCreateResult ::Failed ,
}
}
2016-04-06 13:05:58 +02:00
/// Transaction execution options.
2017-08-28 14:25:16 +02:00
#[ derive(Copy, Clone, PartialEq) ]
pub struct TransactOptions < T , V > {
2016-04-06 13:05:58 +02:00
/// Enable call tracing.
2017-08-28 14:25:16 +02:00
pub tracer : T ,
2016-06-02 12:40:31 +02:00
/// Enable VM tracing.
2017-08-28 14:25:16 +02:00
pub vm_tracer : V ,
2016-04-06 13:05:58 +02:00
/// Check transaction nonce before execution.
pub check_nonce : bool ,
2017-09-05 13:22:19 +02:00
/// Records the output from init contract calls.
pub output_from_init_contract : bool ,
2016-04-06 13:05:58 +02:00
}
2017-08-28 14:25:16 +02:00
impl < T , V > TransactOptions < T , V > {
/// Create new `TransactOptions` with given tracer and VM tracer.
pub fn new ( tracer : T , vm_tracer : V ) -> Self {
TransactOptions {
tracer ,
vm_tracer ,
check_nonce : true ,
2017-09-05 13:22:19 +02:00
output_from_init_contract : false ,
2017-08-28 14:25:16 +02:00
}
}
2020-08-05 06:08:03 +02:00
2017-08-28 14:25:16 +02:00
/// Disables the nonce check
pub fn dont_check_nonce ( mut self ) -> Self {
self . check_nonce = false ;
self
}
2020-08-05 06:08:03 +02:00
2017-09-05 13:22:19 +02:00
/// Saves the output from contract creation.
pub fn save_output_from_contract ( mut self ) -> Self {
self . output_from_init_contract = true ;
self
}
2017-08-28 14:25:16 +02:00
}
impl TransactOptions < trace ::ExecutiveTracer , trace ::ExecutiveVMTracer > {
/// Creates new `TransactOptions` with default tracing and VM tracing.
pub fn with_tracing_and_vm_tracing ( ) -> Self {
TransactOptions {
tracer : trace ::ExecutiveTracer ::default ( ) ,
vm_tracer : trace ::ExecutiveVMTracer ::toplevel ( ) ,
check_nonce : true ,
2017-09-05 13:22:19 +02:00
output_from_init_contract : false ,
2017-08-28 14:25:16 +02:00
}
}
}
impl TransactOptions < trace ::ExecutiveTracer , trace ::NoopVMTracer > {
/// Creates new `TransactOptions` with default tracing and no VM tracing.
pub fn with_tracing ( ) -> Self {
TransactOptions {
tracer : trace ::ExecutiveTracer ::default ( ) ,
vm_tracer : trace ::NoopVMTracer ,
check_nonce : true ,
2017-09-05 13:22:19 +02:00
output_from_init_contract : false ,
2017-08-28 14:25:16 +02:00
}
}
}
impl TransactOptions < trace ::NoopTracer , trace ::ExecutiveVMTracer > {
/// Creates new `TransactOptions` with no tracing and default VM tracing.
pub fn with_vm_tracing ( ) -> Self {
TransactOptions {
tracer : trace ::NoopTracer ,
vm_tracer : trace ::ExecutiveVMTracer ::toplevel ( ) ,
check_nonce : true ,
2017-09-05 13:22:19 +02:00
output_from_init_contract : false ,
2017-08-28 14:25:16 +02:00
}
}
}
impl TransactOptions < trace ::NoopTracer , trace ::NoopVMTracer > {
/// Creates new `TransactOptions` without any tracing.
pub fn with_no_tracing ( ) -> Self {
TransactOptions {
tracer : trace ::NoopTracer ,
vm_tracer : trace ::NoopVMTracer ,
check_nonce : true ,
2017-09-05 13:22:19 +02:00
output_from_init_contract : false ,
2017-08-28 14:25:16 +02:00
}
}
}
2018-10-02 16:33:19 +02:00
/// Trap result returned by executive.
pub type ExecutiveTrapResult < ' a , T > =
vm ::TrapResult < T , CallCreateExecutive < ' a > , CallCreateExecutive < ' a > > ;
/// Trap error for executive.
pub type ExecutiveTrapError < ' a > = vm ::TrapError < CallCreateExecutive < ' a > , CallCreateExecutive < ' a > > ;
enum CallCreateExecutiveKind {
Transfer ( ActionParams ) ,
CallBuiltin ( ActionParams ) ,
ExecCall ( ActionParams , Substate ) ,
ExecCreate ( ActionParams , Substate ) ,
2020-07-29 10:36:15 +02:00
ResumeCall ( OriginInfo , Box < dyn ResumeCall > , Substate ) ,
ResumeCreate ( OriginInfo , Box < dyn ResumeCreate > , Substate ) ,
2018-10-02 16:33:19 +02:00
}
/// Executive for a raw call/create action.
pub struct CallCreateExecutive < ' a > {
info : & ' a EnvInfo ,
machine : & ' a Machine ,
schedule : & ' a Schedule ,
factory : & ' a VmFactory ,
depth : usize ,
stack_depth : usize ,
static_flag : bool ,
is_create : bool ,
gas : U256 ,
kind : CallCreateExecutiveKind ,
}
impl < ' a > CallCreateExecutive < ' a > {
2020-11-04 19:11:05 +01:00
/// Create new state with access list.
pub fn new_substate ( params : & ActionParams , schedule : & ' a Schedule ) -> Substate {
if schedule . eip2929 {
let mut substate = Substate ::from_access_list ( & params . access_list ) ;
substate . access_list . insert_address ( params . address ) ;
substate . access_list . insert_address ( params . sender ) ;
substate
} else {
Substate ::default ( )
}
}
2018-10-02 16:33:19 +02:00
/// Create a new call executive using raw data.
pub fn new_call_raw (
params : ActionParams ,
info : & ' a EnvInfo ,
machine : & ' a Machine ,
schedule : & ' a Schedule ,
factory : & ' a VmFactory ,
depth : usize ,
stack_depth : usize ,
parent_static_flag : bool ,
) -> Self {
trace! (
" Executive::call(params={:?}) self.env_info={:?}, parent_static={} " ,
params ,
info ,
parent_static_flag
) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let gas = params . gas ;
let static_flag = parent_static_flag | | params . call_type = = CallType ::StaticCall ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
// if destination is builtin, try to execute it
let kind = if let Some ( builtin ) = machine . builtin ( & params . code_address , info . number ) {
// Engines aren't supposed to return builtins until activation, but
// prefer to fail rather than silently break consensus.
if ! builtin . is_active ( info . number ) {
panic! (
" Consensus failure: engine implementation prematurely enabled built-in at {} " ,
params . code_address
) ;
}
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
CallCreateExecutiveKind ::CallBuiltin ( params )
} else {
if params . code . is_some ( ) {
2020-11-04 19:11:05 +01:00
let substate = Self ::new_substate ( & params , schedule ) ;
CallCreateExecutiveKind ::ExecCall ( params , substate )
2018-10-02 16:33:19 +02:00
} else {
CallCreateExecutiveKind ::Transfer ( params )
}
} ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
Self {
info ,
machine ,
schedule ,
factory ,
depth ,
stack_depth ,
static_flag ,
kind ,
gas ,
is_create : false ,
}
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
/// Create a new create executive using raw data.
pub fn new_create_raw (
params : ActionParams ,
info : & ' a EnvInfo ,
machine : & ' a Machine ,
schedule : & ' a Schedule ,
factory : & ' a VmFactory ,
depth : usize ,
stack_depth : usize ,
static_flag : bool ,
) -> Self {
trace! (
" Executive::create(params={:?}) self.env_info={:?}, static={} " ,
params ,
info ,
static_flag
) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let gas = params . gas ;
2020-08-05 06:08:03 +02:00
2020-11-04 19:11:05 +01:00
let substate = Self ::new_substate ( & params , schedule ) ;
let kind = CallCreateExecutiveKind ::ExecCreate ( params , substate ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
Self {
info ,
2020-08-05 06:08:03 +02:00
machine ,
2018-10-02 16:33:19 +02:00
schedule ,
factory ,
2020-08-05 06:08:03 +02:00
depth ,
2018-10-02 16:33:19 +02:00
stack_depth ,
static_flag ,
kind ,
2020-08-05 06:08:03 +02:00
gas ,
2018-10-02 16:33:19 +02:00
is_create : true ,
2020-08-05 06:08:03 +02:00
}
}
2018-10-02 16:33:19 +02:00
/// If this executive contains an unconfirmed substate, returns a mutable reference to it.
pub fn unconfirmed_substate ( & mut self ) -> Option < & mut Substate > {
match self . kind {
CallCreateExecutiveKind ::ExecCall ( _ , ref mut unsub ) = > Some ( unsub ) ,
CallCreateExecutiveKind ::ExecCreate ( _ , ref mut unsub ) = > Some ( unsub ) ,
CallCreateExecutiveKind ::ResumeCreate ( _ , _ , ref mut unsub ) = > Some ( unsub ) ,
CallCreateExecutiveKind ::ResumeCall ( _ , _ , ref mut unsub ) = > Some ( unsub ) ,
CallCreateExecutiveKind ::Transfer ( .. ) | CallCreateExecutiveKind ::CallBuiltin ( .. ) = > {
2020-08-05 06:08:03 +02:00
None
2018-10-02 16:33:19 +02:00
}
}
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
fn check_static_flag (
params : & ActionParams ,
static_flag : bool ,
is_create : bool ,
) -> vm ::Result < ( ) > {
if is_create {
if static_flag {
return Err ( vm ::Error ::MutableCallInStaticContext ) ;
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
} else {
if ( static_flag
& & ( params . call_type = = CallType ::StaticCall | | params . call_type = = CallType ::Call ) )
& & params . value . value ( ) > U256 ::zero ( )
{
return Err ( vm ::Error ::MutableCallInStaticContext ) ;
}
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
Ok ( ( ) )
}
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
fn check_eip684 < B : ' a + StateBackend > (
params : & ActionParams ,
state : & State < B > ,
) -> vm ::Result < ( ) > {
if state . exists_and_has_code_or_nonce ( & params . address ) ? {
return Err ( vm ::Error ::OutOfGas ) ;
}
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
Ok ( ( ) )
}
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
fn transfer_exec_balance < B : ' a + StateBackend > (
params : & ActionParams ,
schedule : & Schedule ,
state : & mut State < B > ,
substate : & mut Substate ,
) -> vm ::Result < ( ) > {
if let ActionValue ::Transfer ( val ) = params . value {
state . transfer_balance (
& params . sender ,
& params . address ,
& val ,
substate . to_cleanup_mode ( & schedule ) ,
) ? ;
}
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
Ok ( ( ) )
}
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
fn transfer_exec_balance_and_init_contract < B : ' a + StateBackend > (
params : & ActionParams ,
schedule : & Schedule ,
state : & mut State < B > ,
substate : & mut Substate ,
) -> vm ::Result < ( ) > {
let nonce_offset = if schedule . no_empty { 1 } else { 0 } . into ( ) ;
let prev_bal = state . balance ( & params . address ) ? ;
if let ActionValue ::Transfer ( val ) = params . value {
state . sub_balance (
& params . sender ,
2019-02-11 23:20:51 +01:00
& val ,
& mut substate . to_cleanup_mode ( & schedule ) ,
2020-08-05 06:08:03 +02:00
) ? ;
2018-10-02 16:33:19 +02:00
state . new_contract ( & params . address , val . saturating_add ( prev_bal ) , nonce_offset ) ? ;
} else {
state . new_contract ( & params . address , prev_bal , nonce_offset ) ? ;
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
Ok ( ( ) )
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
fn enact_result < B : ' a + StateBackend > (
result : & vm ::Result < FinalizationResult > ,
state : & mut State < B > ,
substate : & mut Substate ,
un_substate : Substate ,
) {
match * result {
Err ( vm ::Error ::OutOfGas )
| Err ( vm ::Error ::BadJumpDestination { .. } )
| Err ( vm ::Error ::BadInstruction { .. } )
| Err ( vm ::Error ::StackUnderflow { .. } )
| Err ( vm ::Error ::BuiltIn { .. } )
| Err ( vm ::Error ::Wasm { .. } )
| Err ( vm ::Error ::OutOfStack { .. } )
| Err ( vm ::Error ::MutableCallInStaticContext )
| Err ( vm ::Error ::OutOfBounds )
| Err ( vm ::Error ::Reverted )
2020-08-07 19:41:07 +02:00
| Err ( vm ::Error ::SubStackUnderflow { .. } )
| Err ( vm ::Error ::OutOfSubStack { .. } )
| Err ( vm ::Error ::InvalidSubEntry )
2018-10-02 16:33:19 +02:00
| Ok ( FinalizationResult {
apply_state : false , ..
} ) = > {
2020-09-10 08:04:14 +02:00
if let Some ( addr ) = UNPRUNABLE_PRECOMPILE_ADDRESS {
if un_substate . touched . contains ( & addr ) {
substate . touched . insert ( addr ) ;
}
}
2018-10-02 16:33:19 +02:00
state . revert_to_checkpoint ( ) ;
2020-11-04 19:11:05 +01:00
un_substate . access_list . rollback ( ) ;
2018-10-02 16:33:19 +02:00
}
Ok ( _ ) | Err ( vm ::Error ::Internal ( _ ) ) = > {
state . discard_checkpoint ( ) ;
substate . accrue ( un_substate ) ;
}
2020-08-05 06:08:03 +02:00
}
}
2018-10-02 16:33:19 +02:00
/// Creates `Externalities` from `Executive`.
fn as_externalities < ' any , B : ' any + StateBackend , T , V > (
state : & ' any mut State < B > ,
info : & ' any EnvInfo ,
machine : & ' any Machine ,
schedule : & ' any Schedule ,
depth : usize ,
stack_depth : usize ,
static_flag : bool ,
origin_info : & ' any OriginInfo ,
substate : & ' any mut Substate ,
output : OutputPolicy ,
tracer : & ' any mut T ,
vm_tracer : & ' any mut V ,
) -> Externalities < ' any , T , V , B >
where
T : Tracer ,
V : VMTracer ,
{
Externalities ::new (
state ,
info ,
machine ,
schedule ,
depth ,
stack_depth ,
origin_info ,
substate ,
output ,
tracer ,
vm_tracer ,
static_flag ,
)
}
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
/// Execute the executive. If a sub-call/create action is required, a resume trap error is returned. The caller is
/// then expected to call `resume_call` or `resume_create` to continue the execution.
///
/// Current-level tracing is expected to be handled by caller.
pub fn exec < B : ' a + StateBackend , T : Tracer , V : VMTracer > (
mut self ,
state : & mut State < B > ,
substate : & mut Substate ,
tracer : & mut T ,
vm_tracer : & mut V ,
) -> ExecutiveTrapResult < ' a , FinalizationResult > {
match self . kind {
CallCreateExecutiveKind ::Transfer ( ref params ) = > {
assert! ( ! self . is_create ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let mut inner = | | {
Self ::check_static_flag ( params , self . static_flag , self . is_create ) ? ;
Self ::transfer_exec_balance ( params , self . schedule , state , substate ) ? ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
Ok ( FinalizationResult {
gas_left : params . gas ,
return_data : ReturnData ::empty ( ) ,
apply_state : true ,
} )
} ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
Ok ( inner ( ) )
}
CallCreateExecutiveKind ::CallBuiltin ( ref params ) = > {
assert! ( ! self . is_create ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let mut inner = | | {
let builtin = self . machine . builtin ( & params . code_address , self . info . number ) . expect ( " Builtin is_some is checked when creating this kind in new_call_raw; qed " ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
Self ::check_static_flag ( & params , self . static_flag , self . is_create ) ? ;
state . checkpoint ( ) ;
Self ::transfer_exec_balance ( & params , self . schedule , state , substate ) ? ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let default = [ ] ;
let data = if let Some ( ref d ) = params . data {
d as & [ u8 ]
} else {
& default as & [ u8 ]
} ;
2020-08-05 06:08:03 +02:00
2019-09-12 18:43:53 +02:00
// NOTE(niklasad1): block number is used by `builtin alt_bn128 ops` to enable eip1108
let cost = builtin . cost ( data , self . info . number ) ;
2018-10-02 16:33:19 +02:00
if cost < = params . gas {
let mut builtin_out_buffer = Vec ::new ( ) ;
let result = {
let mut builtin_output = BytesRef ::Flexible ( & mut builtin_out_buffer ) ;
builtin . execute ( data , & mut builtin_output )
} ;
if let Err ( e ) = result {
state . revert_to_checkpoint ( ) ;
2020-08-05 06:08:03 +02:00
2019-11-11 21:57:38 +01:00
Err ( vm ::Error ::BuiltIn ( e ) )
2018-10-02 16:33:19 +02:00
} else {
state . discard_checkpoint ( ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let out_len = builtin_out_buffer . len ( ) ;
Ok ( FinalizationResult {
gas_left : params . gas - cost ,
return_data : ReturnData ::new ( builtin_out_buffer , 0 , out_len ) ,
apply_state : true ,
} )
}
} else {
2020-09-10 08:04:14 +02:00
// We need balance > 0 in precompiles to be EIP161 compliant, see PR#11597.
// Since RIPEMD160 was removed in mainnet block #2686351, this is activated only in
// tests to check this specific irregular state transition.
if let Some ( unprunable_addr ) = UNPRUNABLE_PRECOMPILE_ADDRESS {
if unprunable_addr ! = params . code_address
& & state . balance ( & params . code_address ) ? . is_zero ( )
{
substate . touched . remove ( & params . code_address ) ;
}
}
2018-10-02 16:33:19 +02:00
// just drain the whole gas
state . revert_to_checkpoint ( ) ;
Err ( vm ::Error ::OutOfGas )
}
} ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
Ok ( inner ( ) )
}
CallCreateExecutiveKind ::ExecCall ( params , mut unconfirmed_substate ) = > {
assert! ( ! self . is_create ) ;
2020-08-05 06:08:03 +02:00
{
2018-10-02 16:33:19 +02:00
let static_flag = self . static_flag ;
let is_create = self . is_create ;
let schedule = self . schedule ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let mut pre_inner = | | {
Self ::check_static_flag ( & params , static_flag , is_create ) ? ;
state . checkpoint ( ) ;
Self ::transfer_exec_balance ( & params , schedule , state , substate ) ? ;
Ok ( ( ) )
} ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
match pre_inner ( ) {
Ok ( ( ) ) = > ( ) ,
Err ( err ) = > return Ok ( Err ( err ) ) ,
2020-08-05 06:08:03 +02:00
}
}
2018-10-02 16:33:19 +02:00
let origin_info = OriginInfo ::from ( & params ) ;
let exec = self . factory . create ( params , self . schedule , self . depth ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let out = {
let mut ext = Self ::as_externalities (
2020-08-05 06:08:03 +02:00
state ,
2018-10-02 16:33:19 +02:00
self . info ,
self . machine ,
self . schedule ,
self . depth ,
self . stack_depth ,
self . static_flag ,
& origin_info ,
& mut unconfirmed_substate ,
OutputPolicy ::Return ,
tracer ,
vm_tracer ,
) ;
match exec . exec ( & mut ext ) {
Ok ( val ) = > Ok ( val . finalize ( ext ) ) ,
Err ( err ) = > Err ( err ) ,
}
} ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let res = match out {
Ok ( val ) = > val ,
Err ( TrapError ::Call ( subparams , resume ) ) = > {
self . kind = CallCreateExecutiveKind ::ResumeCall (
origin_info ,
resume ,
unconfirmed_substate ,
2020-08-05 06:08:03 +02:00
) ;
2018-10-02 16:33:19 +02:00
return Err ( TrapError ::Call ( subparams , self ) ) ;
}
Err ( TrapError ::Create ( subparams , address , resume ) ) = > {
self . kind = CallCreateExecutiveKind ::ResumeCreate (
origin_info ,
resume ,
unconfirmed_substate ,
) ;
return Err ( TrapError ::Create ( subparams , address , self ) ) ;
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
} ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
Self ::enact_result ( & res , state , substate , unconfirmed_substate ) ;
2020-08-05 06:08:03 +02:00
Ok ( res )
}
2018-10-02 16:33:19 +02:00
CallCreateExecutiveKind ::ExecCreate ( params , mut unconfirmed_substate ) = > {
assert! ( self . is_create ) ;
2020-08-05 06:08:03 +02:00
{
2018-10-02 16:33:19 +02:00
let static_flag = self . static_flag ;
let is_create = self . is_create ;
let schedule = self . schedule ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let mut pre_inner = | | {
Self ::check_eip684 ( & params , state ) ? ;
Self ::check_static_flag ( & params , static_flag , is_create ) ? ;
state . checkpoint ( ) ;
Self ::transfer_exec_balance_and_init_contract (
& params , schedule , state , substate ,
2020-08-05 06:08:03 +02:00
) ? ;
2018-10-02 16:33:19 +02:00
Ok ( ( ) )
} ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
match pre_inner ( ) {
Ok ( ( ) ) = > ( ) ,
Err ( err ) = > return Ok ( Err ( err ) ) ,
2020-08-05 06:08:03 +02:00
}
}
2018-10-02 16:33:19 +02:00
let origin_info = OriginInfo ::from ( & params ) ;
let exec = self . factory . create ( params , self . schedule , self . depth ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let out = {
let mut ext = Self ::as_externalities (
2020-08-05 06:08:03 +02:00
state ,
2018-10-02 16:33:19 +02:00
self . info ,
self . machine ,
self . schedule ,
self . depth ,
self . stack_depth ,
self . static_flag ,
& origin_info ,
& mut unconfirmed_substate ,
OutputPolicy ::InitContract ,
tracer ,
vm_tracer ,
) ;
match exec . exec ( & mut ext ) {
Ok ( val ) = > Ok ( val . finalize ( ext ) ) ,
Err ( err ) = > Err ( err ) ,
2020-08-05 06:08:03 +02:00
}
} ;
2018-10-02 16:33:19 +02:00
let res = match out {
Ok ( val ) = > val ,
Err ( TrapError ::Call ( subparams , resume ) ) = > {
self . kind = CallCreateExecutiveKind ::ResumeCall (
origin_info ,
2020-08-05 06:08:03 +02:00
resume ,
2018-10-02 16:33:19 +02:00
unconfirmed_substate ,
2020-08-05 06:08:03 +02:00
) ;
2018-10-02 16:33:19 +02:00
return Err ( TrapError ::Call ( subparams , self ) ) ;
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
Err ( TrapError ::Create ( subparams , address , resume ) ) = > {
self . kind = CallCreateExecutiveKind ::ResumeCreate (
origin_info ,
2020-08-05 06:08:03 +02:00
resume ,
2018-10-02 16:33:19 +02:00
unconfirmed_substate ,
2020-08-05 06:08:03 +02:00
) ;
2018-10-02 16:33:19 +02:00
return Err ( TrapError ::Create ( subparams , address , self ) ) ;
2020-08-05 06:08:03 +02:00
}
} ;
2018-10-02 16:33:19 +02:00
Self ::enact_result ( & res , state , substate , unconfirmed_substate ) ;
2020-08-05 06:08:03 +02:00
Ok ( res )
}
2018-10-02 16:33:19 +02:00
CallCreateExecutiveKind ::ResumeCall ( .. ) | CallCreateExecutiveKind ::ResumeCreate ( .. ) = > {
panic! ( " This executive has already been executed once. " )
2020-08-05 06:08:03 +02:00
}
}
}
2018-10-02 16:33:19 +02:00
/// Resume execution from a call trap previsouly trapped by `exec`.
2020-08-05 06:08:03 +02:00
///
2018-10-02 16:33:19 +02:00
/// Current-level tracing is expected to be handled by caller.
pub fn resume_call < B : ' a + StateBackend , T : Tracer , V : VMTracer > (
mut self ,
result : vm ::MessageCallResult ,
state : & mut State < B > ,
substate : & mut Substate ,
tracer : & mut T ,
vm_tracer : & mut V ,
) -> ExecutiveTrapResult < ' a , FinalizationResult > {
match self . kind {
CallCreateExecutiveKind ::ResumeCall ( origin_info , resume , mut unconfirmed_substate ) = > {
let out = {
let exec = resume . resume_call ( result ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let mut ext = Self ::as_externalities (
state ,
self . info ,
self . machine ,
self . schedule ,
self . depth ,
self . stack_depth ,
self . static_flag ,
& origin_info ,
& mut unconfirmed_substate ,
if self . is_create {
OutputPolicy ::InitContract
} else {
OutputPolicy ::Return
} ,
tracer ,
vm_tracer ,
) ;
match exec . exec ( & mut ext ) {
Ok ( val ) = > Ok ( val . finalize ( ext ) ) ,
Err ( err ) = > Err ( err ) ,
}
} ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let res = match out {
Ok ( val ) = > val ,
Err ( TrapError ::Call ( subparams , resume ) ) = > {
self . kind = CallCreateExecutiveKind ::ResumeCall (
origin_info ,
resume ,
unconfirmed_substate ,
) ;
return Err ( TrapError ::Call ( subparams , self ) ) ;
}
Err ( TrapError ::Create ( subparams , address , resume ) ) = > {
self . kind = CallCreateExecutiveKind ::ResumeCreate (
origin_info ,
resume ,
unconfirmed_substate ,
) ;
return Err ( TrapError ::Create ( subparams , address , self ) ) ;
}
} ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
Self ::enact_result ( & res , state , substate , unconfirmed_substate ) ;
Ok ( res )
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
CallCreateExecutiveKind ::ResumeCreate ( .. ) = > {
panic! ( " Resumable as create, but called resume_call " )
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
CallCreateExecutiveKind ::Transfer ( .. )
| CallCreateExecutiveKind ::CallBuiltin ( .. )
| CallCreateExecutiveKind ::ExecCall ( .. )
| CallCreateExecutiveKind ::ExecCreate ( .. ) = > panic! ( " Not resumable " ) ,
2020-08-05 06:08:03 +02:00
}
}
2018-10-02 16:33:19 +02:00
/// Resume execution from a create trap previsouly trapped by `exec`.
2020-08-05 06:08:03 +02:00
///
2018-10-02 16:33:19 +02:00
/// Current-level tracing is expected to be handled by caller.
pub fn resume_create < B : ' a + StateBackend , T : Tracer , V : VMTracer > (
mut self ,
result : vm ::ContractCreateResult ,
state : & mut State < B > ,
substate : & mut Substate ,
tracer : & mut T ,
vm_tracer : & mut V ,
) -> ExecutiveTrapResult < ' a , FinalizationResult > {
match self . kind {
CallCreateExecutiveKind ::ResumeCreate (
origin_info ,
resume ,
mut unconfirmed_substate ,
) = > {
let out = {
let exec = resume . resume_create ( result ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let mut ext = Self ::as_externalities (
state ,
self . info ,
self . machine ,
self . schedule ,
self . depth ,
self . stack_depth ,
self . static_flag ,
& origin_info ,
& mut unconfirmed_substate ,
if self . is_create {
OutputPolicy ::InitContract
} else {
OutputPolicy ::Return
} ,
tracer ,
vm_tracer ,
) ;
match exec . exec ( & mut ext ) {
Ok ( val ) = > Ok ( val . finalize ( ext ) ) ,
Err ( err ) = > Err ( err ) ,
}
} ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let res = match out {
Ok ( val ) = > val ,
Err ( TrapError ::Call ( subparams , resume ) ) = > {
self . kind = CallCreateExecutiveKind ::ResumeCall (
origin_info ,
resume ,
unconfirmed_substate ,
) ;
return Err ( TrapError ::Call ( subparams , self ) ) ;
}
Err ( TrapError ::Create ( subparams , address , resume ) ) = > {
self . kind = CallCreateExecutiveKind ::ResumeCreate (
origin_info ,
resume ,
unconfirmed_substate ,
) ;
return Err ( TrapError ::Create ( subparams , address , self ) ) ;
}
} ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
Self ::enact_result ( & res , state , substate , unconfirmed_substate ) ;
Ok ( res )
}
CallCreateExecutiveKind ::ResumeCall ( .. ) = > {
panic! ( " Resumable as call, but called resume_create " )
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
CallCreateExecutiveKind ::Transfer ( .. )
| CallCreateExecutiveKind ::CallBuiltin ( .. )
| CallCreateExecutiveKind ::ExecCall ( .. )
| CallCreateExecutiveKind ::ExecCreate ( .. ) = > panic! ( " Not resumable " ) ,
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
}
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
/// Execute and consume the current executive. This function handles resume traps and sub-level tracing. The caller is expected to handle current-level tracing.
pub fn consume < B : ' a + StateBackend , T : Tracer , V : VMTracer > (
self ,
state : & mut State < B > ,
top_substate : & mut Substate ,
tracer : & mut T ,
vm_tracer : & mut V ,
) -> vm ::Result < FinalizationResult > {
let mut last_res = Some ( (
false ,
self . gas ,
self . exec ( state , top_substate , tracer , vm_tracer ) ,
) ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let mut callstack : Vec < ( Option < Address > , CallCreateExecutive < ' a > ) > = Vec ::new ( ) ;
loop {
match last_res {
None = > {
match callstack . pop ( ) {
Some ( ( _ , exec ) ) = > {
let second_last = callstack . last_mut ( ) ;
let parent_substate = match second_last {
Some ( ( _ , ref mut second_last ) ) = > second_last . unconfirmed_substate ( ) . expect ( " Current stack value is created from second last item; second last item must be call or create; qed " ) ,
None = > top_substate ,
} ;
last_res = Some ( ( exec . is_create , exec . gas , exec . exec ( state , parent_substate , tracer , vm_tracer ) ) ) ;
} ,
None = > panic! ( " When callstack only had one item and it was executed, this function would return; callstack never reaches zero item; qed " ) ,
}
} ,
Some ( ( is_create , gas , Ok ( val ) ) ) = > {
let current = callstack . pop ( ) ;
match current {
Some ( ( address , mut exec ) ) = > {
if is_create {
let address = address . expect ( " If the last executed status was from a create executive, then the destination address was pushed to the callstack; address is_some if it is_create; qed " ) ;
match val {
Ok ( ref val ) if val . apply_state = > {
tracer . done_trace_create (
gas - val . gas_left ,
& val . return_data ,
address
) ;
} ,
Ok ( _ ) = > {
tracer . done_trace_failed ( & vm ::Error ::Reverted ) ;
} ,
Err ( ref err ) = > {
tracer . done_trace_failed ( err ) ;
} ,
}
vm_tracer . done_subtrace ( ) ;
let second_last = callstack . last_mut ( ) ;
let parent_substate = match second_last {
Some ( ( _ , ref mut second_last ) ) = > second_last . unconfirmed_substate ( ) . expect ( " Current stack value is created from second last item; second last item must be call or create; qed " ) ,
None = > top_substate ,
} ;
let contract_create_result = into_contract_create_result ( val , & address , exec . unconfirmed_substate ( ) . expect ( " Executive is resumed from a create; it has an unconfirmed substate; qed " ) ) ;
last_res = Some ( ( exec . is_create , exec . gas , exec . resume_create (
contract_create_result ,
state ,
parent_substate ,
tracer ,
vm_tracer
) ) ) ;
} else {
match val {
Ok ( ref val ) if val . apply_state = > {
tracer . done_trace_call (
gas - val . gas_left ,
& val . return_data ,
) ;
} ,
Ok ( _ ) = > {
tracer . done_trace_failed ( & vm ::Error ::Reverted ) ;
} ,
Err ( ref err ) = > {
tracer . done_trace_failed ( err ) ;
} ,
}
vm_tracer . done_subtrace ( ) ;
let second_last = callstack . last_mut ( ) ;
let parent_substate = match second_last {
Some ( ( _ , ref mut second_last ) ) = > second_last . unconfirmed_substate ( ) . expect ( " Current stack value is created from second last item; second last item must be call or create; qed " ) ,
None = > top_substate ,
} ;
last_res = Some ( ( exec . is_create , exec . gas , exec . resume_call (
into_message_call_result ( val ) ,
state ,
parent_substate ,
tracer ,
vm_tracer
) ) ) ;
}
} ,
None = > return val ,
}
} ,
Some ( ( _ , _ , Err ( TrapError ::Call ( subparams , resume ) ) ) ) = > {
tracer . prepare_trace_call ( & subparams , resume . depth + 1 , resume . machine . builtin ( & subparams . address , resume . info . number ) . is_some ( ) ) ;
vm_tracer . prepare_subtrace ( subparams . code . as_ref ( ) . map_or_else ( | | & [ ] as & [ u8 ] , | d | & * d as & [ u8 ] ) ) ;
let sub_exec = CallCreateExecutive ::new_call_raw (
subparams ,
resume . info ,
resume . machine ,
resume . schedule ,
resume . factory ,
resume . depth + 1 ,
resume . stack_depth ,
resume . static_flag ,
) ;
callstack . push ( ( None , resume ) ) ;
callstack . push ( ( None , sub_exec ) ) ;
last_res = None ;
} ,
Some ( ( _ , _ , Err ( TrapError ::Create ( subparams , address , resume ) ) ) ) = > {
tracer . prepare_trace_create ( & subparams ) ;
vm_tracer . prepare_subtrace ( subparams . code . as_ref ( ) . map_or_else ( | | & [ ] as & [ u8 ] , | d | & * d as & [ u8 ] ) ) ;
let sub_exec = CallCreateExecutive ::new_create_raw (
subparams ,
resume . info ,
resume . machine ,
resume . schedule ,
resume . factory ,
resume . depth + 1 ,
resume . stack_depth ,
resume . static_flag
) ;
callstack . push ( ( Some ( address ) , resume ) ) ;
callstack . push ( ( None , sub_exec ) ) ;
last_res = None ;
} ,
}
}
}
}
2016-01-11 19:25:37 +01:00
/// Transaction executor.
2018-07-09 13:55:27 +02:00
pub struct Executive < ' a , B : ' a > {
2017-02-21 12:35:21 +01:00
state : & ' a mut State < B > ,
2016-01-07 19:05:44 +01:00
info : & ' a EnvInfo ,
2017-09-26 14:19:08 +02:00
machine : & ' a Machine ,
2018-07-23 15:48:01 +02:00
schedule : & ' a Schedule ,
2016-03-18 23:49:12 +01:00
depth : usize ,
2017-06-19 11:41:46 +02:00
static_flag : bool ,
2016-01-07 19:05:44 +01:00
}
2017-09-26 14:19:08 +02:00
impl < ' a , B : ' a + StateBackend > Executive < ' a , B > {
2016-01-11 19:25:37 +01:00
/// Basic constructor.
2018-07-23 15:48:01 +02:00
pub fn new (
state : & ' a mut State < B > ,
info : & ' a EnvInfo ,
machine : & ' a Machine ,
schedule : & ' a Schedule ,
) -> Self {
2016-03-19 12:54:34 +01:00
Executive {
state : state ,
info : info ,
2017-09-26 14:19:08 +02:00
machine : machine ,
2018-07-23 15:48:01 +02:00
schedule : schedule ,
2016-03-19 12:54:34 +01:00
depth : 0 ,
2017-06-19 11:41:46 +02:00
static_flag : false ,
2016-01-09 17:55:47 +01:00
}
2020-08-05 06:08:03 +02:00
}
2016-01-11 14:08:03 +01:00
/// Populates executive from parent properties. Increments executive depth.
2018-07-23 15:48:01 +02:00
pub fn from_parent (
state : & ' a mut State < B > ,
info : & ' a EnvInfo ,
machine : & ' a Machine ,
schedule : & ' a Schedule ,
parent_depth : usize ,
static_flag : bool ,
) -> Self {
2016-01-07 19:05:44 +01:00
Executive {
state : state ,
info : info ,
2017-09-26 14:19:08 +02:00
machine : machine ,
2018-07-23 15:48:01 +02:00
schedule : schedule ,
2016-03-19 12:54:34 +01:00
depth : parent_depth + 1 ,
2017-06-19 11:41:46 +02:00
static_flag : static_flag ,
2016-01-07 19:05:44 +01:00
}
2020-08-05 06:08:03 +02:00
}
2016-04-28 21:47:44 +02:00
/// This function should be used to execute transaction.
2017-08-28 14:25:16 +02:00
pub fn transact < T , V > (
& ' a mut self ,
t : & SignedTransaction ,
options : TransactOptions < T , V > ,
2017-10-20 15:40:25 +02:00
) -> Result < Executed < T ::Output , V ::Output > , ExecutionError >
where
T : Tracer ,
V : VMTracer ,
2017-08-28 14:25:16 +02:00
{
2017-09-05 13:22:19 +02:00
self . transact_with_tracer (
t ,
options . check_nonce ,
options . output_from_init_contract ,
options . tracer ,
options . vm_tracer ,
2020-08-05 06:08:03 +02:00
)
2016-04-08 01:50:55 +02:00
}
2020-08-05 06:08:03 +02:00
2017-05-17 12:41:33 +02:00
/// Execute a transaction in a "virtual" context.
/// This will ensure the caller has enough balance to execute the desired transaction.
/// Used for extra-block executions for things like consensus contracts and RPCs
2017-08-28 14:25:16 +02:00
pub fn transact_virtual < T , V > (
2016-06-02 12:40:31 +02:00
& ' a mut self ,
t : & SignedTransaction ,
options : TransactOptions < T , V > ,
2017-10-20 15:40:25 +02:00
) -> Result < Executed < T ::Output , V ::Output > , ExecutionError >
where
T : Tracer ,
V : VMTracer ,
{
2017-01-13 09:51:36 +01:00
let sender = t . sender ( ) ;
2017-02-26 13:10:50 +01:00
let balance = self . state . balance ( & sender ) ? ;
2018-07-23 15:48:01 +02:00
let needed_balance = t . value . saturating_add ( t . gas . saturating_mul ( t . gas_price ) ) ;
2017-05-17 12:41:33 +02:00
if balance < needed_balance {
2018-07-23 15:48:01 +02:00
// give the sender a sufficient balance
2017-06-28 09:10:57 +02:00
self . state
2017-05-17 12:41:33 +02:00
. add_balance ( & sender , & ( needed_balance - balance ) , CleanupMode ::NoEmpty ) ? ;
2020-08-05 06:08:03 +02:00
}
2017-05-17 12:41:33 +02:00
self . transact ( t , options )
2020-08-05 06:08:03 +02:00
}
2018-07-23 15:48:01 +02:00
/// Execute transaction/call with tracing enabled
2017-08-28 14:25:16 +02:00
fn transact_with_tracer < T , V > (
& ' a mut self ,
t : & SignedTransaction ,
2018-07-23 15:48:01 +02:00
check_nonce : bool ,
2017-09-05 13:22:19 +02:00
output_from_create : bool ,
2018-10-02 16:33:19 +02:00
mut tracer : T ,
2016-06-02 12:40:31 +02:00
mut vm_tracer : V ,
2018-07-23 15:48:01 +02:00
) -> Result < Executed < T ::Output , V ::Output > , ExecutionError >
2020-08-05 06:08:03 +02:00
where
2017-10-20 15:40:25 +02:00
T : Tracer ,
V : VMTracer ,
2020-08-05 06:08:03 +02:00
{
2017-01-13 09:51:36 +01:00
let sender = t . sender ( ) ;
2018-07-23 15:48:01 +02:00
let nonce = self . state . nonce ( & sender ) ? ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let schedule = self . schedule ;
2016-01-15 13:07:44 +01:00
let base_gas_required = U256 ::from ( t . gas_required ( & schedule ) ) ;
2020-08-05 06:08:03 +02:00
2016-01-15 13:07:44 +01:00
if t . gas < base_gas_required {
2018-04-19 13:16:04 +02:00
return Err ( ExecutionError ::NotEnoughBaseGas {
required : base_gas_required ,
2016-01-15 13:07:44 +01:00
got : t . gas ,
} ) ;
2020-08-05 06:08:03 +02:00
}
2016-04-12 13:54:34 +02:00
if ! t . is_unsigned ( )
& & check_nonce
& & schedule . kill_dust ! = CleanDustMode ::Off
2017-06-28 09:10:57 +02:00
& & ! self . state . exists ( & sender ) ?
2018-04-19 13:16:04 +02:00
{
return Err ( ExecutionError ::SenderMustExist ) ;
2016-01-10 12:29:35 +01:00
}
2020-08-05 06:08:03 +02:00
2016-01-11 02:17:29 +01:00
let init_gas = t . gas - base_gas_required ;
2020-08-05 06:08:03 +02:00
2016-01-11 02:17:29 +01:00
// validate transaction nonce
2016-01-11 02:42:02 +01:00
if check_nonce & & t . nonce ! = nonce {
2018-04-19 13:16:04 +02:00
return Err ( ExecutionError ::InvalidNonce {
2016-02-09 16:31:57 +01:00
expected : nonce ,
got : t . nonce ,
2020-08-05 06:08:03 +02:00
} ) ;
}
2016-11-03 22:22:25 +01:00
// validate if transaction fits into given block
2016-02-09 16:31:57 +01:00
if self . info . gas_used + t . gas > self . info . gas_limit {
2016-01-10 12:29:35 +01:00
return Err ( ExecutionError ::BlockGasLimitReached {
gas_limit : self . info . gas_limit ,
2017-02-26 13:10:50 +01:00
gas_used : self . info . gas_used ,
2016-10-06 18:42:54 +02:00
gas : t . gas ,
} ) ;
2020-08-05 06:08:03 +02:00
}
2016-10-06 18:42:54 +02:00
// TODO: we might need bigints here, or at least check overflows.
let balance = self . state . balance ( & sender ) ? ;
2016-01-12 17:40:34 +01:00
let gas_cost = t . gas . full_mul ( t . gas_price ) ;
let total_cost = U512 ::from ( t . value ) + gas_cost ;
2020-08-05 06:08:03 +02:00
2016-01-10 12:29:35 +01:00
// avoid unaffordable transactions
2016-10-06 18:42:54 +02:00
let balance512 = U512 ::from ( balance ) ;
if balance512 < total_cost {
2018-04-19 13:16:04 +02:00
return Err ( ExecutionError ::NotEnoughCash {
required : total_cost ,
got : balance512 ,
2017-06-28 09:10:57 +02:00
} ) ;
2020-08-05 06:08:03 +02:00
}
2020-11-04 19:11:05 +01:00
let mut access_list = AccessList ::new ( schedule . eip2929 ) ;
if schedule . eip2929 {
for ( address , _ ) in self . machine . builtins ( ) {
access_list . insert_address ( * address ) ;
}
}
let mut substate = Substate ::from_access_list ( & access_list ) ;
2020-08-05 06:08:03 +02:00
2016-01-11 02:17:29 +01:00
// NOTE: there can be no invalid transactions from this point.
2018-08-31 17:43:51 +02:00
if ! schedule . keep_unsigned_nonce | | ! t . is_unsigned ( ) {
2017-04-19 14:30:00 +02:00
self . state . inc_nonce ( & sender ) ? ;
}
2017-06-28 09:10:57 +02:00
self . state . sub_balance (
& sender ,
2017-09-26 14:19:08 +02:00
& U256 ::from ( gas_cost ) ,
& mut substate . to_cleanup_mode ( & schedule ) ,
) ? ;
2020-08-05 06:08:03 +02:00
2017-09-26 14:19:08 +02:00
let ( result , output ) = match t . action {
2016-01-11 16:33:08 +01:00
Action ::Create = > {
2016-01-15 15:00:28 +01:00
let ( new_address , code_hash ) = contract_address (
2018-08-13 23:27:13 +02:00
self . machine . create_address_scheme ( self . info . number ) ,
& sender ,
& nonce ,
& t . data ,
) ;
let params = ActionParams {
2018-05-09 08:48:55 +02:00
code_address : new_address . clone ( ) ,
2017-04-19 14:30:00 +02:00
code_hash : code_hash ,
2018-08-13 23:27:13 +02:00
address : new_address ,
sender : sender . clone ( ) ,
2016-01-09 17:55:47 +01:00
origin : sender . clone ( ) ,
2016-01-14 01:18:44 +01:00
gas : init_gas ,
2018-08-13 23:27:13 +02:00
gas_price : t . gas_price ,
value : ActionValue ::Transfer ( t . value ) ,
2016-10-02 18:45:36 +02:00
code : Some ( Arc ::new ( t . data . clone ( ) ) ) ,
2016-01-15 15:00:28 +01:00
data : None ,
2016-07-27 17:41:21 +02:00
call_type : CallType ::None ,
2018-08-13 23:27:13 +02:00
params_type : vm ::ParamsType ::Embedded ,
2020-11-04 19:11:05 +01:00
access_list : access_list ,
2020-08-05 06:08:03 +02:00
} ;
2018-08-13 23:27:13 +02:00
let res = self . create ( params , & mut substate , & mut tracer , & mut vm_tracer ) ;
let out = match & res {
Ok ( res ) if output_from_create = > res . return_data . to_vec ( ) ,
_ = > Vec ::new ( ) ,
} ;
( res , out )
2016-01-09 00:51:09 +01:00
}
2016-01-17 15:56:09 +01:00
Action ::Call ( ref address ) = > {
2016-01-11 16:33:08 +01:00
let params = ActionParams {
2016-01-15 15:00:28 +01:00
code_address : address . clone ( ) ,
2016-01-11 15:23:27 +01:00
address : address . clone ( ) ,
2016-01-09 17:55:47 +01:00
sender : sender . clone ( ) ,
origin : sender . clone ( ) ,
2016-01-14 01:18:44 +01:00
gas : init_gas ,
2016-01-09 17:55:47 +01:00
gas_price : t . gas_price ,
2016-01-20 17:27:33 +01:00
value : ActionValue ::Transfer ( t . value ) ,
2017-02-26 13:10:50 +01:00
code : self . state . code ( address ) ? ,
2018-07-31 07:27:57 +02:00
code_hash : self . state . code_hash ( address ) ? ,
2016-01-15 15:00:28 +01:00
data : Some ( t . data . clone ( ) ) ,
2016-07-27 17:41:21 +02:00
call_type : CallType ::Call ,
2017-11-02 12:49:57 +01:00
params_type : vm ::ParamsType ::Separate ,
2020-11-04 19:11:05 +01:00
access_list : access_list ,
2016-01-09 17:55:47 +01:00
} ;
2018-08-13 23:27:13 +02:00
let res = self . call ( params , & mut substate , & mut tracer , & mut vm_tracer ) ;
let out = match & res {
Ok ( res ) = > res . return_data . to_vec ( ) ,
_ = > Vec ::new ( ) ,
} ;
( res , out )
2016-01-09 17:55:47 +01:00
}
2016-01-09 21:39:38 +01:00
} ;
2020-08-05 06:08:03 +02:00
2016-01-09 21:39:38 +01:00
// finalize here!
2017-08-28 14:25:16 +02:00
Ok ( self . finalize (
t ,
substate ,
result ,
output ,
tracer . drain ( ) ,
vm_tracer . drain ( ) ,
) ? )
2016-01-07 19:05:44 +01:00
}
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
/// Calls contract function with given contract params and stack depth.
/// NOTE. It does not finalize the transaction (doesn't do refunds, nor suicides).
/// Modifies the substate and the output.
/// Returns either gas_left or `vm::Error`.
pub fn call_with_stack_depth < T , V > (
2016-06-02 12:40:31 +02:00
& mut self ,
params : ActionParams ,
2018-10-02 16:33:19 +02:00
substate : & mut Substate ,
stack_depth : usize ,
2016-06-02 12:40:31 +02:00
tracer : & mut T ,
vm_tracer : & mut V ,
2017-08-01 12:37:57 +02:00
) -> vm ::Result < FinalizationResult >
where
T : Tracer ,
V : VMTracer ,
{
2018-10-02 16:33:19 +02:00
tracer . prepare_trace_call (
& params ,
self . depth ,
self . machine
. builtin ( & params . address , self . info . number )
. is_some ( ) ,
) ;
vm_tracer . prepare_subtrace (
2020-08-05 06:08:03 +02:00
params
2018-10-02 16:33:19 +02:00
. code
2020-08-05 06:08:03 +02:00
. as_ref ( )
2018-10-02 16:33:19 +02:00
. map_or_else ( | | & [ ] as & [ u8 ] , | d | & * d as & [ u8 ] ) ,
) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let gas = params . gas ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let vm_factory = self . state . vm_factory ( ) ;
let result = CallCreateExecutive ::new_call_raw (
2020-08-05 06:08:03 +02:00
params ,
2018-10-02 16:33:19 +02:00
self . info ,
self . machine ,
2017-06-28 09:10:57 +02:00
self . schedule ,
2018-10-02 16:33:19 +02:00
& vm_factory ,
self . depth ,
stack_depth ,
self . static_flag ,
)
. consume ( self . state , substate , tracer , vm_tracer ) ;
2020-08-05 06:08:03 +02:00
2016-02-09 16:31:57 +01:00
match result {
2018-10-02 16:33:19 +02:00
Ok ( ref val ) if val . apply_state = > {
tracer . done_trace_call ( gas - val . gas_left , & val . return_data ) ;
}
Ok ( _ ) = > {
tracer . done_trace_failed ( & vm ::Error ::Reverted ) ;
}
Err ( ref err ) = > {
tracer . done_trace_failed ( err ) ;
2016-01-26 10:15:55 +01:00
}
2020-08-05 06:08:03 +02:00
}
2018-10-02 16:33:19 +02:00
vm_tracer . done_subtrace ( ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
result
}
2020-08-05 06:08:03 +02:00
2016-01-09 21:39:38 +01:00
/// Calls contract function with given contract params.
2016-06-02 12:40:31 +02:00
pub fn call < T , V > (
& mut self ,
params : ActionParams ,
substate : & mut Substate ,
tracer : & mut T ,
vm_tracer : & mut V ,
2017-09-15 21:07:54 +02:00
) -> vm ::Result < FinalizationResult >
where
T : Tracer ,
V : VMTracer ,
{
2018-10-02 16:33:19 +02:00
self . call_with_stack_depth ( params , substate , 0 , tracer , vm_tracer )
}
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
/// Creates contract with given contract params and stack depth.
/// NOTE. It does not finalize the transaction (doesn't do refunds, nor suicides).
/// Modifies the substate.
pub fn create_with_stack_depth < T , V > (
& mut self ,
params : ActionParams ,
substate : & mut Substate ,
stack_depth : usize ,
tracer : & mut T ,
vm_tracer : & mut V ,
) -> vm ::Result < FinalizationResult >
where
T : Tracer ,
V : VMTracer ,
{
tracer . prepare_trace_create ( & params ) ;
vm_tracer . prepare_subtrace (
params
. code
. as_ref ( )
. map_or_else ( | | & [ ] as & [ u8 ] , | d | & * d as & [ u8 ] ) ,
) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let address = params . address ;
let gas = params . gas ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
let vm_factory = self . state . vm_factory ( ) ;
let result = CallCreateExecutive ::new_create_raw (
params ,
self . info ,
self . machine ,
self . schedule ,
& vm_factory ,
self . depth ,
stack_depth ,
self . static_flag ,
)
. consume ( self . state , substate , tracer , vm_tracer ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
match result {
Ok ( ref val ) if val . apply_state = > {
tracer . done_trace_create ( gas - val . gas_left , & val . return_data , address ) ;
}
Ok ( _ ) = > {
tracer . done_trace_failed ( & vm ::Error ::Reverted ) ;
}
Err ( ref err ) = > {
tracer . done_trace_failed ( err ) ;
}
2016-01-20 16:52:22 +01:00
}
2018-10-02 16:33:19 +02:00
vm_tracer . done_subtrace ( ) ;
2020-08-05 06:08:03 +02:00
2018-10-02 16:33:19 +02:00
result
}
2020-08-05 06:08:03 +02:00
2016-01-09 21:39:38 +01:00
/// Creates contract with given contract params.
2016-06-02 12:40:31 +02:00
pub fn create < T , V > (
& mut self ,
params : ActionParams ,
substate : & mut Substate ,
tracer : & mut T ,
2017-04-19 14:30:00 +02:00
vm_tracer : & mut V ,
2017-09-15 21:07:54 +02:00
) -> vm ::Result < FinalizationResult >
where
T : Tracer ,
V : VMTracer ,
{
2018-10-02 16:33:19 +02:00
self . create_with_stack_depth ( params , substate , 0 , tracer , vm_tracer )
2016-01-07 19:05:44 +01:00
}
2020-08-05 06:08:03 +02:00
2016-01-09 22:54:16 +01:00
/// Finalizes the transaction (does refunds and suicides).
2017-10-20 15:40:25 +02:00
fn finalize < T , V > (
2016-06-02 12:40:31 +02:00
& mut self ,
t : & SignedTransaction ,
2016-11-03 22:22:25 +01:00
mut substate : Substate ,
2017-09-15 21:07:54 +02:00
result : vm ::Result < FinalizationResult > ,
2016-06-02 12:40:31 +02:00
output : Bytes ,
2017-10-20 15:40:25 +02:00
trace : Vec < T > ,
vm_trace : Option < V > ,
) -> Result < Executed < T , V > , ExecutionError > {
2018-07-23 15:48:01 +02:00
let schedule = self . schedule ;
2020-08-05 06:08:03 +02:00
2016-01-15 00:36:58 +01:00
// refunds from SSTORE nonzero -> zero
2018-10-15 11:09:55 +02:00
assert! (
substate . sstore_clears_refund > = 0 ,
" On transaction level, sstore clears refund cannot go below zero. "
) ;
let sstore_refunds = U256 ::from ( substate . sstore_clears_refund as u64 ) ;
2016-01-15 00:36:58 +01:00
// refunds from contract suicides
let suicide_refunds =
U256 ::from ( schedule . suicide_refund_gas ) * U256 ::from ( substate . suicides . len ( ) ) ;
2016-01-15 18:56:28 +01:00
let refunds_bound = sstore_refunds + suicide_refunds ;
2020-08-05 06:08:03 +02:00
2016-01-15 00:36:58 +01:00
// real ammount to refund
2017-09-15 21:07:54 +02:00
let gas_left_prerefund = match result {
Ok ( FinalizationResult { gas_left , .. } ) = > gas_left ,
_ = > 0. into ( ) ,
} ;
2016-10-06 18:42:54 +02:00
let refunded = cmp ::min ( refunds_bound , ( t . gas - gas_left_prerefund ) > > 1 ) ;
2016-01-15 18:56:28 +01:00
let gas_left = gas_left_prerefund + refunded ;
2020-08-05 06:08:03 +02:00
2019-02-11 23:20:51 +01:00
let gas_used = t . gas . saturating_sub ( gas_left ) ;
let ( refund_value , overflow_1 ) = gas_left . overflowing_mul ( t . gas_price ) ;
let ( fees_value , overflow_2 ) = gas_used . overflowing_mul ( t . gas_price ) ;
if overflow_1 | | overflow_2 {
return Err ( ExecutionError ::TransactionMalformed (
" U256 Overflow " . to_string ( ) ,
) ) ;
}
2020-08-05 06:08:03 +02:00
2016-01-16 01:48:38 +01:00
trace! ( " exec::finalize: t.gas={}, sstore_refunds={}, suicide_refunds={}, refunds_bound={}, gas_left_prerefund={}, refunded={}, gas_left={}, gas_used={}, refund_value={}, fees_value={} \n " ,
t . gas , sstore_refunds , suicide_refunds , refunds_bound , gas_left_prerefund , refunded , gas_left , gas_used , refund_value , fees_value ) ;
2016-01-15 18:56:28 +01:00
2017-01-13 09:51:36 +01:00
let sender = t . sender ( ) ;
2016-10-20 23:41:15 +02:00
trace! (
" exec::finalize: Refunding refund_value={}, sender={} \n " ,
refund_value ,
sender
) ;
2016-11-03 22:22:25 +01:00
// Below: NoEmpty is safe since the sender must already be non-null to have sent this transaction
2017-02-26 13:10:50 +01:00
self . state
. add_balance ( & sender , & refund_value , CleanupMode ::NoEmpty ) ? ;
2016-01-16 01:48:38 +01:00
trace! (
" exec::finalize: Compensating author: fees_value={}, author={} \n " ,
fees_value ,
2017-02-26 13:10:50 +01:00
& self . info . author
) ;
self . state . add_balance (
& self . info . author ,
& fees_value ,
substate . to_cleanup_mode ( & schedule ) ,
) ? ;
2020-08-05 06:08:03 +02:00
2016-01-15 00:36:58 +01:00
// perform suicides
2016-01-17 15:56:09 +01:00
for address in & substate . suicides {
2016-01-15 00:36:58 +01:00
self . state . kill_account ( address ) ;
}
2020-08-05 06:08:03 +02:00
2016-11-03 22:22:25 +01:00
// perform garbage-collection
2019-02-11 23:20:51 +01:00
let min_balance = if schedule . kill_dust ! = CleanDustMode ::Off {
Some ( U256 ::from ( schedule . tx_gas ) . overflowing_mul ( t . gas_price ) . 0 )
} else {
None
} ;
2017-06-28 09:10:57 +02:00
self . state . kill_garbage (
& substate . touched ,
schedule . kill_empty ,
& min_balance ,
schedule . kill_dust = = CleanDustMode ::WithCodeAndStorage ,
2020-08-05 06:08:03 +02:00
) ? ;
2016-02-09 16:31:57 +01:00
match result {
2017-08-01 12:37:57 +02:00
Err ( vm ::Error ::Internal ( msg ) ) = > Err ( ExecutionError ::Internal ( msg ) ) ,
2017-01-12 11:06:12 +01:00
Err ( exception ) = > Ok ( Executed {
exception : Some ( exception ) ,
2016-01-11 17:37:22 +01:00
gas : t . gas ,
gas_used : t . gas ,
refunded : U256 ::zero ( ) ,
cumulative_gas_used : self . info . gas_used + t . gas ,
logs : vec ! [ ] ,
2016-03-18 23:49:12 +01:00
contracts_created : vec ! [ ] ,
2016-03-19 14:29:09 +01:00
output : output ,
2016-03-20 12:04:31 +01:00
trace : trace ,
2016-06-02 12:40:31 +02:00
vm_trace : vm_trace ,
2016-06-02 12:39:25 +02:00
state_diff : None ,
2016-01-11 15:55:54 +01:00
} ) ,
2016-01-11 16:05:21 +01:00
Ok ( r ) = > Ok ( Executed {
2017-09-15 21:07:54 +02:00
exception : if r . apply_state {
None
} else {
Some ( vm ::Error ::Reverted )
} ,
2016-01-11 16:05:21 +01:00
gas : t . gas ,
gas_used : gas_used ,
2016-01-15 18:56:28 +01:00
refunded : refunded ,
2016-01-11 16:05:21 +01:00
cumulative_gas_used : self . info . gas_used + gas_used ,
2016-01-11 17:37:22 +01:00
logs : substate . logs ,
2016-01-15 18:56:28 +01:00
contracts_created : substate . contracts_created ,
2016-03-19 14:29:09 +01:00
output : output ,
2016-03-20 12:04:31 +01:00
trace : trace ,
2016-06-02 12:40:31 +02:00
vm_trace : vm_trace ,
2016-06-02 12:39:25 +02:00
state_diff : None ,
2016-01-14 17:40:38 +01:00
} ) ,
2016-01-09 23:24:01 +01:00
}
2016-01-09 21:39:38 +01:00
}
2016-01-09 17:55:47 +01:00
}
2016-01-07 23:33:54 +01:00
#[ cfg(test) ]
2016-02-08 22:54:33 +01:00
#[ allow(dead_code) ]
2016-01-07 23:33:54 +01:00
mod tests {
2016-01-11 17:49:49 +01:00
use super ::* ;
2016-10-24 18:35:25 +02:00
use error ::ExecutionError ;
2018-01-10 13:35:18 +01:00
use ethereum_types ::{ Address , H256 , U256 , U512 } ;
2016-08-24 18:35:21 +02:00
use ethkey ::{ Generator , Random } ;
2017-08-01 12:37:57 +02:00
use evm ::{ Factory , VMType } ;
2017-09-26 14:19:08 +02:00
use machine ::EthereumMachine ;
2017-07-06 11:26:14 +02:00
use rustc_hex ::FromHex ;
2016-11-03 22:22:25 +01:00
use state ::{ CleanupMode , Substate } ;
2017-07-29 17:12:07 +02:00
use std ::{ str ::FromStr , sync ::Arc } ;
2018-04-09 16:14:33 +02:00
use test_helpers ::{ get_temp_state , get_temp_state_with_factory } ;
2016-06-02 12:40:31 +02:00
use trace ::{
trace , ExecutiveTracer , ExecutiveVMTracer , FlatTrace , MemoryDiff , NoopTracer , NoopVMTracer ,
StorageDiff , Tracer , VMExecutedOperation , VMOperation , VMTrace , VMTracer ,
2020-08-05 06:08:03 +02:00
} ;
2019-01-04 14:05:46 +01:00
use types ::transaction ::{ Action , Transaction } ;
2017-08-01 12:37:57 +02:00
use vm ::{ ActionParams , ActionValue , CallType , CreateContractAddress , EnvInfo } ;
2020-08-05 06:08:03 +02:00
2017-09-26 14:19:08 +02:00
fn make_frontier_machine ( max_depth : usize ) -> EthereumMachine {
let mut machine = ::ethereum ::new_frontier_test_machine ( ) ;
machine . set_schedule_creation_rules ( Box ::new ( move | s , _ | s . max_depth = max_depth ) ) ;
machine
}
2020-08-05 06:08:03 +02:00
2018-05-09 08:48:55 +02:00
fn make_byzantium_machine ( max_depth : usize ) -> EthereumMachine {
let mut machine = ::ethereum ::new_byzantium_test_machine ( ) ;
machine . set_schedule_creation_rules ( Box ::new ( move | s , _ | s . max_depth = max_depth ) ) ;
machine
}
2020-08-05 06:08:03 +02:00
2016-01-07 23:33:54 +01:00
#[ test ]
fn test_contract_address ( ) {
let address = Address ::from_str ( " 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 " ) . unwrap ( ) ;
2016-01-09 02:12:17 +01:00
let expected_address =
Address ::from_str ( " 3f09c73a5ed19289fb9bdc72f1742566df146f56 " ) . unwrap ( ) ;
2017-06-30 11:30:32 +02:00
assert_eq! (
expected_address ,
contract_address (
CreateContractAddress ::FromSenderAndNonce ,
& address ,
& U256 ::from ( 88 ) ,
& [ ]
2020-08-05 06:08:03 +02:00
)
2017-06-30 11:30:32 +02:00
. 0
) ;
2016-01-07 23:33:54 +01:00
}
2020-08-05 06:08:03 +02:00
2016-01-09 13:51:59 +01:00
// TODO: replace params with transactions!
2018-04-04 11:07:49 +02:00
evm_test! { test_sender_balance : test_sender_balance_int }
2016-01-14 16:17:44 +01:00
fn test_sender_balance ( factory : Factory ) {
2016-01-09 02:12:17 +01:00
let sender = Address ::from_str ( " 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 " ) . unwrap ( ) ;
2017-06-30 11:30:32 +02:00
let address = contract_address (
CreateContractAddress ::FromSenderAndNonce ,
& sender ,
& U256 ::zero ( ) ,
& [ ] ,
2020-08-05 06:08:03 +02:00
)
2017-06-30 11:30:32 +02:00
. 0 ;
2016-01-20 16:52:22 +01:00
let mut params = ActionParams ::default ( ) ;
2016-01-09 02:12:17 +01:00
params . address = address . clone ( ) ;
params . sender = sender . clone ( ) ;
2016-01-12 13:39:12 +01:00
params . gas = U256 ::from ( 100_000 ) ;
2016-10-02 18:45:36 +02:00
params . code = Some ( Arc ::new ( " 3331600055 " . from_hex ( ) . unwrap ( ) ) ) ;
2016-01-20 17:31:37 +01:00
params . value = ActionValue ::Transfer ( U256 ::from ( 0x7 ) ) ;
2017-05-30 11:52:33 +02:00
let mut state = get_temp_state_with_factory ( factory ) ;
2017-02-26 13:10:50 +01:00
state
. add_balance ( & sender , & U256 ::from ( 0x100 u64 ) , CleanupMode ::NoEmpty )
. unwrap ( ) ;
2016-02-02 23:06:34 +01:00
let info = EnvInfo ::default ( ) ;
2017-09-26 14:19:08 +02:00
let machine = make_frontier_machine ( 0 ) ;
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2020-08-05 06:08:03 +02:00
2017-09-15 21:07:54 +02:00
let FinalizationResult { gas_left , .. } = {
2018-07-23 15:48:01 +02:00
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2018-08-13 23:27:13 +02:00
ex . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer )
. unwrap ( )
2016-01-12 13:39:12 +01:00
} ;
2020-08-05 06:08:03 +02:00
2016-01-12 13:39:12 +01:00
assert_eq! ( gas_left , U256 ::from ( 79_975 ) ) ;
2017-02-26 13:10:50 +01:00
assert_eq! (
state . storage_at ( & address , & H256 ::new ( ) ) . unwrap ( ) ,
H256 ::from ( & U256 ::from ( 0xf9 u64 ) )
) ;
assert_eq! ( state . balance ( & sender ) . unwrap ( ) , U256 ::from ( 0xf9 ) ) ;
assert_eq! ( state . balance ( & address ) . unwrap ( ) , U256 ::from ( 0x7 ) ) ;
2016-01-12 16:05:54 +01:00
assert_eq! ( substate . contracts_created . len ( ) , 0 ) ;
2020-08-05 06:08:03 +02:00
2016-01-11 17:37:22 +01:00
// TODO: just test state root.
2016-01-09 01:33:50 +01:00
}
2020-08-05 06:08:03 +02:00
2018-04-04 11:07:49 +02:00
evm_test! { test_create_contract_out_of_depth : test_create_contract_out_of_depth_int }
2016-03-19 21:02:44 +01:00
fn test_create_contract_out_of_depth ( factory : Factory ) {
2016-01-12 16:05:54 +01:00
// code:
//
2016-01-12 13:39:12 +01:00
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
// 60 00 - push 0
// 52
// 60 1d - push 29
// 60 03 - push 3
// 60 17 - push 17
// f0 - create
// 60 00 - push 0
// 55 sstore
2016-01-12 16:05:54 +01:00
//
// other code:
//
// 60 10 - push 16
// 80 - duplicate first stack item
// 60 0c - push 12
// 60 00 - push 0
// 39 - copy current code to memory
// 60 00 - push 0
// f3 - return
2020-08-05 06:08:03 +02:00
2016-01-12 13:39:12 +01:00
let code = " 7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055 " . from_hex ( ) . unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2016-01-09 13:51:59 +01:00
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
2017-06-30 11:30:32 +02:00
let address = contract_address (
CreateContractAddress ::FromSenderAndNonce ,
& sender ,
& U256 ::zero ( ) ,
& [ ] ,
2020-08-05 06:08:03 +02:00
)
2017-06-30 11:30:32 +02:00
. 0 ;
2016-01-12 13:39:12 +01:00
// TODO: add tests for 'callcreate'
//let next_address = contract_address(&address, &U256::zero());
2016-01-20 16:52:22 +01:00
let mut params = ActionParams ::default ( ) ;
2016-01-09 13:51:59 +01:00
params . address = address . clone ( ) ;
params . sender = sender . clone ( ) ;
params . origin = sender . clone ( ) ;
2016-01-12 13:39:12 +01:00
params . gas = U256 ::from ( 100_000 ) ;
2016-10-02 18:45:36 +02:00
params . code = Some ( Arc ::new ( code ) ) ;
2016-01-20 17:31:37 +01:00
params . value = ActionValue ::Transfer ( U256 ::from ( 100 ) ) ;
2017-05-30 11:52:33 +02:00
let mut state = get_temp_state_with_factory ( factory ) ;
2017-02-26 13:10:50 +01:00
state
. add_balance ( & sender , & U256 ::from ( 100 ) , CleanupMode ::NoEmpty )
. unwrap ( ) ;
2016-02-02 23:06:34 +01:00
let info = EnvInfo ::default ( ) ;
2017-09-26 14:19:08 +02:00
let machine = make_frontier_machine ( 0 ) ;
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2020-08-05 06:08:03 +02:00
2017-09-15 21:07:54 +02:00
let FinalizationResult { gas_left , .. } = {
2018-07-23 15:48:01 +02:00
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2018-08-13 23:27:13 +02:00
ex . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer )
. unwrap ( )
2016-01-12 13:39:12 +01:00
} ;
2020-08-05 06:08:03 +02:00
2016-01-13 13:16:53 +01:00
assert_eq! ( gas_left , U256 ::from ( 62_976 ) ) ;
// ended with max depth
assert_eq! ( substate . contracts_created . len ( ) , 0 ) ;
}
2020-08-05 06:08:03 +02:00
2018-05-09 08:48:55 +02:00
#[ test ]
fn test_call_to_precompiled_tracing ( ) {
// code:
//
// 60 00 - push 00 out size
// 60 00 - push 00 out offset
// 60 00 - push 00 in size
// 60 00 - push 00 in offset
// 60 01 - push 01 value
// 60 03 - push 03 to
// 61 ffff - push fff gas
// f1 - CALL
2020-08-05 06:08:03 +02:00
2018-05-09 08:48:55 +02:00
let code = " 60006000600060006001600361fffff1 " . from_hex ( ) . unwrap ( ) ;
let sender = Address ::from_str ( " 4444444444444444444444444444444444444444 " ) . unwrap ( ) ;
let address = Address ::from_str ( " 5555555555555555555555555555555555555555 " ) . unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2018-05-09 08:48:55 +02:00
let mut params = ActionParams ::default ( ) ;
params . address = address . clone ( ) ;
params . code_address = address . clone ( ) ;
params . sender = sender . clone ( ) ;
params . origin = sender . clone ( ) ;
params . gas = U256 ::from ( 100_000 ) ;
params . code = Some ( Arc ::new ( code ) ) ;
params . value = ActionValue ::Transfer ( U256 ::from ( 100 ) ) ;
params . call_type = CallType ::Call ;
let mut state = get_temp_state ( ) ;
state
. add_balance ( & sender , & U256 ::from ( 100 ) , CleanupMode ::NoEmpty )
. unwrap ( ) ;
let info = EnvInfo ::default ( ) ;
let machine = make_byzantium_machine ( 5 ) ;
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
2018-05-09 08:48:55 +02:00
let mut substate = Substate ::new ( ) ;
let mut tracer = ExecutiveTracer ::default ( ) ;
let mut vm_tracer = ExecutiveVMTracer ::toplevel ( ) ;
2020-08-05 06:08:03 +02:00
2018-07-23 15:48:01 +02:00
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2018-08-13 23:27:13 +02:00
ex . call ( params , & mut substate , & mut tracer , & mut vm_tracer )
. unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2018-05-09 08:48:55 +02:00
assert_eq! (
tracer . drain ( ) ,
vec! [
FlatTrace {
action : trace ::Action ::Call ( trace ::Call {
from : " 4444444444444444444444444444444444444444 " . into ( ) ,
to : " 5555555555555555555555555555555555555555 " . into ( ) ,
value : 100. into ( ) ,
gas : 100_000. into ( ) ,
input : vec ! [ ] ,
call_type : CallType ::Call
} ) ,
result : trace ::Res ::Call ( trace ::CallResult {
gas_used : 33021. into ( ) ,
output : vec ! [ ]
} ) ,
subtraces : 1 ,
trace_address : Default ::default ( )
} ,
FlatTrace {
action : trace ::Action ::Call ( trace ::Call {
from : " 5555555555555555555555555555555555555555 " . into ( ) ,
to : " 0000000000000000000000000000000000000003 " . into ( ) ,
value : 1. into ( ) ,
gas : 66560. into ( ) ,
input : vec ! [ ] ,
call_type : CallType ::Call
} ) ,
result : trace ::Res ::Call ( trace ::CallResult {
gas_used : 600. into ( ) ,
2018-08-13 23:27:13 +02:00
output : vec ! [
0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 156 , 17 , 133 , 165 , 197 , 233 , 252 ,
84 , 97 , 40 , 8 , 151 , 126 , 232 , 245 , 72 , 178 , 37 , 141 , 49
]
2018-05-09 08:48:55 +02:00
} ) ,
subtraces : 0 ,
trace_address : vec ! [ 0 ] . into_iter ( ) . collect ( ) ,
}
2020-08-05 06:08:03 +02:00
]
2018-05-09 08:48:55 +02:00
) ;
}
2020-08-05 06:08:03 +02:00
2016-09-28 23:33:12 +02:00
#[ test ]
// Tracing is not suported in JIT
fn test_call_to_create ( ) {
2016-03-19 21:02:44 +01:00
// code:
//
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
// 60 00 - push 0
// 52
// 60 1d - push 29
// 60 03 - push 3
2016-06-02 12:40:31 +02:00
// 60 17 - push 23
2016-03-19 21:02:44 +01:00
// f0 - create
// 60 00 - push 0
// 55 sstore
//
// other code:
//
// 60 10 - push 16
// 80 - duplicate first stack item
// 60 0c - push 12
// 60 00 - push 0
// 39 - copy current code to memory
// 60 00 - push 0
// f3 - return
2020-08-05 06:08:03 +02:00
2016-03-19 21:02:44 +01:00
let code = " 7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055 " . from_hex ( ) . unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2016-03-19 21:02:44 +01:00
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
2017-06-30 11:30:32 +02:00
let address = contract_address (
CreateContractAddress ::FromSenderAndNonce ,
& sender ,
& U256 ::zero ( ) ,
& [ ] ,
2020-08-05 06:08:03 +02:00
)
2017-06-30 11:30:32 +02:00
. 0 ;
2016-03-19 21:02:44 +01:00
// TODO: add tests for 'callcreate'
//let next_address = contract_address(&address, &U256::zero());
let mut params = ActionParams ::default ( ) ;
params . address = address . clone ( ) ;
2016-03-21 11:24:03 +01:00
params . code_address = address . clone ( ) ;
2016-03-19 21:02:44 +01:00
params . sender = sender . clone ( ) ;
params . origin = sender . clone ( ) ;
params . gas = U256 ::from ( 100_000 ) ;
2016-10-02 18:45:36 +02:00
params . code = Some ( Arc ::new ( code ) ) ;
2016-03-19 21:02:44 +01:00
params . value = ActionValue ::Transfer ( U256 ::from ( 100 ) ) ;
2016-07-27 17:41:21 +02:00
params . call_type = CallType ::Call ;
2017-04-06 19:26:17 +02:00
let mut state = get_temp_state ( ) ;
2017-02-26 13:10:50 +01:00
state
. add_balance ( & sender , & U256 ::from ( 100 ) , CleanupMode ::NoEmpty )
. unwrap ( ) ;
2016-03-19 21:02:44 +01:00
let info = EnvInfo ::default ( ) ;
2017-09-26 14:19:08 +02:00
let machine = make_frontier_machine ( 5 ) ;
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
let mut tracer = ExecutiveTracer ::default ( ) ;
2016-08-03 23:23:45 +02:00
let mut vm_tracer = ExecutiveVMTracer ::toplevel ( ) ;
2020-08-05 06:08:03 +02:00
2017-09-15 21:07:54 +02:00
let FinalizationResult { gas_left , .. } = {
2018-07-23 15:48:01 +02:00
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2018-08-13 23:27:13 +02:00
ex . call ( params , & mut substate , & mut tracer , & mut vm_tracer )
. unwrap ( )
2016-03-19 21:02:44 +01:00
} ;
2020-08-05 06:08:03 +02:00
2016-06-02 12:40:31 +02:00
assert_eq! ( gas_left , U256 ::from ( 44_752 ) ) ;
2020-08-05 06:08:03 +02:00
2016-07-28 20:31:29 +02:00
let expected_trace = vec! [
FlatTrace {
trace_address : Default ::default ( ) ,
subtraces : 1 ,
2016-04-30 17:41:24 +02:00
action : trace ::Action ::Call ( trace ::Call {
2016-05-31 16:59:01 +02:00
from : " cd1722f3947def4cf144679da39c4c32bdc35681 " . into ( ) ,
to : " b010143a42d5980c7e5ef0e4a4416dc098a4fed3 " . into ( ) ,
value : 100. into ( ) ,
gas : 100000. into ( ) ,
2016-03-19 21:02:44 +01:00
input : vec ! [ ] ,
2016-07-27 17:41:21 +02:00
call_type : CallType ::Call ,
2016-04-08 01:50:55 +02:00
} ) ,
2016-04-30 17:41:24 +02:00
result : trace ::Res ::Call ( trace ::CallResult {
2016-04-08 01:50:55 +02:00
gas_used : U256 ::from ( 55_248 ) ,
output : vec ! [ ] ,
2016-03-19 21:02:44 +01:00
} ) ,
2016-07-28 20:31:29 +02:00
} ,
FlatTrace {
trace_address : vec ! [ 0 ] . into_iter ( ) . collect ( ) ,
subtraces : 0 ,
action : trace ::Action ::Create ( trace ::Create {
from : " b010143a42d5980c7e5ef0e4a4416dc098a4fed3 " . into ( ) ,
value : 23. into ( ) ,
gas : 67979. into ( ) ,
init : vec ! [
96 , 16 , 128 , 96 , 12 , 96 , 0 , 57 , 96 , 0 , 243 , 0 , 96 , 0 , 53 , 84 , 21 , 96 , 9 ,
87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 , 85 ,
2020-08-05 06:08:03 +02:00
] ,
2016-07-28 20:31:29 +02:00
} ) ,
result : trace ::Res ::Create ( trace ::CreateResult {
gas_used : U256 ::from ( 3224 ) ,
address : Address ::from_str ( " c6d80f262ae5e0f164e5fde365044d7ada2bfa34 " ) . unwrap ( ) ,
code : vec ! [ 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 ] ,
} ) ,
2016-04-08 01:50:55 +02:00
} ,
] ;
2020-08-05 06:08:03 +02:00
2017-08-28 14:25:16 +02:00
assert_eq! ( tracer . drain ( ) , expected_trace ) ;
2020-08-05 06:08:03 +02:00
2016-06-02 12:40:31 +02:00
let expected_vm_trace = VMTrace {
parent_step : 0 ,
code : vec ! [ 124 , 96 , 16 , 128 , 96 , 12 , 96 , 0 , 57 , 96 , 0 , 243 , 0 , 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 , 85 , 96 , 0 , 82 , 96 , 29 , 96 , 3 , 96 , 23 , 240 , 96 , 0 , 85 ] ,
operations : vec ! [
2016-06-02 19:04:15 +02:00
VMOperation { pc : 0 , instruction : 124 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99997. into ( ) , stack_push : vec_into ! [ U256 ::from_dec_str ( " 2589892687202724018173567190521546555304938078595079151649957320078677 " ) . unwrap ( ) ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 30 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99994. into ( ) , stack_push : vec_into ! [ 0 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 32 , instruction : 82 , gas_cost : 6. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99988. into ( ) , stack_push : vec_into ! [ ] , mem_diff : Some ( MemoryDiff { offset : 0 , data : vec ! [ 0 , 0 , 0 , 96 , 16 , 128 , 96 , 12 , 96 , 0 , 57 , 96 , 0 , 243 , 0 , 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 , 85 ] } ) , store_diff : None } ) } ,
VMOperation { pc : 33 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99985. into ( ) , stack_push : vec_into ! [ 29 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 35 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99982. into ( ) , stack_push : vec_into ! [ 3 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 37 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99979. into ( ) , stack_push : vec_into ! [ 23 ] , mem_diff : None , store_diff : None } ) } ,
2016-10-15 14:39:15 +02:00
VMOperation { pc : 39 , instruction : 240 , gas_cost : 99979. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 64755. into ( ) , stack_push : vec_into ! [ U256 ::from_dec_str ( " 1135198453258042933984631383966629874710669425204 " ) . unwrap ( ) ] , mem_diff : None , store_diff : None } ) } ,
2016-06-02 19:04:15 +02:00
VMOperation { pc : 40 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 64752. into ( ) , stack_push : vec_into ! [ 0 ] , mem_diff : None , store_diff : None } ) } ,
2016-06-02 12:40:31 +02:00
VMOperation { pc : 42 , instruction : 85 , gas_cost : 20000. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 44752. into ( ) , stack_push : vec_into ! [ ] , mem_diff : None , store_diff : Some ( StorageDiff { location : 0. into ( ) , value : U256 ::from_dec_str ( " 1135198453258042933984631383966629874710669425204 " ) . unwrap ( ) } ) } ) }
] ,
subs : vec ! [
VMTrace {
2016-08-03 23:23:45 +02:00
parent_step : 6 ,
2016-06-02 12:40:31 +02:00
code : vec ! [ 96 , 16 , 128 , 96 , 12 , 96 , 0 , 57 , 96 , 0 , 243 , 0 , 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 , 85 ] ,
operations : vec ! [
2016-06-02 19:04:15 +02:00
VMOperation { pc : 0 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 67976. into ( ) , stack_push : vec_into ! [ 16 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 2 , instruction : 128 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 67973. into ( ) , stack_push : vec_into ! [ 16 , 16 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 3 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 67970. into ( ) , stack_push : vec_into ! [ 12 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 5 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 67967. into ( ) , stack_push : vec_into ! [ 0 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 7 , instruction : 57 , gas_cost : 9. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 67958. into ( ) , stack_push : vec_into ! [ ] , mem_diff : Some ( MemoryDiff { offset : 0 , data : vec ! [ 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 ] } ) , store_diff : None } ) } ,
VMOperation { pc : 8 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 67955. into ( ) , stack_push : vec_into ! [ 0 ] , mem_diff : None , store_diff : None } ) } ,
2016-06-02 12:40:31 +02:00
VMOperation { pc : 10 , instruction : 243 , gas_cost : 0. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 67955. into ( ) , stack_push : vec_into ! [ ] , mem_diff : None , store_diff : None } ) }
] ,
subs : vec ! [ ]
}
]
} ;
assert_eq! ( vm_tracer . drain ( ) . unwrap ( ) , expected_vm_trace ) ;
2016-03-19 21:02:44 +01:00
}
2020-08-05 06:08:03 +02:00
2017-12-29 15:29:18 +01:00
#[ test ]
fn test_trace_reverted_create ( ) {
// code:
//
// 65 60016000fd - push 5 bytes
// 60 00 - push 0
// 52 mstore
// 60 05 - push 5
// 60 1b - push 27
// 60 17 - push 23
// f0 - create
// 60 00 - push 0
// 55 sstore
//
// other code:
//
// 60 01
// 60 00
// fd - revert
2020-08-05 06:08:03 +02:00
2017-12-29 15:29:18 +01:00
let code = " 6460016000fd6000526005601b6017f0600055 " . from_hex ( ) . unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2017-12-29 15:29:18 +01:00
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
let address = contract_address (
CreateContractAddress ::FromSenderAndNonce ,
& sender ,
& U256 ::zero ( ) ,
& [ ] ,
2020-08-05 06:08:03 +02:00
)
2017-12-29 15:29:18 +01:00
. 0 ;
let mut params = ActionParams ::default ( ) ;
params . address = address . clone ( ) ;
params . code_address = address . clone ( ) ;
params . sender = sender . clone ( ) ;
params . origin = sender . clone ( ) ;
params . gas = U256 ::from ( 100_000 ) ;
params . code = Some ( Arc ::new ( code ) ) ;
params . value = ActionValue ::Transfer ( U256 ::from ( 100 ) ) ;
params . call_type = CallType ::Call ;
let mut state = get_temp_state ( ) ;
state
. add_balance ( & sender , & U256 ::from ( 100 ) , CleanupMode ::NoEmpty )
. unwrap ( ) ;
let info = EnvInfo ::default ( ) ;
let machine = ::ethereum ::new_byzantium_test_machine ( ) ;
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
2017-12-29 15:29:18 +01:00
let mut substate = Substate ::new ( ) ;
let mut tracer = ExecutiveTracer ::default ( ) ;
let mut vm_tracer = ExecutiveVMTracer ::toplevel ( ) ;
2020-08-05 06:08:03 +02:00
2017-12-29 15:29:18 +01:00
let FinalizationResult { gas_left , .. } = {
2018-07-23 15:48:01 +02:00
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2018-08-13 23:27:13 +02:00
ex . call ( params , & mut substate , & mut tracer , & mut vm_tracer )
. unwrap ( )
2017-12-29 15:29:18 +01:00
} ;
2020-08-05 06:08:03 +02:00
2017-12-29 15:29:18 +01:00
assert_eq! ( gas_left , U256 ::from ( 62967 ) ) ;
2020-08-05 06:08:03 +02:00
2017-12-29 15:29:18 +01:00
let expected_trace = vec! [
FlatTrace {
trace_address : Default ::default ( ) ,
subtraces : 1 ,
action : trace ::Action ::Call ( trace ::Call {
from : " cd1722f3947def4cf144679da39c4c32bdc35681 " . into ( ) ,
to : " b010143a42d5980c7e5ef0e4a4416dc098a4fed3 " . into ( ) ,
value : 100. into ( ) ,
gas : 100_000. into ( ) ,
input : vec ! [ ] ,
call_type : CallType ::Call ,
2020-08-05 06:08:03 +02:00
} ) ,
2018-10-02 16:33:19 +02:00
result : trace ::Res ::Call ( trace ::CallResult {
2016-06-02 12:40:31 +02:00
gas_used : U256 ::from ( 37_033 ) ,
output : vec ! [ ] ,
2017-12-29 15:29:18 +01:00
} ) ,
2020-08-05 06:08:03 +02:00
} ,
2017-12-29 15:29:18 +01:00
FlatTrace {
trace_address : vec ! [ 0 ] . into_iter ( ) . collect ( ) ,
subtraces : 0 ,
action : trace ::Action ::Create ( trace ::Create {
from : " b010143a42d5980c7e5ef0e4a4416dc098a4fed3 " . into ( ) ,
value : 23. into ( ) ,
gas : 66_917. into ( ) ,
init : vec ! [ 0x60 , 0x01 , 0x60 , 0x00 , 0xfd ] ,
} ) ,
result : trace ::Res ::FailedCreate ( vm ::Error ::Reverted . into ( ) ) ,
} ,
2020-08-05 06:08:03 +02:00
] ;
2017-12-29 15:29:18 +01:00
assert_eq! ( tracer . drain ( ) , expected_trace ) ;
2020-08-05 06:08:03 +02:00
}
#[ test ]
2017-12-29 15:29:18 +01:00
fn test_create_contract ( ) {
// Tracing is not supported in JIT
// code:
2020-08-05 06:08:03 +02:00
//
2016-01-12 16:05:54 +01:00
// 60 10 - push 16
2016-03-19 22:12:52 +01:00
// 80 - duplicate first stack item
2016-01-12 16:05:54 +01:00
// 60 0c - push 12
2016-01-10 16:21:01 +01:00
// 60 00 - push 0
2017-12-29 15:29:18 +01:00
// 39 - copy current code to memory
2016-01-10 16:21:01 +01:00
// 60 00 - push 0
2017-12-29 15:29:18 +01:00
// f3 - return
2020-08-05 06:08:03 +02:00
2016-03-19 22:12:52 +01:00
let code = " 601080600c6000396000f3006000355415600957005b60203560003555 "
2018-02-19 12:27:42 +01:00
. from_hex ( )
. unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2017-12-29 15:29:18 +01:00
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
2018-02-19 12:27:42 +01:00
let address = contract_address (
2017-12-29 15:29:18 +01:00
CreateContractAddress ::FromSenderAndNonce ,
& sender ,
& U256 ::zero ( ) ,
2020-08-05 06:08:03 +02:00
& [ ] ,
2016-09-28 23:33:12 +02:00
)
2020-08-05 06:08:03 +02:00
. 0 ;
2016-09-28 23:33:12 +02:00
// TODO: add tests for 'callcreate'
2016-03-19 22:12:52 +01:00
//let next_address = contract_address(&address, &U256::zero());
let mut params = ActionParams ::default ( ) ;
params . address = address . clone ( ) ;
params . sender = sender . clone ( ) ;
2017-06-30 11:30:32 +02:00
params . origin = sender . clone ( ) ;
params . gas = U256 ::from ( 100_000 ) ;
params . code = Some ( Arc ::new ( code ) ) ;
params . value = ActionValue ::Transfer ( 100. into ( ) ) ;
let mut state = get_temp_state ( ) ;
2020-08-05 06:08:03 +02:00
state
2017-06-30 11:30:32 +02:00
. add_balance ( & sender , & U256 ::from ( 100 ) , CleanupMode ::NoEmpty )
2016-03-19 22:12:52 +01:00
. unwrap ( ) ;
let info = EnvInfo ::default ( ) ;
let machine = make_frontier_machine ( 5 ) ;
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-03-19 22:12:52 +01:00
let mut tracer = ExecutiveTracer ::default ( ) ;
2016-05-31 16:59:01 +02:00
let mut vm_tracer = ExecutiveVMTracer ::toplevel ( ) ;
2020-08-05 06:08:03 +02:00
2016-05-31 16:59:01 +02:00
let FinalizationResult { gas_left , .. } = {
2017-04-06 19:26:17 +02:00
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2017-02-26 13:10:50 +01:00
ex . create ( params . clone ( ) , & mut substate , & mut tracer , & mut vm_tracer )
. unwrap ( )
2020-08-05 06:08:03 +02:00
} ;
2017-02-26 13:10:50 +01:00
assert_eq! ( gas_left , U256 ::from ( 96_776 ) ) ;
2020-08-05 06:08:03 +02:00
2016-08-03 23:23:45 +02:00
let expected_trace = vec! [ FlatTrace {
trace_address : Default ::default ( ) ,
2016-07-28 20:31:29 +02:00
subtraces : 0 ,
2017-09-15 21:07:54 +02:00
action : trace ::Action ::Create ( trace ::Create {
from : params . sender ,
value : 100. into ( ) ,
2018-08-13 23:27:13 +02:00
gas : params . gas ,
init : vec ! [
2016-06-02 12:40:31 +02:00
96 , 16 , 128 , 96 , 12 , 96 , 0 , 57 , 96 , 0 , 243 , 0 , 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 ,
91 , 96 , 32 , 53 , 96 , 0 , 53 , 85 ,
2018-08-13 23:27:13 +02:00
] ,
} ) ,
result : trace ::Res ::Create ( trace ::CreateResult {
2016-06-02 12:40:31 +02:00
gas_used : U256 ::from ( 3224 ) ,
2016-04-08 01:50:55 +02:00
address : params . address ,
2016-06-02 12:40:31 +02:00
code : vec ! [ 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 ] ,
2020-08-05 06:08:03 +02:00
} ) ,
} ] ;
2016-06-02 12:40:31 +02:00
assert_eq! ( tracer . drain ( ) , expected_trace ) ;
2020-08-05 06:08:03 +02:00
2016-07-28 20:31:29 +02:00
let expected_vm_trace = VMTrace {
2016-03-19 22:12:52 +01:00
parent_step : 0 ,
code : vec ! [
96 , 16 , 128 , 96 , 12 , 96 , 0 , 57 , 96 , 0 , 243 , 0 , 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 ,
96 , 32 , 53 , 96 , 0 , 53 , 85 ,
] ,
2016-04-30 17:41:24 +02:00
operations : vec ! [
2016-06-02 12:40:31 +02:00
VMOperation {
2020-08-05 06:08:03 +02:00
pc : 0 ,
2016-04-30 17:41:24 +02:00
instruction : 96 ,
gas_cost : 3. into ( ) ,
executed : Some ( VMExecutedOperation {
2016-04-08 01:50:55 +02:00
gas_used : 99997. into ( ) ,
stack_push : vec_into ! [ 16 ] ,
mem_diff : None ,
store_diff : None ,
2016-03-19 22:12:52 +01:00
} ) ,
2016-04-08 01:50:55 +02:00
} ,
2017-08-28 14:25:16 +02:00
VMOperation {
2020-08-05 06:08:03 +02:00
pc : 2 ,
2017-08-28 14:25:16 +02:00
instruction : 128 ,
gas_cost : 3. into ( ) ,
2016-06-02 12:40:31 +02:00
executed : Some ( VMExecutedOperation {
gas_used : 99994. into ( ) ,
stack_push : vec_into ! [ 16 , 16 ] ,
mem_diff : None ,
store_diff : None ,
} ) ,
} ,
VMOperation {
pc : 3 ,
instruction : 96 ,
gas_cost : 3. into ( ) ,
executed : Some ( VMExecutedOperation {
gas_used : 99991. into ( ) ,
stack_push : vec_into ! [ 12 ] ,
mem_diff : None ,
store_diff : None ,
} ) ,
} ,
VMOperation {
pc : 5 ,
instruction : 96 ,
gas_cost : 3. into ( ) ,
executed : Some ( VMExecutedOperation {
gas_used : 99988. into ( ) ,
stack_push : vec_into ! [ 0 ] ,
mem_diff : None ,
store_diff : None ,
} ) ,
} ,
VMOperation {
pc : 7 ,
instruction : 57 ,
gas_cost : 9. into ( ) ,
executed : Some ( VMExecutedOperation {
gas_used : 99979. into ( ) ,
stack_push : vec_into ! [ ] ,
mem_diff : Some ( MemoryDiff {
offset : 0 ,
data : vec ! [ 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 ] ,
} ) ,
2018-04-04 11:07:49 +02:00
store_diff : None ,
2020-08-05 06:08:03 +02:00
} ) ,
} ,
2018-04-04 11:07:49 +02:00
VMOperation {
2020-08-05 06:08:03 +02:00
pc : 8 ,
2018-04-04 11:07:49 +02:00
instruction : 96 ,
2016-01-14 16:17:44 +01:00
gas_cost : 3. into ( ) ,
executed : Some ( VMExecutedOperation {
2016-01-13 13:16:53 +01:00
gas_used : 99976. into ( ) ,
stack_push : vec_into ! [ 0 ] ,
2016-06-02 12:40:31 +02:00
mem_diff : None ,
2016-01-13 13:16:53 +01:00
store_diff : None ,
2020-08-05 06:08:03 +02:00
} ) ,
} ,
2016-01-13 13:16:53 +01:00
VMOperation {
2020-08-05 06:08:03 +02:00
pc : 10 ,
2016-01-13 13:16:53 +01:00
instruction : 243 ,
gas_cost : 0. into ( ) ,
executed : Some ( VMExecutedOperation {
2016-06-02 12:40:31 +02:00
gas_used : 99976. into ( ) ,
2016-01-13 13:16:53 +01:00
stack_push : vec_into ! [ ] ,
mem_diff : None ,
store_diff : None ,
2020-08-05 06:08:03 +02:00
} ) ,
} ,
] ,
2016-06-02 12:40:31 +02:00
subs : vec ! [ ] ,
2020-08-05 06:08:03 +02:00
} ;
2016-01-13 13:16:53 +01:00
assert_eq! ( vm_tracer . drain ( ) . unwrap ( ) , expected_vm_trace ) ;
2020-08-05 06:08:03 +02:00
}
2016-01-13 13:16:53 +01:00
evm_test! { test_create_contract_value_too_high : test_create_contract_value_too_high_int }
2016-01-14 16:17:44 +01:00
fn test_create_contract_value_too_high ( factory : Factory ) {
2016-01-13 13:16:53 +01:00
// code:
2020-08-05 06:08:03 +02:00
//
2016-01-13 13:16:53 +01:00
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
// 60 00 - push 0
// 52
// 60 1d - push 29
// 60 03 - push 3
// 60 e6 - push 230
2017-06-30 11:30:32 +02:00
// f0 - create a contract trying to send 230.
2016-01-10 16:21:01 +01:00
// 60 00 - push 0
2016-01-13 13:16:53 +01:00
// 55 sstore
2020-08-05 06:08:03 +02:00
//
2016-01-13 13:16:53 +01:00
// other code:
2020-08-05 06:08:03 +02:00
//
2016-01-20 17:31:37 +01:00
// 60 10 - push 16
2017-05-30 11:52:33 +02:00
// 80 - duplicate first stack item
2016-01-12 16:05:54 +01:00
// 60 0c - push 12
2016-01-10 16:21:01 +01:00
// 60 00 - push 0
2017-05-30 11:52:33 +02:00
// 39 - copy current code to memory
2016-01-10 16:21:01 +01:00
// 60 00 - push 0
2017-05-30 11:52:33 +02:00
// f3 - return
2020-08-05 06:08:03 +02:00
2017-05-30 11:52:33 +02:00
let code = " 7c601080600c6000396000f3006000355415600957005b60203560003555600052601d600360e6f0600055 " . from_hex ( ) . unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2017-02-26 13:10:50 +01:00
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
2017-09-15 21:07:54 +02:00
let address = contract_address (
2018-08-13 23:27:13 +02:00
CreateContractAddress ::FromSenderAndNonce ,
& sender ,
& U256 ::zero ( ) ,
2020-08-05 06:08:03 +02:00
& [ ] ,
2018-08-13 23:27:13 +02:00
)
2020-08-05 06:08:03 +02:00
. 0 ;
2018-08-13 23:27:13 +02:00
// TODO: add tests for 'callcreate'
//let next_address = contract_address(&address, &U256::zero());
let mut params = ActionParams ::default ( ) ;
2016-01-09 13:51:59 +01:00
params . address = address . clone ( ) ;
2018-08-13 23:27:13 +02:00
params . sender = sender . clone ( ) ;
2016-01-13 13:16:53 +01:00
params . origin = sender . clone ( ) ;
params . gas = U256 ::from ( 100_000 ) ;
2016-01-12 16:05:54 +01:00
params . code = Some ( Arc ::new ( code ) ) ;
params . value = ActionValue ::Transfer ( U256 ::from ( 100 ) ) ;
2016-01-14 16:17:44 +01:00
let mut state = get_temp_state_with_factory ( factory ) ;
2020-08-05 06:08:03 +02:00
state
2016-01-14 16:17:44 +01:00
. add_balance ( & sender , & U256 ::from ( 100 ) , CleanupMode ::NoEmpty )
. unwrap ( ) ;
2018-02-19 12:27:42 +01:00
let info = EnvInfo ::default ( ) ;
2016-01-14 16:17:44 +01:00
let machine = make_frontier_machine ( 0 ) ;
2016-01-12 16:05:54 +01:00
let schedule = machine . schedule ( info . number ) ;
let mut substate = Substate ::new ( ) ;
2020-08-05 06:08:03 +02:00
2016-01-12 16:05:54 +01:00
let FinalizationResult { gas_left , .. } = {
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
ex . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer )
2018-02-19 12:27:42 +01:00
. unwrap ( )
2020-08-05 06:08:03 +02:00
} ;
2016-01-14 12:33:49 +01:00
assert_eq! ( gas_left , U256 ::from ( 62_976 ) ) ;
assert_eq! ( substate . contracts_created . len ( ) , 0 ) ;
2020-08-05 06:08:03 +02:00
}
2016-01-14 12:33:49 +01:00
evm_test! { test_create_contract_without_max_depth : test_create_contract_without_max_depth_int }
2018-04-04 11:07:49 +02:00
fn test_create_contract_without_max_depth ( factory : Factory ) {
2016-01-14 12:33:49 +01:00
// code:
2020-08-05 06:08:03 +02:00
//
2016-01-14 12:33:49 +01:00
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
// 60 00 - push 0
// 52
// 60 1d - push 29
// 60 03 - push 3
// 60 17 - push 17
2017-06-30 11:30:32 +02:00
// f0 - create
2016-01-10 16:21:01 +01:00
// 60 00 - push 0
2017-06-30 11:30:32 +02:00
// 55 sstore
2020-08-05 06:08:03 +02:00
//
2017-06-30 11:30:32 +02:00
// other code:
2020-08-05 06:08:03 +02:00
//
2016-01-12 16:05:54 +01:00
// 60 10 - push 16
2017-05-30 11:52:33 +02:00
// 80 - duplicate first stack item
2016-01-12 16:05:54 +01:00
// 60 0c - push 12
2016-01-10 16:21:01 +01:00
// 60 00 - push 0
2017-05-30 11:52:33 +02:00
// 39 - copy current code to memory
2016-01-10 16:21:01 +01:00
// 60 00 - push 0
2017-05-30 11:52:33 +02:00
// f3 - return
2020-08-05 06:08:03 +02:00
2017-05-30 11:52:33 +02:00
let code =
2017-02-26 13:10:50 +01:00
" 7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0 "
2018-02-19 12:27:42 +01:00
. from_hex ( )
. unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2017-02-26 13:10:50 +01:00
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
2017-09-26 14:19:08 +02:00
let address = contract_address (
2016-01-12 16:05:54 +01:00
CreateContractAddress ::FromSenderAndNonce ,
& sender ,
2017-06-30 11:30:32 +02:00
& U256 ::zero ( ) ,
2016-01-12 16:05:54 +01:00
& [ ] ,
2020-08-05 06:08:03 +02:00
)
2016-01-12 16:05:54 +01:00
. 0 ;
let next_address = contract_address (
2016-01-16 04:59:53 +01:00
CreateContractAddress ::FromSenderAndNonce ,
2017-06-30 11:30:32 +02:00
& address ,
& U256 ::zero ( ) ,
2020-08-05 06:08:03 +02:00
& [ ] ,
)
. 0 ;
2016-01-16 04:59:53 +01:00
let mut params = ActionParams ::default ( ) ;
2016-02-08 22:54:33 +01:00
params . address = address . clone ( ) ;
params . sender = sender . clone ( ) ;
params . origin = sender . clone ( ) ;
2016-01-13 13:16:53 +01:00
params . gas = U256 ::from ( 100_000 ) ;
2016-02-08 22:54:33 +01:00
params . code = Some ( Arc ::new ( code ) ) ;
2018-04-04 11:07:49 +02:00
params . value = ActionValue ::Transfer ( U256 ::from ( 100 ) ) ;
2016-01-14 16:17:44 +01:00
let mut state = get_temp_state_with_factory ( factory ) ;
2016-01-12 13:39:12 +01:00
state
2018-02-19 12:27:42 +01:00
. add_balance ( & sender , & U256 ::from ( 100 ) , CleanupMode ::NoEmpty )
2016-01-12 13:39:12 +01:00
. unwrap ( ) ;
let info = EnvInfo ::default ( ) ;
let machine = make_frontier_machine ( 1024 ) ;
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2020-08-05 06:08:03 +02:00
{
2016-01-12 13:39:12 +01:00
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2018-08-13 23:27:13 +02:00
ex . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer )
2018-02-19 12:27:42 +01:00
. unwrap ( ) ;
2020-08-05 06:08:03 +02:00
}
2016-01-12 16:05:54 +01:00
assert_eq! ( substate . contracts_created . len ( ) , 1 ) ;
2016-01-12 13:39:12 +01:00
assert_eq! ( substate . contracts_created [ 0 ] , next_address ) ;
2020-08-05 06:08:03 +02:00
}
2018-02-19 12:27:42 +01:00
// test is incorrect, mk
2016-01-12 13:39:12 +01:00
// TODO: fix (preferred) or remove
evm_test_ignore! { test_aba_calls : test_aba_calls_int }
2016-01-14 16:17:44 +01:00
fn test_aba_calls ( factory : Factory ) {
2016-01-12 13:39:12 +01:00
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
// 60 18 - push 18
// 73 945304eb96065b2a98b57a48a06ae28d285a71b5 - push this address
// 61 03e8 - push 1000
// f1 - message call
// 58 - get PC
2016-01-13 13:16:53 +01:00
// 55 - sstore
2020-08-05 06:08:03 +02:00
2018-02-19 12:27:42 +01:00
let code_a = " 6000600060006000601873945304eb96065b2a98b57a48a06ae28d285a71b56103e8f15855 "
. from_hex ( )
. unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2016-01-10 16:21:01 +01:00
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
2016-01-12 13:39:12 +01:00
// 60 17 - push 17
// 73 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 - push this address
// 61 0x01f4 - push 500
// f1 - message call
// 60 01 - push 1
// 01 - add
// 58 - get PC
// 55 - sstore
let code_b =
" 60006000600060006017730f572e5295c57f15886f9b263e2f6d2d6c7b5ec66101f4f16001015855 "
. from_hex ( )
. unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2016-01-12 13:39:12 +01:00
let address_a = Address ::from_str ( " 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 " ) . unwrap ( ) ;
let address_b = Address ::from_str ( " 945304eb96065b2a98b57a48a06ae28d285a71b5 " ) . unwrap ( ) ;
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2016-01-20 16:52:22 +01:00
let mut params = ActionParams ::default ( ) ;
2016-01-12 13:39:12 +01:00
params . address = address_a . clone ( ) ;
params . sender = sender . clone ( ) ;
params . gas = U256 ::from ( 100_000 ) ;
2016-10-02 18:45:36 +02:00
params . code = Some ( Arc ::new ( code_a . clone ( ) ) ) ;
2016-01-20 17:31:37 +01:00
params . value = ActionValue ::Transfer ( U256 ::from ( 100_000 ) ) ;
2020-08-05 06:08:03 +02:00
2017-05-30 11:52:33 +02:00
let mut state = get_temp_state_with_factory ( factory ) ;
2017-02-26 13:10:50 +01:00
state . init_code ( & address_a , code_a . clone ( ) ) . unwrap ( ) ;
state . init_code ( & address_b , code_b . clone ( ) ) . unwrap ( ) ;
state
. add_balance ( & sender , & U256 ::from ( 100_000 ) , CleanupMode ::NoEmpty )
. unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2016-02-02 23:06:34 +01:00
let info = EnvInfo ::default ( ) ;
2017-09-26 14:19:08 +02:00
let machine = make_frontier_machine ( 0 ) ;
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2020-08-05 06:08:03 +02:00
2017-09-15 21:07:54 +02:00
let FinalizationResult { gas_left , .. } = {
2018-07-23 15:48:01 +02:00
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2018-08-13 23:27:13 +02:00
ex . call ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer )
. unwrap ( )
2016-01-12 13:39:12 +01:00
} ;
2020-08-05 06:08:03 +02:00
2016-01-12 13:39:12 +01:00
assert_eq! ( gas_left , U256 ::from ( 73_237 ) ) ;
2017-02-26 13:10:50 +01:00
assert_eq! (
state
. storage_at ( & address_a , & H256 ::from ( & U256 ::from ( 0x23 ) ) )
. unwrap ( ) ,
H256 ::from ( & U256 ::from ( 1 ) )
) ;
2016-01-10 16:21:01 +01:00
}
2020-08-05 06:08:03 +02:00
2016-01-16 04:59:53 +01:00
// test is incorrect, mk
2016-02-08 22:54:33 +01:00
// TODO: fix (preferred) or remove
2018-04-04 11:07:49 +02:00
evm_test_ignore! { test_recursive_bomb1 : test_recursive_bomb1_int }
2016-01-14 16:17:44 +01:00
fn test_recursive_bomb1 ( factory : Factory ) {
2016-01-10 16:21:01 +01:00
// 60 01 - push 1
// 60 00 - push 0
2016-02-09 16:31:57 +01:00
// 54 - sload
2016-01-10 16:21:01 +01:00
// 01 - add
// 60 00 - push 0
// 55 - sstore
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
// 30 - load address
// 60 e0 - push e0
// 5a - get gas
// 03 - sub
// f1 - message call (self in this case)
// 60 01 - push 1
2016-01-12 13:39:12 +01:00
// 55 - sstore
2016-01-10 16:21:01 +01:00
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
2016-01-11 14:08:03 +01:00
let code = " 600160005401600055600060006000600060003060e05a03f1600155 "
. from_hex ( )
. unwrap ( ) ;
2017-06-30 11:30:32 +02:00
let address = contract_address (
CreateContractAddress ::FromSenderAndNonce ,
& sender ,
& U256 ::zero ( ) ,
& [ ] ,
2020-08-05 06:08:03 +02:00
)
2017-06-30 11:30:32 +02:00
. 0 ;
2016-01-20 16:52:22 +01:00
let mut params = ActionParams ::default ( ) ;
2016-01-10 16:21:01 +01:00
params . address = address . clone ( ) ;
2016-01-12 13:39:12 +01:00
params . gas = U256 ::from ( 100_000 ) ;
2016-10-02 18:45:36 +02:00
params . code = Some ( Arc ::new ( code . clone ( ) ) ) ;
2017-05-30 11:52:33 +02:00
let mut state = get_temp_state_with_factory ( factory ) ;
2017-02-26 13:10:50 +01:00
state . init_code ( & address , code ) . unwrap ( ) ;
2016-02-02 23:06:34 +01:00
let info = EnvInfo ::default ( ) ;
2017-09-26 14:19:08 +02:00
let machine = make_frontier_machine ( 0 ) ;
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2020-08-05 06:08:03 +02:00
2017-09-15 21:07:54 +02:00
let FinalizationResult { gas_left , .. } = {
2018-07-23 15:48:01 +02:00
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2018-08-13 23:27:13 +02:00
ex . call ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer )
. unwrap ( )
2016-01-12 13:39:12 +01:00
} ;
2020-08-05 06:08:03 +02:00
2016-01-12 13:39:12 +01:00
assert_eq! ( gas_left , U256 ::from ( 59_870 ) ) ;
2017-02-26 13:10:50 +01:00
assert_eq! (
state
. storage_at ( & address , & H256 ::from ( & U256 ::zero ( ) ) )
. unwrap ( ) ,
H256 ::from ( & U256 ::from ( 1 ) )
) ;
assert_eq! (
state
. storage_at ( & address , & H256 ::from ( & U256 ::one ( ) ) )
2018-08-13 23:27:13 +02:00
. unwrap ( ) ,
2017-02-26 13:10:50 +01:00
H256 ::from ( & U256 ::from ( 1 ) )
2020-08-05 06:08:03 +02:00
) ;
2016-01-09 13:51:59 +01:00
}
2020-08-05 06:08:03 +02:00
2016-01-16 04:59:53 +01:00
// test is incorrect, mk
2016-02-08 22:54:33 +01:00
// TODO: fix (preferred) or remove
2018-04-04 11:07:49 +02:00
evm_test_ignore! { test_transact_simple : test_transact_simple_int }
2016-01-14 16:17:44 +01:00
fn test_transact_simple ( factory : Factory ) {
2016-08-24 18:35:21 +02:00
let keypair = Random . generate ( ) . unwrap ( ) ;
2016-02-04 23:48:29 +01:00
let t = Transaction {
action : Action ::Create ,
value : U256 ::from ( 17 ) ,
data : " 3331600055 " . from_hex ( ) . unwrap ( ) ,
gas : U256 ::from ( 100_000 ) ,
gas_price : U256 ::zero ( ) ,
nonce : U256 ::zero ( ) ,
2016-11-03 22:22:25 +01:00
}
. sign ( keypair . secret ( ) , None ) ;
2017-01-13 09:51:36 +01:00
let sender = t . sender ( ) ;
2017-06-30 11:30:32 +02:00
let contract = contract_address (
CreateContractAddress ::FromSenderAndNonce ,
& sender ,
& U256 ::zero ( ) ,
& [ ] ,
2020-08-05 06:08:03 +02:00
)
2017-06-30 11:30:32 +02:00
. 0 ;
2020-08-05 06:08:03 +02:00
2017-05-30 11:52:33 +02:00
let mut state = get_temp_state_with_factory ( factory ) ;
2017-02-26 13:10:50 +01:00
state
. add_balance ( & sender , & U256 ::from ( 18 ) , CleanupMode ::NoEmpty )
. unwrap ( ) ;
2016-02-02 23:06:34 +01:00
let mut info = EnvInfo ::default ( ) ;
2016-01-12 18:31:47 +01:00
info . gas_limit = U256 ::from ( 100_000 ) ;
2017-09-26 14:19:08 +02:00
let machine = make_frontier_machine ( 0 ) ;
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
2020-08-05 06:08:03 +02:00
2016-01-12 18:31:47 +01:00
let executed = {
2018-07-23 15:48:01 +02:00
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2017-08-28 14:25:16 +02:00
let opts = TransactOptions ::with_no_tracing ( ) ;
2016-04-06 13:05:58 +02:00
ex . transact ( & t , opts ) . unwrap ( )
2016-01-12 18:31:47 +01:00
} ;
2020-08-05 06:08:03 +02:00
2016-01-12 18:31:47 +01:00
assert_eq! ( executed . gas , U256 ::from ( 100_000 ) ) ;
2016-01-14 16:40:50 +01:00
assert_eq! ( executed . gas_used , U256 ::from ( 41_301 ) ) ;
assert_eq! ( executed . refunded , U256 ::from ( 58_699 ) ) ;
assert_eq! ( executed . cumulative_gas_used , U256 ::from ( 41_301 ) ) ;
2016-01-12 18:31:47 +01:00
assert_eq! ( executed . logs . len ( ) , 0 ) ;
assert_eq! ( executed . contracts_created . len ( ) , 0 ) ;
2017-02-26 13:10:50 +01:00
assert_eq! ( state . balance ( & sender ) . unwrap ( ) , U256 ::from ( 1 ) ) ;
assert_eq! ( state . balance ( & contract ) . unwrap ( ) , U256 ::from ( 17 ) ) ;
assert_eq! ( state . nonce ( & sender ) . unwrap ( ) , U256 ::from ( 1 ) ) ;
assert_eq! (
state . storage_at ( & contract , & H256 ::new ( ) ) . unwrap ( ) ,
H256 ::from ( & U256 ::from ( 1 ) )
) ;
2016-01-12 18:31:47 +01:00
}
2020-08-05 06:08:03 +02:00
2018-04-04 11:07:49 +02:00
evm_test! { test_transact_invalid_nonce : test_transact_invalid_nonce_int }
2016-01-14 16:17:44 +01:00
fn test_transact_invalid_nonce ( factory : Factory ) {
2016-08-24 18:35:21 +02:00
let keypair = Random . generate ( ) . unwrap ( ) ;
2016-02-04 23:48:29 +01:00
let t = Transaction {
action : Action ::Create ,
value : U256 ::from ( 17 ) ,
data : " 3331600055 " . from_hex ( ) . unwrap ( ) ,
gas : U256 ::from ( 100_000 ) ,
gas_price : U256 ::zero ( ) ,
nonce : U256 ::one ( ) ,
2016-11-03 22:22:25 +01:00
}
. sign ( keypair . secret ( ) , None ) ;
2017-01-13 09:51:36 +01:00
let sender = t . sender ( ) ;
2020-08-05 06:08:03 +02:00
2017-05-30 11:52:33 +02:00
let mut state = get_temp_state_with_factory ( factory ) ;
2017-02-26 13:10:50 +01:00
state
. add_balance ( & sender , & U256 ::from ( 17 ) , CleanupMode ::NoEmpty )
. unwrap ( ) ;
2016-02-02 23:06:34 +01:00
let mut info = EnvInfo ::default ( ) ;
2016-01-12 19:43:26 +01:00
info . gas_limit = U256 ::from ( 100_000 ) ;
2017-09-26 14:19:08 +02:00
let machine = make_frontier_machine ( 0 ) ;
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
2020-08-05 06:08:03 +02:00
2016-01-12 19:43:26 +01:00
let res = {
2018-07-23 15:48:01 +02:00
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2017-08-28 14:25:16 +02:00
let opts = TransactOptions ::with_no_tracing ( ) ;
2016-04-06 13:05:58 +02:00
ex . transact ( & t , opts )
2016-01-12 19:43:26 +01:00
} ;
2020-08-05 06:08:03 +02:00
2016-01-12 19:43:26 +01:00
match res {
2016-05-14 14:28:44 +02:00
Err ( ExecutionError ::InvalidNonce { expected , got } )
2016-02-09 16:31:57 +01:00
if expected = = U256 ::zero ( ) & & got = = U256 ::one ( ) = >
2020-08-05 06:08:03 +02:00
{
2016-02-09 16:31:57 +01:00
( )
2020-08-05 06:08:03 +02:00
}
2016-01-12 19:43:26 +01:00
_ = > assert! ( false , " Expected invalid nonce error. " ) ,
}
2020-08-05 06:08:03 +02:00
}
2018-04-04 11:07:49 +02:00
evm_test! { test_transact_gas_limit_reached : test_transact_gas_limit_reached_int }
2016-01-14 16:17:44 +01:00
fn test_transact_gas_limit_reached ( factory : Factory ) {
2016-08-24 18:35:21 +02:00
let keypair = Random . generate ( ) . unwrap ( ) ;
2016-02-04 23:48:29 +01:00
let t = Transaction {
action : Action ::Create ,
value : U256 ::from ( 17 ) ,
data : " 3331600055 " . from_hex ( ) . unwrap ( ) ,
gas : U256 ::from ( 80_001 ) ,
gas_price : U256 ::zero ( ) ,
nonce : U256 ::zero ( ) ,
2016-11-03 22:22:25 +01:00
}
. sign ( keypair . secret ( ) , None ) ;
2017-01-13 09:51:36 +01:00
let sender = t . sender ( ) ;
2020-08-05 06:08:03 +02:00
2017-05-30 11:52:33 +02:00
let mut state = get_temp_state_with_factory ( factory ) ;
2017-02-26 13:10:50 +01:00
state
. add_balance ( & sender , & U256 ::from ( 17 ) , CleanupMode ::NoEmpty )
. unwrap ( ) ;
2016-02-02 23:06:34 +01:00
let mut info = EnvInfo ::default ( ) ;
2016-01-12 19:43:26 +01:00
info . gas_used = U256 ::from ( 20_000 ) ;
info . gas_limit = U256 ::from ( 100_000 ) ;
2017-09-26 14:19:08 +02:00
let machine = make_frontier_machine ( 0 ) ;
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
2020-08-05 06:08:03 +02:00
2016-01-12 19:43:26 +01:00
let res = {
2018-07-23 15:48:01 +02:00
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2017-08-28 14:25:16 +02:00
let opts = TransactOptions ::with_no_tracing ( ) ;
2016-04-06 13:05:58 +02:00
ex . transact ( & t , opts )
2016-01-12 19:43:26 +01:00
} ;
2020-08-05 06:08:03 +02:00
2016-01-12 19:43:26 +01:00
match res {
2016-05-14 14:28:44 +02:00
Err ( ExecutionError ::BlockGasLimitReached {
gas_limit ,
gas_used ,
2016-02-09 16:31:57 +01:00
gas ,
} ) if gas_limit = = U256 ::from ( 100_000 )
& & gas_used = = U256 ::from ( 20_000 )
& & gas = = U256 ::from ( 80_001 ) = >
2020-08-05 06:08:03 +02:00
{
2016-02-09 16:31:57 +01:00
( )
2020-08-05 06:08:03 +02:00
}
2016-01-12 19:43:26 +01:00
_ = > assert! ( false , " Expected block gas limit error. " ) ,
2020-08-05 06:08:03 +02:00
}
2016-01-12 19:43:26 +01:00
}
2020-08-05 06:08:03 +02:00
2018-04-04 11:07:49 +02:00
evm_test! { test_not_enough_cash : test_not_enough_cash_int }
2016-01-14 16:17:44 +01:00
fn test_not_enough_cash ( factory : Factory ) {
2016-08-24 18:35:21 +02:00
let keypair = Random . generate ( ) . unwrap ( ) ;
2016-02-04 23:48:29 +01:00
let t = Transaction {
action : Action ::Create ,
value : U256 ::from ( 18 ) ,
data : " 3331600055 " . from_hex ( ) . unwrap ( ) ,
gas : U256 ::from ( 100_000 ) ,
gas_price : U256 ::one ( ) ,
nonce : U256 ::zero ( ) ,
2016-11-03 22:22:25 +01:00
}
. sign ( keypair . secret ( ) , None ) ;
2017-01-13 09:51:36 +01:00
let sender = t . sender ( ) ;
2020-08-05 06:08:03 +02:00
2017-05-30 11:52:33 +02:00
let mut state = get_temp_state_with_factory ( factory ) ;
2017-02-26 13:10:50 +01:00
state
. add_balance ( & sender , & U256 ::from ( 100_017 ) , CleanupMode ::NoEmpty )
. unwrap ( ) ;
2016-02-02 23:06:34 +01:00
let mut info = EnvInfo ::default ( ) ;
2016-01-12 19:43:26 +01:00
info . gas_limit = U256 ::from ( 100_000 ) ;
2017-09-26 14:19:08 +02:00
let machine = make_frontier_machine ( 0 ) ;
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
2020-08-05 06:08:03 +02:00
2016-01-12 18:31:47 +01:00
let res = {
2018-07-23 15:48:01 +02:00
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2017-08-28 14:25:16 +02:00
let opts = TransactOptions ::with_no_tracing ( ) ;
2016-04-06 13:05:58 +02:00
ex . transact ( & t , opts )
2016-01-12 18:31:47 +01:00
} ;
2020-08-05 06:08:03 +02:00
2016-01-12 18:31:47 +01:00
match res {
2016-05-14 14:28:44 +02:00
Err ( ExecutionError ::NotEnoughCash { required , got } )
2016-02-09 16:31:57 +01:00
if required = = U512 ::from ( 100_018 ) & & got = = U512 ::from ( 100_017 ) = >
2020-08-05 06:08:03 +02:00
{
2016-02-09 16:31:57 +01:00
( )
2020-08-05 06:08:03 +02:00
}
2016-01-13 13:16:53 +01:00
_ = > assert! ( false , " Expected not enough cash error. {:?} " , res ) ,
2020-08-05 06:08:03 +02:00
}
2016-01-10 16:21:01 +01:00
}
2020-08-05 06:08:03 +02:00
2018-04-04 11:07:49 +02:00
evm_test! { test_keccak : test_keccak_int }
2017-08-30 19:18:28 +02:00
fn test_keccak ( factory : Factory ) {
2016-01-15 23:32:16 +01:00
let code = " 6064640fffffffff20600055 " . from_hex ( ) . unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2016-01-15 23:32:16 +01:00
let sender = Address ::from_str ( " 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 " ) . unwrap ( ) ;
2017-06-30 11:30:32 +02:00
let address = contract_address (
CreateContractAddress ::FromSenderAndNonce ,
& sender ,
& U256 ::zero ( ) ,
& [ ] ,
2020-08-05 06:08:03 +02:00
)
2017-06-30 11:30:32 +02:00
. 0 ;
2016-01-15 23:32:16 +01:00
// TODO: add tests for 'callcreate'
//let next_address = contract_address(&address, &U256::zero());
2016-01-20 16:52:22 +01:00
let mut params = ActionParams ::default ( ) ;
2016-01-15 23:32:16 +01:00
params . address = address . clone ( ) ;
params . sender = sender . clone ( ) ;
params . origin = sender . clone ( ) ;
params . gas = U256 ::from ( 0x0186a0 ) ;
2016-10-02 18:45:36 +02:00
params . code = Some ( Arc ::new ( code ) ) ;
2016-01-20 17:31:37 +01:00
params . value = ActionValue ::Transfer ( U256 ::from_str ( " 0de0b6b3a7640000 " ) . unwrap ( ) ) ;
2017-05-30 11:52:33 +02:00
let mut state = get_temp_state_with_factory ( factory ) ;
2017-02-26 13:10:50 +01:00
state
. add_balance (
& sender ,
& U256 ::from_str ( " 152d02c7e14af6800000 " ) . unwrap ( ) ,
CleanupMode ::NoEmpty ,
2020-08-05 06:08:03 +02:00
)
2017-02-26 13:10:50 +01:00
. unwrap ( ) ;
2016-02-02 23:06:34 +01:00
let info = EnvInfo ::default ( ) ;
2017-09-26 14:19:08 +02:00
let machine = make_frontier_machine ( 0 ) ;
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2020-08-05 06:08:03 +02:00
2016-01-15 23:32:16 +01:00
let result = {
2018-07-23 15:48:01 +02:00
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2018-08-13 23:27:13 +02:00
ex . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer )
2016-01-15 23:32:16 +01:00
} ;
2020-08-05 06:08:03 +02:00
2016-01-15 23:32:16 +01:00
match result {
2017-05-23 15:49:17 +02:00
Err ( _ ) = > { }
_ = > panic! ( " Expected OutOfGas " ) ,
2020-08-05 06:08:03 +02:00
}
2016-01-15 23:32:16 +01:00
}
2020-08-05 06:08:03 +02:00
2018-04-04 11:07:49 +02:00
evm_test! { test_revert : test_revert_int }
2017-05-23 15:49:17 +02:00
fn test_revert ( factory : Factory ) {
let contract_address =
Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
let sender = Address ::from_str ( " 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 " ) . unwrap ( ) ;
// EIP-140 test case
let code = " 6c726576657274656420646174616000557f726576657274206d657373616765000000000000000000000000000000000000600052600e6000fd " . from_hex ( ) . unwrap ( ) ;
let returns = " 726576657274206d657373616765 " . from_hex ( ) . unwrap ( ) ;
2017-05-30 11:52:33 +02:00
let mut state = get_temp_state_with_factory ( factory . clone ( ) ) ;
2017-05-23 15:49:17 +02:00
state
. add_balance (
& sender ,
& U256 ::from_str ( " 152d02c7e14af68000000 " ) . unwrap ( ) ,
CleanupMode ::NoEmpty ,
2020-08-05 06:08:03 +02:00
)
2017-05-23 15:49:17 +02:00
. unwrap ( ) ;
state . commit ( ) . unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2017-05-23 15:49:17 +02:00
let mut params = ActionParams ::default ( ) ;
params . address = contract_address . clone ( ) ;
params . sender = sender . clone ( ) ;
params . origin = sender . clone ( ) ;
params . gas = U256 ::from ( 20025 ) ;
params . code = Some ( Arc ::new ( code ) ) ;
params . value = ActionValue ::Transfer ( U256 ::zero ( ) ) ;
let info = EnvInfo ::default ( ) ;
2017-09-26 14:19:08 +02:00
let machine = ::ethereum ::new_byzantium_test_machine ( ) ;
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
2017-05-23 15:49:17 +02:00
let mut substate = Substate ::new ( ) ;
2020-08-05 06:08:03 +02:00
2017-05-23 15:49:17 +02:00
let mut output = [ 0 u8 ; 14 ] ;
2018-08-13 23:27:13 +02:00
let FinalizationResult {
gas_left : result ,
return_data ,
..
} = {
2018-07-23 15:48:01 +02:00
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2018-08-13 23:27:13 +02:00
ex . call ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer )
. unwrap ( )
2017-05-23 15:49:17 +02:00
} ;
2018-08-13 23:27:13 +02:00
( & mut output ) . copy_from_slice ( & return_data [ .. ( cmp ::min ( 14 , return_data . len ( ) ) ) ] ) ;
2020-08-05 06:08:03 +02:00
2017-05-23 15:49:17 +02:00
assert_eq! ( result , U256 ::from ( 1 ) ) ;
assert_eq! ( output [ .. ] , returns [ .. ] ) ;
assert_eq! (
state
. storage_at ( & contract_address , & H256 ::from ( & U256 ::zero ( ) ) )
. unwrap ( ) ,
H256 ::from ( & U256 ::from ( 0 ) )
) ;
}
2020-08-05 06:08:03 +02:00
2018-09-07 12:51:08 +02:00
evm_test! { test_eip1283 : test_eip1283_int }
fn test_eip1283 ( factory : Factory ) {
let x1 = Address ::from ( 0x1000 ) ;
let x2 = Address ::from ( 0x1001 ) ;
let y1 = Address ::from ( 0x2001 ) ;
let y2 = Address ::from ( 0x2002 ) ;
let operating_address = Address ::from ( 0 ) ;
let k = H256 ::new ( ) ;
2020-08-05 06:08:03 +02:00
2018-09-07 12:51:08 +02:00
let mut state = get_temp_state_with_factory ( factory . clone ( ) ) ;
state
. new_contract ( & x1 , U256 ::zero ( ) , U256 ::from ( 1 ) )
. unwrap ( ) ;
state
. init_code ( & x1 , " 600160005560006000556001600055 " . from_hex ( ) . unwrap ( ) )
. unwrap ( ) ;
state
. new_contract ( & x2 , U256 ::zero ( ) , U256 ::from ( 1 ) )
. unwrap ( ) ;
state
. init_code ( & x2 , " 600060005560016000556000600055 " . from_hex ( ) . unwrap ( ) )
. unwrap ( ) ;
state
. new_contract ( & y1 , U256 ::zero ( ) , U256 ::from ( 1 ) )
. unwrap ( ) ;
state
. init_code ( & y1 , " 600060006000600061100062fffffff4 " . from_hex ( ) . unwrap ( ) )
. unwrap ( ) ;
state
. new_contract ( & y2 , U256 ::zero ( ) , U256 ::from ( 1 ) )
. unwrap ( ) ;
state
. init_code ( & y2 , " 600060006000600061100162fffffff4 " . from_hex ( ) . unwrap ( ) )
. unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2018-09-07 12:51:08 +02:00
let info = EnvInfo ::default ( ) ;
let machine = ::ethereum ::new_constantinople_test_machine ( ) ;
let schedule = machine . schedule ( info . number ) ;
2020-08-05 06:08:03 +02:00
2018-09-07 12:51:08 +02:00
assert_eq! (
state . storage_at ( & operating_address , & k ) . unwrap ( ) ,
H256 ::from ( U256 ::from ( 0 ) )
) ;
// Test a call via top-level -> y1 -> x1
let ( FinalizationResult { gas_left , .. } , refund , gas ) = {
let gas = U256 ::from ( 0xffffffffff u64 ) ;
let mut params = ActionParams ::default ( ) ;
params . code = Some ( Arc ::new (
" 6001600055600060006000600061200163fffffffff4 "
. from_hex ( )
. unwrap ( ) ,
) ) ;
params . gas = gas ;
let mut substate = Substate ::new ( ) ;
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
let res = ex
. call ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer )
. unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2018-09-07 12:51:08 +02:00
( res , substate . sstore_clears_refund , gas )
} ;
let gas_used = gas - gas_left ;
// sstore: 0 -> (1) -> () -> (1 -> 0 -> 1)
assert_eq! ( gas_used , U256 ::from ( 41860 ) ) ;
2018-10-15 11:09:55 +02:00
assert_eq! ( refund , 19800 ) ;
2020-08-05 06:08:03 +02:00
2018-09-07 12:51:08 +02:00
assert_eq! (
state . storage_at ( & operating_address , & k ) . unwrap ( ) ,
H256 ::from ( U256 ::from ( 1 ) )
) ;
// Test a call via top-level -> y2 -> x2
let ( FinalizationResult { gas_left , .. } , refund , gas ) = {
let gas = U256 ::from ( 0xffffffffff u64 ) ;
let mut params = ActionParams ::default ( ) ;
params . code = Some ( Arc ::new (
" 6001600055600060006000600061200263fffffffff4 "
. from_hex ( )
. unwrap ( ) ,
) ) ;
params . gas = gas ;
let mut substate = Substate ::new ( ) ;
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
let res = ex
. call ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer )
. unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2018-09-07 12:51:08 +02:00
( res , substate . sstore_clears_refund , gas )
} ;
let gas_used = gas - gas_left ;
// sstore: 1 -> (1) -> () -> (0 -> 1 -> 0)
assert_eq! ( gas_used , U256 ::from ( 11860 ) ) ;
2018-10-15 11:09:55 +02:00
assert_eq! ( refund , 19800 ) ;
2018-09-07 12:51:08 +02:00
}
2020-08-05 06:08:03 +02:00
2018-02-19 12:27:42 +01:00
fn wasm_sample_code ( ) -> Arc < Vec < u8 > > {
Arc ::new (
" 0061736d01000000010d0360027f7f0060017f0060000002270303656e7603726574000003656e760673656e646572000103656e76066d656d6f727902010110030201020404017000000501000708010463616c6c00020901000ac10101be0102057f017e4100410028020441c0006b22043602042004412c6a41106a220041003602002004412c6a41086a22014200370200200441186a41106a22024100360200200441186a41086a220342003703002004420037022c2004410036021c20044100360218200441186a1001200020022802002202360200200120032903002205370200200441106a2002360200200441086a200537030020042004290318220537022c200420053703002004411410004100200441c0006a3602040b0b0a010041040b0410c00000 "
. from_hex ( )
. unwrap ( )
)
}
2020-08-05 06:08:03 +02:00
2018-02-19 12:27:42 +01:00
#[ test ]
fn wasm_activated_test ( ) {
let contract_address =
Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
let sender = Address ::from_str ( " 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 " ) . unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2018-02-19 12:27:42 +01:00
let mut state = get_temp_state ( ) ;
state
. add_balance ( & sender , & U256 ::from ( 10000000000 u64 ) , CleanupMode ::NoEmpty )
. unwrap ( ) ;
state . commit ( ) . unwrap ( ) ;
2020-08-05 06:08:03 +02:00
2018-02-19 12:27:42 +01:00
let mut params = ActionParams ::default ( ) ;
params . origin = sender . clone ( ) ;
params . sender = sender . clone ( ) ;
params . address = contract_address . clone ( ) ;
params . gas = U256 ::from ( 20025 ) ;
params . code = Some ( wasm_sample_code ( ) ) ;
2020-08-05 06:08:03 +02:00
2018-02-19 12:27:42 +01:00
let mut info = EnvInfo ::default ( ) ;
2020-08-05 06:08:03 +02:00
2020-10-08 22:37:48 +02:00
// 200 (wasmDisableTransition) > 100 > 10 (wasmActivationTransition)
2018-02-19 12:27:42 +01:00
info . number = 100 ;
2020-08-05 06:08:03 +02:00
2018-02-19 12:27:42 +01:00
// Network with wasm activated at block 10
let machine = ::ethereum ::new_kovan_wasm_test_machine ( ) ;
2020-08-05 06:08:03 +02:00
2018-02-19 12:27:42 +01:00
let mut output = [ 0 u8 ; 20 ] ;
2018-08-13 23:27:13 +02:00
let FinalizationResult {
gas_left : result ,
return_data ,
..
} = {
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2018-08-13 23:27:13 +02:00
ex . call (
params . clone ( ) ,
& mut Substate ::new ( ) ,
& mut NoopTracer ,
& mut NoopVMTracer ,
2020-08-05 06:08:03 +02:00
)
2018-08-13 23:27:13 +02:00
. unwrap ( )
2018-02-19 12:27:42 +01:00
} ;
2018-08-13 23:27:13 +02:00
( & mut output ) . copy_from_slice ( & return_data [ .. ( cmp ::min ( 20 , return_data . len ( ) ) ) ] ) ;
2020-08-05 06:08:03 +02:00
2018-02-19 12:27:42 +01:00
assert_eq! ( result , U256 ::from ( 18433 ) ) ;
// Transaction successfully returned sender
assert_eq! ( output [ .. ] , sender [ .. ] ) ;
2020-08-05 06:08:03 +02:00
2020-10-08 22:37:48 +02:00
// 1 < 10 (wasmActivationTransition)
2018-02-19 12:27:42 +01:00
info . number = 1 ;
2020-08-05 06:08:03 +02:00
2018-02-19 12:27:42 +01:00
let mut output = [ 0 u8 ; 20 ] ;
2018-08-13 23:27:13 +02:00
let FinalizationResult {
gas_left : result ,
return_data ,
..
} = {
2018-07-23 15:48:01 +02:00
let schedule = machine . schedule ( info . number ) ;
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
2018-08-13 23:27:13 +02:00
ex . call (
2020-10-08 22:37:48 +02:00
params . clone ( ) ,
2018-08-13 23:27:13 +02:00
& mut Substate ::new ( ) ,
& mut NoopTracer ,
& mut NoopVMTracer ,
2020-08-05 06:08:03 +02:00
)
2018-08-13 23:27:13 +02:00
. unwrap ( )
2018-02-19 12:27:42 +01:00
} ;
2018-08-13 23:27:13 +02:00
( & mut output [ .. ( cmp ::min ( 20 , return_data . len ( ) ) ) ] )
. copy_from_slice ( & return_data [ .. ( cmp ::min ( 20 , return_data . len ( ) ) ) ] ) ;
2020-08-05 06:08:03 +02:00
2018-02-19 12:27:42 +01:00
assert_eq! ( result , U256 ::from ( 20025 ) ) ;
// Since transaction errored due to wasm was not activated, result is just empty
assert_eq! ( output [ .. ] , [ 0 u8 ; 20 ] [ .. ] ) ;
2020-10-08 22:37:48 +02:00
// 200 == wasmDisableTransition
info . number = 200 ;
let mut output = [ 0 u8 ; 20 ] ;
let FinalizationResult {
gas_left : result ,
return_data ,
..
} = {
let schedule = machine . schedule ( info . number ) ;
let mut ex = Executive ::new ( & mut state , & info , & machine , & schedule ) ;
ex . call (
params ,
& mut Substate ::new ( ) ,
& mut NoopTracer ,
& mut NoopVMTracer ,
)
. unwrap ( )
} ;
( & mut output [ .. ( cmp ::min ( 20 , return_data . len ( ) ) ) ] )
. copy_from_slice ( & return_data [ .. ( cmp ::min ( 20 , return_data . len ( ) ) ) ] ) ;
assert_eq! ( result , U256 ::from ( 20025 ) ) ;
// Since transaction errored due to wasm was deactivated, result is just empty
assert_eq! ( output [ .. ] , [ 0 u8 ; 20 ] [ .. ] ) ;
2018-02-19 12:27:42 +01:00
}
2016-01-07 23:33:54 +01:00
}