Safe Haskell | Safe-Inferred |
---|---|
Language | GHC2021 |
Synopsis
- data Sig = Sig Text [AbiType]
- data LoopHeuristic
- = Naive
- | StackBased
- data ProofResult a b c
- type VerifyResult = ProofResult () (Expr End, SMTCex) (Expr End)
- type EquivResult = ProofResult () SMTCex ()
- isTimeout :: ProofResult a b c -> Bool
- isCex :: ProofResult a b c -> Bool
- isQed :: ProofResult a b c -> Bool
- data VeriOpts = VeriOpts {
- simp :: Bool
- debug :: Bool
- maxIter :: Maybe Integer
- askSmtIters :: Integer
- loopHeuristic :: LoopHeuristic
- rpcInfo :: RpcInfo
- defaultVeriOpts :: VeriOpts
- rpcVeriOpts :: (BlockNumber, Text) -> VeriOpts
- debugVeriOpts :: VeriOpts
- extractCex :: VerifyResult -> Maybe (Expr End, SMTCex)
- inRange :: Int -> Expr EWord -> Prop
- bool :: Expr EWord -> Prop
- symAbiArg :: Text -> AbiType -> CalldataFragment
- data CalldataFragment
- symCalldata :: Text -> [AbiType] -> [String] -> Expr Buf -> (Expr Buf, [Prop])
- cdLen :: [CalldataFragment] -> Expr EWord
- writeSelector :: Expr Buf -> Text -> Expr Buf
- combineFragments :: [CalldataFragment] -> Expr Buf -> (Expr Buf, [Prop])
- abstractVM :: (Expr Buf, [Prop]) -> ByteString -> Maybe Precondition -> Expr Storage -> VM
- loadSymVM :: ContractCode -> Expr Storage -> Expr EWord -> Expr EWord -> (Expr Buf, [Prop]) -> VM
- interpret :: Fetcher -> Maybe Integer -> Integer -> LoopHeuristic -> VM -> Stepper (Expr End) -> IO (Expr End)
- maxIterationsReached :: VM -> Maybe Integer -> Maybe Bool
- askSmtItersReached :: VM -> Integer -> Bool
- isLoopHead :: LoopHeuristic -> VM -> Maybe Bool
- type Precondition = VM -> Prop
- type Postcondition = VM -> Expr End -> Prop
- checkAssert :: SolverGroup -> [Word256] -> ByteString -> Maybe Sig -> [String] -> VeriOpts -> IO (Expr End, [VerifyResult])
- checkAssertions :: [Word256] -> Postcondition
- defaultPanicCodes :: [Word256]
- allPanicCodes :: [Word256]
- panicMsg :: Word256 -> ByteString
- mkCalldata :: Maybe Sig -> [String] -> (Expr Buf, [Prop])
- verifyContract :: SolverGroup -> ByteString -> Maybe Sig -> [String] -> VeriOpts -> Expr Storage -> Maybe Precondition -> Maybe Postcondition -> IO (Expr End, [VerifyResult])
- runExpr :: Stepper (Expr End)
- flattenExpr :: Expr End -> [Expr End]
- reachable :: SolverGroup -> Expr End -> IO ([SMT2], Expr End)
- evalProp :: Prop -> Prop
- extractProps :: Expr End -> [Prop]
- isPartial :: Expr a -> Bool
- getPartials :: [Expr End] -> [PartialExec]
- verify :: SolverGroup -> VeriOpts -> VM -> Maybe Postcondition -> IO (Expr End, [VerifyResult])
- type UnsatCache = TVar [Set Prop]
- equivalenceCheck :: SolverGroup -> ByteString -> ByteString -> VeriOpts -> (Expr Buf, [Prop]) -> IO [EquivResult]
- both' :: (a -> b) -> (a, a) -> (b, b)
- produceModels :: SolverGroup -> Expr End -> IO [(Expr End, CheckSatResult)]
- showModel :: Expr Buf -> (Expr End, CheckSatResult) -> IO ()
- formatCex :: Expr Buf -> SMTCex -> Text
- subModel :: SMTCex -> Expr a -> Expr a
Documentation
data LoopHeuristic Source #
Instances
Generic LoopHeuristic Source # | |
Defined in EVM.SymExec type Rep LoopHeuristic :: Type -> Type # from :: LoopHeuristic -> Rep LoopHeuristic x # to :: Rep LoopHeuristic x -> LoopHeuristic # | |
Read LoopHeuristic Source # | |
Defined in EVM.SymExec readsPrec :: Int -> ReadS LoopHeuristic # readList :: ReadS [LoopHeuristic] # | |
Show LoopHeuristic Source # | |
Defined in EVM.SymExec showsPrec :: Int -> LoopHeuristic -> ShowS # show :: LoopHeuristic -> String # showList :: [LoopHeuristic] -> ShowS # | |
Eq LoopHeuristic Source # | |
Defined in EVM.SymExec (==) :: LoopHeuristic -> LoopHeuristic -> Bool # (/=) :: LoopHeuristic -> LoopHeuristic -> Bool # | |
ParseField LoopHeuristic Source # | |
Defined in EVM.SymExec | |
ParseFields LoopHeuristic Source # | |
Defined in EVM.SymExec | |
ParseRecord LoopHeuristic Source # | |
Defined in EVM.SymExec | |
type Rep LoopHeuristic Source # | |
data ProofResult a b c Source #
Instances
(Show a, Show b, Show c) => Show (ProofResult a b c) Source # | |
Defined in EVM.SymExec showsPrec :: Int -> ProofResult a b c -> ShowS # show :: ProofResult a b c -> String # showList :: [ProofResult a b c] -> ShowS # | |
(Eq a, Eq b, Eq c) => Eq (ProofResult a b c) Source # | |
Defined in EVM.SymExec (==) :: ProofResult a b c -> ProofResult a b c -> Bool # (/=) :: ProofResult a b c -> ProofResult a b c -> Bool # |
type VerifyResult = ProofResult () (Expr End, SMTCex) (Expr End) Source #
type EquivResult = ProofResult () SMTCex () Source #
isTimeout :: ProofResult a b c -> Bool Source #
isCex :: ProofResult a b c -> Bool Source #
isQed :: ProofResult a b c -> Bool Source #
VeriOpts | |
|
rpcVeriOpts :: (BlockNumber, Text) -> VeriOpts Source #
extractCex :: VerifyResult -> Maybe (Expr End, SMTCex) Source #
data CalldataFragment Source #
Instances
Show CalldataFragment Source # | |
Defined in EVM.SymExec showsPrec :: Int -> CalldataFragment -> ShowS # show :: CalldataFragment -> String # showList :: [CalldataFragment] -> ShowS # | |
Eq CalldataFragment Source # | |
Defined in EVM.SymExec (==) :: CalldataFragment -> CalldataFragment -> Bool # (/=) :: CalldataFragment -> CalldataFragment -> Bool # |
symCalldata :: Text -> [AbiType] -> [String] -> Expr Buf -> (Expr Buf, [Prop]) Source #
Generates calldata matching given type signature, optionally specialized with concrete arguments. Any argument given as "symbolic" or omitted at the tail of the list are kept symbolic.
combineFragments :: [CalldataFragment] -> Expr Buf -> (Expr Buf, [Prop]) Source #
abstractVM :: (Expr Buf, [Prop]) -> ByteString -> Maybe Precondition -> Expr Storage -> VM Source #
loadSymVM :: ContractCode -> Expr Storage -> Expr EWord -> Expr EWord -> (Expr Buf, [Prop]) -> VM Source #
interpret :: Fetcher -> Maybe Integer -> Integer -> LoopHeuristic -> VM -> Stepper (Expr End) -> IO (Expr End) Source #
Interpreter which explores all paths at branching points. Returns an 'Expr End' representing the possible executions.
isLoopHead :: LoopHeuristic -> VM -> Maybe Bool Source #
Loop head detection heuristic
The main thing we wish to differentiate between, are actual loop heads, and branch points inside of internal functions that are called multiple times.
One way to do this is to observe that for internal functions, the compiler must always store a stack item representing the location that it must jump back to. If we compare the stack at the time of the previous visit, and the time of the current visit, and notice that this location has changed, then we can guess that the location is a jump point within an internal function instead of a loop (where such locations should be constant between iterations).
This heuristic is not perfect, and can certainly be tricked, but should generally be good enough for most compiler generated and non pathological user generated loops.
type Precondition = VM -> Prop Source #
checkAssert :: SolverGroup -> [Word256] -> ByteString -> Maybe Sig -> [String] -> VeriOpts -> IO (Expr End, [VerifyResult]) Source #
checkAssertions :: [Word256] -> Postcondition Source #
Checks if an assertion violation has been encountered
hevm recognises the following as an assertion violation:
- the invalid opcode (0xfe) (solc < 0.8)
- a revert with a reason of the form `abi.encodeWithSelector("Panic(uint256)", code)`, where code is one of the following (solc >= 0.8): - 0x00: Used for generic compiler inserted panics. - 0x01: If you call assert with an argument that evaluates to false. - 0x11: If an arithmetic operation results in underflow or overflow outside of an unchecked { ... } block. - 0x12; If you divide or modulo by zero (e.g. 5 / 0 or 23 % 0). - 0x21: If you convert a value that is too big or negative into an enum type. - 0x22: If you access a storage byte array that is incorrectly encoded. - 0x31: If you call .pop() on an empty array. - 0x32: If you access an array, bytesN or an array slice at an out-of-bounds or negative index (i.e. x[i] where i >= x.length or i < 0). - 0x41: If you allocate too much memory or create an array that is too large. - 0x51: If you call a zero-initialized variable of internal function type.
defaultPanicCodes :: [Word256] Source #
By default hevm only checks for user-defined assertions
allPanicCodes :: [Word256] Source #
panicMsg :: Word256 -> ByteString Source #
Produces the revert message for solc >=0.8 assertion violations
mkCalldata :: Maybe Sig -> [String] -> (Expr Buf, [Prop]) Source #
Builds a buffer representing calldata from the provided method description and concrete arguments
verifyContract :: SolverGroup -> ByteString -> Maybe Sig -> [String] -> VeriOpts -> Expr Storage -> Maybe Precondition -> Maybe Postcondition -> IO (Expr End, [VerifyResult]) Source #
runExpr :: Stepper (Expr End) Source #
Stepper that parses the result of Stepper.runFully into an Expr End
flattenExpr :: Expr End -> [Expr End] Source #
Converts a given top level expr into a list of final states and the associated path conditions for each state.
reachable :: SolverGroup -> Expr End -> IO ([SMT2], Expr End) Source #
Strips unreachable branches from a given expr Returns a list of executed SMT queries alongside the reduced expression for debugging purposes Note that the reduced expression loses information relative to the original one if jump conditions are removed. This restriction can be removed once Expr supports attaching knowledge to AST nodes. Although this algorithm currently parallelizes nicely, it does not exploit the incremental nature of the task at hand. Introducing support for incremental queries might let us go even faster here. TODO: handle errors properly
getPartials :: [Expr End] -> [PartialExec] Source #
verify :: SolverGroup -> VeriOpts -> VM -> Maybe Postcondition -> IO (Expr End, [VerifyResult]) Source #
Symbolically execute the VM and check all endstates against the postcondition, if available.
equivalenceCheck :: SolverGroup -> ByteString -> ByteString -> VeriOpts -> (Expr Buf, [Prop]) -> IO [EquivResult] Source #
Compares two contract runtimes for trace equivalence by running two VMs and comparing the end states.
We do this by asking the solver to find a common input for each pair of endstates that satisfies the path conditions for both sides and produces a differing output. If we can find such an input, then we have a clear equivalence break, and since we run this check for every pair of end states, the check is exhaustive.
produceModels :: SolverGroup -> Expr End -> IO [(Expr End, CheckSatResult)] Source #