Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
fuzz.test.cpp
Go to the documentation of this file.
1#include <gtest/gtest.h>
2#include <iostream>
3
9
10namespace arithmetic {
11
12// set(addr 0, 5) set(addr 1, 2) OP(addr 0, addr 1, addr 2) return(addr 2)
15{
16 auto set_instruction_1 = SET_8_Instruction{ .value_tag = bb::avm2::MemoryTag::U8,
17 .result_address = ResultAddressRef{ .address = 0 },
18 .value = 5 };
19 auto set_instruction_2 = SET_8_Instruction{ .value_tag = bb::avm2::MemoryTag::U8,
20 .result_address = ResultAddressRef{ .address = 1 },
21 .value = 2 };
22 auto instructions = std::vector<FuzzInstruction>{ set_instruction_1, set_instruction_2, instruction };
23 auto return_options =
24 ReturnOptions{ .return_size = 1, .return_value_tag = return_value_tag, .return_value_offset_index = 2 };
25 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
26 auto control_flow = ControlFlow(instruction_blocks);
28 auto bytecode = control_flow.build_bytecode(return_options);
29 auto cpp_simulator = CppSimulator();
30 auto result = cpp_simulator.simulate(bytecode, {});
31 return result.output.at(0);
32}
33
34TEST(fuzz, ADD8)
35{
36 auto add_instruction =
40 .index = 0,
42 },
43 .b_address =
45 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct } };
46 auto result = get_result_of_instruction(add_instruction);
47 EXPECT_EQ(result, 7);
48}
49
50TEST(fuzz, SUB8)
51{
52 auto sub_instruction = SUB_8_Instruction{
54 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
55 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
56 };
57 auto result = get_result_of_instruction(sub_instruction);
58 EXPECT_EQ(result, 3);
59}
60
61TEST(fuzz, MUL8)
62{
63 auto mul_instruction = MUL_8_Instruction{
65 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
66 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
67 };
68 auto result = get_result_of_instruction(mul_instruction);
69 EXPECT_EQ(result, 10);
70}
71
72TEST(fuzz, DIV8)
73{
74 auto div_instruction = DIV_8_Instruction{
76 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
77 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
78 };
79 auto result = get_result_of_instruction(div_instruction);
80 EXPECT_EQ(result, 2);
81}
82
84{
85 auto eq_instruction = EQ_8_Instruction{
87 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
88 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
89 };
90 auto result = get_result_of_instruction(eq_instruction, bb::avm2::MemoryTag::U1);
91 EXPECT_EQ(result, 0);
92}
93
95{
96 auto lt_instruction = LT_8_Instruction{
98 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
99 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
100 };
101 auto result = get_result_of_instruction(lt_instruction, bb::avm2::MemoryTag::U1);
102 EXPECT_EQ(result, 0);
103}
104
105TEST(fuzz, LTE8)
106{
107 auto lte_instruction = LTE_8_Instruction{
109 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
110 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
111 };
112 auto result = get_result_of_instruction(lte_instruction, bb::avm2::MemoryTag::U1);
113 EXPECT_EQ(result, 0);
114}
115
116TEST(fuzz, AND8)
117{
118 auto and_instruction = AND_8_Instruction{
120 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
121 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
122 };
123 auto result = get_result_of_instruction(and_instruction);
124 EXPECT_EQ(result, 0);
125}
126
128{
129 auto or_instruction = OR_8_Instruction{
131 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
132 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
133 };
134 auto result = get_result_of_instruction(or_instruction);
135 EXPECT_EQ(result, 7);
136}
137
138TEST(fuzz, XOR8)
139{
140 auto xor_instruction = XOR_8_Instruction{
142 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
143 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
144 };
145 auto result = get_result_of_instruction(xor_instruction);
146 EXPECT_EQ(result, 7);
147}
148
149TEST(fuzz, SHL8)
150{
151 auto shl_instruction = SHL_8_Instruction{
153 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
154 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
155 };
156 auto result = get_result_of_instruction(shl_instruction);
157 EXPECT_EQ(result, 20);
158}
159
160TEST(fuzz, SHR8)
161{
162 auto shr_instruction = SHR_8_Instruction{
164 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
165 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
166 };
167 auto result = get_result_of_instruction(shr_instruction);
168 EXPECT_EQ(result, 1);
169}
170
171// set(0, 4, FF) set(1, 2, FF) fdiv(FF, 0, 1, 2) return(2)
172TEST(fuzz, FDIV8)
173{
174 auto fdiv_instruction = FDIV_8_Instruction{
176 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::FF, .index = 1, .mode = AddressingMode::Direct },
177 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
178 };
179 auto set_instruction_1 =
181 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
182 .value = 4 };
183 auto set_instruction_2 =
185 .result_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct },
186 .value = 2 };
187 auto instructions = std::vector<FuzzInstruction>{ set_instruction_1, set_instruction_2, fdiv_instruction };
188
189 auto return_options =
190 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 2 };
191 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
192 auto control_flow = ControlFlow(instruction_blocks);
193 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
194 auto bytecode = control_flow.build_bytecode(return_options);
195 auto cpp_simulator = CppSimulator();
196 auto result = cpp_simulator.simulate(bytecode, {});
197 EXPECT_EQ(result.output.at(0), 2);
198}
199
200// set(0, 0, U8) not(U8, 0, 1) return(1)
201TEST(fuzz, NOT8)
202{
203 auto set_instruction =
205 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
206 .value = 0 };
207 auto not_instruction =
210 .result_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct } };
211 auto instructions = std::vector<FuzzInstruction>{ set_instruction, not_instruction };
212 auto return_options =
213 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U8, .return_value_offset_index = 1 };
214 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
215 auto control_flow = ControlFlow(instruction_blocks);
216 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
217 auto bytecode = control_flow.build_bytecode(return_options);
218 auto cpp_simulator = CppSimulator();
219 auto result = cpp_simulator.simulate(bytecode, {});
220 EXPECT_EQ(result.output.at(0), 255);
221}
222
223// Helper function for 16-bit instructions
224// set(addr 0, 5) set(addr 1, 2) OP_16(addr 0, addr 1, addr 2) return(addr 2)
227{
228 auto set_instruction_1 =
230 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
231 .value = 5 };
232 auto set_instruction_2 =
234 .result_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct },
235 .value = 2 };
236 auto instructions = std::vector<FuzzInstruction>{ set_instruction_1, set_instruction_2, instruction };
237
238 auto return_options =
239 ReturnOptions{ .return_size = 1, .return_value_tag = return_value_tag, .return_value_offset_index = 2 };
240 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
241 auto control_flow = ControlFlow(instruction_blocks);
242 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
243 auto bytecode = control_flow.build_bytecode(return_options);
244 auto cpp_simulator = CppSimulator();
245 auto result = cpp_simulator.simulate(bytecode, {});
246 return result.output.at(0);
247}
248
249TEST(fuzz, ADD16)
250{
251 auto add_instruction = ADD_16_Instruction{
252 .a_address =
255 .index = 0,
257 },
258 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
259 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
260 };
261 auto result = get_result_of_instruction_16(add_instruction);
262 EXPECT_EQ(result, 7);
263}
264
265TEST(fuzz, SUB16)
266{
267 auto sub_instruction = SUB_16_Instruction{
269 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
270 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
271 };
272 auto result = get_result_of_instruction_16(sub_instruction);
273 EXPECT_EQ(result, 3);
274}
275
276TEST(fuzz, MUL16)
277{
278 auto mul_instruction = MUL_16_Instruction{
280 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
281 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
282 };
283 auto result = get_result_of_instruction_16(mul_instruction);
284 EXPECT_EQ(result, 10);
285}
286
287TEST(fuzz, DIV16)
288{
289 auto div_instruction = DIV_16_Instruction{
291 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
292 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
293 };
294 auto result = get_result_of_instruction_16(div_instruction);
295 EXPECT_EQ(result, 2);
296}
297
298TEST(fuzz, EQ16)
299{
300 auto eq_instruction = EQ_16_Instruction{
302 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
303 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
304 };
305 auto result = get_result_of_instruction_16(eq_instruction, bb::avm2::MemoryTag::U1);
306 EXPECT_EQ(result, 0);
307}
308
309TEST(fuzz, LT16)
310{
311 auto lt_instruction = LT_16_Instruction{
313 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
314 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
315 };
316 auto result = get_result_of_instruction_16(lt_instruction, bb::avm2::MemoryTag::U1);
317 EXPECT_EQ(result, 0);
318}
319
320TEST(fuzz, LTE16)
321{
322 auto lte_instruction = LTE_16_Instruction{
324 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
325 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
326 };
327 auto result = get_result_of_instruction_16(lte_instruction, bb::avm2::MemoryTag::U1);
328 EXPECT_EQ(result, 0);
329}
330
331TEST(fuzz, AND16)
332{
333 auto and_instruction = AND_16_Instruction{
335 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
336 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
337 };
338 auto result = get_result_of_instruction_16(and_instruction);
339 EXPECT_EQ(result, 0);
340}
341
342TEST(fuzz, OR16)
343{
344 auto or_instruction = OR_16_Instruction{
346 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
347 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
348 };
349 auto result = get_result_of_instruction_16(or_instruction);
350 EXPECT_EQ(result, 7);
351}
352
353TEST(fuzz, XOR16)
354{
355 auto xor_instruction = XOR_16_Instruction{
357 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
358 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
359 };
360 auto result = get_result_of_instruction_16(xor_instruction);
361 EXPECT_EQ(result, 7);
362}
363
364TEST(fuzz, SHL16)
365{
366 auto shl_instruction = SHL_16_Instruction{
368 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
369 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
370 };
371 auto result = get_result_of_instruction_16(shl_instruction);
372 EXPECT_EQ(result, 20);
373}
374
375TEST(fuzz, SHR16)
376{
377 auto shr_instruction = SHR_16_Instruction{
379 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::U8, .index = 1, .mode = AddressingMode::Direct },
380 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
381 };
382 auto result = get_result_of_instruction_16(shr_instruction);
383 EXPECT_EQ(result, 1);
384}
385
386// set(0, 4, FF) set(1, 2, FF) fdiv_16(FF, 0, 1, 2) return(2)
387TEST(fuzz, FDIV16)
388{
389 auto fdiv_instruction = FDIV_16_Instruction{
391 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::FF, .index = 1, .mode = AddressingMode::Direct },
392 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
393 };
394 auto set_instruction_1 =
396 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
397 .value = 4 };
398 auto set_instruction_2 =
400 .result_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct },
401 .value = 2 };
402 auto instructions = std::vector<FuzzInstruction>{ set_instruction_1, set_instruction_2, fdiv_instruction };
403
404 auto return_options =
405 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 2 };
406 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
407 auto control_flow = ControlFlow(instruction_blocks);
408 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
409 auto bytecode = control_flow.build_bytecode(return_options);
410 auto cpp_simulator = CppSimulator();
411 auto result = cpp_simulator.simulate(bytecode, {});
412 EXPECT_EQ(result.output.at(0), 2);
413}
414
415// set(0, 0, U8) not_16(U8, 0, 1) return(1)
416TEST(fuzz, NOT16)
417{
418 auto set_instruction =
420 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
421 .value = 0 };
422 auto not_instruction = NOT_16_Instruction{
424 .result_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct }
425 };
426 auto instructions = std::vector<FuzzInstruction>{ set_instruction, not_instruction };
427 auto return_options =
428 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U8, .return_value_offset_index = 1 };
429 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
430 auto control_flow = ControlFlow(instruction_blocks);
431 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
432 auto bytecode = control_flow.build_bytecode(return_options);
433 auto cpp_simulator = CppSimulator();
434 auto result = cpp_simulator.simulate(bytecode, {});
435 EXPECT_EQ(result.output.at(0), 255);
436}
437} // namespace arithmetic
438
440// set(10, 1, U16) set(0, 2, U8) cast_8(U8, 0, 1, U16) return(1)
441// if cast worked, should return 2 (the U8 value cast to U16)
442// if cast failed, should return 1 (the original U16 value)
443TEST(fuzz, CAST8)
444{
445 auto set_u16 =
447 .result_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
448 .value = 1 };
450 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
451 .value = 2 };
452 auto cast_instruction = CAST_8_Instruction{
454 .result_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct },
455 .target_tag = bb::avm2::MemoryTag::U16
456 };
457 auto instructions = std::vector<FuzzInstruction>{ set_u16, set_u8, cast_instruction };
458 auto return_options =
459 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U16, .return_value_offset_index = 1 };
460 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
461 auto control_flow = ControlFlow(instruction_blocks);
462 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
463 auto bytecode = control_flow.build_bytecode(return_options);
464 auto cpp_simulator = CppSimulator();
465 auto result = cpp_simulator.simulate(bytecode, {});
466 EXPECT_EQ(result.output.at(0), 2);
467}
468
469// set(10, 1, U16) set(0, 2, U8) cast_16(U8, 0, 1, U16) return(1)
470// if cast worked, should return 2 (the U8 value cast to U16)
471// if cast failed, should return 1 (the original U16 value)
472TEST(fuzz, CAST16)
473{
474 auto set_u16 =
476 .result_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
477 .value = 1 };
479 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
480 .value = 2 };
481 auto cast_instruction = CAST_16_Instruction{
483 .result_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct },
484 .target_tag = bb::avm2::MemoryTag::U16
485 };
486 auto instructions = std::vector<FuzzInstruction>{ set_u16, set_u8, cast_instruction };
487 auto return_options =
488 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U16, .return_value_offset_index = 1 };
489 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
490 auto control_flow = ControlFlow(instruction_blocks);
491 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
492 auto bytecode = control_flow.build_bytecode(return_options);
493 auto cpp_simulator = CppSimulator();
494 auto result = cpp_simulator.simulate(bytecode, {});
495 EXPECT_EQ(result.output.at(0), 2);
496}
497} // namespace type_conversion
498
499namespace machine_memory {
500// set(0, 0xabcd, U16) return(0)
501TEST(fuzz, SET16)
502{
503 const uint16_t test_value = 0xABCD;
504 auto set_instruction =
506 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
507 .value = test_value };
508 auto instructions = std::vector<FuzzInstruction>{ set_instruction };
509 auto return_options =
510 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U16, .return_value_offset_index = 0 };
511 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
512 auto control_flow = ControlFlow(instruction_blocks);
513 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
514 auto bytecode = control_flow.build_bytecode(return_options);
515 auto cpp_simulator = CppSimulator();
516 auto result = cpp_simulator.simulate(bytecode, {});
517 EXPECT_EQ(result.output.at(0), test_value);
518}
519// set(0, 0x12345678, U32) return(0)
520TEST(fuzz, SET32)
521{
522 const uint32_t test_value = 0x12345678UL;
523 auto set_instruction =
525 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
526 .value = test_value };
527 auto instructions = std::vector<FuzzInstruction>{ set_instruction };
528 auto return_options =
529 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U32, .return_value_offset_index = 0 };
530 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
531 auto control_flow = ControlFlow(instruction_blocks);
532 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
533 auto bytecode = control_flow.build_bytecode(return_options);
534 auto cpp_simulator = CppSimulator();
535 auto result = cpp_simulator.simulate(bytecode, {});
536 EXPECT_EQ(result.output.at(0), test_value);
537}
538
539// set(0, 0xabcdef0123456789, U64) return(0)
540TEST(fuzz, SET64)
541{
542 const uint64_t test_value = 0xABCDEF0123456789ULL;
543 auto set_instruction =
545 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
546 .value = test_value };
547 auto instructions = std::vector<FuzzInstruction>{ set_instruction };
548 auto return_options =
549 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U64, .return_value_offset_index = 0 };
550 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
551 auto control_flow = ControlFlow(instruction_blocks);
552 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
553 auto bytecode = control_flow.build_bytecode(return_options);
554 auto cpp_simulator = CppSimulator();
555 auto result = cpp_simulator.simulate(bytecode, {});
556 EXPECT_EQ(result.output.at(0), test_value);
557}
558
559// set(0, something, U128) return(0)
560TEST(fuzz, SET128)
561{
562 const uint64_t test_value_low = 0xFEDCBA9876543210ULL;
563 const uint64_t test_value_high = 0x123456789ABCDEF0ULL;
564 const uint128_t test_value =
565 (static_cast<uint128_t>(test_value_high) << 64) | static_cast<uint128_t>(test_value_low);
566 auto set_instruction =
568 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
569 .value_low = test_value_low,
570 .value_high = test_value_high };
571 auto instructions = std::vector<FuzzInstruction>{ set_instruction };
572 auto return_options = ReturnOptions{ .return_size = 1,
573 .return_value_tag = bb::avm2::MemoryTag::U128,
574 .return_value_offset_index = 0 };
575 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
576 auto control_flow = ControlFlow(instruction_blocks);
577 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
578 auto bytecode = control_flow.build_bytecode(return_options);
579 auto cpp_simulator = CppSimulator();
580 auto result = cpp_simulator.simulate(bytecode, {});
581 EXPECT_EQ(result.output.at(0), test_value);
582}
583
584// set(0, 123456789, FF) return(0)
585TEST(fuzz, SETFF)
586{
587 const bb::avm2::FF test_value = bb::avm2::FF(123456789);
588 auto set_instruction =
590 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
591 .value = test_value };
592 auto instructions = std::vector<FuzzInstruction>{ set_instruction };
593 auto return_options =
594 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 0 };
595 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
596 auto control_flow = ControlFlow(instruction_blocks);
597 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
598 auto bytecode = control_flow.build_bytecode(return_options);
599 auto cpp_simulator = CppSimulator();
600 auto result = cpp_simulator.simulate(bytecode, {});
601 EXPECT_EQ(result.output.at(0), test_value);
602}
603
604// set(0, 0x42, U8) set(1, 0x43, U8) mov_8(U8, 0, 1) return(1)
605TEST(fuzz, MOV8)
606{
607 const uint8_t test_value = 0x42;
608 const uint8_t test_value2 = 0x43;
609 auto set_instruction =
611 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
612 .value = test_value };
613 auto set_instruction2 = SET_8_Instruction{ .value_tag = bb::avm2::MemoryTag::U8,
614 .result_address = ResultAddressRef{ .address = 1 },
615 .value = test_value2 };
616 auto mov_instruction =
619 .result_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct } };
620 auto instructions = std::vector<FuzzInstruction>{ set_instruction, set_instruction2, mov_instruction };
621 auto return_options =
622 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U8, .return_value_offset_index = 1 };
623 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
624 auto control_flow = ControlFlow(instruction_blocks);
625 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
626 auto bytecode = control_flow.build_bytecode(return_options);
627 auto cpp_simulator = CppSimulator();
628 auto result = cpp_simulator.simulate(bytecode, {});
629 EXPECT_EQ(result.output.at(0), test_value);
630}
631
632// set(0, 0xbabe, U16) set(1, 0xc0fe, U16) mov_16(U16, 0, 1) return(1)
633TEST(fuzz, MOV16)
634{
635 const uint16_t test_value = 0xbabe;
636 const uint16_t test_value2 = 0xc0fe;
637 auto set_instruction =
639 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
640 .value = test_value };
641 auto set_instruction2 =
643 .result_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct },
644 .value = test_value2 };
645 auto mov_instruction = MOV_16_Instruction{
647 .result_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct }
648 };
649 auto instructions = std::vector<FuzzInstruction>{ set_instruction, set_instruction2, mov_instruction };
650 auto return_options =
651 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U16, .return_value_offset_index = 1 };
652 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
653 auto control_flow = ControlFlow(instruction_blocks);
654 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
655 auto bytecode = control_flow.build_bytecode(return_options);
656 auto cpp_simulator = CppSimulator();
657 auto result = cpp_simulator.simulate(bytecode, {});
658 EXPECT_EQ(result.output.at(0), test_value);
659}
660
661} // namespace machine_memory
662
663namespace control_flow {
664
665// block1 set return value 10
666// ↓
667// block2 set return value 11 and return return value
668TEST(fuzz, JumpToNewBlockSmoke)
669{
670 auto block1_instructions = std::vector<FuzzInstruction>{ SET_8_Instruction{
672 .result_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
673 .value = 10 } };
674 auto block2_instructions = std::vector<FuzzInstruction>{ SET_8_Instruction{
676 .result_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
677 .value = 11 } };
678 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ block1_instructions, block2_instructions };
679 auto return_options =
680 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U8, .return_value_offset_index = 1 };
681 auto control_flow = ControlFlow(instruction_blocks);
682 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
684 auto bytecode = control_flow.build_bytecode(return_options);
685 auto cpp_simulator = CppSimulator();
686 auto result = cpp_simulator.simulate(bytecode, {});
687 EXPECT_EQ(result.output.at(0), 11);
688}
689
690// block1 set return value 10
691// ↓
692// block2 set return value 11
693// ↓
694// block3 set return value 12 and return return value
695TEST(fuzz, JumpToNewBlockSmoke2)
696{
697 auto block1_instructions = std::vector<FuzzInstruction>{ SET_8_Instruction{
699 .result_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
700 .value = 10 } };
701 auto block2_instructions = std::vector<FuzzInstruction>{ SET_8_Instruction{
703 .result_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
704 .value = 11 } };
705 auto block3_instructions = std::vector<FuzzInstruction>{ SET_8_Instruction{
707 .result_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
708 .value = 12 } };
709 auto instruction_blocks =
710 std::vector<std::vector<FuzzInstruction>>{ block1_instructions, block2_instructions, block3_instructions };
711 auto return_options =
712 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U8, .return_value_offset_index = 1 };
713 auto control_flow = ControlFlow(instruction_blocks);
714 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
717 auto bytecode = control_flow.build_bytecode(return_options);
718 auto cpp_simulator = CppSimulator();
719 auto result = cpp_simulator.simulate(bytecode, {});
720 EXPECT_EQ(result.output.at(0), 12);
721}
722
723// block1 set u8 value 10
724// ↓
725// block2 tries to return u8
726// if blocks does not share defined variables, block2 will return 0
727TEST(fuzz, JumpToNewBlockSharesVariables)
728{
729 auto block1_instructions = std::vector<FuzzInstruction>{ SET_8_Instruction{
731 .result_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
732 .value = 10 } };
733
734 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ block1_instructions };
735 auto return_options =
736 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U8, .return_value_offset_index = 1 };
737 auto control_flow = ControlFlow(instruction_blocks);
738 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
740 auto bytecode = control_flow.build_bytecode(return_options);
741 auto cpp_simulator = CppSimulator();
742 auto result = cpp_simulator.simulate(bytecode, {});
743 EXPECT_EQ(result.output.at(0), 10);
744}
745
746// block1 set u1 condition value
747// ↙ ↘
748// return 11 return 12
749TEST(fuzz, JumpIfToNewBlockSmoke)
750{
751 auto set_true_block = std::vector<FuzzInstruction>{ SET_8_Instruction{
753 .result_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct },
754 .value = 1 } };
755 auto set_false_block = std::vector<FuzzInstruction>{ SET_8_Instruction{
757 .result_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct },
758 .value = 0 } };
759 auto block2_instructions = std::vector<FuzzInstruction>{ SET_8_Instruction{
761 .result_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
762 .value = 11 } };
763 auto block3_instructions = std::vector<FuzzInstruction>{ SET_8_Instruction{
765 .result_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
766 .value = 12 } };
767 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{
768 set_true_block, set_false_block, block2_instructions, block3_instructions
769 };
770 auto return_options =
771 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U8, .return_value_offset_index = 1 };
772 auto control_flow = ControlFlow(instruction_blocks);
773 // set true, go to block2
774 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
776 .else_program_block_instruction_block_idx = 3,
777 .condition_offset_index = 1 });
778 auto bytecode_1 = control_flow.build_bytecode(return_options);
779 auto control_flow2 = ControlFlow(instruction_blocks);
780 // set false, go to block3
781 control_flow2.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 1 });
782 control_flow2.process_cfg_instruction(JumpIfToNewBlock{ .then_program_block_instruction_block_idx = 2,
783 .else_program_block_instruction_block_idx = 3,
784 .condition_offset_index = 1 });
785 auto bytecode_2 = control_flow2.build_bytecode(return_options);
786 auto cpp_simulator = CppSimulator();
787 auto result_1 = cpp_simulator.simulate(bytecode_1, {});
788 auto cpp_simulator2 = CppSimulator();
789 auto result_2 = cpp_simulator2.simulate(bytecode_2, {});
790 EXPECT_EQ(result_1.output.at(0), 11);
791 EXPECT_EQ(result_2.output.at(0), 12);
792}
793
794// set u1 condition value b1
795// ↙ ↘
796// set u1 b2 return 4
797// ↙ ↘
798// ret 2 ret 3
799FF simulate_jump_if_depth_2_helper(uint8_t first_boolean_value, uint8_t second_boolean_value)
800{
801 auto set_instruction_block_1 = SET_8_Instruction{ .value_tag = bb::avm2::MemoryTag::U1,
802 .result_address = ResultAddressRef{ .address = 1 },
803 .value = first_boolean_value };
804 auto instruction_block_1 = std::vector<FuzzInstruction>{ set_instruction_block_1 };
805 auto set_instruction_block_2 = SET_8_Instruction{ .value_tag = bb::avm2::MemoryTag::U1,
806 .result_address = ResultAddressRef{ .address = 2 },
807 .value = second_boolean_value };
808 auto instruction_block_2 = std::vector<FuzzInstruction>{ set_instruction_block_2 };
809 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instruction_block_1, instruction_block_2 };
810 for (uint8_t i = 2; i < 5; i++) {
811 auto set_instruction =
813 .result_address = ResultAddressRef{ .address = i, .mode = AddressingMode::Direct },
814 .value = i };
815 instruction_blocks.push_back({ set_instruction });
816 }
817 auto return_options =
818 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U8, .return_value_offset_index = 1 };
819 auto control_flow = ControlFlow(instruction_blocks);
820 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
821 control_flow.process_cfg_instruction(
823 .else_program_block_instruction_block_idx = 4, // set 4
824 .condition_offset_index = 0 });
825 control_flow.process_cfg_instruction(JumpIfToNewBlock{ .then_program_block_instruction_block_idx = 2, // set 2
826 .else_program_block_instruction_block_idx = 3, // set 3
827 .condition_offset_index = 1 });
828 auto bytecode = control_flow.build_bytecode(return_options);
829 auto cpp_simulator = CppSimulator();
830 auto result = cpp_simulator.simulate(bytecode, {});
831 return result.output.at(0);
832}
833
834TEST(fuzz, JumpIfDepth2Smoke)
835{
836 EXPECT_EQ(simulate_jump_if_depth_2_helper(1, 1), 2);
837 EXPECT_EQ(simulate_jump_if_depth_2_helper(1, 0), 3);
838 EXPECT_EQ(simulate_jump_if_depth_2_helper(0, 1), 4);
839 EXPECT_EQ(simulate_jump_if_depth_2_helper(0, 0), 4);
840}
841
842// set u1 condition
843// ↙ ↘
844// nop ----→ return 2
845FF simulate_jump_to_block_helper(uint8_t condition_value)
846{
847 auto set_instruction_block_1 =
849 .result_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct },
850 .value = condition_value };
851 auto set_return_value_block = std::vector<FuzzInstruction>{ SET_8_Instruction{
853 .result_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
854 .value = 2 } };
855 auto instruction_block_1 = std::vector<FuzzInstruction>{ set_instruction_block_1 };
856 auto instruction_blocks =
857 std::vector<std::vector<FuzzInstruction>>{ instruction_block_1, {}, set_return_value_block };
858 auto return_options =
859 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U8, .return_value_offset_index = 1 };
860 auto control_flow = ControlFlow(instruction_blocks);
861 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
862 control_flow.process_cfg_instruction(
864 .else_program_block_instruction_block_idx = 2, // set return value
865 .condition_offset_index = 0 });
866 control_flow.process_cfg_instruction(JumpToBlock{ .target_block_idx = 2 });
867 auto bytecode = control_flow.build_bytecode(return_options);
868 auto cpp_simulator = CppSimulator();
869 auto result = cpp_simulator.simulate(bytecode, {});
870 return result.output.at(0);
871}
872
873TEST(fuzz, JumpToBlockSmoke)
874{
875 EXPECT_EQ(simulate_jump_to_block_helper(1), 2);
876 EXPECT_EQ(simulate_jump_to_block_helper(0), 2);
877}
878
879// Nice catch! That's actually fully ai generated test.
880// test if terminate with return works
881// set u1 condition value
882// ↙ ↘
883// set FF, ret set U128, ret
884TEST(fuzz, JumpIfToNewBlockWithReturn)
885{
886 // Block 0: Set condition (U1)
887 auto set_condition_block = std::vector<FuzzInstruction>{ SET_8_Instruction{
889 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
890 .value = 1 } };
891
892 // Block 1: Set FF value
893 const bb::avm2::FF ff_value = bb::avm2::FF(123456789);
896 .result_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
897 .value = ff_value } };
898
899 // Block 2: Set U128 value
900 const uint64_t u128_value_low = 0xFEDCBA9876543210ULL;
901 const uint64_t u128_value_high = 0x123456789ABCDEF0ULL;
904 .result_address = ResultAddressRef{ .address = 20, .mode = AddressingMode::Direct },
905 .value_low = u128_value_low,
906 .value_high = u128_value_high } };
907
908 auto instruction_blocks =
909 std::vector<std::vector<FuzzInstruction>>{ set_condition_block, set_ff_block, set_u128_block };
910
911 auto control_flow = ControlFlow(instruction_blocks);
912
913 // Insert condition block
914 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
915
916 // JumpIf: if condition is true (1), go to block 1 (FF), else go to block 2 (U128)
918 .else_program_block_instruction_block_idx = 2,
919 .condition_offset_index = 0 });
920
921 // Finalize then block (FF) with Return
922 control_flow.process_cfg_instruction(FinalizeWithReturn{
924 .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 10 } });
925
926 // Finalize else block (U128) with Return
927 control_flow.process_cfg_instruction(FinalizeWithReturn{
929 .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U128, .return_value_offset_index = 20 } });
930
931 // Test with condition = true (should return FF value)
932 auto control_flow_true = ControlFlow(instruction_blocks);
933 control_flow_true.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
934 control_flow_true.process_cfg_instruction(JumpIfToNewBlock{ .then_program_block_instruction_block_idx = 1,
935 .else_program_block_instruction_block_idx = 2,
936 .condition_offset_index = 0 });
937 control_flow_true.process_cfg_instruction(FinalizeWithReturn{
939 .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 10 } });
940 control_flow_true.process_cfg_instruction(FinalizeWithReturn{
942 .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U128, .return_value_offset_index = 20 } });
943
944 auto bytecode_true = control_flow_true.build_bytecode(ReturnOptions{
945 .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 10 });
946 auto cpp_simulator_true = CppSimulator();
947 auto result_true = cpp_simulator_true.simulate(bytecode_true, {});
948 EXPECT_EQ(result_true.output.at(0), ff_value);
949
950 // Test with condition = false (should return U128 value)
951 auto set_condition_false_block = std::vector<FuzzInstruction>{ SET_8_Instruction{
953 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
954 .value = 0 } };
955 auto instruction_blocks_false =
956 std::vector<std::vector<FuzzInstruction>>{ set_condition_false_block, set_ff_block, set_u128_block };
957
958 auto control_flow_false = ControlFlow(instruction_blocks_false);
959 control_flow_false.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
960 control_flow_false.process_cfg_instruction(JumpIfToNewBlock{ .then_program_block_instruction_block_idx = 1,
961 .else_program_block_instruction_block_idx = 2,
962 .condition_offset_index = 0 });
963 control_flow_false.process_cfg_instruction(FinalizeWithReturn{
965 .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 10 } });
966 control_flow_false.process_cfg_instruction(FinalizeWithReturn{
968 .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U128, .return_value_offset_index = 20 } });
969
970 const uint128_t expected_u128_value =
971 (static_cast<uint128_t>(u128_value_high) << 64) | static_cast<uint128_t>(u128_value_low);
972 auto bytecode_false = control_flow_false.build_bytecode(ReturnOptions{
973 .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U128, .return_value_offset_index = 20 });
974 auto cpp_simulator_false = CppSimulator();
975 auto result_false = cpp_simulator_false.simulate(bytecode_false, {});
976 EXPECT_EQ(result_false.output.at(0), expected_u128_value);
977}
978} // namespace control_flow
979
980namespace public_storage {
981TEST(fuzz, SstoreThenSload)
982{
983 // M[10] = 10
984 auto set_value_instruction =
986 .result_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
987 .value = 10 };
988 // S[10] = M[10]
989 auto sstore_instruction = SSTORE_Instruction{
991 .result_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
992 .slot = 10
993 };
994 // M[2] = S[10], FF tag
995 auto sload_instruction =
997 .slot_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
998 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct } };
999 // M[10] = 11
1000 auto set_value_instruction2 =
1002 .result_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
1003 .value = 11 };
1004
1005 auto set_sstore_sload_block = std::vector<FuzzInstruction>{
1006 set_value_instruction, sstore_instruction, sload_instruction, set_value_instruction2
1007 };
1008
1009 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ set_sstore_sload_block };
1010 // FF should be set via sload instruction
1011 auto return_options = ReturnOptions{ .return_size = 1,
1012 .return_value_tag = bb::avm2::MemoryTag::FF,
1013 .return_value_offset_index = 1 /* after sload instruction */ };
1014 auto control_flow = ControlFlow(instruction_blocks);
1015 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1016 auto bytecode = control_flow.build_bytecode(return_options);
1017 auto cpp_simulator = CppSimulator();
1018 auto result = cpp_simulator.simulate(bytecode, {});
1019 EXPECT_EQ(result.output.at(0), 10);
1020}
1021} // namespace public_storage
1022
1025{
1026 auto getenvvar_instruction =
1028 .type = type };
1029 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ { getenvvar_instruction } };
1030 auto control_flow = ControlFlow(instruction_blocks);
1031 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1032 auto return_options =
1033 ReturnOptions{ .return_size = 1, .return_value_tag = return_value_tag, .return_value_offset_index = 0 };
1034 auto bytecode = control_flow.build_bytecode(return_options);
1035 auto cpp_simulator = CppSimulator();
1036 auto result = cpp_simulator.simulate(bytecode, {});
1037 return result.output.at(0);
1038}
1039
1040TEST(fuzz, GetEnvVarSmoke)
1041{
1042 EXPECT_EQ(getenvvar_helper(0), 42); // address, see simulator.cpp globals
1043 EXPECT_EQ(getenvvar_helper(1), 100); // sender, see simulator.cpp globals
1044 EXPECT_EQ(getenvvar_helper(2), 0); // transaction fee, see simulator.cpp globals
1045 EXPECT_EQ(getenvvar_helper(3), 1); // chain id, see simulator.cpp globals
1046 EXPECT_EQ(getenvvar_helper(4), 1); // version, see simulator.cpp globals
1047 EXPECT_EQ(getenvvar_helper(5), 1); // block number, see simulator.cpp globals
1048 EXPECT_EQ(getenvvar_helper(6, bb::avm2::MemoryTag::U64), 1000000); // timestamp, see simulator.cpp globals
1049 EXPECT_EQ(getenvvar_helper(7), 1); // FEEPERL2GAS = 1, see simulator.cpp gas_fees
1050 EXPECT_EQ(getenvvar_helper(8), 1); // FEEPERDAGAS = 1, see simulator.cpp gas_fees
1051 EXPECT_EQ(getenvvar_helper(9), 0); // is static call is always false
1052 EXPECT_EQ(getenvvar_helper(10), 1000000 - 2 * 6); // L2GASLEFT, gas spent on getenvvar + return
1053 EXPECT_EQ(getenvvar_helper(11), 1000000); // DAGASLEFT, see simulator.cpp
1054}
1055} // namespace execution_environment
1056
1058TEST(fuzz, EmitNullifierThenNullifierExists)
1059{
1060 auto set_field_instruction =
1062 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
1063 .value = 1 };
1064 auto emit_nullifier_instruction = EMITNULLIFIER_Instruction{
1066 };
1067 auto nullifier_exists_instruction = NULLIFIEREXISTS_Instruction{
1069 .contract_address_address = ResultAddressRef{ .address = 10, .mode = AddressingMode::Direct },
1070 .result_address = ResultAddressRef{ .address = 20, .mode = AddressingMode::Direct }
1071 };
1072 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{
1073 { set_field_instruction, emit_nullifier_instruction, nullifier_exists_instruction }
1074 };
1075 auto control_flow = ControlFlow(instruction_blocks);
1076 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1077 auto bytecode = control_flow.build_bytecode(ReturnOptions{
1078 .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U1, .return_value_offset_index = 20 });
1079 auto cpp_simulator = CppSimulator();
1080 auto result = cpp_simulator.simulate(bytecode, {});
1081 EXPECT_EQ(result.output.at(0), 1);
1082}
1083
1084TEST(fuzz, EmitNullifierThenNullifierExistsOverwritingPreviousNullifier)
1085{
1086 auto set_field_instruction =
1088 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
1089 .value = 1 };
1090 auto emit_nullifier_instruction = EMITNULLIFIER_Instruction{
1092 };
1093 auto nullifier_exists_instruction = NULLIFIEREXISTS_Instruction{
1095 .contract_address_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
1096 .result_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct }
1097 }; // GETENVVAR overwrites previous nullifier
1098 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{
1099 { set_field_instruction, emit_nullifier_instruction, nullifier_exists_instruction }
1100 };
1101 auto control_flow = ControlFlow(instruction_blocks);
1102 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1103 auto bytecode = control_flow.build_bytecode(
1104 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U1, .return_value_offset_index = 0 });
1105 auto cpp_simulator = CppSimulator();
1106 auto result = cpp_simulator.simulate(bytecode, {});
1107 EXPECT_EQ(result.output.at(0), 0);
1108}
1109
1110TEST(fuzz, EmitNoteHashThenNoteHashExists)
1111{
1112 auto emit_note_hash_instruction =
1114 .note_hash = 1 };
1115 auto note_hash_exists_instruction = NOTEHASHEXISTS_Instruction{
1116 .notehash_index = 0,
1117 .notehash_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
1118 .leaf_index_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct },
1119 .result_address = ResultAddressRef{ .address = 2, .mode = AddressingMode::Direct }
1120 };
1121 auto instruction_blocks =
1122 std::vector<std::vector<FuzzInstruction>>{ { emit_note_hash_instruction, note_hash_exists_instruction } };
1123 auto control_flow = ControlFlow(instruction_blocks);
1124 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1125 auto bytecode = control_flow.build_bytecode(
1126 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U1, .return_value_offset_index = 0 });
1127 auto cpp_simulator = CppSimulator();
1128 auto result = cpp_simulator.simulate(bytecode, {});
1129 EXPECT_FALSE(result.reverted);
1130 EXPECT_EQ(result.output.at(0), 1);
1131}
1132} // namespace notes_and_nullifiers
1133
1135TEST(fuzz, CopyCalldataThenReturnData)
1136{
1137 auto calldatacopy_instruction = CALLDATACOPY_Instruction{ .dst_address = ResultAddressRef{ .address = 0 },
1138 .copy_size = 1,
1139 .copy_size_address = ResultAddressRef{ .address = 1 },
1140 .cd_start = 0,
1141 .cd_start_address = ResultAddressRef{ .address = 2 } };
1142 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ { calldatacopy_instruction } };
1143 auto control_flow = ControlFlow(instruction_blocks);
1144 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1145 auto bytecode = control_flow.build_bytecode(
1146 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 0 });
1147 auto cpp_simulator = CppSimulator();
1148 auto result = cpp_simulator.simulate(bytecode, { FF(1337) });
1149 EXPECT_EQ(result.output.at(0), 1337);
1150}
1151
1152// call internal function overwrites memory address
1153TEST(fuzz, InternalCall)
1154{
1155 auto set_field_instruction =
1157 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
1158 .value = 1337 };
1159 auto set_field_instruction2 =
1161 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
1162 .value = 313373 };
1163 auto internal_call_instruction = InsertInternalCall{ .target_program_block_instruction_block_idx = 1 };
1164 auto instruction_blocks =
1165 std::vector<std::vector<FuzzInstruction>>{ { set_field_instruction, set_field_instruction2 } };
1166 auto control_flow = ControlFlow(instruction_blocks);
1167 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1168 control_flow.process_cfg_instruction(internal_call_instruction);
1169 auto bytecode = control_flow.build_bytecode(
1170 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 0 });
1171 auto cpp_simulator = CppSimulator();
1172 auto result = cpp_simulator.simulate(bytecode, {});
1173 EXPECT_EQ(result.output.at(0), 313373);
1174}
1175} // namespace calldata_returndata
1176
1178
1179// check if internal call does not halt execution on return
1180TEST(fuzz, InternalCalledBlockUsesInternalReturn)
1181{
1182 auto set_field_instruction =
1184 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
1185 .value = 1337 };
1186 auto set_boolean_instruction =
1188 .result_address = ResultAddressRef{ .address = 1, .mode = AddressingMode::Direct },
1189 .value = 1 };
1190 auto internal_call_instruction = InsertInternalCall{ .target_program_block_instruction_block_idx = 1 };
1191 auto instruction_blocks =
1192 std::vector<std::vector<FuzzInstruction>>{ { set_field_instruction, set_boolean_instruction } };
1193 auto control_flow = ControlFlow(instruction_blocks);
1194 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 1 });
1195 control_flow.process_cfg_instruction(internal_call_instruction);
1196 // this should do nothing, just insert INTERNALRETURN instruction
1197 // otherwise it will halt execution and return 1
1198 control_flow.process_cfg_instruction(FinalizeWithReturn{
1200 .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::U1, .return_value_offset_index = 0 } });
1201 auto bytecode = control_flow.build_bytecode(
1202 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 0 });
1203 auto cpp_simulator = CppSimulator();
1204 auto result = cpp_simulator.simulate(bytecode, {});
1205 EXPECT_EQ(result.output.at(0), 1337);
1206}
1207
1208// SSTORE(0, 1337); call f1; return SLOAD(0);
1209// f1: SSTORE(0, 31337); call f2; INTERNALRETURN
1210// f2: SSTORE(0, 313373); INTERNALRETURN
1211TEST(fuzz, SeveralInternalCalls)
1212{
1213 auto set_field_instruction =
1215 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
1216 .value = 1337 };
1217 auto set_field_instruction2 =
1219 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
1220 .value = 31337 };
1221 auto set_field_instruction3 =
1223 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
1224 .value = 313373 };
1225 auto internal_call_instruction = InsertInternalCall{ .target_program_block_instruction_block_idx = 1 };
1226 auto internal_call_instruction2 = InsertInternalCall{ .target_program_block_instruction_block_idx = 2 };
1227 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{
1228 { set_field_instruction, set_field_instruction2, set_field_instruction3 }
1229 };
1230 auto control_flow = ControlFlow(instruction_blocks);
1231 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1232 control_flow.process_cfg_instruction(internal_call_instruction);
1233 control_flow.process_cfg_instruction(internal_call_instruction2);
1234 auto bytecode = control_flow.build_bytecode(
1235 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 0 });
1236 auto cpp_simulator = CppSimulator();
1237 auto result = cpp_simulator.simulate(bytecode, {});
1238 EXPECT_EQ(result.output.at(0), 313373);
1239}
1240
1258TEST(fuzz, Reentrancy)
1259{
1260 auto set_field_instruction0 =
1262 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
1263 .value = 1 };
1264 auto set_field_instruction1 =
1266 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
1267 .value = 1337 };
1268 auto set_field_instruction2 =
1270 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
1271 .value = 31337 };
1272 auto set_field_instruction3 =
1274 .result_address = ResultAddressRef{ .address = 0, .mode = AddressingMode::Direct },
1275 .value = 313373 };
1276 auto internal_call_instruction = InsertInternalCall{ .target_program_block_instruction_block_idx = 1 };
1277 auto internal_call_instruction2 = InsertInternalCall{ .target_program_block_instruction_block_idx = 2 };
1278 auto internal_call_instruction3 = InsertInternalCall{ .target_program_block_instruction_block_idx = 3 };
1279 auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{
1280 { set_field_instruction0, set_field_instruction1, set_field_instruction2, set_field_instruction3 }
1281 };
1282 auto control_flow = ControlFlow(instruction_blocks);
1283 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1284 // call f1
1285 control_flow.process_cfg_instruction(internal_call_instruction);
1286 // call f2
1287 control_flow.process_cfg_instruction(internal_call_instruction2);
1288 // Should switch context to f1
1289 control_flow.process_cfg_instruction(FinalizeWithReturn{
1291 .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 0 } });
1292 // SSTORE(0, 1337);
1293 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 1 });
1294 // Should switch context to f0 (START)
1295 control_flow.process_cfg_instruction(FinalizeWithReturn{
1297 .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 0 } });
1298 // call f3
1299 control_flow.process_cfg_instruction(internal_call_instruction3);
1300 // Should switch context to f0 (START)
1301 control_flow.process_cfg_instruction(FinalizeWithReturn{
1303 .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 0 } });
1304 auto bytecode = control_flow.build_bytecode(
1305 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 0 });
1306 auto cpp_simulator = CppSimulator();
1307 auto result = cpp_simulator.simulate(bytecode, {});
1308 EXPECT_EQ(result.output.at(0), 313373);
1309}
1310} // namespace internal_calls
1311
1313TEST(fuzz, DirectWithIndirect)
1314{
1315 auto set_field_instruction =
1317 .result_address = ResultAddressRef{ .address = 150, .mode = AddressingMode::Direct },
1318 .value = 10 };
1319 auto set_field_instruction2 =
1321 .result_address = ResultAddressRef{ .address = 3000, .mode = AddressingMode::Direct },
1322 .value = 20 };
1323 auto add_instruction = ADD_8_Instruction{
1324 .a_address =
1325 AddressRef{
1326 .tag = bb::avm2::MemoryTag::FF, .index = 1, .pointer_address = 100, .mode = AddressingMode::Indirect },
1327 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::FF, .index = 0, .mode = AddressingMode::Direct },
1328 .result_address = ResultAddressRef{ .address = 130, .mode = AddressingMode::Direct }
1329 };
1330 auto instruction_blocks =
1331 std::vector<std::vector<FuzzInstruction>>{ { set_field_instruction, set_field_instruction2, add_instruction } };
1332 auto control_flow = ControlFlow(instruction_blocks);
1333 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1334 auto bytecode = control_flow.build_bytecode(
1335 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 2 });
1336 auto cpp_simulator = CppSimulator();
1337 auto result = cpp_simulator.simulate(bytecode, {});
1338 EXPECT_EQ(result.output.at(0), 30);
1339}
1340
1341TEST(fuzz, DirectWithIndirectRelative)
1342{
1343 auto set_field_instruction =
1345 .result_address = ResultAddressRef{ .address = 150, .mode = AddressingMode::Direct },
1346 .value = 10 };
1347 auto set_field_instruction2 =
1349 .result_address = ResultAddressRef{ .address = 3000, .mode = AddressingMode::Direct },
1350 .value = 20 };
1351 auto add_instruction =
1353 .index = 1,
1354 .pointer_address = 100,
1355 .base_offset = 100,
1357 .b_address =
1359 .result_address = ResultAddressRef{ .address = 130, .mode = AddressingMode::Direct } };
1360 auto instruction_blocks =
1361 std::vector<std::vector<FuzzInstruction>>{ { set_field_instruction, set_field_instruction2, add_instruction } };
1362 auto control_flow = ControlFlow(instruction_blocks);
1363 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1364 auto bytecode = control_flow.build_bytecode(
1365 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 2 });
1366 auto cpp_simulator = CppSimulator();
1367 auto result = cpp_simulator.simulate(bytecode, {});
1368 EXPECT_EQ(result.output.at(0), 30);
1369}
1370
1371TEST(fuzz, IndirectResultCanBeUsedInNextInstruction)
1372{
1373 auto set_field_instruction =
1375 .result_address = ResultAddressRef{ .address = 150, .mode = AddressingMode::Direct },
1376 .value = 10 };
1377 auto add_instruction = ADD_8_Instruction{
1379 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::FF, .index = 1, .mode = AddressingMode::Direct },
1380 .result_address = ResultAddressRef{ .address = 130, .pointer_address = 100, .mode = AddressingMode::Indirect }
1381 };
1382 auto mul_instruction = MUL_8_Instruction{
1384 .b_address = AddressRef{ .tag = bb::avm2::MemoryTag::FF, .index = 1, .mode = AddressingMode::Direct },
1385 .result_address = ResultAddressRef{ .address = 150, .mode = AddressingMode::Direct }
1386 };
1387 auto instruction_blocks =
1388 std::vector<std::vector<FuzzInstruction>>{ { set_field_instruction, add_instruction, mul_instruction } };
1389 auto control_flow = ControlFlow(instruction_blocks);
1390 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1391 auto bytecode = control_flow.build_bytecode(
1392 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 2 });
1393 auto cpp_simulator = CppSimulator();
1394 auto result = cpp_simulator.simulate(bytecode, {});
1395 EXPECT_EQ(result.output.at(0), 400);
1396}
1397
1398TEST(fuzz, Memoryaddressing32BitWidth)
1399{
1400 auto set_field_instruction =
1402 .result_address = ResultAddressRef{ .address = 150, .mode = AddressingMode::Direct },
1403 .value = 10 };
1404 auto set_field_instruction2 = SET_FF_Instruction{
1406 .result_address =
1407 ResultAddressRef{ .address = 4294967295, .pointer_address = 100, .mode = AddressingMode::Indirect },
1408 .value = 20
1409 };
1410 auto add_instruction = MUL_8_Instruction{
1412 .b_address =
1413 AddressRef{
1414 .tag = bb::avm2::MemoryTag::FF, .index = 1, .pointer_address = 200, .mode = AddressingMode::Indirect },
1415 .result_address = ResultAddressRef{ .address = 150, .mode = AddressingMode::Direct }
1416 };
1417 auto instruction_blocks =
1418 std::vector<std::vector<FuzzInstruction>>{ { set_field_instruction, set_field_instruction2, add_instruction } };
1419 auto control_flow = ControlFlow(instruction_blocks);
1420 control_flow.process_cfg_instruction(InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1421 auto bytecode = control_flow.build_bytecode(
1422 ReturnOptions{ .return_size = 1, .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 2 });
1423 auto cpp_simulator = CppSimulator();
1424 auto result = cpp_simulator.simulate(bytecode, {});
1425 EXPECT_EQ(result.output.at(0), 200);
1426}
1427} // namespace avm_addressing
::FuzzInstruction FuzzInstruction
SimulatorResult fuzz(const uint8_t *buffer, size_t size)
std::shared_ptr< Napi::ThreadSafeFunction > bytecode
uses barretenberg/vm2 to simulate the bytecode
Definition simulator.hpp:35
Instruction instruction
TEST(fuzz, ADD8)
Definition fuzz.test.cpp:34
FF get_result_of_instruction_16(FuzzInstruction instruction, bb::avm2::MemoryTag return_value_tag=bb::avm2::MemoryTag::U8)
FF get_result_of_instruction(FuzzInstruction instruction, bb::avm2::MemoryTag return_value_tag=bb::avm2::MemoryTag::U8)
Definition fuzz.test.cpp:13
TEST(fuzz, DirectWithIndirect)
AvmFlavorSettings::FF FF
Definition field.hpp:10
TEST(fuzz, CopyCalldataThenReturnData)
TEST(fuzz, JumpToNewBlockSmoke)
FF simulate_jump_if_depth_2_helper(uint8_t first_boolean_value, uint8_t second_boolean_value)
FF simulate_jump_to_block_helper(uint8_t condition_value)
TEST(fuzz, GetEnvVarSmoke)
FF getenvvar_helper(uint8_t type, bb::avm2::MemoryTag return_value_tag=bb::avm2::MemoryTag::FF)
TEST(fuzz, InternalCalledBlockUsesInternalReturn)
TEST(fuzz, SET16)
TEST(fuzz, EmitNullifierThenNullifierExists)
TEST(fuzz, SstoreThenSload)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
TEST(fuzz, CAST8)
unsigned __int128 uint128_t
Definition serialize.hpp:44
mem[result_offset] = mem[a_address] + mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] + mem[b_address]
mem[result_offset] = mem[a_address] & mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] & mem[b_address]
MemoryTagWrapper tag
CALLDATACOPY: M[dstOffset:dstOffset+M[copySizeOffset]] = calldata[M[cdStartOffset]:M[cdStartOffset]+M...
ResultAddressRef dst_address
CAST_16: cast mem[src_offset_index] to target_tag and store at dst_offset.
CAST_8: cast mem[src_offset_index] to target_tag and store at dst_offset.
mem[result_offset] = mem[a_address] / mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] / mem[b_address]
EMITNOTEHASH: M[note_hash_offset] = note_hash; emit note hash to the note hash tree.
ResultAddressRef note_hash_address
EMITNULIFIER: inserts new nullifier to the nullifier tree.
mem[result_offset] = mem[a_address] == mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] == mem[b_address]
AddressRef a_address
finalizes the current block with Return and switches to the first non-terminated block
ReturnOptions return_options
GETENVVAR: M[result_offset] = getenvvar(type)
ResultAddressRef result_address
inserts INTERNALCALL instruction to the current block creates a new block and sets it as the current ...
uint16_t target_program_block_instruction_block_idx
insert instruction block to the current block
finalizes the current block with jump if, creates two new blocks, sets the first as the then block an...
uint16_t then_program_block_instruction_block_idx
finalizes the current block with a jump to the block, which does not create a loop in the graph (defi...
uint16_t target_block_idx
finalizes the current block with jump, creates a new block and sets it as the current block
uint16_t target_program_block_instruction_block_idx
mem[result_offset] = mem[a_address] < mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] < mem[b_address]
AddressRef a_address
mem[result_offset] = mem[a_address] <= mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] <= mem[b_address]
MOV_16 instruction: mem[dst_offset] = mem[src_offset].
MOV_8 instruction: mem[dst_offset] = mem[src_offset].
AddressRef src_address
mem[result_offset] = mem[a_address] * mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] * mem[b_address]
NOTEHASHEXISTS: M[result_offset] = NOTEHASHEXISTS(M[notehash_offset], M[leaf_index_offset]) len = len...
NULLIFIEREXISTS: checks if nullifier exists in the nullifier tree Gets contract's address by GETENVVA...
mem[result_offset] = mem[a_address] | mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] | mem[b_address]
AddressRef a_address
uint8_t return_size
SET_128 instruction.
MemoryTagWrapper value_tag
SET_16 instruction.
MemoryTagWrapper value_tag
SET_32 instruction.
MemoryTagWrapper value_tag
SET_64 instruction.
MemoryTagWrapper value_tag
SET_8 instruction.
MemoryTagWrapper value_tag
SET_FF instruction.
MemoryTagWrapper value_tag
mem[result_offset] = mem[a_address] << mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] << mem[b_address]
mem[result_offset] = mem[a_address] >> mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] >> mem[b_address]
SLOAD: M[slot_offset] = slot; M[result_offset] = S[M[slotOffset]].
SSTORE: M[slot_offset_index] = slot; S[M[slotOffset]] = M[srcOffset].
mem[result_offset] = mem[a_address] - mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] - mem[b_address]
mem[result_offset] = mem[a_address] ^ mem[b_address] (16-bit)
mem[result_offset] = mem[a_address] ^ mem[b_address]