zkevm-rom 0.0.1-security → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of zkevm-rom might be problematic. Click here for more details.

Files changed (232) hide show
  1. package/.eslintrc.js +33 -0
  2. package/.github/CODEOWNERS +14 -0
  3. package/.github/ISSUE_TEMPLATE/bug.yml +38 -0
  4. package/.github/ISSUE_TEMPLATE/feature.yml +26 -0
  5. package/.github/ISSUE_TEMPLATE/question.yml +26 -0
  6. package/.github/workflows/main.yaml +40 -0
  7. package/LICENSE +636 -0
  8. package/README.md +23 -5
  9. package/audits/Hexens_Polygon_zkEVM_PUBLIC_27.02.23.pdf +0 -0
  10. package/audits/Polygon-zkEVM-Public-v1.1-verichains-19-03-2024.pdf +0 -0
  11. package/audits/zkEVM-ROM-upgrade-1-Spearbit-30-May.pdf +0 -0
  12. package/audits/zkEVM-ROM-upgrade-2-Spearbit-21-August.pdf +0 -0
  13. package/audits/zkEVM-engagement-1-Spearbit-27-March.pdf +0 -0
  14. package/audits/zkEVM-engagement-2-Spearbit-27-March.pdf +0 -0
  15. package/audits/zkEVM-engagement-3-Spearbit-6-April.pdf +0 -0
  16. package/counters/README.md +45 -0
  17. package/counters/counters-executor.js +80 -0
  18. package/counters/countersConstants.zkasm +370 -0
  19. package/counters/endIncludes.zkasm +18 -0
  20. package/counters/initIncludes.zkasm +2 -0
  21. package/counters/tests/MLOAD32.zkasm +27 -0
  22. package/counters/tests/MLOADX.zkasm +30 -0
  23. package/counters/tests/MSTORE32.zkasm +32 -0
  24. package/counters/tests/MSTOREX.zkasm +36 -0
  25. package/counters/tests/SHLarith.zkasm +28 -0
  26. package/counters/tests/SHLarithBit.zkasm +28 -0
  27. package/counters/tests/SHRarith.zkasm +28 -0
  28. package/counters/tests/SHRarithBit.zkasm +28 -0
  29. package/counters/tests/abs.zkasm +29 -0
  30. package/counters/tests/addBatchHashByteByByte.zkasm +31 -0
  31. package/counters/tests/computeGasSendCall.zkasm +30 -0
  32. package/counters/tests/divArith.zkasm +27 -0
  33. package/counters/tests/expAD.zkasm +30 -0
  34. package/counters/tests/getLenBits.zkasm +30 -0
  35. package/counters/tests/getLenBytes.zkasm +32 -0
  36. package/counters/tests/isEmptyAccount.zkasm +30 -0
  37. package/counters/tests/mulARITH.zkasm +28 -0
  38. package/counters/tests/offsetUtil.zkasm +29 -0
  39. package/counters/tests/opADDMOD.zkasm +28 -0
  40. package/counters/tests/opAdd.zkasm +27 -0
  41. package/counters/tests/opBLOCKHASH.zkasm +28 -0
  42. package/counters/tests/opCALL.zkasm +41 -0
  43. package/counters/tests/opCALLCODE.zkasm +41 -0
  44. package/counters/tests/opCALLDATACOPY.zkasm +28 -0
  45. package/counters/tests/opCALLDATALOAD.zkasm +27 -0
  46. package/counters/tests/opCODECOPY.zkasm +28 -0
  47. package/counters/tests/opCREATE.zkasm +35 -0
  48. package/counters/tests/opCREATE2.zkasm +35 -0
  49. package/counters/tests/opDELEGATECALL.zkasm +35 -0
  50. package/counters/tests/opDIV.zkasm +27 -0
  51. package/counters/tests/opEXP.zkasm +29 -0
  52. package/counters/tests/opEXTCODECOPY.zkasm +29 -0
  53. package/counters/tests/opMOD.zkasm +27 -0
  54. package/counters/tests/opMUL.zkasm +27 -0
  55. package/counters/tests/opMULMOD.zkasm +28 -0
  56. package/counters/tests/opRETURN.zkasm +32 -0
  57. package/counters/tests/opRETURNDATACOPY.zkasm +29 -0
  58. package/counters/tests/opREVERT.zkasm +32 -0
  59. package/counters/tests/opSDIV.zkasm +28 -0
  60. package/counters/tests/opSHA3.zkasm +28 -0
  61. package/counters/tests/opSIGNEXTEND.zkasm +27 -0
  62. package/counters/tests/opSMOD.zkasm +28 -0
  63. package/counters/tests/opSTATICCALL.zkasm +35 -0
  64. package/counters/tests/opSUB.zkasm +27 -0
  65. package/counters/tests/saveMem.zkasm +31 -0
  66. package/docs/opcode-cost-zk-counters.md +315 -0
  67. package/docs/usage-ecrecover.md +51 -0
  68. package/index.js +43 -0
  69. package/main/block-info.zkasm +204 -0
  70. package/main/constants.zkasm +145 -0
  71. package/main/ecrecover/addFpEc.zkasm +31 -0
  72. package/main/ecrecover/checkSqrtFpEc.zkasm +1558 -0
  73. package/main/ecrecover/constEc.zkasm +13 -0
  74. package/main/ecrecover/ecrecover.zkasm +280 -0
  75. package/main/ecrecover/invFnEc.zkasm +44 -0
  76. package/main/ecrecover/invFpEc.zkasm +45 -0
  77. package/main/ecrecover/mulFnEc.zkasm +36 -0
  78. package/main/ecrecover/mulFpEc.zkasm +36 -0
  79. package/main/ecrecover/mulPointEc.zkasm +311 -0
  80. package/main/ecrecover/sqFpEc.zkasm +38 -0
  81. package/main/ecrecover/sqrtFpEc.zkasm +70 -0
  82. package/main/end.zkasm +4 -0
  83. package/main/l2-tx-hash.zkasm +159 -0
  84. package/main/load-change-l2-block-utils.zkasm +11 -0
  85. package/main/load-change-l2-block.zkasm +28 -0
  86. package/main/load-tx-rlp-utils.zkasm +72 -0
  87. package/main/load-tx-rlp.zkasm +431 -0
  88. package/main/main.zkasm +237 -0
  89. package/main/map-opcodes.zkasm +274 -0
  90. package/main/modexp/array_lib/array_add_AGTB.zkasm +123 -0
  91. package/main/modexp/array_lib/array_add_short.zkasm +85 -0
  92. package/main/modexp/array_lib/array_div.zkasm +215 -0
  93. package/main/modexp/array_lib/array_div_long.zkasm +284 -0
  94. package/main/modexp/array_lib/array_div_short.zkasm +222 -0
  95. package/main/modexp/array_lib/array_mul.zkasm +97 -0
  96. package/main/modexp/array_lib/array_mul_long.zkasm +156 -0
  97. package/main/modexp/array_lib/array_mul_short.zkasm +127 -0
  98. package/main/modexp/array_lib/array_square.zkasm +246 -0
  99. package/main/modexp/array_lib/unused/array_add.zkasm +100 -0
  100. package/main/modexp/array_lib/unused/array_is_odd.zkasm +23 -0
  101. package/main/modexp/array_lib/unused/array_is_one.zkasm +33 -0
  102. package/main/modexp/array_lib/unused/array_is_zero.zkasm +34 -0
  103. package/main/modexp/array_lib/unused/array_sub_AGTB.zkasm +111 -0
  104. package/main/modexp/array_lib/unused/array_unshift.zkasm +37 -0
  105. package/main/modexp/array_lib/utils/array_compare.zkasm +82 -0
  106. package/main/modexp/array_lib/utils/array_trim.zkasm +49 -0
  107. package/main/modexp/constants.zkasm +5 -0
  108. package/main/modexp/modexp.zkasm +296 -0
  109. package/main/modexp/modexp_utils.zkasm +230 -0
  110. package/main/opcodes/arithmetic.zkasm +357 -0
  111. package/main/opcodes/block.zkasm +163 -0
  112. package/main/opcodes/calldata-returndata-code.zkasm +619 -0
  113. package/main/opcodes/comparison.zkasm +446 -0
  114. package/main/opcodes/context-information.zkasm +169 -0
  115. package/main/opcodes/create-terminate-context.zkasm +1011 -0
  116. package/main/opcodes/crypto.zkasm +96 -0
  117. package/main/opcodes/flow-control.zkasm +126 -0
  118. package/main/opcodes/logs.zkasm +193 -0
  119. package/main/opcodes/stack-operations.zkasm +658 -0
  120. package/main/opcodes/storage-memory.zkasm +313 -0
  121. package/main/pairings/BN254/addPointBN254.zkasm +245 -0
  122. package/main/pairings/BN254/ecAdd.zkasm +312 -0
  123. package/main/pairings/BN254/ecMul.zkasm +159 -0
  124. package/main/pairings/BN254/escalarMulBN254.zkasm +155 -0
  125. package/main/pairings/BN254/lineDiffPointsBN254.zkasm +83 -0
  126. package/main/pairings/BN254/lineSamePointsBN254.zkasm +96 -0
  127. package/main/pairings/FP12BN254/CYCLOFP12BN254/compressFp12BN254.zkasm +49 -0
  128. package/main/pairings/FP12BN254/CYCLOFP12BN254/decompressFp12BN254.zkasm +236 -0
  129. package/main/pairings/FP12BN254/CYCLOFP12BN254/expByXCompCycloFp12BN254.zkasm +444 -0
  130. package/main/pairings/FP12BN254/CYCLOFP12BN254/squareCompCycloFp12BN254.zkasm +212 -0
  131. package/main/pairings/FP12BN254/CYCLOFP12BN254/squareCycloFp12BN254.zkasm +228 -0
  132. package/main/pairings/FP12BN254/CYCLOFP12BN254/xBinDecompBN254.zkasm +64 -0
  133. package/main/pairings/FP12BN254/frob2Fp12BN254.zkasm +80 -0
  134. package/main/pairings/FP12BN254/frob3Fp12BN254.zkasm +96 -0
  135. package/main/pairings/FP12BN254/frobFp12BN254.zkasm +96 -0
  136. package/main/pairings/FP12BN254/inverseFp12BN254.zkasm +289 -0
  137. package/main/pairings/FP12BN254/mulFp12BN254.zkasm +408 -0
  138. package/main/pairings/FP12BN254/sparseMulAFp12BN254.zkasm +296 -0
  139. package/main/pairings/FP12BN254/sparseMulBFp12BN254.zkasm +291 -0
  140. package/main/pairings/FP12BN254/squareFp12BN254.zkasm +376 -0
  141. package/main/pairings/FP2BN254/addFp2BN254.zkasm +19 -0
  142. package/main/pairings/FP2BN254/escalarMulFp2BN254.zkasm +20 -0
  143. package/main/pairings/FP2BN254/invFp2BN254.zkasm +66 -0
  144. package/main/pairings/FP2BN254/mulFp2BN254.zkasm +19 -0
  145. package/main/pairings/FP2BN254/squareFp2BN254.zkasm +21 -0
  146. package/main/pairings/FP2BN254/subFp2BN254.zkasm +19 -0
  147. package/main/pairings/FP4BN254/squareFp4BN254.zkasm +76 -0
  148. package/main/pairings/FP6BN254/addFp6BN254.zkasm +59 -0
  149. package/main/pairings/FP6BN254/escalarMulFp6BN254.zkasm +51 -0
  150. package/main/pairings/FP6BN254/inverseFp6BN254.zkasm +208 -0
  151. package/main/pairings/FP6BN254/mulFp6BN254.zkasm +201 -0
  152. package/main/pairings/FP6BN254/sparseMulAFp6BN254.zkasm +65 -0
  153. package/main/pairings/FP6BN254/sparseMulBFp6BN254.zkasm +134 -0
  154. package/main/pairings/FP6BN254/sparseMulCFp6BN254.zkasm +128 -0
  155. package/main/pairings/FP6BN254/squareFp6BN254.zkasm +147 -0
  156. package/main/pairings/FP6BN254/subFp6BN254.zkasm +59 -0
  157. package/main/pairings/FPBN254/addFpBN254.zkasm +29 -0
  158. package/main/pairings/FPBN254/invFpBN254.zkasm +55 -0
  159. package/main/pairings/FPBN254/mulFpBN254.zkasm +29 -0
  160. package/main/pairings/FPBN254/reduceFpBN254.zkasm +25 -0
  161. package/main/pairings/FPBN254/squareFpBN254.zkasm +31 -0
  162. package/main/pairings/FPBN254/subFpBN254.zkasm +36 -0
  163. package/main/pairings/FRBN254/reduceFrBN254.zkasm +25 -0
  164. package/main/pairings/constants.zkasm +62 -0
  165. package/main/pairings/ecPairing.zkasm +244 -0
  166. package/main/pairings/finalExpBN254.zkasm +2095 -0
  167. package/main/pairings/halfPairingBN254.zkasm +428 -0
  168. package/main/pairings/loopLengthBN254.zkasm +75 -0
  169. package/main/pairings/millerLoopBN254.zkasm +741 -0
  170. package/main/pairings/pairingBN254.zkasm +481 -0
  171. package/main/pairings/unused/addFp12BN254.zkasm +130 -0
  172. package/main/pairings/unused/expByXCycloFp12BN254.zkasm +411 -0
  173. package/main/pairings/unused/expFp12BN254.zkasm +333 -0
  174. package/main/pairings/unused/subFp12BN254.zkasm +130 -0
  175. package/main/pairings/unused/xPseudoBinDecompBN254.zkasm +68 -0
  176. package/main/pairings/utilsTests/expCycloFp12BN254.zkasm +334 -0
  177. package/main/precompiled/end.zkasm +42 -0
  178. package/main/precompiled/identity.zkasm +99 -0
  179. package/main/precompiled/pre-ecAdd.zkasm +84 -0
  180. package/main/precompiled/pre-ecMul.zkasm +82 -0
  181. package/main/precompiled/pre-ecPairing.zkasm +72 -0
  182. package/main/precompiled/pre-ecrecover.zkasm +71 -0
  183. package/main/precompiled/pre-modexp.zkasm +367 -0
  184. package/main/precompiled/pre-sha2-256.zkasm +125 -0
  185. package/main/precompiled/revert-precompiled.zkasm +25 -0
  186. package/main/precompiled/selector.zkasm +77 -0
  187. package/main/process-change-l2-block.zkasm +147 -0
  188. package/main/process-tx.zkasm +587 -0
  189. package/main/tables/2-exp.zkasm +260 -0
  190. package/main/touched.zkasm +118 -0
  191. package/main/utils.zkasm +2335 -0
  192. package/main/vars.zkasm +117 -0
  193. package/package.json +62 -3
  194. package/test/bytes-length.zkasm +39 -0
  195. package/test/ecrecover.zkasm +538 -0
  196. package/test/lt4-test.zkasm +38 -0
  197. package/test/mstorex.zkasm +191 -0
  198. package/test/opcalldatacopy.ignore.zkasm +331 -0
  199. package/test/performance/read-push.zkasm +71 -0
  200. package/test/read-push.zkasm +304 -0
  201. package/test/testArrayArith.zkasm +1099 -0
  202. package/test/testArrayUtils.zkasm +335 -0
  203. package/test/testCycloFp12ArithBN254.zkasm +548 -0
  204. package/test/testEcAdd.zkasm +252 -0
  205. package/test/testEcMul.zkasm +231 -0
  206. package/test/testEcPairing.zkasm +436 -0
  207. package/test/testFinalExpBn254.zkasm +139 -0
  208. package/test/testFp12ArithBN254.zkasm +692 -0
  209. package/test/testFp2ArithBN254.zkasm +185 -0
  210. package/test/testFp4ArithBN254.zkasm +128 -0
  211. package/test/testFp6ArithBN254.zkasm +260 -0
  212. package/test/testFpArithBN254.zkasm +159 -0
  213. package/test/testFrArithBN254.zkasm +113 -0
  214. package/test/testHalfPairingBN254.zkasm +285 -0
  215. package/test/testModExp.zkasm +586 -0
  216. package/test/testModExpReturn.zkasm +81 -0
  217. package/test/testPairingBN254.zkasm +463 -0
  218. package/test/testPointArithBN254.zkasm +270 -0
  219. package/test/testSHA256.zkasm +27 -0
  220. package/test/touched-assert.zkasm +59 -0
  221. package/test/utils-expAD.zkasm +48 -0
  222. package/test/utils-getLenBytes.zkasm +36 -0
  223. package/tools/audit-tools/registry-op-checker.js +71 -0
  224. package/tools/get-not-used-labels.js +31 -0
  225. package/tools/helpers/helpers.js +47 -0
  226. package/tools/modexp-utils/README.md +5 -0
  227. package/tools/modexp-utils/modexp-test-gen.js +168 -0
  228. package/tools/modexp-utils/modexp-test-int.sage +37 -0
  229. package/tools/parallel-testing/checker.sh +6 -0
  230. package/tools/parallel-testing/gen-parallel-tests.js +78 -0
  231. package/tools/parallel-testing/parallel-tests-sample/sample.test.js +136 -0
  232. package/tools/run-tests-zkasm.js +83 -0
@@ -0,0 +1,1011 @@
1
+ /**
2
+ * @link [https://www.evm.codes/#00?fork=berlin]
3
+ * @zk-counters
4
+ * - 20 steps
5
+ * @process-opcode
6
+ * - stack input: none
7
+ * - stack output: none
8
+ */
9
+ opSTOP:
10
+ ; checks zk-counters
11
+ %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep)
12
+ ; check if first context
13
+ ; if origin ctx is 0, end tx
14
+ $ => B :MLOAD(originCTX), JMPZ(handleGas)
15
+ ; else handle finish ctx
16
+ $ => A :MLOAD(gasRefund)
17
+ ; check if is a create call
18
+ $ => C :MLOAD(isCreate)
19
+ ; set 1 to D, default stack return in stop code
20
+ 1 => D
21
+ C :JMPZ(opSTOPend)
22
+ ; if is a create, return created contract address
23
+ $ => D :MLOAD(createContractAddress)
24
+
25
+ opSTOPend:
26
+ ; move to origin ctx
27
+ B => CTX
28
+ CTX :MSTORE(currentCTX)
29
+ ; restore retDataCTX, no return data in stop
30
+ 0 :MSTORE(retDataCTX)
31
+ ; handle gas refund
32
+ $ => B :MLOAD(gasCTX)
33
+ A :MSTORE(gasRefund)
34
+ GAS + B => GAS
35
+ ; restore SP and PC from origin CTX
36
+ $ => SP :MLOAD(lastSP)
37
+ $ => PC :MLOAD(lastPC)
38
+ ; store stack output
39
+ D :MSTORE(SP++), JMP(readCode)
40
+
41
+ /**
42
+ * @link [https://www.evm.codes/#f0?fork=berlin]
43
+ * @zk-counters
44
+ * - 200 steps
45
+ * - 2 binary
46
+ * - %MAX_CNT_POSEIDON_SLOAD_SSTORE*3 poseidon
47
+ * @process-opcode
48
+ * - stack input: [value, offset, size]
49
+ * - stack output: [address]
50
+ */
51
+ opCREATE:
52
+ ; checks zk-counters
53
+ %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep)
54
+ %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary)
55
+ %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*3 :JMPN(outOfCountersPoseidon)
56
+
57
+ ; check out-of-gas
58
+ GAS - %CREATE_GAS => GAS :JMPN(outOfGas)
59
+ GAS :MSTORE(gasCall)
60
+
61
+ ; check stack underflow
62
+ SP - 3 :JMPN(stackUnderflow)
63
+ ; check is static
64
+ $ => A :MLOAD(isStaticCall), JMPNZ(invalidStaticTx)
65
+ SP - 1 => SP
66
+ $ => D :MLOAD(SP--); [value => D]
67
+ D :MSTORE(valueCall)
68
+ $ => E :MLOAD(SP--); [offset => E]
69
+ E :MSTORE(argsOffsetCall)
70
+ $ => C :MLOAD(SP); [size => C]
71
+ C :MSTORE(argsLengthCall)
72
+
73
+ ; store lastMemOffset for memory expansion gas cost
74
+ E :MSTORE(lastMemOffset)
75
+ ; store lastMemLength for memory expansion gas cost
76
+ ; compute memory expansion gas cost
77
+ C :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
78
+ ; store current CTX to auxiliary var for later usage
79
+ CTX :MSTORE(originAuxCTX)
80
+
81
+ ; check if source address has enough balance to send to the new account
82
+ $ => A :MLOAD(storageAddr)
83
+ ; set key for smt balance query
84
+ %SMT_KEY_BALANCE => B
85
+ ; 3rd parameter does not apply to nonce or balance
86
+ 0 => C
87
+ ; balance in A
88
+ $ => A :SLOAD
89
+ D => B
90
+ $ :LT,JMPC(opCreateFail)
91
+
92
+ ; check nonce overflow
93
+ $ => A :MLOAD(storageAddr)
94
+ ; set key for smt nonce query
95
+ %SMT_KEY_NONCE => B
96
+ ; nonce in B
97
+ $ => B :SLOAD
98
+ A => C
99
+ %MAX_NONCE => A
100
+ $ :EQ,JMPC(opCreateFail)
101
+
102
+ ;change to a new CTX
103
+ SP :MSTORE(lastSP)
104
+ PC :MSTORE(lastPC)
105
+ ; increase used contexts counter
106
+ $ => A :MLOAD(lastCtxUsed)
107
+ A+1 => CTX :MSTORE(lastCtxUsed)
108
+ CTX :MSTORE(currentCTX)
109
+ 1 :MSTORE(isCreateContract)
110
+ 1 :MSTORE(isCreate)
111
+ ; set origin CTX to this new CTX
112
+ $ => A :MLOAD(originAuxCTX)
113
+ A :MSTORE(originCTX)
114
+
115
+ ; get nonce and update SR
116
+ B :MSTORE(txNonce)
117
+ ; get nonce length bytes
118
+ :CALL(getLenBytes); in: [B: value] out: [A: value bytes length]
119
+ A :MSTORE(lengthNonce)
120
+ ; increase nonce
121
+ 1 => A
122
+ $ => D :ADD
123
+ C => A
124
+ ; set key for smt nonce query
125
+ %SMT_KEY_NONCE => B
126
+ 0 => C
127
+ $ => SR :SSTORE
128
+ ; compute gas send in call
129
+ SR :MSTORE(initSR), CALL(computeGasSendCall); in: [gasCall: gas sent to call] out: [A: min( requested_gas , all_but_one_64th(63/64))]
130
+ ; return to origin CTX to set storage addr, gasRefund and gasCTX
131
+ $ => CTX :MLOAD(originCTX)
132
+ $ => B :MLOAD(storageAddr)
133
+ $ => C :MLOAD(gasRefund)
134
+ GAS - A :MSTORE(gasCTX)
135
+ $ => CTX :MLOAD(currentCTX)
136
+ ; update GAS to computed gas send call
137
+ A => GAS
138
+ B :MSTORE(txSrcAddr)
139
+ C :MSTORE(gasRefund)
140
+ ; set CTX var values
141
+ $ => A :MLOAD(argsLengthCall)
142
+ ; set calldata pointers to current CTX
143
+ A :MSTORE(txCalldataLen), CALL(saveCalldataPointer)
144
+ $ => A :MLOAD(valueCall), CALL(checkpointBlockInfoTree)
145
+ ; Save touched root when a new context is created
146
+ A :MSTORE(txValue), CALL(checkpointTouched)
147
+ :JMP(txType)
148
+
149
+ opCreateFail:
150
+ ; return 0 if create fails
151
+ 0 :MSTORE(retDataCTX)
152
+ 0 :MSTORE(SP++), JMP(readCode); [0 => SP]
153
+
154
+ /**
155
+ * @link [https://www.evm.codes/#f1?fork=berlin]
156
+ * @zk-counters
157
+ * - 200 steps
158
+ * - 3 binary
159
+ * @process-opcode
160
+ * - stack input: [gas, address, value, argsOffset, argsSize, retOffset, retSize]
161
+ * - stack output: [success]
162
+ */
163
+ opCALL:
164
+
165
+ ; checks zk-counters
166
+ %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep)
167
+ %MAX_CNT_BINARY - CNT_BINARY - 3 :JMPN(outOfCountersBinary)
168
+ ; check stack underflow
169
+ SP - 7 :JMPN(stackUnderflow)
170
+ SP - 1 => SP
171
+ ; store current CTX to auxiliary var for later usage
172
+ CTX :MSTORE(originAuxCTX)
173
+ ; store gas call
174
+ $ => A :MLOAD(SP--); [gas => A]
175
+ A :MSTORE(gasCall)
176
+ $ => A :MLOAD(SP--), CALL(maskAddress); [address => A]; in: [A: address] out: [A: masked address]
177
+ ; store address call
178
+ ; Mask address to 20 bytes
179
+ A :MSTORE(addrCall)
180
+ ; store value call
181
+ $ => A :MLOAD(SP--); [value => A]
182
+ A :MSTORE(valueCall)
183
+ ; if is static and value is not 0 -> revert
184
+ $ => B :MLOAD(isStaticCall), JMPZ(opCALL2)
185
+ 0 => B
186
+ $ :EQ,JMPC(opCALL2, invalidStaticTx)
187
+
188
+ opCALL2:
189
+
190
+ ; store bytes offset int the memory, the calldata of the subcontext
191
+ $ => A :MLOAD(SP--); [argsOffset => A]
192
+ A :MSTORE(argsOffsetCall)
193
+ ; store lastMemOffset for memory expansion gas cost
194
+ A :MSTORE(lastMemOffset)
195
+
196
+ ; byte size to copy, size of the calldata of the subcontext
197
+ $ => C :MLOAD(SP--); [argsSize => C]
198
+ C :MSTORE(argsLengthCall)
199
+ ; store lastMemLength for memory expansion gas cost
200
+ C :MSTORE(lastMemLength)
201
+ ; compute memory expansion gas cost
202
+ :CALL(saveMem); in: [lastMemOffset, lastMemLength]
203
+
204
+ ; store byte offset in the memory in bytes, where to store the return data of the sub context
205
+ $ => B :MLOAD(SP--); [retOffset => B]
206
+ B :MSTORE(lastMemOffset)
207
+
208
+ ; store byte size to copy (size of the return data)
209
+ $ => D :MLOAD(SP); [retSize => D]
210
+ ; compute memory expansion gas cost of the return value
211
+ D :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
212
+ $ => B :MLOAD(lastMemOffset)
213
+ ; check if an address is cold. If it is, add it to the touched tree
214
+ $ => A :MLOAD(addrCall), CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold]
215
+
216
+ ;gas_cost = memory_expansion_cost + code_execution_cost + address_access_cost + positive_value_cost + value_to_empty_account_cost
217
+ ; Calculate address_access_cost: 100 for warm account, 2600 for cold account
218
+ GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas)
219
+ ; Calculate positive_value_cost, if value call > 0 -> 9000
220
+ $ => B :MLOAD(valueCall)
221
+ 0 => A
222
+ $ :EQ,JMPC(opCALLend)
223
+
224
+ GAS - %CALL_VALUE_TRANSFER_GAS => GAS :JMPN(outOfGas)
225
+ ; if destAddress is an empty account, we should add 25k of gas to base cost
226
+ $ => E :MLOAD(addrCall), CALL(isEmptyAccount); in: [E: address] out: [E: 0 if is not empty, 1 if is empty]
227
+ GAS - %CALL_NEW_ACCOUNT_GAS*E => GAS :JMPN(outOfGas)
228
+
229
+ opCALLend:
230
+ ; setup vars for next CTX
231
+ $ => B :MLOAD(lastMemOffset)
232
+ $ => D :MLOAD(lastMemLength)
233
+ $ => C :MLOAD(storageAddr)
234
+ $ => E :MLOAD(gasRefund)
235
+ SP :MSTORE(lastSP)
236
+ PC :MSTORE(lastPC)
237
+ ; increase CTX
238
+ $ => A :MLOAD(lastCtxUsed)
239
+ A+1 => CTX :MSTORE(lastCtxUsed)
240
+ CTX :MSTORE(currentCTX)
241
+ $ => A :MLOAD(originAuxCTX)
242
+ A :MSTORE(originCTX)
243
+ C :MSTORE(txSrcAddr)
244
+ E :MSTORE(gasRefund)
245
+ SR :MSTORE(initSR)
246
+ $ => A :MLOAD(addrCall)
247
+ A :MSTORE(txDestAddr)
248
+ A :MSTORE(storageAddr)
249
+ B :MSTORE(retCallOffset)
250
+ D :MSTORE(retCallLength)
251
+ $ => B :MLOAD(valueCall)
252
+ B :MSTORE(txValue)
253
+ 0 => A
254
+ ; compute gas send in call
255
+ $ => C :LT, CALL(computeGasSendCall); in: [gasCall: gas sent to call] out: [A: min( requested_gas , all_but_one_64th(63/64))]
256
+ $ => CTX :MLOAD(originCTX)
257
+ GAS - A :MSTORE(gasCTX)
258
+ ; add stipend (2300) in case of tx with value
259
+ A + %CALL_STIPEND*C => A
260
+ ; move is static bool value to following CTX
261
+ $ => D :MLOAD(isStaticCall)
262
+ $ => CTX :MLOAD(currentCTX)
263
+ D :MSTORE(isStaticCall)
264
+ ; update GAS to computed gas send call
265
+ A => GAS
266
+ $ => A :MLOAD(argsLengthCall)
267
+ ; set calldata pointers to current CTX
268
+ A :MSTORE(txCalldataLen), CALL(saveCalldataPointer)
269
+ ; save touched root when a new context is created
270
+ :CALL(checkpointTouched)
271
+ :CALL(checkpointBlockInfoTree)
272
+ :JMP(txType)
273
+
274
+ /**
275
+ * @link [https://www.evm.codes/#f1?fork=berlin]
276
+ * @zk-counters
277
+ * - 200 steps
278
+ * - 2 binary
279
+ * @process-opcode
280
+ * - stack input: [gas, address, value, argsOffset, argsSize, retOffset, retSize]
281
+ * - stack output: [success]
282
+ */
283
+ opCALLCODE:
284
+ ; checks zk-counters
285
+ %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep)
286
+ %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
287
+ ; check stack underflow
288
+ SP - 7 :JMPN(stackUnderflow)
289
+ SP - 1 => SP
290
+ ; store current CTX to auxiliary var for later usage
291
+ CTX :MSTORE(originAuxCTX)
292
+ ; store gas call
293
+ $ => A :MLOAD(SP--); [gas => A]
294
+ A :MSTORE(gasCall)
295
+ ; store address call
296
+ ; Mask address to 20 bytes
297
+ $ => A :MLOAD(SP--), CALL(maskAddress); [address => A]; in: [A: address] out: [A: masked address]
298
+ A :MSTORE(addrCall)
299
+ ; store value call
300
+ $ => A :MLOAD(SP--); [value => A]
301
+ A :MSTORE(valueCall)
302
+
303
+ ; store bytes offset int the memory, the calldata of the subcontext
304
+ $ => A :MLOAD(SP--); [argsOffset => A]
305
+ A :MSTORE(argsOffsetCall)
306
+ ; store lastMemOffset for memory expansion gas cost
307
+ A :MSTORE(lastMemOffset)
308
+ ; byte size to copy, size of the calldata of the subcontext
309
+ $ => C :MLOAD(SP--); [argsSize => C]
310
+ C :MSTORE(argsLengthCall)
311
+ ; store lastMemLength for memory expansion gas cost
312
+ ; compute memory expansion gas cost
313
+ C :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
314
+
315
+ ; Store byte offset in the memory in bytes, where to store the return data of the sub context.
316
+ $ => B :MLOAD(SP--); [retOffset => B]
317
+ B :MSTORE(lastMemOffset)
318
+ ; Store byte size to copy (size of the return data).
319
+ $ => D :MLOAD(SP); [retSize => D]
320
+ ; compute memory expansion gas cost of the return value
321
+ D :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
322
+ ; check if an address is cold. If it is, add it to the touched tree
323
+ $ => A :MLOAD(addrCall), CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold]
324
+
325
+ ;gas_cost = memory_expansion_cost + code_execution_cost + address_access_cost + positive_value_cost
326
+ ; Calculate address_access_cost: 100 for warm account, 2600 for cold account
327
+ GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas)
328
+ ; Calculate positive_value_cost, if value call > 0 -> 9000
329
+ $ => B :MLOAD(valueCall)
330
+ 0 => A
331
+ $ :EQ,JMPC(opCALLCODEend)
332
+ ; Subtract gas if the call has value
333
+ GAS - %CALL_VALUE_TRANSFER_GAS => GAS :JMPN(outOfGas)
334
+
335
+ opCALLCODEend:
336
+ ; setup vars for next CTX
337
+ $ => B :MLOAD(lastMemOffset)
338
+ $ => D :MLOAD(lastMemLength)
339
+ $ => E :MLOAD(storageAddr)
340
+ $ => C :MLOAD(gasRefund)
341
+ SP :MSTORE(lastSP)
342
+ PC :MSTORE(lastPC)
343
+ ; increase CTX
344
+ $ => A :MLOAD(lastCtxUsed)
345
+ A+1 => CTX :MSTORE(lastCtxUsed)
346
+ CTX :MSTORE(currentCTX)
347
+ $ => A :MLOAD(originAuxCTX)
348
+ A :MSTORE(originCTX)
349
+ E :MSTORE(txSrcAddr)
350
+ E :MSTORE(storageAddr)
351
+ C :MSTORE(gasRefund)
352
+ SR :MSTORE(initSR)
353
+ $ => A :MLOAD(addrCall)
354
+ A :MSTORE(txDestAddr)
355
+ B :MSTORE(retCallOffset)
356
+ D :MSTORE(retCallLength)
357
+ $ => B :MLOAD(valueCall)
358
+ B :MSTORE(txValue)
359
+ 0 => A
360
+ ; compute gas send in call
361
+ $ => C :LT, CALL(computeGasSendCall); in: [gasCall: gas sent to call] out: [A: min( requested_gas , all_but_one_64th(63/64))]
362
+ $ => CTX :MLOAD(originCTX)
363
+ GAS - A :MSTORE(gasCTX)
364
+ ; Add stipend (2300) in case of tx with value
365
+ A + %CALL_STIPEND*C => A
366
+ ; move is static bool value to following CTX
367
+ $ => D :MLOAD(isStaticCall)
368
+ $ => CTX :MLOAD(currentCTX)
369
+ ; update GAS to computed gas send call
370
+ A => GAS
371
+ D :MSTORE(isStaticCall)
372
+ $ => A :MLOAD(argsLengthCall)
373
+ ; set calldata pointers to current CTX
374
+ A :MSTORE(txCalldataLen), CALL(saveCalldataPointer)
375
+ ; Save touched root when a new context is created
376
+ :CALL(checkpointTouched)
377
+ :CALL(checkpointBlockInfoTree)
378
+ :JMP(txType)
379
+ /**
380
+ * @link [https://www.evm.codes/#f3?fork=berlin]
381
+ * @zk-counters
382
+ * - 400 steps
383
+ * - 1 binary
384
+ * @process-opcode
385
+ * - stack input: [offset, size]
386
+ * - stack output: none
387
+ */
388
+ opRETURN:
389
+ ; checks zk-counters
390
+ %MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep)
391
+ %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
392
+ ; check stack underflow
393
+ SP - 2 => SP :JMPN(stackUnderflow)
394
+ $ => E :MLOAD(SP+1); [offset => E]
395
+ $ => C :MLOAD(SP); [size => C]
396
+
397
+ ; store return data values
398
+ E :MSTORE(retDataOffset)
399
+ C :MSTORE(retDataLength)
400
+ ; store lastMemOffset for memory expansion gas cost
401
+ E :MSTORE(lastMemOffset)
402
+ ; store lastMemLength for memory expansion gas cost
403
+ ; compute memory expansion gas cost
404
+ C :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
405
+ ; check is a create
406
+ $ => D :MLOAD(isCreateContract), JMPNZ(opRETURNdeploy)
407
+ ; reduce CTX
408
+ ; if origin ctx is 0, end tx
409
+ $ => B :MLOAD(originCTX), JMPZ(handleGas)
410
+ ; handle gas refund
411
+ $ => B :MLOAD(gasRefund)
412
+ $ => A :MLOAD(currentCTX)
413
+ $ => CTX :MLOAD(originCTX)
414
+ ; set return data context values to origin context
415
+ A :MSTORE(retDataCTX)
416
+ B :MSTORE(gasRefund)
417
+ $ => B :MLOAD(gasCTX)
418
+ B + GAS => GAS
419
+ ; return to current CTX
420
+ $ => CTX :MLOAD(currentCTX)
421
+ $ => D :MLOAD(retCallLength)
422
+ C => A
423
+ D => B
424
+ ; set smallest return length between retCallLength and lastMemLength
425
+ $ :LT,JMPC(preRETURN32)
426
+ D => C
427
+
428
+ preRETURN32:
429
+ $ => B :MLOAD(retCallOffset)
430
+
431
+ ; Copy from memory current CTX to memory origin CTX
432
+ opRETURNloop:
433
+ ; checks dynamic zk-counters
434
+ %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep)
435
+
436
+ C :JMPZ(opRETURNend)
437
+ C - 32 :JMPN(opRETURNfinal)
438
+ ; load first 32 bytes from memory at current CTX
439
+ :CALL(MLOAD32); in: [E: offset] out: [A: value, E: new offset]
440
+ E => D
441
+ ; load origin CTX
442
+ $ => CTX :MLOAD(originCTX)
443
+ B => E
444
+ ; set bytesToStore with value to use in MSTORE
445
+ ; store 32 bytes at origin CTX
446
+ A :MSTORE(bytesToStore), CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset]
447
+ E => B
448
+ D => E
449
+ C - 32 => C
450
+ ; restore current TX
451
+ $ => CTX :MLOAD(currentCTX), JMP(opRETURNloop)
452
+
453
+ opRETURNfinal:
454
+ ; load last bytes
455
+ :CALL(MLOADX); in: [E: offset, C: length] out: [A: value, E: new offset]
456
+ $ => CTX :MLOAD(originCTX)
457
+ B => E
458
+ ; store last bytes
459
+ A :MSTORE(bytesToStore), CALL(MSTOREX); in: [bytesToStore, E: offset, C: length] out: [E: new offset]
460
+ $ => CTX :MLOAD(currentCTX)
461
+
462
+ opRETURNend:
463
+ ; decrease CTX
464
+ $ => CTX :MLOAD(originCTX)
465
+ CTX :MSTORE(currentCTX)
466
+ ; restore origin CTX values
467
+ $ => SP :MLOAD(lastSP)
468
+ $ => PC :MLOAD(lastPC)
469
+ 1 :MSTORE(SP++), JMP(readCode); [1 => SP]
470
+
471
+ opRETURNdeploy:
472
+ ; code size limit = 0x6000
473
+ %CODE_SIZE_LIMIT - C :JMPN(invalidCodeSize)
474
+ ;code_deposit_cost = 200 * returned_code_size
475
+ GAS - %RETURN_GAS_COST * C => GAS :JMPN(outOfGas)
476
+ ; check if first context
477
+ $ => B :MLOAD(originCTX), JMPNZ(opRETURNcreate, endDeploy)
478
+
479
+ opRETURNcreate:
480
+ ; checks zk-counters
481
+ %MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep)
482
+ %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*2 :JMPN(outOfCountersPoseidon)
483
+ %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
484
+ ; save offset memory and length to compute contract hash
485
+ E :MSTORE(memOffsetLinearPoseidon)
486
+ C :MSTORE(memSizeLinearPoseidon), CALL(checkBytecodeStartsEF) ; in: [memOffset], out: [startsWithEF]
487
+ ; check bytecode first byte != 0xEF
488
+ $ :MLOAD(startsWithEF), JMPNZ(invalidCodeStartsEF)
489
+ ; set bytecode length
490
+ ; set key for smt smart contract length query
491
+ $ => A :MLOAD(createContractAddress)
492
+ %SMT_KEY_SC_LENGTH => B
493
+ C => D
494
+ 0 => C
495
+ ; get bytecode and hash it
496
+ $ => SR :SSTORE, CALL(hashPoseidonLinearFromMemory); in: [memOffsetLinearPoseidon, memSizeLinearPoseidon], out: [D: resulting linear poseidon]
497
+ ; set key for smt smart contract bytecode query
498
+ %SMT_KEY_SC_CODE => B
499
+ $ => SR :SSTORE
500
+
501
+ opRETURNcreateEnd:
502
+
503
+ ; return to origin CTX
504
+ $ => B :MLOAD(gasRefund)
505
+ $ => CTX :MLOAD(originCTX)
506
+ ; Update gasRefund at origin CTX
507
+ B :MSTORE(gasRefund)
508
+ $ => B :MLOAD(gasCTX)
509
+ B + GAS => GAS
510
+ CTX :MSTORE(currentCTX)
511
+ 0 :MSTORE(retDataCTX)
512
+ ; set SP and PC
513
+ $ => SP :MLOAD(lastSP)
514
+ $ => PC :MLOAD(lastPC)
515
+ A :MSTORE(SP++), JMP(readCode); [createContractAddress(A) => SP]
516
+
517
+ /**
518
+ * @link [https://www.evm.codes/#f4?fork=berlin]
519
+ * @zk-counters
520
+ * - 400 steps
521
+ * @process-opcode
522
+ * - stack input: [gas, address, argsOffset, argsSize, retOffset, retSize]
523
+ * - stack output: [success]
524
+ */
525
+ opDELEGATECALL:
526
+ ; checks zk-counters
527
+ %MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep)
528
+
529
+ ; check stack underflow
530
+ SP - 6 :JMPN(stackUnderflow)
531
+ SP - 1 => SP
532
+ ; store current CTX to auxiliary var for later usage
533
+ CTX :MSTORE(originAuxCTX)
534
+ ; store gas call
535
+ $ => A :MLOAD(SP--); [gas => A]
536
+ A :MSTORE(gasCall)
537
+ ; store address call
538
+ $ => A :MLOAD(SP--); [address => A]
539
+ ; Mask address to 20 bytes
540
+ :CALL(maskAddress); in: [A: address] out: [A: masked address]
541
+ A :MSTORE(addrCall)
542
+ ; store bytes offset int the memory, the calldata of the subcontext
543
+ $ => A :MLOAD(SP--)
544
+ A :MSTORE(argsOffsetCall); [argsOffset => A]
545
+ ; store lastMemOffset for memory expansion gas cost
546
+ A :MSTORE(lastMemOffset)
547
+
548
+ ; byte size to copy, size of the calldata of the subcontext
549
+ $ => C :MLOAD(SP--); [argsSize => C]
550
+ C :MSTORE(argsLengthCall)
551
+ ; store lastMemLength for memory expansion gas cost
552
+ ; mem expansion gas cost call args
553
+ C :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
554
+
555
+ ; Store byte offset in the memory in bytes, where to store the return data of the sub context.
556
+ $ => B :MLOAD(SP--); [retOffset => B]
557
+ B :MSTORE(lastMemOffset)
558
+ ; Store byte size to copy (size of the return data).
559
+ $ => E :MLOAD(SP); [retSize => D]
560
+ ; Mem expansion gas cost return args
561
+ E :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
562
+ $ => B :MLOAD(lastMemOffset)
563
+ ; check if an address is cold. If it is, add it to the touched tree
564
+ $ => A :MLOAD(addrCall)
565
+ :CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold]
566
+ ;gas_cost = base_gas + gas_sent_with_call
567
+ GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas)
568
+
569
+ ; transition to new CTX
570
+ $ => C :MLOAD(txSrcAddr)
571
+ $ => D :MLOAD(storageAddr)
572
+ SP :MSTORE(lastSP)
573
+ PC :MSTORE(lastPC)
574
+ ; increase CTX
575
+ $ => A :MLOAD(lastCtxUsed)
576
+ A+1 => CTX :MSTORE(lastCtxUsed)
577
+ CTX :MSTORE(currentCTX)
578
+ $ => A :MLOAD(originAuxCTX)
579
+ A :MSTORE(originCTX)
580
+ ; set vars for new CTX
581
+ C :MSTORE(txSrcAddr)
582
+ D :MSTORE(storageAddr)
583
+ 1 :MSTORE(isDelegateCall)
584
+ SR :MSTORE(initSR)
585
+ $ => A :MLOAD(addrCall)
586
+ A :MSTORE(txDestAddr)
587
+ B :MSTORE(retCallOffset)
588
+ ; compute gas send in call
589
+ E :MSTORE(retCallLength), CALL(computeGasSendCall); in: [gasCall: gas sent to call] out: [A: min( requested_gas , all_but_one_64th(63/64))]
590
+ $ => CTX :MLOAD(originCTX)
591
+ GAS - A :MSTORE(gasCTX)
592
+ $ => B :MLOAD(txValue)
593
+ $ => C :MLOAD(gasRefund)
594
+ $ => D :MLOAD(isStaticCall)
595
+ $ => CTX :MLOAD(currentCTX)
596
+ D :MSTORE(isStaticCall)
597
+ B :MSTORE(txValue)
598
+ C :MSTORE(gasRefund)
599
+ A => GAS
600
+
601
+ opDELEGATECALLend:
602
+ $ => A :MLOAD(argsLengthCall)
603
+ ; set calldata pointers to current CTX
604
+ A :MSTORE(txCalldataLen), CALL(saveCalldataPointer)
605
+ ; Save touched root when a new context is created
606
+ :CALL(checkpointTouched)
607
+ :CALL(checkpointBlockInfoTree)
608
+ :JMP(txType)
609
+
610
+ /**
611
+ * @link [https://www.evm.codes/#f5?fork=berlin]
612
+ * @zk-counters
613
+ * - 400 steps
614
+ * - 3 binary
615
+ * - %MAX_CNT_POSEIDON_SLOAD_SSTORE*2 poseidon
616
+ * @process-opcode
617
+ * - stack input: [value, offset, size, salt]
618
+ * - stack output: [address]
619
+ */
620
+ opCREATE2:
621
+ ; checks zk-counters
622
+ %MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep)
623
+ %MAX_CNT_BINARY - CNT_BINARY - 5 :JMPN(outOfCountersBinary)
624
+ %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*2 :JMPN(outOfCountersPoseidon)
625
+ ; check out-of-gas
626
+ GAS - %CREATE_2_GAS => GAS :JMPN(outOfGas)
627
+
628
+ ; check stack underflow
629
+ SP - 4 :JMPN(stackUnderflow)
630
+ ; check is static
631
+ $ => A :MLOAD(isStaticCall), JMPNZ(invalidStaticTx)
632
+ SP - 1 => SP
633
+ $ => A :MLOAD(SP--); [value => D]
634
+ A :MSTORE(valueCall)
635
+ $ => E :MLOAD(SP--); [offset => E]
636
+ E :MSTORE(argsOffsetCall)
637
+ $ => C :MLOAD(SP--); [size => C]
638
+ C :MSTORE(argsLengthCall)
639
+ $ => D :MLOAD(SP); [salt => D]
640
+
641
+
642
+ ; store lastMemOffset for memory expansion gas cost
643
+ E :MSTORE(lastMemOffset)
644
+ ; store lastMemLength for memory expansion gas cost
645
+ ; compute memory expansion gas cost
646
+ C :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
647
+ ; store current CTX to auxiliary var for later usage
648
+ CTX :MSTORE(originAuxCTX)
649
+
650
+ ; cost to hash the initialization code
651
+ C + 31 :MSTORE(arithA)
652
+ 32 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB]
653
+ $ => C :MLOAD(arithRes1)
654
+ GAS => A
655
+ 6 * C => B
656
+ $ :LT,JMPC(outOfGas)
657
+ A - B => GAS
658
+ GAS :MSTORE(gasCall)
659
+
660
+ ; check correctness of Create: depth, can transfer, nonce overflow,
661
+ ; can transfer
662
+ $ => A :MLOAD(storageAddr)
663
+ ; set key for smt balance query
664
+ %SMT_KEY_BALANCE => B
665
+ ; 3rd parameter does not apply to nonce or balance
666
+ 0 => C
667
+ ; balance in A
668
+ $ => A :SLOAD
669
+ $ => B :MLOAD(valueCall)
670
+ $ :LT,JMPC(opCreateFail)
671
+
672
+ ; check nonce overflow
673
+ $ => A :MLOAD(storageAddr)
674
+ ; set key for smt nonce query
675
+ %SMT_KEY_NONCE => B
676
+ ; nonce in B
677
+ $ => B :SLOAD
678
+ A => C
679
+ %MAX_NONCE => A
680
+ $ :EQ,JMPC(opCreateFail)
681
+
682
+ ;change to a new CTX
683
+ SP :MSTORE(lastSP)
684
+ PC :MSTORE(lastPC)
685
+ ; increase used contexts counter
686
+ $ => A :MLOAD(lastCtxUsed)
687
+ A+1 => CTX :MSTORE(lastCtxUsed)
688
+ CTX :MSTORE(currentCTX)
689
+ 1 :MSTORE(isCreateContract)
690
+ 1 :MSTORE(isCreate)
691
+ 1 :MSTORE(isCreate2)
692
+ D :MSTORE(salt)
693
+ ; set origin CTX to this new CTX
694
+ $ => A :MLOAD(originAuxCTX)
695
+ A :MSTORE(originCTX)
696
+
697
+ ; get nonce & update SR
698
+ ; get nonce length bytes
699
+ B :MSTORE(txNonce), CALL(getLenBytes); in: [B: value] out: [A: value bytes length]
700
+ A :MSTORE(lengthNonce)
701
+ ; increase nonce
702
+ 1 => A
703
+ $ => D :ADD
704
+
705
+ C => A
706
+ ; set key for smt nonce query
707
+ %SMT_KEY_NONCE => B
708
+ 0 => C
709
+ $ => SR :SSTORE
710
+ SR :MSTORE(initSR)
711
+ ; compute gas send in call
712
+ A :MSTORE(txSrcAddr), CALL(computeGasSendCall); in: [gasCall: gas sent to call] out: [A: min( requested_gas , all_but_one_64th(63/64))]
713
+ $ => CTX :MLOAD(originCTX)
714
+ $ => C :MLOAD(gasRefund)
715
+ GAS - A :MSTORE(gasCTX)
716
+ $ => CTX :MLOAD(currentCTX)
717
+ C :MSTORE(gasRefund)
718
+ ; update GAS to computed gas send call
719
+ A => GAS
720
+ ; set CTX var values
721
+ $ => A :MLOAD(argsLengthCall)
722
+ ; set calldata pointers to current CTX
723
+ A :MSTORE(txCalldataLen), CALL(saveCalldataPointer)
724
+ $ => A :MLOAD(valueCall), CALL(checkpointBlockInfoTree)
725
+ ; Save touched root when a new context is created
726
+ A :MSTORE(txValue), CALL(checkpointTouched)
727
+ :JMP(txType)
728
+
729
+ /**
730
+ * @link [https://www.evm.codes/#fa?fork=berlin]
731
+ * @zk-counters
732
+ * - 300 steps
733
+ * @process-opcode
734
+ * - stack input: [gas, address, argsOffset, argsSize, retOffset, retSize]
735
+ * - stack output: [success]
736
+ */
737
+ opSTATICCALL:
738
+ ; checks zk-counters
739
+ %MAX_CNT_STEPS - STEP - 300 :JMPN(outOfCountersStep)
740
+ ; check stack underflow
741
+ SP - 6 :JMPN(stackUnderflow)
742
+ SP - 1 => SP
743
+ ; store current CTX to auxiliary var for later usage
744
+ CTX :MSTORE(originAuxCTX)
745
+ ; store gas call
746
+ $ => A :MLOAD(SP--); [gas => A]
747
+ A :MSTORE(gasCall)
748
+ ; mask address to 20 bytes
749
+ $ => A :MLOAD(SP--), CALL(maskAddress); [address => A]; in: [A: address] out: [A: masked address]
750
+ A :MSTORE(addrCall)
751
+ ; store bytes offset int the memory, the calldata of the subcontext
752
+ $ => A :MLOAD(SP--); [argsOffset => A]
753
+ A :MSTORE(argsOffsetCall)
754
+ ; store lastMemOffset for memory expansion gas cost
755
+ A :MSTORE(lastMemOffset)
756
+ ; byte size to copy, size of the calldata of the subcontext
757
+ $ => B :MLOAD(SP--); [argsSize => B]
758
+ B :MSTORE(argsLengthCall)
759
+ ; store lastMemLength for memory expansion gas cost
760
+ ; compute memory expansion gas cost
761
+ B :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
762
+ ; store byte offset in the memory in bytes, where to store the return data of the sub context
763
+ $ => C :MLOAD(SP--); [retOffset => C]
764
+ C :MSTORE(lastMemOffset)
765
+ ; store byte size to copy (size of the return data)
766
+ $ => E :MLOAD(SP); [retSize => E]
767
+ ; compute memory expansion gas cost of the return value
768
+ E :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
769
+ ; check if an address is cold. If it is, add it to the touched tree
770
+ $ => A :MLOAD(addrCall), CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold]
771
+ ;gas_cost = base_gas + gas_sent_with_call
772
+ GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas)
773
+
774
+ ; setup vars for next CTX
775
+ $ => D :MLOAD(storageAddr)
776
+ $ => B :MLOAD(gasRefund)
777
+ SP :MSTORE(lastSP)
778
+ PC :MSTORE(lastPC)
779
+ ; increase CTX
780
+ $ => A :MLOAD(lastCtxUsed)
781
+ A+1 => CTX :MSTORE(lastCtxUsed)
782
+ CTX :MSTORE(currentCTX)
783
+ $ => A :MLOAD(originAuxCTX)
784
+ A :MSTORE(originCTX)
785
+ B :MSTORE(gasRefund)
786
+ 0 :MSTORE(txValue)
787
+ 1 :MSTORE(isStaticCall)
788
+ D :MSTORE(txSrcAddr)
789
+ SR :MSTORE(initSR)
790
+ $ => A :MLOAD(addrCall)
791
+ A :MSTORE(txDestAddr)
792
+ A :MSTORE(storageAddr)
793
+ C :MSTORE(retCallOffset)
794
+ ; compute gas send in call
795
+ E :MSTORE(retCallLength), CALL(computeGasSendCall); in: [gasCall: gas sent to call] out: [A: min( requested_gas , all_but_one_64th(63/64))]
796
+ $ => CTX :MLOAD(originCTX)
797
+ GAS - A :MSTORE(gasCTX)
798
+ $ => CTX :MLOAD(currentCTX)
799
+ ; update GAS to computed gas send call
800
+ A => GAS
801
+ $ => A :MLOAD(argsLengthCall)
802
+ ; set calldata pointers to current CTX
803
+ A :MSTORE(txCalldataLen), CALL(saveCalldataPointer)
804
+ ; save touched root when a new context is created
805
+ :CALL(checkpointTouched)
806
+ :CALL(checkpointBlockInfoTree)
807
+ :JMP(txType)
808
+ /**
809
+ * @link [https://www.evm.codes/#fd?fork=berlin]
810
+ * @zk-counters
811
+ * - 400 steps
812
+ * @process-opcode
813
+ * - stack input: [offset, size]
814
+ * - stack output: none
815
+ */
816
+ opREVERT:
817
+ ; checks zk-counters
818
+ %MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep)
819
+ ; check stack underflow
820
+ SP - 2 => SP :JMPN(stackUnderflow)
821
+ ; load initSR to revert all state changes
822
+ ; revert touched accounts
823
+ $ => SR :MLOAD(initSR), CALL(revertTouched)
824
+
825
+ $ => E :MLOAD(SP+1), CALL(revertBlockInfoTree); [offset => E]
826
+ $ => C :MLOAD(SP); [size => C]
827
+ E :MSTORE(retDataOffset)
828
+ C :MSTORE(retDataLength)
829
+ ; store lastMemOffset for memory expansion gas cost
830
+ E :MSTORE(lastMemOffset)
831
+ ; store lastMemLength for memory expansion gas cost
832
+ ; compute memory expansion gas cost
833
+ C :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
834
+ ; check if first context
835
+ $ => B :MLOAD(originCTX)
836
+ $${eventLog(onError, revert)}
837
+ 0 :MSTORE(gasRefund)
838
+ ; if origin ctx is 0, end tx
839
+ B :JMPZ(handleGasFromError)
840
+ ; decrease CTX
841
+ $ => A :MLOAD(currentCTX)
842
+ B => CTX
843
+ ; add return data context value to origin context
844
+ A :MSTORE(retDataCTX)
845
+ ; return left gas to origin CTX
846
+ $ => B :MLOAD(gasCTX)
847
+ GAS + B => GAS
848
+
849
+ A => CTX
850
+ $ => D :MLOAD(retCallLength)
851
+ C => A
852
+ D => B
853
+ $ :LT,JMPC(preREVERT32)
854
+ D => C
855
+
856
+ ; copy from memory current CTX to memory origin CTX
857
+ preREVERT32:
858
+ $ => B :MLOAD(retCallOffset)
859
+
860
+ opREVERTloop:
861
+ ; checks zk-counters
862
+ %MAX_CNT_STEPS - STEP - 200 :JMPN(outOfCountersStep)
863
+ C :JMPZ(opREVERTend)
864
+ ; load first 32 bytes from memory at current CTX
865
+ C - 32 :JMPN(opREVERTfinal)
866
+ :CALL(MLOAD32); in: [E: offset] out: [A: value, E: new offset]
867
+ E => D
868
+ $ => CTX :MLOAD(originCTX)
869
+ B => E
870
+ ; set bytesToStore with value to use in MSTORE
871
+ ; store 32 bytes at origin CTX
872
+ A :MSTORE(bytesToStore), CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset]
873
+ E => B
874
+ D => E
875
+ C - 32 => C
876
+ ; restore current CTX
877
+ $ => CTX :MLOAD(currentCTX), JMP(opREVERTloop)
878
+
879
+ opREVERTfinal:
880
+ ; copy last bytes
881
+ :CALL(MLOADX); in: [E: offset, C: length] out: [A: value, E: new offset]
882
+ $ => CTX :MLOAD(originCTX)
883
+ B => E
884
+ A :MSTORE(bytesToStore), CALL(MSTOREX); in: [bytesToStore, E: offset, C: length] out: [E: new offset]
885
+ $ => CTX :MLOAD(currentCTX)
886
+
887
+ opREVERTend:
888
+ ; decrease CTX and restore SP and PC
889
+ $ => CTX :MLOAD(originCTX)
890
+ CTX :MSTORE(currentCTX)
891
+ $ => SP :MLOAD(lastSP)
892
+ $ => PC :MLOAD(lastPC)
893
+ 0 :MSTORE(SP++), JMP(readCode); [0 => SP]
894
+
895
+ VAR GLOBAL sendAllAddress
896
+ ; SELFDESTRUCT is deprecated and EIP-4758 is implemented: https://eips.ethereum.org/EIPS/eip-4758
897
+ ; SELFDESTRUCT is now SENDALL
898
+ /**
899
+ * @link [https://www.evm.codes/#ff?fork=berlin] (selfdestruct)
900
+ * @zk-counters
901
+ * - 400 steps
902
+ * - 2 binary
903
+ * - %MAX_CNT_POSEIDON_SLOAD_SSTORE*4 poseidon
904
+ * @process-opcode
905
+ * - stack input: [address]
906
+ * - stack output: none
907
+ */
908
+ opSENDALL:
909
+ ; checks zk-counters
910
+ %MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep)
911
+ %MAX_CNT_BINARY - CNT_BINARY - 4 :JMPN(outOfCountersBinary)
912
+ %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE*4 :JMPN(outOfCountersPoseidon)
913
+ ; check out-of-gas
914
+ GAS - %SENDALL_GAS => GAS :JMPN(outOfGas)
915
+
916
+ ; check stack underflow
917
+ SP - 1 => SP :JMPN(stackUnderflow)
918
+
919
+ ; check is static
920
+ $ => A :MLOAD(isStaticCall), JMPNZ(invalidStaticTx)
921
+ $ => A :MLOAD(storageAddr)
922
+ ; set key for smt balance query
923
+ %SMT_KEY_BALANCE => B
924
+ 0 => C
925
+ ; balance in D
926
+ $ => D :SLOAD
927
+
928
+ ; Address in A & Mask address to 20 bytes
929
+ $ => A :MLOAD(SP), CALL(maskAddress); in: [A: address] out: [A: masked address]
930
+ A :MSTORE(sendAllAddress)
931
+
932
+ ; store address receiver in [C, E]
933
+ A => C, E
934
+
935
+ ; check balance to move is greater than 0
936
+ 0 => A
937
+ D => B
938
+ $ :EQ,JMPC(opSENDALLend) ; no balance to move
939
+
940
+ ; check receiver and storageAddr are not the same
941
+ $ => A :MLOAD(storageAddr)
942
+ C => B
943
+ $ :EQ, JMPC(opSENDALLend)
944
+
945
+ ; move balances
946
+ opSENDALL2:
947
+ ; check gas empty account
948
+ :CALL(isEmptyAccount); in: [E: address] out: [E: 0 if is not empty, 1 if is empty]
949
+ GAS - %CALL_NEW_ACCOUNT_GAS * E => GAS :JMPN(outOfGas)
950
+
951
+ ; save balance storageAddr in arithA for later usage
952
+ D :MSTORE(arithA)
953
+ ; check is cold to compute gas cost
954
+ C => A :CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold]
955
+ GAS - %COLD_ACCOUNT_ACCESS_COST * D => GAS :JMPN(outOfGas)
956
+ ; read previous balance receiver
957
+ ; set key for smt balance query
958
+ %SMT_KEY_BALANCE => B
959
+ 0 => C
960
+ ; balance in E
961
+ $ => E :SLOAD
962
+
963
+ ; compute new receiver balance
964
+ ; Add operation with Arith
965
+ E :MSTORE(arithB), CALL(addARITH); in: [arithA, arithB] out[arithRes1: arithA*arithB]
966
+ $ => D :MLOAD(arithRes1)
967
+
968
+ ; transfer balance to receiver
969
+ $ => A :MLOAD(sendAllAddress); [address => A]
970
+ %SMT_KEY_BALANCE => B
971
+ 0 => C
972
+ $ => SR :SSTORE
973
+
974
+ ; set contract balance to 0
975
+ $ => A :MLOAD(storageAddr)
976
+ 0 => D
977
+ $ => SR :SSTORE
978
+
979
+ opSENDALLend:
980
+ ; if origin ctx is 0, end tx
981
+ $ => A :MLOAD(originCTX), JMPZ(handleGas)
982
+
983
+ ; decrease CTX
984
+ $ => B :MLOAD(gasRefund)
985
+ 1 => D
986
+ $ => C :MLOAD(isCreate), JMPZ(opSENDALLendContinue)
987
+ $ => D :MLOAD(createContractAddress)
988
+
989
+ opSENDALLendContinue:
990
+ A => CTX
991
+ 0 :MSTORE(retDataCTX)
992
+ CTX :MSTORE(currentCTX)
993
+ B :MSTORE(gasRefund)
994
+ $ => C :MLOAD(gasCTX)
995
+ GAS + C => GAS
996
+ ; restore origin CTX values
997
+ $ => SP :MLOAD(lastSP)
998
+ $ => PC :MLOAD(lastPC)
999
+ D :MSTORE(SP++), JMP(readCode); [output => SP]
1000
+
1001
+ /**
1002
+ * @link [https://www.evm.codes/#fe?fork=berlin]
1003
+ * @zk-counters
1004
+ * - 100 steps
1005
+ * @process-opcode
1006
+ * - stack input: none
1007
+ * - stack output: none
1008
+ */
1009
+ opINVALID:
1010
+ ; checks zk-counters
1011
+ %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep, invalidOpcode)