packages feed

hevm 0.50.2 → 0.50.3

raw patch · 32 files changed

+2069/−1577 lines, 32 filesdep +spawndep +stmdep +tasty-benchdep ~basedep ~bytestringdep ~herePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: spawn, stm, tasty-bench

Dependency ranges changed: base, bytestring, here, tasty, text

API changes (from Hackage documentation)

- EVM: [_accessedAddresses] :: SubState -> Set Addr
- EVM: [_accessedStorageKeys] :: SubState -> Set (Addr, W256)
- EVM: [_allowFFI] :: VM -> Bool
- EVM: [_balance] :: Contract -> W256
- EVM: [_baseFee] :: Block -> W256
- EVM: [_block] :: VM -> Block
- EVM: [_burned] :: VM -> Word64
- EVM: [_cache] :: VM -> Cache
- EVM: [_calldata] :: FrameState -> Expr Buf
- EVM: [_caller] :: FrameState -> Expr EWord
- EVM: [_callvalue] :: FrameState -> Expr EWord
- EVM: [_chainId] :: Env -> W256
- EVM: [_codeContract] :: FrameState -> Addr
- EVM: [_codeOps] :: Contract -> Vector (Int, Op)
- EVM: [_code] :: FrameState -> ContractCode
- EVM: [_codehash] :: Contract -> Expr EWord
- EVM: [_coinbase] :: Block -> Addr
- EVM: [_constraints] :: VM -> [Prop]
- EVM: [_contract] :: FrameState -> Addr
- EVM: [_contractcode] :: Contract -> ContractCode
- EVM: [_contracts] :: Env -> Map Addr Contract
- EVM: [_env] :: VM -> Env
- EVM: [_external] :: Contract -> Bool
- EVM: [_fetchedContracts] :: Cache -> Map Addr Contract
- EVM: [_fetchedStorage] :: Cache -> Map W256 (Map W256 W256)
- EVM: [_frameContext] :: Frame -> FrameContext
- EVM: [_frameState] :: Frame -> FrameState
- EVM: [_frames] :: VM -> [Frame]
- EVM: [_gas] :: FrameState -> Word64
- EVM: [_gaslimit] :: Block -> Word64
- EVM: [_gasprice] :: TxState -> W256
- EVM: [_isCreate] :: TxState -> Bool
- EVM: [_iterations] :: VM -> Map CodeLocation Int
- EVM: [_keccakEqs] :: VM -> [Prop]
- EVM: [_logs] :: VM -> [Expr Log]
- EVM: [_maxCodeSize] :: Block -> W256
- EVM: [_memorySize] :: FrameState -> Word64
- EVM: [_memory] :: FrameState -> Expr Buf
- EVM: [_nonce] :: Contract -> W256
- EVM: [_number] :: Block -> W256
- EVM: [_opIxMap] :: Contract -> Vector Int
- EVM: [_origStorage] :: Env -> Map W256 (Map W256 W256)
- EVM: [_origin] :: TxState -> Addr
- EVM: [_path] :: Cache -> Map (CodeLocation, Int) Bool
- EVM: [_pc] :: FrameState -> Int
- EVM: [_prevRandao] :: Block -> W256
- EVM: [_refunds] :: SubState -> [(Addr, Word64)]
- EVM: [_result] :: VM -> Maybe VMResult
- EVM: [_returndata] :: FrameState -> Expr Buf
- EVM: [_schedule] :: Block -> FeeSchedule Word64
- EVM: [_selfdestructs] :: SubState -> [Addr]
- EVM: [_sha3Crack] :: Env -> Map W256 ByteString
- EVM: [_stack] :: FrameState -> [Expr EWord]
- EVM: [_state] :: VM -> FrameState
- EVM: [_static] :: FrameState -> Bool
- EVM: [_storage] :: Env -> Expr Storage
- EVM: [_substate] :: TxState -> SubState
- EVM: [_timestamp] :: Block -> Expr EWord
- EVM: [_toAddr] :: TxState -> Addr
- EVM: [_touchedAccounts] :: SubState -> [Addr]
- EVM: [_traceContract] :: Trace -> Contract
- EVM: [_traceData] :: Trace -> TraceData
- EVM: [_traceOpIx] :: Trace -> Int
- EVM: [_traces] :: VM -> TreePos Empty Trace
- EVM: [_txPriorityFee] :: TxState -> W256
- EVM: [_txReversion] :: TxState -> Map Addr Contract
- EVM: [_tx] :: VM -> TxState
- EVM: [_txgaslimit] :: TxState -> Word64
- EVM: [_value] :: TxState -> Expr EWord
- EVM: [callContextAbi] :: FrameContext -> Maybe W256
- EVM: [callContextCodehash] :: FrameContext -> Expr EWord
- EVM: [callContextContext] :: FrameContext -> Addr
- EVM: [callContextData] :: FrameContext -> Expr Buf
- EVM: [callContextOffset] :: FrameContext -> W256
- EVM: [callContextReversion] :: FrameContext -> (Map Addr Contract, Expr Storage)
- EVM: [callContextSize] :: FrameContext -> W256
- EVM: [callContextSubState] :: FrameContext -> SubState
- EVM: [callContextTarget] :: FrameContext -> Addr
- EVM: [creationContextAddress] :: FrameContext -> Addr
- EVM: [creationContextCodehash] :: FrameContext -> Expr EWord
- EVM: [creationContextReversion] :: FrameContext -> Map Addr Contract
- EVM: [creationContextSubstate] :: FrameContext -> SubState
- EVM: [vmoptAddress] :: VMOpts -> Addr
- EVM: [vmoptAllowFFI] :: VMOpts -> Bool
- EVM: [vmoptBaseFee] :: VMOpts -> W256
- EVM: [vmoptBlockGaslimit] :: VMOpts -> Word64
- EVM: [vmoptCalldata] :: VMOpts -> (Expr Buf, [Prop])
- EVM: [vmoptCaller] :: VMOpts -> Expr EWord
- EVM: [vmoptChainId] :: VMOpts -> W256
- EVM: [vmoptCoinbase] :: VMOpts -> Addr
- EVM: [vmoptContract] :: VMOpts -> Contract
- EVM: [vmoptCreate] :: VMOpts -> Bool
- EVM: [vmoptGas] :: VMOpts -> Word64
- EVM: [vmoptGaslimit] :: VMOpts -> Word64
- EVM: [vmoptGasprice] :: VMOpts -> W256
- EVM: [vmoptMaxCodeSize] :: VMOpts -> W256
- EVM: [vmoptNumber] :: VMOpts -> W256
- EVM: [vmoptOrigin] :: VMOpts -> Addr
- EVM: [vmoptPrevRandao] :: VMOpts -> W256
- EVM: [vmoptPriorityFee] :: VMOpts -> W256
- EVM: [vmoptSchedule] :: VMOpts -> FeeSchedule Word64
- EVM: [vmoptStorageBase] :: VMOpts -> StorageBase
- EVM: [vmoptTimestamp] :: VMOpts -> Expr EWord
- EVM: [vmoptTxAccessList] :: VMOpts -> Map Addr [W256]
- EVM: [vmoptValue] :: VMOpts -> Expr EWord
- EVM.Dapp: [_contextEnv] :: DappContext -> Map Addr Contract
- EVM.Dapp: [_contextInfo] :: DappContext -> DappInfo
- EVM.Dapp: [_dappAbiMap] :: DappInfo -> Map Word32 Method
- EVM.Dapp: [_dappAstIdMap] :: DappInfo -> Map Int Value
- EVM.Dapp: [_dappAstSrcMap] :: DappInfo -> SrcMap -> Maybe Value
- EVM.Dapp: [_dappErrorMap] :: DappInfo -> Map W256 SolError
- EVM.Dapp: [_dappEventMap] :: DappInfo -> Map W256 Event
- EVM.Dapp: [_dappRoot] :: DappInfo -> FilePath
- EVM.Dapp: [_dappSolcByCode] :: DappInfo -> [(Code, SolcContract)]
- EVM.Dapp: [_dappSolcByHash] :: DappInfo -> Map W256 (CodeType, SolcContract)
- EVM.Dapp: [_dappSolcByName] :: DappInfo -> Map Text SolcContract
- EVM.Dapp: [_dappSources] :: DappInfo -> SourceCache
- EVM.Dapp: [_dappUnitTests] :: DappInfo -> [(Text, [(Test, [AbiType])])]
- EVM.Dapp: [immutableLocations] :: Code -> [Reference]
- EVM.Dapp: [raw] :: Code -> ByteString
- EVM.Dapp: contextEnv :: Lens' DappContext (Map Addr Contract)
- EVM.Dapp: contextInfo :: Lens' DappContext DappInfo
- EVM.Dapp: dappAbiMap :: Lens' DappInfo (Map Word32 Method)
- EVM.Dapp: dappAstIdMap :: Lens' DappInfo (Map Int Value)
- EVM.Dapp: dappAstSrcMap :: Lens' DappInfo (SrcMap -> Maybe Value)
- EVM.Dapp: dappErrorMap :: Lens' DappInfo (Map W256 SolError)
- EVM.Dapp: dappEventMap :: Lens' DappInfo (Map W256 Event)
- EVM.Dapp: dappRoot :: Lens' DappInfo FilePath
- EVM.Dapp: dappSolcByCode :: Lens' DappInfo [(Code, SolcContract)]
- EVM.Dapp: dappSolcByHash :: Lens' DappInfo (Map W256 (CodeType, SolcContract))
- EVM.Dapp: dappSolcByName :: Lens' DappInfo (Map Text SolcContract)
- EVM.Dapp: dappSources :: Lens' DappInfo SourceCache
- EVM.Dapp: dappUnitTests :: Lens' DappInfo [(Text, [(Test, [AbiType])])]
- EVM.Facts: [addr] :: Fact -> Addr
- EVM.Facts: [blob] :: Fact -> ByteString
- EVM.Facts: [dataASCII] :: Data -> ASCII
- EVM.Facts: [fileData] :: File -> Data
- EVM.Facts: [filePath] :: File -> Path
- EVM.Facts: [what] :: Fact -> W256
- EVM.Facts: [which] :: Fact -> W256
- EVM.FeeSchedule: [g_access_list_address] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_access_list_storage_key] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_balance] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_base] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_blockhash] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_call] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_callstipend] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_callvalue] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_codedeposit] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_cold_account_access] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_cold_sload] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_copy] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_create] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_ecadd] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_ecmul] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_exp] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_expbyte] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_extcode] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_extcodehash] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_fround] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_high] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_jumpdest] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_log] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_logdata] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_logtopic] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_low] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_memory] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_mid] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_newaccount] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_pairing_base] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_pairing_point] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_quaddivisor] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_selfdestruct] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_selfdestruct_newaccount] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_sha3] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_sha3word] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_sload] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_sreset] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_sset] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_transaction] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_txcreate] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_txdatanonzero] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_txdatazero] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_verylow] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_warm_storage_read] :: FeeSchedule n -> n
- EVM.FeeSchedule: [g_zero] :: FeeSchedule n -> n
- EVM.FeeSchedule: [r_block] :: FeeSchedule n -> n
- EVM.FeeSchedule: [r_sclear] :: FeeSchedule n -> n
- EVM.FeeSchedule: [r_selfdestruct] :: FeeSchedule n -> n
- EVM.SMT: Bitwuzla :: Solver
- EVM.SMT: CVC5 :: Solver
- EVM.SMT: Custom :: Text -> Solver
- EVM.SMT: Error :: Text -> CheckSatResult
- EVM.SMT: Sat :: SMTCex -> CheckSatResult
- EVM.SMT: SolverGroup :: Chan Task -> SolverGroup
- EVM.SMT: SolverInstance :: Solver -> Handle -> Handle -> Handle -> ProcessHandle -> SolverInstance
- EVM.SMT: Task :: SMT2 -> Chan CheckSatResult -> Task
- EVM.SMT: Unknown :: CheckSatResult
- EVM.SMT: Unsat :: CheckSatResult
- EVM.SMT: Z3 :: Solver
- EVM.SMT: [_process] :: SolverInstance -> ProcessHandle
- EVM.SMT: [_stderr] :: SolverInstance -> Handle
- EVM.SMT: [_stdin] :: SolverInstance -> Handle
- EVM.SMT: [_stdout] :: SolverInstance -> Handle
- EVM.SMT: [_type] :: SolverInstance -> Solver
- EVM.SMT: [blockContextV] :: CexVars -> [Text]
- EVM.SMT: [blockContext] :: SMTCex -> Map (Expr EWord) W256
- EVM.SMT: [buffersV] :: CexVars -> [Text]
- EVM.SMT: [buffers] :: SMTCex -> Map (Expr Buf) ByteString
- EVM.SMT: [calldataV] :: CexVars -> [Text]
- EVM.SMT: [resultChan] :: Task -> Chan CheckSatResult
- EVM.SMT: [script] :: Task -> SMT2
- EVM.SMT: [txContextV] :: CexVars -> [Text]
- EVM.SMT: [txContext] :: SMTCex -> Map (Expr EWord) W256
- EVM.SMT: [vars] :: SMTCex -> Map (Expr EWord) W256
- EVM.SMT: checkSat :: SolverGroup -> SMT2 -> IO CheckSatResult
- EVM.SMT: data CheckSatResult
- EVM.SMT: data Solver
- EVM.SMT: data SolverInstance
- EVM.SMT: data Task
- EVM.SMT: getValue :: SolverInstance -> Text -> IO Text
- EVM.SMT: instance GHC.Classes.Eq EVM.SMT.CheckSatResult
- EVM.SMT: instance GHC.Show.Show EVM.SMT.CheckSatResult
- EVM.SMT: instance GHC.Show.Show EVM.SMT.Solver
- EVM.SMT: isErr :: CheckSatResult -> Bool
- EVM.SMT: isSat :: CheckSatResult -> Bool
- EVM.SMT: isUnsat :: CheckSatResult -> Bool
- EVM.SMT: newtype SolverGroup
- EVM.SMT: readSExpr :: Handle -> IO [Text]
- EVM.SMT: sendCommand :: SolverInstance -> Text -> IO Text
- EVM.SMT: sendLine :: SolverInstance -> Text -> IO Text
- EVM.SMT: sendLine' :: SolverInstance -> Text -> IO ()
- EVM.SMT: sendScript :: SolverInstance -> SMT2 -> IO (Either Text ())
- EVM.SMT: solverArgs :: Solver -> Maybe Natural -> [Text]
- EVM.SMT: spawnSolver :: Solver -> Maybe Natural -> IO SolverInstance
- EVM.SMT: stopSolver :: SolverInstance -> IO ()
- EVM.SMT: withSolvers :: Solver -> Natural -> Maybe Natural -> (SolverGroup -> IO a) -> IO a
- EVM.Solidity: [_abiMap] :: SolcContract -> Map Word32 Method
- EVM.Solidity: [_constructorInputs] :: SolcContract -> [(Text, AbiType)]
- EVM.Solidity: [_contractName] :: SolcContract -> Text
- EVM.Solidity: [_creationCode] :: SolcContract -> ByteString
- EVM.Solidity: [_creationCodehash] :: SolcContract -> W256
- EVM.Solidity: [_creationSrcmap] :: SolcContract -> Seq SrcMap
- EVM.Solidity: [_errorMap] :: SolcContract -> Map W256 SolError
- EVM.Solidity: [_eventMap] :: SolcContract -> Map W256 Event
- EVM.Solidity: [_immutableReferences] :: SolcContract -> Map W256 [Reference]
- EVM.Solidity: [_methodInputs] :: Method -> [(Text, AbiType)]
- EVM.Solidity: [_methodMutability] :: Method -> Mutability
- EVM.Solidity: [_methodName] :: Method -> Text
- EVM.Solidity: [_methodOutput] :: Method -> [(Text, AbiType)]
- EVM.Solidity: [_methodSignature] :: Method -> Text
- EVM.Solidity: [_offset] :: StorageItem -> Int
- EVM.Solidity: [_refLength] :: Reference -> Int
- EVM.Solidity: [_refStart] :: Reference -> Int
- EVM.Solidity: [_runtimeCode] :: SolcContract -> ByteString
- EVM.Solidity: [_runtimeCodehash] :: SolcContract -> W256
- EVM.Solidity: [_runtimeSrcmap] :: SolcContract -> Seq SrcMap
- EVM.Solidity: [_slot] :: StorageItem -> Int
- EVM.Solidity: [_sourceAsts] :: SourceCache -> Map Text Value
- EVM.Solidity: [_sourceFiles] :: SourceCache -> [(Text, ByteString)]
- EVM.Solidity: [_sourceLines] :: SourceCache -> [Vector ByteString]
- EVM.Solidity: [_storageLayout] :: SolcContract -> Maybe (Map Text StorageItem)
- EVM.Solidity: [_type] :: StorageItem -> SlotType
- EVM.Solidity: [srcMapFile] :: SrcMap -> {-# UNPACK #-}Int
- EVM.Solidity: [srcMapJump] :: SrcMap -> JumpType
- EVM.Solidity: [srcMapLength] :: SrcMap -> {-# UNPACK #-}Int
- EVM.Solidity: [srcMapModifierDepth] :: SrcMap -> {-# UNPACK #-}Int
- EVM.Solidity: [srcMapOffset] :: SrcMap -> {-# UNPACK #-}Int
- EVM.Solidity: abiMap :: Lens' SolcContract (Map Word32 Method)
- EVM.Solidity: constructorInputs :: Lens' SolcContract [(Text, AbiType)]
- EVM.Solidity: contractName :: Lens' SolcContract Text
- EVM.Solidity: creationCode :: Lens' SolcContract ByteString
- EVM.Solidity: creationCodehash :: Lens' SolcContract W256
- EVM.Solidity: creationSrcmap :: Lens' SolcContract (Seq SrcMap)
- EVM.Solidity: errorMap :: Lens' SolcContract (Map W256 SolError)
- EVM.Solidity: eventMap :: Lens' SolcContract (Map W256 Event)
- EVM.Solidity: immutableReferences :: Lens' SolcContract (Map W256 [Reference])
- EVM.Solidity: methodInputs :: Lens' Method [(Text, AbiType)]
- EVM.Solidity: methodMutability :: Lens' Method Mutability
- EVM.Solidity: methodName :: Lens' Method Text
- EVM.Solidity: methodOutput :: Lens' Method [(Text, AbiType)]
- EVM.Solidity: methodSignature :: Lens' Method Text
- EVM.Solidity: runtimeCode :: Lens' SolcContract ByteString
- EVM.Solidity: runtimeCodehash :: Lens' SolcContract W256
- EVM.Solidity: runtimeSrcmap :: Lens' SolcContract (Seq SrcMap)
- EVM.Solidity: sourceAsts :: Lens' SourceCache (Map Text Value)
- EVM.Solidity: sourceFiles :: Lens' SourceCache [(Text, ByteString)]
- EVM.Solidity: sourceLines :: Lens' SourceCache [Vector ByteString]
- EVM.Solidity: storageLayout :: Lens' SolcContract (Maybe (Map Text StorageItem))
- EVM.SymExec: [askSmtIters] :: VeriOpts -> Maybe Integer
- EVM.SymExec: [debug] :: VeriOpts -> Bool
- EVM.SymExec: [maxIter] :: VeriOpts -> Maybe Integer
- EVM.SymExec: [rpcInfo] :: VeriOpts -> RpcInfo
- EVM.SymExec: [simp] :: VeriOpts -> Bool
- EVM.SymExec: containsA :: Eq a => Eq b => Eq c => ProofResult a b c -> [(d, e, ProofResult a b c)] -> Bool
- EVM.SymExec: type EquivalenceResult = ProofResult ([VM], [VM]) VM ()
- EVM.TTY: [_browserContractList] :: UiBrowserState -> List Name (Addr, Contract)
- EVM.TTY: [_browserVm] :: UiBrowserState -> UiVmState
- EVM.TTY: [_testOpts] :: UiTestPickerState -> UnitTestOptions
- EVM.TTY: [_testPickerDapp] :: UiTestPickerState -> DappInfo
- EVM.TTY: [_testPickerList] :: UiTestPickerState -> List Name (Text, Text)
- EVM.TTY: [_uiShowMemory] :: UiVmState -> Bool
- EVM.TTY: [_uiSnapshots] :: UiVmState -> Map Int (VM, Stepper ())
- EVM.TTY: [_uiStep] :: UiVmState -> Int
- EVM.TTY: [_uiStepper] :: UiVmState -> Stepper ()
- EVM.TTY: [_uiTestOpts] :: UiVmState -> UnitTestOptions
- EVM.TTY: [_uiVm] :: UiVmState -> VM
- EVM.Transaction: [accessAddress] :: AccessListEntry -> Addr
- EVM.Transaction: [accessStorageKeys] :: AccessListEntry -> [W256]
- EVM.Transaction: [txAccessList] :: Transaction -> [AccessListEntry]
- EVM.Transaction: [txData] :: Transaction -> ByteString
- EVM.Transaction: [txGasLimit] :: Transaction -> Word64
- EVM.Transaction: [txGasPrice] :: Transaction -> Maybe W256
- EVM.Transaction: [txMaxFeePerGas] :: Transaction -> Maybe W256
- EVM.Transaction: [txMaxPriorityFeeGas] :: Transaction -> Maybe W256
- EVM.Transaction: [txNonce] :: Transaction -> W256
- EVM.Transaction: [txR] :: Transaction -> W256
- EVM.Transaction: [txS] :: Transaction -> W256
- EVM.Transaction: [txToAddr] :: Transaction -> Maybe Addr
- EVM.Transaction: [txType] :: Transaction -> TxType
- EVM.Transaction: [txV] :: Transaction -> W256
- EVM.Transaction: [txValue] :: Transaction -> W256
- EVM.Types: [addressWord160] :: Addr -> Word160
- EVM.UnitTest: [askSmtIters] :: UnitTestOptions -> Maybe Integer
- EVM.UnitTest: [covMatch] :: UnitTestOptions -> Maybe Text
- EVM.UnitTest: [dapp] :: UnitTestOptions -> DappInfo
- EVM.UnitTest: [ffiAllowed] :: UnitTestOptions -> Bool
- EVM.UnitTest: [fuzzRuns] :: UnitTestOptions -> Int
- EVM.UnitTest: [match] :: UnitTestOptions -> Text
- EVM.UnitTest: [maxDepth] :: UnitTestOptions -> Maybe Int
- EVM.UnitTest: [maxIter] :: UnitTestOptions -> Maybe Integer
- EVM.UnitTest: [replay] :: UnitTestOptions -> Maybe (Text, ByteString)
- EVM.UnitTest: [rpcInfo] :: UnitTestOptions -> RpcInfo
- EVM.UnitTest: [smtDebug] :: UnitTestOptions -> Bool
- EVM.UnitTest: [smtTimeout] :: UnitTestOptions -> Maybe Natural
- EVM.UnitTest: [solver] :: UnitTestOptions -> Maybe Text
- EVM.UnitTest: [solvers] :: UnitTestOptions -> SolverGroup
- EVM.UnitTest: [srcContract] :: OpLocation -> Contract
- EVM.UnitTest: [srcOpIx] :: OpLocation -> Int
- EVM.UnitTest: [testAddress] :: TestVMParams -> Addr
- EVM.UnitTest: [testBalanceCreate] :: TestVMParams -> W256
- EVM.UnitTest: [testBaseFee] :: TestVMParams -> W256
- EVM.UnitTest: [testCaller] :: TestVMParams -> Addr
- EVM.UnitTest: [testChainId] :: TestVMParams -> W256
- EVM.UnitTest: [testCoinbase] :: TestVMParams -> Addr
- EVM.UnitTest: [testGasCall] :: TestVMParams -> Word64
- EVM.UnitTest: [testGasCreate] :: TestVMParams -> Word64
- EVM.UnitTest: [testGaslimit] :: TestVMParams -> Word64
- EVM.UnitTest: [testGasprice] :: TestVMParams -> W256
- EVM.UnitTest: [testMaxCodeSize] :: TestVMParams -> W256
- EVM.UnitTest: [testNumber] :: TestVMParams -> W256
- EVM.UnitTest: [testOrigin] :: TestVMParams -> Addr
- EVM.UnitTest: [testParams] :: UnitTestOptions -> TestVMParams
- EVM.UnitTest: [testPrevrandao] :: TestVMParams -> W256
- EVM.UnitTest: [testPriorityFee] :: TestVMParams -> W256
- EVM.UnitTest: [testTimestamp] :: TestVMParams -> W256
- EVM.UnitTest: [verbose] :: UnitTestOptions -> Maybe Int
- EVM.UnitTest: [vmModifier] :: UnitTestOptions -> VM -> VM
+ EVM: [$sel:_accessedAddresses:SubState] :: SubState -> Set Addr
+ EVM: [$sel:_accessedStorageKeys:SubState] :: SubState -> Set (Addr, W256)
+ EVM: [$sel:_allowFFI:VM] :: VM -> Bool
+ EVM: [$sel:_balance:Contract] :: Contract -> W256
+ EVM: [$sel:_baseFee:Block] :: Block -> W256
+ EVM: [$sel:_block:VM] :: VM -> Block
+ EVM: [$sel:_burned:VM] :: VM -> Word64
+ EVM: [$sel:_cache:VM] :: VM -> Cache
+ EVM: [$sel:_calldata:FrameState] :: FrameState -> Expr Buf
+ EVM: [$sel:_caller:FrameState] :: FrameState -> Expr EWord
+ EVM: [$sel:_callvalue:FrameState] :: FrameState -> Expr EWord
+ EVM: [$sel:_chainId:Env] :: Env -> W256
+ EVM: [$sel:_code:FrameState] :: FrameState -> ContractCode
+ EVM: [$sel:_codeContract:FrameState] :: FrameState -> Addr
+ EVM: [$sel:_codeOps:Contract] :: Contract -> Vector (Int, Op)
+ EVM: [$sel:_codehash:Contract] :: Contract -> Expr EWord
+ EVM: [$sel:_coinbase:Block] :: Block -> Addr
+ EVM: [$sel:_constraints:VM] :: VM -> [Prop]
+ EVM: [$sel:_contract:FrameState] :: FrameState -> Addr
+ EVM: [$sel:_contractcode:Contract] :: Contract -> ContractCode
+ EVM: [$sel:_contracts:Env] :: Env -> Map Addr Contract
+ EVM: [$sel:_env:VM] :: VM -> Env
+ EVM: [$sel:_external:Contract] :: Contract -> Bool
+ EVM: [$sel:_fetchedContracts:Cache] :: Cache -> Map Addr Contract
+ EVM: [$sel:_fetchedStorage:Cache] :: Cache -> Map W256 (Map W256 W256)
+ EVM: [$sel:_frameContext:Frame] :: Frame -> FrameContext
+ EVM: [$sel:_frameState:Frame] :: Frame -> FrameState
+ EVM: [$sel:_frames:VM] :: VM -> [Frame]
+ EVM: [$sel:_gas:FrameState] :: FrameState -> Word64
+ EVM: [$sel:_gaslimit:Block] :: Block -> Word64
+ EVM: [$sel:_gasprice:TxState] :: TxState -> W256
+ EVM: [$sel:_isCreate:TxState] :: TxState -> Bool
+ EVM: [$sel:_iterations:VM] :: VM -> Map CodeLocation Int
+ EVM: [$sel:_keccakEqs:VM] :: VM -> [Prop]
+ EVM: [$sel:_logs:VM] :: VM -> [Expr Log]
+ EVM: [$sel:_maxCodeSize:Block] :: Block -> W256
+ EVM: [$sel:_memory:FrameState] :: FrameState -> Expr Buf
+ EVM: [$sel:_memorySize:FrameState] :: FrameState -> Word64
+ EVM: [$sel:_nonce:Contract] :: Contract -> W256
+ EVM: [$sel:_number:Block] :: Block -> W256
+ EVM: [$sel:_opIxMap:Contract] :: Contract -> Vector Int
+ EVM: [$sel:_origStorage:Env] :: Env -> Map W256 (Map W256 W256)
+ EVM: [$sel:_origin:TxState] :: TxState -> Addr
+ EVM: [$sel:_overrideCaller:VM] :: VM -> Maybe (Expr EWord)
+ EVM: [$sel:_path:Cache] :: Cache -> Map (CodeLocation, Int) Bool
+ EVM: [$sel:_pc:FrameState] :: FrameState -> Int
+ EVM: [$sel:_prevRandao:Block] :: Block -> W256
+ EVM: [$sel:_refunds:SubState] :: SubState -> [(Addr, Word64)]
+ EVM: [$sel:_result:VM] :: VM -> Maybe VMResult
+ EVM: [$sel:_returndata:FrameState] :: FrameState -> Expr Buf
+ EVM: [$sel:_schedule:Block] :: Block -> FeeSchedule Word64
+ EVM: [$sel:_selfdestructs:SubState] :: SubState -> [Addr]
+ EVM: [$sel:_sha3Crack:Env] :: Env -> Map W256 ByteString
+ EVM: [$sel:_stack:FrameState] :: FrameState -> [Expr EWord]
+ EVM: [$sel:_state:VM] :: VM -> FrameState
+ EVM: [$sel:_static:FrameState] :: FrameState -> Bool
+ EVM: [$sel:_storage:Env] :: Env -> Expr Storage
+ EVM: [$sel:_substate:TxState] :: TxState -> SubState
+ EVM: [$sel:_timestamp:Block] :: Block -> Expr EWord
+ EVM: [$sel:_toAddr:TxState] :: TxState -> Addr
+ EVM: [$sel:_touchedAccounts:SubState] :: SubState -> [Addr]
+ EVM: [$sel:_traceContract:Trace] :: Trace -> Contract
+ EVM: [$sel:_traceData:Trace] :: Trace -> TraceData
+ EVM: [$sel:_traceOpIx:Trace] :: Trace -> Int
+ EVM: [$sel:_traces:VM] :: VM -> TreePos Empty Trace
+ EVM: [$sel:_tx:VM] :: VM -> TxState
+ EVM: [$sel:_txPriorityFee:TxState] :: TxState -> W256
+ EVM: [$sel:_txReversion:TxState] :: TxState -> Map Addr Contract
+ EVM: [$sel:_txgaslimit:TxState] :: TxState -> Word64
+ EVM: [$sel:_value:TxState] :: TxState -> Expr EWord
+ EVM: [$sel:callContextAbi:CreationContext] :: FrameContext -> Maybe W256
+ EVM: [$sel:callContextCodehash:CreationContext] :: FrameContext -> Expr EWord
+ EVM: [$sel:callContextContext:CreationContext] :: FrameContext -> Addr
+ EVM: [$sel:callContextData:CreationContext] :: FrameContext -> Expr Buf
+ EVM: [$sel:callContextOffset:CreationContext] :: FrameContext -> W256
+ EVM: [$sel:callContextReversion:CreationContext] :: FrameContext -> (Map Addr Contract, Expr Storage)
+ EVM: [$sel:callContextSize:CreationContext] :: FrameContext -> W256
+ EVM: [$sel:callContextSubState:CreationContext] :: FrameContext -> SubState
+ EVM: [$sel:callContextTarget:CreationContext] :: FrameContext -> Addr
+ EVM: [$sel:creationContextAddress:CreationContext] :: FrameContext -> Addr
+ EVM: [$sel:creationContextCodehash:CreationContext] :: FrameContext -> Expr EWord
+ EVM: [$sel:creationContextReversion:CreationContext] :: FrameContext -> Map Addr Contract
+ EVM: [$sel:creationContextSubstate:CreationContext] :: FrameContext -> SubState
+ EVM: [$sel:vmoptAddress:VMOpts] :: VMOpts -> Addr
+ EVM: [$sel:vmoptAllowFFI:VMOpts] :: VMOpts -> Bool
+ EVM: [$sel:vmoptBaseFee:VMOpts] :: VMOpts -> W256
+ EVM: [$sel:vmoptBlockGaslimit:VMOpts] :: VMOpts -> Word64
+ EVM: [$sel:vmoptCalldata:VMOpts] :: VMOpts -> (Expr Buf, [Prop])
+ EVM: [$sel:vmoptCaller:VMOpts] :: VMOpts -> Expr EWord
+ EVM: [$sel:vmoptChainId:VMOpts] :: VMOpts -> W256
+ EVM: [$sel:vmoptCoinbase:VMOpts] :: VMOpts -> Addr
+ EVM: [$sel:vmoptContract:VMOpts] :: VMOpts -> Contract
+ EVM: [$sel:vmoptCreate:VMOpts] :: VMOpts -> Bool
+ EVM: [$sel:vmoptGas:VMOpts] :: VMOpts -> Word64
+ EVM: [$sel:vmoptGaslimit:VMOpts] :: VMOpts -> Word64
+ EVM: [$sel:vmoptGasprice:VMOpts] :: VMOpts -> W256
+ EVM: [$sel:vmoptMaxCodeSize:VMOpts] :: VMOpts -> W256
+ EVM: [$sel:vmoptNumber:VMOpts] :: VMOpts -> W256
+ EVM: [$sel:vmoptOrigin:VMOpts] :: VMOpts -> Addr
+ EVM: [$sel:vmoptPrevRandao:VMOpts] :: VMOpts -> W256
+ EVM: [$sel:vmoptPriorityFee:VMOpts] :: VMOpts -> W256
+ EVM: [$sel:vmoptSchedule:VMOpts] :: VMOpts -> FeeSchedule Word64
+ EVM: [$sel:vmoptStorageBase:VMOpts] :: VMOpts -> StorageBase
+ EVM: [$sel:vmoptTimestamp:VMOpts] :: VMOpts -> Expr EWord
+ EVM: [$sel:vmoptTxAccessList:VMOpts] :: VMOpts -> Map Addr [W256]
+ EVM: [$sel:vmoptValue:VMOpts] :: VMOpts -> Expr EWord
+ EVM: overrideCaller :: Lens' VM (Maybe (Expr 'EWord))
+ EVM.Dapp: [$sel:abiMap:DappInfo] :: DappInfo -> Map Word32 Method
+ EVM.Dapp: [$sel:astIdMap:DappInfo] :: DappInfo -> Map Int Value
+ EVM.Dapp: [$sel:astSrcMap:DappInfo] :: DappInfo -> SrcMap -> Maybe Value
+ EVM.Dapp: [$sel:env:DappContext] :: DappContext -> Map Addr Contract
+ EVM.Dapp: [$sel:errorMap:DappInfo] :: DappInfo -> Map W256 SolError
+ EVM.Dapp: [$sel:eventMap:DappInfo] :: DappInfo -> Map W256 Event
+ EVM.Dapp: [$sel:immutableLocations:Code] :: Code -> [Reference]
+ EVM.Dapp: [$sel:info:DappContext] :: DappContext -> DappInfo
+ EVM.Dapp: [$sel:raw:Code] :: Code -> ByteString
+ EVM.Dapp: [$sel:root:DappInfo] :: DappInfo -> FilePath
+ EVM.Dapp: [$sel:solcByCode:DappInfo] :: DappInfo -> [(Code, SolcContract)]
+ EVM.Dapp: [$sel:solcByHash:DappInfo] :: DappInfo -> Map W256 (CodeType, SolcContract)
+ EVM.Dapp: [$sel:solcByName:DappInfo] :: DappInfo -> Map Text SolcContract
+ EVM.Dapp: [$sel:sources:DappInfo] :: DappInfo -> SourceCache
+ EVM.Dapp: [$sel:unitTests:DappInfo] :: DappInfo -> [(Text, [(Test, [AbiType])])]
+ EVM.Facts: [$sel:addr:BalanceFact] :: Fact -> Addr
+ EVM.Facts: [$sel:blob:BalanceFact] :: Fact -> ByteString
+ EVM.Facts: [$sel:dataASCII:Data] :: Data -> ASCII
+ EVM.Facts: [$sel:fileData:File] :: File -> Data
+ EVM.Facts: [$sel:filePath:File] :: File -> Path
+ EVM.Facts: [$sel:what:BalanceFact] :: Fact -> W256
+ EVM.Facts: [$sel:which:BalanceFact] :: Fact -> W256
+ EVM.FeeSchedule: [$sel:g_access_list_address:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_access_list_storage_key:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_balance:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_base:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_blockhash:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_call:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_callstipend:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_callvalue:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_codedeposit:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_cold_account_access:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_cold_sload:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_copy:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_create:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_ecadd:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_ecmul:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_exp:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_expbyte:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_extcode:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_extcodehash:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_fround:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_high:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_jumpdest:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_log:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_logdata:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_logtopic:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_low:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_memory:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_mid:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_newaccount:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_pairing_base:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_pairing_point:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_quaddivisor:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_selfdestruct:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_selfdestruct_newaccount:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_sha3:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_sha3word:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_sload:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_sreset:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_sset:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_transaction:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_txcreate:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_txdatanonzero:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_txdatazero:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_verylow:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_warm_storage_read:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:g_zero:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:r_block:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:r_sclear:FeeSchedule] :: FeeSchedule n -> n
+ EVM.FeeSchedule: [$sel:r_selfdestruct:FeeSchedule] :: FeeSchedule n -> n
+ EVM.Op: OpBaseFee :: Op
+ EVM.SMT: [$sel:blockContext:SMTCex] :: SMTCex -> Map (Expr EWord) W256
+ EVM.SMT: [$sel:blockContextV:CexVars] :: CexVars -> [Text]
+ EVM.SMT: [$sel:buffers:SMTCex] :: SMTCex -> Map (Expr Buf) ByteString
+ EVM.SMT: [$sel:buffersV:CexVars] :: CexVars -> [Text]
+ EVM.SMT: [$sel:calldataV:CexVars] :: CexVars -> [Text]
+ EVM.SMT: [$sel:store:SMTCex] :: SMTCex -> Map W256 (Map W256 W256)
+ EVM.SMT: [$sel:storeReads:CexVars] :: CexVars -> [(Expr EWord, Expr EWord)]
+ EVM.SMT: [$sel:txContext:SMTCex] :: SMTCex -> Map (Expr EWord) W256
+ EVM.SMT: [$sel:txContextV:CexVars] :: CexVars -> [Text]
+ EVM.SMT: [$sel:vars:SMTCex] :: SMTCex -> Map (Expr EWord) W256
+ EVM.SMT: findStorageReads :: Prop -> [(Expr EWord, Expr EWord)]
+ EVM.SMT: getStore :: (Text -> IO Text) -> [(Expr EWord, Expr EWord)] -> IO (Map W256 (Map W256 W256))
+ EVM.SMT: interpret1DArray :: Map Symbol Term -> Term -> W256 -> W256
+ EVM.SMT: interpret2DArray :: Map Symbol Term -> Term -> W256 -> W256 -> W256
+ EVM.SMT: interpretNDArray :: (Map Symbol Term -> Term -> a) -> Map Symbol Term -> Term -> W256 -> a
+ EVM.SMT: isAbstractStorage :: Expr Storage -> Bool
+ EVM.SMT: referencedBlockContextGo :: Expr a -> [Builder]
+ EVM.SMT: referencedBufsGo :: Expr a -> [Builder]
+ EVM.SMT: referencedFrameContextGo :: Expr a -> [Builder]
+ EVM.SMT: referencedVarsGo :: Expr a -> [Builder]
+ EVM.Solidity: [$sel:abiMap:SolcContract] :: SolcContract -> Map Word32 Method
+ EVM.Solidity: [$sel:asts:SourceCache] :: SourceCache -> Map Text Value
+ EVM.Solidity: [$sel:constructorInputs:SolcContract] :: SolcContract -> [(Text, AbiType)]
+ EVM.Solidity: [$sel:contractName:SolcContract] :: SolcContract -> Text
+ EVM.Solidity: [$sel:creationCode:SolcContract] :: SolcContract -> ByteString
+ EVM.Solidity: [$sel:creationCodehash:SolcContract] :: SolcContract -> W256
+ EVM.Solidity: [$sel:creationSrcmap:SolcContract] :: SolcContract -> Seq SrcMap
+ EVM.Solidity: [$sel:errorMap:SolcContract] :: SolcContract -> Map W256 SolError
+ EVM.Solidity: [$sel:eventMap:SolcContract] :: SolcContract -> Map W256 Event
+ EVM.Solidity: [$sel:files:SourceCache] :: SourceCache -> [(Text, ByteString)]
+ EVM.Solidity: [$sel:immutableReferences:SolcContract] :: SolcContract -> Map W256 [Reference]
+ EVM.Solidity: [$sel:inputs:Method] :: Method -> [(Text, AbiType)]
+ EVM.Solidity: [$sel:length:Reference] :: Reference -> Int
+ EVM.Solidity: [$sel:lines:SourceCache] :: SourceCache -> [Vector ByteString]
+ EVM.Solidity: [$sel:methodSignature:Method] :: Method -> Text
+ EVM.Solidity: [$sel:mutability:Method] :: Method -> Mutability
+ EVM.Solidity: [$sel:name:Method] :: Method -> Text
+ EVM.Solidity: [$sel:offset:StorageItem] :: StorageItem -> Int
+ EVM.Solidity: [$sel:output:Method] :: Method -> [(Text, AbiType)]
+ EVM.Solidity: [$sel:runtimeCode:SolcContract] :: SolcContract -> ByteString
+ EVM.Solidity: [$sel:runtimeCodehash:SolcContract] :: SolcContract -> W256
+ EVM.Solidity: [$sel:runtimeSrcmap:SolcContract] :: SolcContract -> Seq SrcMap
+ EVM.Solidity: [$sel:slot:StorageItem] :: StorageItem -> Int
+ EVM.Solidity: [$sel:slotType:StorageItem] :: StorageItem -> SlotType
+ EVM.Solidity: [$sel:srcMapFile:SM] :: SrcMap -> {-# UNPACK #-}Int
+ EVM.Solidity: [$sel:srcMapJump:SM] :: SrcMap -> JumpType
+ EVM.Solidity: [$sel:srcMapLength:SM] :: SrcMap -> {-# UNPACK #-}Int
+ EVM.Solidity: [$sel:srcMapModifierDepth:SM] :: SrcMap -> {-# UNPACK #-}Int
+ EVM.Solidity: [$sel:srcMapOffset:SM] :: SrcMap -> {-# UNPACK #-}Int
+ EVM.Solidity: [$sel:start:Reference] :: Reference -> Int
+ EVM.Solidity: [$sel:storageLayout:SolcContract] :: SolcContract -> Maybe (Map Text StorageItem)
+ EVM.Solvers: Bitwuzla :: Solver
+ EVM.Solvers: CVC5 :: Solver
+ EVM.Solvers: Custom :: Text -> Solver
+ EVM.Solvers: Error :: Text -> CheckSatResult
+ EVM.Solvers: Sat :: SMTCex -> CheckSatResult
+ EVM.Solvers: SolverGroup :: Chan Task -> SolverGroup
+ EVM.Solvers: SolverInstance :: Solver -> Handle -> Handle -> Handle -> ProcessHandle -> SolverInstance
+ EVM.Solvers: Task :: SMT2 -> Chan CheckSatResult -> Task
+ EVM.Solvers: Unknown :: CheckSatResult
+ EVM.Solvers: Unsat :: CheckSatResult
+ EVM.Solvers: Z3 :: Solver
+ EVM.Solvers: [$sel:_process:SolverInstance] :: SolverInstance -> ProcessHandle
+ EVM.Solvers: [$sel:_stderr:SolverInstance] :: SolverInstance -> Handle
+ EVM.Solvers: [$sel:_stdin:SolverInstance] :: SolverInstance -> Handle
+ EVM.Solvers: [$sel:_stdout:SolverInstance] :: SolverInstance -> Handle
+ EVM.Solvers: [$sel:_type:SolverInstance] :: SolverInstance -> Solver
+ EVM.Solvers: [$sel:resultChan:Task] :: Task -> Chan CheckSatResult
+ EVM.Solvers: [$sel:script:Task] :: Task -> SMT2
+ EVM.Solvers: checkSat :: SolverGroup -> SMT2 -> IO CheckSatResult
+ EVM.Solvers: data CheckSatResult
+ EVM.Solvers: data Solver
+ EVM.Solvers: data SolverInstance
+ EVM.Solvers: data Task
+ EVM.Solvers: getValue :: SolverInstance -> Text -> IO Text
+ EVM.Solvers: instance GHC.Classes.Eq EVM.Solvers.CheckSatResult
+ EVM.Solvers: instance GHC.Show.Show EVM.Solvers.CheckSatResult
+ EVM.Solvers: instance GHC.Show.Show EVM.Solvers.Solver
+ EVM.Solvers: isErr :: CheckSatResult -> Bool
+ EVM.Solvers: isSat :: CheckSatResult -> Bool
+ EVM.Solvers: isUnsat :: CheckSatResult -> Bool
+ EVM.Solvers: newtype SolverGroup
+ EVM.Solvers: readSExpr :: Handle -> IO [Text]
+ EVM.Solvers: sendCommand :: SolverInstance -> Text -> IO Text
+ EVM.Solvers: sendLine :: SolverInstance -> Text -> IO Text
+ EVM.Solvers: sendLine' :: SolverInstance -> Text -> IO ()
+ EVM.Solvers: sendScript :: SolverInstance -> SMT2 -> IO (Either Text ())
+ EVM.Solvers: solverArgs :: Solver -> Maybe Natural -> [Text]
+ EVM.Solvers: spawnSolver :: Solver -> Maybe Natural -> IO SolverInstance
+ EVM.Solvers: stopSolver :: SolverInstance -> IO ()
+ EVM.Solvers: withSolvers :: Solver -> Natural -> Maybe Natural -> (SolverGroup -> IO a) -> IO a
+ EVM.SymExec: [$sel:askSmtIters:VeriOpts] :: VeriOpts -> Maybe Integer
+ EVM.SymExec: [$sel:debug:VeriOpts] :: VeriOpts -> Bool
+ EVM.SymExec: [$sel:maxIter:VeriOpts] :: VeriOpts -> Maybe Integer
+ EVM.SymExec: [$sel:rpcInfo:VeriOpts] :: VeriOpts -> RpcInfo
+ EVM.SymExec: [$sel:simp:VeriOpts] :: VeriOpts -> Bool
+ EVM.SymExec: isCex :: ProofResult a b c -> Bool
+ EVM.SymExec: isTimeout :: ProofResult a b c -> Bool
+ EVM.SymExec: type EquivResult = ProofResult () (SMTCex) ()
+ EVM.SymExec: type UnsatCache = TVar [Set Prop]
+ EVM.TTY: [$sel:_browserContractList:UiBrowserState] :: UiBrowserState -> List Name (Addr, Contract)
+ EVM.TTY: [$sel:_browserVm:UiBrowserState] :: UiBrowserState -> UiVmState
+ EVM.TTY: [$sel:_testOpts:UiTestPickerState] :: UiTestPickerState -> UnitTestOptions
+ EVM.TTY: [$sel:_testPickerDapp:UiTestPickerState] :: UiTestPickerState -> DappInfo
+ EVM.TTY: [$sel:_testPickerList:UiTestPickerState] :: UiTestPickerState -> List Name (Text, Text)
+ EVM.TTY: [$sel:_uiShowMemory:UiVmState] :: UiVmState -> Bool
+ EVM.TTY: [$sel:_uiSnapshots:UiVmState] :: UiVmState -> Map Int (VM, Stepper ())
+ EVM.TTY: [$sel:_uiStep:UiVmState] :: UiVmState -> Int
+ EVM.TTY: [$sel:_uiStepper:UiVmState] :: UiVmState -> Stepper ()
+ EVM.TTY: [$sel:_uiTestOpts:UiVmState] :: UiVmState -> UnitTestOptions
+ EVM.TTY: [$sel:_uiVm:UiVmState] :: UiVmState -> VM
+ EVM.Transaction: [$sel:accessAddress:AccessListEntry] :: AccessListEntry -> Addr
+ EVM.Transaction: [$sel:accessStorageKeys:AccessListEntry] :: AccessListEntry -> [W256]
+ EVM.Transaction: [$sel:txAccessList:Transaction] :: Transaction -> [AccessListEntry]
+ EVM.Transaction: [$sel:txData:Transaction] :: Transaction -> ByteString
+ EVM.Transaction: [$sel:txGasLimit:Transaction] :: Transaction -> Word64
+ EVM.Transaction: [$sel:txGasPrice:Transaction] :: Transaction -> Maybe W256
+ EVM.Transaction: [$sel:txMaxFeePerGas:Transaction] :: Transaction -> Maybe W256
+ EVM.Transaction: [$sel:txMaxPriorityFeeGas:Transaction] :: Transaction -> Maybe W256
+ EVM.Transaction: [$sel:txNonce:Transaction] :: Transaction -> W256
+ EVM.Transaction: [$sel:txR:Transaction] :: Transaction -> W256
+ EVM.Transaction: [$sel:txS:Transaction] :: Transaction -> W256
+ EVM.Transaction: [$sel:txToAddr:Transaction] :: Transaction -> Maybe Addr
+ EVM.Transaction: [$sel:txType:Transaction] :: Transaction -> TxType
+ EVM.Transaction: [$sel:txV:Transaction] :: Transaction -> W256
+ EVM.Transaction: [$sel:txValue:Transaction] :: Transaction -> W256
+ EVM.Types: StackUnderrun :: Error
+ EVM.Types: [$sel:addressWord160:Addr] :: Addr -> Word160
+ EVM.Types: pand :: [Prop] -> Prop
+ EVM.Types: por :: [Prop] -> Prop
+ EVM.UnitTest: [$sel:askSmtIters:UnitTestOptions] :: UnitTestOptions -> Maybe Integer
+ EVM.UnitTest: [$sel:covMatch:UnitTestOptions] :: UnitTestOptions -> Maybe Text
+ EVM.UnitTest: [$sel:dapp:UnitTestOptions] :: UnitTestOptions -> DappInfo
+ EVM.UnitTest: [$sel:ffiAllowed:UnitTestOptions] :: UnitTestOptions -> Bool
+ EVM.UnitTest: [$sel:fuzzRuns:UnitTestOptions] :: UnitTestOptions -> Int
+ EVM.UnitTest: [$sel:match:UnitTestOptions] :: UnitTestOptions -> Text
+ EVM.UnitTest: [$sel:maxDepth:UnitTestOptions] :: UnitTestOptions -> Maybe Int
+ EVM.UnitTest: [$sel:maxIter:UnitTestOptions] :: UnitTestOptions -> Maybe Integer
+ EVM.UnitTest: [$sel:replay:UnitTestOptions] :: UnitTestOptions -> Maybe (Text, ByteString)
+ EVM.UnitTest: [$sel:rpcInfo:UnitTestOptions] :: UnitTestOptions -> RpcInfo
+ EVM.UnitTest: [$sel:smtDebug:UnitTestOptions] :: UnitTestOptions -> Bool
+ EVM.UnitTest: [$sel:smtTimeout:UnitTestOptions] :: UnitTestOptions -> Maybe Natural
+ EVM.UnitTest: [$sel:solver:UnitTestOptions] :: UnitTestOptions -> Maybe Text
+ EVM.UnitTest: [$sel:solvers:UnitTestOptions] :: UnitTestOptions -> SolverGroup
+ EVM.UnitTest: [$sel:srcContract:OpLocation] :: OpLocation -> Contract
+ EVM.UnitTest: [$sel:srcOpIx:OpLocation] :: OpLocation -> Int
+ EVM.UnitTest: [$sel:testAddress:TestVMParams] :: TestVMParams -> Addr
+ EVM.UnitTest: [$sel:testBalanceCreate:TestVMParams] :: TestVMParams -> W256
+ EVM.UnitTest: [$sel:testBaseFee:TestVMParams] :: TestVMParams -> W256
+ EVM.UnitTest: [$sel:testCaller:TestVMParams] :: TestVMParams -> Addr
+ EVM.UnitTest: [$sel:testChainId:TestVMParams] :: TestVMParams -> W256
+ EVM.UnitTest: [$sel:testCoinbase:TestVMParams] :: TestVMParams -> Addr
+ EVM.UnitTest: [$sel:testGasCall:TestVMParams] :: TestVMParams -> Word64
+ EVM.UnitTest: [$sel:testGasCreate:TestVMParams] :: TestVMParams -> Word64
+ EVM.UnitTest: [$sel:testGaslimit:TestVMParams] :: TestVMParams -> Word64
+ EVM.UnitTest: [$sel:testGasprice:TestVMParams] :: TestVMParams -> W256
+ EVM.UnitTest: [$sel:testMaxCodeSize:TestVMParams] :: TestVMParams -> W256
+ EVM.UnitTest: [$sel:testNumber:TestVMParams] :: TestVMParams -> W256
+ EVM.UnitTest: [$sel:testOrigin:TestVMParams] :: TestVMParams -> Addr
+ EVM.UnitTest: [$sel:testParams:UnitTestOptions] :: UnitTestOptions -> TestVMParams
+ EVM.UnitTest: [$sel:testPrevrandao:TestVMParams] :: TestVMParams -> W256
+ EVM.UnitTest: [$sel:testPriorityFee:TestVMParams] :: TestVMParams -> W256
+ EVM.UnitTest: [$sel:testTimestamp:TestVMParams] :: TestVMParams -> W256
+ EVM.UnitTest: [$sel:verbose:UnitTestOptions] :: UnitTestOptions -> Maybe Int
+ EVM.UnitTest: [$sel:vmModifier:UnitTestOptions] :: UnitTestOptions -> VM -> VM
- EVM: VM :: Maybe VMResult -> FrameState -> [Frame] -> Env -> Block -> TxState -> [Expr Log] -> TreePos Empty Trace -> Cache -> Word64 -> Map CodeLocation Int -> [Prop] -> [Prop] -> Bool -> VM
+ EVM: VM :: Maybe VMResult -> FrameState -> [Frame] -> Env -> Block -> TxState -> [Expr Log] -> TreePos Empty Trace -> Cache -> Word64 -> Map CodeLocation Int -> [Prop] -> [Prop] -> Bool -> Maybe (Expr EWord) -> VM
- EVM: traceTopLog :: MonadState VM m => [Expr Log] -> m ()
+ EVM: traceTopLog :: [Expr Log] -> EVM ()
- EVM: withTraceLocation :: MonadState VM m => TraceData -> m Trace
+ EVM: withTraceLocation :: TraceData -> EVM Trace
- EVM.Exec: exec :: MonadState VM m => m VMResult
+ EVM.Exec: exec :: State VM VMResult
- EVM.Exec: execWhile :: MonadState VM m => (VM -> Bool) -> m Int
+ EVM.Exec: execWhile :: (VM -> Bool) -> State VM Int
- EVM.Exec: run :: MonadState VM m => m VM
+ EVM.Exec: run :: State VM VM
- EVM.SMT: CexVars :: [Text] -> [Text] -> [Text] -> [Text] -> CexVars
+ EVM.SMT: CexVars :: [Text] -> [Text] -> [(Expr EWord, Expr EWord)] -> [Text] -> [Text] -> CexVars
- EVM.SMT: SMTCex :: Map (Expr EWord) W256 -> Map (Expr Buf) ByteString -> Map (Expr EWord) W256 -> Map (Expr EWord) W256 -> SMTCex
+ EVM.SMT: SMTCex :: Map (Expr EWord) W256 -> Map (Expr Buf) ByteString -> Map W256 (Map W256 W256) -> Map (Expr EWord) W256 -> Map (Expr EWord) W256 -> SMTCex
- EVM.SMT: getBufs :: SolverInstance -> [Text] -> IO (Map (Expr Buf) ByteString)
+ EVM.SMT: getBufs :: (Text -> IO Text) -> [Text] -> IO (Map (Expr Buf) ByteString)
- EVM.SMT: getVars :: (Text -> Expr EWord) -> SolverInstance -> [Text] -> IO (Map (Expr EWord) W256)
+ EVM.SMT: getVars :: (Text -> Expr EWord) -> (Text -> IO Text) -> [Text] -> IO (Map (Expr EWord) W256)
- EVM.SymExec: equivalenceCheck :: SolverGroup -> ByteString -> ByteString -> VeriOpts -> Maybe (Text, [AbiType]) -> IO [(Maybe SMTCex, Prop, ProofResult () () ())]
+ EVM.SymExec: equivalenceCheck :: SolverGroup -> ByteString -> ByteString -> VeriOpts -> Maybe (Text, [AbiType]) -> IO [EquivResult]

Files

CHANGELOG.md view
@@ -5,6 +5,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.50.3] - 2023-02-17++### Fixed++- `hevm symbolic` exits with status code `1` if counterexamples or timeouts are found++### Added++- New cheatcode `prank(address)` that sets `msg.sender` to the specified address for the next call.+- Improved equivalence checker that avoids checking similar branches more than once.+- Improved simplification for arithmetic expressions+- Construction of storage counterexamples based on the model returned by the SMT solver.+- Static binaries for macos+ ## [0.50.2] - 2023-01-06  ### Fixed
+ bench/bench.hs view
@@ -0,0 +1,85 @@+module Main where++import GHC.Natural++import qualified Paths_hevm as Paths++import Test.Tasty (localOption)+import Test.Tasty.Bench+import Data.Functor+import Data.String.Here+import Data.ByteString (ByteString)+import qualified Data.Text as T++import EVM (StorageModel(..))+import EVM.SymExec+import EVM.Solidity+import EVM.Solvers+import EVM.ABI+import EVM.Dapp+import EVM.Types+import qualified EVM.TTY as TTY++findPanics :: Solver -> Natural -> Maybe Integer -> ByteString -> IO ()+findPanics solver count iters c = do+  (_, res) <- withSolvers solver count Nothing $ \s -> do+    let opts = defaultVeriOpts+          { maxIter = iters+          , askSmtIters = (+ 1) <$> iters+          }+    checkAssert s allPanicCodes c Nothing [] opts+  putStrLn "done"+++-- constructs a benchmark suite that checks the given bytecode for reachable+-- assertion violations takes an iteration bound, as well as a list of solver+-- counts to benchmark, allowing us to construct benchmarks that compare the+-- performance impact of increasing solver parallelisation+mkbench :: IO ByteString -> String -> Maybe Integer -> [Natural] -> Benchmark+mkbench c name iters counts = localOption WallTime $ env c (bgroup name . bmarks)+  where+    bmarks c' = concat $ [+       [ bench ("cvc5-" <> show i) $ nfIO $ findPanics CVC5 i iters c'+       , bench ("z3-" <> show i) $ nfIO $ findPanics Z3 i iters c'+       ]+       | i <- counts+     ]++main :: IO ()+main = defaultMain+  [ mkbench erc20 "erc20" Nothing [1, 2, 4, 8, 16]+  , mkbench (pure vat) "vat" Nothing [4]+  , mkbench (pure deposit) "deposit" (Just 32) [4]+  , mkbench (pure uniV2Pair) "uniV2" (Just 10) [4]+  ]+++--- Helpers ----------------------------------------------------------------------------------------+++debugContract :: ByteString -> IO ()+debugContract c = withSolvers CVC5 4 Nothing $ \solvers -> do+  let prestate = abstractVM Nothing [] c Nothing SymbolicS+  void $ TTY.runFromVM solvers Nothing Nothing emptyDapp prestate+++--- Bytecodes --------------------------------------------------------------------------------------+++erc20 :: IO ByteString+erc20 = do+  source <- readFile =<< Paths.getDataFileName "bench/contracts/erc20.sol"+  Just c <- solcRuntime "ERC20" (T.pack source)+  pure c++-- requires solc-0.6.12 to build from source+vat :: ByteString+vat = hexByteString "vat" "608060405234801561001057600080fd5b50600436106101c45760003560e01c80637cdd3fde116100f9578063bb35783b11610097578063dc4d20fa11610071578063dc4d20fa1461096c578063f059212a146109b0578063f24e23eb14610a08578063f37ac61c14610a76576101c4565b8063bb35783b14610848578063bf353dbb146108b6578063d9638d361461090e576101c4565b80639c52a7f1116100d35780639c52a7f11461074a578063a3b22fc41461078e578063b65337df146107d2578063babe8a3f1461082a576101c4565b80637cdd3fde14610652578063870c616d146106aa578063957aa58c1461072c576101c4565b80634538c4eb11610166578063692450091161014057806369245009146104ac5780636c25b346146104b6578063760887031461050e5780637bab3f40146105b0576101c4565b80634538c4eb146103785780636111be2e146103f057806365fae35e14610468576101c4565b80632424be5c116101a25780632424be5c1461028b57806329ae8114146102f45780632d61a3551461032c5780633b6631951461034a576101c4565b80630dca59c1146101c95780631a0b287e146101e7578063214414d514610229575b600080fd5b6101d1610aa4565b6040518082815260200191505060405180910390f35b610227600480360360608110156101fd57600080fd5b81019080803590602001909291908035906020019092919080359060200190929190505050610aaa565b005b6102756004803603604081101561023f57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d23565b6040518082815260200191505060405180910390f35b6102d7600480360360408110156102a157600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610d48565b604051808381526020018281526020019250505060405180910390f35b61032a6004803603604081101561030a57600080fd5b810190808035906020019092919080359060200190929190505050610d79565b005b610334610f4b565b6040518082815260200191505060405180910390f35b6103766004803603602081101561036057600080fd5b8101908080359060200190929190505050610f51565b005b6103da6004803603604081101561038e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506110bb565b6040518082815260200191505060405180910390f35b6104666004803603608081101561040657600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506110e0565b005b6104aa6004803603602081101561047e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506112be565b005b6104b4611431565b005b6104f8600480360360208110156104cc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506114ef565b6040518082815260200191505060405180910390f35b6105ae600480360360c081101561052457600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190505050611507565b005b610650600480360360c08110156105c657600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190505050611cbe565b005b6106a86004803603606081101561066857600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611f88565b005b61072a600480360360a08110156106c057600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803590602001909291905050506120ef565b005b6107346124ee565b6040518082815260200191505060405180910390f35b61078c6004803603602081101561076057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506124f4565b005b6107d0600480360360208110156107a457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612667565b005b610828600480360360608110156107e857600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506126eb565b005b6108326128fb565b6040518082815260200191505060405180910390f35b6108b46004803603606081101561085e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612901565b005b6108f8600480360360208110156108cc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612a9a565b6040518082815260200191505060405180910390f35b61093a6004803603602081101561092457600080fd5b8101908080359060200190929190505050612ab2565b604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390f35b6109ae6004803603602081101561098257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612ae8565b005b6109f2600480360360208110156109c657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612b6d565b6040518082815260200191505060405180910390f35b610a7460048036036060811015610a1e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050612b85565b005b610aa260048036036020811015610a8c57600080fd5b8101908080359060200190929190505050612d7a565b005b60075481565b60016000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414610b5e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f5661742f6e6f742d617574686f72697a6564000000000000000000000000000081525060200191505060405180910390fd5b6001600a5414610bd6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f5661742f6e6f742d6c697665000000000000000000000000000000000000000081525060200191505060405180910390fd5b7f73706f7400000000000000000000000000000000000000000000000000000000821415610c1e57806002600085815260200190815260200160002060020181905550610d1e565b7f6c696e6500000000000000000000000000000000000000000000000000000000821415610c6657806002600085815260200190815260200160002060030181905550610d1d565b7f6475737400000000000000000000000000000000000000000000000000000000821415610cae57806002600085815260200190815260200160002060040181905550610d1c565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f5661742f66696c652d756e7265636f676e697a65642d706172616d000000000081525060200191505060405180910390fd5b5b5b505050565b6004602052816000526040600020602052806000526040600020600091509150505481565b6003602052816000526040600020602052806000526040600020600091509150508060000154908060010154905082565b60016000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414610e2d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f5661742f6e6f742d617574686f72697a6564000000000000000000000000000081525060200191505060405180910390fd5b6001600a5414610ea5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f5661742f6e6f742d6c697665000000000000000000000000000000000000000081525060200191505060405180910390fd5b7f4c696e6500000000000000000000000000000000000000000000000000000000821415610ed95780600981905550610f47565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f5661742f66696c652d756e7265636f676e697a65642d706172616d000000000081525060200191505060405180910390fd5b5050565b60085481565b60016000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414611005576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f5661742f6e6f742d617574686f72697a6564000000000000000000000000000081525060200191505060405180910390fd5b6000600260008381526020019081526020016000206001015414611091576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5661742f696c6b2d616c72656164792d696e697400000000000000000000000081525060200191505060405180910390fd5b6b033b2e3c9fd0803ce8000000600260008381526020019081526020016000206001018190555050565b6001602052816000526040600020602052806000526040600020600091509150505481565b6110ea8333612ebf565b61115c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5661742f6e6f742d616c6c6f776564000000000000000000000000000000000081525060200191505060405180910390fd5b6111b66004600086815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482612f7f565b6004600086815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506112646004600086815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482612f99565b6004600086815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050505050565b60016000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414611372576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f5661742f6e6f742d617574686f72697a6564000000000000000000000000000081525060200191505060405180910390fd5b6001600a54146113ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f5661742f6e6f742d6c697665000000000000000000000000000000000000000081525060200191505060405180910390fd5b60016000808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050565b60016000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054146114e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f5661742f6e6f742d617574686f72697a6564000000000000000000000000000081525060200191505060405180910390fd5b6000600a81905550565b60056020528060005260406000206000915090505481565b6001600a541461157f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f5661742f6e6f742d6c697665000000000000000000000000000000000000000081525060200191505060405180910390fd5b6115876130b2565b6003600088815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060400160405290816000820154815260200160018201548152505090506116006130cc565b600260008981526020019081526020016000206040518060a00160405290816000820154815260200160018201548152602001600282015481526020016003820154815260200160048201548152505090506000816020015114156116cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5661742f696c6b2d6e6f742d696e69740000000000000000000000000000000081525060200191505060405180910390fd5b6116db826000015185612fb3565b8260000181815250506116f2826020015184612fb3565b826020018181525050611709816000015184612fb3565b8160000181815250506000611722826020015185612ff2565b905060006117388360200151856020015161302d565b905061174660075483612fb3565b600781905550611782600086131561177d856060015161176e8760000151886020015161302d565b11156009546007541115613059565b613066565b6117f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f5661742f6365696c696e672d657863656564656400000000000000000000000081525060200191505060405180910390fd5b61182361180960008713156000891215613059565b61181b8660000151866040015161302d565b831115613066565b611895576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f5661742f6e6f742d73616665000000000000000000000000000000000000000081525060200191505060405180910390fd5b6118b96118aa60008713156000891215613059565b6118b48b33612ebf565b613066565b61192b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f5661742f6e6f742d616c6c6f7765642d7500000000000000000000000000000081525060200191505060405180910390fd5b611942600087131561193d8a33612ebf565b613066565b6119b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f5661742f6e6f742d616c6c6f7765642d7600000000000000000000000000000081525060200191505060405180910390fd5b6119cb60008612156119c68933612ebf565b613066565b611a3d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f5661742f6e6f742d616c6c6f7765642d7700000000000000000000000000000081525060200191505060405180910390fd5b611a5560008560200151148460800151831015613066565b611ac7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260088152602001807f5661742f6475737400000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b611b21600460008c815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205487613073565b600460008c815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611bbe600560008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483612fb3565b600560008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555083600360008c815260200190815260200160002060008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082015181600001556020820151816001015590505082600260008c8152602001908152602001600020600082015181600001556020820151816001015560408201518160020155606082015181600301556080820151816004015590505050505050505050505050565b60016000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414611d72576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f5661742f6e6f742d617574686f72697a6564000000000000000000000000000081525060200191505060405180910390fd5b60006003600088815260200190815260200160002060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000600260008981526020019081526020016000209050611deb826000015485612fb3565b8260000181905550611e01826001015484612fb3565b8260010181905550611e17816000015484612fb3565b81600001819055506000611e2f826001015485612ff2565b9050611e8b600460008b815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205486613073565b600460008b815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611f28600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482613073565b600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550611f7760085482613073565b600881905550505050505050505050565b60016000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541461203c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f5661742f6e6f742d617574686f72697a6564000000000000000000000000000081525060200191505060405180910390fd5b6120966004600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482612fb3565b6004600085815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505050565b60006003600087815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060006003600088815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060006002600089815260200190815260200160002090506121bc836000015486613073565b83600001819055506121d2836001015485613073565b83600101819055506121e8826000015486612fb3565b82600001819055506121fe826001015485612fb3565b8260010181905550600061221a8460010154836001015461302d565b905060006122308460010154846001015461302d565b905061224e61223f8a33612ebf565b6122498a33612ebf565b613059565b6122c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5661742f6e6f742d616c6c6f776564000000000000000000000000000000000081525060200191505060405180910390fd5b6122d28560000154846002015461302d565b821115612347576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5661742f6e6f742d736166652d7372630000000000000000000000000000000081525060200191505060405180910390fd5b6123598460000154846002015461302d565b8111156123ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f5661742f6e6f742d736166652d6473740000000000000000000000000000000081525060200191505060405180910390fd5b6123e683600401548310156000876001015414613066565b612458576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f5661742f647573742d737263000000000000000000000000000000000000000081525060200191505060405180910390fd5b61247083600401548210156000866001015414613066565b6124e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f5661742f647573742d647374000000000000000000000000000000000000000081525060200191505060405180910390fd5b50505050505050505050565b600a5481565b60016000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054146125a8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f5661742f6e6f742d617574686f72697a6564000000000000000000000000000081525060200191505060405180910390fd5b6001600a5414612620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f5661742f6e6f742d6c697665000000000000000000000000000000000000000081525060200191505060405180910390fd5b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050565b60018060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050565b60016000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541461279f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f5661742f6e6f742d617574686f72697a6564000000000000000000000000000081525060200191505060405180910390fd5b6001600a5414612817576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f5661742f6e6f742d6c697665000000000000000000000000000000000000000081525060200191505060405180910390fd5b600060026000858152602001908152602001600020905061283c816001015483612fb3565b81600101819055506000612854826000015484612ff2565b905061289f600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482612fb3565b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506128ee60075482612fb3565b6007819055505050505050565b60095481565b61290b8333612ebf565b61297d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f5661742f6e6f742d616c6c6f776564000000000000000000000000000000000081525060200191505060405180910390fd5b6129c6600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482612f7f565b600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612a52600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482612f99565b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550505050565b60006020528060005260406000206000915090505481565b60026020528060005260406000206000915090508060000154908060010154908060020154908060030154908060040154905085565b6000600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555050565b60066020528060005260406000206000915090505481565b60016000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414612c39576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f5661742f6e6f742d617574686f72697a6564000000000000000000000000000081525060200191505060405180910390fd5b612c82600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482612f99565b600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612d0e600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205482612f99565b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612d5d60085482612f99565b600881905550612d6f60075482612f99565b600781905550505050565b6000339050612dc8600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483612f7f565b600660008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612e54600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205483612f7f565b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550612ea360085483612f7f565b600881905550612eb560075483612f7f565b6007819055505050565b6000612f778273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161460018060008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205414613066565b905092915050565b6000828284039150811115612f9357600080fd5b92915050565b6000828284019150811015612fad57600080fd5b92915050565b60008183019050600082121580612fca5750828111155b612fd357600080fd5b600082131580612fe35750828110155b612fec57600080fd5b92915050565b60008183029050600083121561300757600080fd5b600082148061301e57508282828161301b57fe5b05145b61302757600080fd5b92915050565b60008082148061304a575082828385029250828161304757fe5b04145b61305357600080fd5b92915050565b6000818316905092915050565b6000818317905092915050565b6000818303905060008213158061308a5750828111155b61309357600080fd5b6000821215806130a35750828110155b6130ac57600080fd5b92915050565b604051806040016040528060008152602001600081525090565b6040518060a001604052806000815260200160008152602001600081526020016000815260200160008152509056fea2646970667358221220a6981c73e66c77a4325e4426a14f7d3876fbe831438d34792d1fdac37b02a51d64736f6c634300060c0033"++-- requires solc-0.6.13 to build+deposit :: ByteString+deposit = hexByteString "deposit" "60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100b6578063621fd130146101e3578063c5f2892f14610273575b600080fd5b34801561005057600080fd5b5061009c6004803603602081101561006757600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061029e565b604051808215151515815260200191505060405180910390f35b6101e1600480360360808110156100cc57600080fd5b81019080803590602001906401000000008111156100e957600080fd5b8201836020820111156100fb57600080fd5b8035906020019184600183028401116401000000008311171561011d57600080fd5b90919293919293908035906020019064010000000081111561013e57600080fd5b82018360208201111561015057600080fd5b8035906020019184600183028401116401000000008311171561017257600080fd5b90919293919293908035906020019064010000000081111561019357600080fd5b8201836020820111156101a557600080fd5b803590602001918460018302840111640100000000831117156101c757600080fd5b909192939192939080359060200190929190505050610370565b005b3480156101ef57600080fd5b506101f8610fd0565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561023857808201518184015260208101905061021d565b50505050905090810190601f1680156102655780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561027f57600080fd5b50610288610fe2565b6040518082815260200191505060405180910390f35b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061036957507f85640907000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b603087879050146103cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806116ec6026913960400191505060405180910390fd5b60208585905014610428576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806116836036913960400191505060405180910390fd5b60608383905014610484576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061175f6029913960400191505060405180910390fd5b670de0b6b3a76400003410156104e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806117396026913960400191505060405180910390fd5b6000633b9aca0034816104f457fe5b061461054b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806116b96033913960400191505060405180910390fd5b6000633b9aca00348161055a57fe5b04905067ffffffffffffffff80168111156105c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806117126027913960400191505060405180910390fd5b60606105cb82611314565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a610600602054611314565b60405180806020018060200180602001806020018060200186810386528e8e82818152602001925080828437600081840152601f19601f82011690508083019250505086810385528c8c82818152602001925080828437600081840152601f19601f82011690508083019250505086810384528a818151815260200191508051906020019080838360005b838110156106a657808201518184015260208101905061068b565b50505050905090810190601f1680156106d35780820380516001836020036101000a031916815260200191505b508681038352898982818152602001925080828437600081840152601f19601f820116905080830192505050868103825287818151815260200191508051906020019080838360005b8381101561073757808201518184015260208101905061071c565b50505050905090810190601f1680156107645780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b6040516020018084848082843780830192505050826fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff1916815260100193505050506040516020818303038152906040526040518082805190602001908083835b6020831061080e57805182526020820191506020810190506020830392506107eb565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610850573d6000803e3d6000fd5b5050506040513d602081101561086557600080fd5b8101908080519060200190929190505050905060006002808888600090604092610891939291906115da565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108eb57805182526020820191506020810190506020830392506108c8565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa15801561092d573d6000803e3d6000fd5b5050506040513d602081101561094257600080fd5b8101908080519060200190929190505050600289896040908092610968939291906115da565b6000801b604051602001808484808284378083019250505082815260200193505050506040516020818303038152906040526040518082805190602001908083835b602083106109cd57805182526020820191506020810190506020830392506109aa565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610a0f573d6000803e3d6000fd5b5050506040513d6020811015610a2457600080fd5b810190808051906020019092919050505060405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610a8e5780518252602082019150602081019050602083039250610a6b565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610ad0573d6000803e3d6000fd5b5050506040513d6020811015610ae557600080fd5b810190808051906020019092919050505090506000600280848c8c604051602001808481526020018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610b615780518252602082019150602081019050602083039250610b3e565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610ba3573d6000803e3d6000fd5b5050506040513d6020811015610bb857600080fd5b8101908080519060200190929190505050600286600060401b866040516020018084805190602001908083835b60208310610c085780518252602082019150602081019050602083039250610be5565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610c935780518252602082019150602081019050602083039250610c70565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610cd5573d6000803e3d6000fd5b5050506040513d6020811015610cea57600080fd5b810190808051906020019092919050505060405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610d545780518252602082019150602081019050602083039250610d31565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610d96573d6000803e3d6000fd5b5050506040513d6020811015610dab57600080fd5b81019080805190602001909291905050509050858114610e16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252605481526020018061162f6054913960600191505060405180910390fd5b6001602060020a0360205410610e77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061160e6021913960400191505060405180910390fd5b60016020600082825401925050819055506000602054905060008090505b6020811015610fb75760018083161415610ec8578260008260208110610eb757fe5b018190555050505050505050610fc7565b600260008260208110610ed757fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610f335780518252602082019150602081019050602083039250610f10565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610f75573d6000803e3d6000fd5b5050506040513d6020811015610f8a57600080fd5b8101908080519060200190929190505050925060028281610fa757fe5b0491508080600101915050610e95565b506000610fc057fe5b5050505050505b50505050505050565b6060610fdd602054611314565b905090565b6000806000602054905060008090505b60208110156111d057600180831614156110e05760026000826020811061101557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310611071578051825260208201915060208101905060208303925061104e565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa1580156110b3573d6000803e3d6000fd5b5050506040513d60208110156110c857600080fd5b810190808051906020019092919050505092506111b6565b600283602183602081106110f057fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061114b5780518252602082019150602081019050602083039250611128565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa15801561118d573d6000803e3d6000fd5b5050506040513d60208110156111a257600080fd5b810190808051906020019092919050505092505b600282816111c057fe5b0491508080600101915050610ff2565b506002826111df602054611314565b600060401b6040516020018084815260200183805190602001908083835b6020831061122057805182526020820191506020810190506020830392506111fd565b6001836020036101000a0380198251168184511680821785525050505050509050018267ffffffffffffffff191667ffffffffffffffff1916815260180193505050506040516020818303038152906040526040518082805190602001908083835b602083106112a55780518252602082019150602081019050602083039250611282565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa1580156112e7573d6000803e3d6000fd5b5050506040513d60208110156112fc57600080fd5b81019080805190602001909291905050509250505090565b6060600867ffffffffffffffff8111801561132e57600080fd5b506040519080825280601f01601f1916602001820160405280156113615781602001600182028036833780820191505090505b50905060008260c01b90508060076008811061137957fe5b1a60f81b8260008151811061138a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806006600881106113c657fe5b1a60f81b826001815181106113d757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060056008811061141357fe5b1a60f81b8260028151811061142457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060046008811061146057fe5b1a60f81b8260038151811061147157fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806003600881106114ad57fe5b1a60f81b826004815181106114be57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806002600881106114fa57fe5b1a60f81b8260058151811061150b57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060016008811061154757fe5b1a60f81b8260068151811061155857fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060006008811061159457fe5b1a60f81b826007815181106115a557fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b600080858511156115ea57600080fd5b838611156115f757600080fd5b600185028301915084860390509450949250505056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a2646970667358221220e859959599195b69dd53a5a8e7d6218056606794a75a0aadd9fecf8dc64eae7064736f6c634300060b0033"++-- requires waffle to be installed to build+uniV2Pair :: ByteString+uniV2Pair = hexByteString "uniV2" "608060405234801561001057600080fd5b50600436106101a95760003560e01c80636a627842116100f9578063ba9a7a5611610097578063d21220a711610071578063d21220a7146108c4578063d505accf1461090e578063dd62ed3e146109a7578063fff6cae914610a1f576101a9565b8063ba9a7a5614610818578063bc25cf7714610836578063c45a01551461087a576101a9565b80637ecebe00116100d35780637ecebe001461067857806389afcb44146106d057806395d89b411461072f578063a9059cbb146107b2576101a9565b80636a627842146105aa57806370a08231146106025780637464fc3d1461065a576101a9565b806323b872dd116101665780633644e515116101405780633644e515146104ec578063485cc9551461050a5780635909c0d51461056e5780635a3d54931461058c576101a9565b806323b872dd1461042457806330adf81f146104aa578063313ce567146104c8576101a9565b8063022c0d9f146101ae57806306fdde031461025b5780630902f1ac146102de578063095ea7b3146103565780630dfe1681146103bc57806318160ddd14610406575b600080fd5b610259600480360360808110156101c457600080fd5b810190808035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561021557600080fd5b82018360208201111561022757600080fd5b8035906020019184600183028401116401000000008311171561024957600080fd5b9091929391929390505050610a29565b005b610263611216565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102a3578082015181840152602081019050610288565b50505050905090810190601f1680156102d05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102e661124f565b60405180846dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff168152602001836dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff1681526020018263ffffffff1663ffffffff168152602001935050505060405180910390f35b6103a26004803603604081101561036c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506112ac565b604051808215151515815260200191505060405180910390f35b6103c46112c3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61040e6112e9565b6040518082815260200191505060405180910390f35b6104906004803603606081101561043a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506112ef565b604051808215151515815260200191505060405180910390f35b6104b26114ba565b6040518082815260200191505060405180910390f35b6104d06114e1565b604051808260ff1660ff16815260200191505060405180910390f35b6104f46114e6565b6040518082815260200191505060405180910390f35b61056c6004803603604081101561052057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506114ec565b005b610576611635565b6040518082815260200191505060405180910390f35b61059461163b565b6040518082815260200191505060405180910390f35b6105ec600480360360208110156105c057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611641565b6040518082815260200191505060405180910390f35b6106446004803603602081101561061857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611af2565b6040518082815260200191505060405180910390f35b610662611b0a565b6040518082815260200191505060405180910390f35b6106ba6004803603602081101561068e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611b10565b6040518082815260200191505060405180910390f35b610712600480360360208110156106e657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050611b28565b604051808381526020018281526020019250505060405180910390f35b610737612115565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561077757808201518184015260208101905061075c565b50505050905090810190601f1680156107a45780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6107fe600480360360408110156107c857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061214e565b604051808215151515815260200191505060405180910390f35b610820612165565b6040518082815260200191505060405180910390f35b6108786004803603602081101561084c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061216b565b005b610882612446565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6108cc61246c565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6109a5600480360360e081101561092457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050612492565b005b610a09600480360360408110156109bd57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506127d6565b6040518082815260200191505060405180910390f35b610a276127fb565b005b6001600c5414610aa1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f556e697377617056323a204c4f434b454400000000000000000000000000000081525060200191505060405180910390fd5b6000600c819055506000851180610ab85750600084115b610b0d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061397c6025913960400191505060405180910390fd5b600080610b1861124f565b5091509150816dffffffffffffffffffffffffffff1687108015610b4b5750806dffffffffffffffffffffffffffff1686105b610ba0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806139c56021913960400191505060405180910390fd5b6000806000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508173ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614158015610c5957508073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614155b610ccb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f556e697377617056323a20494e56414c49445f544f000000000000000000000081525060200191505060405180910390fd5b60008b1115610ce057610cdf828a8d612a7b565b5b60008a1115610cf557610cf4818a8c612a7b565b5b6000888890501115610ddd578873ffffffffffffffffffffffffffffffffffffffff166310d1e85c338d8d8c8c6040518663ffffffff1660e01b8152600401808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001858152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509650505050505050600060405180830381600087803b158015610dc457600080fd5b505af1158015610dd8573d6000803e3d6000fd5b505050505b8173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610e5a57600080fd5b505afa158015610e6e573d6000803e3d6000fd5b505050506040513d6020811015610e8457600080fd5b810190808051906020019092919050505093508073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610f1457600080fd5b505afa158015610f28573d6000803e3d6000fd5b505050506040513d6020811015610f3e57600080fd5b810190808051906020019092919050505092505050600089856dffffffffffffffffffffffffffff16038311610f75576000610f8b565b89856dffffffffffffffffffffffffffff160383035b9050600089856dffffffffffffffffffffffffffff16038311610faf576000610fc5565b89856dffffffffffffffffffffffffffff160383035b90506000821180610fd65750600081115b61102b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806139a16024913960400191505060405180910390fd5b6000611067611044600385612cc890919063ffffffff16565b6110596103e888612cc890919063ffffffff16565b612d5d90919063ffffffff16565b905060006110a5611082600385612cc890919063ffffffff16565b6110976103e888612cc890919063ffffffff16565b612d5d90919063ffffffff16565b90506110ef620f42406110e1896dffffffffffffffffffffffffffff168b6dffffffffffffffffffffffffffff16612cc890919063ffffffff16565b612cc890919063ffffffff16565b6111028284612cc890919063ffffffff16565b1015611176576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600c8152602001807f556e697377617056323a204b000000000000000000000000000000000000000081525060200191505060405180910390fd5b505061118484848888612de0565b8873ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d82284848f8f6040518085815260200184815260200183815260200182815260200194505050505060405180910390a35050505050506001600c819055505050505050565b6040518060400160405280600a81526020017f556e69737761702056320000000000000000000000000000000000000000000081525081565b6000806000600860009054906101000a90046dffffffffffffffffffffffffffff1692506008600e9054906101000a90046dffffffffffffffffffffffffffff1691506008601c9054906101000a900463ffffffff169050909192565b60006112b933848461315e565b6001905092915050565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60005481565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054146114a45761142382600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612d5d90919063ffffffff16565b600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505b6114af848484613249565b600190509392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c960001b81565b601281565b60035481565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146115af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f556e697377617056323a20464f5242494444454e00000000000000000000000081525060200191505060405180910390fd5b81600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050565b60095481565b600a5481565b60006001600c54146116bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f556e697377617056323a204c4f434b454400000000000000000000000000000081525060200191505060405180910390fd5b6000600c819055506000806116ce61124f565b50915091506000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561177457600080fd5b505afa158015611788573d6000803e3d6000fd5b505050506040513d602081101561179e57600080fd5b810190808051906020019092919050505090506000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561185257600080fd5b505afa158015611866573d6000803e3d6000fd5b505050506040513d602081101561187c57600080fd5b8101908080519060200190929190505050905060006118b4856dffffffffffffffffffffffffffff1684612d5d90919063ffffffff16565b905060006118db856dffffffffffffffffffffffffffff1684612d5d90919063ffffffff16565b905060006118e987876133dd565b9050600080549050600081141561193d576119296103e861191b6119168688612cc890919063ffffffff16565b6135be565b612d5d90919063ffffffff16565b985061193860006103e8613620565b6119a0565b61199d886dffffffffffffffffffffffffffff166119648387612cc890919063ffffffff16565b8161196b57fe5b04886dffffffffffffffffffffffffffff166119908487612cc890919063ffffffff16565b8161199757fe5b0461373a565b98505b600089116119f9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180613a0e6028913960400191505060405180910390fd5b611a038a8a613620565b611a0f86868a8a612de0565b8115611a8757611a806008600e9054906101000a90046dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff16600860009054906101000a90046dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff16612cc890919063ffffffff16565b600b819055505b3373ffffffffffffffffffffffffffffffffffffffff167f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f8585604051808381526020018281526020019250505060405180910390a250505050505050506001600c81905550919050565b60016020528060005260406000206000915090505481565b600b5481565b60046020528060005260406000206000915090505481565b6000806001600c5414611ba3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f556e697377617056323a204c4f434b454400000000000000000000000000000081525060200191505060405180910390fd5b6000600c81905550600080611bb661124f565b50915091506000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611c8857600080fd5b505afa158015611c9c573d6000803e3d6000fd5b505050506040513d6020811015611cb257600080fd5b8101908080519060200190929190505050905060008273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611d4457600080fd5b505afa158015611d58573d6000803e3d6000fd5b505050506040513d6020811015611d6e57600080fd5b810190808051906020019092919050505090506000600160003073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205490506000611dd188886133dd565b905060008054905080611ded8685612cc890919063ffffffff16565b81611df457fe5b049a5080611e0b8585612cc890919063ffffffff16565b81611e1257fe5b04995060008b118015611e25575060008a115b611e7a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806139e66028913960400191505060405180910390fd5b611e843084613753565b611e8f878d8d612a7b565b611e9a868d8c612a7b565b8673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611f1757600080fd5b505afa158015611f2b573d6000803e3d6000fd5b505050506040513d6020811015611f4157600080fd5b810190808051906020019092919050505094508573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611fd157600080fd5b505afa158015611fe5573d6000803e3d6000fd5b505050506040513d6020811015611ffb57600080fd5b8101908080519060200190929190505050935061201a85858b8b612de0565b81156120925761208b6008600e9054906101000a90046dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff16600860009054906101000a90046dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff16612cc890919063ffffffff16565b600b819055505b8b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d819364968d8d604051808381526020018281526020019250505060405180910390a35050505050505050506001600c81905550915091565b6040518060400160405280600681526020017f554e492d5632000000000000000000000000000000000000000000000000000081525081565b600061215b338484613249565b6001905092915050565b6103e881565b6001600c54146121e3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f556e697377617056323a204c4f434b454400000000000000000000000000000081525060200191505060405180910390fd5b6000600c819055506000600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506123398284612334600860009054906101000a90046dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156122eb57600080fd5b505afa1580156122ff573d6000803e3d6000fd5b505050506040513d602081101561231557600080fd5b8101908080519060200190929190505050612d5d90919063ffffffff16565b612a7b565b61243981846124346008600e9054906101000a90046dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156123eb57600080fd5b505afa1580156123ff573d6000803e3d6000fd5b505050506040513d602081101561241557600080fd5b8101908080519060200190929190505050612d5d90919063ffffffff16565b612a7b565b50506001600c8190555050565b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b42841015612508576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f556e697377617056323a2045585049524544000000000000000000000000000081525060200191505060405180910390fd5b60006003547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c960001b898989600460008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815480929190600101919050558a604051602001808781526020018673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200184815260200183815260200182815260200196505050505050506040516020818303038152906040528051906020012060405160200180807f190100000000000000000000000000000000000000000000000000000000000081525060020183815260200182815260200192505050604051602081830303815290604052805190602001209050600060018286868660405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156126da573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415801561274e57508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b6127c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f556e697377617056323a20494e56414c49445f5349474e41545552450000000081525060200191505060405180910390fd5b6127cb89898961315e565b505050505050505050565b6002602052816000526040600020602052806000526040600020600091509150505481565b6001600c5414612873576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f556e697377617056323a204c4f434b454400000000000000000000000000000081525060200191505060405180910390fd5b6000600c81905550612a71600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561291d57600080fd5b505afa158015612931573d6000803e3d6000fd5b505050506040513d602081101561294757600080fd5b8101908080519060200190929190505050600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156129f757600080fd5b505afa158015612a0b573d6000803e3d6000fd5b505050506040513d6020811015612a2157600080fd5b8101908080519060200190929190505050600860009054906101000a90046dffffffffffffffffffffffffffff166008600e9054906101000a90046dffffffffffffffffffffffffffff16612de0565b6001600c81905550565b600060608473ffffffffffffffffffffffffffffffffffffffff166040518060400160405280601981526020017f7472616e7366657228616464726573732c75696e743235362900000000000000815250805190602001208585604051602401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040518082805190602001908083835b60208310612ba85780518252602082019150602081019050602083039250612b85565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612c0a576040519150601f19603f3d011682016040523d82523d6000602084013e612c0f565b606091505b5091509150818015612c4f5750600081511480612c4e5750808060200190516020811015612c3c57600080fd5b81019080805190602001909291905050505b5b612cc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f556e697377617056323a205452414e534645525f4641494c454400000000000081525060200191505060405180910390fd5b5050505050565b600080821480612ce55750828283850292508281612ce257fe5b04145b612d57576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f64732d6d6174682d6d756c2d6f766572666c6f7700000000000000000000000081525060200191505060405180910390fd5b92915050565b6000828284039150811115612dda576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f64732d6d6174682d7375622d756e646572666c6f77000000000000000000000081525060200191505060405180910390fd5b92915050565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6dffffffffffffffffffffffffffff168411158015612e5057507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6dffffffffffffffffffffffffffff168311155b612ec2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f556e697377617056323a204f564552464c4f570000000000000000000000000081525060200191505060405180910390fd5b60006401000000004281612ed257fe5b06905060006008601c9054906101000a900463ffffffff168203905060008163ffffffff16118015612f1557506000846dffffffffffffffffffffffffffff1614155b8015612f3257506000836dffffffffffffffffffffffffffff1614155b15613014578063ffffffff16612f7785612f4b8661386d565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661389890919063ffffffff16565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16026009600082825401925050819055508063ffffffff16612fe584612fb98761386d565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1661389890919063ffffffff16565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1602600a600082825401925050819055505b85600860006101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff160217905550846008600e6101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff160217905550816008601c6101000a81548163ffffffff021916908363ffffffff1602179055507f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1600860009054906101000a90046dffffffffffffffffffffffffffff166008600e9054906101000a90046dffffffffffffffffffffffffffff1660405180836dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff168152602001826dffffffffffffffffffffffffffff166dffffffffffffffffffffffffffff1681526020019250505060405180910390a1505050505050565b80600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b61329b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612d5d90919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061333081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546138f890919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600080600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663017e7e586040518163ffffffff1660e01b815260040160206040518083038186803b15801561344857600080fd5b505afa15801561345c573d6000803e3d6000fd5b505050506040513d602081101561347257600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141591506000600b54905082156135a4576000811461359f57600061350a613505866dffffffffffffffffffffffffffff16886dffffffffffffffffffffffffffff16612cc890919063ffffffff16565b6135be565b90506000613517836135be565b90508082111561359c57600061354a6135398385612d5d90919063ffffffff16565b600054612cc890919063ffffffff16565b9050600061357483613566600587612cc890919063ffffffff16565b6138f890919063ffffffff16565b9050600081838161358157fe5b0490506000811115613598576135978782613620565b5b5050505b50505b6135b6565b600081146135b5576000600b819055505b5b505092915050565b6000600382111561360d5781905060006001600284816135da57fe5b040190505b81811015613607578091506002818285816135f657fe5b0401816135ff57fe5b0490506135df565b5061361b565b6000821461361a57600190505b5b919050565b613635816000546138f890919063ffffffff16565b60008190555061368d81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546138f890919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b6000818310613749578161374b565b825b905092915050565b6137a581600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612d5d90919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506137fd81600054612d5d90919063ffffffff16565b600081905550600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b60006e010000000000000000000000000000826dffffffffffffffffffffffffffff16029050919050565b6000816dffffffffffffffffffffffffffff167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16816138ef57fe5b04905092915050565b6000828284019150811015613975576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f64732d6d6174682d6164642d6f766572666c6f7700000000000000000000000081525060200191505060405180910390fd5b9291505056fe556e697377617056323a20494e53554646494349454e545f4f55545055545f414d4f554e54556e697377617056323a20494e53554646494349454e545f494e5055545f414d4f554e54556e697377617056323a20494e53554646494349454e545f4c4951554944495459556e697377617056323a20494e53554646494349454e545f4c49515549444954595f4255524e4544556e697377617056323a20494e53554646494349454e545f4c49515549444954595f4d494e544544a265627a7a723158201d9cc769ec1244e0335eb71f99a94869ae6ea3596ebb2c69f8185f53f440e2c664736f6c63430005100032"
+ bench/contracts/erc20.sol view
@@ -0,0 +1,42 @@+contract ERC20 {+  // --- ERC20 Data ---+  string  public constant name     = "TOKEN";+  string  public constant symbol   = "TKN";+  string  public constant version  = "1";+  uint8   public constant decimals = 18;+  uint256 public totalSupply;++  mapping (address => uint)                      public balanceOf;+  mapping (address => mapping (address => uint)) public allowance;++  event Approval(address indexed src, address indexed guy, uint wad);+  event Transfer(address indexed src, address indexed dst, uint wad);++  constructor(uint supply) public {+      balanceOf[msg.sender] = supply;+      totalSupply = supply;+  }++  // --- Token ---+  function transfer(address dst, uint wad) external returns (bool) {+      return transferFrom(msg.sender, dst, wad);+  }+  function transferFrom(address src, address dst, uint wad)+      public returns (bool)+  {+      require(balanceOf[src] >= wad, "erc20/insufficient-balance");+      if (src != msg.sender && allowance[src][msg.sender] != type(uint).max) {+          require(allowance[src][msg.sender] >= wad, "erc20/insufficient-allowance");+          allowance[src][msg.sender] -= wad;+      }+      balanceOf[src] -= wad;+      balanceOf[dst] += wad;+      emit Transfer(src, dst, wad);+      return true;+  }+  function approve(address usr, uint wad) external returns (bool) {+      allowance[msg.sender][usr] = wad;+      emit Approval(msg.sender, usr, wad);+      return true;+  }+}
hevm-cli/hevm-cli.hs view
@@ -16,6 +16,7 @@ import EVM.Debug import qualified EVM.Expr as Expr import EVM.SMT+import EVM.Solvers import qualified EVM.TTY as TTY import EVM.Solidity import EVM.Expr (litAddr)@@ -187,8 +188,8 @@  optsMode :: Command Options.Unwrapped -> Mode optsMode x-  | Main.debug x = Debug-  | jsontrace x = JsonTrace+  | x.debug = Debug+  | x.jsontrace = JsonTrace   | otherwise = Run  applyCache :: (Maybe String, Maybe String) -> IO (EVM.VM -> EVM.VM)@@ -211,51 +212,51 @@  unitTestOptions :: Command Options.Unwrapped -> SolverGroup -> String -> IO UnitTestOptions unitTestOptions cmd solvers testFile = do-  let root = fromMaybe "." (dappRoot cmd)+  let root = fromMaybe "." cmd.dappRoot   srcInfo <- readSolc testFile >>= \case     Nothing -> error "Could not read .sol.json file"     Just (contractMap, sourceCache) ->       pure $ dappInfo root contractMap sourceCache -  vmModifier <- applyCache (state cmd, cache cmd)+  vmModifier <- applyCache (cmd.state, cmd.cache) -  params <- getParametersFromEnvironmentVariables (rpc cmd)+  params <- getParametersFromEnvironmentVariables cmd.rpc    let-    testn = testNumber params+    testn = params.testNumber     block' = if 0 == testn        then EVM.Fetch.Latest        else EVM.Fetch.BlockNumber testn    pure EVM.UnitTest.UnitTestOptions-    { EVM.UnitTest.solvers = solvers-    , EVM.UnitTest.rpcInfo = case rpc cmd of+    { solvers = solvers+    , rpcInfo = case cmd.rpc of          Just url -> Just (block', url)          Nothing  -> Nothing-    , EVM.UnitTest.maxIter = maxIterations cmd-    , EVM.UnitTest.askSmtIters = askSmtIterations cmd-    , EVM.UnitTest.smtDebug = smtdebug cmd-    , EVM.UnitTest.smtTimeout = smttimeout cmd-    , EVM.UnitTest.solver = solver cmd-    , EVM.UnitTest.covMatch = pack <$> covMatch cmd-    , EVM.UnitTest.verbose = verbose cmd-    , EVM.UnitTest.match = pack $ fromMaybe ".*" (match cmd)-    , EVM.UnitTest.maxDepth = depth cmd-    , EVM.UnitTest.fuzzRuns = fromMaybe 100 (fuzzRuns cmd)-    , EVM.UnitTest.replay = do-        arg' <- replay cmd+    , maxIter = cmd.maxIterations+    , askSmtIters = cmd.askSmtIterations+    , smtDebug = cmd.smtdebug+    , smtTimeout = cmd.smttimeout+    , solver = cmd.solver+    , covMatch = pack <$> cmd.covMatch+    , verbose = cmd.verbose+    , match = pack $ fromMaybe ".*" cmd.match+    , maxDepth = cmd.depth+    , fuzzRuns = fromMaybe 100 cmd.fuzzRuns+    , replay = do+        arg' <- cmd.replay         return (fst arg', LazyByteString.fromStrict (hexByteString "--replay" $ strip0x $ snd arg'))-    , EVM.UnitTest.vmModifier = vmModifier-    , EVM.UnitTest.testParams = params-    , EVM.UnitTest.dapp = srcInfo-    , EVM.UnitTest.ffiAllowed = ffi cmd+    , vmModifier = vmModifier+    , testParams = params+    , dapp = srcInfo+    , ffiAllowed = cmd.ffi     }  main :: IO () main = do   cmd <- Options.unwrapRecord "hevm -- Ethereum evaluator"   let-    root = fromMaybe "." (dappRoot cmd)+    root = fromMaybe "." cmd.dappRoot   case cmd of     Version {} -> putStrLn (showVersion Paths.version)     Symbolic {} -> withCurrentDirectory root $ assert cmd@@ -265,12 +266,12 @@     DappTest {} ->       withCurrentDirectory root $ do         cores <- num <$> getNumProcessors-        withSolvers Z3 cores (smttimeout cmd) $ \solvers -> do-          testFile <- findJsonFile (jsonFile cmd)+        withSolvers Z3 cores cmd.smttimeout $ \solvers -> do+          testFile <- findJsonFile cmd.jsonFile           testOpts <- unitTestOptions cmd solvers testFile-          case (coverage cmd, optsMode cmd) of+          case (cmd.coverage, optsMode cmd) of             (False, Run) -> do-              res <- dappTest testOpts testFile (cache cmd)+              res <- dappTest testOpts testFile cmd.cache               unless res exitFailure             (False, Debug) -> liftIO $ TTY.main testOpts root testFile             (False, JsonTrace) -> error "json traces not implemented for dappTest"@@ -298,21 +299,21 @@  equivalence :: Command Options.Unwrapped -> IO () equivalence cmd = do-  let bytecodeA = hexByteString "--code" . strip0x $ codeA cmd-      bytecodeB = hexByteString "--code" . strip0x $ codeB cmd+  let bytecodeA = hexByteString "--code" . strip0x $ cmd.codeA+      bytecodeB = hexByteString "--code" . strip0x $ cmd.codeB       veriOpts = VeriOpts { simp = True                           , debug = False-                          , maxIter = maxIterations cmd-                          , askSmtIters = askSmtIterations cmd+                          , maxIter = cmd.maxIterations+                          , askSmtIters = cmd.askSmtIterations                           , rpcInfo = Nothing                           }    withSolvers Z3 3 Nothing $ \s -> do     res <- equivalenceCheck s bytecodeA bytecodeB veriOpts Nothing-    case containsA (Cex()) res of+    case not (any isCex res) of       False -> do         putStrLn "No discrepancies found"-        when (containsA (EVM.SymExec.Timeout()) res) $ do+        when (any isTimeout res) $ do           putStrLn "But timeout(s) occurred"           exitFailure       True -> do@@ -321,8 +322,8 @@  getSrcInfo :: Command Options.Unwrapped -> IO DappInfo getSrcInfo cmd =-  let root = fromMaybe "." (dappRoot cmd)-  in case (jsonFile cmd) of+  let root = fromMaybe "." cmd.dappRoot+  in case cmd.jsonFile of     Nothing ->       pure emptyDapp     Just json -> readSolc json >>= \case@@ -339,10 +340,10 @@ -- If function signatures are known, they should always be given for best results. assert :: Command Options.Unwrapped -> IO () assert cmd = do-  let block'  = maybe EVM.Fetch.Latest EVM.Fetch.BlockNumber (block cmd)-      rpcinfo = (,) block' <$> rpc cmd+  let block'  = maybe EVM.Fetch.Latest EVM.Fetch.BlockNumber cmd.block+      rpcinfo = (,) block' <$> cmd.rpc       decipher = hexByteString "bytes" . strip0x-  calldata' <- case (Main.calldata cmd, sig cmd) of+  calldata' <- case (cmd.calldata, cmd.sig) of     -- fully abstract calldata     (Nothing, Nothing) -> pure       ( AbstractBuf "txdata"@@ -350,7 +351,7 @@       -- this is way larger than would ever be allowed by the gas limit       -- and avoids spurious counterexamples during abi decoding       -- TODO: can we encode calldata as an array with a smaller length?-      , [Expr.bufLength (AbstractBuf "txtdata") .< (Lit (2 ^ (64 :: Integer)))]+      , [Expr.bufLength (AbstractBuf "txdata") .< (Lit (2 ^ (64 :: Integer)))]       )      -- fully concrete calldata@@ -358,25 +359,25 @@     -- calldata according to given abi with possible specializations from the `arg` list     (Nothing, Just sig') -> do       method' <- functionAbi sig'-      let typs = snd <$> view methodInputs method'-      pure $ symCalldata (view methodSignature method') typs (arg cmd) mempty+      let typs = snd <$> method'.inputs+      pure $ symCalldata method'.methodSignature typs cmd.arg (AbstractBuf "txdata")     _ -> error "incompatible options: calldata and abi"    preState <- symvmFromCommand cmd calldata'-  let errCodes = fromMaybe defaultPanicCodes (assertions cmd)+  let errCodes = fromMaybe defaultPanicCodes cmd.assertions   cores <- num <$> getNumProcessors-  let solverCount = fromMaybe cores (numSolvers cmd)-  withSolvers EVM.SMT.Z3 solverCount (smttimeout cmd) $ \solvers -> do-    if Main.debug cmd then do+  let solverCount = fromMaybe cores cmd.numSolvers+  withSolvers EVM.Solvers.Z3 solverCount cmd.smttimeout $ \solvers -> do+    if cmd.debug then do       srcInfo <- getSrcInfo cmd       void $ TTY.runFromVM         solvers         rpcinfo-        (maxIterations cmd)+        cmd.maxIterations         srcInfo         preState     else do-      let opts = VeriOpts { simp = True, debug = smtdebug cmd, maxIter = maxIterations cmd, askSmtIters = askSmtIterations cmd, rpcInfo = rpcinfo}+      let opts = VeriOpts { simp = True, debug = cmd.smtdebug, maxIter = cmd.maxIterations, askSmtIters = cmd.askSmtIterations, rpcInfo = rpcinfo}       (expr, res) <- verify solvers opts preState (Just $ checkAssertions errCodes)       case res of         [Qed _] -> putStrLn "\nQED: No reachable property violations discovered\n"@@ -396,16 +397,17 @@                    , ""                    ] <> fmap (formatExpr) (getTimeouts cexs)           T.putStrLn $ T.unlines (counterexamples <> unknowns)-      when (showTree cmd) $ do+          exitFailure+      when cmd.showTree $ do         putStrLn "=== Expression ===\n"         T.putStrLn $ formatExpr expr         putStrLn ""-      when (showReachableTree cmd) $ do+      when cmd.showReachableTree $ do         reached <- reachable solvers expr         putStrLn "=== Reachable Expression ===\n"         T.putStrLn (formatExpr . snd $ reached)         putStrLn ""-      when (getModels cmd) $ do+      when cmd.getModels $ do         putStrLn $ "=== Models for " <> show (Expr.numBranches expr) <> " branches ===\n"         ms <- produceModels solvers expr         forM_ ms (showModel (fst calldata'))@@ -427,13 +429,13 @@   readSolc solcFile >>=     \case       Just (contractMap, sourceCache) -> do-        let unitTests = findUnitTests (EVM.UnitTest.match opts) $ Map.elems contractMap+        let unitTests = findUnitTests opts.match $ Map.elems contractMap         covs <- mconcat <$> mapM           (coverageForUnitTestContract opts contractMap sourceCache) unitTests         let           dapp = dappInfo "." contractMap sourceCache           f (k, vs) = do-            when (shouldPrintCoverage (EVM.UnitTest.covMatch opts) k) $ do+            when (shouldPrintCoverage opts.covMatch k) $ do               putStr ("\x1b[0m" ++ "————— hevm coverage for ") -- Prefixed with color reset               putStrLn (unpack k ++ " —————")               putStrLn ""@@ -470,7 +472,7 @@     case optsMode cmd of       Run -> do         vm' <- execStateT (EVM.Stepper.interpret (EVM.Fetch.oracle solvers rpcinfo) . void $ EVM.Stepper.execFully) vm-        when (trace cmd) $ T.hPutStr stderr (showTraceTree dapp vm')+        when cmd.trace $ T.hPutStr stderr (showTraceTree dapp vm')         case view EVM.result vm' of           Nothing ->             error "internal error; no EVM result"@@ -488,11 +490,11 @@                   ConcreteBuf msg' -> msg'                   _ -> "<symbolic>"             print $ ByteStringS msg-            case state cmd of+            case cmd.state of               Nothing -> pure ()               Just path ->                 Git.saveFacts (Git.RepoAt path) (Facts.vmFacts vm')-            case cache cmd of+            case cmd.cache of               Nothing -> pure ()               Just path ->                 Git.saveFacts (Git.RepoAt path) (Facts.cacheFacts (view EVM.cache vm'))@@ -500,15 +502,15 @@       Debug -> void $ TTY.runFromVM solvers rpcinfo Nothing dapp vm       --JsonTrace -> void $ execStateT (interpretWithTrace fetcher EVM.Stepper.runFully) vm       _ -> error "TODO"-     where block' = maybe EVM.Fetch.Latest EVM.Fetch.BlockNumber (block cmd)-           rpcinfo = (,) block' <$> rpc cmd+     where block' = maybe EVM.Fetch.Latest EVM.Fetch.BlockNumber cmd.block+           rpcinfo = (,) block' <$> cmd.rpc  -- | Creates a (concrete) VM from command line options vmFromCommand :: Command Options.Unwrapped -> IO EVM.VM vmFromCommand cmd = do-  withCache <- applyCache (state cmd, cache cmd)+  withCache <- applyCache (cmd.state, cmd.cache) -  (miner,ts,baseFee,blockNum,prevRan) <- case rpc cmd of+  (miner,ts,baseFee,blockNum,prevRan) <- case cmd.rpc of     Nothing -> return (0,Lit 0,0,0,0)     Just url -> EVM.Fetch.fetchBlockFrom block' url >>= \case       Nothing -> error "Could not fetch block"@@ -519,7 +521,7 @@                                    , _prevRandao                                    ) -  contract <- case (rpc cmd, address cmd, code cmd) of+  contract <- case (cmd.rpc, cmd.address, cmd.code) of     (Just url, Just addr', Just c) -> do       EVM.Fetch.fetchContractFrom block' url addr' >>= \case         Nothing ->@@ -552,43 +554,43 @@    return $ EVM.Transaction.initTx $ withCache (vm0 baseFee miner ts' blockNum prevRan contract)     where-        block'   = maybe EVM.Fetch.Latest EVM.Fetch.BlockNumber (block cmd)-        value'   = word value 0-        caller'  = addr caller 0-        origin'  = addr origin 0-        calldata' = ConcreteBuf $ bytes Main.calldata ""+        block'   = maybe EVM.Fetch.Latest EVM.Fetch.BlockNumber cmd.block+        value'   = word (.value) 0+        caller'  = addr (.caller) 0+        origin'  = addr (.origin) 0+        calldata' = ConcreteBuf $ bytes (.calldata) ""         decipher = hexByteString "bytes" . strip0x-        mkCode bs = if create cmd+        mkCode bs = if cmd.create                     then EVM.InitCode bs mempty                     else EVM.RuntimeCode (EVM.ConcreteRuntimeCode bs)-        address' = if create cmd-              then addr address (createAddress origin' (word nonce 0))-              else addr address 0xacab+        address' = if cmd.create+              then addr (.address) (createAddress origin' (word (.nonce) 0))+              else addr (.address) 0xacab          vm0 baseFee miner ts blockNum prevRan c = EVM.makeVm $ EVM.VMOpts-          { EVM.vmoptContract      = c-          , EVM.vmoptCalldata      = (calldata', [])-          , EVM.vmoptValue         = Lit value'-          , EVM.vmoptAddress       = address'-          , EVM.vmoptCaller        = litAddr caller'-          , EVM.vmoptOrigin        = origin'-          , EVM.vmoptGas           = word64 gas 0xffffffffffffffff-          , EVM.vmoptBaseFee       = baseFee-          , EVM.vmoptPriorityFee   = word priorityFee 0-          , EVM.vmoptGaslimit      = word64 gaslimit 0xffffffffffffffff-          , EVM.vmoptCoinbase      = addr coinbase miner-          , EVM.vmoptNumber        = word number blockNum-          , EVM.vmoptTimestamp     = Lit $ word timestamp ts-          , EVM.vmoptBlockGaslimit = word64 gaslimit 0xffffffffffffffff-          , EVM.vmoptGasprice      = word gasprice 0-          , EVM.vmoptMaxCodeSize   = word maxcodesize 0xffffffff-          , EVM.vmoptPrevRandao    = word prevRandao prevRan-          , EVM.vmoptSchedule      = FeeSchedule.berlin-          , EVM.vmoptChainId       = word chainid 1-          , EVM.vmoptCreate        = create cmd-          , EVM.vmoptStorageBase   = EVM.Concrete-          , EVM.vmoptTxAccessList  = mempty -- TODO: support me soon-          , EVM.vmoptAllowFFI      = False+          { vmoptContract      = c+          , vmoptCalldata      = (calldata', [])+          , vmoptValue         = Lit value'+          , vmoptAddress       = address'+          , vmoptCaller        = litAddr caller'+          , vmoptOrigin        = origin'+          , vmoptGas           = word64 (.gas) 0xffffffffffffffff+          , vmoptBaseFee       = baseFee+          , vmoptPriorityFee   = word (.priorityFee) 0+          , vmoptGaslimit      = word64 (.gaslimit) 0xffffffffffffffff+          , vmoptCoinbase      = addr (.coinbase) miner+          , vmoptNumber        = word (.number) blockNum+          , vmoptTimestamp     = Lit $ word (.timestamp) ts+          , vmoptBlockGaslimit = word64 (.gaslimit) 0xffffffffffffffff+          , vmoptGasprice      = word (.gasprice) 0+          , vmoptMaxCodeSize   = word (.maxcodesize) 0xffffffff+          , vmoptPrevRandao    = word (.prevRandao) prevRan+          , vmoptSchedule      = FeeSchedule.berlin+          , vmoptChainId       = word (.chainid) 1+          , vmoptCreate        = (.create) cmd+          , vmoptStorageBase   = EVM.Concrete+          , vmoptTxAccessList  = mempty -- TODO: support me soon+          , vmoptAllowFFI      = False           }         word f def = fromMaybe def (f cmd)         word64 f def = fromMaybe def (f cmd)@@ -597,7 +599,7 @@  symvmFromCommand :: Command Options.Unwrapped -> (Expr Buf, [Prop]) -> IO (EVM.VM) symvmFromCommand cmd calldata' = do-  (miner,blockNum,baseFee,prevRan) <- case rpc cmd of+  (miner,blockNum,baseFee,prevRan) <- case cmd.rpc of     Nothing -> return (0,0,0,0)     Just url -> EVM.Fetch.fetchBlockFrom block' url >>= \case       Nothing -> error "Could not fetch block"@@ -609,10 +611,10 @@    let     caller' = Caller 0-    ts = maybe Timestamp Lit (timestamp cmd)-    callvalue' = maybe (CallValue 0) Lit (value cmd)+    ts = maybe Timestamp Lit cmd.timestamp+    callvalue' = maybe (CallValue 0) Lit cmd.value   -- TODO: rework this, ConcreteS not needed anymore-  let store = case storageModel cmd of+  let store = case cmd.storageModel of                 -- InitialS and SymbolicS can read and write to symbolic locations                 -- ConcreteS cannot (instead values can be fetched from rpc!)                 -- Initial defaults to 0 for uninitialized storage slots,@@ -620,18 +622,18 @@                 Just InitialS  -> EmptyStore                 Just ConcreteS -> ConcreteStore mempty                 Just SymbolicS -> AbstractStore-                Nothing -> if create cmd then EmptyStore else AbstractStore+                Nothing -> if cmd.create then EmptyStore else AbstractStore -  withCache <- applyCache (state cmd, cache cmd)+  withCache <- applyCache (cmd.state, cmd.cache) -  contract' <- case (rpc cmd, address cmd, code cmd) of+  contract' <- case (cmd.rpc, cmd.address, cmd.code) of     (Just url, Just addr', _) ->       EVM.Fetch.fetchContractFrom block' url addr' >>= \case         Nothing ->           error "contract not found."         Just contract' -> return contract''           where-            contract'' = case code cmd of+            contract'' = case cmd.code of               Nothing -> contract'               -- if both code and url is given,               -- fetch the contract and overwrite the code@@ -652,38 +654,38 @@    where     decipher = hexByteString "bytes" . strip0x-    block'   = maybe EVM.Fetch.Latest EVM.Fetch.BlockNumber (block cmd)-    origin'  = addr origin 0-    mkCode bs = if create cmd+    block'   = maybe EVM.Fetch.Latest EVM.Fetch.BlockNumber cmd.block+    origin'  = addr (.origin) 0+    mkCode bs = if cmd.create                    then EVM.InitCode bs mempty                    else EVM.RuntimeCode (EVM.ConcreteRuntimeCode bs)-    address' = if create cmd-          then addr address (createAddress origin' (word nonce 0))-          else addr address 0xacab+    address' = if cmd.create+          then addr (.address) (createAddress origin' (word (.nonce) 0))+          else addr (.address) 0xacab     vm0 baseFee miner ts blockNum prevRan cd' callvalue' caller' c = EVM.makeVm $ EVM.VMOpts-      { EVM.vmoptContract      = c-      , EVM.vmoptCalldata      = cd'-      , EVM.vmoptValue         = callvalue'-      , EVM.vmoptAddress       = address'-      , EVM.vmoptCaller        = caller'-      , EVM.vmoptOrigin        = origin'-      , EVM.vmoptGas           = word64 gas 0xffffffffffffffff-      , EVM.vmoptGaslimit      = word64 gaslimit 0xffffffffffffffff-      , EVM.vmoptBaseFee       = baseFee-      , EVM.vmoptPriorityFee   = word priorityFee 0-      , EVM.vmoptCoinbase      = addr coinbase miner-      , EVM.vmoptNumber        = word number blockNum-      , EVM.vmoptTimestamp     = ts-      , EVM.vmoptBlockGaslimit = word64 gaslimit 0xffffffffffffffff-      , EVM.vmoptGasprice      = word gasprice 0-      , EVM.vmoptMaxCodeSize   = word maxcodesize 0xffffffff-      , EVM.vmoptPrevRandao    = word prevRandao prevRan-      , EVM.vmoptSchedule      = FeeSchedule.berlin-      , EVM.vmoptChainId       = word chainid 1-      , EVM.vmoptCreate        = create cmd-      , EVM.vmoptStorageBase   = EVM.Symbolic-      , EVM.vmoptTxAccessList  = mempty-      , EVM.vmoptAllowFFI      = False+      { vmoptContract      = c+      , vmoptCalldata      = cd'+      , vmoptValue         = callvalue'+      , vmoptAddress       = address'+      , vmoptCaller        = caller'+      , vmoptOrigin        = origin'+      , vmoptGas           = word64 (.gas) 0xffffffffffffffff+      , vmoptGaslimit      = word64 (.gaslimit) 0xffffffffffffffff+      , vmoptBaseFee       = baseFee+      , vmoptPriorityFee   = word (.priorityFee) 0+      , vmoptCoinbase      = addr (.coinbase) miner+      , vmoptNumber        = word (.number) blockNum+      , vmoptTimestamp     = ts+      , vmoptBlockGaslimit = word64 (.gaslimit) 0xffffffffffffffff+      , vmoptGasprice      = word (.gasprice) 0+      , vmoptMaxCodeSize   = word (.maxcodesize) 0xffffffff+      , vmoptPrevRandao    = word (.prevRandao) prevRan+      , vmoptSchedule      = FeeSchedule.berlin+      , vmoptChainId       = word (.chainid) 1+      , vmoptCreate        = (.create) cmd+      , vmoptStorageBase   = EVM.Symbolic+      , vmoptTxAccessList  = mempty+      , vmoptAllowFFI      = False       }     word f def = fromMaybe def (f cmd)     addr f def = fromMaybe def (f cmd)
hevm.cabal view
@@ -2,7 +2,7 @@ name:   hevm version:-  0.50.2+  0.50.3 synopsis:   Ethereum virtual machine evaluator description:@@ -24,6 +24,7 @@   Simple extra-source-files:   CHANGELOG.md+  bench/contracts/erc20.sol   test/contracts/lib/test.sol   test/contracts/lib/erc20.sol   test/contracts/pass/trivial.sol@@ -45,6 +46,11 @@   default:     False   manual:      True +flag devel+  description: Sets flag for compilation during development+  default:     False+  manual:      True+ source-repository head   type:     git   location: https://github.com/ethereum/hevm.git@@ -52,9 +58,14 @@ common shared   if flag(ci)     ghc-options: -Werror+  if flag(devel)+    ghc-options: -j   default-language: GHC2021   default-extensions:+    DuplicateRecordFields     LambdaCase+    NoFieldSelectors+    OverloadedRecordDot     OverloadedStrings     RecordWildCards     TypeFamilies@@ -72,6 +83,7 @@     EVM.Dev,     EVM.Expr,     EVM.SMT,+    EVM.Solvers,     EVM.Exec,     EVM.Facts,     EVM.Facts.Git,@@ -99,8 +111,10 @@     Paths_hevm   autogen-modules:     Paths_hevm-  ghc-options:-    -Wall -Wno-deprecations -Wno-unticked-promoted-constructors -Wno-orphans+  if flag(devel)+    ghc-options: -Wall -Wno-deprecations -Wno-unticked-promoted-constructors -Wno-orphans -j+  else+    ghc-options: -Wall -Wno-deprecations -Wno-unticked-promoted-constructors -Wno-orphans   extra-libraries:     secp256k1, ff   if os(linux)@@ -164,6 +178,8 @@     smt2-parser                       >= 0.1.0.1,     word-wrap                         >= 0.5 && < 0.6,     spool                             >= 0.1 && < 0.2,+    stm                               >= 2.5.0 && < 2.6.0,+    spawn                             >= 0.3 && < 0.4   hs-source-dirs:     src @@ -173,8 +189,10 @@     hevm-cli   main-is:     hevm-cli.hs-  ghc-options:-    -Wall -threaded -with-rtsopts=-N -Wno-unticked-promoted-constructors -Wno-orphans+  if flag(devel)+    ghc-options: -Wall -threaded -with-rtsopts=-N -Wno-unticked-promoted-constructors -Wno-orphans -j+  else+    ghc-options: -Wall -threaded -with-rtsopts=-N -Wno-unticked-promoted-constructors -Wno-orphans   other-modules:     Paths_hevm   if os(darwin)@@ -213,12 +231,18 @@     text,     unordered-containers,     vector,-    vty+    vty,+    stm,+    spawn +--- Test Helpers ---+ common test-base   import: shared-  ghc-options:-    -Wall -Wno-unticked-promoted-constructors -Wno-orphans+  if flag (devel)+    ghc-options: -Wall -Wno-unticked-promoted-constructors -Wno-orphans -j+  else+    ghc-options: -Wall -Wno-unticked-promoted-constructors -Wno-orphans   hs-source-dirs:     test   extra-libraries:@@ -257,6 +281,9 @@     time,     array,     vector,+    tasty-bench,+    stm >= 2.5.0,+    spawn >= 0.3,     witherable,     smt2-parser >= 0.1.0.1 @@ -307,3 +334,30 @@     exitcode-stdio-1.0   main-is:     BlockchainTests.hs++--- Benchmarks ---++benchmark bench+  import: shared+  type:+    exitcode-stdio-1.0+  main-is:+    bench.hs+  hs-source-dirs:+    bench+  if os(darwin)+     extra-libraries: c+++  else+     extra-libraries: stdc+++  other-modules:+    Paths_hevm+  autogen-modules:+    Paths_hevm+  build-depends:+    base,+    tasty-bench,+    tasty,+    bytestring,+    text,+    hevm,+    here
src/EVM.hs view
@@ -8,56 +8,53 @@  import Prelude hiding (log, exponent, GT, LT) -import Data.Text (unpack)-import Data.Text.Encoding (decodeUtf8, encodeUtf8) import EVM.ABI-import EVM.Types hiding (IllegalOverflow, Error)-import EVM.Solidity import EVM.Concrete (createAddress, create2Address)-import EVM.Op-import EVM.Expr (readStorage, writeStorage, readByte, readWord, writeWord, writeByte, bufLength, indexWord, litAddr, readBytes, word256At, copySlice)+import EVM.Expr (readStorage, writeStorage, readByte, readWord, writeWord,+  writeByte, bufLength, indexWord, litAddr, readBytes, word256At, copySlice)+import EVM.Expr qualified as Expr import EVM.FeeSchedule (FeeSchedule (..))-import Options.Generic as Options-import qualified EVM.Precompiled-import qualified EVM.Expr as Expr+import EVM.Op+import EVM.Precompiled qualified+import EVM.Solidity+import EVM.Types hiding (IllegalOverflow, Error)  import Control.Lens hiding (op, (:<), (|>), (.>)) import Control.Monad.State.Strict hiding (state)--import Data.ByteString              (ByteString)-import Data.ByteString.Lazy         (fromStrict)-import Data.Map.Strict              (Map)-import Data.Set                     (Set, insert, member, fromList)-import Data.Maybe                   (fromMaybe, fromJust)-import Data.Sequence                (Seq)-import Data.Vector.Storable         (Vector)-import Data.Foldable                (toList)-import Data.Word                    (Word8, Word32, Word64)-import Data.Bits                    (FiniteBits, countLeadingZeros, finiteBitSize)-+import Data.Bits (FiniteBits, countLeadingZeros, finiteBitSize)+import Data.ByteArray qualified as BA+import Data.ByteString (ByteString)+import Data.ByteString qualified as BS+import Data.ByteString.Lazy (fromStrict)+import Data.ByteString.Lazy qualified as LS+import Data.ByteString.Char8 qualified as Char8+import Data.Foldable (toList)+import Data.List (find)+import Data.Map.Strict (Map)+import Data.Map.Strict qualified as Map+import Data.Maybe (fromMaybe, fromJust)+import Data.Set (Set, insert, member, fromList)+import Data.Sequence (Seq)+import Data.Sequence qualified as Seq+import Data.Text (unpack)+import Data.Text.Encoding (decodeUtf8, encodeUtf8) import Data.Tree+import Data.Tree.Zipper qualified as Zipper import Data.Tuple.Curry-import Data.List (find)--import qualified Data.ByteString      as BS-import qualified Data.ByteString.Lazy as LS-import qualified Data.ByteString.Char8 as Char8-import qualified Data.ByteArray       as BA-import qualified Data.Map.Strict      as Map-import qualified Data.Sequence        as Seq-import qualified Data.Tree.Zipper     as Zipper-import qualified Data.Vector          as V-import qualified Data.Vector.Storable as Vector-import qualified Data.Vector.Storable.Mutable as Vector--import qualified Data.Vector as RegularVector+import Data.Vector qualified as RegularVector+import Data.Vector qualified as V+import Data.Vector.Storable (Vector)+import Data.Vector.Storable qualified as Vector+import Data.Vector.Storable.Mutable qualified as Vector+import Data.Word (Word8, Word32, Word64)+import Options.Generic as Options -import Crypto.Number.ModArithmetic (expFast)-import qualified Crypto.Hash as Crypto import Crypto.Hash (Digest, SHA256, RIPEMD160, digestFromByteString)+import Crypto.Hash qualified as Crypto+import Crypto.Number.ModArithmetic (expFast) import Crypto.PubKey.ECC.ECDSA (signDigestWith, PrivateKey(..), Signature(..))-import Crypto.PubKey.ECC.Types (getCurveByName, CurveName(..), Point(..)) import Crypto.PubKey.ECC.Generate (generateQ)+import Crypto.PubKey.ECC.Types (getCurveByName, CurveName(..), Point(..))  -- * Data types @@ -112,6 +109,7 @@   , _constraints    :: [Prop]   , _keccakEqs      :: [Prop]   , _allowFFI       :: Bool+  , _overrideCaller :: Maybe (Expr EWord)   }   deriving (Show) @@ -433,9 +431,9 @@  instance Semigroup Cache where   a <> b = Cache-    { _fetchedContracts = Map.unionWith unifyCachedContract (view fetchedContracts a) (view fetchedContracts b)-    , _fetchedStorage = Map.unionWith unifyCachedStorage (view fetchedStorage a) (view fetchedStorage b)-    , _path = mappend (view path a) (view path b)+    { _fetchedContracts = Map.unionWith unifyCachedContract a._fetchedContracts b._fetchedContracts+    , _fetchedStorage = Map.unionWith unifyCachedStorage a._fetchedStorage b._fetchedStorage+    , _path = mappend a._path b._path     }  unifyCachedStorage :: Map W256 W256 -> Map W256 W256 -> Map W256 W256@@ -464,78 +462,79 @@  currentContract :: VM -> Maybe Contract currentContract vm =-  view (env . contracts . at (view (state . codeContract) vm)) vm+  Map.lookup vm._state._codeContract vm._env._contracts  -- * Data constructors  makeVm :: VMOpts -> VM makeVm o =-  let txaccessList = vmoptTxAccessList o-      txorigin = vmoptOrigin o-      txtoAddr = vmoptAddress o+  let txaccessList = o.vmoptTxAccessList+      txorigin = o.vmoptOrigin+      txtoAddr = o.vmoptAddress       initialAccessedAddrs = fromList $ [txorigin, txtoAddr] ++ [1..9] ++ (Map.keys txaccessList)       initialAccessedStorageKeys = fromList $ foldMap (uncurry (map . (,))) (Map.toList txaccessList)-      touched = if vmoptCreate o then [txorigin] else [txorigin, txtoAddr]+      touched = if o.vmoptCreate then [txorigin] else [txorigin, txtoAddr]   in   VM   { _result = Nothing   , _frames = mempty   , _tx = TxState-    { _gasprice = vmoptGasprice o-    , _txgaslimit = vmoptGaslimit o-    , _txPriorityFee = vmoptPriorityFee o+    { _gasprice = o.vmoptGasprice+    , _txgaslimit = o.vmoptGaslimit+    , _txPriorityFee = o.vmoptPriorityFee     , _origin = txorigin     , _toAddr = txtoAddr-    , _value = vmoptValue o+    , _value = o.vmoptValue     , _substate = SubState mempty touched initialAccessedAddrs initialAccessedStorageKeys mempty     --, _accessList = txaccessList-    , _isCreate = vmoptCreate o+    , _isCreate = o.vmoptCreate     , _txReversion = Map.fromList-      [(vmoptAddress o, vmoptContract o)]+      [(o.vmoptAddress , o.vmoptContract )]     }   , _logs = []   , _traces = Zipper.fromForest []   , _block = Block-    { _coinbase = vmoptCoinbase o-    , _timestamp = vmoptTimestamp o-    , _number = vmoptNumber o-    , _prevRandao = vmoptPrevRandao o-    , _maxCodeSize = vmoptMaxCodeSize o-    , _gaslimit = vmoptBlockGaslimit o-    , _baseFee = vmoptBaseFee o-    , _schedule = vmoptSchedule o+    { _coinbase = o.vmoptCoinbase+    , _timestamp = o.vmoptTimestamp+    , _number = o.vmoptNumber+    , _prevRandao = o.vmoptPrevRandao+    , _maxCodeSize = o.vmoptMaxCodeSize+    , _gaslimit = o.vmoptBlockGaslimit+    , _baseFee = o.vmoptBaseFee+    , _schedule = o.vmoptSchedule     }   , _state = FrameState     { _pc = 0     , _stack = mempty     , _memory = mempty     , _memorySize = 0-    , _code = view contractcode $ vmoptContract o-    , _contract = vmoptAddress o-    , _codeContract = vmoptAddress o-    , _calldata = fst $ vmoptCalldata o-    , _callvalue = vmoptValue o-    , _caller = vmoptCaller o-    , _gas = vmoptGas o+    , _code = o.vmoptContract._contractcode+    , _contract = o.vmoptAddress+    , _codeContract = o.vmoptAddress+    , _calldata = fst o.vmoptCalldata+    , _callvalue = o.vmoptValue+    , _caller = o.vmoptCaller+    , _gas = o.vmoptGas     , _returndata = mempty     , _static = False     }   , _env = Env     { _sha3Crack = mempty-    , _chainId = vmoptChainId o-    , _storage = if vmoptStorageBase o == Concrete then EmptyStore else AbstractStore+    , _chainId = o.vmoptChainId+    , _storage = if o.vmoptStorageBase == Concrete then EmptyStore else AbstractStore     , _origStorage = mempty     , _contracts = Map.fromList-      [(vmoptAddress o, vmoptContract o)]+      [(o.vmoptAddress, o.vmoptContract )]     --, _keccakUsed = mempty     --, _storageModel = vmoptStorageModel o     }   , _cache = Cache mempty mempty mempty   , _burned = 0-  , _constraints = snd $ vmoptCalldata o+  , _constraints = snd o.vmoptCalldata   , _keccakEqs = mempty   , _iterations = mempty-  , _allowFFI = vmoptAllowFFI o+  , _allowFFI = o.vmoptAllowFFI+  , _overrideCaller = Nothing   }  -- | Initialize empty contract with given code@@ -565,30 +564,25 @@   vm <- get    let-    -- Convenience function to access parts of the current VM state.-    -- Arcane type signature needed to avoid monomorphism restriction.-    the :: (b -> VM -> Const a VM) -> ((a -> Const a a) -> b) -> a-    the f g = view (f . g) vm-     -- Convenient aliases-    mem  = the state memory-    stk  = the state stack-    self = the state contract-    this = fromMaybe (error "internal error: state contract") (preview (ix self) (the env contracts))+    mem  = vm._state._memory+    stk  = vm._state._stack+    self = vm._state._contract+    this = fromMaybe (error "internal error: state contract") (Map.lookup self vm._env._contracts) -    fees@FeeSchedule {..} = the block schedule+    fees@FeeSchedule {..} = vm._block._schedule      doStop = finishFrame (FrameReturned mempty)    if self > 0x0 && self <= 0x9 then do     -- call to precompile     let ?op = 0x00 -- dummy value-    case bufLength (the state calldata) of+    case bufLength vm._state._calldata of       (Lit calldatasize) -> do-          copyBytesToMemory (the state calldata) (Lit calldatasize) (Lit 0) (Lit 0)-          executePrecompile self (the state gas) 0 calldatasize 0 0 []+          copyBytesToMemory vm._state._calldata (Lit calldatasize) (Lit 0) (Lit 0)+          executePrecompile self vm._state._gas 0 calldatasize 0 0 []           vmx <- get-          case view (state.stack) vmx of+          case vmx._state._stack of             (x:_) -> case x of               Lit (num -> x' :: Integer) -> case x' of                 0 -> do@@ -600,32 +594,32 @@                     out <- use (state . returndata)                     finishFrame (FrameReturned out)               e -> vmError $-                UnexpectedSymbolicArg (view (state . pc) vmx) "precompile returned a symbolic value" [e]+                UnexpectedSymbolicArg vmx._state._pc "precompile returned a symbolic value" [e]             _ ->               underrun-      e -> vmError $ UnexpectedSymbolicArg (the state pc) "cannot call precompiles with symbolic data" [e]+      e -> vmError $ UnexpectedSymbolicArg vm._state._pc "cannot call precompiles with symbolic data" [e] -  else if the state pc >= opslen (the state code)+  else if vm._state._pc >= opslen vm._state._code     then doStop      else do-      let ?op = case (the state code) of-                  InitCode conc _ -> BS.index conc (the state pc)-                  RuntimeCode (ConcreteRuntimeCode bs) -> BS.index bs (the state pc)+      let ?op = case vm._state._code of+                  InitCode conc _ -> BS.index conc vm._state._pc+                  RuntimeCode (ConcreteRuntimeCode bs) -> BS.index bs vm._state._pc                   RuntimeCode (SymbolicRuntimeCode ops) ->                     fromMaybe (error "could not analyze symbolic code") $-                      unlitByte $ ops V.! the state pc+                      unlitByte $ ops V.! vm._state._pc        case ?op of          -- op: PUSH         x | x >= 0x60 && x <= 0x7f -> do           let !n = num x - 0x60 + 1-              !xs = case the state code of-                InitCode conc _ -> Lit $ word $ padRight n $ BS.take n (BS.drop (1 + the state pc) conc)-                RuntimeCode (ConcreteRuntimeCode bs) -> Lit $ word $ BS.take n $ BS.drop (1 + the state pc) bs+              !xs = case vm._state._code of+                InitCode conc _ -> Lit $ word $ padRight n $ BS.take n (BS.drop (1 + vm._state._pc) conc)+                RuntimeCode (ConcreteRuntimeCode bs) -> Lit $ word $ BS.take n $ BS.drop (1 + vm._state._pc) bs                 RuntimeCode (SymbolicRuntimeCode ops) ->-                  let bytes = V.take n $ V.drop (1 + the state pc) ops+                  let bytes = V.take n $ V.drop (1 + vm._state._pc) ops                   in readWord (Lit 0) $ Expr.fromList $ padLeft' 32 bytes           limitStack 1 $             burn g_verylow $ do@@ -667,7 +661,7 @@                 forceConcrete2 (xOffset', xSize') "LOG" $ \(xOffset, xSize) -> do                     let (topics, xs') = splitAt n xs                         bytes         = readMemory xOffset' xSize' vm-                        logs'         = (LogEntry (litAddr self) bytes topics) : (view logs vm)+                        logs'         = (LogEntry (litAddr self) bytes topics) : vm._logs                     burn (g_log + g_logdata * (num xSize) + num n * g_logtopic) $                       accessMemoryRange fees xOffset xSize $ do                         traceTopLog logs'@@ -770,33 +764,33 @@                 fetchAccount (num x) $ \c -> do                   next                   assign (state . stack) xs-                  push (num $ view balance c)+                  push (num c._balance)             [] ->               underrun          -- op: ORIGIN         0x32 ->           limitStack 1 . burn g_base $-            next >> push (num (the tx origin))+            next >> push (num vm._tx._origin)          -- op: CALLER         0x33 ->           limitStack 1 . burn g_base $-            next >> pushSym (the state caller)+            next >> pushSym vm._state._caller          -- op: CALLVALUE         0x34 ->           limitStack 1 . burn g_base $-            next >> pushSym (the state callvalue)+            next >> pushSym vm._state._callvalue          -- op: CALLDATALOAD         0x35 -> stackOp1 (const g_verylow) $-          \ind -> Expr.readWord ind (the state calldata)+          \ind -> Expr.readWord ind vm._state._calldata          -- op: CALLDATASIZE         0x36 ->           limitStack 1 . burn g_base $-            next >> pushSym (bufLength (the state calldata))+            next >> pushSym (bufLength vm._state._calldata)          -- op: CALLDATACOPY         0x37 ->@@ -808,13 +802,13 @@                     accessMemoryRange fees xTo xSize $ do                       next                       assign (state . stack) xs-                      copyBytesToMemory (the state calldata) xSize' xFrom xTo'+                      copyBytesToMemory vm._state._calldata xSize' xFrom xTo'             _ -> underrun          -- op: CODESIZE         0x38 ->           limitStack 1 . burn g_base $-            next >> pushSym (codelen (the state code))+            next >> pushSym (codelen vm._state._code)          -- op: CODECOPY         0x39 ->@@ -830,14 +824,14 @@                           accessMemoryRange fees memOffset n $ do                             next                             assign (state . stack) xs-                            copyBytesToMemory (toBuf $ the state code) n' codeOffset memOffset'+                            copyBytesToMemory (toBuf vm._state._code) n' codeOffset memOffset'                       else vmError IllegalOverflow             _ -> underrun          -- op: GASPRICE         0x3a ->           limitStack 1 . burn g_base $-            next >> push (the tx gasprice)+            next >> push vm._tx._gasprice          -- op: EXTCODESIZE         0x3b ->@@ -857,6 +851,7 @@               _ -> do                 assign (state . stack) xs                 pushSym (CodeSize x')+                next             [] ->               underrun @@ -883,7 +878,7 @@         -- op: RETURNDATASIZE         0x3d ->           limitStack 1 . burn g_base $-            next >> pushSym (bufLength (the state returndata))+            next >> pushSym (bufLength vm._state._returndata)          -- op: RETURNDATACOPY         0x3e ->@@ -896,13 +891,13 @@                     assign (state . stack) xs                      let jump True = vmError EVM.InvalidMemoryAccess-                        jump False = copyBytesToMemory (the state returndata) xSize' xFrom xTo'+                        jump False = copyBytesToMemory vm._state._returndata xSize' xFrom xTo' -                    case (xFrom, bufLength (the state returndata)) of+                    case (xFrom, bufLength vm._state._returndata) of                       (Lit f, Lit l) ->                         jump $ l < f + xSize || f + xSize < f                       _ -> do-                        let oob = Expr.lt (bufLength $ the state returndata) (Expr.add xFrom xSize')+                        let oob = Expr.lt (bufLength vm._state._returndata) (Expr.add xFrom xSize')                             overflow = Expr.lt (Expr.add xFrom xSize') (xFrom)                         loc <- codeloc                         branch loc (Expr.or oob overflow) jump@@ -927,7 +922,7 @@           -- We adopt the fake block hash scheme of the VMTests,           -- so that blockhash(i) is the hash of i as decimal ASCII.           stackOp1 (const g_blockhash) $ \case-            (Lit i) -> if i + 256 < the block number || i >= the block number+            (Lit i) -> if i + 256 < vm._block._number || i >= vm._block._number                        then Lit 0                        else (num i :: Integer) & show & Char8.pack & keccak' & Lit             i -> BlockHash i@@ -935,42 +930,42 @@         -- op: COINBASE         0x41 ->           limitStack 1 . burn g_base $-            next >> push (num (the block coinbase))+            next >> push (num vm._block._coinbase)          -- op: TIMESTAMP         0x42 ->           limitStack 1 . burn g_base $-            next >> pushSym (the block timestamp)+            next >> pushSym vm._block._timestamp          -- op: NUMBER         0x43 ->           limitStack 1 . burn g_base $-            next >> push (the block number)+            next >> push vm._block._number          -- op: PREVRANDAO         0x44 -> do           limitStack 1 . burn g_base $-            next >> push (the block prevRandao)+            next >> push vm._block._prevRandao          -- op: GASLIMIT         0x45 ->           limitStack 1 . burn g_base $-            next >> push (num $ the block gaslimit)+            next >> push (num vm._block._gaslimit)          -- op: CHAINID         0x46 ->           limitStack 1 . burn g_base $-            next >> push (the env chainId)+            next >> push vm._env._chainId          -- op: SELFBALANCE         0x47 ->           limitStack 1 . burn g_low $-            next >> push (view balance this)+            next >> push this._balance          -- op: BASEFEE         0x48 ->           limitStack 1 . burn g_base $-            next >> push (the block baseFee)+            next >> push vm._block._baseFee          -- op: POP         0x50 ->@@ -1034,7 +1029,7 @@                 if num availableGas <= g_callstipend                   then finishFrame (FrameErrored (OutOfGas availableGas (num g_callstipend)))                   else do-                    let original = case readStorage (litAddr self) x (ConcreteStore $ the env origStorage) of+                    let original = case readStorage (litAddr self) x (ConcreteStore vm._env._origStorage) of                                      Just (Lit v) -> v                                      _ -> 0                     let storage_cost = case (maybeLitWord current, maybeLitWord new) of@@ -1107,17 +1102,17 @@         -- op: PC         0x58 ->           limitStack 1 . burn g_base $-            next >> push (num (the state pc))+            next >> push (num vm._state._pc)          -- op: MSIZE         0x59 ->           limitStack 1 . burn g_base $-            next >> push (num (the state memorySize))+            next >> push (num vm._state._memorySize)          -- op: GAS         0x5a ->           limitStack 1 . burn g_base $-            next >> push (num (the state gas - g_base))+            next >> push (num (vm._state._gas - g_base))          -- op: JUMPDEST         0x5b -> burn g_jumpdest next@@ -1149,7 +1144,7 @@                 accessMemoryRange fees xOffset xSize $ do                   availableGas <- use (state . gas)                   let-                    newAddr = createAddress self (view nonce this)+                    newAddr = createAddress self this._nonce                     (cost, gas') = costOfCreate fees availableGas 0                   _ <- accessAccountForGas newAddr                   burn (cost - gas') $ do@@ -1177,8 +1172,9 @@                   delegateCall this (num xGas) xTo xTo xValue xInOffset xInSize xOutOffset xOutSize xs $ \callee -> do                     zoom state $ do                       assign callvalue (Lit xValue)-                      assign caller (litAddr self)+                      assign caller $ fromMaybe (litAddr self) (vm ^. overrideCaller)                       assign contract callee+                    assign overrideCaller Nothing                     transfer self callee xValue                     touchAccount self                     touchAccount callee@@ -1201,7 +1197,8 @@                   delegateCall this (num xGas) xTo (litAddr self) xValue xInOffset xInSize xOutOffset xOutSize xs $ \_ -> do                     zoom state $ do                       assign callvalue (Lit xValue)-                      assign caller (litAddr self)+                      assign caller $ fromMaybe (litAddr self) (vm ^. overrideCaller)+                    assign overrideCaller Nothing                     touchAccount self             _ ->               underrun@@ -1215,10 +1212,10 @@                   output = readMemory xOffset' xSize' vm                   codesize = fromMaybe (error "RETURN: cannot return dynamically sized abstract data")                                . unlit . bufLength $ output-                  maxsize = the block maxCodeSize-                  creation = case view frames vm of-                    [] -> the tx isCreate-                    frame:_ -> case view frameContext frame of+                  maxsize = vm._block._maxCodeSize+                  creation = case vm._frames of+                    [] -> vm._tx._isCreate+                    frame:_ -> case frame._frameContext of                        CreationContext {} -> True                        CallContext {} -> False                 if creation@@ -1292,9 +1289,10 @@                 delegateCall this (num xGas) xTo xTo 0 xInOffset xInSize xOutOffset xOutSize xs $ \callee -> do                   zoom state $ do                     assign callvalue (Lit 0)-                    assign caller (litAddr self)+                    assign caller $ fromMaybe (litAddr self) (vm ^. overrideCaller)                     assign contract callee                     assign static True+                  assign overrideCaller Nothing                   touchAccount self                   touchAccount callee             _ ->@@ -1308,7 +1306,7 @@             (xTo':_) -> forceConcrete xTo' "SELFDESTRUCT" $ \(num -> xTo) -> do               acc <- accessAccountForGas (num xTo)               let cost = if acc then 0 else g_cold_account_access-                  funds = view balance this+                  funds = this._balance                   recipientExists = accountExists xTo vm                   c_new = if not recipientExists && funds /= 0                           then g_selfdestruct_newaccount@@ -1351,20 +1349,20 @@   -> EVM () callChecks this xGas xContext xTo xValue xInOffset xInSize xOutOffset xOutSize xs continue = do   vm <- get-  let fees = view (block . schedule) vm+  let fees = vm._block._schedule   accessMemoryRange fees xInOffset xInSize $     accessMemoryRange fees xOutOffset xOutSize $ do       availableGas <- use (state . gas)       let recipientExists = accountExists xContext vm       (cost, gas') <- costOfCall fees recipientExists xValue availableGas xGas xTo       burn (cost - gas') $ do-        if xValue > num (view balance this)+        if xValue > num this._balance         then do           assign (state . stack) (Lit 0 : xs)           assign (state . returndata) mempty-          pushTrace $ ErrorTrace $ BalanceTooLow xValue (view balance this)+          pushTrace $ ErrorTrace $ BalanceTooLow xValue this._balance           next-        else if length (view frames vm) >= 1024+        else if length vm._frames >= 1024              then do                assign (state . stack) (Lit 0 : xs)                assign (state . returndata) mempty@@ -1389,18 +1387,20 @@     self <- use (state . contract)     stk <- use (state . stack)     pc' <- use (state . pc)-    case stk of-      (x:_) -> case maybeLitWord x of-        Just 0 ->-          return ()-        Just 1 ->-          fetchAccount recipient $ \_ -> do--          transfer self recipient xValue-          touchAccount self-          touchAccount recipient-        _ -> vmError $ UnexpectedSymbolicArg pc' "symbolic return value from precompile" [x]-      _ -> underrun+    result' <- use result+    case result' of+      Nothing -> case stk of+        (x:_) -> case maybeLitWord x of+          Just 0 ->+            return ()+          Just 1 ->+            fetchAccount recipient $ \_ -> do+              transfer self recipient xValue+              touchAccount self+              touchAccount recipient+          _ -> vmError $ UnexpectedSymbolicArg pc' "unexpected return value from precompile" [x]+        _ -> underrun+      _ -> pure ()  executePrecompile   :: (?op :: Word8)@@ -1410,7 +1410,7 @@ executePrecompile preCompileAddr gasCap inOffset inSize outOffset outSize xs  = do   vm <- get   let input = readMemory (Lit inOffset) (Lit inSize) vm-      fees = view (block . schedule) vm+      fees = vm._block._schedule       cost = costOfPrecompile fees preCompileAddr input       notImplemented = error $ "precompile at address " <> show preCompileAddr <> " not yet implemented"       precompileFail = burn (gasCap - cost) $ do@@ -1426,32 +1426,29 @@       case preCompileAddr of         -- ECRECOVER         0x1 ->-         -- TODO: support symbolic variant-         forceConcreteBuf input "ECRECOVER" $ \input' ->-          case EVM.Precompiled.execute 0x1 (truncpadlit 128 input') 32 of-            Nothing -> do-              -- return no output for invalid signature-              assign (state . stack) (Lit 1 : xs)-              assign (state . returndata) mempty-              next-            Just output -> do-              assign (state . stack) (Lit 1 : xs)-              assign (state . returndata) (ConcreteBuf output)-              copyBytesToMemory (ConcreteBuf output) (Lit outSize) (Lit 0) (Lit outOffset)-              next+          -- TODO: support symbolic variant+          forceConcreteBuf input "ECRECOVER" $ \input' -> do+            case EVM.Precompiled.execute 0x1 (truncpadlit 128 input') 32 of+              Nothing -> do+                -- return no output for invalid signature+                assign (state . stack) (Lit 1 : xs)+                assign (state . returndata) mempty+                next+              Just output -> do+                assign (state . stack) (Lit 1 : xs)+                assign (state . returndata) (ConcreteBuf output)+                copyBytesToMemory (ConcreteBuf output) (Lit outSize) (Lit 0) (Lit outOffset)+                next          -- SHA2-256-        0x2 ->+        0x2 -> forceConcreteBuf input "SHA2-256" $ \input' -> do           let-            hash = case input of-                     ConcreteBuf input' -> sha256Buf input'-                     _ -> WriteWord (Lit 0) (SHA256 input) mempty+            hash = sha256Buf input'             sha256Buf x = ConcreteBuf $ BA.convert (Crypto.hash x :: Digest SHA256)-          in do-            assign (state . stack) (Lit 1 : xs)-            assign (state . returndata) hash-            copyBytesToMemory hash (Lit outSize) (Lit 0) (Lit outOffset)-            next+          assign (state . stack) (Lit 1 : xs)+          assign (state . returndata) hash+          copyBytesToMemory hash (Lit outSize) (Lit 0) (Lit outOffset)+          next          -- RIPEMD-160         0x3 ->@@ -1601,7 +1598,7 @@ pushToSequence f x = f %= (Seq.|> x)  getCodeLocation :: VM -> CodeLocation-getCodeLocation vm = (view (state . contract) vm, view (state . pc) vm)+getCodeLocation vm = (vm._state._contract, vm._state._pc)  branch :: CodeLocation -> Expr EWord -> (Bool -> EVM ()) -> EVM () branch loc cond continue = do@@ -1652,13 +1649,13 @@         Just x ->           continue x         Nothing ->-          if view external c-          then-            -- check if the slot is cached-            use (cache . fetchedContracts . at addr) >>= \case-              Nothing -> forceConcrete slot "cannot read symbolic slots via RPC" mkQuery-              Just _ -> forceConcrete slot "cannot read symbolic slots via rpc" $-                \s -> maybe (mkQuery s) continue (readStorage (litAddr addr) slot store)+          if c._external then+            forceConcrete slot "cannot read symbolic slots via RPC" $ \litSlot -> do+              -- check if the slot is cached+              cachedStore <- use (cache . fetchedStorage)+              case Map.lookup (num addr) cachedStore >>= Map.lookup litSlot of+                Nothing -> mkQuery litSlot+                Just val -> continue (Lit val)           else do             modifying (env . storage) (writeStorage (litAddr addr) slot (Lit 0))             continue $ Lit 0@@ -1676,19 +1673,19 @@  accountExists :: Addr -> VM -> Bool accountExists addr vm =-  case view (env . contracts . at addr) vm of+  case Map.lookup addr vm._env._contracts of     Just c -> not (accountEmpty c)     Nothing -> False  -- EIP 161 accountEmpty :: Contract -> Bool accountEmpty c =-  case view contractcode c of+  case c._contractcode of     RuntimeCode (ConcreteRuntimeCode "") -> True     RuntimeCode (SymbolicRuntimeCode b) -> null b     _ -> False-  && (view nonce c == 0)-  && (view balance c == 0)+  && c._nonce == 0+  && c._balance  == 0  -- * How to finalize a transaction finalize :: EVM ()@@ -1731,7 +1728,7 @@   txOrigin     <- use (tx . origin)   sumRefunds   <- (sum . (snd <$>)) <$> (use (tx . substate . refunds))   miner        <- use (block . coinbase)-  blockReward  <- num . r_block <$> (use (block . schedule))+  blockReward  <- num . (.r_block) <$> (use (block . schedule))   gasPrice     <- use (tx . gasprice)   priorityFee  <- use (tx . txPriorityFee)   gasLimit     <- use (tx . txgaslimit)@@ -1813,16 +1810,11 @@     else       vmError (OutOfGas available n) ---forceConcreteAddr :: SAddr -> (Addr -> EVM ()) -> EVM ()---forceConcreteAddr n continue = case maybeLitAddr n of-  --Nothing -> vmError UnexpectedSymbolicArg-  --Just c -> continue c- forceConcrete :: Expr EWord -> String -> (W256 -> EVM ()) -> EVM () forceConcrete n msg continue = case maybeLitWord n of   Nothing -> do     vm <- get-    vmError $ UnexpectedSymbolicArg (view (state . pc) vm) msg [n]+    vmError $ UnexpectedSymbolicArg vm._state._pc msg [n]   Just c -> continue c  forceConcrete2 :: (Expr EWord, Expr EWord) -> String -> ((W256, W256) -> EVM ()) -> EVM ()@@ -1830,41 +1822,41 @@   (Just c, Just d) -> continue (c, d)   _ -> do     vm <- get-    vmError $ UnexpectedSymbolicArg (view (state . pc) vm) msg [n, m]+    vmError $ UnexpectedSymbolicArg vm._state._pc msg [n, m]  forceConcrete3 :: (Expr EWord, Expr EWord, Expr EWord) -> String -> ((W256, W256, W256) -> EVM ()) -> EVM () forceConcrete3 (k,n,m) msg continue = case (maybeLitWord k, maybeLitWord n, maybeLitWord m) of   (Just c, Just d, Just f) -> continue (c, d, f)   _ -> do     vm <- get-    vmError $ UnexpectedSymbolicArg (view (state . pc) vm) msg [k, n, m]+    vmError $ UnexpectedSymbolicArg vm._state._pc msg [k, n, m]  forceConcrete4 :: (Expr EWord, Expr EWord, Expr EWord, Expr EWord) -> String -> ((W256, W256, W256, W256) -> EVM ()) -> EVM () forceConcrete4 (k,l,n,m) msg continue = case (maybeLitWord k, maybeLitWord l, maybeLitWord n, maybeLitWord m) of   (Just b, Just c, Just d, Just f) -> continue (b, c, d, f)   _ -> do     vm <- get-    vmError $ UnexpectedSymbolicArg (view (state . pc) vm) msg [k, l, n, m]+    vmError $ UnexpectedSymbolicArg vm._state._pc msg [k, l, n, m]  forceConcrete5 :: (Expr EWord, Expr EWord, Expr EWord, Expr EWord, Expr EWord) -> String -> ((W256, W256, W256, W256, W256) -> EVM ()) -> EVM () forceConcrete5 (k,l,m,n,o) msg continue = case (maybeLitWord k, maybeLitWord l, maybeLitWord m, maybeLitWord n, maybeLitWord o) of   (Just a, Just b, Just c, Just d, Just e) -> continue (a, b, c, d, e)   _ -> do     vm <- get-    vmError $ UnexpectedSymbolicArg (view (state . pc) vm) msg [k, l, m, n, o]+    vmError $ UnexpectedSymbolicArg vm._state._pc msg [k, l, m, n, o]  forceConcrete6 :: (Expr EWord, Expr EWord, Expr EWord, Expr EWord, Expr EWord, Expr EWord) -> String -> ((W256, W256, W256, W256, W256, W256) -> EVM ()) -> EVM () forceConcrete6 (k,l,m,n,o,p) msg continue = case (maybeLitWord k, maybeLitWord l, maybeLitWord m, maybeLitWord n, maybeLitWord o, maybeLitWord p) of   (Just a, Just b, Just c, Just d, Just e, Just f) -> continue (a, b, c, d, e, f)   _ -> do     vm <- get-    vmError $ UnexpectedSymbolicArg (view (state . pc) vm) msg [k, l, m, n, o, p]+    vmError $ UnexpectedSymbolicArg vm._state._pc msg [k, l, m, n, o, p]  forceConcreteBuf :: Expr Buf -> String -> (ByteString -> EVM ()) -> EVM () forceConcreteBuf (ConcreteBuf b) _ continue = continue b forceConcreteBuf b msg _ = do     vm <- get-    vmError $ UnexpectedSymbolicArg (view (state . pc) vm) msg [b]+    vmError $ UnexpectedSymbolicArg vm._state._pc msg [b]  -- * Substate manipulation refund :: Word64 -> EVM ()@@ -1933,7 +1925,7 @@     abi = readBytes 4 (Lit inOffset) mem     input = readMemory (Lit $ inOffset + 4) (Lit $ inSize - 4) vm   case maybeLitWord abi of-    Nothing -> vmError $ UnexpectedSymbolicArg (view (state . pc) vm) "symbolic cheatcode selector" [abi]+    Nothing -> vmError $ UnexpectedSymbolicArg vm._state._pc "symbolic cheatcode selector" [abi]     Just (fromIntegral -> abi') ->       case Map.lookup abi' cheatActions of         Nothing ->@@ -1951,7 +1943,7 @@     [ action "ffi(string[])" $         \sig outOffset outSize input -> do           vm <- get-          if view EVM.allowFFI vm then+          if vm._allowFFI then             case decodeBuf [AbiArrayDynamicType AbiStringType] input of               CAbi valsArr -> case valsArr of                 [AbiArrayDynamic AbiStringType strsV] ->@@ -2049,6 +2041,11 @@                       addr = Lit . W256 . word256 . BS.drop 12 . BS.take 32 . keccakBytes $ pub                     assign (state . returndata . word256At (Lit 0)) addr                     assign (state . memory . word256At outOffset) addr+          _ -> vmError (BadCheatCode sig),++      action "prank(address)" $+        \sig _ _ input -> case decodeStaticArgs 0 1 input of+          [addr]  -> assign overrideCaller (Just addr)           _ -> vmError (BadCheatCode sig)      ]@@ -2093,12 +2090,12 @@                                     , callContextContext   = xContext'                                     , callContextOffset    = xOutOffset                                     , callContextSize      = xOutSize-                                    , callContextCodehash  = view codehash target-                                    , callContextReversion = (view (env . contracts) vm0, view (env . storage) vm0)-                                    , callContextSubState  = view (tx . substate) vm0+                                    , callContextCodehash  = target._codehash+                                    , callContextReversion = (vm0._env._contracts, vm0._env._storage)+                                    , callContextSubState  = vm0._tx._substate                                     , callContextAbi =                                         if xInSize >= 4-                                        then case unlit $ readBytes 4 (Lit xInOffset) (view (state . memory) vm0)+                                        then case unlit $ readBytes 4 (Lit xInOffset) vm0._state._memory                                              of Nothing -> Nothing                                                 Just abi -> Just $ num abi                                         else Nothing@@ -2110,7 +2107,7 @@                   vm1 <- get                    pushTo frames $ Frame-                    { _frameState = (set stack xs) (view state vm1)+                    { _frameState = vm1._state { _stack = xs }                     , _frameContext = newContext                     } @@ -2121,13 +2118,13 @@                   zoom state $ do                     assign gas (num xGas)                     assign pc 0-                    assign code (clearInitCode (view contractcode target))+                    assign code (clearInitCode target._contractcode)                     assign codeContract xTo'                     assign stack mempty                     assign memory mempty                     assign memorySize 0                     assign returndata mempty-                    assign calldata (copySlice (Lit xInOffset) (Lit 0) (Lit xInSize) (view (state . memory) vm0) mempty)+                    assign calldata (copySlice (Lit xInOffset) (Lit 0) (Lit xInSize) vm0._state._memory mempty)                    continue xTo' @@ -2136,7 +2133,7 @@ -- EIP 684 collision :: Maybe Contract -> Bool collision c' = case c' of-  Just c -> (view nonce c /= 0) || case view contractcode c of+  Just c -> c._nonce /= 0 || case c._contractcode of     RuntimeCode (ConcreteRuntimeCode "") -> False     RuntimeCode (SymbolicRuntimeCode b) -> not $ null b     _ -> True@@ -2148,25 +2145,25 @@ create self this xGas' xValue xs newAddr initCode = do   vm0 <- get   let xGas = num xGas'-  if view nonce this == num (maxBound :: Word64)+  if this._nonce == num (maxBound :: Word64)   then do     assign (state . stack) (Lit 0 : xs)     assign (state . returndata) mempty     pushTrace $ ErrorTrace NonceOverflow     next-  else if xValue > view balance this+  else if xValue > this._balance   then do     assign (state . stack) (Lit 0 : xs)     assign (state . returndata) mempty-    pushTrace $ ErrorTrace $ BalanceTooLow xValue (view balance this)+    pushTrace $ ErrorTrace $ BalanceTooLow xValue this._balance     next-  else if length (view frames vm0) >= 1024+  else if length vm0._frames >= 1024   then do     assign (state . stack) (Lit 0 : xs)     assign (state . returndata) mempty     pushTrace $ ErrorTrace CallDepthLimitReached     next-  else if collision $ view (env . contracts . at newAddr) vm0+  else if collision $ Map.lookup newAddr vm0._env._contracts   then burn xGas $ do     assign (state . stack) (Lit 0 : xs)     assign (state . returndata) mempty@@ -2188,20 +2185,20 @@           pure $ InitCode (BS.pack $ V.toList conc) sym     case contract' of       Nothing ->-        vmError $ UnexpectedSymbolicArg (view (state . pc) vm0) "initcode must have a concrete prefix" []+        vmError $ UnexpectedSymbolicArg vm0._state._pc "initcode must have a concrete prefix" []       Just c -> do         let           newContract = initialContract c           newContext  =             CreationContext { creationContextAddress   = newAddr-                            , creationContextCodehash  = view codehash newContract-                            , creationContextReversion = view (env . contracts) vm0-                            , creationContextSubstate  = view (tx . substate) vm0+                            , creationContextCodehash  = newContract._codehash+                            , creationContextReversion = vm0._env._contracts+                            , creationContextSubstate  = vm0._tx._substate                             }          zoom (env . contracts) $ do           oldAcc <- use (at newAddr)-          let oldBal = maybe 0 (view balance) oldAcc+          let oldBal = maybe 0 (._balance) oldAcc            assign (at newAddr) (Just (newContract & balance .~ oldBal))           modifying (ix self . nonce) succ@@ -2223,7 +2220,7 @@         vm1 <- get         pushTo frames $ Frame           { _frameContext = newContext-          , _frameState   = (set stack xs) (view state vm1)+          , _frameState   = vm1._state { _stack = xs }           }          assign state $@@ -2241,12 +2238,13 @@ replaceCode target newCode =   zoom (env . contracts . at target) $     get >>= \case-      Just now -> case (view contractcode now) of+      Just now -> case now._contractcode of         InitCode _ _ ->           put . Just $-          initialContract newCode-          & set balance (view balance now)-          & set nonce   (view nonce now)+            (initialContract newCode)+              { _balance = now._balance+              , _nonce = now._nonce+              }         RuntimeCode _ ->           error ("internal error: can't replace code of deployed contract " <> show target)       Nothing ->@@ -2255,7 +2253,7 @@ replaceCodeOfSelf :: ContractCode -> EVM () replaceCodeOfSelf newCode = do   vm <- get-  replaceCode (view (state . contract) vm) newCode+  replaceCode vm._state._contract newCode  resetState :: EVM () resetState = do@@ -2270,7 +2268,7 @@ vmError e = finishFrame (FrameErrored e)  underrun :: EVM ()-underrun = vmError StackUnderrun+underrun = vmError EVM.StackUnderrun  -- | A stack frame can be popped in three ways. data FrameResult@@ -2288,7 +2286,7 @@ finishFrame how = do   oldVm <- get -  case view frames oldVm of+  case oldVm._frames of     -- Is the current frame the only one?     [] -> do       case how of@@ -2308,26 +2306,26 @@           FrameReverted e ->             ErrorTrace (EVM.Revert e)           FrameReturned output ->-            ReturnTrace output (view frameContext nextFrame)+            ReturnTrace output nextFrame._frameContext       -- Pop to the previous level of the debug trace stack.       popTrace        -- Pop the top frame.       assign frames remainingFrames       -- Install the state of the frame to which we shall return.-      assign state (view frameState nextFrame)+      assign state nextFrame._frameState        -- When entering a call, the gas allowance is counted as burned       -- in advance; this unburns the remainder and adds it to the       -- parent frame.-      let remainingGas = view (state . gas) oldVm+      let remainingGas = oldVm._state._gas           reclaimRemainingGasAllowance = do             modifying burned (subtract remainingGas)             modifying (state . gas) (+ remainingGas)        -- Now dispatch on whether we were creating or calling,       -- and whether we shall return, revert, or error (six cases).-      case view frameContext nextFrame of+      case nextFrame._frameContext of          -- Were we calling?         CallContext _ _ (Lit -> outOffset) (Lit -> outSize) _ _ _ reversion substate' -> do@@ -2377,7 +2375,7 @@         CreationContext _ _ reversion substate' -> do           creator <- use (state . contract)           let-            createe = view (state . contract) oldVm+            createe = oldVm._state._contract             revertContracts = assign (env . contracts) reversion'             revertSubstate  = assign (tx . substate) substate' @@ -2399,7 +2397,7 @@                   case Expr.toList output of                     Nothing -> vmError $                       UnexpectedSymbolicArg-                        (view (state . pc) oldVm)+                        oldVm._state._pc                         "runtime code cannot have an abstract length"                         [output]                     Just newCode -> do@@ -2476,19 +2474,18 @@       copySlice xOffset yOffset (Expr.min size (bufLength bs)) bs mem  readMemory :: Expr EWord -> Expr EWord -> VM -> Expr Buf-readMemory offset size vm = copySlice offset (Lit 0) size (view (state . memory) vm) mempty+readMemory offset size vm = copySlice offset (Lit 0) size vm._state._memory mempty  -- * Tracing -withTraceLocation-  :: (MonadState VM m) => TraceData -> m Trace+withTraceLocation :: TraceData -> EVM Trace withTraceLocation x = do   vm <- get   let this = fromJust $ currentContract vm   pure Trace     { _traceData = x     , _traceContract = this-    , _traceOpIx = fromMaybe 0 $ (view opIxMap this) Vector.!? (view (state . pc) vm)+    , _traceOpIx = fromMaybe 0 $ this._opIxMap Vector.!? vm._state._pc     }  pushTrace :: TraceData -> EVM ()@@ -2517,9 +2514,9 @@     Just z' -> zipperRootForest (Zipper.nextSpace z')  traceForest :: VM -> Forest Trace-traceForest = view (traces . to zipperRootForest)+traceForest vm = zipperRootForest vm._traces -traceTopLog :: (MonadState VM m) => [Expr Log] -> m ()+traceTopLog :: [Expr Log] -> EVM () traceTopLog [] = noop traceTopLog ((LogEntry addr bytes topics) : _) = do   trace <- withTraceLocation (EventTrace addr bytes topics)@@ -2666,7 +2663,7 @@ vmOpIx :: VM -> Maybe Int vmOpIx vm =   do self <- currentContract vm-     (view opIxMap self) Vector.!? (view (state . pc) vm)+     self._opIxMap Vector.!? vm._state._pc  opParams :: VM -> Map String (Expr EWord) opParams vm =@@ -2939,8 +2936,8 @@ codeloc :: EVM CodeLocation codeloc = do   vm <- get-  let self = view (state . contract) vm-      loc = view (state . pc) vm+  let self = vm._state._contract+      loc = vm._state._pc   pure (self, loc)  -- * Emacs setup
src/EVM/CSE.hs view
@@ -40,43 +40,43 @@   -- buffers   e@(WriteWord {}) -> do     s <- get-    case Map.lookup e (bufs s) of+    case Map.lookup e s.bufs of       Just v -> pure $ GVar (BufVar v)       Nothing -> do         let-          next = count s-          bs' = Map.insert e next (bufs s)+          next = s.count+          bs' = Map.insert e next s.bufs         put $ s{bufs=bs', count=next+1}         pure $ GVar (BufVar next)   e@(WriteByte {}) -> do     s <- get-    case Map.lookup e (bufs s) of+    case Map.lookup e s.bufs of       Just v -> pure $ GVar (BufVar v)       Nothing -> do         let-          next = count s-          bs' = Map.insert e next (bufs s)+          next = s.count+          bs' = Map.insert e next s.bufs         put $ s{bufs=bs', count=next+1}         pure $ GVar (BufVar next)   e@(CopySlice {}) -> do     s <- get-    case Map.lookup e (bufs s) of+    case Map.lookup e s.bufs of       Just v -> pure $ GVar (BufVar v)       Nothing -> do         let-          next = count s-          bs' = Map.insert e next (bufs s)+          next = s.count+          bs' = Map.insert e next s.bufs         put $ s{count=next+1, bufs=bs'}         pure $ GVar (BufVar next)   -- storage   e@(SStore {}) -> do     s <- get-    case Map.lookup e (stores s) of+    case Map.lookup e s.stores of       Just v -> pure $ GVar (StoreVar v)       Nothing -> do         let-          next = count s-          ss' = Map.insert e next (stores s)+          next = s.count+          ss' = Map.insert e next s.stores         put $ s{count=next+1, stores=ss'}         pure $ GVar (StoreVar next)   e -> pure e@@ -91,7 +91,7 @@ eliminateExpr :: Expr a -> (Expr a, BufEnv, StoreEnv) eliminateExpr e =   let (e', st) = runState (eliminateExpr' e) initState in-  (e', invertKeyVal (bufs st), invertKeyVal (stores st))+  (e', invertKeyVal st.bufs, invertKeyVal st.stores)  -- | Common subexpression elimination pass for Prop eliminateProp' :: Prop -> State BuilderState Prop@@ -106,4 +106,4 @@ eliminateProps :: [Prop] -> ([Prop], BufEnv, StoreEnv) eliminateProps props =   let (props', st) = runState (eliminateProps' props) initState in-  (props',  invertKeyVal (bufs st),  invertKeyVal (stores st))+  (props',  invertKeyVal st.bufs,  invertKeyVal st.stores)
src/EVM/Dapp.hs view
@@ -1,64 +1,55 @@-{-# Language TemplateHaskell #-}- module EVM.Dapp where -import EVM (Trace, traceContract, traceOpIx, ContractCode(..), Contract(..), codehash, contractcode, RuntimeCode (..))+import EVM (Trace(..), ContractCode(..), Contract(..), RuntimeCode (..)) import EVM.ABI (Event, AbiType, SolError)+import EVM.Concrete import EVM.Debug (srcMapCodePos) import EVM.Solidity import EVM.Types (W256, abiKeccak, keccak', Addr, regexMatches, unlit, unlitByte) -import Data.ByteString (ByteString)-import qualified Data.ByteString as BS+import Control.Arrow ((>>>)) import Data.Aeson (Value) import Data.Bifunctor (first)+import Data.ByteString (ByteString)+import Data.ByteString qualified as BS+import Data.List (find, sort)+import Data.Map (Map)+import Data.Map qualified as Map+import Data.Maybe (isJust, fromJust, mapMaybe)+import Data.Sequence qualified as Seq import Data.Text (Text, isPrefixOf, pack, unpack) import Data.Text.Encoding (encodeUtf8)-import Data.Map (Map, toList, elems)-import Data.List (sort)-import Data.Maybe (isJust, fromJust, mapMaybe)+import Data.Vector qualified as V import Data.Word (Word32)-import EVM.Concrete -import Control.Arrow ((>>>))-import Control.Lens--import Data.List (find)-import qualified Data.Map        as Map-import qualified Data.Vector as V- data DappInfo = DappInfo-  { _dappRoot       :: FilePath-  , _dappSolcByName :: Map Text SolcContract-  , _dappSolcByHash :: Map W256 (CodeType, SolcContract)-  , _dappSolcByCode :: [(Code, SolcContract)] -- for contracts with `immutable` vars.-  , _dappSources    :: SourceCache-  , _dappUnitTests  :: [(Text, [(Test, [AbiType])])]-  , _dappAbiMap     :: Map Word32 Method-  , _dappEventMap   :: Map W256 Event-  , _dappErrorMap   :: Map W256 SolError-  , _dappAstIdMap   :: Map Int Value-  , _dappAstSrcMap  :: SrcMap -> Maybe Value+  { root       :: FilePath+  , solcByName :: Map Text SolcContract+  , solcByHash :: Map W256 (CodeType, SolcContract)+  , solcByCode :: [(Code, SolcContract)] -- for contracts with `immutable` vars.+  , sources    :: SourceCache+  , unitTests  :: [(Text, [(Test, [AbiType])])]+  , abiMap     :: Map Word32 Method+  , eventMap   :: Map W256 Event+  , errorMap   :: Map W256 SolError+  , astIdMap   :: Map Int Value+  , astSrcMap  :: SrcMap -> Maybe Value   }  -- | bytecode modulo immutables, to identify contracts-data Code =-  Code {-    raw :: ByteString,-    immutableLocations :: [Reference]+data Code = Code+  { raw :: ByteString+  , immutableLocations :: [Reference]   }   deriving Show  data DappContext = DappContext-  { _contextInfo :: DappInfo-  , _contextEnv  :: Map Addr Contract+  { info :: DappInfo+  , env  :: Map Addr Contract   }  data Test = ConcreteTest Text | SymbolicTest Text | InvariantTest Text -makeLenses ''DappInfo-makeLenses ''DappContext- instance Show Test where   show t = unpack $ extractSig t @@ -67,31 +58,31 @@ dappInfo root solcByName sources =   let     solcs = Map.elems solcByName-    astIds = astIdMap $ snd <$> toList (view sourceAsts sources)-    immutables = filter ((/=) mempty . (view immutableReferences)) solcs+    astIds = astIdMap $ snd <$> Map.toList sources.asts+    immutables = filter ((/=) mempty . (.immutableReferences)) solcs    in DappInfo-    { _dappRoot = root-    , _dappUnitTests = findAllUnitTests solcs-    , _dappSources = sources-    , _dappSolcByName = solcByName-    , _dappSolcByHash =+    { root = root+    , unitTests = findAllUnitTests solcs+    , sources = sources+    , solcByName = solcByName+    , solcByHash =         let-          f g k = Map.fromList [(view g x, (k, x)) | x <- solcs]+          f g k = Map.fromList [(g x, (k, x)) | x <- solcs]         in           mappend-           (f runtimeCodehash  Runtime)-           (f creationCodehash Creation)+           (f (.runtimeCodehash)  Runtime)+           (f (.creationCodehash) Creation)       -- contracts with immutable locations can't be id by hash-    , _dappSolcByCode =-      [(Code (_runtimeCode x) (concat $ elems $ _immutableReferences x), x) | x <- immutables]+    , solcByCode =+      [(Code x.runtimeCode (concat $ Map.elems x.immutableReferences), x) | x <- immutables]       -- Sum up the ABI maps from all the contracts.-    , _dappAbiMap   = mconcat (map (view abiMap) solcs)-    , _dappEventMap = mconcat (map (view eventMap) solcs)-    , _dappErrorMap = mconcat (map (view errorMap) solcs)+    , abiMap   = mconcat (map (.abiMap) solcs)+    , eventMap = mconcat (map (.eventMap) solcs)+    , errorMap = mconcat (map (.errorMap) solcs) -    , _dappAstIdMap  = astIds-    , _dappAstSrcMap = astSrcMap astIds+    , astIdMap  = astIds+    , astSrcMap = astSrcMap astIds     }  emptyDapp :: DappInfo@@ -123,24 +114,24 @@ findUnitTests :: Text -> ([SolcContract] -> [(Text, [(Test, [AbiType])])]) findUnitTests match =   concatMap $ \c ->-    case preview (abiMap . ix unitTestMarkerAbi) c of+    case Map.lookup unitTestMarkerAbi c.abiMap of       Nothing -> []       Just _  ->         let testNames = unitTestMethodsFiltered (regexMatches match) c-        in [(view contractName c, testNames) | not (BS.null (view runtimeCode c)) && not (null testNames)]+        in [(c.contractName, testNames) | not (BS.null c.runtimeCode) && not (null testNames)]  unitTestMethodsFiltered :: (Text -> Bool) -> (SolcContract -> [(Test, [AbiType])]) unitTestMethodsFiltered matcher c =   let-    testName method = (view contractName c) <> "." <> (extractSig (fst method))+    testName method = c.contractName <> "." <> (extractSig (fst method))   in     filter (matcher . testName) (unitTestMethods c)  unitTestMethods :: SolcContract -> [(Test, [AbiType])] unitTestMethods =-  view abiMap+  (.abiMap)   >>> Map.elems-  >>> map (\f -> (mkTest $ view methodSignature f, snd <$> view methodInputs f))+  >>> map (\f -> (mkTest f.methodSignature, snd <$> f.inputs))   >>> filter (isJust . fst)   >>> fmap (first fromJust) @@ -150,41 +141,37 @@ extractSig (InvariantTest sig) = sig  traceSrcMap :: DappInfo -> Trace -> Maybe SrcMap-traceSrcMap dapp trace =-  let-    h = view traceContract trace-    i = view traceOpIx trace-  in srcMap dapp h i+traceSrcMap dapp trace = srcMap dapp trace._traceContract trace._traceOpIx  srcMap :: DappInfo -> Contract -> Int -> Maybe SrcMap srcMap dapp contr opIndex = do   sol <- findSrc contr dapp-  case view contractcode contr of+  case contr._contractcode of     (InitCode _ _) ->-      preview (creationSrcmap . ix opIndex) sol+      Seq.lookup opIndex sol.creationSrcmap     (RuntimeCode _) ->-      preview (runtimeSrcmap . ix opIndex) sol+      Seq.lookup opIndex sol.runtimeSrcmap  findSrc :: Contract -> DappInfo -> Maybe SolcContract findSrc c dapp = do-  hash <- unlit (view codehash c)-  case preview (dappSolcByHash . ix hash) dapp of+  hash <- unlit c._codehash+  case Map.lookup hash dapp.solcByHash of     Just (_, v) -> Just v-    Nothing -> lookupCode (view contractcode c) dapp+    Nothing -> lookupCode c._contractcode dapp   lookupCode :: ContractCode -> DappInfo -> Maybe SolcContract lookupCode (InitCode c _) a =-  snd <$> preview (dappSolcByHash . ix (keccak' (stripBytecodeMetadata c))) a+  snd <$> Map.lookup (keccak' (stripBytecodeMetadata c)) a.solcByHash lookupCode (RuntimeCode (ConcreteRuntimeCode c)) a =-  case snd <$> preview (dappSolcByHash . ix (keccak' (stripBytecodeMetadata c))) a of+  case snd <$> Map.lookup (keccak' (stripBytecodeMetadata c)) a.solcByHash of     Just x -> return x-    Nothing -> snd <$> find (compareCode c . fst) (view dappSolcByCode a)+    Nothing -> snd <$> find (compareCode c . fst) a.solcByCode lookupCode (RuntimeCode (SymbolicRuntimeCode c)) a = let     code = BS.pack $ mapMaybe unlitByte $ V.toList c-  in case snd <$> preview (dappSolcByHash . ix (keccak' (stripBytecodeMetadata code))) a of+  in case snd <$> Map.lookup (keccak' (stripBytecodeMetadata code)) a.solcByHash of     Just x -> return x-    Nothing -> snd <$> find (compareCode code . fst) (view dappSolcByCode a)+    Nothing -> snd <$> find (compareCode code . fst) a.solcByCode  compareCode :: ByteString -> Code -> Bool compareCode raw (Code template locs) =@@ -198,7 +185,7 @@   case traceSrcMap dapp trace of     Nothing -> Left "<no source map>"     Just sm ->-      case srcMapCodePos (view dappSources dapp) sm of+      case srcMapCodePos dapp.sources sm of         Nothing -> Left "<source not found>"         Just (fileName, lineIx) ->           Right (fileName <> ":" <> pack (show lineIx))
src/EVM/Debug.hs view
@@ -1,7 +1,7 @@ module EVM.Debug where  import EVM          (Contract, nonce, balance, bytecode, codehash)-import EVM.Solidity (SrcMap, srcMapFile, srcMapOffset, srcMapLength, SourceCache, sourceFiles)+import EVM.Solidity (SrcMap, srcMapFile, srcMapOffset, srcMapLength, SourceCache(..)) import EVM.Types    (Addr) import EVM.Expr     (bufLength) @@ -43,12 +43,12 @@  srcMapCodePos :: SourceCache -> SrcMap -> Maybe (Text, Int) srcMapCodePos cache sm =-  fmap (second f) $ cache ^? sourceFiles . ix (srcMapFile sm)+  fmap (second f) $ cache.files ^? ix sm.srcMapFile   where-    f v = ByteString.count 0xa (ByteString.take (srcMapOffset sm - 1) v) + 1+    f v = ByteString.count 0xa (ByteString.take (sm.srcMapOffset - 1) v) + 1  srcMapCode :: SourceCache -> SrcMap -> Maybe ByteString srcMapCode cache sm =-  fmap f $ cache ^? sourceFiles . ix (srcMapFile sm)+  fmap f $ cache.files ^? ix sm.srcMapFile   where-    f (_, v) = ByteString.take (min 80 (srcMapLength sm)) (ByteString.drop (srcMapOffset sm) v)+    f (_, v) = ByteString.take (min 80 sm.srcMapLength) (ByteString.drop sm.srcMapOffset v)
src/EVM/Dev.hs view
@@ -19,6 +19,7 @@  import EVM import EVM.SMT+import EVM.Solvers import EVM.Types import EVM.Expr (numBranches, simplify) import EVM.SymExec
src/EVM/Exec.hs view
@@ -8,12 +8,10 @@ import qualified EVM.FeeSchedule as FeeSchedule  import Control.Lens-import Control.Monad.State.Class (MonadState)-import Control.Monad.State.Strict (runState)+import Control.Monad.Trans.State.Strict (get, State) import Data.ByteString (ByteString) import Data.Maybe (isNothing) -import qualified Control.Monad.State.Class as State  ethrunAddress :: Addr ethrunAddress = Addr 0x00a329c0648769a73afac7f9381e08fb43dbea72@@ -47,26 +45,27 @@     }) & set (env . contracts . at ethrunAddress)              (Just (initialContract (RuntimeCode (ConcreteRuntimeCode "")))) -exec :: MonadState VM m => m VMResult-exec =-  use EVM.result >>= \case-    Nothing -> State.state (runState exec1) >> exec-    Just x  -> return x+exec :: State VM VMResult+exec = do+  vm <- get+  case vm._result of+    Nothing -> exec1 >> exec+    Just r -> pure r -run :: MonadState VM m => m VM-run =-  use EVM.result >>= \case-    Nothing -> State.state (runState exec1) >> run-    Just _  -> State.get+run :: State VM VM+run = do+  vm <- get+  case vm._result of+    Nothing -> exec1 >> run+    Just _ -> pure vm -execWhile :: MonadState VM m => (VM -> Bool) -> m Int+execWhile :: (VM -> Bool) -> State VM Int execWhile p = go 0   where     go i = do-      x <- State.get-      if p x && isNothing (view result x)+      vm <- get+      if p vm && isNothing vm._result         then do-          State.state (runState exec1)           go $! (i + 1)       else-        return i+        pure i
src/EVM/Expr.hs view
@@ -678,6 +678,28 @@       | x == 0 = b       | otherwise = a +    -- simple div/mod/add/sub+    go (Div o1@(Lit _)  o2@(Lit _)) = EVM.Expr.div  o1 o2+    go (SDiv o1@(Lit _) o2@(Lit _)) = EVM.Expr.sdiv o1 o2+    go (Mod o1@(Lit _)  o2@(Lit _)) = EVM.Expr.mod  o1 o2+    go (SMod o1@(Lit _) o2@(Lit _)) = EVM.Expr.smod o1 o2+    go (Add o1@(Lit _)  o2@(Lit _)) = EVM.Expr.add  o1 o2+    go (Sub o1@(Lit _)  o2@(Lit _)) = EVM.Expr.sub  o1 o2++    -- double add/sub.+    -- Notice that everything is done mod 2**256. So for example:+    -- (a-b)+c observes the same arithmetic equalities as we are used to+    --         in infinite integers. In fact, it can be re-written as:+    -- (a+(W256Max-b)+c), which is the same as:+    -- (a+c+(W256Max-b)), which is the same as:+    -- (a+(c-b))+    -- In other words, subtraction is just adding a much larger number.+    --    So 3-1 mod 6 = 3+(6-1) mod 6 = 3+5 mod 6 = 5+3 mod 6 = 2+    go (Sub (Sub orig (Lit x)) (Lit y)) = Sub orig (Lit (y+x))+    go (Sub (Add orig (Lit x)) (Lit y)) = Sub orig (Lit (y-x))+    go (Add (Add orig (Lit x)) (Lit y)) = Add orig (Lit (y+x))+    go (Add (Sub orig (Lit x)) (Lit y)) = Add orig (Lit (y-x))+     -- redundant add / sub     go o@(Sub (Add a b) c)       | a == c = b
src/EVM/Facts.hs view
@@ -33,7 +33,7 @@   ) where  import EVM          (VM, Contract, Cache)-import EVM          (balance, nonce, storage, bytecode, env, contracts, contract, state, cache, fetchedStorage, fetchedContracts)+import EVM          (balance, nonce, storage, bytecode, env, contracts, cache, fetchedStorage, fetchedContracts) import EVM.Types    (Addr, W256, Expr(..), num) import EVM.Expr     (writeStorage, litAddr) @@ -112,15 +112,15 @@ contractFacts a x store = case view bytecode x of   ConcreteBuf b ->     storageFacts a store ++-    [ BalanceFact a (view balance x)-    , NonceFact   a (view nonce x)+    [ BalanceFact a x._balance+    , NonceFact   a x._nonce     , CodeFact    a b     ]   _ ->     -- here simply ignore storing the bytecode     storageFacts a store ++-    [ BalanceFact a (view balance x)-    , NonceFact   a (view nonce x)+    [ BalanceFact a x._balance+    , NonceFact   a x._nonce     ]  @@ -136,13 +136,13 @@  cacheFacts :: Cache -> Set Fact cacheFacts c = Set.fromList $ do-  (k, v) <- Map.toList (view EVM.fetchedContracts c)-  contractFacts k v (view EVM.fetchedStorage c)+  (k, v) <- Map.toList c._fetchedContracts+  contractFacts k v c._fetchedStorage  vmFacts :: VM -> Set Fact vmFacts vm = Set.fromList $ do-  (k, v) <- Map.toList (view (env . contracts) vm)-  case view (env . storage) vm of+  (k, v) <- Map.toList vm._env._contracts+  case vm._env._storage of     EmptyStore -> contractFacts k v Map.empty     ConcreteStore s -> contractFacts k v s     _ -> error "cannot serialize an abstract store"@@ -159,7 +159,7 @@   case fact of     CodeFact    {..} -> flip execState vm $ do       assign (env . contracts . at addr) (Just (EVM.initialContract (EVM.RuntimeCode (EVM.ConcreteRuntimeCode blob))))-      when (view (state . contract) vm == addr) $ EVM.loadContract addr+      when (vm._state._contract == addr) $ EVM.loadContract addr     StorageFact {..} ->       vm & over (env . storage) (writeStorage (litAddr addr) (Lit which) (Lit what))     BalanceFact {..} ->@@ -172,9 +172,9 @@   case fact of     CodeFact    {..} -> flip execState vm $ do       assign (cache . fetchedContracts . at addr) (Just (EVM.initialContract (EVM.RuntimeCode (EVM.ConcreteRuntimeCode blob))))-      when (view (state . contract) vm == addr) $ EVM.loadContract addr+      when (vm._state._contract == addr) $ EVM.loadContract addr     StorageFact {..} -> let-        store = view (cache . fetchedStorage) vm+        store = vm._cache._fetchedStorage         ctrct = Map.findWithDefault Map.empty (num addr) store       in         vm & set (cache . fetchedStorage) (Map.insert (num addr) (Map.insert which what ctrct) store)@@ -214,7 +214,7 @@   where     mk :: AsASCII a => [ASCII] -> ASCII -> a -> File     mk prefix base a =-      File (Path (dump (addr fact) : prefix) base)+      File (Path (dump fact.addr : prefix) base)            (Data $ dump a)  -- This lets us easier pattern match on serialized things.
src/EVM/Fetch.hs view
@@ -8,6 +8,7 @@ import EVM.ABI import EVM.Types    (Addr, W256, hexText, Expr(Lit), Expr(..), Prop(..), (.&&), (./=)) import EVM.SMT+import EVM.Solvers import EVM          (EVM, Contract, Block, initialContract, nonce, balance, external) import qualified EVM.FeeSchedule as FeeSchedule 
src/EVM/Format.hs view
@@ -1,7 +1,6 @@ {-# Language DataKinds #-} {-# Language ImplicitParams #-} - module EVM.Format   ( formatExpr   , contractNamePart@@ -27,45 +26,39 @@  import Prelude hiding (Word) -import qualified EVM-import EVM.Dapp (DappInfo (..), dappSolcByHash, dappAbiMap, showTraceLocation, dappEventMap, dappErrorMap)-import EVM.Dapp (DappContext (..), contextInfo, contextEnv)-import EVM (VM, cheatCode, traceForest, traceData, Error (..))-import EVM (Trace, TraceData (..), Query (..), FrameContext (..))-import EVM.Types (maybeLitWord, W256 (..), num, word, Expr(..), EType(..))-import EVM.Types (Addr, ByteStringS(..), Error(..))-import EVM.ABI (AbiValue (..), Event (..), AbiType (..), SolError (..))-import EVM.ABI (Indexed (NotIndexed), getAbiSeq)-import EVM.ABI (parseTypeName, formatString)-import EVM.Solidity (SolcContract(..), contractName, abiMap)-import EVM.Solidity (methodOutput, methodSignature, methodName)-import EVM.Hexdump-+import EVM qualified+import EVM (VM, cheatCode, traceForest, Error(..), Trace,+  TraceData(..), Query(..), FrameContext(..))+import EVM.ABI (AbiValue (..), Event (..), AbiType (..), SolError(..),+  Indexed(NotIndexed), getAbiSeq, parseTypeName, formatString)+import EVM.Dapp (DappContext(..), DappInfo(..), showTraceLocation)+import EVM.Expr qualified as Expr+import EVM.Hexdump (prettyHex)+import EVM.Solidity (SolcContract(..), Method(..))+import EVM.Types (maybeLitWord, W256(..), num, word, Expr(..), EType(..), Addr,+  ByteStringS(..), Error(..)) import Control.Arrow ((>>>))-import Control.Lens (view, preview, ix, _2, to, (^?!))+import Control.Lens (preview, ix, _2) import Data.Binary.Get (runGetOrFail)-import Data.Bits       (shiftR)+import Data.Bits (shiftR) import Data.ByteString (ByteString)+import Data.ByteString qualified as BS import Data.ByteString.Builder (byteStringHex, toLazyByteString) import Data.ByteString.Lazy (toStrict, fromStrict)+import Data.Char qualified as Char import Data.DoubleWord (signedWord) import Data.Foldable (toList)+import Data.Functor ((<&>))+import Data.Map qualified as Map import Data.Maybe (catMaybes, fromMaybe, fromJust)-import Data.Text (Text, pack, unpack, intercalate)-import Data.Text (dropEnd, splitOn)+import Data.Text (Text, pack, unpack, intercalate, dropEnd, splitOn)+import Data.Text qualified as T import Data.Text.Encoding (decodeUtf8, decodeUtf8') import Data.Tree.View (showTree) import Data.Vector (Vector) import Data.Word (Word32) import Numeric (showHex) -import qualified Data.ByteString as BS-import qualified Data.Char as Char-import qualified Data.Map as Map-import qualified Data.Text as Text-import qualified EVM.Expr as Expr-import qualified Data.Text as T- data Signedness = Signed | Unsigned   deriving (Show) @@ -73,7 +66,7 @@ showDec signed (W256 w)   | i == num cheatCode = "<hevm cheat address>"   | (i :: Integer) == 2 ^ (256 :: Integer) - 1 = "MAX_UINT256"-  | otherwise = Text.pack (show (i :: Integer))+  | otherwise = T.pack (show (i :: Integer))   where     i = case signed of           Signed   -> num (signedWord w)@@ -85,18 +78,18 @@ showWordExplanation :: W256 -> DappInfo -> Text showWordExplanation w _ | w > 0xffffffff = showDec Unsigned w showWordExplanation w dapp =-  case Map.lookup (fromIntegral w) (view dappAbiMap dapp) of+  case Map.lookup (fromIntegral w) dapp.abiMap of     Nothing -> showDec Unsigned w-    Just x  -> "keccak(\"" <> view methodSignature x <> "\")"+    Just x  -> "keccak(\"" <> x.methodSignature <> "\")"  humanizeInteger :: (Num a, Integral a, Show a) => a -> Text humanizeInteger =-  Text.intercalate ","+  T.intercalate ","   . reverse-  . map Text.reverse-  . Text.chunksOf 3-  . Text.reverse-  . Text.pack+  . map T.reverse+  . T.chunksOf 3+  . T.reverse+  . T.pack   . show  prettyIfConcreteWord :: Expr EWord -> Text@@ -109,14 +102,14 @@ showAbiValue (AbiBytesDynamic bs) = formatBytes bs showAbiValue (AbiBytes _ bs) = formatBinary bs showAbiValue (AbiAddress addr) =-  let dappinfo = view contextInfo ?context-      contracts = view contextEnv ?context-      name = case (Map.lookup addr contracts) of+  let dappinfo = ?context.info+      contracts = ?context.env+      name = case Map.lookup addr contracts of         Nothing -> ""         Just contract ->-          let hash = maybeLitWord $ view EVM.codehash contract+          let hash = maybeLitWord contract._codehash           in case hash of-               Just h -> maybeContractName' (preview (dappSolcByHash . ix h . _2) dappinfo)+               Just h -> maybeContractName' (preview (ix h . _2) dappinfo.solcByHash)                Nothing -> ""   in     name <> "@" <> (pack $ show addr)@@ -147,9 +140,9 @@  showError :: (?context :: DappContext) => Expr Buf -> Text showError (ConcreteBuf bs) =-  let dappinfo = view contextInfo ?context+  let dappinfo = ?context.info       bs4 = BS.take 4 bs-  in case Map.lookup (word bs4) (view dappErrorMap dappinfo) of+  in case Map.lookup (word bs4) dappinfo.errorMap of       Just (SolError errName ts) -> errName <> " " <> showCall ts (ConcreteBuf bs)       Nothing -> case bs4 of                   -- Method ID for Error(string)@@ -165,7 +158,7 @@   decodeUtf8' >>>     either       (const False)-      (Text.all (\c-> Char.isPrint c && (not . Char.isControl) c))+      (T.all (\c-> Char.isPrint c && (not . Char.isControl) c))  formatBytes :: ByteString -> Text formatBytes b =@@ -177,7 +170,7 @@  -- a string that came from bytes, displayed with special quotes formatBString :: ByteString -> Text-formatBString b = mconcat [ "«",  Text.dropAround (=='"') (pack $ formatString b), "»" ]+formatBString b = mconcat [ "«",  T.dropAround (=='"') (pack $ formatString b), "»" ]  formatBinary :: ByteString -> Text formatBinary =@@ -199,14 +192,14 @@  showTrace :: DappInfo -> VM -> Trace -> Text showTrace dapp vm trace =-  let ?context = DappContext { _contextInfo = dapp, _contextEnv = vm ^?! EVM.env . EVM.contracts }+  let ?context = DappContext { info = dapp, env = vm._env._contracts }   in let     pos =       case showTraceLocation dapp trace of         Left x -> " \x1b[1m" <> x <> "\x1b[0m"         Right x -> " \x1b[1m(" <> x <> ")\x1b[0m"-    fullAbiMap = view dappAbiMap dapp-  in case view traceData trace of+    fullAbiMap = dapp.abiMap+  in case trace._traceData of     EventTrace _ bytes topics ->       let logn = mconcat             [ "\x1b[36m"@@ -233,7 +226,7 @@         (t1:_) ->           case maybeLitWord t1 of             Just topic ->-              case Map.lookup (topic) (view dappEventMap dapp) of+              case Map.lookup topic dapp.eventMap of                 Just (Event name _ types) ->                   knownTopic name types                 Nothing ->@@ -255,9 +248,9 @@                           Nothing  ->                             "<symbolic>"                       in-                        case Map.lookup sig (view dappAbiMap dapp) of+                        case Map.lookup sig dapp.abiMap of                           Just m ->-                            lognote (view methodSignature m) usr+                            lognote m.methodSignature usr                           Nothing ->                             logn                     _ ->@@ -289,7 +282,7 @@       "← " <>         case Map.lookup (fromIntegral abi) fullAbiMap of           Just m  ->-            case unzip (view methodOutput m) of+            case unzip m.output of               ([], []) ->                 formatSBinary out               (_, ts) ->@@ -305,7 +298,7 @@       t     FrameTrace (CreationContext addr (Lit hash) _ _ ) -> -- FIXME: irrefutable pattern       "create "-      <> maybeContractName (preview (dappSolcByHash . ix hash . _2) dapp)+      <> maybeContractName (preview (ix hash . _2) dapp.solcByHash)       <> "@" <> pack (show addr)       <> pos     FrameTrace (CreationContext addr _ _ _ ) ->@@ -318,7 +311,7 @@                      then "call "                      else "delegatecall "           hash' = fromJust $ maybeLitWord hash-      in case preview (dappSolcByHash . ix hash' . _2) dapp of+      in case preview (ix hash' . _2) dapp.solcByHash of         Nothing ->           calltype             <> pack (show target)@@ -326,9 +319,9 @@             <> case Map.lookup (fromIntegral (fromMaybe 0x00 abi)) fullAbiMap of                  Just m  ->                    "\x1b[1m"-                   <> view methodName m+                   <> m.name                    <> "\x1b[0m"-                   <> showCall (catMaybes (getAbiTypes (view methodSignature m))) calldata+                   <> showCall (catMaybes (getAbiTypes m.methodSignature)) calldata                  Nothing ->                    formatSBinary calldata             <> pos@@ -336,7 +329,7 @@         Just solc ->           calltype             <> "\x1b[1m"-            <> view (contractName . to contractNamePart) solc+            <> contractNamePart solc.contractName             <> "::"             <> maybe "[fallback function]"                  (fromMaybe "[unknown method]" . maybeAbiName solc)@@ -356,20 +349,20 @@  maybeContractName :: Maybe SolcContract -> Text maybeContractName =-  maybe "<unknown contract>" (view (contractName . to contractNamePart))+  maybe "<unknown contract>" (contractNamePart . (.contractName))  maybeContractName' :: Maybe SolcContract -> Text maybeContractName' =-  maybe "" (view (contractName . to contractNamePart))+  maybe "" (contractNamePart . (.contractName))  maybeAbiName :: SolcContract -> W256 -> Maybe Text-maybeAbiName solc abi = preview (abiMap . ix (fromIntegral abi) . methodSignature) solc+maybeAbiName solc abi = Map.lookup (fromIntegral abi) solc.abiMap <&> (.methodSignature)  contractNamePart :: Text -> Text-contractNamePart x = Text.split (== ':') x !! 1+contractNamePart x = T.split (== ':') x !! 1  contractPathPart :: Text -> Text-contractPathPart x = Text.split (== ':') x !! 0+contractPathPart x = T.split (== ':') x !! 0  prettyError :: EVM.Types.Error -> String prettyError= \case@@ -379,6 +372,7 @@   EVM.Types.StackLimitExceeded -> "Stack limit exceeded"   EVM.Types.InvalidMemoryAccess -> "Invalid memory access"   EVM.Types.BadJumpDestination -> "Bad jump destination"+  EVM.Types.StackUnderrun -> "Stack underrun"   TmpErr err -> "Temp error: " <> err  
src/EVM/Keccak.hs view
@@ -27,7 +27,7 @@ go = \case   e@(Keccak _) -> do     s <- get-    put $ s{keccaks=Set.insert e (keccaks s)}+    put $ s{keccaks=Set.insert e s.keccaks}     pure e   e -> pure e @@ -73,7 +73,7 @@   where     (_, st) = runState (findKeccakPropsExprs ps bufs stores) initState -    injectivity = fmap injProp $ combine (Set.toList (keccaks st))-    minValue = fmap minProp (Set.toList (keccaks st))+    injectivity = fmap injProp $ combine (Set.toList st.keccaks)+    minValue = fmap minProp (Set.toList st.keccaks)  
src/EVM/Op.hs view
@@ -62,6 +62,7 @@   | OpGaslimit   | OpChainid   | OpSelfbalance+  | OpBaseFee   | OpPop   | OpMload   | OpMstore@@ -145,6 +146,7 @@   OpGaslimit -> "GASLIMIT"   OpChainid -> "CHAINID"   OpSelfbalance -> "SELFBALANCE"+  OpBaseFee -> "BASEFEE"   OpPop -> "POP"   OpMload -> "MLOAD"   OpMstore -> "MSTORE"
src/EVM/SMT.hs view
@@ -13,33 +13,28 @@  import Prelude hiding (LT, GT) -import GHC.Natural import Control.Monad-import GHC.IO.Handle (Handle, hFlush, hSetBuffering, BufferMode(..))-import Control.Concurrent.Chan (Chan, newChan, writeChan, readChan)-import Control.Concurrent (forkIO, killThread)-import Data.Char (isSpace) import Data.Containers.ListUtils (nubOrd) import Language.SMT2.Parser (getValueRes, parseCommentFreeFileMsg)-import Language.SMT2.Syntax (SpecConstant(..), GeneralRes(..), Term(..), QualIdentifier(..), Identifier(..), Sort(..), Index(..), VarBinding(..))+import Language.SMT2.Syntax (Symbol, SpecConstant(..), GeneralRes(..), Term(..), QualIdentifier(..), Identifier(..), Sort(..), Index(..), VarBinding(..)) import Data.Word-import Numeric (readHex)+import Numeric (readHex, readBin) import Data.ByteString (ByteString)  import qualified Data.ByteString as BS import qualified Data.List as List import Data.List.NonEmpty (NonEmpty((:|)))+import qualified Data.List.NonEmpty as NonEmpty import Data.String.Here-import Data.Maybe+import Data.Maybe (fromJust) import Data.Map (Map) import qualified Data.Map as Map import Data.Text.Lazy (Text) import qualified Data.Text as TS import qualified Data.Text.Lazy as T-import qualified Data.Text.Lazy.IO as T import Data.Text.Lazy.Builder import Data.Bifunctor (second)-import System.Process (createProcess, cleanupProcess, proc, ProcessHandle, std_in, std_out, std_err, StdStream(..))+import Data.Semigroup (Any, Any(..), getAny)  import EVM.Types import EVM.Traversals@@ -53,18 +48,20 @@ data CexVars = CexVars   { calldataV :: [Text]   , buffersV :: [Text]+  , storeReads :: [(Expr EWord, Expr EWord)] -- a list of relevant store reads   , blockContextV :: [Text]   , txContextV :: [Text]   }   deriving (Eq, Show)  instance Semigroup CexVars where-  (CexVars a b c d) <> (CexVars a2 b2 c2 d2) = CexVars (a <> a2) (b <> b2) (c <> c2) (d <> d2)+  (CexVars a b c d e) <> (CexVars a2 b2 c2 d2 e2) = CexVars (a <> a2) (b <> b2) (c <> c2) (d <> d2) (e <> e2)  instance Monoid CexVars where     mempty = CexVars       { calldataV = mempty       , buffersV = mempty+      , storeReads = mempty       , blockContextV = mempty       , txContextV = mempty       }@@ -72,13 +69,14 @@ data SMTCex = SMTCex   { vars :: Map (Expr EWord) W256   , buffers :: Map (Expr Buf) ByteString+  , store :: Map W256 (Map W256 W256)   , blockContext :: Map (Expr EWord) W256   , txContext :: Map (Expr EWord) W256   }   deriving (Eq, Show)  getVar :: EVM.SMT.SMTCex -> TS.Text -> W256-getVar cex name = fromJust $ Map.lookup (Var name) (vars cex)+getVar cex name = fromJust $ Map.lookup (Var name) cex.vars  data SMT2 = SMT2 [Builder] CexVars   deriving (Eq, Show)@@ -125,6 +123,7 @@   <> keccakAssumes   <> SMT2 [""] mempty   <> SMT2 (fmap (\p -> "(assert " <> p <> ")") encs) mempty+  <> SMT2 [] mempty{storeReads = storageReads}    where     (ps_elim, bufs, stores) = eliminateProps ps@@ -137,11 +136,125 @@     bufVals = Map.elems bufs     storeVals = Map.elems stores +    storageReads = nubOrd $ concatMap findStorageReads ps+     keccakAssumes       = SMT2 ["; keccak assumptions"] mempty       <> SMT2 (fmap (\p -> "(assert " <> propToSMT p <> ")") (keccakAssumptions ps_elim bufVals storeVals)) mempty  +referencedBufsGo :: Expr a -> [Builder]+referencedBufsGo = \case+  AbstractBuf s -> [fromText s]+  _ -> []++referencedBufs :: Expr a -> [Builder]+referencedBufs expr = nubOrd $ foldExpr referencedBufsGo [] expr++referencedBufs' :: Prop -> [Builder]+referencedBufs' prop = nubOrd $ foldProp referencedBufsGo [] prop+++referencedVarsGo :: Expr a -> [Builder]+referencedVarsGo = \case+  Var s -> [fromText s]+  _ -> []++referencedVars :: Expr a -> [Builder]+referencedVars expr = nubOrd $ foldExpr referencedVarsGo [] expr++referencedVars' :: Prop -> [Builder]+referencedVars' prop = nubOrd $ foldProp referencedVarsGo [] prop+++referencedFrameContextGo :: Expr a -> [Builder]+referencedFrameContextGo = \case+  CallValue a -> [fromLazyText $ T.append "callvalue_" (T.pack . show $ a)]+  Caller a -> [fromLazyText $ T.append "caller_" (T.pack . show $ a)]+  Address a -> [fromLazyText $ T.append "address_" (T.pack . show $ a)]+  Balance {} -> error "TODO: BALANCE"+  SelfBalance {} -> error "TODO: SELFBALANCE"+  Gas {} -> error "TODO: GAS"+  _ -> []++referencedFrameContext :: Expr a -> [Builder]+referencedFrameContext expr = nubOrd $ foldExpr referencedFrameContextGo [] expr++referencedFrameContext' :: Prop -> [Builder]+referencedFrameContext' prop = nubOrd $ foldProp referencedFrameContextGo [] prop+++referencedBlockContextGo :: Expr a -> [Builder]+referencedBlockContextGo = \case+  Origin -> ["origin"]+  Coinbase -> ["coinbase"]+  Timestamp -> ["timestamp"]+  BlockNumber -> ["blocknumber"]+  PrevRandao -> ["prevrandao"]+  GasLimit -> ["gaslimit"]+  ChainId -> ["chainid"]+  BaseFee -> ["basefee"]+  _ -> []++referencedBlockContext :: Expr a -> [Builder]+referencedBlockContext expr = nubOrd $ foldExpr referencedBlockContextGo [] expr++referencedBlockContext' :: Prop -> [Builder]+referencedBlockContext' prop = nubOrd $ foldProp referencedBlockContextGo [] prop+++isAbstractStorage :: Expr Storage -> Bool+isAbstractStorage = getAny . foldExpr go (Any False)+  where+    go :: Expr a -> Any+    go AbstractStore = Any True+    go _ = Any False++-- | This function overapproximates the reads from the abstract+-- storage. Potentially, it can return locations that do not read a+-- slot directly from the abstract store but from subsequent writes on+-- the store (e.g, SLoad addr idx (SStore addr idx val AbstractStore)).+-- However, we expect that most of such reads will have been+-- simplified away.+findStorageReads :: Prop -> [(Expr EWord, Expr EWord)]+findStorageReads = foldProp go []+  where+    go :: Expr a -> [(Expr EWord, Expr EWord)]+    go = \case+      SLoad addr slot storage -> [(addr, slot) | isAbstractStorage storage]+      _ -> []+++declareBufs :: [Builder] -> SMT2+declareBufs names = SMT2 ("; buffers" : fmap declareBuf names <> ("; buffer lengths" : fmap declareLength names)) cexvars+  where+    declareBuf n = "(declare-const " <> n <> " (Array (_ BitVec 256) (_ BitVec 8)))"+    declareLength n = "(define-const " <> n <> "_length" <> " (_ BitVec 256) (bufLength " <> n <> "))"+    cexvars = mempty{buffersV = fmap toLazyText names}+++-- Given a list of 256b VM variable names, create an SMT2 object with the variables declared+declareVars :: [Builder] -> SMT2+declareVars names = SMT2 (["; variables"] <> fmap declare names) cexvars+  where+    declare n = "(declare-const " <> n <> " (_ BitVec 256))"+    cexvars = mempty{calldataV = fmap toLazyText names}+++declareFrameContext :: [Builder] -> SMT2+declareFrameContext names = SMT2 (["; frame context"] <> fmap declare names) cexvars+  where+    declare n = "(declare-const " <> n <> " (_ BitVec 256))"+    cexvars = mempty{txContextV = fmap toLazyText names}+++declareBlockContext :: [Builder] -> SMT2+declareBlockContext names = SMT2 (["; block context"] <> fmap declare names) cexvars+  where+    declare n = "(declare-const " <> n <> " (_ BitVec 256))"+    cexvars = mempty{blockContextV = fmap toLazyText names}++ prelude :: SMT2 prelude =  (flip SMT2) mempty $ fmap (fromLazyText . T.drop 2) . T.lines $ [i|   ; logic@@ -348,6 +461,7 @@     (ite (= b (_ bv28 256)) ((_ sign_extend 24 ) ((_ extract 231  0) val))     (ite (= b (_ bv29 256)) ((_ sign_extend 16 ) ((_ extract 239  0) val))     (ite (= b (_ bv30 256)) ((_ sign_extend 8  ) ((_ extract 247  0) val)) val))))))))))))))))))))))))))))))))+   ; storage   (declare-const abstractStore Storage)   (define-const emptyStore Storage ((as const Storage) ((as const (Array (_ BitVec 256) (_ BitVec 256))) #x0000000000000000000000000000000000000000000000000000000000000000)))@@ -357,145 +471,7 @@   (define-fun sload ((addr Word) (key Word) (storage Storage)) Word (select (select storage addr) key))   |] -declareBufs :: [Builder] -> SMT2-declareBufs names = SMT2 ("; buffers" : fmap declareBuf names <> ("; buffer lengths" : fmap declareLength names)) cexvars-  where-    declareBuf n = "(declare-const " <> n <> " (Array (_ BitVec 256) (_ BitVec 8)))"-    declareLength n = "(define-const " <> n <> "_length" <> " (_ BitVec 256) (bufLength " <> n <> "))"-    cexvars = CexVars-      { calldataV = mempty-      , buffersV = (fmap toLazyText names)-      , blockContextV = mempty-      , txContextV = mempty-      } -referencedBufs :: Expr a -> [Builder]-referencedBufs expr = nubOrd (foldExpr go [] expr)-  where-    go :: Expr a -> [Builder]-    go = \case-      AbstractBuf s -> [fromText s]-      _ -> []--referencedBufs' :: Prop -> [Builder]-referencedBufs' = \case-  PEq a b -> nubOrd $ referencedBufs a <> referencedBufs b-  PLT a b -> nubOrd $ referencedBufs a <> referencedBufs b-  PGT a b -> nubOrd $ referencedBufs a <> referencedBufs b-  PLEq a b -> nubOrd $ referencedBufs a <> referencedBufs b-  PGEq a b -> nubOrd $ referencedBufs a <> referencedBufs b-  PAnd a b -> nubOrd $ referencedBufs' a <> referencedBufs' b-  POr a b -> nubOrd $ referencedBufs' a <> referencedBufs' b-  PNeg a -> referencedBufs' a-  PBool _ -> []--referencedVars' :: Prop -> [Builder]-referencedVars' = \case-  PEq a b -> nubOrd $ referencedVars a <> referencedVars b-  PLT a b -> nubOrd $ referencedVars a <> referencedVars b-  PGT a b -> nubOrd $ referencedVars a <> referencedVars b-  PLEq a b -> nubOrd $ referencedVars a <> referencedVars b-  PGEq a b -> nubOrd $ referencedVars a <> referencedVars b-  PAnd a b -> nubOrd $ referencedVars' a <> referencedVars' b-  POr a b -> nubOrd $ referencedVars' a <> referencedVars' b-  PNeg a -> referencedVars' a-  PBool _ -> []--referencedFrameContext' :: Prop -> [Builder]-referencedFrameContext' = \case-  PEq a b -> nubOrd $ referencedFrameContext a <> referencedFrameContext b-  PLT a b -> nubOrd $ referencedFrameContext a <> referencedFrameContext b-  PGT a b -> nubOrd $ referencedFrameContext a <> referencedFrameContext b-  PLEq a b -> nubOrd $ referencedFrameContext a <> referencedFrameContext b-  PGEq a b -> nubOrd $ referencedFrameContext a <> referencedFrameContext b-  PAnd a b -> nubOrd $ referencedFrameContext' a <> referencedFrameContext' b-  POr a b -> nubOrd $ referencedFrameContext' a <> referencedFrameContext' b-  PNeg a -> referencedFrameContext' a-  PBool _ -> []--referencedBlockContext' :: Prop -> [Builder]-referencedBlockContext' = \case-  PEq a b -> nubOrd $ referencedBlockContext a <> referencedBlockContext b-  PLT a b -> nubOrd $ referencedBlockContext a <> referencedBlockContext b-  PGT a b -> nubOrd $ referencedBlockContext a <> referencedBlockContext b-  PLEq a b -> nubOrd $ referencedBlockContext a <> referencedBlockContext b-  PGEq a b -> nubOrd $ referencedBlockContext a <> referencedBlockContext b-  PAnd a b -> nubOrd $ referencedBlockContext' a <> referencedBlockContext' b-  POr a b -> nubOrd $ referencedBlockContext' a <> referencedBlockContext' b-  PNeg a -> referencedBlockContext' a-  PBool _ -> []---- Given a list of 256b VM variable names, create an SMT2 object with the variables declared-declareVars :: [Builder] -> SMT2-declareVars names = SMT2 (["; variables"] <> fmap declare names) cexvars-  where-    declare n = "(declare-const " <> n <> " (_ BitVec 256))"-    cexvars = CexVars-      { calldataV = fmap toLazyText names-      , buffersV = mempty-      , blockContextV = mempty-      , txContextV = mempty-      }--referencedVars :: Expr a -> [Builder]-referencedVars expr = nubOrd (foldExpr go [] expr)-  where-    go :: Expr a -> [Builder]-    go = \case-      Var s -> [fromText s]-      _ -> []--declareFrameContext :: [Builder] -> SMT2-declareFrameContext names = SMT2 (["; frame context"] <> fmap declare names) cexvars-  where-    declare n = "(declare-const " <> n <> " (_ BitVec 256))"-    cexvars = CexVars-      { calldataV = mempty-      , buffersV = mempty-      , blockContextV = mempty-      , txContextV = fmap toLazyText names-      }--referencedFrameContext :: Expr a -> [Builder]-referencedFrameContext expr = nubOrd (foldExpr go [] expr)-  where-    go :: Expr a -> [Builder]-    go = \case-      CallValue a -> [fromLazyText $ T.append "callvalue_" (T.pack . show $ a)]-      Caller a -> [fromLazyText $ T.append "caller_" (T.pack . show $ a)]-      Address a -> [fromLazyText $ T.append "address_" (T.pack . show $ a)]-      Balance {} -> error "TODO: BALANCE"-      SelfBalance {} -> error "TODO: SELFBALANCE"-      Gas {} -> error "TODO: GAS"-      _ -> []--declareBlockContext :: [Builder] -> SMT2-declareBlockContext names = SMT2 (["; block context"] <> fmap declare names) cexvars-  where-    declare n = "(declare-const " <> n <> " (_ BitVec 256))"-    cexvars = CexVars-      { calldataV = mempty-      , buffersV = mempty-      , blockContextV = fmap toLazyText names-      , txContextV = mempty-      }--referencedBlockContext :: Expr a -> [Builder]-referencedBlockContext expr = nubOrd (foldExpr go [] expr)-  where-    go :: Expr a -> [Builder]-    go = \case-      Origin -> ["origin"]-      Coinbase -> ["coinbase"]-      Timestamp -> ["timestamp"]-      BlockNumber -> ["blocknumber"]-      PrevRandao -> ["prevrandao"]-      GasLimit -> ["gaslimit"]-      ChainId -> ["chainid"]-      BaseFee -> ["basefee"]-      _ -> []-- exprToSMT :: Expr a -> Builder exprToSMT = \case   Lit w -> fromLazyText $ "(_ bv" <> (T.pack $ show (num w :: Integer)) <> " 256)"@@ -565,6 +541,14 @@         bLift = "(concat (_ bv0 256) " <> bExp <> ")"         cLift = "(concat (_ bv0 256) " <> cExp <> ")"     in  "((_ extract 255 0) (ite (= " <> cExp <> " (_ bv0 256)) (_ bv0 512) (bvurem (bvmul " <> aLift `sp` bLift <> ")" <> cLift <> ")))"+  AddMod a b c ->+    let aExp = exprToSMT a+        bExp = exprToSMT b+        cExp = exprToSMT c+        aLift = "(concat (_ bv0 256) " <> aExp <> ")"+        bLift = "(concat (_ bv0 256) " <> bExp <> ")"+        cLift = "(concat (_ bv0 256) " <> cExp <> ")"+    in  "((_ extract 255 0) (ite (= " <> cExp <> " (_ bv0 256)) (_ bv0 512) (bvurem (bvadd " <> aLift `sp` bLift <> ")" <> cLift <> ")))"   EqByte a b ->     let cond = op2 "=" a b in     "(ite " <> cond `sp` one `sp` zero <> ")"@@ -684,71 +668,70 @@       "(" <> op <> " " <> aenc <> " " <> benc <> ")"  --- ** Execution ** ------------------------------------------------------------------------------- +-- ** Helpers ** --------------------------------------------------------------------------------- --- | Supported solvers-data Solver-  = Z3-  | CVC5-  | Bitwuzla-  | Custom Text -instance Show Solver where-  show Z3 = "z3"-  show CVC5 = "cvc5"-  show Bitwuzla = "bitwuzla"-  show (Custom s) = T.unpack s+-- | Stores a region of src into dst+copySlice :: Expr EWord -> Expr EWord -> Expr EWord -> Builder -> Builder -> Builder+copySlice srcOffset dstOffset size@(Lit _) src dst+  | size == (Lit 0) = dst+  | otherwise =+    let size' = (sub size (Lit 1))+        encDstOff = exprToSMT (add dstOffset size')+        encSrcOff = exprToSMT (add srcOffset size')+        child = copySlice srcOffset dstOffset size' src dst in+    "(store " <> child `sp` encDstOff `sp` "(select " <> src `sp` encSrcOff <> "))"+copySlice _ _ _ _ _ = error "TODO: implement copySlice with a symbolically sized region" +-- | Unrolls an exponentiation into a series of multiplications+expandExp :: Expr EWord -> W256 -> Builder+expandExp base expnt+  | expnt == 1 = exprToSMT base+  | otherwise =+    let b = exprToSMT base+        n = expandExp base (expnt - 1) in+    "(bvmul " <> b `sp` n <> ")" --- | A running solver instance-data SolverInstance = SolverInstance-  { _type :: Solver-  , _stdin :: Handle-  , _stdout :: Handle-  , _stderr :: Handle-  , _process :: ProcessHandle-  }+-- | Concatenates a list of bytes into a larger bitvector+concatBytes :: [Expr Byte] -> Builder+concatBytes bytes =+  let bytesRev = reverse bytes+      a2 = exprToSMT (head bytesRev) in+  foldl wrap a2 $ tail bytesRev+  where+    wrap inner byte =+      let byteSMT = exprToSMT byte in+      "(concat " <> byteSMT `sp` inner <> ")" --- | A channel representing a group of solvers-newtype SolverGroup = SolverGroup (Chan Task)+-- | Concatenates a list of bytes into a larger bitvector+writeBytes :: ByteString -> Expr Buf -> Builder+writeBytes bytes buf = snd $ BS.foldl' wrap (0, exprToSMT buf) bytes+  where+    -- we don't need to store zeros if the base buffer is empty+    skipZeros = buf == mempty+    wrap :: (Int, Builder) -> Word8 -> (Int, Builder)+    wrap (idx, inner) byte =+      if skipZeros && byte == 0+      then (idx + 1, inner)+      else let+          byteSMT = exprToSMT (LitByte byte)+          idxSMT = exprToSMT . Lit . num $ idx+        in (idx + 1, "(store " <> inner `sp` idxSMT `sp` byteSMT <> ")") --- | A script to be executed, a list of models to be extracted in the case of a sat result, and a channel where the result should be written-data Task = Task-  { script :: SMT2-  , resultChan :: Chan CheckSatResult-  }+encodeConcreteStore :: Map W256 (Map W256 W256) -> Builder+encodeConcreteStore s = foldl encodeWrite "emptyStore" writes+  where+    asList = fmap (second Map.toList) $ Map.toList s+    writes = concatMap (\(addr, ws) -> fmap (\(k, v) -> (addr, k, v)) ws) asList+    encodeWrite prev (addr, key, val) = let+        encAddr = exprToSMT (Lit addr)+        encKey = exprToSMT (Lit key)+        encVal = exprToSMT (Lit val)+      in "(sstore " <> encAddr `sp` encKey `sp` encVal `sp` prev <> ")" --- | The result of a call to (check-sat)-data CheckSatResult-  = Sat SMTCex-  | Unsat-  | Unknown-  | Error TS.Text-  deriving (Show, Eq) -isSat :: CheckSatResult -> Bool-isSat (Sat _) = True-isSat _ = False--isErr :: CheckSatResult -> Bool-isErr (Error _) = True-isErr _ = False--isUnsat :: CheckSatResult -> Bool-isUnsat Unsat = True-isUnsat _ = False--checkSat :: SolverGroup -> SMT2 -> IO CheckSatResult-checkSat (SolverGroup taskQueue) script = do-  -- prepare result channel-  resChan <- newChan--  -- send task to solver group-  writeChan taskQueue (Task script resChan)--  -- collect result-  readChan resChan+-- ** Cex parsing ** --------------------------------------------------------------------------------  parseW256 :: SpecConstant -> W256 parseW256 = parseSC@@ -759,6 +742,11 @@ parseW8 :: SpecConstant -> Word8 parseW8 = parseSC +parseSC :: (Num a, Eq a) => SpecConstant -> a+parseSC (SCHexadecimal a) = fst . head . Numeric.readHex . T.unpack . T.fromStrict $ a+parseSC (SCBinary a) = fst . head . Numeric.readBin . T.unpack . T.fromStrict $ a+parseSC sc = error $ "Internal Error: cannot parse: " <> show sc+ parseErr :: (Show a) => a -> b parseErr res = error $ "Internal Error: cannot parse solver response: " <> show res @@ -783,12 +771,12 @@   ('a':'d':'d':'r':'e':'s':'s':'_':frame) -> Address (read frame)   t -> error $ "Internal Error: cannot parse " <> t <> " into an Expr" -getVars :: (TS.Text -> Expr EWord) -> SolverInstance -> [TS.Text] -> IO (Map (Expr EWord) W256)-getVars parseFn inst names = Map.mapKeys parseFn <$> foldM getOne mempty names+getVars :: (TS.Text -> Expr EWord) -> (Text -> IO Text) -> [TS.Text] -> IO (Map (Expr EWord) W256)+getVars parseFn getVal names = Map.mapKeys parseFn <$> foldM getOne mempty names   where     getOne :: Map TS.Text W256 -> TS.Text -> IO (Map TS.Text W256)     getOne acc name = do-      raw <- getValue inst (T.fromStrict name)+      raw <- getVal (T.fromStrict name)       let         parsed = case parseCommentFreeFileMsg getValueRes (T.toStrict raw) of           Right (ResSpecific (valParsed :| [])) -> valParsed@@ -803,12 +791,12 @@           r -> parseErr r       pure $ Map.insert name val acc -getBufs :: SolverInstance -> [TS.Text] -> IO (Map (Expr Buf) ByteString)-getBufs inst names = foldM getBuf mempty names+getBufs :: (Text -> IO Text) -> [TS.Text] -> IO (Map (Expr Buf) ByteString)+getBufs getVal names = foldM getBuf mempty names   where     getLength :: TS.Text -> IO Int     getLength name = do-      val <- getValue inst (T.fromStrict name <> "_length")+      val <- getVal (T.fromStrict name <> "_length")       len <- case parseCommentFreeFileMsg getValueRes (T.toStrict val) of         Right (ResSpecific (parsed :| [])) -> case parsed of           (TermQualIdentifier (Unqualified (IdSymbol symbol)), (TermSpecConstant sc))@@ -833,7 +821,7 @@       -- this buffer and then use that to produce a shorter counterexample (by       -- replicating the constant byte up to the length).       len <- getLength name-      val <- getValue inst (T.fromStrict name)+      val <- getVal (T.fromStrict name)       buf <- case parseCommentFreeFileMsg getValueRes (T.toStrict val) of         Right (ResSpecific (valParsed :| [])) -> case valParsed of           (TermQualIdentifier (Unqualified (IdSymbol symbol)), term)@@ -886,213 +874,91 @@                             <> " in environment mapping"           p -> parseErr p --parseSC :: (Num a, Eq a) => SpecConstant -> a-parseSC (SCHexadecimal a) = fst . head . Numeric.readHex . T.unpack . T.fromStrict $ a-parseSC sc = error $ "Internal Error: cannot parse: " <> show sc--withSolvers :: Solver -> Natural -> Maybe Natural -> (SolverGroup -> IO a) -> IO a-withSolvers solver count timeout cont = do-  -- spawn solvers-  instances <- mapM (const $ spawnSolver solver timeout) [1..count]--  -- spawn orchestration thread-  taskQueue <- newChan-  availableInstances <- newChan-  forM_ instances (writeChan availableInstances)-  orchestrateId <- forkIO $ orchestrate taskQueue availableInstances+getStore :: (Text -> IO Text) -> [(Expr EWord, Expr EWord)] -> IO (Map W256 (Map W256 W256))+getStore getVal sreads = do+  raw <- getVal "abstractStore"+  let parsed = case parseCommentFreeFileMsg getValueRes (T.toStrict raw) of+                 Right (ResSpecific (valParsed :| [])) -> valParsed+                 r -> parseErr r+      -- first interpret SMT term as a function+      fun = case parsed of+              (TermQualIdentifier (Unqualified (IdSymbol symbol)), term) ->+                if symbol == "abstractStore"+                then interpret2DArray Map.empty term+                else error "Internal Error: solver did not return model for requested value"+              r -> parseErr r -  -- run continuation with task queue-  res <- cont (SolverGroup taskQueue)+  -- then create a map by adding only the locations that are read by the program+  foldM (\m (addr, slot) -> do+            addr' <- queryValue addr+            slot' <- queryValue slot+            pure $ addElem addr' slot' m fun) Map.empty sreads -  -- cleanup and return results-  mapM_ stopSolver instances-  killThread orchestrateId-  pure res   where-    orchestrate queue avail = do-      task <- readChan queue-      inst <- readChan avail-      _ <- forkIO $ runTask task inst avail-      orchestrate queue avail -    runTask (Task (SMT2 cmds cexvars) r) inst availableInstances = do-      -- reset solver and send all lines of provided script-      out <- sendScript inst (SMT2 ("(reset)" : cmds) cexvars)-      case out of-        -- if we got an error then return it-        Left e -> writeChan r (Error ("error while writing SMT to solver: " <> T.toStrict e))-        -- otherwise call (check-sat), parse the result, and send it down the result channel-        Right () -> do-          sat <- sendLine inst "(check-sat)"-          res <- case sat of-            "sat" -> do-              calldatamodels <- getVars parseVar inst (fmap T.toStrict $ calldataV cexvars)-              buffermodels <- getBufs inst (fmap T.toStrict $ buffersV cexvars)-              blockctxmodels <- getVars parseBlockCtx inst (fmap T.toStrict $ blockContextV cexvars)-              txctxmodels <- getVars parseFrameCtx inst (fmap T.toStrict $ txContextV cexvars)-              pure $ Sat $ SMTCex-                { vars = calldatamodels-                , buffers = buffermodels-                , blockContext = blockctxmodels-                , txContext = txctxmodels-                }-            "unsat" -> pure Unsat-            "timeout" -> pure Unknown-            "unknown" -> pure Unknown-            _ -> pure . Error $ T.toStrict $ "Unable to parse solver output: " <> sat-          writeChan r res+    addElem :: W256 -> W256 -> Map W256 (Map W256 W256) -> (W256 -> W256 -> W256) -> Map W256 (Map W256 W256)+    addElem addr slot store fun =+      case Map.lookup addr store of+        Just m -> Map.insert addr (Map.insert slot (fun addr slot) m) store+        Nothing -> Map.insert addr (Map.singleton slot (fun addr slot)) store -      -- put the instance back in the list of available instances-      writeChan availableInstances inst --- | Arguments used when spawing a solver instance-solverArgs :: Solver -> Maybe (Natural) -> [Text]-solverArgs solver timeout = case solver of-  Bitwuzla -> error "TODO: Bitwuzla args"-  Z3 ->-    [ "-in" ]-  CVC5 ->-    [ "--lang=smt"-    , "--no-interactive"-    , "--produce-models"-    , "--tlimit-per=" <> T.pack (show (1000 * fromMaybe 10 timeout))-    ]-  Custom _ -> []+    queryValue :: Expr EWord -> IO W256+    queryValue (Lit w) = pure w+    queryValue w = do+      let expr = toLazyText $ exprToSMT w+      raw <- getVal expr+      case parseCommentFreeFileMsg getValueRes (T.toStrict raw) of+        Right (ResSpecific (valParsed :| [])) ->+          case valParsed of+            (_, TermSpecConstant sc) -> pure $ parseW256 sc+            _ -> error "Internal Error: cannot parse model for storage index"+        r -> parseErr r --- | Spawns a solver instance, and sets the various global config options that we use for our queries-spawnSolver :: Solver -> Maybe (Natural) -> IO SolverInstance-spawnSolver solver timeout = do-  let cmd = (proc (show solver) (fmap T.unpack $ solverArgs solver timeout)) { std_in = CreatePipe, std_out = CreatePipe, std_err = CreatePipe }-  (Just stdin, Just stdout, Just stderr, process) <- createProcess cmd-  hSetBuffering stdin (BlockBuffering (Just 1000000))-  let solverInstance = SolverInstance solver stdin stdout stderr process-  case timeout of-    Nothing -> pure solverInstance-    Just t -> case solver of-        CVC5 -> pure solverInstance-        _ -> do-          _ <- sendLine' solverInstance $ "(set-option :timeout " <> T.pack (show t) <> ")"-          pure solverInstance --- | Cleanly shutdown a running solver instnace-stopSolver :: SolverInstance -> IO ()-stopSolver (SolverInstance _ stdin stdout stderr process) = cleanupProcess (Just stdin, Just stdout, Just stderr, process) --- | Sends a list of commands to the solver. Returns the first error, if there was one.-sendScript :: SolverInstance -> SMT2 -> IO (Either Text ())-sendScript solver (SMT2 cmds _) = do-  sendLine' solver (T.unlines $ fmap toLazyText cmds)-  pure $ Right()---- | Sends a single command to the solver, returns the first available line from the output buffer-sendCommand :: SolverInstance -> Text -> IO Text-sendCommand inst cmd = do-  -- trim leading whitespace-  let cmd' = T.dropWhile isSpace cmd-  case T.unpack cmd' of-    "" -> pure "success"      -- ignore blank lines-    ';' : _ -> pure "success" -- ignore comments-    _ -> sendLine inst cmd'---- | Sends a string to the solver and appends a newline, returns the first available line from the output buffer-sendLine :: SolverInstance -> Text -> IO Text-sendLine (SolverInstance _ stdin stdout _ _) cmd = do-  T.hPutStr stdin (T.append cmd "\n")-  hFlush stdin-  T.hGetLine stdout---- | Sends a string to the solver and appends a newline, doesn't return stdout-sendLine' :: SolverInstance -> Text -> IO ()-sendLine' (SolverInstance _ stdin _ _ _) cmd = do-  T.hPutStr stdin (T.append cmd "\n")-  hFlush stdin---- | Returns a string representation of the model for the requested variable-getValue :: SolverInstance -> Text -> IO Text-getValue (SolverInstance _ stdin stdout _ _) var = do-  T.hPutStr stdin (T.append (T.append "(get-value (" var) "))\n")-  hFlush stdin-  fmap (T.unlines . reverse) (readSExpr stdout)+-- | Interpret an N-dimensional array as a value of type a.+-- Parameterized by an interpretation function for array values.+interpretNDArray :: (Map Symbol Term -> Term -> a) -> (Map Symbol Term) -> Term -> (W256 -> a)+interpretNDArray interp env = \case+  -- variable reference+  TermQualIdentifier (Unqualified (IdSymbol s)) ->+    case Map.lookup s env of+      Just t -> interpretNDArray interp env t+      Nothing -> error "Internal error: unknown identifier, cannot parse array"+  -- (let (x t') t)+  TermLet (VarBinding x t' :| []) t -> interpretNDArray interp (Map.insert x t' env) t+  TermLet (VarBinding x t' :| lets) t -> interpretNDArray interp (Map.insert x t' env) (TermLet (NonEmpty.fromList lets) t)+  -- (as const (Array (_ BitVec 256) (_ BitVec 256))) SpecConstant+  TermApplication asconst (val :| []) | isArrConst asconst ->+    \_ -> interp env val+  -- (store arr ind val)+  TermApplication store (arr :| [TermSpecConstant ind, val]) | isStore store ->+    \x -> if x == parseW256 ind then interp env val else interpretNDArray interp env arr x+  t -> error $ "Internal error: cannot parse array value. Unexpected term: " <> (show t) --- | Reads lines from h until we have a balanced sexpr-readSExpr :: Handle -> IO [Text]-readSExpr h = go 0 0 []   where-    go 0 0 _ = do-      line <- T.hGetLine h-      let ls = T.length $ T.filter (== '(') line-          rs = T.length $ T.filter (== ')') line-      if ls == rs-         then pure [line]-         else go ls rs [line]-    go ls rs prev = do-      line <- T.hGetLine h-      let ls' = T.length $ T.filter (== '(') line-          rs' = T.length $ T.filter (== ')') line-      if (ls + ls') == (rs + rs')-         then pure $ line : prev-         else go (ls + ls') (rs + rs') (line : prev)--+    isArrConst :: QualIdentifier -> Bool+    isArrConst = \case+      Qualified (IdSymbol "const") (SortParameter (IdSymbol "Array") _) -> True+      _ -> False --- ** Helpers ** ---------------------------------------------------------------------------------+    isStore :: QualIdentifier -> Bool+    isStore t = t == Unqualified (IdSymbol "store")  --- | Stores a region of src into dst-copySlice :: Expr EWord -> Expr EWord -> Expr EWord -> Builder -> Builder -> Builder-copySlice srcOffset dstOffset size@(Lit _) src dst-  | size == (Lit 0) = dst-  | otherwise =-    let size' = (sub size (Lit 1))-        encDstOff = exprToSMT (add dstOffset size')-        encSrcOff = exprToSMT (add srcOffset size')-        child = copySlice srcOffset dstOffset size' src dst in-    "(store " <> child `sp` encDstOff `sp` "(select " <> src `sp` encSrcOff <> "))"-copySlice _ _ _ _ _ = error "TODO: implement copySlice with a symbolically sized region"---- | Unrolls an exponentiation into a series of multiplications-expandExp :: Expr EWord -> W256 -> Builder-expandExp base expnt-  | expnt == 1 = exprToSMT base-  | otherwise =-    let b = exprToSMT base-        n = expandExp base (expnt - 1) in-    "(bvmul " <> b `sp` n <> ")"---- | Concatenates a list of bytes into a larger bitvector-concatBytes :: [Expr Byte] -> Builder-concatBytes bytes =-  let bytesRev = reverse bytes-      a2 = exprToSMT (head bytesRev) in-  foldl wrap a2 $ tail bytesRev-  where-    wrap inner byte =-      let byteSMT = exprToSMT byte in-      "(concat " <> byteSMT `sp` inner <> ")"---- | Concatenates a list of bytes into a larger bitvector-writeBytes :: ByteString -> Expr Buf -> Builder-writeBytes bytes buf = snd $ BS.foldl' wrap (0, exprToSMT buf) bytes+-- | Interpret an 1-dimensional array as a function+interpret1DArray :: (Map Symbol Term) -> Term -> (W256 -> W256)+interpret1DArray = interpretNDArray interpretW256   where-    -- we don't need to store zeros if the base buffer is empty-    skipZeros = buf == mempty-    wrap :: (Int, Builder) -> Word8 -> (Int, Builder)-    wrap (idx, inner) byte =-      if skipZeros && byte == 0-      then (idx + 1, inner)-      else let-          byteSMT = exprToSMT (LitByte byte)-          idxSMT = exprToSMT . Lit . num $ idx-        in (idx + 1, "(store " <> inner `sp` idxSMT `sp` byteSMT <> ")")+    interpretW256 :: (Map Symbol Term) -> Term -> W256+    interpretW256 _ (TermSpecConstant val) = parseW256 val+    interpretW256 env (TermQualIdentifier (Unqualified (IdSymbol s))) =+      case Map.lookup s env of+        Just t -> interpretW256 env t+        Nothing -> error "Internal error: unknown identifier, cannot parse array"+    interpretW256 _ t = error $ "Internal error: cannot parse array value. Unexpected term: " <> (show t) -encodeConcreteStore :: Map W256 (Map W256 W256) -> Builder-encodeConcreteStore s = foldl encodeWrite "emptyStore" writes-  where-    asList = fmap (second Map.toList) $ Map.toList s-    writes = concatMap (\(addr, ws) -> fmap (\(k, v) -> (addr, k, v)) ws) asList-    encodeWrite prev (addr, key, val) = let-        encAddr = exprToSMT (Lit addr)-        encKey = exprToSMT (Lit key)-        encVal = exprToSMT (Lit val)-      in "(sstore " <> encAddr `sp` encKey `sp` encVal `sp` prev <> ")"+-- | Interpret an 2-dimensional array as a function+interpret2DArray :: (Map Symbol Term) -> Term -> (W256 -> W256 -> W256)+interpret2DArray = interpretNDArray interpret1DArray
src/EVM/Solidity.hs view
@@ -1,7 +1,6 @@ {-# Language DeriveAnyClass #-} {-# Language DataKinds #-} {-# Language StrictData #-}-{-# Language TemplateHaskell #-} {-# Language QuasiQuotes #-}  module EVM.Solidity@@ -21,33 +20,12 @@   , SlotType (..)   , Reference(..)   , Mutability(..)-  , methodName-  , methodSignature-  , methodInputs-  , methodOutput-  , methodMutability-  , abiMap-  , eventMap-  , errorMap-  , storageLayout-  , contractName-  , constructorInputs-  , creationCode   , functionAbi   , makeSrcMaps   , readSolc   , readJSON   , readStdJSON   , readCombinedJSON-  , runtimeCode-  , runtimeCodehash-  , creationCodehash-  , runtimeSrcmap-  , creationSrcmap-  , sourceFiles-  , sourceLines-  , sourceAsts-  , immutableReferences   , stripBytecodeMetadata   , stripBytecodeMetadataSym   , signature@@ -66,49 +44,48 @@ import EVM.Types  import Control.Applicative+import Control.Lens hiding (Indexed, (.=)) import Control.Monad-import Control.Lens         hiding (Indexed, (.=))-import qualified Data.String.Here as Here import Data.Aeson hiding (json) import Data.Aeson.Types import Data.Aeson.Lens-import qualified Data.Aeson.KeyMap as KeyMap+import Data.Aeson.Key qualified as Key+import Data.Aeson.KeyMap qualified as KeyMap import Data.Scientific-import Data.ByteString      (ByteString)+import Data.ByteString (ByteString)+import Data.ByteString qualified as BS+import Data.ByteString.Base16 qualified as BS16 import Data.ByteString.Lazy (toStrict)-import Data.Char            (isDigit)+import Data.Char (isDigit) import Data.Foldable-import Data.Map.Strict      (Map)+import Data.Map.Strict (Map)+import Data.Map.Strict qualified as Map+import Data.HashMap.Strict qualified as HMap+import Data.List (sort, isPrefixOf, isInfixOf, elemIndex, tails, findIndex)+import Data.List.NonEmpty (NonEmpty)+import Data.List.NonEmpty qualified as NonEmpty import Data.Maybe-import Data.Word            (Word8, Word32)-import Data.List.NonEmpty   (NonEmpty) import Data.Semigroup-import Data.Sequence        (Seq)-import Data.Text            (Text, pack, intercalate)-import Data.Text.Encoding   (encodeUtf8, decodeUtf8)-import Data.Text.IO         (readFile, writeFile)-import Data.Vector          (Vector)-import GHC.Generics         (Generic)-import Prelude hiding       (readFile, writeFile)-import System.IO hiding     (readFile, writeFile)+import Data.Sequence (Seq)+import Data.String.Here qualified as Here+import Data.Text (Text, pack, intercalate)+import Data.Text qualified as Text+import Data.Text.Encoding (encodeUtf8, decodeUtf8)+import Data.Text.IO (readFile, writeFile)+import Data.Vector (Vector)+import Data.Vector qualified as Vector+import Data.Word (Word8, Word32)+import GHC.Generics (Generic)+import Prelude hiding (readFile, writeFile)+import System.IO hiding (readFile, writeFile) import System.IO.Temp import System.Process-import Text.Read            (readMaybe)--import qualified Data.Aeson.Key as Key-import qualified Data.ByteString        as BS-import qualified Data.ByteString.Base16 as BS16-import qualified Data.HashMap.Strict    as HMap-import qualified Data.Map.Strict        as Map-import qualified Data.Text              as Text-import qualified Data.Vector            as Vector-import qualified Data.List.NonEmpty     as NonEmpty-import Data.List (sort, isPrefixOf, isInfixOf, elemIndex, tails, findIndex)+import Text.Read (readMaybe) -data StorageItem = StorageItem {-  _type   :: SlotType,-  _offset :: Int,-  _slot   :: Int+data StorageItem = StorageItem+  { slotType :: SlotType+  , offset :: Int+  , slot :: Int   } deriving (Show, Eq)  data SlotType@@ -143,27 +120,27 @@   readsPrec _ s = [(StorageValue $ fromMaybe (error "could not parse storage item") (parseTypeName mempty (pack s)),"")]  data SolcContract = SolcContract-  { _runtimeCodehash  :: W256-  , _creationCodehash :: W256-  , _runtimeCode      :: ByteString-  , _creationCode     :: ByteString-  , _contractName     :: Text-  , _constructorInputs :: [(Text, AbiType)]-  , _abiMap           :: Map Word32 Method-  , _eventMap         :: Map W256 Event-  , _errorMap         :: Map W256 SolError-  , _immutableReferences :: Map W256 [Reference]-  , _storageLayout    :: Maybe (Map Text StorageItem)-  , _runtimeSrcmap    :: Seq SrcMap-  , _creationSrcmap   :: Seq SrcMap+  { runtimeCodehash  :: W256+  , creationCodehash :: W256+  , runtimeCode      :: ByteString+  , creationCode     :: ByteString+  , contractName     :: Text+  , constructorInputs :: [(Text, AbiType)]+  , abiMap           :: Map Word32 Method+  , eventMap         :: Map W256 Event+  , errorMap         :: Map W256 SolError+  , immutableReferences :: Map W256 [Reference]+  , storageLayout    :: Maybe (Map Text StorageItem)+  , runtimeSrcmap    :: Seq SrcMap+  , creationSrcmap   :: Seq SrcMap   } deriving (Show, Eq, Generic)  data Method = Method-  { _methodOutput :: [(Text, AbiType)]-  , _methodInputs :: [(Text, AbiType)]-  , _methodName :: Text-  , _methodSignature :: Text-  , _methodMutability :: Mutability+  { output :: [(Text, AbiType)]+  , inputs :: [(Text, AbiType)]+  , name :: Text+  , methodSignature :: Text+  , mutability :: Mutability   } deriving (Show, Eq, Ord, Generic)  data Mutability@@ -174,14 +151,14 @@  deriving (Show, Eq, Ord, Generic)  data SourceCache = SourceCache-  { _sourceFiles  :: [(Text, ByteString)]-  , _sourceLines  :: [(Vector ByteString)]-  , _sourceAsts   :: Map Text Value+  { files  :: [(Text, ByteString)]+  , lines  :: [(Vector ByteString)]+  , asts   :: Map Text Value   } deriving (Show, Eq, Generic)  data Reference = Reference-  { _refStart :: Int,-    _refLength :: Int+  { start :: Int,+    length :: Int   } deriving (Show, Eq)  instance FromJSON Reference where@@ -220,10 +197,6 @@ data CodeType = Creation | Runtime   deriving (Show, Eq, Ord) -makeLenses ''SolcContract-makeLenses ''SourceCache-makeLenses ''Method- -- Obscure but efficient parser for the Solidity sourcemap format. makeSrcMaps :: Text -> Maybe (Seq SrcMap) makeSrcMaps = (\case (_, Fe, _) -> Nothing; x -> Just (done x))@@ -278,9 +251,9 @@       f (fp, Nothing) = BS.readFile $ Text.unpack fp   xs <- mapM f paths   return $! SourceCache-    { _sourceFiles = zip (fst <$> paths) xs-    , _sourceLines = map (Vector.fromList . BS.split 0xa) xs-    , _sourceAsts  = asts+    { files = zip (fst <$> paths) xs+    , lines = map (Vector.fromList . BS.split 0xa) xs+    , asts  = asts     }  lineSubrange ::@@ -324,19 +297,19 @@ solidity contract src = do   (json, path) <- solidity' src   let (sol, _, _) = fromJust $ readJSON json-  return (sol ^? ix (path <> ":" <> contract) . creationCode)+  pure $ Map.lookup (path <> ":" <> contract) sol <&> (.creationCode)  solcRuntime :: Text -> Text -> IO (Maybe ByteString) solcRuntime contract src = do   (json, path) <- solidity' src   let (sol, _, _) = fromJust $ readJSON json-  return (sol ^? ix (path <> ":" <> contract) . runtimeCode)+  pure $ Map.lookup (path <> ":" <> contract) sol <&> (.runtimeCode)  functionAbi :: Text -> IO Method functionAbi f = do   (json, path) <- solidity' ("contract ABI { function " <> f <> " public {}}")   let (sol, _, _) = fromJust $ readJSON json-  case Map.toList $ sol ^?! ix (path <> ":ABI") . abiMap of+  case Map.toList $ (fromJust (Map.lookup (path <> ":ABI") sol)).abiMap of      [(_,b)] -> return b      _ -> error "hevm internal error: unexpected abi format" @@ -365,24 +338,24 @@                  Just v -> v                                       -- solc >= 0.8                  Nothing -> (x ^?! key "abi" . _String) ^?! _Array -- solc <  0.8       in SolcContract {-        _runtimeCode      = theRuntimeCode,-        _creationCode     = theCreationCode,-        _runtimeCodehash  = keccak' (stripBytecodeMetadata theRuntimeCode),-        _creationCodehash = keccak' (stripBytecodeMetadata theCreationCode),-        _runtimeSrcmap    = force "internal error: srcmap-runtime" (makeSrcMaps (x ^?! key "srcmap-runtime" . _String)),-        _creationSrcmap   = force "internal error: srcmap" (makeSrcMaps (x ^?! key "srcmap" . _String)),-        _contractName = s,-        _constructorInputs = mkConstructor abis,-        _abiMap       = mkAbiMap abis,-        _eventMap     = mkEventMap abis,-        _errorMap     = mkErrorMap abis,-        _storageLayout = mkStorageLayout $ x ^? key "storage-layout",-        _immutableReferences = mempty -- TODO: deprecate combined-json+        runtimeCode      = theRuntimeCode,+        creationCode     = theCreationCode,+        runtimeCodehash  = keccak' (stripBytecodeMetadata theRuntimeCode),+        creationCodehash = keccak' (stripBytecodeMetadata theCreationCode),+        runtimeSrcmap    = force "internal error: srcmap-runtime" (makeSrcMaps (x ^?! key "srcmap-runtime" . _String)),+        creationSrcmap   = force "internal error: srcmap" (makeSrcMaps (x ^?! key "srcmap" . _String)),+        contractName = s,+        constructorInputs = mkConstructor abis,+        abiMap       = mkAbiMap abis,+        eventMap     = mkEventMap abis,+        errorMap     = mkErrorMap abis,+        storageLayout = mkStorageLayout $ x ^? key "storage-layout",+        immutableReferences = mempty -- TODO: deprecate combined-json       }  readStdJSON :: Text -> Maybe (Map Text SolcContract, Map Text Value, [(Text, Maybe ByteString)]) readStdJSON json = do-  contracts <- KeyMap.toHashMapText <$> json ^? key "contracts" ._Object+  contracts <- KeyMap.toHashMapText <$> json ^? key "contracts" . _Object   -- TODO: support the general case of "urls" and "content" in the standard json   sources <- KeyMap.toHashMapText <$>  json ^? key "sources" . _Object   let asts = force "JSON lacks abstract syntax trees." . preview (key "ast") <$> sources@@ -408,19 +381,19 @@         abis = force ("abi key not found in " <> show x) $           toList <$> x ^? key "abi" . _Array       in (s <> ":" <> c, (SolcContract {-        _runtimeCode      = theRuntimeCode,-        _creationCode     = theCreationCode,-        _runtimeCodehash  = keccak' (stripBytecodeMetadata theRuntimeCode),-        _creationCodehash = keccak' (stripBytecodeMetadata theCreationCode),-        _runtimeSrcmap    = force "internal error: srcmap-runtime" (makeSrcMaps (runtime ^?! key "sourceMap" . _String)),-        _creationSrcmap   = force "internal error: srcmap" (makeSrcMaps (creation ^?! key "sourceMap" . _String)),-        _contractName = s <> ":" <> c,-        _constructorInputs = mkConstructor abis,-        _abiMap        = mkAbiMap abis,-        _eventMap      = mkEventMap abis,-        _errorMap      = mkErrorMap abis,-        _storageLayout = mkStorageLayout $ x ^? key "storageLayout",-        _immutableReferences = fromMaybe mempty $+        runtimeCode      = theRuntimeCode,+        creationCode     = theCreationCode,+        runtimeCodehash  = keccak' (stripBytecodeMetadata theRuntimeCode),+        creationCodehash = keccak' (stripBytecodeMetadata theCreationCode),+        runtimeSrcmap    = force "internal error: srcmap-runtime" (makeSrcMaps (runtime ^?! key "sourceMap" . _String)),+        creationSrcmap   = force "internal error: srcmap" (makeSrcMaps (creation ^?! key "sourceMap" . _String)),+        contractName = s <> ":" <> c,+        constructorInputs = mkConstructor abis,+        abiMap        = mkAbiMap abis,+        eventMap      = mkEventMap abis,+        errorMap      = mkErrorMap abis,+        storageLayout = mkStorageLayout $ x ^? key "storageLayout",+        immutableReferences = fromMaybe mempty $           do x' <- runtime ^? key "immutableReferences"              case fromJSON x' of                Success a -> return a@@ -433,13 +406,13 @@     relevant = filter (\y -> "function" == y ^?! key "type" . _String) abis     f abi =       (abiKeccak (encodeUtf8 (signature abi)),-       Method { _methodName = abi ^?! key "name" . _String-              , _methodSignature = signature abi-              , _methodInputs = map parseMethodInput+       Method { name = abi ^?! key "name" . _String+              , methodSignature = signature abi+              , inputs = map parseMethodInput                  (toList (abi ^?! key "inputs" . _Array))-              , _methodOutput = map parseMethodInput+              , output = map parseMethodInput                  (toList (abi ^?! key "outputs" . _Array))-              , _methodMutability = parseMutability+              , mutability = parseMutability                  (abi ^?! key "stateMutability" . _String)               })   in f <$> relevant@@ -474,7 +447,7 @@      ( stripKeccak $ keccak' (encodeUtf8 (signature abi))      , SolError        (abi ^?! key "name" . _String)-       (map (\y -> ( force "internal error: type" (parseTypeName' y)))+       (map (force "internal error: type" . parseTypeName')        (toList $ abi ^?! key "inputs" . _Array))      )   in f <$> relevant
+ src/EVM/Solvers.hs view
@@ -0,0 +1,239 @@+{-# Language DataKinds #-}+{-# Language GADTs #-}+{-# Language PolyKinds #-}+{-# Language ScopedTypeVariables #-}+{-# Language TypeApplications #-}+{-# Language QuasiQuotes #-}++{- |+    Module: EVM.Solvers+    Description: Solver orchestration+-}+module EVM.Solvers where++import Prelude hiding (LT, GT)++import GHC.Natural+import Control.Monad+import GHC.IO.Handle (Handle, hFlush, hSetBuffering, BufferMode(..))+import Control.Concurrent.Chan (Chan, newChan, writeChan, readChan)+import Control.Concurrent (forkIO, killThread)+import Data.Char (isSpace)++import Data.Maybe (fromMaybe)+import Data.Text.Lazy (Text)+import qualified Data.Text as TS+import qualified Data.Text.Lazy as T+import qualified Data.Text.Lazy.IO as T+import Data.Text.Lazy.Builder+import System.Process (createProcess, cleanupProcess, proc, ProcessHandle, std_in, std_out, std_err, StdStream(..))++import EVM.SMT++-- | Supported solvers+data Solver+  = Z3+  | CVC5+  | Bitwuzla+  | Custom Text++instance Show Solver where+  show Z3 = "z3"+  show CVC5 = "cvc5"+  show Bitwuzla = "bitwuzla"+  show (Custom s) = T.unpack s+++-- | A running solver instance+data SolverInstance = SolverInstance+  { _type :: Solver+  , _stdin :: Handle+  , _stdout :: Handle+  , _stderr :: Handle+  , _process :: ProcessHandle+  }++-- | A channel representing a group of solvers+newtype SolverGroup = SolverGroup (Chan Task)++-- | A script to be executed, a list of models to be extracted in the case of a sat result, and a channel where the result should be written+data Task = Task+  { script :: SMT2+  , resultChan :: Chan CheckSatResult+  }++-- | The result of a call to (check-sat)+data CheckSatResult+  = Sat SMTCex+  | Unsat+  | Unknown+  | Error TS.Text+  deriving (Show, Eq)++isSat :: CheckSatResult -> Bool+isSat (Sat _) = True+isSat _ = False++isErr :: CheckSatResult -> Bool+isErr (Error _) = True+isErr _ = False++isUnsat :: CheckSatResult -> Bool+isUnsat Unsat = True+isUnsat _ = False++checkSat :: SolverGroup -> SMT2 -> IO CheckSatResult+checkSat (SolverGroup taskQueue) script = do+  -- prepare result channel+  resChan <- newChan++  -- send task to solver group+  writeChan taskQueue (Task script resChan)++  -- collect result+  readChan resChan++withSolvers :: Solver -> Natural -> Maybe Natural -> (SolverGroup -> IO a) -> IO a+withSolvers solver count timeout cont = do+  -- spawn solvers+  instances <- mapM (const $ spawnSolver solver timeout) [1..count]++  -- spawn orchestration thread+  taskQueue <- newChan+  availableInstances <- newChan+  forM_ instances (writeChan availableInstances)+  orchestrateId <- forkIO $ orchestrate taskQueue availableInstances++  -- run continuation with task queue+  res <- cont (SolverGroup taskQueue)++  -- cleanup and return results+  mapM_ stopSolver instances+  killThread orchestrateId+  pure res+  where+    orchestrate queue avail = do+      task <- readChan queue+      inst <- readChan avail+      _ <- forkIO $ runTask task inst avail+      orchestrate queue avail++    runTask (Task (SMT2 cmds cexvars) r) inst availableInstances = do+      -- reset solver and send all lines of provided script+      out <- sendScript inst (SMT2 ("(reset)" : cmds) cexvars)+      case out of+        -- if we got an error then return it+        Left e -> writeChan r (Error ("error while writing SMT to solver: " <> T.toStrict e))+        -- otherwise call (check-sat), parse the result, and send it down the result channel+        Right () -> do+          sat <- sendLine inst "(check-sat)"+          res <- case sat of+            "sat" -> do+              calldatamodels <- getVars parseVar (getValue inst) (fmap T.toStrict cexvars.calldataV)+              buffermodels <- getBufs (getValue inst) (fmap T.toStrict cexvars.buffersV)+              storagemodels <- getStore (getValue inst) cexvars.storeReads+              blockctxmodels <- getVars parseBlockCtx (getValue inst) (fmap T.toStrict cexvars.blockContextV)+              txctxmodels <- getVars parseFrameCtx (getValue inst) (fmap T.toStrict cexvars.txContextV)+              pure $ Sat $ SMTCex+                { vars = calldatamodels+                , buffers = buffermodels+                , store = storagemodels+                , blockContext = blockctxmodels+                , txContext = txctxmodels+                }+            "unsat" -> pure Unsat+            "timeout" -> pure Unknown+            "unknown" -> pure Unknown+            _ -> pure . Error $ T.toStrict $ "Unable to parse solver output: " <> sat+          writeChan r res++      -- put the instance back in the list of available instances+      writeChan availableInstances inst++-- | Arguments used when spawing a solver instance+solverArgs :: Solver -> Maybe (Natural) -> [Text]+solverArgs solver timeout = case solver of+  Bitwuzla -> error "TODO: Bitwuzla args"+  Z3 ->+    [ "-in" ]+  CVC5 ->+    [ "--lang=smt"+    , "--no-interactive"+    , "--produce-models"+    , "--tlimit-per=" <> T.pack (show (1000 * fromMaybe 10 timeout))+    ]+  Custom _ -> []++-- | Spawns a solver instance, and sets the various global config options that we use for our queries+spawnSolver :: Solver -> Maybe (Natural) -> IO SolverInstance+spawnSolver solver timeout = do+  let cmd = (proc (show solver) (fmap T.unpack $ solverArgs solver timeout)) { std_in = CreatePipe, std_out = CreatePipe, std_err = CreatePipe }+  (Just stdin, Just stdout, Just stderr, process) <- createProcess cmd+  hSetBuffering stdin (BlockBuffering (Just 1000000))+  let solverInstance = SolverInstance solver stdin stdout stderr process+  case timeout of+    Nothing -> pure solverInstance+    Just t -> case solver of+        CVC5 -> pure solverInstance+        _ -> do+          _ <- sendLine' solverInstance $ "(set-option :timeout " <> T.pack (show t) <> ")"+          pure solverInstance++-- | Cleanly shutdown a running solver instnace+stopSolver :: SolverInstance -> IO ()+stopSolver (SolverInstance _ stdin stdout stderr process) = cleanupProcess (Just stdin, Just stdout, Just stderr, process)++-- | Sends a list of commands to the solver. Returns the first error, if there was one.+sendScript :: SolverInstance -> SMT2 -> IO (Either Text ())+sendScript solver (SMT2 cmds _) = do+  sendLine' solver (T.unlines $ fmap toLazyText cmds)+  pure $ Right()++-- | Sends a single command to the solver, returns the first available line from the output buffer+sendCommand :: SolverInstance -> Text -> IO Text+sendCommand inst cmd = do+  -- trim leading whitespace+  let cmd' = T.dropWhile isSpace cmd+  case T.unpack cmd' of+    "" -> pure "success"      -- ignore blank lines+    ';' : _ -> pure "success" -- ignore comments+    _ -> sendLine inst cmd'++-- | Sends a string to the solver and appends a newline, returns the first available line from the output buffer+sendLine :: SolverInstance -> Text -> IO Text+sendLine (SolverInstance _ stdin stdout _ _) cmd = do+  T.hPutStr stdin (T.append cmd "\n")+  hFlush stdin+  T.hGetLine stdout++-- | Sends a string to the solver and appends a newline, doesn't return stdout+sendLine' :: SolverInstance -> Text -> IO ()+sendLine' (SolverInstance _ stdin _ _ _) cmd = do+  T.hPutStr stdin (T.append cmd "\n")+  hFlush stdin++-- | Returns a string representation of the model for the requested variable+getValue :: SolverInstance -> Text -> IO Text+getValue (SolverInstance _ stdin stdout _ _) var = do+  T.hPutStr stdin (T.append (T.append "(get-value (" var) "))\n")+  hFlush stdin+  fmap (T.unlines . reverse) (readSExpr stdout)++-- | Reads lines from h until we have a balanced sexpr+readSExpr :: Handle -> IO [Text]+readSExpr h = go 0 0 []+  where+    go 0 0 _ = do+      line <- T.hGetLine h+      let ls = T.length $ T.filter (== '(') line+          rs = T.length $ T.filter (== ')') line+      if ls == rs+         then pure [line]+         else go ls rs [line]+    go ls rs prev = do+      line <- T.hGetLine h+      let ls' = T.length $ T.filter (== '(') line+          rs' = T.length $ T.filter (== ')') line+      if (ls + ls') == (rs + rs')+         then pure $ line : prev+         else go (ls + ls') (rs + rs') (line : prev)
src/EVM/Stepper.hs view
@@ -99,7 +99,7 @@ runFully :: Stepper EVM.VM runFully = do   vm <- run-  case EVM._result vm of+  case vm._result of     Nothing -> error "should not occur"     Just (VMFailure (Query q)) ->       wait q >> runFully@@ -133,9 +133,9 @@     eval (action :>>= k) =       case action of         Exec ->-          EVM.Exec.exec >>= interpret fetcher . k+          (State.state . runState) EVM.Exec.exec >>= interpret fetcher . k         Run ->-          EVM.Exec.run >>= interpret fetcher . k+          (State.state . runState) EVM.Exec.run >>= interpret fetcher . k         Wait q ->           do m <- liftIO (fetcher q)              State.state (runState m) >> interpret fetcher (k ())
src/EVM/StorageLayout.hs view
@@ -2,22 +2,19 @@  -- Figures out the layout of storage slots for Solidity contracts. -import EVM.Dapp (DappInfo, dappAstSrcMap, dappAstIdMap)+import EVM.Dapp (DappInfo(..)) import EVM.Solidity (SolcContract, creationSrcmap, SlotType(..)) import EVM.ABI (AbiType (..), parseTypeName) +import Control.Lens import Data.Aeson (Value (..)) import Data.Aeson.Lens--import Control.Lens--import Data.Text (Text, unpack, pack, words)- import Data.Foldable (toList)+import Data.List.NonEmpty qualified as NonEmpty+import Data.Map qualified as Map import Data.Maybe (fromMaybe, isJust)-import qualified Data.List.NonEmpty as NonEmpty--import qualified Data.Sequence as Seq+import Data.Sequence qualified as Seq+import Data.Text (Text, unpack, pack, words)  import Prelude hiding (words) @@ -32,9 +29,9 @@ findContractDefinition dapp solc =   -- The first source mapping in the contract's creation code   -- corresponds to the source field of the contract definition.-  case Seq.viewl (view creationSrcmap solc) of+  case Seq.viewl solc.creationSrcmap of     firstSrcMap Seq.:< _ ->-      (view dappAstSrcMap dapp) firstSrcMap+      dapp.astSrcMap firstSrcMap     _ ->       Nothing @@ -57,7 +54,7 @@           (\case              Number i -> fromMaybe (error "malformed AST JSON") $                storageVariablesForContract =<<-                 preview (dappAstIdMap . ix (floor i)) dapp+                 Map.lookup (floor i) dapp.astIdMap              _ ->                error "malformed AST JSON") 
src/EVM/SymExec.hs view
@@ -1,16 +1,19 @@+{-# Language TupleSections #-} {-# Language DataKinds #-}  module EVM.SymExec where  import Prelude hiding (Word) +import Data.Tuple (swap) import Control.Lens hiding (pre)-import EVM hiding (Query, Revert, push)+import EVM hiding (Query, Revert, push, bytecode, cache) import qualified EVM import EVM.Exec import qualified EVM.Fetch as Fetch import EVM.ABI import EVM.SMT+import EVM.Solvers import EVM.Traversals import qualified EVM.Expr as Expr import EVM.Stepper (Stepper)@@ -23,11 +26,9 @@ import Data.DoubleWord (Word256) import Control.Concurrent.Async import Data.Maybe-import Data.List (foldl')-import Data.Tuple (swap)+import Data.List (foldl', sortBy) import Data.ByteString (ByteString)-import Data.List (find)-import Data.ByteString (null, pack)+import qualified Data.ByteString as BS import qualified Control.Monad.State.Class as State import Data.Bifunctor (first, second) import Data.Text (Text)@@ -37,20 +38,31 @@ import qualified Data.Text.IO as T import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy.IO as TL-import EVM.Format (formatExpr, indent, formatBinary)+import EVM.Format (formatExpr)+import Data.Set (Set, isSubsetOf, size)+import qualified Data.Set as Set+import Control.Concurrent.STM (atomically, TVar, readTVarIO, readTVar, newTVarIO, writeTVar)+import Control.Concurrent.Spawn+import GHC.Conc (getNumProcessors)+import EVM.Format (indent, formatBinary)  data ProofResult a b c = Qed a | Cex b | Timeout c   deriving (Show, Eq) type VerifyResult = ProofResult () (Expr End, SMTCex) (Expr End)-type EquivalenceResult = ProofResult ([VM], [VM]) VM ()+type EquivResult = ProofResult () (SMTCex) () +isTimeout :: ProofResult a b c -> Bool+isTimeout (Timeout _) = True+isTimeout _ = False++isCex :: ProofResult a b c -> Bool+isCex (Cex _) = True+isCex _ = False+ isQed :: ProofResult a b c -> Bool isQed (Qed _) = True isQed _ = False -containsA :: Eq a => Eq b => Eq c => ProofResult a b c -> [(d , e, ProofResult a b c)] -> Bool-containsA a lst = isJust $ Data.List.find (\(_, _, c) -> c == a) lst- data VeriOpts = VeriOpts   { simp :: Bool   , debug :: Bool@@ -165,7 +177,7 @@ abstractVM typesignature concreteArgs contractCode maybepre storagemodel = finalVm   where     (calldata', calldataProps) = case typesignature of-                 Nothing -> (AbstractBuf "txdata", [])+                 Nothing -> (AbstractBuf "txdata", [Expr.bufLength (AbstractBuf "txdata") .< (Lit (2 ^ (64 :: Integer)))])                  Just (name, typs) -> symCalldata name typs concreteArgs (AbstractBuf "txdata")     store = case storagemodel of               SymbolicS -> AbstractStore@@ -232,9 +244,9 @@     eval (action Operational.:>>= k) =       case action of         Stepper.Exec ->-          exec >>= interpret fetcher maxIter askSmtIters . k+          (State.state . runState) exec >>= interpret fetcher maxIter askSmtIters . k         Stepper.Run ->-          run >>= interpret fetcher maxIter askSmtIters . k+          (State.state . runState) run >>= interpret fetcher maxIter askSmtIters . k         Stepper.IOAct q ->           mapStateT liftIO q >>= interpret fetcher maxIter askSmtIters . k         Stepper.Ask (EVM.PleaseChoosePath cond continue) -> do@@ -277,9 +289,9 @@ maxIterationsReached _ Nothing = Nothing maxIterationsReached vm (Just maxIter) =   let codelocation = getCodeLocation vm-      iters = view (iterations . at codelocation . non 0) vm+      iters = view (at codelocation . non 0) vm._iterations   in if num maxIter <= iters-     then view (cache . path . at (codelocation, iters - 1)) vm+     then Map.lookup (codelocation, iters - 1) vm._cache._path      else Nothing  @@ -333,7 +345,7 @@  pruneDeadPaths :: [VM] -> [VM] pruneDeadPaths =-  filter $ \vm -> case view result vm of+  filter $ \vm -> case vm._result of     Just (VMFailure DeadPath) -> False     _ -> True @@ -341,10 +353,10 @@ runExpr :: Stepper.Stepper (Expr End) runExpr = do   vm <- Stepper.runFully-  let asserts = view keccakEqs vm-  pure $ case view result vm of+  let asserts = vm._keccakEqs+  pure $ case vm._result of     Nothing -> error "Internal Error: vm in intermediate state after call to runFully"-    Just (VMSuccess buf) -> Return asserts buf (view (env . EVM.storage) vm)+    Just (VMSuccess buf) -> Return asserts buf vm._env._storage     Just (VMFailure e) -> case e of       UnrecognizedOpcode _ -> Failure asserts Invalid       SelfDestruction -> Failure asserts SelfDestruct@@ -353,6 +365,7 @@       EVM.Revert buf -> EVM.Types.Revert asserts buf       EVM.InvalidMemoryAccess -> Failure asserts EVM.Types.InvalidMemoryAccess       EVM.BadJumpDestination -> Failure asserts EVM.Types.BadJumpDestination+      EVM.StackUnderrun -> Failure asserts EVM.Types.StackUnderrun       e' -> Failure asserts $ EVM.Types.TmpErr (show e')  -- | Converts a given top level expr into a list of final states and the associated path conditions for each state@@ -457,12 +470,12 @@ verify solvers opts preState maybepost = do   putStrLn "Exploring contract" -  exprInter <- evalStateT (interpret (Fetch.oracle solvers (rpcInfo opts)) (maxIter opts) (askSmtIters opts) runExpr) preState-  when (debug opts) $ T.writeFile "unsimplified.expr" (formatExpr exprInter)+  exprInter <- evalStateT (interpret (Fetch.oracle solvers opts.rpcInfo) opts.maxIter opts.askSmtIters runExpr) preState+  when opts.debug $ T.writeFile "unsimplified.expr" (formatExpr exprInter)    putStrLn "Simplifying expression"-  expr <- if (simp opts) then (pure $ Expr.simplify exprInter) else pure exprInter-  when (debug opts) $ T.writeFile "simplified.expr" (formatExpr expr)+  expr <- if opts.simp then (pure $ Expr.simplify exprInter) else pure exprInter+  when opts.debug $ T.writeFile "simplified.expr" (formatExpr expr)    putStrLn $ "Explored contract (" <> show (Expr.numBranches expr) <> " branches)" @@ -475,11 +488,11 @@           \(_, leaf) -> case evalProp (post preState leaf) of             PBool True -> False             _ -> True-        assumes = view constraints preState+        assumes = preState._constraints         withQueries = fmap (\(pcs, leaf) -> (assertProps (PNeg (post preState leaf) : assumes <> extractProps leaf <> pcs), leaf)) canViolate       putStrLn $ "Checking for reachability of " <> show (length withQueries) <> " potential property violation(s)" -      when (debug opts) $ forM_ (zip [(1 :: Int)..] withQueries) $ \(idx, (q, leaf)) -> do+      when opts.debug $ forM_ (zip [(1 :: Int)..] withQueries) $ \(idx, (q, leaf)) -> do         TL.writeFile           ("query-" <> show idx <> ".smt2")           ("; " <> (TL.pack $ show leaf) <> "\n\n" <> formatSMT2 q <> "\n\n(check-sat)")@@ -494,75 +507,138 @@     toVRes :: (CheckSatResult, Expr End) -> VerifyResult     toVRes (res, leaf) = case res of       Sat model -> Cex (leaf, model)-      EVM.SMT.Unknown -> Timeout leaf+      EVM.Solvers.Unknown -> Timeout leaf       Unsat -> Qed ()       Error e -> error $ "Internal Error: solver responded with error: " <> show e +type UnsatCache = TVar [Set Prop]+ -- | Compares two contract runtimes for trace equivalence by running two VMs and comparing the end states.-equivalenceCheck :: SolverGroup -> ByteString -> ByteString -> VeriOpts -> Maybe (Text, [AbiType]) -> IO [(Maybe SMTCex, Prop, ProofResult () () ())]+--+-- 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.+equivalenceCheck :: SolverGroup -> ByteString -> ByteString -> VeriOpts -> Maybe (Text, [AbiType]) -> IO [EquivResult] equivalenceCheck solvers bytecodeA bytecodeB opts signature' = do-  let-    bytecodeA' = if Data.ByteString.null bytecodeA then Data.ByteString.pack [0] else bytecodeA-    bytecodeB' = if Data.ByteString.null bytecodeB then Data.ByteString.pack [0] else bytecodeB-    preStateA = abstractVM signature' [] bytecodeA' Nothing SymbolicS-    preStateB = abstractVM signature' [] bytecodeB' Nothing SymbolicS+  case bytecodeA == bytecodeB of+    True -> do+      putStrLn "bytecodeA and bytecodeB are identical"+      pure [Qed ()]+    False -> do+      branchesA <- getBranches bytecodeA+      branchesB <- getBranches bytecodeB+      let allPairs = [(a,b) | a <- branchesA, b <- branchesB]+      putStrLn $ "Found " <> (show $ length allPairs) <> " total pairs of endstates" -  aExpr <- evalStateT (interpret (Fetch.oracle solvers Nothing) (maxIter opts) (askSmtIters opts) runExpr) preStateA-  bExpr <- evalStateT (interpret (Fetch.oracle solvers Nothing) (maxIter opts) (askSmtIters opts) runExpr) preStateB-  aExprSimp <- if (simp opts) then (pure $ Expr.simplify aExpr) else pure aExpr-  bExprSimp <- if (simp opts) then (pure $ Expr.simplify bExpr) else pure bExpr-  when (debug opts) $ putStrLn $ "num of aExprSimp endstates:" <> (show $ length $ flattenExpr aExprSimp) <> "\nnum of bExprSimp endstates:" <> (show $ length $ flattenExpr bExprSimp)+      when opts.debug $ putStrLn+                        $ "endstates in bytecodeA: " <> (show $ length branchesA)+                       <> "\nendstates in bytecodeB: " <> (show $ length branchesB) -  -- Check each pair of end states for equality:-  let-      differingEndStates = uncurry distinct <$> [(a,b) | a <- flattenExpr aExprSimp, b <- flattenExpr bExprSimp]-      distinct :: ([Prop], Expr End) -> ([Prop], Expr End) -> Prop-      distinct (aProps, aEnd) (bProps, bEnd) =-        let-          differingResults = case (aEnd, bEnd) of-            (Return _ aOut aStore, Return _ bOut bStore) ->-              if aOut == bOut && aStore == bStore then PBool False-                                                  else aStore ./= bStore  .|| aOut ./= bOut-            (Return {}, _) -> PBool True-            (_, Return {}) -> PBool True-            (Revert _ a, Revert _ b) -> if a==b then PBool False else a ./= b-            (Revert _ _, _) -> PBool True-            (_, Revert _ _) -> PBool True-            (Failure _ erra, Failure _ errb) -> if erra==errb then PBool False else PBool True-            (GVar _, _) -> error "Expressions cannot contain global vars"-            (_ , GVar _) -> error "Expressions cannot contain global vars"-            (Failure _ (TmpErr s), _) -> error $ "Unhandled error: " <> s-            (_, Failure _ (TmpErr s)) -> error $ "Unhandled error: " <> s-            (ITE _ _ _, _ ) -> error "Expressions must be flattened"-            (_, ITE _ _ _) -> error "Expressions must be flattened"+      let differingEndStates = sortBySize (mapMaybe (uncurry distinct) allPairs)+      putStrLn $ "Asking the SMT solver for " <> (show $ length differingEndStates) <> " pairs"+      when opts.debug $ forM_ (zip differingEndStates [(1::Integer)..]) (\(x, i) ->+        T.writeFile ("prop-checked-" <> show i) (T.pack $ show x)) -        -- if the SMT solver can find a common input that satisfies BOTH sets of path conditions-        -- AND the output differs, then we are in trouble. We do this for _every_ pair of paths, which-        -- makes this exhaustive-        in-        if differingResults == PBool False-           then PBool False-           else (foldl PAnd (PBool True) aProps) .&& (foldl PAnd (PBool True) bProps)  .&& differingResults-  -- If there exists a pair of end states where this is not the case,-  -- the following constraint is satisfiable+      knownUnsat <- newTVarIO []+      procs <- getNumProcessors+      results <- checkAll differingEndStates knownUnsat procs -  let diffEndStFilt = filter (/= PBool False) differingEndStates-  putStrLn $ "Equivalence checking " <> (show $ length diffEndStFilt) <> " combinations"-  when (debug opts) $ forM_ (zip diffEndStFilt [1 :: Integer ..]) (\(x, i) -> T.writeFile ("prop-checked-" <> show i) (T.pack $ show x))-  results <- flip mapConcurrently (zip diffEndStFilt [1 :: Integer ..]) $ \(prop, i) -> do-    let assertedProps = assertProps [prop]-    let filename = "eq-check-" <> show i <> ".smt2"-    when (debug opts) $ T.writeFile (filename) $ (TL.toStrict $ formatSMT2 assertedProps) <> "\n(check-sat)"-    res <- case prop of-      PBool False -> pure Unsat-      _ -> checkSat solvers assertedProps-    case res of-     Sat a -> return (Just a, prop, Cex ())-     Unsat -> return (Nothing, prop, Qed ())-     EVM.SMT.Unknown -> return (Nothing, prop, Timeout ())-     Error txt -> error $ "Error while running solver: `" <> T.unpack txt <> "` SMT file was: `" <> filename <> "`"-  return $ filter (\(_, _, res) -> res /= Qed ()) results+      let useful = foldr (\(_, b) n -> if b then n+1 else n) (0::Integer) results+      putStrLn $ "Reuse of previous queries was Useful in " <> (show useful) <> " cases"+      case all isQed . fmap fst $ results of+        True -> pure [Qed ()]+        False -> pure $ filter (/= Qed ()) . fmap fst $ results+  where+    -- we order the sets by size because this gives us more cache hits when+    -- running our queries later on (since we rely on a subset check)+    sortBySize :: [Set a] -> [Set a]+    sortBySize = sortBy (\a b -> if size a > size b then Prelude.LT else Prelude.GT) +    -- returns True if a is a subset of any of the sets in b+    subsetAny :: Set Prop -> [Set Prop] -> Bool+    subsetAny a b = foldr (\bp acc -> acc || isSubsetOf a bp) False b++    -- decompiles the given bytecode into a list of branches+    getBranches :: ByteString -> IO [([Prop], Expr End)]+    getBranches bs = do+      let+        bytecode = if BS.null bs then BS.pack [0] else bs+        prestate = abstractVM signature' [] bytecode Nothing SymbolicS+      expr <- evalStateT (interpret (Fetch.oracle solvers Nothing) opts.maxIter opts.askSmtIters runExpr) prestate+      let simpl = if opts.simp then (Expr.simplify expr) else expr+      pure $ flattenExpr simpl++    -- checks for satisfiability of all the props in the provided set. skips+    -- the solver if we can determine unsatisfiability from the cache already+    -- the last element of the returned tuple indicates whether the cache was+    -- used or not+    check :: UnsatCache -> Set Prop -> IO (EquivResult, Bool)+    check knownUnsat props = do+      let smt = assertProps $ Set.toList props+      ku <- readTVarIO knownUnsat+      res <- if subsetAny props ku+             then pure (True, Unsat)+             else (fmap ((False),) (checkSat solvers smt))+      case res of+        (_, Sat x) -> pure (Cex x, False)+        (quick, Unsat) -> case quick of+                            True  -> pure (Qed (), quick)+                            False -> do+                              -- nb: we might end up with duplicates here due to a+                              -- potential race, but it doesn't matter for correctness+                              atomically $ readTVar knownUnsat >>= writeTVar knownUnsat . (props :)+                              pure (Qed (), False)+        (_, EVM.Solvers.Unknown) -> pure (Timeout (), False)+        (_, Error txt) -> error $ "Error while running solver: `" <> T.unpack txt -- <> "` SMT file was: `" <> filename <> "`"++    -- Allows us to run it in parallel. Note that this (seems to) run it+    -- from left-to-right, and with a max of K threads. This is in contrast to+    -- mapConcurrently which would spawn as many threads as there are jobs, and+    -- run them in a random order. We ordered them correctly, though so that'd be bad+    checkAll :: [(Set Prop)] -> UnsatCache -> Int -> IO [(EquivResult, Bool)]+    checkAll input cache numproc = do+       wrap <- pool numproc+       parMapIO (wrap . (check cache)) input++    -- Takes two branches and returns a set of props that will need to be+    -- satisfied for the two branches to violate the equivalence check. i.e.+    -- for a given pair of branches, equivalence is violated if there exists an+    -- input that satisfies the branch conditions from both sides and produces+    -- a differing result in each branch+    distinct :: ([Prop], Expr End) -> ([Prop], Expr End) -> Maybe (Set Prop)+    distinct (aProps, aEnd) (bProps, bEnd) =+      let+        differingResults = case (aEnd, bEnd) of+          (Return _ aOut aStore, Return _ bOut bStore) ->+            if aOut == bOut && aStore == bStore+            then PBool False+            else aStore ./= bStore .|| aOut ./= bOut+          (Return {}, _) -> PBool True+          (_, Return {}) -> PBool True+          (Revert _ a, Revert _ b) -> if a == b then PBool False else a ./= b+          (Revert _ _, _) -> PBool True+          (_, Revert _ _) -> PBool True+          (Failure _ (TmpErr s), _) -> error $ "Unhandled error: " <> s+          (_, Failure _ (TmpErr s)) -> error $ "Unhandled error: " <> s+          (Failure _ erra, Failure _ errb) -> if erra==errb then PBool False else PBool True+          (ITE _ _ _, _) -> error "Expressions must be flattened"+          (_, ITE _ _ _) -> error "Expressions must be flattened"+          (a, b) -> if a == b+                    then PBool False+                    else error $ "Internal Error: Unimplemented. Left: " <> show a <> " Right: " <> show b+      in case differingResults of+        -- if the end states are the same, then they can never produce a+        -- different result under any circumstances+        PBool False -> Nothing+        -- if we can statically determine that the end states differ, then we+        -- ask the solver to find us inputs that satisfy both sets of branch+        -- conditions+        PBool True  -> Just . Set.fromList $ aProps <> bProps+        -- if we cannot statically determine whether or not the end states+        -- differ, then we ask the solver if the end states can differ if both+        -- sets of path conditions are satisfiable+        _ -> Just . Set.fromList $ differingResults : aProps <> bProps+ both' :: (a -> b) -> (a, a) -> (b, b) both' f (x, y) = (f x, f y) @@ -580,7 +656,7 @@   case res of     Unsat -> pure () -- ignore unreachable branches     Error e -> error $ "Internal error: smt solver returned an error: " <> show e-    EVM.SMT.Unknown -> do+    EVM.Solvers.Unknown -> do       putStrLn "--- Branch ---"       putStrLn ""       putStrLn "Unable to produce a model for the following end state:"@@ -601,11 +677,12 @@   formatCex :: Expr Buf -> SMTCex -> Text-formatCex cd m@(SMTCex _ _ blockContext txContext) = T.unlines $+formatCex cd m@(SMTCex _ _ store blockContext txContext) = T.unlines $   [ "Calldata:"   , indent 2 cd'   , ""   ]+  <> storeCex   <> txCtx   <> blockCtx   where@@ -618,6 +695,15 @@     -- payable functions).     cd' = prettyBuf $ Expr.simplify $ subModel m cd +    storeCex :: [Text]+    storeCex+      | Map.null store = []+      | otherwise =+          [ "Storage:"+          , indent 2 $ T.unlines $ Map.foldrWithKey (\key val acc -> ("Addr " <> (T.pack $ show key) <> ": " <> (T.pack $ show (Map.toList val))) : acc) mempty store+          , ""+          ]+     txCtx :: [Text]     txCtx       | Map.null txContext = []@@ -663,7 +749,7 @@  -- | Takes a buffer and a Cex and replaces all abstract values in the buf with concrete ones from the Cex subModel :: SMTCex -> Expr a -> Expr a-subModel c expr = subBufs (buffers c) . subVars (vars c) . subVars (blockContext c) . subVars (txContext c) $ expr+subModel c expr = subBufs c.buffers . subVars c.vars . subStore c.store . subVars c.blockContext . subVars c.txContext $ expr   where     subVars model b = Map.foldlWithKey subVar b model     subVar :: Expr a -> Expr EWord -> W256 -> Expr a@@ -685,4 +771,12 @@           a@(AbstractBuf _) -> if a == var                       then ConcreteBuf val                       else a+          e -> e++    subStore :: Map W256 (Map W256 W256) -> Expr a -> Expr a+    subStore m b = mapExpr go b+      where+        go :: Expr a -> Expr a+        go = \case+          AbstractStore -> ConcreteStore m           e -> e
src/EVM/TTY.hs view
@@ -1,6 +1,7 @@ {-# Language TemplateHaskell #-} {-# Language ImplicitParams #-} {-# Language DataKinds #-}+ module EVM.TTY where  import Prelude hiding (lookup, Word)@@ -14,52 +15,44 @@ import EVM.ABI (abiTypeSolidity, decodeAbiValue, AbiType(..), emptyAbi) import EVM.SymExec (maxIterationsReached, symCalldata) import EVM.Expr (simplify)-import EVM.Dapp (DappInfo, dappInfo, Test, extractSig, Test(..), srcMap)-import EVM.Dapp (dappUnitTests, unitTestMethods, dappSolcByName, dappSolcByHash, dappSources)-import EVM.Dapp (dappAstSrcMap)+import EVM.Dapp (DappInfo(..), dappInfo, Test, extractSig, Test(..), srcMap, unitTestMethods) import EVM.Debug-import EVM.Format (showWordExact, showWordExplanation)-import EVM.Format (contractNamePart, contractPathPart, showTraceTree, prettyIfConcreteWord, formatExpr)+import EVM.Fetch (Fetcher)+import EVM.Fetch qualified as Fetch+import EVM.Format (showWordExact, showWordExplanation, contractNamePart,+  contractPathPart, showTraceTree, prettyIfConcreteWord, formatExpr) import EVM.Hexdump (prettyHex)-import EVM.SMT (SolverGroup)+import EVM.Solvers (SolverGroup) import EVM.Op import EVM.Solidity hiding (storageLayout) import EVM.Types hiding (padRight) import EVM.UnitTest-import EVM.StorageLayout-import Text.Wrap- import EVM.Stepper (Stepper)-import qualified EVM.Stepper as Stepper-import qualified EVM.Fetch as Fetch-import qualified Control.Monad.Operational as Operational--import EVM.Fetch (Fetcher)+import EVM.Stepper qualified as Stepper+import EVM.StorageLayout+import EVM.TTYCenteredList qualified as Centered  import Control.Lens hiding (List)+import Control.Monad.Operational qualified as Operational import Control.Monad.State.Strict hiding (state)- import Data.Aeson.Lens import Data.ByteString (ByteString)+import Data.ByteString qualified as BS+import Data.List (sort, find) import Data.Maybe (isJust, fromJust, fromMaybe, isNothing) import Data.Map (Map, insert, lookupLT, singleton, filter)+import Data.Map qualified as Map import Data.Text (Text, pack)+import Data.Text qualified as T+import Data.Text qualified as Text import Data.Text.Encoding (decodeUtf8)-import Data.List (sort, find)+import Data.Vector qualified as Vec+import Data.Vector.Storable qualified as SVec import Data.Version (showVersion)--import qualified Data.ByteString as BS-import qualified Data.Text as T-import qualified Data.Map as Map-import qualified Data.Text as Text-import qualified Data.Vector as Vec-import qualified Data.Vector.Storable as SVec-import qualified Graphics.Vty as V-import qualified System.Console.Haskeline as Readline--import qualified EVM.TTYCenteredList as Centered--import qualified Paths_hevm as Paths+import Graphics.Vty qualified as V+import System.Console.Haskeline qualified as Readline+import Paths_hevm qualified as Paths+import Text.Wrap  data Name   = AbiPane@@ -222,7 +215,7 @@  isUnitTestContract :: Text -> DappInfo -> Bool isUnitTestContract name dapp =-  elem name (map fst (view dappUnitTests dapp))+  elem name (map fst dapp.unitTests)  mkVty :: IO V.Vty mkVty = do@@ -258,7 +251,7 @@   v <- mkVty   ui2 <- customMain v mkVty Nothing (app opts) (ViewVm ui0)   case ui2 of-    ViewVm ui -> return (view uiVm ui)+    ViewVm ui -> return ui._uiVm     _ -> error "internal error: customMain returned prematurely"  @@ -303,7 +296,7 @@                   (Vec.fromList                    (concatMap                     (debuggableTests opts)-                    (view dappUnitTests dapp)))+                    dapp.unitTests))                   1             , _testPickerDapp = dapp             , _testOpts = opts@@ -325,7 +318,7 @@     (Continue steps, ui') ->       put (ViewVm (ui' & set uiStepper steps))   where-    m = interpret mode (view uiStepper ui)+    m = interpret mode ui._uiStepper     nxt = runStateT m ui  backstepUntil@@ -334,21 +327,21 @@   => (UiVmState -> Pred VM) -> EventM n UiState () backstepUntil p = get >>= \case   ViewVm s ->-    case view uiStep s of+    case s._uiStep of       0 -> pure ()       n -> do         s1 <- liftIO $ backstep s         let           -- find a previous vm that satisfies the predicate-          snapshots' = Data.Map.filter (p s1 . fst) (view uiSnapshots s1)+          snapshots' = Data.Map.filter (p s1 . fst) s1._uiSnapshots         case lookupLT n snapshots' of           -- If no such vm exists, go to the beginning           Nothing ->             let-              (step', (vm', stepper')) = fromJust $ lookupLT (n - 1) (view uiSnapshots s)+              (step', (vm', stepper')) = fromJust $ lookupLT (n - 1) s._uiSnapshots               s2 = s1                 & set uiVm vm'-                & set (uiVm . cache) (view (uiVm . cache) s1)+                & set (uiVm . cache) s1._uiVm._cache                 & set uiStep step'                 & set uiStepper stepper'             in takeStep s2 (Step 0)@@ -357,7 +350,7 @@             let               s2 = s1                 & set uiVm vm'-                & set (uiVm . cache) (view (uiVm . cache) s1)+                & set (uiVm . cache) s1._uiVm._cache                 & set uiStep step'                 & set uiStepper stepper'             in takeStep s2 (StepUntil (not . p s1))@@ -368,7 +361,7 @@      ,?maxIter :: Maybe Integer)   => UiVmState -> IO UiVmState backstep s =-  case view uiStep s of+  case s._uiStep of     -- We're already at the first step; ignore command.     0 -> pure s     -- To step backwards, we revert to the previous snapshot@@ -378,10 +371,10 @@     -- any blocking queries, and also the memory view.     n ->       let-        (step, (vm, stepper)) = fromJust $ lookupLT n (view uiSnapshots s)+        (step, (vm, stepper)) = fromJust $ lookupLT n s._uiSnapshots         s1 = s           & set uiVm vm-          & set (uiVm . cache) (view (uiVm . cache) s)+          & set (uiVm . cache) s._uiVm._cache           & set uiStep step           & set uiStepper stepper         stepsToTake = n - step - 1@@ -419,14 +412,14 @@ appEvent (VtyEvent (V.EvKey V.KEsc [])) = get >>= \case   ViewVm s -> do     let opts = s ^. uiTestOpts-        dapp' = dapp opts-        tests = concatMap (debuggableTests opts) (dapp' ^. dappUnitTests)+        dapp = opts.dapp+        tests = concatMap (debuggableTests opts) dapp.unitTests     case tests of       [] -> halt       ts ->         put $ ViewPicker $ UiTestPickerState           { _testPickerList = list TestPickerPane (Vec.fromList ts) 1-          , _testPickerDapp = dapp'+          , _testPickerDapp = dapp           , _testOpts = opts           }   ViewHelp s -> put (ViewVm s)@@ -441,15 +434,15 @@       { _browserContractList =           list             BrowserPane-            (Vec.fromList (Map.toList (view (uiVm . env . contracts) s)))+            (Vec.fromList (Map.toList s._uiVm._env._contracts))             2       , _browserVm = s       }   ViewPicker s ->-    case listSelectedElement (view testPickerList s) of+    case listSelectedElement s._testPickerList of       Nothing -> error "nothing selected"       Just (_, x) -> do-        let initVm  = initialUiVmStateForTest (view testOpts s) x+        let initVm  = initialUiVmStateForTest s._testOpts x         put (ViewVm initVm)   _ -> pure () @@ -514,10 +507,10 @@     -- We keep the current cache so we don't have to redo     -- any blocking queries.     let-      (vm, stepper) = fromJust (Map.lookup 0 (view uiSnapshots s))+      (vm, stepper) = fromJust (Map.lookup 0 s._uiSnapshots)       s' = s         & set uiVm vm-        & set (uiVm . cache) (view (uiVm . cache) s)+        & set (uiVm . cache) s._uiVm._cache         & set uiStep 0         & set uiStepper stepper @@ -527,7 +520,7 @@ -- Vm Overview: p - backstep appEvent (VtyEvent (V.EvKey (V.KChar 'p') [])) = get >>= \case   ViewVm s ->-    case view uiStep s of+    case s._uiStep of       0 ->         -- We're already at the first step; ignore command.         pure ()@@ -538,10 +531,10 @@         -- We keep the current cache so we don't have to redo         -- any blocking queries, and also the memory view.         let-          (step, (vm, stepper)) = fromJust $ lookupLT n (view uiSnapshots s)+          (step, (vm, stepper)) = fromJust $ lookupLT n s._uiSnapshots           s1 = s             & set uiVm vm -- set the vm to the one from the snapshot-            & set (uiVm . cache) (view (uiVm . cache) s) -- persist the cache+            & set (uiVm . cache) s._uiVm._cache -- persist the cache             & set uiStep step             & set uiStepper stepper           stepsToTake = n - step - 1@@ -562,7 +555,7 @@   ViewVm s ->     case view (uiVm . result) s of       Just (VMFailure (Choose (PleaseChoosePath _ contin))) ->-        takeStep (s & set uiStepper (Stepper.evm (contin True) >> (view uiStepper s)))+        takeStep (s & set uiStepper (Stepper.evm (contin True) >> s._uiStepper))           (Step 1)       _ -> pure ()   _ -> pure ()@@ -570,9 +563,9 @@ -- Vm Overview: 1 - choose jump appEvent (VtyEvent (V.EvKey (V.KChar '1') [])) = get >>= \case   ViewVm s ->-    case view (uiVm . result) s of+    case s._uiVm._result of       Just (VMFailure (Choose (PleaseChoosePath _ contin))) ->-        takeStep (s & set uiStepper (Stepper.evm (contin False) >> (view uiStepper s)))+        takeStep (s & set uiStepper (Stepper.evm (contin False) >> s._uiStepper))           (Step 1)       _ -> pure ()   _ -> pure ()@@ -616,7 +609,7 @@       SymbolicTest _ -> symCalldata theTestName types [] (AbstractBuf "txdata")       _ -> (error "unreachable", error "unreachable")     (test, types) = fromJust $ find (\(test',_) -> extractSig test' == theTestName) $ unitTestMethods testContract-    testContract = fromJust $ view (dappSolcByName . at theContractName) dapp+    testContract = fromJust $ Map.lookup theContractName dapp.solcByName     vm0 =       initialUnitTestVm opts testContract     script = do@@ -697,7 +690,7 @@              withHighlight selected $                txt " Debug " <+> txt (contractNamePart x) <+> txt "::" <+> txt y)           True-          (view testPickerList ui)+          ui._testPickerList   ]  drawVmBrowser :: UiBrowserState -> [UiWidget]@@ -708,48 +701,47 @@             renderList               (\selected (k, c') ->                  withHighlight selected . txt . mconcat $-                   [ fromMaybe "<unknown contract>" . flip preview dapp' $-                       ( dappSolcByHash . ix (maybeHash c')-                       . _2 . contractName )+                   [ fromMaybe "<unknown contract>" $+                       Map.lookup (maybeHash c') dapp.solcByHash <&> (.contractName) . snd                    , "\n"                    , "  ", pack (show k)                    ])               True-              (view browserContractList ui)-      , case flip preview dapp' (dappSolcByHash . ix (maybeHash c) . _2) of+              ui._browserContractList+      , case snd <$> Map.lookup (maybeHash c) dapp.solcByHash of           Nothing ->             hBox               [ borderWithLabel (txt "Contract information") . padBottom Max . padRight Max $ vBox-                  [ txt ("Codehash: " <>    pack (show (view codehash c)))-                  , txt ("Nonce: "    <> showWordExact (view nonce    c))-                  , txt ("Balance: "  <> showWordExact (view balance  c))+                  [ txt ("Codehash: " <> pack (show c._codehash))+                  , txt ("Nonce: "    <> showWordExact c._nonce)+                  , txt ("Balance: "  <> showWordExact c._balance)                   --, txt ("Storage: "  <> storageDisplay (view storage c)) -- TODO: fix this                   ]                 ]           Just sol ->             hBox               [ borderWithLabel (txt "Contract information") . padBottom Max . padRight (Pad 2) $ vBox-                  [ txt "Name: " <+> txt (contractNamePart (view contractName sol))-                  , txt "File: " <+> txt (contractPathPart (view contractName sol))+                  [ txt "Name: " <+> txt (contractNamePart sol.contractName)+                  , txt "File: " <+> txt (contractPathPart sol.contractName)                   , txt " "                   , txt "Constructor inputs:"-                  , vBox . flip map (view constructorInputs sol) $+                  , vBox . flip map sol.constructorInputs $                       \(name, abiType) -> txt ("  " <> name <> ": " <> abiTypeSolidity abiType)                   , txt "Public methods:"-                  , vBox . flip map (sort (Map.elems (view abiMap sol))) $-                      \method -> txt ("  " <> view methodSignature method)+                  , vBox . flip map (sort (Map.elems sol.abiMap)) $+                      \method -> txt ("  " <> method.methodSignature)                   --, txt ("Storage:" <> storageDisplay (view storage c)) -- TODO: fix this                   ]               , borderWithLabel (txt "Storage slots") . padBottom Max . padRight Max $ vBox-                  (map txt (storageLayout dapp' sol))+                  (map txt (storageLayout dapp sol))               ]       ]   ]   where-    dapp' = dapp (view (browserVm . uiTestOpts) ui)-    (_, (_, c)) = fromJust $ listSelectedElement (view browserContractList ui)+    dapp = ui._browserVm._uiTestOpts.dapp+    (_, (_, c)) = fromJust $ listSelectedElement ui._browserContractList --        currentContract  = view (dappSolcByHash . ix ) dapp-    maybeHash ch = fromJust (error "Internal error: cannot find concrete codehash for partially symbolic code") (maybeLitWord (view codehash ch))+    maybeHash ch = fromJust (error "Internal error: cannot find concrete codehash for partially symbolic code") (maybeLitWord ch._codehash)  drawVm :: UiVmState -> [UiWidget] drawVm ui =@@ -813,35 +805,35 @@   :: UiVmState -> Pred VM isNewTraceAdded ui vm =   let-    currentTraceTree = length <$> traceForest (view uiVm ui)+    currentTraceTree = length <$> traceForest ui._uiVm     newTraceTree = length <$> traceForest vm   in currentTraceTree /= newTraceTree  isNextSourcePosition   :: UiVmState -> Pred VM isNextSourcePosition ui vm =-  let dapp' = dapp (view uiTestOpts ui)-      initialPosition = currentSrcMap dapp' (view uiVm ui)-  in currentSrcMap dapp' vm /= initialPosition+  let dapp = ui._uiTestOpts.dapp+      initialPosition = currentSrcMap dapp ui._uiVm+  in currentSrcMap dapp vm /= initialPosition  isNextSourcePositionWithoutEntering   :: UiVmState -> Pred VM isNextSourcePositionWithoutEntering ui vm =   let-    dapp'           = dapp (view uiTestOpts ui)-    vm0             = view uiVm ui-    initialPosition = currentSrcMap dapp' vm0-    initialHeight   = length (view frames vm0)+    dapp            = ui._uiTestOpts.dapp+    vm0             = ui._uiVm+    initialPosition = currentSrcMap dapp vm0+    initialHeight   = length vm0._frames   in-    case currentSrcMap dapp' vm of+    case currentSrcMap dapp vm of       Nothing ->         False       Just here ->         let           moved = Just here /= initialPosition-          deeper = length (view frames vm) > initialHeight+          deeper = length vm._frames > initialHeight           boring =-            case srcMapCode (view dappSources dapp') here of+            case srcMapCode dapp.sources here of               Just bs ->                 BS.isPrefixOf "contract " bs               Nothing ->@@ -850,20 +842,20 @@            moved && not deeper && not boring  isExecutionHalted :: UiVmState -> Pred VM-isExecutionHalted _ vm = isJust (view result vm)+isExecutionHalted _ vm = isJust vm._result  currentSrcMap :: DappInfo -> VM -> Maybe SrcMap currentSrcMap dapp vm = do   this <- currentContract vm-  i <- (view opIxMap this) SVec.!? (view (state . pc) vm)+  i <- this._opIxMap SVec.!? vm._state._pc   srcMap dapp this i  drawStackPane :: UiVmState -> UiWidget drawStackPane ui =   let-    gasText = showWordExact (num $ view (uiVm . state . gas) ui)+    gasText = showWordExact (num ui._uiVm._state._gas)     labelText = txt ("Gas available: " <> gasText <> "; stack:")-    stackList = list StackPane (Vec.fromList $ zip [(1 :: Int)..] (fmap simplify $ view (uiVm . state . stack) ui)) 2+    stackList = list StackPane (Vec.fromList $ zip [(1 :: Int)..] (simplify <$> ui._uiVm._state._stack)) 2   in hBorderWithLabel labelText <=>     renderList       (\_ (i, w) ->@@ -872,14 +864,14 @@                <+> ourWrap (Text.unpack $ prettyIfConcreteWord w)            , dim (txt ("   " <> case unlit w of                        Nothing -> ""-                       Just u -> showWordExplanation u $ dapp (view uiTestOpts ui)))+                       Just u -> showWordExplanation u ui._uiTestOpts.dapp))            ])       False       stackList  message :: VM -> String message vm =-  case view result vm of+  case vm._result of     Just (VMSuccess (ConcreteBuf msg)) ->       "VMSuccess: " <> (show $ ByteStringS msg)     Just (VMSuccess (msg)) ->@@ -889,13 +881,13 @@     Just (VMFailure err) ->       "VMFailure: " <> show err     Nothing ->-      "Executing EVM code in " <> show (view (state . contract) vm)+      "Executing EVM code in " <> show vm._state._contract   drawBytecodePane :: UiVmState -> UiWidget drawBytecodePane ui =   let-    vm = view uiVm ui+    vm = ui._uiVm     move = maybe id listMoveTo $ vmOpIx vm   in     hBorderWithLabel (str $ message vm) <=>@@ -905,7 +897,7 @@                     else withDefAttr boldAttr (opWidget x))       False       (move $ list BytecodePane-        (maybe mempty (view codeOps) (currentContract vm))+        (maybe mempty (._codeOps) (currentContract vm))         1)  @@ -922,31 +914,31 @@  drawTracePane :: UiVmState -> UiWidget drawTracePane s =-  let vm = view uiVm s-      dapp' = dapp (view uiTestOpts s)+  let vm = s._uiVm+      dapp = s._uiTestOpts.dapp       traceList =         list           TracePane           (Vec.fromList             . Text.lines-            . showTraceTree dapp'+            . showTraceTree dapp             $ vm)           1 -  in case view uiShowMemory s of+  in case s._uiShowMemory of     True -> viewport TracePane Vertical $         hBorderWithLabel (txt "Calldata")-        <=> ourWrap (prettyIfConcrete (view (state . calldata) vm))+        <=> ourWrap (prettyIfConcrete vm._state._calldata)         <=> hBorderWithLabel (txt "Returndata")-        <=> ourWrap (prettyIfConcrete (view (state . returndata) vm))+        <=> ourWrap (prettyIfConcrete vm._state._returndata)         <=> hBorderWithLabel (txt "Output")-        <=> ourWrap (maybe "" show (view result vm))+        <=> ourWrap (maybe "" show vm._result)         <=> hBorderWithLabel (txt "Cache")-        <=> ourWrap (show (view (cache . path) vm))+        <=> ourWrap (show vm._cache._path)         <=> hBorderWithLabel (txt "Path Conditions")-        <=> (ourWrap $ show $ view constraints vm)+        <=> (ourWrap $ show $ vm._constraints)         <=> hBorderWithLabel (txt "Memory")-        <=> (ourWrap (prettyIfConcrete (view (state . memory) vm)))+        <=> (ourWrap (prettyIfConcrete vm._state._memory))     False ->       hBorderWithLabel (txt "Trace")       <=> renderList@@ -965,45 +957,40 @@       }  solidityList :: VM -> DappInfo -> List Name (Int, ByteString)-solidityList vm dapp' =+solidityList vm dapp =   list SolidityPane-    (case currentSrcMap dapp' vm of+    (case currentSrcMap dapp vm of         Nothing -> mempty         Just x ->-          view (dappSources-            . sourceLines-            . ix (srcMapFile x)+          view (+            ix x.srcMapFile             . to (Vec.imap (,)))-          dapp')+          dapp.sources.lines)     1  drawSolidityPane :: UiVmState -> UiWidget drawSolidityPane ui =-  let dapp' = dapp (view uiTestOpts ui)-      dappSrcs = view dappSources dapp'-      vm = view uiVm ui-  in case currentSrcMap dapp' vm of+  let dapp = ui._uiTestOpts.dapp+      dappSrcs = dapp.sources+      vm = ui._uiVm+  in case currentSrcMap dapp vm of     Nothing -> padBottom Max (hBorderWithLabel (txt "<no source map>"))     Just sm ->           let-            rows = (_sourceLines dappSrcs) !! srcMapFile sm-            subrange = lineSubrange rows (srcMapOffset sm, srcMapLength sm)+            rows = dappSrcs.lines !! sm.srcMapFile+            subrange = lineSubrange rows (sm.srcMapOffset, sm.srcMapLength)             fileName :: Maybe Text-            fileName = preview (dappSources . sourceFiles . ix (srcMapFile sm) . _1) dapp'+            fileName = preview (ix sm.srcMapFile . _1) dapp.sources.files             lineNo :: Maybe Int-            lineNo = maybe Nothing (\a -> Just (a - 1))-              (snd <$>-                (srcMapCodePos-                 (view dappSources dapp')-                 sm))+            lineNo = ((\a -> Just (a - 1)) . snd) =<< srcMapCodePos dapp.sources sm           in vBox             [ hBorderWithLabel $                 txt (fromMaybe "<unknown>" fileName)-                  <+> str (":" ++ show lineNo)+                  <+> str (":" ++ (maybe "?" show lineNo))                    -- Show the AST node type if present                   <+> txt (" (" <> fromMaybe "?"-                                    ((view dappAstSrcMap dapp') sm+                                    (dapp.astSrcMap sm                                        >>= preview (key "name" . _String)) <> ")")             , Centered.renderList                 (\_ (i, line) ->@@ -1021,7 +1008,7 @@                                   ])                 False                 ((maybe id listMoveTo lineNo)-                  (solidityList vm dapp'))+                  (solidityList vm dapp))             ]  ifTallEnough :: Int -> Widget n -> Widget n -> Widget n
src/EVM/Transaction.hs view
@@ -52,94 +52,94 @@ -- | utility function for getting a more useful representation of accesslistentries -- duplicates only matter for gas computation txAccessMap :: Transaction -> Map Addr [W256]-txAccessMap tx = ((Map.fromListWith (++)) . makeTups) $ txAccessList tx-  where makeTups = map (\ale -> (accessAddress ale, accessStorageKeys ale))+txAccessMap tx = ((Map.fromListWith (++)) . makeTups) tx.txAccessList+  where makeTups = map (\ale -> (ale.accessAddress , ale.accessStorageKeys ))  ecrec :: W256 -> W256 -> W256 -> W256 -> Maybe Addr ecrec v r s e = num . word <$> EVM.Precompiled.execute 1 input 32   where input = BS.concat (word256Bytes <$> [e, v, r, s])  sender :: Int -> Transaction -> Maybe Addr-sender chainId tx = ecrec v' (txR tx) (txS tx) hash+sender chainId tx = ecrec v' tx.txR  tx.txS hash   where hash = keccak' (signingData chainId tx)-        v    = txV tx+        v    = tx.txV         v'   = if v == 27 || v == 28 then v                else 27 + v  signingData :: Int -> Transaction -> ByteString signingData chainId tx =-  case txType tx of+  case tx.txType of     LegacyTransaction -> if v == (chainId * 2 + 35) || v == (chainId * 2 + 36)       then eip155Data       else normalData     AccessListTransaction -> eip2930Data     EIP1559Transaction -> eip1559Data-  where v          = fromIntegral (txV tx)-        to'        = case txToAddr tx of+  where v          = fromIntegral tx.txV+        to'        = case tx.txToAddr of           Just a  -> BS $ word160Bytes a           Nothing -> BS mempty-        maxFee = fromJust $ txMaxFeePerGas tx-        maxPrio = fromJust $ txMaxPriorityFeeGas tx-        gasPrice = fromJust $ txGasPrice tx-        accessList = txAccessList tx+        maxFee = fromJust tx.txMaxFeePerGas+        maxPrio = fromJust tx.txMaxPriorityFeeGas+        gasPrice = fromJust tx.txGasPrice+        accessList = tx.txAccessList         rlpAccessList = EVM.RLP.List $ map (\accessEntry ->-          EVM.RLP.List [BS $ word160Bytes (accessAddress accessEntry),-                        EVM.RLP.List $ map rlpWordFull $ accessStorageKeys accessEntry]+          EVM.RLP.List [BS $ word160Bytes accessEntry.accessAddress,+                        EVM.RLP.List $ map rlpWordFull accessEntry.accessStorageKeys]           ) accessList-        normalData = rlpList [rlpWord256 (txNonce tx),+        normalData = rlpList [rlpWord256 tx.txNonce,                               rlpWord256 gasPrice,-                              rlpWord256 (num $ txGasLimit tx),+                              rlpWord256 (num tx.txGasLimit),                               to',-                              rlpWord256 (txValue tx),-                              BS (txData tx)]-        eip155Data = rlpList [rlpWord256 (txNonce tx),+                              rlpWord256 tx.txValue,+                              BS tx.txData]+        eip155Data = rlpList [rlpWord256 tx.txNonce,                               rlpWord256 gasPrice,-                              rlpWord256 (num $ txGasLimit tx),+                              rlpWord256 (num tx.txGasLimit),                               to',-                              rlpWord256 (txValue tx),-                              BS (txData tx),+                              rlpWord256 tx.txValue,+                              BS tx.txData,                               rlpWord256 (fromIntegral chainId),                               rlpWord256 0x0,                               rlpWord256 0x0]         eip1559Data = cons 0x02 $ rlpList [           rlpWord256 (fromIntegral chainId),-          rlpWord256 (txNonce tx),+          rlpWord256 tx.txNonce,           rlpWord256 maxPrio,           rlpWord256 maxFee,-          rlpWord256 (num $ txGasLimit tx),+          rlpWord256 (num tx.txGasLimit),           to',-          rlpWord256 (txValue tx),-          BS (txData tx),+          rlpWord256 tx.txValue,+          BS tx.txData,           rlpAccessList]          eip2930Data = cons 0x01 $ rlpList [           rlpWord256 (fromIntegral chainId),-          rlpWord256 (txNonce tx),+          rlpWord256 tx.txNonce,           rlpWord256 gasPrice,-          rlpWord256 (num $ txGasLimit tx),+          rlpWord256 (num tx.txGasLimit),           to',-          rlpWord256 (txValue tx),-          BS (txData tx),+          rlpWord256 tx.txValue,+          BS tx.txData,           rlpAccessList]  accessListPrice :: FeeSchedule Word64 -> [AccessListEntry] -> Word64 accessListPrice fs al =     sum (map       (\ale ->-        g_access_list_address fs +-        (g_access_list_storage_key fs * (fromIntegral . length) (accessStorageKeys ale)))+        fs.g_access_list_address  ++        (fs.g_access_list_storage_key  * (fromIntegral . length) ale.accessStorageKeys))         al)  txGasCost :: FeeSchedule Word64 -> Transaction -> Word64 txGasCost fs tx =-  let calldata     = txData tx+  let calldata     = tx.txData       zeroBytes    = BS.count 0 calldata       nonZeroBytes = BS.length calldata - zeroBytes-      baseCost     = g_transaction fs-        + (if isNothing (txToAddr tx) then g_txcreate fs else 0)-        + (accessListPrice fs $ txAccessList tx)-      zeroCost     = g_txdatazero fs-      nonZeroCost  = g_txdatanonzero fs+      baseCost     = fs.g_transaction+        + (if isNothing tx.txToAddr then fs.g_txcreate else 0)+        + (accessListPrice fs tx.txAccessList )+      zeroCost     = fs.g_txdatazero+      nonZeroCost  = fs.g_txdatanonzero   in baseCost + zeroCost * (fromIntegral zeroBytes) + nonZeroCost * (fromIntegral nonZeroBytes)  instance FromJSON AccessListEntry where@@ -200,16 +200,16 @@ -- and pay receiving address initTx :: EVM.VM -> EVM.VM initTx vm = let-    toAddr   = view (EVM.state . EVM.contract) vm-    origin   = view (EVM.tx . EVM.origin) vm-    gasPrice = view (EVM.tx . EVM.gasprice) vm-    gasLimit = view (EVM.tx . EVM.txgaslimit) vm-    coinbase = view (EVM.block . EVM.coinbase) vm-    value    = view (EVM.state . EVM.callvalue) vm-    toContract = initialContract (view (EVM.state . EVM.code) vm)-    preState = setupTx origin coinbase gasPrice gasLimit $ view (EVM.env . EVM.contracts) vm+    toAddr   = vm._state._contract+    origin   = vm._tx._origin+    gasPrice = vm._tx._gasprice+    gasLimit = vm._tx._txgaslimit+    coinbase = vm._block._coinbase+    value    = vm._state._callvalue+    toContract = initialContract vm._state._code+    preState = setupTx origin coinbase gasPrice gasLimit vm._env._contracts     oldBalance = view (accountAt toAddr . balance) preState-    creation = view (EVM.tx . EVM.isCreate) vm+    creation = vm._tx._isCreate     initState = (case unlit value of       Just v -> ((Map.adjust (over balance (subtract v))) origin)               . (Map.adjust (over balance (+ v))) toAddr
src/EVM/Types.hs view
@@ -5,7 +5,7 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE DefaultSignatures #-} -{-# OPTIONS_GHC -Wno-error=inline-rule-shadowing #-}+{-# OPTIONS_GHC -Wno-inline-rule-shadowing #-}  module EVM.Types where @@ -16,7 +16,7 @@ import Data.Map (Map) import Data.Bifunctor (first) import Data.Char-import Data.List (isPrefixOf)+import Data.List (isPrefixOf, foldl') import Data.ByteString (ByteString) import Data.ByteString.Base16 as BS16 import Data.ByteString.Builder (byteStringHex, toLazyByteString)@@ -124,6 +124,7 @@   | StackLimitExceeded   | InvalidMemoryAccess   | BadJumpDestination+  | StackUnderrun   | SelfDestruct   | TmpErr String   deriving (Show, Eq, Ord)@@ -410,6 +411,12 @@ (./=) :: (Typeable a) => Expr a -> Expr a -> Prop x ./= y = PNeg (PEq x y) +pand :: [Prop] -> Prop+pand = foldl' PAnd (PBool True)++por :: [Prop] -> Prop+por = foldl' POr (PBool False)+ instance Eq Prop where   PBool a == PBool b = a == b   PEq (a :: Expr x) (b :: Expr x) == PEq (c :: Expr y) (d :: Expr y)@@ -639,7 +646,7 @@ word256Bytes x = BS.pack [byteAt x (31 - i) | i <- [0..31]]  word160Bytes :: Addr -> ByteString-word160Bytes x = BS.pack [byteAt (addressWord160 x) (19 - i) | i <- [0..19]]+word160Bytes x = BS.pack [byteAt x.addressWord160 (19 - i) | i <- [0..19]]  newtype Nibble = Nibble Word8   deriving ( Num, Integral, Real, Ord, Enum, Eq, Bounded, Generic)
src/EVM/UnitTest.hs view
@@ -9,65 +9,57 @@ import EVM.ABI import EVM.Concrete import EVM.SMT+import EVM.Solvers import EVM.Dapp import EVM.Debug (srcMapCodePos) import EVM.Exec import EVM.Expr (litAddr, readStorage', simplify)+import EVM.Expr qualified as Expr+import EVM.Facts qualified as Facts+import EVM.Facts.Git qualified as Git+import EVM.FeeSchedule qualified as FeeSchedule+import EVM.Fetch qualified as Fetch import EVM.Format import EVM.Solidity-import qualified EVM.SymExec as SymExec+import EVM.SymExec qualified as SymExec import EVM.SymExec (defaultVeriOpts, symCalldata, verify, isQed, extractCex, runExpr, subModel, VeriOpts) import EVM.Types hiding (Failure) import EVM.Transaction (initTx) import EVM.RLP-import qualified EVM.Facts     as Facts-import qualified EVM.Facts.Git as Git-import qualified EVM.Fetch     as Fetch-import qualified EVM.Expr      as Expr--import qualified EVM.FeeSchedule as FeeSchedule- import EVM.Stepper (Stepper, interpret)-import qualified EVM.Stepper as Stepper-import qualified Control.Monad.Operational as Operational+import EVM.Stepper qualified as Stepper +import Control.Monad.Operational qualified as Operational import Control.Lens hiding (Indexed, elements, List, passing)-import Control.Monad.State.Strict hiding (state)-import qualified Control.Monad.State.Strict as State- import Control.Monad.Par.Class (spawn_)+import Control.Monad.Par.Class qualified as Par import Control.Monad.Par.IO (runParIO)--import qualified Data.ByteString.Lazy as BSLazy-import Data.Binary.Get    (runGet)-import Data.ByteString    (ByteString)-import Data.Decimal       (DecimalRaw(..))-import Data.Either        (isRight)-import Data.Foldable      (toList)-import Data.Map           (Map)-import Data.Maybe         (fromMaybe, catMaybes, fromJust, isJust, fromMaybe, mapMaybe, isNothing)-import Data.Text          (isPrefixOf, stripSuffix, intercalate, Text, pack, unpack)-import Data.Word          (Word32, Word64)-import Data.Text.Encoding (encodeUtf8)-import System.Environment (lookupEnv)-import System.IO          (hFlush, stdout)-import GHC.Natural--import qualified Control.Monad.Par.Class as Par-import qualified Data.ByteString as BS-import qualified Data.Map as Map-import qualified Data.Text as Text-import qualified Data.Text.IO as Text-+import Control.Monad.State.Strict hiding (state)+import Control.Monad.State.Strict qualified as State+import Data.ByteString.Lazy qualified as BSLazy+import Data.Binary.Get (runGet)+import Data.ByteString (ByteString)+import Data.ByteString qualified as BS+import Data.Decimal (DecimalRaw(..))+import Data.Either (isRight)+import Data.Foldable (toList)+import Data.Map (Map)+import Data.Map qualified as Map+import Data.Maybe (fromMaybe, catMaybes, fromJust, isJust, fromMaybe, mapMaybe, isNothing) import Data.MultiSet (MultiSet)-import qualified Data.MultiSet as MultiSet-+import Data.MultiSet qualified as MultiSet import Data.Set (Set)-import qualified Data.Set as Set-+import Data.Set qualified as Set+import Data.Text (isPrefixOf, stripSuffix, intercalate, Text, pack, unpack)+import Data.Text qualified as Text+import Data.Text.Encoding (encodeUtf8)+import Data.Text.IO qualified as Text import Data.Vector (Vector)-import qualified Data.Vector as Vector-+import Data.Vector qualified as Vector+import Data.Word (Word32, Word64)+import GHC.Natural+import System.Environment (lookupEnv)+import System.IO (hFlush, stdout) import Test.QuickCheck hiding (verbose)  data UnitTestOptions = UnitTestOptions@@ -127,10 +119,10 @@ -- | Generate VeriOpts from UnitTestOptions makeVeriOpts :: UnitTestOptions -> VeriOpts makeVeriOpts opts =-   defaultVeriOpts { SymExec.debug = smtDebug opts-                   , SymExec.maxIter = maxIter opts-                   , SymExec.askSmtIters = askSmtIters opts-                   , SymExec.rpcInfo = rpcInfo opts+   defaultVeriOpts { SymExec.debug = opts.smtDebug+                   , SymExec.maxIter = opts.maxIter+                   , SymExec.askSmtIters = opts.askSmtIters+                   , SymExec.rpcInfo = opts.rpcInfo                    }  -- | Top level CLI endpoint for dapp-test@@ -139,7 +131,7 @@   out <- liftIO $ readSolc solcFile   case out of     Just (contractMap, _) -> do-      let unitTests = findUnitTests (EVM.UnitTest.match opts) $ Map.elems contractMap+      let unitTests = findUnitTests opts.match $ Map.elems contractMap       results <- concatMapM (runUnitTestContract opts contractMap) unitTests       let (passing, vms) = unzip results       case cache' of@@ -148,13 +140,11 @@         Just path ->           -- merge all of the post-vm caches and save into the state           let-            evmcache = mconcat [view EVM.cache vm | vm <- vms]+            evmcache = mconcat [vm._cache | vm <- vms]           in             liftIO $ Git.saveFacts (Git.RepoAt path) (Facts.cacheFacts evmcache) -      if and passing-         then return True-         else return False+      return $ and passing     Nothing ->       error ("Failed to read Solidity JSON for `" ++ solcFile ++ "'") @@ -164,7 +154,7 @@ initializeUnitTest :: UnitTestOptions -> SolcContract -> Stepper () initializeUnitTest UnitTestOptions { .. } theContract = do -  let addr = testAddress testParams+  let addr = testParams.testAddress    Stepper.evm $ do     -- Maybe modify the initial VM, e.g. to load library code@@ -177,10 +167,10 @@    Stepper.evm $ do     -- Give a balance to the test target-    env . contracts . ix addr . balance += testBalanceCreate testParams+    env . contracts . ix addr . balance += testParams.testBalanceCreate      -- call setUp(), if it exists, to initialize the test contract-    let theAbi = view abiMap theContract+    let theAbi = theContract.abiMap         setUp  = abiKeccak (encodeUtf8 "setUp()")      when (isJust (Map.lookup setUp theAbi)) $ do@@ -218,11 +208,11 @@   Stepper.evm $ do     cs <- use (env . contracts)     abiCall testParams (Right bs)-    let (Method _ inputs sig _ _) = fromMaybe (error "unknown abi call") $ Map.lookup (num $ word $ BS.take 4 bs) (view dappAbiMap dapp)+    let (Method _ inputs sig _ _) = fromMaybe (error "unknown abi call") $ Map.lookup (num $ word $ BS.take 4 bs) dapp.abiMap         types = snd <$> inputs     let ?context = DappContext dapp cs-    this <- fromMaybe (error "unknown target") <$> (use (env . contracts . at (testAddress testParams)))-    let name = maybe "" (contractNamePart . view contractName) $ lookupCode (view contractcode this) dapp+    this <- fromMaybe (error "unknown target") <$> (use (env . contracts . at testParams.testAddress))+    let name = maybe "" (contractNamePart . (.contractName)) $ lookupCode this._contractcode dapp     pushTrace (EntryTrace (name <> "." <> sig <> "(" <> intercalate "," ((pack . show) <$> types) <> ")" <> showCall types (ConcreteBuf bs)))   -- Try running the test method   Stepper.execFully >>= \case@@ -266,10 +256,10 @@   } deriving (Show)  instance Eq OpLocation where-  (==) (OpLocation a b) (OpLocation a' b') = b == b' && view contractcode a == view contractcode a'+  (==) (OpLocation a b) (OpLocation a' b') = b == b' && a._contractcode == a'._contractcode  instance Ord OpLocation where-  compare (OpLocation a b) (OpLocation a' b') = compare (view contractcode a, b) (view contractcode a', b')+  compare (OpLocation a b) (OpLocation a' b') = compare (a._contractcode, b) (a'._contractcode, b')  srcMapForOpLocation :: DappInfo -> OpLocation -> Maybe SrcMap srcMapForOpLocation dapp (OpLocation contr opIx) = srcMap dapp contr opIx@@ -295,7 +285,7 @@   -- This is just like `exec` except for every instruction evaluated,   -- we also increment a counter indexed by the current code location.   vm0 <- use _1-  case view result vm0 of+  case vm0._result of     Nothing -> do       vm1 <- zoom _1 (State.state (runState exec1) >> get)       zoom _2 (modify (MultiSet.insert (currentOpLocation vm1)))@@ -341,7 +331,7 @@ coverageReport dapp cov =   let     sources :: SourceCache-    sources = view dappSources dapp+    sources = dapp.sources      allPositions :: Set (Text, Int)     allPositions =@@ -349,9 +339,9 @@       . mapMaybe (srcMapCodePos sources)       . toList       $ mconcat-        ( view dappSolcByName dapp+        ( dapp.solcByName         & Map.elems-        & map (\x -> view runtimeSrcmap x <> view creationSrcmap x)+        & map (\x -> x.runtimeSrcmap <> x.creationSrcmap)         )       ) @@ -362,8 +352,8 @@     linesByName =       Map.fromList $ zipWith           (\(name, _) lines' -> (name, lines'))-          (view sourceFiles sources)-          (view sourceLines sources)+          sources.files+          sources.lines      f :: Text -> Vector ByteString -> Vector (Int, ByteString)     f name =@@ -388,7 +378,7 @@   opts@(UnitTestOptions {..}) contractMap _ (name, testNames) = do    -- Look for the wanted contract by name from the Solidity info-  case preview (ix name) contractMap of+  case Map.lookup name contractMap of     Nothing ->       -- Fail if there's no such contract       error $ "Contract " ++ unpack name ++ " not found"@@ -432,7 +422,7 @@     ++ unpack name    -- Look for the wanted contract by name from the Solidity info-  case preview (ix name) contractMap of+  case Map.lookup name contractMap of     Nothing ->       -- Fail if there's no such contract       error $ "Contract " ++ unpack name ++ " not found"@@ -446,7 +436,7 @@             (Stepper.enter name >> initializeUnitTest opts theContract))           vm0 -      case view result vm1 of+      case vm1._result of         Nothing -> error "internal error: setUp() did not end with a result"         Just (VMFailure _) -> liftIO $ do           Text.putStrLn "\x1b[31m[BAIL]\x1b[0m setUp() "@@ -461,7 +451,7 @@             runCache (results, vm) (test, types) = do               (t, r, vm') <- runTest opts vm (test, types)               liftIO $ Text.putStrLn t-              let vmCached = vm & set cache (view cache vm')+              let vmCached = vm { _cache = vm'._cache }               pure (((r, vm'): results), vmCached)            -- Run all the test cases and print their status updates,@@ -527,31 +517,33 @@      Nothing ->       Stepper.evmIO $ do        vm <- get-       let cs = view (env . contracts) vm-           noCode c = case view contractcode c of+       let cs = vm._env._contracts+           noCode c = case c._contractcode of              RuntimeCode (ConcreteRuntimeCode "") -> True              RuntimeCode (SymbolicRuntimeCode c') -> null c'              _ -> False-           mutable m = view methodMutability m `elem` [NonPayable, Payable]+           mutable m = m.mutability `elem` [NonPayable, Payable]            knownAbis :: Map Addr SolcContract            knownAbis =              -- exclude contracts without code-             Map.filter (not . BS.null . view runtimeCode) $+             Map.filter (not . BS.null . (.runtimeCode)) $              -- exclude contracts without state changing functions-             Map.filter (not . null . Map.filter mutable . view abiMap) $+             Map.filter (not . null . Map.filter mutable . (.abiMap)) $              -- exclude testing abis-             Map.filter (isNothing . preview (abiMap . ix unitTestMarkerAbi)) $+             Map.filter (isNothing . preview (ix unitTestMarkerAbi) . (.abiMap)) $              -- pick all contracts with known compiler artifacts-             fmap fromJust (Map.filter isJust $ Map.fromList [(addr, lookupCode (view contractcode c) dapp) | (addr, c)  <- Map.toList cs])+             fmap fromJust (Map.filter isJust $ Map.fromList [(addr, lookupCode c._contractcode dapp) | (addr, c)  <- Map.toList cs])            selected = [(addr,-                        fromMaybe (error ("no src found for: " <> show addr)) $ lookupCode (view contractcode (fromMaybe (error $ "contract not found: " <> show addr) $ Map.lookup addr cs)) dapp)+                        fromMaybe (error ("no src found for: " <> show addr)) $+                          lookupCode (fromMaybe (error $ "contract not found: " <> show addr) $+                            Map.lookup addr cs)._contractcode dapp)                        | addr  <- targets]        -- go to IO and generate a random valid call to any known contract        liftIO $ do          -- select random contract          (target, solcInfo) <- generate $ elements (if null targets then Map.toList knownAbis else selected)          -- choose a random mutable method-         (_, (Method _ inputs sig _ _)) <- generate (elements $ Map.toList $ Map.filter mutable $ view abiMap solcInfo)+         (_, (Method _ inputs sig _ _)) <- generate (elements $ Map.toList $ Map.filter mutable solcInfo.abiMap)          let types = snd <$> inputs          -- set the caller to a random address with 90% probability, 10% known EOA address          let knownEOAs = Map.keys $ Map.filter noCode cs@@ -567,7 +559,7 @@          let cd = abiMethod (sig <> "(" <> intercalate "," ((pack . show) <$> types) <> ")") args          -- increment timestamp with random amount          timepassed <- num <$> generate (arbitrarySizedNatural :: Gen Word32)-         let ts = fromMaybe (error "symbolic timestamp not supported here") $ maybeLitWord $ view (block . timestamp) vm+         let ts = fromMaybe (error "symbolic timestamp not supported here") $ maybeLitWord vm._block._timestamp          return (caller', target, cd, num ts + timepassed)  let opts' = opts { testParams = testParams {testAddress = target, testCaller = caller', testTimestamp = timestamp'}}      thisCallRLP = List [BS $ word160Bytes caller', BS $ word160Bytes target, BS cd, BS $ word256Bytes timestamp']@@ -593,7 +585,7 @@ getTargetContracts UnitTestOptions{..} = do   vm <- Stepper.evm get   let contract' = fromJust $ currentContract vm-      theAbi = view abiMap $ fromJust $ lookupCode (view contractcode contract') dapp+      theAbi = (fromJust $ lookupCode contract'._contractcode dapp).abiMap       setUp  = abiKeccak (encodeUtf8 "targetContracts()")   case Map.lookup setUp theAbi of     Nothing -> return []@@ -653,7 +645,7 @@       (EVM.Stepper.interpret (Fetch.oracle solvers rpcInfo) (checkFailures opts testName bailed)) vm'   if success   then-     let gasSpent = num (testGasCall testParams) - view (state . gas) vm'+     let gasSpent = num testParams.testGasCall - vm'._state._gas          gasText = pack $ show (fromIntegral gasSpent :: Integer)      in         pure@@ -721,7 +713,7 @@ symRun opts@UnitTestOptions{..} vm testName types = do     let cd = symCalldata testName types [] (AbstractBuf "txdata")         shouldFail = "proveFail" `isPrefixOf` testName-        testContract = view (state . contract) vm+        testContract = vm._state._contract      -- define postcondition depending on `shouldFail`     -- We directly encode the failure conditions from failed() in ds-test since this is easier to encode than a call into failed()@@ -764,7 +756,7 @@     , intercalate "\n" $ indentLines 2 . mkMsg <$> failures'     ]     where-      ctx = DappContext { _contextInfo = dapp, _contextEnv = mempty }+      ctx = DappContext { info = dapp, env = mempty }       showRes = \case                        Return _ _ _ -> if "proveFail" `isPrefixOf` testName                                       then "Successful execution"@@ -835,7 +827,7 @@  passOutput :: VM -> UnitTestOptions -> Text -> Text passOutput vm UnitTestOptions { .. } testName =-  let ?context = DappContext { _contextInfo = dapp, _contextEnv = vm ^?! EVM.env . EVM.contracts }+  let ?context = DappContext { info = dapp, env = vm._env._contracts }   in let v = fromMaybe 0 verbose   in if (v > 1) then     mconcat@@ -843,7 +835,7 @@       , fromMaybe "" (stripSuffix "()" testName)       , "\n"       , if (v > 2) then indentLines 2 (showTraceTree dapp vm) else ""-      , indentLines 2 (formatTestLogs (view dappEventMap dapp) (view logs vm))+      , indentLines 2 (formatTestLogs dapp.eventMap vm._logs)       , "\n"       ]     else ""@@ -851,7 +843,7 @@ -- TODO failOutput :: VM -> UnitTestOptions -> Text -> Text failOutput vm UnitTestOptions { .. } testName =-  let ?context = DappContext { _contextInfo = dapp, _contextEnv = vm ^?! EVM.env . EVM.contracts}+  let ?context = DappContext { info = dapp, env = vm._env._contracts}   in mconcat   [ "Failure: "   , fromMaybe "" (stripSuffix "()" testName)@@ -859,7 +851,7 @@   , case verbose of       Just _ -> indentLines 2 (showTraceTree dapp vm)       _ -> ""-  , indentLines 2 (formatTestLogs (view dappEventMap dapp) (view logs vm))+  , indentLines 2 (formatTestLogs dapp.eventMap vm._logs)   , "\n"   ] @@ -955,7 +947,7 @@   assign (state . caller) (litAddr testCaller)   assign (state . gas) testGasCall   origin' <- fromMaybe (initialContract (RuntimeCode (ConcreteRuntimeCode ""))) <$> use (env . contracts . at testOrigin)-  let originBal = view balance origin'+  let originBal = origin'._balance   when (originBal < testGasprice * (num testGasCall)) $ error "insufficient balance for gas cost"   vm <- get   put $ initTx vm@@ -965,7 +957,7 @@   let     TestVMParams {..} = testParams     vm = makeVm $ VMOpts-           { vmoptContract = initialContract (InitCode (view creationCode theContract) mempty)+           { vmoptContract = initialContract (InitCode theContract.creationCode mempty)            , vmoptCalldata = mempty            , vmoptValue = Lit 0            , vmoptAddress = testAddress
test/BlockchainTests.hs view
@@ -13,7 +13,7 @@ import EVM.FeeSchedule qualified import EVM.Fetch qualified import EVM.Stepper qualified-import EVM.SMT (withSolvers, Solver(Z3))+import EVM.Solvers (withSolvers, Solver(Z3)) import EVM.Transaction import EVM.TTY qualified as TTY import EVM.Types@@ -104,11 +104,7 @@  -- CI has issues with some heaver tests, disable in bulk ciIgnoredFiles :: [String]-ciIgnoredFiles =-  [ "BlockchainTests/GeneralStateTests/VMTests/vmPerformance"-  , "BlockchainTests/GeneralStateTests/stQuadraticComplexityTest"-  , "BlockchainTests/GeneralStateTests/stStaticCall"-  ]+ciIgnoredFiles = []  commonProblematicTests :: Map String (TestTree -> TestTree) commonProblematicTests = Map.fromList@@ -186,8 +182,8 @@         , ("bad-storage", not okData  || okMoney || okNonce || okCode)         , ("bad-code",    not okCode  || okMoney || okNonce || okData)         ])-    check = checkContracts x-    expected = testExpectation x+    check = x.checkContracts+    expected = x.testExpectation     actual = Map.map (,mempty) $ view (EVM.env . EVM.contracts) vm -- . to (fmap (clearZeroStorage.clearOrigStorage))) vm     printStorage = show -- TODO: fixme @@ -203,7 +199,7 @@  checkExpectation :: Bool -> Case -> EVM.VM -> IO (Maybe String) checkExpectation diff x vm = do-  let expectation = testExpectation x+  let expectation = x.testExpectation       (okState, b2, b3, b4, b5) = checkExpectedContracts vm expectation   if okState then     pure Nothing@@ -260,7 +256,7 @@ clearCode :: (EVM.Contract, Storage) -> (EVM.Contract, Storage) clearCode (c, s) = (set contractcode (EVM.RuntimeCode (EVM.ConcreteRuntimeCode "")) c, s) -newtype ContractWithStorage = ContractWithStorage { unContractWithStorage :: (EVM.Contract, Storage) }+newtype ContractWithStorage = ContractWithStorage (EVM.Contract, Storage)  instance FromJSON ContractWithStorage where   parseJSON (JSON.Object v) = do@@ -302,10 +298,11 @@ parseContracts ::   Which -> JSON.Object -> JSON.Parser (Map Addr (EVM.Contract, Storage)) parseContracts w v =-  (Map.map unContractWithStorage) <$> (v .: which >>= parseJSON)+  (Map.map unwrap) <$> (v .: which >>= parseJSON)   where which = case w of           Pre  -> "pre"           Post -> "postState"+        unwrap (ContractWithStorage x) = x  parseBCSuite ::   Lazy.ByteString -> Either String (Map String Case)@@ -343,7 +340,7 @@ fromBlockchainCase :: BlockchainCase -> Either BlockchainError Case fromBlockchainCase (BlockchainCase blocks preState postState network) =   case (blocks, network) of-    ([block], "London") -> case blockTxs block of+    ([block], "London") -> case block.blockTxs of       [tx] -> fromBlockchainCase' block tx preState postState       []        -> Left NoTxs       _         -> Left TooManyTxs@@ -354,7 +351,7 @@                        -> Map Addr (EVM.Contract, Storage) -> Map Addr (EVM.Contract, Storage)                        -> Either BlockchainError Case fromBlockchainCase' block tx preState postState =-  let isCreate = isNothing (txToAddr tx) in+  let isCreate = isNothing tx.txToAddr in   case (sender 1 tx, checkTx tx block preState) of       (Nothing, _) -> Left SignatureUnverified       (_, Nothing) -> Left (if isCreate then FailedCreate else InvalidTx)@@ -362,21 +359,21 @@         (EVM.VMOpts          { vmoptContract      = EVM.initialContract theCode          , vmoptCalldata      = (cd, [])-         , vmoptValue         = Lit (txValue tx)+         , vmoptValue         = Lit tx.txValue          , vmoptAddress       = toAddr          , vmoptCaller        = litAddr origin          , vmoptStorageBase   = Concrete          , vmoptOrigin        = origin-         , vmoptGas           = txGasLimit tx - fromIntegral (txGasCost feeSchedule tx)-         , vmoptBaseFee       = blockBaseFee block-         , vmoptPriorityFee   = priorityFee tx (blockBaseFee block)-         , vmoptGaslimit      = txGasLimit tx-         , vmoptNumber        = blockNumber block-         , vmoptTimestamp     = Lit $ blockTimestamp block-         , vmoptCoinbase      = blockCoinbase block-         , vmoptPrevRandao    = blockDifficulty block+         , vmoptGas           = tx.txGasLimit  - fromIntegral (txGasCost feeSchedule tx)+         , vmoptBaseFee       = block.blockBaseFee+         , vmoptPriorityFee   = priorityFee tx block.blockBaseFee+         , vmoptGaslimit      = tx.txGasLimit+         , vmoptNumber        = block.blockNumber+         , vmoptTimestamp     = Lit block.blockTimestamp+         , vmoptCoinbase      = block.blockCoinbase+         , vmoptPrevRandao    = block.blockDifficulty          , vmoptMaxCodeSize   = 24576-         , vmoptBlockGaslimit = blockGasLimit block+         , vmoptBlockGaslimit = block.blockGasLimit          , vmoptGasprice      = effectiveGasPrice          , vmoptSchedule      = feeSchedule          , vmoptChainId       = 1@@ -387,38 +384,38 @@         checkState         postState           where-            toAddr = fromMaybe (EVM.createAddress origin senderNonce) (txToAddr tx)+            toAddr = fromMaybe (EVM.createAddress origin senderNonce) tx.txToAddr             senderNonce = view (accountAt origin . nonce) (Map.map fst preState)             feeSchedule = EVM.FeeSchedule.berlin             toCode = Map.lookup toAddr preState             theCode = if isCreate-                      then EVM.InitCode (txData tx) mempty+                      then EVM.InitCode tx.txData mempty                       else maybe (EVM.RuntimeCode (EVM.ConcreteRuntimeCode "")) (view contractcode . fst) toCode-            effectiveGasPrice = effectiveprice tx (blockBaseFee block)+            effectiveGasPrice = effectiveprice tx block.blockBaseFee             cd = if isCreate                  then mempty-                 else ConcreteBuf $ txData tx+                 else ConcreteBuf tx.txData  effectiveprice :: Transaction -> W256 -> W256 effectiveprice tx baseFee = priorityFee tx baseFee + baseFee  priorityFee :: Transaction -> W256 -> W256 priorityFee tx baseFee = let-    (txPrioMax, txMaxFee) = case txType tx of+    (txPrioMax, txMaxFee) = case tx.txType of                EIP1559Transaction ->-                 let maxPrio = fromJust $ txMaxPriorityFeeGas tx-                     maxFee = fromJust $ txMaxFeePerGas tx+                 let maxPrio = fromJust tx.txMaxPriorityFeeGas+                     maxFee = fromJust tx.txMaxFeePerGas                  in (maxPrio, maxFee)                _ ->-                 let gasPrice = fromJust $ txGasPrice tx+                 let gasPrice = fromJust tx.txGasPrice                  in (gasPrice, gasPrice)   in min txPrioMax (txMaxFee - baseFee)  maxBaseFee :: Transaction -> W256 maxBaseFee tx =-  case txType tx of-     EIP1559Transaction -> fromJust $ txMaxFeePerGas tx-     _ -> fromJust $ txGasPrice tx+  case tx.txType of+     EIP1559Transaction -> fromJust tx.txMaxFeePerGas+     _ -> fromJust tx.txGasPrice  validateTx :: Transaction -> Block -> Map Addr (EVM.Contract, Storage) -> Maybe () validateTx tx block cs = do@@ -426,9 +423,9 @@   origin        <- sender 1 tx   originBalance <- (view balance) <$> view (at origin) cs'   originNonce   <- (view nonce)   <$> view (at origin) cs'-  let gasDeposit = (effectiveprice tx (blockBaseFee block)) * (num $ txGasLimit tx)-  if gasDeposit + (txValue tx) <= originBalance-    && txNonce tx == originNonce && blockBaseFee block <= maxBaseFee tx+  let gasDeposit = (effectiveprice tx block.blockBaseFee) * (num tx.txGasLimit)+  if gasDeposit + tx.txValue <= originBalance+    && tx.txNonce == originNonce && block.blockBaseFee <= maxBaseFee tx   then Just ()   else Nothing @@ -436,9 +433,9 @@ checkTx tx block prestate = do   origin <- sender 1 tx   validateTx tx block prestate-  let isCreate   = isNothing (txToAddr tx)+  let isCreate   = isNothing tx.txToAddr       senderNonce = view (accountAt origin . nonce) (Map.map fst prestate)-      toAddr      = fromMaybe (EVM.createAddress origin senderNonce) (txToAddr tx)+      toAddr      = fromMaybe (EVM.createAddress origin senderNonce) tx.txToAddr       prevCode    = view (accountAt toAddr . contractcode) (Map.map fst prestate)       prevNonce   = view (accountAt toAddr . nonce) (Map.map fst prestate)   if isCreate && ((case prevCode of {EVM.RuntimeCode (EVM.ConcreteRuntimeCode b) -> not (BS.null b); _ -> True}) || (prevNonce /= 0))@@ -449,10 +446,10 @@ vmForCase :: Case -> EVM.VM vmForCase x =   let-    a = checkContracts x+    a = x.checkContracts     cs = Map.map fst a     st = Map.mapKeys num $ Map.map snd a-    vm = EVM.makeVm (testVmOpts x)+    vm = EVM.makeVm x.testVmOpts       & set (EVM.env . EVM.contracts) cs       & set (EVM.env . EVM.storage) (ConcreteStore st)       & set (EVM.env . EVM.origStorage) st
test/EVM/TestUtils.hs view
@@ -13,7 +13,7 @@ import System.Process (readProcess)  import EVM.Solidity-import EVM.SMT+import EVM.Solvers import EVM.Dapp import EVM.UnitTest import EVM.Fetch (RpcInfo)
test/contracts/pass/cheatCodes.sol view
@@ -10,12 +10,19 @@     function sign(uint256,bytes32) external returns (uint8,bytes32,bytes32);     function addr(uint256) external returns (address);     function ffi(string[] calldata) external returns (bytes memory);+    function prank(address) external; }  contract HasStorage {     uint slot0 = 10; } +contract Prankster {+    function prankme() public returns (address) {+        return msg.sender;+    }+}+ contract CheatCodes is DSTest {     address store = address(new HasStorage());     Hevm hevm = Hevm(HEVM_ADDRESS);@@ -85,5 +92,13 @@          (string memory output) = abi.decode(hevm.ffi(inputs), (string));         assertEq(output, "acab");+    }++    function test_prank() public {+        Prankster prankster = new Prankster();+        assertEq(prankster.prankme(), address(this));+        hevm.prank(address(0xdeadbeef));+        assertEq(prankster.prankme(), address(0xdeadbeef));+        assertEq(prankster.prankme(), address(this));     } }
test/rpc.hs view
@@ -16,6 +16,7 @@ import EVM import EVM.ABI import EVM.SMT+import EVM.Solvers import EVM.Fetch import EVM.SymExec import EVM.TestUtils
test/test.hs view
@@ -43,7 +43,7 @@ import Data.Binary.Put (runPut) import Data.Binary.Get (runGetOrFail) -import EVM hiding (Query, allowFFI)+import EVM import EVM.SymExec import EVM.ABI import EVM.Exec@@ -53,11 +53,14 @@ import EVM.Solidity import EVM.Types import EVM.Traversals+import EVM.Concrete (createAddress) import EVM.SMT hiding (one)+import EVM.Solvers import qualified EVM.Expr as Expr import qualified Data.Text as T import Data.List (isSubsequenceOf) import EVM.TestUtils+import GHC.Conc (getNumProcessors)  main :: IO () main = defaultMain tests@@ -87,6 +90,29 @@         (SLoad (Lit 0x0) (Lit 0x0) (SStore (Var "1312") (Lit 0x0) (Lit 0x0) (ConcreteStore $ Map.fromList [(0x0, Map.fromList [(0x0, 0xab)])])))         (Expr.readStorage' (Lit 0x0) (Lit 0x0)           (SStore (Lit 0xacab) (Lit 0xdead) (Lit 0x0) (SStore (Var "1312") (Lit 0x0) (Lit 0x0) (ConcreteStore $ Map.fromList [(0x0, Map.fromList [(0x0, 0xab)])]))))++    , testCase "accessStorage uses fetchedStorage" $ do+        let dummyContract =+              (initialContract (RuntimeCode (ConcreteRuntimeCode mempty)))+                { _external = True }+            vm = vmForEthrunCreation ""+            -- perform the initial access+            vm1 = execState (EVM.accessStorage 0 (Lit 0) (pure . pure ())) vm+            -- it should fetch the contract first+            vm2 = case vm1._result of+                    Just (VMFailure (Query (PleaseFetchContract _addr continue))) ->+                      execState (continue dummyContract) vm1+                    _ -> error "unexpected result"+            -- then it should fetch the slow+            vm3 = case vm2._result of+                    Just (VMFailure (Query (PleaseFetchSlot _addr _slot continue))) ->+                      execState (continue 1337) vm2+                    _ -> error "unexpected result"+            -- perform the same access as for vm1+            vm4 = execState (EVM.accessStorage 0 (Lit 0) (pure . pure ())) vm3++        -- there won't be query now as accessStorage uses fetch cache+        assertBool (show vm4._result) (isNothing vm4._result)     ]   -- These tests fuzz the simplifier by generating a random expression,   -- applying some simplification rules, and then using the smt encoding to@@ -149,6 +175,10 @@         let simplified = Expr.writeWord idx val buf             full = WriteWord idx val buf         checkEquiv simplified full+    , testProperty "arith-simplification" $ \(_ :: Int) -> ioProperty $ do+        expr <- generate . sized $ genWordArith 15+        let simplified = Expr.simplify expr+        checkEquiv expr simplified     , testProperty "readByte-equivalance" $ \(buf, idx) -> ioProperty $ do         let simplified = Expr.readByte idx buf             full = ReadByte idx buf@@ -426,7 +456,7 @@         (json, path') <- solidity' srccode         let (solc', _, _) = fromJust $ readJSON json             initCode :: ByteString-            initCode = fromJust $ solc' ^? ix (path' <> ":A") . creationCode+            initCode = (fromJust $ solc' ^? ix (path' <> ":A")).creationCode         -- add constructor arguments         assertEqual "constructor args screwed up metadata stripping" (stripBytecodeMetadata (initCode <> encodeAbiValue (AbiUInt 256 1))) (stripBytecodeMetadata initCode)     ]@@ -649,7 +679,6 @@         putStrLn "Require works as expected"      ,      testCase "ITE-with-bitwise-AND" $ do-        --- using ignore to suppress huge output        Just c <- solcRuntime "C"          [i|          contract C {@@ -670,7 +699,6 @@        putStrLn "expected counterexample found"      ,      testCase "ITE-with-bitwise-OR" $ do-        --- using ignore to suppress huge output        Just c <- solcRuntime "C"          [i|          contract C {@@ -988,6 +1016,29 @@         (_, [Qed _]) <- withSolvers Z3 1 Nothing $ \s -> checkAssert s defaultPanicCodes c (Just ("fun(uint256,uint256)", [AbiUIntType 256, AbiUIntType 256])) [] defaultVeriOpts         putStrLn "XOR works as expected"       ,+      testCase "opcode-addmod-no-overflow" $ do+        Just c <- solcRuntime "MyContract"+            [i|+            contract MyContract {+              function fun(uint8 a, uint8 b, uint8 c) external pure {+                require(a < 4);+                require(b < 4);+                require(c < 4);+                uint16 r1;+                uint16 r2;+                uint16 g2;+                assembly {+                  r1 := add(a,b)+                  r2 := mod(r1, c)+                  g2 := addmod (a, b, c)+                }+                assert (r2 == g2);+              }+            }+            |]+        (_, [Qed _]) <- withSolvers Z3 1 Nothing $ \s -> checkAssert s defaultPanicCodes c (Just ("fun(uint8,uint8,uint8)", [AbiUIntType 8, AbiUIntType 8, AbiUIntType 8])) [] defaultVeriOpts+        putStrLn "ADDMOD is fine on NON overflow values"+      ,       testCase "opcode-mulmod-no-overflow" $ do         Just c <- solcRuntime "MyContract"             [i|@@ -1589,8 +1640,7 @@           (res, [Qed _]) <- withSolvers Z3 1 Nothing $ \s -> checkAssert s defaultPanicCodes c Nothing [] defaultVeriOpts           putStrLn $ "successfully explored: " <> show (Expr.numBranches res) <> " paths"         ,-        ignoreTest $ testCase "keccak soundness" $ do-        --- using ignore to suppress huge output+        testCase "keccak soundness" $ do           Just c <- solcRuntime "C"             [i|               contract C {@@ -1625,17 +1675,26 @@               aAddr = Addr 0x35D1b3F3D7966A1DFe207aa4514C12a259A0492B           Just c <- solcRuntime "C" code'           Just a <- solcRuntime "A" code'-          (_, [Cex _]) <- withSolvers Z3 1 Nothing $ \s -> do+          (_, [Cex (_, cex)]) <- withSolvers Z3 1 Nothing $ \s -> do             let vm0 = abstractVM (Just ("call_A()", [])) [] c Nothing SymbolicS             let vm = vm0                   & set (state . callvalue) (Lit 0)                   & over (env . contracts)                        (Map.insert aAddr (initialContract (RuntimeCode (ConcreteRuntimeCode a))))-                  -- NOTE: this used to as follows, but there is no _storage field in Contract record-                  -- (Map.insert aAddr (initialContract (RuntimeCode $ ConcreteBuffer a) &-                  --                     set EVM.storage (EVM.Symbolic [] store)))             verify s defaultVeriOpts vm (Just $ checkAssertions defaultPanicCodes)-          putStrLn "found counterexample:"++          let storeCex = cex.store+              addrC = W256 $ num $ createAddress ethrunAddress 1+              addrA = W256 0x35D1b3F3D7966A1DFe207aa4514C12a259A0492B+              testCex = Map.size storeCex == 2 &&+                        case (Map.lookup addrC storeCex, Map.lookup addrA storeCex) of+                          (Just sC, Just sA) -> Map.size sC == 1 && Map.size sA == 1 &&+                            case (Map.lookup 0 sC, Map.lookup 0 sA) of+                              (Just x, Just y) -> x /= y+                              _ -> False+                          _ -> False+          assertBool "Did not find expected storage cex" testCex+          putStrLn "expected counterexample found"         ,         expectFail $ testCase "calling unique contracts (read from storage)" $ do           Just c <- solcRuntime "C"@@ -1713,6 +1772,69 @@            (_, [Qed _]) <- withSolvers Z3 1 Nothing $ \s -> checkAssert s defaultPanicCodes c (Just ("distributivity(uint256,uint256,uint256)", [AbiUIntType 256, AbiUIntType 256, AbiUIntType 256])) [] defaultVeriOpts           putStrLn "Proven"+        ,+        testCase "storage-cex-1" $ do+          Just c <- solcRuntime "C"+            [i|+            contract C {+              uint x;+              uint y;+              function fun(uint256 a) external{+                assert (x == y);+              }+            }+            |]+          (_, [(Cex (_, cex))]) <- withSolvers Z3 1 Nothing $ \s -> checkAssert s [0x01] c (Just ("fun(uint256)", [AbiUIntType 256])) [] defaultVeriOpts+          let addr =  W256 $ num $ createAddress ethrunAddress 1+              testCex = Map.size cex.store == 1 &&+                        case Map.lookup addr cex.store of+                          Just s -> Map.size s == 2 &&+                                    case (Map.lookup 0 s, Map.lookup 1 s) of+                                      (Just x, Just y) -> x /= y+                                      _ -> False+                          _ -> False+          assertBool "Did not find expected storage cex" testCex+          putStrLn "Expected counterexample found"+        ,+        testCase "storage-cex-2" $ do+          Just c <- solcRuntime "C"+            [i|+            contract C {+              uint[10] arr1;+              uint[10] arr2;+              function fun(uint256 a) external{+                assert (arr1[0] < arr2[a]);+              }+            }+            |]+          (_, [(Cex (_, cex))]) <- withSolvers Z3 1 Nothing $ \s -> checkAssert s [0x01] c (Just ("fun(uint256)", [AbiUIntType 256])) [] defaultVeriOpts+          let addr = W256 $ num $ createAddress ethrunAddress 1+              a = getVar cex "arg1"+              testCex = Map.size cex.store == 1 &&+                        case Map.lookup addr cex.store of+                          Just s -> Map.size s == 2 &&+                                    case (Map.lookup 0 s, Map.lookup (10 + a) s) of+                                      (Just x, Just y) -> x >= y+                                      _ -> False+                          _ -> False+          assertBool "Did not find expected storage cex" testCex+          putStrLn "Expected counterexample found"+        ,+        testCase "storage-cex-concrete" $ do+          Just c <- solcRuntime "C"+            [i|+            contract C {+              uint x;+              uint y;+              function fun(uint256 a) external{+                assert (x != y);+              }+            }+            |]+          (_, [Cex (_, cex)]) <- withSolvers Z3 1 Nothing $ \s -> verifyContract s c (Just ("fun(uint256)", [AbiUIntType 256])) [] defaultVeriOpts ConcreteS Nothing (Just $ checkAssertions [0x01])+          let testCex = Map.null cex.store+          assertBool "Did not find expected storage cex" testCex+          putStrLn "Expected counterexample found"  ]   , testGroup "Equivalence checking"     [@@ -1739,7 +1861,7 @@           |]         withSolvers Z3 3 Nothing $ \s -> do           a <- equivalenceCheck s aPrgm bPrgm defaultVeriOpts Nothing-          assertBool "Must have a difference" (not (null a))+          assertBool "Must have a difference" (any isCex a)       ,       testCase "eq-sol-exp-qed" $ do         Just aPrgm <- solcRuntime "C"@@ -1764,7 +1886,7 @@           |]         withSolvers Z3 3 Nothing $ \s -> do           a <- equivalenceCheck s aPrgm bPrgm defaultVeriOpts Nothing-          assertEqual "Must have no difference" [] a+          assertEqual "Must have no difference" [Qed ()] a           return ()       ,       testCase "eq-sol-exp-cex" $ do@@ -1792,70 +1914,31 @@         withSolvers Z3 3 Nothing $ \s -> do           let myVeriOpts = VeriOpts{ simp = True, debug = False, maxIter = Just 2, askSmtIters = Just 2, rpcInfo = Nothing}           a <- equivalenceCheck s aPrgm bPrgm myVeriOpts Nothing-          assertEqual "Must be different" (containsA (Cex ()) a) True+          assertEqual "Must be different" (any isCex a) True           return ()       , testCase "eq-all-yul-optimization-tests" $ do         let myVeriOpts = VeriOpts{ simp = True, debug = False, maxIter = Just 5, askSmtIters = Just 20, rpcInfo = Nothing }             ignoredTests = [-                      "controlFlowSimplifier/terminating_for_nested.yul"-                    , "controlFlowSimplifier/terminating_for_nested_reversed.yul"-                     -- unbounded loop ---                    , "commonSubexpressionEliminator/branches_for.yul"-                    , "commonSubexpressionEliminator/loop.yul"-                    , "conditionalSimplifier/clear_after_if_continue.yul"+                    "commonSubexpressionEliminator/branches_for.yul"                     , "conditionalSimplifier/no_opt_if_break_is_not_last.yul"-                    , "conditionalUnsimplifier/clear_after_if_continue.yul"                     , "conditionalUnsimplifier/no_opt_if_break_is_not_last.yul"                     , "expressionSimplifier/inside_for.yul"                     , "forLoopConditionIntoBody/cond_types.yul"                     , "forLoopConditionIntoBody/simple.yul"                     , "fullSimplify/inside_for.yul"-                    , "fullSuite/devcon_example.yul"-                    , "fullSuite/loopInvariantCodeMotion.yul"                     , "fullSuite/no_move_loop_orig.yul"-                    , "loadResolver/loop.yul"                     , "loopInvariantCodeMotion/multi.yul"-                    , "loopInvariantCodeMotion/recursive.yul"-                    , "loopInvariantCodeMotion/simple.yul"-                    , "redundantAssignEliminator/for_branch.yul"-                    , "redundantAssignEliminator/for_break.yul"-                    , "redundantAssignEliminator/for_continue.yul"-                    , "redundantAssignEliminator/for_decl_inside_break_continue.yul"-                    , "redundantAssignEliminator/for_deep_noremove.yul"                     , "redundantAssignEliminator/for_deep_simple.yul"-                    , "redundantAssignEliminator/for_multi_break.yul"-                    , "redundantAssignEliminator/for_nested.yul"-                    , "redundantAssignEliminator/for_rerun.yul"-                    , "redundantAssignEliminator/for_stmnts_after_break_continue.yul"-                    , "rematerialiser/branches_for1.yul"-                    , "rematerialiser/branches_for2.yul"-                    , "rematerialiser/for_break.yul"-                    , "rematerialiser/for_continue.yul"-                    , "rematerialiser/for_continue_2.yul"-                    , "rematerialiser/for_continue_with_assignment_in_post.yul"-                    , "rematerialiser/no_remat_in_loop.yul"-                    , "ssaTransform/for_reassign_body.yul"-                    , "ssaTransform/for_reassign_init.yul"-                    , "ssaTransform/for_reassign_post.yul"-                    , "ssaTransform/for_simple.yul"-                    , "loopInvariantCodeMotion/nonMovable.yul"-                    , "unusedAssignEliminator/for_rerun.yul"-                    , "unusedAssignEliminator/for_continue_3.yul"+                    , "unusedAssignEliminator/for_deep_noremove.yul"                     , "unusedAssignEliminator/for_deep_simple.yul"                     , "ssaTransform/for_def_in_init.yul"-                    , "rematerialiser/many_refs_small_cost_loop.yul"+                    , "loopInvariantCodeMotion/simple_state.yul"+                    , "loopInvariantCodeMotion/simple.yul"+                    , "loopInvariantCodeMotion/recursive.yul"+                    , "loopInvariantCodeMotion/no_move_staticall_returndatasize.yul"                     , "loopInvariantCodeMotion/no_move_state_loop.yul"-                    , "loopInvariantCodeMotion/dependOnVarInLoop.yul"-                    , "forLoopInitRewriter/empty_pre.yul"-                    , "loadResolver/keccak_crash.yul"-                    , "blockFlattener/for_stmt.yul" -- symb input can loop it forever-                    , "unusedAssignEliminator/for.yul" -- not infinite, just 2**256-3                     , "loopInvariantCodeMotion/no_move_state.yul" -- not infinite, but rollaround on a large int-                    , "loopInvariantCodeMotion/non-ssavar.yul" -- same as above-                    , "forLoopInitRewriter/complex_pre.yul"-                    , "rematerialiser/some_refs_small_cost_loop.yul" -- not infinite but 100 long-                    , "forLoopInitRewriter/simple.yul"                     , "loopInvariantCodeMotion/no_move_loop.yul"                      -- unexpected symbolic arg --@@ -1905,11 +1988,15 @@                     , "fullSuite/ssaReverse.yul"                     , "rematerialiser/cheap_caller.yul"                     , "rematerialiser/non_movable_instruction.yul"+                    , "rematerialiser/for_break.yul"+                    , "rematerialiser/for_continue.yul"+                    , "rematerialiser/for_continue_2.yul"                     , "ssaAndBack/multi_assign.yul"                     , "ssaAndBack/multi_assign_if.yul"                     , "ssaAndBack/multi_assign_switch.yul"                     , "ssaAndBack/simple.yul"                     , "ssaReverser/simple.yul"+                    , "loopInvariantCodeMotion/simple_storage.yul"                      -- OpMstore8                     , "loadResolver/memory_with_different_kinds_of_invalidation.yul"@@ -1924,7 +2011,6 @@                     , "commonSubexpressionEliminator/object_access.yul"                     , "expressionSplitter/object_access.yul"                     , "fullSuite/stack_compressor_msize.yul"-                    , "varNameCleaner/function_names.yul"                      -- stack too deep --                     , "fullSuite/abi2.yul"@@ -2021,20 +2107,16 @@                     , "unusedStoreEliminator/remove_before_revert.yul"                     , "unusedStoreEliminator/unknown_length2.yul"                     , "unusedStoreEliminator/unrelated_relative.yul"+                    , "fullSuite/extcodelength.yul"+                    , "unusedStoreEliminator/create_inside_function.yul"-- "trying to reset symbolic storage with writes in create"                      -- Takes too long, would timeout on most test setups.                     -- We could probably fix these by "bunching together" queries-                    , "fullSuite/clear_after_if_continue.yul"-                    , "reasoningBasedSimplifier/smod.yul"                     , "reasoningBasedSimplifier/mulmod.yul"                      -- TODO check what's wrong with these!-                    , "unusedStoreEliminator/create_inside_function.yul"-                    , "fullSimplify/not_applied_removes_non_constant_and_not_movable.yul" -- create bug?-                    , "unusedStoreEliminator/create.yul" -- create bug?-                    , "fullSuite/extcodelength.yul" -- extcodecopy bug?-                    , "loadResolver/keccak_short.yul" -- keccak bug-                    , "reasoningBasedSimplifier/signed_division.yul" -- ACTUAL bug, SDIV I think?+                    , "loadResolver/keccak_short.yul" -- ACTUAL bug -- keccak+                    , "reasoningBasedSimplifier/signed_division.yul" -- ACTUAL bug, SDIV                     ]          solcRepo <- fromMaybe (error "cannot find solidity repo") <$> (lookupEnv "HEVM_SOLIDITY_REPO")@@ -2053,9 +2135,8 @@                 False -> recursiveList ax (a:b)           recursiveList [] b = pure b         files <- recursiveList fullpaths []-        --         let filesFiltered = filter (\file -> not $ any (\filt -> Data.List.isSubsequenceOf filt file) ignoredTests) files-        --+         -- Takes one file which follows the Solidity Yul optimizer unit tests format,         -- extracts both the nonoptimized and the optimized versions, and checks equivalence.         forM_ filesFiltered (\f-> do@@ -2083,7 +2164,7 @@             filteredBSym = symbolicMem [ replaceAll "" $ x *=~[re|^//|] | x <- onlyAfter [re|^// step:|] unfiltered, not $ x =~ [re|^$|] ]           start <- getCurrentTime           putStrLn $ "Checking file: " <> f-          when (debug myVeriOpts) $ do+          when myVeriOpts.debug $ do             putStrLn "-------------Original Below-----------------"             mapM_ putStrLn unfiltered             putStrLn "------------- Filtered A + Symb below-----------------"@@ -2093,14 +2174,17 @@             putStrLn "------------- END -----------------"           Just aPrgm <- yul "" $ T.pack $ unlines filteredASym           Just bPrgm <- yul "" $ T.pack $ unlines filteredBSym-          withSolvers CVC5 6 (Just 3) $ \s -> do+          procs <- getNumProcessors+          withSolvers CVC5 (num procs) (Just 100) $ \s -> do             res <- equivalenceCheck s aPrgm bPrgm myVeriOpts Nothing             end <- getCurrentTime-            case containsA (Cex()) res of+            case any isCex res of               False -> do                 print $ "OK. Took " <> (show $ diffUTCTime end start) <> " seconds"-                let timeouts = filter (\(_, _, c) -> c == EVM.SymExec.Timeout()) res-                unless (null timeouts) $ putStrLn $ "But " <> (show $ length timeouts) <> " timeout(s) occurred"+                let timeouts = filter isTimeout res+                unless (null timeouts) $ do+                  putStrLn $ "But " <> (show $ length timeouts) <> " timeout(s) occurred"+                  error "Encountered timeouts, error"               True -> do                 putStrLn $ "Not OK: " <> show f <> " Got: " <> show res                 error "Was NOT equivalent, error"@@ -2123,7 +2207,7 @@        print res        pure $ case res of          Unsat -> True-         EVM.SMT.Unknown -> True+         EVM.Solvers.Unknown -> True          Sat _ -> False          Error _ -> False @@ -2132,7 +2216,7 @@ runSimpleVM x ins = case loadVM x of                       Nothing -> Nothing                       Just vm -> let calldata' = (ConcreteBuf ins)-                       in case runState (assign (state.calldata) calldata' >> exec) vm of+                       in case runState (assign (state . calldata) calldata' >> exec) vm of                             (VMSuccess (ConcreteBuf bs), _) -> Just bs                             _ -> Nothing @@ -2429,6 +2513,46 @@    subBuf = defaultBuf (sz `div` 10)    subStore = genStorage (sz `div` 10)    subByte = genByte (sz `div` 10)++genWordArith :: Int -> Int -> Gen (Expr EWord)+genWordArith litFreq 0 = frequency+  [ (litFreq, fmap Lit arbitrary)+  , (1, oneof [ fmap Lit arbitrary ])+  ]+genWordArith litFreq sz = frequency+  [ (litFreq, fmap Lit arbitrary)+  , (20, frequency+    [ (20, liftM2 Add  subWord subWord)+    , (20, liftM2 Sub  subWord subWord)+    , (20, liftM2 Mul  subWord subWord)+    , (20, liftM2 SEx  subWord subWord)+    , (20, liftM2 Xor  subWord subWord)+    -- these reduce variability+    , (3 , liftM2 Min  subWord subWord)+    , (3 , liftM2 Div  subWord subWord)+    , (3 , liftM2 SDiv subWord subWord)+    , (3 , liftM2 Mod  subWord subWord)+    , (3 , liftM2 SMod subWord subWord)+    , (3 , liftM2 SHL  subWord subWord)+    , (3 , liftM2 SHR  subWord subWord)+    , (3 , liftM2 SAR  subWord subWord)+    , (3 , liftM2 Or   subWord subWord)+    -- comparisons, reducing variability greatly+    , (1 , liftM2 LEq  subWord subWord)+    , (1 , liftM2 GEq  subWord subWord)+    , (1 , liftM2 SLT  subWord subWord)+    --(1, , liftM2 SGT subWord subWord+    , (1 , liftM2 Eq   subWord subWord)+    , (1 , liftM2 And  subWord subWord)+    , (1 , fmap IsZero subWord        )+    -- Expensive below+    --(1,  liftM3 AddMod subWord subWord subWord+    --(1,  liftM3 MulMod subWord subWord subWord+    --(1,  liftM2 Exp subWord litWord+    ])+  ]+ where+   subWord = genWordArith (litFreq `div` 2) (sz `div` 2)  defaultBuf :: Int -> Gen (Expr Buf) defaultBuf = genBuf (4_000_000)