ethereum-analyzer 2.0.2 → 3.0.0
raw patch · 34 files changed
+1857/−3989 lines, 34 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Ethereum.Analyzer: HplCode :: Maybe Label -> HplBody -> HplCode
- Ethereum.Analyzer: HplContract :: HplCode -> HplCode -> HplContract
- Ethereum.Analyzer: [CoOp] :: Label -> HplOp C O
- Ethereum.Analyzer: [HpCodeCopy] :: Word256 -> HplOp O O
- Ethereum.Analyzer: [OcOp] :: (Word256, Operation) -> [Label] -> HplOp O C
- Ethereum.Analyzer: [OoOp] :: (Word256, Operation) -> HplOp O O
- Ethereum.Analyzer: [bodyOf] :: HplCode -> HplBody
- Ethereum.Analyzer: [ctorOf] :: HplContract -> HplCode
- Ethereum.Analyzer: [dispatcherOf] :: HplContract -> HplCode
- Ethereum.Analyzer: [entryOf] :: HplCode -> Maybe Label
- Ethereum.Analyzer: data HplCode
- Ethereum.Analyzer: data HplContract
- Ethereum.Analyzer: data HplOp e x
- Ethereum.Analyzer: data WordLabelMapM a
- Ethereum.Analyzer: evmOps2HplCode :: [(Word256, Operation)] -> WordLabelMapM HplCode
- Ethereum.Analyzer: evmOps2HplContract :: [(Word256, Operation)] -> WordLabelMapM HplContract
- Ethereum.Analyzer: labelFor :: Word256 -> WordLabelMapM Label
- Ethereum.Analyzer: labelsFor :: [Word256] -> WordLabelMapM [Label]
- Ethereum.Analyzer: showOp :: (Word256, Operation) -> String
- Ethereum.Analyzer: showOps :: [(Word256, Operation)] -> [String]
- Ethereum.Analyzer: type HplBody = Body HplOp
- Ethereum.Analyzer: type WordLabelMapFuelM = CheckingFuelMonad WordLabelMapM
- Ethereum.Analyzer: unWordLabelMapM :: UnWordLabelMapM a => WordLabelMapM a -> a
- Ethereum.Analyzer.CfgAugWithTopNPass: doCfgAugWithTopNPass :: HasEvmBytecode a => a -> WordLabelMapM HplContract
- Ethereum.Analyzer.CfgAugmentPass: doCfgAugmentPass :: HplContract -> WordLabelMapM HplContract
- Ethereum.Analyzer.Disasm: EvmBytecode :: ByteString -> EvmBytecode
- Ethereum.Analyzer.Disasm: EvmHexString :: Text -> EvmHexString
- Ethereum.Analyzer.Disasm: [unEvmBytecode] :: EvmBytecode -> ByteString
- Ethereum.Analyzer.Disasm: [unEvmHexString] :: EvmHexString -> Text
- Ethereum.Analyzer.Disasm: class HasEvmBytecode a
- Ethereum.Analyzer.Disasm: disasm :: HasEvmBytecode a => a -> [(Word256, Operation)]
- Ethereum.Analyzer.Disasm: evmBytecodeOf :: HasEvmBytecode a => a -> EvmBytecode
- Ethereum.Analyzer.Disasm: instance Ethereum.Analyzer.Disasm.HasEvmBytecode Blockchain.Data.Code.Code
- Ethereum.Analyzer.Disasm: instance Ethereum.Analyzer.Disasm.HasEvmBytecode Ethereum.Analyzer.Disasm.EvmBytecode
- Ethereum.Analyzer.Disasm: instance Ethereum.Analyzer.Disasm.HasEvmBytecode Ethereum.Analyzer.Disasm.EvmHexString
- Ethereum.Analyzer.Disasm: instance GHC.Classes.Eq Ethereum.Analyzer.Disasm.EvmBytecode
- Ethereum.Analyzer.Disasm: instance GHC.Classes.Eq Ethereum.Analyzer.Disasm.EvmHexString
- Ethereum.Analyzer.Disasm: instance GHC.Show.Show Ethereum.Analyzer.Disasm.EvmBytecode
- Ethereum.Analyzer.Disasm: instance GHC.Show.Show Ethereum.Analyzer.Disasm.EvmHexString
- Ethereum.Analyzer.Disasm: newtype EvmBytecode
- Ethereum.Analyzer.Disasm: newtype EvmHexString
- Ethereum.Analyzer.Util: disasmToDotText :: HasEvmBytecode a => a -> Text
- Ethereum.Analyzer.Util: disasmToDotText2 :: HasEvmBytecode a => a -> (Text, Text)
- Ethereum.Analyzer.Util: toDotText :: HplBody -> Text
+ Ethereum.Analyzer.EVM: EvmBytecode :: ByteString -> EvmBytecode
+ Ethereum.Analyzer.EVM: EvmHexString :: Text -> EvmHexString
+ Ethereum.Analyzer.EVM: HplCode :: Maybe Label -> HplBody -> HplCode
+ Ethereum.Analyzer.EVM: HplContract :: HplCode -> HplCode -> HplContract
+ Ethereum.Analyzer.EVM: [CoOp] :: Label -> HplOp C O
+ Ethereum.Analyzer.EVM: [HpCodeCopy] :: Word256 -> HplOp O O
+ Ethereum.Analyzer.EVM: [OcOp] :: (Word256, Operation) -> [Label] -> HplOp O C
+ Ethereum.Analyzer.EVM: [OoOp] :: (Word256, Operation) -> HplOp O O
+ Ethereum.Analyzer.EVM: [bodyOf] :: HplCode -> HplBody
+ Ethereum.Analyzer.EVM: [ctorOf] :: HplContract -> HplCode
+ Ethereum.Analyzer.EVM: [dispatcherOf] :: HplContract -> HplCode
+ Ethereum.Analyzer.EVM: [entryOf] :: HplCode -> Maybe Label
+ Ethereum.Analyzer.EVM: [unEvmBytecode] :: EvmBytecode -> ByteString
+ Ethereum.Analyzer.EVM: [unEvmHexString] :: EvmHexString -> Text
+ Ethereum.Analyzer.EVM: class HasEvmBytecode a
+ Ethereum.Analyzer.EVM: data HplCode
+ Ethereum.Analyzer.EVM: data HplContract
+ Ethereum.Analyzer.EVM: data HplOp e x
+ Ethereum.Analyzer.EVM: data WordLabelMapM a
+ Ethereum.Analyzer.EVM: disasm :: HasEvmBytecode a => a -> [(Word256, Operation)]
+ Ethereum.Analyzer.EVM: disasmToDotText :: HasEvmBytecode a => a -> Text
+ Ethereum.Analyzer.EVM: disasmToDotText2 :: HasEvmBytecode a => a -> (Text, Text)
+ Ethereum.Analyzer.EVM: doCfgAugWithTopNPass :: HasEvmBytecode a => a -> WordLabelMapM HplContract
+ Ethereum.Analyzer.EVM: doCfgAugmentPass :: HplContract -> WordLabelMapM HplContract
+ Ethereum.Analyzer.EVM: evmBytecodeOf :: HasEvmBytecode a => a -> EvmBytecode
+ Ethereum.Analyzer.EVM: evmOps2HplCode :: [(Word256, Operation)] -> WordLabelMapM HplCode
+ Ethereum.Analyzer.EVM: evmOps2HplContract :: [(Word256, Operation)] -> WordLabelMapM HplContract
+ Ethereum.Analyzer.EVM: labelFor :: Word256 -> WordLabelMapM Label
+ Ethereum.Analyzer.EVM: labelsFor :: [Word256] -> WordLabelMapM [Label]
+ Ethereum.Analyzer.EVM: newtype EvmBytecode
+ Ethereum.Analyzer.EVM: newtype EvmHexString
+ Ethereum.Analyzer.EVM: showOp :: (Word256, Operation) -> String
+ Ethereum.Analyzer.EVM: showOps :: [(Word256, Operation)] -> [String]
+ Ethereum.Analyzer.EVM: toDotText :: HplBody -> Text
+ Ethereum.Analyzer.EVM: type HplBody = Body HplOp
+ Ethereum.Analyzer.EVM: type WordLabelMapFuelM = CheckingFuelMonad WordLabelMapM
+ Ethereum.Analyzer.EVM: unWordLabelMapM :: UnWordLabelMapM a => WordLabelMapM a -> a
Files
- ethereum-analyzer.cabal +17/−16
- src/Ethereum/Analyzer.hs +0/−9
- src/Ethereum/Analyzer/CfgAugWithTopNPass.hs +0/−395
- src/Ethereum/Analyzer/CfgAugmentPass.hs +0/−145
- src/Ethereum/Analyzer/Common.hs +2/−2
- src/Ethereum/Analyzer/Debug.hs +0/−2
- src/Ethereum/Analyzer/Disasm.hs +0/−53
- src/Ethereum/Analyzer/EVM.hs +13/−0
- src/Ethereum/Analyzer/EVM/CfgAugWithTopNPass.hs +396/−0
- src/Ethereum/Analyzer/EVM/CfgAugmentPass.hs +145/−0
- src/Ethereum/Analyzer/EVM/Disasm.hs +53/−0
- src/Ethereum/Analyzer/EVM/IR.hs +234/−0
- src/Ethereum/Analyzer/EVM/Util.hs +77/−0
- src/Ethereum/Analyzer/IR.hs +0/−234
- src/Ethereum/Analyzer/Solidity/AstJson.hs +3/−3
- src/Ethereum/Analyzer/Solidity/Foreach.hs +1/−1
- src/Ethereum/Analyzer/Solidity/Simple.hs +8/−6
- src/Ethereum/Analyzer/Util.hs +0/−77
- test/Ethereum/Analyzer/CfgAugWithTopNPassSpec.hs +0/−29
- test/Ethereum/Analyzer/CfgAugmentPassSpec.hs +0/−181
- test/Ethereum/Analyzer/EVM/CfgAugWithTopNPassSpec.hs +28/−0
- test/Ethereum/Analyzer/EVM/CfgAugmentPassSpec.hs +180/−0
- test/Ethereum/Analyzer/EVM/IRSpec.hs +183/−0
- test/Ethereum/Analyzer/EVM/UtilSpec.hs +397/−0
- test/Ethereum/Analyzer/IRSpec.hs +0/−183
- test/Ethereum/Analyzer/Solidity/AstJsonSpec.hs +21/−0
- test/Ethereum/Analyzer/Solidity/ForeachSpec.hs +10/−23
- test/Ethereum/Analyzer/Solidity/SimpleSpec.hs +48/−392
- test/Ethereum/Analyzer/SoliditySpec.hs +1/−45
- test/Ethereum/Analyzer/TestData/Asts.hs +36/−0
- test/Ethereum/Analyzer/TestData/Basic.hs +1/−1
- test/Ethereum/Analyzer/TestData/DaoJson.hs +0/−1790
- test/Ethereum/Analyzer/UtilSpec.hs +0/−399
- test/Ethereum/AnalyzerSpec.hs +3/−3
ethereum-analyzer.cabal view
@@ -1,7 +1,7 @@ name: ethereum-analyzer-version: 2.0.2+version: 3.0.0 synopsis: A Ethereum contract analyzer.-homepage: https://github.com/ethereumK/ethereum-analyzer+homepage: https://github.com/zchn/ethereum-analyzer license: Apache-2.0 license-file: LICENSE author: Kevin Chen@@ -21,7 +21,7 @@ source-repository this type: git location: https://github.com/zchn/ethereum-analyzer- tag: v2.0.2+ tag: v3.0.0 subdir: ethereum-analyzer library@@ -44,15 +44,15 @@ , unordered-containers , wl-pprint-text - exposed-modules: Ethereum.Analyzer- , Ethereum.Analyzer.Common- , Ethereum.Analyzer.CfgAugmentPass- , Ethereum.Analyzer.CfgAugWithTopNPass+ exposed-modules: Ethereum.Analyzer.Common+ , Ethereum.Analyzer.EVM , Ethereum.Analyzer.Debug- , Ethereum.Analyzer.Disasm , Ethereum.Analyzer.Solidity- , Ethereum.Analyzer.Util- other-modules: Ethereum.Analyzer.IR+ other-modules: Ethereum.Analyzer.EVM.IR+ , Ethereum.Analyzer.EVM.CfgAugmentPass+ , Ethereum.Analyzer.EVM.CfgAugWithTopNPass+ , Ethereum.Analyzer.EVM.Disasm+ , Ethereum.Analyzer.EVM.Util , Ethereum.Analyzer.Solidity.AstJson , Ethereum.Analyzer.Solidity.Finding , Ethereum.Analyzer.Solidity.Foreach@@ -69,16 +69,17 @@ ghc-options: -Wall hs-source-dirs: test main-is: Spec.hs- other-modules: Ethereum.Analyzer.CfgAugmentPassSpec- , Ethereum.Analyzer.CfgAugWithTopNPassSpec- , Ethereum.Analyzer.IRSpec- , Ethereum.Analyzer.SoliditySpec+ other-modules: Ethereum.Analyzer.EVM.CfgAugmentPassSpec+ , Ethereum.Analyzer.EVM.CfgAugWithTopNPassSpec+ , Ethereum.Analyzer.EVM.IRSpec+ , Ethereum.Analyzer.EVM.UtilSpec+ , Ethereum.Analyzer.Solidity.AstJsonSpec , Ethereum.Analyzer.Solidity.ForeachSpec , Ethereum.Analyzer.Solidity.SimpleSpec+ , Ethereum.Analyzer.SoliditySpec+ , Ethereum.Analyzer.TestData.Asts , Ethereum.Analyzer.TestData.Basic- , Ethereum.Analyzer.TestData.DaoJson , Ethereum.Analyzer.TestData.StorageJson- , Ethereum.Analyzer.UtilSpec , Ethereum.AnalyzerSpec build-depends: base >= 4 && < 5 , GenericPretty
− src/Ethereum/Analyzer.hs
@@ -1,9 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}--module Ethereum.Analyzer- ( module Ethereum.Analyzer.Disasm- , module Ethereum.Analyzer.IR- ) where--import Ethereum.Analyzer.Disasm-import Ethereum.Analyzer.IR
− src/Ethereum/Analyzer/CfgAugWithTopNPass.hs
@@ -1,395 +0,0 @@-{-# LANGUAGE OverloadedStrings, FlexibleContexts,- NoImplicitPrelude, FlexibleInstances, GADTs, Rank2Types,- TypeFamilies, UndecidableInstances #-}--module Ethereum.Analyzer.CfgAugWithTopNPass- ( doCfgAugWithTopNPass- ) where--import Protolude hiding (show)--import Blockchain.ExtWord-import Blockchain.VM.Opcodes as BVO-import Compiler.Hoopl-import Data.Bits as Db-import Data.ByteString as DB-import Data.List as DL-import Data.List.Extra as DLE-import Data.Set as DS hiding (toList)-import Ethereum.Analyzer-import Ethereum.Analyzer.Common-import GHC.Show-import Legacy.Haskoin.V0102.Network.Haskoin.Crypto.BigWord--type StackElemFact = WithTop (Set Word256)--joinStackElemBase- :: Label- -> OldFact (Set Word256)- -> NewFact (Set Word256)- -> (ChangeFlag, Set Word256)-joinStackElemBase _ (OldFact oldF) (NewFact newF) =- if newF `isSubsetOf` oldF- then (NoChange, oldF)- else (SomeChange, oldF `DS.union` newF)--joinStackElemFact- :: Label- -> OldFact StackElemFact- -> NewFact StackElemFact- -> (ChangeFlag, StackElemFact)-joinStackElemFact = liftJoinTop joinStackElemBase--type StackNFact = [StackElemFact]--joinStackNFact :: Label- -> OldFact StackNFact- -> NewFact StackNFact- -> (ChangeFlag, StackNFact)-joinStackNFact l (OldFact oldF) (NewFact newF) =- let zipped =- DL.zipWith- (\a b -> joinStackElemFact l (OldFact a) (NewFact b))- oldF- newF- (changedL, joinedF) = DL.unzip zipped- in ( changeIf $- DL.any- (\c ->- case c of- SomeChange -> True- NoChange -> False)- changedL- , joinedF)--stackNLattice :: Int -> DataflowLattice StackNFact-stackNLattice depth =- DataflowLattice- { fact_name = "stackNLattice"- , fact_bot = DL.replicate depth (PElem DS.empty)- , fact_join = joinStackNFact- }--_sizeBound :: Int-_sizeBound = 10--mkTopList- :: forall b b1 a.- [b] -> [Pointed C b1 a]-mkTopList = DL.map (const Top)--pairCompute :: (Word256 -> Word256 -> Word256) -> StackNFact -> StackNFact-pairCompute fun flist =- case flist of- [] -> mkTopList flist- [_] -> mkTopList flist- Top:_:tl -> (Top : tl) <> [Top]- _:Top:tl -> (Top : tl) <> [Top]- PElem st1:PElem st2:tl ->- let l1 = toList st1- in ((PElem $ DS.unions $ DL.map (\e1 -> DS.map (fun e1) st2) l1) : tl) <>- [Top]--popStack :: Int -> StackNFact -> StackNFact-popStack 0 f = f-popStack n (_:t) = popStack (n - 1) (t <> [Top])-popStack _ [] = []--pushStack' :: StackElemFact -> StackNFact -> StackNFact-pushStack' e flist = e : DLE.dropEnd 1 flist--pushStack :: Word256 -> StackNFact -> StackNFact-pushStack wd = pushStack' (PElem $ DS.singleton wd)--pushTop :: StackNFact -> StackNFact-pushTop flist = Top : DLE.dropEnd 1 flist--b2w256 :: Bool -> Word256-b2w256 True = 1-b2w256 False = 0---- w256Not :: Word256 -> Word256--- w256Not wd = bytesToWord256 $ DL.map complement $ word256ToBytes wd-w256And :: Word256 -> Word256 -> Word256-w256And wd1 wd2 =- bytesToWord256 $ DL.zipWith (.&.) (word256ToBytes wd1) (word256ToBytes wd2)--w256Or :: Word256 -> Word256 -> Word256-w256Or wd1 wd2 =- bytesToWord256 $ DL.zipWith (.|.) (word256ToBytes wd1) (word256ToBytes wd2)--w256Xor :: Word256 -> Word256 -> Word256-w256Xor wd1 wd2 =- bytesToWord256 $ DL.zipWith Db.xor (word256ToBytes wd1) (word256ToBytes wd2)--peekStack :: Int -> StackNFact -> StackElemFact-peekStack _ [] = Top-peekStack 1 (h:_) = h-peekStack n (_:t) = peekStack (n - 1) t--swapStack :: Int -> StackNFact -> StackNFact-swapStack n stk =- if n + 1 > DL.length stk- then pushTop $ popStack 1 stk- else let (h1:t1, h2:t2) = DL.splitAt n stk- in (h2 : t1) <> (h1 : t2)--stackNTransfer :: FwdTransfer HplOp StackNFact-stackNTransfer = mkFTransfer3 coT ooT ocT- where- coT :: HplOp C O -> StackNFact -> StackNFact- coT _ =- DL.map- (\f ->- case f of- Top -> Top- PElem st ->- if DS.size st > _sizeBound- then Top- else PElem st)- ooT :: HplOp O O -> StackNFact -> StackNFact- ooT (OoOp (_, op)) f = opT op f- ooT (HpCodeCopy _) f = f- ocT :: HplOp O C -> StackNFact -> FactBase StackNFact- -- TODO(zchn): Implement JUMPI narrowing- ocT hplop@(OcOp (_, op) _) f = distributeFact hplop (opT op f)- opT :: Operation -> StackNFact -> StackNFact- opT STOP flist = flist- opT ADD flist = pairCompute (+) flist- opT MUL flist = pairCompute (*) flist- opT SUB flist = pairCompute (-) flist- -- TODO(zchn): handle DIVs and MODs- opT DIV flist = popStack 2 flist- opT SDIV flist = popStack 2 flist- opT MOD flist = pairCompute mod flist- opT SMOD flist = popStack 2 flist- -- TODO(zchn): is this right?- opT ADDMOD flist = pairCompute (+) flist- opT MULMOD flist = pairCompute (*) flist- opT EXP flist = popStack 2 flist- opT SIGNEXTEND flist = popStack 2 flist- opT NEG flist = opT SUB $ pushStack 0 flist- opT BVO.LT flist = pairCompute (\a b -> b2w256 $ a < b) flist- opT BVO.GT flist = pairCompute (\a b -> b2w256 $ a > b) flist- -- TODO(zchn): is this right?- opT SLT flist = pairCompute (\a b -> b2w256 $ a < b) flist- opT SGT flist = pairCompute (\a b -> b2w256 $ a > b) flist- opT BVO.EQ flist = pairCompute (\a b -> b2w256 $ a == b) flist- opT ISZERO flist = opT BVO.EQ $ pushStack 0 flist- opT NOT flist = opT BVO.EQ $ pushStack 0 flist- opT AND flist = pairCompute w256And flist- opT OR flist = pairCompute w256Or flist- opT XOR flist = pairCompute w256Xor flist- opT BYTE flist = pushTop $ popStack 2 flist- opT SHA3 flist = pushTop $ popStack 2 flist- opT ADDRESS f = pushTop f- opT BALANCE f = pushTop f- opT ORIGIN f = pushTop f- opT CALLER f = pushTop f- opT CALLVALUE f = pushTop f- opT CALLDATALOAD f = pushTop $ popStack 1 f- opT CALLDATASIZE f = pushTop f- opT CALLDATACOPY f = popStack 3 f- opT CODESIZE f = pushTop f- opT CODECOPY f = popStack 3 f- opT GASPRICE f = pushTop f- opT EXTCODESIZE f = pushTop f- opT EXTCODECOPY f = pushTop $ pushTop $ pushTop $ pushTop f- opT BLOCKHASH f = pushTop f- opT COINBASE f = pushTop f- opT TIMESTAMP f = pushTop f- opT NUMBER f = pushTop f- opT DIFFICULTY f = pushTop f- opT GASLIMIT f = pushTop f- opT POP f = popStack 1 f- opT MLOAD f = pushTop $ popStack 1 f- opT MSTORE f = popStack 2 f- opT MSTORE8 f = popStack 2 f- opT SLOAD f = pushTop $ popStack 1 f- opT SSTORE f = popStack 2 f- opT JUMP f = popStack 1 f- opT JUMPI f = popStack 2 f- opT PC f = pushTop f- opT MSIZE f = pushTop f- opT GAS f = pushTop f- opT JUMPDEST flist = flist- opT (PUSH wl) flist = pushStack (varBytesToWord256 wl) flist- opT DUP1 flist = pushStack' (peekStack 1 flist) flist- opT DUP2 flist = pushStack' (peekStack 2 flist) flist- opT DUP3 flist = pushStack' (peekStack 3 flist) flist- opT DUP4 flist = pushStack' (peekStack 4 flist) flist- opT DUP5 flist = pushStack' (peekStack 5 flist) flist- opT DUP6 flist = pushStack' (peekStack 6 flist) flist- opT DUP7 flist = pushStack' (peekStack 7 flist) flist- opT DUP8 flist = pushStack' (peekStack 8 flist) flist- opT DUP9 flist = pushStack' (peekStack 9 flist) flist- opT DUP10 flist = pushStack' (peekStack 10 flist) flist- opT DUP11 flist = pushStack' (peekStack 11 flist) flist- opT DUP12 flist = pushStack' (peekStack 12 flist) flist- opT DUP13 flist = pushStack' (peekStack 13 flist) flist- opT DUP14 flist = pushStack' (peekStack 14 flist) flist- opT DUP15 flist = pushStack' (peekStack 15 flist) flist- opT DUP16 flist = pushStack' (peekStack 16 flist) flist- opT SWAP1 flist = swapStack 1 flist- opT SWAP2 flist = swapStack 2 flist- opT SWAP3 flist = swapStack 3 flist- opT SWAP4 flist = swapStack 4 flist- opT SWAP5 flist = swapStack 5 flist- opT SWAP6 flist = swapStack 6 flist- opT SWAP7 flist = swapStack 7 flist- opT SWAP8 flist = swapStack 8 flist- opT SWAP9 flist = swapStack 9 flist- opT SWAP10 flist = swapStack 10 flist- opT SWAP11 flist = swapStack 11 flist- opT SWAP12 flist = swapStack 12 flist- opT SWAP13 flist = swapStack 13 flist- opT SWAP14 flist = swapStack 14 flist- opT SWAP15 flist = swapStack 15 flist- opT SWAP16 flist = swapStack 16 flist- opT LOG0 flist = popStack 2 flist- opT LOG1 flist = popStack 3 flist- opT LOG2 flist = popStack 4 flist- opT LOG3 flist = popStack 5 flist- opT LOG4 flist = popStack 6 flist- opT CREATE flist = flist- opT CALL flist = pushTop $ popStack 7 flist- opT CALLCODE flist = pushTop $ popStack 7 flist- opT RETURN flist = popStack 2 flist- opT DELEGATECALL flist = pushTop $ popStack 7 flist- opT SUICIDE flist = popStack 1 flist- -- opT LABEL String flist = flist- -- opT PUSHLABEL String flist = flist- -- opT PUSHDIFF String String flist = flist- -- opT DATA ByteString flist = flist- -- opT MalformedOpcode Word8 flist = flist- opT op@LABEL {} _ =- panic $ "Unexpected(stackTopTransfer): " <> toS (show op)- opT op@PUSHLABEL {} _ =- panic $ "Unexpected(stackTopTransfer): " <> toS (show op)- opT op@PUSHDIFF {} _ =- panic $ "Unexpected(stackTopTransfer): " <> toS (show op)- opT op@DATA {} _ = panic $ "Unexpected(stackTopTransfer): " <> toS (show op)- opT op@MalformedOpcode {} _ =- panic $ "Unexpected(stackTopTransfer): " <> toS (show op)- -- TODO(zchn): Implement interp- opT _ flist = DL.map (const Top) flist--opGUnit :: HplOp e x -> Graph HplOp e x-opGUnit co@CoOp {} = gUnitCO $ BlockCO co BNil-opGUnit oo@OoOp {} = gUnitOO $ BMiddle oo-opGUnit oo@HpCodeCopy {} = gUnitOO $ BMiddle oo-opGUnit oc@OcOp {} = gUnitOC $ BlockOC BNil oc---- catPElems :: [Pointed e x t] -> [t]--- catPElems = mapMaybe maybePElem--- where--- maybePElem (PElem v) = Just v--- maybePElem _ = Nothing-cfgAugWithTopNRewrite :: FwdRewrite WordLabelMapFuelM HplOp StackNFact-cfgAugWithTopNRewrite = mkFRewrite3 coR ooR ocR- where- 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 op@(OoOp (_, CODECOPY)) f =- case peekStack 2 f of- Top -> return $ Just $ opGUnit op- PElem vals ->- return $- 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 op@(OcOp (loc, ope) ll) f =- case ope of- JUMP -> handleJmp- JUMPI -> handleJmp- _ -> return $ Just $ opGUnit op- where- handleJmp :: WordLabelMapFuelM (Maybe (Graph HplOp O C))- handleJmp =- case DL.head f of- Top -> return $ Just $ opGUnit op -- TODO(zchn): Should return all targets- PElem st -> do- newll <- liftFuel $ labelsFor $ toList st- return $- Just $- opGUnit $ OcOp (loc, ope) $ toList $ fromList (ll <> newll)--_depthBound :: Int-_depthBound = 16--cfgAugWithTopNPass :: FwdPass WordLabelMapFuelM HplOp StackNFact-cfgAugWithTopNPass =- FwdPass- { fp_lattice = stackNLattice _depthBound- , fp_transfer = stackNTransfer- , fp_rewrite = cfgAugWithTopNRewrite- }--doCfgAugWithTopNPass- :: HasEvmBytecode a- => a -> WordLabelMapM HplContract-doCfgAugWithTopNPass a = do- let disasmd = disasm a- contract <- evmOps2HplContract disasmd- let entry_ = entryOf $ ctorOf contract- body = bodyOf $ ctorOf contract- case entry_ of- Nothing -> return contract- Just entry -> do- newBody <-- runWithFuel- 10000000000- (fst <$>- analyzeAndRewriteFwdBody- cfgAugWithTopNPass- entry- body- (mapSingleton entry $ fact_bot $ fp_lattice cfgAugWithTopNPass))- let blocks = DL.map snd $ bodyList newBody- ooOps =- DL.concatMap ((\(_, b, _) -> blockToList b) . blockSplit) blocks- newHexstrings =- mapMaybe- (\op ->- case op of- HpCodeCopy offset ->- let newhs =- EvmBytecode $- DB.drop (fromInteger (getBigWordInteger offset)) $- unEvmBytecode (evmBytecodeOf a)- in if DB.null $ unEvmBytecode newhs- then Nothing- else Just newhs- _ -> Nothing)- ooOps- case newHexstrings of- [] -> return contract {ctorOf = HplCode (Just entry) newBody}- [newhs] -> do- HplCode (Just disEntry) disBody <- evmOps2HplCode $ disasm newhs- newDisBody <-- runWithFuel- 10000000000- (fst <$>- analyzeAndRewriteFwdBody- cfgAugWithTopNPass- disEntry- disBody- (mapSingleton disEntry $- fact_bot $ fp_lattice cfgAugWithTopNPass))- return- HplContract- { ctorOf = HplCode (Just entry) newBody- , dispatcherOf = HplCode (Just disEntry) newDisBody- }- _ ->- panic $- "doCfgAugWithTopNPass: unexpected newHexstrings length: " <>- toS (show (DL.length newHexstrings))
− src/Ethereum/Analyzer/CfgAugmentPass.hs
@@ -1,145 +0,0 @@-{-# LANGUAGE OverloadedStrings, FlexibleContexts,- FlexibleInstances, GADTs, Rank2Types, TypeFamilies,- UndecidableInstances #-}--module Ethereum.Analyzer.CfgAugmentPass- ( doCfgAugmentPass- ) where--import Protolude hiding (show)--import Blockchain.ExtWord-import Blockchain.VM.Opcodes-import Compiler.Hoopl---- import Data.Bits-import Data.List as DL-import Data.Set as DS hiding (toList)-import Ethereum.Analyzer-import Ethereum.Analyzer.Common-import GHC.Show--type StackTopFact = WithTop (Set Word256)--joinJumpTargets- :: Label- -> OldFact (Set Word256)- -> NewFact (Set Word256)- -> (ChangeFlag, Set Word256)-joinJumpTargets _ (OldFact oldF) (NewFact newF) =- if newF `isSubsetOf` oldF- then (NoChange, oldF)- else (SomeChange, oldF `DS.union` newF)--joinStackTopFact- :: Label- -> OldFact StackTopFact- -> NewFact StackTopFact- -> (ChangeFlag, StackTopFact)-joinStackTopFact = liftJoinTop joinJumpTargets--stackTopLattice :: DataflowLattice StackTopFact-stackTopLattice =- DataflowLattice- { fact_name = "stackTopLattice"- , fact_bot = PElem DS.empty- , fact_join = joinStackTopFact- }--stackTopTransfer :: FwdTransfer HplOp StackTopFact-stackTopTransfer = mkFTransfer3 coT ooT ocT- where- coT :: HplOp C O -> StackTopFact -> StackTopFact- coT _ f = f- ooT :: HplOp O O -> StackTopFact -> StackTopFact- ooT (OoOp (_, op)) f = opT op f- ooT (HpCodeCopy _) f = f- ocT :: HplOp O C -> StackTopFact -> FactBase StackTopFact- ocT hplop@(OcOp (_, op) _) f = distributeFact hplop (opT op f)- opT :: Operation -> StackTopFact -> StackTopFact- opT DUP1 f = f- opT ISZERO (PElem st) =- PElem $- DS.map- (\wd ->- if wd == 0- then 1- else 0)- st- opT JUMPDEST f = f- opT NEG (PElem st) = PElem $ DS.map (\wd -> -wd) st- opT NOT (PElem st) =- 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)- opT op@PUSHLABEL {} _ =- panic $ "Unexpected(stackTopTransfer): " <> toS (show op)- opT op@PUSHDIFF {} _ =- panic $ "Unexpected(stackTopTransfer): " <> toS (show op)- opT op@DATA {} _ = panic $ "Unexpected(stackTopTransfer): " <> toS (show op)- opT op@MalformedOpcode {} _ =- panic $ "Unexpected(stackTopTransfer): " <> toS (show op)- opT _ _ = Top--opGUnit :: HplOp e x -> Graph HplOp e x-opGUnit co@CoOp {} = gUnitCO $ BlockCO co BNil-opGUnit oo@OoOp {} = gUnitOO $ BMiddle oo-opGUnit oo@HpCodeCopy {} = gUnitOO $ BMiddle oo-opGUnit oc@OcOp {} = gUnitOC $ BlockOC BNil oc--cfgAugmentRewrite :: FwdRewrite WordLabelMapFuelM HplOp StackTopFact-cfgAugmentRewrite = mkFRewrite3 coR ooR ocR- where- 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 op _ = return $ Just $ opGUnit op- ocR :: HplOp O C- -> StackTopFact- -> WordLabelMapFuelM (Maybe (Graph HplOp O C))- ocR op@(OcOp (loc, ope) ll) f =- case ope of- JUMP -> handleJmp- JUMPI -> handleJmp- _ -> return $ Just $ opGUnit op- where- handleJmp :: WordLabelMapFuelM (Maybe (Graph HplOp O C))- handleJmp =- case f of- Top -> return $ Just $ opGUnit op -- TODO(zchn): Should return all targets- PElem st -> do- newll <- liftFuel $ labelsFor $ toList st- return $- Just $- opGUnit $ OcOp (loc, ope) $ toList $ fromList (ll <> newll)--cfgAugmentPass :: FwdPass WordLabelMapFuelM HplOp StackTopFact-cfgAugmentPass =- FwdPass- { fp_lattice = stackTopLattice- , fp_transfer = stackTopTransfer- , fp_rewrite = cfgAugmentRewrite- }--doCfgAugmentPass :: HplContract -> WordLabelMapM HplContract-doCfgAugmentPass contract =- let entry_ = entryOf $ ctorOf contract- body = bodyOf $ ctorOf contract- in case entry_ of- Nothing -> return contract- Just entry -> do- newBody <-- runWithFuel- 1000000- (fst <$>- analyzeAndRewriteFwdBody- cfgAugmentPass- entry- body- (mapSingleton entry Top))- return contract {ctorOf = HplCode (Just entry) newBody}
src/Ethereum/Analyzer/Common.hs view
@@ -22,8 +22,8 @@ s2t4Either :: StringConv s Text => Either s a -> Either Text a-s2t4Either (Left s) = (Left $ toS s)-s2t4Either (Right r) = (Right r)+s2t4Either (Left s) = Left $ toS s+s2t4Either (Right r) = Right r unexpectedPanic :: Show a
src/Ethereum/Analyzer/Debug.hs view
@@ -6,8 +6,6 @@ import Protolude -import Compiler.Hoopl-import Ethereum.Analyzer.Common import Ethereum.Analyzer.Solidity import qualified Text.PrettyPrint.GenericPretty as GP
− src/Ethereum/Analyzer/Disasm.hs
@@ -1,53 +0,0 @@-module Ethereum.Analyzer.Disasm- ( EvmBytecode(..)- , EvmHexString(..)- , HasEvmBytecode(..)- , disasm- ) where--import Protolude hiding (show)--import Blockchain.Data.Code-import Blockchain.ExtWord-import Blockchain.Util-import Blockchain.VM.Code-import Blockchain.VM.Opcodes-import Data.HexString--class HasEvmBytecode a where- evmBytecodeOf :: a -> EvmBytecode--newtype EvmBytecode = EvmBytecode- { unEvmBytecode :: ByteString- } deriving (Show, Eq)--newtype EvmHexString = EvmHexString- { unEvmHexString :: Text- } deriving (Show, Eq)--instance HasEvmBytecode EvmBytecode where- evmBytecodeOf = identity--instance HasEvmBytecode EvmHexString where- evmBytecodeOf =- EvmBytecode . toBytes . hexString . encodeUtf8 . unEvmHexString--instance HasEvmBytecode Code where- evmBytecodeOf (Code bs) = EvmBytecode bs- evmBytecodeOf _ = EvmBytecode ""--disasm- :: HasEvmBytecode a- => a -> [(Word256, Operation)]-disasm a =- let bs = (unEvmBytecode . evmBytecodeOf) a- hardlimit = 10000- in disasmBSAt bs 0 hardlimit--disasmBSAt :: ByteString -> Word256 -> Int -> [(Word256, Operation)]-disasmBSAt "" _ _ = []-disasmBSAt _ _ 0 = []-disasmBSAt bs base limit =- (base, op) : disasmBSAt (safeDrop next bs) (base + next) (limit - 1)- where- (op, next) = getOperationAt' bs 0
+ src/Ethereum/Analyzer/EVM.hs view
@@ -0,0 +1,13 @@+module Ethereum.Analyzer.EVM+ ( module Ethereum.Analyzer.EVM.CfgAugmentPass+ , module Ethereum.Analyzer.EVM.CfgAugWithTopNPass+ , module Ethereum.Analyzer.EVM.Disasm+ , module Ethereum.Analyzer.EVM.IR+ , module Ethereum.Analyzer.EVM.Util+ ) where++import Ethereum.Analyzer.EVM.CfgAugWithTopNPass+import Ethereum.Analyzer.EVM.CfgAugmentPass+import Ethereum.Analyzer.EVM.Disasm+import Ethereum.Analyzer.EVM.IR+import Ethereum.Analyzer.EVM.Util
+ src/Ethereum/Analyzer/EVM/CfgAugWithTopNPass.hs view
@@ -0,0 +1,396 @@+{-# LANGUAGE OverloadedStrings, FlexibleContexts,+ NoImplicitPrelude, FlexibleInstances, GADTs, Rank2Types,+ TypeFamilies, UndecidableInstances #-}++module Ethereum.Analyzer.EVM.CfgAugWithTopNPass+ ( doCfgAugWithTopNPass+ ) where++import Protolude hiding (show)++import Blockchain.ExtWord+import Blockchain.VM.Opcodes as BVO+import Compiler.Hoopl+import Data.Bits as Db+import Data.ByteString as DB+import Data.List as DL+import Data.List.Extra as DLE+import Data.Set as DS hiding (toList)+import Ethereum.Analyzer.Common+import Ethereum.Analyzer.EVM.Disasm+import Ethereum.Analyzer.EVM.IR+import GHC.Show+import Legacy.Haskoin.V0102.Network.Haskoin.Crypto.BigWord++type StackElemFact = WithTop (Set Word256)++joinStackElemBase+ :: Label+ -> OldFact (Set Word256)+ -> NewFact (Set Word256)+ -> (ChangeFlag, Set Word256)+joinStackElemBase _ (OldFact oldF) (NewFact newF) =+ if newF `isSubsetOf` oldF+ then (NoChange, oldF)+ else (SomeChange, oldF `DS.union` newF)++joinStackElemFact+ :: Label+ -> OldFact StackElemFact+ -> NewFact StackElemFact+ -> (ChangeFlag, StackElemFact)+joinStackElemFact = liftJoinTop joinStackElemBase++type StackNFact = [StackElemFact]++joinStackNFact :: Label+ -> OldFact StackNFact+ -> NewFact StackNFact+ -> (ChangeFlag, StackNFact)+joinStackNFact l (OldFact oldF) (NewFact newF) =+ let zipped =+ DL.zipWith+ (\a b -> joinStackElemFact l (OldFact a) (NewFact b))+ oldF+ newF+ (changedL, joinedF) = DL.unzip zipped+ in ( changeIf $+ DL.any+ (\c ->+ case c of+ SomeChange -> True+ NoChange -> False)+ changedL+ , joinedF)++stackNLattice :: Int -> DataflowLattice StackNFact+stackNLattice depth =+ DataflowLattice+ { fact_name = "stackNLattice"+ , fact_bot = DL.replicate depth (PElem DS.empty)+ , fact_join = joinStackNFact+ }++_sizeBound :: Int+_sizeBound = 10++mkTopList+ :: forall b b1 a.+ [b] -> [Pointed C b1 a]+mkTopList = DL.map (const Top)++pairCompute :: (Word256 -> Word256 -> Word256) -> StackNFact -> StackNFact+pairCompute fun flist =+ case flist of+ [] -> mkTopList flist+ [_] -> mkTopList flist+ Top:_:tl -> (Top : tl) <> [Top]+ _:Top:tl -> (Top : tl) <> [Top]+ PElem st1:PElem st2:tl ->+ let l1 = toList st1+ in ((PElem $ DS.unions $ DL.map (\e1 -> DS.map (fun e1) st2) l1) : tl) <>+ [Top]++popStack :: Int -> StackNFact -> StackNFact+popStack 0 f = f+popStack n (_:t) = popStack (n - 1) (t <> [Top])+popStack _ [] = []++pushStack' :: StackElemFact -> StackNFact -> StackNFact+pushStack' e flist = e : DLE.dropEnd 1 flist++pushStack :: Word256 -> StackNFact -> StackNFact+pushStack wd = pushStack' (PElem $ DS.singleton wd)++pushTop :: StackNFact -> StackNFact+pushTop flist = Top : DLE.dropEnd 1 flist++b2w256 :: Bool -> Word256+b2w256 True = 1+b2w256 False = 0++-- w256Not :: Word256 -> Word256+-- w256Not wd = bytesToWord256 $ DL.map complement $ word256ToBytes wd+w256And :: Word256 -> Word256 -> Word256+w256And wd1 wd2 =+ bytesToWord256 $ DL.zipWith (.&.) (word256ToBytes wd1) (word256ToBytes wd2)++w256Or :: Word256 -> Word256 -> Word256+w256Or wd1 wd2 =+ bytesToWord256 $ DL.zipWith (.|.) (word256ToBytes wd1) (word256ToBytes wd2)++w256Xor :: Word256 -> Word256 -> Word256+w256Xor wd1 wd2 =+ bytesToWord256 $ DL.zipWith Db.xor (word256ToBytes wd1) (word256ToBytes wd2)++peekStack :: Int -> StackNFact -> StackElemFact+peekStack _ [] = Top+peekStack 1 (h:_) = h+peekStack n (_:t) = peekStack (n - 1) t++swapStack :: Int -> StackNFact -> StackNFact+swapStack n stk =+ if n + 1 > DL.length stk+ then pushTop $ popStack 1 stk+ else let (h1:t1, h2:t2) = DL.splitAt n stk+ in (h2 : t1) <> (h1 : t2)++stackNTransfer :: FwdTransfer HplOp StackNFact+stackNTransfer = mkFTransfer3 coT ooT ocT+ where+ coT :: HplOp C O -> StackNFact -> StackNFact+ coT _ =+ DL.map+ (\f ->+ case f of+ Top -> Top+ PElem st ->+ if DS.size st > _sizeBound+ then Top+ else PElem st)+ ooT :: HplOp O O -> StackNFact -> StackNFact+ ooT (OoOp (_, op)) f = opT op f+ ooT (HpCodeCopy _) f = f+ ocT :: HplOp O C -> StackNFact -> FactBase StackNFact+ -- TODO(zchn): Implement JUMPI narrowing+ ocT hplop@(OcOp (_, op) _) f = distributeFact hplop (opT op f)+ opT :: Operation -> StackNFact -> StackNFact+ opT STOP flist = flist+ opT ADD flist = pairCompute (+) flist+ opT MUL flist = pairCompute (*) flist+ opT SUB flist = pairCompute (-) flist+ -- TODO(zchn): handle DIVs and MODs+ opT DIV flist = popStack 2 flist+ opT SDIV flist = popStack 2 flist+ opT MOD flist = pairCompute mod flist+ opT SMOD flist = popStack 2 flist+ -- TODO(zchn): is this right?+ opT ADDMOD flist = pairCompute (+) flist+ opT MULMOD flist = pairCompute (*) flist+ opT EXP flist = popStack 2 flist+ opT SIGNEXTEND flist = popStack 2 flist+ opT NEG flist = opT SUB $ pushStack 0 flist+ opT BVO.LT flist = pairCompute (\a b -> b2w256 $ a < b) flist+ opT BVO.GT flist = pairCompute (\a b -> b2w256 $ a > b) flist+ -- TODO(zchn): is this right?+ opT SLT flist = pairCompute (\a b -> b2w256 $ a < b) flist+ opT SGT flist = pairCompute (\a b -> b2w256 $ a > b) flist+ opT BVO.EQ flist = pairCompute (\a b -> b2w256 $ a == b) flist+ opT ISZERO flist = opT BVO.EQ $ pushStack 0 flist+ opT NOT flist = opT BVO.EQ $ pushStack 0 flist+ opT AND flist = pairCompute w256And flist+ opT OR flist = pairCompute w256Or flist+ opT XOR flist = pairCompute w256Xor flist+ opT BYTE flist = pushTop $ popStack 2 flist+ opT SHA3 flist = pushTop $ popStack 2 flist+ opT ADDRESS f = pushTop f+ opT BALANCE f = pushTop f+ opT ORIGIN f = pushTop f+ opT CALLER f = pushTop f+ opT CALLVALUE f = pushTop f+ opT CALLDATALOAD f = pushTop $ popStack 1 f+ opT CALLDATASIZE f = pushTop f+ opT CALLDATACOPY f = popStack 3 f+ opT CODESIZE f = pushTop f+ opT CODECOPY f = popStack 3 f+ opT GASPRICE f = pushTop f+ opT EXTCODESIZE f = pushTop f+ opT EXTCODECOPY f = pushTop $ pushTop $ pushTop $ pushTop f+ opT BLOCKHASH f = pushTop f+ opT COINBASE f = pushTop f+ opT TIMESTAMP f = pushTop f+ opT NUMBER f = pushTop f+ opT DIFFICULTY f = pushTop f+ opT GASLIMIT f = pushTop f+ opT POP f = popStack 1 f+ opT MLOAD f = pushTop $ popStack 1 f+ opT MSTORE f = popStack 2 f+ opT MSTORE8 f = popStack 2 f+ opT SLOAD f = pushTop $ popStack 1 f+ opT SSTORE f = popStack 2 f+ opT JUMP f = popStack 1 f+ opT JUMPI f = popStack 2 f+ opT PC f = pushTop f+ opT MSIZE f = pushTop f+ opT GAS f = pushTop f+ opT JUMPDEST flist = flist+ opT (PUSH wl) flist = pushStack (varBytesToWord256 wl) flist+ opT DUP1 flist = pushStack' (peekStack 1 flist) flist+ opT DUP2 flist = pushStack' (peekStack 2 flist) flist+ opT DUP3 flist = pushStack' (peekStack 3 flist) flist+ opT DUP4 flist = pushStack' (peekStack 4 flist) flist+ opT DUP5 flist = pushStack' (peekStack 5 flist) flist+ opT DUP6 flist = pushStack' (peekStack 6 flist) flist+ opT DUP7 flist = pushStack' (peekStack 7 flist) flist+ opT DUP8 flist = pushStack' (peekStack 8 flist) flist+ opT DUP9 flist = pushStack' (peekStack 9 flist) flist+ opT DUP10 flist = pushStack' (peekStack 10 flist) flist+ opT DUP11 flist = pushStack' (peekStack 11 flist) flist+ opT DUP12 flist = pushStack' (peekStack 12 flist) flist+ opT DUP13 flist = pushStack' (peekStack 13 flist) flist+ opT DUP14 flist = pushStack' (peekStack 14 flist) flist+ opT DUP15 flist = pushStack' (peekStack 15 flist) flist+ opT DUP16 flist = pushStack' (peekStack 16 flist) flist+ opT SWAP1 flist = swapStack 1 flist+ opT SWAP2 flist = swapStack 2 flist+ opT SWAP3 flist = swapStack 3 flist+ opT SWAP4 flist = swapStack 4 flist+ opT SWAP5 flist = swapStack 5 flist+ opT SWAP6 flist = swapStack 6 flist+ opT SWAP7 flist = swapStack 7 flist+ opT SWAP8 flist = swapStack 8 flist+ opT SWAP9 flist = swapStack 9 flist+ opT SWAP10 flist = swapStack 10 flist+ opT SWAP11 flist = swapStack 11 flist+ opT SWAP12 flist = swapStack 12 flist+ opT SWAP13 flist = swapStack 13 flist+ opT SWAP14 flist = swapStack 14 flist+ opT SWAP15 flist = swapStack 15 flist+ opT SWAP16 flist = swapStack 16 flist+ opT LOG0 flist = popStack 2 flist+ opT LOG1 flist = popStack 3 flist+ opT LOG2 flist = popStack 4 flist+ opT LOG3 flist = popStack 5 flist+ opT LOG4 flist = popStack 6 flist+ opT CREATE flist = flist+ opT CALL flist = pushTop $ popStack 7 flist+ opT CALLCODE flist = pushTop $ popStack 7 flist+ opT RETURN flist = popStack 2 flist+ opT DELEGATECALL flist = pushTop $ popStack 7 flist+ opT SUICIDE flist = popStack 1 flist+ -- opT LABEL String flist = flist+ -- opT PUSHLABEL String flist = flist+ -- opT PUSHDIFF String String flist = flist+ -- opT DATA ByteString flist = flist+ -- opT MalformedOpcode Word8 flist = flist+ opT op@LABEL {} _ =+ panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ opT op@PUSHLABEL {} _ =+ panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ opT op@PUSHDIFF {} _ =+ panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ opT op@DATA {} _ = panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ opT op@MalformedOpcode {} _ =+ panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ -- TODO(zchn): Implement interp+ opT _ flist = DL.map (const Top) flist++opGUnit :: HplOp e x -> Graph HplOp e x+opGUnit co@CoOp {} = gUnitCO $ BlockCO co BNil+opGUnit oo@OoOp {} = gUnitOO $ BMiddle oo+opGUnit oo@HpCodeCopy {} = gUnitOO $ BMiddle oo+opGUnit oc@OcOp {} = gUnitOC $ BlockOC BNil oc++-- catPElems :: [Pointed e x t] -> [t]+-- catPElems = mapMaybe maybePElem+-- where+-- maybePElem (PElem v) = Just v+-- maybePElem _ = Nothing+cfgAugWithTopNRewrite :: FwdRewrite WordLabelMapFuelM HplOp StackNFact+cfgAugWithTopNRewrite = mkFRewrite3 coR ooR ocR+ where+ 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 op@(OoOp (_, CODECOPY)) f =+ case peekStack 2 f of+ Top -> return $ Just $ opGUnit op+ PElem vals ->+ return $+ 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 op@(OcOp (loc, ope) ll) f =+ case ope of+ JUMP -> handleJmp+ JUMPI -> handleJmp+ _ -> return $ Just $ opGUnit op+ where+ handleJmp :: WordLabelMapFuelM (Maybe (Graph HplOp O C))+ handleJmp =+ case DL.head f of+ Top -> return $ Just $ opGUnit op -- TODO(zchn): Should return all targets+ PElem st -> do+ newll <- liftFuel $ labelsFor $ toList st+ return $+ Just $+ opGUnit $ OcOp (loc, ope) $ toList $ fromList (ll <> newll)++_depthBound :: Int+_depthBound = 16++cfgAugWithTopNPass :: FwdPass WordLabelMapFuelM HplOp StackNFact+cfgAugWithTopNPass =+ FwdPass+ { fp_lattice = stackNLattice _depthBound+ , fp_transfer = stackNTransfer+ , fp_rewrite = cfgAugWithTopNRewrite+ }++doCfgAugWithTopNPass+ :: HasEvmBytecode a+ => a -> WordLabelMapM HplContract+doCfgAugWithTopNPass a = do+ let disasmd = disasm a+ contract <- evmOps2HplContract disasmd+ let entry_ = entryOf $ ctorOf contract+ body = bodyOf $ ctorOf contract+ case entry_ of+ Nothing -> return contract+ Just entry -> do+ newBody <-+ runWithFuel+ 10000000000+ (fst <$>+ analyzeAndRewriteFwdBody+ cfgAugWithTopNPass+ entry+ body+ (mapSingleton entry $ fact_bot $ fp_lattice cfgAugWithTopNPass))+ let blocks = DL.map snd $ bodyList newBody+ ooOps =+ DL.concatMap ((\(_, b, _) -> blockToList b) . blockSplit) blocks+ newHexstrings =+ mapMaybe+ (\op ->+ case op of+ HpCodeCopy offset ->+ let newhs =+ EvmBytecode $+ DB.drop (fromInteger (getBigWordInteger offset)) $+ unEvmBytecode (evmBytecodeOf a)+ in if DB.null $ unEvmBytecode newhs+ then Nothing+ else Just newhs+ _ -> Nothing)+ ooOps+ case newHexstrings of+ [] -> return contract {ctorOf = HplCode (Just entry) newBody}+ [newhs] -> do+ HplCode (Just disEntry) disBody <- evmOps2HplCode $ disasm newhs+ newDisBody <-+ runWithFuel+ 10000000000+ (fst <$>+ analyzeAndRewriteFwdBody+ cfgAugWithTopNPass+ disEntry+ disBody+ (mapSingleton disEntry $+ fact_bot $ fp_lattice cfgAugWithTopNPass))+ return+ HplContract+ { ctorOf = HplCode (Just entry) newBody+ , dispatcherOf = HplCode (Just disEntry) newDisBody+ }+ _ ->+ panic $+ "doCfgAugWithTopNPass: unexpected newHexstrings length: " <>+ toS (show (DL.length newHexstrings))
+ src/Ethereum/Analyzer/EVM/CfgAugmentPass.hs view
@@ -0,0 +1,145 @@+{-# LANGUAGE OverloadedStrings, FlexibleContexts,+ FlexibleInstances, GADTs, Rank2Types, TypeFamilies,+ UndecidableInstances #-}++module Ethereum.Analyzer.EVM.CfgAugmentPass+ ( doCfgAugmentPass+ ) where++import Protolude hiding (show)++import Blockchain.ExtWord+import Blockchain.VM.Opcodes+import Compiler.Hoopl++-- import Data.Bits+import Data.List as DL+import Data.Set as DS hiding (toList)+import Ethereum.Analyzer.Common+import Ethereum.Analyzer.EVM.IR+import GHC.Show++type StackTopFact = WithTop (Set Word256)++joinJumpTargets+ :: Label+ -> OldFact (Set Word256)+ -> NewFact (Set Word256)+ -> (ChangeFlag, Set Word256)+joinJumpTargets _ (OldFact oldF) (NewFact newF) =+ if newF `isSubsetOf` oldF+ then (NoChange, oldF)+ else (SomeChange, oldF `DS.union` newF)++joinStackTopFact+ :: Label+ -> OldFact StackTopFact+ -> NewFact StackTopFact+ -> (ChangeFlag, StackTopFact)+joinStackTopFact = liftJoinTop joinJumpTargets++stackTopLattice :: DataflowLattice StackTopFact+stackTopLattice =+ DataflowLattice+ { fact_name = "stackTopLattice"+ , fact_bot = PElem DS.empty+ , fact_join = joinStackTopFact+ }++stackTopTransfer :: FwdTransfer HplOp StackTopFact+stackTopTransfer = mkFTransfer3 coT ooT ocT+ where+ coT :: HplOp C O -> StackTopFact -> StackTopFact+ coT _ f = f+ ooT :: HplOp O O -> StackTopFact -> StackTopFact+ ooT (OoOp (_, op)) f = opT op f+ ooT (HpCodeCopy _) f = f+ ocT :: HplOp O C -> StackTopFact -> FactBase StackTopFact+ ocT hplop@(OcOp (_, op) _) f = distributeFact hplop (opT op f)+ opT :: Operation -> StackTopFact -> StackTopFact+ opT DUP1 f = f+ opT ISZERO (PElem st) =+ PElem $+ DS.map+ (\wd ->+ if wd == 0+ then 1+ else 0)+ st+ opT JUMPDEST f = f+ opT NEG (PElem st) = PElem $ DS.map (\wd -> -wd) st+ opT NOT (PElem st) =+ 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)+ opT op@PUSHLABEL {} _ =+ panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ opT op@PUSHDIFF {} _ =+ panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ opT op@DATA {} _ = panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ opT op@MalformedOpcode {} _ =+ panic $ "Unexpected(stackTopTransfer): " <> toS (show op)+ opT _ _ = Top++opGUnit :: HplOp e x -> Graph HplOp e x+opGUnit co@CoOp {} = gUnitCO $ BlockCO co BNil+opGUnit oo@OoOp {} = gUnitOO $ BMiddle oo+opGUnit oo@HpCodeCopy {} = gUnitOO $ BMiddle oo+opGUnit oc@OcOp {} = gUnitOC $ BlockOC BNil oc++cfgAugmentRewrite :: FwdRewrite WordLabelMapFuelM HplOp StackTopFact+cfgAugmentRewrite = mkFRewrite3 coR ooR ocR+ where+ 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 op _ = return $ Just $ opGUnit op+ ocR :: HplOp O C+ -> StackTopFact+ -> WordLabelMapFuelM (Maybe (Graph HplOp O C))+ ocR op@(OcOp (loc, ope) ll) f =+ case ope of+ JUMP -> handleJmp+ JUMPI -> handleJmp+ _ -> return $ Just $ opGUnit op+ where+ handleJmp :: WordLabelMapFuelM (Maybe (Graph HplOp O C))+ handleJmp =+ case f of+ Top -> return $ Just $ opGUnit op -- TODO(zchn): Should return all targets+ PElem st -> do+ newll <- liftFuel $ labelsFor $ toList st+ return $+ Just $+ opGUnit $ OcOp (loc, ope) $ toList $ fromList (ll <> newll)++cfgAugmentPass :: FwdPass WordLabelMapFuelM HplOp StackTopFact+cfgAugmentPass =+ FwdPass+ { fp_lattice = stackTopLattice+ , fp_transfer = stackTopTransfer+ , fp_rewrite = cfgAugmentRewrite+ }++doCfgAugmentPass :: HplContract -> WordLabelMapM HplContract+doCfgAugmentPass contract =+ let entry_ = entryOf $ ctorOf contract+ body = bodyOf $ ctorOf contract+ in case entry_ of+ Nothing -> return contract+ Just entry -> do+ newBody <-+ runWithFuel+ 1000000+ (fst <$>+ analyzeAndRewriteFwdBody+ cfgAugmentPass+ entry+ body+ (mapSingleton entry Top))+ return contract {ctorOf = HplCode (Just entry) newBody}
+ src/Ethereum/Analyzer/EVM/Disasm.hs view
@@ -0,0 +1,53 @@+module Ethereum.Analyzer.EVM.Disasm+ ( EvmBytecode(..)+ , EvmHexString(..)+ , HasEvmBytecode(..)+ , disasm+ ) where++import Protolude hiding (show)++import Blockchain.Data.Code+import Blockchain.ExtWord+import Blockchain.Util+import Blockchain.VM.Code+import Blockchain.VM.Opcodes+import Data.HexString++class HasEvmBytecode a where+ evmBytecodeOf :: a -> EvmBytecode++newtype EvmBytecode = EvmBytecode+ { unEvmBytecode :: ByteString+ } deriving (Show, Eq)++newtype EvmHexString = EvmHexString+ { unEvmHexString :: Text+ } deriving (Show, Eq)++instance HasEvmBytecode EvmBytecode where+ evmBytecodeOf = identity++instance HasEvmBytecode EvmHexString where+ evmBytecodeOf =+ EvmBytecode . toBytes . hexString . encodeUtf8 . unEvmHexString++instance HasEvmBytecode Code where+ evmBytecodeOf (Code bs) = EvmBytecode bs+ evmBytecodeOf _ = EvmBytecode ""++disasm+ :: HasEvmBytecode a+ => a -> [(Word256, Operation)]+disasm a =+ let bs = (unEvmBytecode . evmBytecodeOf) a+ hardlimit = 10000+ in disasmBSAt bs 0 hardlimit++disasmBSAt :: ByteString -> Word256 -> Int -> [(Word256, Operation)]+disasmBSAt "" _ _ = []+disasmBSAt _ _ 0 = []+disasmBSAt bs base limit =+ (base, op) : disasmBSAt (safeDrop next bs) (base + next) (limit - 1)+ where+ (op, next) = getOperationAt' bs 0
+ src/Ethereum/Analyzer/EVM/IR.hs view
@@ -0,0 +1,234 @@+{-# LANGUAGE FlexibleContexts, OverloadedStrings,+ NoImplicitPrelude, FlexibleInstances, GADTs, Rank2Types,+ TypeFamilies, ScopedTypeVariables, UndecidableInstances #-}++module Ethereum.Analyzer.EVM.IR+ ( HplBody+ , HplCode(..)+ , HplContract(..)+ , HplOp(..)+ , WordLabelMapM+ , WordLabelMapFuelM+ , unWordLabelMapM+ , evmOps2HplCode+ , evmOps2HplContract+ , labelFor+ , labelsFor+ , showOp+ , showOps+ ) where++import Protolude hiding (show)++import Blockchain.ExtWord as BE+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 Legacy.Haskoin.V0102.Network.Haskoin.Crypto.BigWord++data HplOp e x where+ CoOp :: Label -> HplOp C O+ OoOp :: (Word256, Operation) -> HplOp O O+ OcOp :: (Word256, Operation) -> [Label] -> HplOp O C+ HpCodeCopy :: Word256 -> HplOp O O++showLoc :: Word256 -> String+showLoc = show . getBigWordInteger++showOp :: (Word256, Operation) -> String+showOp (lineNo, op) = showLoc lineNo <> ": " <> show op++showOps :: [(Word256, Operation)] -> [String]+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 (HpCodeCopy offset) = "HpCodeCopy " <> show offset++instance Show (Block HplOp C C) where+ show (a :: Block HplOp C C) =+ let (h, m, t) = blockSplit a+ in DL.unlines $ [show h] <> DL.map show (blockToList m) <> [show t]++instance Eq (HplOp C O) where+ (==) (CoOp a) (CoOp b) = a == b++instance Eq (HplOp O O) where+ (==) (OoOp a) (OoOp b) = a == b+ (==) (HpCodeCopy a) (HpCodeCopy b) = a == b+ (==) _ _ = False++instance Eq (HplOp O C) where+ (==) (OcOp a _) (OcOp b _) = a == b++instance NonLocal HplOp where+ entryLabel (CoOp l) = l+ successors (OcOp _ ll) = ll++type HplBody = Body HplOp++data HplCode = HplCode+ { entryOf :: Maybe Label+ , bodyOf :: HplBody+ } deriving (Show)++data HplContract = HplContract+ { ctorOf :: HplCode+ , dispatcherOf :: HplCode+ } deriving (Show)++emptyCode :: HplCode+emptyCode = HplCode Nothing emptyBody++evmOps2HplContract :: [(Word256, Operation)] -> WordLabelMapM HplContract+evmOps2HplContract l = do+ ctorBody <- evmOps2HplCode l+ return HplContract {ctorOf = ctorBody, dispatcherOf = emptyCode}++evmOps2HplCode :: [(Word256, Operation)] -> WordLabelMapM HplCode+evmOps2HplCode [] = return emptyCode+evmOps2HplCode l@((loc, _):_) = do+ entry <- labelFor loc+ body <- _evmOps2HplBody l+ return HplCode {entryOf = Just entry, bodyOf = body}++_evmOps2HplBody :: [(Word256, Operation)] -> WordLabelMapM HplBody+_evmOps2HplBody [] = return emptyBody+_evmOps2HplBody el@((loc, _):_) = do+ l <- labelFor loc+ doEvmOps2HplBody emptyBody (blockJoinHead (CoOp l) emptyBlock) el+ where+ doEvmOps2HplBody+ :: HplBody+ -> Block HplOp C O+ -> [(Word256, Operation)]+ -> WordLabelMapM HplBody+ doEvmOps2HplBody body _ [] = return body -- sliently discarding bad hds+ doEvmOps2HplBody body hd [h'] =+ if isTerminator (snd h')+ then return $ addBlock (blockJoinTail hd (OcOp h' [])) body+ else return body+ doEvmOps2HplBody body hd (h':(t'@((loc', op'):_)))+ | isTerminator (snd h') = do+ l' <- labelFor loc'+ doEvmOps2HplBody+ (addBlock+ (blockJoinTail hd (OcOp h' [l' | canPassThrough (snd h')]))+ body)+ (blockJoinHead (CoOp l') emptyBlock)+ t'+ | op' /= JUMPDEST = doEvmOps2HplBody body (blockSnoc hd (OoOp h')) t'+ | otherwise = do+ l' <- labelFor loc'+ doEvmOps2HplBody+ (addBlock+ (blockJoinTail hd (OcOp h' [l' | canPassThrough (snd h')]))+ body)+ (blockJoinHead (CoOp l') emptyBlock)+ t'++isTerminator :: Operation -> Bool+isTerminator STOP = True+isTerminator JUMP = True+isTerminator JUMPI = True+isTerminator CALL = True+isTerminator CALLCODE = True+isTerminator RETURN = True+isTerminator DELEGATECALL = True+isTerminator INVALID = True+isTerminator SUICIDE = True+isTerminator _ = False++canPassThrough :: Operation -> Bool+canPassThrough STOP = False+canPassThrough JUMP = False+canPassThrough RETURN = False+canPassThrough INVALID = False+canPassThrough SUICIDE = False+canPassThrough _ = True++--------------------------------------------------------------------------------+-- The WordLabelMapM monad+--------------------------------------------------------------------------------+type WordLabelMap = Bimap Word256 Label++newtype WordLabelMapM a =+ WordLabelMapM (WordLabelMap -> SimpleUniqueMonad (WordLabelMap, a))++instance CheckpointMonad WordLabelMapM where+ type Checkpoint WordLabelMapM = (WordLabelMap, Checkpoint SimpleUniqueMonad)+ checkpoint =+ let mapper+ :: WordLabelMap+ -> SimpleUniqueMonad (WordLabelMap, Checkpoint WordLabelMapM)+ mapper m = do+ suCheckpoint <- CH.checkpoint+ return (m, (m, suCheckpoint))+ in WordLabelMapM mapper+ restart (m, suCheckpoint) =+ let mapper :: WordLabelMap -> CH.SimpleUniqueMonad (WordLabelMap, ())+ mapper _ = do+ _ <- CH.restart suCheckpoint+ return (m, ())+ in WordLabelMapM mapper++type WordLabelMapFuelM = CheckingFuelMonad WordLabelMapM++labelFor :: Word256 -> WordLabelMapM Label+labelFor word = WordLabelMapM f+ where+ f m =+ case DB.lookup word m of+ Just l' -> return (m, l')+ Nothing -> do+ l' <- freshLabel+ let m' = DB.insert word l' m+ return (m', l')++labelsFor :: [Word256] -> WordLabelMapM [Label]+labelsFor = mapM labelFor++instance Monad WordLabelMapM where+ return = pure+ WordLabelMapM f1 >>= k =+ WordLabelMapM $ \m -> do+ (m', x) <- f1 m+ let (WordLabelMapM f2) = k x+ f2 m'++instance Functor WordLabelMapM where+ fmap = liftM++instance Applicative WordLabelMapM where+ pure x = WordLabelMapM (\m -> return (m, x))+ (<*>) = ap++class UnWordLabelMapM a where+ unWordLabelMapM :: WordLabelMapM a -> a++instance UnWordLabelMapM Int where+ unWordLabelMapM = internalUnWordLabelMapM++instance UnWordLabelMapM Text where+ unWordLabelMapM = internalUnWordLabelMapM++instance UnWordLabelMapM DTL.Text where+ unWordLabelMapM = internalUnWordLabelMapM++instance (UnWordLabelMapM a, UnWordLabelMapM b) =>+ UnWordLabelMapM (a, b) where+ unWordLabelMapM = internalUnWordLabelMapM++internalUnWordLabelMapM :: WordLabelMapM a -> a+internalUnWordLabelMapM (WordLabelMapM f) =+ snd $ runSimpleUniqueMonad (f DB.empty)
+ src/Ethereum/Analyzer/EVM/Util.hs view
@@ -0,0 +1,77 @@+{-# LANGUAGE FlexibleContexts, FlexibleInstances, GADTs,+ NoImplicitPrelude, Rank2Types, TypeFamilies, UndecidableInstances+ #-}++module Ethereum.Analyzer.EVM.Util+ ( toDotText+ , disasmToDotText+ , disasmToDotText2+ ) where++import Protolude hiding (show)++import Compiler.Hoopl+import Data.Graph.Inductive.Graph as DGIG+import Data.Graph.Inductive.PatriciaTree+import Data.GraphViz+import Data.GraphViz.Printing hiding ((<>))+import qualified Data.Text.Lazy as DTL+import Ethereum.Analyzer.EVM.CfgAugWithTopNPass+import Ethereum.Analyzer.EVM.CfgAugmentPass+import Ethereum.Analyzer.EVM.Disasm+import Ethereum.Analyzer.EVM.IR+import GHC.Show+import Text.Read (read)++disasmToDotText+ :: HasEvmBytecode a+ => a -> Text+disasmToDotText a =+ let disasmd = disasm a+ result =+ unWordLabelMapM $ do+ contract <- evmOps2HplContract disasmd+ toDotText <$> (bodyOf . ctorOf <$> doCfgAugmentPass contract)+ in result++disasmToDotText2+ :: HasEvmBytecode a+ => a -> (Text, Text)+disasmToDotText2 a =+ let result =+ unWordLabelMapM $ do+ contract' <- doCfgAugWithTopNPass a+ return+ ( toDotText $ bodyOf (ctorOf contract')+ , toDotText $ bodyOf (dispatcherOf contract'))+ in result++toDotText :: HplBody -> Text+toDotText bd =+ let bdGr = toGr bd+ dotG = toDotGraph bdGr+ dotCode = toDot dotG+ in DTL.toStrict $ renderDot dotCode++toGr :: HplBody -> Gr (Block HplOp C C) ()+toGr bd =+ let lblToNode l = read (drop 1 $ toS $ show l)+ (nList, eList) =+ mapFoldWithKey+ (\lbl blk (nList', eList') ->+ let node = lblToNode lbl+ edgs = map (\l -> (node, lblToNode l, ())) (successors blk)+ in (nList' <> [(node, blk)], eList' <> edgs))+ ([], [])+ bd+ in mkGraph nList eList++visParams+ :: forall n el.+ GraphvizParams n (Block HplOp C C) el () (Block HplOp C C)+visParams =+ nonClusteredParams+ {fmtNode = \(_, nl) -> [textLabel (toS $ show nl), shape BoxShape]}++toDotGraph :: Gr (Block HplOp C C) () -> DotGraph Node+toDotGraph = graphToDot visParams
− src/Ethereum/Analyzer/IR.hs
@@ -1,234 +0,0 @@-{-# LANGUAGE FlexibleContexts, OverloadedStrings,- NoImplicitPrelude, FlexibleInstances, GADTs, Rank2Types,- TypeFamilies, ScopedTypeVariables, UndecidableInstances #-}--module Ethereum.Analyzer.IR- ( HplBody- , HplCode(..)- , HplContract(..)- , HplOp(..)- , WordLabelMapM- , WordLabelMapFuelM- , unWordLabelMapM- , evmOps2HplCode- , evmOps2HplContract- , labelFor- , labelsFor- , showOp- , showOps- ) where--import Protolude hiding (show)--import Blockchain.ExtWord as BE-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 Legacy.Haskoin.V0102.Network.Haskoin.Crypto.BigWord--data HplOp e x where- CoOp :: Label -> HplOp C O- OoOp :: (Word256, Operation) -> HplOp O O- OcOp :: (Word256, Operation) -> [Label] -> HplOp O C- HpCodeCopy :: Word256 -> HplOp O O--showLoc :: Word256 -> String-showLoc = show . getBigWordInteger--showOp :: (Word256, Operation) -> String-showOp (lineNo, op) = showLoc lineNo <> ": " <> show op--showOps :: [(Word256, Operation)] -> [String]-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 (HpCodeCopy offset) = "HpCodeCopy " <> show offset--instance Show (Block HplOp C C) where- show (a :: Block HplOp C C) =- let (h, m, t) = blockSplit a- in DL.unlines $ [show h] <> DL.map show (blockToList m) <> [show t]--instance Eq (HplOp C O) where- (==) (CoOp a) (CoOp b) = a == b--instance Eq (HplOp O O) where- (==) (OoOp a) (OoOp b) = a == b- (==) (HpCodeCopy a) (HpCodeCopy b) = a == b- (==) _ _ = False--instance Eq (HplOp O C) where- (==) (OcOp a _) (OcOp b _) = a == b--instance NonLocal HplOp where- entryLabel (CoOp l) = l- successors (OcOp _ ll) = ll--type HplBody = Body HplOp--data HplCode = HplCode- { entryOf :: Maybe Label- , bodyOf :: HplBody- } deriving (Show)--data HplContract = HplContract- { ctorOf :: HplCode- , dispatcherOf :: HplCode- } deriving (Show)--emptyCode :: HplCode-emptyCode = HplCode Nothing emptyBody--evmOps2HplContract :: [(Word256, Operation)] -> WordLabelMapM HplContract-evmOps2HplContract l = do- ctorBody <- evmOps2HplCode l- return HplContract {ctorOf = ctorBody, dispatcherOf = emptyCode}--evmOps2HplCode :: [(Word256, Operation)] -> WordLabelMapM HplCode-evmOps2HplCode [] = return emptyCode-evmOps2HplCode l@((loc, _):_) = do- entry <- labelFor loc- body <- _evmOps2HplBody l- return HplCode {entryOf = Just entry, bodyOf = body}--_evmOps2HplBody :: [(Word256, Operation)] -> WordLabelMapM HplBody-_evmOps2HplBody [] = return emptyBody-_evmOps2HplBody el@((loc, _):_) = do- l <- labelFor loc- doEvmOps2HplBody emptyBody (blockJoinHead (CoOp l) emptyBlock) el- where- doEvmOps2HplBody- :: HplBody- -> Block HplOp C O- -> [(Word256, Operation)]- -> WordLabelMapM HplBody- doEvmOps2HplBody body _ [] = return body -- sliently discarding bad hds- doEvmOps2HplBody body hd [h'] =- if isTerminator (snd h')- then return $ addBlock (blockJoinTail hd (OcOp h' [])) body- else return body- doEvmOps2HplBody body hd (h':(t'@((loc', op'):_)))- | isTerminator (snd h') = do- l' <- labelFor loc'- doEvmOps2HplBody- (addBlock- (blockJoinTail hd (OcOp h' [l' | canPassThrough (snd h')]))- body)- (blockJoinHead (CoOp l') emptyBlock)- t'- | op' /= JUMPDEST = doEvmOps2HplBody body (blockSnoc hd (OoOp h')) t'- | otherwise = do- l' <- labelFor loc'- doEvmOps2HplBody- (addBlock- (blockJoinTail hd (OcOp h' [l' | canPassThrough (snd h')]))- body)- (blockJoinHead (CoOp l') emptyBlock)- t'--isTerminator :: Operation -> Bool-isTerminator STOP = True-isTerminator JUMP = True-isTerminator JUMPI = True-isTerminator CALL = True-isTerminator CALLCODE = True-isTerminator RETURN = True-isTerminator DELEGATECALL = True-isTerminator INVALID = True-isTerminator SUICIDE = True-isTerminator _ = False--canPassThrough :: Operation -> Bool-canPassThrough STOP = False-canPassThrough JUMP = False-canPassThrough RETURN = False-canPassThrough INVALID = False-canPassThrough SUICIDE = False-canPassThrough _ = True------------------------------------------------------------------------------------- The WordLabelMapM monad----------------------------------------------------------------------------------type WordLabelMap = Bimap Word256 Label--newtype WordLabelMapM a =- WordLabelMapM (WordLabelMap -> SimpleUniqueMonad (WordLabelMap, a))--instance CheckpointMonad WordLabelMapM where- type Checkpoint WordLabelMapM = (WordLabelMap, Checkpoint SimpleUniqueMonad)- checkpoint =- let mapper- :: WordLabelMap- -> SimpleUniqueMonad (WordLabelMap, Checkpoint WordLabelMapM)- mapper m = do- suCheckpoint <- CH.checkpoint- return (m, (m, suCheckpoint))- in WordLabelMapM mapper- restart (m, suCheckpoint) =- let mapper :: WordLabelMap -> CH.SimpleUniqueMonad (WordLabelMap, ())- mapper _ = do- _ <- CH.restart suCheckpoint- return (m, ())- in WordLabelMapM mapper--type WordLabelMapFuelM = CheckingFuelMonad WordLabelMapM--labelFor :: Word256 -> WordLabelMapM Label-labelFor word = WordLabelMapM f- where- f m =- case DB.lookup word m of- Just l' -> return (m, l')- Nothing -> do- l' <- freshLabel- let m' = DB.insert word l' m- return (m', l')--labelsFor :: [Word256] -> WordLabelMapM [Label]-labelsFor = mapM labelFor--instance Monad WordLabelMapM where- return = pure- WordLabelMapM f1 >>= k =- WordLabelMapM $ \m -> do- (m', x) <- f1 m- let (WordLabelMapM f2) = k x- f2 m'--instance Functor WordLabelMapM where- fmap = liftM--instance Applicative WordLabelMapM where- pure x = WordLabelMapM (\m -> return (m, x))- (<*>) = ap--class UnWordLabelMapM a where- unWordLabelMapM :: WordLabelMapM a -> a--instance UnWordLabelMapM Int where- unWordLabelMapM = internalUnWordLabelMapM--instance UnWordLabelMapM Text where- unWordLabelMapM = internalUnWordLabelMapM--instance UnWordLabelMapM DTL.Text where- unWordLabelMapM = internalUnWordLabelMapM--instance (UnWordLabelMapM a, UnWordLabelMapM b) =>- UnWordLabelMapM (a, b) where- unWordLabelMapM = internalUnWordLabelMapM--internalUnWordLabelMapM :: WordLabelMapM a -> a-internalUnWordLabelMapM (WordLabelMapM f) =- snd $ runSimpleUniqueMonad (f DB.empty)
src/Ethereum/Analyzer/Solidity/AstJson.hs view
@@ -18,11 +18,11 @@ decodeSoleNodes :: LByteString -> Either Text [SolNode] decodeSoleNodes combined_ast = do- value <- (s2t4Either (eitherDecode combined_ast) :: Either Text Value)+ value <- s2t4Either (eitherDecode combined_ast) :: Either Text Value case value of Object o1 -> do srcObj <-- (maybeToRight "Could not find 'sources' in object" (lookup "sources" o1) :: Either Text Value)+ maybeToRight "Could not find 'sources' in object" (lookup "sources" o1) :: Either Text Value case srcObj of Object o2 -> do let srcUnitObjs = elems o2@@ -100,7 +100,7 @@ instance Pretty SolNode where pretty n@SolNode {name = name}- | name == Nothing = prettyAst n -- Top level AST+ | isNothing name = prettyAst n -- Top level AST | name == Just "SourceUnit" = prettySourceUnit n | name == Just "PragmaDirective" = PP.empty | name == Just "ContractDefinition" = prettyContractDefinition n
src/Ethereum/Analyzer/Solidity/Foreach.hs view
@@ -33,7 +33,7 @@ _eOf :: Statement -> [Expression] _eOf (StLocalVarDecl _) = [] _eOf (StAssign _ e) = [e]-_eOf (StIf _ _ _) = []+_eOf (StIf{}) = [] _eOf (StLoop _) = [] _eOf StBreak = [] _eOf StContinue = []
src/Ethereum/Analyzer/Solidity/Simple.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-}+{-# OPTIONS_GHC -fno-warn-name-shadowing #-} module Ethereum.Analyzer.Solidity.Simple ( Contract(..)@@ -135,7 +136,7 @@ } } = [VarDecl (Idfr vName) (Unknown vType)] s2sVarDecls SolNode {name = Just "ParameterList", children = Just pChildren} =- concat (map s2sVarDecls pChildren)+ concatMap s2sVarDecls pChildren s2sVarDecls _ = [] s2sFuns@@ -159,10 +160,10 @@ :: UniqueMonad m => SolNode -> m [Statement] s2sStatements SolNode {name = Just "Block", children = Just sChildren} =- concat <$> (mapM s2sStatements sChildren)+ concat <$> mapM s2sStatements sChildren s2sStatements SolNode { name = Just "ExpressionStatement" , children = Just sChildren- } = concat <$> (mapM s2sStatements sChildren)+ } = concat <$> mapM s2sStatements sChildren s2sStatements SolNode { name = Just "Assignment" , children = Just [lval, rval] , attributes = Just SolNode {operator = Just op}@@ -170,9 +171,10 @@ (prelval, simpleLval) <- s2sLval lval (prerval, simpleRval) <- s2sLval rval return $ prerval <> prelval <> [StAssign simpleLval $ ExpLval simpleRval]-s2sStatements e@SolNode {name = Just "Return", children = Just sChildren} = do+s2sStatements e@SolNode {name = Just "Return", children = ch} = do+ let sChildren = fromMaybe [] ch presAndRvals <- mapM s2sLval sChildren- let prerval = concat (map fst presAndRvals)+ let prerval = concatMap fst presAndRvals let simpleRvals = map snd presAndRvals return $ prerval <> [StReturn simpleRvals] s2sStatements e@SolNode { name = Just "UnaryOperation"@@ -193,7 +195,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 [SolNode { name = Just "Identifier" , attributes = Just SolNode {value = Just idName} }]
− src/Ethereum/Analyzer/Util.hs
@@ -1,77 +0,0 @@-{-# LANGUAGE FlexibleContexts, FlexibleInstances, GADTs,- NoImplicitPrelude, Rank2Types, TypeFamilies, UndecidableInstances- #-}--module Ethereum.Analyzer.Util- ( toDotText- , disasmToDotText- , disasmToDotText2- ) where--import Protolude hiding (show)--import Compiler.Hoopl-import Data.Graph.Inductive.Graph as DGIG-import Data.Graph.Inductive.PatriciaTree-import Data.GraphViz-import Data.GraphViz.Printing hiding ((<>))-import qualified Data.Text.Lazy as DTL-import Ethereum.Analyzer.CfgAugWithTopNPass-import Ethereum.Analyzer.CfgAugmentPass-import Ethereum.Analyzer.Disasm-import Ethereum.Analyzer.IR-import GHC.Show-import Text.Read (read)--disasmToDotText- :: HasEvmBytecode a- => a -> Text-disasmToDotText a =- let disasmd = disasm a- result =- unWordLabelMapM $ do- contract <- evmOps2HplContract disasmd- toDotText <$> (bodyOf . ctorOf <$> doCfgAugmentPass contract)- in result--disasmToDotText2- :: HasEvmBytecode a- => a -> (Text, Text)-disasmToDotText2 a =- let result =- unWordLabelMapM $ do- contract' <- doCfgAugWithTopNPass a- return- ( toDotText $ bodyOf (ctorOf contract')- , toDotText $ bodyOf (dispatcherOf contract'))- in result--toDotText :: HplBody -> Text-toDotText bd =- let bdGr = toGr bd- dotG = toDotGraph bdGr- dotCode = toDot dotG- in DTL.toStrict $ renderDot dotCode--toGr :: HplBody -> Gr (Block HplOp C C) ()-toGr bd =- let lblToNode l = read (drop 1 $ toS $ show l)- (nList, eList) =- mapFoldWithKey- (\lbl blk (nList', eList') ->- let node = lblToNode lbl- edgs = map (\l -> (node, lblToNode l, ())) (successors blk)- in (nList' <> [(node, blk)], eList' <> edgs))- ([], [])- bd- in mkGraph nList eList--visParams- :: forall n el.- GraphvizParams n (Block HplOp C C) el () (Block HplOp C C)-visParams =- nonClusteredParams- {fmtNode = \(_, nl) -> [textLabel (toS $ show nl), shape BoxShape]}--toDotGraph :: Gr (Block HplOp C C) () -> DotGraph Node-toDotGraph = graphToDot visParams
− test/Ethereum/Analyzer/CfgAugWithTopNPassSpec.hs
@@ -1,29 +0,0 @@-{-# LANGUAGE OverloadedStrings, NoImplicitPrelude, FlexibleContexts- #-}--module Ethereum.Analyzer.CfgAugWithTopNPassSpec- ( spec- ) where--import Protolude hiding (show)--import Data.Text as DT-import Ethereum.Analyzer-import Ethereum.Analyzer.CfgAugWithTopNPass-import Ethereum.Analyzer.TestData.Basic-import GHC.Show-import Test.Hspec--spec :: Spec-spec =- describe "doCfgAugWithTopNPass" $ do- it "works for hexstring1" $ do- let result =- unWordLabelMapM $ toS . show <$> doCfgAugWithTopNPass hexstring1- DT.length result `shouldBe` 4815- it "works for hexstring2" $ do- let result =- toS $- unWordLabelMapM- ((toS . show <$> doCfgAugWithTopNPass hexstring2) :: WordLabelMapM Text)- result `shouldContain` "OC: 9: JUMPI -> [L2,L4]"
− test/Ethereum/Analyzer/CfgAugmentPassSpec.hs
@@ -1,181 +0,0 @@-{-# LANGUAGE OverloadedStrings, FlexibleContexts #-}--module Ethereum.Analyzer.CfgAugmentPassSpec- ( spec- ) where--import Protolude hiding (show)--import Data.Text (length)-import Ethereum.Analyzer-import Ethereum.Analyzer.CfgAugmentPass-import Ethereum.Analyzer.TestData.Basic-import GHC.Show-import Test.Hspec--spec :: Spec-spec =- describe "doCfgAugmentPass" $ do- it "works for hexstring1" $ do- let disasmd = disasm hexstring1- result =- unWordLabelMapM $ do- contract <- evmOps2HplContract disasmd- (toS . show <$> doCfgAugmentPass contract) :: WordLabelMapM Text- Data.Text.length result `shouldBe` 4769- it "works for hexstring2" $ do- let disasmd@((_, _):_) = disasm hexstring2- result =- unWordLabelMapM $ do- contract <- evmOps2HplContract disasmd- toS . show . bodyOf . ctorOf <$> doCfgAugmentPass contract- result `shouldBe` expectedHexString2CtorBody--expectedHexString2CtorBody :: Text-expectedHexString2CtorBody =- "LM (UM (fromList [(1,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 -> [L2,L4]\n" <>- "),(2,CO: L2\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 -> [L3,L7]\n" <>- "),(3,CO: L3\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 -> [L4,L9]\n" <>- "),(4,CO: L4\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 -> [L5,L6]\n" <>- "),(5,CO: L5\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 -> [L6]\n" <>- "),(6,CO: L6\n" <>- "OO: 108: JUMPDEST\n" <>- "OC: 109: JUMP -> []\n" <>- "),(7,CO: L7\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 -> [L6,L8]\n" <>- "),(8,CO: L8\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,CO: L9\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 -> [L6,L10]\n" <>- "),(10,CO: L10\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 -> [L11]\n" <>- "),(11,CO: L11\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" <>- ")]))"
+ test/Ethereum/Analyzer/EVM/CfgAugWithTopNPassSpec.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE OverloadedStrings, NoImplicitPrelude, FlexibleContexts+ #-}++module Ethereum.Analyzer.EVM.CfgAugWithTopNPassSpec+ ( spec+ ) where++import Protolude hiding (show)++import Data.Text as DT+import Ethereum.Analyzer.EVM+import Ethereum.Analyzer.TestData.Basic+import GHC.Show+import Test.Hspec++spec :: Spec+spec =+ describe "doCfgAugWithTopNPass" $ do+ it "works for hexstring1" $ do+ let result =+ unWordLabelMapM $ toS . show <$> doCfgAugWithTopNPass hexstring1+ DT.length result `shouldBe` 4815+ it "works for hexstring2" $ do+ let result =+ toS $+ unWordLabelMapM+ ((toS . show <$> doCfgAugWithTopNPass hexstring2) :: WordLabelMapM Text)+ (result :: [Char]) `shouldContain` "OC: 9: JUMPI -> [L2,L4]"
+ test/Ethereum/Analyzer/EVM/CfgAugmentPassSpec.hs view
@@ -0,0 +1,180 @@+{-# LANGUAGE OverloadedStrings, FlexibleContexts #-}++module Ethereum.Analyzer.EVM.CfgAugmentPassSpec+ ( spec+ ) where++import Protolude hiding (show)++import Data.Text (length)+import Ethereum.Analyzer.EVM+import Ethereum.Analyzer.TestData.Basic+import GHC.Show+import Test.Hspec++spec :: Spec+spec =+ describe "doCfgAugmentPass" $ do+ it "works for hexstring1" $ do+ let disasmd = disasm hexstring1+ result =+ unWordLabelMapM $ do+ contract <- evmOps2HplContract disasmd+ (toS . show <$> doCfgAugmentPass contract) :: WordLabelMapM Text+ Data.Text.length result `shouldBe` 4769+ it "works for hexstring2" $ do+ let disasmd@((_, _):_) = disasm hexstring2+ result =+ unWordLabelMapM $ do+ contract <- evmOps2HplContract disasmd+ toS . show . bodyOf . ctorOf <$> doCfgAugmentPass contract+ result `shouldBe` expectedHexString2CtorBody++expectedHexString2CtorBody :: Text+expectedHexString2CtorBody =+ "LM (UM (fromList [(1,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 -> [L2,L4]\n" <>+ "),(2,CO: L2\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 -> [L3,L7]\n" <>+ "),(3,CO: L3\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 -> [L4,L9]\n" <>+ "),(4,CO: L4\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 -> [L5,L6]\n" <>+ "),(5,CO: L5\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 -> [L6]\n" <>+ "),(6,CO: L6\n" <>+ "OO: 108: JUMPDEST\n" <>+ "OC: 109: JUMP -> []\n" <>+ "),(7,CO: L7\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 -> [L6,L8]\n" <>+ "),(8,CO: L8\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,CO: L9\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 -> [L6,L10]\n" <>+ "),(10,CO: L10\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 -> [L11]\n" <>+ "),(11,CO: L11\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" <>+ ")]))"
+ test/Ethereum/Analyzer/EVM/IRSpec.hs view
@@ -0,0 +1,183 @@+module Ethereum.Analyzer.EVM.IRSpec+ ( spec+ ) where++import Protolude hiding (show)++import Compiler.Hoopl+import Ethereum.Analyzer.EVM+import Ethereum.Analyzer.TestData.Basic+import GHC.Show+import Test.Hspec++spec :: Spec+spec =+ describe "e2h" $ do+ it "works for hexstring1" $ do+ let disasmd = disasm hexstring1+ unWordLabelMapM (mapSize . bodyOf . ctorOf <$> evmOps2HplContract disasmd) `shouldBe`+ 327+ it "works for hexstring2" $ do+ let disasmd = disasm hexstring2+ unWordLabelMapM (mapSize . bodyOf . ctorOf <$> evmOps2HplContract disasmd) `shouldBe`+ 12+ -- it "shows voteHexstring" $+ -- do let disasmd = disasm voteHexstring+ -- unWordLabelMapM (show <$> (evmOps2HplBody disasmd)) `shouldBe` ""+ it "shows HplBody" $ do+ let disasmd = disasm hexstring2+ unWordLabelMapM+ ((toS . show . bodyOf . ctorOf <$> evmOps2HplContract disasmd) :: WordLabelMapM Text) `shouldBe`+ toS expectedHexString2CtorBody++expectedHexString2CtorBody :: Text+expectedHexString2CtorBody =+ "LM (UM (fromList [(1,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 -> [L2]\n" <>+ "),(2,CO: L2\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 -> [L3]\n" <>+ "),(3,CO: L3\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 -> [L4]\n" <>+ "),(4,CO: L4\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 -> [L5]\n" <>+ "),(5,CO: L5\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 -> [L6]\n" <>+ "),(6,CO: L6\n" <>+ "OO: 108: JUMPDEST\n" <>+ "OC: 109: JUMP -> []\n" <>+ "),(7,CO: L7\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 -> [L8]\n" <>+ "),(8,CO: L8\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,CO: L9\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 -> [L10]\n" <>+ "),(10,CO: L10\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 -> [L11]\n" <>+ "),(11,CO: L11\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,CO: L12\n" <>+ "OO: 213: JUMPDEST\n" <>+ "OC: 214: STOP -> []\n" <>+ ")]))"
+ test/Ethereum/Analyzer/EVM/UtilSpec.hs view
@@ -0,0 +1,397 @@+{-# LANGUAGE OverloadedStrings, NoImplicitPrelude #-}++module Ethereum.Analyzer.EVM.UtilSpec+ ( spec+ ) where++import Protolude hiding (show)++import Data.Text+import Ethereum.Analyzer.EVM+import Ethereum.Analyzer.TestData.Basic+import Test.Hspec++spec :: Spec+spec =+ describe "toDotText" $ do+ it "shows HplBody's dot graph" $ do+ let disasmd = disasm hexstring2+ (unpack . unWordLabelMapM)+ (toDotText . bodyOf . ctorOf <$> evmOps2HplContract disasmd) `shouldBe`+ toS expectedHexString2RawDot+ it "shows HplBody after CfgAugmentPass" $ do+ let disasmd@((_, _):_) = disasm hexstring2+ result =+ (unpack . unWordLabelMapM) $ do+ contract <- evmOps2HplContract disasmd+ toDotText . bodyOf . ctorOf <$> doCfgAugmentPass contract+ result `shouldBe` toS expectedHexString2AugDot++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 -> [L2]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 2 [label=\"CO: L2\\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 -> [L3]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 3 [label=\"CO: L3\\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 -> [L4]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 4 [label=\"CO: L4\\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 -> [L5]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 5 [label=\"CO: L5\\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 -> [L6]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 6 [label=\"CO: L6\\n" <>+ "OO: 108: JUMPDEST\\n" <>+ "OC: 109: JUMP -> []\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 7 [label=\"CO: L7\\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 -> [L8]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 8 [label=\"CO: L8\\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" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 9 [label=\"CO: L9\\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 -> [L10]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 10 [label=\"CO: L10\\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 -> [L11]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 11 [label=\"CO: L11\\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" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 12 [label=\"CO: L12\\n" <>+ "OO: 213: JUMPDEST\\n" <>+ "OC: 214: STOP -> []\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 1 -> 2;\n" <>+ " 2 -> 3;\n" <>+ " 3 -> 4;\n" <>+ " 4 -> 5;\n" <>+ " 5 -> 6;\n" <>+ " 7 -> 8;\n" <>+ " 9 -> 10;\n" <>+ " 10 -> 11;\n" <>+ "}"++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 -> [L2,L4]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 2 [label=\"CO: L2\\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 -> [L3,L7]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 3 [label=\"CO: L3\\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 -> [L4,L9]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 4 [label=\"CO: L4\\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 -> [L5,L6]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 5 [label=\"CO: L5\\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 -> [L6]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 6 [label=\"CO: L6\\n" <>+ "OO: 108: JUMPDEST\\n" <>+ "OC: 109: JUMP -> []\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 7 [label=\"CO: L7\\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 -> [L6,L8]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 8 [label=\"CO: L8\\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" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 9 [label=\"CO: L9\\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 -> [L6,L10]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 10 [label=\"CO: L10\\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 -> [L11]\\n" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 11 [label=\"CO: L11\\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" <>+ "\"\n" <>+ " ,shape=box];\n" <>+ " 1 -> 2;\n" <>+ " 1 -> 4;\n" <>+ " 2 -> 3;\n" <>+ " 2 -> 7;\n" <>+ " 3 -> 4;\n" <>+ " 3 -> 9;\n" <>+ " 4 -> 5;\n" <>+ " 4 -> 6;\n" <>+ " 5 -> 6;\n" <>+ " 7 -> 6;\n" <>+ " 7 -> 8;\n" <>+ " 9 -> 6;\n" <>+ " 9 -> 10;\n" <>+ " 10 -> 11;\n" <>+ "}"
− test/Ethereum/Analyzer/IRSpec.hs
@@ -1,183 +0,0 @@-module Ethereum.Analyzer.IRSpec- ( spec- ) where--import Protolude hiding (show)--import Compiler.Hoopl-import Ethereum.Analyzer-import Ethereum.Analyzer.TestData.Basic-import GHC.Show-import Test.Hspec--spec :: Spec-spec =- describe "e2h" $ do- it "works for hexstring1" $ do- let disasmd = disasm hexstring1- unWordLabelMapM (mapSize . bodyOf . ctorOf <$> evmOps2HplContract disasmd) `shouldBe`- 327- it "works for hexstring2" $ do- let disasmd = disasm hexstring2- unWordLabelMapM (mapSize . bodyOf . ctorOf <$> evmOps2HplContract disasmd) `shouldBe`- 12- -- it "shows voteHexstring" $- -- do let disasmd = disasm voteHexstring- -- unWordLabelMapM (show <$> (evmOps2HplBody disasmd)) `shouldBe` ""- it "shows HplBody" $ do- let disasmd = disasm hexstring2- unWordLabelMapM- ((toS . show . bodyOf . ctorOf <$> evmOps2HplContract disasmd) :: WordLabelMapM Text) `shouldBe`- toS expectedHexString2CtorBody--expectedHexString2CtorBody :: Text-expectedHexString2CtorBody =- "LM (UM (fromList [(1,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 -> [L2]\n" <>- "),(2,CO: L2\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 -> [L3]\n" <>- "),(3,CO: L3\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 -> [L4]\n" <>- "),(4,CO: L4\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 -> [L5]\n" <>- "),(5,CO: L5\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 -> [L6]\n" <>- "),(6,CO: L6\n" <>- "OO: 108: JUMPDEST\n" <>- "OC: 109: JUMP -> []\n" <>- "),(7,CO: L7\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 -> [L8]\n" <>- "),(8,CO: L8\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,CO: L9\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 -> [L10]\n" <>- "),(10,CO: L10\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 -> [L11]\n" <>- "),(11,CO: L11\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,CO: L12\n" <>- "OO: 213: JUMPDEST\n" <>- "OC: 214: STOP -> []\n" <>- ")]))"
+ test/Ethereum/Analyzer/Solidity/AstJsonSpec.hs view
@@ -0,0 +1,21 @@+{-# LANGUAGE OverloadedStrings #-}++module Ethereum.Analyzer.Solidity.AstJsonSpec+ ( spec+ ) where++import Protolude++import Ethereum.Analyzer.Solidity+import Ethereum.Analyzer.TestData.Asts+import Test.Hspec++spec :: Spec+spec = describe "AstJson" $ mapM_ nonEmptyAstFile testFilepaths++nonEmptyAstFile :: Text -> SpecWith ()+nonEmptyAstFile filepath =+ context (toS filepath) $+ it "returns [SolNode]" $ do+ nodes <- solNodesOf filepath+ length (nodes :: [SolNode]) `shouldSatisfy` (0 <)
test/Ethereum/Analyzer/Solidity/ForeachSpec.hs view
@@ -5,33 +5,20 @@ import Protolude hiding (show) import Ethereum.Analyzer.Solidity-import Ethereum.Analyzer.TestData.DaoJson (simpleDaoJson) import Ethereum.Analyzer.TestData.StorageJson (storageJson) import Test.Hspec spec :: Spec spec = do describe "statementsOf" $- parallel $ do- it "works for storageJson" $ do- case decodeContracts storageJson of- Right contracts ->- sum (map (length . statementsOf) contracts) `shouldBe` 2- Left err -> expectationFailure $ toS err- it "works for simpleDaoJson" $ do- case decodeContracts simpleDaoJson of- Right contracts ->- sum (map (length . statementsOf) contracts) `shouldBe` 39- Left err -> expectationFailure $ toS err+ it "works for storageJson" $ do+ case decodeContracts storageJson of+ Right contracts ->+ sum (map (length . statementsOf) contracts) `shouldBe` 2+ Left err -> expectationFailure $ toS err describe "expressionsOf" $- parallel $ do- it "works for storageJson" $ do- case decodeContracts storageJson of- Right contracts ->- sum (map (length . expressionsOf) contracts) `shouldBe` 1- Left err -> expectationFailure $ toS err- it "works for simpleDaoJson" $ do- case decodeContracts simpleDaoJson of- Right contracts ->- sum (map (length . expressionsOf) contracts) `shouldBe` 33- Left err -> expectationFailure $ toS err+ it "works for storageJson" $ do+ case decodeContracts storageJson of+ Right contracts ->+ sum (map (length . expressionsOf) contracts) `shouldBe` 1+ Left err -> expectationFailure $ toS err
test/Ethereum/Analyzer/Solidity/SimpleSpec.hs view
@@ -8,7 +8,7 @@ -- import Ethereum.Analyzer.Common import Ethereum.Analyzer.Solidity-import Ethereum.Analyzer.TestData.DaoJson (simpleDaoJson)+import Ethereum.Analyzer.TestData.Asts import Ethereum.Analyzer.TestData.StorageJson (storageJson) -- import GHC.Show (Show(..))@@ -16,396 +16,52 @@ import qualified Text.PrettyPrint.GenericPretty as GP spec :: Spec-spec =+spec = do describe "e2h" $- parallel $ do it "parses storageJson" $ do- let eitherContracts = do- solNodes <- decodeSoleNodes (toS storageJson)- let mContracts = mapM s2sContracts solNodes- let contracts = concat $ runSimpleUniqueMonad mContracts- return contracts- GP.pp eitherContracts- eitherContracts `shouldBe`- Right- [ Contract- { cName = "SimpleStorage"- , cStateVars =- [VarDecl {vName = Idfr "storedData", vType = Unknown "uint256"}]- , cFunctions =- [ FunDefinition- { fName = Idfr "set"- , fParams =- [VarDecl {vName = Idfr "x", vType = Unknown "uint256"}]- , fReturns = []- , fBody =- [ StAssign- (JustId (Idfr "storedData"))- (ExpLval (JustId (Idfr "x")))- ]- }- , FunDefinition- { fName = Idfr "get"- , fParams = []- , fReturns =- [VarDecl {vName = Idfr "", vType = Unknown "uint256"}]- , fBody = [StReturn [JustId (Idfr "storedData")]]- }- ]- }- ]- it "parses simpleDaoJson" $ do- let eitherContracts = do- solNodes <- decodeSoleNodes (toS simpleDaoJson)- let mContracts = mapM s2sContracts solNodes- let contracts = concat $ runSimpleUniqueMonad mContracts- return contracts- GP.pp eitherContracts- eitherContracts `shouldBe`- Right- [ Contract- { cName = "SimpleDAO"- , cStateVars =- [ VarDecl- { vName = Idfr "credit"- , vType = Unknown "mapping(address => uint256)"- }- ]- , cFunctions =- [ FunDefinition- { fName = Idfr "donate"- , fParams =- [VarDecl {vName = Idfr "to", vType = Unknown "address"}]- , fReturns = []- , fBody =- [ StAssign- (Index- { iArray = JustId (Idfr "credit")- , iIndex =- Index- { iArray = JustId (Idfr "credit")- , iIndex = JustId (Idfr "to")- }- })- (ExpLval- (Member- { mObj = JustId (Idfr "msg")- , mField = Idfr "value"- }))- ]- }- , FunDefinition- { fName = Idfr "withdraw"- , fParams =- [ VarDecl- {vName = Idfr "amount", vType = Unknown "uint256"}- ]- , fReturns = []- , fBody =- [ StAssign- (JustId (Idfr "v1"))- (ExpBin- ">="- (Index- { iArray = JustId (Idfr "credit")- , iIndex =- Index- { iArray = JustId (Idfr "credit")- , iIndex =- Member- { mObj = JustId (Idfr "msg")- , mField = Idfr "sender"- }- }- })- (JustId (Idfr "amount")))- , StIf- (JustId (Idfr "v1"))- [ StAssign- (JustId (Idfr "v2"))- (ExpCall- (Member- { mObj =- Member- { mObj =- Member- { mObj = JustId (Idfr "msg")- , mField = Idfr "sender"- }- , mField = Idfr "call"- }- , mField = Idfr "value"- })- [JustId (Idfr "amount")])- , StAssign- (JustId (Idfr "v3"))- (ExpCall (JustId (Idfr "v2")) [])- , StLocalVarDecl- (VarDecl- {vName = Idfr "res", vType = Unknown "bool"})- , StAssign- (JustId (Idfr "res"))- (ExpLval (JustId (Idfr "v3")))- , StAssign- (Index- { iArray = JustId (Idfr "credit")- , iIndex =- Index- { iArray = JustId (Idfr "credit")- , iIndex =- Member- { mObj = JustId (Idfr "msg")- , mField = Idfr "sender"- }- }- })- (ExpLval (JustId (Idfr "amount")))- ]- []- ]- }- , FunDefinition- { fName = Idfr "queryCredit"- , fParams =- [VarDecl {vName = Idfr "to", vType = Unknown "address"}]- , fReturns =- [VarDecl {vName = Idfr "", vType = Unknown "uint256"}]- , fBody =- [ StReturn- [ Index- { iArray = JustId (Idfr "credit")- , iIndex =- Index- { iArray = JustId (Idfr "credit")- , iIndex = JustId (Idfr "to")- }- }- ]- ]- }- ]- }- , Contract- { cName = "Mallory"- , cStateVars =- [ VarDecl- {vName = Idfr "dao", vType = Unknown "contract SimpleDAO"}- , VarDecl {vName = Idfr "owner", vType = Unknown "address"}- ]- , cFunctions =- [ FunDefinition- { fName = Idfr "Mallory"- , fParams =- [ VarDecl- { vName = Idfr "addr"- , vType = Unknown "contract SimpleDAO"- }- ]- , fReturns = []- , fBody =- [ StAssign- (JustId (Idfr "owner"))- (ExpLval- (Member- { mObj = JustId (Idfr "msg")- , mField = Idfr "sender"- }))- , StAssign- (JustId (Idfr "dao"))- (ExpLval (JustId (Idfr "addr")))- ]- }- , FunDefinition- { fName = Idfr "getJackpot"- , fParams = []- , fReturns = []- , fBody =- [ StAssign- (JustId (Idfr "v6"))- (ExpCall- (Member- { mObj = JustId (Idfr "owner")- , mField = Idfr "send"- })- [ Member- { mObj = JustId (Idfr "this")- , mField = Idfr "balance"- }- ])- , StLocalVarDecl- (VarDecl {vName = Idfr "res", vType = Unknown "bool"})- , StAssign- (JustId (Idfr "res"))- (ExpLval (JustId (Idfr "v6")))- ]- }- , FunDefinition- { fName = Idfr ""- , fParams = []- , fReturns = []- , fBody =- [ StAssign- (JustId (Idfr "v4"))- (ExpCall- (Member- { mObj = JustId (Idfr "dao")- , mField = Idfr "queryCredit"- })- [JustId (Idfr "this")])- , StAssign- (JustId (Idfr "v5"))- (ExpCall- (Member- { mObj = JustId (Idfr "dao")- , mField = Idfr "withdraw"- })- [JustId (Idfr "v4")])- , StAssign- (JustId (Idfr "_"))- (ExpLval (JustId (Idfr "v5")))- ]- }- ]- }- , Contract- { cName = "Mallory2"- , cStateVars =- [ VarDecl- {vName = Idfr "dao", vType = Unknown "contract SimpleDAO"}- , VarDecl {vName = Idfr "owner", vType = Unknown "address"}- , VarDecl {vName = Idfr "performAttack", vType = Unknown "bool"}- ]- , cFunctions =- [ FunDefinition- { fName = Idfr "Mallory2"- , fParams =- [ VarDecl- { vName = Idfr "addr"- , vType = Unknown "contract SimpleDAO"- }- ]- , fReturns = []- , fBody =- [ StAssign- (JustId (Idfr "owner"))- (ExpLval- (Member- { mObj = JustId (Idfr "msg")- , mField = Idfr "sender"- }))- , StAssign- (JustId (Idfr "dao"))- (ExpLval (JustId (Idfr "addr")))- ]- }- , FunDefinition- { fName = Idfr "attack"- , fParams = []- , fReturns = []- , fBody =- [ StAssign (JustId (Idfr "v13")) (ExpLiteral "1")- , StAssign- (JustId (Idfr "v14"))- (ExpCall- (Member- { mObj =- Member- { mObj = JustId (Idfr "dao")- , mField = Idfr "donate"- }- , mField = Idfr "value"- })- [JustId (Idfr "v13")])- , StAssign- (JustId (Idfr "v15"))- (ExpCall (JustId (Idfr "v14")) [JustId (Idfr "this")])- , StAssign- (JustId (Idfr "_"))- (ExpLval (JustId (Idfr "v15")))- , StAssign (JustId (Idfr "v16")) (ExpLiteral "1")- , StAssign- (JustId (Idfr "v17"))- (ExpCall- (Member- { mObj = JustId (Idfr "dao")- , mField = Idfr "withdraw"- })- [JustId (Idfr "v16")])- , StAssign- (JustId (Idfr "_"))- (ExpLval (JustId (Idfr "v17")))- ]- }- , FunDefinition- { fName = Idfr "getJackpot"- , fParams = []- , fReturns = []- , fBody =- [ StAssign- (JustId (Idfr "v10"))- (ExpCall- (Member- { mObj = JustId (Idfr "dao")- , mField = Idfr "withdraw"- })- [ Member- { mObj = JustId (Idfr "dao")- , mField = Idfr "balance"- }- ])- , StAssign- (JustId (Idfr "_"))- (ExpLval (JustId (Idfr "v10")))- , StAssign- (JustId (Idfr "v11"))- (ExpCall- (Member- { mObj = JustId (Idfr "owner")- , mField = Idfr "send"- })- [ Member- { mObj = JustId (Idfr "this")- , mField = Idfr "balance"- }- ])- , StLocalVarDecl- (VarDecl {vName = Idfr "res", vType = Unknown "bool"})- , StAssign- (JustId (Idfr "res"))- (ExpLval (JustId (Idfr "v11")))- , StAssign (JustId (Idfr "v12")) (ExpLiteral "true")- , StAssign- (JustId (Idfr "performAttack"))- (ExpLval (JustId (Idfr "v12")))- ]- }- , FunDefinition- { fName = Idfr ""- , fParams = []- , fReturns = []- , fBody =- [ StIf- (JustId (Idfr "performAttack"))- [ StAssign (JustId (Idfr "v7")) (ExpLiteral "false")- , StAssign- (JustId (Idfr "performAttack"))- (ExpLval (JustId (Idfr "v7")))- , StAssign (JustId (Idfr "v8")) (ExpLiteral "1")- , StAssign- (JustId (Idfr "v9"))- (ExpCall- (Member- { mObj = JustId (Idfr "dao")- , mField = Idfr "withdraw"- })- [JustId (Idfr "v8")])- , StAssign- (JustId (Idfr "_"))- (ExpLval (JustId (Idfr "v9")))- ]- []- ]- }- ]- }- ]+ let eitherContracts = do+ solNodes <- decodeSoleNodes (toS storageJson)+ let mContracts = mapM s2sContracts solNodes+ let contracts = concat $ runSimpleUniqueMonad mContracts+ return contracts+ -- GP.pp eitherContracts+ eitherContracts `shouldBe`+ Right+ [ Contract+ { cName = "SimpleStorage"+ , cStateVars =+ [VarDecl {vName = Idfr "storedData", vType = Unknown "uint256"}]+ , cFunctions =+ [ FunDefinition+ { fName = Idfr "set"+ , fParams =+ [VarDecl {vName = Idfr "x", vType = Unknown "uint256"}]+ , fReturns = []+ , fBody =+ [ StAssign+ (JustId (Idfr "storedData"))+ (ExpLval (JustId (Idfr "x")))+ ]+ }+ , FunDefinition+ { fName = Idfr "get"+ , fParams = []+ , fReturns =+ [VarDecl {vName = Idfr "", vType = Unknown "uint256"}]+ , fBody = [StReturn [JustId (Idfr "storedData")]]+ }+ ]+ }+ ]+ describe "Simple" $ mapM_ nonEmptySimple testFilepaths++nonEmptySimple :: Text -> SpecWith ()+nonEmptySimple filepath =+ context (toS filepath) $+ it "converts SolNode to Contracts" $ do+ contracts <-+ do solNodes <- solNodesOf filepath+ let mContracts = mapM s2sContracts solNodes+ let contracts = concat $ runSimpleUniqueMonad mContracts+ return contracts+ length contracts `shouldSatisfy` (0 <)
test/Ethereum/Analyzer/SoliditySpec.hs view
@@ -4,9 +4,7 @@ import Protolude hiding (show) -import Ethereum.Analyzer.Common import Ethereum.Analyzer.Solidity-import Ethereum.Analyzer.TestData.DaoJson (simpleDaoJson) import Ethereum.Analyzer.TestData.StorageJson (storageJson) import GHC.Show (Show(..)) import Test.Hspec@@ -14,49 +12,7 @@ spec :: Spec spec =- describe "e2h" $- parallel $ do- it "pretty-prints simpleDaoJson" $ do- let prettySol =- (show <$> renderPretty 1.0 80) . (pretty :: [SolNode] -> Doc) <$>- decodeSoleNodes (toS simpleDaoJson)- -- putStrLn $ fromRight "" prettySol- prettySol `shouldBe`- Right- ("[//--SourceUnit--\n" <>- "contract SimpleDAO {mapping(address => uint256) credit\n" <>- " ;fun donate (address to)(){(credit[to]+=msg.value)}\n" <>- " ;fun withdraw (uint256 amount)\n" <>- " ()\n" <>- " {if((credit[msg.sender]>=amount)\n" <>- " ,{bool res = msg.sender.call.value(amount)()\n" <>- " ;(credit[msg.sender]-=amount)})}\n" <>- " ;fun queryCredit (address to)(uint256){return(credit[to])}}\n" <>- "contract Mallory {contract SimpleDAO dao\n" <>- " ;address owner\n" <>- " ;fun Mallory (contract SimpleDAO addr)\n" <>- " ()\n" <>- " {(owner=msg.sender);(dao=addr)}\n" <>- " ;fun getJackpot ()(){bool res = owner.send(this.balance)}\n" <>- " ;fun ()(){(dao.withdraw(dao.queryCredit(this)))}}\n" <>- "contract Mallory2 {contract SimpleDAO dao\n" <>- " ;address owner\n" <>- " ;bool performAttack\n" <>- " ;fun Mallory2 (contract SimpleDAO addr)\n" <>- " ()\n" <>- " {(owner=msg.sender);(dao=addr)}\n" <>- " ;fun attack ()\n" <>- " ()\n" <>- " {(dao.donate.value(1)(this));(dao.withdraw(1))}\n" <>- " ;fun getJackpot ()\n" <>- " ()\n" <>- " {(dao.withdraw(dao.balance))\n" <>- " ;bool res = owner.send(this.balance)\n" <>- " ;(performAttack=true)}\n" <>- " ;fun ()\n" <>- " ()\n" <>- " {if(performAttack\n" <>- " ,{(performAttack=false);(dao.withdraw(1))})}}]")+ describe "e2h" $ do it "pretty-prints storageJson" $ do let prettySol = (show <$> renderPretty 1.0 80) . (pretty :: [SolNode] -> Doc) <$>
+ test/Ethereum/Analyzer/TestData/Asts.hs view
@@ -0,0 +1,36 @@+module Ethereum.Analyzer.TestData.Asts+ ( solNodesOf+ , testFilepaths+ ) where++import Protolude++import Ethereum.Analyzer.Solidity++solNodesOf :: Text -> IO [SolNode]+solNodesOf path = do+ content <- readFile (toS path)+ case decodeSoleNodes $ toS content of+ Left err -> throwIO $ AssertionFailed $ toS err+ Right nodes -> return nodes++testFilepaths :: [Text]+testFilepaths =+ [ "../examples/co2.unica.it/ethereum/GaslessSend_42.ast.json"+ , "../examples/co2.unica.it/ethereum/SendTest.ast.json"+ , "../examples/co2.unica.it/ethereum/OddsAndEvens_0.4.2.ast.json"+ , "../examples/co2.unica.it/ethereum/SetProvider_0.4.2.ast.json"+ , "../examples/co2.unica.it/ethereum/SimpleDAO_0.4.2.ast.json"+ , "../examples/co2.unica.it/ethereum/KotET_0.4.2.ast.json"+ , "../examples/co2.unica.it/ethereum/Set_0.4.2.ast.json"+ , "../examples/co2.unica.it/ethereum/Bob_0.4.2.ast.json"+ , "../examples/slockit/DAO.ast.json"+ , "../examples/analysis-benchmark/selfdestruct-over-suicide.ast.json"+ , "../examples/solidity.readthedocs.io/solidity-by-example/voting.ast.json"+ , "../examples/solidity.readthedocs.io/control-structures/loops.ast.json"+ , "../examples/solidity.readthedocs.io/control-structures/tuple-min.ast.json"+ , "../examples/solidity.readthedocs.io/control-structures/tuple.ast.json"+ , "../examples/solidity.readthedocs.io/control-structures/tuple-min-0.4.17.ast.json"+ , "../examples/solidity.readthedocs.io/introduction-to-smart-contracts/storage.ast.json"+ , "../examples/solidity.readthedocs.io/introduction-to-smart-contracts/subcurrency.ast.json"+ ]
test/Ethereum/Analyzer/TestData/Basic.hs view
@@ -6,7 +6,7 @@ , voteHexstring ) where -import Ethereum.Analyzer.Disasm+import Ethereum.Analyzer.EVM hexstring1 :: EvmHexString hexstring1 =
− test/Ethereum/Analyzer/TestData/DaoJson.hs
@@ -1,1790 +0,0 @@-module Ethereum.Analyzer.TestData.DaoJson- ( simpleDaoJson- ) where--import Protolude hiding (show)--simpleDaoJson :: Text-simpleDaoJson =- "{" <> " \"contracts\": {" <> " \"SimpleDAO_0.4.2.sol:Mallory\": {" <>- " }," <>- " \"SimpleDAO_0.4.2.sol:Mallory2\": {" <>- " }," <>- " \"SimpleDAO_0.4.2.sol:SimpleDAO\": {" <>- " }" <>- " }," <>- " \"sourceList\": [" <>- " \"SimpleDAO_0.4.2.sol\"" <>- " ]," <>- " \"sources\": {" <>- " \"SimpleDAO_0.4.2.sol\": {" <>- " \"AST\": {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"literals\": [" <>- " \"solidity\"," <>- " \"^\"," <>- " \"0.4\"," <>- " \".2\"" <>- " ]" <>- " }," <>- " \"id\": 1," <>- " \"name\": \"PragmaDirective\"," <>- " \"src\": \"0:23:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"fullyImplemented\": true," <>- " \"isLibrary\": false," <>- " \"linearizedBaseContracts\": [" <>- " 62" <>- " ]," <>- " \"name\": \"SimpleDAO\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"credit\"," <>- " \"storageLocation\": \"default\"," <>- " \"type\": \"mapping(address => uint256)\"," <>- " \"visibility\": \"public\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"address\"" <>- " }," <>- " \"id\": 2," <>- " \"name\": \"ElementaryTypeName\"," <>- " \"src\": \"60:7:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"uint\"" <>- " }," <>- " \"id\": 3," <>- " \"name\": \"ElementaryTypeName\"," <>- " \"src\": \"71:4:0\"" <>- " }" <>- " ]," <>- " \"id\": 4," <>- " \"name\": \"Mapping\"," <>- " \"src\": \"51:25:0\"" <>- " }" <>- " ]," <>- " \"id\": 5," <>- " \"name\": \"VariableDeclaration\"," <>- " \"src\": \"51:39:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"donate\"," <>- " \"payable\": true," <>- " \"visibility\": \"public\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"to\"," <>- " \"storageLocation\": \"default\"," <>- " \"type\": \"address\"," <>- " \"visibility\": \"internal\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"address\"" <>- " }," <>- " \"id\": 6," <>- " \"name\": \"ElementaryTypeName\"," <>- " \"src\": \"115:7:0\"" <>- " }" <>- " ]," <>- " \"id\": 7," <>- " \"name\": \"VariableDeclaration\"," <>- " \"src\": \"115:10:0\"" <>- " }" <>- " ]," <>- " \"id\": 8," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"114:12:0\"" <>- " }," <>- " {" <>- " \"children\": []," <>- " \"id\": 9," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"135:0:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"operator\": \"+=\"," <>- " \"type\": \"uint256\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"uint256\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"mapping(address => uint256)\"," <>- " \"value\": \"credit\"" <>- " }," <>- " \"id\": 10," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"141:6:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"address\"," <>- " \"value\": \"to\"" <>- " }," <>- " \"id\": 11," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"148:2:0\"" <>- " }" <>- " ]," <>- " \"id\": 12," <>- " \"name\": \"IndexAccess\"," <>- " \"src\": \"141:10:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"value\"," <>- " \"type\": \"uint256\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"msg\"," <>- " \"value\": \"msg\"" <>- " }," <>- " \"id\": 13," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"155:3:0\"" <>- " }" <>- " ]," <>- " \"id\": 14," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"155:9:0\"" <>- " }" <>- " ]," <>- " \"id\": 15," <>- " \"name\": \"Assignment\"," <>- " \"src\": \"141:23:0\"" <>- " }" <>- " ]," <>- " \"id\": 16," <>- " \"name\": \"ExpressionStatement\"," <>- " \"src\": \"141:23:0\"" <>- " }" <>- " ]," <>- " \"id\": 17," <>- " \"name\": \"Block\"," <>- " \"src\": \"135:34:0\"" <>- " }" <>- " ]," <>- " \"id\": 18," <>- " \"name\": \"FunctionDefinition\"," <>- " \"src\": \"99:70:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"withdraw\"," <>- " \"payable\": false," <>- " \"visibility\": \"public\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"amount\"," <>- " \"storageLocation\": \"default\"," <>- " \"type\": \"uint256\"," <>- " \"visibility\": \"internal\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"uint\"" <>- " }," <>- " \"id\": 19," <>- " \"name\": \"ElementaryTypeName\"," <>- " \"src\": \"195:4:0\"" <>- " }" <>- " ]," <>- " \"id\": 20," <>- " \"name\": \"VariableDeclaration\"," <>- " \"src\": \"195:11:0\"" <>- " }" <>- " ]," <>- " \"id\": 21," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"194:13:0\"" <>- " }," <>- " {" <>- " \"children\": []," <>- " \"id\": 22," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"208:0:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"operator\": \">=\"," <>- " \"type\": \"bool\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"uint256\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"mapping(address => uint256)\"," <>- " \"value\": \"credit\"" <>- " }," <>- " \"id\": 23," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"218:6:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"sender\"," <>- " \"type\": \"address\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"msg\"," <>- " \"value\": \"msg\"" <>- " }," <>- " \"id\": 24," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"225:3:0\"" <>- " }" <>- " ]," <>- " \"id\": 25," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"225:10:0\"" <>- " }" <>- " ]," <>- " \"id\": 26," <>- " \"name\": \"IndexAccess\"," <>- " \"src\": \"218:18:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"uint256\"," <>- " \"value\": \"amount\"" <>- " }," <>- " \"id\": 27," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"239:6:0\"" <>- " }" <>- " ]," <>- " \"id\": 28," <>- " \"name\": \"BinaryOperation\"," <>- " \"src\": \"218:27:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"res\"," <>- " \"storageLocation\": \"default\"," <>- " \"type\": \"bool\"," <>- " \"visibility\": \"internal\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"bool\"" <>- " }," <>- " \"id\": 29," <>- " \"name\": \"ElementaryTypeName\"," <>- " \"src\": \"255:4:0\"" <>- " }" <>- " ]," <>- " \"id\": 30," <>- " \"name\": \"VariableDeclaration\"," <>- " \"src\": \"255:8:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"bool\"," <>- " \"type_conversion\": false" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"function () payable returns (bool)\"," <>- " \"type_conversion\": false" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"value\"," <>- " \"type\": \"function (uint256) returns (function () payable returns (bool))\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"call\"," <>- " \"type\": \"function () payable returns (bool)\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"sender\"," <>- " \"type\": \"address\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"msg\"," <>- " \"value\": \"msg\"" <>- " }," <>- " \"id\": 31," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"266:3:0\"" <>- " }" <>- " ]," <>- " \"id\": 32," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"266:10:0\"" <>- " }" <>- " ]," <>- " \"id\": 33," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"266:15:0\"" <>- " }" <>- " ]," <>- " \"id\": 34," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"266:21:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"uint256\"," <>- " \"value\": \"amount\"" <>- " }," <>- " \"id\": 35," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"288:6:0\"" <>- " }" <>- " ]," <>- " \"id\": 36," <>- " \"name\": \"FunctionCall\"," <>- " \"src\": \"266:29:0\"" <>- " }" <>- " ]," <>- " \"id\": 37," <>- " \"name\": \"FunctionCall\"," <>- " \"src\": \"266:31:0\"" <>- " }" <>- " ]," <>- " \"id\": 38," <>- " \"name\": \"VariableDeclarationStatement\"," <>- " \"src\": \"255:42:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"operator\": \"-=\"," <>- " \"type\": \"uint256\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"uint256\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"mapping(address => uint256)\"," <>- " \"value\": \"credit\"" <>- " }," <>- " \"id\": 39," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"305:6:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"sender\"," <>- " \"type\": \"address\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"msg\"," <>- " \"value\": \"msg\"" <>- " }," <>- " \"id\": 40," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"312:3:0\"" <>- " }" <>- " ]," <>- " \"id\": 41," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"312:10:0\"" <>- " }" <>- " ]," <>- " \"id\": 42," <>- " \"name\": \"IndexAccess\"," <>- " \"src\": \"305:18:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"uint256\"," <>- " \"value\": \"amount\"" <>- " }," <>- " \"id\": 43," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"325:6:0\"" <>- " }" <>- " ]," <>- " \"id\": 44," <>- " \"name\": \"Assignment\"," <>- " \"src\": \"305:26:0\"" <>- " }" <>- " ]," <>- " \"id\": 45," <>- " \"name\": \"ExpressionStatement\"," <>- " \"src\": \"305:26:0\"" <>- " }" <>- " ]," <>- " \"id\": 46," <>- " \"name\": \"Block\"," <>- " \"src\": \"247:91:0\"" <>- " }" <>- " ]," <>- " \"id\": 47," <>- " \"name\": \"IfStatement\"," <>- " \"src\": \"214:124:0\"" <>- " }" <>- " ]," <>- " \"id\": 48," <>- " \"name\": \"Block\"," <>- " \"src\": \"208:134:0\"" <>- " }" <>- " ]," <>- " \"id\": 49," <>- " \"name\": \"FunctionDefinition\"," <>- " \"src\": \"177:165:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"queryCredit\"," <>- " \"payable\": false," <>- " \"visibility\": \"public\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"to\"," <>- " \"storageLocation\": \"default\"," <>- " \"type\": \"address\"," <>- " \"visibility\": \"internal\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"address\"" <>- " }," <>- " \"id\": 50," <>- " \"name\": \"ElementaryTypeName\"," <>- " \"src\": \"369:7:0\"" <>- " }" <>- " ]," <>- " \"id\": 51," <>- " \"name\": \"VariableDeclaration\"," <>- " \"src\": \"369:10:0\"" <>- " }" <>- " ]," <>- " \"id\": 52," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"368:12:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"\"," <>- " \"storageLocation\": \"default\"," <>- " \"type\": \"uint256\"," <>- " \"visibility\": \"internal\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"uint\"" <>- " }," <>- " \"id\": 53," <>- " \"name\": \"ElementaryTypeName\"," <>- " \"src\": \"390:4:0\"" <>- " }" <>- " ]," <>- " \"id\": 54," <>- " \"name\": \"VariableDeclaration\"," <>- " \"src\": \"390:4:0\"" <>- " }" <>- " ]," <>- " \"id\": 55," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"389:6:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"uint256\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"mapping(address => uint256)\"," <>- " \"value\": \"credit\"" <>- " }," <>- " \"id\": 56," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"408:6:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"address\"," <>- " \"value\": \"to\"" <>- " }," <>- " \"id\": 57," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"415:2:0\"" <>- " }" <>- " ]," <>- " \"id\": 58," <>- " \"name\": \"IndexAccess\"," <>- " \"src\": \"408:10:0\"" <>- " }" <>- " ]," <>- " \"id\": 59," <>- " \"name\": \"Return\"," <>- " \"src\": \"401:17:0\"" <>- " }" <>- " ]," <>- " \"id\": 60," <>- " \"name\": \"Block\"," <>- " \"src\": \"395:28:0\"" <>- " }" <>- " ]," <>- " \"id\": 61," <>- " \"name\": \"FunctionDefinition\"," <>- " \"src\": \"348:75:0\"" <>- " }" <>- " ]," <>- " \"id\": 62," <>- " \"name\": \"ContractDefinition\"," <>- " \"src\": \"25:400:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"fullyImplemented\": true," <>- " \"isLibrary\": false," <>- " \"linearizedBaseContracts\": [" <>- " 107" <>- " ]," <>- " \"name\": \"Mallory\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"dao\"," <>- " \"storageLocation\": \"default\"," <>- " \"type\": \"contract SimpleDAO\"," <>- " \"visibility\": \"public\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"SimpleDAO\"" <>- " }," <>- " \"id\": 63," <>- " \"name\": \"UserDefinedTypeName\"," <>- " \"src\": \"449:9:0\"" <>- " }" <>- " ]," <>- " \"id\": 64," <>- " \"name\": \"VariableDeclaration\"," <>- " \"src\": \"449:20:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"owner\"," <>- " \"storageLocation\": \"default\"," <>- " \"type\": \"address\"," <>- " \"visibility\": \"internal\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"address\"" <>- " }," <>- " \"id\": 65," <>- " \"name\": \"ElementaryTypeName\"," <>- " \"src\": \"473:7:0\"" <>- " }" <>- " ]," <>- " \"id\": 66," <>- " \"name\": \"VariableDeclaration\"," <>- " \"src\": \"473:13:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"Mallory\"," <>- " \"payable\": false," <>- " \"visibility\": \"public\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"addr\"," <>- " \"storageLocation\": \"default\"," <>- " \"type\": \"contract SimpleDAO\"," <>- " \"visibility\": \"internal\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"SimpleDAO\"" <>- " }," <>- " \"id\": 67," <>- " \"name\": \"UserDefinedTypeName\"," <>- " \"src\": \"508:9:0\"" <>- " }" <>- " ]," <>- " \"id\": 68," <>- " \"name\": \"VariableDeclaration\"," <>- " \"src\": \"508:14:0\"" <>- " }" <>- " ]," <>- " \"id\": 69," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"507:16:0\"" <>- " }," <>- " {" <>- " \"children\": []," <>- " \"id\": 70," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"523:0:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"operator\": \"=\"," <>- " \"type\": \"address\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"address\"," <>- " \"value\": \"owner\"" <>- " }," <>- " \"id\": 71," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"530:5:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"sender\"," <>- " \"type\": \"address\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"msg\"," <>- " \"value\": \"msg\"" <>- " }," <>- " \"id\": 72," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"538:3:0\"" <>- " }" <>- " ]," <>- " \"id\": 73," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"538:10:0\"" <>- " }" <>- " ]," <>- " \"id\": 74," <>- " \"name\": \"Assignment\"," <>- " \"src\": \"530:18:0\"" <>- " }" <>- " ]," <>- " \"id\": 75," <>- " \"name\": \"ExpressionStatement\"," <>- " \"src\": \"530:18:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"operator\": \"=\"," <>- " \"type\": \"contract SimpleDAO\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"contract SimpleDAO\"," <>- " \"value\": \"dao\"" <>- " }," <>- " \"id\": 76," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"554:3:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"contract SimpleDAO\"," <>- " \"value\": \"addr\"" <>- " }," <>- " \"id\": 77," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"560:4:0\"" <>- " }" <>- " ]," <>- " \"id\": 78," <>- " \"name\": \"Assignment\"," <>- " \"src\": \"554:10:0\"" <>- " }" <>- " ]," <>- " \"id\": 79," <>- " \"name\": \"ExpressionStatement\"," <>- " \"src\": \"554:10:0\"" <>- " }" <>- " ]," <>- " \"id\": 80," <>- " \"name\": \"Block\"," <>- " \"src\": \"523:46:0\"" <>- " }" <>- " ]," <>- " \"id\": 81," <>- " \"name\": \"FunctionDefinition\"," <>- " \"src\": \"491:78:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"getJackpot\"," <>- " \"payable\": false," <>- " \"visibility\": \"public\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"children\": []," <>- " \"id\": 82," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"594:2:0\"" <>- " }," <>- " {" <>- " \"children\": []," <>- " \"id\": 83," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"597:0:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"res\"," <>- " \"storageLocation\": \"default\"," <>- " \"type\": \"bool\"," <>- " \"visibility\": \"internal\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"bool\"" <>- " }," <>- " \"id\": 84," <>- " \"name\": \"ElementaryTypeName\"," <>- " \"src\": \"604:4:0\"" <>- " }" <>- " ]," <>- " \"id\": 85," <>- " \"name\": \"VariableDeclaration\"," <>- " \"src\": \"604:8:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"bool\"," <>- " \"type_conversion\": false" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"send\"," <>- " \"type\": \"function (uint256) returns (bool)\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"address\"," <>- " \"value\": \"owner\"" <>- " }," <>- " \"id\": 86," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"615:5:0\"" <>- " }" <>- " ]," <>- " \"id\": 87," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"615:10:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"balance\"," <>- " \"type\": \"uint256\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"contract Mallory\"," <>- " \"value\": \"this\"" <>- " }," <>- " \"id\": 88," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"626:4:0\"" <>- " }" <>- " ]," <>- " \"id\": 89," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"626:12:0\"" <>- " }" <>- " ]," <>- " \"id\": 90," <>- " \"name\": \"FunctionCall\"," <>- " \"src\": \"615:24:0\"" <>- " }" <>- " ]," <>- " \"id\": 91," <>- " \"name\": \"VariableDeclarationStatement\"," <>- " \"src\": \"604:35:0\"" <>- " }" <>- " ]," <>- " \"id\": 92," <>- " \"name\": \"Block\"," <>- " \"src\": \"597:48:0\"" <>- " }" <>- " ]," <>- " \"id\": 93," <>- " \"name\": \"FunctionDefinition\"," <>- " \"src\": \"575:70:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"\"," <>- " \"payable\": true," <>- " \"visibility\": \"public\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"children\": []," <>- " \"id\": 94," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"657:2:0\"" <>- " }," <>- " {" <>- " \"children\": []," <>- " \"id\": 95," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"668:0:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"tuple()\"," <>- " \"type_conversion\": false" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"withdraw\"," <>- " \"type\": \"function (uint256) external\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"contract SimpleDAO\"," <>- " \"value\": \"dao\"" <>- " }," <>- " \"id\": 96," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"675:3:0\"" <>- " }" <>- " ]," <>- " \"id\": 98," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"675:12:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"uint256\"," <>- " \"type_conversion\": false" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"queryCredit\"," <>- " \"type\": \"function (address) external returns (uint256)\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"contract SimpleDAO\"," <>- " \"value\": \"dao\"" <>- " }," <>- " \"id\": 99," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"688:3:0\"" <>- " }" <>- " ]," <>- " \"id\": 100," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"688:15:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"contract Mallory\"," <>- " \"value\": \"this\"" <>- " }," <>- " \"id\": 101," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"704:4:0\"" <>- " }" <>- " ]," <>- " \"id\": 102," <>- " \"name\": \"FunctionCall\"," <>- " \"src\": \"688:21:0\"" <>- " }" <>- " ]," <>- " \"id\": 103," <>- " \"name\": \"FunctionCall\"," <>- " \"src\": \"675:35:0\"" <>- " }" <>- " ]," <>- " \"id\": 104," <>- " \"name\": \"ExpressionStatement\"," <>- " \"src\": \"675:35:0\"" <>- " }" <>- " ]," <>- " \"id\": 105," <>- " \"name\": \"Block\"," <>- " \"src\": \"668:48:0\"" <>- " }" <>- " ]," <>- " \"id\": 106," <>- " \"name\": \"FunctionDefinition\"," <>- " \"src\": \"649:67:0\"" <>- " }" <>- " ]," <>- " \"id\": 107," <>- " \"name\": \"ContractDefinition\"," <>- " \"src\": \"428:290:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"fullyImplemented\": true," <>- " \"isLibrary\": false," <>- " \"linearizedBaseContracts\": [" <>- " 190" <>- " ]," <>- " \"name\": \"Mallory2\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"dao\"," <>- " \"storageLocation\": \"default\"," <>- " \"type\": \"contract SimpleDAO\"," <>- " \"visibility\": \"public\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"SimpleDAO\"" <>- " }," <>- " \"id\": 108," <>- " \"name\": \"UserDefinedTypeName\"," <>- " \"src\": \"742:9:0\"" <>- " }" <>- " ]," <>- " \"id\": 109," <>- " \"name\": \"VariableDeclaration\"," <>- " \"src\": \"742:20:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"owner\"," <>- " \"storageLocation\": \"default\"," <>- " \"type\": \"address\"," <>- " \"visibility\": \"internal\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"address\"" <>- " }," <>- " \"id\": 110," <>- " \"name\": \"ElementaryTypeName\"," <>- " \"src\": \"766:7:0\"" <>- " }" <>- " ]," <>- " \"id\": 111," <>- " \"name\": \"VariableDeclaration\"," <>- " \"src\": \"766:13:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"performAttack\"," <>- " \"storageLocation\": \"default\"," <>- " \"type\": \"bool\"," <>- " \"visibility\": \"public\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"bool\"" <>- " }," <>- " \"id\": 112," <>- " \"name\": \"ElementaryTypeName\"," <>- " \"src\": \"784:4:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"hexvalue\": \"74727565\"," <>- " \"subdenomination\": null," <>- " \"token\": \"true\"," <>- " \"type\": \"bool\"," <>- " \"value\": \"true\"" <>- " }," <>- " \"id\": 113," <>- " \"name\": \"Literal\"," <>- " \"src\": \"812:4:0\"" <>- " }" <>- " ]," <>- " \"id\": 114," <>- " \"name\": \"VariableDeclaration\"," <>- " \"src\": \"784:32:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"Mallory2\"," <>- " \"payable\": false," <>- " \"visibility\": \"public\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"addr\"," <>- " \"storageLocation\": \"default\"," <>- " \"type\": \"contract SimpleDAO\"," <>- " \"visibility\": \"internal\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"SimpleDAO\"" <>- " }," <>- " \"id\": 115," <>- " \"name\": \"UserDefinedTypeName\"," <>- " \"src\": \"839:9:0\"" <>- " }" <>- " ]," <>- " \"id\": 116," <>- " \"name\": \"VariableDeclaration\"," <>- " \"src\": \"839:14:0\"" <>- " }" <>- " ]," <>- " \"id\": 117," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"838:16:0\"" <>- " }," <>- " {" <>- " \"children\": []," <>- " \"id\": 118," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"854:0:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"operator\": \"=\"," <>- " \"type\": \"address\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"address\"," <>- " \"value\": \"owner\"" <>- " }," <>- " \"id\": 119," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"860:5:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"sender\"," <>- " \"type\": \"address\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"msg\"," <>- " \"value\": \"msg\"" <>- " }," <>- " \"id\": 120," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"868:3:0\"" <>- " }" <>- " ]," <>- " \"id\": 121," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"868:10:0\"" <>- " }" <>- " ]," <>- " \"id\": 122," <>- " \"name\": \"Assignment\"," <>- " \"src\": \"860:18:0\"" <>- " }" <>- " ]," <>- " \"id\": 123," <>- " \"name\": \"ExpressionStatement\"," <>- " \"src\": \"860:18:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"operator\": \"=\"," <>- " \"type\": \"contract SimpleDAO\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"contract SimpleDAO\"," <>- " \"value\": \"dao\"" <>- " }," <>- " \"id\": 124," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"884:3:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"contract SimpleDAO\"," <>- " \"value\": \"addr\"" <>- " }," <>- " \"id\": 125," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"890:4:0\"" <>- " }" <>- " ]," <>- " \"id\": 126," <>- " \"name\": \"Assignment\"," <>- " \"src\": \"884:10:0\"" <>- " }" <>- " ]," <>- " \"id\": 127," <>- " \"name\": \"ExpressionStatement\"," <>- " \"src\": \"884:10:0\"" <>- " }" <>- " ]," <>- " \"id\": 128," <>- " \"name\": \"Block\"," <>- " \"src\": \"854:45:0\"" <>- " }" <>- " ]," <>- " \"id\": 129," <>- " \"name\": \"FunctionDefinition\"," <>- " \"src\": \"821:78:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"attack\"," <>- " \"payable\": true," <>- " \"visibility\": \"public\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"children\": []," <>- " \"id\": 130," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"922:2:0\"" <>- " }," <>- " {" <>- " \"children\": []," <>- " \"id\": 131," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"932:0:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"tuple()\"," <>- " \"type_conversion\": false" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"function (address) payable external\"," <>- " \"type_conversion\": false" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"value\"," <>- " \"type\": \"function (uint256) returns (function (address) payable external)\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"donate\"," <>- " \"type\": \"function (address) payable external\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"contract SimpleDAO\"," <>- " \"value\": \"dao\"" <>- " }," <>- " \"id\": 132," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"938:3:0\"" <>- " }" <>- " ]," <>- " \"id\": 135," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"938:10:0\"" <>- " }" <>- " ]," <>- " \"id\": 136," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"938:16:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"hexvalue\": \"31\"," <>- " \"subdenomination\": null," <>- " \"token\": null," <>- " \"type\": \"int_const 1\"," <>- " \"value\": \"1\"" <>- " }," <>- " \"id\": 137," <>- " \"name\": \"Literal\"," <>- " \"src\": \"955:1:0\"" <>- " }" <>- " ]," <>- " \"id\": 138," <>- " \"name\": \"FunctionCall\"," <>- " \"src\": \"938:19:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"contract Mallory2\"," <>- " \"value\": \"this\"" <>- " }," <>- " \"id\": 139," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"958:4:0\"" <>- " }" <>- " ]," <>- " \"id\": 140," <>- " \"name\": \"FunctionCall\"," <>- " \"src\": \"938:25:0\"" <>- " }" <>- " ]," <>- " \"id\": 141," <>- " \"name\": \"ExpressionStatement\"," <>- " \"src\": \"938:25:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"tuple()\"," <>- " \"type_conversion\": false" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"withdraw\"," <>- " \"type\": \"function (uint256) external\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"contract SimpleDAO\"," <>- " \"value\": \"dao\"" <>- " }," <>- " \"id\": 142," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"969:3:0\"" <>- " }" <>- " ]," <>- " \"id\": 144," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"969:12:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"hexvalue\": \"31\"," <>- " \"subdenomination\": null," <>- " \"token\": null," <>- " \"type\": \"int_const 1\"," <>- " \"value\": \"1\"" <>- " }," <>- " \"id\": 145," <>- " \"name\": \"Literal\"," <>- " \"src\": \"982:1:0\"" <>- " }" <>- " ]," <>- " \"id\": 146," <>- " \"name\": \"FunctionCall\"," <>- " \"src\": \"969:15:0\"" <>- " }" <>- " ]," <>- " \"id\": 147," <>- " \"name\": \"ExpressionStatement\"," <>- " \"src\": \"969:15:0\"" <>- " }" <>- " ]," <>- " \"id\": 148," <>- " \"name\": \"Block\"," <>- " \"src\": \"932:57:0\"" <>- " }" <>- " ]," <>- " \"id\": 149," <>- " \"name\": \"FunctionDefinition\"," <>- " \"src\": \"907:82:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"getJackpot\"," <>- " \"payable\": false," <>- " \"visibility\": \"public\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"children\": []," <>- " \"id\": 150," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"1012:2:0\"" <>- " }," <>- " {" <>- " \"children\": []," <>- " \"id\": 151," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"1014:0:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"tuple()\"," <>- " \"type_conversion\": false" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"withdraw\"," <>- " \"type\": \"function (uint256) external\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"contract SimpleDAO\"," <>- " \"value\": \"dao\"" <>- " }," <>- " \"id\": 152," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"1020:3:0\"" <>- " }" <>- " ]," <>- " \"id\": 154," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"1020:12:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"balance\"," <>- " \"type\": \"uint256\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"contract SimpleDAO\"," <>- " \"value\": \"dao\"" <>- " }," <>- " \"id\": 155," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"1033:3:0\"" <>- " }" <>- " ]," <>- " \"id\": 156," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"1033:11:0\"" <>- " }" <>- " ]," <>- " \"id\": 157," <>- " \"name\": \"FunctionCall\"," <>- " \"src\": \"1020:25:0\"" <>- " }" <>- " ]," <>- " \"id\": 158," <>- " \"name\": \"ExpressionStatement\"," <>- " \"src\": \"1020:25:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"res\"," <>- " \"storageLocation\": \"default\"," <>- " \"type\": \"bool\"," <>- " \"visibility\": \"internal\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"name\": \"bool\"" <>- " }," <>- " \"id\": 159," <>- " \"name\": \"ElementaryTypeName\"," <>- " \"src\": \"1051:4:0\"" <>- " }" <>- " ]," <>- " \"id\": 160," <>- " \"name\": \"VariableDeclaration\"," <>- " \"src\": \"1051:8:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"bool\"," <>- " \"type_conversion\": false" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"send\"," <>- " \"type\": \"function (uint256) returns (bool)\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"address\"," <>- " \"value\": \"owner\"" <>- " }," <>- " \"id\": 161," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"1062:5:0\"" <>- " }" <>- " ]," <>- " \"id\": 162," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"1062:10:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"balance\"," <>- " \"type\": \"uint256\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"contract Mallory2\"," <>- " \"value\": \"this\"" <>- " }," <>- " \"id\": 163," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"1073:4:0\"" <>- " }" <>- " ]," <>- " \"id\": 164," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"1073:12:0\"" <>- " }" <>- " ]," <>- " \"id\": 165," <>- " \"name\": \"FunctionCall\"," <>- " \"src\": \"1062:24:0\"" <>- " }" <>- " ]," <>- " \"id\": 166," <>- " \"name\": \"VariableDeclarationStatement\"," <>- " \"src\": \"1051:35:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"operator\": \"=\"," <>- " \"type\": \"bool\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"bool\"," <>- " \"value\": \"performAttack\"" <>- " }," <>- " \"id\": 167," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"1092:13:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"hexvalue\": \"74727565\"," <>- " \"subdenomination\": null," <>- " \"token\": \"true\"," <>- " \"type\": \"bool\"," <>- " \"value\": \"true\"" <>- " }," <>- " \"id\": 168," <>- " \"name\": \"Literal\"," <>- " \"src\": \"1108:4:0\"" <>- " }" <>- " ]," <>- " \"id\": 169," <>- " \"name\": \"Assignment\"," <>- " \"src\": \"1092:20:0\"" <>- " }" <>- " ]," <>- " \"id\": 170," <>- " \"name\": \"ExpressionStatement\"," <>- " \"src\": \"1092:20:0\"" <>- " }" <>- " ]," <>- " \"id\": 171," <>- " \"name\": \"Block\"," <>- " \"src\": \"1014:103:0\"" <>- " }" <>- " ]," <>- " \"id\": 172," <>- " \"name\": \"FunctionDefinition\"," <>- " \"src\": \"993:124:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"constant\": false," <>- " \"name\": \"\"," <>- " \"payable\": true," <>- " \"visibility\": \"public\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"children\": []," <>- " \"id\": 173," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"1129:2:0\"" <>- " }," <>- " {" <>- " \"children\": []," <>- " \"id\": 174," <>- " \"name\": \"ParameterList\"," <>- " \"src\": \"1140:0:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"bool\"," <>- " \"value\": \"performAttack\"" <>- " }," <>- " \"id\": 175," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"1150:13:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"operator\": \"=\"," <>- " \"type\": \"bool\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"bool\"," <>- " \"value\": \"performAttack\"" <>- " }," <>- " \"id\": 176," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"1174:13:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"hexvalue\": \"66616c7365\"," <>- " \"subdenomination\": null," <>- " \"token\": \"false\"," <>- " \"type\": \"bool\"," <>- " \"value\": \"false\"" <>- " }," <>- " \"id\": 177," <>- " \"name\": \"Literal\"," <>- " \"src\": \"1190:5:0\"" <>- " }" <>- " ]," <>- " \"id\": 178," <>- " \"name\": \"Assignment\"," <>- " \"src\": \"1174:21:0\"" <>- " }" <>- " ]," <>- " \"id\": 179," <>- " \"name\": \"ExpressionStatement\"," <>- " \"src\": \"1174:21:0\"" <>- " }," <>- " {" <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"tuple()\"," <>- " \"type_conversion\": false" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"member_name\": \"withdraw\"," <>- " \"type\": \"function (uint256) external\"" <>- " }," <>- " \"children\": [" <>- " {" <>- " \"attributes\": {" <>- " \"type\": \"contract SimpleDAO\"," <>- " \"value\": \"dao\"" <>- " }," <>- " \"id\": 180," <>- " \"name\": \"Identifier\"," <>- " \"src\": \"1204:3:0\"" <>- " }" <>- " ]," <>- " \"id\": 182," <>- " \"name\": \"MemberAccess\"," <>- " \"src\": \"1204:12:0\"" <>- " }," <>- " {" <>- " \"attributes\": {" <>- " \"hexvalue\": \"31\"," <>- " \"subdenomination\": null," <>- " \"token\": null," <>- " \"type\": \"int_const 1\"," <>- " \"value\": \"1\"" <>- " }," <>- " \"id\": 183," <>- " \"name\": \"Literal\"," <>- " \"src\": \"1217:1:0\"" <>- " }" <>- " ]," <>- " \"id\": 184," <>- " \"name\": \"FunctionCall\"," <>- " \"src\": \"1204:15:0\"" <>- " }" <>- " ]," <>- " \"id\": 185," <>- " \"name\": \"ExpressionStatement\"," <>- " \"src\": \"1204:15:0\"" <>- " }" <>- " ]," <>- " \"id\": 186," <>- " \"name\": \"Block\"," <>- " \"src\": \"1165:61:0\"" <>- " }" <>- " ]," <>- " \"id\": 187," <>- " \"name\": \"IfStatement\"," <>- " \"src\": \"1146:80:0\"" <>- " }" <>- " ]," <>- " \"id\": 188," <>- " \"name\": \"Block\"," <>- " \"src\": \"1140:90:0\"" <>- " }" <>- " ]," <>- " \"id\": 189," <>- " \"name\": \"FunctionDefinition\"," <>- " \"src\": \"1121:109:0\"" <>- " }" <>- " ]," <>- " \"id\": 190," <>- " \"name\": \"ContractDefinition\"," <>- " \"src\": \"720:512:0\"" <>- " }" <>- " ]," <>- " \"name\": \"SourceUnit\"" <>- " }" <>- " }" <>- " }," <>- " \"version\": \"0.4.11+commit.68ef5810.Linux.g++\"" <>- "}"
− test/Ethereum/Analyzer/UtilSpec.hs
@@ -1,399 +0,0 @@-{-# LANGUAGE OverloadedStrings, NoImplicitPrelude #-}--module Ethereum.Analyzer.UtilSpec- ( spec- ) where--import Protolude hiding (show)--import Data.Text-import Ethereum.Analyzer-import Ethereum.Analyzer.CfgAugmentPass-import Ethereum.Analyzer.TestData.Basic-import Ethereum.Analyzer.Util-import Test.Hspec--spec :: Spec-spec =- describe "toDotText" $ do- it "shows HplBody's dot graph" $ do- let disasmd = disasm hexstring2- (unpack . unWordLabelMapM)- (toDotText . bodyOf . ctorOf <$> evmOps2HplContract disasmd) `shouldBe`- toS expectedHexString2RawDot- it "shows HplBody after CfgAugmentPass" $ do- let disasmd@((_, _):_) = disasm hexstring2- result =- (unpack . unWordLabelMapM) $ do- contract <- evmOps2HplContract disasmd- toDotText . bodyOf . ctorOf <$> doCfgAugmentPass contract- result `shouldBe` toS expectedHexString2AugDot--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 -> [L2]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 2 [label=\"CO: L2\\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 -> [L3]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 3 [label=\"CO: L3\\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 -> [L4]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 4 [label=\"CO: L4\\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 -> [L5]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 5 [label=\"CO: L5\\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 -> [L6]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 6 [label=\"CO: L6\\n" <>- "OO: 108: JUMPDEST\\n" <>- "OC: 109: JUMP -> []\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 7 [label=\"CO: L7\\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 -> [L8]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 8 [label=\"CO: L8\\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" <>- "\"\n" <>- " ,shape=box];\n" <>- " 9 [label=\"CO: L9\\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 -> [L10]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 10 [label=\"CO: L10\\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 -> [L11]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 11 [label=\"CO: L11\\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" <>- "\"\n" <>- " ,shape=box];\n" <>- " 12 [label=\"CO: L12\\n" <>- "OO: 213: JUMPDEST\\n" <>- "OC: 214: STOP -> []\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 1 -> 2;\n" <>- " 2 -> 3;\n" <>- " 3 -> 4;\n" <>- " 4 -> 5;\n" <>- " 5 -> 6;\n" <>- " 7 -> 8;\n" <>- " 9 -> 10;\n" <>- " 10 -> 11;\n" <>- "}"--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 -> [L2,L4]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 2 [label=\"CO: L2\\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 -> [L3,L7]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 3 [label=\"CO: L3\\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 -> [L4,L9]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 4 [label=\"CO: L4\\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 -> [L5,L6]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 5 [label=\"CO: L5\\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 -> [L6]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 6 [label=\"CO: L6\\n" <>- "OO: 108: JUMPDEST\\n" <>- "OC: 109: JUMP -> []\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 7 [label=\"CO: L7\\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 -> [L6,L8]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 8 [label=\"CO: L8\\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" <>- "\"\n" <>- " ,shape=box];\n" <>- " 9 [label=\"CO: L9\\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 -> [L6,L10]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 10 [label=\"CO: L10\\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 -> [L11]\\n" <>- "\"\n" <>- " ,shape=box];\n" <>- " 11 [label=\"CO: L11\\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" <>- "\"\n" <>- " ,shape=box];\n" <>- " 1 -> 2;\n" <>- " 1 -> 4;\n" <>- " 2 -> 3;\n" <>- " 2 -> 7;\n" <>- " 3 -> 4;\n" <>- " 3 -> 9;\n" <>- " 4 -> 5;\n" <>- " 4 -> 6;\n" <>- " 5 -> 6;\n" <>- " 7 -> 6;\n" <>- " 7 -> 8;\n" <>- " 9 -> 6;\n" <>- " 9 -> 10;\n" <>- " 10 -> 11;\n" <>- "}"
test/Ethereum/AnalyzerSpec.hs view
@@ -8,7 +8,7 @@ import Data.List as DL import Data.List.Extra as DLE-import Ethereum.Analyzer+import Ethereum.Analyzer.EVM import Ethereum.Analyzer.TestData.Basic import GHC.Show import Test.Hspec@@ -17,13 +17,13 @@ spec = describe "disasm" $ do it "works for hexstring1" $ do- let disasmd1 = toS $ show $ showOps $ disasm hexstring1+ let disasmd1 = show $ showOps $ disasm hexstring1 DL.take 60 disasmd1 `shouldBe` "[\"0: PUSH [96]\",\"2: PUSH [64]\",\"4: MSTORE\",\"5: PUSH [2]\",\"7:" DLE.takeEnd 60 disasmd1 `shouldBe` "]\",\"6989: JUMP\",\"6990: JUMPDEST\",\"6991: SWAP1\",\"6992: JUMP\"]" it "works for hexstring2" $ do- let disasmd2 = toS $ show $ showOps $ disasm hexstring2+ let disasmd2 = show $ showOps $ disasm hexstring2 disasmd2 `shouldBe` "[\"0: PUSH [96]\"," ++ "\"2: PUSH [64]\"," ++ "\"4: MSTORE\"," ++