module EVM.Exec where
import EVM
import EVM.Concrete (createAddress)
import EVM.Symbolic (litAddr)
import EVM.Types
import qualified EVM.FeeSchedule as FeeSchedule
import Control.Lens
import Control.Monad.State.Class (MonadState)
import Control.Monad.State.Strict (runState)
import Data.ByteString (ByteString)
import Data.Maybe (isNothing)
import qualified Control.Monad.State.Class as State
ethrunAddress :: Addr
ethrunAddress = Addr 0x00a329c0648769a73afac7f9381e08fb43dbea72
vmForEthrunCreation :: ByteString -> VM
vmForEthrunCreation creationCode =
(makeVm $ VMOpts
{ vmoptContract = initialContract (InitCode creationCode)
, vmoptCalldata = (mempty, 0)
, vmoptValue = 0
, vmoptAddress = createAddress ethrunAddress 1
, vmoptCaller = litAddr ethrunAddress
, vmoptOrigin = ethrunAddress
, vmoptCoinbase = 0
, vmoptNumber = 0
, vmoptTimestamp = 0
, vmoptBlockGaslimit = 0
, vmoptGasprice = 0
, vmoptDifficulty = 0
, vmoptGas = 0xffffffffffffffff
, vmoptGaslimit = 0xffffffffffffffff
, vmoptMaxCodeSize = 0xffffffff
, vmoptSchedule = FeeSchedule.istanbul
, vmoptChainId = 1
, vmoptCreate = False
, vmoptStorageModel = ConcreteS
}) & set (env . contracts . at ethrunAddress)
(Just (initialContract (RuntimeCode mempty)))
exec :: MonadState VM m => m VMResult
exec =
use EVM.result >>= \case
Nothing -> State.state (runState exec1) >> exec
Just x -> return x
run :: MonadState VM m => m VM
run =
use EVM.result >>= \case
Nothing -> State.state (runState exec1) >> run
Just _ -> State.get
execWhile :: MonadState VM m => (VM -> Bool) -> m Int
execWhile p = go 0
where
go i = do
x <- State.get
if p x && isNothing (view result x)
then do
State.state (runState exec1)
go $! (i + 1)
else
return i