packages feed

hevm-0.51.0: src/EVM/Op.hs

{-# LANGUAGE DataKinds #-}

module EVM.Op
  ( Op
  , GenericOp (..)
  , opString
  , intToOpName
  , getOp
  , readOp
  ) where

import EVM.Expr qualified as Expr
import EVM.Types

import Data.Vector qualified as V
import Data.Word (Word8)
import Numeric (showHex)

intToOpName:: Int -> String
intToOpName a =
  case a of
   0x00-> "STOP"
   0x01-> "ADD"
   0x02-> "MUL"
   0x03-> "SUB"
   0x04-> "DIV"
   0x05-> "SDIV"
   0x06-> "MOD"
   0x07-> "SMOD"
   0x08-> "ADDMOD"
   0x09-> "MULMOD"
   0x0a-> "EXP"
   0x0b-> "SIGNEXTEND"
   --
   0x10 -> "LT"
   0x11 -> "GT"
   0x12 -> "SLT"
   0x13 -> "SGT"
   0x14 -> "EQ"
   0x15 -> "ISZERO"
   0x16 -> "AND"
   0x17 -> "OR"
   0x18 -> "XOR"
   0x19 -> "NOT"
   0x1a -> "BYTE"
   0x1b -> "SHL"
   0x1c -> "SHR"
   0x1d -> "SAR"
   0x20 -> "SHA3"
   0x30 -> "ADDRESS"
   --
   0x31 -> "BALANCE"
   0x32 -> "ORIGIN"
   0x33 -> "CALLER"
   0x34 -> "CALLVALUE"
   0x35 -> "CALLDATALOAD"
   0x36 -> "CALLDATASIZE"
   0x37 -> "CALLDATACOPY"
   0x38 -> "CODESIZE"
   0x39 -> "CODECOPY"
   0x3a -> "GASPRICE"
   0x3b -> "EXTCODESIZE"
   0x3c -> "EXTCODECOPY"
   0x3d -> "RETURNDATASIZE"
   0x3e -> "RETURNDATACOPY"
   0x3f -> "EXTCODEHASH"
   0x40 -> "BLOCKHASH"
   0x41 -> "COINBASE"
   0x42 -> "TIMESTAMP"
   0x43 -> "NUMBER"
   0x44 -> "PREVRANDAO"
   0x45 -> "GASLIMIT"
   0x46 -> "CHAINID"
   0x47 -> "SELFBALANCE"
   0x48 -> "BASEFEE"
   0x50 -> "POP"
   0x51 -> "MLOAD"
   0x52 -> "MSTORE"
   0x53 -> "MSTORE8"
   0x54 -> "SLOAD"
   0x55 -> "SSTORE"
   0x56 -> "JUMP"
   0x57 -> "JUMPI"
   0x58 -> "PC"
   0x59 -> "MSIZE"
   0x5a -> "GAS"
   0x5b -> "JUMPDEST"
   --
   0x60 -> "PUSH1"
   0x61 -> "PUSH2"
   0x62 -> "PUSH3"
   0x63 -> "PUSH4"
   0x64 -> "PUSH5"
   0x65 -> "PUSH6"
   0x66 -> "PUSH7"
   0x67 -> "PUSH8"
   0x68 -> "PUSH9"
   0x69 -> "PUSH10"
   0x6a -> "PUSH11"
   0x6b -> "PUSH12"
   0x6c -> "PUSH13"
   0x6d -> "PUSH14"
   0x6e -> "PUSH15"
   0x6f -> "PUSH16"
   0x70 -> "PUSH17"
   0x71 -> "PUSH18"
   0x72 -> "PUSH19"
   0x73 -> "PUSH20"
   0x74 -> "PUSH21"
   0x75 -> "PUSH22"
   0x76 -> "PUSH23"
   0x77 -> "PUSH24"
   0x78 -> "PUSH25"
   0x79 -> "PUSH26"
   0x7a -> "PUSH27"
   0x7b -> "PUSH28"
   0x7c -> "PUSH29"
   0x7d -> "PUSH30"
   0x7e -> "PUSH31"
   0x7f -> "PUSH32"
   --
   0x80 -> "DUP1"
   0x81 -> "DUP2"
   0x82 -> "DUP3"
   0x83 -> "DUP4"
   0x84 -> "DUP5"
   0x85 -> "DUP6"
   0x86 -> "DUP7"
   0x87 -> "DUP8"
   0x88 -> "DUP9"
   0x89 -> "DUP10"
   0x8a -> "DUP11"
   0x8b -> "DUP12"
   0x8c -> "DUP13"
   0x8d -> "DUP14"
   0x8e -> "DUP15"
   0x8f -> "DUP16"
   --
   0x90 -> "SWAP1"
   0x91 -> "SWAP2"
   0x92 -> "SWAP3"
   0x93 -> "SWAP4"
   0x94 -> "SWAP5"
   0x95 -> "SWAP6"
   0x96 -> "SWAP7"
   0x97 -> "SWAP8"
   0x98 -> "SWAP9"
   0x99 -> "SWAP10"
   0x9a -> "SWAP11"
   0x9b -> "SWAP12"
   0x9c -> "SWAP13"
   0x9d -> "SWAP14"
   0x9e -> "SWAP15"
   0x9f -> "SWAP16"
   --
   0xa0 -> "LOG0"
   0xa1 -> "LOG1"
   0xa2 -> "LOG2"
   0xa3 -> "LOG3"
   0xa4 -> "LOG4"
   --
   0xf0 -> "CREATE"
   0xf1 -> "CALL"
   0xf2 -> "CALLCODE"
   0xf3 -> "RETURN"
   0xf4 -> "DELEGATECALL"
   0xf5 -> "CREATE2"
   0xfa -> "STATICCALL"
   0xfd -> "REVERT"
   0xfe -> "INVALID"
   0xff -> "SELFDESTRUCT"
   _ -> "UNKNOWN "

opString :: (Integral a, Show a) => (a, Op) -> String
opString (i, o) = let showPc x | x < 0x10 = '0' : showHex x ""
                               | otherwise = showHex x ""
                  in showPc i <> " " ++ case o of
  OpStop -> "STOP"
  OpAdd -> "ADD"
  OpMul -> "MUL"
  OpSub -> "SUB"
  OpDiv -> "DIV"
  OpSdiv -> "SDIV"
  OpMod -> "MOD"
  OpSmod -> "SMOD"
  OpAddmod -> "ADDMOD"
  OpMulmod -> "MULMOD"
  OpExp -> "EXP"
  OpSignextend -> "SIGNEXTEND"
  OpLt -> "LT"
  OpGt -> "GT"
  OpSlt -> "SLT"
  OpSgt -> "SGT"
  OpEq -> "EQ"
  OpIszero -> "ISZERO"
  OpAnd -> "AND"
  OpOr -> "OR"
  OpXor -> "XOR"
  OpNot -> "NOT"
  OpByte -> "BYTE"
  OpShl -> "SHL"
  OpShr -> "SHR"
  OpSar -> "SAR"
  OpSha3 -> "SHA3"
  OpAddress -> "ADDRESS"
  OpBalance -> "BALANCE"
  OpOrigin -> "ORIGIN"
  OpCaller -> "CALLER"
  OpCallvalue -> "CALLVALUE"
  OpCalldataload -> "CALLDATALOAD"
  OpCalldatasize -> "CALLDATASIZE"
  OpCalldatacopy -> "CALLDATACOPY"
  OpCodesize -> "CODESIZE"
  OpCodecopy -> "CODECOPY"
  OpGasprice -> "GASPRICE"
  OpExtcodesize -> "EXTCODESIZE"
  OpExtcodecopy -> "EXTCODECOPY"
  OpReturndatasize -> "RETURNDATASIZE"
  OpReturndatacopy -> "RETURNDATACOPY"
  OpExtcodehash -> "EXTCODEHASH"
  OpBlockhash -> "BLOCKHASH"
  OpCoinbase -> "COINBASE"
  OpTimestamp -> "TIMESTAMP"
  OpNumber -> "NUMBER"
  OpPrevRandao -> "PREVRANDAO"
  OpGaslimit -> "GASLIMIT"
  OpChainid -> "CHAINID"
  OpSelfbalance -> "SELFBALANCE"
  OpBaseFee -> "BASEFEE"
  OpPop -> "POP"
  OpMload -> "MLOAD"
  OpMstore -> "MSTORE"
  OpMstore8 -> "MSTORE8"
  OpSload -> "SLOAD"
  OpSstore -> "SSTORE"
  OpJump -> "JUMP"
  OpJumpi -> "JUMPI"
  OpPc -> "PC"
  OpMsize -> "MSIZE"
  OpGas -> "GAS"
  OpJumpdest -> "JUMPDEST"
  OpCreate -> "CREATE"
  OpCall -> "CALL"
  OpStaticcall -> "STATICCALL"
  OpCallcode -> "CALLCODE"
  OpReturn -> "RETURN"
  OpDelegatecall -> "DELEGATECALL"
  OpCreate2 -> "CREATE2"
  OpSelfdestruct -> "SELFDESTRUCT"
  OpDup x -> "DUP" ++ show x
  OpSwap x -> "SWAP" ++ show x
  OpLog x -> "LOG" ++ show x
  OpPush x -> case x of
    Lit x' -> "PUSH 0x" ++ (showHex x' "")
    _ -> "PUSH " ++ show x
  OpRevert -> "REVERT"
  OpUnknown x -> case x of
    254 -> "INVALID"
    _ -> "UNKNOWN " ++ (showHex x "")

readOp :: Word8 -> [Expr Byte] -> Op
readOp x xs =
  (\n -> Expr.readBytes (fromIntegral n) (Lit 0) (Expr.fromList $ V.fromList xs)) <$> getOp x

getOp :: Word8 -> GenericOp Word8
getOp x | x >= 0x80 && x <= 0x8f = OpDup (x - 0x80 + 1)
getOp x | x >= 0x90 && x <= 0x9f = OpSwap (x - 0x90 + 1)
getOp x | x >= 0xa0 && x <= 0xa4 = OpLog (x - 0xa0)
getOp x | x >= 0x60 && x <= 0x7f = OpPush (x - 0x60 + 1)
getOp x = case x of
  0x00 -> OpStop
  0x01 -> OpAdd
  0x02 -> OpMul
  0x03 -> OpSub
  0x04 -> OpDiv
  0x05 -> OpSdiv
  0x06 -> OpMod
  0x07 -> OpSmod
  0x08 -> OpAddmod
  0x09 -> OpMulmod
  0x0a -> OpExp
  0x0b -> OpSignextend
  0x10 -> OpLt
  0x11 -> OpGt
  0x12 -> OpSlt
  0x13 -> OpSgt
  0x14 -> OpEq
  0x15 -> OpIszero
  0x16 -> OpAnd
  0x17 -> OpOr
  0x18 -> OpXor
  0x19 -> OpNot
  0x1a -> OpByte
  0x1b -> OpShl
  0x1c -> OpShr
  0x1d -> OpSar
  0x20 -> OpSha3
  0x30 -> OpAddress
  0x31 -> OpBalance
  0x32 -> OpOrigin
  0x33 -> OpCaller
  0x34 -> OpCallvalue
  0x35 -> OpCalldataload
  0x36 -> OpCalldatasize
  0x37 -> OpCalldatacopy
  0x38 -> OpCodesize
  0x39 -> OpCodecopy
  0x3a -> OpGasprice
  0x3b -> OpExtcodesize
  0x3c -> OpExtcodecopy
  0x3d -> OpReturndatasize
  0x3e -> OpReturndatacopy
  0x3f -> OpExtcodehash
  0x40 -> OpBlockhash
  0x41 -> OpCoinbase
  0x42 -> OpTimestamp
  0x43 -> OpNumber
  0x44 -> OpPrevRandao
  0x45 -> OpGaslimit
  0x46 -> OpChainid
  0x47 -> OpSelfbalance
  0x48 -> OpBaseFee
  0x50 -> OpPop
  0x51 -> OpMload
  0x52 -> OpMstore
  0x53 -> OpMstore8
  0x54 -> OpSload
  0x55 -> OpSstore
  0x56 -> OpJump
  0x57 -> OpJumpi
  0x58 -> OpPc
  0x59 -> OpMsize
  0x5a -> OpGas
  0x5b -> OpJumpdest
  0xf0 -> OpCreate
  0xf1 -> OpCall
  0xf2 -> OpCallcode
  0xf3 -> OpReturn
  0xf4 -> OpDelegatecall
  0xf5 -> OpCreate2
  0xfd -> OpRevert
  0xfa -> OpStaticcall
  0xff -> OpSelfdestruct
  _    -> OpUnknown x