2018-06-04 10:19:50 +02:00
// Copyright 2015-2018 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-13 00:13:09 +01:00
//! VM Instructions list and utility functions
2018-06-27 13:33:32 +02:00
pub use self ::Instruction ::* ;
2016-01-13 00:13:09 +01:00
2018-06-27 13:33:32 +02:00
macro_rules ! enum_with_from_u8 {
(
$( #[ $enum_attr:meta ] ) *
pub enum $name :ident {
$( $( #[ $variant_attr:meta ] ) * $variant :ident = $discriminator :expr ) , + ,
}
) = > {
$( #[ $enum_attr ] ) *
pub enum $name {
$( $( #[ $variant_attr ] ) * $variant = $discriminator ) , + ,
}
2016-01-13 00:13:09 +01:00
2018-06-27 13:33:32 +02:00
impl $name {
#[ doc = " Convert from u8 to the given enum " ]
pub fn from_u8 ( value : u8 ) -> Option < Self > {
match value {
$( $discriminator = > Some ( $variant ) ) , + ,
_ = > None ,
}
}
}
} ;
2017-05-30 19:31:43 +02:00
}
2018-06-27 13:33:32 +02:00
enum_with_from_u8! {
#[ doc = " Virtual machine bytecode instruction. " ]
#[ repr(u8) ]
2018-09-17 16:16:49 +02:00
#[ derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug, Hash) ]
2018-06-27 13:33:32 +02:00
pub enum Instruction {
#[ doc = " halts execution " ]
STOP = 0x00 ,
#[ doc = " addition operation " ]
ADD = 0x01 ,
#[ doc = " mulitplication operation " ]
MUL = 0x02 ,
#[ doc = " subtraction operation " ]
SUB = 0x03 ,
#[ doc = " integer division operation " ]
DIV = 0x04 ,
#[ doc = " signed integer division operation " ]
SDIV = 0x05 ,
#[ doc = " modulo remainder operation " ]
MOD = 0x06 ,
#[ doc = " signed modulo remainder operation " ]
SMOD = 0x07 ,
#[ doc = " unsigned modular addition " ]
ADDMOD = 0x08 ,
#[ doc = " unsigned modular multiplication " ]
MULMOD = 0x09 ,
#[ doc = " exponential operation " ]
EXP = 0x0a ,
#[ doc = " extend length of signed integer " ]
SIGNEXTEND = 0x0b ,
#[ doc = " less-than comparision " ]
LT = 0x10 ,
#[ doc = " greater-than comparision " ]
GT = 0x11 ,
#[ doc = " signed less-than comparision " ]
SLT = 0x12 ,
#[ doc = " signed greater-than comparision " ]
SGT = 0x13 ,
#[ doc = " equality comparision " ]
EQ = 0x14 ,
#[ doc = " simple not operator " ]
ISZERO = 0x15 ,
#[ doc = " bitwise AND operation " ]
AND = 0x16 ,
#[ doc = " bitwise OR operation " ]
OR = 0x17 ,
#[ doc = " bitwise XOR operation " ]
XOR = 0x18 ,
#[ doc = " bitwise NOT opertation " ]
NOT = 0x19 ,
#[ doc = " retrieve single byte from word " ]
BYTE = 0x1a ,
#[ doc = " shift left operation " ]
SHL = 0x1b ,
#[ doc = " logical shift right operation " ]
SHR = 0x1c ,
#[ doc = " arithmetic shift right operation " ]
SAR = 0x1d ,
#[ doc = " compute SHA3-256 hash " ]
SHA3 = 0x20 ,
#[ doc = " get address of currently executing account " ]
ADDRESS = 0x30 ,
#[ doc = " get balance of the given account " ]
BALANCE = 0x31 ,
#[ doc = " get execution origination address " ]
ORIGIN = 0x32 ,
#[ doc = " get caller address " ]
CALLER = 0x33 ,
#[ doc = " get deposited value by the instruction/transaction responsible for this execution " ]
CALLVALUE = 0x34 ,
#[ doc = " get input data of current environment " ]
CALLDATALOAD = 0x35 ,
#[ doc = " get size of input data in current environment " ]
CALLDATASIZE = 0x36 ,
#[ doc = " copy input data in current environment to memory " ]
CALLDATACOPY = 0x37 ,
#[ doc = " get size of code running in current environment " ]
CODESIZE = 0x38 ,
#[ doc = " copy code running in current environment to memory " ]
CODECOPY = 0x39 ,
#[ doc = " get price of gas in current environment " ]
GASPRICE = 0x3a ,
#[ doc = " get external code size (from another contract) " ]
EXTCODESIZE = 0x3b ,
#[ doc = " copy external code (from another contract) " ]
EXTCODECOPY = 0x3c ,
#[ doc = " get the size of the return data buffer for the last call " ]
RETURNDATASIZE = 0x3d ,
#[ doc = " copy return data buffer to memory " ]
RETURNDATACOPY = 0x3e ,
2018-07-31 07:27:57 +02:00
#[ doc = " return the keccak256 hash of contract code " ]
EXTCODEHASH = 0x3f ,
2018-06-27 13:33:32 +02:00
#[ doc = " get hash of most recent complete block " ]
BLOCKHASH = 0x40 ,
#[ doc = " get the block's coinbase address " ]
COINBASE = 0x41 ,
#[ doc = " get the block's timestamp " ]
TIMESTAMP = 0x42 ,
#[ doc = " get the block's number " ]
NUMBER = 0x43 ,
#[ doc = " get the block's difficulty " ]
DIFFICULTY = 0x44 ,
#[ doc = " get the block's gas limit " ]
GASLIMIT = 0x45 ,
#[ doc = " remove item from stack " ]
POP = 0x50 ,
#[ doc = " load word from memory " ]
MLOAD = 0x51 ,
#[ doc = " save word to memory " ]
MSTORE = 0x52 ,
#[ doc = " save byte to memory " ]
MSTORE8 = 0x53 ,
#[ doc = " load word from storage " ]
SLOAD = 0x54 ,
#[ doc = " save word to storage " ]
SSTORE = 0x55 ,
#[ doc = " alter the program counter " ]
JUMP = 0x56 ,
#[ doc = " conditionally alter the program counter " ]
JUMPI = 0x57 ,
#[ doc = " get the program counter " ]
PC = 0x58 ,
#[ doc = " get the size of active memory " ]
MSIZE = 0x59 ,
#[ doc = " get the amount of available gas " ]
GAS = 0x5a ,
#[ doc = " set a potential jump destination " ]
JUMPDEST = 0x5b ,
#[ doc = " place 1 byte item on stack " ]
PUSH1 = 0x60 ,
#[ doc = " place 2 byte item on stack " ]
PUSH2 = 0x61 ,
#[ doc = " place 3 byte item on stack " ]
PUSH3 = 0x62 ,
#[ doc = " place 4 byte item on stack " ]
PUSH4 = 0x63 ,
#[ doc = " place 5 byte item on stack " ]
PUSH5 = 0x64 ,
#[ doc = " place 6 byte item on stack " ]
PUSH6 = 0x65 ,
#[ doc = " place 7 byte item on stack " ]
PUSH7 = 0x66 ,
#[ doc = " place 8 byte item on stack " ]
PUSH8 = 0x67 ,
#[ doc = " place 9 byte item on stack " ]
PUSH9 = 0x68 ,
#[ doc = " place 10 byte item on stack " ]
PUSH10 = 0x69 ,
#[ doc = " place 11 byte item on stack " ]
PUSH11 = 0x6a ,
#[ doc = " place 12 byte item on stack " ]
PUSH12 = 0x6b ,
#[ doc = " place 13 byte item on stack " ]
PUSH13 = 0x6c ,
#[ doc = " place 14 byte item on stack " ]
PUSH14 = 0x6d ,
#[ doc = " place 15 byte item on stack " ]
PUSH15 = 0x6e ,
#[ doc = " place 16 byte item on stack " ]
PUSH16 = 0x6f ,
#[ doc = " place 17 byte item on stack " ]
PUSH17 = 0x70 ,
#[ doc = " place 18 byte item on stack " ]
PUSH18 = 0x71 ,
#[ doc = " place 19 byte item on stack " ]
PUSH19 = 0x72 ,
#[ doc = " place 20 byte item on stack " ]
PUSH20 = 0x73 ,
#[ doc = " place 21 byte item on stack " ]
PUSH21 = 0x74 ,
#[ doc = " place 22 byte item on stack " ]
PUSH22 = 0x75 ,
#[ doc = " place 23 byte item on stack " ]
PUSH23 = 0x76 ,
#[ doc = " place 24 byte item on stack " ]
PUSH24 = 0x77 ,
#[ doc = " place 25 byte item on stack " ]
PUSH25 = 0x78 ,
#[ doc = " place 26 byte item on stack " ]
PUSH26 = 0x79 ,
#[ doc = " place 27 byte item on stack " ]
PUSH27 = 0x7a ,
#[ doc = " place 28 byte item on stack " ]
PUSH28 = 0x7b ,
#[ doc = " place 29 byte item on stack " ]
PUSH29 = 0x7c ,
#[ doc = " place 30 byte item on stack " ]
PUSH30 = 0x7d ,
#[ doc = " place 31 byte item on stack " ]
PUSH31 = 0x7e ,
#[ doc = " place 32 byte item on stack " ]
PUSH32 = 0x7f ,
#[ doc = " copies the highest item in the stack to the top of the stack " ]
DUP1 = 0x80 ,
#[ doc = " copies the second highest item in the stack to the top of the stack " ]
DUP2 = 0x81 ,
#[ doc = " copies the third highest item in the stack to the top of the stack " ]
DUP3 = 0x82 ,
#[ doc = " copies the 4th highest item in the stack to the top of the stack " ]
DUP4 = 0x83 ,
#[ doc = " copies the 5th highest item in the stack to the top of the stack " ]
DUP5 = 0x84 ,
#[ doc = " copies the 6th highest item in the stack to the top of the stack " ]
DUP6 = 0x85 ,
#[ doc = " copies the 7th highest item in the stack to the top of the stack " ]
DUP7 = 0x86 ,
#[ doc = " copies the 8th highest item in the stack to the top of the stack " ]
DUP8 = 0x87 ,
#[ doc = " copies the 9th highest item in the stack to the top of the stack " ]
DUP9 = 0x88 ,
#[ doc = " copies the 10th highest item in the stack to the top of the stack " ]
DUP10 = 0x89 ,
#[ doc = " copies the 11th highest item in the stack to the top of the stack " ]
DUP11 = 0x8a ,
#[ doc = " copies the 12th highest item in the stack to the top of the stack " ]
DUP12 = 0x8b ,
#[ doc = " copies the 13th highest item in the stack to the top of the stack " ]
DUP13 = 0x8c ,
#[ doc = " copies the 14th highest item in the stack to the top of the stack " ]
DUP14 = 0x8d ,
#[ doc = " copies the 15th highest item in the stack to the top of the stack " ]
DUP15 = 0x8e ,
#[ doc = " copies the 16th highest item in the stack to the top of the stack " ]
DUP16 = 0x8f ,
#[ doc = " swaps the highest and second highest value on the stack " ]
SWAP1 = 0x90 ,
#[ doc = " swaps the highest and third highest value on the stack " ]
SWAP2 = 0x91 ,
#[ doc = " swaps the highest and 4th highest value on the stack " ]
SWAP3 = 0x92 ,
#[ doc = " swaps the highest and 5th highest value on the stack " ]
SWAP4 = 0x93 ,
#[ doc = " swaps the highest and 6th highest value on the stack " ]
SWAP5 = 0x94 ,
#[ doc = " swaps the highest and 7th highest value on the stack " ]
SWAP6 = 0x95 ,
#[ doc = " swaps the highest and 8th highest value on the stack " ]
SWAP7 = 0x96 ,
#[ doc = " swaps the highest and 9th highest value on the stack " ]
SWAP8 = 0x97 ,
#[ doc = " swaps the highest and 10th highest value on the stack " ]
SWAP9 = 0x98 ,
#[ doc = " swaps the highest and 11th highest value on the stack " ]
SWAP10 = 0x99 ,
#[ doc = " swaps the highest and 12th highest value on the stack " ]
SWAP11 = 0x9a ,
#[ doc = " swaps the highest and 13th highest value on the stack " ]
SWAP12 = 0x9b ,
#[ doc = " swaps the highest and 14th highest value on the stack " ]
SWAP13 = 0x9c ,
#[ doc = " swaps the highest and 15th highest value on the stack " ]
SWAP14 = 0x9d ,
#[ doc = " swaps the highest and 16th highest value on the stack " ]
SWAP15 = 0x9e ,
#[ doc = " swaps the highest and 17th highest value on the stack " ]
SWAP16 = 0x9f ,
#[ doc = " Makes a log entry, no topics. " ]
LOG0 = 0xa0 ,
#[ doc = " Makes a log entry, 1 topic. " ]
LOG1 = 0xa1 ,
#[ doc = " Makes a log entry, 2 topics. " ]
LOG2 = 0xa2 ,
#[ doc = " Makes a log entry, 3 topics. " ]
LOG3 = 0xa3 ,
#[ doc = " Makes a log entry, 4 topics. " ]
LOG4 = 0xa4 ,
#[ doc = " create a new account with associated code " ]
CREATE = 0xf0 ,
#[ doc = " message-call into an account " ]
CALL = 0xf1 ,
#[ doc = " message-call with another account's code only " ]
CALLCODE = 0xf2 ,
#[ doc = " halt execution returning output data " ]
RETURN = 0xf3 ,
#[ doc = " like CALLCODE but keeps caller's value and sender " ]
DELEGATECALL = 0xf4 ,
#[ doc = " create a new account and set creation address to sha3(sender + sha3(init code)) % 2**160 " ]
2018-08-31 17:43:51 +02:00
CREATE2 = 0xf5 ,
2018-06-27 13:33:32 +02:00
#[ doc = " stop execution and revert state changes. Return output data. " ]
REVERT = 0xfd ,
#[ doc = " like CALL but it does not take value, nor modify the state " ]
STATICCALL = 0xfa ,
#[ doc = " halt execution and register account for later deletion " ]
SUICIDE = 0xff ,
}
2016-01-13 00:13:09 +01:00
}
2018-06-27 13:33:32 +02:00
impl Instruction {
/// Returns true if given instruction is `PUSHN` instruction.
pub fn is_push ( & self ) -> bool {
* self > = PUSH1 & & * self < = PUSH32
2017-06-09 12:31:03 +02:00
}
2018-06-27 13:33:32 +02:00
/// Returns number of bytes to read for `PUSHN` instruction
/// PUSH1 -> 1
pub fn push_bytes ( & self ) -> Option < usize > {
if self . is_push ( ) {
Some ( ( ( * self as u8 ) - ( PUSH1 as u8 ) + 1 ) as usize )
} else {
None
}
}
2016-01-13 15:21:13 +01:00
2016-01-13 00:13:09 +01:00
2018-06-27 13:33:32 +02:00
/// Returns stack position of item to duplicate
/// DUP1 -> 0
pub fn dup_position ( & self ) -> Option < usize > {
if * self > = DUP1 & & * self < = DUP16 {
Some ( ( ( * self as u8 ) - ( DUP1 as u8 ) ) as usize )
} else {
None
}
}
2016-01-13 15:21:13 +01:00
2016-01-13 00:13:09 +01:00
2018-06-27 13:33:32 +02:00
/// Returns stack position of item to SWAP top with
/// SWAP1 -> 1
pub fn swap_position ( & self ) -> Option < usize > {
if * self > = SWAP1 & & * self < = SWAP16 {
Some ( ( ( * self as u8 ) - ( SWAP1 as u8 ) + 1 ) as usize )
} else {
None
}
}
2016-01-13 15:21:13 +01:00
2018-06-27 13:33:32 +02:00
/// Returns number of topics to take from stack
/// LOG0 -> 0
pub fn log_topics ( & self ) -> Option < usize > {
if * self > = LOG0 & & * self < = LOG4 {
Some ( ( ( * self as u8 ) - ( LOG0 as u8 ) ) as usize )
} else {
None
}
}
2016-01-13 00:13:09 +01:00
2018-06-27 13:33:32 +02:00
/// Returns the instruction info.
pub fn info ( & self ) -> & 'static InstructionInfo {
INSTRUCTIONS [ * self as usize ] . as_ref ( ) . expect ( " A instruction is defined in Instruction enum, but it is not found in InstructionInfo struct; this indicates a logic failure in the code. " )
}
2016-01-13 15:21:13 +01:00
}
2016-07-05 15:15:44 +02:00
#[ derive(PartialEq, Clone, Copy) ]
2016-01-13 15:21:13 +01:00
pub enum GasPriceTier {
/// 0 Zero
2016-01-16 17:08:57 +01:00
Zero ,
2016-01-13 15:21:13 +01:00
/// 2 Quick
2016-01-16 17:08:57 +01:00
Base ,
2016-01-13 15:21:13 +01:00
/// 3 Fastest
2016-01-16 17:08:57 +01:00
VeryLow ,
2016-01-13 15:21:13 +01:00
/// 5 Fast
2016-01-16 17:08:57 +01:00
Low ,
2016-01-13 15:21:13 +01:00
/// 8 Mid
2016-01-16 17:08:57 +01:00
Mid ,
2016-01-13 15:21:13 +01:00
/// 10 Slow
2016-01-16 17:08:57 +01:00
High ,
2016-01-13 15:21:13 +01:00
/// 20 Ext
2016-01-16 17:08:57 +01:00
Ext ,
2016-01-13 15:21:13 +01:00
/// Multiparam or otherwise special
2016-01-16 17:08:57 +01:00
Special ,
2016-07-11 16:18:27 +02:00
}
2018-06-27 13:33:32 +02:00
impl GasPriceTier {
/// Returns the index in schedule for specific `GasPriceTier`
pub fn idx ( & self ) -> usize {
match self {
& GasPriceTier ::Zero = > 0 ,
& GasPriceTier ::Base = > 1 ,
& GasPriceTier ::VeryLow = > 2 ,
& GasPriceTier ::Low = > 3 ,
& GasPriceTier ::Mid = > 4 ,
& GasPriceTier ::High = > 5 ,
& GasPriceTier ::Ext = > 6 ,
& GasPriceTier ::Special = > 7 ,
}
2016-01-13 15:21:13 +01:00
}
}
2017-06-12 22:34:51 +02:00
/// EVM instruction information.
2018-06-27 13:33:32 +02:00
#[ derive(Copy, Clone) ]
2016-01-13 15:21:13 +01:00
pub struct InstructionInfo {
2017-06-12 22:34:51 +02:00
/// Mnemonic name.
2016-01-13 15:21:13 +01:00
pub name : & 'static str ,
2017-06-12 22:34:51 +02:00
/// Number of stack arguments.
2016-01-13 15:21:13 +01:00
pub args : usize ,
2017-06-12 22:34:51 +02:00
/// Number of returned stack items.
2016-01-13 15:21:13 +01:00
pub ret : usize ,
2017-06-12 22:34:51 +02:00
/// Gas price tier.
2016-01-13 15:21:13 +01:00
pub tier : GasPriceTier
}
2016-06-02 12:40:31 +02:00
2016-01-13 15:21:13 +01:00
impl InstructionInfo {
2017-06-12 22:34:51 +02:00
/// Create new instruction info.
2017-06-13 17:38:10 +02:00
pub fn new ( name : & 'static str , args : usize , ret : usize , tier : GasPriceTier ) -> Self {
2016-01-13 15:21:13 +01:00
InstructionInfo {
name : name ,
args : args ,
ret : ret ,
tier : tier
}
}
}
2016-07-11 16:18:27 +02:00
lazy_static! {
2017-06-12 22:34:51 +02:00
/// Static instruction table.
2018-06-27 13:33:32 +02:00
static ref INSTRUCTIONS : [ Option < InstructionInfo > ; 0x100 ] = {
let mut arr = [ None ; 0x100 ] ;
arr [ STOP as usize ] = Some ( InstructionInfo ::new ( " STOP " , 0 , 0 , GasPriceTier ::Zero ) ) ;
arr [ ADD as usize ] = Some ( InstructionInfo ::new ( " ADD " , 2 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ SUB as usize ] = Some ( InstructionInfo ::new ( " SUB " , 2 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ MUL as usize ] = Some ( InstructionInfo ::new ( " MUL " , 2 , 1 , GasPriceTier ::Low ) ) ;
arr [ DIV as usize ] = Some ( InstructionInfo ::new ( " DIV " , 2 , 1 , GasPriceTier ::Low ) ) ;
arr [ SDIV as usize ] = Some ( InstructionInfo ::new ( " SDIV " , 2 , 1 , GasPriceTier ::Low ) ) ;
arr [ MOD as usize ] = Some ( InstructionInfo ::new ( " MOD " , 2 , 1 , GasPriceTier ::Low ) ) ;
arr [ SMOD as usize ] = Some ( InstructionInfo ::new ( " SMOD " , 2 , 1 , GasPriceTier ::Low ) ) ;
arr [ EXP as usize ] = Some ( InstructionInfo ::new ( " EXP " , 2 , 1 , GasPriceTier ::Special ) ) ;
arr [ NOT as usize ] = Some ( InstructionInfo ::new ( " NOT " , 1 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ LT as usize ] = Some ( InstructionInfo ::new ( " LT " , 2 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ GT as usize ] = Some ( InstructionInfo ::new ( " GT " , 2 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ SLT as usize ] = Some ( InstructionInfo ::new ( " SLT " , 2 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ SGT as usize ] = Some ( InstructionInfo ::new ( " SGT " , 2 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ EQ as usize ] = Some ( InstructionInfo ::new ( " EQ " , 2 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ ISZERO as usize ] = Some ( InstructionInfo ::new ( " ISZERO " , 1 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ AND as usize ] = Some ( InstructionInfo ::new ( " AND " , 2 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ OR as usize ] = Some ( InstructionInfo ::new ( " OR " , 2 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ XOR as usize ] = Some ( InstructionInfo ::new ( " XOR " , 2 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ BYTE as usize ] = Some ( InstructionInfo ::new ( " BYTE " , 2 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ SHL as usize ] = Some ( InstructionInfo ::new ( " SHL " , 2 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ SHR as usize ] = Some ( InstructionInfo ::new ( " SHR " , 2 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ SAR as usize ] = Some ( InstructionInfo ::new ( " SAR " , 2 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ ADDMOD as usize ] = Some ( InstructionInfo ::new ( " ADDMOD " , 3 , 1 , GasPriceTier ::Mid ) ) ;
arr [ MULMOD as usize ] = Some ( InstructionInfo ::new ( " MULMOD " , 3 , 1 , GasPriceTier ::Mid ) ) ;
arr [ SIGNEXTEND as usize ] = Some ( InstructionInfo ::new ( " SIGNEXTEND " , 2 , 1 , GasPriceTier ::Low ) ) ;
arr [ RETURNDATASIZE as usize ] = Some ( InstructionInfo ::new ( " RETURNDATASIZE " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ RETURNDATACOPY as usize ] = Some ( InstructionInfo ::new ( " RETURNDATACOPY " , 3 , 0 , GasPriceTier ::VeryLow ) ) ;
arr [ SHA3 as usize ] = Some ( InstructionInfo ::new ( " SHA3 " , 2 , 1 , GasPriceTier ::Special ) ) ;
arr [ ADDRESS as usize ] = Some ( InstructionInfo ::new ( " ADDRESS " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ BALANCE as usize ] = Some ( InstructionInfo ::new ( " BALANCE " , 1 , 1 , GasPriceTier ::Special ) ) ;
arr [ ORIGIN as usize ] = Some ( InstructionInfo ::new ( " ORIGIN " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ CALLER as usize ] = Some ( InstructionInfo ::new ( " CALLER " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ CALLVALUE as usize ] = Some ( InstructionInfo ::new ( " CALLVALUE " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ CALLDATALOAD as usize ] = Some ( InstructionInfo ::new ( " CALLDATALOAD " , 1 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ CALLDATASIZE as usize ] = Some ( InstructionInfo ::new ( " CALLDATASIZE " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ CALLDATACOPY as usize ] = Some ( InstructionInfo ::new ( " CALLDATACOPY " , 3 , 0 , GasPriceTier ::VeryLow ) ) ;
2018-07-31 07:27:57 +02:00
arr [ EXTCODEHASH as usize ] = Some ( InstructionInfo ::new ( " EXTCODEHASH " , 1 , 1 , GasPriceTier ::Special ) ) ;
2018-06-27 13:33:32 +02:00
arr [ CODESIZE as usize ] = Some ( InstructionInfo ::new ( " CODESIZE " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ CODECOPY as usize ] = Some ( InstructionInfo ::new ( " CODECOPY " , 3 , 0 , GasPriceTier ::VeryLow ) ) ;
arr [ GASPRICE as usize ] = Some ( InstructionInfo ::new ( " GASPRICE " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ EXTCODESIZE as usize ] = Some ( InstructionInfo ::new ( " EXTCODESIZE " , 1 , 1 , GasPriceTier ::Special ) ) ;
arr [ EXTCODECOPY as usize ] = Some ( InstructionInfo ::new ( " EXTCODECOPY " , 4 , 0 , GasPriceTier ::Special ) ) ;
arr [ BLOCKHASH as usize ] = Some ( InstructionInfo ::new ( " BLOCKHASH " , 1 , 1 , GasPriceTier ::Ext ) ) ;
arr [ COINBASE as usize ] = Some ( InstructionInfo ::new ( " COINBASE " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ TIMESTAMP as usize ] = Some ( InstructionInfo ::new ( " TIMESTAMP " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ NUMBER as usize ] = Some ( InstructionInfo ::new ( " NUMBER " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ DIFFICULTY as usize ] = Some ( InstructionInfo ::new ( " DIFFICULTY " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ GASLIMIT as usize ] = Some ( InstructionInfo ::new ( " GASLIMIT " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ POP as usize ] = Some ( InstructionInfo ::new ( " POP " , 1 , 0 , GasPriceTier ::Base ) ) ;
arr [ MLOAD as usize ] = Some ( InstructionInfo ::new ( " MLOAD " , 1 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ MSTORE as usize ] = Some ( InstructionInfo ::new ( " MSTORE " , 2 , 0 , GasPriceTier ::VeryLow ) ) ;
arr [ MSTORE8 as usize ] = Some ( InstructionInfo ::new ( " MSTORE8 " , 2 , 0 , GasPriceTier ::VeryLow ) ) ;
arr [ SLOAD as usize ] = Some ( InstructionInfo ::new ( " SLOAD " , 1 , 1 , GasPriceTier ::Special ) ) ;
arr [ SSTORE as usize ] = Some ( InstructionInfo ::new ( " SSTORE " , 2 , 0 , GasPriceTier ::Special ) ) ;
arr [ JUMP as usize ] = Some ( InstructionInfo ::new ( " JUMP " , 1 , 0 , GasPriceTier ::Mid ) ) ;
arr [ JUMPI as usize ] = Some ( InstructionInfo ::new ( " JUMPI " , 2 , 0 , GasPriceTier ::High ) ) ;
arr [ PC as usize ] = Some ( InstructionInfo ::new ( " PC " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ MSIZE as usize ] = Some ( InstructionInfo ::new ( " MSIZE " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ GAS as usize ] = Some ( InstructionInfo ::new ( " GAS " , 0 , 1 , GasPriceTier ::Base ) ) ;
arr [ JUMPDEST as usize ] = Some ( InstructionInfo ::new ( " JUMPDEST " , 0 , 0 , GasPriceTier ::Special ) ) ;
arr [ PUSH1 as usize ] = Some ( InstructionInfo ::new ( " PUSH1 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH2 as usize ] = Some ( InstructionInfo ::new ( " PUSH2 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH3 as usize ] = Some ( InstructionInfo ::new ( " PUSH3 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH4 as usize ] = Some ( InstructionInfo ::new ( " PUSH4 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH5 as usize ] = Some ( InstructionInfo ::new ( " PUSH5 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH6 as usize ] = Some ( InstructionInfo ::new ( " PUSH6 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH7 as usize ] = Some ( InstructionInfo ::new ( " PUSH7 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH8 as usize ] = Some ( InstructionInfo ::new ( " PUSH8 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH9 as usize ] = Some ( InstructionInfo ::new ( " PUSH9 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH10 as usize ] = Some ( InstructionInfo ::new ( " PUSH10 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH11 as usize ] = Some ( InstructionInfo ::new ( " PUSH11 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH12 as usize ] = Some ( InstructionInfo ::new ( " PUSH12 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH13 as usize ] = Some ( InstructionInfo ::new ( " PUSH13 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH14 as usize ] = Some ( InstructionInfo ::new ( " PUSH14 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH15 as usize ] = Some ( InstructionInfo ::new ( " PUSH15 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH16 as usize ] = Some ( InstructionInfo ::new ( " PUSH16 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH17 as usize ] = Some ( InstructionInfo ::new ( " PUSH17 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH18 as usize ] = Some ( InstructionInfo ::new ( " PUSH18 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH19 as usize ] = Some ( InstructionInfo ::new ( " PUSH19 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH20 as usize ] = Some ( InstructionInfo ::new ( " PUSH20 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH21 as usize ] = Some ( InstructionInfo ::new ( " PUSH21 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH22 as usize ] = Some ( InstructionInfo ::new ( " PUSH22 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH23 as usize ] = Some ( InstructionInfo ::new ( " PUSH23 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH24 as usize ] = Some ( InstructionInfo ::new ( " PUSH24 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH25 as usize ] = Some ( InstructionInfo ::new ( " PUSH25 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH26 as usize ] = Some ( InstructionInfo ::new ( " PUSH26 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH27 as usize ] = Some ( InstructionInfo ::new ( " PUSH27 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH28 as usize ] = Some ( InstructionInfo ::new ( " PUSH28 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH29 as usize ] = Some ( InstructionInfo ::new ( " PUSH29 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH30 as usize ] = Some ( InstructionInfo ::new ( " PUSH30 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH31 as usize ] = Some ( InstructionInfo ::new ( " PUSH31 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ PUSH32 as usize ] = Some ( InstructionInfo ::new ( " PUSH32 " , 0 , 1 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP1 as usize ] = Some ( InstructionInfo ::new ( " DUP1 " , 1 , 2 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP2 as usize ] = Some ( InstructionInfo ::new ( " DUP2 " , 2 , 3 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP3 as usize ] = Some ( InstructionInfo ::new ( " DUP3 " , 3 , 4 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP4 as usize ] = Some ( InstructionInfo ::new ( " DUP4 " , 4 , 5 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP5 as usize ] = Some ( InstructionInfo ::new ( " DUP5 " , 5 , 6 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP6 as usize ] = Some ( InstructionInfo ::new ( " DUP6 " , 6 , 7 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP7 as usize ] = Some ( InstructionInfo ::new ( " DUP7 " , 7 , 8 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP8 as usize ] = Some ( InstructionInfo ::new ( " DUP8 " , 8 , 9 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP9 as usize ] = Some ( InstructionInfo ::new ( " DUP9 " , 9 , 10 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP10 as usize ] = Some ( InstructionInfo ::new ( " DUP10 " , 10 , 11 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP11 as usize ] = Some ( InstructionInfo ::new ( " DUP11 " , 11 , 12 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP12 as usize ] = Some ( InstructionInfo ::new ( " DUP12 " , 12 , 13 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP13 as usize ] = Some ( InstructionInfo ::new ( " DUP13 " , 13 , 14 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP14 as usize ] = Some ( InstructionInfo ::new ( " DUP14 " , 14 , 15 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP15 as usize ] = Some ( InstructionInfo ::new ( " DUP15 " , 15 , 16 , GasPriceTier ::VeryLow ) ) ;
arr [ DUP16 as usize ] = Some ( InstructionInfo ::new ( " DUP16 " , 16 , 17 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP1 as usize ] = Some ( InstructionInfo ::new ( " SWAP1 " , 2 , 2 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP2 as usize ] = Some ( InstructionInfo ::new ( " SWAP2 " , 3 , 3 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP3 as usize ] = Some ( InstructionInfo ::new ( " SWAP3 " , 4 , 4 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP4 as usize ] = Some ( InstructionInfo ::new ( " SWAP4 " , 5 , 5 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP5 as usize ] = Some ( InstructionInfo ::new ( " SWAP5 " , 6 , 6 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP6 as usize ] = Some ( InstructionInfo ::new ( " SWAP6 " , 7 , 7 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP7 as usize ] = Some ( InstructionInfo ::new ( " SWAP7 " , 8 , 8 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP8 as usize ] = Some ( InstructionInfo ::new ( " SWAP8 " , 9 , 9 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP9 as usize ] = Some ( InstructionInfo ::new ( " SWAP9 " , 10 , 10 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP10 as usize ] = Some ( InstructionInfo ::new ( " SWAP10 " , 11 , 11 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP11 as usize ] = Some ( InstructionInfo ::new ( " SWAP11 " , 12 , 12 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP12 as usize ] = Some ( InstructionInfo ::new ( " SWAP12 " , 13 , 13 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP13 as usize ] = Some ( InstructionInfo ::new ( " SWAP13 " , 14 , 14 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP14 as usize ] = Some ( InstructionInfo ::new ( " SWAP14 " , 15 , 15 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP15 as usize ] = Some ( InstructionInfo ::new ( " SWAP15 " , 16 , 16 , GasPriceTier ::VeryLow ) ) ;
arr [ SWAP16 as usize ] = Some ( InstructionInfo ::new ( " SWAP16 " , 17 , 17 , GasPriceTier ::VeryLow ) ) ;
arr [ LOG0 as usize ] = Some ( InstructionInfo ::new ( " LOG0 " , 2 , 0 , GasPriceTier ::Special ) ) ;
arr [ LOG1 as usize ] = Some ( InstructionInfo ::new ( " LOG1 " , 3 , 0 , GasPriceTier ::Special ) ) ;
arr [ LOG2 as usize ] = Some ( InstructionInfo ::new ( " LOG2 " , 4 , 0 , GasPriceTier ::Special ) ) ;
arr [ LOG3 as usize ] = Some ( InstructionInfo ::new ( " LOG3 " , 5 , 0 , GasPriceTier ::Special ) ) ;
arr [ LOG4 as usize ] = Some ( InstructionInfo ::new ( " LOG4 " , 6 , 0 , GasPriceTier ::Special ) ) ;
arr [ CREATE as usize ] = Some ( InstructionInfo ::new ( " CREATE " , 3 , 1 , GasPriceTier ::Special ) ) ;
arr [ CALL as usize ] = Some ( InstructionInfo ::new ( " CALL " , 7 , 1 , GasPriceTier ::Special ) ) ;
arr [ CALLCODE as usize ] = Some ( InstructionInfo ::new ( " CALLCODE " , 7 , 1 , GasPriceTier ::Special ) ) ;
arr [ RETURN as usize ] = Some ( InstructionInfo ::new ( " RETURN " , 2 , 0 , GasPriceTier ::Zero ) ) ;
arr [ DELEGATECALL as usize ] = Some ( InstructionInfo ::new ( " DELEGATECALL " , 6 , 1 , GasPriceTier ::Special ) ) ;
arr [ STATICCALL as usize ] = Some ( InstructionInfo ::new ( " STATICCALL " , 6 , 1 , GasPriceTier ::Special ) ) ;
arr [ SUICIDE as usize ] = Some ( InstructionInfo ::new ( " SUICIDE " , 1 , 0 , GasPriceTier ::Special ) ) ;
2018-08-01 13:17:04 +02:00
arr [ CREATE2 as usize ] = Some ( InstructionInfo ::new ( " CREATE2 " , 4 , 1 , GasPriceTier ::Special ) ) ;
2018-06-27 13:33:32 +02:00
arr [ REVERT as usize ] = Some ( InstructionInfo ::new ( " REVERT " , 2 , 0 , GasPriceTier ::Zero ) ) ;
2016-07-11 16:18:27 +02:00
arr
} ;
}
2016-01-16 17:27:54 +01:00
/// Maximal number of topics for log instructions
2018-06-27 13:33:32 +02:00
pub const MAX_NO_OF_TOPICS : usize = 4 ;
#[ cfg(test) ]
mod tests {
use super ::* ;
#[ test ]
fn test_is_push ( ) {
assert! ( PUSH1 . is_push ( ) ) ;
assert! ( PUSH32 . is_push ( ) ) ;
assert! ( ! DUP1 . is_push ( ) ) ;
}
#[ test ]
fn test_get_push_bytes ( ) {
assert_eq! ( PUSH1 . push_bytes ( ) , Some ( 1 ) ) ;
assert_eq! ( PUSH3 . push_bytes ( ) , Some ( 3 ) ) ;
assert_eq! ( PUSH32 . push_bytes ( ) , Some ( 32 ) ) ;
}
#[ test ]
fn test_get_dup_position ( ) {
assert_eq! ( DUP1 . dup_position ( ) , Some ( 0 ) ) ;
assert_eq! ( DUP5 . dup_position ( ) , Some ( 4 ) ) ;
assert_eq! ( DUP10 . dup_position ( ) , Some ( 9 ) ) ;
}
#[ test ]
fn test_get_swap_position ( ) {
assert_eq! ( SWAP1 . swap_position ( ) , Some ( 1 ) ) ;
assert_eq! ( SWAP5 . swap_position ( ) , Some ( 5 ) ) ;
assert_eq! ( SWAP10 . swap_position ( ) , Some ( 10 ) ) ;
}
#[ test ]
fn test_get_log_topics ( ) {
assert_eq! ( LOG0 . log_topics ( ) , Some ( 0 ) ) ;
assert_eq! ( LOG2 . log_topics ( ) , Some ( 2 ) ) ;
assert_eq! ( LOG4 . log_topics ( ) , Some ( 4 ) ) ;
}
}