@layerzerolabs/protocol-stellar-v2 0.2.64 → 0.2.66
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 +230 -307
- package/.turbo/turbo-lint.log +175 -175
- package/.turbo/turbo-test.log +2047 -1975
- package/Cargo.lock +0 -16
- package/Cargo.toml +0 -1
- package/contracts/oapps/oft/integration-tests/extensions/test_oft_fee.rs +22 -0
- package/contracts/oapps/oft/integration-tests/extensions/test_pausable.rs +9 -2
- package/contracts/oapps/oft/integration-tests/extensions/test_rate_limiter.rs +27 -2
- package/contracts/oapps/oft/integration-tests/setup.rs +22 -18
- package/contracts/oapps/oft/integration-tests/utils.rs +81 -34
- package/contracts/oapps/oft/src/extensions/oft_fee.rs +13 -0
- package/contracts/oapps/oft/src/oft.rs +10 -2
- package/package.json +5 -5
- package/sdk/.turbo/turbo-test.log +284 -291
- package/sdk/dist/generated/oft.d.ts +3 -3
- package/sdk/dist/generated/oft.js +3 -3
- package/sdk/node_modules/.bin/vitest +2 -2
- package/sdk/package.json +2 -2
- package/contracts/oapps/console-oft/Cargo.toml +0 -30
- package/contracts/oapps/console-oft/integration-tests/extensions/mod.rs +0 -5
- package/contracts/oapps/console-oft/integration-tests/extensions/test_combined.rs +0 -90
- package/contracts/oapps/console-oft/integration-tests/extensions/test_oft_fee.rs +0 -186
- package/contracts/oapps/console-oft/integration-tests/extensions/test_ownership.rs +0 -161
- package/contracts/oapps/console-oft/integration-tests/extensions/test_pausable.rs +0 -154
- package/contracts/oapps/console-oft/integration-tests/extensions/test_rate_limiter.rs +0 -479
- package/contracts/oapps/console-oft/integration-tests/mod.rs +0 -3
- package/contracts/oapps/console-oft/integration-tests/setup.rs +0 -303
- package/contracts/oapps/console-oft/integration-tests/utils.rs +0 -685
- package/contracts/oapps/console-oft/src/errors.rs +0 -7
- package/contracts/oapps/console-oft/src/extensions/mod.rs +0 -3
- package/contracts/oapps/console-oft/src/extensions/oft_fee.rs +0 -239
- package/contracts/oapps/console-oft/src/extensions/pausable.rs +0 -185
- package/contracts/oapps/console-oft/src/extensions/rate_limiter.rs +0 -478
- package/contracts/oapps/console-oft/src/interfaces/mintable.rs +0 -14
- package/contracts/oapps/console-oft/src/interfaces/mod.rs +0 -3
- package/contracts/oapps/console-oft/src/lib.rs +0 -26
- package/contracts/oapps/console-oft/src/oft.rs +0 -208
- package/contracts/oapps/console-oft/src/oft_access_control.rs +0 -93
- package/contracts/oapps/console-oft/src/oft_types/lock_unlock.rs +0 -50
- package/contracts/oapps/console-oft/src/oft_types/mint_burn.rs +0 -50
- package/contracts/oapps/console-oft/src/oft_types/mod.rs +0 -24
- package/contracts/oapps/console-oft/src/tests/extensions/mod.rs +0 -3
- package/contracts/oapps/console-oft/src/tests/extensions/oft_fee.rs +0 -255
- package/contracts/oapps/console-oft/src/tests/extensions/pausable.rs +0 -212
- package/contracts/oapps/console-oft/src/tests/extensions/rate_limiter.rs +0 -992
- package/contracts/oapps/console-oft/src/tests/mod.rs +0 -2
- package/contracts/oapps/console-oft/src/tests/oft_types/lock_unlock.rs +0 -185
- package/contracts/oapps/console-oft/src/tests/oft_types/mod.rs +0 -1
package/Cargo.lock
CHANGED
|
@@ -292,22 +292,6 @@ dependencies = [
|
|
|
292
292
|
"windows-sys",
|
|
293
293
|
]
|
|
294
294
|
|
|
295
|
-
[[package]]
|
|
296
|
-
name = "console-oft"
|
|
297
|
-
version = "0.0.1"
|
|
298
|
-
dependencies = [
|
|
299
|
-
"cfg-if",
|
|
300
|
-
"common-macros",
|
|
301
|
-
"endpoint-v2",
|
|
302
|
-
"message-lib-common",
|
|
303
|
-
"oapp",
|
|
304
|
-
"oapp-macros",
|
|
305
|
-
"oft-core",
|
|
306
|
-
"simple-message-lib",
|
|
307
|
-
"soroban-sdk",
|
|
308
|
-
"utils",
|
|
309
|
-
]
|
|
310
|
-
|
|
311
295
|
[[package]]
|
|
312
296
|
name = "const-oid"
|
|
313
297
|
version = "0.9.6"
|
package/Cargo.toml
CHANGED
|
@@ -50,7 +50,6 @@ blocked-message-lib = { path = "contracts/message-libs/blocked-message-lib" }
|
|
|
50
50
|
oapp = { path = "contracts/oapps/oapp" }
|
|
51
51
|
oapp-macros = { path = "contracts/oapps/oapp-macros" }
|
|
52
52
|
oft = { path = "contracts/oapps/oft" }
|
|
53
|
-
console-oft = { path = "contracts/oapps/console-oft" }
|
|
54
53
|
oft-core = { path = "contracts/oapps/oft-core" }
|
|
55
54
|
price-feed = { path = "contracts/workers/price-feed" }
|
|
56
55
|
simple-message-lib = { path = "contracts/message-libs/simple-message-lib" }
|
|
@@ -29,6 +29,14 @@ fn test_cross_chain_with_zero_fee() {
|
|
|
29
29
|
mint_oft_token_to(&env, &chain_a, &sender, 10_000_000);
|
|
30
30
|
mint_to(&env, &chain_a.owner, &chain_a.native_token, &sender, 10_000_000_000);
|
|
31
31
|
|
|
32
|
+
// Default fee state on both OFTs
|
|
33
|
+
assert_eq!(chain_a.oft.default_fee_bps(), None);
|
|
34
|
+
assert_eq!(chain_a.oft.fee_deposit_address(), None);
|
|
35
|
+
assert_eq!(chain_a.oft.effective_fee_bps(&chain_b.eid), 0);
|
|
36
|
+
assert_eq!(chain_b.oft.default_fee_bps(), None);
|
|
37
|
+
assert_eq!(chain_b.oft.fee_deposit_address(), None);
|
|
38
|
+
assert_eq!(chain_b.oft.effective_fee_bps(&chain_a.eid), 0);
|
|
39
|
+
|
|
32
40
|
let to = address_to_peer_bytes32(&receiver);
|
|
33
41
|
let send_param = create_send_param(&env, chain_b.eid, 1_000_000, 0, &to);
|
|
34
42
|
let (_, _, oft_receipt) = quote_oft(&chain_a, &sender, &send_param);
|
|
@@ -67,6 +75,12 @@ fn test_cross_chain_with_fee() {
|
|
|
67
75
|
// Enable 1% fee (100 bps)
|
|
68
76
|
set_fee_deposit_address(&env, &chain_a, &chain_a.fee_collector);
|
|
69
77
|
set_default_fee_bps(&env, &chain_a, 100);
|
|
78
|
+
assert_eq!(chain_a.oft.default_fee_bps(), Some(100));
|
|
79
|
+
assert_eq!(chain_a.oft.fee_deposit_address(), Some(chain_a.fee_collector.clone()));
|
|
80
|
+
assert_eq!(chain_a.oft.effective_fee_bps(&chain_b.eid), 100);
|
|
81
|
+
assert_eq!(chain_b.oft.default_fee_bps(), None);
|
|
82
|
+
assert_eq!(chain_b.oft.fee_deposit_address(), None);
|
|
83
|
+
assert_eq!(chain_b.oft.effective_fee_bps(&chain_a.eid), 0);
|
|
70
84
|
|
|
71
85
|
let to = address_to_peer_bytes32(&receiver);
|
|
72
86
|
let amount_ld = 1_000_000i128;
|
|
@@ -119,6 +133,14 @@ fn test_cross_chain_with_destination_specific_fee() {
|
|
|
119
133
|
set_fee_deposit_address(&env, &chain_a, &chain_a.fee_collector);
|
|
120
134
|
set_default_fee_bps(&env, &chain_a, 100); // 1%
|
|
121
135
|
set_fee_bps(&env, &chain_a, chain_b.eid, 200); // 2% for chain_b
|
|
136
|
+
assert_eq!(chain_a.oft.default_fee_bps(), Some(100));
|
|
137
|
+
assert_eq!(chain_a.oft.fee_bps(&chain_b.eid), Some(200));
|
|
138
|
+
assert_eq!(chain_a.oft.fee_deposit_address(), Some(chain_a.fee_collector.clone()));
|
|
139
|
+
assert_eq!(chain_a.oft.effective_fee_bps(&chain_b.eid), 200);
|
|
140
|
+
assert_eq!(chain_b.oft.default_fee_bps(), None);
|
|
141
|
+
assert_eq!(chain_b.oft.fee_bps(&chain_a.eid), None);
|
|
142
|
+
assert_eq!(chain_b.oft.fee_deposit_address(), None);
|
|
143
|
+
assert_eq!(chain_b.oft.effective_fee_bps(&chain_a.eid), 0);
|
|
122
144
|
|
|
123
145
|
let to = address_to_peer_bytes32(&receiver);
|
|
124
146
|
let amount_ld = 1_000_000i128;
|
|
@@ -26,8 +26,9 @@ fn test_send_succeeds_when_unpaused() {
|
|
|
26
26
|
mint_oft_token_to(&env, &chain_a, &sender, 10_000_000);
|
|
27
27
|
mint_to(&env, &chain_a.owner, &chain_a.native_token, &sender, 10_000_000_000);
|
|
28
28
|
|
|
29
|
-
// Default state should be unpaused
|
|
29
|
+
// Default state should be unpaused on both OFTs
|
|
30
30
|
assert!(!is_paused(&chain_a));
|
|
31
|
+
assert!(!is_paused(&chain_b));
|
|
31
32
|
|
|
32
33
|
let to = address_to_peer_bytes32(&receiver);
|
|
33
34
|
let send_param = create_send_param(&env, chain_b.eid, 1_000_000, 0, &to);
|
|
@@ -74,6 +75,7 @@ fn test_send_fails_when_paused() {
|
|
|
74
75
|
// Pause the OFT
|
|
75
76
|
set_paused(&env, &chain_a, true);
|
|
76
77
|
assert!(is_paused(&chain_a));
|
|
78
|
+
assert!(!is_paused(&chain_b));
|
|
77
79
|
|
|
78
80
|
// Send should fail when paused
|
|
79
81
|
let success = try_send(&env, &chain_a, &sender, &send_param, &fee, &sender, &oft_receipt);
|
|
@@ -108,6 +110,7 @@ fn test_receive_fails_when_paused() {
|
|
|
108
110
|
// Pause chain_b's OFT before receiving
|
|
109
111
|
set_paused(&env, &chain_b, true);
|
|
110
112
|
assert!(is_paused(&chain_b));
|
|
113
|
+
assert!(!is_paused(&chain_a));
|
|
111
114
|
|
|
112
115
|
// Receive should fail on paused destination
|
|
113
116
|
let success = try_lz_receive(&env, &chain_b, &executor, &packet, &receiver, 0);
|
|
@@ -128,11 +131,15 @@ fn test_cross_chain_succeeds_after_unpause() {
|
|
|
128
131
|
mint_oft_token_to(&env, &chain_a, &sender, 10_000_000);
|
|
129
132
|
mint_to(&env, &chain_a.owner, &chain_a.native_token, &sender, 10_000_000_000);
|
|
130
133
|
|
|
131
|
-
// Pause and then unpause
|
|
134
|
+
// Pause and then unpause on chain_a; chain_b remains unpaused throughout
|
|
135
|
+
assert!(!is_paused(&chain_a));
|
|
136
|
+
assert!(!is_paused(&chain_b));
|
|
132
137
|
set_paused(&env, &chain_a, true);
|
|
133
138
|
assert!(is_paused(&chain_a));
|
|
139
|
+
assert!(!is_paused(&chain_b));
|
|
134
140
|
set_paused(&env, &chain_a, false);
|
|
135
141
|
assert!(!is_paused(&chain_a));
|
|
142
|
+
assert!(!is_paused(&chain_b));
|
|
136
143
|
|
|
137
144
|
// Send should work after unpause
|
|
138
145
|
let to = address_to_peer_bytes32(&receiver);
|
|
@@ -31,6 +31,9 @@ fn test_send_without_rate_limit() {
|
|
|
31
31
|
// Default capacity should be i128::MAX (unlimited)
|
|
32
32
|
let capacity = rate_limit_capacity(&chain_a, &Direction::Outbound, chain_b.eid);
|
|
33
33
|
assert_eq!(capacity, i128::MAX);
|
|
34
|
+
assert_eq!(rate_limit_in_flight(&chain_a, &Direction::Outbound, chain_b.eid), 0);
|
|
35
|
+
assert_eq!(rate_limit_capacity(&chain_b, &Direction::Outbound, chain_a.eid), i128::MAX);
|
|
36
|
+
assert_eq!(rate_limit_in_flight(&chain_b, &Direction::Outbound, chain_a.eid), 0);
|
|
34
37
|
|
|
35
38
|
let to = address_to_peer_bytes32(&receiver);
|
|
36
39
|
let send_param = create_send_param(&env, chain_b.eid, 50_000_000, 0, &to);
|
|
@@ -66,8 +69,9 @@ fn test_send_within_rate_limit() {
|
|
|
66
69
|
// Set rate limit: 10M per 3600 seconds (1 hour)
|
|
67
70
|
set_rate_limit(&env, &chain_a, &Direction::Outbound, chain_b.eid, 10_000_000, 3600);
|
|
68
71
|
|
|
69
|
-
|
|
70
|
-
assert_eq!(
|
|
72
|
+
assert_eq!(rate_limit_capacity(&chain_a, &Direction::Outbound, chain_b.eid), 10_000_000);
|
|
73
|
+
assert_eq!(rate_limit_capacity(&chain_b, &Direction::Outbound, chain_a.eid), i128::MAX);
|
|
74
|
+
assert_eq!(rate_limit_in_flight(&chain_b, &Direction::Outbound, chain_a.eid), 0);
|
|
71
75
|
|
|
72
76
|
// Send 5M (within limit)
|
|
73
77
|
let to = address_to_peer_bytes32(&receiver);
|
|
@@ -113,6 +117,9 @@ fn test_send_exceeds_rate_limit() {
|
|
|
113
117
|
|
|
114
118
|
// Set rate limit: 1M per 3600 seconds
|
|
115
119
|
set_rate_limit(&env, &chain_a, &Direction::Outbound, chain_b.eid, 1_000_000, 3600);
|
|
120
|
+
assert_eq!(rate_limit_capacity(&chain_a, &Direction::Outbound, chain_b.eid), 1_000_000);
|
|
121
|
+
assert_eq!(rate_limit_capacity(&chain_b, &Direction::Outbound, chain_a.eid), i128::MAX);
|
|
122
|
+
assert_eq!(rate_limit_in_flight(&chain_b, &Direction::Outbound, chain_a.eid), 0);
|
|
116
123
|
|
|
117
124
|
// Try to send 5M (exceeds limit)
|
|
118
125
|
let to = address_to_peer_bytes32(&receiver);
|
|
@@ -122,6 +129,8 @@ fn test_send_exceeds_rate_limit() {
|
|
|
122
129
|
|
|
123
130
|
let success = try_send(&env, &chain_a, &sender, &send_param, &fee, &sender, &oft_receipt);
|
|
124
131
|
assert!(!success);
|
|
132
|
+
assert_eq!(rate_limit_in_flight(&chain_a, &Direction::Outbound, chain_b.eid), 0);
|
|
133
|
+
assert_eq!(rate_limit_in_flight(&chain_b, &Direction::Outbound, chain_a.eid), 0);
|
|
125
134
|
}
|
|
126
135
|
|
|
127
136
|
/// Test rate limit decay over time
|
|
@@ -140,6 +149,9 @@ fn test_rate_limit_decay() {
|
|
|
140
149
|
|
|
141
150
|
// Set rate limit: 10M per 1000 seconds
|
|
142
151
|
set_rate_limit(&env, &chain_a, &Direction::Outbound, chain_b.eid, 10_000_000, 1000);
|
|
152
|
+
assert_eq!(rate_limit_capacity(&chain_a, &Direction::Outbound, chain_b.eid), 10_000_000);
|
|
153
|
+
assert_eq!(rate_limit_capacity(&chain_b, &Direction::Outbound, chain_a.eid), i128::MAX);
|
|
154
|
+
assert_eq!(rate_limit_in_flight(&chain_b, &Direction::Outbound, chain_a.eid), 0);
|
|
143
155
|
|
|
144
156
|
let to = address_to_peer_bytes32(&receiver);
|
|
145
157
|
|
|
@@ -176,6 +188,9 @@ fn test_rate_limit_decay() {
|
|
|
176
188
|
validate_packet(&env, &chain_b, &packet_event2);
|
|
177
189
|
let packet2 = decode_packet(&env, &packet_event2.0);
|
|
178
190
|
lz_receive(&env, &chain_b, &executor, &packet2, &receiver, 0);
|
|
191
|
+
assert!(rate_limit_capacity(&chain_a, &Direction::Outbound, chain_b.eid) < 10_000_000);
|
|
192
|
+
assert_eq!(rate_limit_capacity(&chain_b, &Direction::Outbound, chain_a.eid), i128::MAX);
|
|
193
|
+
assert_eq!(rate_limit_in_flight(&chain_b, &Direction::Outbound, chain_a.eid), 0);
|
|
179
194
|
}
|
|
180
195
|
|
|
181
196
|
/// Test gross mode: round-trip shows gross mode doesn't release outbound capacity
|
|
@@ -199,6 +214,9 @@ fn test_gross_mode_does_not_release() {
|
|
|
199
214
|
|
|
200
215
|
// Set Gross mode rate limit on chain_a outbound: 10M per 3600 seconds
|
|
201
216
|
set_rate_limit_with_mode(&env, &chain_a, &Direction::Outbound, chain_b.eid, 10_000_000, 3600, Mode::Gross);
|
|
217
|
+
assert_eq!(rate_limit_capacity(&chain_a, &Direction::Outbound, chain_b.eid), 10_000_000);
|
|
218
|
+
assert_eq!(rate_limit_capacity(&chain_b, &Direction::Outbound, chain_a.eid), i128::MAX);
|
|
219
|
+
assert_eq!(rate_limit_in_flight(&chain_b, &Direction::Outbound, chain_a.eid), 0);
|
|
202
220
|
|
|
203
221
|
// Step 1: Send 8M from chain_a to chain_b
|
|
204
222
|
let to_b = address_to_peer_bytes32(&receiver_b);
|
|
@@ -242,6 +260,8 @@ fn test_gross_mode_does_not_release() {
|
|
|
242
260
|
// Should only have ~2M capacity left, NOT 8M (if it were Net mode)
|
|
243
261
|
let capacity_after_return = rate_limit_capacity(&chain_a, &Direction::Outbound, chain_b.eid);
|
|
244
262
|
assert!(capacity_after_return < 3_000_000, "Gross mode: capacity should remain low");
|
|
263
|
+
assert_eq!(rate_limit_capacity(&chain_b, &Direction::Outbound, chain_a.eid), i128::MAX);
|
|
264
|
+
assert_eq!(rate_limit_in_flight(&chain_b, &Direction::Outbound, chain_a.eid), 0);
|
|
245
265
|
}
|
|
246
266
|
|
|
247
267
|
/// Test net mode (default): round-trip shows net mode releases outbound capacity
|
|
@@ -265,6 +285,9 @@ fn test_net_mode_does_release() {
|
|
|
265
285
|
|
|
266
286
|
// Set Net mode rate limit on chain_a outbound: 10M per 3600 seconds
|
|
267
287
|
set_rate_limit_with_mode(&env, &chain_a, &Direction::Outbound, chain_b.eid, 10_000_000, 3600, Mode::Net);
|
|
288
|
+
assert_eq!(rate_limit_capacity(&chain_a, &Direction::Outbound, chain_b.eid), 10_000_000);
|
|
289
|
+
assert_eq!(rate_limit_capacity(&chain_b, &Direction::Outbound, chain_a.eid), i128::MAX);
|
|
290
|
+
assert_eq!(rate_limit_in_flight(&chain_b, &Direction::Outbound, chain_a.eid), 0);
|
|
268
291
|
|
|
269
292
|
// Step 1: Send 8M from chain_a to chain_b
|
|
270
293
|
let to_b = address_to_peer_bytes32(&receiver_b);
|
|
@@ -308,4 +331,6 @@ fn test_net_mode_does_release() {
|
|
|
308
331
|
// Should have much more capacity now (8M sent - 6M received back = ~2M net)
|
|
309
332
|
let capacity_after_return = rate_limit_capacity(&chain_a, &Direction::Outbound, chain_b.eid);
|
|
310
333
|
assert!(capacity_after_return > 7_000_000, "Net mode: capacity should increase after receiving");
|
|
334
|
+
assert_eq!(rate_limit_capacity(&chain_b, &Direction::Outbound, chain_a.eid), i128::MAX);
|
|
335
|
+
assert_eq!(rate_limit_in_flight(&chain_b, &Direction::Outbound, chain_a.eid), 0);
|
|
311
336
|
}
|
|
@@ -89,7 +89,7 @@ pub struct TestSetup<'a> {
|
|
|
89
89
|
pub chain_b: ChainSetup<'a>,
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
fn setup_chain<'a>(env: &Env) -> ChainSetup<'a> {
|
|
92
|
+
fn setup_chain<'a>(env: &Env, use_mint_burn: bool) -> ChainSetup<'a> {
|
|
93
93
|
let owner = Address::generate(env);
|
|
94
94
|
|
|
95
95
|
// Create native token FIRST - this must match the endpoint's NATIVE_TOKEN constant
|
|
@@ -107,26 +107,31 @@ fn setup_chain<'a>(env: &Env) -> ChainSetup<'a> {
|
|
|
107
107
|
let oft_sac = env.register_stellar_asset_contract_v2(owner.clone());
|
|
108
108
|
let oft_token = oft_sac.address();
|
|
109
109
|
let sac_wrapper_address = env.register(MockSacWrapper, (&oft_token,));
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
110
|
+
|
|
111
|
+
let mode = if use_mint_burn {
|
|
112
|
+
env.mock_auths(&[MockAuth {
|
|
113
|
+
address: &owner,
|
|
114
|
+
invoke: &MockAuthInvoke {
|
|
115
|
+
contract: &oft_token,
|
|
116
|
+
fn_name: "set_admin",
|
|
117
|
+
args: (&sac_wrapper_address,).into_val(env),
|
|
118
|
+
sub_invokes: &[],
|
|
119
|
+
},
|
|
120
|
+
}]);
|
|
121
|
+
StellarAssetClient::new(env, &oft_token).set_admin(&sac_wrapper_address);
|
|
122
|
+
OftType::MintBurn(sac_wrapper_address.clone())
|
|
123
|
+
} else {
|
|
124
|
+
OftType::LockUnlock
|
|
125
|
+
};
|
|
120
126
|
|
|
121
127
|
let eid: u32 = 30400; // Test EID
|
|
122
128
|
let endpoint_address = env.register(EndpointV2, (&owner, eid, &native_token));
|
|
123
129
|
let fee_recipient = Address::generate(env);
|
|
124
130
|
let sml_address = env.register(SimpleMessageLib, (&owner, &endpoint_address, &fee_recipient));
|
|
125
131
|
let delegate: Option<Address> = Some(owner.clone());
|
|
126
|
-
let shared_decimals: u32 = 6;
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
let oft_address = env.register(OFT, (&oft_token, &shared_decimals, &mode, &endpoint_address, delegate.as_ref().unwrap()));
|
|
132
|
+
let shared_decimals: u32 = 6;
|
|
133
|
+
let oft_address =
|
|
134
|
+
env.register(OFT, (&oft_token, &shared_decimals, &mode, &endpoint_address, delegate.as_ref().unwrap()));
|
|
130
135
|
|
|
131
136
|
let endpoint = EndpointV2Client::new(env, &endpoint_address);
|
|
132
137
|
let sml = SimpleMessageLibClient::new(env, &sml_address);
|
|
@@ -161,8 +166,8 @@ fn setup_chain<'a>(env: &Env) -> ChainSetup<'a> {
|
|
|
161
166
|
|
|
162
167
|
pub fn setup<'a>() -> TestSetup<'a> {
|
|
163
168
|
let env = Env::default();
|
|
164
|
-
let chain_a = setup_chain(&env);
|
|
165
|
-
let chain_b = setup_chain(&env);
|
|
169
|
+
let chain_a = setup_chain(&env, false);
|
|
170
|
+
let chain_b = setup_chain(&env, true);
|
|
166
171
|
|
|
167
172
|
let chain_a_oft_token_decimals = TokenClient::new(&env, &chain_a.oft_token).decimals();
|
|
168
173
|
let chain_b_oft_token_decimals = TokenClient::new(&env, &chain_b.oft_token).decimals();
|
|
@@ -214,7 +219,6 @@ pub fn wire_oft(env: &Env, chains: &[&ChainSetup<'_>]) {
|
|
|
214
219
|
}
|
|
215
220
|
|
|
216
221
|
pub fn set_peer(env: &Env, owner: &Address, oft: &OFTClient<'_>, dst_eid: u32, peer: &BytesN<32>) {
|
|
217
|
-
|
|
218
222
|
let peer_option = Some(peer.clone());
|
|
219
223
|
env.mock_auths(&[MockAuth {
|
|
220
224
|
address: owner,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
//! Utility functions for OFT-STD integration tests.
|
|
2
2
|
|
|
3
|
-
use crate::extensions::rate_limiter::{Direction, Mode, RateLimitConfig, RATE_LIMITER_MANAGER_ROLE};
|
|
4
3
|
use crate::extensions::oft_fee::FEE_CONFIG_MANAGER_ROLE;
|
|
5
4
|
use crate::extensions::pausable::{PAUSER_ROLE, UNPAUSER_ROLE};
|
|
5
|
+
use crate::extensions::rate_limiter::{Direction, Mode, RateLimitConfig, RATE_LIMITER_MANAGER_ROLE};
|
|
6
6
|
use crate::integration_tests::setup::{decode_packet, ChainSetup};
|
|
7
|
+
use crate::oft_types::OftType;
|
|
7
8
|
use crate::MintableClient;
|
|
8
9
|
use endpoint_v2::{MessagingFee, Origin, OutboundPacket};
|
|
9
10
|
use message_lib_common::packet_codec_v1;
|
|
@@ -78,6 +79,21 @@ pub fn send(
|
|
|
78
79
|
refund_address: &Address,
|
|
79
80
|
oft_receipt: &OFTReceipt,
|
|
80
81
|
) {
|
|
82
|
+
let token_sub_invoke = match chain.oft.oft_type() {
|
|
83
|
+
OftType::LockUnlock => MockAuthInvoke {
|
|
84
|
+
contract: &chain.oft_token,
|
|
85
|
+
fn_name: "transfer",
|
|
86
|
+
args: (sender, &chain.oft.address, &oft_receipt.amount_received_ld).into_val(env),
|
|
87
|
+
sub_invokes: &[],
|
|
88
|
+
},
|
|
89
|
+
OftType::MintBurn(_) => MockAuthInvoke {
|
|
90
|
+
contract: &chain.oft_token,
|
|
91
|
+
fn_name: "burn",
|
|
92
|
+
args: (sender, &oft_receipt.amount_received_ld).into_val(env),
|
|
93
|
+
sub_invokes: &[],
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
|
|
81
97
|
env.mock_auths(&[MockAuth {
|
|
82
98
|
address: sender,
|
|
83
99
|
invoke: &MockAuthInvoke {
|
|
@@ -85,18 +101,13 @@ pub fn send(
|
|
|
85
101
|
fn_name: "send",
|
|
86
102
|
args: (sender, send_param, fee, refund_address).into_val(env),
|
|
87
103
|
sub_invokes: &[
|
|
104
|
+
token_sub_invoke,
|
|
88
105
|
MockAuthInvoke {
|
|
89
106
|
contract: &chain.native_token,
|
|
90
107
|
fn_name: "transfer",
|
|
91
108
|
args: (sender, &chain.endpoint.address, &fee.native_fee).into_val(env),
|
|
92
109
|
sub_invokes: &[],
|
|
93
110
|
},
|
|
94
|
-
MockAuthInvoke {
|
|
95
|
-
contract: &chain.oft_token,
|
|
96
|
-
fn_name: "burn",
|
|
97
|
-
args: (sender, &oft_receipt.amount_received_ld).into_val(env),
|
|
98
|
-
sub_invokes: &[],
|
|
99
|
-
},
|
|
100
111
|
],
|
|
101
112
|
},
|
|
102
113
|
}]);
|
|
@@ -116,6 +127,21 @@ pub fn send_with_fee(
|
|
|
116
127
|
fee_deposit_address: &Address,
|
|
117
128
|
) {
|
|
118
129
|
let fee_amount = oft_receipt.amount_sent_ld - oft_receipt.amount_received_ld;
|
|
130
|
+
let token_sub_invoke = match chain.oft.oft_type() {
|
|
131
|
+
OftType::LockUnlock => MockAuthInvoke {
|
|
132
|
+
contract: &chain.oft_token,
|
|
133
|
+
fn_name: "transfer",
|
|
134
|
+
args: (sender, &chain.oft.address, &oft_receipt.amount_received_ld).into_val(env),
|
|
135
|
+
sub_invokes: &[],
|
|
136
|
+
},
|
|
137
|
+
OftType::MintBurn(_) => MockAuthInvoke {
|
|
138
|
+
contract: &chain.oft_token,
|
|
139
|
+
fn_name: "burn",
|
|
140
|
+
args: (sender, &oft_receipt.amount_received_ld).into_val(env),
|
|
141
|
+
sub_invokes: &[],
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
|
|
119
145
|
env.mock_auths(&[MockAuth {
|
|
120
146
|
address: sender,
|
|
121
147
|
invoke: &MockAuthInvoke {
|
|
@@ -123,18 +149,13 @@ pub fn send_with_fee(
|
|
|
123
149
|
fn_name: "send",
|
|
124
150
|
args: (sender, send_param, fee, refund_address).into_val(env),
|
|
125
151
|
sub_invokes: &[
|
|
152
|
+
token_sub_invoke,
|
|
126
153
|
MockAuthInvoke {
|
|
127
154
|
contract: &chain.oft_token,
|
|
128
155
|
fn_name: "transfer",
|
|
129
156
|
args: (sender, fee_deposit_address, &fee_amount).into_val(env),
|
|
130
157
|
sub_invokes: &[],
|
|
131
158
|
},
|
|
132
|
-
MockAuthInvoke {
|
|
133
|
-
contract: &chain.oft_token,
|
|
134
|
-
fn_name: "burn",
|
|
135
|
-
args: (sender, &oft_receipt.amount_received_ld).into_val(env),
|
|
136
|
-
sub_invokes: &[],
|
|
137
|
-
},
|
|
138
159
|
MockAuthInvoke {
|
|
139
160
|
contract: &chain.native_token,
|
|
140
161
|
fn_name: "transfer",
|
|
@@ -156,6 +177,21 @@ pub fn try_send(
|
|
|
156
177
|
refund_address: &Address,
|
|
157
178
|
oft_receipt: &OFTReceipt,
|
|
158
179
|
) -> bool {
|
|
180
|
+
let token_sub_invoke = match chain.oft.oft_type() {
|
|
181
|
+
OftType::LockUnlock => MockAuthInvoke {
|
|
182
|
+
contract: &chain.oft_token,
|
|
183
|
+
fn_name: "transfer",
|
|
184
|
+
args: (sender, &chain.oft.address, &oft_receipt.amount_received_ld).into_val(env),
|
|
185
|
+
sub_invokes: &[],
|
|
186
|
+
},
|
|
187
|
+
OftType::MintBurn(_) => MockAuthInvoke {
|
|
188
|
+
contract: &chain.oft_token,
|
|
189
|
+
fn_name: "burn",
|
|
190
|
+
args: (sender, &oft_receipt.amount_received_ld).into_val(env),
|
|
191
|
+
sub_invokes: &[],
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
|
|
159
195
|
env.mock_auths(&[MockAuth {
|
|
160
196
|
address: sender,
|
|
161
197
|
invoke: &MockAuthInvoke {
|
|
@@ -163,18 +199,13 @@ pub fn try_send(
|
|
|
163
199
|
fn_name: "send",
|
|
164
200
|
args: (sender, send_param, fee, refund_address).into_val(env),
|
|
165
201
|
sub_invokes: &[
|
|
202
|
+
token_sub_invoke,
|
|
166
203
|
MockAuthInvoke {
|
|
167
204
|
contract: &chain.native_token,
|
|
168
205
|
fn_name: "transfer",
|
|
169
206
|
args: (sender, &chain.endpoint.address, &fee.native_fee).into_val(env),
|
|
170
207
|
sub_invokes: &[],
|
|
171
208
|
},
|
|
172
|
-
MockAuthInvoke {
|
|
173
|
-
contract: &chain.oft_token,
|
|
174
|
-
fn_name: "burn",
|
|
175
|
-
args: (sender, &oft_receipt.amount_received_ld).into_val(env),
|
|
176
|
-
sub_invokes: &[],
|
|
177
|
-
},
|
|
178
209
|
],
|
|
179
210
|
},
|
|
180
211
|
}]);
|
|
@@ -318,21 +349,37 @@ pub fn mint_to(env: &Env, owner: &Address, token: &Address, to: &Address, amount
|
|
|
318
349
|
/// Mints the OFT token (via the Mintable wrapper) to the given address.
|
|
319
350
|
/// Use when OFT is MintBurn; the wrapper calls the underlying SAC mint.
|
|
320
351
|
pub fn mint_oft_token_to(env: &Env, chain: &ChainSetup<'_>, to: &Address, amount: i128) {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
|
|
352
|
+
match chain.oft.oft_type() {
|
|
353
|
+
OftType::LockUnlock => {
|
|
354
|
+
env.mock_auths(&[MockAuth {
|
|
355
|
+
address: &chain.owner,
|
|
356
|
+
invoke: &MockAuthInvoke {
|
|
357
|
+
contract: &chain.oft_token,
|
|
358
|
+
fn_name: "mint",
|
|
359
|
+
args: (to, &amount).into_val(env),
|
|
360
|
+
sub_invokes: &[],
|
|
361
|
+
},
|
|
362
|
+
}]);
|
|
363
|
+
StellarAssetClient::new(env, &chain.oft_token).mint(to, &amount);
|
|
364
|
+
}
|
|
365
|
+
OftType::MintBurn(_) => {
|
|
366
|
+
env.mock_auths(&[MockAuth {
|
|
367
|
+
address: &chain.owner,
|
|
368
|
+
invoke: &MockAuthInvoke {
|
|
369
|
+
contract: &chain.sac_wrapper,
|
|
370
|
+
fn_name: "mint",
|
|
371
|
+
args: (to, &amount, &chain.owner).into_val(env),
|
|
372
|
+
sub_invokes: &[MockAuthInvoke {
|
|
373
|
+
contract: &chain.oft_token,
|
|
374
|
+
fn_name: "mint",
|
|
375
|
+
args: (to, &amount).into_val(env),
|
|
376
|
+
sub_invokes: &[],
|
|
377
|
+
}],
|
|
378
|
+
},
|
|
379
|
+
}]);
|
|
380
|
+
MintableClient::new(env, &chain.sac_wrapper).mint(to, &amount, &chain.owner);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
336
383
|
}
|
|
337
384
|
|
|
338
385
|
pub fn transfer_sac_admin(env: &Env, owner: &Address, token: &Address, new_admin: &Address) {
|
|
@@ -265,4 +265,17 @@ pub trait OFTFeeInternal {
|
|
|
265
265
|
fn __fee_deposit_address(env: &Env) -> Option<Address> {
|
|
266
266
|
OFTFeeStorage::fee_deposit_address(env)
|
|
267
267
|
}
|
|
268
|
+
|
|
269
|
+
/// Back-calculates the pre-fee amount given a post-fee amount.
|
|
270
|
+
/// Returns the smallest `x` such that `x - fee(x) >= amount_after_fee`.
|
|
271
|
+
fn __amount_before_fee(env: &Env, dst_eid: u32, amount_after_fee: i128) -> i128 {
|
|
272
|
+
let fee_bps = Self::__effective_fee_bps(env, dst_eid);
|
|
273
|
+
if fee_bps == 0 {
|
|
274
|
+
return amount_after_fee;
|
|
275
|
+
}
|
|
276
|
+
if fee_bps == BASE_FEE_BPS {
|
|
277
|
+
return 0;
|
|
278
|
+
}
|
|
279
|
+
(amount_after_fee * BASE_FEE_BPS as i128) / (BASE_FEE_BPS - fee_bps) as i128
|
|
280
|
+
}
|
|
268
281
|
}
|
|
@@ -68,8 +68,16 @@ impl OFTCore for OFT {
|
|
|
68
68
|
fee_details.push_back(OFTFeeDetail { fee_amount_ld, description: Bytes::from_slice(env, b"OFT Fee") });
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
-
//
|
|
72
|
-
|
|
71
|
+
// Rate limit capacity, capped to u64::MAX (the safe ceiling from __quote_oft default)
|
|
72
|
+
let mut max_amount_ld = Self::rate_limit_capacity(env, &Direction::Outbound, send_param.dst_eid);
|
|
73
|
+
if max_amount_ld != i128::MAX {
|
|
74
|
+
// Back-calculate pre-fee amount so max_amount_ld represents the largest input to send()
|
|
75
|
+
max_amount_ld = Self::__amount_before_fee(env, send_param.dst_eid, max_amount_ld);
|
|
76
|
+
} else {
|
|
77
|
+
// No rate limit configured — use the bounded default
|
|
78
|
+
max_amount_ld = u64::MAX as i128;
|
|
79
|
+
}
|
|
80
|
+
limit.max_amount_ld = max_amount_ld;
|
|
73
81
|
|
|
74
82
|
(limit, fee_details, receipt)
|
|
75
83
|
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@layerzerolabs/protocol-stellar-v2",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.66",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "LZBL-1.2",
|
|
6
6
|
"devDependencies": {
|
|
7
7
|
"@types/node": "^22.18.6",
|
|
8
8
|
"tsx": "^4.19.3",
|
|
9
9
|
"typescript": "^5.8.2",
|
|
10
|
-
"@layerzerolabs/
|
|
11
|
-
"@layerzerolabs/
|
|
12
|
-
"@layerzerolabs/
|
|
10
|
+
"@layerzerolabs/common-node-utils": "0.2.66",
|
|
11
|
+
"@layerzerolabs/vm-tooling-stellar": "0.2.66",
|
|
12
|
+
"@layerzerolabs/stellar-ts-bindings-gen": "0.2.66"
|
|
13
13
|
},
|
|
14
14
|
"publishConfig": {
|
|
15
15
|
"access": "restricted",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"externalRepoConfig": {
|
|
19
19
|
"targets": [
|
|
20
20
|
"audit-external",
|
|
21
|
-
"
|
|
21
|
+
"onesig-client"
|
|
22
22
|
]
|
|
23
23
|
},
|
|
24
24
|
"scripts": {
|