Skip to content

EIP 7702 Implement SetCode transactions #2755

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
132 changes: 114 additions & 18 deletions kevm-pyk/src/kevm_pyk/kproj/evm-semantics/driver.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
syntax EthereumCommand ::= loadTx ( Account ) [symbol(loadTx)]
// --------------------------------------------------------------
rule <k> loadTx(_) => startTx ... </k>
<statusCode> _ => EVMC_OUT_OF_GAS </statusCode>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change looks good, but I think this tule was removed in https://github.com/runtimeverification/evm-semantics/pull/2756/files. Which one is the latest version, I think the EIP-7623's one?

<statusCode> _ => EVMC_INVALID_BLOCK </statusCode>
<txPending> ListItem(TXID:Int) REST => REST </txPending>
<schedule> SCHED </schedule>
<message>
Expand All @@ -132,6 +132,7 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
=> #accessAccounts ACCTFROM #newAddr(ACCTFROM, NONCE) #precompiledAccountsSet(SCHED)
~> #deductBlobGas
~> #loadAccessList(TA)
~> #loadAuthorities(AUTH)
~> #checkCreate ACCTFROM VALUE
~> #create ACCTFROM #newAddr(ACCTFROM, NONCE) VALUE CODE
~> #finishTx ~> #finalizeTx(false) ~> startTx
Expand All @@ -145,12 +146,13 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
<txPending> ListItem(TXID:Int) ... </txPending>
<coinbase> MINER </coinbase>
<message>
<msgID> TXID </msgID>
<txGasLimit> GLIMIT </txGasLimit>
<to> .Account </to>
<value> VALUE </value>
<data> CODE </data>
<txAccess> TA </txAccess>
<msgID> TXID </msgID>
<txGasLimit> GLIMIT </txGasLimit>
<to> .Account </to>
<value> VALUE </value>
<data> CODE </data>
<txAccess> TA </txAccess>
<txAuthList> AUTH </txAuthList>
...
</message>
<account>
Expand All @@ -169,6 +171,7 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
=> #accessAccounts ACCTFROM ACCTTO #precompiledAccountsSet(SCHED)
~> #deductBlobGas
~> #loadAccessList(TA)
~> #loadAuthorities(AUTH)
~> #checkCall ACCTFROM VALUE
~> #call ACCTFROM ACCTTO ACCTTO VALUE VALUE DATA false
~> #finishTx ~> #finalizeTx(false) ~> startTx
Expand All @@ -189,6 +192,7 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
<data> DATA </data>
<txAccess> TA </txAccess>
<txVersionedHashes> TVH </txVersionedHashes>
<txAuthList> AUTH </txAuthList>
...
</message>
<versionedHashes> _ => TVH </versionedHashes>
Expand All @@ -203,18 +207,8 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
requires ACCTTO =/=K .Account
andBool #isValidTransaction(TXID, ACCTFROM)

rule <k> loadTx(ACCTFROM) => startTx ... </k>
<statusCode> _ => EVMC_INVALID_BLOCK </statusCode>
<txPending> ListItem(_TXID:Int) REST => REST </txPending>
<account>
<acctID> ACCTFROM </acctID>
<code> ACCTCODE </code>
...
</account>
requires notBool ACCTCODE ==K .Bytes

rule <k> loadTx(_) => startTx ... </k>
<statusCode> _ => EVMC_OUT_OF_GAS </statusCode>
<statusCode> _ => EVMC_INVALID_BLOCK </statusCode>
<txPending> ListItem(_TXID:Int) REST => REST </txPending> [owise]

syntax EthereumCommand ::= "#finishTx"
Expand Down Expand Up @@ -275,6 +269,93 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
<callGas> GLIMIT => GLIMIT -Int Gaccesslistaddress < SCHED > </callGas>
```

Processing SetCode Transaction Authority Entries
================================================

- The `#loadAuthorities` function processes the list of authorization entries in EIP-7702 SetCode transactions.
- First rule skips processing if transaction is not SetCode type or the auth list is empty.
- Second rule processes each authorization entry by recovering the signer, adding delegation, and continuing with remaining entries.
- The `#addAuthority` function implements the EIP's verification steps:
- Verifies chain ID matches (or is 0)
- Verifies the authority account's nonce matches authorization
- Sets delegation code (0xEF0100 + address) or clears it if address is 0
- Increments the authority's nonce
- Provides gas refund for non-empty accounts
- Creates new accounts when needed

```k
syntax InternalOp ::= #loadAuthorities ( List ) [symbol(#loadAuthorities)]
// --------------------------------------------------------------------------
rule <k> #loadAuthorities(_) => .K ... </k>
<txPending> ListItem(TXID:Int) ... </txPending>
<message>
<msgID> TXID </msgID>
<txType> TXTYPE </txType>
...
</message>
requires notBool TXTYPE ==K SetCode

rule <k> #loadAuthorities( .List ) => .K ... </k>
<txPending> ListItem(TXID:Int) ... </txPending>
<message>
<msgID> TXID </msgID>
<txType> SetCode </txType>
...
</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)
... </k>
<txPending> ListItem(TXID:Int) ... </txPending>
<message>
<msgID> TXID </msgID>
<txType> SetCode </txType>
...
</message>
<callGas> GLIMIT => GLIMIT -Int 25000 </callGas> [owise]

syntax InternalOp ::= #setDelegation ( Account , Bytes , Bytes , Bytes ) [symbol(#setDelegation)]
// -------------------------------------------------------------------------------------------------
rule <k> #setDelegation(.Account , _, _, _) => .K ... </k>

rule <k> #setDelegation(AUTHORITY, CID, _NONCE, _ADDR) => .K ... </k> <chainID> ENV_CID </chainID>
requires notBool AUTHORITY ==K .Account
andBool notBool #asWord(CID) in (SetItem(ENV_CID) SetItem(0))

rule <k> #setDelegation(AUTHORITY, CID, NONCE, ADDR)
=> #let EXISTS = #accountExists(AUTHORITY)
#in (#if EXISTS #then .K #else #newAccount AUTHORITY #fi
~> #touchAccounts AUTHORITY ~> #accessAccounts AUTHORITY
~> #addAuthority(AUTHORITY, CID, NONCE, ADDR, EXISTS))
...
</k> [owise]

syntax InternalOp ::= #addAuthority ( Account , Bytes , Bytes , Bytes , Bool) [symbol(#addAuthority)]
// -----------------------------------------------------------------------------------------------------
rule <k> #addAuthority(AUTHORITY, _CID, NONCE, _ADDR, _EXISTS) => .K ... </k>
<account>
<acctID> AUTHORITY </acctID>
<code> ACCTCODE </code>
<nonce> ACCTNONCE </nonce>
...
</account>
requires notBool (ACCTCODE ==K .Bytes orBool #isValidDelegation(ACCTCODE))
orBool notBool (#asWord(NONCE) ==K ACCTNONCE)

rule <k> #addAuthority(AUTHORITY, _CID, NONCE, ADDR, EXISTS) => .K ... </k>
<schedule> SCHED </schedule>
<refund> REFUND => #if EXISTS #then REFUND +Int Gnewaccount < SCHED > -Int Gauthbase < SCHED > #else REFUND #fi </refund>
<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 (ACCTCODE ==K .Bytes orBool #isValidDelegation(ACCTCODE))
andBool #asWord(NONCE) ==K ACCTNONCE
```

- `exception` only clears from the `<k>` cell if there is an exception preceding it.
- `failure_` holds the name of a test that failed if a test does fail.
- `success` sets the `<exit-code>` to `0` and the `<mode>` to `SUCCESS`.
Expand Down Expand Up @@ -654,6 +735,21 @@ Here we check the other post-conditions associated with an EVM test.
rule <k> check "transactions" : ("maxFeePerBlobGas" : VALUE) => .K ... </k> <txOrder> ListItem(TXID) ... </txOrder> <message> <msgID> TXID </msgID> <txMaxBlobFee> VALUE </txMaxBlobFee> ... </message>
rule <k> check "transactions" : ("sender" : VALUE) => .K ... </k> <txOrder> ListItem(TXID) ... </txOrder> <message> <msgID> TXID </msgID> <sigV> TW </sigV> <sigR> TR </sigR> <sigS> TS </sigS> ... </message> <chainID> B </chainID> requires #sender( #getTxData(TXID), TW, TR, TS, B ) ==K VALUE

rule <k> check "transactions" : "authorizationList" : [ .JSONs ] => .K ... </k>
rule <k> check "transactions" : "authorizationList" : [ { "chainId": CID, "address": ADDR, "nonce": NONCE, "v": _, "r": SIGR, "s": SIGS, "signer": _, "yParity": SIGY } , REST ]
=> check "transactions" : "authorizationList" : [ #hex2Bytes(CID), #hex2Bytes(ADDR), #hex2Bytes(NONCE), #hex2Bytes(SIGY), #hex2Bytes(SIGR), #hex2Bytes(SIGS) ]
~> check "transactions" : "authorizationList" : [ REST ]
...
</k>
rule <k> check "transactions" : "authorizationList" : [ AUTH ] => .K ... </k>
<txOrder> ListItem(TXID) ... </txOrder>
<message> <msgID> TXID </msgID> <txAuthList> AUTHLIST </txAuthList> ... </message> requires #parseJSONs2List(AUTH) in AUTHLIST

syntax Bytes ::= #hex2Bytes ( String ) [function] //TODO: Is this needed?
// -------------------------------------------------
rule #hex2Bytes("0x00") => b""
rule #hex2Bytes(S) => #parseByteStack(S) [owise]

syntax Bool ::= isInAccessListStorage ( Int , JSON ) [symbol(isInAccessListStorage), function]
| isInAccessList ( Account , Int , JSON ) [symbol(isInAccessList), function]
// -------------------------------------------------------------------------------------------------
Expand Down
11 changes: 7 additions & 4 deletions kevm-pyk/src/kevm_pyk/kproj/evm-semantics/evm-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -443,30 +443,33 @@ Productions related to transactions
| "AccessList"
| "DynamicFee"
| "Blob"
// ------------------------
| "SetCode"
// ---------------------------

syntax Int ::= #dasmTxPrefix ( TxType ) [symbol(#dasmTxPrefix), function]
// -------------------------------------------------------------------------
rule #dasmTxPrefix (Legacy) => 0
rule #dasmTxPrefix (AccessList) => 1
rule #dasmTxPrefix (DynamicFee) => 2
rule #dasmTxPrefix (Blob) => 3
rule #dasmTxPrefix (SetCode) => 4

syntax TxType ::= #asmTxPrefix ( Int ) [symbol(#asmTxPrefix), function]
// -----------------------------------------------------------------------
rule #asmTxPrefix (0) => Legacy
rule #asmTxPrefix (1) => AccessList
rule #asmTxPrefix (2) => DynamicFee
rule #asmTxPrefix (3) => Blob
rule #asmTxPrefix (4) => SetCode

syntax TxData ::= LegacyTx | AccessListTx | DynamicFeeTx | BlobTx
// -----------------------------------------------------------------

syntax TxData ::= LegacyTx | AccessListTx | DynamicFeeTx | BlobTx | SetCodeTx
// -----------------------------------------------------------------------------
syntax LegacyTx ::= LegacyTxData ( nonce: Int, gasPrice: Int, gasLimit: Int, to: Account, value: Int, data: Bytes ) [symbol(LegacyTxData)]
| LegacySignedTxData ( nonce: Int, gasPrice: Int, gasLimit: Int, to: Account, value: Int, data: Bytes, networkChainId: Int ) [symbol(LegacySignedTxData)]
syntax AccessListTx ::= AccessListTxData ( nonce: Int, gasPrice: Int, gasLimit: Int, to: Account, value: Int, data: Bytes, chainId: Int, accessLists: JSONs ) [symbol(AccessListTxData)]
syntax DynamicFeeTx ::= DynamicFeeTxData ( nonce: Int, priorityGasFee: Int, maxGasFee: Int, gasLimit: Int, to: Account, value: Int, data: Bytes, chainId: Int, accessLists: JSONs) [symbol(DynamicFeeTxData)]
syntax BlobTx ::= BlobTxData ( nonce: Int, priorityGasFee: Int, maxGasFee: Int, gasLimit: Int, to: Account, value: Int, data: Bytes, chainId: Int, accessLists: JSONs, maxBlobGasFee: Int, blobVersionedHashes: List ) [symbol(BlobTxData)]
syntax SetCodeTx ::= SetCodeTxData ( nonce: Int, priorityGasFee: Int, maxGasFee: Int, gasLimit: Int, to: Account, value: Int, data: Bytes, chainId: Int, accessLists: JSONs, authorizationList: List) [symbol(SetCodeTxData)]
// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

endmodule
Expand Down
Loading
Loading