|
19 | 19 | ) |
20 | 20 | from ethereum_test_vm import Opcode, UndefinedOpcodes |
21 | 21 | from ethereum_test_vm import Opcodes as Op |
| 22 | +from tests.unscheduled.eip7692_eof_v1.eip3540_eof_v1.opcodes import V1_EOF_ONLY_OPCODES |
| 23 | +from tests.unscheduled.eip7692_eof_v1.gas_test import gas_test |
22 | 24 |
|
23 | 25 | REFERENCE_SPEC_GIT_PATH = "N/A" |
24 | 26 | REFERENCE_SPEC_VERSION = "N/A" |
25 | 27 |
|
26 | 28 |
|
27 | 29 | def prepare_stack(opcode: Opcode) -> Bytecode: |
28 | 30 | """Prepare valid stack for opcode.""" |
29 | | - if opcode == Op.CREATE: |
30 | | - return Op.MSTORE(0, 0x6001600155) + Op.PUSH1(5) + Op.PUSH1(27) + Op.PUSH1(5) |
31 | | - if opcode == Op.CREATE2: |
32 | | - return Op.MSTORE(0, 0x6001600155) + Op.PUSH1(1) + Op.PUSH1(5) + Op.PUSH1(27) + Op.PUSH1(5) |
33 | 31 | if opcode == Op.JUMPI: |
34 | | - return Op.PUSH1(1) + Op.PUSH1(5) |
| 32 | + return Op.PUSH1(1) + Op.PUSH1(3) + Op.PC + Op.ADD |
35 | 33 | if opcode == Op.JUMP: |
36 | | - return Op.PUSH1(3) |
37 | | - if opcode == Op.RETURNDATACOPY: |
38 | | - return Op.PUSH1(0) * 3 |
39 | | - return Op.PUSH1(0x01) * 32 |
| 34 | + return Op.PUSH1(3) + Op.PC + Op.ADD |
| 35 | + return Op.PUSH1(0x00) * 32 |
40 | 36 |
|
41 | 37 |
|
42 | 38 | def prepare_suffix(opcode: Opcode) -> Bytecode: |
@@ -122,3 +118,161 @@ def test_cover_revert(state_test: StateTestFiller, pre: Alloc) -> None: |
122 | 118 | ) |
123 | 119 |
|
124 | 120 | state_test(env=Environment(), pre=pre, post={}, tx=tx) |
| 121 | + |
| 122 | + |
| 123 | +opcode_to_gas = { |
| 124 | + Op.ADD: 3, |
| 125 | + Op.MUL: 5, |
| 126 | + Op.SUB: 3, |
| 127 | + Op.DIV: 5, |
| 128 | + Op.SDIV: 5, |
| 129 | + Op.MOD: 5, |
| 130 | + Op.SMOD: 5, |
| 131 | + Op.ADDMOD: 8, |
| 132 | + Op.MULMOD: 8, |
| 133 | + Op.EXP: 10, |
| 134 | + Op.SIGNEXTEND: 5, |
| 135 | + Op.LT: 3, |
| 136 | + Op.GT: 3, |
| 137 | + Op.SLT: 3, |
| 138 | + Op.SGT: 3, |
| 139 | + Op.EQ: 3, |
| 140 | + Op.ISZERO: 3, |
| 141 | + Op.AND: 3, |
| 142 | + Op.OR: 3, |
| 143 | + Op.XOR: 3, |
| 144 | + Op.NOT: 3, |
| 145 | + Op.BYTE: 3, |
| 146 | + Op.SHL: 3, |
| 147 | + Op.SHR: 3, |
| 148 | + Op.SAR: 3, |
| 149 | + Op.CLZ: 5, |
| 150 | + Op.SHA3: 30, |
| 151 | + Op.ADDRESS: 2, |
| 152 | + Op.BALANCE: 100, |
| 153 | + Op.ORIGIN: 2, |
| 154 | + Op.CALLER: 2, |
| 155 | + Op.CALLVALUE: 2, |
| 156 | + Op.CALLDATALOAD: 3, |
| 157 | + Op.CALLDATASIZE: 2, |
| 158 | + Op.CALLDATACOPY: 3, |
| 159 | + Op.CODESIZE: 2, |
| 160 | + Op.CODECOPY: 3, |
| 161 | + Op.GASPRICE: 2, |
| 162 | + Op.EXTCODESIZE: 100, |
| 163 | + Op.EXTCODECOPY: 100, |
| 164 | + Op.RETURNDATASIZE: 2, |
| 165 | + Op.RETURNDATACOPY: 3, |
| 166 | + Op.EXTCODEHASH: 100, |
| 167 | + Op.BLOCKHASH: 20, |
| 168 | + Op.COINBASE: 2, |
| 169 | + Op.TIMESTAMP: 2, |
| 170 | + Op.NUMBER: 2, |
| 171 | + Op.PREVRANDAO: 2, |
| 172 | + Op.GASLIMIT: 2, |
| 173 | + Op.CHAINID: 2, |
| 174 | + Op.SELFBALANCE: 5, |
| 175 | + Op.BASEFEE: 2, |
| 176 | + Op.BLOBHASH: 3, |
| 177 | + Op.BLOBBASEFEE: 2, |
| 178 | + Op.POP: 2, |
| 179 | + Op.MLOAD: 3, |
| 180 | + Op.MSTORE: 3, |
| 181 | + Op.MSTORE8: 3, |
| 182 | + Op.SLOAD: 100, |
| 183 | + Op.JUMP: 8, |
| 184 | + Op.JUMPI: 10, |
| 185 | + Op.PC: 2, |
| 186 | + Op.MSIZE: 2, |
| 187 | + Op.GAS: 2, |
| 188 | + Op.JUMPDEST: 1, |
| 189 | + Op.TLOAD: 100, |
| 190 | + Op.TSTORE: 100, |
| 191 | + Op.MCOPY: 3, |
| 192 | + Op.PUSH0: 2, |
| 193 | + Op.LOG0: 375, |
| 194 | + Op.LOG1: 2 * 375, |
| 195 | + Op.LOG2: 3 * 375, |
| 196 | + Op.LOG3: 4 * 375, |
| 197 | + Op.LOG4: 5 * 375, |
| 198 | + Op.CREATE: 32000, |
| 199 | + Op.CALL: 100, |
| 200 | + Op.CALLCODE: 100, |
| 201 | + Op.DELEGATECALL: 100, |
| 202 | + Op.CREATE2: 32000, |
| 203 | + Op.STATICCALL: 100, |
| 204 | + Op.SELFDESTRUCT: 5000, |
| 205 | +} |
| 206 | + |
| 207 | +# PUSHx, SWAPx, DUPx have uniform gas costs |
| 208 | +for opcode in set(Op): |
| 209 | + if 0x60 <= opcode.int() <= 0x9F: |
| 210 | + opcode_to_gas[opcode] = 3 |
| 211 | + |
| 212 | +constant_gas_opcodes = ( |
| 213 | + set(Op) |
| 214 | + - |
| 215 | + # zero constant gas opcodes - untestable |
| 216 | + {Op.STOP, Op.RETURN, Op.REVERT, Op.INVALID} |
| 217 | + - |
| 218 | + # TODO: EOF opcodes. Remove once EOF is removed |
| 219 | + set(V1_EOF_ONLY_OPCODES) |
| 220 | + - |
| 221 | + # SSTORE - untestable due to 2300 gas stipend rule |
| 222 | + {Op.SSTORE} |
| 223 | +) |
| 224 | + |
| 225 | + |
| 226 | +# NOTE: Gas costs varying across forks not being supported yet would make this |
| 227 | +# test very complex. |
| 228 | +@pytest.mark.valid_at("Osaka") |
| 229 | +@pytest.mark.parametrize("opcode", sorted(constant_gas_opcodes)) |
| 230 | +def test_constant_gas( |
| 231 | + state_test: StateTestFiller, pre: Alloc, opcode: Op, fork: Fork, env: Environment |
| 232 | +) -> None: |
| 233 | + """Test that constant gas opcodes work as expected.""" |
| 234 | + warm_gas = opcode_to_gas[opcode] |
| 235 | + cold_gas = warm_gas + ( |
| 236 | + 2500 |
| 237 | + if opcode |
| 238 | + in [ |
| 239 | + Op.BALANCE, |
| 240 | + Op.EXTCODESIZE, |
| 241 | + Op.EXTCODECOPY, |
| 242 | + Op.EXTCODEHASH, |
| 243 | + Op.CALL, |
| 244 | + Op.CALLCODE, |
| 245 | + Op.DELEGATECALL, |
| 246 | + Op.STATICCALL, |
| 247 | + ] |
| 248 | + else 2600 |
| 249 | + if opcode == Op.SELFDESTRUCT |
| 250 | + else 2000 |
| 251 | + if opcode == Op.SLOAD |
| 252 | + else 0 |
| 253 | + ) |
| 254 | + |
| 255 | + if fork.transaction_gas_limit_cap(): |
| 256 | + env.gas_limit = fork.transaction_gas_limit_cap() |
| 257 | + |
| 258 | + # Using `TLOAD` / `TSTORE` to work around warm/cold gas differences. We |
| 259 | + # need a counter to pick a distinct salt on each `CREATE2` and avoid |
| 260 | + # running into address conflicts. |
| 261 | + code_increment_counter = Op.TLOAD(1234) + Op.DUP1 + Op.TSTORE(1234, Op.PUSH1(1) + Op.ADD) |
| 262 | + setup_code = ( |
| 263 | + Op.MLOAD(0) |
| 264 | + + Op.POP |
| 265 | + + prepare_stack(opcode) |
| 266 | + + (code_increment_counter if opcode == Op.CREATE2 else Bytecode()) |
| 267 | + ) |
| 268 | + gas_test( |
| 269 | + state_test, |
| 270 | + env, |
| 271 | + pre, |
| 272 | + setup_code=setup_code, |
| 273 | + subject_code=opcode, |
| 274 | + tear_down_code=prepare_suffix(opcode), |
| 275 | + cold_gas=cold_gas, |
| 276 | + warm_gas=warm_gas, |
| 277 | + eof=False, |
| 278 | + ) |
0 commit comments