an intermediate symbolic execution engine for EVM bytecode
16

Configure Feed

Select the types of activity you want to include in your feed.

symevm / src / SymbolicExpression.hs
4.9 kB 160 lines
1{-# LANGUAGE DeriveGeneric #-} 2{-# LANGUAGE DeriveAnyClass #-} 3 4module SymbolicExpression where 5 6import Data.Word 7import Data.Map.Strict (Map) 8import qualified Data.Map.Strict as Map 9import GHC.Generics (Generic) 10import Data.Bits hiding (And, Xor) 11 12data SymExpr 13 = Concrete Integer 14 | Symbolic String Int 15 | Add SymExpr SymExpr 16 | Sub SymExpr SymExpr 17 | Mul SymExpr SymExpr 18 | Div SymExpr SymExpr 19 | Mod SymExpr SymExpr 20 | Exp SymExpr SymExpr 21 | SDiv SymExpr SymExpr 22 | SMod SymExpr SymExpr 23 | Lt SymExpr SymExpr 24 | Gt SymExpr SymExpr 25 | SLt SymExpr SymExpr 26 | SGt SymExpr SymExpr 27 | Eq SymExpr SymExpr 28 | IsZero SymExpr 29 | And SymExpr SymExpr 30 | Or SymExpr SymExpr 31 | Xor SymExpr SymExpr 32 | Not SymExpr 33 | Byte SymExpr SymExpr 34 | Shl SymExpr SymExpr 35 | Shr SymExpr SymExpr 36 | Sar SymExpr SymExpr 37 | Sha3 SymExpr SymExpr 38 | Address 39 | Balance SymExpr 40 | Origin 41 | Caller 42 | CallValue 43 | CallDataLoad SymExpr 44 | CallDataSize 45 | CodeSize 46 | GasPrice 47 | BlockHash SymExpr 48 | Coinbase 49 | Timestamp 50 | Number 51 | Difficulty 52 | GasLimit 53 | ChainId 54 | SelfBalance 55 | BaseFee 56 deriving (Eq, Ord, Generic, Show) 57 58data Constraint 59 = CTrue SymExpr 60 | CFalse SymExpr 61 | CEq SymExpr SymExpr 62 | CNeq SymExpr SymExpr 63 | CLt SymExpr SymExpr 64 | CGt SymExpr SymExpr 65 deriving (Eq, Ord, Show) 66 67mkAdd :: SymExpr -> SymExpr -> SymExpr 68mkAdd (Concrete 0) e = e 69mkAdd e (Concrete 0) = e 70mkAdd (Concrete a) (Concrete b) = Concrete ((a + b) `mod` (2^256)) 71mkAdd a b = Add a b 72 73mkSub :: SymExpr -> SymExpr -> SymExpr 74mkSub e (Concrete 0) = e 75mkSub (Concrete a) (Concrete b) = Concrete ((a - b) `mod` (2^256)) 76mkSub a b = Sub a b 77 78mkMul :: SymExpr -> SymExpr -> SymExpr 79mkMul (Concrete 0) _ = Concrete 0 80mkMul _ (Concrete 0) = Concrete 0 81mkMul (Concrete 1) e = e 82mkMul e (Concrete 1) = e 83mkMul (Concrete a) (Concrete b) = Concrete ((a * b) `mod` (2^256)) 84mkMul a b = Mul a b 85 86mkDiv :: SymExpr -> SymExpr -> SymExpr 87mkDiv _ (Concrete 0) = Concrete 0 88mkDiv e (Concrete 1) = e 89mkDiv (Concrete a) (Concrete b) = if b == 0 then Concrete 0 else Concrete (a `div` b) 90mkDiv a b = Div a b 91 92mkMod :: SymExpr -> SymExpr -> SymExpr 93mkMod _ (Concrete 0) = Concrete 0 94mkMod (Concrete a) (Concrete b) = if b == 0 then Concrete 0 else Concrete (a `mod` b) 95mkMod a b = Mod a b 96 97mkLt :: SymExpr -> SymExpr -> SymExpr 98mkLt (Concrete a) (Concrete b) = Concrete (if a < b then 1 else 0) 99mkLt a b = Lt a b 100 101mkGt :: SymExpr -> SymExpr -> SymExpr 102mkGt (Concrete a) (Concrete b) = Concrete (if a > b then 1 else 0) 103mkGt a b = Gt a b 104 105mkEq :: SymExpr -> SymExpr -> SymExpr 106mkEq a b | a == b = Concrete 1 107mkEq (Concrete a) (Concrete b) = Concrete (if a == b then 1 else 0) 108mkEq a b = Eq a b 109 110mkIsZero :: SymExpr -> SymExpr 111mkIsZero (Concrete 0) = Concrete 1 112mkIsZero (Concrete _) = Concrete 0 113mkIsZero e = IsZero e 114 115mkAnd :: SymExpr -> SymExpr -> SymExpr 116mkAnd (Concrete 0) _ = Concrete 0 117mkAnd _ (Concrete 0) = Concrete 0 118mkAnd (Concrete a) (Concrete b) = Concrete (a .&. b) 119mkAnd a b = And a b 120 121mkOr :: SymExpr -> SymExpr -> SymExpr 122mkOr (Concrete a) (Concrete b) = Concrete (a .|. b) 123mkOr a b = Or a b 124 125mkXor :: SymExpr -> SymExpr -> SymExpr 126mkXor (Concrete a) (Concrete b) = Concrete (xor a b) 127mkXor a b = Xor a b 128 129mkNot :: SymExpr -> SymExpr 130mkNot (Concrete a) = Concrete ((2^256 - 1) - a) 131mkNot e = Not e 132 133prettyExpr :: SymExpr -> String 134prettyExpr (Concrete n) = show n 135prettyExpr (Symbolic name id) = name ++ "_" ++ show id 136prettyExpr (Add a b) = "(" ++ prettyExpr a ++ " + " ++ prettyExpr b ++ ")" 137prettyExpr (Sub a b) = "(" ++ prettyExpr a ++ " - " ++ prettyExpr b ++ ")" 138prettyExpr (Mul a b) = "(" ++ prettyExpr a ++ " * " ++ prettyExpr b ++ ")" 139prettyExpr (Div a b) = "(" ++ prettyExpr a ++ " / " ++ prettyExpr b ++ ")" 140prettyExpr (Mod a b) = "(" ++ prettyExpr a ++ " % " ++ prettyExpr b ++ ")" 141prettyExpr (Lt a b) = "(" ++ prettyExpr a ++ " < " ++ prettyExpr b ++ ")" 142prettyExpr (Gt a b) = "(" ++ prettyExpr a ++ " > " ++ prettyExpr b ++ ")" 143prettyExpr (Eq a b) = "(" ++ prettyExpr a ++ " == " ++ prettyExpr b ++ ")" 144prettyExpr (IsZero a) = "IsZero(" ++ prettyExpr a ++ ")" 145prettyExpr (And a b) = "(" ++ prettyExpr a ++ " & " ++ prettyExpr b ++ ")" 146prettyExpr (Or a b) = "(" ++ prettyExpr a ++ " | " ++ prettyExpr b ++ ")" 147prettyExpr (Not a) = "~" ++ prettyExpr a 148prettyExpr Caller = "caller" 149prettyExpr CallValue = "callvalue" 150prettyExpr (CallDataLoad offset) = "calldataload(" ++ prettyExpr offset ++ ")" 151prettyExpr CallDataSize = "calldatasize" 152prettyExpr _ = "<expr>" 153 154prettyConstraint :: Constraint -> String 155prettyConstraint (CTrue e) = prettyExpr e ++ " != 0" 156prettyConstraint (CFalse e) = prettyExpr e ++ " == 0" 157prettyConstraint (CEq a b) = prettyExpr a ++ " == " ++ prettyExpr b 158prettyConstraint (CNeq a b) = prettyExpr a ++ " != " ++ prettyExpr b 159prettyConstraint (CLt a b) = prettyExpr a ++ " < " ++ prettyExpr b 160prettyConstraint (CGt a b) = prettyExpr a ++ " > " ++ prettyExpr b