ethereum-analyzer 3.3.0 → 3.3.1
raw patch · 18 files changed
+258/−227 lines, 18 files
Files
- ChangeLog.md +6/−0
- ethereum-analyzer.cabal +3/−2
- src/Ckev/In/Text.hs +22/−0
- src/Ethereum/Analyzer/Common.hs +5/−5
- src/Ethereum/Analyzer/Debug.hs +2/−2
- src/Ethereum/Analyzer/EVM/CfgAugWithTopNPass.hs +7/−7
- src/Ethereum/Analyzer/EVM/CfgAugmentPass.hs +6/−6
- src/Ethereum/Analyzer/EVM/IR.hs +20/−22
- src/Ethereum/Analyzer/Solidity/AstJson.hs +4/−1
- src/Ethereum/Analyzer/Solidity/Hoople.hs +5/−5
- src/Ethereum/Analyzer/Solidity/Simple.hs +16/−14
- src/Ethereum/Analyzer/Util.hs +10/−10
- test/Ethereum/Analyzer/EVM/CfgAugWithTopNPassSpec.hs +3/−3
- test/Ethereum/Analyzer/EVM/CfgAugmentPassSpec.hs +3/−3
- test/Ethereum/Analyzer/EVM/IRSpec.hs +2/−2
- test/Ethereum/Analyzer/Solidity/SimpleSpec.hs +1/−1
- test/Ethereum/Analyzer/SoliditySpec.hs +2/−2
- test/Ethereum/AnalyzerSpec.hs +141/−142
ChangeLog.md view
@@ -1,3 +1,9 @@+3.3.1 / 2017-12-24+==================++ * Replace usage of String with Text.+ * Fix the name collision bug that causes a Hackage build failure.+ TODOs ================== * Support struct type.
ethereum-analyzer.cabal view
@@ -1,5 +1,5 @@ name: ethereum-analyzer-version: 3.3.0+version: 3.3.1 synopsis: A Ethereum contract analyzer. homepage: https://github.com/zchn/ethereum-analyzer license: Apache-2.0@@ -21,7 +21,7 @@ source-repository this type: git location: https://github.com/zchn/ethereum-analyzer- tag: v3.3.0+ tag: v3.3.1 subdir: ethereum-analyzer library@@ -49,6 +49,7 @@ , Ethereum.Analyzer.Debug , Ethereum.Analyzer.Solidity , Ethereum.Analyzer.Util+ , Ckev.In.Text other-modules: Ethereum.Analyzer.EVM.IR , Ethereum.Analyzer.EVM.CfgAugmentPass , Ethereum.Analyzer.EVM.CfgAugWithTopNPass
+ src/Ckev/In/Text.hs view
@@ -0,0 +1,22 @@+{-# LANGUAGE CPP, RankNTypes, GADTs, ScopedTypeVariables, FlexibleContexts #-}+module Ckev.In.Text ( ShowText(..)+ , showT+ , showGraphT) where++import Protolude hiding (show)++import Compiler.Hoopl+import GHC.Show (Show(..))++showT :: (Show a) => a -> Text+showT = toS . show++class ShowText a where+ showText :: a -> Text++-- Compiler.Hoopl++type ShowingT n = forall e x . n e x -> Text++showGraphT :: forall n e x . ShowingT n -> Graph n e x -> Text+showGraphT n = toS . (showGraph $ toS . n)
src/Ethereum/Analyzer/Common.hs view
@@ -13,7 +13,7 @@ import Blockchain.ExtWord import Data.ByteString as DB import Data.Either (Either(..))-import GHC.Show (Show(..))+import Ckev.In.Text fromRight :: b -> Either a b -> b fromRight _ (Right v) = v@@ -23,12 +23,12 @@ s2t4Either (Left s) = Left $ toS s s2t4Either (Right r) = Right r -unexpectedPanic :: Show a => a -> b-unexpectedPanic n = panic . toS $ "unexpected: " <> show n <> show callStack+unexpectedPanic :: ShowText a => a -> b+unexpectedPanic n = panic $ "unexpected: " <> showText n -unimplementedPanic :: Show a => a -> b+unimplementedPanic :: ShowText a => a -> b unimplementedPanic n =- panic . toS $ "unimplemented: " <> show n <> show callStack+ panic $ "unimplemented: " <> showText n varBytesToWord256 :: [Word8] -> Word256 varBytesToWord256 w8l =
src/Ethereum/Analyzer/Debug.hs view
@@ -7,7 +7,7 @@ import Protolude hiding (show) -import GHC.Show (Show(..))+import Ckev.In.Text import Ethereum.Analyzer.Solidity import Text.PrettyPrint.Leijen.Text as PP hiding ((<$>))@@ -27,4 +27,4 @@ pprintContracts = putDoc . pretty prettyContracts :: [Contract] -> Text-prettyContracts = toS . show . pretty+prettyContracts = showT . pretty
src/Ethereum/Analyzer/EVM/CfgAugWithTopNPass.hs view
@@ -19,7 +19,7 @@ import Ethereum.Analyzer.Common import Ethereum.Analyzer.EVM.Disasm import Ethereum.Analyzer.EVM.IR-import GHC.Show+import Ckev.In.Text import Legacy.Haskoin.V0102.Network.Haskoin.Crypto.BigWord type StackElemFact = WithTop (Set Word256)@@ -265,14 +265,14 @@ -- opT DATA ByteString flist = flist -- opT MalformedOpcode Word8 flist = flist opT op@LABEL {} _ =- panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ panic $ "Unexpected(stackTopTransfer): " <> toS (showT op) opT op@PUSHLABEL {} _ =- panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ panic $ "Unexpected(stackTopTransfer): " <> toS (showT op) opT op@PUSHDIFF {} _ =- panic $ "Unexpected(stackTopTransfer): " <> toS (show op)- opT op@DATA {} _ = panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ panic $ "Unexpected(stackTopTransfer): " <> toS (showT op)+ opT op@DATA {} _ = panic $ "Unexpected(stackTopTransfer): " <> toS (showT op) opT op@MalformedOpcode {} _ =- panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ panic $ "Unexpected(stackTopTransfer): " <> toS (showT op) -- TODO(zchn): Implement interp opT _ flist = DL.map (const Top) flist @@ -382,4 +382,4 @@ _ -> panic $ "doCfgAugWithTopNPass: unexpected newHexstrings length: " <>- toS (show (DL.length newHexstrings))+ toS (showT (DL.length newHexstrings))
src/Ethereum/Analyzer/EVM/CfgAugmentPass.hs view
@@ -17,7 +17,7 @@ import Data.Set as DS hiding (toList) import Ethereum.Analyzer.Common import Ethereum.Analyzer.EVM.IR-import GHC.Show+import Ckev.In.Text type StackTopFact = WithTop (Set Word256) @@ -74,14 +74,14 @@ PElem $ DS.map (bytesToWord256 . DL.map complement . word256ToBytes) st opT (PUSH w8l) _ = PElem $ DS.singleton $ varBytesToWord256 w8l opT op@LABEL {} _ =- panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ panic $ "Unexpected(stackTopTransfer): " <> toS (showT op) opT op@PUSHLABEL {} _ =- panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ panic $ "Unexpected(stackTopTransfer): " <> toS (showT op) opT op@PUSHDIFF {} _ =- panic $ "Unexpected(stackTopTransfer): " <> toS (show op)- opT op@DATA {} _ = panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ panic $ "Unexpected(stackTopTransfer): " <> toS (showT op)+ opT op@DATA {} _ = panic $ "Unexpected(stackTopTransfer): " <> toS (showT op) opT op@MalformedOpcode {} _ =- panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ panic $ "Unexpected(stackTopTransfer): " <> toS (showT op) opT _ _ = Top opGUnit :: HplOp e x -> Graph HplOp e x
src/Ethereum/Analyzer/EVM/IR.hs view
@@ -23,19 +23,14 @@ import Blockchain.VM.Opcodes as BVO import Compiler.Hoopl as CH --- import Control.Monad as CM import Data.Bimap as DB-import Data.List as DL-import Data.String (String)---- import Data.Graph.Inductive.Graph as DGIG import qualified Data.Text.Lazy as DTL-import GHC.Show+import Ckev.In.Text import Legacy.Haskoin.V0102.Network.Haskoin.Crypto.BigWord newtype MyLabel = MyLabel { unMyLabel :: Label- } deriving (Eq)+ } deriving (Eq, Show) data HplOp e x where CoOp :: Label -> HplOp C O@@ -45,22 +40,22 @@ HpEnd :: MyLabel -> HplOp O C HpCodeCopy :: Word256 -> HplOp O O -showLoc :: Word256 -> String-showLoc = show . getBigWordInteger+showLoc :: Word256 -> Text+showLoc = showT . getBigWordInteger -showOp :: (Word256, Operation) -> String-showOp (lineNo, op) = showLoc lineNo <> ": " <> show op+showOp :: (Word256, Operation) -> Text+showOp (lineNo, op) = showLoc lineNo <> ": " <> showT op -showOps :: [(Word256, Operation)] -> [String]+showOps :: [(Word256, Operation)] -> [Text] showOps = fmap showOp -instance Show (HplOp e x) where- show (CoOp l) = "CO: " <> show l- show (OoOp op) = "OO: " <> showOp op- show (OcOp op ll) = "OC: " <> showOp op <> " -> " <> show ll- show (HpJump _ l) = "OC: HpJump -> " <> show l- show HpEnd {} = "OC: HpEnd"- show (HpCodeCopy offset) = "HpCodeCopy " <> show offset+instance ShowText (HplOp e x) where+ showText (CoOp l) = "CO: " <> showT l+ showText (OoOp op) = "OO: " <> showOp op+ showText (OcOp op ll) = "OC: " <> showOp op <> " -> " <> showT ll+ showText (HpJump _ l) = "OC: HpJump -> " <> showT l+ showText HpEnd {} = "OC: HpEnd"+ showText (HpCodeCopy offset) = "HpCodeCopy " <> showT offset instance Eq (HplOp C O) where (==) (CoOp a) (CoOp b) = a == b@@ -84,13 +79,16 @@ type HplCfg = Graph HplOp O C -instance Show HplCfg where- show = showGraph show+instance ShowText HplCfg where+ showText = showGraphT showText data HplContract = HplContract { ctorOf :: HplCfg , dispatcherOf :: HplCfg- } deriving (Show)+ }++instance ShowText HplContract where+ showText c = showT [showText $ ctorOf c, showText $ dispatcherOf c] emptyHplCfg :: UniqueMonad m => m HplCfg emptyHplCfg = do
src/Ethereum/Analyzer/Solidity/AstJson.hs view
@@ -13,7 +13,7 @@ import Data.Aeson.Types import Data.HashMap.Lazy hiding (map) import Ethereum.Analyzer.Common-import GHC.Show (Show(..))+import Ckev.In.Text import Text.PrettyPrint.Leijen.Text as PP decodeSoleNodes :: LByteString -> Either Text [SolNode]@@ -57,6 +57,9 @@ , visibility :: Maybe Text , children :: Maybe [SolNode] } deriving (Eq, Generic, Show)++instance ShowText SolNode where+ showText = showT instance ToJSON SolNode where toJSON =
src/Ethereum/Analyzer/Solidity/Hoople.hs view
@@ -10,9 +10,9 @@ import Compiler.Hoopl import Ethereum.Analyzer.Solidity.Simple-import GHC.Show (Show(..))+import Ckev.In.Text import Text.PrettyPrint.Leijen.Text hiding ((<$>))-import qualified Text.PrettyPrint.Leijen.Text as PP+-- import qualified Text.PrettyPrint.Leijen.Text as PP data HContract = HContract { hcName :: Text@@ -32,7 +32,7 @@ } instance Pretty Label where- pretty = textStrict . toS . show+ pretty = textStrict . toS . showT data HStatement e x where CoSt :: Label -> HStatement C O@@ -50,8 +50,8 @@ pretty (OcSt st ll) = pretty st <+> textStrict "->" <+> prettyList ll pretty (OcJump l) = textStrict "jump" <+> textStrict "->" <+> pretty l -instance Show (HStatement e x) where- show = show . pretty+instance ShowText (HStatement e x) where+ showText = showT . pretty instance NonLocal HStatement where entryLabel (CoSt lbl) = lbl
src/Ethereum/Analyzer/Solidity/Simple.hs view
@@ -15,15 +15,15 @@ , decodeContracts ) where -import Protolude hiding (show)+import Protolude hiding ((<>), show) import Compiler.Hoopl import Data.Text (replace) import Ethereum.Analyzer.Common import Ethereum.Analyzer.Solidity.AstJson-import GHC.Show (Show(..))+import Ckev.In.Text import Text.PrettyPrint.Leijen.Text hiding ((<$>))-import qualified Text.PrettyPrint.Leijen.Text as PP+-- import qualified Text.PrettyPrint.Leijen.Text as PP decodeContracts :: Text -> Either Text [Contract] decodeContracts astJsonText = do@@ -70,6 +70,9 @@ | Tuple [LValue] deriving (Eq, Generic, Show) +instance ShowText LValue where+ showText = showT+ instance Pretty LValue where pretty (JustId v) = pretty v pretty (Index a i) = pretty a <> brackets (pretty i)@@ -224,25 +227,24 @@ } = concat <$> mapM s2sStatements sChildren s2sStatements SolNode { name = Just "Assignment" , children = Just [lval, rval]- , attributes = Just SolNode {operator = Just op}+ , attributes = Just SolNode {operator = Just _} } = do (prelval, simpleLval) <- s2sLval lval (prerval, simpleRval) <- s2sLval rval return $ prerval <> prelval <> [StAssign simpleLval $ ExpLval simpleRval]-s2sStatements e@SolNode {name = Just "Return", children = ch} = do+s2sStatements SolNode {name = Just "Return", children = ch} = do let sChildren = fromMaybe [] ch presAndRvals <- mapM s2sLval sChildren let prerval = concatMap fst presAndRvals let simpleRvals = map snd presAndRvals return $ prerval <> [StReturn simpleRvals]-s2sStatements e@SolNode { name = Just "UnaryOperation"+s2sStatements SolNode { name = Just "UnaryOperation" , children = Just [op1] , attributes = Just SolNode {operator = Just "delete"} } = do (preOp1, lvalOp1) <- s2sLval op1- newVar <- uniqueVar- return $ preOp1 <> [StDelete (JustId $ Idfr newVar)]-s2sStatements e@SolNode { name = Just "UnaryOperation"+ return $ preOp1 <> [StDelete lvalOp1]+s2sStatements SolNode { name = Just "UnaryOperation" , children = Just [SolNode { name = Just "Identifier" , attributes = Just SolNode {value = Just idName} }]@@ -253,7 +255,7 @@ let newidfr = JustId $ Idfr newVar return [StAssign newidfr $ ExpLiteral "1", StAssign idfr $ ExpBin "+" idfr newidfr]-s2sStatements e@SolNode { name = Just "UnaryOperation"+s2sStatements SolNode { name = Just "UnaryOperation" , children = Just [op1] , attributes = Just SolNode {operator = Just "++"} } = do@@ -276,7 +278,7 @@ let newidfr = JustId $ Idfr newVar return [StAssign newidfr $ ExpLiteral "1", StAssign idfr $ ExpBin "-" idfr newidfr]-s2sStatements e@SolNode { name = Just "UnaryOperation"+s2sStatements SolNode { name = Just "UnaryOperation" , children = Just [op1] , attributes = Just SolNode {operator = Just "--"} } = do@@ -357,7 +359,7 @@ } = do (prelval, simpleLval) <- s2sLval obj return (prelval, Member simpleLval (Idfr mName))-s2sLval n@SolNode {name = Just "IndexAccess", children = Just (c1:ctail)} = do+s2sLval SolNode {name = Just "IndexAccess", children = Just (c1:ctail)} = do (prelval, simpleLval) <- s2sLval c1 (presub, simpleLvalSub) <- handleSubscription simpleLval ctail return (presub <> prelval, Index simpleLval simpleLvalSub)@@ -450,10 +452,10 @@ s2sLval n = unimplementedPanic n {children = Nothing} uniqueVar :: UniqueMonad m => m Text-uniqueVar = ("v" <>) . toS . show <$> freshUnique+uniqueVar = ("v" <>) . toS . showT <$> freshUnique -- lastLvalOf :: [Statement] -> LValue -- lastLvalOf [_, StAssign lval _] = lval -- lastLvalOf (_ : t) = lastLvalOf t -- lastLvalOf _ = errorLValue-errorLValue = JustId (Idfr "ERROR!")+-- errorLValue = JustId (Idfr "ERROR!")
src/Ethereum/Analyzer/Util.hs view
@@ -9,21 +9,21 @@ import Protolude hiding (show) import Compiler.Hoopl as CH+import Ckev.In.Text import Data.Graph.Inductive.Graph as DGIG import Data.Graph.Inductive.PatriciaTree import Data.GraphViz import Data.GraphViz.Printing hiding ((<>))-import qualified Data.List as DL+import qualified Data.Text as DT import qualified Data.Text.Lazy as DTL-import GHC.Show import Text.Read (read) -instance (Show (n C O), Show (n O O), Show (n O C)) => Show (Block n C C) where- show a =+instance (ShowText (n C O), ShowText (n O O), ShowText (n O C)) => ShowText (Block n C C) where+ showText a = let (h, m, t) = blockSplit a- in DL.unlines $ [show h] <> map show (blockToList m) <> [show t]+ in DT.unlines $ [showText h] <> map showText (blockToList m) <> [showText t] -toDotText :: (NonLocal n, Show (Block n C C)) => CH.Graph n O C -> Text+toDotText :: (NonLocal n, ShowText (Block n C C)) => CH.Graph n O C -> Text toDotText bd = let bdGr = toGr bd dotG = toDotGraph bdGr@@ -32,7 +32,7 @@ toGr :: NonLocal n => CH.Graph n O C -> Gr (Block n C C) () toGr bd =- let lblToNode l = read (drop 1 $ toS $ show l)+ let lblToNode l = read (drop 1 $ toS $ showT l) blocks = postorder_dfs bd (nList, eList) = foldr@@ -45,13 +45,13 @@ in mkGraph nList eList visParams ::- (Show (Block n C C)) => GraphvizParams p (Block n C C) el () (Block n C C)+ (ShowText (Block n C C)) => GraphvizParams p (Block n C C) el () (Block n C C) visParams = nonClusteredParams { fmtNode = \(_, nl) ->- [textLabel (DTL.replace "\n" "\\l" $ toS $ show nl), shape BoxShape]+ [textLabel (DTL.replace "\n" "\\l" $ toS $ showText nl), shape BoxShape] } -toDotGraph :: (Show (Block n C C)) => Gr (Block n C C) () -> DotGraph Node+toDotGraph :: (ShowText (Block n C C)) => Gr (Block n C C) () -> DotGraph Node toDotGraph = graphToDot visParams
test/Ethereum/Analyzer/EVM/CfgAugWithTopNPassSpec.hs view
@@ -10,7 +10,7 @@ import Data.Text as DT import Ethereum.Analyzer.EVM import Ethereum.Analyzer.TestData.Basic-import GHC.Show+import Ckev.In.Text import Test.Hspec spec :: Spec@@ -18,11 +18,11 @@ describe "doCfgAugWithTopNPass" $ do it "works for hexstring1" $ do let result =- unWordLabelMapM $ toS . show <$> doCfgAugWithTopNPass hexstring1+ unWordLabelMapM $ showText <$> doCfgAugWithTopNPass hexstring1 DT.length result `shouldBe` 4634 it "works for hexstring2" $ do let result = toS $ unWordLabelMapM- ((toS . show <$> doCfgAugWithTopNPass hexstring2) :: WordLabelMapM Text)+ ((toS . showText <$> doCfgAugWithTopNPass hexstring2) :: WordLabelMapM Text) (result :: [Char]) `shouldContain` "OC: 9: JUMPI -> [L3,L5]"
test/Ethereum/Analyzer/EVM/CfgAugmentPassSpec.hs view
@@ -9,7 +9,7 @@ import Data.Text (length) import Ethereum.Analyzer.EVM import Ethereum.Analyzer.TestData.Basic-import GHC.Show+import Ckev.In.Text import Test.Hspec spec :: Spec@@ -20,14 +20,14 @@ result = unWordLabelMapM $ do contract <- evmOps2HplContract disasmd- (toS . show <$> doCfgAugmentPass contract) :: WordLabelMapM Text+ (showText <$> doCfgAugmentPass contract) :: WordLabelMapM Text Data.Text.length result `shouldBe` 4588 it "works for hexstring2" $ do let disasmd@((_, _):_) = disasm hexstring2 result = unWordLabelMapM $ do contract <- evmOps2HplContract disasmd- toS . show . ctorOf <$> doCfgAugmentPass contract+ showText . ctorOf <$> doCfgAugmentPass contract result `shouldBe` expectedHexString2CtorBody expectedHexString2CtorBody :: Text
test/Ethereum/Analyzer/EVM/IRSpec.hs view
@@ -5,9 +5,9 @@ import Protolude hiding (show) import Compiler.Hoopl+import Ckev.In.Text import Ethereum.Analyzer.EVM import Ethereum.Analyzer.TestData.Basic-import GHC.Show import Test.Hspec spec :: Spec@@ -29,7 +29,7 @@ it "shows HplCfg" $ do let disasmd = disasm hexstring2 unWordLabelMapM- ((toS . show . ctorOf <$> evmOps2HplContract disasmd) :: WordLabelMapM Text) `shouldBe`+ ((showText . ctorOf <$> evmOps2HplContract disasmd) :: WordLabelMapM Text) `shouldBe` toS expectedHexString2CtorBody expectedHexString2CtorBody :: Text
test/Ethereum/Analyzer/Solidity/SimpleSpec.hs view
@@ -11,7 +11,7 @@ import Ethereum.Analyzer.TestData.Asts import Ethereum.Analyzer.TestData.StorageJson (storageJson) --- import GHC.Show (Show(..))+-- import Ckev.In.Text import Test.Hspec spec :: Spec
test/Ethereum/Analyzer/SoliditySpec.hs view
@@ -4,9 +4,9 @@ import Protolude hiding (show) +import Ckev.In.Text import Ethereum.Analyzer.Solidity import Ethereum.Analyzer.TestData.StorageJson (storageJson)-import GHC.Show (Show(..)) import Test.Hspec import Text.PrettyPrint.Leijen.Text (Doc, pretty, renderPretty) @@ -15,7 +15,7 @@ describe "e2h" $ do it "pretty-prints storageJson" $ do let prettySol =- (show <$> renderPretty 1.0 80) . (pretty :: [SolNode] -> Doc) <$>+ (showT <$> renderPretty 1.0 80) . (pretty :: [SolNode] -> Doc) <$> decodeSoleNodes (toS storageJson) -- putStrLn $ fromRight "" prettySol prettySol `shouldBe`
test/Ethereum/AnalyzerSpec.hs view
@@ -6,156 +6,155 @@ import Protolude hiding (show) -import Data.List as DL-import Data.List.Extra as DLE+import Ckev.In.Text+import Data.Text as DT import Ethereum.Analyzer.EVM import Ethereum.Analyzer.TestData.Basic-import GHC.Show import Test.Hspec spec :: Spec spec = describe "disasm" $ do it "works for hexstring1" $ do- let disasmd1 = show $ showOps $ disasm hexstring1- DL.take 60 disasmd1 `shouldBe`+ let disasmd1 = showT $ showOps $ disasm hexstring1+ DT.take 60 disasmd1 `shouldBe` "[\"0: PUSH [96]\",\"2: PUSH [64]\",\"4: MSTORE\",\"5: PUSH [2]\",\"7:"- DLE.takeEnd 60 disasmd1 `shouldBe`+ DT.takeEnd 60 disasmd1 `shouldBe` "]\",\"6989: JUMP\",\"6990: JUMPDEST\",\"6991: SWAP1\",\"6992: JUMP\"]" it "works for hexstring2" $ do- let disasmd2 = show $ showOps $ disasm hexstring2- disasmd2 `shouldBe` "[\"0: PUSH [96]\"," ++- "\"2: PUSH [64]\"," ++- "\"4: MSTORE\"," ++- "\"5: CALLDATASIZE\"," ++- "\"6: ISZERO\"," ++- "\"7: PUSH [39]\"," ++- "\"9: JUMPI\"," ++- "\"10: PUSH [224]\"," ++- "\"12: PUSH [2]\"," ++- "\"14: EXP\"," ++- "\"15: PUSH [0]\"," ++- "\"17: CALLDATALOAD\"," ++- "\"18: DIV\"," ++- "\"19: PUSH [65,192,225,181]\"," ++- "\"24: DUP2\"," ++- "\"25: EQ\"," ++- "\"26: PUSH [110]\"," ++- "\"28: JUMPI\"," ++- "\"29: DUP1\"," ++- "\"30: PUSH [229,34,83,129]\"," ++- "\"35: EQ\"," ++- "\"36: PUSH [150]\"," ++- "\"38: JUMPI\"," ++- "\"39: JUMPDEST\"," ++- "\"40: PUSH [213]\"," ++- "\"42: PUSH [0]\"," ++- "\"44: CALLVALUE\"," ++- "\"45: GT\"," ++- "\"46: ISZERO\"," ++- "\"47: PUSH [108]\"," ++- "\"49: JUMPI\"," ++- "\"50: CALLVALUE\"," ++- "\"51: PUSH [96]\"," ++- "\"53: SWAP1\"," ++- "\"54: DUP2\"," ++- "\"55: MSTORE\"," ++- "\"56: PUSH [88]\"," ++- "\"58: SWAP1\"," ++- "\"59: PUSH [1]\"," ++- "\"61: PUSH [160]\"," ++- "\"63: PUSH [2]\"," ++- "\"65: EXP\"," ++- "\"66: SUB\"," ++- "\"67: CALLER\"," ++- "\"68: AND\"," ++- "\"69: SWAP1\"," ++- "\"70: PUSH [144,137,8,9,198,84,241,29,110,114,162,143,166,1,73,119,10,13,17,236,108,146,49,157,108,235,43,176,164,234,26,21]\"," ++- "\"103: SWAP1\"," ++- "\"104: PUSH [32]\"," ++- "\"106: SWAP1\"," ++- "\"107: LOG3\"," ++- "\"108: JUMPDEST\"," ++- "\"109: JUMP\"," ++- "\"110: JUMPDEST\"," ++- "\"111: PUSH [213]\"," ++- "\"113: PUSH [0]\"," ++- "\"115: SLOAD\"," ++- "\"116: PUSH [1]\"," ++- "\"118: PUSH [160]\"," ++- "\"120: PUSH [2]\"," ++- "\"122: EXP\"," ++- "\"123: SUB\"," ++- "\"124: SWAP1\"," ++- "\"125: DUP2\"," ++- "\"126: AND\"," ++- "\"127: CALLER\"," ++- "\"128: SWAP2\"," ++- "\"129: SWAP1\"," ++- "\"130: SWAP2\"," ++- "\"131: AND\"," ++- "\"132: EQ\"," ++- "\"133: ISZERO\"," ++- "\"134: PUSH [108]\"," ++- "\"136: JUMPI\"," ++- "\"137: PUSH [0]\"," ++- "\"139: SLOAD\"," ++- "\"140: PUSH [1]\"," ++- "\"142: PUSH [160]\"," ++- "\"144: PUSH [2]\"," ++- "\"146: EXP\"," ++- "\"147: SUB\"," ++- "\"148: AND\"," ++- "\"149: SUICIDE\"," ++- "\"150: JUMPDEST\"," ++- "\"151: PUSH [213]\"," ++- "\"153: PUSH [0]\"," ++- "\"155: SLOAD\"," ++- "\"156: PUSH [1]\"," ++- "\"158: PUSH [160]\"," ++- "\"160: PUSH [2]\"," ++- "\"162: EXP\"," ++- "\"163: SUB\"," ++- "\"164: SWAP1\"," ++- "\"165: DUP2\"," ++- "\"166: AND\"," ++- "\"167: CALLER\"," ++- "\"168: SWAP2\"," ++- "\"169: SWAP1\"," ++- "\"170: SWAP2\"," ++- "\"171: AND\"," ++- "\"172: EQ\"," ++- "\"173: ISZERO\"," ++- "\"174: PUSH [108]\"," ++- "\"176: JUMPI\"," ++- "\"177: PUSH [0]\"," ++- "\"179: DUP1\"," ++- "\"180: SLOAD\"," ++- "\"181: PUSH [1]\"," ++- "\"183: PUSH [160]\"," ++- "\"185: PUSH [2]\"," ++- "\"187: EXP\"," ++- "\"188: SUB\"," ++- "\"189: SWAP1\"," ++- "\"190: DUP2\"," ++- "\"191: AND\"," ++- "\"192: SWAP2\"," ++- "\"193: SWAP1\"," ++- "\"194: ADDRESS\"," ++- "\"195: AND\"," ++- "\"196: BALANCE\"," ++- "\"197: PUSH [96]\"," ++- "\"199: DUP3\"," ++- "\"200: DUP2\"," ++- "\"201: DUP2\"," ++- "\"202: DUP2\"," ++- "\"203: DUP6\"," ++- "\"204: DUP9\"," ++- "\"205: DUP4\"," ++- "\"206: CALL\"," ++- "\"207: POP\"," ++- "\"208: POP\"," ++- "\"209: POP\"," ++- "\"210: POP\"," ++- "\"211: POP\"," ++- "\"212: JUMP\"," ++ "\"213: JUMPDEST\"," ++ "\"214: STOP\"]"+ let disasmd2 = showT $ showOps $ disasm hexstring2+ disasmd2 `shouldBe` DT.concat ["[\"0: PUSH [96]\",",+ "\"2: PUSH [64]\",",+ "\"4: MSTORE\",",+ "\"5: CALLDATASIZE\",",+ "\"6: ISZERO\",",+ "\"7: PUSH [39]\",",+ "\"9: JUMPI\",",+ "\"10: PUSH [224]\",",+ "\"12: PUSH [2]\",",+ "\"14: EXP\",",+ "\"15: PUSH [0]\",",+ "\"17: CALLDATALOAD\",",+ "\"18: DIV\",",+ "\"19: PUSH [65,192,225,181]\",",+ "\"24: DUP2\",",+ "\"25: EQ\",",+ "\"26: PUSH [110]\",",+ "\"28: JUMPI\",",+ "\"29: DUP1\",",+ "\"30: PUSH [229,34,83,129]\",",+ "\"35: EQ\",",+ "\"36: PUSH [150]\",",+ "\"38: JUMPI\",",+ "\"39: JUMPDEST\",",+ "\"40: PUSH [213]\",",+ "\"42: PUSH [0]\",",+ "\"44: CALLVALUE\",",+ "\"45: GT\",",+ "\"46: ISZERO\",",+ "\"47: PUSH [108]\",",+ "\"49: JUMPI\",",+ "\"50: CALLVALUE\",",+ "\"51: PUSH [96]\",",+ "\"53: SWAP1\",",+ "\"54: DUP2\",",+ "\"55: MSTORE\",",+ "\"56: PUSH [88]\",",+ "\"58: SWAP1\",",+ "\"59: PUSH [1]\",",+ "\"61: PUSH [160]\",",+ "\"63: PUSH [2]\",",+ "\"65: EXP\",",+ "\"66: SUB\",",+ "\"67: CALLER\",",+ "\"68: AND\",",+ "\"69: SWAP1\",",+ "\"70: PUSH [144,137,8,9,198,84,241,29,110,114,162,143,166,1,73,119,10,13,17,236,108,146,49,157,108,235,43,176,164,234,26,21]\",",+ "\"103: SWAP1\",",+ "\"104: PUSH [32]\",",+ "\"106: SWAP1\",",+ "\"107: LOG3\",",+ "\"108: JUMPDEST\",",+ "\"109: JUMP\",",+ "\"110: JUMPDEST\",",+ "\"111: PUSH [213]\",",+ "\"113: PUSH [0]\",",+ "\"115: SLOAD\",",+ "\"116: PUSH [1]\",",+ "\"118: PUSH [160]\",",+ "\"120: PUSH [2]\",",+ "\"122: EXP\",",+ "\"123: SUB\",",+ "\"124: SWAP1\",",+ "\"125: DUP2\",",+ "\"126: AND\",",+ "\"127: CALLER\",",+ "\"128: SWAP2\",",+ "\"129: SWAP1\",",+ "\"130: SWAP2\",",+ "\"131: AND\",",+ "\"132: EQ\",",+ "\"133: ISZERO\",",+ "\"134: PUSH [108]\",",+ "\"136: JUMPI\",",+ "\"137: PUSH [0]\",",+ "\"139: SLOAD\",",+ "\"140: PUSH [1]\",",+ "\"142: PUSH [160]\",",+ "\"144: PUSH [2]\",",+ "\"146: EXP\",",+ "\"147: SUB\",",+ "\"148: AND\",",+ "\"149: SUICIDE\",",+ "\"150: JUMPDEST\",",+ "\"151: PUSH [213]\",",+ "\"153: PUSH [0]\",",+ "\"155: SLOAD\",",+ "\"156: PUSH [1]\",",+ "\"158: PUSH [160]\",",+ "\"160: PUSH [2]\",",+ "\"162: EXP\",",+ "\"163: SUB\",",+ "\"164: SWAP1\",",+ "\"165: DUP2\",",+ "\"166: AND\",",+ "\"167: CALLER\",",+ "\"168: SWAP2\",",+ "\"169: SWAP1\",",+ "\"170: SWAP2\",",+ "\"171: AND\",",+ "\"172: EQ\",",+ "\"173: ISZERO\",",+ "\"174: PUSH [108]\",",+ "\"176: JUMPI\",",+ "\"177: PUSH [0]\",",+ "\"179: DUP1\",",+ "\"180: SLOAD\",",+ "\"181: PUSH [1]\",",+ "\"183: PUSH [160]\",",+ "\"185: PUSH [2]\",",+ "\"187: EXP\",",+ "\"188: SUB\",",+ "\"189: SWAP1\",",+ "\"190: DUP2\",",+ "\"191: AND\",",+ "\"192: SWAP2\",",+ "\"193: SWAP1\",",+ "\"194: ADDRESS\",",+ "\"195: AND\",",+ "\"196: BALANCE\",",+ "\"197: PUSH [96]\",",+ "\"199: DUP3\",",+ "\"200: DUP2\",",+ "\"201: DUP2\",",+ "\"202: DUP2\",",+ "\"203: DUP6\",",+ "\"204: DUP9\",",+ "\"205: DUP4\",",+ "\"206: CALL\",",+ "\"207: POP\",",+ "\"208: POP\",",+ "\"209: POP\",",+ "\"210: POP\",",+ "\"211: POP\",",+ "\"212: JUMP\",", "\"213: JUMPDEST\",", "\"214: STOP\"]"]