packages feed

ethereum-analyzer 3.2.0 → 3.3.0

raw patch · 16 files changed

+474/−382 lines, 16 files

Files

ChangeLog.md view
@@ -1,5 +1,23 @@-# Revision history for ethereum-analyzer+TODOs+==================+  * Support struct type.+  * Support contract type.+  * Support special for loops in CryptoKitties.+  * Support EVM opcode from ea-analyzer.+  * Support InlineAssembly.+  * Fix the bug in handling 'IndexAccess'.+  * Fix the bug in handling 'new'.+  * Fix the bug in handling 'delete'.+  * Show all contracts and functions in a single dot file. -## 0.1.0.0  -- YYYY-mm-dd -* First version. Released on an unsuspecting world.+3.3.0 / 2017-12-21+==================++ * Pretty print Simple opcode.+ * Support NewExpression. Add InlineAssembly as a StTodo.+ * Support generalized ++ and --+ * Add all CryptoKitties contracts.+ * Add example for EVM CFG.+ * Add REVERT per EIP 140.+ * bugfix: Add StContinue to loops when needed.
ethereum-analyzer.cabal view
@@ -1,5 +1,5 @@ name:                ethereum-analyzer-version:             3.2.0+version:             3.3.0 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.2.0+  tag:      v3.3.0   subdir:   ethereum-analyzer  library
src/Ethereum/Analyzer/Common.hs view
@@ -19,21 +19,16 @@ fromRight _ (Right v) = v fromRight v (Left _) = v -s2t4Either-  :: StringConv s Text-  => Either s a -> Either Text a+s2t4Either :: StringConv s Text => Either s a -> Either Text a s2t4Either (Left s) = Left $ toS s s2t4Either (Right r) = Right r -unexpectedPanic-  :: Show a-  => a -> b-unexpectedPanic n = panic . toS $ "unexpected: " ++ show n+unexpectedPanic :: Show a => a -> b+unexpectedPanic n = panic . toS $ "unexpected: " <> show n <> show callStack -unimplementedPanic-  :: Show a-  => a -> b-unimplementedPanic n = panic . toS $ "unimplemented: " ++ show n+unimplementedPanic :: Show a => a -> b+unimplementedPanic n =+  panic . toS $ "unimplemented: " <> show n <> show callStack  varBytesToWord256 :: [Word8] -> Word256 varBytesToWord256 w8l =
src/Ethereum/Analyzer/Debug.hs view
@@ -5,19 +5,26 @@   , dbgGetSimpleSol   ) where -import Protolude+import Protolude hiding (show) +import GHC.Show (Show(..))+ import Ethereum.Analyzer.Solidity-import qualified Text.PrettyPrint.GenericPretty as GP+import Text.PrettyPrint.Leijen.Text as PP hiding ((<$>)) +_mergeEither :: Either t t -> t+_mergeEither (Right v) = v+_mergeEither (Left v) = v+ dbgGetSimpleSol :: Text -> Either Text [Contract] dbgGetSimpleSol = decodeContracts  pprintSimpleSol :: Text -> IO ()-pprintSimpleSol = GP.pp . dbgGetSimpleSol+pprintSimpleSol ast =+  putText $ _mergeEither $ (toS . prettyContracts) <$> (decodeContracts ast)  pprintContracts :: [Contract] -> IO ()-pprintContracts = GP.pp+pprintContracts = putDoc . pretty  prettyContracts :: [Contract] -> Text-prettyContracts = toS . GP.pretty+prettyContracts = toS . show . pretty
src/Ethereum/Analyzer/EVM/CfgAugWithTopNPass.hs view
@@ -24,8 +24,8 @@  type StackElemFact = WithTop (Set Word256) -joinStackElemBase-  :: Label+joinStackElemBase ::+     Label   -> OldFact (Set Word256)   -> NewFact (Set Word256)   -> (ChangeFlag, Set Word256)@@ -34,8 +34,8 @@     then (NoChange, oldF)     else (SomeChange, oldF `DS.union` newF) -joinStackElemFact-  :: Label+joinStackElemFact ::+     Label   -> OldFact StackElemFact   -> NewFact StackElemFact   -> (ChangeFlag, StackElemFact)@@ -43,10 +43,11 @@  type StackNFact = [StackElemFact] -joinStackNFact :: Label-               -> OldFact StackNFact-               -> NewFact StackNFact-               -> (ChangeFlag, StackNFact)+joinStackNFact ::+     Label+  -> OldFact StackNFact+  -> NewFact StackNFact+  -> (ChangeFlag, StackNFact) joinStackNFact l (OldFact oldF) (NewFact newF) =   let zipped =         DL.zipWith@@ -74,9 +75,7 @@ _sizeBound :: Int _sizeBound = 10 -mkTopList-  :: forall b b1 a.-     [b] -> [Pointed C b1 a]+mkTopList :: forall b b1 a. [b] -> [Pointed C b1 a] mkTopList = DL.map (const Top)  pairCompute :: (Word256 -> Word256 -> Word256) -> StackNFact -> StackNFact@@ -293,13 +292,11 @@ cfgAugWithTopNRewrite :: FwdRewrite WordLabelMapFuelM HplOp StackNFact cfgAugWithTopNRewrite = mkFRewrite3 coR ooR ocR   where-    coR :: HplOp C O-        -> StackNFact-        -> WordLabelMapFuelM (Maybe (Graph HplOp C O))+    coR ::+         HplOp C O -> StackNFact -> WordLabelMapFuelM (Maybe (Graph HplOp C O))     coR op _ = return $ Just $ opGUnit op-    ooR :: HplOp O O-        -> StackNFact-        -> WordLabelMapFuelM (Maybe (Graph HplOp O O))+    ooR ::+         HplOp O O -> StackNFact -> WordLabelMapFuelM (Maybe (Graph HplOp O O))     ooR op@(OoOp (_, CODECOPY)) f =       case peekStack 2 f of         Top -> return $ Just $ opGUnit op@@ -308,9 +305,8 @@           Just $           DS.foldl (\a b -> catGraphNodeOO a $ HpCodeCopy b) (opGUnit op) vals     ooR op _ = return $ Just $ opGUnit op-    ocR :: HplOp O C-        -> StackNFact-        -> WordLabelMapFuelM (Maybe (Graph HplOp O C))+    ocR ::+         HplOp O C -> StackNFact -> WordLabelMapFuelM (Maybe (Graph HplOp O C))     ocR op@HpJump {} _ = return (Just (opGUnit op))     ocR op@HpEnd {} _ = return (Just (opGUnit op))     ocR op@(OcOp (loc, ope) ll) f =@@ -340,9 +336,7 @@   , fp_rewrite = cfgAugWithTopNRewrite   } -doCfgAugWithTopNPass-  :: HasEvmBytecode a-  => a -> WordLabelMapM HplContract+doCfgAugWithTopNPass :: HasEvmBytecode a => a -> WordLabelMapM HplContract doCfgAugWithTopNPass a = do   let disasmd = disasm a   contract <- evmOps2HplContract disasmd@@ -372,7 +366,9 @@           ([] :: [EvmBytecode])   case newHexstrings of     [] -> return contract {ctorOf = newBody}-    [newhs] -> do+    newhs : _ -> do+      -- TODO(zchn): fix the handling of CryptoKittiesSalesAuction.evm so that+      --  the above match can be changed to "[newhs] -> do".       disBody <- evmOps2HplCfg $ disasm newhs       newDisBody <-         runWithFuel
src/Ethereum/Analyzer/EVM/CfgAugmentPass.hs view
@@ -21,8 +21,8 @@  type StackTopFact = WithTop (Set Word256) -joinJumpTargets-  :: Label+joinJumpTargets ::+     Label   -> OldFact (Set Word256)   -> NewFact (Set Word256)   -> (ChangeFlag, Set Word256)@@ -31,8 +31,8 @@     then (NoChange, oldF)     else (SomeChange, oldF `DS.union` newF) -joinStackTopFact-  :: Label+joinStackTopFact ::+     Label   -> OldFact StackTopFact   -> NewFact StackTopFact   -> (ChangeFlag, StackTopFact)@@ -95,17 +95,20 @@ cfgAugmentRewrite :: FwdRewrite WordLabelMapFuelM HplOp StackTopFact cfgAugmentRewrite = mkFRewrite3 coR ooR ocR   where-    coR :: HplOp C O-        -> StackTopFact-        -> WordLabelMapFuelM (Maybe (Graph HplOp C O))+    coR ::+         HplOp C O+      -> StackTopFact+      -> WordLabelMapFuelM (Maybe (Graph HplOp C O))     coR op _ = return $ Just $ opGUnit op-    ooR :: HplOp O O-        -> StackTopFact-        -> WordLabelMapFuelM (Maybe (Graph HplOp O O))+    ooR ::+         HplOp O O+      -> StackTopFact+      -> WordLabelMapFuelM (Maybe (Graph HplOp O O))     ooR op _ = return $ Just $ opGUnit op-    ocR :: HplOp O C-        -> StackTopFact-        -> WordLabelMapFuelM (Maybe (Graph HplOp O C))+    ocR ::+         HplOp O C+      -> StackTopFact+      -> WordLabelMapFuelM (Maybe (Graph HplOp O C))     ocR op@HpJump {} _ = return (Just (opGUnit op))     ocR op@HpEnd {} _ = return (Just (opGUnit op))     ocR op@(OcOp (loc, ope) ll) f =
src/Ethereum/Analyzer/EVM/Disasm.hs view
@@ -36,9 +36,7 @@   evmBytecodeOf (Code bs) = EvmBytecode bs   evmBytecodeOf _ = EvmBytecode "" -disasm-  :: HasEvmBytecode a-  => a -> [(Word256, Operation)]+disasm :: HasEvmBytecode a => a -> [(Word256, Operation)] disasm a =   let bs = (unEvmBytecode . evmBytecodeOf) a       hardlimit = 10000
src/Ethereum/Analyzer/EVM/IR.hs view
@@ -38,12 +38,12 @@   } deriving (Eq)  data HplOp e x where-        CoOp :: Label -> HplOp C O-        OoOp :: (Word256, Operation) -> HplOp O O-        OcOp :: (Word256, Operation) -> [Label] -> HplOp O C-        HpJump :: MyLabel -> Label -> HplOp O C-        HpEnd :: MyLabel -> HplOp O C-        HpCodeCopy :: Word256 -> HplOp O O+  CoOp :: Label -> HplOp C O+  OoOp :: (Word256, Operation) -> HplOp O O+  OcOp :: (Word256, Operation) -> [Label] -> HplOp O C+  HpJump :: MyLabel -> Label -> HplOp O C+  HpEnd :: MyLabel -> HplOp O C+  HpCodeCopy :: Word256 -> HplOp O O  showLoc :: Word256 -> String showLoc = show . getBigWordInteger@@ -92,9 +92,7 @@   , dispatcherOf :: HplCfg   } deriving (Show) -emptyHplCfg-  :: UniqueMonad m-  => m HplCfg+emptyHplCfg :: UniqueMonad m => m HplCfg emptyHplCfg = do   l <- myFreshLabel   return $ mkLast (HpEnd l)@@ -105,9 +103,7 @@   ec <- emptyHplCfg   return HplContract {ctorOf = ctorBody, dispatcherOf = ec} -myFreshLabel-  :: UniqueMonad m-  => m MyLabel+myFreshLabel :: UniqueMonad m => m MyLabel myFreshLabel = fmap MyLabel freshLabel  evmOps2HplCfg :: [(Word256, Operation)] -> WordLabelMapM HplCfg@@ -117,10 +113,11 @@   jpLabel <- myFreshLabel   doEvmOps2HplCfg (mkLast $ HpJump jpLabel l) (mkFirst $ CoOp l) el   where-    doEvmOps2HplCfg :: HplCfg-                    -> Graph HplOp C O-                    -> [(Word256, Operation)]-                    -> WordLabelMapM HplCfg+    doEvmOps2HplCfg ::+         HplCfg+      -> Graph HplOp C O+      -> [(Word256, Operation)]+      -> WordLabelMapM HplCfg     doEvmOps2HplCfg body _ [] = return body -- sliently discarding bad hds     doEvmOps2HplCfg body hd [h'] =       if isTerminator (snd h')@@ -172,8 +169,8 @@ instance CheckpointMonad WordLabelMapM where   type Checkpoint WordLabelMapM = (WordLabelMap, Checkpoint SimpleUniqueMonad)   checkpoint =-    let mapper-          :: WordLabelMap+    let mapper ::+             WordLabelMap           -> SimpleUniqueMonad (WordLabelMap, Checkpoint WordLabelMapM)         mapper m = do           suCheckpoint <- CH.checkpoint@@ -236,8 +233,7 @@ instance UnWordLabelMapM DTL.Text where   unWordLabelMapM = internalUnWordLabelMapM -instance (UnWordLabelMapM a, UnWordLabelMapM b) =>-         UnWordLabelMapM (a, b) where+instance (UnWordLabelMapM a, UnWordLabelMapM b) => UnWordLabelMapM (a, b) where   unWordLabelMapM = internalUnWordLabelMapM  internalUnWordLabelMapM :: WordLabelMapM a -> a
src/Ethereum/Analyzer/EVM/Util.hs view
@@ -15,9 +15,7 @@ import Ethereum.Analyzer.EVM.IR import Ethereum.Analyzer.Util -disasmToDotText-  :: HasEvmBytecode a-  => a -> Text+disasmToDotText :: HasEvmBytecode a => a -> Text disasmToDotText a =   let disasmd = disasm a       result =@@ -26,9 +24,7 @@           toDotText <$> (ctorOf <$> doCfgAugmentPass contract)   in result -disasmToDotText2-  :: HasEvmBytecode a-  => a -> (Text, Text)+disasmToDotText2 :: HasEvmBytecode a => a -> (Text, Text) disasmToDotText2 a =   let result =         unWordLabelMapM $ do
src/Ethereum/Analyzer/Solidity/AstJson.hs view
@@ -7,7 +7,7 @@   , defSolNode   ) where -import Protolude hiding (show, (<>))+import Protolude hiding ((<>), show)  import Data.Aeson import Data.Aeson.Types
src/Ethereum/Analyzer/Solidity/Foreach.hs view
@@ -39,5 +39,5 @@ _eOf StContinue = [] _eOf (StReturn _) = [] _eOf (StDelete _) = []-_eOf st@(StTodo _) = unimplementedPanic st+_eOf (StTodo _) = [] _eOf StThrow = []
src/Ethereum/Analyzer/Solidity/Hoople.hs view
@@ -9,8 +9,10 @@ import Protolude hiding ((<*>), show)  import Compiler.Hoopl-import GHC.Show (Show(..)) import Ethereum.Analyzer.Solidity.Simple+import GHC.Show (Show(..))+import Text.PrettyPrint.Leijen.Text hiding ((<$>))+import qualified Text.PrettyPrint.Leijen.Text as PP  data HContract = HContract   { hcName :: Text@@ -29,19 +31,27 @@   , hfCFG :: CFG   } +instance Pretty Label where+  pretty = textStrict . toS . show+ data HStatement e x where-        CoSt :: Label -> HStatement C O-        OoSt :: Statement -> HStatement O O-        OcSt :: Statement -> [Label] -> HStatement O C-        OcJump :: Label -> HStatement O C+  CoSt :: Label -> HStatement C O+  OoSt :: Statement -> HStatement O O+  OcSt :: Statement -> [Label] -> HStatement O C+  OcJump :: Label -> HStatement O C +instance Pretty (HStatement e x) where+  pretty (CoSt l) = pretty l+  pretty (OoSt st) = pretty st+  pretty (OcSt (StIf lval _ _) ll) =+    textStrict "OcIf" <+> pretty lval <+> textStrict "->" <+> prettyList ll+  pretty (OcSt (StLoop _) ll) =+    textStrict "OcLoop" <+> textStrict "->" <+> prettyList ll+  pretty (OcSt st ll) = pretty st <+> textStrict "->" <+> prettyList ll+  pretty (OcJump l) = textStrict "jump" <+> textStrict "->" <+> pretty l+ instance Show (HStatement e x) where-  show (CoSt l) = show l-  show (OoSt st) = show st-  show (OcSt (StIf lval _ _) ll) = "if " <> show lval <> " -> " <> show ll-  show (OcSt (StLoop _) ll) = "loop -> " <> show ll-  show (OcSt st ll) = show st <> " -> " <> show ll-  show (OcJump l) = "jump -> " <> show l+  show = show . pretty  instance NonLocal HStatement where   entryLabel (CoSt lbl) = lbl@@ -52,16 +62,12 @@   mkBranchNode = OcJump   mkLabelNode = CoSt -hoopleOf-  :: UniqueMonad m-  => Contract -> m HContract+hoopleOf :: UniqueMonad m => Contract -> m HContract hoopleOf Contract {cName = name, cStateVars = vars, cFunctions = funs} = do   hFuns <- mapM hfunOf funs   return $ HContract name vars hFuns -hfunOf-  :: UniqueMonad m-  => FunDefinition -> m HFunDefinition+hfunOf :: UniqueMonad m => FunDefinition -> m HFunDefinition hfunOf FunDefinition { fName = name                      , fParams = params                      , fReturns = returns@@ -74,9 +80,7 @@   cfg <- graphOfAGraph acfg   return $ HFunDefinition name params returns cfg -graphOf-  :: UniqueMonad m-  => [Statement] -> Label -> Label -> m ACFG+graphOf :: UniqueMonad m => [Statement] -> Label -> Label -> m ACFG graphOf [] exitL _ = return $ mkBranch exitL graphOf (h:t) exitL loopL = do   postDom <- graphOf t exitL loopL
src/Ethereum/Analyzer/Solidity/Simple.hs view
@@ -18,11 +18,12 @@ 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 qualified Text.PrettyPrint as PP-import qualified Text.PrettyPrint.GenericPretty as GP+import Text.PrettyPrint.Leijen.Text hiding ((<$>))+import qualified Text.PrettyPrint.Leijen.Text as PP  decodeContracts :: Text -> Either Text [Contract] decodeContracts astJsonText = do@@ -35,42 +36,81 @@   { cName :: Text   , cStateVars :: [VarDecl]   , cFunctions :: [FunDefinition]-  } deriving (Eq, Generic, Show, GP.Out)+  } deriving (Eq, Generic, Show) +instance Pretty Contract where+  pretty Contract { cName = _name+                  , cStateVars = _statevars+                  , cFunctions = _functions+                  } =+    textStrict _name <+>+    braces (vsep $ map pretty _statevars <> map pretty _functions)+ data VarDecl = VarDecl   { vName :: Idfr   , vType :: VarType-  } deriving (Eq, Generic, Show, GP.Out)+  } deriving (Eq, Generic, Show) -newtype Idfr =-  Idfr { unIdfr :: Text }-  deriving (Eq, Generic, Show, GP.Out)+instance Pretty VarDecl where+  pretty VarDecl {vName = _name, vType = _type} = pretty _type <+> pretty _name +newtype Idfr = Idfr+  { unIdfr :: Text+  } deriving (Eq, Generic, Show)++instance Pretty Idfr where+  pretty = textStrict . unIdfr+ data LValue   = JustId Idfr   | Index { iArray :: LValue-         ,  iIndex :: LValue}+          , iIndex :: LValue }   | Member { mObj :: LValue-          ,  mField :: Idfr}+           , mField :: Idfr }   | Tuple [LValue]-  deriving (Eq, Generic, Show, GP.Out)+  deriving (Eq, Generic, Show) +instance Pretty LValue where+  pretty (JustId v) = pretty v+  pretty (Index a i) = pretty a <> brackets (pretty i)+  pretty (Member o f) = pretty o <> textStrict "." <> pretty f+  pretty (Tuple l) = tupled (map pretty l)+ data VarType   = Int256   | Uint256+  | Bool   | Address   | Mapping VarType             VarType   | Unknown Text-  deriving (Eq, Generic, Show, GP.Out)+  deriving (Eq, Generic, Show) +instance Pretty VarType where+  pretty Int256 = textStrict "int256"+  pretty Uint256 = textStrict "uint256"+  pretty Bool = textStrict "bool"+  pretty Address = textStrict "address"+  pretty (Mapping k v) = pretty k <> textStrict "->" <> pretty v+  pretty (Unknown t) = textStrict ("unknown_" <> t)+ data FunDefinition = FunDefinition   { fName :: Idfr   , fParams :: [VarDecl]   , fReturns :: [VarDecl]   , fBody :: [Statement]-  } deriving (Eq, Generic, Show, GP.Out)+  } deriving (Eq, Generic, Show) +instance Pretty FunDefinition where+  pretty FunDefinition { fName = _name+                       , fParams = _params+                       , fReturns = _returns+                       , fBody = _body+                       } =+    pretty _name <> tupled (map pretty _params) <+>+    textStrict "returns" <> tupled (map pretty _returns) <+>+    semiBraces (map pretty _body)+ data Statement   = StLocalVarDecl VarDecl   | StAssign LValue@@ -85,8 +125,24 @@   | StDelete LValue   | StTodo Text   | StThrow-  deriving (Eq, Generic, Show, GP.Out)+  deriving (Eq, Generic, Show) +instance Pretty Statement where+  pretty (StLocalVarDecl vd) = pretty vd+  pretty (StAssign lv exp) = pretty lv <+> textStrict "=" <+> pretty exp+  pretty (StIf cond thenB elseB) =+    textStrict "if" <+>+    parens (pretty cond) <+>+    semiBraces (map pretty thenB) <+>+    textStrict "else" <+> semiBraces (map pretty elseB)+  pretty (StLoop loopB) = textStrict "loop" <+> semiBraces (map pretty loopB)+  pretty (StBreak) = textStrict "break"+  pretty (StContinue) = textStrict "continue"+  pretty (StReturn rvals) = textStrict "return" <+> tupled (map pretty rvals)+  pretty (StDelete v) = textStrict "delete" <+> pretty v+  pretty (StTodo t) = textStrict "todo" <+> textStrict t+  pretty (StThrow) = textStrict "throw"+ data Expression   = ExpUnary Text              LValue@@ -97,17 +153,16 @@   | ExpLval LValue   | ExpCall LValue             [LValue]-  deriving (Eq, Generic, Show, GP.Out)--instance GP.Out Text where-  doc = PP.quotes . PP.text . toS-  docPrec _ = GP.doc+  deriving (Eq, Generic, Show) -instance GP.Out SolNode+instance Pretty Expression where+  pretty (ExpUnary op v) = textStrict op <> pretty v+  pretty (ExpBin op v1 v2) = pretty v1 <> textStrict op <> pretty v2+  pretty (ExpLiteral v) = pretty v+  pretty (ExpLval lv) = pretty lv+  pretty (ExpCall f lvals) = pretty f <> tupled (map pretty lvals) -s2sContracts-  :: UniqueMonad m-  => SolNode -> m [Contract]+s2sContracts :: UniqueMonad m => SolNode -> m [Contract] s2sContracts SolNode {_AST = Just n} = s2sContracts n s2sContracts SolNode {name = Just "SourceUnit", children = Just sChildren} =   concat <$> mapM s2sContracts sChildren@@ -118,9 +173,7 @@   (vars, funs) <- s2sVarsFuns vChildren   return [Contract cName vars funs]   where-    s2sVarsFuns-      :: UniqueMonad m-      => [SolNode] -> m ([VarDecl], [FunDefinition])+    s2sVarsFuns :: UniqueMonad m => [SolNode] -> m ([VarDecl], [FunDefinition])     s2sVarsFuns [] = return ([], [])     s2sVarsFuns (h:t) = do       (vars', funs') <- s2sVarsFuns t@@ -134,14 +187,21 @@                     , attributes = Just SolNode { name = Just vName                                                 , _type = Just vType                                                 }-                    } = [VarDecl (Idfr vName) (Unknown vType)]+                    } =+  [ VarDecl+      (Idfr vName)+      (case vType of+         "bool" -> Bool+         "address" -> Address+         "int256" -> Int256+         "uint256" -> Uint256+         _ -> Unknown vType)+  ] s2sVarDecls SolNode {name = Just "ParameterList", children = Just pChildren} =   concatMap s2sVarDecls pChildren s2sVarDecls _ = [] -s2sFuns-  :: UniqueMonad m-  => SolNode -> m [FunDefinition]+s2sFuns :: UniqueMonad m => SolNode -> m [FunDefinition] s2sFuns SolNode { name = Just "FunctionDefinition"                 , children = Just [params, returns, body]                 , attributes = Just SolNode {name = Just fName}@@ -156,9 +216,7 @@     ] s2sFuns _ = return [] -s2sStatements-  :: UniqueMonad m-  => SolNode -> m [Statement]+s2sStatements :: UniqueMonad m => SolNode -> m [Statement] s2sStatements SolNode {name = Just "Block", children = Just sChildren} =   concat <$> mapM s2sStatements sChildren s2sStatements SolNode { name = Just "ExpressionStatement"@@ -195,6 +253,18 @@   let newidfr = JustId $ Idfr newVar   return     [StAssign newidfr $ ExpLiteral "1", StAssign idfr $ ExpBin "+" idfr newidfr]+s2sStatements e@SolNode { name = Just "UnaryOperation"+                        , children = Just [op1]+                        , attributes = Just SolNode {operator = Just "++"}+                        } = do+  (preOp1, lvalOp1) <- s2sLval op1+  newVar <- uniqueVar+  let newidfr = JustId $ Idfr newVar+  return $+    preOp1 <>+    [ StAssign newidfr $ ExpLiteral "1"+    , StAssign lvalOp1 $ ExpBin "+" lvalOp1 newidfr+    ] s2sStatements SolNode { name = Just "UnaryOperation"                       , children = Just [SolNode { name = Just "Identifier"                                                  , attributes = Just SolNode {value = Just idName}@@ -206,6 +276,18 @@   let newidfr = JustId $ Idfr newVar   return     [StAssign newidfr $ ExpLiteral "1", StAssign idfr $ ExpBin "-" idfr newidfr]+s2sStatements e@SolNode { name = Just "UnaryOperation"+                        , children = Just [op1]+                        , attributes = Just SolNode {operator = Just "--"}+                        } = do+  (preOp1, lvalOp1) <- s2sLval op1+  newVar <- uniqueVar+  let newidfr = JustId $ Idfr newVar+  return $+    preOp1 <>+    [ StAssign newidfr $ ExpLiteral "1"+    , StAssign lvalOp1 $ ExpBin "-" lvalOp1 newidfr+    ] s2sStatements SolNode { name = Just "IfStatement"                       , children = Just [cond, thenBr]                       } = do@@ -224,7 +306,7 @@                       } = do   (precond, lvalcond) <- s2sLval cond   bodySts <- s2sStatements body-  return [StLoop (precond <> [StIf lvalcond bodySts [StBreak]])]+  return [StLoop (precond <> [StIf lvalcond (bodySts <> [StContinue]) [StBreak]])] s2sStatements SolNode { name = Just "DoWhileStatement"                       , children = Just [cond, body]                       } = do@@ -240,7 +322,7 @@   bodySts <- s2sStatements body   return $     initSts <>-    [StLoop (precond <> [StIf lvalcond (bodySts <> iterSts) [StBreak]])]+    [StLoop (precond <> [StIf lvalcond (bodySts <> iterSts <> [StContinue]) [StBreak]])] s2sStatements SolNode {name = Just "Break"} = return [StBreak] s2sStatements SolNode {name = Just "Continue"} = return [StContinue] s2sStatements SolNode { name = Just "VariableDeclarationStatement"@@ -259,11 +341,11 @@   -- TODO(zchn): Handle this properly.  = return [] s2sStatements SolNode {name = Just "Throw"} = return [StThrow]-s2sStatements s = unimplementedPanic s {children = Nothing}+s2sStatements SolNode {name = Just "InlineAssembly"} =+  return [StTodo "InlineAssembly"]+s2sStatements s = unimplementedPanic s -s2sLval-  :: UniqueMonad m-  => SolNode -> m ([Statement], LValue)+s2sLval :: UniqueMonad m => SolNode -> m ([Statement], LValue) s2sLval SolNode { name = Just "Identifier"                 , attributes = Just SolNode {value = Just idName}                 } = return ([], JustId (Idfr idName))@@ -280,9 +362,8 @@   (presub, simpleLvalSub) <- handleSubscription simpleLval ctail   return (presub <> prelval, Index simpleLval simpleLvalSub)   where-    handleSubscription-      :: UniqueMonad m-      => LValue -> [SolNode] -> m ([Statement], LValue)+    handleSubscription ::+         UniqueMonad m => LValue -> [SolNode] -> m ([Statement], LValue)     handleSubscription lv [] = unexpectedPanic lv     handleSubscription lv [subNode] = do       (presub', simpleLvalSub') <- s2sLval subNode@@ -361,11 +442,14 @@   let preArgs = concatMap fst preAndlvals -- TODO(zchn): reverse?   let lvalArgs = map snd preAndlvals   return (preArgs, Tuple lvalArgs)+s2sLval SolNode { name = Just "NewExpression"+                , attributes = Just SolNode {_type = Just t}+                } = do+  let normalized = "_ea_new_" <> replace t " " "_"+  return ([], JustId $ Idfr normalized) s2sLval n = unimplementedPanic n {children = Nothing} -uniqueVar-  :: UniqueMonad m-  => m Text+uniqueVar :: UniqueMonad m => m Text uniqueVar = ("v" <>) . toS . show <$> freshUnique  -- lastLvalOf :: [Statement] -> LValue
src/Ethereum/Analyzer/Util.hs view
@@ -13,30 +13,24 @@ import Data.Graph.Inductive.PatriciaTree import Data.GraphViz import Data.GraphViz.Printing hiding ((<>))-import qualified Data.Text.Lazy as DTL import qualified Data.List as DL+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+instance (Show (n C O), Show (n O O), Show (n O C)) => Show (Block n C C) where   show a =     let (h, m, t) = blockSplit a     in DL.unlines $ [show h] <> map show (blockToList m) <> [show t] -toDotText-  :: (NonLocal n, Show (Block n C C))-  => CH.Graph n O C -> Text+toDotText :: (NonLocal n, Show (Block n C C)) => CH.Graph n O C -> Text toDotText bd =   let bdGr = toGr bd       dotG = toDotGraph bdGr       dotCode = toDot dotG   in DTL.toStrict $ renderDot dotCode -toGr-  :: NonLocal n-  => CH.Graph n O C -> Gr (Block n C C) ()+toGr :: NonLocal n => CH.Graph n O C -> Gr (Block n C C) () toGr bd =   let lblToNode l = read (drop 1 $ toS $ show l)       blocks = postorder_dfs bd@@ -50,14 +44,14 @@           blocks   in mkGraph nList eList -visParams-  :: (Show (Block n C C))-  => GraphvizParams p (Block n C C) el () (Block n C C)+visParams ::+     (Show (Block n C C)) => GraphvizParams p (Block n C C) el () (Block n C C) visParams =   nonClusteredParams-  {fmtNode = \(_, nl) -> [textLabel (toS $ show nl), shape BoxShape]}+  { fmtNode =+      \(_, nl) ->+        [textLabel (DTL.replace "\n" "\\l" $ toS $ show nl), shape BoxShape]+  } -toDotGraph-  :: (Show (Block n C C))-  => Gr (Block n C C) () -> DotGraph Node+toDotGraph :: (Show (Block n C C)) => Gr (Block n C C) () -> DotGraph Node toDotGraph = graphToDot visParams
test/Ethereum/Analyzer/EVM/UtilSpec.hs view
@@ -31,74 +31,74 @@ -- There are more opcode in the hexstring than printed here. expectedHexString2RawDot :: Text expectedHexString2RawDot =-  "digraph {\n" <> "    1 [label=\"CO: L1\\n" <> "OO: 0: PUSH [96]\\n" <>-  "OO: 2: PUSH [64]\\n" <>-  "OO: 4: MSTORE\\n" <>-  "OO: 5: CALLDATASIZE\\n" <>-  "OO: 6: ISZERO\\n" <>-  "OO: 7: PUSH [39]\\n" <>-  "OC: 9: JUMPI -> [L3]\\n" <>+  "digraph {\n" <> "    1 [label=\"CO: L1\\l" <> "OO: 0: PUSH [96]\\l" <>+  "OO: 2: PUSH [64]\\l" <>+  "OO: 4: MSTORE\\l" <>+  "OO: 5: CALLDATASIZE\\l" <>+  "OO: 6: ISZERO\\l" <>+  "OO: 7: PUSH [39]\\l" <>+  "OC: 9: JUMPI -> [L3]\\l" <>   "\"\n" <>   "      ,shape=box];\n" <>-  "    3 [label=\"CO: L3\\n" <>-  "OO: 10: PUSH [224]\\n" <>-  "OO: 12: PUSH [2]\\n" <>-  "OO: 14: EXP\\n" <>-  "OO: 15: PUSH [0]\\n" <>-  "OO: 17: CALLDATALOAD\\n" <>-  "OO: 18: DIV\\n" <>-  "OO: 19: PUSH [65,192,225,181]\\n" <>-  "OO: 24: DUP2\\n" <>-  "OO: 25: EQ\\n" <>-  "OO: 26: PUSH [110]\\n" <>-  "OC: 28: JUMPI -> [L4]\\n" <>+  "    3 [label=\"CO: L3\\l" <>+  "OO: 10: PUSH [224]\\l" <>+  "OO: 12: PUSH [2]\\l" <>+  "OO: 14: EXP\\l" <>+  "OO: 15: PUSH [0]\\l" <>+  "OO: 17: CALLDATALOAD\\l" <>+  "OO: 18: DIV\\l" <>+  "OO: 19: PUSH [65,192,225,181]\\l" <>+  "OO: 24: DUP2\\l" <>+  "OO: 25: EQ\\l" <>+  "OO: 26: PUSH [110]\\l" <>+  "OC: 28: JUMPI -> [L4]\\l" <>   "\"\n" <>   "      ,shape=box];\n" <>-  "    4 [label=\"CO: L4\\n" <>-  "OO: 29: DUP1\\n" <>-  "OO: 30: PUSH [229,34,83,129]\\n" <>-  "OO: 35: EQ\\n" <>-  "OO: 36: PUSH [150]\\n" <>-  "OC: 38: JUMPI -> [L5]\\n" <>+  "    4 [label=\"CO: L4\\l" <>+  "OO: 29: DUP1\\l" <>+  "OO: 30: PUSH [229,34,83,129]\\l" <>+  "OO: 35: EQ\\l" <>+  "OO: 36: PUSH [150]\\l" <>+  "OC: 38: JUMPI -> [L5]\\l" <>   "\"\n" <>   "      ,shape=box];\n" <>-  "    5 [label=\"CO: L5\\n" <>-  "OO: 39: JUMPDEST\\n" <>-  "OO: 40: PUSH [213]\\n" <>-  "OO: 42: PUSH [0]\\n" <>-  "OO: 44: CALLVALUE\\n" <>-  "OO: 45: GT\\n" <>-  "OO: 46: ISZERO\\n" <>-  "OO: 47: PUSH [108]\\n" <>-  "OC: 49: JUMPI -> [L6]\\n" <>+  "    5 [label=\"CO: L5\\l" <>+  "OO: 39: JUMPDEST\\l" <>+  "OO: 40: PUSH [213]\\l" <>+  "OO: 42: PUSH [0]\\l" <>+  "OO: 44: CALLVALUE\\l" <>+  "OO: 45: GT\\l" <>+  "OO: 46: ISZERO\\l" <>+  "OO: 47: PUSH [108]\\l" <>+  "OC: 49: JUMPI -> [L6]\\l" <>   "\"\n" <>   "      ,shape=box];\n" <>-  "    6 [label=\"CO: L6\\n" <>-  "OO: 50: CALLVALUE\\n" <>-  "OO: 51: PUSH [96]\\n" <>-  "OO: 53: SWAP1\\n" <>-  "OO: 54: DUP2\\n" <>-  "OO: 55: MSTORE\\n" <>-  "OO: 56: PUSH [88]\\n" <>-  "OO: 58: SWAP1\\n" <>-  "OO: 59: PUSH [1]\\n" <>-  "OO: 61: PUSH [160]\\n" <>-  "OO: 63: PUSH [2]\\n" <>-  "OO: 65: EXP\\n" <>-  "OO: 66: SUB\\n" <>-  "OO: 67: CALLER\\n" <>-  "OO: 68: AND\\n" <>-  "OO: 69: SWAP1\\n" <>-  "OO: 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]\\n" <>-  "OO: 103: SWAP1\\n" <>-  "OO: 104: PUSH [32]\\n" <>-  "OO: 106: SWAP1\\n" <>-  "OC: 107: LOG3 -> [L7]\\n" <>+  "    6 [label=\"CO: L6\\l" <>+  "OO: 50: CALLVALUE\\l" <>+  "OO: 51: PUSH [96]\\l" <>+  "OO: 53: SWAP1\\l" <>+  "OO: 54: DUP2\\l" <>+  "OO: 55: MSTORE\\l" <>+  "OO: 56: PUSH [88]\\l" <>+  "OO: 58: SWAP1\\l" <>+  "OO: 59: PUSH [1]\\l" <>+  "OO: 61: PUSH [160]\\l" <>+  "OO: 63: PUSH [2]\\l" <>+  "OO: 65: EXP\\l" <>+  "OO: 66: SUB\\l" <>+  "OO: 67: CALLER\\l" <>+  "OO: 68: AND\\l" <>+  "OO: 69: SWAP1\\l" <>+  "OO: 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]\\l" <>+  "OO: 103: SWAP1\\l" <>+  "OO: 104: PUSH [32]\\l" <>+  "OO: 106: SWAP1\\l" <>+  "OC: 107: LOG3 -> [L7]\\l" <>   "\"\n" <>   "      ,shape=box];\n" <>-  "    7 [label=\"CO: L7\\n" <>-  "OO: 108: JUMPDEST\\n" <>-  "OC: 109: JUMP -> []\\n" <>+  "    7 [label=\"CO: L7\\l" <>+  "OO: 108: JUMPDEST\\l" <>+  "OC: 109: JUMP -> []\\l" <>   "\"\n" <>   "      ,shape=box];\n" <>   "    1 -> 3;\n" <>@@ -110,171 +110,171 @@  expectedHexString2AugDot :: Text expectedHexString2AugDot =-  "digraph {\n" <> "    1 [label=\"CO: L1\\n" <> "OO: 0: PUSH [96]\\n" <>-  "OO: 2: PUSH [64]\\n" <>-  "OO: 4: MSTORE\\n" <>-  "OO: 5: CALLDATASIZE\\n" <>-  "OO: 6: ISZERO\\n" <>-  "OO: 7: PUSH [39]\\n" <>-  "OC: 9: JUMPI -> [L3,L5]\\n" <>+  "digraph {\n" <> "    1 [label=\"CO: L1\\l" <> "OO: 0: PUSH [96]\\l" <>+  "OO: 2: PUSH [64]\\l" <>+  "OO: 4: MSTORE\\l" <>+  "OO: 5: CALLDATASIZE\\l" <>+  "OO: 6: ISZERO\\l" <>+  "OO: 7: PUSH [39]\\l" <>+  "OC: 9: JUMPI -> [L3,L5]\\l" <>   "\"\n" <>   "      ,shape=box];\n" <>-  "    3 [label=\"CO: L3\\n" <>-  "OO: 10: PUSH [224]\\n" <>-  "OO: 12: PUSH [2]\\n" <>-  "OO: 14: EXP\\n" <>-  "OO: 15: PUSH [0]\\n" <>-  "OO: 17: CALLDATALOAD\\n" <>-  "OO: 18: DIV\\n" <>-  "OO: 19: PUSH [65,192,225,181]\\n" <>-  "OO: 24: DUP2\\n" <>-  "OO: 25: EQ\\n" <>-  "OO: 26: PUSH [110]\\n" <>-  "OC: 28: JUMPI -> [L4,L8]\\n" <>+  "    3 [label=\"CO: L3\\l" <>+  "OO: 10: PUSH [224]\\l" <>+  "OO: 12: PUSH [2]\\l" <>+  "OO: 14: EXP\\l" <>+  "OO: 15: PUSH [0]\\l" <>+  "OO: 17: CALLDATALOAD\\l" <>+  "OO: 18: DIV\\l" <>+  "OO: 19: PUSH [65,192,225,181]\\l" <>+  "OO: 24: DUP2\\l" <>+  "OO: 25: EQ\\l" <>+  "OO: 26: PUSH [110]\\l" <>+  "OC: 28: JUMPI -> [L4,L8]\\l" <>   "\"\n" <>   "      ,shape=box];\n" <>-  "    4 [label=\"CO: L4\\n" <>-  "OO: 29: DUP1\\n" <>-  "OO: 30: PUSH [229,34,83,129]\\n" <>-  "OO: 35: EQ\\n" <>-  "OO: 36: PUSH [150]\\n" <>-  "OC: 38: JUMPI -> [L5,L10]\\n" <>+  "    4 [label=\"CO: L4\\l" <>+  "OO: 29: DUP1\\l" <>+  "OO: 30: PUSH [229,34,83,129]\\l" <>+  "OO: 35: EQ\\l" <>+  "OO: 36: PUSH [150]\\l" <>+  "OC: 38: JUMPI -> [L5,L10]\\l" <>   "\"\n" <>   "      ,shape=box];\n" <>-  "    5 [label=\"CO: L5\\n" <>-  "OO: 39: JUMPDEST\\n" <>-  "OO: 40: PUSH [213]\\n" <>-  "OO: 42: PUSH [0]\\n" <>-  "OO: 44: CALLVALUE\\n" <>-  "OO: 45: GT\\n" <>-  "OO: 46: ISZERO\\n" <>-  "OO: 47: PUSH [108]\\n" <>-  "OC: 49: JUMPI -> [L6,L7]\\n" <>+  "    5 [label=\"CO: L5\\l" <>+  "OO: 39: JUMPDEST\\l" <>+  "OO: 40: PUSH [213]\\l" <>+  "OO: 42: PUSH [0]\\l" <>+  "OO: 44: CALLVALUE\\l" <>+  "OO: 45: GT\\l" <>+  "OO: 46: ISZERO\\l" <>+  "OO: 47: PUSH [108]\\l" <>+  "OC: 49: JUMPI -> [L6,L7]\\l" <>   "\"\n" <>   "      ,shape=box];\n" <>-  "    6 [label=\"CO: L6\\n" <>-  "OO: 50: CALLVALUE\\n" <>-  "OO: 51: PUSH [96]\\n" <>-  "OO: 53: SWAP1\\n" <>-  "OO: 54: DUP2\\n" <>-  "OO: 55: MSTORE\\n" <>-  "OO: 56: PUSH [88]\\n" <>-  "OO: 58: SWAP1\\n" <>-  "OO: 59: PUSH [1]\\n" <>-  "OO: 61: PUSH [160]\\n" <>-  "OO: 63: PUSH [2]\\n" <>-  "OO: 65: EXP\\n" <>-  "OO: 66: SUB\\n" <>-  "OO: 67: CALLER\\n" <>-  "OO: 68: AND\\n" <>-  "OO: 69: SWAP1\\n" <>-  "OO: 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]\\n" <>-  "OO: 103: SWAP1\\n" <>-  "OO: 104: PUSH [32]\\n" <>-  "OO: 106: SWAP1\\n" <>-  "OC: 107: LOG3 -> [L7]\\n" <>+  "    6 [label=\"CO: L6\\l" <>+  "OO: 50: CALLVALUE\\l" <>+  "OO: 51: PUSH [96]\\l" <>+  "OO: 53: SWAP1\\l" <>+  "OO: 54: DUP2\\l" <>+  "OO: 55: MSTORE\\l" <>+  "OO: 56: PUSH [88]\\l" <>+  "OO: 58: SWAP1\\l" <>+  "OO: 59: PUSH [1]\\l" <>+  "OO: 61: PUSH [160]\\l" <>+  "OO: 63: PUSH [2]\\l" <>+  "OO: 65: EXP\\l" <>+  "OO: 66: SUB\\l" <>+  "OO: 67: CALLER\\l" <>+  "OO: 68: AND\\l" <>+  "OO: 69: SWAP1\\l" <>+  "OO: 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]\\l" <>+  "OO: 103: SWAP1\\l" <>+  "OO: 104: PUSH [32]\\l" <>+  "OO: 106: SWAP1\\l" <>+  "OC: 107: LOG3 -> [L7]\\l" <>   "\"\n" <>   "      ,shape=box];\n" <>-  "    7 [label=\"CO: L7\\n" <>-  "OO: 108: JUMPDEST\\n" <>-  "OC: 109: JUMP -> []\\n" <>+  "    7 [label=\"CO: L7\\l" <>+  "OO: 108: JUMPDEST\\l" <>+  "OC: 109: JUMP -> []\\l" <>   "\"\n" <>   "      ,shape=box];\n" <>-  "    8 [label=\"CO: L8\\n" <>-  "OO: 110: JUMPDEST\\n" <>-  "OO: 111: PUSH [213]\\n" <>-  "OO: 113: PUSH [0]\\n" <>-  "OO: 115: SLOAD\\n" <>-  "OO: 116: PUSH [1]\\n" <>-  "OO: 118: PUSH [160]\\n" <>-  "OO: 120: PUSH [2]\\n" <>-  "OO: 122: EXP\\n" <>-  "OO: 123: SUB\\n" <>-  "OO: 124: SWAP1\\n" <>-  "OO: 125: DUP2\\n" <>-  "OO: 126: AND\\n" <>-  "OO: 127: CALLER\\n" <>-  "OO: 128: SWAP2\\n" <>-  "OO: 129: SWAP1\\n" <>-  "OO: 130: SWAP2\\n" <>-  "OO: 131: AND\\n" <>-  "OO: 132: EQ\\n" <>-  "OO: 133: ISZERO\\n" <>-  "OO: 134: PUSH [108]\\n" <>-  "OC: 136: JUMPI -> [L7,L9]\\n" <>+  "    8 [label=\"CO: L8\\l" <>+  "OO: 110: JUMPDEST\\l" <>+  "OO: 111: PUSH [213]\\l" <>+  "OO: 113: PUSH [0]\\l" <>+  "OO: 115: SLOAD\\l" <>+  "OO: 116: PUSH [1]\\l" <>+  "OO: 118: PUSH [160]\\l" <>+  "OO: 120: PUSH [2]\\l" <>+  "OO: 122: EXP\\l" <>+  "OO: 123: SUB\\l" <>+  "OO: 124: SWAP1\\l" <>+  "OO: 125: DUP2\\l" <>+  "OO: 126: AND\\l" <>+  "OO: 127: CALLER\\l" <>+  "OO: 128: SWAP2\\l" <>+  "OO: 129: SWAP1\\l" <>+  "OO: 130: SWAP2\\l" <>+  "OO: 131: AND\\l" <>+  "OO: 132: EQ\\l" <>+  "OO: 133: ISZERO\\l" <>+  "OO: 134: PUSH [108]\\l" <>+  "OC: 136: JUMPI -> [L7,L9]\\l" <>   "\"\n" <>   "      ,shape=box];\n" <>-  "    9 [label=\"CO: L9\\n" <>-  "OO: 137: PUSH [0]\\n" <>-  "OO: 139: SLOAD\\n" <>-  "OO: 140: PUSH [1]\\n" <>-  "OO: 142: PUSH [160]\\n" <>-  "OO: 144: PUSH [2]\\n" <>-  "OO: 146: EXP\\n" <>-  "OO: 147: SUB\\n" <>-  "OO: 148: AND\\n" <>-  "OC: 149: SUICIDE -> []\\n" <>+  "    9 [label=\"CO: L9\\l" <>+  "OO: 137: PUSH [0]\\l" <>+  "OO: 139: SLOAD\\l" <>+  "OO: 140: PUSH [1]\\l" <>+  "OO: 142: PUSH [160]\\l" <>+  "OO: 144: PUSH [2]\\l" <>+  "OO: 146: EXP\\l" <>+  "OO: 147: SUB\\l" <>+  "OO: 148: AND\\l" <>+  "OC: 149: SUICIDE -> []\\l" <>   "\"\n" <>   "      ,shape=box];\n" <>-  "    10 [label=\"CO: L10\\n" <>-  "OO: 150: JUMPDEST\\n" <>-  "OO: 151: PUSH [213]\\n" <>-  "OO: 153: PUSH [0]\\n" <>-  "OO: 155: SLOAD\\n" <>-  "OO: 156: PUSH [1]\\n" <>-  "OO: 158: PUSH [160]\\n" <>-  "OO: 160: PUSH [2]\\n" <>-  "OO: 162: EXP\\n" <>-  "OO: 163: SUB\\n" <>-  "OO: 164: SWAP1\\n" <>-  "OO: 165: DUP2\\n" <>-  "OO: 166: AND\\n" <>-  "OO: 167: CALLER\\n" <>-  "OO: 168: SWAP2\\n" <>-  "OO: 169: SWAP1\\n" <>-  "OO: 170: SWAP2\\n" <>-  "OO: 171: AND\\n" <>-  "OO: 172: EQ\\n" <>-  "OO: 173: ISZERO\\n" <>-  "OO: 174: PUSH [108]\\n" <>-  "OC: 176: JUMPI -> [L7,L11]\\n" <>+  "    10 [label=\"CO: L10\\l" <>+  "OO: 150: JUMPDEST\\l" <>+  "OO: 151: PUSH [213]\\l" <>+  "OO: 153: PUSH [0]\\l" <>+  "OO: 155: SLOAD\\l" <>+  "OO: 156: PUSH [1]\\l" <>+  "OO: 158: PUSH [160]\\l" <>+  "OO: 160: PUSH [2]\\l" <>+  "OO: 162: EXP\\l" <>+  "OO: 163: SUB\\l" <>+  "OO: 164: SWAP1\\l" <>+  "OO: 165: DUP2\\l" <>+  "OO: 166: AND\\l" <>+  "OO: 167: CALLER\\l" <>+  "OO: 168: SWAP2\\l" <>+  "OO: 169: SWAP1\\l" <>+  "OO: 170: SWAP2\\l" <>+  "OO: 171: AND\\l" <>+  "OO: 172: EQ\\l" <>+  "OO: 173: ISZERO\\l" <>+  "OO: 174: PUSH [108]\\l" <>+  "OC: 176: JUMPI -> [L7,L11]\\l" <>   "\"\n" <>   "       ,shape=box];\n" <>-  "    11 [label=\"CO: L11\\n" <>-  "OO: 177: PUSH [0]\\n" <>-  "OO: 179: DUP1\\n" <>-  "OO: 180: SLOAD\\n" <>-  "OO: 181: PUSH [1]\\n" <>-  "OO: 183: PUSH [160]\\n" <>-  "OO: 185: PUSH [2]\\n" <>-  "OO: 187: EXP\\n" <>-  "OO: 188: SUB\\n" <>-  "OO: 189: SWAP1\\n" <>-  "OO: 190: DUP2\\n" <>-  "OO: 191: AND\\n" <>-  "OO: 192: SWAP2\\n" <>-  "OO: 193: SWAP1\\n" <>-  "OO: 194: ADDRESS\\n" <>-  "OO: 195: AND\\n" <>-  "OO: 196: BALANCE\\n" <>-  "OO: 197: PUSH [96]\\n" <>-  "OO: 199: DUP3\\n" <>-  "OO: 200: DUP2\\n" <>-  "OO: 201: DUP2\\n" <>-  "OO: 202: DUP2\\n" <>-  "OO: 203: DUP6\\n" <>-  "OO: 204: DUP9\\n" <>-  "OO: 205: DUP4\\n" <>-  "OC: 206: CALL -> [L12]\\n" <>+  "    11 [label=\"CO: L11\\l" <>+  "OO: 177: PUSH [0]\\l" <>+  "OO: 179: DUP1\\l" <>+  "OO: 180: SLOAD\\l" <>+  "OO: 181: PUSH [1]\\l" <>+  "OO: 183: PUSH [160]\\l" <>+  "OO: 185: PUSH [2]\\l" <>+  "OO: 187: EXP\\l" <>+  "OO: 188: SUB\\l" <>+  "OO: 189: SWAP1\\l" <>+  "OO: 190: DUP2\\l" <>+  "OO: 191: AND\\l" <>+  "OO: 192: SWAP2\\l" <>+  "OO: 193: SWAP1\\l" <>+  "OO: 194: ADDRESS\\l" <>+  "OO: 195: AND\\l" <>+  "OO: 196: BALANCE\\l" <>+  "OO: 197: PUSH [96]\\l" <>+  "OO: 199: DUP3\\l" <>+  "OO: 200: DUP2\\l" <>+  "OO: 201: DUP2\\l" <>+  "OO: 202: DUP2\\l" <>+  "OO: 203: DUP6\\l" <>+  "OO: 204: DUP9\\l" <>+  "OO: 205: DUP4\\l" <>+  "OC: 206: CALL -> [L12]\\l" <>   "\"\n" <>   "       ,shape=box];\n" <>-  "    12 [label=\"CO: L12\\n" <>-  "OO: 207: POP\\n" <>-  "OO: 208: POP\\n" <>-  "OO: 209: POP\\n" <>-  "OO: 210: POP\\n" <>-  "OO: 211: POP\\n" <>-  "OC: 212: JUMP -> []\\n" <>+  "    12 [label=\"CO: L12\\l" <>+  "OO: 207: POP\\l" <>+  "OO: 208: POP\\l" <>+  "OO: 209: POP\\l" <>+  "OO: 210: POP\\l" <>+  "OO: 211: POP\\l" <>+  "OC: 212: JUMP -> []\\l" <>   "\"\n" <>   "       ,shape=box];\n" <>   "    1 -> 3;\n" <>
test/Ethereum/Analyzer/Solidity/SimpleSpec.hs view
@@ -13,7 +13,6 @@  -- import GHC.Show (Show(..)) import Test.Hspec-import qualified Text.PrettyPrint.GenericPretty as GP  spec :: Spec spec = do@@ -30,25 +29,27 @@           [ Contract             { cName = "SimpleStorage"             , cStateVars =-                [VarDecl {vName = Idfr "storedData", vType = Unknown "uint256"}]+                [ VarDecl+                  {vName = Idfr {unIdfr = "storedData"}, vType = Uint256}+                ]             , cFunctions =                 [ FunDefinition-                  { fName = Idfr "set"+                  { fName = Idfr {unIdfr = "set"}                   , fParams =-                      [VarDecl {vName = Idfr "x", vType = Unknown "uint256"}]+                      [VarDecl {vName = Idfr {unIdfr = "x"}, vType = Uint256}]                   , fReturns = []                   , fBody =                       [ StAssign-                          (JustId (Idfr "storedData"))-                          (ExpLval (JustId (Idfr "x")))+                          (JustId (Idfr {unIdfr = "storedData"}))+                          (ExpLval (JustId (Idfr {unIdfr = "x"})))                       ]                   }                 , FunDefinition-                  { fName = Idfr "get"+                  { fName = Idfr {unIdfr = "get"}                   , fParams = []                   , fReturns =-                      [VarDecl {vName = Idfr "", vType = Unknown "uint256"}]-                  , fBody = [StReturn [JustId (Idfr "storedData")]]+                      [VarDecl {vName = Idfr {unIdfr = ""}, vType = Uint256}]+                  , fBody = [StReturn [JustId (Idfr {unIdfr = "storedData"})]]                   }                 ]             }