@layerzerolabs/protocol-stellar-v2 0.2.65 → 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.
Files changed (48) hide show
  1. package/.turbo/turbo-build.log +218 -299
  2. package/.turbo/turbo-lint.log +225 -98
  3. package/.turbo/turbo-test.log +2010 -1924
  4. package/Cargo.lock +0 -16
  5. package/Cargo.toml +0 -1
  6. package/contracts/oapps/oft/integration-tests/extensions/test_oft_fee.rs +22 -0
  7. package/contracts/oapps/oft/integration-tests/extensions/test_pausable.rs +9 -2
  8. package/contracts/oapps/oft/integration-tests/extensions/test_rate_limiter.rs +27 -2
  9. package/contracts/oapps/oft/integration-tests/setup.rs +22 -18
  10. package/contracts/oapps/oft/integration-tests/utils.rs +81 -34
  11. package/contracts/oapps/oft/src/extensions/oft_fee.rs +13 -0
  12. package/contracts/oapps/oft/src/oft.rs +10 -2
  13. package/package.json +4 -4
  14. package/sdk/.turbo/turbo-test.log +299 -307
  15. package/sdk/dist/generated/oft.d.ts +3 -3
  16. package/sdk/dist/generated/oft.js +3 -3
  17. package/sdk/node_modules/.bin/vitest +2 -2
  18. package/sdk/package.json +1 -1
  19. package/contracts/oapps/console-oft/Cargo.toml +0 -30
  20. package/contracts/oapps/console-oft/integration-tests/extensions/mod.rs +0 -5
  21. package/contracts/oapps/console-oft/integration-tests/extensions/test_combined.rs +0 -90
  22. package/contracts/oapps/console-oft/integration-tests/extensions/test_oft_fee.rs +0 -186
  23. package/contracts/oapps/console-oft/integration-tests/extensions/test_ownership.rs +0 -161
  24. package/contracts/oapps/console-oft/integration-tests/extensions/test_pausable.rs +0 -154
  25. package/contracts/oapps/console-oft/integration-tests/extensions/test_rate_limiter.rs +0 -479
  26. package/contracts/oapps/console-oft/integration-tests/mod.rs +0 -3
  27. package/contracts/oapps/console-oft/integration-tests/setup.rs +0 -303
  28. package/contracts/oapps/console-oft/integration-tests/utils.rs +0 -685
  29. package/contracts/oapps/console-oft/src/errors.rs +0 -7
  30. package/contracts/oapps/console-oft/src/extensions/mod.rs +0 -3
  31. package/contracts/oapps/console-oft/src/extensions/oft_fee.rs +0 -239
  32. package/contracts/oapps/console-oft/src/extensions/pausable.rs +0 -185
  33. package/contracts/oapps/console-oft/src/extensions/rate_limiter.rs +0 -478
  34. package/contracts/oapps/console-oft/src/interfaces/mintable.rs +0 -14
  35. package/contracts/oapps/console-oft/src/interfaces/mod.rs +0 -3
  36. package/contracts/oapps/console-oft/src/lib.rs +0 -26
  37. package/contracts/oapps/console-oft/src/oft.rs +0 -208
  38. package/contracts/oapps/console-oft/src/oft_access_control.rs +0 -93
  39. package/contracts/oapps/console-oft/src/oft_types/lock_unlock.rs +0 -50
  40. package/contracts/oapps/console-oft/src/oft_types/mint_burn.rs +0 -50
  41. package/contracts/oapps/console-oft/src/oft_types/mod.rs +0 -24
  42. package/contracts/oapps/console-oft/src/tests/extensions/mod.rs +0 -3
  43. package/contracts/oapps/console-oft/src/tests/extensions/oft_fee.rs +0 -255
  44. package/contracts/oapps/console-oft/src/tests/extensions/pausable.rs +0 -212
  45. package/contracts/oapps/console-oft/src/tests/extensions/rate_limiter.rs +0 -992
  46. package/contracts/oapps/console-oft/src/tests/mod.rs +0 -2
  47. package/contracts/oapps/console-oft/src/tests/oft_types/lock_unlock.rs +0 -185
  48. package/contracts/oapps/console-oft/src/tests/oft_types/mod.rs +0 -1
@@ -1,478 +0,0 @@
1
- use crate as oft;
2
- use common_macros::{contract_error, contract_trait, only_role, storage};
3
- use soroban_sdk::{assert_with_error, contractevent, contracttype, Address, Env};
4
- use utils::rbac::RoleBasedAccessControl;
5
-
6
- /// Role required for all rate limiter management operations.
7
- pub const RATE_LIMITER_MANAGER_ROLE: &str = "RATE_LIMITER_MANAGER_ROLE";
8
-
9
- /// ID of the default rate limit configuration.
10
- pub const DEFAULT_ID: u128 = 0;
11
-
12
- /// Sentinel value indicating unlimited capacity (no rate limiting applied).
13
- pub const UNLIMITED_AMOUNT: i128 = i128::MAX;
14
-
15
- // =========================================================================
16
- // Types
17
- // =========================================================================
18
-
19
- /// Global configuration for the rate limiter.
20
- ///
21
- /// - `use_global_state`: when true, all IDs share config and state from DEFAULT_ID (0)
22
- /// - `is_globally_disabled`: when true, all rate limit checks are bypassed
23
- #[contracttype]
24
- #[derive(Clone, Debug, Default, Eq, PartialEq)]
25
- pub struct RateLimitGlobalConfig {
26
- pub use_global_state: bool,
27
- pub is_globally_disabled: bool,
28
- }
29
-
30
- /// Per-Destination ID configuration: flags, limits, and windows.
31
- ///
32
- /// Stored per Destination ID. If no config is stored for an ID, it inherits from DEFAULT_ID (0).
33
- /// If DEFAULT_ID has no config either, `RateLimitConfig::default()` is used.
34
- #[contracttype]
35
- #[derive(Clone, Debug, Eq, PartialEq)]
36
- pub struct RateLimitConfig {
37
- /// Whether outbound (send) rate limiting is enabled
38
- pub outbound_enabled: bool,
39
- /// Whether inbound (receive) rate limiting is enabled
40
- pub inbound_enabled: bool,
41
- /// Whether inbound flow releases outbound capacity and vice versa
42
- pub net_accounting_enabled: bool,
43
- /// Whether per-address exemptions are checked for this Destination ID
44
- pub address_exemption_enabled: bool,
45
- /// Maximum outbound (send) capacity in outbound window period
46
- pub outbound_limit: i128,
47
- /// Maximum inbound (receive) capacity in inbound window period
48
- pub inbound_limit: i128,
49
- /// Time window (in seconds) over which outbound usage fully decays back to zero
50
- pub outbound_window: u64,
51
- /// Time window (in seconds) over which inbound usage fully decays back to zero
52
- pub inbound_window: u64,
53
- }
54
-
55
- impl Default for RateLimitConfig {
56
- fn default() -> Self {
57
- Self {
58
- outbound_enabled: true,
59
- inbound_enabled: true,
60
- net_accounting_enabled: true,
61
- address_exemption_enabled: false,
62
- outbound_limit: 0,
63
- inbound_limit: 0,
64
- outbound_window: 0,
65
- inbound_window: 0,
66
- }
67
- }
68
- }
69
-
70
- /// Mutable usage counters and timestamp for a rate-limited Destination ID.
71
- #[contracttype]
72
- #[derive(Clone, Debug, Default, Eq, PartialEq)]
73
- pub struct RateLimitState {
74
- pub outbound_usage: i128,
75
- pub inbound_usage: i128,
76
- pub last_updated: u64,
77
- }
78
-
79
- /// Decayed usage and available capacity for a single Destination ID.
80
- #[contracttype]
81
- #[derive(Clone, Debug, Eq, PartialEq)]
82
- pub struct RateLimitUsages {
83
- pub outbound_usage: i128,
84
- pub outbound_available_amount: i128,
85
- pub inbound_usage: i128,
86
- pub inbound_available_amount: i128,
87
- }
88
-
89
- // =========================================================================
90
- // Storage
91
- // =========================================================================
92
-
93
- #[storage]
94
- enum RateLimitStorage {
95
- #[instance(RateLimitGlobalConfig)]
96
- #[default(Default::default())]
97
- GlobalConfig,
98
-
99
- #[persistent(RateLimitConfig)]
100
- RateLimitConfigs { id: u128 },
101
-
102
- #[persistent(RateLimitState)]
103
- #[default(Default::default())]
104
- RateLimitStates { id: u128 },
105
-
106
- #[persistent(bool)]
107
- #[default(false)]
108
- AddressExemptions { user: Address },
109
- }
110
-
111
- // =========================================================================
112
- // Errors
113
- // =========================================================================
114
-
115
- #[contract_error]
116
- pub enum RateLimitError {
117
- ExemptionStateIdempotent = 3120,
118
- InboundLimitNegative,
119
- InboundUsageNegative,
120
- InvalidAmount,
121
- LastUpdatedInFuture,
122
- OutboundLimitNegative,
123
- OutboundUsageNegative,
124
- RateLimitExceeded,
125
- }
126
-
127
- // =========================================================================
128
- // Events
129
- // =========================================================================
130
-
131
- #[contractevent]
132
- #[derive(Clone, Debug, Eq, PartialEq)]
133
- pub struct RateLimitConfigUpdated {
134
- #[topic]
135
- pub id: u128,
136
- pub config: Option<RateLimitConfig>,
137
- }
138
-
139
- #[contractevent]
140
- #[derive(Clone, Debug, Eq, PartialEq)]
141
- pub struct RateLimitStateUpdated {
142
- #[topic]
143
- pub id: u128,
144
- pub state: RateLimitState,
145
- }
146
-
147
- #[contractevent]
148
- #[derive(Clone, Debug, Eq, PartialEq)]
149
- pub struct RateLimitGlobalConfigUpdated {
150
- pub global_config: Option<RateLimitGlobalConfig>,
151
- }
152
-
153
- #[contractevent]
154
- #[derive(Clone, Debug, Eq, PartialEq)]
155
- pub struct RateLimitExemptionUpdated {
156
- #[topic]
157
- pub user: Address,
158
- pub is_exempt: bool,
159
- }
160
-
161
- // =========================================================================
162
- // Public Trait — mirrors EVM RateLimiterRBACUpgradeable
163
- // =========================================================================
164
-
165
- /// Rate limiter extension — controls token flow per Destination ID with rolling window decay.
166
- ///
167
- /// **Default state:** Closed (outbound+inbound enabled, limits=0). All transfers are blocked
168
- /// until the admin explicitly sets non-zero limits via `set_rate_limit_config`.
169
- ///
170
- /// **Config resolution:** Each Destination ID can override the DEFAULT_ID (0) config, or
171
- /// inherit it. When `use_global_state` is true, all Destination IDs share config and state from DEFAULT_ID.
172
- ///
173
- /// **Decay model:** Usage decays linearly over the configured window:
174
- /// `current_usage = max(0, in_flight - limit * time_elapsed / window)`
175
- /// `available = max(0, limit - current_usage)`
176
- ///
177
- /// **Net accounting:** When enabled, inbound flow releases outbound capacity and vice versa.
178
- #[contract_trait]
179
- pub trait RateLimiter: RateLimiterInternal + RoleBasedAccessControl {
180
- // === Management (RBAC-guarded) ===
181
-
182
- /// Sets or removes the global config (use_global_state, is_globally_disabled).
183
- ///
184
- /// - `Some(config)` — stores global config.
185
- /// - `None` — removes global config (reverts to default: both flags `false`).
186
- #[only_role(operator, RATE_LIMITER_MANAGER_ROLE)]
187
- fn set_rate_limit_global_config(
188
- env: &soroban_sdk::Env,
189
- global_config: &Option<oft::rate_limiter::RateLimitGlobalConfig>,
190
- operator: &soroban_sdk::Address,
191
- ) {
192
- Self::__set_rate_limit_global_config(env, global_config);
193
- }
194
-
195
- /// Sets or removes rate limit configuration for a Destination ID.
196
- ///
197
- /// - `Some(config)` — validates and stores config for this Destination ID.
198
- /// - `None` — removes per-Destination ID config (falls back to DEFAULT_ID).
199
- #[only_role(operator, RATE_LIMITER_MANAGER_ROLE)]
200
- fn set_rate_limit_config(
201
- env: &soroban_sdk::Env,
202
- id: u128,
203
- config: &Option<oft::rate_limiter::RateLimitConfig>,
204
- operator: &soroban_sdk::Address,
205
- ) {
206
- Self::__set_rate_limit_config(env, id, config);
207
- }
208
-
209
- /// Directly sets rate limit state (usage, last_updated) for admin correction.
210
- #[only_role(operator, RATE_LIMITER_MANAGER_ROLE)]
211
- fn set_rate_limit_state(
212
- env: &soroban_sdk::Env,
213
- id: u128,
214
- state: &oft::rate_limiter::RateLimitState,
215
- operator: &soroban_sdk::Address,
216
- ) {
217
- Self::__set_rate_limit_state(env, id, state);
218
- }
219
-
220
- /// Sets per-address exemption from rate limiting.
221
- ///
222
- /// Exempt addresses bypass rate limit checks entirely (when `address_exemption_enabled`
223
- /// is true in the config).
224
- #[only_role(operator, RATE_LIMITER_MANAGER_ROLE)]
225
- fn set_rate_limit_exemption(
226
- env: &soroban_sdk::Env,
227
- user: &soroban_sdk::Address,
228
- is_exempt: bool,
229
- operator: &soroban_sdk::Address,
230
- ) {
231
- Self::__set_rate_limit_exemption(env, user, is_exempt);
232
- }
233
-
234
- /// Snapshots decayed usage to storage for the given Destination ID.
235
- #[only_role(operator, RATE_LIMITER_MANAGER_ROLE)]
236
- fn checkpoint_rate_limit(env: &soroban_sdk::Env, id: u128, operator: &soroban_sdk::Address) {
237
- Self::__checkpoint_rate_limit(env, id);
238
- }
239
-
240
- // === Views ===
241
-
242
- /// Returns the global rate limit configuration.
243
- fn get_rate_limit_global_config(env: &soroban_sdk::Env) -> oft::rate_limiter::RateLimitGlobalConfig {
244
- RateLimitStorage::global_config(env)
245
- }
246
-
247
- /// Returns the raw per-Destination ID state and config (not resolved through inheritance).
248
- ///
249
- /// Config is `None` when no per-Destination ID config is stored.
250
- fn rate_limits(
251
- env: &soroban_sdk::Env,
252
- id: u128,
253
- ) -> (oft::rate_limiter::RateLimitState, Option<oft::rate_limiter::RateLimitConfig>) {
254
- (RateLimitStorage::rate_limit_states(env, id), RateLimitStorage::rate_limit_configs(env, id))
255
- }
256
-
257
- /// Returns whether the given address is exempt from rate limiting.
258
- fn is_rate_limit_exemption(env: &soroban_sdk::Env, user: &soroban_sdk::Address) -> bool {
259
- RateLimitStorage::address_exemptions(env, user)
260
- }
261
-
262
- /// Returns the current decayed usage and available capacity for the given Destination ID.
263
- ///
264
- /// If globally disabled, returns `UNLIMITED_AMOUNT` for available amounts.
265
- /// If a direction is not enabled, returns `UNLIMITED_AMOUNT` for that direction's available amount.
266
- fn get_rate_limit_usages(env: &soroban_sdk::Env, id: u128) -> oft::rate_limiter::RateLimitUsages {
267
- let (_state_id, state, config) = Self::__get_rate_limit_state_and_config(env, id);
268
-
269
- let mut usages = Self::__get_rate_limit_usages(env, &config, &state);
270
- let global = RateLimitStorage::global_config(env);
271
- if global.is_globally_disabled {
272
- usages.outbound_available_amount = UNLIMITED_AMOUNT;
273
- usages.inbound_available_amount = UNLIMITED_AMOUNT;
274
- } else {
275
- if !config.outbound_enabled {
276
- usages.outbound_available_amount = UNLIMITED_AMOUNT;
277
- }
278
- if !config.inbound_enabled {
279
- usages.inbound_available_amount = UNLIMITED_AMOUNT;
280
- }
281
- }
282
-
283
- usages
284
- }
285
- }
286
-
287
- // =========================================================================
288
- // Internal Trait — mirrors EVM RateLimiterBaseUpgradeable internals
289
- // =========================================================================
290
-
291
- /// Internal trait for rate limiter operations.
292
- ///
293
- /// Provides the flow hooks (`__outflow` / `__inflow`) called by `OFTInternal::__debit` and
294
- /// `OFTInternal::__credit`, as well as the core decay calculation and config resolution.
295
- pub trait RateLimiterInternal {
296
- // === OFT Hooks ===
297
-
298
- /// Hook called from `__debit` — consumes outbound capacity and releases inbound (if net accounting).
299
- fn __outflow(env: &Env, id: u128, from: &Address, amount: i128) {
300
- Self::__apply_rate_limit(env, id, from, amount, true);
301
- }
302
-
303
- /// Hook called from `__credit` — consumes inbound capacity and releases outbound (if net accounting).
304
- fn __inflow(env: &Env, id: u128, to: &Address, amount: i128) {
305
- Self::__apply_rate_limit(env, id, to, amount, false);
306
- }
307
-
308
- // === Core Logic ===
309
-
310
- /// Applies rate limit for a single flow direction.
311
- fn __apply_rate_limit(env: &Env, id: u128, user: &Address, amount: i128, is_outflow: bool) {
312
- assert_with_error!(env, amount >= 0, RateLimitError::InvalidAmount);
313
-
314
- if RateLimitStorage::global_config(env).is_globally_disabled {
315
- return;
316
- }
317
-
318
- let (state_id, mut state, config) = Self::__get_rate_limit_state_and_config(env, id);
319
-
320
- let (forward_enabled, backward_enabled) = if is_outflow {
321
- (config.outbound_enabled, config.inbound_enabled)
322
- } else {
323
- (config.inbound_enabled, config.outbound_enabled)
324
- };
325
-
326
- if (!forward_enabled && (!backward_enabled || !config.net_accounting_enabled))
327
- || (config.address_exemption_enabled && RateLimitStorage::has_address_exemptions(env, user))
328
- {
329
- return;
330
- }
331
-
332
- let usages = Self::__get_rate_limit_usages(env, &config, &state);
333
-
334
- let (mut forward_usage, forward_available, mut backward_usage) = if is_outflow {
335
- (usages.outbound_usage, usages.outbound_available_amount, usages.inbound_usage)
336
- } else {
337
- (usages.inbound_usage, usages.inbound_available_amount, usages.outbound_usage)
338
- };
339
-
340
- if forward_enabled {
341
- assert_with_error!(env, amount <= forward_available, RateLimitError::RateLimitExceeded);
342
- forward_usage += amount;
343
- }
344
-
345
- if backward_enabled && config.net_accounting_enabled {
346
- backward_usage = (backward_usage - amount).max(0);
347
- }
348
-
349
- let (new_outbound_usage, new_inbound_usage) =
350
- if is_outflow { (forward_usage, backward_usage) } else { (backward_usage, forward_usage) };
351
-
352
- state.outbound_usage = new_outbound_usage;
353
- state.inbound_usage = new_inbound_usage;
354
- state.last_updated = env.ledger().timestamp();
355
-
356
- RateLimitStorage::set_rate_limit_states(env, state_id, &state);
357
- }
358
-
359
- /// Resolves the state and config for a given Destination ID.
360
- ///
361
- /// Returns `(state_id, state, config)` where:
362
- /// - `state_id`: Effective storage key (may differ from `id` when `use_global_state` is true)
363
- /// - `state`: Current state from storage (returned by value; caller should copy to a `mut` local)
364
- /// - `config`: Resolved config (per-Destination ID override, or inherited from DEFAULT_ID)
365
- ///
366
- /// Resolution rules:
367
- /// - If `use_global_state`: all Destination IDs share DEFAULT_ID state and config
368
- /// - If per-Destination ID config exists: use it
369
- /// - Otherwise: inherit config from DEFAULT_ID (or default if DEFAULT_ID config absent)
370
- fn __get_rate_limit_state_and_config(env: &Env, id: u128) -> (u128, RateLimitState, RateLimitConfig) {
371
- let effective_id = if RateLimitStorage::global_config(env).use_global_state { DEFAULT_ID } else { id };
372
- let state = RateLimitStorage::rate_limit_states(env, effective_id);
373
- let config = Self::__effective_config(env, effective_id);
374
- (effective_id, state, config)
375
- }
376
-
377
- /// Resolves the effective config for a given Destination ID.
378
- ///
379
- /// If a per-Destination ID config exists, uses it.
380
- /// Otherwise falls back to DEFAULT_ID config, or `RateLimitConfig::default()` if absent.
381
- fn __effective_config(env: &Env, id: u128) -> RateLimitConfig {
382
- RateLimitStorage::rate_limit_configs(env, id)
383
- .unwrap_or_else(|| RateLimitStorage::rate_limit_configs(env, DEFAULT_ID).unwrap_or_default())
384
- }
385
-
386
- // === Decay Calculation ===
387
-
388
- /// Calculates decayed outbound and inbound usages from the resolved config + state.
389
- fn __get_rate_limit_usages(env: &Env, config: &RateLimitConfig, state: &RateLimitState) -> RateLimitUsages {
390
- let (outbound_usage, outbound_available_amount) = Self::__get_rate_limit_usage(
391
- env,
392
- state.last_updated,
393
- state.outbound_usage,
394
- config.outbound_limit,
395
- config.outbound_window,
396
- );
397
- let (inbound_usage, inbound_available_amount) = Self::__get_rate_limit_usage(
398
- env,
399
- state.last_updated,
400
- state.inbound_usage,
401
- config.inbound_limit,
402
- config.inbound_window,
403
- );
404
- RateLimitUsages { outbound_usage, outbound_available_amount, inbound_usage, inbound_available_amount }
405
- }
406
-
407
- /// Calculates the decayed usage and available capacity for a single direction.
408
- ///
409
- /// Decay formula: `decay = limit * time_elapsed / window` (pro-rata, saturating on overflow).
410
- /// A window of 0 is treated as 1 to avoid division by zero.
411
- fn __get_rate_limit_usage(
412
- env: &Env,
413
- last_updated: u64,
414
- amount_in_flight: i128,
415
- limit: i128,
416
- window: u64,
417
- ) -> (i128, i128) {
418
- let now = env.ledger().timestamp();
419
- assert_with_error!(env, now >= last_updated, RateLimitError::LastUpdatedInFuture);
420
- let time_since_last_update = (now - last_updated) as i128;
421
- let effective_window = if window == 0 { 1i128 } else { window as i128 };
422
-
423
- let decay = limit.saturating_mul(time_since_last_update) / effective_window;
424
- let current_usage = (amount_in_flight - decay).max(0);
425
- let available_amount = (limit - current_usage).max(0);
426
- (current_usage, available_amount)
427
- }
428
-
429
- // === Checkpoint ===
430
-
431
- fn __checkpoint_rate_limit(env: &Env, id: u128) {
432
- let (state_id, mut state, config) = Self::__get_rate_limit_state_and_config(env, id);
433
- let usages = Self::__get_rate_limit_usages(env, &config, &state);
434
-
435
- state.outbound_usage = usages.outbound_usage;
436
- state.inbound_usage = usages.inbound_usage;
437
- state.last_updated = env.ledger().timestamp();
438
-
439
- RateLimitStorage::set_rate_limit_states(env, state_id, &state);
440
- }
441
-
442
- // === Internal Setters ===
443
-
444
- fn __set_rate_limit_global_config(env: &Env, global_config: &Option<RateLimitGlobalConfig>) {
445
- RateLimitStorage::set_or_remove_global_config(env, global_config);
446
- RateLimitGlobalConfigUpdated { global_config: global_config.clone() }.publish(env);
447
- }
448
-
449
- fn __set_rate_limit_config(env: &Env, id: u128, config: &Option<RateLimitConfig>) {
450
- if let Some(cfg) = config {
451
- assert_with_error!(env, cfg.outbound_limit >= 0, RateLimitError::OutboundLimitNegative);
452
- assert_with_error!(env, cfg.inbound_limit >= 0, RateLimitError::InboundLimitNegative);
453
- }
454
- RateLimitStorage::set_or_remove_rate_limit_configs(env, id, config);
455
- RateLimitConfigUpdated { id, config: config.clone() }.publish(env);
456
- }
457
-
458
- fn __set_rate_limit_state(env: &Env, id: u128, state: &RateLimitState) {
459
- assert_with_error!(env, state.last_updated <= env.ledger().timestamp(), RateLimitError::LastUpdatedInFuture);
460
- assert_with_error!(env, state.outbound_usage >= 0, RateLimitError::OutboundUsageNegative);
461
- assert_with_error!(env, state.inbound_usage >= 0, RateLimitError::InboundUsageNegative);
462
-
463
- RateLimitStorage::set_rate_limit_states(env, id, state);
464
- RateLimitStateUpdated { id, state: state.clone() }.publish(env);
465
- }
466
-
467
- fn __set_rate_limit_exemption(env: &Env, user: &Address, is_exempt: bool) {
468
- let current = RateLimitStorage::address_exemptions(env, user);
469
- assert_with_error!(env, current != is_exempt, RateLimitError::ExemptionStateIdempotent);
470
-
471
- if is_exempt {
472
- RateLimitStorage::set_address_exemptions(env, user, &true);
473
- } else {
474
- RateLimitStorage::remove_address_exemptions(env, user);
475
- }
476
- RateLimitExemptionUpdated { user: user.clone(), is_exempt }.publish(env);
477
- }
478
- }
@@ -1,14 +0,0 @@
1
- //! Mintable trait - the interface the OFT uses to mint tokens on credit (receive).
2
-
3
- use soroban_sdk::{contractclient, Address, Env};
4
-
5
- /// The mint interface for OFT MintBurn operations.
6
- ///
7
- /// A contract that implements `mint` (e.g. SAC Manager or a token wrapper) is used
8
- /// for crediting; the OFT calls the token (SAC) directly for burn on debit.
9
- #[contractclient(name = "MintableClient")]
10
- pub trait Mintable {
11
- /// Mints `amount` tokens to `to`. The `operator` address is the caller (e.g. OFT)
12
- /// requesting the mint, for use by SAC wrappers that enforce authorization.
13
- fn mint(env: &Env, to: &Address, amount: i128, operator: &Address);
14
- }
@@ -1,3 +0,0 @@
1
- mod mintable;
2
-
3
- pub use mintable::*;
@@ -1,26 +0,0 @@
1
- #![no_std]
2
-
3
- mod errors;
4
- mod extensions;
5
- mod interfaces;
6
- mod oft_types;
7
-
8
- pub use errors::*;
9
- pub use extensions::*;
10
- pub use interfaces::*;
11
- pub use oft_types::*;
12
-
13
- cfg_if::cfg_if! {
14
- // Include implementation when NOT in library mode, OR when testutils is enabled (for tests)
15
- if #[cfg(any(not(feature = "library"), feature = "testutils"))] {
16
- mod oft;
17
- pub use oft::*;
18
- }
19
- }
20
-
21
- #[cfg(test)]
22
- #[path = "../integration-tests/mod.rs"]
23
- pub mod integration_tests;
24
-
25
- #[cfg(test)]
26
- mod tests;