@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.
- package/.turbo/turbo-build.log +377 -392
- package/.turbo/turbo-lint.log +209 -207
- package/.turbo/turbo-test.log +1687 -1753
- package/contracts/oapps/oft/integration-tests/extensions/test_oft_fee.rs +5 -11
- package/contracts/oapps/oft/integration-tests/extensions/test_pausable.rs +7 -14
- package/contracts/oapps/oft/integration-tests/extensions/test_rate_limiter.rs +11 -22
- package/contracts/oapps/oft/integration-tests/setup.rs +59 -7
- package/contracts/oapps/oft/integration-tests/utils.rs +28 -2
- package/contracts/oapps/oft/src/interfaces/mintable.rs +14 -0
- package/contracts/oapps/oft/src/interfaces/mod.rs +2 -2
- package/contracts/oapps/oft/src/oft.rs +3 -3
- package/contracts/oapps/oft/src/oft_types/mint_burn.rs +8 -8
- package/contracts/oapps/oft/src/oft_types/mod.rs +3 -4
- package/contracts/oapps/oft/src/tests/extensions/rate_limiter.rs +7 -5
- package/contracts/oapps/sac-manager/src/errors.rs +14 -0
- package/contracts/{sac-manager → oapps/sac-manager}/src/lib.rs +0 -4
- package/contracts/oapps/sac-manager/src/sac_manager.rs +115 -0
- package/contracts/oapps/sac-manager/src/storage.rs +20 -0
- package/contracts/{sac-manager → oapps/sac-manager}/src/tests/mod.rs +0 -4
- package/contracts/oapps/sac-manager/src/tests/sac_manager/clawback.rs +86 -0
- package/contracts/oapps/sac-manager/src/tests/sac_manager/mint.rs +58 -0
- package/contracts/{sac-manager → oapps/sac-manager}/src/tests/sac_manager/mod.rs +1 -3
- package/contracts/oapps/sac-manager/src/tests/sac_manager/set_minter.rs +69 -0
- package/contracts/oapps/sac-manager/src/tests/sac_manager/test_helper.rs +18 -0
- package/contracts/oapps/sac-manager/src/tests/sac_manager/view_functions.rs +28 -0
- package/contracts/{sac-manager → oapps/sac-manager}/src/tests/test_helper.rs +16 -59
- package/package.json +8 -3
- package/sdk/.turbo/turbo-test.log +373 -374
- package/sdk/dist/generated/oft.d.ts +3 -3
- package/sdk/dist/generated/oft.js +4 -4
- package/sdk/dist/generated/sac_manager.d.ts +26 -318
- package/sdk/dist/generated/sac_manager.js +23 -129
- package/sdk/package.json +6 -1
- package/sdk/test/oft-sml.test.ts +72 -36
- package/sdk/test/sac-manager-redistribution.test.ts +38 -182
- package/contracts/oapps/oft/src/interfaces/mint_burnable.rs +0 -18
- package/contracts/sac-manager/src/errors.rs +0 -18
- package/contracts/sac-manager/src/extensions/mod.rs +0 -6
- package/contracts/sac-manager/src/extensions/redistribution.rs +0 -109
- package/contracts/sac-manager/src/extensions/supply_control/mod.rs +0 -488
- package/contracts/sac-manager/src/extensions/supply_control/rate_limit.rs +0 -126
- package/contracts/sac-manager/src/interfaces/mod.rs +0 -3
- package/contracts/sac-manager/src/interfaces/sac_manager.rs +0 -52
- package/contracts/sac-manager/src/sac_manager.rs +0 -193
- package/contracts/sac-manager/src/storage.rs +0 -20
- package/contracts/sac-manager/src/tests/redistribution/mod.rs +0 -1
- package/contracts/sac-manager/src/tests/redistribution/redistribute_funds.rs +0 -82
- package/contracts/sac-manager/src/tests/sac_manager/admin_mint.rs +0 -206
- package/contracts/sac-manager/src/tests/sac_manager/burn.rs +0 -215
- package/contracts/sac-manager/src/tests/sac_manager/clawback.rs +0 -209
- package/contracts/sac-manager/src/tests/sac_manager/mint.rs +0 -252
- package/contracts/sac-manager/src/tests/sac_manager/set_oft_address.rs +0 -47
- package/contracts/sac-manager/src/tests/sac_manager/test_helper.rs +0 -75
- package/contracts/sac-manager/src/tests/sac_manager/view_functions.rs +0 -60
- package/contracts/sac-manager/src/tests/supply_control/enumerable_set.rs +0 -256
- package/contracts/sac-manager/src/tests/supply_control/mod.rs +0 -8
- package/contracts/sac-manager/src/tests/supply_control/refill.rs +0 -90
- package/contracts/sac-manager/src/tests/supply_control/set_mint_whitelist.rs +0 -245
- package/contracts/sac-manager/src/tests/supply_control/set_supply_controller.rs +0 -267
- package/contracts/sac-manager/src/tests/supply_control/set_supply_controller_manager.rs +0 -122
- package/contracts/sac-manager/src/tests/supply_control/test_helper.rs +0 -38
- package/contracts/sac-manager/src/tests/supply_control/update_allow_any_mint_burn.rs +0 -114
- package/contracts/sac-manager/src/tests/supply_control/update_limit_config.rs +0 -257
- /package/contracts/{sac-manager → oapps/sac-manager}/Cargo.toml +0 -0
- /package/contracts/{sac-manager → oapps/sac-manager}/src/tests/sac_manager/set_admin.rs +0 -0
- /package/contracts/{sac-manager → oapps/sac-manager}/src/tests/sac_manager/set_authorized.rs +0 -0
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
//! authorized_mint Integration Tests
|
|
2
|
-
//!
|
|
3
|
-
//! Core mint logic (supply control, redistribution, events) is tested via
|
|
4
|
-
//! MintBurnable tests in `mint.rs`. These tests focus on authorized_mint-specific
|
|
5
|
-
//! behavior: auth, owner fallback, and supply controllers calling directly.
|
|
6
|
-
|
|
7
|
-
use super::test_helper::{mock_authorized_mint_auth, mock_set_authorized_auth, mock_set_supply_controller_auth};
|
|
8
|
-
use crate::errors::SacManagerError;
|
|
9
|
-
use crate::extensions::redistribution::RedistributeFunds;
|
|
10
|
-
use crate::extensions::supply_control::SupplyIncreased;
|
|
11
|
-
use crate::extensions::supply_control::{LimitConfig, SupplyControlError, SupplyControllerConfig};
|
|
12
|
-
use crate::tests::test_helper::TestSetup;
|
|
13
|
-
use soroban_sdk::{testutils::IssuerFlags, Vec};
|
|
14
|
-
use utils::testing_utils::{assert_contains_event, assert_contains_events};
|
|
15
|
-
|
|
16
|
-
// =========================================================================
|
|
17
|
-
// authorized_mint Tests (without Supply Control — owner only)
|
|
18
|
-
// =========================================================================
|
|
19
|
-
|
|
20
|
-
#[test]
|
|
21
|
-
fn test_authorized_mint_by_owner() {
|
|
22
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
23
|
-
let recipient = setup.generate_address();
|
|
24
|
-
|
|
25
|
-
mock_authorized_mint_auth(&setup, &setup.owner, &recipient, 1000_i128);
|
|
26
|
-
setup.sac_manager_client.authorized_mint(&setup.owner, &recipient, &1000);
|
|
27
|
-
assert_eq!(setup.sac_client.balance(&recipient), 1000);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
#[test]
|
|
31
|
-
fn test_authorized_mint_redistributes_when_recipient_blacklisted() {
|
|
32
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().with_redistribution_enabled().build();
|
|
33
|
-
let blacklisted_recipient = setup.generate_address();
|
|
34
|
-
|
|
35
|
-
// Enable issuer flags required for blacklist and clawback behavior in SAC tests.
|
|
36
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::RevocableFlag);
|
|
37
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::ClawbackEnabledFlag);
|
|
38
|
-
|
|
39
|
-
mock_set_authorized_auth(&setup, &blacklisted_recipient, false);
|
|
40
|
-
setup.sac_manager_client.set_authorized(&blacklisted_recipient, &false);
|
|
41
|
-
assert!(!setup.sac_client.authorized(&blacklisted_recipient));
|
|
42
|
-
|
|
43
|
-
let owner_balance_before = setup.sac_client.balance(&setup.owner);
|
|
44
|
-
let blacklisted_balance_before = setup.sac_client.balance(&blacklisted_recipient);
|
|
45
|
-
|
|
46
|
-
// authorized_mint resolves recipient to owner when target is blacklisted (redistribution path).
|
|
47
|
-
mock_authorized_mint_auth(&setup, &setup.owner, &blacklisted_recipient, 700_i128);
|
|
48
|
-
setup.sac_manager_client.authorized_mint(&setup.owner, &blacklisted_recipient, &700);
|
|
49
|
-
|
|
50
|
-
// No SupplyIncreased when supply control is off; only RedistributeFunds is emitted.
|
|
51
|
-
let expected = RedistributeFunds { user: blacklisted_recipient.clone(), amount: 700 };
|
|
52
|
-
assert_contains_event(&setup.env, &setup.sac_manager, expected);
|
|
53
|
-
|
|
54
|
-
assert_eq!(setup.sac_client.balance(&blacklisted_recipient), blacklisted_balance_before);
|
|
55
|
-
assert_eq!(setup.sac_client.balance(&setup.owner), owner_balance_before + 700);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
#[test]
|
|
59
|
-
fn test_authorized_mint_by_non_owner_fails_without_supply_control() {
|
|
60
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
61
|
-
let recipient = setup.generate_address();
|
|
62
|
-
let random = setup.generate_address();
|
|
63
|
-
|
|
64
|
-
// Supply control is off — only owner can call
|
|
65
|
-
mock_authorized_mint_auth(&setup, &random, &recipient, 1000_i128);
|
|
66
|
-
let result = setup.sac_manager_client.try_authorized_mint(&random, &recipient, &1000);
|
|
67
|
-
assert_eq!(result.err().unwrap().unwrap(), SacManagerError::Unauthorized.into());
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// =========================================================================
|
|
71
|
-
// authorized_mint Tests (with Supply Control)
|
|
72
|
-
// =========================================================================
|
|
73
|
-
|
|
74
|
-
#[test]
|
|
75
|
-
fn test_authorized_mint_by_supply_controller() {
|
|
76
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().with_supply_control_enabled().build();
|
|
77
|
-
let recipient = setup.generate_address();
|
|
78
|
-
let controller = setup.generate_address();
|
|
79
|
-
|
|
80
|
-
let config = SupplyControllerConfig {
|
|
81
|
-
limit_config: LimitConfig { limit_capacity: 10_000, refill_per_second: 0 },
|
|
82
|
-
allow_any_mint_burn: true,
|
|
83
|
-
whitelist_addresses: Vec::new(&setup.env),
|
|
84
|
-
};
|
|
85
|
-
mock_set_supply_controller_auth(&setup, &setup.sc_manager, &controller, &Some(config.clone()));
|
|
86
|
-
setup.sac_manager_client.set_supply_controller(&setup.sc_manager, &controller, &Some(config.clone()));
|
|
87
|
-
|
|
88
|
-
mock_authorized_mint_auth(&setup, &controller, &recipient, 1000_i128);
|
|
89
|
-
setup.sac_manager_client.authorized_mint(&controller, &recipient, &1000);
|
|
90
|
-
assert_eq!(setup.sac_client.balance(&recipient), 1000);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
#[test]
|
|
94
|
-
fn test_authorized_mint_by_owner_fails_with_supply_control_without_config() {
|
|
95
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().with_supply_control_enabled().build();
|
|
96
|
-
let recipient = setup.generate_address();
|
|
97
|
-
|
|
98
|
-
// Owner is not auto-authorized when supply control is enabled and has no controller config.
|
|
99
|
-
mock_authorized_mint_auth(&setup, &setup.owner, &recipient, 1000_i128);
|
|
100
|
-
let result = setup.sac_manager_client.try_authorized_mint(&setup.owner, &recipient, &1000);
|
|
101
|
-
assert_eq!(result.err().unwrap().unwrap(), SupplyControlError::NotFound.into());
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
#[test]
|
|
105
|
-
fn test_authorized_mint_redistributes_with_supply_control_enabled() {
|
|
106
|
-
let setup = TestSetup::new()
|
|
107
|
-
.with_manager_as_sac_admin()
|
|
108
|
-
.with_supply_control_enabled()
|
|
109
|
-
.with_redistribution_enabled()
|
|
110
|
-
.build();
|
|
111
|
-
let controller = setup.generate_address();
|
|
112
|
-
let blacklisted_recipient = setup.generate_address();
|
|
113
|
-
|
|
114
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::RevocableFlag);
|
|
115
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::ClawbackEnabledFlag);
|
|
116
|
-
|
|
117
|
-
// Force redistribution path by blacklisting recipient.
|
|
118
|
-
mock_set_authorized_auth(&setup, &blacklisted_recipient, false);
|
|
119
|
-
setup.sac_manager_client.set_authorized(&blacklisted_recipient, &false);
|
|
120
|
-
assert!(!setup.sac_client.authorized(&blacklisted_recipient));
|
|
121
|
-
|
|
122
|
-
let config = SupplyControllerConfig {
|
|
123
|
-
limit_config: LimitConfig { limit_capacity: 10_000, refill_per_second: 0 },
|
|
124
|
-
allow_any_mint_burn: true,
|
|
125
|
-
whitelist_addresses: Vec::new(&setup.env),
|
|
126
|
-
};
|
|
127
|
-
mock_set_supply_controller_auth(&setup, &setup.sc_manager, &controller, &Some(config.clone()));
|
|
128
|
-
setup.sac_manager_client.set_supply_controller(&setup.sc_manager, &controller, &Some(config));
|
|
129
|
-
|
|
130
|
-
let owner_balance_before = setup.sac_client.balance(&setup.owner);
|
|
131
|
-
let blacklisted_balance_before = setup.sac_client.balance(&blacklisted_recipient);
|
|
132
|
-
|
|
133
|
-
mock_authorized_mint_auth(&setup, &controller, &blacklisted_recipient, 700_i128);
|
|
134
|
-
setup.sac_manager_client.authorized_mint(&controller, &blacklisted_recipient, &700);
|
|
135
|
-
|
|
136
|
-
let expected = SupplyIncreased { controller: controller.clone(), to: blacklisted_recipient.clone(), amount: 700 };
|
|
137
|
-
let expected2 = RedistributeFunds { user: blacklisted_recipient.clone(), amount: 700 };
|
|
138
|
-
assert_contains_events(&setup.env, &setup.sac_manager, &[&expected, &expected2]);
|
|
139
|
-
|
|
140
|
-
assert_eq!(setup.sac_client.balance(&blacklisted_recipient), blacklisted_balance_before);
|
|
141
|
-
assert_eq!(setup.sac_client.balance(&setup.owner), owner_balance_before + 700);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
#[test]
|
|
145
|
-
fn test_authorized_mint_succeeds_when_amount_equals_rate_limit() {
|
|
146
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().with_supply_control_enabled().build();
|
|
147
|
-
let recipient = setup.generate_address();
|
|
148
|
-
let controller = setup.generate_address();
|
|
149
|
-
|
|
150
|
-
let config = SupplyControllerConfig {
|
|
151
|
-
limit_config: LimitConfig { limit_capacity: 1_000, refill_per_second: 1 },
|
|
152
|
-
allow_any_mint_burn: true,
|
|
153
|
-
whitelist_addresses: Vec::new(&setup.env),
|
|
154
|
-
};
|
|
155
|
-
mock_set_supply_controller_auth(&setup, &setup.sc_manager, &controller, &Some(config.clone()));
|
|
156
|
-
setup.sac_manager_client.set_supply_controller(&setup.sc_manager, &controller, &Some(config));
|
|
157
|
-
|
|
158
|
-
mock_authorized_mint_auth(&setup, &controller, &recipient, 1000_i128);
|
|
159
|
-
setup.sac_manager_client.authorized_mint(&controller, &recipient, &1000);
|
|
160
|
-
assert_eq!(setup.sac_client.balance(&recipient), 1000);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
#[test]
|
|
164
|
-
fn test_authorized_mint_fails_when_amount_exceeds_rate_limit() {
|
|
165
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().with_supply_control_enabled().build();
|
|
166
|
-
let recipient = setup.generate_address();
|
|
167
|
-
let controller = setup.generate_address();
|
|
168
|
-
|
|
169
|
-
let config = SupplyControllerConfig {
|
|
170
|
-
limit_config: LimitConfig { limit_capacity: 1_000, refill_per_second: 1 },
|
|
171
|
-
allow_any_mint_burn: true,
|
|
172
|
-
whitelist_addresses: Vec::new(&setup.env),
|
|
173
|
-
};
|
|
174
|
-
mock_set_supply_controller_auth(&setup, &setup.sc_manager, &controller, &Some(config.clone()));
|
|
175
|
-
setup.sac_manager_client.set_supply_controller(&setup.sc_manager, &controller, &Some(config));
|
|
176
|
-
|
|
177
|
-
mock_authorized_mint_auth(&setup, &controller, &recipient, 1001_i128);
|
|
178
|
-
let result = setup.sac_manager_client.try_authorized_mint(&controller, &recipient, &1001);
|
|
179
|
-
assert_eq!(result.err().unwrap().unwrap(), SupplyControlError::RateLimitExceeded.into());
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
#[test]
|
|
183
|
-
fn test_authorized_mint_fails_without_supply_controller_config() {
|
|
184
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().with_supply_control_enabled().build();
|
|
185
|
-
let recipient = setup.generate_address();
|
|
186
|
-
let random = setup.generate_address();
|
|
187
|
-
|
|
188
|
-
// Supply control enabled but sender is NOT a supply controller
|
|
189
|
-
mock_authorized_mint_auth(&setup, &random, &recipient, 1000_i128);
|
|
190
|
-
let result = setup.sac_manager_client.try_authorized_mint(&random, &recipient, &1000);
|
|
191
|
-
assert_eq!(result.err().unwrap().unwrap(), SupplyControlError::NotFound.into());
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// =========================================================================
|
|
195
|
-
// authorized_mint Auth Tests
|
|
196
|
-
// =========================================================================
|
|
197
|
-
|
|
198
|
-
#[test]
|
|
199
|
-
#[should_panic(expected = "Error(Auth, InvalidAction)")]
|
|
200
|
-
fn test_authorized_mint_without_auth() {
|
|
201
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
202
|
-
let recipient = setup.generate_address();
|
|
203
|
-
|
|
204
|
-
// No auth mocked — sender.require_auth() fails
|
|
205
|
-
setup.sac_manager_client.authorized_mint(&setup.owner, &recipient, &1000);
|
|
206
|
-
}
|
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
//! Burn (MintBurnable) Integration Tests
|
|
2
|
-
//!
|
|
3
|
-
//! Burn tests use explicit mock_auth setup so nested auth for `sac.burn`
|
|
4
|
-
//! (`from.require_auth()`) is asserted deterministically.
|
|
5
|
-
|
|
6
|
-
use super::test_helper::{mock_sac_owner_mint_auth, mock_set_mint_whitelist_auth, mock_set_supply_controller_auth};
|
|
7
|
-
use crate::errors::SacManagerError;
|
|
8
|
-
use crate::extensions::supply_control::{LimitConfig, SupplyControlClient, SupplyControlError, SupplyControllerConfig};
|
|
9
|
-
use crate::tests::sac_manager::test_helper::mock_burn_auth;
|
|
10
|
-
use crate::tests::test_helper::{mock_auth, mock_oft_mint_auth, TestSetup};
|
|
11
|
-
use crate::extensions::supply_control::SupplyDecreased;
|
|
12
|
-
use soroban_sdk::Vec;
|
|
13
|
-
use utils::testing_utils::assert_contains_event;
|
|
14
|
-
|
|
15
|
-
// =========================================================================
|
|
16
|
-
// Burn Tests (with Supply Control)
|
|
17
|
-
// =========================================================================
|
|
18
|
-
|
|
19
|
-
#[test]
|
|
20
|
-
fn test_burn_by_oft_with_supply_control() {
|
|
21
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().with_supply_control_enabled().build();
|
|
22
|
-
|
|
23
|
-
let config = SupplyControllerConfig {
|
|
24
|
-
limit_config: LimitConfig { limit_capacity: 10_000, refill_per_second: 0 },
|
|
25
|
-
allow_any_mint_burn: true,
|
|
26
|
-
whitelist_addresses: Vec::new(&setup.env),
|
|
27
|
-
};
|
|
28
|
-
mock_set_supply_controller_auth(&setup, &setup.sc_manager, &setup.oft, &Some(config.clone()));
|
|
29
|
-
setup.sac_manager_client.set_supply_controller(&setup.sc_manager, &setup.oft, &Some(config.clone()));
|
|
30
|
-
|
|
31
|
-
// Mint tokens to OFT
|
|
32
|
-
mock_oft_mint_auth(&setup, &setup.oft, 1000_i128);
|
|
33
|
-
setup.sac_manager_client.mint(&setup.oft, &1000);
|
|
34
|
-
assert_eq!(setup.sac_client.balance(&setup.oft), 1000);
|
|
35
|
-
|
|
36
|
-
// OFT burns its own tokens
|
|
37
|
-
mock_burn_auth(&setup, &setup.oft, 500_i128);
|
|
38
|
-
setup.sac_manager_client.burn(&setup.oft, &500);
|
|
39
|
-
let expected = SupplyDecreased { controller: setup.oft.clone(), from: setup.oft.clone(), amount: 500 };
|
|
40
|
-
assert_contains_event(&setup.env, &setup.sac_manager, expected);
|
|
41
|
-
assert_eq!(setup.sac_client.balance(&setup.oft), 500);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
#[test]
|
|
45
|
-
fn test_burn_from_user_by_oft() {
|
|
46
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().with_supply_control_enabled().build();
|
|
47
|
-
let user = setup.generate_address();
|
|
48
|
-
|
|
49
|
-
let config = SupplyControllerConfig {
|
|
50
|
-
limit_config: LimitConfig { limit_capacity: 10_000, refill_per_second: 0 },
|
|
51
|
-
allow_any_mint_burn: true,
|
|
52
|
-
whitelist_addresses: Vec::new(&setup.env),
|
|
53
|
-
};
|
|
54
|
-
mock_set_supply_controller_auth(&setup, &setup.sc_manager, &setup.oft, &Some(config.clone()));
|
|
55
|
-
setup.sac_manager_client.set_supply_controller(&setup.sc_manager, &setup.oft, &Some(config.clone()));
|
|
56
|
-
|
|
57
|
-
// Mint tokens to user
|
|
58
|
-
mock_oft_mint_auth(&setup, &user, 1000_i128);
|
|
59
|
-
setup.sac_manager_client.mint(&user, &1000);
|
|
60
|
-
assert_eq!(setup.sac_client.balance(&user), 1000);
|
|
61
|
-
|
|
62
|
-
// OFT burns tokens from user (user authorizes at SAC level)
|
|
63
|
-
mock_burn_auth(&setup, &user, 500_i128);
|
|
64
|
-
setup.sac_manager_client.burn(&user, &500);
|
|
65
|
-
let expected = SupplyDecreased { controller: setup.oft.clone(), from: user.clone(), amount: 500 };
|
|
66
|
-
assert_contains_event(&setup.env, &setup.sac_manager, expected);
|
|
67
|
-
assert_eq!(setup.sac_client.balance(&user), 500);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
#[test]
|
|
71
|
-
fn test_burn_from_self_fails_when_allow_any_mint_burn_is_false() {
|
|
72
|
-
let setup = TestSetup::new().with_supply_control_enabled().build();
|
|
73
|
-
|
|
74
|
-
let config = SupplyControllerConfig {
|
|
75
|
-
limit_config: LimitConfig { limit_capacity: 10_000, refill_per_second: 0 },
|
|
76
|
-
allow_any_mint_burn: false,
|
|
77
|
-
whitelist_addresses: Vec::new(&setup.env),
|
|
78
|
-
};
|
|
79
|
-
mock_set_supply_controller_auth(&setup, &setup.sc_manager, &setup.oft, &Some(config.clone()));
|
|
80
|
-
setup.sac_manager_client.set_supply_controller(&setup.sc_manager, &setup.oft, &Some(config.clone()));
|
|
81
|
-
|
|
82
|
-
// Mint to OFT directly via SAC owner
|
|
83
|
-
mock_sac_owner_mint_auth(&setup, &setup.oft, 1000_i128);
|
|
84
|
-
setup.sac_client.mint(&setup.oft, &1000);
|
|
85
|
-
assert_eq!(setup.sac_client.balance(&setup.oft), 1000);
|
|
86
|
-
|
|
87
|
-
// Burn-from-self should fail when allow_any_mint_burn is false
|
|
88
|
-
mock_burn_auth(&setup, &setup.oft, 500_i128);
|
|
89
|
-
let result = setup.sac_manager_client.try_burn(&setup.oft, &500);
|
|
90
|
-
assert_eq!(result.err().unwrap().unwrap(), SupplyControlError::CannotBurnFromAddress.into());
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// =========================================================================
|
|
94
|
-
// Burn Error Cases (Supply Control)
|
|
95
|
-
// =========================================================================
|
|
96
|
-
|
|
97
|
-
#[test]
|
|
98
|
-
fn test_burn_fails_when_oft_not_supply_controller() {
|
|
99
|
-
let setup = TestSetup::new().with_supply_control_enabled().build();
|
|
100
|
-
let user = setup.generate_address();
|
|
101
|
-
|
|
102
|
-
// Mint tokens to user directly via SAC (bypassing supply control).
|
|
103
|
-
// Here SAC admin is still owner (not sac_manager), so owner can mint.
|
|
104
|
-
mock_sac_owner_mint_auth(&setup, &user, 1000_i128);
|
|
105
|
-
setup.sac_client.mint(&user, &1000);
|
|
106
|
-
|
|
107
|
-
// OFT is NOT added as supply controller — burn should fail
|
|
108
|
-
mock_burn_auth(&setup, &user, 500_i128);
|
|
109
|
-
let result = setup.sac_manager_client.try_burn(&user, &500);
|
|
110
|
-
assert_eq!(result.err().unwrap().unwrap(), SupplyControlError::NotFound.into());
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
#[test]
|
|
114
|
-
fn test_burn_fails_when_controller_cannot_burn_from_address() {
|
|
115
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().with_supply_control_enabled().build();
|
|
116
|
-
let user = setup.generate_address();
|
|
117
|
-
|
|
118
|
-
// OFT as controller WITHOUT allow_any_mint_burn
|
|
119
|
-
let config = SupplyControllerConfig {
|
|
120
|
-
limit_config: LimitConfig { limit_capacity: 10_000, refill_per_second: 0 },
|
|
121
|
-
allow_any_mint_burn: false,
|
|
122
|
-
whitelist_addresses: Vec::new(&setup.env),
|
|
123
|
-
};
|
|
124
|
-
mock_set_supply_controller_auth(&setup, &setup.sc_manager, &setup.oft, &Some(config.clone()));
|
|
125
|
-
setup.sac_manager_client.set_supply_controller(&setup.sc_manager, &setup.oft, &Some(config.clone()));
|
|
126
|
-
|
|
127
|
-
// Whitelist user for OFT controller to allow minting (allow_any=false)
|
|
128
|
-
let sc_client = SupplyControlClient::new(&setup.env, &setup.sac_manager);
|
|
129
|
-
mock_set_mint_whitelist_auth(&setup, &setup.sc_manager, &setup.oft, &user, true);
|
|
130
|
-
sc_client.set_mint_whitelist(&setup.sc_manager, &setup.oft, &user, &true);
|
|
131
|
-
|
|
132
|
-
// Mint tokens to user
|
|
133
|
-
mock_oft_mint_auth(&setup, &user, 1000_i128);
|
|
134
|
-
setup.sac_manager_client.mint(&user, &1000);
|
|
135
|
-
|
|
136
|
-
// OFT tries to burn from user without allow_any_mint_burn - should fail
|
|
137
|
-
mock_burn_auth(&setup, &user, 500_i128);
|
|
138
|
-
let result = setup.sac_manager_client.try_burn(&user, &500);
|
|
139
|
-
assert_eq!(result.err().unwrap().unwrap(), SupplyControlError::CannotBurnFromAddress.into());
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// =========================================================================
|
|
143
|
-
// Burn Tests (without Supply Control) — OFT calls burn
|
|
144
|
-
// =========================================================================
|
|
145
|
-
|
|
146
|
-
#[test]
|
|
147
|
-
fn test_burn_by_oft_without_supply_control() {
|
|
148
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
149
|
-
|
|
150
|
-
// Supply control is disabled by default
|
|
151
|
-
assert!(!setup.sac_manager_client.supply_control_enabled());
|
|
152
|
-
|
|
153
|
-
// Mint tokens to OFT first
|
|
154
|
-
mock_oft_mint_auth(&setup, &setup.oft, 1000_i128);
|
|
155
|
-
setup.sac_manager_client.mint(&setup.oft, &1000);
|
|
156
|
-
assert_eq!(setup.sac_client.balance(&setup.oft), 1000);
|
|
157
|
-
|
|
158
|
-
// OFT can burn when supply control is disabled
|
|
159
|
-
mock_burn_auth(&setup, &setup.oft, 500_i128);
|
|
160
|
-
setup.sac_manager_client.burn(&setup.oft, &500);
|
|
161
|
-
assert_eq!(setup.sac_client.balance(&setup.oft), 500);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
#[test]
|
|
165
|
-
fn test_burn_fails_when_amount_exceeds_balance() {
|
|
166
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
167
|
-
|
|
168
|
-
mock_oft_mint_auth(&setup, &setup.oft, 100_i128);
|
|
169
|
-
setup.sac_manager_client.mint(&setup.oft, &100);
|
|
170
|
-
assert_eq!(setup.sac_client.balance(&setup.oft), 100);
|
|
171
|
-
|
|
172
|
-
mock_burn_auth(&setup, &setup.oft, 200_i128);
|
|
173
|
-
let result = setup.sac_manager_client.try_burn(&setup.oft, &200);
|
|
174
|
-
assert!(result.is_err());
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
#[test]
|
|
178
|
-
fn test_burn_fails_when_oft_not_set() {
|
|
179
|
-
let setup = TestSetup::new().without_oft().build();
|
|
180
|
-
let user = setup.generate_address();
|
|
181
|
-
|
|
182
|
-
// Mock from auth so we pass from.require_auth() and reach the OFT address check
|
|
183
|
-
mock_auth(&setup.env, &setup.sac_manager, &user, "burn", (&user, 500_i128));
|
|
184
|
-
let result = setup.sac_manager_client.try_burn(&user, &500);
|
|
185
|
-
assert_eq!(result.err().unwrap().unwrap(), SacManagerError::OftAddressNotSet.into());
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// =========================================================================
|
|
189
|
-
// Burn Auth Tests
|
|
190
|
-
// =========================================================================
|
|
191
|
-
|
|
192
|
-
#[test]
|
|
193
|
-
#[should_panic(expected = "Error(Auth, InvalidAction)")]
|
|
194
|
-
fn test_burn_fails_without_oft_auth() {
|
|
195
|
-
// No mock_burn_auth — the OFT address won't be authorized
|
|
196
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
197
|
-
let user = setup.generate_address();
|
|
198
|
-
|
|
199
|
-
setup.sac_manager_client.burn(&user, &500);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
#[test]
|
|
203
|
-
#[should_panic(expected = "Error(Auth, InvalidAction)")]
|
|
204
|
-
fn test_burn_fails_without_from_auth_even_if_oft_auth_present() {
|
|
205
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
206
|
-
let user = setup.generate_address();
|
|
207
|
-
|
|
208
|
-
mock_oft_mint_auth(&setup, &user, 1000_i128);
|
|
209
|
-
setup.sac_manager_client.mint(&user, &1000);
|
|
210
|
-
assert_eq!(setup.sac_client.balance(&user), 1000);
|
|
211
|
-
|
|
212
|
-
// Only root OFT auth is mocked; nested SAC burn auth for `from` is intentionally missing.
|
|
213
|
-
mock_auth(&setup.env, &setup.sac_manager, &setup.oft, "burn", (&user, 500_i128));
|
|
214
|
-
setup.sac_manager_client.burn(&user, &500);
|
|
215
|
-
}
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
//! Clawback Integration Tests
|
|
2
|
-
//!
|
|
3
|
-
//! Tests for admin-initiated clawback functionality via `clawback`.
|
|
4
|
-
//! The clawback operation uses SAC clawback, which requires AUTH_CLAWBACK_ENABLED
|
|
5
|
-
//! flag on the SAC issuer.
|
|
6
|
-
//!
|
|
7
|
-
//! Core burn logic (supply control validation) is shared with MintBurnable::burn
|
|
8
|
-
//! in `burn.rs`. These tests focus on clawback-specific behavior: auth, owner
|
|
9
|
-
//! fallback, clawback mechanics, and supply controllers calling directly.
|
|
10
|
-
|
|
11
|
-
use super::test_helper::{mock_authorized_mint_auth, mock_clawback_auth, mock_set_supply_controller_auth};
|
|
12
|
-
use crate::errors::SacManagerError;
|
|
13
|
-
use crate::extensions::supply_control::{LimitConfig, SupplyControlError, SupplyControllerConfig, SupplyDecreased};
|
|
14
|
-
use crate::tests::test_helper::TestSetup;
|
|
15
|
-
use soroban_sdk::{testutils::IssuerFlags, Vec};
|
|
16
|
-
use utils::testing_utils::assert_contains_event;
|
|
17
|
-
|
|
18
|
-
// =========================================================================
|
|
19
|
-
// clawback Tests (without Supply Control — owner only)
|
|
20
|
-
// =========================================================================
|
|
21
|
-
|
|
22
|
-
#[test]
|
|
23
|
-
fn test_clawback_by_owner() {
|
|
24
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
25
|
-
let user = setup.generate_address();
|
|
26
|
-
|
|
27
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::RevocableFlag);
|
|
28
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::ClawbackEnabledFlag);
|
|
29
|
-
|
|
30
|
-
// Mint tokens to user first
|
|
31
|
-
mock_authorized_mint_auth(&setup, &setup.owner, &user, 1000_i128);
|
|
32
|
-
setup.sac_manager_client.authorized_mint(&setup.owner, &user, &1000);
|
|
33
|
-
assert_eq!(setup.sac_client.balance(&user), 1000);
|
|
34
|
-
|
|
35
|
-
// Owner clawbacks tokens from user (no SupplyDecreased event when supply control is off)
|
|
36
|
-
mock_clawback_auth(&setup, &setup.owner, &user, 500_i128);
|
|
37
|
-
setup.sac_manager_client.clawback(&setup.owner, &user, &500);
|
|
38
|
-
assert_eq!(setup.sac_client.balance(&user), 500);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
#[test]
|
|
42
|
-
fn test_clawback_full_balance() {
|
|
43
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
44
|
-
let user = setup.generate_address();
|
|
45
|
-
|
|
46
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::RevocableFlag);
|
|
47
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::ClawbackEnabledFlag);
|
|
48
|
-
|
|
49
|
-
mock_authorized_mint_auth(&setup, &setup.owner, &user, 1000_i128);
|
|
50
|
-
setup.sac_manager_client.authorized_mint(&setup.owner, &user, &1000);
|
|
51
|
-
|
|
52
|
-
// Clawback full balance (boundary case: amount == balance)
|
|
53
|
-
mock_clawback_auth(&setup, &setup.owner, &user, 1000_i128);
|
|
54
|
-
setup.sac_manager_client.clawback(&setup.owner, &user, &1000);
|
|
55
|
-
assert_eq!(setup.sac_client.balance(&user), 0);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
#[test]
|
|
59
|
-
fn test_clawback_fails_when_amount_exceeds_balance() {
|
|
60
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
61
|
-
let user = setup.generate_address();
|
|
62
|
-
|
|
63
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::RevocableFlag);
|
|
64
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::ClawbackEnabledFlag);
|
|
65
|
-
|
|
66
|
-
mock_authorized_mint_auth(&setup, &setup.owner, &user, 100_i128);
|
|
67
|
-
setup.sac_manager_client.authorized_mint(&setup.owner, &user, &100);
|
|
68
|
-
|
|
69
|
-
mock_clawback_auth(&setup, &setup.owner, &user, 200_i128);
|
|
70
|
-
let result = setup.sac_manager_client.try_clawback(&setup.owner, &user, &200);
|
|
71
|
-
assert!(result.is_err());
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
#[test]
|
|
75
|
-
fn test_clawback_by_non_owner_fails_without_supply_control() {
|
|
76
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
77
|
-
let user = setup.generate_address();
|
|
78
|
-
let random = setup.generate_address();
|
|
79
|
-
|
|
80
|
-
// Supply control is off — only owner can call
|
|
81
|
-
mock_clawback_auth(&setup, &random, &user, 500_i128);
|
|
82
|
-
let result = setup.sac_manager_client.try_clawback(&random, &user, &500);
|
|
83
|
-
assert_eq!(result.err().unwrap().unwrap(), SacManagerError::Unauthorized.into());
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// =========================================================================
|
|
87
|
-
// clawback Tests (with Supply Control)
|
|
88
|
-
// =========================================================================
|
|
89
|
-
|
|
90
|
-
#[test]
|
|
91
|
-
fn test_clawback_by_supply_controller() {
|
|
92
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().with_supply_control_enabled().build();
|
|
93
|
-
let user = setup.generate_address();
|
|
94
|
-
let controller = setup.generate_address();
|
|
95
|
-
|
|
96
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::RevocableFlag);
|
|
97
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::ClawbackEnabledFlag);
|
|
98
|
-
|
|
99
|
-
let config = SupplyControllerConfig {
|
|
100
|
-
limit_config: LimitConfig { limit_capacity: 10_000, refill_per_second: 0 },
|
|
101
|
-
allow_any_mint_burn: true,
|
|
102
|
-
whitelist_addresses: Vec::new(&setup.env),
|
|
103
|
-
};
|
|
104
|
-
mock_set_supply_controller_auth(&setup, &setup.sc_manager, &controller, &Some(config.clone()));
|
|
105
|
-
setup.sac_manager_client.set_supply_controller(&setup.sc_manager, &controller, &Some(config));
|
|
106
|
-
|
|
107
|
-
// Mint tokens to user via controller
|
|
108
|
-
mock_authorized_mint_auth(&setup, &controller, &user, 1000_i128);
|
|
109
|
-
setup.sac_manager_client.authorized_mint(&controller, &user, &1000);
|
|
110
|
-
assert_eq!(setup.sac_client.balance(&user), 1000);
|
|
111
|
-
|
|
112
|
-
// Controller clawbacks from user
|
|
113
|
-
mock_clawback_auth(&setup, &controller, &user, 500_i128);
|
|
114
|
-
setup.sac_manager_client.clawback(&controller, &user, &500);
|
|
115
|
-
|
|
116
|
-
let expected = SupplyDecreased { controller: controller.clone(), from: user.clone(), amount: 500 };
|
|
117
|
-
assert_contains_event(&setup.env, &setup.sac_manager, expected);
|
|
118
|
-
|
|
119
|
-
assert_eq!(setup.sac_client.balance(&user), 500);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
#[test]
|
|
123
|
-
fn test_clawback_by_owner_fails_with_supply_control_without_config() {
|
|
124
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().with_supply_control_enabled().build();
|
|
125
|
-
let user = setup.generate_address();
|
|
126
|
-
|
|
127
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::RevocableFlag);
|
|
128
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::ClawbackEnabledFlag);
|
|
129
|
-
|
|
130
|
-
// Owner is not auto-authorized when supply control is enabled and has no controller config.
|
|
131
|
-
mock_clawback_auth(&setup, &setup.owner, &user, 500_i128);
|
|
132
|
-
let result = setup.sac_manager_client.try_clawback(&setup.owner, &user, &500);
|
|
133
|
-
assert_eq!(result.err().unwrap().unwrap(), SupplyControlError::NotFound.into());
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
#[test]
|
|
137
|
-
fn test_clawback_fails_without_supply_controller_config() {
|
|
138
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().with_supply_control_enabled().build();
|
|
139
|
-
let user = setup.generate_address();
|
|
140
|
-
let random = setup.generate_address();
|
|
141
|
-
|
|
142
|
-
// Supply control enabled but sender is NOT a supply controller
|
|
143
|
-
mock_clawback_auth(&setup, &random, &user, 500_i128);
|
|
144
|
-
let result = setup.sac_manager_client.try_clawback(&random, &user, &500);
|
|
145
|
-
assert_eq!(result.err().unwrap().unwrap(), SupplyControlError::NotFound.into());
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
#[test]
|
|
149
|
-
fn test_clawback_fails_when_controller_cannot_burn_from_address() {
|
|
150
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().with_supply_control_enabled().build();
|
|
151
|
-
let user = setup.generate_address();
|
|
152
|
-
let controller = setup.generate_address();
|
|
153
|
-
|
|
154
|
-
// Controller WITHOUT allow_any_mint_burn
|
|
155
|
-
let config = SupplyControllerConfig {
|
|
156
|
-
limit_config: LimitConfig { limit_capacity: 10_000, refill_per_second: 0 },
|
|
157
|
-
allow_any_mint_burn: false,
|
|
158
|
-
whitelist_addresses: Vec::new(&setup.env),
|
|
159
|
-
};
|
|
160
|
-
mock_set_supply_controller_auth(&setup, &setup.sc_manager, &controller, &Some(config.clone()));
|
|
161
|
-
setup.sac_manager_client.set_supply_controller(&setup.sc_manager, &controller, &Some(config));
|
|
162
|
-
|
|
163
|
-
// Controller tries to burn from user without allow_any_mint_burn — should fail
|
|
164
|
-
mock_clawback_auth(&setup, &controller, &user, 500_i128);
|
|
165
|
-
let result = setup.sac_manager_client.try_clawback(&controller, &user, &500);
|
|
166
|
-
assert_eq!(result.err().unwrap().unwrap(), SupplyControlError::CannotBurnFromAddress.into());
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
#[test]
|
|
170
|
-
fn test_clawback_by_controller_from_self() {
|
|
171
|
-
let setup = TestSetup::new().with_manager_as_sac_admin().with_supply_control_enabled().build();
|
|
172
|
-
let controller = setup.generate_address();
|
|
173
|
-
|
|
174
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::RevocableFlag);
|
|
175
|
-
setup.sac_contract.issuer().set_flag(IssuerFlags::ClawbackEnabledFlag);
|
|
176
|
-
|
|
177
|
-
// Controller WITH allow_any_mint_burn — required for any burn including from self
|
|
178
|
-
let config = SupplyControllerConfig {
|
|
179
|
-
limit_config: LimitConfig { limit_capacity: 10_000, refill_per_second: 0 },
|
|
180
|
-
allow_any_mint_burn: true,
|
|
181
|
-
whitelist_addresses: Vec::new(&setup.env),
|
|
182
|
-
};
|
|
183
|
-
mock_set_supply_controller_auth(&setup, &setup.sc_manager, &controller, &Some(config.clone()));
|
|
184
|
-
setup.sac_manager_client.set_supply_controller(&setup.sc_manager, &controller, &Some(config));
|
|
185
|
-
|
|
186
|
-
// Mint tokens to controller itself
|
|
187
|
-
mock_authorized_mint_auth(&setup, &controller, &controller, 1000_i128);
|
|
188
|
-
setup.sac_manager_client.authorized_mint(&controller, &controller, &1000);
|
|
189
|
-
assert_eq!(setup.sac_client.balance(&controller), 1000);
|
|
190
|
-
|
|
191
|
-
// Controller clawbacks from self — requires allow_any_mint_burn
|
|
192
|
-
mock_clawback_auth(&setup, &controller, &controller, 500_i128);
|
|
193
|
-
setup.sac_manager_client.clawback(&controller, &controller, &500);
|
|
194
|
-
assert_eq!(setup.sac_client.balance(&controller), 500);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// =========================================================================
|
|
198
|
-
// clawback Auth Tests
|
|
199
|
-
// =========================================================================
|
|
200
|
-
|
|
201
|
-
#[test]
|
|
202
|
-
#[should_panic(expected = "Error(Auth, InvalidAction)")]
|
|
203
|
-
fn test_clawback_fails_without_auth() {
|
|
204
|
-
let setup = TestSetup::new().build();
|
|
205
|
-
let user = setup.generate_address();
|
|
206
|
-
|
|
207
|
-
// Should panic because sender doesn't authorize the call
|
|
208
|
-
setup.sac_manager_client.clawback(&setup.owner, &user, &300);
|
|
209
|
-
}
|