module Ethereum.Analyzer.EVM.Disasm
( EvmBytecode(..)
, EvmHexString(..)
, HasEvmBytecode(..)
, disasm
) where
import Protolude hiding (show)
import Blockchain.Data.Code
import Blockchain.ExtWord
import Blockchain.Util
import Blockchain.VM.Code
import Blockchain.VM.Opcodes
import Data.HexString
class HasEvmBytecode a where
evmBytecodeOf :: a -> EvmBytecode
newtype EvmBytecode = EvmBytecode
{ unEvmBytecode :: ByteString
} deriving (Show, Eq)
newtype EvmHexString = EvmHexString
{ unEvmHexString :: Text
} deriving (Show, Eq)
instance HasEvmBytecode EvmBytecode where
evmBytecodeOf = identity
instance HasEvmBytecode EvmHexString where
evmBytecodeOf =
EvmBytecode . toBytes . hexString . encodeUtf8 . unEvmHexString
instance HasEvmBytecode Code where
evmBytecodeOf (Code bs) = EvmBytecode bs
evmBytecodeOf _ = EvmBytecode ""
disasm :: HasEvmBytecode a => a -> [(Word256, Operation)]
disasm a =
let bs = (unEvmBytecode . evmBytecodeOf) a
hardlimit = 10000
in disasmBSAt bs 0 hardlimit
disasmBSAt :: ByteString -> Word256 -> Int -> [(Word256, Operation)]
disasmBSAt "" _ _ = []
disasmBSAt _ _ 0 = []
disasmBSAt bs base limit =
(base, op) : disasmBSAt (safeDrop next bs) (base + next) (limit 1)
where
(op, next) = getOperationAt' bs 0