@layerzerolabs/oapp-stellar-contracts 0.2.122
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/Cargo.toml +44 -0
- package/LICENSE +23 -0
- package/README.md +5 -0
- package/clippy.toml +6 -0
- package/package.json +53 -0
- package/rust-toolchain.toml +4 -0
- package/rustfmt.toml +15 -0
- package/src/errors.rs +13 -0
- package/src/interfaces/mod.rs +3 -0
- package/src/interfaces/oapp_msg_inspector.rs +70 -0
- package/src/lib.rs +15 -0
- package/src/oapp_core.rs +143 -0
- package/src/oapp_options_type3.rs +133 -0
- package/src/oapp_receiver.rs +195 -0
- package/src/oapp_sender.rs +152 -0
- package/src/tests/mod.rs +5 -0
- package/src/tests/oapp_core.rs +225 -0
- package/src/tests/oapp_options_type3.rs +246 -0
- package/src/tests/oapp_receiver.rs +383 -0
- package/src/tests/oapp_sender.rs +570 -0
- package/src/tests/test_macros.rs +434 -0
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
use crate::{self as oapp, errors::OAppError, oapp_receiver::LzReceiveInternal, oapp_sender::FeePayer};
|
|
2
|
+
use endpoint_v2::{MessagingFee, MessagingParams, MessagingReceipt, Origin};
|
|
3
|
+
use soroban_sdk::{
|
|
4
|
+
contract, contractimpl, symbol_short,
|
|
5
|
+
testutils::{Address as _, MockAuth, MockAuthInvoke},
|
|
6
|
+
token::{StellarAssetClient, TokenClient},
|
|
7
|
+
Address, Bytes, BytesN, Env, IntoVal,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
// Mock Endpoint contract
|
|
11
|
+
#[contract]
|
|
12
|
+
pub struct MockEndpoint;
|
|
13
|
+
|
|
14
|
+
#[contractimpl]
|
|
15
|
+
impl MockEndpoint {
|
|
16
|
+
pub fn __constructor(env: Env, zro_token: &Address, native_token: &Address) {
|
|
17
|
+
// Store as Option<Address> so zro() can return None when unavailable.
|
|
18
|
+
env.storage().instance().set(&symbol_short!("zro"), &Some(zro_token.clone()));
|
|
19
|
+
env.storage().instance().set(&symbol_short!("ntk"), native_token);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
pub fn set_delegate(_env: Env, _oapp: Address, _delegate: Option<Address>) {
|
|
23
|
+
// do nothing in mock
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
pub fn quote(_env: Env, _sender: Address, params: MessagingParams) -> MessagingFee {
|
|
27
|
+
MessagingFee { native_fee: 1000, zro_fee: if params.pay_in_zro { 500 } else { 0 } }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
pub fn send(env: Env, _sender: Address, params: MessagingParams, _refund_address: Address) -> MessagingReceipt {
|
|
31
|
+
// Record last send call for assertions
|
|
32
|
+
env.storage().instance().set(&symbol_short!("snds"), &_sender);
|
|
33
|
+
env.storage().instance().set(&symbol_short!("sndp"), ¶ms);
|
|
34
|
+
env.storage().instance().set(&symbol_short!("sndr"), &_refund_address);
|
|
35
|
+
|
|
36
|
+
// Return mock receipt
|
|
37
|
+
MessagingReceipt {
|
|
38
|
+
guid: BytesN::from_array(&env, &[1u8; 32]),
|
|
39
|
+
nonce: 1,
|
|
40
|
+
fee: MessagingFee { native_fee: 1000, zro_fee: if params.pay_in_zro { 500 } else { 0 } },
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
pub fn last_send(env: Env) -> (Address, MessagingParams, Address) {
|
|
45
|
+
(
|
|
46
|
+
env.storage().instance().get(&symbol_short!("snds")).unwrap(),
|
|
47
|
+
env.storage().instance().get(&symbol_short!("sndp")).unwrap(),
|
|
48
|
+
env.storage().instance().get(&symbol_short!("sndr")).unwrap(),
|
|
49
|
+
)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
pub fn zro(env: Env) -> Option<Address> {
|
|
53
|
+
// Return a mock ZRO token address (or None if not set)
|
|
54
|
+
env.storage().instance().get(&symbol_short!("zro")).unwrap_or(None)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
pub fn native_token(env: Env) -> Address {
|
|
58
|
+
env.storage().instance().get(&symbol_short!("ntk")).unwrap()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
pub fn set_zro(env: Env, zro: &Option<Address>) {
|
|
62
|
+
env.storage().instance().set(&symbol_short!("zro"), zro);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#[oapp_macros::oapp]
|
|
67
|
+
#[common_macros::lz_contract]
|
|
68
|
+
pub struct DummyOAppSender;
|
|
69
|
+
|
|
70
|
+
impl LzReceiveInternal for DummyOAppSender {
|
|
71
|
+
fn __lz_receive(
|
|
72
|
+
_env: &Env,
|
|
73
|
+
_origin: &Origin,
|
|
74
|
+
_guid: &BytesN<32>,
|
|
75
|
+
_message: &Bytes,
|
|
76
|
+
_extra_data: &Bytes,
|
|
77
|
+
_executor: &Address,
|
|
78
|
+
_value: i128,
|
|
79
|
+
) {
|
|
80
|
+
// Not used in sender tests
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
#[contractimpl]
|
|
85
|
+
impl DummyOAppSender {
|
|
86
|
+
pub fn __constructor(env: &Env, owner: &Address, endpoint: &Address) {
|
|
87
|
+
oapp::oapp_core::init_ownable_oapp::<Self>(env, owner, endpoint, owner);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
pub fn quote(env: &Env, dst_eid: u32, message: &Bytes, options: &Bytes, pay_in_zro: bool) -> MessagingFee {
|
|
91
|
+
Self::__quote(env, dst_eid, message, options, pay_in_zro)
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
pub fn send(
|
|
95
|
+
env: &Env,
|
|
96
|
+
sender: &Address,
|
|
97
|
+
dst_eid: u32,
|
|
98
|
+
message: &Bytes,
|
|
99
|
+
options: &Bytes,
|
|
100
|
+
fee: &MessagingFee,
|
|
101
|
+
refund_address: &Address,
|
|
102
|
+
) -> MessagingReceipt {
|
|
103
|
+
sender.require_auth();
|
|
104
|
+
Self::__lz_send(env, dst_eid, message, options, &FeePayer::Verified(sender.clone()), fee, refund_address)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
pub fn pay_native_fee(env: &Env, fee_payer: &Address, native_fee: i128) {
|
|
108
|
+
fee_payer.require_auth();
|
|
109
|
+
Self::__pay_native(env, fee_payer, native_fee)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
pub fn pay_zro_fee(env: &Env, fee_payer: &Address, zro_fee: i128) {
|
|
113
|
+
fee_payer.require_auth();
|
|
114
|
+
Self::__pay_zro(env, fee_payer, zro_fee)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const REMOTE_EID: u32 = 100;
|
|
119
|
+
const UNSET_EID: u32 = 999;
|
|
120
|
+
|
|
121
|
+
struct TestSetup<'a> {
|
|
122
|
+
env: Env,
|
|
123
|
+
token_admin: Address,
|
|
124
|
+
endpoint: Address,
|
|
125
|
+
owner: Address,
|
|
126
|
+
oapp_client: DummyOAppSenderClient<'a>,
|
|
127
|
+
native_token: Address,
|
|
128
|
+
zro_token: Address,
|
|
129
|
+
native_token_client: TokenClient<'a>,
|
|
130
|
+
native_token_admin_client: StellarAssetClient<'a>,
|
|
131
|
+
zro_token_admin_client: StellarAssetClient<'a>,
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
fn setup<'a>() -> TestSetup<'a> {
|
|
135
|
+
let env = Env::default();
|
|
136
|
+
|
|
137
|
+
let owner = Address::generate(&env);
|
|
138
|
+
|
|
139
|
+
let token_admin = Address::generate(&env);
|
|
140
|
+
// Deploy mock tokens
|
|
141
|
+
let native_token_sac = env.register_stellar_asset_contract_v2(token_admin.clone());
|
|
142
|
+
let native_token = native_token_sac.address();
|
|
143
|
+
let native_token_client = TokenClient::new(&env, &native_token);
|
|
144
|
+
let native_token_admin_client = StellarAssetClient::new(&env, &native_token);
|
|
145
|
+
|
|
146
|
+
let zro_token_sac = env.register_stellar_asset_contract_v2(token_admin.clone());
|
|
147
|
+
let zro_token = zro_token_sac.address();
|
|
148
|
+
let zro_token_admin_client = StellarAssetClient::new(&env, &zro_token);
|
|
149
|
+
|
|
150
|
+
// Deploy mock endpoint
|
|
151
|
+
let endpoint = env.register(MockEndpoint, (&zro_token, &native_token));
|
|
152
|
+
|
|
153
|
+
// Deploy OApp
|
|
154
|
+
let oapp = env.register(DummyOAppSender, (&owner, &endpoint));
|
|
155
|
+
let oapp_client = DummyOAppSenderClient::new(&env, &oapp);
|
|
156
|
+
|
|
157
|
+
TestSetup {
|
|
158
|
+
env,
|
|
159
|
+
endpoint,
|
|
160
|
+
token_admin,
|
|
161
|
+
native_token_client,
|
|
162
|
+
native_token_admin_client,
|
|
163
|
+
zro_token_admin_client,
|
|
164
|
+
native_token,
|
|
165
|
+
zro_token,
|
|
166
|
+
owner,
|
|
167
|
+
oapp_client,
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
fn set_peer_with_auth(
|
|
172
|
+
env: &Env,
|
|
173
|
+
owner: &Address,
|
|
174
|
+
oapp_client: &DummyOAppSenderClient<'_>,
|
|
175
|
+
eid: u32,
|
|
176
|
+
peer: &BytesN<32>,
|
|
177
|
+
) {
|
|
178
|
+
let peer_option = Some(peer.clone());
|
|
179
|
+
env.mock_auths(&[MockAuth {
|
|
180
|
+
address: owner,
|
|
181
|
+
invoke: &MockAuthInvoke {
|
|
182
|
+
contract: &oapp_client.address,
|
|
183
|
+
fn_name: "set_peer",
|
|
184
|
+
args: (&eid, &peer_option, owner).into_val(env),
|
|
185
|
+
sub_invokes: &[],
|
|
186
|
+
},
|
|
187
|
+
}]);
|
|
188
|
+
oapp_client.set_peer(&eid, &peer_option, owner);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
fn mint_to(
|
|
192
|
+
env: &Env,
|
|
193
|
+
token_admin: &Address,
|
|
194
|
+
token: &Address,
|
|
195
|
+
token_admin_client: &StellarAssetClient<'_>,
|
|
196
|
+
to: &Address,
|
|
197
|
+
amount: i128,
|
|
198
|
+
) {
|
|
199
|
+
env.mock_auths(&[MockAuth {
|
|
200
|
+
address: token_admin,
|
|
201
|
+
invoke: &MockAuthInvoke {
|
|
202
|
+
contract: token,
|
|
203
|
+
fn_name: "mint",
|
|
204
|
+
args: (to, amount).into_val(env),
|
|
205
|
+
sub_invokes: &[],
|
|
206
|
+
},
|
|
207
|
+
}]);
|
|
208
|
+
token_admin_client.mint(to, &amount);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
fn mock_send_auth(
|
|
212
|
+
env: &Env,
|
|
213
|
+
sender: &Address,
|
|
214
|
+
oapp_client: &DummyOAppSenderClient<'_>,
|
|
215
|
+
dst_eid: u32,
|
|
216
|
+
message: &Bytes,
|
|
217
|
+
options: &Bytes,
|
|
218
|
+
fee: &MessagingFee,
|
|
219
|
+
refund_address: &Address,
|
|
220
|
+
native_token: &Address,
|
|
221
|
+
endpoint: &Address,
|
|
222
|
+
zro_token: &Address,
|
|
223
|
+
) {
|
|
224
|
+
let native_transfer = MockAuthInvoke {
|
|
225
|
+
contract: native_token,
|
|
226
|
+
fn_name: "transfer",
|
|
227
|
+
args: (sender, endpoint, &fee.native_fee).into_val(env),
|
|
228
|
+
sub_invokes: &[],
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
if fee.zro_fee > 0 {
|
|
232
|
+
let zro_transfer = MockAuthInvoke {
|
|
233
|
+
contract: zro_token,
|
|
234
|
+
fn_name: "transfer",
|
|
235
|
+
args: (sender, endpoint, &fee.zro_fee).into_val(env),
|
|
236
|
+
sub_invokes: &[],
|
|
237
|
+
};
|
|
238
|
+
let sub_invokes = [native_transfer, zro_transfer];
|
|
239
|
+
env.mock_auths(&[MockAuth {
|
|
240
|
+
address: sender,
|
|
241
|
+
invoke: &MockAuthInvoke {
|
|
242
|
+
contract: &oapp_client.address,
|
|
243
|
+
fn_name: "send",
|
|
244
|
+
args: (sender, &dst_eid, message, options, fee, refund_address).into_val(env),
|
|
245
|
+
sub_invokes: &sub_invokes,
|
|
246
|
+
},
|
|
247
|
+
}]);
|
|
248
|
+
} else {
|
|
249
|
+
let sub_invokes = [native_transfer];
|
|
250
|
+
env.mock_auths(&[MockAuth {
|
|
251
|
+
address: sender,
|
|
252
|
+
invoke: &MockAuthInvoke {
|
|
253
|
+
contract: &oapp_client.address,
|
|
254
|
+
fn_name: "send",
|
|
255
|
+
args: (sender, &dst_eid, message, options, fee, refund_address).into_val(env),
|
|
256
|
+
sub_invokes: &sub_invokes,
|
|
257
|
+
},
|
|
258
|
+
}]);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
#[test]
|
|
263
|
+
fn test_quote_with_peer_set() {
|
|
264
|
+
let TestSetup { env, owner, oapp_client, .. } = setup();
|
|
265
|
+
|
|
266
|
+
// Set peer for destination
|
|
267
|
+
let peer = BytesN::from_array(&env, &[1; 32]);
|
|
268
|
+
set_peer_with_auth(&env, &owner, &oapp_client, REMOTE_EID, &peer);
|
|
269
|
+
|
|
270
|
+
let message = Bytes::from_array(&env, &[1, 2, 3, 4, 5]);
|
|
271
|
+
let options = Bytes::from_array(&env, &[6, 7, 8]);
|
|
272
|
+
|
|
273
|
+
// Test quote without ZRO
|
|
274
|
+
let fee = oapp_client.quote(&REMOTE_EID, &message, &options, &false);
|
|
275
|
+
assert_eq!(fee.native_fee, 1000);
|
|
276
|
+
assert_eq!(fee.zro_fee, 0);
|
|
277
|
+
|
|
278
|
+
// Test quote with ZRO
|
|
279
|
+
let fee_with_zro = oapp_client.quote(&REMOTE_EID, &message, &options, &true);
|
|
280
|
+
assert_eq!(fee_with_zro.native_fee, 1000);
|
|
281
|
+
assert_eq!(fee_with_zro.zro_fee, 500);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
#[test]
|
|
285
|
+
fn test_quote_without_peer_panics() {
|
|
286
|
+
let TestSetup { env, oapp_client, .. } = setup();
|
|
287
|
+
|
|
288
|
+
let message = Bytes::from_array(&env, &[1, 2, 3]);
|
|
289
|
+
let options = Bytes::from_array(&env, &[]);
|
|
290
|
+
|
|
291
|
+
// This should panic because no peer is set for UNSET_EID
|
|
292
|
+
let result = oapp_client.try_quote(&UNSET_EID, &message, &options, &false);
|
|
293
|
+
assert_eq!(result.err().unwrap().ok().unwrap(), OAppError::NoPeer.into());
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
#[test]
|
|
297
|
+
fn test_lz_send_native_only() {
|
|
298
|
+
let TestSetup {
|
|
299
|
+
env,
|
|
300
|
+
oapp_client,
|
|
301
|
+
endpoint,
|
|
302
|
+
native_token,
|
|
303
|
+
zro_token,
|
|
304
|
+
native_token_client,
|
|
305
|
+
native_token_admin_client,
|
|
306
|
+
token_admin,
|
|
307
|
+
owner,
|
|
308
|
+
..
|
|
309
|
+
} = setup();
|
|
310
|
+
|
|
311
|
+
// Setup peer
|
|
312
|
+
let peer = BytesN::from_array(&env, &[2; 32]);
|
|
313
|
+
set_peer_with_auth(&env, &owner, &oapp_client, REMOTE_EID, &peer);
|
|
314
|
+
|
|
315
|
+
let sender = Address::generate(&env);
|
|
316
|
+
mint_to(&env, &token_admin, &native_token, &native_token_admin_client, &sender, 1000i128);
|
|
317
|
+
|
|
318
|
+
let message = Bytes::from_array(&env, &[1, 2, 3]);
|
|
319
|
+
let options = Bytes::from_array(&env, &[]);
|
|
320
|
+
let refund_address = Address::generate(&env);
|
|
321
|
+
let fee = MessagingFee { native_fee: 1000, zro_fee: 0 };
|
|
322
|
+
|
|
323
|
+
mock_send_auth(
|
|
324
|
+
&env,
|
|
325
|
+
&sender,
|
|
326
|
+
&oapp_client,
|
|
327
|
+
REMOTE_EID,
|
|
328
|
+
&message,
|
|
329
|
+
&options,
|
|
330
|
+
&fee,
|
|
331
|
+
&refund_address,
|
|
332
|
+
&native_token,
|
|
333
|
+
&endpoint,
|
|
334
|
+
&zro_token,
|
|
335
|
+
);
|
|
336
|
+
let receipt = oapp_client.send(&sender, &REMOTE_EID, &message, &options, &fee, &refund_address);
|
|
337
|
+
|
|
338
|
+
assert_eq!(receipt.nonce, 1);
|
|
339
|
+
assert_eq!(receipt.fee.native_fee, 1000);
|
|
340
|
+
assert_eq!(receipt.fee.zro_fee, 0);
|
|
341
|
+
|
|
342
|
+
// Assert the endpoint received the correct send params
|
|
343
|
+
let endpoint_client = MockEndpointClient::new(&env, &endpoint);
|
|
344
|
+
let (endpoint_sender, params, refund) = endpoint_client.last_send();
|
|
345
|
+
assert_eq!(endpoint_sender, oapp_client.address);
|
|
346
|
+
assert_eq!(params.dst_eid, REMOTE_EID);
|
|
347
|
+
assert_eq!(params.receiver, peer);
|
|
348
|
+
assert_eq!(params.message, message);
|
|
349
|
+
assert_eq!(params.options, options);
|
|
350
|
+
assert_eq!(params.pay_in_zro, false);
|
|
351
|
+
assert_eq!(refund, refund_address);
|
|
352
|
+
|
|
353
|
+
assert_eq!(native_token_client.balance(&sender), 0);
|
|
354
|
+
assert_eq!(native_token_client.balance(&endpoint), 1000);
|
|
355
|
+
assert_eq!(TokenClient::new(&env, &zro_token).balance(&endpoint), 0);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
#[test]
|
|
359
|
+
fn test_lz_send_with_zro() {
|
|
360
|
+
let TestSetup {
|
|
361
|
+
env,
|
|
362
|
+
oapp_client,
|
|
363
|
+
endpoint,
|
|
364
|
+
native_token,
|
|
365
|
+
zro_token,
|
|
366
|
+
native_token_client,
|
|
367
|
+
native_token_admin_client,
|
|
368
|
+
zro_token_admin_client,
|
|
369
|
+
token_admin,
|
|
370
|
+
owner,
|
|
371
|
+
..
|
|
372
|
+
} = setup();
|
|
373
|
+
|
|
374
|
+
// Setup peer
|
|
375
|
+
let peer = BytesN::from_array(&env, &[3; 32]);
|
|
376
|
+
set_peer_with_auth(&env, &owner, &oapp_client, REMOTE_EID, &peer);
|
|
377
|
+
|
|
378
|
+
let sender = Address::generate(&env);
|
|
379
|
+
let fee = MessagingFee { native_fee: 1000, zro_fee: 500 };
|
|
380
|
+
mint_to(&env, &token_admin, &native_token, &native_token_admin_client, &sender, fee.native_fee);
|
|
381
|
+
mint_to(&env, &token_admin, &zro_token, &zro_token_admin_client, &sender, fee.zro_fee);
|
|
382
|
+
|
|
383
|
+
let message = Bytes::from_array(&env, &[4, 5, 6]);
|
|
384
|
+
let options = Bytes::from_array(&env, &[7]);
|
|
385
|
+
let refund_address = Address::generate(&env);
|
|
386
|
+
|
|
387
|
+
mock_send_auth(
|
|
388
|
+
&env,
|
|
389
|
+
&sender,
|
|
390
|
+
&oapp_client,
|
|
391
|
+
REMOTE_EID,
|
|
392
|
+
&message,
|
|
393
|
+
&options,
|
|
394
|
+
&fee,
|
|
395
|
+
&refund_address,
|
|
396
|
+
&native_token,
|
|
397
|
+
&endpoint,
|
|
398
|
+
&zro_token,
|
|
399
|
+
);
|
|
400
|
+
let receipt = oapp_client.send(&sender, &REMOTE_EID, &message, &options, &fee, &refund_address);
|
|
401
|
+
|
|
402
|
+
assert_eq!(receipt.nonce, 1);
|
|
403
|
+
assert_eq!(receipt.fee.native_fee, 1000);
|
|
404
|
+
assert_eq!(receipt.fee.zro_fee, 500);
|
|
405
|
+
|
|
406
|
+
// Assert the endpoint received the correct send params
|
|
407
|
+
let endpoint_client = MockEndpointClient::new(&env, &endpoint);
|
|
408
|
+
let (endpoint_sender, params, refund) = endpoint_client.last_send();
|
|
409
|
+
assert_eq!(endpoint_sender, oapp_client.address);
|
|
410
|
+
assert_eq!(params.dst_eid, REMOTE_EID);
|
|
411
|
+
assert_eq!(params.receiver, peer);
|
|
412
|
+
assert_eq!(params.message, message);
|
|
413
|
+
assert_eq!(params.options, options);
|
|
414
|
+
assert_eq!(params.pay_in_zro, true);
|
|
415
|
+
assert_eq!(refund, refund_address);
|
|
416
|
+
|
|
417
|
+
assert_eq!(native_token_client.balance(&sender), 0);
|
|
418
|
+
assert_eq!(native_token_client.balance(&endpoint), 1000);
|
|
419
|
+
|
|
420
|
+
let zro_token_client = TokenClient::new(&env, &zro_token);
|
|
421
|
+
assert_eq!(zro_token_client.balance(&sender), 0);
|
|
422
|
+
assert_eq!(zro_token_client.balance(&endpoint), 500);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
#[test]
|
|
426
|
+
fn test_pay_native() {
|
|
427
|
+
let TestSetup { env, oapp_client, endpoint, native_token, native_token_admin_client, token_admin, .. } = setup();
|
|
428
|
+
|
|
429
|
+
let payer = Address::generate(&env);
|
|
430
|
+
let payment_amount = 2000i128;
|
|
431
|
+
|
|
432
|
+
// Fund the payer
|
|
433
|
+
mint_to(&env, &token_admin, &native_token, &native_token_admin_client, &payer, payment_amount);
|
|
434
|
+
|
|
435
|
+
// Make payment
|
|
436
|
+
env.mock_auths(&[MockAuth {
|
|
437
|
+
address: &payer,
|
|
438
|
+
invoke: &MockAuthInvoke {
|
|
439
|
+
contract: &oapp_client.address,
|
|
440
|
+
fn_name: "pay_native_fee",
|
|
441
|
+
args: (&payer, &payment_amount).into_val(&env),
|
|
442
|
+
sub_invokes: &[MockAuthInvoke {
|
|
443
|
+
contract: &native_token,
|
|
444
|
+
fn_name: "transfer",
|
|
445
|
+
args: (&payer, &endpoint, &payment_amount).into_val(&env),
|
|
446
|
+
sub_invokes: &[],
|
|
447
|
+
}],
|
|
448
|
+
},
|
|
449
|
+
}]);
|
|
450
|
+
oapp_client.pay_native_fee(&payer, &payment_amount);
|
|
451
|
+
|
|
452
|
+
// Verify balances
|
|
453
|
+
assert_eq!(native_token_admin_client.balance(&payer), 0);
|
|
454
|
+
assert_eq!(native_token_admin_client.balance(&endpoint), payment_amount);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
#[test]
|
|
458
|
+
#[should_panic(expected = "balance is not sufficient to spend")]
|
|
459
|
+
fn test_pay_native_insufficient_balance() {
|
|
460
|
+
let TestSetup { env, oapp_client, endpoint, native_token, native_token_admin_client, token_admin, .. } = setup();
|
|
461
|
+
|
|
462
|
+
let balance = 500i128;
|
|
463
|
+
let payment_amount = 1000i128;
|
|
464
|
+
|
|
465
|
+
let payer = Address::generate(&env);
|
|
466
|
+
|
|
467
|
+
// Fund with less than required
|
|
468
|
+
mint_to(&env, &token_admin, &native_token, &native_token_admin_client, &payer, balance);
|
|
469
|
+
|
|
470
|
+
// This should panic due to insufficient balance
|
|
471
|
+
env.mock_auths(&[MockAuth {
|
|
472
|
+
address: &payer,
|
|
473
|
+
invoke: &MockAuthInvoke {
|
|
474
|
+
contract: &oapp_client.address,
|
|
475
|
+
fn_name: "pay_native_fee",
|
|
476
|
+
args: (&payer, &payment_amount).into_val(&env),
|
|
477
|
+
sub_invokes: &[MockAuthInvoke {
|
|
478
|
+
contract: &native_token,
|
|
479
|
+
fn_name: "transfer",
|
|
480
|
+
args: (&payer, &endpoint, &payment_amount).into_val(&env),
|
|
481
|
+
sub_invokes: &[],
|
|
482
|
+
}],
|
|
483
|
+
},
|
|
484
|
+
}]);
|
|
485
|
+
oapp_client.pay_native_fee(&payer, &payment_amount);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
#[test]
|
|
489
|
+
fn test_pay_zro_success() {
|
|
490
|
+
let TestSetup { env, oapp_client, endpoint, zro_token, zro_token_admin_client, token_admin, .. } = setup();
|
|
491
|
+
|
|
492
|
+
let payer = Address::generate(&env);
|
|
493
|
+
let payment_amount = 500i128;
|
|
494
|
+
mint_to(&env, &token_admin, &zro_token, &zro_token_admin_client, &payer, payment_amount);
|
|
495
|
+
|
|
496
|
+
env.mock_auths(&[MockAuth {
|
|
497
|
+
address: &payer,
|
|
498
|
+
invoke: &MockAuthInvoke {
|
|
499
|
+
contract: &oapp_client.address,
|
|
500
|
+
fn_name: "pay_zro_fee",
|
|
501
|
+
args: (&payer, &payment_amount).into_val(&env),
|
|
502
|
+
sub_invokes: &[MockAuthInvoke {
|
|
503
|
+
contract: &zro_token,
|
|
504
|
+
fn_name: "transfer",
|
|
505
|
+
args: (&payer, &endpoint, &payment_amount).into_val(&env),
|
|
506
|
+
sub_invokes: &[],
|
|
507
|
+
}],
|
|
508
|
+
},
|
|
509
|
+
}]);
|
|
510
|
+
oapp_client.pay_zro_fee(&payer, &payment_amount);
|
|
511
|
+
|
|
512
|
+
assert_eq!(zro_token_admin_client.balance(&payer), 0);
|
|
513
|
+
assert_eq!(zro_token_admin_client.balance(&endpoint), payment_amount);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
#[test]
|
|
517
|
+
#[should_panic(expected = "balance is not sufficient to spend")]
|
|
518
|
+
fn test_pay_zro_insufficient_balance() {
|
|
519
|
+
let TestSetup { env, oapp_client, endpoint, zro_token, zro_token_admin_client, token_admin, .. } = setup();
|
|
520
|
+
|
|
521
|
+
let payer = Address::generate(&env);
|
|
522
|
+
let balance = 100i128;
|
|
523
|
+
let payment_amount = 500i128;
|
|
524
|
+
|
|
525
|
+
// Fund with less than required
|
|
526
|
+
mint_to(&env, &token_admin, &zro_token, &zro_token_admin_client, &payer, balance);
|
|
527
|
+
|
|
528
|
+
env.mock_auths(&[MockAuth {
|
|
529
|
+
address: &payer,
|
|
530
|
+
invoke: &MockAuthInvoke {
|
|
531
|
+
contract: &oapp_client.address,
|
|
532
|
+
fn_name: "pay_zro_fee",
|
|
533
|
+
args: (&payer, &payment_amount).into_val(&env),
|
|
534
|
+
sub_invokes: &[MockAuthInvoke {
|
|
535
|
+
contract: &zro_token,
|
|
536
|
+
fn_name: "transfer",
|
|
537
|
+
args: (&payer, &endpoint, &payment_amount).into_val(&env),
|
|
538
|
+
sub_invokes: &[],
|
|
539
|
+
}],
|
|
540
|
+
},
|
|
541
|
+
}]);
|
|
542
|
+
oapp_client.pay_zro_fee(&payer, &payment_amount);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
#[test]
|
|
546
|
+
fn test_pay_zro_unavailable_returns_error() {
|
|
547
|
+
let TestSetup { env, oapp_client, endpoint, zro_token, .. } = setup();
|
|
548
|
+
|
|
549
|
+
let endpoint_client = MockEndpointClient::new(&env, &endpoint);
|
|
550
|
+
endpoint_client.set_zro(&None);
|
|
551
|
+
|
|
552
|
+
let payer = Address::generate(&env);
|
|
553
|
+
let payment_amount = 500i128;
|
|
554
|
+
|
|
555
|
+
env.mock_auths(&[MockAuth {
|
|
556
|
+
address: &payer,
|
|
557
|
+
invoke: &MockAuthInvoke {
|
|
558
|
+
contract: &oapp_client.address,
|
|
559
|
+
fn_name: "pay_zro_fee",
|
|
560
|
+
args: (&payer, &payment_amount).into_val(&env),
|
|
561
|
+
sub_invokes: &[],
|
|
562
|
+
},
|
|
563
|
+
}]);
|
|
564
|
+
let result = oapp_client.try_pay_zro_fee(&payer, &payment_amount);
|
|
565
|
+
assert_eq!(result.err().unwrap().ok().unwrap(), OAppError::ZroTokenUnavailable.into());
|
|
566
|
+
|
|
567
|
+
// Ensure we did not transfer any ZRO accidentally
|
|
568
|
+
let token_client = TokenClient::new(&env, &zro_token);
|
|
569
|
+
assert_eq!(token_client.balance(&payer), 0);
|
|
570
|
+
}
|