Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
bdd65b7
kproj/{schedule,driver}.md: eip-8037 state-creation gas cost increase…
anvacaru Jul 14, 2026
df53c0a
kproj/schedule.md: add missing Ghasauthbaserefund << DEFAULT >> rule
anvacaru Jul 15, 2026
4a8e7cb
kproj/{evm,gas,driver,schedule,state-utils}.md: implement eip-8037 st…
anvacaru Jul 15, 2026
b338726
kproj/{evm,gas}.md: restructure amsterdam sstore regular gas (eip-803…
anvacaru Jul 16, 2026
80a19b0
kproj/{evm,driver}.md: eip-8037 CREATE new-account OOG halts caller a…
anvacaru Jul 20, 2026
4c9d678
kproj/{evm,driver}.md: charge eip-8037 create new-account state gas b…
anvacaru Jul 20, 2026
8eb365f
kproj/{evm,driver}.md: align eip-8037 frame state-gas lifecycle, eip-…
anvacaru Jul 20, 2026
7234346
kproj/{gas,state-utils}.md: enforce per-tx block-gas-remaining admiss…
anvacaru Jul 20, 2026
2b69972
tests/specs: add eip-8037 callState cells to closed-form spec configs
anvacaru Jul 24, 2026
934f666
kproj/{evm.md,lemmas/lemmas.k}: make zero state-gas charges symbolic …
anvacaru Jul 24, 2026
f2a44bd
formatting
anvacaru Jul 27, 2026
a77b7a6
kproj/evm.md: give system-contract calls the eip-8037 state-gas reser…
anvacaru Jul 27, 2026
d7ca663
add implementation for eip-8038
anvacaru Aug 27, 2026
f29a9e4
Merge branch 'amsterdam-foundation' into eip-8037
anvacaru Aug 27, 2026
48ea4be
Merge branch 'amsterdam-foundation' into eip-8037
anvacaru Aug 28, 2026
f67eeaf
update golden expected files
anvacaru Aug 28, 2026
06e7077
refactor create state gas in its own production
anvacaru Aug 30, 2026
81a805b
update kontrol proof specs
anvacaru Aug 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 102 additions & 32 deletions kevm-pyk/src/kevm_pyk/kproj/evm-semantics/driver.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,9 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
</k>
<schedule> SCHED </schedule>
<gasPrice> _ => #effectiveGasPrice(TXID) </gasPrice>
<callGas> _ => GLIMIT -Int G0(SCHED, CODE, true) </callGas>
<callGas> _ => GLIMIT -Int G0(SCHED, CODE, true) -Int #txStateGasReservoir(SCHED, GLIMIT) </callGas>
<stateGasReservoir> _ => #txStateGasReservoir(SCHED, GLIMIT) </stateGasReservoir>
<stateGasSpilled> _ => 0 </stateGasSpilled>
<origin> _ => ACCTFROM </origin>
<callDepth> _ => -1 </callDepth>
<txPending> ListItem(TXID:Int) ... </txPending>
Expand Down Expand Up @@ -159,15 +161,19 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
=> #accessAccounts ACCTFROM ACCTTO #precompiledAccountsSet(SCHED)
~> #deductBlobGas
~> #loadAccessList(TA)
~> #pushWorldState ~> #pushCallStack
~> #loadAuthorities(AUTH)
~> #dropWorldState ~> #dropCallStack
~> #checkCall ACCTFROM VALUE
~> #call ACCTFROM ACCTTO ACCTTO VALUE VALUE DATA false
~> #finishTx ~> #finalizeTx(false, Ctxfloor(SCHED, DATA)) ~> startTx
...
</k>
<schedule> SCHED </schedule>
<gasPrice> _ => #effectiveGasPrice(TXID) </gasPrice>
<callGas> _ => GLIMIT -Int G0(SCHED, DATA, false) </callGas>
<callGas> _ => GLIMIT -Int G0(SCHED, DATA, false) -Int #txStateGasReservoir(SCHED, GLIMIT) </callGas>
<stateGasReservoir> _ => #txStateGasReservoir(SCHED, GLIMIT) </stateGasReservoir>
<stateGasSpilled> _ => 0 </stateGasSpilled>
<origin> _ => ACCTFROM </origin>
<callDepth> _ => -1 </callDepth>
<txPending> ListItem(TXID:Int) ... </txPending>
Expand Down Expand Up @@ -202,8 +208,10 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a

syntax EthereumCommand ::= "#finishTx"
// --------------------------------------
rule <statusCode> _:ExceptionalStatusCode </statusCode> <k> #halt ~> #finishTx => #popCallStack ~> #popWorldState ... </k>
rule <statusCode> EVMC_REVERT </statusCode> <k> #halt ~> #finishTx => #popCallStack ~> #popWorldState ~> #refund GAVAIL ... </k> <gas> GAVAIL </gas>
rule <statusCode> _:ExceptionalStatusCode </statusCode> <k> #halt ~> #finishTx => #popCallStack ~> #popWorldState ... </k>
rule <statusCode> EVMC_REVERT </statusCode> <k> #halt ~> #finishTx => #popCallStack ~> #popWorldState ~> #refund (GAVAIL +Gas SGS) ... </k>
<gas> GAVAIL </gas>
<stateGasSpilled> SGS </stateGasSpilled>

rule <statusCode> EVMC_SUCCESS </statusCode>
<k> #halt ~> #finishTx => #mkCodeDeposit ACCT ... </k>
Expand All @@ -216,8 +224,10 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
</message>

rule <statusCode> EVMC_SUCCESS </statusCode>
<k> #halt ~> #finishTx => #popCallStack ~> #dropWorldState ~> #refund GAVAIL ... </k>
<k> #halt ~> #finishTx => #popCallStack ~> #dropWorldState ~> #restoreStateGas SGR SGS ~> #refund GAVAIL ... </k>
<gas> GAVAIL </gas>
<stateGasReservoir> SGR </stateGasReservoir>
<stateGasSpilled> SGS </stateGasSpilled>
<txPending> ListItem(TXID:Int) ... </txPending>
<message>
<msgID> TXID </msgID>
Expand Down Expand Up @@ -261,19 +271,21 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
Processing SetCode Transaction Authority Entries
================================================

- The `#loadAuthorities` function processes authorization entries in EIP-7702 SetCode transactions, charging 25000 gas per tuple regardless of validity.
- The `#loadAuthorities` function processes authorization entries in EIP-7702 SetCode transactions, charging 25000 gas per tuple regardless of validity on pre-Amsterdam schedules.
- Skips processing if transaction is not SetCode type; processes each authorization tuple by recovering the signer and attempting delegation.
- The Amsterdam (`Ghasstategas`) charge model threads three sets through the tuple loop, mirroring EELS `set_delegation`: accounts already written by the transaction (seeded with the sender, plus the recipient of a value-bearing call), authorities that must never be charged `Gauthbase` again (delegated before the transaction, or already charged), and authorities touched by an earlier tuple.
- The `#addAuthority` function implements EIP-7702 verification and delegation:
- Validates that the chain ID matches current chain (or is 0) and nonce is within bounds
- Checks if authority account code is empty or already delegated
- Verifies that the authority nonce equals authorization nonce
- Sets delegation code (0xEF0100 + address) and increments nonce on success
- Provides refund (25000 - 12500 = 12500 gas) only for accounts that existed before processing
- A new account will be created for Authorities that are not in the `<accounts>` state, without increasing the refund amount
- Pre-Amsterdam: provides refund (25000 - 12500 = 12500 gas) only for accounts that existed before processing; a new account will be created for Authorities that are not in the `<accounts>` state, without increasing the refund amount
- Amsterdam: charges `Gnewaccount` state gas for authorities with no account leaf, `Gaccountwrite` regular gas on the transaction's first write to the authority, and `Gauthbase` state gas at most once per authority for a net-new delegation indicator

```k
syntax InternalOp ::= #loadAuthorities ( List ) [symbol(#loadAuthorities)]
// --------------------------------------------------------------------------
| #loadAuthorities ( List , Set , Set , Set ) [symbol(#loadAuthoritiesAux)]
// -----------------------------------------------------------------------------------------------
rule <k> #loadAuthorities(_) => .K ... </k>
<txPending> ListItem(TXID:Int) ... </txPending>
<message>
Expand All @@ -283,42 +295,56 @@ Processing SetCode Transaction Authority Entries
</message>
requires notBool TXTYPE ==K SetCode

rule <k> #loadAuthorities( .List ) => .K ... </k>
rule <k> #loadAuthorities(AUTHS)
=> #loadAuthorities(AUTHS, SetItem(ORG) |Set (#if VALUE >Int 0 #then SetItem(TT) #else .Set #fi), .Set, .Set)
... </k>
<origin> ORG </origin>
<txPending> ListItem(TXID:Int) ... </txPending>
<message>
<msgID> TXID </msgID>
<txType> SetCode </txType>
<to> TT </to>
<value> VALUE </value>
...
</message>

rule <k> #loadAuthorities (ListItem(ListItem(CID) ListItem(ADDR) ListItem(NONCE) ListItem(YPAR) ListItem(SIGR) ListItem(SIGS)) REST )
=> #setDelegation (#recoverAuthority(CID, ADDR, NONCE, YPAR, SIGR, SIGS), CID, NONCE, ADDR)
~> #loadAuthorities (REST)
rule <k> #loadAuthorities( .List, _, _, _ ) => .K ... </k>

rule <k> #loadAuthorities (ListItem(ListItem(CID) ListItem(ADDR) ListItem(NONCE) ListItem(YPAR) ListItem(SIGR) ListItem(SIGS)) REST, W, NB, T)
=> #setDelegation (#recoverAuthority(CID, ADDR, NONCE, YPAR, SIGR, SIGS), CID, NONCE, ADDR, REST, W, NB, T)
... </k>
<txPending> ListItem(TXID:Int) ... </txPending>
<message>
<msgID> TXID </msgID>
<txType> SetCode </txType>
...
</message>
<callGas> GLIMIT => GLIMIT -Int 25000 </callGas> [owise]
<schedule> SCHED </schedule>
<callGas> GLIMIT => GLIMIT -Int 25000 </callGas>
requires notBool Ghasstategas << SCHED >>

syntax InternalOp ::= #setDelegation ( Account , Bytes , Bytes , Bytes ) [symbol(#setDelegation)]
// -------------------------------------------------------------------------------------------------
rule <k> #setDelegation(AUTHORITY, CID, NONCE, _ADDR) => .K ... </k> <chainID> ENV_CID </chainID>
rule <k> #loadAuthorities (ListItem(ListItem(CID) ListItem(ADDR) ListItem(NONCE) ListItem(YPAR) ListItem(SIGR) ListItem(SIGS)) REST, W, NB, T)
=> #setDelegation (#recoverAuthority(CID, ADDR, NONCE, YPAR, SIGR, SIGS), CID, NONCE, ADDR, REST, W, NB, T)
... </k>
<schedule> SCHED </schedule>
requires Ghasstategas << SCHED >>

syntax InternalOp ::= #setDelegation ( Account , Bytes , Bytes , Bytes , List , Set , Set , Set ) [symbol(#setDelegation)]
// --------------------------------------------------------------------------------------------------------------------------
rule <k> #setDelegation(AUTHORITY, CID, NONCE, _ADDR, REST, W, NB, T) => #loadAuthorities(REST, W, NB, T) ... </k> <chainID> ENV_CID </chainID>
requires AUTHORITY ==K .Account
orBool (notBool #asWord(CID) in (SetItem(ENV_CID) SetItem(0)))
orBool (#asWord(NONCE) >=Int maxUInt64)

rule <k> #setDelegation(AUTHORITY, CID, NONCE, ADDR)
rule <k> #setDelegation(AUTHORITY, CID, NONCE, ADDR, REST, W, NB, T)
=> #touchAccounts AUTHORITY ~> #accessAccounts AUTHORITY
~> #addAuthority(AUTHORITY, CID, NONCE, ADDR)
~> #addAuthority(AUTHORITY, CID, NONCE, ADDR, REST, W, NB, T)
...
</k> [owise]

syntax InternalOp ::= #addAuthority ( Account , Bytes , Bytes , Bytes ) [symbol(#addAuthority)]
// -----------------------------------------------------------------------------------------------
rule <k> #addAuthority(AUTHORITY, _CID, NONCE, _ADDR) => .K ... </k>
syntax Set ::= #authNoBase ( Set , Set , Account , Bytes ) [symbol(#authNoBase), function, total]
// -------------------------------------------------------------------------------------------------
rule #authNoBase(NB, T, AUTHORITY, ACCTCODE) => NB |Set SetItem(AUTHORITY)
requires notBool AUTHORITY in T andBool #isValidDelegation(ACCTCODE)
rule #authNoBase(NB, _, _, _) => NB [owise]

syntax InternalOp ::= #addAuthority ( Account , Bytes , Bytes , Bytes , List , Set , Set , Set ) [symbol(#addAuthority)]
// ------------------------------------------------------------------------------------------------------------------------
rule <k> #addAuthority(AUTHORITY, _CID, NONCE, _ADDR, REST, W, NB, T) => #loadAuthorities(REST, W, NB, T) ... </k>
<account>
<acctID> AUTHORITY </acctID>
<code> ACCTCODE </code>
Expand All @@ -328,7 +354,7 @@ Processing SetCode Transaction Authority Entries
requires notBool (ACCTCODE ==K .Bytes orBool #isValidDelegation(ACCTCODE))
orBool (notBool #asWord(NONCE) ==K ACCTNONCE)

rule <k> #addAuthority(AUTHORITY, _CID, NONCE, ADDR) => .K ... </k>
rule <k> #addAuthority(AUTHORITY, _CID, NONCE, ADDR, REST, W, NB, T) => #loadAuthorities(REST, W, NB, T) ... </k>
<schedule> SCHED </schedule>
<refund> REFUND => REFUND +Int Gnewaccount < SCHED > -Int Gauthbase < SCHED > </refund>
<account>
Expand All @@ -337,10 +363,52 @@ Processing SetCode Transaction Authority Entries
<nonce> ACCTNONCE => ACCTNONCE +Int 1 </nonce>
...
</account>
requires (ACCTCODE ==K .Bytes orBool #isValidDelegation(ACCTCODE))
requires Ghasauthbaserefund << SCHED >>
andBool (ACCTCODE ==K .Bytes orBool #isValidDelegation(ACCTCODE))
andBool #asWord(NONCE) ==K ACCTNONCE

rule <k> #addAuthority(AUTHORITY, _CID, NONCE, ADDR) => .K ... </k>
rule <k> #addAuthority(AUTHORITY, _CID, NONCE, ADDR, REST, W, NB, T)
=> #if Ghasstategas << SCHED >> andBool notBool AUTHORITY in W #then Gaccountwrite < SCHED > #else 0 #fi ~> #deductCallGas
~> #if Ghasstategas << SCHED >> andBool #asWord(ADDR) =/=Int 0 andBool notBool AUTHORITY in #authNoBase(NB, T, AUTHORITY, ACCTCODE) #then Gauthbase < SCHED > #else 0 #fi ~> #chargeStateGasIntoCallGas
~> #loadAuthorities(REST, W |Set SetItem(AUTHORITY), #authNoBase(NB, T, AUTHORITY, ACCTCODE) |Set (#if #asWord(ADDR) =/=Int 0 #then SetItem(AUTHORITY) #else .Set #fi), T |Set SetItem(AUTHORITY))
...
</k>
<schedule> SCHED </schedule>
<account>
<acctID> AUTHORITY </acctID>
<code> ACCTCODE => #if #asWord(ADDR) ==Int 0 #then .Bytes #else EOA_DELEGATION_MARKER +Bytes ADDR #fi </code>
<nonce> ACCTNONCE => ACCTNONCE +Int 1 </nonce>
...
</account>
requires notBool Ghasauthbaserefund << SCHED >>
andBool (ACCTCODE ==K .Bytes orBool #isValidDelegation(ACCTCODE))
andBool #asWord(NONCE) ==K ACCTNONCE

rule <k> #addAuthority(AUTHORITY, _CID, NONCE, ADDR, REST, W, NB, T) => #loadAuthorities(REST, W, NB, T) ... </k>
<schedule> SCHED </schedule>
<accounts>
( .Bag
=>
<account>
<acctID> AUTHORITY </acctID>
<code> #if #asWord(ADDR) ==Int 0 #then .Bytes #else EOA_DELEGATION_MARKER +Bytes ADDR #fi </code>
<nonce> 1 </nonce>
...
</account>
)
...
</accounts>
requires #asWord(NONCE) ==Int 0 andBool notBool #accountExists(AUTHORITY)
andBool notBool Ghasstategas << SCHED >>

rule <k> #addAuthority(AUTHORITY, _CID, NONCE, ADDR, REST, W, NB, T)
=> Gnewaccount < SCHED > ~> #chargeStateGasIntoCallGas
~> #if notBool AUTHORITY in W #then Gaccountwrite < SCHED > #else 0 #fi ~> #deductCallGas
~> #if #asWord(ADDR) =/=Int 0 #then Gauthbase < SCHED > #else 0 #fi ~> #chargeStateGasIntoCallGas
~> #loadAuthorities(REST, W |Set SetItem(AUTHORITY), NB |Set (#if #asWord(ADDR) =/=Int 0 #then SetItem(AUTHORITY) #else .Set #fi), T |Set SetItem(AUTHORITY))
...
</k>
<schedule> SCHED </schedule>
<accounts>
( .Bag
=>
Expand All @@ -354,8 +422,10 @@ Processing SetCode Transaction Authority Entries
...
</accounts>
requires #asWord(NONCE) ==Int 0 andBool notBool #accountExists(AUTHORITY)
andBool Ghasstategas << SCHED >>

rule <k> #addAuthority(AUTHORITY, _CID, NONCE, _ADDR) => .K ... </k> requires notBool (#accountExists(AUTHORITY) orBool #asWord(NONCE) ==Int 0)
rule <k> #addAuthority(AUTHORITY, _CID, NONCE, _ADDR, REST, W, NB, T) => #loadAuthorities(REST, W, NB, T) ... </k>
requires notBool (#accountExists(AUTHORITY) orBool #asWord(NONCE) ==Int 0)
```

- `exception` only clears from the `<k>` cell if there is an exception preceding it.
Expand Down
Loading