@zkasm/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 @zkasm/zkevm-rom might be problematic. Click here for more details.
- package/.eslintrc.js +33 -0
- package/.github/CODEOWNERS +14 -0
- package/.github/ISSUE_TEMPLATE/bug.yml +38 -0
- package/.github/ISSUE_TEMPLATE/feature.yml +26 -0
- package/.github/ISSUE_TEMPLATE/question.yml +26 -0
- package/.github/workflows/main.yaml +40 -0
- package/LICENSE +636 -0
- package/README.md +23 -5
- package/audits/Hexens_Polygon_zkEVM_PUBLIC_27.02.23.pdf +0 -0
- package/audits/Polygon-zkEVM-Public-v1.1-verichains-19-03-2024.pdf +0 -0
- package/audits/zkEVM-ROM-upgrade-1-Spearbit-30-May.pdf +0 -0
- package/audits/zkEVM-ROM-upgrade-2-Spearbit-21-August.pdf +0 -0
- package/audits/zkEVM-engagement-1-Spearbit-27-March.pdf +0 -0
- package/audits/zkEVM-engagement-2-Spearbit-27-March.pdf +0 -0
- package/audits/zkEVM-engagement-3-Spearbit-6-April.pdf +0 -0
- package/counters/README.md +45 -0
- package/counters/counters-executor.js +80 -0
- package/counters/countersConstants.zkasm +370 -0
- package/counters/endIncludes.zkasm +18 -0
- package/counters/initIncludes.zkasm +2 -0
- package/counters/tests/MLOAD32.zkasm +27 -0
- package/counters/tests/MLOADX.zkasm +30 -0
- package/counters/tests/MSTORE32.zkasm +32 -0
- package/counters/tests/MSTOREX.zkasm +36 -0
- package/counters/tests/SHLarith.zkasm +28 -0
- package/counters/tests/SHLarithBit.zkasm +28 -0
- package/counters/tests/SHRarith.zkasm +28 -0
- package/counters/tests/SHRarithBit.zkasm +28 -0
- package/counters/tests/abs.zkasm +29 -0
- package/counters/tests/addBatchHashByteByByte.zkasm +31 -0
- package/counters/tests/computeGasSendCall.zkasm +30 -0
- package/counters/tests/divArith.zkasm +27 -0
- package/counters/tests/expAD.zkasm +30 -0
- package/counters/tests/getLenBits.zkasm +30 -0
- package/counters/tests/getLenBytes.zkasm +32 -0
- package/counters/tests/isEmptyAccount.zkasm +30 -0
- package/counters/tests/mulARITH.zkasm +28 -0
- package/counters/tests/offsetUtil.zkasm +29 -0
- package/counters/tests/opADDMOD.zkasm +28 -0
- package/counters/tests/opAdd.zkasm +27 -0
- package/counters/tests/opBLOCKHASH.zkasm +28 -0
- package/counters/tests/opCALL.zkasm +41 -0
- package/counters/tests/opCALLCODE.zkasm +41 -0
- package/counters/tests/opCALLDATACOPY.zkasm +28 -0
- package/counters/tests/opCALLDATALOAD.zkasm +27 -0
- package/counters/tests/opCODECOPY.zkasm +28 -0
- package/counters/tests/opCREATE.zkasm +35 -0
- package/counters/tests/opCREATE2.zkasm +35 -0
- package/counters/tests/opDELEGATECALL.zkasm +35 -0
- package/counters/tests/opDIV.zkasm +27 -0
- package/counters/tests/opEXP.zkasm +29 -0
- package/counters/tests/opEXTCODECOPY.zkasm +29 -0
- package/counters/tests/opMOD.zkasm +27 -0
- package/counters/tests/opMUL.zkasm +27 -0
- package/counters/tests/opMULMOD.zkasm +28 -0
- package/counters/tests/opRETURN.zkasm +32 -0
- package/counters/tests/opRETURNDATACOPY.zkasm +29 -0
- package/counters/tests/opREVERT.zkasm +32 -0
- package/counters/tests/opSDIV.zkasm +28 -0
- package/counters/tests/opSHA3.zkasm +28 -0
- package/counters/tests/opSIGNEXTEND.zkasm +27 -0
- package/counters/tests/opSMOD.zkasm +28 -0
- package/counters/tests/opSTATICCALL.zkasm +35 -0
- package/counters/tests/opSUB.zkasm +27 -0
- package/counters/tests/saveMem.zkasm +31 -0
- package/docs/opcode-cost-zk-counters.md +315 -0
- package/docs/usage-ecrecover.md +51 -0
- package/index.js +43 -0
- package/main/block-info.zkasm +204 -0
- package/main/constants.zkasm +145 -0
- package/main/ecrecover/addFpEc.zkasm +31 -0
- package/main/ecrecover/checkSqrtFpEc.zkasm +1558 -0
- package/main/ecrecover/constEc.zkasm +13 -0
- package/main/ecrecover/ecrecover.zkasm +280 -0
- package/main/ecrecover/invFnEc.zkasm +44 -0
- package/main/ecrecover/invFpEc.zkasm +45 -0
- package/main/ecrecover/mulFnEc.zkasm +36 -0
- package/main/ecrecover/mulFpEc.zkasm +36 -0
- package/main/ecrecover/mulPointEc.zkasm +311 -0
- package/main/ecrecover/sqFpEc.zkasm +38 -0
- package/main/ecrecover/sqrtFpEc.zkasm +70 -0
- package/main/end.zkasm +4 -0
- package/main/l2-tx-hash.zkasm +159 -0
- package/main/load-change-l2-block-utils.zkasm +11 -0
- package/main/load-change-l2-block.zkasm +28 -0
- package/main/load-tx-rlp-utils.zkasm +72 -0
- package/main/load-tx-rlp.zkasm +431 -0
- package/main/main.zkasm +237 -0
- package/main/map-opcodes.zkasm +274 -0
- package/main/modexp/array_lib/array_add_AGTB.zkasm +123 -0
- package/main/modexp/array_lib/array_add_short.zkasm +85 -0
- package/main/modexp/array_lib/array_div.zkasm +215 -0
- package/main/modexp/array_lib/array_div_long.zkasm +284 -0
- package/main/modexp/array_lib/array_div_short.zkasm +222 -0
- package/main/modexp/array_lib/array_mul.zkasm +97 -0
- package/main/modexp/array_lib/array_mul_long.zkasm +156 -0
- package/main/modexp/array_lib/array_mul_short.zkasm +127 -0
- package/main/modexp/array_lib/array_square.zkasm +246 -0
- package/main/modexp/array_lib/unused/array_add.zkasm +100 -0
- package/main/modexp/array_lib/unused/array_is_odd.zkasm +23 -0
- package/main/modexp/array_lib/unused/array_is_one.zkasm +33 -0
- package/main/modexp/array_lib/unused/array_is_zero.zkasm +34 -0
- package/main/modexp/array_lib/unused/array_sub_AGTB.zkasm +111 -0
- package/main/modexp/array_lib/unused/array_unshift.zkasm +37 -0
- package/main/modexp/array_lib/utils/array_compare.zkasm +82 -0
- package/main/modexp/array_lib/utils/array_trim.zkasm +49 -0
- package/main/modexp/constants.zkasm +5 -0
- package/main/modexp/modexp.zkasm +296 -0
- package/main/modexp/modexp_utils.zkasm +230 -0
- package/main/opcodes/arithmetic.zkasm +357 -0
- package/main/opcodes/block.zkasm +163 -0
- package/main/opcodes/calldata-returndata-code.zkasm +619 -0
- package/main/opcodes/comparison.zkasm +446 -0
- package/main/opcodes/context-information.zkasm +169 -0
- package/main/opcodes/create-terminate-context.zkasm +1011 -0
- package/main/opcodes/crypto.zkasm +96 -0
- package/main/opcodes/flow-control.zkasm +126 -0
- package/main/opcodes/logs.zkasm +193 -0
- package/main/opcodes/stack-operations.zkasm +658 -0
- package/main/opcodes/storage-memory.zkasm +313 -0
- package/main/pairings/BN254/addPointBN254.zkasm +245 -0
- package/main/pairings/BN254/ecAdd.zkasm +312 -0
- package/main/pairings/BN254/ecMul.zkasm +159 -0
- package/main/pairings/BN254/escalarMulBN254.zkasm +155 -0
- package/main/pairings/BN254/lineDiffPointsBN254.zkasm +83 -0
- package/main/pairings/BN254/lineSamePointsBN254.zkasm +96 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/compressFp12BN254.zkasm +49 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/decompressFp12BN254.zkasm +236 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/expByXCompCycloFp12BN254.zkasm +444 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/squareCompCycloFp12BN254.zkasm +212 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/squareCycloFp12BN254.zkasm +228 -0
- package/main/pairings/FP12BN254/CYCLOFP12BN254/xBinDecompBN254.zkasm +64 -0
- package/main/pairings/FP12BN254/frob2Fp12BN254.zkasm +80 -0
- package/main/pairings/FP12BN254/frob3Fp12BN254.zkasm +96 -0
- package/main/pairings/FP12BN254/frobFp12BN254.zkasm +96 -0
- package/main/pairings/FP12BN254/inverseFp12BN254.zkasm +289 -0
- package/main/pairings/FP12BN254/mulFp12BN254.zkasm +408 -0
- package/main/pairings/FP12BN254/sparseMulAFp12BN254.zkasm +296 -0
- package/main/pairings/FP12BN254/sparseMulBFp12BN254.zkasm +291 -0
- package/main/pairings/FP12BN254/squareFp12BN254.zkasm +376 -0
- package/main/pairings/FP2BN254/addFp2BN254.zkasm +19 -0
- package/main/pairings/FP2BN254/escalarMulFp2BN254.zkasm +20 -0
- package/main/pairings/FP2BN254/invFp2BN254.zkasm +66 -0
- package/main/pairings/FP2BN254/mulFp2BN254.zkasm +19 -0
- package/main/pairings/FP2BN254/squareFp2BN254.zkasm +21 -0
- package/main/pairings/FP2BN254/subFp2BN254.zkasm +19 -0
- package/main/pairings/FP4BN254/squareFp4BN254.zkasm +76 -0
- package/main/pairings/FP6BN254/addFp6BN254.zkasm +59 -0
- package/main/pairings/FP6BN254/escalarMulFp6BN254.zkasm +51 -0
- package/main/pairings/FP6BN254/inverseFp6BN254.zkasm +208 -0
- package/main/pairings/FP6BN254/mulFp6BN254.zkasm +201 -0
- package/main/pairings/FP6BN254/sparseMulAFp6BN254.zkasm +65 -0
- package/main/pairings/FP6BN254/sparseMulBFp6BN254.zkasm +134 -0
- package/main/pairings/FP6BN254/sparseMulCFp6BN254.zkasm +128 -0
- package/main/pairings/FP6BN254/squareFp6BN254.zkasm +147 -0
- package/main/pairings/FP6BN254/subFp6BN254.zkasm +59 -0
- package/main/pairings/FPBN254/addFpBN254.zkasm +29 -0
- package/main/pairings/FPBN254/invFpBN254.zkasm +55 -0
- package/main/pairings/FPBN254/mulFpBN254.zkasm +29 -0
- package/main/pairings/FPBN254/reduceFpBN254.zkasm +25 -0
- package/main/pairings/FPBN254/squareFpBN254.zkasm +31 -0
- package/main/pairings/FPBN254/subFpBN254.zkasm +36 -0
- package/main/pairings/FRBN254/reduceFrBN254.zkasm +25 -0
- package/main/pairings/constants.zkasm +62 -0
- package/main/pairings/ecPairing.zkasm +244 -0
- package/main/pairings/finalExpBN254.zkasm +2095 -0
- package/main/pairings/halfPairingBN254.zkasm +428 -0
- package/main/pairings/loopLengthBN254.zkasm +75 -0
- package/main/pairings/millerLoopBN254.zkasm +741 -0
- package/main/pairings/pairingBN254.zkasm +481 -0
- package/main/pairings/unused/addFp12BN254.zkasm +130 -0
- package/main/pairings/unused/expByXCycloFp12BN254.zkasm +411 -0
- package/main/pairings/unused/expFp12BN254.zkasm +333 -0
- package/main/pairings/unused/subFp12BN254.zkasm +130 -0
- package/main/pairings/unused/xPseudoBinDecompBN254.zkasm +68 -0
- package/main/pairings/utilsTests/expCycloFp12BN254.zkasm +334 -0
- package/main/precompiled/end.zkasm +42 -0
- package/main/precompiled/identity.zkasm +99 -0
- package/main/precompiled/pre-ecAdd.zkasm +84 -0
- package/main/precompiled/pre-ecMul.zkasm +82 -0
- package/main/precompiled/pre-ecPairing.zkasm +72 -0
- package/main/precompiled/pre-ecrecover.zkasm +71 -0
- package/main/precompiled/pre-modexp.zkasm +367 -0
- package/main/precompiled/pre-sha2-256.zkasm +125 -0
- package/main/precompiled/revert-precompiled.zkasm +25 -0
- package/main/precompiled/selector.zkasm +77 -0
- package/main/process-change-l2-block.zkasm +147 -0
- package/main/process-tx.zkasm +587 -0
- package/main/tables/2-exp.zkasm +260 -0
- package/main/touched.zkasm +118 -0
- package/main/utils.zkasm +2335 -0
- package/main/vars.zkasm +117 -0
- package/package.json +62 -3
- package/test/bytes-length.zkasm +39 -0
- package/test/ecrecover.zkasm +538 -0
- package/test/lt4-test.zkasm +38 -0
- package/test/mstorex.zkasm +191 -0
- package/test/opcalldatacopy.ignore.zkasm +331 -0
- package/test/performance/read-push.zkasm +71 -0
- package/test/read-push.zkasm +304 -0
- package/test/testArrayArith.zkasm +1099 -0
- package/test/testArrayUtils.zkasm +335 -0
- package/test/testCycloFp12ArithBN254.zkasm +548 -0
- package/test/testEcAdd.zkasm +252 -0
- package/test/testEcMul.zkasm +231 -0
- package/test/testEcPairing.zkasm +436 -0
- package/test/testFinalExpBn254.zkasm +139 -0
- package/test/testFp12ArithBN254.zkasm +692 -0
- package/test/testFp2ArithBN254.zkasm +185 -0
- package/test/testFp4ArithBN254.zkasm +128 -0
- package/test/testFp6ArithBN254.zkasm +260 -0
- package/test/testFpArithBN254.zkasm +159 -0
- package/test/testFrArithBN254.zkasm +113 -0
- package/test/testHalfPairingBN254.zkasm +285 -0
- package/test/testModExp.zkasm +586 -0
- package/test/testModExpReturn.zkasm +81 -0
- package/test/testPairingBN254.zkasm +463 -0
- package/test/testPointArithBN254.zkasm +270 -0
- package/test/testSHA256.zkasm +27 -0
- package/test/touched-assert.zkasm +59 -0
- package/test/utils-expAD.zkasm +48 -0
- package/test/utils-getLenBytes.zkasm +36 -0
- package/tools/audit-tools/registry-op-checker.js +71 -0
- package/tools/get-not-used-labels.js +31 -0
- package/tools/helpers/helpers.js +47 -0
- package/tools/modexp-utils/README.md +5 -0
- package/tools/modexp-utils/modexp-test-gen.js +168 -0
- package/tools/modexp-utils/modexp-test-int.sage +37 -0
- package/tools/parallel-testing/checker.sh +6 -0
- package/tools/parallel-testing/gen-parallel-tests.js +78 -0
- package/tools/parallel-testing/parallel-tests-sample/sample.test.js +136 -0
- 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)
|