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,619 @@
1
+
2
+ /**
3
+ * @link [https://www.evm.codes/#35?fork=berlin]
4
+ * @zk-counters
5
+ * - 1 binary
6
+ * - 100 steps
7
+ * @process-opcode
8
+ * - stack input: [offset]
9
+ * - stack output: [data(offset)]
10
+ */
11
+ opCALLDATALOAD:
12
+ ; checks zk-counters
13
+ %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
14
+ %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
15
+
16
+ ; check stack underflow
17
+ SP - 1 => SP :JMPN(stackUnderflow)
18
+ ; check out-of-gas
19
+ GAS - %GAS_FASTEST_STEP => GAS :JMPN(outOfGas)
20
+ ; return 0 for contract creation
21
+ $ :MLOAD(isCreateContract), JMPNZ(CALLDATALOADreturn0)
22
+ $ => A :MLOAD(SP); [offset => A]
23
+ $ => B :MLOAD(txCalldataLen)
24
+ ; if offset is not lower than calldata length, return 0.
25
+ ; This check is also done at `readFromCalldataOffset` but we do it here with a binary to be sure offset is lower than 32 bits
26
+ $ :LT,JMPNC(CALLDATALOADreturn0)
27
+ 32 :MSTORE(readXFromCalldataLength)
28
+ A :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataOffset: result value]
29
+ $ => A :MLOAD(readXFromCalldataResult)
30
+ A :MSTORE(SP++), JMP(readCode); [data(offset) => SP]
31
+
32
+ CALLDATALOADreturn0:
33
+ 0 :MSTORE(SP++), JMP(readCode); [0 => SP]
34
+
35
+ /**
36
+ * @link [https://www.evm.codes/#36?fork=berlin]
37
+ * @zk-counters
38
+ * - 100 steps
39
+ * @process-opcode
40
+ * - stack input: []
41
+ * - stack output: [size]
42
+ */
43
+ opCALLDATASIZE:
44
+ ; checks zk-counters
45
+ %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
46
+ ; check out-of-gas
47
+ GAS-%GAS_QUICK_STEP => GAS :JMPN(outOfGas)
48
+ ; return 0 for contract creation
49
+ $ :MLOAD(isCreateContract), JMPNZ(opCALLDATASIZEdep)
50
+ $ => B :MLOAD(txCalldataLen)
51
+ B :MSTORE(SP++); [size => SP]
52
+ ; check stack overflow
53
+ %MAX_STACK_SIZE - SP :JMPN(stackOverflow, readCode)
54
+
55
+ opCALLDATASIZEdep:
56
+ 0 :MSTORE(SP++); [0 => SP]
57
+ ; check stack overflow
58
+ %MAX_STACK_SIZE - SP :JMPN(stackOverflow, readCode)
59
+
60
+ VAR GLOBAL auxDestOffset
61
+ VAR GLOBAL calldataCopyOffset ; current calldatacopy offset
62
+ VAR GLOBAL auxOffset ; original calldatacopy offset
63
+ VAR GLOBAL numLastBytes
64
+ /**
65
+ * @link [https://www.evm.codes/#37?fork=berlin]
66
+ * @zk-counters
67
+ * - 100 steps
68
+ * - 2 binary
69
+ * @process-opcode
70
+ * - stack input: [destOffset, offset, size]
71
+ * - stack output: []
72
+ */
73
+ opCALLDATACOPY:
74
+ ; checks zk-counters
75
+ %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
76
+ %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
77
+ ; check stack underflow
78
+ SP - 3 => SP :JMPN(stackUnderflow)
79
+ $ => E :MLOAD(SP+2); [destOffset => E]
80
+ $ => B :MLOAD(SP+1); [offset => B]
81
+ B :MSTORE(auxOffset)
82
+ B :MSTORE(calldataCopyOffset)
83
+ $ => C :MLOAD(SP); [size => C]
84
+ C :MSTORE(numLastBytes)
85
+ ; store lastMemOffset for memory expansion gas cost
86
+ E :MSTORE(lastMemOffset)
87
+ ; store lastMemLength for memory expansion gas cost
88
+ C :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
89
+ ; check out-of-gas
90
+ GAS - %GAS_FASTEST_STEP => GAS :JMPN(outOfGas)
91
+ ;${3*((C+31)/32)}
92
+ ;(C+31)/32 => A
93
+ C+31 => A
94
+ :CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32]
95
+ GAS - 3*E => GAS :JMPN(outOfGas)
96
+ ; Recover destOffset at E
97
+ $ => E :MLOAD(lastMemOffset)
98
+ ; Recover size at C
99
+ $ => C :MLOAD(lastMemLength)
100
+ ; If is a calldataCopy called from codeCopy, copy code from calldata allocation, else if is a create contract, return 0
101
+ $ :MLOAD(isCalldataCopyFromCodeCopy), JMPNZ(continueOpCalldatacopyFromCodeCopy)
102
+ $ :MLOAD(isCreateContract), JMPNZ(opCALLDATACOPY0, continueOpCalldatacopy)
103
+ continueOpCalldatacopyFromCodeCopy:
104
+ 0 :MSTORE(isCalldataCopyFromCodeCopy)
105
+ continueOpCalldatacopy:
106
+ B => A
107
+ $ => B :MLOAD(txCalldataLen); less than 2**32 bytes (calldata). Enforced by memory expansion gas cost & smart contract batchL2DataHash
108
+ ; if offset is not lower than calldata length, return 0
109
+ ; This check is also done at `readFromCalldataOffset` but we do it here with a binary to be sure offset is lower than 32 bits
110
+ $ :LT,JMPNC(opCALLDATACOPY0)
111
+ B => A
112
+ $ => B :MLOAD(auxOffset)
113
+ B + C => B
114
+ 32 :MSTORE(readXFromCalldataLength)
115
+ ; if txCalldataLen < (offset + size) --> opCALLDATACOPYX0
116
+ $ :LT,JMPC(opCALLDATACOPYX0)
117
+ $ => B :MLOAD(auxOffset),JMP(opCALLDATACOPYloop)
118
+
119
+ opCALLDATACOPYX0:
120
+ $ => C :MLOAD(txCalldataLen)
121
+ $ => B :MLOAD(auxOffset)
122
+ C - B => C :MSTORE(numLastBytes)
123
+
124
+ opCALLDATACOPYloop:
125
+ ; checks zk-counters
126
+ %MAX_CNT_STEPS - STEP - 300 :JMPN(outOfCountersStep)
127
+ ; finish loop
128
+ C :JMPZ(opCALLDATACOPYcheckLen)
129
+ ; copy last bytes
130
+ C - 32 :JMPN(opCALLDATACOPYfinal)
131
+ B + 32 :MSTORE(calldataCopyOffset)
132
+ B :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value]
133
+ $ => A :MLOAD(readXFromCalldataResult)
134
+ A :MSTORE(bytesToStore)
135
+ $ => A :MLOAD(lastMemOffset)
136
+ ; checks zk-counters
137
+ %MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - 1 :JMPN(outOfCountersMemalign)
138
+ ; Store 32 bytes from calldata to memory
139
+ :CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32]
140
+ E :MSTORE(auxDestOffset)
141
+ $ => A :MLOAD(MEM:E)
142
+ $ => B :MLOAD(MEM:E+1)
143
+ ${memAlignWR_W0(A,mem.bytesToStore,C)} => D ; no trust calculate W0
144
+ ${memAlignWR_W1(B,mem.bytesToStore,C)} => E ; no trust calculate W1
145
+ $ :MEM_ALIGN_WR,MLOAD(bytesToStore)
146
+ E => A
147
+ $ => E :MLOAD(auxDestOffset)
148
+ D :MSTORE(MEM:E) ; write W0
149
+ A :MSTORE(MEM:E+1) ; write W1
150
+ ; recover stack pointer
151
+ $ => C :MLOAD(numLastBytes)
152
+ C - 32 => C :MSTORE(numLastBytes)
153
+ $ => E :MLOAD(lastMemOffset)
154
+ E + 32 => E :MSTORE(lastMemOffset)
155
+ $ => B :MLOAD(calldataCopyOffset), JMP(opCALLDATACOPYloop)
156
+
157
+ opCALLDATACOPYfinal:
158
+ ; copy last bytes
159
+ C :MSTORE(readXFromCalldataLength)
160
+ $ => D :MLOAD(calldataCopyOffset)
161
+ D :MSTORE(readXFromCalldataOffset), CALL(readFromCalldataOffset); in: [readXFromCalldataOffset: offset value, readXFromCalldataLength: length value], out: [readXFromCalldataResult: result value]
162
+ $ => A :MLOAD(readXFromCalldataResult)
163
+
164
+ ; set bytesToStore with value to use in MSTORE
165
+ A :MSTORE(bytesToStore), CALL(MSTOREX); in: [bytesToStore, E: offset, C: length] out: [E: new offset]
166
+ :JMP(opCALLDATACOPYcheckLen)
167
+
168
+ opCALLDATACOPY0:
169
+ C :JMPZ(opCALLDATACOPYend)
170
+ 32 - C :JMPN(opCALLDATACOPY320)
171
+ ; set bytesToStore with value to use in MSTORE
172
+ 0 :MSTORE(bytesToStore), CALL(MSTOREX); in: [bytesToStore, E: offset, C: length] out: [E: new offset]
173
+ :JMP(opCALLDATACOPYend)
174
+
175
+ opCALLDATACOPY320:
176
+ ; set bytesToStore with value to use in MSTORE
177
+ 0 :MSTORE(bytesToStore), CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset]
178
+ C - 32 => C :JMP(opCALLDATACOPY0)
179
+
180
+ opCALLDATACOPYcheckLen:
181
+ ; fill missing values with 0 (size > calldata)
182
+ $ => C :MLOAD(lastMemLength)
183
+ $ => A :MLOAD(txCalldataLen)
184
+ $ => B :MLOAD(auxOffset)
185
+ C - A + B => C :JMPN(opCALLDATACOPYend, opCALLDATACOPY0)
186
+
187
+
188
+ opCALLDATACOPYend:
189
+ :JMP(readCode)
190
+
191
+ /**
192
+ * @link [https://www.evm.codes/#38?fork=berlin]
193
+ * @zk-counters
194
+ * - %MAX_CNT_POSEIDON_SLOAD_SSTORE poseidon
195
+ * - 30 steps
196
+ * @process-opcode
197
+ * - stack input: []
198
+ * - stack output: [size]
199
+ */
200
+ opCODESIZE:
201
+ ; checks zk-counters
202
+ %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE :JMPN(outOfCountersPoseidon)
203
+ %MAX_CNT_STEPS - STEP - 30 :JMPN(outOfCountersStep)
204
+ ; check out-of-gas
205
+ GAS-%GAS_QUICK_STEP => GAS :JMPN(outOfGas)
206
+ ; if is create, get size from calldata
207
+ $ => A :MLOAD(isCreateContract), JMPNZ(opCODESIZEdep)
208
+ ; else, from storage
209
+ $ => A :MLOAD(txDestAddr)
210
+ ; set key for smt bytecode length query
211
+ %SMT_KEY_SC_LENGTH => B
212
+ 0 => C
213
+ $ => A :SLOAD
214
+ A :MSTORE(SP++); [size => SP]
215
+ ; check stack overflow
216
+ %MAX_STACK_SIZE - SP :JMPN(stackOverflow, readCode)
217
+
218
+ opCODESIZEdep:
219
+ $ => B :MLOAD(txCalldataLen)
220
+ B :MSTORE(SP++); [size => SP]
221
+ ; check stack overflow
222
+ %MAX_STACK_SIZE - SP :JMPN(stackOverflow, readCode)
223
+
224
+ VAR GLOBAL memOffset
225
+ VAR GLOBAL remainingBytes
226
+ VAR GLOBAL previousValue
227
+ VAR GLOBAL codecopyHashId
228
+ VAR GLOBAL codecopyBytecodeLength
229
+ VAR GLOBAL memInteger
230
+ ; Flag to check if the calldataCopy function is being called from the codecopy function
231
+ VAR CTX isCalldataCopyFromCodeCopy
232
+ /**
233
+ * @link [https://www.evm.codes/#39?fork=berlin]
234
+ * @zk-counters
235
+ * - dynamic binary: 2 * size
236
+ * - dynamic mem align: 2 * size
237
+ * - dynamic poseidon: %MAX_CNT_POSEIDON_SLOAD_SSTORE * 2 * size
238
+ * - dynamic steps: 100 * size
239
+ * @process-opcode
240
+ * - stack input: [destOffset, offset, size]
241
+ * - stack output: []
242
+ */
243
+ opCODECOPY:
244
+ ;Check counters
245
+ %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
246
+ ; if is a create, copy from calldata
247
+ $ => A :MLOAD(isCreateContract), JMPZ(continueOpCODECOPY)
248
+ 1 :MSTORE(isCalldataCopyFromCodeCopy), JMP(opCALLDATACOPY)
249
+ continueOpCODECOPY:
250
+ ; check stack underflow
251
+ SP - 3 => SP :JMPN(stackUnderflow)
252
+ $ => C :MLOAD(SP+2); [destOffset => C]
253
+ $ => D :MLOAD(SP+1); [offset => D]
254
+ $ => E :MLOAD(SP); [size => E]
255
+ ; store lastMemOffset for memory expansion gas cost
256
+ C :MSTORE(lastMemOffset)
257
+ ; store lastMemLength for memory expansion gas cost
258
+ ; compute memory expansion gas cost
259
+ E :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
260
+ ; check out-of-gas
261
+ GAS - %GAS_FASTEST_STEP => GAS :JMPN(outOfGas)
262
+ ;${3*((E+31)/32)}
263
+ E+31 => A
264
+ ;(E+31)/32
265
+ A :MSTORE(arithA)
266
+ 32 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB]
267
+ $ => A :MLOAD(arithRes1)
268
+ ; Mul operation with Arith
269
+ ; 3*((E+31)/32)
270
+ 3 :MSTORE(arithA)
271
+ A :MSTORE(arithB), CALL(mulARITH); in: [arithA, arithB] out: [arithRes1: arithA*arithB]
272
+ $ => A :MLOAD(arithRes1)
273
+
274
+ GAS - A => GAS :JMPN(outOfGas)
275
+
276
+
277
+ ; if offset is above data len, length => offset
278
+ D => A
279
+ $ => B :MLOAD(bytecodeLength)
280
+ $ :LT, JMPC(opCODECOPY2)
281
+ B => A
282
+
283
+ opCODECOPY2:
284
+ ; init vars for copy the code
285
+ A => HASHPOS
286
+ $ => D :MLOAD(contractHashId)
287
+ ; set hashId to get bytes from
288
+ D :MSTORE(codecopyHashId)
289
+ ; set contract bytecode length
290
+ B :MSTORE(codecopyBytecodeLength)
291
+ C :MSTORE(memOffset)
292
+ E :MSTORE(remainingBytes)
293
+
294
+ opCODECOPYloopInit:
295
+ ; checks zk-counters
296
+ %MAX_CNT_MEM_ALIGN - CNT_MEM_ALIGN - E :JMPN(outOfCountersMemalign)
297
+
298
+ opCODECOPYloop:
299
+ %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
300
+ %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
301
+
302
+ $ => B :MLOAD(remainingBytes), JMPZ(readCode)
303
+ $ => A :MLOAD(memOffset), CALL(offsetUtil); in: [A: offset] out: [E: offset/32, C: offset%32]
304
+ E :MSTORE(memInteger)
305
+ ; read M0 previous value
306
+ $ => A :MLOAD(MEM:E)
307
+ A :MSTORE(previousValue), CALL(opCODECOPYLoadBytes); in:[codecopyBytecodeLength, codecopyHashId] out: [B: readByte]
308
+ $ => A :MLOAD(previousValue)
309
+ ${memAlignWR8_W0(A,B,C)} => D ; no trust calculate W0
310
+ B :MEM_ALIGN_WR8 ; only use LSB of B, rest of bytes could be non zero
311
+ $ => E :MLOAD(memInteger)
312
+ D :MSTORE(MEM:E) ; write W0
313
+ ; update vars loop
314
+ $ => B :MLOAD(remainingBytes)
315
+ B - 1 => B ; decrease 1 byte from length
316
+ B :MSTORE(remainingBytes)
317
+ $ => A :MLOAD(memOffset)
318
+ A + 1 => A ; increment offset to write the next byte
319
+ A :MSTORE(memOffset), JMP(opCODECOPYloop)
320
+
321
+
322
+ ; @info Load 0 if read bytecode position is above bytecode length
323
+ opCODECOPYLoadBytes:
324
+ 0 => A
325
+ $ => B :MLOAD(codecopyBytecodeLength)
326
+ $ :EQ, JMPC(readZero)
327
+ HASHPOS => A
328
+ $ :LT, JMPC(readValueBytecode)
329
+ readZero:
330
+ 0 => B :RETURN
331
+ readValueBytecode:
332
+ $ => E :MLOAD(codecopyHashId)
333
+ ; read value to write in memory
334
+ $ => B :HASHP1(E), RETURN
335
+
336
+ /**
337
+ * @link [https://www.evm.codes/#3B?fork=berlin]
338
+ * @zk-counters
339
+ * - 100 steps
340
+ * - %MAX_CNT_POSEIDON_SLOAD_SSTORE poseidon
341
+ * @process-opcode
342
+ * - stack input: [address]
343
+ * - stack output: [size]
344
+ */
345
+ opEXTCODESIZE:
346
+ ; checks zk-counters
347
+ %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
348
+ %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE :JMPN(outOfCountersPoseidon)
349
+ ; check stack underflow
350
+ SP - 1 => SP :JMPN(stackUnderflow)
351
+ $ => A :MLOAD(SP), CALL(maskAddress); [address => A]; in: [A: address] out: [A: masked address]
352
+ :CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold]
353
+ ; check out-of-gas
354
+ GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas)
355
+ ; set key for smt smart contract length query
356
+ %SMT_KEY_SC_LENGTH => B
357
+ 0 => C
358
+ $ => A :SLOAD
359
+ A :MSTORE(SP++), JMP(readCode); [size => SP]
360
+
361
+ ; read hash smt
362
+ ; put 32 by 32 bytes in the hashP
363
+ ; assert bytes with hash smt
364
+
365
+ ; read byte from hashP and copy into memory
366
+ ; over length => set 0's
367
+ VAR GLOBAL tmpContractHashId
368
+ VAR GLOBAL tmpContractLength
369
+ /**
370
+ * @link [https://www.evm.codes/#51?fork=berlin]
371
+ * @zk-counters
372
+ * - dynamic: 100
373
+ * - dynamic poseidon: %MAX_CNT_POSEIDON_SLOAD_SSTORE + f(size)
374
+ * @process-opcode
375
+ * - stack input: [address, destOffset, offset, size]
376
+ * - stack output: []
377
+ */
378
+ opEXTCODECOPY:
379
+ ; checks zk-counters
380
+ %MAX_CNT_STEPS - STEP - 300 :JMPN(outOfCountersStep)
381
+ %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
382
+
383
+ ; check stack underflow
384
+ SP - 4 => SP :JMPN(stackUnderflow)
385
+ $ => A :MLOAD(SP+3), CALL(maskAddress); [address => A]; in: [A: address] out: [A: masked address]
386
+ :CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold]
387
+
388
+ ; check out-of-gas
389
+ GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas)
390
+ :CALL(opEXTCODECOPYLoadBytecode)
391
+ $ => C :MLOAD(SP+2); [destOffset => C]
392
+ $ => D :MLOAD(SP+1); [offset => D]
393
+ $ => E :MLOAD(SP); [size => E]
394
+
395
+ ; store lastMemOffset for memory expansion gas cost
396
+ C :MSTORE(lastMemOffset)
397
+
398
+ ; store lastMemLength for memory expansion gas cost
399
+ ; compute memory expansion gas cost
400
+ E :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
401
+
402
+ ; check out-of-gas
403
+ ;${3*((E+31)/32)}
404
+ E+31 => A
405
+ ;(E+31)/32
406
+ A :MSTORE(arithA)
407
+ 32 :MSTORE(arithB)
408
+ :CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB]
409
+ $ => A :MLOAD(arithRes1)
410
+ ; Mul operation with Arith
411
+ ; 3*((E+31)/32)
412
+ 3 :MSTORE(arithA)
413
+ A :MSTORE(arithB), CALL(mulARITH); in: [arithA, arithB] out: [arithRes1: arithA*arithB]
414
+ $ => A :MLOAD(arithRes1)
415
+ ; check out-of-gas
416
+ GAS - A => GAS :JMPN(outOfGas)
417
+ ; if offset is above data len, length => offset
418
+ D => A
419
+ $ => B :MLOAD(tmpContractLength)
420
+ $ :LT, JMPC(opEXTCODECOPY2)
421
+ B => A
422
+
423
+ opEXTCODECOPY2:
424
+ ; init vars for copy the code
425
+ A => HASHPOS
426
+ $ => D :MLOAD(tmpContractHashId)
427
+ D :MSTORE(codecopyHashId) ; set hashId to get bytes from
428
+ B :MSTORE(codecopyBytecodeLength) ; set contract bytecode length
429
+ C :MSTORE(memOffset)
430
+ E :MSTORE(remainingBytes), JMP(opCODECOPYloopInit)
431
+
432
+ VAR GLOBAL tmpZkPCext
433
+ opEXTCODECOPYLoadBytecode:
434
+ %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE :JMPN(outOfCountersPoseidon)
435
+ ; set key for smt smart contract length query
436
+ %SMT_KEY_SC_LENGTH => B
437
+ 0 => C
438
+ $ => D :SLOAD
439
+ ; if length is 0, nothing to check
440
+ ; after the implementation of EIP170, the maximum bytecode size is 24.576 bytes, less than 2**32
441
+ D :MSTORE(tmpContractLength), JMPZ(opEXTCODECOPYCheckHashEnd)
442
+
443
+ ; check poseidon counters
444
+ ; 56 is the value used by the prover to increment poseidon counters depending on the hash length
445
+ RR :MSTORE(tmpZkPCext)
446
+ D + 1 :MSTORE(arithA)
447
+ 56 :MSTORE(arithB), CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB]
448
+ $ => RR :MLOAD(tmpZkPCext)
449
+ $ => B :MLOAD(arithRes1)
450
+ %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE - 1 - B :JMPN(outOfCountersPoseidon)
451
+ %MAX_CNT_PADDING_PG - CNT_PADDING_PG - 1 - B :JMPN(outOfCountersPadding)
452
+
453
+ ; set key for smt smart contract code query
454
+ %SMT_KEY_SC_CODE => B
455
+ 0 => C
456
+ $ => A :SLOAD
457
+
458
+ ; get a new hashPId
459
+ $ => E :MLOAD(nextHashPId)
460
+ E :MSTORE(tmpContractHashId)
461
+ E + 1 :MSTORE(nextHashPId)
462
+
463
+ ; load contract bytecode
464
+ A :HASHPDIGEST(E)
465
+ opEXTCODECOPYCheckHashEnd:
466
+ :RETURN
467
+
468
+ /**
469
+ * @link [https://www.evm.codes/#3D?fork=berlin]
470
+ * @zk-counters
471
+ * - 1 binary
472
+ * - 20 steps
473
+ * @process-opcode
474
+ * - stack input: []
475
+ * - stack output: [size]
476
+ */
477
+ opRETURNDATASIZE:
478
+ ; checks zk-counters
479
+ %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCountersBinary)
480
+ %MAX_CNT_STEPS - STEP - 20 :JMPN(outOfCountersStep)
481
+
482
+ ; check out-of-gas
483
+ GAS - %GAS_QUICK_STEP => GAS :JMPN(outOfGas)
484
+ ; Load ret data length from last ctx
485
+ $ => B :MLOAD(retDataCTX)
486
+ ; if no retDataCTX(0), retDataLength = 0
487
+ 0 => A
488
+ $ :EQ, JMPC(endOpRETURNDATASIZE)
489
+ B => CTX
490
+ $ => A :MLOAD(retDataLength)
491
+ ; Restore current context
492
+ $ => CTX :MLOAD(currentCTX)
493
+
494
+ endOpRETURNDATASIZE:
495
+ A :MSTORE(SP++); [size => SP]
496
+ ; check stack overflow
497
+ %MAX_STACK_SIZE - SP :JMPN(stackOverflow, readCode)
498
+
499
+ /**
500
+ * @link [https://www.evm.codes/#3E?fork=berlin]
501
+ * @zk-counters
502
+ * - 2 binary
503
+ * - dynamic steps: 400 + 100 * size
504
+ * @process-opcode
505
+ * - stack input: [destOffset, offset, size]
506
+ * - stack output: []
507
+ */
508
+ opRETURNDATACOPY:
509
+ ; checks zk-counters
510
+ %MAX_CNT_STEPS - STEP - 400 :JMPN(outOfCountersStep)
511
+ %MAX_CNT_BINARY - CNT_BINARY - 2 :JMPN(outOfCountersBinary)
512
+ ; check stack underflow
513
+ SP - 3 => SP :JMPN(stackUnderflow)
514
+ ; check out-of-gas
515
+ GAS - %GAS_FASTEST_STEP => GAS :JMPN(outOfGas)
516
+
517
+ $ => D :MLOAD(SP+2); [destOffset => D]
518
+ $ => E :MLOAD(SP+1); [offset => E]
519
+ $ => C :MLOAD(SP); [size => C]
520
+ ; store lastMemOffset for memory expansion gas cost
521
+ D :MSTORE(lastMemOffset)
522
+ ; store lastMemLength for memory expansion gas cost
523
+ C :MSTORE(lastMemLength), CALL(saveMem); in: [lastMemOffset, lastMemLength]
524
+ ; if retDataCTX is 0, end opcode execution
525
+ $ => B :MLOAD(retDataCTX)
526
+ 0 => A
527
+ $ :EQ, JMPC(opRETURNDATACOPYEmpty)
528
+
529
+ ; Load ret data length from last ctx
530
+ B => CTX
531
+ E => B
532
+
533
+ $ => A :MLOAD(retDataLength)
534
+ $ => E :MLOAD(retDataOffset)
535
+ $ => CTX :MLOAD(currentCTX)
536
+ ; A is retDataLength
537
+ ; B is offset
538
+ $ :LT, JMPC(outOfGas)
539
+ ; if retDataLength < offset + size -> OOG
540
+ A - B - C :JMPN(outOfGas)
541
+
542
+ ; E ret data offset (memory pointer) of last context, B offset in return data that want to retrieve
543
+ E + B => B ; memory pointer where start to copy memory
544
+ ;${3*((C+31)/32)}
545
+ C+31 => A
546
+ ;(C+31)/32
547
+ A :MSTORE(arithA)
548
+ 32 :MSTORE(arithB)
549
+ :CALL(divARITH); in: [arithA, arithB] out: [arithRes1: arithA/arithB, arithRes2: arithA%arithB]
550
+ $ => A :MLOAD(arithRes1)
551
+ ; Mul operation with Arith
552
+ ; 3*((C+31)/32)
553
+ 3 :MSTORE(arithA)
554
+ A :MSTORE(arithB), CALL(mulARITH); in: [arithA, arithB] out: [arithRes1: arithA*arithB]
555
+ $ => A :MLOAD(arithRes1)
556
+ ; check out-of-gas
557
+ GAS - A => GAS :JMPN(outOfGas)
558
+
559
+ opRETURNDATACOPYloop:
560
+ %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
561
+ C :JMPZ(readCode)
562
+ C - 32 :JMPN(opRETURNDATACOPYfinal)
563
+ B => E
564
+ ; Load memory from last context used
565
+ $ => CTX :MLOAD(retDataCTX), CALL(MLOAD32); in: [E: offset] out: [A: value, E: new offset]
566
+ ; save new offset at B
567
+ ; Save memory to the current context
568
+ $ => CTX :MLOAD(currentCTX)
569
+ E => B
570
+ D => E
571
+ ; set bytesToStore with value to use in MSTORE
572
+ A :MSTORE(bytesToStore), CALL(MSTORE32); in: [bytesToStore, E: offset] out: [E: new offset]
573
+ E => D
574
+ C - 32 => C :JMP(opRETURNDATACOPYloop)
575
+
576
+ opRETURNDATACOPYfinal:
577
+ B => E
578
+ ; Load memory from last context used
579
+ $ => CTX :MLOAD(retDataCTX), CALL(MLOADX); in: [E: offset, C: length] out: [A: value, E: new offset]
580
+ ; save memory to the current context
581
+ $ => CTX :MLOAD(currentCTX)
582
+ E => B ; offset retDataCTX
583
+ D => E ; offset current CTX
584
+ ; set bytesToStore with value to use in MSTORE
585
+ A :MSTORE(bytesToStore), CALL(MSTOREX); in: [bytesToStore, E: offset, C: length] out: [E: new offset]
586
+ :JMP(readCode)
587
+
588
+ opRETURNDATACOPYEmpty:
589
+ ; offset return data + len return data must be 0
590
+ E => A
591
+ C => B
592
+ $ => B :ADD, JMPC(outOfGas)
593
+ 0 => A
594
+ $ :EQ, JMPC(readCode, outOfGas)
595
+
596
+ /**
597
+ * @link [https://www.evm.codes/#3F?fork=berlin]
598
+ * @zk-counters
599
+ * - 100 steps
600
+ * - %MAX_CNT_POSEIDON_SLOAD_SSTORE poseidon
601
+ * @process-opcode
602
+ * - stack input: [address]
603
+ * - stack output: [hash]
604
+ */
605
+ opEXTCODEHASH:
606
+ ; checks zk-counters
607
+ %MAX_CNT_STEPS - STEP - 100 :JMPN(outOfCountersStep)
608
+ %MAX_CNT_POSEIDON_G - CNT_POSEIDON_G - %MAX_CNT_POSEIDON_SLOAD_SSTORE :JMPN(outOfCountersPoseidon)
609
+ ; check stack underflow
610
+ SP - 1 => SP :JMPN(stackUnderflow)
611
+ $ => A :MLOAD(SP), CALL(maskAddress); [address => A]; in: [A: address] out: [A: masked address]
612
+ :CALL(isColdAddress); in: [A: address] out: [D: 0 if warm, 1 if cold]
613
+ ; check out-of-gas
614
+ GAS - %WARM_STORAGE_READ_GAS - D * %COLD_ACCOUNT_ACCESS_COST_REDUCED => GAS :JMPN(outOfGas)
615
+ ; set key for smt smart contract code hash query
616
+ %SMT_KEY_SC_CODE => B
617
+ 0 => C
618
+ $ => A :SLOAD
619
+ A :MSTORE(SP++), JMP(readCode); [hash => SP]