{-# Language DataKinds #-}
{-# Language ImplicitParams #-}
{-# Language TemplateHaskell #-}
module EVM.Format where
import Prelude hiding (Word)
import qualified EVM
import EVM.Dapp (DappInfo (..), dappSolcByHash, dappAbiMap, showTraceLocation, dappEventMap, dappErrorMap)
import EVM.Dapp (DappContext (..), contextInfo, contextEnv)
import EVM.Concrete ( wordValue )
import EVM (VM, VMResult(..), cheatCode, traceForest, traceData, Error (..), result)
import EVM (Trace, TraceData (..), Log (..), Query (..), FrameContext (..), Storage(..))
import EVM.SymExec
import EVM.Symbolic (len, litWord)
import EVM.Types (maybeLitWord, Word (..), Whiff(..), SymWord(..), W256 (..), num, word)
import EVM.Types (Addr, Buffer(..), ByteStringS(..))
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 Control.Arrow ((>>>))
import Control.Lens (view, preview, ix, _2, to, makeLenses, over, each, (^?!))
import Data.Binary.Get (runGetOrFail)
import Data.Bits (shiftR)
import Data.ByteString (ByteString)
import Data.ByteString.Builder (byteStringHex, toLazyByteString)
import Data.ByteString.Lazy (toStrict, fromStrict)
import Data.DoubleWord (signedWord)
import Data.Foldable (toList)
import Data.Maybe (catMaybes, fromMaybe)
import Data.Text (Text, pack, unpack, intercalate)
import Data.Text (dropEnd, splitOn)
import Data.Text.Encoding (decodeUtf8, decodeUtf8')
import Data.Tree (Tree (Node))
import Data.Tree.View (showTree)
import Data.Vector (Vector)
import Data.Word (Word32)
import qualified Data.ByteString as BS
import qualified Data.Char as Char
import qualified Data.Map as Map
import qualified Data.Text as Text
data Signedness = Signed | Unsigned
deriving (Int -> Signedness -> ShowS
[Signedness] -> ShowS
Signedness -> String
(Int -> Signedness -> ShowS)
-> (Signedness -> String)
-> ([Signedness] -> ShowS)
-> Show Signedness
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Signedness] -> ShowS
$cshowList :: [Signedness] -> ShowS
show :: Signedness -> String
$cshow :: Signedness -> String
showsPrec :: Int -> Signedness -> ShowS
$cshowsPrec :: Int -> Signedness -> ShowS
Show)
showDec :: Signedness -> W256 -> Text
showDec :: Signedness -> W256 -> Text
showDec Signedness
signed (W256 Word256
w) =
let
i :: Integer
i = case Signedness
signed of
Signedness
Signed -> Int256 -> Integer
forall a b. (Integral a, Num b) => a -> b
num (Word256 -> SignedWord Word256
forall w. BinaryWord w => w -> SignedWord w
signedWord Word256
w)
Signedness
Unsigned -> Word256 -> Integer
forall a b. (Integral a, Num b) => a -> b
num Word256
w
in
if Integer
i Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Addr -> Integer
forall a b. (Integral a, Num b) => a -> b
num Addr
cheatCode
then Text
"<hevm cheat address>"
else if (Integer
i :: Integer) Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
2 Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ (Integer
256 :: Integer) Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1
then Text
"MAX_UINT256"
else String -> Text
Text.pack (Integer -> String
forall a. Show a => a -> String
show (Integer
i :: Integer))
showWordExact :: Word -> Text
showWordExact :: Word -> Text
showWordExact (C Whiff
_ (W256 Word256
w)) = Word256 -> Text
forall a. (Num a, Integral a, Show a) => a -> Text
humanizeInteger Word256
w
showWordExplanation :: W256 -> DappInfo -> Text
showWordExplanation :: W256 -> DappInfo -> Text
showWordExplanation W256
w DappInfo
_ | W256
w W256 -> W256 -> Bool
forall a. Ord a => a -> a -> Bool
> W256
0xffffffff = Signedness -> W256 -> Text
showDec Signedness
Unsigned W256
w
showWordExplanation W256
w DappInfo
dapp =
case Word32 -> Map Word32 Method -> Maybe Method
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (W256 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral W256
w) (Getting (Map Word32 Method) DappInfo (Map Word32 Method)
-> DappInfo -> Map Word32 Method
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (Map Word32 Method) DappInfo (Map Word32 Method)
Lens' DappInfo (Map Word32 Method)
dappAbiMap DappInfo
dapp) of
Maybe Method
Nothing -> Signedness -> W256 -> Text
showDec Signedness
Unsigned W256
w
Just Method
x -> Text
"keccak(\"" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Getting Text Method Text -> Method -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Text Method Text
Lens' Method Text
methodSignature Method
x Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\")"
humanizeInteger :: (Num a, Integral a, Show a) => a -> Text
humanizeInteger :: a -> Text
humanizeInteger =
Text -> [Text] -> Text
Text.intercalate Text
","
([Text] -> Text) -> (a -> [Text]) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> [Text]
forall a. [a] -> [a]
reverse
([Text] -> [Text]) -> (a -> [Text]) -> a -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map Text -> Text
Text.reverse
([Text] -> [Text]) -> (a -> [Text]) -> a -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Text -> [Text]
Text.chunksOf Int
3
(Text -> [Text]) -> (a -> Text) -> a -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
Text.reverse
(Text -> Text) -> (a -> Text) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
Text.pack
(String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show
showAbiValue :: (?context :: DappContext) => AbiValue -> Text
showAbiValue :: AbiValue -> Text
showAbiValue (AbiBytes Int
_ ByteString
bs) =
ByteString -> Text
formatBytes ByteString
bs
showAbiValue (AbiAddress Addr
addr) =
let dappinfo :: DappInfo
dappinfo = Getting DappInfo DappContext DappInfo -> DappContext -> DappInfo
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting DappInfo DappContext DappInfo
Lens' DappContext DappInfo
contextInfo ?context::DappContext
DappContext
?context
contracts :: Map Addr Contract
contracts = Getting (Map Addr Contract) DappContext (Map Addr Contract)
-> DappContext -> Map Addr Contract
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (Map Addr Contract) DappContext (Map Addr Contract)
Lens' DappContext (Map Addr Contract)
contextEnv ?context::DappContext
DappContext
?context
name :: Text
name = case (Addr -> Map Addr Contract -> Maybe Contract
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Addr
addr Map Addr Contract
contracts) of
Maybe Contract
Nothing -> Text
""
Just Contract
contract ->
let hash :: W256
hash = Getting W256 Contract W256 -> Contract -> W256
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting W256 Contract W256
Lens' Contract W256
EVM.codehash Contract
contract
solcContract :: Maybe SolcContract
solcContract = (Getting (First SolcContract) DappInfo SolcContract
-> DappInfo -> Maybe SolcContract
forall s (m :: * -> *) a.
MonadReader s m =>
Getting (First a) s a -> m (Maybe a)
preview ((Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> DappInfo -> Const (First SolcContract) DappInfo
Lens' DappInfo (Map W256 (CodeType, SolcContract))
dappSolcByHash ((Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> DappInfo -> Const (First SolcContract) DappInfo)
-> ((SolcContract -> Const (First SolcContract) SolcContract)
-> Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> Getting (First SolcContract) DappInfo SolcContract
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (Map W256 (CodeType, SolcContract))
-> Traversal'
(Map W256 (CodeType, SolcContract))
(IxValue (Map W256 (CodeType, SolcContract)))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Index (Map W256 (CodeType, SolcContract))
W256
hash (((CodeType, SolcContract)
-> Const (First SolcContract) (CodeType, SolcContract))
-> Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> ((SolcContract -> Const (First SolcContract) SolcContract)
-> (CodeType, SolcContract)
-> Const (First SolcContract) (CodeType, SolcContract))
-> (SolcContract -> Const (First SolcContract) SolcContract)
-> Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SolcContract -> Const (First SolcContract) SolcContract)
-> (CodeType, SolcContract)
-> Const (First SolcContract) (CodeType, SolcContract)
forall s t a b. Field2 s t a b => Lens s t a b
_2) DappInfo
dappinfo)
in Maybe SolcContract -> Text
maybeContractName' Maybe SolcContract
solcContract
in
Text
name Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"@" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Addr -> String
forall a. Show a => a -> String
show Addr
addr)
showAbiValue AbiValue
v = String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ AbiValue -> String
forall a. Show a => a -> String
show AbiValue
v
showAbiValues :: (?context :: DappContext) => Vector AbiValue -> Text
showAbiValues :: Vector AbiValue -> Text
showAbiValues Vector AbiValue
vs = [Text] -> Text
parenthesise ((?context::DappContext) => Vector AbiValue -> [Text]
Vector AbiValue -> [Text]
textAbiValues Vector AbiValue
vs)
textAbiValues :: (?context :: DappContext) => Vector AbiValue -> [Text]
textAbiValues :: Vector AbiValue -> [Text]
textAbiValues Vector AbiValue
vs = Vector Text -> [Text]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList ((AbiValue -> Text) -> Vector AbiValue -> Vector Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (?context::DappContext) => AbiValue -> Text
AbiValue -> Text
showAbiValue Vector AbiValue
vs)
textValues :: (?context :: DappContext) => [AbiType] -> Buffer -> [Text]
textValues :: [AbiType] -> Buffer -> [Text]
textValues [AbiType]
ts (SymbolicBuffer [SWord 8]
_) = [String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ AbiType -> String
forall a. Show a => a -> String
show AbiType
t | AbiType
t <- [AbiType]
ts]
textValues [AbiType]
ts (ConcreteBuffer ByteString
bs) =
case Get (Vector AbiValue)
-> ByteString
-> Either
(ByteString, ByteOffset, String)
(ByteString, ByteOffset, Vector AbiValue)
forall a.
Get a
-> ByteString
-> Either
(ByteString, ByteOffset, String) (ByteString, ByteOffset, a)
runGetOrFail (Int -> [AbiType] -> Get (Vector AbiValue)
getAbiSeq ([AbiType] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [AbiType]
ts) [AbiType]
ts) (ByteString -> ByteString
fromStrict ByteString
bs) of
Right (ByteString
_, ByteOffset
_, Vector AbiValue
xs) -> (?context::DappContext) => Vector AbiValue -> [Text]
Vector AbiValue -> [Text]
textAbiValues Vector AbiValue
xs
Left (ByteString
_, ByteOffset
_, String
_) -> [ByteString -> Text
formatBinary ByteString
bs]
parenthesise :: [Text] -> Text
parenthesise :: [Text] -> Text
parenthesise [Text]
ts = Text
"(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
intercalate Text
", " [Text]
ts Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
showValues :: (?context :: DappContext) => [AbiType] -> Buffer -> Text
showValues :: [AbiType] -> Buffer -> Text
showValues [AbiType]
ts Buffer
b = [Text] -> Text
parenthesise ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ (?context::DappContext) => [AbiType] -> Buffer -> [Text]
[AbiType] -> Buffer -> [Text]
textValues [AbiType]
ts Buffer
b
showValue :: (?context :: DappContext) => AbiType -> Buffer -> Text
showValue :: AbiType -> Buffer -> Text
showValue AbiType
t Buffer
b = [Text] -> Text
forall a. [a] -> a
head ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ (?context::DappContext) => [AbiType] -> Buffer -> [Text]
[AbiType] -> Buffer -> [Text]
textValues [AbiType
t] Buffer
b
showCall :: (?context :: DappContext) => [AbiType] -> Buffer -> Text
showCall :: [AbiType] -> Buffer -> Text
showCall [AbiType]
ts (SymbolicBuffer [SWord 8]
bs) = (?context::DappContext) => [AbiType] -> Buffer -> Text
[AbiType] -> Buffer -> Text
showValues [AbiType]
ts (Buffer -> Text) -> Buffer -> Text
forall a b. (a -> b) -> a -> b
$ [SWord 8] -> Buffer
SymbolicBuffer (Int -> [SWord 8] -> [SWord 8]
forall a. Int -> [a] -> [a]
drop Int
4 [SWord 8]
bs)
showCall [AbiType]
ts (ConcreteBuffer ByteString
bs) = (?context::DappContext) => [AbiType] -> Buffer -> Text
[AbiType] -> Buffer -> Text
showValues [AbiType]
ts (Buffer -> Text) -> Buffer -> Text
forall a b. (a -> b) -> a -> b
$ ByteString -> Buffer
ConcreteBuffer (Int -> ByteString -> ByteString
BS.drop Int
4 ByteString
bs)
showError :: (?context :: DappContext) => ByteString -> Text
showError :: ByteString -> Text
showError ByteString
bs =
let dappinfo :: DappInfo
dappinfo = Getting DappInfo DappContext DappInfo -> DappContext -> DappInfo
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting DappInfo DappContext DappInfo
Lens' DappContext DappInfo
contextInfo ?context::DappContext
DappContext
?context
bs4 :: ByteString
bs4 = Int -> ByteString -> ByteString
BS.take Int
4 ByteString
bs
in case W256 -> Map W256 SolError -> Maybe SolError
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (ByteString -> W256
word ByteString
bs4) (Getting (Map W256 SolError) DappInfo (Map W256 SolError)
-> DappInfo -> Map W256 SolError
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (Map W256 SolError) DappInfo (Map W256 SolError)
Lens' DappInfo (Map W256 SolError)
dappErrorMap DappInfo
dappinfo) of
Just (SolError Text
errName [AbiType]
ts) -> Text
errName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (?context::DappContext) => [AbiType] -> Buffer -> Text
[AbiType] -> Buffer -> Text
showCall [AbiType]
ts (ByteString -> Buffer
ConcreteBuffer ByteString
bs)
Maybe SolError
Nothing -> case ByteString
bs4 of
ByteString
"\b\195y\160" -> (?context::DappContext) => [AbiType] -> Buffer -> Text
[AbiType] -> Buffer -> Text
showCall [AbiType
AbiStringType] (ByteString -> Buffer
ConcreteBuffer ByteString
bs)
ByteString
_ -> ByteString -> Text
formatBinary ByteString
bs
isPrintable :: ByteString -> Bool
isPrintable :: ByteString -> Bool
isPrintable =
ByteString -> Either UnicodeException Text
decodeUtf8' (ByteString -> Either UnicodeException Text)
-> (Either UnicodeException Text -> Bool) -> ByteString -> Bool
forall k (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>>
(UnicodeException -> Bool)
-> (Text -> Bool) -> Either UnicodeException Text -> Bool
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either
(Bool -> UnicodeException -> Bool
forall a b. a -> b -> a
const Bool
False)
((Char -> Bool) -> Text -> Bool
Text.all (\Char
c-> Char -> Bool
Char.isPrint Char
c Bool -> Bool -> Bool
&& (Bool -> Bool
not (Bool -> Bool) -> (Char -> Bool) -> Char -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Bool
Char.isControl) Char
c))
formatBytes :: ByteString -> Text
formatBytes :: ByteString -> Text
formatBytes ByteString
b =
let (ByteString
s, ByteString
_) = (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
BS.spanEnd (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0) ByteString
b
in
if ByteString -> Bool
isPrintable ByteString
s
then ByteString -> Text
formatBString ByteString
s
else ByteString -> Text
formatBinary ByteString
b
formatSBytes :: Buffer -> Text
formatSBytes :: Buffer -> Text
formatSBytes (SymbolicBuffer [SWord 8]
b) = Text
"<" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack (Int -> String
forall a. Show a => a -> String
show ([SWord 8] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [SWord 8]
b)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" symbolic bytes>"
formatSBytes (ConcreteBuffer ByteString
b) = ByteString -> Text
formatBytes ByteString
b
formatBString :: ByteString -> Text
formatBString :: ByteString -> Text
formatBString ByteString
b = [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat [ Text
"«", (Char -> Bool) -> Text -> Text
Text.dropAround (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
==Char
'"') (String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ ByteString -> String
formatString ByteString
b), Text
"»" ]
formatSString :: Buffer -> Text
formatSString :: Buffer -> Text
formatSString (SymbolicBuffer [SWord 8]
bs) = Text
"<" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack (Int -> String
forall a. Show a => a -> String
show ([SWord 8] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [SWord 8]
bs)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" symbolic bytes (string)>"
formatSString (ConcreteBuffer ByteString
bs) = String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ ByteString -> String
formatString ByteString
bs
formatBinary :: ByteString -> Text
formatBinary :: ByteString -> Text
formatBinary =
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
(<>) Text
"0x" (Text -> Text) -> (ByteString -> Text) -> ByteString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
decodeUtf8 (ByteString -> Text)
-> (ByteString -> ByteString) -> ByteString -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
toStrict (ByteString -> ByteString)
-> (ByteString -> ByteString) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> ByteString
toLazyByteString (Builder -> ByteString)
-> (ByteString -> Builder) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Builder
byteStringHex
formatSBinary :: Buffer -> Text
formatSBinary :: Buffer -> Text
formatSBinary (SymbolicBuffer [SWord 8]
bs) = Text
"<" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack (Int -> String
forall a. Show a => a -> String
show ([SWord 8] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [SWord 8]
bs)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" symbolic bytes>"
formatSBinary (ConcreteBuffer ByteString
bs) = ByteString -> Text
formatBinary ByteString
bs
showTraceTree :: DappInfo -> VM -> Text
showTraceTree :: DappInfo -> VM -> Text
showTraceTree DappInfo
dapp VM
vm =
let forest :: Forest Trace
forest = VM -> Forest Trace
traceForest VM
vm
traces :: [Tree String]
traces = (Tree Trace -> Tree String) -> Forest Trace -> [Tree String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Trace -> String) -> Tree Trace -> Tree String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text -> String
unpack (Text -> String) -> (Trace -> Text) -> Trace -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DappInfo -> VM -> Trace -> Text
showTrace DappInfo
dapp VM
vm)) Forest Trace
forest
in String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ (Tree String -> String) -> [Tree String] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Tree String -> String
showTree [Tree String]
traces
unindexed :: [(Text, AbiType, Indexed)] -> [AbiType]
unindexed :: [(Text, AbiType, Indexed)] -> [AbiType]
unindexed [(Text, AbiType, Indexed)]
ts = [AbiType
t | (Text
_, AbiType
t, Indexed
NotIndexed) <- [(Text, AbiType, Indexed)]
ts]
showTrace :: DappInfo -> VM -> Trace -> Text
showTrace :: DappInfo -> VM -> Trace -> Text
showTrace DappInfo
dapp VM
vm Trace
trace =
let ?context = DappContext { _contextInfo = dapp, _contextEnv = vm ^?! EVM.env . EVM.contracts }
in let
pos :: Text
pos =
case DappInfo -> Trace -> Either Text Text
showTraceLocation DappInfo
dapp Trace
trace of
Left Text
x -> Text
" \x1b[1m" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
x Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\x1b[0m"
Right Text
x -> Text
" \x1b[1m(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
x Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")\x1b[0m"
fullAbiMap :: Map Word32 Method
fullAbiMap = Getting (Map Word32 Method) DappInfo (Map Word32 Method)
-> DappInfo -> Map Word32 Method
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (Map Word32 Method) DappInfo (Map Word32 Method)
Lens' DappInfo (Map Word32 Method)
dappAbiMap DappInfo
dapp
in case Getting TraceData Trace TraceData -> Trace -> TraceData
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting TraceData Trace TraceData
Lens' Trace TraceData
traceData Trace
trace of
EventTrace (Log Addr
_ Buffer
bytes [SymWord]
topics) ->
let logn :: Text
logn = [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
[ Text
"\x1b[36m"
, Text
"log" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (String -> Text
pack (Int -> String
forall a. Show a => a -> String
show ([SymWord] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [SymWord]
topics)))
, [Text] -> Text
parenthesise (((SymWord -> Text) -> [SymWord] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (String -> Text
pack (String -> Text) -> (SymWord -> String) -> SymWord -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SymWord -> String
forall a. Show a => a -> String
show) [SymWord]
topics) [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Buffer -> Text
formatSBinary Buffer
bytes])
, Text
"\x1b[0m"
] Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pos
knownTopic :: Text -> [(Text, AbiType, Indexed)] -> Text
knownTopic Text
name [(Text, AbiType, Indexed)]
types = [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
[ Text
"\x1b[36m"
, Text
name
, (?context::DappContext) => [AbiType] -> Buffer -> Text
[AbiType] -> Buffer -> Text
showValues ([(Text, AbiType, Indexed)] -> [AbiType]
unindexed [(Text, AbiType, Indexed)]
types) Buffer
bytes
, Text
"\x1b[0m"
] Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pos
lognote :: Text -> Text -> Text
lognote Text
sig Text
usr = [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat
[ Text
"\x1b[36m"
, Text
"LogNote"
, [Text] -> Text
parenthesise [Text
sig, Text
usr, Text
"..."]
, Text
"\x1b[0m"
] Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pos
in case [SymWord]
topics of
[] ->
Text
logn
(SymWord
t1:[SymWord]
_) ->
case SymWord -> Maybe Word
maybeLitWord SymWord
t1 of
Just Word
topic ->
case W256 -> Map W256 Event -> Maybe Event
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (Word -> W256
wordValue Word
topic) (Getting (Map W256 Event) DappInfo (Map W256 Event)
-> DappInfo -> Map W256 Event
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (Map W256 Event) DappInfo (Map W256 Event)
Lens' DappInfo (Map W256 Event)
dappEventMap DappInfo
dapp) of
Just (Event Text
name Anonymity
_ [(Text, AbiType, Indexed)]
types) ->
Text -> [(Text, AbiType, Indexed)] -> Text
knownTopic Text
name [(Text, AbiType, Indexed)]
types
Maybe Event
Nothing ->
case [SymWord]
topics of
[SymWord
_, SymWord
t2, SymWord
_, SymWord
_] ->
let
sig :: Word32
sig = W256 -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (W256 -> Word32) -> W256 -> Word32
forall a b. (a -> b) -> a -> b
$ W256 -> Int -> W256
forall a. Bits a => a -> Int -> a
shiftR (Word -> W256
wordValue Word
topic) Int
224 :: Word32
usr :: Text
usr = case SymWord -> Maybe Word
maybeLitWord SymWord
t2 of
Just Word
w ->
String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Addr -> String
forall a. Show a => a -> String
show (Addr -> String) -> Addr -> String
forall a b. (a -> b) -> a -> b
$ (Word -> Addr
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
w :: Addr)
Maybe Word
Nothing ->
Text
"<symbolic>"
in
case Word32 -> Map Word32 Method -> Maybe Method
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Word32
sig (Getting (Map Word32 Method) DappInfo (Map Word32 Method)
-> DappInfo -> Map Word32 Method
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (Map Word32 Method) DappInfo (Map Word32 Method)
Lens' DappInfo (Map Word32 Method)
dappAbiMap DappInfo
dapp) of
Just Method
m ->
Text -> Text -> Text
lognote (Getting Text Method Text -> Method -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Text Method Text
Lens' Method Text
methodSignature Method
m) Text
usr
Maybe Method
Nothing ->
Text
logn
[SymWord]
_ ->
Text
logn
Maybe Word
Nothing ->
Text
logn
QueryTrace Query
q ->
case Query
q of
PleaseFetchContract Addr
addr StorageModel
_ Contract -> EVM ()
_ ->
Text
"fetch contract " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack (Addr -> String
forall a. Show a => a -> String
show Addr
addr) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pos
PleaseFetchSlot Addr
addr Word
slot Word -> EVM ()
_ ->
Text
"fetch storage slot " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack (Word -> String
forall a. Show a => a -> String
show Word
slot) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" from " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack (Addr -> String
forall a. Show a => a -> String
show Addr
addr) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pos
PleaseAskSMT {} ->
Text
"ask smt" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pos
PleaseMakeUnique {} ->
Text
"make unique value" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pos
PleaseDoFFI [String]
cmd ByteString -> EVM ()
_ ->
Text
"execute ffi " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack ([String] -> String
forall a. Show a => a -> String
show [String]
cmd) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pos
ErrorTrace Error
e ->
case Error
e of
Revert ByteString
out ->
Text
"\x1b[91merror\x1b[0m " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"Revert " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (?context::DappContext) => ByteString -> Text
ByteString -> Text
showError ByteString
out Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pos
Error
_ ->
Text
"\x1b[91merror\x1b[0m " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack (Error -> String
forall a. Show a => a -> String
show Error
e) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pos
ReturnTrace Buffer
out (CallContext Addr
_ Addr
_ Word
_ Word
_ W256
_ (Just Word
abi) Buffer
_ Map Addr Contract
_ SubState
_) ->
Text
"← " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
case Word32 -> Map Word32 Method -> Maybe Method
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (Word -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
abi) Map Word32 Method
fullAbiMap of
Just Method
m ->
case [(Text, AbiType)] -> ([Text], [AbiType])
forall a b. [(a, b)] -> ([a], [b])
unzip (Getting [(Text, AbiType)] Method [(Text, AbiType)]
-> Method -> [(Text, AbiType)]
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting [(Text, AbiType)] Method [(Text, AbiType)]
Lens' Method [(Text, AbiType)]
methodOutput Method
m) of
([], []) ->
Buffer -> Text
formatSBinary Buffer
out
([Text]
_, [AbiType]
ts) ->
(?context::DappContext) => [AbiType] -> Buffer -> Text
[AbiType] -> Buffer -> Text
showValues [AbiType]
ts Buffer
out
Maybe Method
Nothing ->
Buffer -> Text
formatSBinary Buffer
out
ReturnTrace Buffer
out (CallContext {}) ->
Text
"← " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Buffer -> Text
formatSBinary Buffer
out
ReturnTrace Buffer
out (CreationContext {}) ->
Text
"← " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack (Int -> String
forall a. Show a => a -> String
show (Buffer -> Int
len Buffer
out)) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" bytes of code"
EntryTrace Text
t ->
Text
t
FrameTrace (CreationContext Addr
addr W256
hash Map Addr Contract
_ SubState
_ ) ->
Text
"create "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Maybe SolcContract -> Text
maybeContractName (Getting (First SolcContract) DappInfo SolcContract
-> DappInfo -> Maybe SolcContract
forall s (m :: * -> *) a.
MonadReader s m =>
Getting (First a) s a -> m (Maybe a)
preview ((Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> DappInfo -> Const (First SolcContract) DappInfo
Lens' DappInfo (Map W256 (CodeType, SolcContract))
dappSolcByHash ((Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> DappInfo -> Const (First SolcContract) DappInfo)
-> ((SolcContract -> Const (First SolcContract) SolcContract)
-> Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> Getting (First SolcContract) DappInfo SolcContract
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (Map W256 (CodeType, SolcContract))
-> Traversal'
(Map W256 (CodeType, SolcContract))
(IxValue (Map W256 (CodeType, SolcContract)))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Index (Map W256 (CodeType, SolcContract))
W256
hash (((CodeType, SolcContract)
-> Const (First SolcContract) (CodeType, SolcContract))
-> Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> ((SolcContract -> Const (First SolcContract) SolcContract)
-> (CodeType, SolcContract)
-> Const (First SolcContract) (CodeType, SolcContract))
-> (SolcContract -> Const (First SolcContract) SolcContract)
-> Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SolcContract -> Const (First SolcContract) SolcContract)
-> (CodeType, SolcContract)
-> Const (First SolcContract) (CodeType, SolcContract)
forall s t a b. Field2 s t a b => Lens s t a b
_2) DappInfo
dapp)
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"@" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack (Addr -> String
forall a. Show a => a -> String
show Addr
addr)
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pos
FrameTrace (CallContext Addr
target Addr
context Word
_ Word
_ W256
hash Maybe Word
abi Buffer
calldata Map Addr Contract
_ SubState
_) ->
let calltype :: Text
calltype = if Addr
target Addr -> Addr -> Bool
forall a. Eq a => a -> a -> Bool
== Addr
context
then Text
"call "
else Text
"delegatecall "
in case Getting (First SolcContract) DappInfo SolcContract
-> DappInfo -> Maybe SolcContract
forall s (m :: * -> *) a.
MonadReader s m =>
Getting (First a) s a -> m (Maybe a)
preview ((Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> DappInfo -> Const (First SolcContract) DappInfo
Lens' DappInfo (Map W256 (CodeType, SolcContract))
dappSolcByHash ((Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> DappInfo -> Const (First SolcContract) DappInfo)
-> ((SolcContract -> Const (First SolcContract) SolcContract)
-> Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> Getting (First SolcContract) DappInfo SolcContract
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (Map W256 (CodeType, SolcContract))
-> Traversal'
(Map W256 (CodeType, SolcContract))
(IxValue (Map W256 (CodeType, SolcContract)))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Index (Map W256 (CodeType, SolcContract))
W256
hash (((CodeType, SolcContract)
-> Const (First SolcContract) (CodeType, SolcContract))
-> Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> ((SolcContract -> Const (First SolcContract) SolcContract)
-> (CodeType, SolcContract)
-> Const (First SolcContract) (CodeType, SolcContract))
-> (SolcContract -> Const (First SolcContract) SolcContract)
-> Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SolcContract -> Const (First SolcContract) SolcContract)
-> (CodeType, SolcContract)
-> Const (First SolcContract) (CodeType, SolcContract)
forall s t a b. Field2 s t a b => Lens s t a b
_2) DappInfo
dapp of
Maybe SolcContract
Nothing ->
Text
calltype
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack (Addr -> String
forall a. Show a => a -> String
show Addr
target)
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
pack String
"::"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> case Word32 -> Map Word32 Method -> Maybe Method
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (Word -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word -> Maybe Word -> Word
forall a. a -> Maybe a -> a
fromMaybe Word
0x00 Maybe Word
abi)) Map Word32 Method
fullAbiMap of
Just Method
m ->
Text
"\x1b[1m"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Getting Text Method Text -> Method -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Text Method Text
Lens' Method Text
methodName Method
m
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\x1b[0m"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> (?context::DappContext) => [AbiType] -> Buffer -> Text
[AbiType] -> Buffer -> Text
showCall ([Maybe AbiType] -> [AbiType]
forall a. [Maybe a] -> [a]
catMaybes (Text -> [Maybe AbiType]
getAbiTypes (Getting Text Method Text -> Method -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Text Method Text
Lens' Method Text
methodSignature Method
m))) Buffer
calldata
Maybe Method
Nothing ->
Buffer -> Text
formatSBinary Buffer
calldata
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pos
Just SolcContract
solc ->
Text
calltype
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\x1b[1m"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Getting Text SolcContract Text -> SolcContract -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (Getting Text SolcContract Text
Lens' SolcContract Text
contractName Getting Text SolcContract Text
-> ((Text -> Const Text Text) -> Text -> Const Text Text)
-> Getting Text SolcContract Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text)
-> (Text -> Const Text Text) -> Text -> Const Text Text
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to Text -> Text
contractNamePart) SolcContract
solc
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"::"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> (Word -> Text) -> Maybe Word -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"[fallback function]"
(Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
"[unknown method]" (Maybe Text -> Text) -> (Word -> Maybe Text) -> Word -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SolcContract -> Word -> Maybe Text
maybeAbiName SolcContract
solc)
Maybe Word
abi
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> ([Maybe AbiType] -> Text) -> Maybe [Maybe AbiType] -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Text
"(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Buffer -> Text
formatSBinary Buffer
calldata Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")")
(\[Maybe AbiType]
x -> (?context::DappContext) => [AbiType] -> Buffer -> Text
[AbiType] -> Buffer -> Text
showCall ([Maybe AbiType] -> [AbiType]
forall a. [Maybe a] -> [a]
catMaybes [Maybe AbiType]
x) Buffer
calldata)
(Maybe Word
abi Maybe Word
-> (Word -> Maybe [Maybe AbiType]) -> Maybe [Maybe AbiType]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Text -> [Maybe AbiType]) -> Maybe Text -> Maybe [Maybe AbiType]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> [Maybe AbiType]
getAbiTypes (Maybe Text -> Maybe [Maybe AbiType])
-> (Word -> Maybe Text) -> Word -> Maybe [Maybe AbiType]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SolcContract -> Word -> Maybe Text
maybeAbiName SolcContract
solc)
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\x1b[0m"
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
pos
getAbiTypes :: Text -> [Maybe AbiType]
getAbiTypes :: Text -> [Maybe AbiType]
getAbiTypes Text
abi = (Text -> Maybe AbiType) -> [Text] -> [Maybe AbiType]
forall a b. (a -> b) -> [a] -> [b]
map (Vector AbiType -> Text -> Maybe AbiType
parseTypeName Vector AbiType
forall a. Monoid a => a
mempty) [Text]
types
where
types :: [Text]
types =
(Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter (Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Text
"") ([Text] -> [Text]) -> [Text] -> [Text]
forall a b. (a -> b) -> a -> b
$
Text -> Text -> [Text]
splitOn Text
"," (Int -> Text -> Text
dropEnd Int
1 ([Text] -> Text
forall a. [a] -> a
last (Text -> Text -> [Text]
splitOn Text
"(" Text
abi)))
maybeContractName :: Maybe SolcContract -> Text
maybeContractName :: Maybe SolcContract -> Text
maybeContractName =
Text -> (SolcContract -> Text) -> Maybe SolcContract -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"<unknown contract>" (Getting Text SolcContract Text -> SolcContract -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (Getting Text SolcContract Text
Lens' SolcContract Text
contractName Getting Text SolcContract Text
-> ((Text -> Const Text Text) -> Text -> Const Text Text)
-> Getting Text SolcContract Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text)
-> (Text -> Const Text Text) -> Text -> Const Text Text
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to Text -> Text
contractNamePart))
maybeContractName' :: Maybe SolcContract -> Text
maybeContractName' :: Maybe SolcContract -> Text
maybeContractName' =
Text -> (SolcContract -> Text) -> Maybe SolcContract -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
"" (Getting Text SolcContract Text -> SolcContract -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (Getting Text SolcContract Text
Lens' SolcContract Text
contractName Getting Text SolcContract Text
-> ((Text -> Const Text Text) -> Text -> Const Text Text)
-> Getting Text SolcContract Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text)
-> (Text -> Const Text Text) -> Text -> Const Text Text
forall (p :: * -> * -> *) (f :: * -> *) s a.
(Profunctor p, Contravariant f) =>
(s -> a) -> Optic' p f s a
to Text -> Text
contractNamePart))
maybeAbiName :: SolcContract -> Word -> Maybe Text
maybeAbiName :: SolcContract -> Word -> Maybe Text
maybeAbiName SolcContract
solc Word
abi = Getting (First Text) SolcContract Text
-> SolcContract -> Maybe Text
forall s (m :: * -> *) a.
MonadReader s m =>
Getting (First a) s a -> m (Maybe a)
preview ((Map Word32 Method -> Const (First Text) (Map Word32 Method))
-> SolcContract -> Const (First Text) SolcContract
Lens' SolcContract (Map Word32 Method)
abiMap ((Map Word32 Method -> Const (First Text) (Map Word32 Method))
-> SolcContract -> Const (First Text) SolcContract)
-> ((Text -> Const (First Text) Text)
-> Map Word32 Method -> Const (First Text) (Map Word32 Method))
-> Getting (First Text) SolcContract Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (Map Word32 Method)
-> Traversal' (Map Word32 Method) (IxValue (Map Word32 Method))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix (Word -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word
abi) ((Method -> Const (First Text) Method)
-> Map Word32 Method -> Const (First Text) (Map Word32 Method))
-> ((Text -> Const (First Text) Text)
-> Method -> Const (First Text) Method)
-> (Text -> Const (First Text) Text)
-> Map Word32 Method
-> Const (First Text) (Map Word32 Method)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Const (First Text) Text)
-> Method -> Const (First Text) Method
Lens' Method Text
methodSignature) SolcContract
solc
contractNamePart :: Text -> Text
contractNamePart :: Text -> Text
contractNamePart Text
x = (Char -> Bool) -> Text -> [Text]
Text.split (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
':') Text
x [Text] -> Int -> Text
forall a. [a] -> Int -> a
!! Int
1
contractPathPart :: Text -> Text
contractPathPart :: Text -> Text
contractPathPart Text
x = (Char -> Bool) -> Text -> [Text]
Text.split (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
':') Text
x [Text] -> Int -> Text
forall a. [a] -> Int -> a
!! Int
0
prettyvmresult :: (?context :: DappContext) => VMResult -> String
prettyvmresult :: VMResult -> String
prettyvmresult (EVM.VMFailure (EVM.Revert ByteString
"")) = String
"Revert"
prettyvmresult (EVM.VMFailure (EVM.Revert ByteString
msg)) = String
"Revert" String -> ShowS
forall a. [a] -> [a] -> [a]
++ (Text -> String
unpack (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ (?context::DappContext) => ByteString -> Text
ByteString -> Text
showError ByteString
msg)
prettyvmresult (EVM.VMFailure (EVM.UnrecognizedOpcode Word8
254)) = String
"Assertion violation"
prettyvmresult (EVM.VMFailure Error
err) = String
"Failed: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Error -> String
forall a. Show a => a -> String
show Error
err
prettyvmresult (EVM.VMSuccess (ConcreteBuffer ByteString
msg)) =
if ByteString -> Bool
BS.null ByteString
msg
then String
"Stop"
else String
"Return: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ByteStringS -> String
forall a. Show a => a -> String
show (ByteString -> ByteStringS
ByteStringS ByteString
msg)
prettyvmresult (EVM.VMSuccess (SymbolicBuffer [SWord 8]
msg)) =
String
"Return: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show ([SWord 8] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [SWord 8]
msg) String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" symbolic bytes"
currentSolc :: DappInfo -> VM -> Maybe SolcContract
currentSolc :: DappInfo -> VM -> Maybe SolcContract
currentSolc DappInfo
dapp VM
vm =
let
this :: Contract
this = VM
vm VM -> Getting (Endo Contract) VM Contract -> Contract
forall s a. HasCallStack => s -> Getting (Endo a) s a -> a
^?! (Env -> Const (Endo Contract) Env)
-> VM -> Const (Endo Contract) VM
Lens' VM Env
EVM.env ((Env -> Const (Endo Contract) Env)
-> VM -> Const (Endo Contract) VM)
-> ((Contract -> Const (Endo Contract) Contract)
-> Env -> Const (Endo Contract) Env)
-> Getting (Endo Contract) VM Contract
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map Addr Contract -> Const (Endo Contract) (Map Addr Contract))
-> Env -> Const (Endo Contract) Env
Lens' Env (Map Addr Contract)
EVM.contracts ((Map Addr Contract -> Const (Endo Contract) (Map Addr Contract))
-> Env -> Const (Endo Contract) Env)
-> ((Contract -> Const (Endo Contract) Contract)
-> Map Addr Contract -> Const (Endo Contract) (Map Addr Contract))
-> (Contract -> Const (Endo Contract) Contract)
-> Env
-> Const (Endo Contract) Env
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (Map Addr Contract)
-> Traversal' (Map Addr Contract) (IxValue (Map Addr Contract))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix (Getting Addr VM Addr -> VM -> Addr
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((FrameState -> Const Addr FrameState) -> VM -> Const Addr VM
Lens' VM FrameState
EVM.state ((FrameState -> Const Addr FrameState) -> VM -> Const Addr VM)
-> ((Addr -> Const Addr Addr)
-> FrameState -> Const Addr FrameState)
-> Getting Addr VM Addr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Addr -> Const Addr Addr) -> FrameState -> Const Addr FrameState
Lens' FrameState Addr
EVM.contract) VM
vm)
h :: W256
h = Getting W256 Contract W256 -> Contract -> W256
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting W256 Contract W256
Lens' Contract W256
EVM.codehash Contract
this
in
Getting (First SolcContract) DappInfo SolcContract
-> DappInfo -> Maybe SolcContract
forall s (m :: * -> *) a.
MonadReader s m =>
Getting (First a) s a -> m (Maybe a)
preview ((Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> DappInfo -> Const (First SolcContract) DappInfo
Lens' DappInfo (Map W256 (CodeType, SolcContract))
dappSolcByHash ((Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> DappInfo -> Const (First SolcContract) DappInfo)
-> ((SolcContract -> Const (First SolcContract) SolcContract)
-> Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> Getting (First SolcContract) DappInfo SolcContract
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index (Map W256 (CodeType, SolcContract))
-> Traversal'
(Map W256 (CodeType, SolcContract))
(IxValue (Map W256 (CodeType, SolcContract)))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Index (Map W256 (CodeType, SolcContract))
W256
h (((CodeType, SolcContract)
-> Const (First SolcContract) (CodeType, SolcContract))
-> Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract)))
-> ((SolcContract -> Const (First SolcContract) SolcContract)
-> (CodeType, SolcContract)
-> Const (First SolcContract) (CodeType, SolcContract))
-> (SolcContract -> Const (First SolcContract) SolcContract)
-> Map W256 (CodeType, SolcContract)
-> Const (First SolcContract) (Map W256 (CodeType, SolcContract))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SolcContract -> Const (First SolcContract) SolcContract)
-> (CodeType, SolcContract)
-> Const (First SolcContract) (CodeType, SolcContract)
forall s t a b. Field2 s t a b => Lens s t a b
_2) DappInfo
dapp
data TreeLine = TreeLine {
TreeLine -> String
_indent :: String,
TreeLine -> String
_content :: String
}
makeLenses ''TreeLine
showTreeIndentSymbol :: Bool
-> Bool
-> String
showTreeIndentSymbol :: Bool -> Bool -> String
showTreeIndentSymbol Bool
True Bool
True = String
"\x2514"
showTreeIndentSymbol Bool
False Bool
True = String
"\x251c"
showTreeIndentSymbol Bool
True Bool
False = String
" "
showTreeIndentSymbol Bool
False Bool
False = String
"\x2502"
flattenTree :: Int ->
Int ->
Tree [String] ->
[TreeLine]
flattenTree :: Int -> Int -> Tree [String] -> [TreeLine]
flattenTree Int
_ Int
_ (Node [] Forest [String]
_) = []
flattenTree Int
totalCases Int
i (Node (String
x:[String]
xs) Forest [String]
cs) = let
isLastCase :: Bool
isLastCase = Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1 Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
totalCases
indenthead :: String
indenthead = Bool -> Bool -> String
showTreeIndentSymbol Bool
isLastCase Bool
True String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
i String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" "
indentchild :: String
indentchild = Bool -> Bool -> String
showTreeIndentSymbol Bool
isLastCase Bool
False String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" "
in String -> String -> TreeLine
TreeLine String
indenthead String
x
TreeLine -> [TreeLine] -> [TreeLine]
forall a. a -> [a] -> [a]
: ((String -> String -> TreeLine
TreeLine String
indentchild (String -> TreeLine) -> [String] -> [TreeLine]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [String]
xs) [TreeLine] -> [TreeLine] -> [TreeLine]
forall a. [a] -> [a] -> [a]
++ ASetter [TreeLine] [TreeLine] String String
-> ShowS -> [TreeLine] -> [TreeLine]
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
over ((TreeLine -> Identity TreeLine)
-> [TreeLine] -> Identity [TreeLine]
forall s t a b. Each s t a b => Traversal s t a b
each ((TreeLine -> Identity TreeLine)
-> [TreeLine] -> Identity [TreeLine])
-> ((String -> Identity String) -> TreeLine -> Identity TreeLine)
-> ASetter [TreeLine] [TreeLine] String String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Identity String) -> TreeLine -> Identity TreeLine
Lens' TreeLine String
indent) (String -> ShowS
forall a. Semigroup a => a -> a -> a
(<>) String
indentchild) (Forest [String] -> [TreeLine]
flattenForest Forest [String]
cs))
flattenForest :: [Tree [String]] -> [TreeLine]
flattenForest :: Forest [String] -> [TreeLine]
flattenForest Forest [String]
forest = [[TreeLine]] -> [TreeLine]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[TreeLine]] -> [TreeLine]) -> [[TreeLine]] -> [TreeLine]
forall a b. (a -> b) -> a -> b
$ (Int -> Tree [String] -> [TreeLine])
-> [Int] -> Forest [String] -> [[TreeLine]]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (Int -> Int -> Tree [String] -> [TreeLine]
flattenTree (Forest [String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length Forest [String]
forest)) [Int
0..] Forest [String]
forest
leftpad :: Int -> String -> String
leftpad :: Int -> ShowS
leftpad Int
n = String -> ShowS
forall a. Semigroup a => a -> a -> a
(<>) (String -> ShowS) -> String -> ShowS
forall a b. (a -> b) -> a -> b
$ Int -> Char -> String
forall a. Int -> a -> [a]
replicate Int
n Char
' '
showTree' :: Tree [String] -> String
showTree' :: Tree [String] -> String
showTree' (Node [String]
s []) = [String] -> String
unlines [String]
s
showTree' (Node [String]
_ Forest [String]
children) =
let
treeLines :: [TreeLine]
treeLines = Forest [String] -> [TreeLine]
flattenForest Forest [String]
children
maxIndent :: Int
maxIndent = Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (String -> Int) -> (TreeLine -> String) -> TreeLine -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TreeLine -> String
_indent (TreeLine -> Int) -> [TreeLine] -> [Int]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [TreeLine]
treeLines)
showTreeLine :: TreeLine -> String
showTreeLine (TreeLine String
colIndent String
colContent) =
let indentSize :: Int
indentSize = Int
maxIndent Int -> Int -> Int
forall a. Num a => a -> a -> a
- String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
colIndent
in String
colIndent String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> ShowS
leftpad Int
indentSize String
colContent
in [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ TreeLine -> String
showTreeLine (TreeLine -> String) -> [TreeLine] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [TreeLine]
treeLines
showStorage :: [(SymWord, SymWord)] -> [String]
showStorage :: [(SymWord, SymWord)] -> [String]
showStorage = ((SymWord, SymWord) -> String) -> [(SymWord, SymWord)] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (\(SymWord
k, SymWord
v) -> SymWord -> String
forall a. Show a => a -> String
show SymWord
k String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
" => " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> SymWord -> String
forall a. Show a => a -> String
show SymWord
v)
showLeafInfo :: DappInfo -> BranchInfo -> [String]
showLeafInfo :: DappInfo -> BranchInfo -> [String]
showLeafInfo DappInfo
srcInfo (BranchInfo VM
vm Maybe Whiff
_) = let
?context = DappContext { _contextInfo = srcInfo, _contextEnv = vm ^?! EVM.env . EVM.contracts }
in let
self :: Addr
self = Getting Addr VM Addr -> VM -> Addr
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((FrameState -> Const Addr FrameState) -> VM -> Const Addr VM
Lens' VM FrameState
EVM.state ((FrameState -> Const Addr FrameState) -> VM -> Const Addr VM)
-> ((Addr -> Const Addr Addr)
-> FrameState -> Const Addr FrameState)
-> Getting Addr VM Addr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Addr -> Const Addr Addr) -> FrameState -> Const Addr FrameState
Lens' FrameState Addr
EVM.contract) VM
vm
updates :: [(SymWord, SymWord)]
updates = case Getting (Map Addr Contract) VM (Map Addr Contract)
-> VM -> Map Addr Contract
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view ((Env -> Const (Map Addr Contract) Env)
-> VM -> Const (Map Addr Contract) VM
Lens' VM Env
EVM.env ((Env -> Const (Map Addr Contract) Env)
-> VM -> Const (Map Addr Contract) VM)
-> ((Map Addr Contract
-> Const (Map Addr Contract) (Map Addr Contract))
-> Env -> Const (Map Addr Contract) Env)
-> Getting (Map Addr Contract) VM (Map Addr Contract)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map Addr Contract
-> Const (Map Addr Contract) (Map Addr Contract))
-> Env -> Const (Map Addr Contract) Env
Lens' Env (Map Addr Contract)
EVM.contracts) VM
vm Map Addr Contract
-> Getting (Endo Storage) (Map Addr Contract) Storage -> Storage
forall s a. HasCallStack => s -> Getting (Endo a) s a -> a
^?! Index (Map Addr Contract)
-> Traversal' (Map Addr Contract) (IxValue (Map Addr Contract))
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Index (Map Addr Contract)
Addr
self ((Contract -> Const (Endo Storage) Contract)
-> Map Addr Contract -> Const (Endo Storage) (Map Addr Contract))
-> ((Storage -> Const (Endo Storage) Storage)
-> Contract -> Const (Endo Storage) Contract)
-> Getting (Endo Storage) (Map Addr Contract) Storage
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Storage -> Const (Endo Storage) Storage)
-> Contract -> Const (Endo Storage) Contract
Lens' Contract Storage
EVM.storage of
Symbolic [(SymWord, SymWord)]
v SArray (WordN 256) (WordN 256)
_ -> [(SymWord, SymWord)]
v
Concrete Map Word SymWord
x -> [(Word -> SymWord
litWord Word
k,SymWord
v) | (Word
k, SymWord
v) <- Map Word SymWord -> [(Word, SymWord)]
forall k a. Map k a -> [(k, a)]
Map.toList Map Word SymWord
x]
showResult :: [String]
showResult = [(?context::DappContext) => VMResult -> String
VMResult -> String
prettyvmresult VMResult
res | Just VMResult
res <- [Getting (Maybe VMResult) VM (Maybe VMResult)
-> VM -> Maybe VMResult
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (Maybe VMResult) VM (Maybe VMResult)
Lens' VM (Maybe VMResult)
result VM
vm]]
in [String]
showResult
[String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [(SymWord, SymWord)] -> [String]
showStorage [(SymWord, SymWord)]
updates
[String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
""]
showBranchInfoWithAbi :: DappInfo -> BranchInfo -> [String]
showBranchInfoWithAbi :: DappInfo -> BranchInfo -> [String]
showBranchInfoWithAbi DappInfo
_ (BranchInfo VM
_ Maybe Whiff
Nothing) = [String
""]
showBranchInfoWithAbi DappInfo
srcInfo (BranchInfo VM
vm (Just Whiff
y)) =
case Whiff
y of
(IsZero (Eq (Literal W256
x) Whiff
_)) ->
let
abimap :: Maybe (Map Word32 Method)
abimap = Getting (Map Word32 Method) SolcContract (Map Word32 Method)
-> SolcContract -> Map Word32 Method
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting (Map Word32 Method) SolcContract (Map Word32 Method)
Lens' SolcContract (Map Word32 Method)
abiMap (SolcContract -> Map Word32 Method)
-> Maybe SolcContract -> Maybe (Map Word32 Method)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DappInfo -> VM -> Maybe SolcContract
currentSolc DappInfo
srcInfo VM
vm
method :: Maybe Method
method = Maybe (Map Word32 Method)
abimap Maybe (Map Word32 Method)
-> (Map Word32 Method -> Maybe Method) -> Maybe Method
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Word32 -> Map Word32 Method -> Maybe Method
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup (W256 -> Word32
forall a b. (Integral a, Num b) => a -> b
num W256
x)
in [String -> (Method -> String) -> Maybe Method -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Whiff -> String
forall a. Show a => a -> String
show Whiff
y) (Text -> String
forall a. Show a => a -> String
show (Text -> String) -> (Method -> Text) -> Method -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Getting Text Method Text -> Method -> Text
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Text Method Text
Lens' Method Text
methodSignature) Maybe Method
method]
Whiff
y' -> [Whiff -> String
forall a. Show a => a -> String
show Whiff
y']
renderTree :: (a -> [String])
-> (a -> [String])
-> Tree a
-> Tree [String]
renderTree :: (a -> [String]) -> (a -> [String]) -> Tree a -> Tree [String]
renderTree a -> [String]
showBranch a -> [String]
showLeaf (Node a
b []) = [String] -> Forest [String] -> Tree [String]
forall a. a -> Forest a -> Tree a
Node (a -> [String]
showBranch a
b [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ a -> [String]
showLeaf a
b) []
renderTree a -> [String]
showBranch a -> [String]
showLeaf (Node a
b [Tree a]
cs) = [String] -> Forest [String] -> Tree [String]
forall a. a -> Forest a -> Tree a
Node (a -> [String]
showBranch a
b) ((a -> [String]) -> (a -> [String]) -> Tree a -> Tree [String]
forall a.
(a -> [String]) -> (a -> [String]) -> Tree a -> Tree [String]
renderTree a -> [String]
showBranch a -> [String]
showLeaf (Tree a -> Tree [String]) -> [Tree a] -> Forest [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Tree a]
cs)