diff --git a/etk-asm/src/asm.rs b/etk-asm/src/asm.rs index a0555961..6acc7351 100644 --- a/etk-asm/src/asm.rs +++ b/etk-asm/src/asm.rs @@ -6,7 +6,7 @@ mod error { use crate::ops::Expression; use crate::ParseError; - use etk_ops::cancun::Op; + use etk_ops::prague::Op; use num_bigint::BigInt; use snafu::{Backtrace, Snafu}; @@ -132,7 +132,7 @@ mod error { pub use self::error::Error; use crate::ops::expression::{self, Terminal}; use crate::ops::{self, AbstractOp, Assemble, Expression, Imm, MacroDefinition}; -use etk_ops::cancun::Op; +use etk_ops::prague::Op; use rand::Rng; use snafu::OptionExt; use std::collections::{hash_map, HashMap, HashSet, VecDeque}; @@ -185,7 +185,7 @@ impl From> for RawOp { /// ```rust /// use etk_asm::asm::Assembler; /// use etk_asm::ops::AbstractOp; -/// use etk_ops::cancun::{Op, GetPc}; +/// use etk_ops::prague::{Op, GetPc}; /// # use etk_asm::asm::Error; /// # /// # use hex_literal::hex; @@ -711,7 +711,7 @@ mod tests { InstructionMacroDefinition, InstructionMacroInvocation, Terminal, }; use assert_matches::assert_matches; - use etk_ops::cancun::*; + use etk_ops::prague::*; use hex_literal::hex; use num_bigint::{BigInt, Sign}; diff --git a/etk-asm/src/ast.rs b/etk-asm/src/ast.rs index a4d2e15d..9cd3a3a6 100644 --- a/etk-asm/src/ast.rs +++ b/etk-asm/src/ast.rs @@ -1,5 +1,5 @@ use crate::ops::{Abstract, AbstractOp, ExpressionMacroDefinition, InstructionMacroDefinition}; -use etk_ops::cancun::Op; +use etk_ops::prague::Op; use std::path::PathBuf; #[derive(Debug, Clone, PartialEq)] diff --git a/etk-asm/src/disasm.rs b/etk-asm/src/disasm.rs index bad65da2..4f6caf9b 100644 --- a/etk-asm/src/disasm.rs +++ b/etk-asm/src/disasm.rs @@ -25,7 +25,7 @@ mod error { } } -use etk_ops::cancun::Op; +use etk_ops::prague::Op; pub use self::error::Error; @@ -96,7 +96,7 @@ impl<'a> Iterator for Iter<'a> { /// /// ## Example /// ```rust -/// use etk_ops::cancun::{Op, GetPc, Stop}; +/// use etk_ops::prague::{Op, GetPc, Stop}; /// use etk_asm::disasm::Disassembler; /// # use etk_asm::disasm::Offset; /// @@ -158,7 +158,7 @@ impl Disassembler { #[cfg(test)] mod tests { - use etk_ops::cancun::*; + use etk_ops::prague::*; use hex_literal::hex; diff --git a/etk-asm/src/ops.rs b/etk-asm/src/ops.rs index 1749459a..0c202c36 100644 --- a/etk-asm/src/ops.rs +++ b/etk-asm/src/ops.rs @@ -2,7 +2,7 @@ mod error { use super::expression; - use etk_ops::cancun::Op; + use etk_ops::prague::Op; use num_bigint::BigInt; use snafu::{Backtrace, Snafu}; @@ -43,7 +43,7 @@ mod types; pub(crate) use self::error::Error; -use etk_ops::cancun::{Op, Operation, Push32}; +use etk_ops::prague::{Op, Operation, Push32}; pub use self::error::UnknownSpecifierError; pub use self::expression::{Context, Expression, Terminal}; diff --git a/etk-asm/src/parse/asm.pest b/etk-asm/src/parse/asm.pest index 19c9f1bd..7fa11cf5 100644 --- a/etk-asm/src/parse/asm.pest +++ b/etk-asm/src/parse/asm.pest @@ -3,7 +3,7 @@ /////////////////////// program = _{ SOI ~ inner ~ EOI } inner = _{ NEWLINE* ~ (stmt ~ (NEWLINE+|";"))* ~ stmt? } -stmt = _{ label_definition | builtin | local_macro | push | op } +stmt = _{ label_definition | builtin | local_macro | push | jumpf | op } ////////////////////// // opcode mnemonics // @@ -24,6 +24,7 @@ op = @{ "basefee" | "invalid" | "push0" | "mcopy" } push = ${ "push" ~ word_size ~ WHITESPACE ~ expression } +jumpf = ${ "jumpf" ~ WHITESPACE ~ expression } swap = @{ "swap" ~ half_word_size } dup = @{ "dup" ~ half_word_size } log = @{ "log" ~ '0'..'4' } diff --git a/etk-asm/src/parse/mod.rs b/etk-asm/src/parse/mod.rs index dba643c7..8c720e4b 100644 --- a/etk-asm/src/parse/mod.rs +++ b/etk-asm/src/parse/mod.rs @@ -21,7 +21,7 @@ use self::{ }; use crate::ast::Node; use crate::ops::AbstractOp; -use etk_ops::cancun::Op; +use etk_ops::prague::{JumpF, Op}; use num_bigint::BigInt; use pest::{iterators::Pair, Parser}; @@ -48,6 +48,7 @@ fn parse_abstract_op(pair: Pair) -> Result { AbstractOp::Label(pair.into_inner().next().unwrap().as_str().to_string()) } Rule::push => parse_push(pair)?, + Rule::jumpf => parse_jumpf(pair)?, Rule::op => { let spec: Op<()> = pair.as_str().parse().unwrap(); let op = Op::new(spec).unwrap(); @@ -78,6 +79,15 @@ fn parse_push(pair: Pair) -> Result { Ok(AbstractOp::Op(spec.with(expr).unwrap())) } +fn parse_jumpf(pair: Pair) -> Result { + let mut pair = pair.into_inner(); + let n = expression::parse(pair.next().unwrap())?; + + let spec = Op::JumpF(JumpF(n.try_into().unwrap())); + + Ok(AbstractOp::Op(spec)) +} + #[cfg(test)] mod tests { use super::*; @@ -86,7 +96,7 @@ mod tests { InstructionMacroDefinition, InstructionMacroInvocation, Terminal, }; use assert_matches::assert_matches; - use etk_ops::cancun::*; + use etk_ops::prague::*; use hex_literal::hex; use num_bigint::Sign; use std::path::PathBuf; diff --git a/etk-asm/tests/asm.rs b/etk-asm/tests/asm.rs index 36fc72cf..0bfecc67 100644 --- a/etk-asm/tests/asm.rs +++ b/etk-asm/tests/asm.rs @@ -258,6 +258,8 @@ fn every_op() -> Result<(), Error> { a3 a4 + e5 aabbccddeeff00112233445566778899 + f0 f1 f2 diff --git a/etk-asm/tests/asm/every-op/main.etk b/etk-asm/tests/asm/every-op/main.etk index 5516a8cd..952cddda 100644 --- a/etk-asm/tests/asm/every-op/main.etk +++ b/etk-asm/tests/asm/every-op/main.etk @@ -138,6 +138,8 @@ log2 log3 log4 +jumpf 0xAABBCCDDEEFF00112233445566778899 + create call callcode diff --git a/etk-dasm/src/bin/disease/selectors.rs b/etk-dasm/src/bin/disease/selectors.rs index ad21a6c9..d1caa135 100644 --- a/etk-dasm/src/bin/disease/selectors.rs +++ b/etk-dasm/src/bin/disease/selectors.rs @@ -1,6 +1,6 @@ use etk_4byte::reverse_selector; -use etk_ops::cancun::{Op, Operation}; +use etk_ops::prague::{Op, Operation}; use std::fmt; @@ -69,7 +69,7 @@ impl fmt::Display for DisplayOp { #[cfg(test)] mod tests { - use etk_ops::cancun::*; + use etk_ops::prague::*; use hex_literal::hex; diff --git a/etk-dasm/src/blocks/annotated.rs b/etk-dasm/src/blocks/annotated.rs index 382c17e3..9e4117a7 100644 --- a/etk-dasm/src/blocks/annotated.rs +++ b/etk-dasm/src/blocks/annotated.rs @@ -2,7 +2,7 @@ //! (ie. stack/memory/storage). use crate::sym::{Expr, Var}; -use etk_ops::cancun::*; +use etk_ops::prague::*; use std::collections::VecDeque; @@ -659,6 +659,11 @@ impl<'a> Annotator<'a> { let _topic3 = stack.pop(); } + Op::JumpF(JumpF(imm)) => { + let expr = Expr::constant(imm); + return Some(Exit::Unconditional(expr)); + } + Op::Swap1(_) => stack.swap(1), Op::Swap2(_) => stack.swap(2), Op::Swap3(_) => stack.swap(3), @@ -885,7 +890,6 @@ impl<'a> Annotator<'a> { | Op::InvalidE2(_) | Op::InvalidE3(_) | Op::InvalidE4(_) - | Op::InvalidE5(_) | Op::InvalidE6(_) | Op::InvalidE7(_) | Op::InvalidE8(_) diff --git a/etk-dasm/src/blocks/basic.rs b/etk-dasm/src/blocks/basic.rs index ee0b2abf..d00de6c5 100644 --- a/etk-dasm/src/blocks/basic.rs +++ b/etk-dasm/src/blocks/basic.rs @@ -1,7 +1,7 @@ //! A list of EVM instructions with a single point of entry and a single exit. use etk_asm::disasm::Offset; -use etk_ops::cancun::{Op, Operation}; +use etk_ops::prague::{Op, Operation}; /// A list of EVM instructions with a single point of entry and a single exit. #[derive(Debug, Eq, PartialEq)] @@ -107,7 +107,7 @@ impl Separator { #[cfg(test)] mod tests { - use etk_ops::cancun::*; + use etk_ops::prague::*; use super::*; diff --git a/etk-ops/build.rs b/etk-ops/build.rs index 97699974..9537a753 100644 --- a/etk-ops/build.rs +++ b/etk-ops/build.rs @@ -167,6 +167,11 @@ fn generate_fork(fork_name: &str) -> Result<(), Error> { let mut immediate_mut_matches = quote! {}; let mut into_immediate_matches = quote! {}; let names: Vec<_> = ops.iter().map(|(n, _)| format_ident!("{}", n)).collect(); + let immediate_ops: Vec<_> = ops + .iter() + .filter(|(_, op)| op.extra_len > 0) + .map(|(n, _)| format_ident!("{}", n)) + .collect(); for (name, op) in &ops { let name = format_ident!("{}", name); @@ -680,41 +685,11 @@ fn generate_fork(fork_name: &str) -> Result<(), Error> { T: ?Sized + super::Immediates, #(I: TryInto,)* { - // TODO: Automate generating these? let result = match self { - Self::Push1(_) => Op::Push1(Push1(immediate.try_into()?)), - Self::Push2(_) => Op::Push2(Push2(immediate.try_into()?)), - Self::Push3(_) => Op::Push3(Push3(immediate.try_into()?)), - Self::Push4(_) => Op::Push4(Push4(immediate.try_into()?)), - Self::Push5(_) => Op::Push5(Push5(immediate.try_into()?)), - Self::Push6(_) => Op::Push6(Push6(immediate.try_into()?)), - Self::Push7(_) => Op::Push7(Push7(immediate.try_into()?)), - Self::Push8(_) => Op::Push8(Push8(immediate.try_into()?)), - Self::Push9(_) => Op::Push9(Push9(immediate.try_into()?)), - Self::Push10(_) => Op::Push10(Push10(immediate.try_into()?)), - Self::Push11(_) => Op::Push11(Push11(immediate.try_into()?)), - Self::Push12(_) => Op::Push12(Push12(immediate.try_into()?)), - Self::Push13(_) => Op::Push13(Push13(immediate.try_into()?)), - Self::Push14(_) => Op::Push14(Push14(immediate.try_into()?)), - Self::Push15(_) => Op::Push15(Push15(immediate.try_into()?)), - Self::Push16(_) => Op::Push16(Push16(immediate.try_into()?)), - Self::Push17(_) => Op::Push17(Push17(immediate.try_into()?)), - Self::Push18(_) => Op::Push18(Push18(immediate.try_into()?)), - Self::Push19(_) => Op::Push19(Push19(immediate.try_into()?)), - Self::Push20(_) => Op::Push20(Push20(immediate.try_into()?)), - Self::Push21(_) => Op::Push21(Push21(immediate.try_into()?)), - Self::Push22(_) => Op::Push22(Push22(immediate.try_into()?)), - Self::Push23(_) => Op::Push23(Push23(immediate.try_into()?)), - Self::Push24(_) => Op::Push24(Push24(immediate.try_into()?)), - Self::Push25(_) => Op::Push25(Push25(immediate.try_into()?)), - Self::Push26(_) => Op::Push26(Push26(immediate.try_into()?)), - Self::Push27(_) => Op::Push27(Push27(immediate.try_into()?)), - Self::Push28(_) => Op::Push28(Push28(immediate.try_into()?)), - Self::Push29(_) => Op::Push29(Push29(immediate.try_into()?)), - Self::Push30(_) => Op::Push30(Push30(immediate.try_into()?)), - Self::Push31(_) => Op::Push31(Push31(immediate.try_into()?)), - Self::Push32(_) => Op::Push32(Push32(immediate.try_into()?)), - _ => panic!("only push operations can be combined"), + #( + Self::#immediate_ops(_) => Op::#immediate_ops(#immediate_ops(immediate.try_into()?)), + )* + _ => panic!("only jumpf/push operations can be combined"), }; Ok(result) @@ -852,4 +827,5 @@ fn main() { generate_fork("london").unwrap(); generate_fork("shanghai").unwrap(); generate_fork("cancun").unwrap(); + generate_fork("prague").unwrap(); } diff --git a/etk-ops/src/lib.rs b/etk-ops/src/lib.rs index 52520016..9dd774a4 100644 --- a/etk-ops/src/lib.rs +++ b/etk-ops/src/lib.rs @@ -29,6 +29,11 @@ pub mod cancun { include!(concat!(env!("OUT_DIR"), "/cancun.rs")); } +pub mod prague { + //! Instructions available in the Prague hard fork. + include!(concat!(env!("OUT_DIR"), "/prague.rs")); +} + /// Error that can occur when parsing an operation from a string. #[derive(Debug, Snafu)] pub struct FromStrError { diff --git a/etk-ops/src/prague.toml b/etk-ops/src/prague.toml new file mode 100644 index 00000000..04b59f22 --- /dev/null +++ b/etk-ops/src/prague.toml @@ -0,0 +1,917 @@ +[Stop] +code = 0x00 +mnemonic = "stop" +pushes = 0 +pops = 0 +exits = true + +[Add] +code = 0x01 +mnemonic = "add" +pushes = 1 +pops = 2 + +[Mul] +code = 0x02 +mnemonic = "mul" +pushes = 1 +pops = 2 + +[Sub] +code = 0x03 +mnemonic = "sub" +pushes = 1 +pops = 2 + +[Div] +code = 0x04 +mnemonic = "div" +pushes = 1 +pops = 2 + +[SDiv] +code = 0x05 +mnemonic = "sdiv" +pushes = 1 +pops = 2 + +[Mod] +code = 0x06 +mnemonic = "mod" +pushes = 1 +pops = 2 + +[SMod] +code = 0x07 +mnemonic = "smod" +pushes = 1 +pops = 2 + +[AddMod] +code = 0x08 +mnemonic = "addmod" +pushes = 1 +pops = 3 + +[MulMod] +code = 0x09 +mnemonic = "mulmod" +pushes = 1 +pops = 3 + +[Exp] +code = 0x0a +mnemonic = "exp" +pushes = 1 +pops = 2 + +[SignExtend] +code = 0x0b +mnemonic = "signextend" +pushes = 1 +pops = 2 + +[Lt] +code = 0x10 +mnemonic = "lt" +pushes = 1 +pops = 2 + +[Gt] +code = 0x11 +mnemonic = "gt" +pushes = 1 +pops = 2 + +[SLt] +code = 0x12 +mnemonic = "slt" +pushes = 1 +pops = 2 + +[SGt] +code = 0x13 +mnemonic = "sgt" +pushes = 1 +pops = 2 + +[Eq] +code = 0x14 +mnemonic = "eq" +pushes = 1 +pops = 2 + +[IsZero] +code = 0x15 +mnemonic = "iszero" +pushes = 1 +pops = 1 + +[And] +code = 0x16 +mnemonic = "and" +pushes = 1 +pops = 2 + +[Or] +code = 0x17 +mnemonic = "or" +pushes = 1 +pops = 2 + +[Xor] +code = 0x18 +mnemonic = "xor" +pushes = 1 +pops = 2 + +[Not] +code = 0x19 +mnemonic = "not" +pushes = 1 +pops = 1 + +[Byte] +code = 0x1a +mnemonic = "byte" +pushes = 1 +pops = 2 + +[Shl] +code = 0x1b +mnemonic = "shl" +pushes = 1 +pops = 2 + +[Shr] +code = 0x1c +mnemonic = "shr" +pushes = 1 +pops = 2 + +[Sar] +code = 0x1d +mnemonic = "sar" +pushes = 1 +pops = 2 + +[Keccak256] +code = 0x20 +mnemonic = "keccak256" +pushes = 1 +pops = 2 + +[Address] +code = 0x30 +mnemonic = "address" +pushes = 1 +pops = 0 + +[Balance] +code = 0x31 +mnemonic = "balance" +pushes = 1 +pops = 1 + +[Origin] +code = 0x32 +mnemonic = "origin" +pushes = 1 +pops = 0 + +[Caller] +code = 0x33 +mnemonic = "caller" +pushes = 1 +pops = 0 + +[CallValue] +code = 0x34 +mnemonic = "callvalue" +pushes = 1 +pops = 0 + +[CallDataLoad] +code = 0x35 +mnemonic = "calldataload" +pushes = 1 +pops = 1 + +[CallDataSize] +code = 0x36 +mnemonic = "calldatasize" +pushes = 1 +pops = 0 + +[CallDataCopy] +code = 0x37 +mnemonic = "calldatacopy" +pushes = 0 +pops = 3 + +[CodeSize] +code = 0x38 +mnemonic = "codesize" +pushes = 1 +pops = 0 + +[CodeCopy] +code = 0x39 +mnemonic = "codecopy" +pushes = 0 +pops = 3 + +[GasPrice] +code = 0x3a +mnemonic = "gasprice" +pushes = 1 +pops = 0 + +[ExtCodeSize] +code = 0x3b +mnemonic = "extcodesize" +pushes = 1 +pops = 1 + +[ExtCodeCopy] +code = 0x3c +mnemonic = "extcodecopy" +pushes = 0 +pops = 4 + +[ReturnDataSize] +code = 0x3d +mnemonic = "returndatasize" +pushes = 1 +pops = 0 + +[ReturnDataCopy] +code = 0x3e +mnemonic = "returndatacopy" +pushes = 0 +pops = 3 + +[ExtCodeHash] +code = 0x3f +mnemonic = "extcodehash" +pushes = 1 +pops = 1 + +[BlockHash] +code = 0x40 +mnemonic = "blockhash" +pushes = 1 +pops = 1 + +[Coinbase] +code = 0x41 +mnemonic = "coinbase" +pushes = 1 +pops = 0 + +[Timestamp] +code = 0x42 +mnemonic = "timestamp" +pushes = 1 +pops = 0 + +[Number] +code = 0x43 +mnemonic = "number" +pushes = 1 +pops = 0 + +[Difficulty] +code = 0x44 +mnemonic = "difficulty" +pushes = 1 +pops = 0 + +[GasLimit] +code = 0x45 +mnemonic = "gaslimit" +pushes = 1 +pops = 0 + +[ChainId] +code = 0x46 +mnemonic = "chainid" +pushes = 1 +pops = 0 + +[SelfBalance] +code = 0x47 +mnemonic = "selfbalance" +pushes = 1 +pops = 0 + +[BaseFee] +code = 0x48 +mnemonic = "basefee" +pushes = 1 +pops = 0 + +[Pop] +code = 0x50 +mnemonic = "pop" +pushes = 0 +pops = 1 + +[MLoad] +code = 0x51 +mnemonic = "mload" +pushes = 1 +pops = 1 + +[MStore] +code = 0x52 +mnemonic = "mstore" +pushes = 0 +pops = 2 + +[MStore8] +code = 0x53 +mnemonic = "mstore8" +pushes = 1 +pops = 2 + +[SLoad] +code = 0x54 +mnemonic = "sload" +pushes = 1 +pops = 1 + +[SStore] +code = 0x55 +mnemonic = "sstore" +pushes = 0 +pops = 2 + +[Jump] +code = 0x56 +mnemonic = "jump" +pushes = 0 +pops = 1 +jump = true + +[JumpI] +code = 0x57 +mnemonic = "jumpi" +pushes = 0 +pops = 2 +jump = true + +[GetPc] +code = 0x58 +mnemonic = "pc" +pushes = 1 +pops = 0 + +[MSize] +code = 0x59 +mnemonic = "msize" +pushes = 1 +pops = 0 + +[Gas] +code = 0x5a +mnemonic = "gas" +pushes = 1 +pops = 0 + +[JumpDest] +code = 0x5b +mnemonic = "jumpdest" +pushes = 0 +pops = 0 +jump_target = true + +[MCopy] +code = 0x5e +mnemonic = "mcopy" +pushes = 0 +pops = 3 + +[Push0] +code = 0x5f +mnemonic = "push0" +extra_len = 0 +pushes = 1 +pops = 0 + +[Push1] +code = 0x60 +mnemonic = "push1" +extra_len = 1 +pushes = 1 +pops = 0 + +[Push2] +code = 0x61 +mnemonic = "push2" +extra_len = 2 +pushes = 1 +pops = 0 + +[Push3] +code = 0x62 +mnemonic = "push3" +extra_len = 3 +pushes = 1 +pops = 0 + +[Push4] +code = 0x63 +mnemonic = "push4" +extra_len = 4 +pushes = 1 +pops = 0 + +[Push5] +code = 0x64 +mnemonic = "push5" +extra_len = 5 +pushes = 1 +pops = 0 + +[Push6] +code = 0x65 +mnemonic = "push6" +extra_len = 6 +pushes = 1 +pops = 0 + +[Push7] +code = 0x66 +mnemonic = "push7" +extra_len = 7 +pushes = 1 +pops = 0 + +[Push8] +code = 0x67 +mnemonic = "push8" +extra_len = 8 +pushes = 1 +pops = 0 + +[Push9] +code = 0x68 +mnemonic = "push9" +extra_len = 9 +pushes = 1 +pops = 0 + +[Push10] +code = 0x69 +mnemonic = "push10" +extra_len = 10 +pushes = 1 +pops = 0 + +[Push11] +code = 0x6a +mnemonic = "push11" +extra_len = 11 +pushes = 1 +pops = 0 + +[Push12] +code = 0x6b +mnemonic = "push12" +extra_len = 12 +pushes = 1 +pops = 0 + +[Push13] +code = 0x6c +mnemonic = "push13" +extra_len = 13 +pushes = 1 +pops = 0 + +[Push14] +code = 0x6d +mnemonic = "push14" +extra_len = 14 +pushes = 1 +pops = 0 + +[Push15] +code = 0x6e +mnemonic = "push15" +extra_len = 15 +pushes = 1 +pops = 0 + +[Push16] +code = 0x6f +mnemonic = "push16" +extra_len = 16 +pushes = 1 +pops = 0 + +[Push17] +code = 0x70 +mnemonic = "push17" +extra_len = 17 +pushes = 1 +pops = 0 + +[Push18] +code = 0x71 +mnemonic = "push18" +extra_len = 18 +pushes = 1 +pops = 0 + +[Push19] +code = 0x72 +mnemonic = "push19" +extra_len = 19 +pushes = 1 +pops = 0 + +[Push20] +code = 0x73 +mnemonic = "push20" +extra_len = 20 +pushes = 1 +pops = 0 + +[Push21] +code = 0x74 +mnemonic = "push21" +extra_len = 21 +pushes = 1 +pops = 0 + +[Push22] +code = 0x75 +mnemonic = "push22" +extra_len = 22 +pushes = 1 +pops = 0 + +[Push23] +code = 0x76 +mnemonic = "push23" +extra_len = 23 +pushes = 1 +pops = 0 + +[Push24] +code = 0x77 +mnemonic = "push24" +extra_len = 24 +pushes = 1 +pops = 0 + +[Push25] +code = 0x78 +mnemonic = "push25" +extra_len = 25 +pushes = 1 +pops = 0 + +[Push26] +code = 0x79 +mnemonic = "push26" +extra_len = 26 +pushes = 1 +pops = 0 + +[Push27] +code = 0x7a +mnemonic = "push27" +extra_len = 27 +pushes = 1 +pops = 0 + +[Push28] +code = 0x7b +mnemonic = "push28" +extra_len = 28 +pushes = 1 +pops = 0 + +[Push29] +code = 0x7c +mnemonic = "push29" +extra_len = 29 +pushes = 1 +pops = 0 + +[Push30] +code = 0x7d +mnemonic = "push30" +extra_len = 30 +pushes = 1 +pops = 0 + +[Push31] +code = 0x7e +mnemonic = "push31" +extra_len = 31 +pushes = 1 +pops = 0 + +[Push32] +code = 0x7f +mnemonic = "push32" +extra_len = 32 +pushes = 1 +pops = 0 + +[Dup1] +code = 0x80 +mnemonic = "dup1" +pushes = 2 +pops = 1 + +[Dup2] +code = 0x81 +mnemonic = "dup2" +pushes = 3 +pops = 2 + +[Dup3] +code = 0x82 +mnemonic = "dup3" +pushes = 4 +pops = 3 + +[Dup4] +code = 0x83 +mnemonic = "dup4" +pushes = 5 +pops = 4 + +[Dup5] +code = 0x84 +mnemonic = "dup5" +pushes = 6 +pops = 5 + +[Dup6] +code = 0x85 +mnemonic = "dup6" +pushes = 7 +pops = 6 + +[Dup7] +code = 0x86 +mnemonic = "dup7" +pushes = 8 +pops = 7 + +[Dup8] +code = 0x87 +mnemonic = "dup8" +pushes = 9 +pops = 8 + +[Dup9] +code = 0x88 +mnemonic = "dup9" +pushes = 10 +pops = 9 + +[Dup10] +code = 0x89 +mnemonic = "dup10" +pushes = 11 +pops = 10 + +[Dup11] +code = 0x8a +mnemonic = "dup11" +pushes = 12 +pops = 11 + +[Dup12] +code = 0x8b +mnemonic = "dup12" +pushes = 13 +pops = 12 + +[Dup13] +code = 0x8c +mnemonic = "dup13" +pushes = 14 +pops = 13 + +[Dup14] +code = 0x8d +mnemonic = "dup14" +pushes = 15 +pops = 14 + +[Dup15] +code = 0x8e +mnemonic = "dup15" +pushes = 16 +pops = 15 + +[Dup16] +code = 0x8f +mnemonic = "dup16" +pushes = 17 +pops = 16 + +[Swap1] +code = 0x90 +mnemonic = "swap1" +pushes = 2 +pops = 2 + +[Swap2] +code = 0x91 +mnemonic = "swap2" +pushes = 3 +pops = 3 + +[Swap3] +code = 0x92 +mnemonic = "swap3" +pushes = 4 +pops = 4 + +[Swap4] +code = 0x93 +mnemonic = "swap4" +pushes = 5 +pops = 5 + +[Swap5] +code = 0x94 +mnemonic = "swap5" +pushes = 6 +pops = 6 + +[Swap6] +code = 0x95 +mnemonic = "swap6" +pushes = 7 +pops = 7 + +[Swap7] +code = 0x96 +mnemonic = "swap7" +pushes = 8 +pops = 8 + +[Swap8] +code = 0x97 +mnemonic = "swap8" +pushes = 9 +pops = 9 + +[Swap9] +code = 0x98 +mnemonic = "swap9" +pushes = 10 +pops = 10 + +[Swap10] +code = 0x99 +mnemonic = "swap10" +pushes = 11 +pops = 11 + +[Swap11] +code = 0x9a +mnemonic = "swap11" +pushes = 12 +pops = 12 + +[Swap12] +code = 0x9b +mnemonic = "swap12" +pushes = 13 +pops = 13 + +[Swap13] +code = 0x9c +mnemonic = "swap13" +pushes = 14 +pops = 14 + +[Swap14] +code = 0x9d +mnemonic = "swap14" +pushes = 15 +pops = 15 + +[Swap15] +code = 0x9e +mnemonic = "swap15" +pushes = 16 +pops = 16 + +[Swap16] +code = 0x9f +mnemonic = "swap16" +pushes = 17 +pops = 17 + +[Log0] +code = 0xa0 +mnemonic = "log0" +pushes = 2 +pops = 2 + +[Log1] +code = 0xa1 +mnemonic = "log1" +pushes = 3 +pops = 3 + +[Log2] +code = 0xa2 +mnemonic = "log2" +pushes = 4 +pops = 4 + +[Log3] +code = 0xa3 +mnemonic = "log3" +pushes = 5 +pops = 5 + +[Log4] +code = 0xa4 +mnemonic = "log4" +pushes = 6 +pops = 6 + +[JumpF] +code = 0xe5 +mnemonic = "jumpf" +extra_len = 16 +pushes = 0 +pops = 0 +jump = true + +[Create] +code = 0xf0 +mnemonic = "create" +pushes = 1 +pops = 3 + +[Call] +code = 0xf1 +mnemonic = "call" +pushes = 1 +pops = 7 + +[CallCode] +code = 0xf2 +mnemonic = "callcode" +pushes = 1 +pops = 7 + +[Return] +code = 0xf3 +mnemonic = "return" +pushes = 0 +pops = 2 +exits = true + +[DelegateCall] +code = 0xf4 +mnemonic = "delegatecall" +pushes = 1 +pops = 6 + +[Create2] +code = 0xf5 +mnemonic = "create2" +pushes = 1 +pops = 4 + +[StaticCall] +code = 0xfa +mnemonic = "staticcall" +pushes = 1 +pops = 6 + +[Revert] +code = 0xfd +mnemonic = "revert" +pushes = 0 +pops = 2 +exits = true + +[Invalid] +code = 0xfe +mnemonic = "invalid" +pushes = 0 +pops = 0 +exits = true + +[SelfDestruct] +code = 0xff +mnemonic = "selfdestruct" +pushes = 0 +pops = 2