ethereum-analyzer 3.2.0 → 3.3.0
raw patch · 16 files changed
+474/−382 lines, 16 files
Files
- ChangeLog.md +21/−3
- ethereum-analyzer.cabal +2/−2
- src/Ethereum/Analyzer/Common.hs +6/−11
- src/Ethereum/Analyzer/Debug.hs +12/−5
- src/Ethereum/Analyzer/EVM/CfgAugWithTopNPass.hs +20/−24
- src/Ethereum/Analyzer/EVM/CfgAugmentPass.hs +16/−13
- src/Ethereum/Analyzer/EVM/Disasm.hs +1/−3
- src/Ethereum/Analyzer/EVM/IR.hs +16/−20
- src/Ethereum/Analyzer/EVM/Util.hs +2/−6
- src/Ethereum/Analyzer/Solidity/AstJson.hs +1/−1
- src/Ethereum/Analyzer/Solidity/Foreach.hs +1/−1
- src/Ethereum/Analyzer/Solidity/Hoople.hs +24/−20
- src/Ethereum/Analyzer/Solidity/Simple.hs +128/−44
- src/Ethereum/Analyzer/Util.hs +11/−17
- test/Ethereum/Analyzer/EVM/UtilSpec.hs +203/−203
- test/Ethereum/Analyzer/Solidity/SimpleSpec.hs +10/−9
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"})]] } ] }