@layerzerolabs/protocol-stellar-v2 0.2.33 → 0.2.34

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 (66) hide show
  1. package/.turbo/turbo-build.log +377 -392
  2. package/.turbo/turbo-lint.log +209 -207
  3. package/.turbo/turbo-test.log +1687 -1753
  4. package/contracts/oapps/oft/integration-tests/extensions/test_oft_fee.rs +5 -11
  5. package/contracts/oapps/oft/integration-tests/extensions/test_pausable.rs +7 -14
  6. package/contracts/oapps/oft/integration-tests/extensions/test_rate_limiter.rs +11 -22
  7. package/contracts/oapps/oft/integration-tests/setup.rs +59 -7
  8. package/contracts/oapps/oft/integration-tests/utils.rs +28 -2
  9. package/contracts/oapps/oft/src/interfaces/mintable.rs +14 -0
  10. package/contracts/oapps/oft/src/interfaces/mod.rs +2 -2
  11. package/contracts/oapps/oft/src/oft.rs +3 -3
  12. package/contracts/oapps/oft/src/oft_types/mint_burn.rs +8 -8
  13. package/contracts/oapps/oft/src/oft_types/mod.rs +3 -4
  14. package/contracts/oapps/oft/src/tests/extensions/rate_limiter.rs +7 -5
  15. package/contracts/oapps/sac-manager/src/errors.rs +14 -0
  16. package/contracts/{sac-manager → oapps/sac-manager}/src/lib.rs +0 -4
  17. package/contracts/oapps/sac-manager/src/sac_manager.rs +115 -0
  18. package/contracts/oapps/sac-manager/src/storage.rs +20 -0
  19. package/contracts/{sac-manager → oapps/sac-manager}/src/tests/mod.rs +0 -4
  20. package/contracts/oapps/sac-manager/src/tests/sac_manager/clawback.rs +86 -0
  21. package/contracts/oapps/sac-manager/src/tests/sac_manager/mint.rs +58 -0
  22. package/contracts/{sac-manager → oapps/sac-manager}/src/tests/sac_manager/mod.rs +1 -3
  23. package/contracts/oapps/sac-manager/src/tests/sac_manager/set_minter.rs +69 -0
  24. package/contracts/oapps/sac-manager/src/tests/sac_manager/test_helper.rs +18 -0
  25. package/contracts/oapps/sac-manager/src/tests/sac_manager/view_functions.rs +28 -0
  26. package/contracts/{sac-manager → oapps/sac-manager}/src/tests/test_helper.rs +16 -59
  27. package/package.json +8 -3
  28. package/sdk/.turbo/turbo-test.log +373 -374
  29. package/sdk/dist/generated/oft.d.ts +3 -3
  30. package/sdk/dist/generated/oft.js +4 -4
  31. package/sdk/dist/generated/sac_manager.d.ts +26 -318
  32. package/sdk/dist/generated/sac_manager.js +23 -129
  33. package/sdk/package.json +6 -1
  34. package/sdk/test/oft-sml.test.ts +72 -36
  35. package/sdk/test/sac-manager-redistribution.test.ts +38 -182
  36. package/contracts/oapps/oft/src/interfaces/mint_burnable.rs +0 -18
  37. package/contracts/sac-manager/src/errors.rs +0 -18
  38. package/contracts/sac-manager/src/extensions/mod.rs +0 -6
  39. package/contracts/sac-manager/src/extensions/redistribution.rs +0 -109
  40. package/contracts/sac-manager/src/extensions/supply_control/mod.rs +0 -488
  41. package/contracts/sac-manager/src/extensions/supply_control/rate_limit.rs +0 -126
  42. package/contracts/sac-manager/src/interfaces/mod.rs +0 -3
  43. package/contracts/sac-manager/src/interfaces/sac_manager.rs +0 -52
  44. package/contracts/sac-manager/src/sac_manager.rs +0 -193
  45. package/contracts/sac-manager/src/storage.rs +0 -20
  46. package/contracts/sac-manager/src/tests/redistribution/mod.rs +0 -1
  47. package/contracts/sac-manager/src/tests/redistribution/redistribute_funds.rs +0 -82
  48. package/contracts/sac-manager/src/tests/sac_manager/admin_mint.rs +0 -206
  49. package/contracts/sac-manager/src/tests/sac_manager/burn.rs +0 -215
  50. package/contracts/sac-manager/src/tests/sac_manager/clawback.rs +0 -209
  51. package/contracts/sac-manager/src/tests/sac_manager/mint.rs +0 -252
  52. package/contracts/sac-manager/src/tests/sac_manager/set_oft_address.rs +0 -47
  53. package/contracts/sac-manager/src/tests/sac_manager/test_helper.rs +0 -75
  54. package/contracts/sac-manager/src/tests/sac_manager/view_functions.rs +0 -60
  55. package/contracts/sac-manager/src/tests/supply_control/enumerable_set.rs +0 -256
  56. package/contracts/sac-manager/src/tests/supply_control/mod.rs +0 -8
  57. package/contracts/sac-manager/src/tests/supply_control/refill.rs +0 -90
  58. package/contracts/sac-manager/src/tests/supply_control/set_mint_whitelist.rs +0 -245
  59. package/contracts/sac-manager/src/tests/supply_control/set_supply_controller.rs +0 -267
  60. package/contracts/sac-manager/src/tests/supply_control/set_supply_controller_manager.rs +0 -122
  61. package/contracts/sac-manager/src/tests/supply_control/test_helper.rs +0 -38
  62. package/contracts/sac-manager/src/tests/supply_control/update_allow_any_mint_burn.rs +0 -114
  63. package/contracts/sac-manager/src/tests/supply_control/update_limit_config.rs +0 -257
  64. /package/contracts/{sac-manager → oapps/sac-manager}/Cargo.toml +0 -0
  65. /package/contracts/{sac-manager → oapps/sac-manager}/src/tests/sac_manager/set_admin.rs +0 -0
  66. /package/contracts/{sac-manager → oapps/sac-manager}/src/tests/sac_manager/set_authorized.rs +0 -0
@@ -1,126 +0,0 @@
1
- //! Rate limiting types and logic for supply control.
2
- //!
3
- //! Pure rate-limit primitives: configuration, runtime state, and the token-bucket
4
- //! refill algorithm. No storage or authorization concerns — those live in the
5
- //! parent `supply_control` module.
6
-
7
- use super::SupplyControlError;
8
- use soroban_sdk::contracttype;
9
-
10
- /// A `refill_per_second` value of 0 means rate limit checking is skipped (unlimited minting).
11
- pub(super) const SKIP_RATE_LIMIT_CHECK: i128 = 0;
12
-
13
- // =========================================================================
14
- // Types
15
- // =========================================================================
16
-
17
- /// Limit configuration for rate limiting.
18
- #[contracttype]
19
- #[derive(Clone, Debug, Eq, PartialEq)]
20
- pub struct LimitConfig {
21
- /// Max amount for the rate limit
22
- pub limit_capacity: i128,
23
- /// Amount to add to limit each second up to the limitCapacity.
24
- /// A value of 0 means rate limiting is disabled (unlimited minting allowed).
25
- pub refill_per_second: i128,
26
- }
27
-
28
- /// Rate limit state (the runtime state that persists across config updates).
29
- #[contracttype]
30
- #[derive(Clone, Debug, Eq, PartialEq)]
31
- pub struct RateLimitState {
32
- /// Remaining amount for the time period
33
- pub remaining_amount: i128,
34
- /// Timestamp of last refill
35
- pub last_refill_time: u64,
36
- }
37
-
38
- // =========================================================================
39
- // Helper Functions
40
- // =========================================================================
41
-
42
- /// Refills and returns the remaining amount based on elapsed time.
43
- /// Returns `Err(SupplyControlError::OldTimestamp)` if `timestamp` is older than `last_refill_time`.
44
- /// On arithmetic overflow, returns `limit_capacity` (aligned with EVM RateLimiter).
45
- pub(super) fn refill(
46
- limit_config: &LimitConfig,
47
- state: &RateLimitState,
48
- timestamp: u64,
49
- ) -> Result<i128, SupplyControlError> {
50
- if timestamp < state.last_refill_time {
51
- return Err(SupplyControlError::OldTimestamp);
52
- }
53
-
54
- let seconds_elapsed = timestamp - state.last_refill_time;
55
- let new_tokens = (seconds_elapsed as i128).checked_mul(limit_config.refill_per_second);
56
- let amount = new_tokens.and_then(|t| state.remaining_amount.checked_add(t));
57
-
58
- Ok(match amount {
59
- Some(amount) => amount.min(limit_config.limit_capacity),
60
- None => limit_config.limit_capacity,
61
- })
62
- }
63
-
64
- /// Gets remaining amount that can be sent in the window.
65
- /// A `refill_per_second` of 0 is a special value indicating rate limit checking is skipped.
66
- pub(super) fn get_remaining_amount(
67
- limit_config: &LimitConfig,
68
- state: &RateLimitState,
69
- timestamp: u64,
70
- ) -> Result<i128, SupplyControlError> {
71
- if limit_config.refill_per_second == SKIP_RATE_LIMIT_CHECK {
72
- return Ok(i128::MAX);
73
- }
74
- refill(limit_config, state, timestamp)
75
- }
76
-
77
- /// Attempts to consume `amount` from the rate limit budget.
78
- ///
79
- /// 1. Skips if rate limiting is disabled (`refill_per_second == 0`).
80
- /// 2. Refills the bucket based on elapsed time.
81
- /// 3. Checks if `amount` fits within the remaining capacity.
82
- /// 4. Deducts `amount` and updates the state in place.
83
- ///
84
- /// Returns `Err(RateLimitExceeded)` if the amount exceeds remaining capacity.
85
- /// Returns `Err(OldTimestamp)` if `timestamp` is older than `last_refill_time`.
86
- pub(super) fn try_consume(
87
- limit_config: &LimitConfig,
88
- state: &mut RateLimitState,
89
- timestamp: u64,
90
- amount: i128,
91
- ) -> Result<(), SupplyControlError> {
92
- if limit_config.refill_per_second == SKIP_RATE_LIMIT_CHECK {
93
- return Ok(());
94
- }
95
- if amount < 0 {
96
- return Err(SupplyControlError::InvalidAmount);
97
- }
98
-
99
- state.remaining_amount = refill(limit_config, state, timestamp)?;
100
- state.last_refill_time = timestamp;
101
-
102
- if amount > state.remaining_amount {
103
- return Err(SupplyControlError::RateLimitExceeded);
104
- }
105
-
106
- state.remaining_amount -= amount;
107
- Ok(())
108
- }
109
-
110
- // ============================================================================
111
- // Test-only Functions
112
- // ============================================================================
113
-
114
- #[cfg(test)]
115
- pub(crate) mod test {
116
- use super::*;
117
-
118
- /// Test-only wrapper for refill to enable testing.
119
- pub fn refill_for_test(
120
- limit_config: &LimitConfig,
121
- state: &RateLimitState,
122
- timestamp: u64,
123
- ) -> Result<i128, SupplyControlError> {
124
- refill(limit_config, state, timestamp)
125
- }
126
- }
@@ -1,3 +0,0 @@
1
- mod sac_manager;
2
-
3
- pub use sac_manager::*;
@@ -1,52 +0,0 @@
1
- //! SAC Manager interface - ISacManager trait.
2
- //!
3
- //! Defines the admin-only methods where the SAC manager adds value beyond the raw SAC.
4
- //! Mint/burn for the OFT are provided via the MintBurnable trait.
5
- //! Pure pass-through queries (balance, decimals, name, symbol, etc.)
6
- //! should be called directly on the underlying SAC.
7
-
8
- use common_macros::contract_trait;
9
- use soroban_sdk::{Address, Env};
10
-
11
- // =========================================================================
12
- // ISacManager Interface
13
- // =========================================================================
14
-
15
- /// SAC Manager Interface.
16
- ///
17
- /// Admin-only operations are authorized via the contract owner (Ownable).
18
- /// OFT mint/burn operations are handled by the MintBurnable trait separately.
19
- #[contract_trait(client_name = "ISacManagerClient")]
20
- pub trait ISacManager {
21
- // =========================================================================
22
- // Admin Operations
23
- // =========================================================================
24
-
25
- /// Mints `amount` to `to`. Subject to supply control when enabled.
26
- /// When supply control is off, only the owner can call.
27
- fn authorized_mint(env: &Env, sender: &Address, to: &Address, amount: i128);
28
-
29
- /// Clawback `amount` from `from` account. Subject to supply control when enabled.
30
- /// When supply control is off, only the owner or OFT can call.
31
- fn clawback(env: &Env, sender: &Address, from: &Address, amount: i128);
32
-
33
- /// Releases the SAC admin role. Owner-only.
34
- fn release_sac_admin(env: &Env, to: &Address);
35
-
36
- /// Sets whether the account is authorized to use its balance. Admin-only.
37
- fn set_authorized(env: &Env, id: &Address, authorize: bool);
38
-
39
- /// Sets the OFT contract address authorized to call mint/burn.
40
- /// Must be called after construction since OFT and sac-manager are circular dependencies.
41
- fn set_oft_address(env: &Env, new_oft: &Address);
42
-
43
- // =========================================================================
44
- // View Functions
45
- // =========================================================================
46
-
47
- /// Returns the underlying SAC (Stellar Asset Contract) address managed by this contract.
48
- fn underlying_sac(env: &Env) -> Address;
49
-
50
- /// Returns the OFT contract address authorized to call mint/burn.
51
- fn oft_address(env: &Env) -> Address;
52
- }
@@ -1,193 +0,0 @@
1
- //! SAC Manager Contract - Manages a Stellar Asset Contract (SAC) as its admin.
2
- //!
3
- //! This contract becomes the admin of a SAC and provides:
4
- //! - MintBurnable interface for OFT (mint/burn with supply control)
5
- //! - Admin operations (admin_mint, clawback, set_admin, set_authorized)
6
- //! - Redistribution feature (transfer to blacklisted → redirect to configurable target)
7
- //! - Supply control feature (rate limiting on mint)
8
- //! - Upgradeable (owner-authorized)
9
- //!
10
- //! ## Authorization Model
11
- //!
12
- //! - **Owner** (via Ownable): The admin address. Can do everything (upgrades, TTL, admin ops).
13
- //! - **OFT address**: Stored separately. Can only call mint/burn (MintBurnable interface).
14
- //! - **Redistribution target**: Always the current owner address.
15
-
16
- use crate::{
17
- errors::SacManagerError,
18
- extensions::{
19
- redistribution::{Redistribution, RedistributionInternal},
20
- supply_control::{LimitConfig, SupplyControl, SupplyControlInternal, SupplyControllerConfig},
21
- },
22
- interfaces::ISacManager,
23
- storage::SacManagerStorage,
24
- };
25
- use common_macros::{contract_impl, lz_contract, only_auth};
26
- use oft::MintBurnable;
27
- use soroban_sdk::{assert_with_error, token::StellarAssetClient, Address, Env, Vec};
28
- use utils::{option_ext::OptionExt, ownable::OwnableInitializer};
29
-
30
- // =========================================================================
31
- // SAC Manager Contract
32
- // =========================================================================
33
-
34
- /// SAC Manager Contract
35
- ///
36
- /// Manages a SAC as its admin, forwarding token actions to
37
- /// the underlying SAC while enforcing access control and feature policies.
38
- #[lz_contract(upgradeable(no_migration))]
39
- pub struct SacManager;
40
-
41
- #[contract_impl]
42
- impl SacManager {
43
- /// Constructs the SAC manager contract.
44
- ///
45
- /// # Arguments
46
- /// * `sac_token` - The underlying Stellar Asset Contract address
47
- /// * `owner` - The initial owner address (for upgrades, owner ops, redistribution target)
48
- /// * `redistribution_enabled` - Whether redistribution is enabled globally
49
- /// * `supply_control_enabled` - Whether supply control is enabled globally
50
- ///
51
- /// Note: The OFT address must be set separately via `set_oft_address` after construction,
52
- /// because the OFT and sac-manager have a circular dependency on each other's addresses.
53
- pub fn __constructor(
54
- env: &Env,
55
- sac_token: &Address,
56
- owner: &Address,
57
- redistribution_enabled: bool,
58
- supply_control_enabled: bool,
59
- ) {
60
- // Initialize admin for upgrade/TTL authorization and admin operations
61
- Self::init_owner(env, owner);
62
-
63
- // Store SAC token
64
- SacManagerStorage::set_sac_token(env, sac_token);
65
-
66
- // Set feature flags
67
- if redistribution_enabled {
68
- Self::__enable_redistribution(env);
69
- }
70
- if supply_control_enabled {
71
- Self::__enable_supply_control(env);
72
- }
73
- }
74
- }
75
-
76
- // =========================================================================
77
- // MintBurnable Implementation (OFT interface)
78
- // =========================================================================
79
-
80
- #[contract_impl]
81
- impl MintBurnable for SacManager {
82
- fn mint(env: &Env, to: &Address, amount: i128) {
83
- let oft = Self::oft_address(env);
84
- Self::authorized_mint(env, &oft, to, amount);
85
- }
86
-
87
- fn burn(env: &Env, from: &Address, amount: i128) {
88
- from.require_auth();
89
-
90
- let oft = Self::oft_address(env);
91
- oft.require_auth();
92
- Self::__enforce_burn(env, &oft, from, amount, |_| {});
93
-
94
- sac_client::<Self>(env).burn(from, &amount);
95
- }
96
- }
97
-
98
- // =========================================================================
99
- // ISacManager Implementation (Owner operations)
100
- // =========================================================================
101
-
102
- #[contract_impl(contracttrait)]
103
- impl ISacManager for SacManager {
104
- // =========================================================================
105
- // Supply Control Operations
106
- // =========================================================================
107
-
108
- fn authorized_mint(env: &Env, sender: &Address, to: &Address, amount: i128) {
109
- sender.require_auth();
110
-
111
- // Validate the mint operation by supply control extension if needed.
112
- Self::__enforce_mint(env, sender, to, amount, |sender| {
113
- assert_with_error!(
114
- env,
115
- Some(sender) == Self::owner(env).as_ref() || sender == &Self::oft_address(env),
116
- SacManagerError::Unauthorized
117
- )
118
- });
119
-
120
- // Resolve the actual receiver address by redistribution extension if needed.
121
- let actual_to = Self::__redistribute_funds(env, to, amount);
122
-
123
- // Mint the tokens to the actual receiver address.
124
- sac_client::<Self>(env).mint(&actual_to, &amount);
125
- }
126
-
127
- fn clawback(env: &Env, sender: &Address, from: &Address, amount: i128) {
128
- sender.require_auth();
129
- Self::__enforce_burn(env, sender, from, amount, |sender| {
130
- assert_with_error!(env, Some(sender) == Self::owner(env).as_ref(), SacManagerError::Unauthorized)
131
- });
132
-
133
- sac_client::<Self>(env).clawback(from, &amount);
134
- }
135
-
136
- // =========================================================================
137
- // SAC Admin Operations
138
- // =========================================================================
139
-
140
- #[only_auth]
141
- fn release_sac_admin(env: &Env, to: &Address) {
142
- sac_client::<Self>(env).set_admin(to);
143
- }
144
-
145
- #[only_auth]
146
- fn set_authorized(env: &Env, id: &Address, authorize: bool) {
147
- sac_client::<Self>(env).set_authorized(id, &authorize);
148
- }
149
-
150
- #[only_auth]
151
- fn set_oft_address(env: &Env, new_oft: &Address) {
152
- assert_with_error!(
153
- env,
154
- Some(new_oft) != SacManagerStorage::oft_address(env).as_ref(),
155
- SacManagerError::SameValue
156
- );
157
- SacManagerStorage::set_oft_address(env, new_oft);
158
- }
159
-
160
- // =========================================================================
161
- // View Functions
162
- // =========================================================================
163
-
164
- fn underlying_sac(env: &Env) -> Address {
165
- SacManagerStorage::sac_token(env).unwrap()
166
- }
167
-
168
- fn oft_address(env: &Env) -> Address {
169
- SacManagerStorage::oft_address(env).unwrap_or_panic(env, SacManagerError::OftAddressNotSet)
170
- }
171
- }
172
-
173
- // =========================================================================
174
- // Extension Implementations
175
- // =========================================================================
176
-
177
- /// Supply control trait implementation
178
- #[contract_impl(contracttrait)]
179
- impl SupplyControl for SacManager {}
180
- impl SupplyControlInternal for SacManager {}
181
-
182
- /// Redistribution trait implementation
183
- #[contract_impl(contracttrait)]
184
- impl Redistribution for SacManager {}
185
- impl RedistributionInternal for SacManager {}
186
-
187
- // =========================================================================
188
- // Helper Functions
189
- // =========================================================================
190
-
191
- pub(crate) fn sac_client<T: ISacManager>(env: &Env) -> StellarAssetClient<'_> {
192
- StellarAssetClient::new(env, &T::underlying_sac(env))
193
- }
@@ -1,20 +0,0 @@
1
- //! Storage definitions for the SAC manager contract.
2
- //!
3
- //! Each feature module owns its own storage to maintain modularity.
4
- //! This file contains the core storage and feature enable flags.
5
-
6
- use common_macros::storage;
7
- use soroban_sdk::Address;
8
-
9
- /// Core storage for the SacManager contract.
10
- /// Contains essential state and feature enable flags.
11
- #[storage]
12
- pub enum SacManagerStorage {
13
- /// The underlying SAC (Stellar Asset Contract) address
14
- #[instance(Address)]
15
- SacToken,
16
-
17
- /// The OFT contract address (authorized to call mint/burn)
18
- #[instance(Address)]
19
- OftAddress,
20
- }
@@ -1 +0,0 @@
1
- mod redistribute_funds;
@@ -1,82 +0,0 @@
1
- //! Redistribution Extension Integration Tests
2
- //!
3
- //! Tests for the redistribution feature including:
4
- //! - redistribute_funds auth requirements
5
- //! - redistribute_funds error cases (NotBlacklisted)
6
-
7
- use crate::extensions::redistribution::RedistributionError;
8
- use crate::tests::test_helper::{mock_auth, TestSetup};
9
- use crate::extensions::redistribution::{RedistributeFunds, RedistributionClient};
10
- use soroban_sdk::{testutils::IssuerFlags, Address};
11
- use utils::testing_utils::assert_contains_event;
12
-
13
- fn mock_redistribute_funds_auth(setup: &TestSetup, from: &Address, amount: i128) {
14
- mock_auth(&setup.env, &setup.sac_manager, &setup.owner, "redistribute_blacklisted_funds", (from, amount));
15
- }
16
-
17
- // =========================================================================
18
- // redistribute_funds Happy Path
19
- // =========================================================================
20
-
21
- #[test]
22
- fn test_redistribute_funds_success() {
23
- let setup = TestSetup::new().with_manager_as_sac_admin().with_redistribution_enabled().build();
24
- let blacklisted_user = setup.generate_address();
25
- let redistribution_client = RedistributionClient::new(&setup.env, &setup.sac_manager);
26
-
27
- // Enable issuer flags required by set_authorized + clawback in SAC tests.
28
- setup.sac_contract.issuer().set_flag(IssuerFlags::RevocableFlag);
29
- setup.sac_contract.issuer().set_flag(IssuerFlags::ClawbackEnabledFlag);
30
-
31
- // Prepare user funds, then blacklist the user.
32
- mock_auth(&setup.env, &setup.sac_manager, &setup.oft, "mint", (&blacklisted_user, 1_000_i128));
33
- setup.sac_manager_client.mint(&blacklisted_user, &1_000);
34
- mock_auth(&setup.env, &setup.sac_manager, &setup.owner, "set_authorized", (&blacklisted_user, false));
35
- setup.sac_manager_client.set_authorized(&blacklisted_user, &false);
36
-
37
- let owner_balance_before = setup.sac_client.balance(&setup.owner);
38
- let user_balance_before = setup.sac_client.balance(&blacklisted_user);
39
- assert_eq!(user_balance_before, 1_000);
40
- assert!(!setup.sac_client.authorized(&blacklisted_user));
41
-
42
- mock_redistribute_funds_auth(&setup, &blacklisted_user, 400_i128);
43
- redistribution_client.redistribute_blacklisted_funds(&blacklisted_user, &400);
44
-
45
- let expected = RedistributeFunds { user: blacklisted_user.clone(), amount: 400 };
46
- assert_contains_event(&setup.env, &setup.sac_manager, expected);
47
-
48
- // Verify clawback from user + mint to owner.
49
- assert_eq!(setup.sac_client.balance(&blacklisted_user), user_balance_before - 400);
50
- assert_eq!(setup.sac_client.balance(&setup.owner), owner_balance_before + 400);
51
- }
52
-
53
- // =========================================================================
54
- // redistribute_funds Error Cases
55
- // =========================================================================
56
-
57
- #[test]
58
- fn test_redistribute_funds_fails_if_not_blacklisted() {
59
- let setup = TestSetup::new().with_manager_as_sac_admin().with_redistribution_enabled().build();
60
- let user = setup.generate_address();
61
- let redistribution_client = RedistributionClient::new(&setup.env, &setup.sac_manager);
62
-
63
- // User is authorized by default (not blacklisted) — should fail
64
- mock_redistribute_funds_auth(&setup, &user, 100_i128);
65
- let result = redistribution_client.try_redistribute_blacklisted_funds(&user, &100);
66
- assert_eq!(result.err().unwrap().unwrap(), RedistributionError::NotBlacklisted.into());
67
- }
68
-
69
- // =========================================================================
70
- // redistribute_funds Auth Tests
71
- // =========================================================================
72
-
73
- #[test]
74
- #[should_panic(expected = "Error(Auth, InvalidAction)")]
75
- fn test_redistribute_funds_fails_without_owner_auth() {
76
- let setup = TestSetup::new().with_manager_as_sac_admin().with_redistribution_enabled().build();
77
- let user = setup.generate_address();
78
- let redistribution_client = RedistributionClient::new(&setup.env, &setup.sac_manager);
79
-
80
- // No auth mocked — owner auth fails
81
- redistribution_client.redistribute_blacklisted_funds(&user, &100);
82
- }