2017-01-25 18:51:41 +01:00
// Copyright 2015-2017 Parity Technologies (UK) Ltd.
2016-02-05 13:40:41 +01:00
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// 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.
// Parity is distributed in the hope that it will be useful,
// 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
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
2016-01-11 02:42:02 +01:00
//! Transaction Execution environment.
2017-07-29 17:12:07 +02:00
use std ::cmp ;
2017-07-29 21:56:42 +02:00
use std ::sync ::Arc ;
2017-08-30 19:18:28 +02:00
use hash ::keccak ;
2016-10-24 18:35:25 +02:00
use util ::* ;
2017-02-21 12:35:21 +01:00
use state ::{ Backend as StateBackend , State , Substate , CleanupMode } ;
2016-07-28 20:32:20 +02:00
use engines ::Engine ;
2017-08-01 12:37:57 +02:00
use vm ::EnvInfo ;
2016-10-24 18:35:25 +02:00
use error ::ExecutionError ;
2017-08-01 12:37:57 +02:00
use evm ::{ CallType , Factory , Finalize , FinalizationResult } ;
use vm ::{ self , Ext , CreateContractAddress , ReturnData , CleanDustMode , ActionParams , ActionValue } ;
use wasm ;
2016-01-15 14:22:46 +01:00
use externalities ::* ;
2017-08-28 14:25:16 +02:00
use trace ::{ self , FlatTrace , VMTrace , Tracer , VMTracer } ;
2016-10-24 18:35:25 +02:00
use transaction ::{ Action , SignedTransaction } ;
2016-01-26 10:15:55 +01:00
use crossbeam ;
2017-07-12 13:09:17 +02:00
pub use executed ::{ Executed , ExecutionResult } ;
2016-05-16 18:33:32 +02:00
2016-10-06 18:42:54 +02:00
/// Roughly estimate what stack size each level of evm depth will use
2016-01-26 10:15:55 +01:00
/// TODO [todr] We probably need some more sophisticated calculations here (limit on my machine 132)
2016-05-02 13:13:12 +02:00
/// Maybe something like here: `https://github.com/ethereum/libethereum/blob/4db169b8504f2b87f7d5a481819cfb959fc65f6c/libethereum/ExtVM.cpp`
2016-10-06 18:42:54 +02:00
const STACK_SIZE_PER_DEPTH : usize = 24 * 1024 ;
2016-01-07 23:33:54 +01:00
2017-07-10 17:42:10 +02:00
const WASM_MAGIC_NUMBER : & 'static [ u8 ; 4 ] = b " \0 asm " ;
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 ;
2016-09-01 14:29:59 +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
} ,
CreateContractAddress ::FromCodeHash = > {
2017-08-30 19:18:28 +02:00
let code_hash = keccak ( code ) ;
2017-04-19 14:48:02 +02:00
let mut buffer = [ 0xff u8 ; 20 + 32 ] ;
2017-04-19 14:30:00 +02:00
& 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
} ,
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
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-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 ,
}
}
/// Disables the nonce check
pub fn dont_check_nonce ( mut self ) -> Self {
self . check_nonce = false ;
self
}
}
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 ,
}
}
}
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 ,
}
}
}
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 ,
}
}
}
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-07-29 17:12:07 +02:00
pub fn executor < E > ( engine : & E , vm_factory : & Factory , params : & ActionParams )
2017-08-01 12:37:57 +02:00
-> Box < vm ::Vm > where E : Engine + ? Sized
2017-07-10 17:42:10 +02:00
{
if engine . supports_wasm ( ) & & params . code . as_ref ( ) . map_or ( false , | code | code . len ( ) > 4 & & & code [ 0 .. 4 ] = = WASM_MAGIC_NUMBER ) {
Box ::new (
wasm ::WasmInterpreter ::new ( )
// prefer to fail fast
. expect ( " Failed to create wasm runtime " )
)
} else {
vm_factory . create ( params . gas )
}
}
2016-01-11 19:25:37 +01:00
/// Transaction executor.
2017-05-30 11:52:33 +02:00
pub struct Executive < ' a , B : ' a + StateBackend , E : ' a + Engine + ? Sized > {
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-05-30 11:52:33 +02:00
engine : & ' a E ,
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-05-30 11:52:33 +02:00
impl < ' a , B : ' a + StateBackend , E : Engine + ? Sized > Executive < ' a , B , E > {
2016-01-11 19:25:37 +01:00
/// Basic constructor.
2017-05-30 11:52:33 +02:00
pub fn new ( state : & ' a mut State < B > , info : & ' a EnvInfo , engine : & ' a E ) -> Self {
2016-03-19 12:54:34 +01:00
Executive {
state : state ,
info : info ,
engine : engine ,
depth : 0 ,
2017-06-19 11:41:46 +02:00
static_flag : false ,
2016-03-19 12:54:34 +01:00
}
2016-01-09 17:55:47 +01:00
}
2016-01-09 00:51:09 +01:00
2016-01-11 14:08:03 +01:00
/// Populates executive from parent properties. Increments executive depth.
2017-06-19 11:41:46 +02:00
pub fn from_parent ( state : & ' a mut State < B > , info : & ' a EnvInfo , engine : & ' a E , parent_depth : usize , static_flag : bool ) -> Self {
2016-01-07 19:05:44 +01:00
Executive {
state : state ,
info : info ,
engine : engine ,
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
}
}
2016-01-15 14:22:46 +01:00
/// Creates `Externalities` from `Executive`.
2016-06-03 11:36:30 +02:00
pub fn as_externalities < ' any , T , V > (
& ' any mut self ,
2016-06-02 12:40:31 +02:00
origin_info : OriginInfo ,
2016-06-03 11:36:30 +02:00
substate : & ' any mut Substate ,
output : OutputPolicy < ' any , ' any > ,
tracer : & ' any mut T ,
2017-06-19 11:41:46 +02:00
vm_tracer : & ' any mut V ,
static_call : bool ,
2017-05-30 11:52:33 +02:00
) -> Externalities < ' any , T , V , B , E > where T : Tracer , V : VMTracer {
2017-06-19 11:41:46 +02:00
let is_static = self . static_flag | | static_call ;
Externalities ::new ( self . state , self . info , self . engine , self . depth , origin_info , substate , output , tracer , vm_tracer , is_static )
2016-01-15 14:22:46 +01: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 > )
-> Result < Executed , ExecutionError > where T : Tracer , V : VMTracer ,
{
self . transact_with_tracer ( t , options . check_nonce , options . tracer , options . vm_tracer )
2016-04-08 01:50:55 +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 > ( & ' a mut self , t : & SignedTransaction , options : TransactOptions < T , V > )
-> Result < Executed , ExecutionError > where T : Tracer , V : VMTracer ,
{
2017-05-17 12:41:33 +02:00
let sender = t . sender ( ) ;
let balance = self . state . balance ( & sender ) ? ;
2017-08-15 10:07:00 +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 {
// give the sender a sufficient balance
self . state . add_balance ( & sender , & ( needed_balance - balance ) , CleanupMode ::NoEmpty ) ? ;
}
self . transact ( t , options )
}
2016-04-28 21:47:44 +02:00
/// Execute transaction/call with tracing enabled
2017-08-28 14:25:16 +02:00
fn transact_with_tracer < T , V > (
2016-06-02 12:40:31 +02:00
& ' a mut self ,
t : & SignedTransaction ,
check_nonce : bool ,
mut tracer : T ,
mut vm_tracer : V
) -> Result < Executed , 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 nonce = self . state . nonce ( & sender ) ? ;
2016-01-10 12:29:35 +01:00
2017-04-19 14:30:00 +02:00
let schedule = self . engine . schedule ( self . info . number ) ;
2016-01-15 13:07:44 +01:00
let base_gas_required = U256 ::from ( t . gas_required ( & schedule ) ) ;
if t . gas < base_gas_required {
return Err ( From ::from ( ExecutionError ::NotEnoughBaseGas { required : base_gas_required , got : t . gas } ) ) ;
}
2017-06-28 09:10:57 +02:00
if ! t . is_unsigned ( ) & & check_nonce & & schedule . kill_dust ! = CleanDustMode ::Off & & ! self . state . exists ( & sender ) ? {
return Err ( From ::from ( ExecutionError ::SenderMustExist ) ) ;
}
2016-01-15 13:07:44 +01:00
let init_gas = t . gas - base_gas_required ;
2016-01-14 02:20:46 +01:00
2016-01-10 12:29:35 +01:00
// validate transaction nonce
2016-04-12 13:54:34 +02:00
if check_nonce & & t . nonce ! = nonce {
return Err ( From ::from ( ExecutionError ::InvalidNonce { expected : nonce , got : t . nonce } ) ) ;
2016-01-10 12:29:35 +01:00
}
2016-02-09 16:31:57 +01:00
2016-01-11 02:17:29 +01:00
// validate if transaction fits into given block
2016-01-11 02:42:02 +01:00
if self . info . gas_used + t . gas > self . info . gas_limit {
2016-02-09 16:31:57 +01:00
return Err ( From ::from ( ExecutionError ::BlockGasLimitReached {
gas_limit : self . info . gas_limit ,
gas_used : self . info . gas_used ,
gas : t . gas
2016-01-11 20:47:19 +01:00
} ) ) ;
2016-01-11 02:17:29 +01:00
}
2016-01-10 12:29:35 +01:00
// TODO: we might need bigints here, or at least check overflows.
2017-02-26 13:10:50 +01:00
let balance = self . state . balance ( & sender ) ? ;
2016-10-06 18:42:54 +02:00
let gas_cost = t . gas . full_mul ( t . gas_price ) ;
2016-01-12 17:40:34 +01:00
let total_cost = U512 ::from ( t . value ) + gas_cost ;
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 {
return Err ( From ::from ( ExecutionError ::NotEnoughCash { required : total_cost , got : balance512 } ) ) ;
2016-01-10 12:29:35 +01:00
}
2016-01-07 21:29:36 +01:00
2017-06-28 09:10:57 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-11 02:17:29 +01:00
// NOTE: there can be no invalid transactions from this point.
2017-04-19 14:30:00 +02:00
if ! t . is_unsigned ( ) {
self . state . inc_nonce ( & sender ) ? ;
}
2017-06-28 09:10:57 +02:00
self . state . sub_balance ( & sender , & U256 ::from ( gas_cost ) , & mut substate . to_cleanup_mode ( & schedule ) ) ? ;
2016-01-11 15:55:54 +01:00
2017-06-06 17:47:12 +02:00
let ( result , output ) = match t . action {
2016-01-17 15:56:09 +01:00
Action ::Create = > {
2017-06-30 11:30:32 +02:00
let ( new_address , code_hash ) = contract_address ( self . engine . create_address_scheme ( self . info . number ) , & sender , & nonce , & t . data ) ;
2016-01-11 16:33:08 +01:00
let params = ActionParams {
2016-01-15 15:00:28 +01:00
code_address : new_address . clone ( ) ,
2017-04-19 14:30:00 +02:00
code_hash : code_hash ,
2016-01-15 15:00:28 +01:00
address : new_address ,
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 ) ,
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 ,
2016-01-09 17:55:47 +01:00
} ;
2016-06-02 12:40:31 +02:00
( self . create ( params , & mut substate , & mut tracer , & mut vm_tracer ) , vec! [ ] )
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 ) ? ,
2017-06-30 11:30:32 +02:00
code_hash : Some ( 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 ,
2016-01-09 17:55:47 +01:00
} ;
2016-01-13 15:26:52 +01:00
let mut out = vec! [ ] ;
2016-06-02 12:40:31 +02:00
( self . call ( params , & mut substate , BytesRef ::Flexible ( & mut out ) , & mut tracer , & mut vm_tracer ) , out )
2016-01-09 17:55:47 +01: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
}
2016-06-02 12:40:31 +02:00
fn exec_vm < T , V > (
& mut self ,
params : ActionParams ,
unconfirmed_substate : & mut Substate ,
output_policy : OutputPolicy ,
tracer : & mut T ,
vm_tracer : & mut V
2017-08-01 12:37:57 +02:00
) -> vm ::Result < FinalizationResult > where T : Tracer , V : VMTracer {
2016-10-06 18:42:54 +02:00
let depth_threshold = ::io ::LOCAL_STACK_SIZE . with ( | sz | sz . get ( ) / STACK_SIZE_PER_DEPTH ) ;
2017-06-19 11:41:46 +02:00
let static_call = params . call_type = = CallType ::StaticCall ;
2016-10-06 18:42:54 +02:00
2016-01-26 10:15:55 +01:00
// Ordinary execution - keep VM in same thread
2016-10-06 18:42:54 +02:00
if ( self . depth + 1 ) % depth_threshold ! = 0 {
2017-05-30 11:52:33 +02:00
let vm_factory = self . state . vm_factory ( ) ;
2017-06-19 11:41:46 +02:00
let mut ext = self . as_externalities ( OriginInfo ::from ( & params ) , unconfirmed_substate , output_policy , tracer , vm_tracer , static_call ) ;
2016-03-20 19:20:37 +01:00
trace! ( target : " executive " , " ext.schedule.have_delegate_call: {} " , ext . schedule ( ) . have_delegate_call ) ;
2017-07-10 17:42:10 +02:00
return executor ( self . engine , & vm_factory , & params ) . exec ( params , & mut ext ) . finalize ( ext ) ;
2016-01-26 10:15:55 +01:00
}
// Start in new thread to reset stack
// TODO [todr] No thread builder yet, so we need to reset once for a while
// https://github.com/aturon/crossbeam/issues/16
crossbeam ::scope ( | scope | {
2017-07-10 17:42:10 +02:00
let engine = self . engine ;
2017-05-30 11:52:33 +02:00
let vm_factory = self . state . vm_factory ( ) ;
2017-06-19 11:41:46 +02:00
let mut ext = self . as_externalities ( OriginInfo ::from ( & params ) , unconfirmed_substate , output_policy , tracer , vm_tracer , static_call ) ;
2016-01-26 10:15:55 +01:00
scope . spawn ( move | | {
2017-07-10 17:42:10 +02:00
executor ( engine , & vm_factory , & params ) . exec ( params , & mut ext ) . finalize ( ext )
2016-01-26 10:15:55 +01:00
} )
} ) . join ( )
}
2016-01-09 21:39:38 +01:00
/// Calls contract function with given contract params.
2016-01-11 02:17:29 +01:00
/// NOTE. It does not finalize the transaction (doesn't do refunds, nor suicides).
/// Modifies the substate and the output.
2017-08-01 12:37:57 +02:00
/// Returns either gas_left or `vm::Error`.
2016-06-02 12:40:31 +02:00
pub fn call < T , V > (
& mut self ,
params : ActionParams ,
substate : & mut Substate ,
mut output : BytesRef ,
tracer : & mut T ,
vm_tracer : & mut V
2017-08-01 12:37:57 +02:00
) -> vm ::Result < ( U256 , ReturnData ) > where T : Tracer , V : VMTracer {
2017-06-19 11:41:46 +02:00
trace! ( " Executive::call(params={:?}) self.env_info={:?} " , params , self . info ) ;
if ( params . call_type = = CallType ::StaticCall | |
( ( params . call_type = = CallType ::Call | | params . call_type = = CallType ::DelegateCall ) & &
self . static_flag ) )
& & params . value . value ( ) > 0. into ( ) {
2017-08-01 12:37:57 +02:00
return Err ( vm ::Error ::MutableCallInStaticContext ) ;
2017-06-19 11:41:46 +02:00
}
2016-01-14 17:40:38 +01:00
// backup used in case of running out of gas
2016-10-22 15:22:16 +02:00
self . state . checkpoint ( ) ;
2016-01-14 17:40:38 +01:00
2017-04-19 14:30:00 +02:00
let schedule = self . engine . schedule ( self . info . number ) ;
2016-11-03 22:22:25 +01:00
2016-01-09 22:54:16 +01:00
// at first, transfer value to destination
2016-01-20 17:27:33 +01:00
if let ActionValue ::Transfer ( val ) = params . value {
2017-02-26 13:10:50 +01:00
self . state . transfer_balance ( & params . sender , & params . address , & val , substate . to_cleanup_mode ( & schedule ) ) ? ;
2016-01-20 16:52:22 +01:00
}
2016-01-09 22:54:16 +01:00
2017-03-21 17:36:38 +01:00
// if destination is builtin, try to execute it
if let Some ( builtin ) = self . engine . builtin ( & params . code_address , self . info . number ) {
// Engines aren't supposed to return builtins until activation, but
// prefer to fail rather than silently break consensus.
if ! builtin . is_active ( self . info . number ) {
panic! ( " Consensus failure: engine implementation prematurely enabled built-in at {} " , params . code_address ) ;
}
2016-02-09 16:31:57 +01:00
2016-01-15 15:00:28 +01:00
let default = [ ] ;
2016-01-17 15:56:09 +01:00
let data = if let Some ( ref d ) = params . data { d as & [ u8 ] } else { & default as & [ u8 ] } ;
2016-01-15 15:14:41 +01:00
2016-04-30 17:41:24 +02:00
let trace_info = tracer . prepare_trace_call ( & params ) ;
2017-03-21 17:36:38 +01:00
let cost = builtin . cost ( data ) ;
2016-07-24 17:38:21 +02:00
if cost < = params . gas {
2017-03-27 17:17:49 +02:00
if let Err ( e ) = builtin . execute ( data , & mut output ) {
self . state . revert_to_checkpoint ( ) ;
2017-08-01 12:37:57 +02:00
let evm_err : vm ::Error = e . into ( ) ;
2017-03-27 17:17:49 +02:00
tracer . trace_failed_call ( trace_info , vec! [ ] , evm_err . clone ( ) . into ( ) ) ;
Err ( evm_err )
} else {
self . state . discard_checkpoint ( ) ;
// trace only top level calls to builtins to avoid DDoS attacks
if self . depth = = 0 {
let mut trace_output = tracer . prepare_trace_output ( ) ;
if let Some ( mut out ) = trace_output . as_mut ( ) {
* out = output . to_owned ( ) ;
}
tracer . trace_call (
trace_info ,
cost ,
trace_output ,
vec! [ ]
) ;
2016-04-30 17:41:24 +02:00
}
2017-06-06 17:47:12 +02:00
Ok ( ( params . gas - cost , ReturnData ::empty ( ) ) )
2016-07-24 17:38:21 +02:00
}
} else {
2016-01-14 17:40:38 +01:00
// just drain the whole gas
2016-10-22 15:22:16 +02:00
self . state . revert_to_checkpoint ( ) ;
2016-04-30 17:41:24 +02:00
2017-08-01 12:37:57 +02:00
tracer . trace_failed_call ( trace_info , vec! [ ] , vm ::Error ::OutOfGas . into ( ) ) ;
2016-04-30 17:41:24 +02:00
2017-08-01 12:37:57 +02:00
Err ( vm ::Error ::OutOfGas )
2016-01-09 22:54:16 +01:00
}
2016-03-21 11:24:03 +01:00
} else {
2016-04-08 01:50:55 +02:00
let trace_info = tracer . prepare_trace_call ( & params ) ;
let mut trace_output = tracer . prepare_trace_output ( ) ;
let mut subtracer = tracer . subtracer ( ) ;
2016-06-02 12:40:31 +02:00
2016-04-08 01:50:55 +02:00
let gas = params . gas ;
2016-03-18 23:49:12 +01:00
2016-03-21 11:24:03 +01:00
if params . code . is_some ( ) {
// part of substate that may be reverted
2016-04-08 01:50:55 +02:00
let mut unconfirmed_substate = Substate ::new ( ) ;
2016-01-15 18:56:28 +01:00
2016-06-02 12:40:31 +02:00
// TODO: make ActionParams pass by ref then avoid copy altogether.
2016-07-24 17:38:21 +02:00
let mut subvmtracer = vm_tracer . prepare_subtrace ( params . code . as_ref ( ) . expect ( " scope is conditional on params.code.is_some(); qed " ) ) ;
2016-06-02 12:40:31 +02:00
2016-03-21 11:24:03 +01:00
let res = {
2016-06-02 12:40:31 +02:00
self . exec_vm ( params , & mut unconfirmed_substate , OutputPolicy ::Return ( output , trace_output . as_mut ( ) ) , & mut subtracer , & mut subvmtracer )
2016-03-21 11:24:03 +01:00
} ;
2016-03-20 19:20:37 +01:00
2017-07-10 13:23:40 +02:00
vm_tracer . done_subtrace ( subvmtracer ) ;
2016-06-02 12:40:31 +02:00
2016-03-21 11:24:03 +01:00
trace! ( target : " executive " , " res={:?} " , res ) ;
2016-03-18 23:49:12 +01:00
2017-08-28 14:25:16 +02:00
let traces = subtracer . drain ( ) ;
2016-04-08 01:50:55 +02:00
match res {
2017-05-23 15:49:17 +02:00
Ok ( ref res ) = > tracer . trace_call (
2016-04-08 01:50:55 +02:00
trace_info ,
2017-05-23 15:49:17 +02:00
gas - res . gas_left ,
2016-04-08 01:50:55 +02:00
trace_output ,
2016-07-27 17:41:21 +02:00
traces
2016-04-08 01:50:55 +02:00
) ,
2017-02-26 13:10:50 +01:00
Err ( ref e ) = > tracer . trace_failed_call ( trace_info , traces , e . into ( ) ) ,
2016-04-08 01:50:55 +02:00
} ;
2016-03-18 23:49:12 +01:00
2016-03-21 11:24:03 +01:00
trace! ( target : " executive " , " substate={:?}; unconfirmed_substate={:?} \n " , substate , unconfirmed_substate ) ;
2016-04-08 01:50:55 +02:00
self . enact_result ( & res , substate , unconfirmed_substate ) ;
2016-03-21 11:24:03 +01:00
trace! ( target : " executive " , " enacted: substate={:?} \n " , substate ) ;
2017-06-06 17:47:12 +02:00
res . map ( | r | ( r . gas_left , r . return_data ) )
2016-03-21 11:24:03 +01:00
} else {
// otherwise it's just a basic transaction, only do tracing, if necessary.
2016-10-22 15:22:16 +02:00
self . state . discard_checkpoint ( ) ;
2016-04-08 01:50:55 +02:00
2016-07-28 20:31:29 +02:00
tracer . trace_call ( trace_info , U256 ::zero ( ) , trace_output , vec! [ ] ) ;
2017-06-06 17:47:12 +02:00
Ok ( ( params . gas , ReturnData ::empty ( ) ) )
2016-03-21 11:24:03 +01:00
}
2016-01-09 22:54:16 +01:00
}
2016-01-07 19:05:44 +01:00
}
2016-02-09 16:31:57 +01:00
2016-01-09 21:39:38 +01:00
/// Creates contract with given contract params.
2016-01-11 02:17:29 +01:00
/// NOTE. It does not finalize the transaction (doesn't do refunds, nor suicides).
/// Modifies the substate.
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-08-01 12:37:57 +02:00
) -> vm ::Result < ( U256 , ReturnData ) > where T : Tracer , V : VMTracer {
2017-04-19 14:30:00 +02:00
2017-05-05 16:00:40 +02:00
let scheme = self . engine . create_address_scheme ( self . info . number ) ;
if scheme ! = CreateContractAddress ::FromSenderAndNonce & & self . state . exists_and_has_code ( & params . address ) ? {
2017-08-01 12:37:57 +02:00
return Err ( vm ::Error ::OutOfGas ) ;
2017-04-19 14:30:00 +02:00
}
2017-06-19 11:41:46 +02:00
if params . call_type = = CallType ::StaticCall | | self . static_flag {
let trace_info = tracer . prepare_trace_create ( & params ) ;
2017-08-01 12:37:57 +02:00
tracer . trace_failed_create ( trace_info , vec! [ ] , vm ::Error ::MutableCallInStaticContext . into ( ) ) ;
return Err ( vm ::Error ::MutableCallInStaticContext ) ;
2017-06-19 11:41:46 +02:00
}
2016-01-14 17:40:38 +01:00
// backup used in case of running out of gas
2016-10-22 15:22:16 +02:00
self . state . checkpoint ( ) ;
2016-01-14 17:40:38 +01:00
2016-01-15 00:54:19 +01:00
// part of substate that may be reverted
2016-04-08 01:50:55 +02:00
let mut unconfirmed_substate = Substate ::new ( ) ;
2016-01-15 00:54:19 +01:00
2016-01-29 18:33:47 +01:00
// create contract and transfer value to it if necessary
2017-05-05 16:00:40 +02:00
let schedule = self . engine . schedule ( self . info . number ) ;
2016-11-03 22:22:25 +01:00
let nonce_offset = if schedule . no_empty { 1 } else { 0 } . into ( ) ;
2017-02-26 13:10:50 +01:00
let prev_bal = self . state . balance ( & params . address ) ? ;
2016-01-20 17:27:33 +01:00
if let ActionValue ::Transfer ( val ) = params . value {
2017-06-28 09:10:57 +02:00
self . state . sub_balance ( & params . sender , & val , & mut substate . to_cleanup_mode ( & schedule ) ) ? ;
2016-11-03 22:22:25 +01:00
self . state . new_contract ( & params . address , val + prev_bal , nonce_offset ) ;
2016-01-29 18:33:47 +01:00
} else {
2016-11-03 22:22:25 +01:00
self . state . new_contract ( & params . address , prev_bal , nonce_offset ) ;
2016-01-20 16:52:22 +01:00
}
2016-01-09 17:55:47 +01:00
2016-04-08 01:50:55 +02:00
let trace_info = tracer . prepare_trace_create ( & params ) ;
let mut trace_output = tracer . prepare_trace_output ( ) ;
let mut subtracer = tracer . subtracer ( ) ;
let gas = params . gas ;
2016-03-18 23:49:12 +01:00
let created = params . address . clone ( ) ;
2016-07-26 20:31:25 +02:00
let mut subvmtracer = vm_tracer . prepare_subtrace ( params . code . as_ref ( ) . expect ( " two ways into create (Externalities::create and Executive::transact_with_tracer); both place `Some(...)` `code` in `params`; qed " ) ) ;
2016-06-02 12:40:31 +02:00
2016-01-14 17:40:38 +01:00
let res = {
2016-06-02 12:40:31 +02:00
self . exec_vm ( params , & mut unconfirmed_substate , OutputPolicy ::InitContract ( trace_output . as_mut ( ) ) , & mut subtracer , & mut subvmtracer )
2016-01-14 17:40:38 +01:00
} ;
2016-03-18 23:49:12 +01:00
2017-07-10 13:23:40 +02:00
vm_tracer . done_subtrace ( subvmtracer ) ;
2016-06-02 12:40:31 +02:00
2016-04-08 01:50:55 +02:00
match res {
2017-05-23 15:49:17 +02:00
Ok ( ref res ) = > tracer . trace_create (
2016-04-08 01:50:55 +02:00
trace_info ,
2017-05-23 15:49:17 +02:00
gas - res . gas_left ,
2016-04-08 01:50:55 +02:00
trace_output ,
created ,
2017-08-28 14:25:16 +02:00
subtracer . drain ( )
2016-04-08 01:50:55 +02:00
) ,
2017-08-28 14:25:16 +02:00
Err ( ref e ) = > tracer . trace_failed_create ( trace_info , subtracer . drain ( ) , e . into ( ) )
2016-04-08 01:50:55 +02:00
} ;
2016-03-18 23:49:12 +01:00
2016-04-08 01:50:55 +02:00
self . enact_result ( & res , substate , unconfirmed_substate ) ;
2017-06-06 17:47:12 +02:00
res . map ( | r | ( r . gas_left , r . return_data ) )
2016-01-07 19:05:44 +01:00
}
2016-01-09 21:39:38 +01:00
2016-01-09 22:54:16 +01:00
/// Finalizes the transaction (does refunds and suicides).
2016-06-02 12:40:31 +02:00
fn finalize (
& mut self ,
t : & SignedTransaction ,
2016-11-03 22:22:25 +01:00
mut substate : Substate ,
2017-08-01 12:37:57 +02:00
result : vm ::Result < ( U256 , ReturnData ) > ,
2016-06-02 12:40:31 +02:00
output : Bytes ,
2016-07-28 20:31:29 +02:00
trace : Vec < FlatTrace > ,
2016-06-02 12:40:31 +02:00
vm_trace : Option < VMTrace >
) -> ExecutionResult {
2017-04-19 14:30:00 +02:00
let schedule = self . engine . schedule ( self . info . number ) ;
2016-01-15 00:36:58 +01:00
// refunds from SSTORE nonzero -> zero
2016-01-16 20:11:12 +01:00
let sstore_refunds = U256 ::from ( schedule . sstore_refund_gas ) * substate . sstore_clears_count ;
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 ;
2016-01-15 00:36:58 +01:00
// real ammount to refund
2017-06-06 17:47:12 +02:00
let gas_left_prerefund = match result { Ok ( ( x , _ ) ) = > x , _ = > 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 ;
let gas_used = t . gas - gas_left ;
let refund_value = gas_left * t . gas_price ;
let fees_value = gas_used * t . gas_price ;
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 , & self . info . author ) ;
2017-02-26 13:10:50 +01:00
self . state . add_balance ( & self . info . author , & fees_value , substate . to_cleanup_mode ( & schedule ) ) ? ;
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 ) ;
}
2016-11-03 22:22:25 +01:00
// perform garbage-collection
2017-06-28 09:10:57 +02:00
let min_balance = if schedule . kill_dust ! = CleanDustMode ::Off { Some ( U256 ::from ( schedule . tx_gas ) * t . gas_price ) } else { None } ;
self . state . kill_garbage ( & substate . touched , schedule . kill_empty , & min_balance , schedule . kill_dust = = CleanDustMode ::WithCodeAndStorage ) ? ;
2016-11-03 22:22:25 +01: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 ) = > {
2016-01-11 17:37:22 +01:00
Ok ( Executed {
2017-01-12 11:06:12 +01:00
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 17:37:22 +01:00
} )
2016-01-11 15:55:54 +01:00
} ,
2016-01-15 18:56:28 +01:00
_ = > {
2016-01-11 16:05:21 +01:00
Ok ( Executed {
2017-01-12 11:06:12 +01:00
exception : None ,
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-11 16:05:21 +01:00
} )
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-14 17:40:38 +01:00
2017-08-01 12:37:57 +02:00
fn enact_result ( & mut self , result : & vm ::Result < FinalizationResult > , substate : & mut Substate , un_substate : Substate ) {
2016-01-17 15:56:09 +01:00
match * result {
2017-08-01 12:37:57 +02:00
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 )
2017-05-23 15:49:17 +02:00
| Ok ( FinalizationResult { apply_state : false , .. } ) = > {
2016-10-22 15:22:16 +02:00
self . state . revert_to_checkpoint ( ) ;
2016-01-15 00:04:40 +01:00
} ,
2017-08-01 12:37:57 +02:00
Ok ( _ ) | Err ( vm ::Error ::Internal ( _ ) ) = > {
2016-10-22 15:22:16 +02:00
self . state . discard_checkpoint ( ) ;
2016-04-08 01:50:55 +02:00
substate . accrue ( un_substate ) ;
2016-02-03 19:34:51 +01:00
}
2016-01-14 17:40: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-11-28 17:05:37 +01:00
use std ::sync ::Arc ;
2017-07-29 17:12:07 +02:00
use std ::str ::FromStr ;
2017-07-06 11:26:14 +02:00
use rustc_hex ::FromHex ;
2016-08-24 18:35:21 +02:00
use ethkey ::{ Generator , Random } ;
2016-01-11 17:49:49 +01:00
use super ::* ;
2017-07-29 17:12:07 +02:00
use util ::{ H256 , U256 , U512 , Address } ;
2016-11-28 17:05:37 +01:00
use util ::bytes ::BytesRef ;
2017-08-01 12:37:57 +02:00
use vm ::{ ActionParams , ActionValue , CallType , EnvInfo , CreateContractAddress } ;
use evm ::{ Factory , VMType } ;
2016-10-24 18:35:25 +02:00
use error ::ExecutionError ;
2016-11-03 22:22:25 +01:00
use state ::{ Substate , CleanupMode } ;
2016-01-31 10:52:07 +01:00
use tests ::helpers ::* ;
2016-04-30 17:41:24 +02:00
use trace ::trace ;
2016-07-28 20:31:29 +02:00
use trace ::{ FlatTrace , Tracer , NoopTracer , ExecutiveTracer } ;
2016-06-02 12:40:31 +02:00
use trace ::{ VMTrace , VMOperation , VMExecutedOperation , MemoryDiff , StorageDiff , VMTracer , NoopVMTracer , ExecutiveVMTracer } ;
2016-10-24 18:35:25 +02:00
use transaction ::{ Action , Transaction } ;
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 ) , & [ ] ) . 0 ) ;
2016-01-07 23:33:54 +01:00
}
2016-01-09 01:33:50 +01:00
2016-01-09 13:51:59 +01:00
// TODO: replace params with transactions!
2016-01-14 16:17:44 +01:00
evm_test! { test_sender_balance : test_sender_balance_jit , test_sender_balance_int }
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 ( ) , & [ ] ) . 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 ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-09 02:12:17 +01:00
2017-06-06 17:47:12 +02:00
let ( gas_left , _ ) = {
2017-05-30 11:52:33 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine ) ;
2016-06-02 12:40:31 +02:00
ex . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer ) . unwrap ( )
2016-01-12 13:39:12 +01:00
} ;
2016-01-09 02:12:17 +01: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
// 0 cause contract hasn't returned
assert_eq! ( substate . contracts_created . len ( ) , 0 ) ;
2016-01-11 17:37:22 +01:00
// TODO: just test state root.
2016-01-09 01:33:50 +01:00
}
2016-01-09 13:51:59 +01:00
2016-03-19 21:02:44 +01:00
evm_test! { test_create_contract_out_of_depth : test_create_contract_out_of_depth_jit , test_create_contract_out_of_depth_int }
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
2016-01-12 13:39:12 +01:00
let code = " 7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055 " . from_hex ( ) . unwrap ( ) ;
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 ( ) , & [ ] ) . 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 ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-09 13:51:59 +01:00
2017-06-06 17:47:12 +02:00
let ( gas_left , _ ) = {
2017-05-30 11:52:33 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine ) ;
2016-06-02 12:40:31 +02:00
ex . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer ) . unwrap ( )
2016-01-12 13:39:12 +01:00
} ;
2016-02-09 16:31:57 +01: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 ) ;
}
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
let code = " 7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0600055 " . from_hex ( ) . unwrap ( ) ;
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
2017-06-30 11:30:32 +02:00
let address = contract_address ( CreateContractAddress ::FromSenderAndNonce , & sender , & U256 ::zero ( ) , & [ ] ) . 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 ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 5 ) ;
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 ( ) ;
2016-03-19 21:02:44 +01:00
2017-06-06 17:47:12 +02:00
let ( gas_left , _ ) = {
2017-05-30 11:52:33 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine ) ;
2016-03-19 21:02:44 +01:00
let output = BytesRef ::Fixed ( & mut [ 0 u8 ; 0 ] ) ;
2016-06-02 12:40:31 +02:00
ex . call ( params , & mut substate , output , & mut tracer , & mut vm_tracer ) . unwrap ( )
2016-03-19 21:02:44 +01:00
} ;
2016-06-02 12:40:31 +02:00
assert_eq! ( gas_left , U256 ::from ( 44_752 ) ) ;
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 ]
} ) ,
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
} ] ;
2016-07-28 20:31:29 +02:00
2017-08-28 14:25:16 +02:00
assert_eq! ( tracer . drain ( ) , expected_trace ) ;
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
}
2016-09-28 23:33:12 +02:00
#[ test ]
fn test_create_contract ( ) {
// Tracing is not supported in JIT
2016-03-19 22:12:52 +01:00
// 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
let code = " 601080600c6000396000f3006000355415600957005b60203560003555 " . from_hex ( ) . unwrap ( ) ;
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
2017-06-30 11:30:32 +02:00
let address = contract_address ( CreateContractAddress ::FromSenderAndNonce , & sender , & U256 ::zero ( ) , & [ ] ) . 0 ;
2016-03-19 22:12:52 +01:00
// TODO: add tests for 'callcreate'
//let next_address = contract_address(&address, &U256::zero());
let mut params = ActionParams ::default ( ) ;
params . address = address . clone ( ) ;
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-05-31 16:59:01 +02:00
params . value = ActionValue ::Transfer ( 100. into ( ) ) ;
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 22:12:52 +01:00
let info = EnvInfo ::default ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 5 ) ;
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 ( ) ;
2016-03-19 22:12:52 +01:00
2017-06-06 17:47:12 +02:00
let ( gas_left , _ ) = {
2017-05-30 11:52:33 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine ) ;
2016-06-02 12:40:31 +02:00
ex . create ( params . clone ( ) , & mut substate , & mut tracer , & mut vm_tracer ) . unwrap ( )
2016-03-19 22:12:52 +01:00
} ;
2016-06-02 12:40:31 +02:00
assert_eq! ( gas_left , U256 ::from ( 96_776 ) ) ;
2016-07-28 20:31:29 +02:00
let expected_trace = vec! [ FlatTrace {
trace_address : Default ::default ( ) ,
subtraces : 0 ,
2016-04-30 17:41:24 +02:00
action : trace ::Action ::Create ( trace ::Create {
2016-03-19 22:12:52 +01:00
from : params . sender ,
2016-05-31 16:59:01 +02:00
value : 100. into ( ) ,
2016-03-19 22:12:52 +01:00
gas : params . gas ,
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 ] ,
2016-04-08 01:50:55 +02:00
} ) ,
2016-04-30 17:41:24 +02:00
result : trace ::Res ::Create ( trace ::CreateResult {
2016-04-08 01:50:55 +02:00
gas_used : U256 ::from ( 3224 ) ,
address : params . address ,
code : vec ! [ 96 , 0 , 53 , 84 , 21 , 96 , 9 , 87 , 0 , 91 , 96 , 32 , 53 , 96 , 0 , 53 ]
2016-03-19 22:12:52 +01:00
} ) ,
2016-04-08 01:50:55 +02:00
} ] ;
2016-07-28 20:31:29 +02:00
2017-08-28 14:25:16 +02:00
assert_eq! ( tracer . drain ( ) , expected_trace ) ;
2016-06-02 19:04:15 +02:00
2016-06-02 12:40:31 +02:00
let expected_vm_trace = VMTrace {
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 ] ,
operations : vec ! [
VMOperation { pc : 0 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99997. 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 : 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 ] } ) , store_diff : None } ) } ,
VMOperation { pc : 8 , instruction : 96 , gas_cost : 3. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99976. into ( ) , stack_push : vec_into ! [ 0 ] , mem_diff : None , store_diff : None } ) } ,
VMOperation { pc : 10 , instruction : 243 , gas_cost : 0. into ( ) , executed : Some ( VMExecutedOperation { gas_used : 99976. 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 22:12:52 +01:00
}
2016-03-21 11:24:03 +01:00
2016-01-14 16:17:44 +01:00
evm_test! { test_create_contract_value_too_high : test_create_contract_value_too_high_jit , test_create_contract_value_too_high_int }
fn test_create_contract_value_too_high ( factory : Factory ) {
2016-01-13 13:16:53 +01:00
// code:
//
// 7c 601080600c6000396000f3006000355415600957005b60203560003555 - push 29 bytes?
// 60 00 - push 0
// 52
// 60 1d - push 29
// 60 03 - push 3
// 60 e6 - push 230
// f0 - create a contract trying to send 230.
// 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
let code = " 7c601080600c6000396000f3006000355415600957005b60203560003555600052601d600360e6f0600055 " . from_hex ( ) . unwrap ( ) ;
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
2017-06-30 11:30:32 +02:00
let address = contract_address ( CreateContractAddress ::FromSenderAndNonce , & sender , & U256 ::zero ( ) , & [ ] ) . 0 ;
2016-01-13 13:16:53 +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-13 13:16:53 +01:00
params . address = address . clone ( ) ;
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-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 ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-13 13:16:53 +01:00
2017-06-06 17:47:12 +02:00
let ( gas_left , _ ) = {
2017-05-30 11:52:33 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine ) ;
2016-06-02 12:40:31 +02:00
ex . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer ) . unwrap ( )
2016-01-13 13:16:53 +01:00
} ;
2016-02-09 16:31:57 +01:00
2016-01-13 13:16:53 +01:00
assert_eq! ( gas_left , U256 ::from ( 62_976 ) ) ;
2016-01-12 16:05:54 +01:00
assert_eq! ( substate . contracts_created . len ( ) , 0 ) ;
}
2016-01-14 16:17:44 +01:00
evm_test! { test_create_contract_without_max_depth : test_create_contract_without_max_depth_jit , test_create_contract_without_max_depth_int }
fn test_create_contract_without_max_depth ( factory : Factory ) {
2016-01-12 16:05:54 +01:00
// code:
//
// 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
//
// 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
2016-01-14 12:33:49 +01:00
let code = " 7c601080600c6000396000f3006000355415600957005b60203560003555600052601d60036017f0 " . from_hex ( ) . unwrap ( ) ;
2016-01-12 16:05:54 +01: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 ( ) , & [ ] ) . 0 ;
let next_address = contract_address ( CreateContractAddress ::FromSenderAndNonce , & address , & U256 ::zero ( ) , & [ ] ) . 0 ;
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 16:05:54 +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 ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 1024 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-09 13:51:59 +01:00
{
2017-05-30 11:52:33 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine ) ;
2016-06-02 12:40:31 +02:00
ex . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer ) . unwrap ( ) ;
2016-01-09 13:51:59 +01:00
}
2016-02-09 16:31:57 +01:00
2016-01-12 16:05:54 +01:00
assert_eq! ( substate . contracts_created . len ( ) , 1 ) ;
assert_eq! ( substate . contracts_created [ 0 ] , next_address ) ;
2016-01-12 13:39:12 +01: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
2016-01-16 04:59:53 +01:00
evm_test_ignore! { test_aba_calls : test_aba_calls_jit , 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
// 55 - sstore
let code_a = " 6000600060006000601873945304eb96065b2a98b57a48a06ae28d285a71b56103e8f15855 " . from_hex ( ) . unwrap ( ) ;
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
// 60 00 - push 0
// 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 ( ) ;
let address_a = Address ::from_str ( " 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 " ) . unwrap ( ) ;
let address_b = Address ::from_str ( " 945304eb96065b2a98b57a48a06ae28d285a71b5 " ) . unwrap ( ) ;
let sender = Address ::from_str ( " cd1722f3947def4cf144679da39c4c32bdc35681 " ) . unwrap ( ) ;
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 ) ) ;
2016-01-12 13:39:12 +01: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 ( ) ;
2016-01-12 13:39:12 +01:00
2016-02-02 23:06:34 +01:00
let info = EnvInfo ::default ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-12 13:39:12 +01:00
2017-06-06 17:47:12 +02:00
let ( gas_left , _ ) = {
2017-05-30 11:52:33 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine ) ;
2016-06-02 12:40:31 +02:00
ex . call ( params , & mut substate , BytesRef ::Fixed ( & mut [ ] ) , & mut NoopTracer , & mut NoopVMTracer ) . unwrap ( )
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
}
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
2016-01-16 04:59:53 +01:00
evm_test_ignore! { test_recursive_bomb1 : test_recursive_bomb1_jit , 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 ( ) , & [ ] ) . 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 ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-10 16:21:01 +01:00
2017-06-06 17:47:12 +02:00
let ( gas_left , _ ) = {
2017-05-30 11:52:33 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine ) ;
2016-06-02 12:40:31 +02:00
ex . call ( params , & mut substate , BytesRef ::Fixed ( & mut [ ] ) , & mut NoopTracer , & mut NoopVMTracer ) . unwrap ( )
2016-01-12 13:39:12 +01:00
} ;
2016-01-10 16:21:01 +01: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 ( ) ) ) . unwrap ( ) , H256 ::from ( & U256 ::from ( 1 ) ) ) ;
2016-01-09 13:51:59 +01:00
}
2016-01-12 18:31:47 +01: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
2016-01-16 04:59:53 +01:00
evm_test_ignore! { test_transact_simple : test_transact_simple_jit , 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 ( ) , & [ ] ) . 0 ;
2016-01-12 18:31:47 +01: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 ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-01-12 18:31:47 +01:00
let executed = {
2017-05-30 11:52:33 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine ) ;
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
} ;
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
}
2016-01-14 16:17:44 +01:00
evm_test! { test_transact_invalid_nonce : test_transact_invalid_nonce_jit , test_transact_invalid_nonce_int }
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 ( ) ;
2016-02-04 23:48:29 +01: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 ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-01-12 19:43:26 +01:00
let res = {
2017-05-30 11:52:33 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine ) ;
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
} ;
2016-02-09 16:31:57 +01: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 ( ) = > ( ) ,
2016-01-12 19:43:26 +01:00
_ = > assert! ( false , " Expected invalid nonce error. " )
}
}
2016-01-14 16:17:44 +01:00
evm_test! { test_transact_gas_limit_reached : test_transact_gas_limit_reached_jit , test_transact_gas_limit_reached_int }
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 ( ) ;
2016-01-12 19:43:26 +01: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 ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-01-12 19:43:26 +01:00
let res = {
2017-05-30 11:52:33 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine ) ;
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
} ;
match res {
2016-05-14 14:28:44 +02:00
Err ( ExecutionError ::BlockGasLimitReached { gas_limit , gas_used , gas } )
2016-02-09 16:31:57 +01:00
if gas_limit = = U256 ::from ( 100_000 ) & & gas_used = = U256 ::from ( 20_000 ) & & gas = = U256 ::from ( 80_001 ) = > ( ) ,
2016-01-12 19:43:26 +01:00
_ = > assert! ( false , " Expected block gas limit error. " )
}
}
2016-01-14 16:17:44 +01:00
evm_test! { test_not_enough_cash : test_not_enough_cash_jit , test_not_enough_cash_int }
fn test_not_enough_cash ( factory : Factory ) {
2016-02-04 23:48:29 +01:00
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 ( ) ;
2016-01-12 19:43:26 +01: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 ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-01-12 18:31:47 +01:00
let res = {
2017-05-30 11:52:33 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine ) ;
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
} ;
2016-02-09 16:31:57 +01: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 ) = > ( ) ,
2016-01-13 13:16:53 +01:00
_ = > assert! ( false , " Expected not enough cash error. {:?} " , res )
2016-01-10 16:21:01 +01:00
}
2016-01-09 13:51:59 +01:00
}
2016-01-15 23:32:16 +01:00
2017-08-30 19:18:28 +02:00
evm_test! { test_keccak : test_keccak_jit , test_keccak_int }
fn test_keccak ( factory : Factory ) {
2016-01-15 23:32:16 +01:00
let code = " 6064640fffffffff20600055 " . from_hex ( ) . unwrap ( ) ;
let sender = Address ::from_str ( " 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6 " ) . unwrap ( ) ;
2017-06-30 11:30:32 +02:00
let address = contract_address ( CreateContractAddress ::FromSenderAndNonce , & sender , & U256 ::zero ( ) , & [ ] ) . 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 ) . unwrap ( ) ;
2016-02-02 23:06:34 +01:00
let info = EnvInfo ::default ( ) ;
2016-05-19 00:44:49 +02:00
let engine = TestEngine ::new ( 0 ) ;
2016-04-08 01:50:55 +02:00
let mut substate = Substate ::new ( ) ;
2016-01-15 23:32:16 +01:00
let result = {
2017-05-30 11:52:33 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine ) ;
2016-06-02 12:40:31 +02:00
ex . create ( params , & mut substate , & mut NoopTracer , & mut NoopVMTracer )
2016-01-15 23:32:16 +01:00
} ;
match result {
2017-05-23 15:49:17 +02:00
Err ( _ ) = > { } ,
_ = > panic! ( " Expected OutOfGas " ) ,
2016-01-15 23:32:16 +01:00
}
}
2017-05-23 15:49:17 +02:00
evm_test! { test_revert : test_revert_jit , test_revert_int }
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 ) . unwrap ( ) ;
state . commit ( ) . unwrap ( ) ;
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 ( ) ) ;
2017-05-30 11:52:33 +02:00
let mut state = get_temp_state_with_factory ( factory ) ;
2017-05-23 15:49:17 +02:00
state . add_balance ( & sender , & U256 ::from_str ( " 152d02c7e14af68000000 " ) . unwrap ( ) , CleanupMode ::NoEmpty ) . unwrap ( ) ;
let info = EnvInfo ::default ( ) ;
let engine = TestEngine ::new_metropolis ( ) ;
let mut substate = Substate ::new ( ) ;
let mut output = [ 0 u8 ; 14 ] ;
2017-06-06 17:47:12 +02:00
let ( result , _ ) = {
2017-05-30 11:52:33 +02:00
let mut ex = Executive ::new ( & mut state , & info , & engine ) ;
2017-05-23 15:49:17 +02:00
ex . call ( params , & mut substate , BytesRef ::Fixed ( & mut output ) , & mut NoopTracer , & mut NoopVMTracer ) . unwrap ( )
} ;
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 ) ) ) ;
}
2016-01-07 23:33:54 +01:00
}