Skip to content

Commit 869573e

Browse files
committed
hevm: london hard fork
1 parent d10dbe5 commit 869573e

File tree

9 files changed

+151
-74
lines changed

9 files changed

+151
-74
lines changed

release.nix

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ let
88
ethereum-test-suite = x: x.fetchFromGitHub {
99
owner = "ethereum";
1010
repo = "tests";
11-
rev = "644967e345bbc6642fab613e1b1737abbe131f78";
12-
sha256 = "1525yzmc5wig5pkz904k2rqz11ygiql8mzb6djym9w87bymfvzm9";
11+
rev = "e20d7f39aae1e33394ae6b94590d15083e224fa5";
12+
sha256 = "1i68k3b8sxawbm65mwph8d5ld9jdjh08c6hln0vygjgwmd0j4n30";
1313
};
1414

1515
# run all General State Tests, skipping performance heavy tests and the ones missing
@@ -19,7 +19,7 @@ let
1919
export PATH=${x.pkgs.hevm}/bin:${x.pkgs.jq}/bin:$PATH
2020
${x.pkgs.hevm}/bin/hevm compliance \
2121
--tests ${ethereum-test-suite x} \
22-
--skip "(Create2Recursive|Create1000|recursiveCreateReturn|underflowTest|walletRemoveOwnerRemovePending|Return5000|randomStatetest177|loopExp|loopMul)" \
22+
--skip "(Create2Recursive|Create1000|recursiveCreateReturn|underflowTest|walletRemoveOwnerRemovePending|Return5000|randomStatetest177|loopExp|loopMul|FirstByte)" \
2323
--timeout 20 \
2424
--html > $out/index.html
2525
# Disable obsolete VMTests - gas expectations broken by Istanbul

src/hevm/hevm-cli/hevm-cli.hs

+18-8
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ data Command w
104104
, gas :: w ::: Maybe W256 <?> "Tx: gas amount"
105105
, number :: w ::: Maybe W256 <?> "Block: number"
106106
, timestamp :: w ::: Maybe W256 <?> "Block: timestamp"
107+
, basefee :: w ::: Maybe W256 <?> "Block: base fee"
108+
, priorityFee :: w ::: Maybe W256 <?> "Tx: priority fee"
107109
, gaslimit :: w ::: Maybe W256 <?> "Tx: gas limit"
108110
, gasprice :: w ::: Maybe W256 <?> "Tx: gas price"
109111
, create :: w ::: Bool <?> "Tx: creation"
@@ -155,6 +157,8 @@ data Command w
155157
, gas :: w ::: Maybe W256 <?> "Tx: gas amount"
156158
, number :: w ::: Maybe W256 <?> "Block: number"
157159
, timestamp :: w ::: Maybe W256 <?> "Block: timestamp"
160+
, basefee :: w ::: Maybe W256 <?> "Block: base fee"
161+
, priorityFee :: w ::: Maybe W256 <?> "Tx: priority fee"
158162
, gaslimit :: w ::: Maybe W256 <?> "Tx: gas limit"
159163
, gasprice :: w ::: Maybe W256 <?> "Tx: gas price"
160164
, create :: w ::: Bool <?> "Tx: creation"
@@ -707,12 +711,13 @@ vmFromCommand :: Command Options.Unwrapped -> IO EVM.VM
707711
vmFromCommand cmd = do
708712
withCache <- applyCache (state cmd, cache cmd)
709713

710-
(miner,ts,blockNum,diff) <- case rpc cmd of
711-
Nothing -> return (0,0,0,0)
714+
(miner,ts,baseFee,blockNum,diff) <- case rpc cmd of
715+
Nothing -> return (0,0,0,0,0)
712716
Just url -> EVM.Fetch.fetchBlockFrom block' url >>= \case
713717
Nothing -> error "Could not fetch block"
714718
Just EVM.Block{..} -> return (_coinbase
715719
, wordValue $ forceLit _timestamp
720+
, wordValue _baseFee
716721
, wordValue _number
717722
, wordValue _difficulty
718723
)
@@ -745,7 +750,7 @@ vmFromCommand cmd = do
745750
(_, _, Nothing) ->
746751
error "must provide at least (rpc + address) or code"
747752

748-
return $ VMTest.initTx $ withCache (vm0 miner ts blockNum diff contract)
753+
return $ VMTest.initTx $ withCache (vm0 baseFee miner ts blockNum diff contract)
749754
where
750755
decipher = hexByteString "bytes" . strip0x
751756
block' = maybe EVM.Fetch.Latest EVM.Fetch.BlockNumber (block cmd)
@@ -758,14 +763,16 @@ vmFromCommand cmd = do
758763
then addr address (createAddress origin' (word nonce 0))
759764
else addr address 0xacab
760765

761-
vm0 miner ts blockNum diff c = EVM.makeVm $ EVM.VMOpts
766+
vm0 baseFee miner ts blockNum diff c = EVM.makeVm $ EVM.VMOpts
762767
{ EVM.vmoptContract = c
763768
, EVM.vmoptCalldata = (calldata', litWord (num $ len calldata'))
764769
, EVM.vmoptValue = w256lit value'
765770
, EVM.vmoptAddress = address'
766771
, EVM.vmoptCaller = litAddr caller'
767772
, EVM.vmoptOrigin = origin'
768773
, EVM.vmoptGas = word gas 0
774+
, EVM.vmoptBaseFee = baseFee
775+
, EVM.vmoptPriorityFee = word priorityFee 0
769776
, EVM.vmoptGaslimit = word gas 0
770777
, EVM.vmoptCoinbase = addr coinbase miner
771778
, EVM.vmoptNumber = word number blockNum
@@ -788,12 +795,13 @@ vmFromCommand cmd = do
788795
symvmFromCommand :: Command Options.Unwrapped -> Query EVM.VM
789796
symvmFromCommand cmd = do
790797

791-
(miner,blockNum,diff) <- case rpc cmd of
792-
Nothing -> return (0,0,0)
798+
(miner,blockNum,baseFee,diff) <- case rpc cmd of
799+
Nothing -> return (0,0,0,0)
793800
Just url -> io $ EVM.Fetch.fetchBlockFrom block' url >>= \case
794801
Nothing -> error "Could not fetch block"
795802
Just EVM.Block{..} -> return (_coinbase
796803
, wordValue _number
804+
, wordValue _baseFee
797805
, wordValue _difficulty
798806
)
799807

@@ -853,7 +861,7 @@ symvmFromCommand cmd = do
853861
(_, _, Nothing) ->
854862
error "must provide at least (rpc + address) or code"
855863

856-
return $ (VMTest.initTx $ withCache $ vm0 miner ts blockNum diff cdlen calldata' callvalue' caller' contract')
864+
return $ (VMTest.initTx $ withCache $ vm0 baseFee miner ts blockNum diff cdlen calldata' callvalue' caller' contract')
857865
& over EVM.constraints (<> [pathCond])
858866
& set (EVM.env . EVM.contracts . (ix address') . EVM.storage) store
859867

@@ -865,7 +873,7 @@ symvmFromCommand cmd = do
865873
address' = if create cmd
866874
then addr address (createAddress origin' (word nonce 0))
867875
else addr address 0xacab
868-
vm0 miner ts blockNum diff cdlen calldata' callvalue' caller' c = EVM.makeVm $ EVM.VMOpts
876+
vm0 baseFee miner ts blockNum diff cdlen calldata' callvalue' caller' c = EVM.makeVm $ EVM.VMOpts
869877
{ EVM.vmoptContract = c
870878
, EVM.vmoptCalldata = (calldata', cdlen)
871879
, EVM.vmoptValue = callvalue'
@@ -874,6 +882,8 @@ symvmFromCommand cmd = do
874882
, EVM.vmoptOrigin = origin'
875883
, EVM.vmoptGas = word gas 0xffffffffffffffff
876884
, EVM.vmoptGaslimit = word gas 0xffffffffffffffff
885+
, EVM.vmoptBaseFee = baseFee
886+
, EVM.vmoptPriorityFee = word priorityFee 0
877887
, EVM.vmoptCoinbase = addr coinbase miner
878888
, EVM.vmoptNumber = word number blockNum
879889
, EVM.vmoptTimestamp = ts

src/hevm/src/EVM.hs

+36-31
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ data Error
8585
| InvalidMemoryAccess
8686
| CallDepthLimitReached
8787
| MaxCodeSizeExceeded Word Word
88+
| InvalidFormat
8889
| PrecompileFailure
8990
| UnexpectedSymbolicArg
9091
| DeadPath
@@ -194,6 +195,7 @@ data VMOpts = VMOpts
194195
{ vmoptContract :: Contract
195196
, vmoptCalldata :: (Buffer, SymWord)
196197
, vmoptValue :: SymWord
198+
, vmoptPriorityFee :: W256
197199
, vmoptAddress :: Addr
198200
, vmoptCaller :: SAddr
199201
, vmoptOrigin :: Addr
@@ -206,6 +208,7 @@ data VMOpts = VMOpts
206208
, vmoptMaxCodeSize :: W256
207209
, vmoptBlockGaslimit :: W256
208210
, vmoptGasprice :: W256
211+
, vmoptBaseFee :: W256
209212
, vmoptSchedule :: FeeSchedule Integer
210213
, vmoptChainId :: W256
211214
, vmoptCreate :: Bool
@@ -268,6 +271,7 @@ data FrameState = FrameState
268271
data TxState = TxState
269272
{ _gasprice :: Word
270273
, _txgaslimit :: Word
274+
, _txPriorityFee :: Word
271275
, _origin :: Addr
272276
, _toAddr :: Addr
273277
, _value :: SymWord
@@ -376,6 +380,7 @@ data Block = Block
376380
, _number :: Word
377381
, _difficulty :: Word
378382
, _gaslimit :: Word
383+
, _baseFee :: Word
379384
, _maxCodeSize :: Word
380385
, _schedule :: FeeSchedule Integer
381386
} deriving Show
@@ -459,6 +464,7 @@ makeVm o =
459464
, _tx = TxState
460465
{ _gasprice = w256 $ vmoptGasprice o
461466
, _txgaslimit = w256 $ vmoptGaslimit o
467+
, _txPriorityFee = w256 $ vmoptPriorityFee o
462468
, _origin = txorigin
463469
, _toAddr = txtoAddr
464470
, _value = vmoptValue o
@@ -477,6 +483,7 @@ makeVm o =
477483
, _difficulty = w256 $ vmoptDifficulty o
478484
, _maxCodeSize = w256 $ vmoptMaxCodeSize o
479485
, _gaslimit = w256 $ vmoptBlockGaslimit o
486+
, _baseFee = w256 $ vmoptBaseFee o
480487
, _schedule = vmoptSchedule o
481488
}
482489
, _state = FrameState
@@ -962,6 +969,11 @@ exec1 = do
962969
limitStack 1 . burn g_low $
963970
next >> push (view balance this)
964971

972+
-- op: BASEFEE
973+
0x48 ->
974+
limitStack 1 . burn g_base $
975+
next >> push (the block baseFee)
976+
965977
-- op: POP
966978
0x50 ->
967979
case stk of
@@ -1051,12 +1063,12 @@ exec1 = do
10511063
unless (current' == new') $
10521064
if current' == original
10531065
then when (original /= 0 && new' == 0) $
1054-
refund r_sclear
1066+
refund (g_sreset + g_access_list_storage_key)
10551067
else do
10561068
when (original /= 0) $
10571069
if new' == 0
1058-
then refund r_sclear
1059-
else unRefund r_sclear
1070+
then refund (g_sreset + g_access_list_storage_key)
1071+
else unRefund (g_sreset + g_access_list_storage_key)
10601072
when (original == new') $
10611073
if original == 0
10621074
then refund (g_sset - g_sload)
@@ -1197,31 +1209,24 @@ exec1 = do
11971209
output = readMemory xOffset xSize vm
11981210
codesize = num (len output)
11991211
maxsize = the block maxCodeSize
1200-
case view frames vm of
1201-
[] ->
1202-
case (the tx isCreate) of
1203-
True ->
1204-
if codesize > maxsize
1205-
then
1206-
finishFrame (FrameErrored (MaxCodeSizeExceeded maxsize codesize))
1207-
else
1208-
burn (g_codedeposit * num codesize) $
1209-
finishFrame (FrameReturned output)
1210-
False ->
1212+
creation = case view frames vm of
1213+
[] -> the tx isCreate
1214+
frame:_ -> case view frameContext frame of
1215+
CreationContext {} -> True
1216+
CallContext {} -> False
1217+
if creation
1218+
then
1219+
if codesize > maxsize
1220+
then
1221+
finishFrame (FrameErrored (MaxCodeSizeExceeded maxsize codesize))
1222+
else
1223+
if isConcretely (readByteOrZero 0 output) ((==) 0xef)
1224+
then finishFrame $ FrameErrored InvalidFormat
1225+
else do
1226+
burn (g_codedeposit * num codesize) $
12111227
finishFrame (FrameReturned output)
1212-
(frame: _) -> do
1213-
let
1214-
context = view frameContext frame
1215-
case context of
1216-
CreationContext {} ->
1217-
if codesize > maxsize
1218-
then
1219-
finishFrame (FrameErrored (MaxCodeSizeExceeded maxsize codesize))
1220-
else
1221-
burn (g_codedeposit * num codesize) $
1222-
finishFrame (FrameReturned output)
1223-
CallContext {} ->
1224-
finishFrame (FrameReturned output)
1228+
else
1229+
finishFrame (FrameReturned output)
12251230
_ -> underrun
12261231

12271232
-- op: DELEGATECALL
@@ -1298,8 +1303,6 @@ exec1 = do
12981303
then num g_selfdestruct_newaccount
12991304
else 0
13001305
burn (g_selfdestruct + c_new + cost) $ do
1301-
destructs <- use (tx . substate . selfdestructs)
1302-
unless (elem self destructs) $ refund r_selfdestruct
13031306
selfdestruct self
13041307
touchAccount xTo
13051308

@@ -1744,14 +1747,16 @@ finalize = do
17441747
miner <- use (block . coinbase)
17451748
blockReward <- num . r_block <$> (use (block . schedule))
17461749
gasPrice <- use (tx . gasprice)
1750+
priorityFee <- use (tx . txPriorityFee)
17471751
gasLimit <- use (tx . txgaslimit)
17481752
gasRemaining <- use (state . gas)
17491753

17501754
let
17511755
gasUsed = gasLimit - gasRemaining
1752-
cappedRefund = min (quot gasUsed 2) (num sumRefunds)
1756+
cappedRefund = min (quot gasUsed 5) (num sumRefunds)
17531757
originPay = (gasRemaining + cappedRefund) * gasPrice
1754-
minerPay = gasPrice * (gasUsed - cappedRefund)
1758+
1759+
minerPay = priorityFee * gasUsed
17551760

17561761
modifying (env . contracts)
17571762
(Map.adjust (over balance (+ originPay)) txOrigin)

src/hevm/src/EVM/Exec.hs

+2
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ vmForEthrunCreation creationCode =
3535
, vmoptDifficulty = 0
3636
, vmoptGas = 0xffffffffffffffff
3737
, vmoptGaslimit = 0xffffffffffffffff
38+
, vmoptBaseFee = 0
39+
, vmoptPriorityFee = 0
3840
, vmoptMaxCodeSize = 0xffffffff
3941
, vmoptSchedule = FeeSchedule.berlin
4042
, vmoptChainId = 1

src/hevm/src/EVM/Fetch.hs

+2-1
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,9 @@ parseBlock j = do
113113
timestamp <- litWord . readText <$> j ^? key "timestamp" . _String
114114
number <- readText <$> j ^? key "number" . _String
115115
difficulty <- readText <$> j ^? key "difficulty" . _String
116+
baseFee <- readText <$> j ^? key "baseFee" . _String
116117
-- default codesize, default gas limit, default feescedule
117-
return $ EVM.Block coinbase timestamp number difficulty 0xffffffff 0xffffffff FeeSchedule.berlin
118+
return $ EVM.Block coinbase timestamp number difficulty 0xffffffff baseFee 0xffffffff FeeSchedule.berlin
118119

119120
fetchWithSession :: Text -> Session -> Value -> IO (Maybe Value)
120121
fetchWithSession url sess x = do

src/hevm/src/EVM/SymExec.hs

+2
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ loadSymVM x initStore model addr callvalue' calldata' =
138138
, vmoptDifficulty = 0
139139
, vmoptGas = 0xffffffffffffffff
140140
, vmoptGaslimit = 0xffffffffffffffff
141+
, vmoptBaseFee = 0
142+
, vmoptPriorityFee = 0
141143
, vmoptMaxCodeSize = 0xffffffff
142144
, vmoptSchedule = FeeSchedule.berlin
143145
, vmoptChainId = 1

0 commit comments

Comments
 (0)