ZK-COUNTERS TABLE
opcode |
name |
cnt_arith |
cnt_binary |
cnt_mem_align |
cnt_keccak_f |
cnt_padding_pg |
cnt_poseidon_g |
is_dynamic |
0x00 |
STOP |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x01 |
ADD |
0 |
1 |
0 |
0 |
0 |
0 |
false |
0x02 |
MUL |
1 |
0 |
0 |
0 |
0 |
0 |
false |
0x03 |
SUB |
0 |
1 |
0 |
0 |
0 |
0 |
false |
0x04 |
DIV |
1 |
2 |
0 |
0 |
0 |
0 |
false |
0x05 |
SDIV |
1 |
8 |
0 |
0 |
0 |
0 |
false |
0x06 |
MOD |
1 |
2 |
0 |
0 |
0 |
0 |
false |
0x07 |
SMOD |
1 |
8 |
0 |
0 |
0 |
0 |
false |
0x08 |
ADDMOD |
1 |
3 |
0 |
0 |
0 |
0 |
false |
0x09 |
MULMOD |
2 |
2 |
0 |
0 |
0 |
0 |
false |
0x0a |
EXP |
512 |
1025 |
0 |
0 |
0 |
0 |
true |
0x0b |
SIGNEXTEND |
0 |
6 |
0 |
0 |
0 |
0 |
false |
0x10 |
LT |
0 |
1 |
0 |
0 |
0 |
0 |
false |
0x11 |
GT |
0 |
1 |
0 |
0 |
0 |
0 |
false |
0x12 |
SLT |
0 |
1 |
0 |
0 |
0 |
0 |
false |
0x13 |
SGT |
0 |
1 |
0 |
0 |
0 |
0 |
false |
0x14 |
EQ |
0 |
1 |
0 |
0 |
0 |
0 |
false |
0x15 |
ISZERO |
0 |
1 |
0 |
0 |
0 |
0 |
false |
0x16 |
AND |
0 |
1 |
0 |
0 |
0 |
0 |
false |
0x17 |
OR |
0 |
1 |
0 |
0 |
0 |
0 |
false |
0x18 |
XOR |
0 |
1 |
0 |
0 |
0 |
0 |
false |
0x19 |
NOT |
0 |
1 |
0 |
0 |
0 |
0 |
false |
0x1a |
BYTE |
2 |
4 |
0 |
0 |
0 |
0 |
false |
0x1b |
SHL |
1 |
2 |
0 |
0 |
0 |
0 |
false |
0x1c |
SHR |
1 |
3 |
0 |
0 |
0 |
0 |
false |
0x1d |
SAR |
2 |
10 |
0 |
0 |
0 |
0 |
false |
0x20 |
SHA3 |
192 |
193 |
2 |
2 |
0 |
10 |
true |
0x30 |
ADDRESS |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x31 |
BALANCE |
0 |
0 |
0 |
0 |
0 |
9 |
false |
0x32 |
ORIGIN |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x33 |
CALLER |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x34 |
CALLVALUE |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x35 |
CALLDATALOAD |
64 |
66 |
0 |
0 |
0 |
0 |
true |
0x36 |
CALLDATASIZE |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x37 |
CALLDATACOPY |
- |
- |
- |
0 |
0 |
0 |
true |
0x38 |
CODESIZE |
0 |
0 |
0 |
0 |
0 |
252 |
true |
0x39 |
CODECOPY |
0 |
- |
- |
0 |
0 |
255 |
true |
0x3a |
GASPRICE |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x3b |
EXTCODESIZE |
0 |
0 |
0 |
0 |
0 |
255 |
true |
0x3c |
EXTCODECOPY |
0 |
- |
- |
0 |
11 |
510 |
true |
0x3d |
RETURNDATASIZE |
0 |
1 |
0 |
0 |
0 |
0 |
false |
0x3e |
RETURNDATACOPY |
- |
- |
2 |
0 |
0 |
0 |
true |
0x3f |
EXTCODEHASH |
0 |
0 |
0 |
0 |
0 |
255 |
true |
0x40 |
BLOCKHASH |
0 |
0 |
0 |
1 |
0 |
9 |
false |
0x41 |
COINBASE |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x42 |
TIMESTAMP |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x43 |
NUMBER |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x44 |
DIFFICULTY |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x45 |
GASLIMIT |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x46 |
CHAINID |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x47 |
SELFBALANCE |
0 |
0 |
0 |
0 |
0 |
255 |
true |
0x50 |
POP |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x51 |
MLOAD |
32 |
32 |
1 |
0 |
0 |
255 |
true |
0x52 |
MSTORE |
32 |
32 |
1 |
0 |
0 |
255 |
true |
0x53 |
MSTORE8 |
32 |
1 |
1 |
0 |
0 |
255 |
false |
0x54 |
SLOAD |
0 |
0 |
0 |
0 |
0 |
255 |
true |
0x55 |
SSTORE |
0 |
- |
0 |
0 |
0 |
255 |
true |
0x56 |
JUMP |
0 |
- |
0 |
0 |
0 |
0 |
true |
0x57 |
JUMPI |
0 |
- |
0 |
0 |
0 |
0 |
true |
0x59 |
MSIZE |
1 |
3 |
0 |
0 |
0 |
0 |
false |
0x5a |
GAS |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x5b |
JUMPDEST |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x60 |
PUSH1 |
0 |
3 |
0 |
0 |
0 |
0 |
true |
0x61 |
PUSH2 |
0 |
4 |
0 |
0 |
0 |
0 |
true |
0x62 |
PUSH3 |
0 |
5 |
0 |
0 |
0 |
0 |
false |
0x63 |
PUSH4 |
0 |
2 |
0 |
0 |
0 |
0 |
false |
0x64 |
PUSH5 |
0 |
4 |
0 |
0 |
0 |
0 |
false |
0x65 |
PUSH6 |
0 |
5 |
0 |
0 |
0 |
0 |
false |
0x66 |
PUSH7 |
0 |
6 |
0 |
0 |
0 |
0 |
false |
0x67 |
PUSH8 |
0 |
3 |
0 |
0 |
0 |
0 |
false |
0x68 |
PUSH9 |
0 |
5 |
0 |
0 |
0 |
0 |
false |
0x69 |
PUSH10 |
0 |
6 |
0 |
0 |
0 |
0 |
false |
0x6a |
PUSH11 |
0 |
7 |
0 |
0 |
0 |
0 |
false |
0x6b |
PUSH12 |
0 |
4 |
0 |
0 |
0 |
0 |
false |
0x6c |
PUSH13 |
0 |
6 |
0 |
0 |
0 |
0 |
false |
0x6d |
PUSH14 |
0 |
7 |
0 |
0 |
0 |
0 |
false |
0x6e |
PUSH15 |
0 |
8 |
0 |
0 |
0 |
0 |
false |
0x6f |
PUSH16 |
0 |
5 |
0 |
0 |
0 |
0 |
false |
0x70 |
PUSH17 |
0 |
7 |
0 |
0 |
0 |
0 |
false |
0x71 |
PUSH18 |
0 |
8 |
0 |
0 |
0 |
0 |
false |
0x72 |
PUSH19 |
0 |
9 |
0 |
0 |
0 |
0 |
false |
0x73 |
PUSH20 |
0 |
6 |
0 |
0 |
0 |
0 |
false |
0x74 |
PUSH21 |
0 |
8 |
0 |
0 |
0 |
0 |
false |
0x75 |
PUSH22 |
0 |
9 |
0 |
0 |
0 |
0 |
false |
0x76 |
PUSH23 |
0 |
10 |
0 |
0 |
0 |
0 |
false |
0x77 |
PUSH24 |
0 |
7 |
0 |
0 |
0 |
0 |
false |
0x78 |
PUSH25 |
0 |
9 |
0 |
0 |
0 |
0 |
false |
0x79 |
PUSH26 |
0 |
10 |
0 |
0 |
0 |
0 |
false |
0x7a |
PUSH27 |
0 |
11 |
0 |
0 |
0 |
0 |
false |
0x7b |
PUSH28 |
0 |
8 |
0 |
0 |
0 |
0 |
false |
0x7c |
PUSH29 |
0 |
10 |
0 |
0 |
0 |
0 |
false |
0x7d |
PUSH30 |
0 |
11 |
0 |
0 |
0 |
0 |
false |
0x7e |
PUSH31 |
0 |
12 |
0 |
0 |
0 |
0 |
false |
0x7f |
PUSH32 |
0 |
9 |
0 |
0 |
0 |
0 |
false |
0x80 |
DUP1 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x81 |
DUP2 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x82 |
DUP3 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x83 |
DUP4 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x84 |
DUP5 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x85 |
DUP6 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x86 |
DUP7 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x87 |
DUP8 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x88 |
DUP9 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x90 |
SWAP1 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x91 |
SWAP2 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x92 |
SWAP3 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x93 |
SWAP4 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x94 |
SWAP5 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x95 |
SWAP6 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0x96 |
SWAP7 |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0xa0 |
LOG0 |
0 |
- |
0 |
0 |
0 |
0 |
true |
0xa1 |
LOG1 |
0 |
- |
0 |
0 |
0 |
0 |
true |
0xa2 |
LOG2 |
0 |
- |
0 |
0 |
0 |
0 |
true |
0xa3 |
LOG3 |
0 |
- |
0 |
0 |
0 |
0 |
true |
0xa4 |
LOG4 |
0 |
- |
0 |
0 |
0 |
0 |
true |
0xf0 |
CREATE |
- |
- |
0 |
- |
0 |
- |
true |
0xf1 |
CALL |
- |
- |
0 |
0 |
- |
- |
true |
0xf2 |
CALLCODE |
- |
- |
0 |
0 |
- |
- |
true |
0xf3 |
RETURN |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0xf4 |
DELEGATECALL |
- |
- |
0 |
0 |
- |
- |
true |
0xf5 |
CREATE2 |
- |
- |
0 |
- |
0 |
- |
true |
0xfa |
STATICCALL |
- |
- |
0 |
0 |
- |
- |
true |
0xfd |
REVERT |
0 |
0 |
0 |
0 |
0 |
0 |
false |
0xfe |
INVALID |
0 |
1 |
0 |
0 |
0 |
0 |
false |
Dynamic zk-counters
In the following doc, we calculate the cost of processing the opcode. It's important to also add the cost of calculating the cost
EXP
Inputs:
1- a: integer base.
2- exponent: integer exponent.
dynamic_gas = 50 * exponent_byte_size
We need to calculate the exponent byte size to get the gas cost. The counters cost is dynamic but we can't calculate the cost without consuming counters in a dynamic way. We need to find a way to get the size of the exponent in a constant manner or handle the counters limitations from the zkasm.
Maximum setted: Maxmimun byte syze = 256 bytes. Max counters = 256 * (2A + 4B) + 1B = 512A + 1025B
SHA3
L = input length
L/32 = A
L % 32 > 0 ? true -> B = 1, false -> B = 0
cnt_arith = 2 + B6
cnt_binary = 2 + A + B9
cnt_keccak = 1
CALLDATALOAD
L = byte offset in the calldata.
L/32 = A
L % 32 > 0 ? true -> B = 1, false -> B = 0
counters = divARITH + B*(SHLarith + SHRarith)
CALLDATACOPY
L = Length to copy.
L/32 = A
L % 32 > 0 ? true -> B = 1, false -> B = 0
counters = A(divARITH + SHLarith + SHRarith + MSTORE32) + SHLarith2 + SHRarith + MSTOREX
CODESIZE
counters = SLOAD
CODECOPY
L = bytes to copy.
if is createContract -> counters = CALLDATACOPY
else -> counters = LT + L*(LT + MEM_ALIGN_WR8)
EXTCODESIZE
counters = SLOAD
EXTCODECOPY
L = bytes to copy.
if is createContract -> counters = CALLDATACOPY
else -> counters = LT + L*(LT + MEM_ALIGN_WR8)
RETURNDATACOPY
L = Length to copy.
L/32 = A
L % 32 > 0 ? true -> B = 1, false -> B = 0
counters = 2EQ + LT + divARITH + mulARITH + A(MLOAD32 + MSTORE32) + B*(MLOADX + MSTOREX)
EXTCODEHASH
counters = SLOAD
SELFBALANCE
counters = SLOAD
MLOAD
counters = MLOAD32
MSTORE
counters = MSTORE32
SLOAD
counters = SLOAD
SSTORE
Cant calculate
JUMPI
isCreateContract ? true -> A = 1, false -> A = 0
isCreate ? true -> B = 1, false -> B = 0
counters = EQ + A(B(MLOADX + SHRarith) + (1-B)(EQ)) + (1-A)(EQ)
JUMP
isCreateContract ? true -> A = 1, false -> A = 0
isCreate ? true -> B = 1, false -> B = 0
counters = EQ + A(B(MLOADX + SHRarith) + (1-B)(EQ)) + (1-A)(EQ)
LOG
L = byte size to copy.
L/32 = A
L % 32 > 0 ? true -> B = 1, false -> B = 0
counters = AMLOAD32 + BMLOADX
CREATE
counters = computeGasSendCall + copySP + SLOAD + SSTORE + getLenBytes
CALL
argsLengthCall + retLength == 0 ? true -> A = 1, false -> A = 0
argsOffsetCall > memLength ? true -> B = 1, false -> B = 0
counters = addARITH + EQ + (1-A)(LT +BsaveMem ) + LT + isEmptyAccount + computeGasSendCall + copySP
CALLCODE
counters = 2EQ + LT2 + computeGasSendCall + copySP
DELEGATECALL
counters = 2EQ + LT2 + computeGasSendCall + copySP
CREATE2
counters = computeGasSendCall + copySP + SLOAD + SSTORE + getLenBytes
STATICCALL
counters = 2EQ + LT2 + computeGasSendCall + copySP
REGS TABLE
REG Name |
cnt_arith |
cnt_binary |
cnt_mem_align |
cnt_keccak_f |
cnt_padding_pg |
cnt_poseidon_g |
is_dynamic |
LT |
0 |
1 |
0 |
0 |
0 |
0 |
false |
EQ |
0 |
1 |
0 |
0 |
0 |
0 |
false |
ARITH |
1 |
0 |
0 |
0 |
0 |
0 |
false |
SLOAD |
0 |
0 |
0 |
0 |
0 |
11 |
true |
SSTORE |
0 |
0 |
0 |
0 |
0 |
11 |
true |
MEM_ALIGN_WR8 |
0 |
0 |
1 |
0 |
0 |
0 |
false |
Dynamic regs
SSTORE
SLOAD
Should check how SLOAD is implemented
Functions TABLE
FUNC Name |
cnt_arith |
cnt_binary |
cnt_mem_align |
cnt_keccak_f |
cnt_padding_pg |
cnt_poseidon_g |
is_dynamic |
addARITH |
0 |
1 |
0 |
0 |
0 |
0 |
false |
divARITH |
1 |
2 |
0 |
0 |
0 |
0 |
false |
subARITH |
0 |
1 |
0 |
0 |
0 |
0 |
false |
mulARITH |
1 |
0 |
0 |
0 |
0 |
0 |
false |
saveMem |
0 |
0 |
0 |
0 |
0 |
0 |
false |
computeGasSendCall |
0 |
1 |
0 |
0 |
0 |
0 |
false |
copySP |
- |
- |
0 |
0 |
0 |
0 |
true |
MLOAD32 |
0 |
0 |
0 |
0 |
0 |
0 |
true |
MLOADX |
0 |
0 |
0 |
0 |
0 |
0 |
true |
MSTORE32 |
0 |
0 |
0 |
0 |
0 |
0 |
true |
MSTOREX |
0 |
0 |
0 |
0 |
0 |
0 |
true |
sliceA |
0 |
0 |
0 |
0 |
0 |
0 |
false |
SHRarith |
- |
- |
0 |
0 |
0 |
0 |
true |
SHLarith |
- |
- |
0 |
0 |
0 |
0 |
true |
opCODECOPYLoadBytes |
0 |
1 |
0 |
0 |
0 |
0 |
false |
isEmptyAccount |
- |
- |
0 |
0 |
0 |
0 |
true |
Dynamic functions
copySP
It depends on the stack size.
L = stack length
L/32 = A
L % 32 > 0 ? true -> B = 1, false -> B = 0
counters = MLOAD32 * (A + B)
MLOAD32
MSTORE32
MSTOREX
MLOADX
L = bytes length
L > 0 ? true -> A = 1, false -> A = 0
isMSTOREX ? true -> B = 1, false -> B = 0
counters = LT + B(2SHRarith + 2SHLarith) + (1-B)(C(2SHLarith + 4SHRarith) + (1-C)(2SHRarith + 2SHLarith) + MEM_ALIGN_WR)
MAX:
counters = 192A + 193B + 2MA
SHRarith
SHLarith
A -> bytes to shift
D -> times to shift (A << D)
E -> D > 256? true = 1, false = 0
counters= ARITH + EQ + (1-E) (D(LT + ARITH)) = 1A + 1B + (1-E)(D(1A + 1B)
MAX:
counters = 32A + 32B
isEmptyAccount
isNotPrecompiled ? true -> A = 1, false -> A = 0
zeroBalance ? true -> B = 1, false -> B = 0
zeroNonce ? true -> C = 1, false -> C = 0
counters = LT + A(SLOAD + LT + B(SLOAD + LT + C*(SLOAD + LT)))
https://github.com/0xPolygonHermez/zkevm-rom/blob/main/docs/opcode-cost-zk-counters.md