@layerzerolabs/protocol-stellar-v2 0.2.40 → 0.2.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +312 -397
- package/.turbo/turbo-lint.log +185 -245
- package/.turbo/turbo-test.log +1846 -1942
- package/Cargo.lock +22 -127
- package/Cargo.toml +4 -6
- package/contracts/common-macros/src/lib.rs +38 -15
- package/contracts/common-macros/src/lz_contract.rs +12 -21
- package/contracts/common-macros/src/tests/lz_contract.rs +17 -8
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__lz_contract__snapshot_generated_lz_contract_code.snap +20 -0
- package/contracts/common-macros/src/upgradeable.rs +37 -30
- package/contracts/endpoint-v2/src/endpoint_v2.rs +4 -3
- package/contracts/endpoint-v2/src/errors.rs +2 -2
- package/contracts/endpoint-v2/src/messaging_channel.rs +11 -0
- package/contracts/endpoint-v2/src/messaging_composer.rs +1 -0
- package/contracts/endpoint-v2/src/tests/endpoint_v2/clear.rs +12 -25
- package/contracts/endpoint-v2/src/tests/endpoint_v2/initializable.rs +4 -4
- package/contracts/endpoint-v2/src/tests/endpoint_v2/verifiable.rs +50 -10
- package/contracts/endpoint-v2/src/tests/endpoint_v2/verify.rs +6 -35
- package/contracts/endpoint-v2/src/tests/messaging_channel/burn.rs +2 -2
- package/contracts/endpoint-v2/src/tests/messaging_channel/clear_payload.rs +50 -1
- package/contracts/endpoint-v2/src/tests/messaging_channel/inbound.rs +78 -0
- package/contracts/endpoint-v2/src/tests/messaging_channel/insert_and_drain_pending_nonces.rs +272 -0
- package/contracts/endpoint-v2/src/tests/messaging_channel/mod.rs +1 -0
- package/contracts/endpoint-v2/src/tests/messaging_channel/nilify.rs +10 -5
- package/contracts/endpoint-v2/src/tests/messaging_channel/skip.rs +30 -0
- package/contracts/macro-integration-tests/tests/runtime/oapp/mod.rs +25 -6
- package/contracts/macro-integration-tests/tests/runtime/oapp/oapp_core.rs +13 -11
- package/contracts/macro-integration-tests/tests/runtime/oapp/options_type3.rs +13 -10
- package/contracts/macro-integration-tests/tests/runtime/oapp/receiver.rs +15 -11
- package/contracts/macro-integration-tests/tests/runtime/oapp/sender.rs +5 -3
- package/contracts/macro-integration-tests/tests/runtime/ownable/mod.rs +1 -1
- package/contracts/macro-integration-tests/tests/runtime/ownable/two_step_transfer.rs +14 -12
- package/contracts/macro-integration-tests/tests/runtime/upgradeable/migrate_guard_and_state.rs +3 -9
- package/contracts/macro-integration-tests/tests/ui/lz_contract/fail/upgradeable_invalid_inner_option.stderr +24 -1
- package/contracts/macro-integration-tests/tests/ui/lz_contract/fail/upgradeable_missing_internal.stderr +3 -3
- package/contracts/macro-integration-tests/tests/ui/lz_contract/pass/upgradeable_rbac.rs +44 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/missing_auth_trait.rs +28 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/missing_auth_trait.stderr +397 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/missing_lz_receive_internal.rs +1 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/missing_lz_receive_internal.stderr +10 -10
- package/contracts/macro-integration-tests/tests/ui/oapp/pass/custom_all.rs +4 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/pass/custom_single_trait.rs +7 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/pass/minimal_contract.rs +5 -4
- package/contracts/macro-integration-tests/tests/ui/oapp/pass/struct_with_fields.rs +2 -0
- package/contracts/macro-integration-tests/tests/ui/ownable/pass/basic.rs +1 -1
- package/contracts/macro-integration-tests/tests/ui/upgradeable/fail/attr_args.stderr +1 -1
- package/contracts/macro-integration-tests/tests/ui/upgradeable/fail/missing_auth_trait.stderr +2 -2
- package/contracts/macro-integration-tests/tests/ui/upgradeable/fail/missing_upgradeable_internal.stderr +2 -2
- package/contracts/macro-integration-tests/tests/ui/upgradeable/pass/rbac.rs +44 -0
- package/contracts/oapps/counter/integration_tests/utils.rs +5 -3
- package/contracts/oapps/counter/src/counter.rs +4 -3
- package/contracts/oapps/counter/src/tests/mod.rs +16 -1
- package/contracts/oapps/counter/src/tests/test_counter.rs +5 -2
- package/contracts/oapps/oapp/src/oapp_core.rs +22 -8
- package/contracts/oapps/oapp/src/oapp_options_type3.rs +7 -5
- package/contracts/oapps/oapp/src/tests/mod.rs +21 -0
- package/contracts/oapps/oapp/src/tests/oapp_core.rs +14 -11
- package/contracts/oapps/oapp/src/tests/oapp_options_type3.rs +17 -10
- package/contracts/oapps/oapp/src/tests/oapp_receiver.rs +6 -3
- package/contracts/oapps/oapp/src/tests/oapp_sender.rs +5 -3
- package/contracts/oapps/oapp/src/tests/test_macros.rs +25 -0
- package/contracts/oapps/oapp-macros/src/generators.rs +12 -9
- package/contracts/oapps/oapp-macros/src/lib.rs +1 -1
- package/contracts/oapps/oapp-macros/src/tests/snapshots/oapp_macros__tests__oapp__snapshot_generate_oapp.snap +15 -7
- package/contracts/oapps/oft/integration-tests/setup.rs +22 -4
- package/contracts/oapps/oft/integration-tests/utils.rs +94 -13
- package/contracts/oapps/oft/src/extensions/oft_fee.rs +23 -10
- package/contracts/oapps/oft/src/extensions/pausable.rs +31 -10
- package/contracts/oapps/oft/src/extensions/rate_limiter.rs +9 -4
- package/contracts/oapps/oft/src/oft.rs +3 -3
- package/contracts/oapps/oft/src/tests/extensions/oft_fee.rs +39 -27
- package/contracts/oapps/oft/src/tests/extensions/pausable.rs +38 -24
- package/contracts/oapps/oft/src/tests/extensions/rate_limiter.rs +87 -69
- package/contracts/oapps/oft/src/tests/oft_types/lock_unlock.rs +1 -0
- package/contracts/oapps/oft-core/integration-tests/setup.rs +28 -3
- package/contracts/oapps/oft-core/src/oft_core.rs +11 -6
- package/contracts/oapps/oft-core/src/tests/test_msg_inspector.rs +20 -20
- package/contracts/oapps/oft-core/src/tests/test_utils.rs +33 -3
- package/contracts/upgrader/src/lib.rs +67 -30
- package/contracts/upgrader/src/tests/test_data/test_upgradeable_contract3.wasm +0 -0
- package/contracts/upgrader/src/tests/test_data/test_upgradeable_contract4.wasm +0 -0
- package/contracts/upgrader/src/tests/test_upgrader.rs +50 -4
- package/contracts/utils/src/ownable.rs +16 -5
- package/contracts/utils/src/tests/ownable.rs +39 -39
- package/contracts/utils/src/upgradeable.rs +60 -17
- package/docs/oapp-guide.md +18 -13
- package/package.json +5 -5
- package/sdk/.turbo/turbo-test.log +359 -348
- package/sdk/dist/generated/bml.d.ts +4 -4
- package/sdk/dist/generated/bml.js +6 -6
- package/sdk/dist/generated/counter.d.ts +269 -123
- package/sdk/dist/generated/counter.js +45 -25
- package/sdk/dist/generated/dvn.d.ts +4 -6
- package/sdk/dist/generated/dvn.js +8 -8
- package/sdk/dist/generated/dvn_fee_lib.d.ts +8 -10
- package/sdk/dist/generated/dvn_fee_lib.js +8 -8
- package/sdk/dist/generated/endpoint.d.ts +9 -9
- package/sdk/dist/generated/endpoint.js +9 -9
- package/sdk/dist/generated/executor.d.ts +9 -11
- package/sdk/dist/generated/executor.js +11 -11
- package/sdk/dist/generated/executor_fee_lib.d.ts +9 -11
- package/sdk/dist/generated/executor_fee_lib.js +11 -11
- package/sdk/dist/generated/executor_helper.d.ts +4 -4
- package/sdk/dist/generated/executor_helper.js +6 -6
- package/sdk/dist/generated/layerzero_view.d.ts +9 -11
- package/sdk/dist/generated/layerzero_view.js +11 -11
- package/sdk/dist/generated/oft.d.ts +323 -156
- package/sdk/dist/generated/oft.js +65 -43
- package/sdk/dist/generated/price_feed.d.ts +8 -10
- package/sdk/dist/generated/price_feed.js +8 -8
- package/sdk/dist/generated/sac_manager.d.ts +8 -8
- package/sdk/dist/generated/sac_manager.js +6 -6
- package/sdk/dist/generated/sml.d.ts +9 -9
- package/sdk/dist/generated/sml.js +9 -9
- package/sdk/dist/generated/treasury.d.ts +9 -9
- package/sdk/dist/generated/treasury.js +9 -9
- package/sdk/dist/generated/uln302.d.ts +9 -9
- package/sdk/dist/generated/uln302.js +9 -9
- package/sdk/dist/generated/upgrader.d.ts +25 -16
- package/sdk/dist/generated/upgrader.js +5 -5
- package/sdk/package.json +1 -1
- package/sdk/test/counter-sml.test.ts +20 -0
- package/sdk/test/counter-uln.test.ts +20 -0
- package/sdk/test/oft-sml.test.ts +22 -0
- package/sdk/test/upgrader.test.ts +1 -0
- package/ts-bindings-gen.toml +67 -0
- package/turbo.json +1 -8
- package/tools/ts-bindings-gen/Cargo.toml +0 -16
- package/tools/ts-bindings-gen/src/main.rs +0 -214
|
@@ -123,6 +123,36 @@ fn test_inbound_out_of_order_populates_pending_and_drains_when_gap_closed() {
|
|
|
123
123
|
assert_eq!(endpoint_client.inbound_payload_hash(&receiver, &src_eid, &sender, &2u64), Some(hash_2));
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
+
#[test]
|
|
127
|
+
fn test_inbound_when_nonce_already_pending_does_not_advance_inbound_nonce() {
|
|
128
|
+
let context = setup();
|
|
129
|
+
let env = &context.env;
|
|
130
|
+
let endpoint_client = &context.endpoint_client;
|
|
131
|
+
|
|
132
|
+
let receiver = Address::generate(env);
|
|
133
|
+
let src_eid = 2;
|
|
134
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
135
|
+
|
|
136
|
+
// First inbound at nonce 2 adds it to pending (gap at nonce 1).
|
|
137
|
+
let hash_2_a = BytesN::from_array(env, &[0x22u8; 32]);
|
|
138
|
+
env.as_contract(&endpoint_client.address, || {
|
|
139
|
+
EndpointV2::inbound_for_test(env, &receiver, src_eid, &sender, 2u64, &hash_2_a)
|
|
140
|
+
});
|
|
141
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 0);
|
|
142
|
+
assert_eq!(endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender), soroban_sdk::vec![env, 2u64]);
|
|
143
|
+
assert_eq!(endpoint_client.inbound_payload_hash(&receiver, &src_eid, &sender, &2u64), Some(hash_2_a.clone()));
|
|
144
|
+
|
|
145
|
+
// Re-inbound at the same nonce should overwrite the payload hash, but should NOT duplicate pending
|
|
146
|
+
// entries nor advance inbound_nonce (gap at nonce 1 still exists).
|
|
147
|
+
let hash_2_b = BytesN::from_array(env, &[0x23u8; 32]);
|
|
148
|
+
env.as_contract(&endpoint_client.address, || {
|
|
149
|
+
EndpointV2::inbound_for_test(env, &receiver, src_eid, &sender, 2u64, &hash_2_b)
|
|
150
|
+
});
|
|
151
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 0);
|
|
152
|
+
assert_eq!(endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender), soroban_sdk::vec![env, 2u64]);
|
|
153
|
+
assert_eq!(endpoint_client.inbound_payload_hash(&receiver, &src_eid, &sender, &2u64), Some(hash_2_b));
|
|
154
|
+
}
|
|
155
|
+
|
|
126
156
|
#[test]
|
|
127
157
|
#[should_panic(expected = "Error(Contract, #11)")] // EndpointError::InvalidNonce
|
|
128
158
|
fn test_inbound_rejects_nonce_beyond_pending_window() {
|
|
@@ -141,6 +171,52 @@ fn test_inbound_rejects_nonce_beyond_pending_window() {
|
|
|
141
171
|
});
|
|
142
172
|
}
|
|
143
173
|
|
|
174
|
+
#[test]
|
|
175
|
+
fn test_inbound_accepts_upper_bound_when_inbound_nonce_nonzero() {
|
|
176
|
+
let context = setup();
|
|
177
|
+
let env = &context.env;
|
|
178
|
+
let endpoint_client = &context.endpoint_client;
|
|
179
|
+
|
|
180
|
+
let receiver = Address::generate(env);
|
|
181
|
+
let src_eid = 2;
|
|
182
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
183
|
+
|
|
184
|
+
// Set inbound_nonce to 100 so the upper bound is 356 (= 100 + 256).
|
|
185
|
+
context.set_inbound_nonce(&receiver, src_eid, &sender, 100);
|
|
186
|
+
|
|
187
|
+
let hash = BytesN::from_array(env, &[0xabu8; 32]);
|
|
188
|
+
env.as_contract(&endpoint_client.address, || {
|
|
189
|
+
EndpointV2::inbound_for_test(env, &receiver, src_eid, &sender, 356u64, &hash)
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Nonce 356 is not consecutive to 100, so it stays pending and inbound_nonce does not advance.
|
|
193
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 100);
|
|
194
|
+
assert_eq!(
|
|
195
|
+
endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender),
|
|
196
|
+
soroban_sdk::vec![env, 356u64]
|
|
197
|
+
);
|
|
198
|
+
assert_eq!(endpoint_client.inbound_payload_hash(&receiver, &src_eid, &sender, &356u64), Some(hash));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
#[test]
|
|
202
|
+
#[should_panic(expected = "Error(Contract, #11)")] // EndpointError::InvalidNonce
|
|
203
|
+
fn test_inbound_rejects_beyond_upper_bound_when_inbound_nonce_nonzero() {
|
|
204
|
+
let context = setup();
|
|
205
|
+
let env = &context.env;
|
|
206
|
+
let endpoint_client = &context.endpoint_client;
|
|
207
|
+
|
|
208
|
+
let receiver = Address::generate(env);
|
|
209
|
+
let src_eid = 2;
|
|
210
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
211
|
+
|
|
212
|
+
context.set_inbound_nonce(&receiver, src_eid, &sender, 100);
|
|
213
|
+
|
|
214
|
+
let hash = BytesN::from_array(env, &[0xabu8; 32]);
|
|
215
|
+
env.as_contract(&endpoint_client.address, || {
|
|
216
|
+
EndpointV2::inbound_for_test(env, &receiver, src_eid, &sender, 357u64, &hash)
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
144
220
|
#[test]
|
|
145
221
|
#[should_panic(expected = "Error(Contract, #11)")] // EndpointError::InvalidNonce
|
|
146
222
|
fn test_inbound_rejects_reverify_when_nonce_leq_inbound_and_payload_missing() {
|
|
@@ -184,4 +260,6 @@ fn test_inbound_allows_reverify_when_nonce_leq_inbound_and_payload_exists() {
|
|
|
184
260
|
EndpointV2::inbound_for_test(env, &receiver, src_eid, &sender, 1u64, &new_hash)
|
|
185
261
|
});
|
|
186
262
|
assert_eq!(endpoint_client.inbound_payload_hash(&receiver, &src_eid, &sender, &1u64), Some(new_hash));
|
|
263
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 1);
|
|
264
|
+
assert!(endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender).is_empty());
|
|
187
265
|
}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
use soroban_sdk::{testutils::Address as _, Address, BytesN};
|
|
2
|
+
|
|
3
|
+
use crate::{endpoint_v2::EndpointV2, tests::endpoint_setup::setup};
|
|
4
|
+
|
|
5
|
+
fn insert_and_drain(
|
|
6
|
+
context: &crate::tests::endpoint_setup::TestSetup,
|
|
7
|
+
receiver: &Address,
|
|
8
|
+
src_eid: u32,
|
|
9
|
+
sender: &BytesN<32>,
|
|
10
|
+
nonce: u64,
|
|
11
|
+
) {
|
|
12
|
+
let env = &context.env;
|
|
13
|
+
let endpoint_client = &context.endpoint_client;
|
|
14
|
+
env.as_contract(&endpoint_client.address, || {
|
|
15
|
+
EndpointV2::insert_and_drain_pending_nonces_for_test(env, receiver, src_eid, sender, nonce)
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
#[test]
|
|
20
|
+
fn test_insert_and_drain_inserts_sorted_and_dedupes() {
|
|
21
|
+
let context = setup();
|
|
22
|
+
let env = &context.env;
|
|
23
|
+
let endpoint_client = &context.endpoint_client;
|
|
24
|
+
|
|
25
|
+
let receiver = Address::generate(env);
|
|
26
|
+
let src_eid = 2u32;
|
|
27
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
28
|
+
|
|
29
|
+
// Start with inbound_nonce = 0.
|
|
30
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 0);
|
|
31
|
+
assert!(endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender).is_empty());
|
|
32
|
+
|
|
33
|
+
// Insert out of order: 3 then 2. Pending should remain sorted.
|
|
34
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 3);
|
|
35
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 2);
|
|
36
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 0);
|
|
37
|
+
assert_eq!(
|
|
38
|
+
endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender),
|
|
39
|
+
soroban_sdk::vec![env, 2u64, 3u64]
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
// Re-inserting an already pending nonce should be a no-op (no duplicates, no drain).
|
|
43
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 2);
|
|
44
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 0);
|
|
45
|
+
assert_eq!(
|
|
46
|
+
endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender),
|
|
47
|
+
soroban_sdk::vec![env, 2u64, 3u64]
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 1);
|
|
51
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 3);
|
|
52
|
+
assert!(endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender).is_empty());
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
#[test]
|
|
56
|
+
fn test_insert_and_drain_drains_consecutive_sequence() {
|
|
57
|
+
let context = setup();
|
|
58
|
+
let env = &context.env;
|
|
59
|
+
let endpoint_client = &context.endpoint_client;
|
|
60
|
+
|
|
61
|
+
let receiver = Address::generate(env);
|
|
62
|
+
let src_eid = 2u32;
|
|
63
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
64
|
+
|
|
65
|
+
// Insert 2 and 3, then insert 1. Inserting 1 should drain 1,2,3 and advance inbound_nonce to 3.
|
|
66
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 2);
|
|
67
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 3);
|
|
68
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 0);
|
|
69
|
+
assert_eq!(
|
|
70
|
+
endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender),
|
|
71
|
+
soroban_sdk::vec![env, 2u64, 3u64]
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 1);
|
|
75
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 3);
|
|
76
|
+
assert!(endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender).is_empty());
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
#[test]
|
|
80
|
+
fn test_insert_and_drain_leaves_nonconsecutive_tail_pending() {
|
|
81
|
+
let context = setup();
|
|
82
|
+
let env = &context.env;
|
|
83
|
+
let endpoint_client = &context.endpoint_client;
|
|
84
|
+
|
|
85
|
+
let receiver = Address::generate(env);
|
|
86
|
+
let src_eid = 2u32;
|
|
87
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
88
|
+
|
|
89
|
+
// Insert 2 and 4, then insert 1. Drain should advance to 2 but leave 4 pending (gap at 3).
|
|
90
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 2);
|
|
91
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 4);
|
|
92
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 1);
|
|
93
|
+
|
|
94
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 2);
|
|
95
|
+
assert_eq!(endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender), soroban_sdk::vec![env, 4u64]);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
#[test]
|
|
99
|
+
fn test_insert_and_drain_accepts_upper_bound_when_inbound_nonce_zero() {
|
|
100
|
+
let context = setup();
|
|
101
|
+
let env = &context.env;
|
|
102
|
+
let endpoint_client = &context.endpoint_client;
|
|
103
|
+
|
|
104
|
+
let receiver = Address::generate(env);
|
|
105
|
+
let src_eid = 2u32;
|
|
106
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
107
|
+
|
|
108
|
+
// inbound_nonce == 0: 256 is allowed.
|
|
109
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 256);
|
|
110
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 0);
|
|
111
|
+
assert_eq!(endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender), soroban_sdk::vec![env, 256u64]);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
#[test]
|
|
115
|
+
#[should_panic(expected = "Error(Contract, #11)")] // EndpointError::InvalidNonce
|
|
116
|
+
fn test_insert_and_drain_rejects_beyond_upper_bound_when_inbound_nonce_zero() {
|
|
117
|
+
let context = setup();
|
|
118
|
+
let env = &context.env;
|
|
119
|
+
|
|
120
|
+
let receiver = Address::generate(env);
|
|
121
|
+
let src_eid = 2u32;
|
|
122
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
123
|
+
|
|
124
|
+
// inbound_nonce == 0: 257 is out of range (max is 256).
|
|
125
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 257);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
#[test]
|
|
129
|
+
#[should_panic(expected = "Error(Contract, #11)")] // EndpointError::InvalidNonce
|
|
130
|
+
fn test_insert_and_drain_rejects_nonce_leq_inbound_nonce() {
|
|
131
|
+
let context = setup();
|
|
132
|
+
let env = &context.env;
|
|
133
|
+
let endpoint_client = &context.endpoint_client;
|
|
134
|
+
|
|
135
|
+
let receiver = Address::generate(env);
|
|
136
|
+
let src_eid = 2u32;
|
|
137
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
138
|
+
|
|
139
|
+
// Advance inbound_nonce to 5 via storage utility.
|
|
140
|
+
context.set_inbound_nonce(&receiver, src_eid, &sender, 5);
|
|
141
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 5);
|
|
142
|
+
|
|
143
|
+
// Calling with new_nonce == inbound_nonce should panic InvalidNonce.
|
|
144
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 5);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
#[test]
|
|
148
|
+
fn test_insert_and_drain_accepts_upper_bound_when_inbound_nonce_nonzero() {
|
|
149
|
+
let context = setup();
|
|
150
|
+
let env = &context.env;
|
|
151
|
+
let endpoint_client = &context.endpoint_client;
|
|
152
|
+
|
|
153
|
+
let receiver = Address::generate(env);
|
|
154
|
+
let src_eid = 2u32;
|
|
155
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
156
|
+
|
|
157
|
+
// inbound_nonce == 100: upper bound is 356 (= 100 + 256).
|
|
158
|
+
context.set_inbound_nonce(&receiver, src_eid, &sender, 100);
|
|
159
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 356);
|
|
160
|
+
|
|
161
|
+
// Not consecutive to 100, so it remains pending and inbound_nonce does not advance.
|
|
162
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 100);
|
|
163
|
+
assert_eq!(endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender), soroban_sdk::vec![env, 356u64]);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
#[test]
|
|
167
|
+
#[should_panic(expected = "Error(Contract, #11)")] // EndpointError::InvalidNonce
|
|
168
|
+
fn test_insert_and_drain_rejects_beyond_upper_bound_when_inbound_nonce_nonzero() {
|
|
169
|
+
let context = setup();
|
|
170
|
+
let env = &context.env;
|
|
171
|
+
|
|
172
|
+
let receiver = Address::generate(env);
|
|
173
|
+
let src_eid = 2u32;
|
|
174
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
175
|
+
|
|
176
|
+
context.set_inbound_nonce(&receiver, src_eid, &sender, 100);
|
|
177
|
+
|
|
178
|
+
// inbound_nonce == 100: 357 is out of range (max is 356).
|
|
179
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 357);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
#[test]
|
|
183
|
+
fn test_insert_and_drain_drains_across_existing_pending_tail_when_inbound_nonce_nonzero() {
|
|
184
|
+
let context = setup();
|
|
185
|
+
let env = &context.env;
|
|
186
|
+
let endpoint_client = &context.endpoint_client;
|
|
187
|
+
|
|
188
|
+
let receiver = Address::generate(env);
|
|
189
|
+
let src_eid = 2u32;
|
|
190
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
191
|
+
|
|
192
|
+
// Set inbound_nonce to 2.
|
|
193
|
+
context.set_inbound_nonce(&receiver, src_eid, &sender, 2);
|
|
194
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 2);
|
|
195
|
+
|
|
196
|
+
// Insert 4 first -> pending [4], inbound_nonce remains 2 (missing 3).
|
|
197
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 4);
|
|
198
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 2);
|
|
199
|
+
assert_eq!(endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender), soroban_sdk::vec![env, 4u64]);
|
|
200
|
+
|
|
201
|
+
// Insert 3 -> should drain 3 then 4 and advance inbound_nonce to 4.
|
|
202
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 3);
|
|
203
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 4);
|
|
204
|
+
assert!(endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender).is_empty());
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
#[test]
|
|
208
|
+
fn test_insert_and_drain_drains_single_next_nonce_when_no_pending() {
|
|
209
|
+
let context = setup();
|
|
210
|
+
let env = &context.env;
|
|
211
|
+
let endpoint_client = &context.endpoint_client;
|
|
212
|
+
|
|
213
|
+
let receiver = Address::generate(env);
|
|
214
|
+
let src_eid = 2u32;
|
|
215
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
216
|
+
|
|
217
|
+
context.set_inbound_nonce(&receiver, src_eid, &sender, 5);
|
|
218
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 5);
|
|
219
|
+
assert!(endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender).is_empty());
|
|
220
|
+
|
|
221
|
+
// Insert exactly inbound_nonce + 1. This should drain immediately and leave pending empty.
|
|
222
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 6);
|
|
223
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 6);
|
|
224
|
+
assert!(endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender).is_empty());
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
#[test]
|
|
228
|
+
fn test_insert_and_drain_window_holds_255_when_inbound_plus_one_missing_then_drains() {
|
|
229
|
+
let context = setup();
|
|
230
|
+
let env = &context.env;
|
|
231
|
+
let endpoint_client = &context.endpoint_client;
|
|
232
|
+
|
|
233
|
+
let receiver = Address::generate(env);
|
|
234
|
+
let src_eid = 2u32;
|
|
235
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
236
|
+
|
|
237
|
+
// Fill the pending window with 2..=256 while nonce 1 is still missing.
|
|
238
|
+
// This creates 255 pending nonces and inbound_nonce remains 0.
|
|
239
|
+
for nonce in 2u64..=256u64 {
|
|
240
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, nonce);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 0);
|
|
244
|
+
let pending = endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender);
|
|
245
|
+
assert_eq!(pending.len(), 255);
|
|
246
|
+
assert_eq!(pending.get(0).unwrap(), 2u64);
|
|
247
|
+
assert_eq!(pending.get(254).unwrap(), 256u64);
|
|
248
|
+
|
|
249
|
+
// Inserting nonce 1 closes the gap and drains the entire window.
|
|
250
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 1);
|
|
251
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 256);
|
|
252
|
+
assert!(endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender).is_empty());
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
#[test]
|
|
256
|
+
#[should_panic(expected = "Error(Contract, #11)")] // EndpointError::InvalidNonce
|
|
257
|
+
fn test_insert_and_drain_rejects_257_when_missing_inbound_plus_one() {
|
|
258
|
+
let context = setup();
|
|
259
|
+
let env = &context.env;
|
|
260
|
+
|
|
261
|
+
let receiver = Address::generate(env);
|
|
262
|
+
let src_eid = 2u32;
|
|
263
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
264
|
+
|
|
265
|
+
// Keep inbound_nonce at 0 and fill 2..=256 into pending.
|
|
266
|
+
for nonce in 2u64..=256u64 {
|
|
267
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, nonce);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// 257 is outside the allowed range (0, 256] while inbound_nonce is still 0.
|
|
271
|
+
insert_and_drain(&context, &receiver, src_eid, &sender, 257);
|
|
272
|
+
}
|
|
@@ -92,6 +92,7 @@ fn test_nilify_success_with_stored_payload() {
|
|
|
92
92
|
|
|
93
93
|
// Verify payload hash is stored.
|
|
94
94
|
assert_eq!(endpoint_client.inbound_payload_hash(&receiver, &src_eid, &sender, &nonce), Some(payload_hash.clone()));
|
|
95
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 1);
|
|
95
96
|
|
|
96
97
|
// Nilify the payload.
|
|
97
98
|
let payload_hash_opt = Some(payload_hash.clone());
|
|
@@ -114,9 +115,10 @@ fn test_nilify_success_with_stored_payload() {
|
|
|
114
115
|
let nilified_hash = endpoint_client.inbound_payload_hash(&receiver, &src_eid, &sender, &nonce);
|
|
115
116
|
let expected_nil_hash = nil_hash(&context);
|
|
116
117
|
assert_eq!(nilified_hash, Some(expected_nil_hash));
|
|
118
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 1);
|
|
117
119
|
}
|
|
118
120
|
|
|
119
|
-
// Successful nilify with None (
|
|
121
|
+
// Successful nilify with None (no existing payload hash) when nonce > inbound_nonce
|
|
120
122
|
#[test]
|
|
121
123
|
fn test_nilify_success_with_empty_payload() {
|
|
122
124
|
let context = setup();
|
|
@@ -150,9 +152,9 @@ fn test_nilify_success_with_empty_payload() {
|
|
|
150
152
|
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 2);
|
|
151
153
|
}
|
|
152
154
|
|
|
153
|
-
// Nilify with None counts
|
|
155
|
+
// Nilify with None counts toward `inbound_nonce` advancement (via pending-nonce draining).
|
|
154
156
|
#[test]
|
|
155
|
-
fn
|
|
157
|
+
fn test_nilify_with_none_advances_inbound_nonce_without_changing_payload_hashes() {
|
|
156
158
|
let context = setup();
|
|
157
159
|
let env = &context.env;
|
|
158
160
|
let endpoint_client = &context.endpoint_client;
|
|
@@ -211,7 +213,7 @@ fn test_nilify_closes_gap_and_drains_pending_nonces() {
|
|
|
211
213
|
);
|
|
212
214
|
}
|
|
213
215
|
|
|
214
|
-
// Nilify is allowed when nonce <=
|
|
216
|
+
// Nilify is allowed when nonce <= inbound_nonce if an `inbound_payload_hash` exists
|
|
215
217
|
#[test]
|
|
216
218
|
fn test_nilify_allows_when_nonce_is_checkpointed_if_payload_exists() {
|
|
217
219
|
let context = setup();
|
|
@@ -232,7 +234,7 @@ fn test_nilify_allows_when_nonce_is_checkpointed_if_payload_exists() {
|
|
|
232
234
|
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 10);
|
|
233
235
|
assert_eq!(endpoint_client.inbound_payload_hash(&receiver, &src_eid, &sender, &nonce), Some(payload_hash.clone()));
|
|
234
236
|
|
|
235
|
-
// Even though nonce <=
|
|
237
|
+
// Even though nonce <= inbound_nonce, this should succeed because a payload hash exists.
|
|
236
238
|
let payload_hash_opt = Some(payload_hash.clone());
|
|
237
239
|
nilify_with_auth(&context, &receiver, &receiver, src_eid, &sender, nonce, &payload_hash_opt);
|
|
238
240
|
assert_eq!(endpoint_client.inbound_payload_hash(&receiver, &src_eid, &sender, &nonce), Some(nil_hash(&context)));
|
|
@@ -253,16 +255,19 @@ fn test_nilify_allows_repeated_call_when_already_nilified() {
|
|
|
253
255
|
|
|
254
256
|
// First nilify: verified payload hash -> nil hash.
|
|
255
257
|
context.inbound_as_verified(&receiver, src_eid, &sender, nonce, &payload_hash);
|
|
258
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 1);
|
|
256
259
|
let payload_hash_opt = Some(payload_hash);
|
|
257
260
|
nilify_with_auth(&context, &receiver, &receiver, src_eid, &sender, nonce, &payload_hash_opt);
|
|
258
261
|
|
|
259
262
|
let nil = nil_hash(&context);
|
|
260
263
|
assert_eq!(endpoint_client.inbound_payload_hash(&receiver, &src_eid, &sender, &nonce), Some(nil.clone()));
|
|
264
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 1);
|
|
261
265
|
|
|
262
266
|
// Second nilify: passing the current stored nil hash should succeed.
|
|
263
267
|
let nil_opt = Some(nil.clone());
|
|
264
268
|
nilify_with_auth(&context, &receiver, &receiver, src_eid, &sender, nonce, &nil_opt);
|
|
265
269
|
assert_eq!(endpoint_client.inbound_payload_hash(&receiver, &src_eid, &sender, &nonce), Some(nil));
|
|
270
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 1);
|
|
266
271
|
}
|
|
267
272
|
|
|
268
273
|
// Delegate authorization (delegate(receiver) is allowed)
|
|
@@ -248,6 +248,36 @@ fn test_skip_closes_gap_and_advances_inbound_nonce() {
|
|
|
248
248
|
assert_eq!(endpoint_client.inbound_payload_hash(&receiver, &src_eid, &sender, &2), Some(payload_hash_2));
|
|
249
249
|
}
|
|
250
250
|
|
|
251
|
+
// Skipping a missing nonce can close *part* of the gap while leaving later gaps pending.
|
|
252
|
+
#[test]
|
|
253
|
+
fn test_skip_closes_gap_but_pending_inbound_nonces_not_empty() {
|
|
254
|
+
let context = setup();
|
|
255
|
+
let env = &context.env;
|
|
256
|
+
let endpoint_client = &context.endpoint_client;
|
|
257
|
+
|
|
258
|
+
let receiver = Address::generate(env);
|
|
259
|
+
let src_eid = 2;
|
|
260
|
+
let sender = BytesN::from_array(env, &[1u8; 32]);
|
|
261
|
+
|
|
262
|
+
// Verify nonce 2 and 4 out-of-order. inbound_nonce stays 0 because nonce 1 is missing, and
|
|
263
|
+
// pending list contains [2, 4] (gap at 1 and 3).
|
|
264
|
+
let payload_hash_2 = BytesN::from_array(env, &[0x11u8; 32]);
|
|
265
|
+
let payload_hash_4 = BytesN::from_array(env, &[0x22u8; 32]);
|
|
266
|
+
context.inbound_as_verified(&receiver, src_eid, &sender, 2, &payload_hash_2);
|
|
267
|
+
context.inbound_as_verified(&receiver, src_eid, &sender, 4, &payload_hash_4);
|
|
268
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 0);
|
|
269
|
+
|
|
270
|
+
// Skip nonce 1 closes the first gap and drains consecutive pending nonces up to 2,
|
|
271
|
+
// but nonce 4 remains pending because nonce 3 is still missing.
|
|
272
|
+
skip_with_auth(&context, &receiver, &receiver, src_eid, &sender, 1);
|
|
273
|
+
assert_eq!(endpoint_client.inbound_nonce(&receiver, &src_eid, &sender), 2);
|
|
274
|
+
assert_eq!(endpoint_client.pending_inbound_nonces(&receiver, &src_eid, &sender), soroban_sdk::vec![env, 4u64]);
|
|
275
|
+
|
|
276
|
+
// Payload hashes remain intact.
|
|
277
|
+
assert_eq!(endpoint_client.inbound_payload_hash(&receiver, &src_eid, &sender, &2), Some(payload_hash_2));
|
|
278
|
+
assert_eq!(endpoint_client.inbound_payload_hash(&receiver, &src_eid, &sender, &4), Some(payload_hash_4));
|
|
279
|
+
}
|
|
280
|
+
|
|
251
281
|
// Repeated skip of the same nonce is rejected
|
|
252
282
|
#[test]
|
|
253
283
|
fn test_skip_rejects_repeated_same_nonce() {
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
use endpoint_v2::Origin;
|
|
2
|
+
use oapp::oapp_core::OAPP_ADMIN_ROLE;
|
|
2
3
|
use oapp::oapp_receiver::LzReceiveInternal;
|
|
3
4
|
use oapp_macros::oapp;
|
|
4
|
-
use soroban_sdk::{
|
|
5
|
+
use soroban_sdk::{
|
|
6
|
+
contractimpl, symbol_short,
|
|
7
|
+
testutils::{MockAuth, MockAuthInvoke},
|
|
8
|
+
Address, Bytes, BytesN, Env, IntoVal, Symbol,
|
|
9
|
+
};
|
|
5
10
|
|
|
6
11
|
mod oapp_core;
|
|
7
12
|
mod options_type3;
|
|
@@ -11,12 +16,10 @@ mod sender;
|
|
|
11
16
|
/// Shared contract used by oapp-macros runtime tests.
|
|
12
17
|
///
|
|
13
18
|
/// Notes:
|
|
14
|
-
/// - `#[oapp]`
|
|
15
|
-
///
|
|
16
|
-
/// - `oapp::oapp_receiver::OAppReceiver` (contract trait)
|
|
17
|
-
/// - `oapp::oapp_options_type3::OAppOptionsType3` (contract trait)
|
|
18
|
-
/// - `oapp::oapp_sender::OAppSenderInternal` (internal trait)
|
|
19
|
+
/// - `#[oapp]` generates only trait impls. User must apply `#[lz_contract]` (or similar) for contract + TTL + Auth.
|
|
20
|
+
/// - Default trait impls: `OAppCore`, `OAppReceiver`, `OAppOptionsType3`, `OAppSenderInternal`
|
|
19
21
|
#[oapp]
|
|
22
|
+
#[common_macros::lz_contract]
|
|
20
23
|
pub struct TestOApp;
|
|
21
24
|
|
|
22
25
|
impl LzReceiveInternal for TestOApp {
|
|
@@ -46,3 +49,19 @@ impl TestOApp {
|
|
|
46
49
|
env.storage().instance().get(&symbol_short!("lzr_c")).unwrap_or(false)
|
|
47
50
|
}
|
|
48
51
|
}
|
|
52
|
+
|
|
53
|
+
/// Grants `OAPP_ADMIN_ROLE` to `owner` via the public `grant_role` interface.
|
|
54
|
+
/// Call after `init()` in tests that exercise RBAC-protected entrypoints.
|
|
55
|
+
pub fn grant_oapp_admin(env: &Env, contract: &Address, owner: &Address) {
|
|
56
|
+
let role = Symbol::new(env, OAPP_ADMIN_ROLE);
|
|
57
|
+
env.mock_auths(&[MockAuth {
|
|
58
|
+
address: owner,
|
|
59
|
+
invoke: &MockAuthInvoke {
|
|
60
|
+
contract,
|
|
61
|
+
fn_name: "grant_role",
|
|
62
|
+
args: (owner, &role, owner).into_val(env),
|
|
63
|
+
sub_invokes: &[],
|
|
64
|
+
},
|
|
65
|
+
}]);
|
|
66
|
+
utils::rbac::RoleBasedAccessControlClient::new(env, contract).grant_role(owner, &role, owner);
|
|
67
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Runtime tests: OAppCore behavior generated by `#[oapp]`.
|
|
2
2
|
|
|
3
|
-
use super::{TestOApp, TestOAppClient};
|
|
3
|
+
use super::{grant_oapp_admin, TestOApp, TestOAppClient};
|
|
4
4
|
use oapp::oapp_core::{OAppCoreStorage, PeerSet};
|
|
5
5
|
use soroban_sdk::{
|
|
6
6
|
contract, contractimpl,
|
|
@@ -64,6 +64,7 @@ fn set_peer_requires_auth_and_updates_storage() {
|
|
|
64
64
|
let owner = Address::generate(&env);
|
|
65
65
|
let endpoint = Address::generate(&env);
|
|
66
66
|
client.init(&owner, &endpoint);
|
|
67
|
+
grant_oapp_admin(&env, &contract_id, &owner);
|
|
67
68
|
|
|
68
69
|
let eid: u32 = 101;
|
|
69
70
|
let peer = Some(BytesN::<32>::from_array(&env, &[7u8; 32]));
|
|
@@ -72,7 +73,7 @@ fn set_peer_requires_auth_and_updates_storage() {
|
|
|
72
73
|
assert_eq!(client.peer(&eid), None);
|
|
73
74
|
|
|
74
75
|
// Unauthorized set should fail.
|
|
75
|
-
let unauthorized = client.try_set_peer(&eid, &peer);
|
|
76
|
+
let unauthorized = client.try_set_peer(&eid, &peer, &owner);
|
|
76
77
|
assert_eq!(
|
|
77
78
|
unauthorized.unwrap_err().unwrap(),
|
|
78
79
|
Error::from_type_and_code(ScErrorType::Context, ScErrorCode::InvalidAction)
|
|
@@ -85,11 +86,11 @@ fn set_peer_requires_auth_and_updates_storage() {
|
|
|
85
86
|
invoke: &MockAuthInvoke {
|
|
86
87
|
contract: &contract_id,
|
|
87
88
|
fn_name: "set_peer",
|
|
88
|
-
args: (&eid, &peer).into_val(&env),
|
|
89
|
+
args: (&eid, &peer, &owner).into_val(&env),
|
|
89
90
|
sub_invokes: &[],
|
|
90
91
|
},
|
|
91
92
|
}])
|
|
92
|
-
.set_peer(&eid, &peer);
|
|
93
|
+
.set_peer(&eid, &peer, &owner);
|
|
93
94
|
|
|
94
95
|
// Assert event before any other contract call (Soroban events are per-call).
|
|
95
96
|
assert_contains_event(&env, &contract_id, PeerSet { eid, peer: peer.clone() });
|
|
@@ -106,11 +107,11 @@ fn set_peer_requires_auth_and_updates_storage() {
|
|
|
106
107
|
invoke: &MockAuthInvoke {
|
|
107
108
|
contract: &contract_id,
|
|
108
109
|
fn_name: "set_peer",
|
|
109
|
-
args: (&eid, &none).into_val(&env),
|
|
110
|
+
args: (&eid, &none, &owner).into_val(&env),
|
|
110
111
|
sub_invokes: &[],
|
|
111
112
|
},
|
|
112
113
|
}]);
|
|
113
|
-
client.set_peer(&eid, &none);
|
|
114
|
+
client.set_peer(&eid, &none, &owner);
|
|
114
115
|
assert_contains_event(&env, &contract_id, PeerSet { eid, peer: None });
|
|
115
116
|
env.as_contract(&contract_id, || {
|
|
116
117
|
assert_eq!(OAppCoreStorage::peer(&env, eid), None);
|
|
@@ -128,10 +129,11 @@ fn set_delegate_requires_auth_and_updates_endpoint() {
|
|
|
128
129
|
|
|
129
130
|
let owner = Address::generate(&env);
|
|
130
131
|
client.init(&owner, &endpoint_id);
|
|
132
|
+
grant_oapp_admin(&env, &contract_id, &owner);
|
|
131
133
|
|
|
132
134
|
// Unauthorized set should fail.
|
|
133
135
|
let delegate = Some(Address::generate(&env));
|
|
134
|
-
let unauthorized = client.try_set_delegate(&delegate);
|
|
136
|
+
let unauthorized = client.try_set_delegate(&delegate, &owner);
|
|
135
137
|
assert_eq!(
|
|
136
138
|
unauthorized.unwrap_err().unwrap(),
|
|
137
139
|
Error::from_type_and_code(ScErrorType::Context, ScErrorCode::InvalidAction)
|
|
@@ -144,11 +146,11 @@ fn set_delegate_requires_auth_and_updates_endpoint() {
|
|
|
144
146
|
invoke: &MockAuthInvoke {
|
|
145
147
|
contract: &contract_id,
|
|
146
148
|
fn_name: "set_delegate",
|
|
147
|
-
args: (&delegate,).into_val(&env),
|
|
149
|
+
args: (&delegate, &owner).into_val(&env),
|
|
148
150
|
sub_invokes: &[],
|
|
149
151
|
},
|
|
150
152
|
}])
|
|
151
|
-
.set_delegate(&delegate);
|
|
153
|
+
.set_delegate(&delegate, &owner);
|
|
152
154
|
|
|
153
155
|
assert_eq!(endpoint_client.delegate(&contract_id), delegate);
|
|
154
156
|
|
|
@@ -160,11 +162,11 @@ fn set_delegate_requires_auth_and_updates_endpoint() {
|
|
|
160
162
|
invoke: &MockAuthInvoke {
|
|
161
163
|
contract: &contract_id,
|
|
162
164
|
fn_name: "set_delegate",
|
|
163
|
-
args: (&none,).into_val(&env),
|
|
165
|
+
args: (&none, &owner).into_val(&env),
|
|
164
166
|
sub_invokes: &[],
|
|
165
167
|
},
|
|
166
168
|
}])
|
|
167
|
-
.set_delegate(&none);
|
|
169
|
+
.set_delegate(&none, &owner);
|
|
168
170
|
|
|
169
171
|
assert_eq!(endpoint_client.delegate(&contract_id), None);
|
|
170
172
|
}
|