@@ -120,6 +120,7 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
120
120
=> #accessAccounts ACCTFROM #newAddr(ACCTFROM, NONCE) #precompiledAccountsSet(SCHED)
121
121
~> #deductBlobGas
122
122
~> #loadAccessList(TA)
123
+ ~> #loadAuthorities(AUTH)
123
124
~> #checkCreate ACCTFROM VALUE
124
125
~> #create ACCTFROM #newAddr(ACCTFROM, NONCE) VALUE CODE
125
126
~> #finishTx ~> #finalizeTx(false, Ctxfloor(SCHED, CODE)) ~> startTx
@@ -133,12 +134,13 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
133
134
<txPending> ListItem(TXID:Int) ... </txPending>
134
135
<coinbase> MINER </coinbase>
135
136
<message>
136
- <msgID> TXID </msgID>
137
- <txGasLimit> GLIMIT </txGasLimit>
138
- <to> .Account </to>
139
- <value> VALUE </value>
140
- <data> CODE </data>
141
- <txAccess> TA </txAccess>
137
+ <msgID> TXID </msgID>
138
+ <txGasLimit> GLIMIT </txGasLimit>
139
+ <to> .Account </to>
140
+ <value> VALUE </value>
141
+ <data> CODE </data>
142
+ <txAccess> TA </txAccess>
143
+ <txAuthList> AUTH </txAuthList>
142
144
...
143
145
</message>
144
146
<account>
@@ -157,6 +159,7 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
157
159
=> #accessAccounts ACCTFROM ACCTTO #precompiledAccountsSet(SCHED)
158
160
~> #deductBlobGas
159
161
~> #loadAccessList(TA)
162
+ ~> #loadAuthorities(AUTH)
160
163
~> #checkCall ACCTFROM VALUE
161
164
~> #call ACCTFROM ACCTTO ACCTTO VALUE VALUE DATA false
162
165
~> #finishTx ~> #finalizeTx(false, Ctxfloor(SCHED, DATA)) ~> startTx
@@ -177,6 +180,7 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
177
180
<data> DATA </data>
178
181
<txAccess> TA </txAccess>
179
182
<txVersionedHashes> TVH </txVersionedHashes>
183
+ <txAuthList> AUTH </txAuthList>
180
184
...
181
185
</message>
182
186
<versionedHashes> _ => TVH </versionedHashes>
@@ -193,7 +197,7 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
193
197
andBool GLIMIT >=Int maxInt(G0(SCHED, DATA, false), Ctxfloor(SCHED, DATA))
194
198
195
199
rule <k> loadTx(_) => startTx ... </k>
196
- <statusCode> _ => EVMC_OUT_OF_GAS </statusCode>
200
+ <statusCode> _ => EVMC_INVALID_BLOCK </statusCode>
197
201
<txPending> ListItem(_TXID:Int) REST => REST </txPending> [owise]
198
202
199
203
syntax EthereumCommand ::= "#finishTx"
@@ -254,6 +258,106 @@ To do so, we'll extend sort `JSON` with some EVM specific syntax, and provide a
254
258
<callGas> GLIMIT => GLIMIT -Int Gaccesslistaddress < SCHED > </callGas>
255
259
```
256
260
261
+ Processing SetCode Transaction Authority Entries
262
+ ================================================
263
+
264
+ - The ` #loadAuthorities ` function processes authorization entries in EIP-7702 SetCode transactions, charging 25000 gas per tuple regardless of validity.
265
+ - Skips processing if transaction is not SetCode type; processes each authorization tuple by recovering the signer and attempting delegation.
266
+ - The ` #addAuthority ` function implements EIP-7702 verification and delegation:
267
+ - Validates that the chain ID matches current chain (or is 0) and nonce is within bounds
268
+ - Checks if authority account code is empty or already delegated
269
+ - Verifies that the authority nonce equals authorization nonce
270
+ - Sets delegation code (0xEF0100 + address) and increments nonce on success
271
+ - Provides refund (25000 - 12500 = 12500 gas) only for accounts that existed before processing
272
+ - A new account will be created for Authorities that are not in the ` <accounts> ` state, without increasing the refund amount
273
+
274
+ ``` k
275
+ syntax InternalOp ::= #loadAuthorities ( List ) [symbol(#loadAuthorities)]
276
+ // --------------------------------------------------------------------------
277
+ rule <k> #loadAuthorities(_) => .K ... </k>
278
+ <txPending> ListItem(TXID:Int) ... </txPending>
279
+ <message>
280
+ <msgID> TXID </msgID>
281
+ <txType> TXTYPE </txType>
282
+ ...
283
+ </message>
284
+ requires notBool TXTYPE ==K SetCode
285
+
286
+ rule <k> #loadAuthorities( .List ) => .K ... </k>
287
+ <txPending> ListItem(TXID:Int) ... </txPending>
288
+ <message>
289
+ <msgID> TXID </msgID>
290
+ <txType> SetCode </txType>
291
+ ...
292
+ </message>
293
+
294
+ rule <k> #loadAuthorities (ListItem(ListItem(CID) ListItem(ADDR) ListItem(NONCE) ListItem(YPAR) ListItem(SIGR) ListItem(SIGS)) REST )
295
+ => #setDelegation (#recoverAuthority (CID, ADDR, NONCE, YPAR, SIGR, SIGS ), CID, NONCE, ADDR)
296
+ ~> #loadAuthorities (REST)
297
+ ... </k>
298
+ <txPending> ListItem(TXID:Int) ... </txPending>
299
+ <message>
300
+ <msgID> TXID </msgID>
301
+ <txType> SetCode </txType>
302
+ ...
303
+ </message>
304
+ <callGas> GLIMIT => GLIMIT -Int 25000 </callGas> [owise]
305
+
306
+ syntax InternalOp ::= #setDelegation ( Account , Bytes , Bytes , Bytes ) [symbol(#setDelegation)]
307
+ // -------------------------------------------------------------------------------------------------
308
+ rule <k> #setDelegation(AUTHORITY, CID, NONCE, _ADDR) => .K ... </k> <chainID> ENV_CID </chainID>
309
+ requires AUTHORITY ==K .Account
310
+ orBool (notBool #asWord(CID) in (SetItem(ENV_CID) SetItem(0)))
311
+ orBool (#asWord(NONCE) >=Int maxUInt64)
312
+
313
+ rule <k> #setDelegation(AUTHORITY, CID, NONCE, ADDR)
314
+ => #touchAccounts AUTHORITY ~> #accessAccounts AUTHORITY
315
+ ~> #addAuthority(AUTHORITY, CID, NONCE, ADDR)
316
+ ...
317
+ </k> [owise]
318
+
319
+ syntax InternalOp ::= #addAuthority ( Account , Bytes , Bytes , Bytes ) [symbol(#addAuthority)]
320
+ // -----------------------------------------------------------------------------------------------
321
+ rule <k> #addAuthority(AUTHORITY, _CID, NONCE, _ADDR) => .K ... </k>
322
+ <account>
323
+ <acctID> AUTHORITY </acctID>
324
+ <code> ACCTCODE </code>
325
+ <nonce> ACCTNONCE </nonce>
326
+ ...
327
+ </account>
328
+ requires notBool (ACCTCODE ==K .Bytes orBool #isValidDelegation(ACCTCODE))
329
+ orBool (notBool #asWord(NONCE) ==K ACCTNONCE)
330
+
331
+ rule <k> #addAuthority(AUTHORITY, _CID, NONCE, ADDR) => .K ... </k>
332
+ <schedule> SCHED </schedule>
333
+ <refund> REFUND => REFUND +Int Gnewaccount < SCHED > -Int Gauthbase < SCHED > </refund>
334
+ <account>
335
+ <acctID> AUTHORITY </acctID>
336
+ <code> ACCTCODE => #if #asWord(ADDR) ==Int 0 #then .Bytes #else EOA_DELEGATION_MARKER +Bytes ADDR #fi </code>
337
+ <nonce> ACCTNONCE => ACCTNONCE +Int 1 </nonce>
338
+ ...
339
+ </account>
340
+ requires (ACCTCODE ==K .Bytes orBool #isValidDelegation(ACCTCODE))
341
+ andBool #asWord(NONCE) ==K ACCTNONCE
342
+
343
+ rule <k> #addAuthority(AUTHORITY, _CID, NONCE, ADDR) => .K ... </k>
344
+ <accounts>
345
+ ( .Bag
346
+ =>
347
+ <account>
348
+ <acctID> AUTHORITY </acctID>
349
+ <code> #if #asWord(ADDR) ==Int 0 #then .Bytes #else EOA_DELEGATION_MARKER +Bytes ADDR #fi </code>
350
+ <nonce> 1 </nonce>
351
+ ...
352
+ </account>
353
+ )
354
+ ...
355
+ </accounts>
356
+ requires #asWord(NONCE) ==Int 0 andBool notBool #accountExists(AUTHORITY)
357
+
358
+ rule <k> #addAuthority(AUTHORITY, _CID, NONCE, _ADDR) => .K ... </k> requires notBool (#accountExists(AUTHORITY) orBool #asWord(NONCE) ==Int 0)
359
+ ```
360
+
257
361
- ` exception ` only clears from the ` <k> ` cell if there is an exception preceding it.
258
362
- ` failure_ ` holds the name of a test that failed if a test does fail.
259
363
- ` success ` sets the ` <exit-code> ` to ` 0 ` and the ` <mode> ` to ` SUCCESS ` .
@@ -633,6 +737,21 @@ Here we check the other post-conditions associated with an EVM test.
633
737
rule <k> check "transactions" : ("maxFeePerBlobGas" : VALUE) => .K ... </k> <txOrder> ListItem(TXID) ... </txOrder> <message> <msgID> TXID </msgID> <txMaxBlobFee> VALUE </txMaxBlobFee> ... </message>
634
738
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
635
739
740
+ rule <k> check "transactions" : "authorizationList" : [ .JSONs ] => .K ... </k>
741
+ rule <k> check "transactions" : "authorizationList" : [ { "chainId": CID, "address": ADDR, "nonce": NONCE, "v": _, "r": SIGR, "s": SIGS, "signer": _, "yParity": SIGY } , REST ]
742
+ => check "transactions" : "authorizationList" : [ #hex2Bytes(CID), #hex2Bytes(ADDR), #hex2Bytes(NONCE), #hex2Bytes(SIGY), #hex2Bytes(SIGR), #hex2Bytes(SIGS) ]
743
+ ~> check "transactions" : "authorizationList" : [ REST ]
744
+ ...
745
+ </k>
746
+ rule <k> check "transactions" : "authorizationList" : [ AUTH ] => .K ... </k>
747
+ <txOrder> ListItem(TXID) ... </txOrder>
748
+ <message> <msgID> TXID </msgID> <txAuthList> AUTHLIST </txAuthList> ... </message> requires #parseJSONs2List(AUTH) in AUTHLIST
749
+
750
+ syntax Bytes ::= #hex2Bytes ( String ) [function] //TODO: Is this needed?
751
+ // -------------------------------------------------
752
+ rule #hex2Bytes("0x00") => b""
753
+ rule #hex2Bytes(S) => #parseByteStack(S) [owise]
754
+
636
755
syntax Bool ::= isInAccessListStorage ( Int , JSON ) [symbol(isInAccessListStorage), function]
637
756
| isInAccessList ( Account , Int , JSON ) [symbol(isInAccessList), function]
638
757
// -------------------------------------------------------------------------------------------------
0 commit comments