Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
contract_instance_manager.test.cpp
Go to the documentation of this file.
2
3#include <gmock/gmock.h>
4#include <gtest/gtest.h>
5#include <optional>
6
15
16using ::testing::_;
17using ::testing::Return;
18using ::testing::SizeIs;
19using ::testing::StrictMock;
20
21namespace bb::avm2::simulation {
22namespace {
23
24class ContractInstanceManagerTest : public ::testing::Test {
25 protected:
26 StrictMock<MockContractDB> contract_db;
27 StrictMock<MockHighLevelMerkleDB> merkle_db;
28 StrictMock<MockUpdateCheck> update_check;
29 StrictMock<MockFieldGreaterThan> field_gt;
30 EventEmitter<ContractInstanceRetrievalEvent> event_emitter;
31};
32
33// Test that querying an empty protocol contract slot (addresses 7-11 are currently unused)
34// correctly returns nullopt with exists=false, rather than crashing.
35TEST_F(ContractInstanceManagerTest, EmptyProtocolContractSlotReturnsNullopt)
36{
37 // Create protocol contracts with only first 6 slots filled (matching real configuration)
38 // Slots 7-11 are zero (empty).
39 ProtocolContracts protocol_contracts;
40 for (uint32_t i = 0; i < 6; i++) {
41 // Fill slots 0-5 (addresses 1-6) with non-zero derived addresses
42 protocol_contracts.derived_addresses[i] = AztecAddress(FF(0x1000 + i));
43 }
44 // Slots 6-10 (addresses 7-11) are left as zero (default)
45
46 ContractInstanceManager manager(contract_db, merkle_db, update_check, field_gt, protocol_contracts, event_emitter);
47
48 // Query address 7 - an empty protocol contract slot
49 AztecAddress empty_slot_address = AztecAddress(7);
50
51 // Setup mocks
52 TreeStates tree_states = {};
53 EXPECT_CALL(merkle_db, get_tree_state()).WillOnce(Return(tree_states));
54
55 // The contract DB should return nullopt since the instance doesn't exist
56 EXPECT_CALL(contract_db, get_contract_instance(empty_slot_address)).WillOnce(Return(std::nullopt));
57
58 // ff_gt(MAX_PROTOCOL_CONTRACTS=11, 7-1=6) returns true because 11 > 6
59 // This means address 7 IS in the protocol contract range
60 EXPECT_CALL(field_gt, ff_gt(FF(MAX_PROTOCOL_CONTRACTS), FF(6))).WillOnce(Return(true));
61
62 // The call should NOT crash and should return nullopt
63 auto result = manager.get_contract_instance(empty_slot_address);
64
65 // Verify the result
66 EXPECT_FALSE(result.has_value());
67
68 // Verify the event was emitted correctly
69 auto events = event_emitter.dump_events();
70 ASSERT_THAT(events, SizeIs(1));
71 EXPECT_EQ(events[0].address, empty_slot_address);
72 EXPECT_FALSE(events[0].exists);
73 EXPECT_TRUE(events[0].is_protocol_contract);
74 EXPECT_EQ(events[0].contract_instance, ContractInstance{});
75}
76
77// Test that a valid protocol contract (e.g., address 1) works correctly
78TEST_F(ContractInstanceManagerTest, ValidProtocolContractReturnsInstance)
79{
80 // Create protocol contracts with first slot filled
81 ProtocolContracts protocol_contracts;
82 AztecAddress derived_addr = AztecAddress(FF(0x12345));
83 protocol_contracts.derived_addresses[0] = derived_addr; // Address 1 -> index 0
84
85 ContractInstanceManager manager(contract_db, merkle_db, update_check, field_gt, protocol_contracts, event_emitter);
86
87 // Query address 1 - a valid protocol contract
88 AztecAddress protocol_address = AztecAddress(1);
89
90 // Create a contract instance
92
93 // Setup mocks
94 TreeStates tree_states = {};
95 EXPECT_CALL(merkle_db, get_tree_state()).WillOnce(Return(tree_states));
96 EXPECT_CALL(contract_db, get_contract_instance(protocol_address)).WillOnce(Return(instance));
97
98 // ff_gt(MAX_PROTOCOL_CONTRACTS=11, 1-1=0) returns true because 11 > 0
99 EXPECT_CALL(field_gt, ff_gt(FF(MAX_PROTOCOL_CONTRACTS), FF(0))).WillOnce(Return(true));
100
101 // The call should succeed and return the instance
102 auto result = manager.get_contract_instance(protocol_address);
103
104 // Verify the result
105 ASSERT_TRUE(result.has_value());
106 EXPECT_EQ(result.value(), instance);
107
108 // Verify the event was emitted correctly
109 auto events = event_emitter.dump_events();
110 ASSERT_THAT(events, SizeIs(1));
111 EXPECT_EQ(events[0].address, protocol_address);
112 EXPECT_TRUE(events[0].exists);
113 EXPECT_TRUE(events[0].is_protocol_contract);
114 EXPECT_EQ(events[0].contract_instance, instance);
115}
116
117// Test that a regular (non-protocol) contract that exists works correctly
118TEST_F(ContractInstanceManagerTest, RegularContractExistsReturnsInstance)
119{
120 ProtocolContracts protocol_contracts; // Empty - no protocol contracts
121
122 ContractInstanceManager manager(contract_db, merkle_db, update_check, field_gt, protocol_contracts, event_emitter);
123
124 // Query a regular address (outside protocol contract range)
125 AztecAddress regular_address = AztecAddress(FF(0x1234567890ULL));
126
127 // Create a contract instance
128 ContractInstance instance = testing::random_contract_instance();
129
130 // Setup mocks
131 TreeStates tree_states = {};
132 EXPECT_CALL(merkle_db, get_tree_state()).WillOnce(Return(tree_states));
133 EXPECT_CALL(contract_db, get_contract_instance(regular_address)).WillOnce(Return(instance));
134
135 // ff_gt(11, large_address - 1) returns false - not in protocol range
136 EXPECT_CALL(field_gt, ff_gt(FF(MAX_PROTOCOL_CONTRACTS), regular_address - 1)).WillOnce(Return(false));
137
138 // Nullifier exists - contract is deployed
139 EXPECT_CALL(merkle_db, nullifier_exists(FF(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), regular_address))
140 .WillOnce(Return(true));
141
142 // Update check is performed for regular contracts
143 EXPECT_CALL(update_check, check_current_class_id(regular_address, instance));
144
145 // The call should succeed
146 auto result = manager.get_contract_instance(regular_address);
147
148 // Verify the result
149 ASSERT_TRUE(result.has_value());
150 EXPECT_EQ(result.value(), instance);
151
152 // Verify the event
153 auto events = event_emitter.dump_events();
154 ASSERT_THAT(events, SizeIs(1));
155 EXPECT_EQ(events[0].address, regular_address);
156 EXPECT_TRUE(events[0].exists);
157 EXPECT_FALSE(events[0].is_protocol_contract);
158}
159
160// Test that a regular contract that doesn't exist returns nullopt
161TEST_F(ContractInstanceManagerTest, RegularContractNotExistsReturnsNullopt)
162{
163 ProtocolContracts protocol_contracts; // Empty
164
165 ContractInstanceManager manager(contract_db, merkle_db, update_check, field_gt, protocol_contracts, event_emitter);
166
167 AztecAddress non_existent_address = AztecAddress(FF(0xDEADBEEFULL));
168
169 // Setup mocks
170 TreeStates tree_states = {};
171 EXPECT_CALL(merkle_db, get_tree_state()).WillOnce(Return(tree_states));
172 EXPECT_CALL(contract_db, get_contract_instance(non_existent_address)).WillOnce(Return(std::nullopt));
173
174 // Not in protocol range
175 EXPECT_CALL(field_gt, ff_gt(FF(MAX_PROTOCOL_CONTRACTS), non_existent_address - 1)).WillOnce(Return(false));
176
177 // Nullifier doesn't exist - contract not deployed
178 EXPECT_CALL(merkle_db, nullifier_exists(FF(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS), non_existent_address))
179 .WillOnce(Return(false));
180
181 // The call should return nullopt
182 auto result = manager.get_contract_instance(non_existent_address);
183
184 EXPECT_FALSE(result.has_value());
185
186 // Verify the event
187 auto events = event_emitter.dump_events();
188 ASSERT_THAT(events, SizeIs(1));
189 EXPECT_EQ(events[0].address, non_existent_address);
190 EXPECT_FALSE(events[0].exists);
191 EXPECT_FALSE(events[0].is_protocol_contract);
192}
193
194} // namespace
195} // namespace bb::avm2::simulation
FieldGreaterThan field_gt
std::shared_ptr< Napi::ThreadSafeFunction > instance
#define MAX_PROTOCOL_CONTRACTS
#define CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS
StrictMock< MockHighLevelMerkleDB > merkle_db
StrictMock< MockContractDB > contract_db
EventEmitter< DataCopyEvent > event_emitter
StrictMock< MockUpdateCheck > update_check
ContractInstance random_contract_instance()
Definition fixtures.cpp:159
AvmFlavorSettings::FF FF
Definition field.hpp:10
TEST_F(IPATest, ChallengesAreZero)
Definition ipa.test.cpp:185
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13