@@ -1646,3 +1646,231 @@ TEST(fuzz, StaticCallToNonStaticFunctionSuccessCopy)
16461646 EXPECT_EQ (result.reverted , false );
16471647}
16481648} // namespace external_calls
1649+
1650+ namespace crypto_ops {
1651+
1652+ TEST (fuzz, Poseidon2PermSmoke)
1653+ {
1654+ // Set up 4 FF values for Poseidon2 permutation input
1655+ std::vector<FuzzInstruction> instructions;
1656+ for (uint32_t i = 0 ; i < 4 ; i++) {
1657+ instructions.push_back (
1658+ SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1659+ .result_address = AddressRef{ .address = i, .mode = AddressingMode::Direct },
1660+ .value = FF (i + 1 ) });
1661+ }
1662+ // Poseidon2 permutation: reads from address 0-3, writes to address 10-13
1663+ instructions.push_back (
1664+ POSEIDON2PERM_Instruction{ .src_address = AddressRef{ .address = 0 , .mode = AddressingMode::Direct },
1665+ .dst_address = AddressRef{ .address = 10 , .mode = AddressingMode::Direct } });
1666+
1667+ auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
1668+ auto control_flow = ControlFlow (instruction_blocks);
1669+ control_flow.process_cfg_instruction (InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1670+ auto bytecode = control_flow.build_bytecode (
1671+ ReturnOptions{ .return_size = 1 , .return_value_tag = bb::avm2::MemoryTag::FF, .return_value_offset_index = 2 });
1672+
1673+ auto result = simulate_with_default_tx (bytecode, {});
1674+ EXPECT_FALSE (result.reverted );
1675+ }
1676+
1677+ TEST (fuzz, Keccakf1600Smoke)
1678+ {
1679+ // Set up 25 U64 values for Keccak-f[1600] permutation input
1680+ std::vector<FuzzInstruction> instructions;
1681+ for (uint32_t i = 0 ; i < 25 ; i++) {
1682+ instructions.push_back (
1683+ SET_64_Instruction{ .value_tag = bb::avm2::MemoryTag::U64,
1684+ .result_address = AddressRef{ .address = i, .mode = AddressingMode::Direct },
1685+ .value = static_cast <uint64_t >(i + 1 ) });
1686+ }
1687+ // Keccak-f[1600]: reads from address 0-24, writes to address 100-124
1688+ instructions.push_back (
1689+ KECCAKF1600_Instruction{ .src_address = AddressRef{ .address = 0 , .mode = AddressingMode::Direct },
1690+ .dst_address = AddressRef{ .address = 100 , .mode = AddressingMode::Direct } });
1691+
1692+ auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
1693+ auto control_flow = ControlFlow (instruction_blocks);
1694+ control_flow.process_cfg_instruction (InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1695+ auto bytecode = control_flow.build_bytecode (ReturnOptions{
1696+ .return_size = 1 , .return_value_tag = bb::avm2::MemoryTag::U64, .return_value_offset_index = 25 });
1697+
1698+ auto result = simulate_with_default_tx (bytecode, {});
1699+ EXPECT_FALSE (result.reverted );
1700+ }
1701+
1702+ TEST (fuzz, Sha256CompressionSmoke)
1703+ {
1704+ // Set up 8 U32 values for state and 16 U32 values for input
1705+ std::vector<FuzzInstruction> instructions;
1706+
1707+ // State: addresses 0-7
1708+ for (uint32_t i = 0 ; i < 8 ; i++) {
1709+ instructions.push_back (
1710+ SET_32_Instruction{ .value_tag = bb::avm2::MemoryTag::U32,
1711+ .result_address = AddressRef{ .address = i, .mode = AddressingMode::Direct },
1712+ .value = i + 1 });
1713+ }
1714+ // Input: addresses 20-35
1715+ for (uint32_t i = 0 ; i < 16 ; i++) {
1716+ instructions.push_back (
1717+ SET_32_Instruction{ .value_tag = bb::avm2::MemoryTag::U32,
1718+ .result_address = AddressRef{ .address = 20 + i, .mode = AddressingMode::Direct },
1719+ .value = i + 100 });
1720+ }
1721+ // SHA256 compression: state at 0-7, input at 20-35, output at 50-57
1722+ instructions.push_back (
1723+ SHA256COMPRESSION_Instruction{ .state_address = AddressRef{ .address = 0 , .mode = AddressingMode::Direct },
1724+ .input_address = AddressRef{ .address = 20 , .mode = AddressingMode::Direct },
1725+ .dst_address = AddressRef{ .address = 50 , .mode = AddressingMode::Direct } });
1726+
1727+ auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
1728+ auto control_flow = ControlFlow (instruction_blocks);
1729+ control_flow.process_cfg_instruction (InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1730+ auto bytecode = control_flow.build_bytecode (ReturnOptions{
1731+ .return_size = 1 , .return_value_tag = bb::avm2::MemoryTag::U32, .return_value_offset_index = 12 });
1732+
1733+ auto result = simulate_with_default_tx (bytecode, {});
1734+ EXPECT_FALSE (result.reverted );
1735+ }
1736+
1737+ TEST (fuzz, EcaddSmoke)
1738+ {
1739+ std::vector<FuzzInstruction> instructions;
1740+
1741+ // Use the generator point G = (1, sqrt(-16)) as p1
1742+ // For simplicity, we'll use infinity points which should work
1743+ // Set p1 as infinity: x=0, y=0, infinite=1
1744+ instructions.push_back (
1745+ SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1746+ .result_address = AddressRef{ .address = 0 , .mode = AddressingMode::Direct },
1747+ .value = FF (0 ) }); // p1.x
1748+ instructions.push_back (
1749+ SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1750+ .result_address = AddressRef{ .address = 1 , .mode = AddressingMode::Direct },
1751+ .value = FF (0 ) }); // p1.y
1752+ instructions.push_back (
1753+ SET_8_Instruction{ .value_tag = bb::avm2::MemoryTag::U1,
1754+ .result_address = AddressRef{ .address = 2 , .mode = AddressingMode::Direct },
1755+ .value = 1 }); // p1.infinite = true
1756+
1757+ // Set p2 as infinity too
1758+ instructions.push_back (
1759+ SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1760+ .result_address = AddressRef{ .address = 3 , .mode = AddressingMode::Direct },
1761+ .value = FF (0 ) }); // p2.x
1762+ instructions.push_back (
1763+ SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1764+ .result_address = AddressRef{ .address = 4 , .mode = AddressingMode::Direct },
1765+ .value = FF (0 ) }); // p2.y
1766+ instructions.push_back (
1767+ SET_8_Instruction{ .value_tag = bb::avm2::MemoryTag::U1,
1768+ .result_address = AddressRef{ .address = 5 , .mode = AddressingMode::Direct },
1769+ .value = 1 }); // p2.infinite = true
1770+
1771+ // ECADD instruction: infinity + infinity = infinity
1772+ instructions.push_back (ECADD_Instruction{ .p1_x = AddressRef{ .address = 0 , .mode = AddressingMode::Direct },
1773+ .p1_y = AddressRef{ .address = 1 , .mode = AddressingMode::Direct },
1774+ .p1_infinite = AddressRef{ .address = 2 , .mode = AddressingMode::Direct },
1775+ .p2_x = AddressRef{ .address = 3 , .mode = AddressingMode::Direct },
1776+ .p2_y = AddressRef{ .address = 4 , .mode = AddressingMode::Direct },
1777+ .p2_infinite = AddressRef{ .address = 5 , .mode = AddressingMode::Direct },
1778+ .result = AddressRef{ .address = 10 , .mode = AddressingMode::Direct } });
1779+
1780+ auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
1781+ auto control_flow = ControlFlow (instruction_blocks);
1782+ control_flow.process_cfg_instruction (InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1783+ // Return the infinite flag of the result (should be 1)
1784+ auto bytecode = control_flow.build_bytecode (
1785+ ReturnOptions{ .return_size = 1 , .return_value_tag = bb::avm2::MemoryTag::U1, .return_value_offset_index = 3 });
1786+
1787+ auto result = simulate_with_default_tx (bytecode, {});
1788+ EXPECT_FALSE (result.reverted );
1789+ }
1790+
1791+ } // namespace crypto_ops
1792+
1793+ namespace conversions {
1794+
1795+ TEST (fuzz, ToRadixBESmoke)
1796+ {
1797+ std::vector<FuzzInstruction> instructions;
1798+
1799+ // Set value to convert (FF)
1800+ instructions.push_back (
1801+ SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1802+ .result_address = AddressRef{ .address = 0 , .mode = AddressingMode::Direct },
1803+ .value = FF (255 ) });
1804+ // Set radix (U32) = 2 (binary)
1805+ instructions.push_back (
1806+ SET_32_Instruction{ .value_tag = bb::avm2::MemoryTag::U32,
1807+ .result_address = AddressRef{ .address = 1 , .mode = AddressingMode::Direct },
1808+ .value = 2 });
1809+ // Set num_limbs (U32) = 8
1810+ instructions.push_back (
1811+ SET_32_Instruction{ .value_tag = bb::avm2::MemoryTag::U32,
1812+ .result_address = AddressRef{ .address = 2 , .mode = AddressingMode::Direct },
1813+ .value = 8 });
1814+ // Set output_bits (U1) = 1 (since radix is 2)
1815+ instructions.push_back (
1816+ SET_8_Instruction{ .value_tag = bb::avm2::MemoryTag::U1,
1817+ .result_address = AddressRef{ .address = 3 , .mode = AddressingMode::Direct },
1818+ .value = 1 });
1819+
1820+ // TORADIXBE instruction
1821+ instructions.push_back (
1822+ TORADIXBE_Instruction{ .value_address = AddressRef{ .address = 0 , .mode = AddressingMode::Direct },
1823+ .radix_address = AddressRef{ .address = 1 , .mode = AddressingMode::Direct },
1824+ .num_limbs_address = AddressRef{ .address = 2 , .mode = AddressingMode::Direct },
1825+ .output_bits_address = AddressRef{ .address = 3 , .mode = AddressingMode::Direct },
1826+ .dst_address = AddressRef{ .address = 10 , .mode = AddressingMode::Direct },
1827+ .is_output_bits = true });
1828+
1829+ auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
1830+ auto control_flow = ControlFlow (instruction_blocks);
1831+ control_flow.process_cfg_instruction (InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1832+ auto bytecode = control_flow.build_bytecode (
1833+ ReturnOptions{ .return_size = 1 , .return_value_tag = bb::avm2::MemoryTag::U1, .return_value_offset_index = 2 });
1834+
1835+ auto result = simulate_with_default_tx (bytecode, {});
1836+ EXPECT_FALSE (result.reverted );
1837+ }
1838+
1839+ } // namespace conversions
1840+
1841+ namespace l1_l2_messaging {
1842+
1843+ TEST (fuzz, L1ToL2MsgExistsSmoke)
1844+ {
1845+ std::vector<FuzzInstruction> instructions;
1846+
1847+ // Set msg_hash (FF)
1848+ instructions.push_back (
1849+ SET_FF_Instruction{ .value_tag = bb::avm2::MemoryTag::FF,
1850+ .result_address = AddressRef{ .address = 0 , .mode = AddressingMode::Direct },
1851+ .value = FF (12345 ) });
1852+ // Set leaf_index (U64)
1853+ instructions.push_back (
1854+ SET_64_Instruction{ .value_tag = bb::avm2::MemoryTag::U64,
1855+ .result_address = AddressRef{ .address = 1 , .mode = AddressingMode::Direct },
1856+ .value = 0 });
1857+
1858+ // L1TOL2MSGEXISTS instruction - check if message exists (it won't, but shouldn't revert)
1859+ instructions.push_back (
1860+ L1TOL2MSGEXISTS_Instruction{ .msg_hash_address = AddressRef{ .address = 0 , .mode = AddressingMode::Direct },
1861+ .leaf_index_address = AddressRef{ .address = 1 , .mode = AddressingMode::Direct },
1862+ .result_address = AddressRef{ .address = 2 , .mode = AddressingMode::Direct } });
1863+
1864+ auto instruction_blocks = std::vector<std::vector<FuzzInstruction>>{ instructions };
1865+ auto control_flow = ControlFlow (instruction_blocks);
1866+ control_flow.process_cfg_instruction (InsertSimpleInstructionBlock{ .instruction_block_idx = 0 });
1867+ auto bytecode = control_flow.build_bytecode (
1868+ ReturnOptions{ .return_size = 1 , .return_value_tag = bb::avm2::MemoryTag::U1, .return_value_offset_index = 0 });
1869+
1870+ auto result = simulate_with_default_tx (bytecode, {});
1871+ EXPECT_FALSE (result.reverted );
1872+ // Message doesn't exist, so result should be 0
1873+ EXPECT_EQ (result.output .at (0 ), FF::zero ());
1874+ }
1875+
1876+ } // namespace l1_l2_messaging
0 commit comments