hevm-0.51.2: src/EVM/Assembler.hs
{-# LANGUAGE DataKinds #-}
{-|
Module : Assembler
Description : Assembler for EVM opcodes used in the HEVM symbolic checker
-}
module EVM.Assembler where
import EVM.Expr qualified as Expr
import EVM.Op
import EVM.Types
import Data.Vector (Vector)
import Data.Vector qualified as V
assemble :: [Op] -> Vector (Expr Byte)
assemble os = V.fromList $ concatMap go os
where
go :: Op -> [Expr Byte]
go = \case
OpStop -> [LitByte 0x00]
OpAdd -> [LitByte 0x01]
OpMul -> [LitByte 0x02]
OpSub -> [LitByte 0x03]
OpDiv -> [LitByte 0x04]
OpSdiv -> [LitByte 0x05]
OpMod -> [LitByte 0x06]
OpSmod -> [LitByte 0x07]
OpAddmod -> [LitByte 0x08]
OpMulmod -> [LitByte 0x09]
OpExp -> [LitByte 0x0A]
OpSignextend -> [LitByte 0x0B]
OpLt -> [LitByte 0x10]
OpGt -> [LitByte 0x11]
OpSlt -> [LitByte 0x12]
OpSgt -> [LitByte 0x13]
OpEq -> [LitByte 0x14]
OpIszero -> [LitByte 0x15]
OpAnd -> [LitByte 0x16]
OpOr -> [LitByte 0x17]
OpXor -> [LitByte 0x18]
OpNot -> [LitByte 0x19]
OpByte -> [LitByte 0x1A]
OpShl -> [LitByte 0x1B]
OpShr -> [LitByte 0x1C]
OpSar -> [LitByte 0x1D]
OpSha3 -> [LitByte 0x20]
OpAddress -> [LitByte 0x30]
OpBalance -> [LitByte 0x31]
OpOrigin -> [LitByte 0x32]
OpCaller -> [LitByte 0x33]
OpCallvalue -> [LitByte 0x34]
OpCalldataload -> [LitByte 0x35]
OpCalldatasize -> [LitByte 0x36]
OpCalldatacopy -> [LitByte 0x37]
OpCodesize -> [LitByte 0x38]
OpCodecopy -> [LitByte 0x39]
OpGasprice -> [LitByte 0x3A]
OpExtcodesize -> [LitByte 0x3B]
OpExtcodecopy -> [LitByte 0x3C]
OpReturndatasize -> [LitByte 0x3D]
OpReturndatacopy -> [LitByte 0x3E]
OpExtcodehash -> [LitByte 0x3F]
OpBlockhash -> [LitByte 0x40]
OpCoinbase -> [LitByte 0x41]
OpTimestamp -> [LitByte 0x42]
OpNumber -> [LitByte 0x43]
OpPrevRandao -> [LitByte 0x44]
OpGaslimit -> [LitByte 0x45]
OpChainid -> [LitByte 0x46]
OpSelfbalance -> [LitByte 0x47]
OpBaseFee -> [LitByte 0x48]
OpPop -> [LitByte 0x50]
OpMload -> [LitByte 0x51]
OpMstore -> [LitByte 0x52]
OpMstore8 -> [LitByte 0x53]
OpSload -> [LitByte 0x54]
OpSstore -> [LitByte 0x55]
OpJump -> [LitByte 0x56]
OpJumpi -> [LitByte 0x57]
OpPc -> [LitByte 0x58]
OpMsize -> [LitByte 0x59]
OpGas -> [LitByte 0x5A]
OpJumpdest -> [LitByte 0x5B]
OpCreate -> [LitByte 0xF0]
OpCall -> [LitByte 0xF1]
OpStaticcall -> [LitByte 0xFA]
OpCallcode -> [LitByte 0xF2]
OpReturn -> [LitByte 0xF3]
OpDelegatecall -> [LitByte 0xF4]
OpCreate2 -> [LitByte 0xF5]
OpRevert -> [LitByte 0xFD]
OpSelfdestruct -> [LitByte 0xFF]
OpDup n ->
if 1 <= n && n <= 16
then [LitByte (0x80 + (n - 1))]
else internalError $ "invalid argument to OpDup: " <> show n
OpSwap n ->
if 1 <= n && n <= 16
then [LitByte (0x90 + (n - 1))]
else internalError $ "invalid argument to OpSwap: " <> show n
OpLog n ->
if 0 <= n && n <= 4
then [LitByte (0xA0 + n)]
else internalError $ "invalid argument to OpLog: " <> show n
-- we just always assemble OpPush into PUSH32
OpPush wrd -> (LitByte 0x7f) : [Expr.indexWord (Lit i) wrd | i <- [0..31]]
OpPush0 -> [LitByte 0x5f]
OpUnknown o -> [LitByte o]