@layerzerolabs/protocol-stellar-v2 0.2.35 → 0.2.37

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 (105) hide show
  1. package/.turbo/turbo-build.log +274 -268
  2. package/.turbo/turbo-lint.log +216 -213
  3. package/.turbo/turbo-test.log +1735 -1994
  4. package/contracts/common-macros/src/auth.rs +5 -5
  5. package/contracts/common-macros/src/lib.rs +69 -0
  6. package/contracts/common-macros/src/rbac.rs +90 -0
  7. package/contracts/common-macros/src/tests/lz_contract.rs +5 -7
  8. package/contracts/common-macros/src/tests/mod.rs +1 -0
  9. package/contracts/common-macros/src/tests/rbac.rs +420 -0
  10. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_multisig_code.snap +4 -4
  11. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_ownable_code.snap +5 -12
  12. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__rbac__snapshot_preserve_function_signature.snap +17 -0
  13. package/contracts/common-macros/src/tests/storage/parse_name.rs +0 -1
  14. package/contracts/macro-integration-tests/tests/runtime/lz_contract/wrapper_default.rs +1 -1
  15. package/contracts/macro-integration-tests/tests/runtime/lz_contract/wrapper_multisig.rs +1 -1
  16. package/contracts/macro-integration-tests/tests/runtime/lz_contract/wrapper_multisig_upgradeable.rs +1 -1
  17. package/contracts/macro-integration-tests/tests/runtime/multisig/self_auth.rs +1 -1
  18. package/contracts/macro-integration-tests/tests/runtime/ownable/initialization.rs +8 -5
  19. package/contracts/macro-integration-tests/tests/runtime/ownable/ownership_transfer.rs +2 -2
  20. package/contracts/macro-integration-tests/tests/runtime/rbac/guard_behavior.rs +91 -0
  21. package/contracts/macro-integration-tests/tests/runtime/rbac/mod.rs +30 -0
  22. package/contracts/macro-integration-tests/tests/runtime/ttl_configurable/configuration.rs +2 -2
  23. package/contracts/macro-integration-tests/tests/runtime/upgradeable/migrate_guard_and_state.rs +4 -4
  24. package/contracts/macro-integration-tests/tests/ui/lz_contract/pass/basic.rs +1 -1
  25. package/contracts/macro-integration-tests/tests/ui/ownable/pass/basic.rs +1 -1
  26. package/contracts/macro-integration-tests/tests/ui/rbac/fail/missing_env.rs +18 -0
  27. package/contracts/macro-integration-tests/tests/ui/rbac/fail/missing_env.stderr +16 -0
  28. package/contracts/macro-integration-tests/tests/ui/rbac/fail/param_not_address.rs +18 -0
  29. package/contracts/macro-integration-tests/tests/ui/rbac/fail/param_not_address.stderr +24 -0
  30. package/contracts/macro-integration-tests/tests/ui/rbac/fail/param_not_found.rs +18 -0
  31. package/contracts/macro-integration-tests/tests/ui/rbac/fail/param_not_found.stderr +24 -0
  32. package/contracts/macro-integration-tests/tests/ui/rbac/pass/basic.rs +71 -0
  33. package/contracts/macro-integration-tests/tests/ui_rbac.rs +12 -0
  34. package/contracts/oapps/oft/src/interfaces/mintable.rs +2 -2
  35. package/contracts/oapps/oft/src/tests/extensions/oft_fee.rs +2 -2
  36. package/contracts/oapps/oft/src/tests/extensions/pausable.rs +2 -2
  37. package/contracts/oapps/oft/src/tests/extensions/rate_limiter.rs +2 -2
  38. package/contracts/oapps/sac-manager/Cargo.toml +0 -1
  39. package/contracts/oapps/sac-manager/src/interfaces/mod.rs +3 -0
  40. package/contracts/oapps/sac-manager/src/interfaces/sac_admin_wrapper.rs +49 -0
  41. package/contracts/oapps/sac-manager/src/lib.rs +3 -3
  42. package/contracts/oapps/sac-manager/src/sac_manager.rs +45 -73
  43. package/contracts/oapps/sac-manager/src/storage.rs +2 -9
  44. package/contracts/oapps/sac-manager/src/tests/sac_manager/clawback.rs +8 -10
  45. package/contracts/oapps/sac-manager/src/tests/sac_manager/mint.rs +13 -18
  46. package/contracts/oapps/sac-manager/src/tests/sac_manager/mod.rs +0 -1
  47. package/contracts/oapps/sac-manager/src/tests/sac_manager/set_admin.rs +22 -12
  48. package/contracts/oapps/sac-manager/src/tests/sac_manager/set_authorized.rs +19 -9
  49. package/contracts/oapps/sac-manager/src/tests/sac_manager/test_helper.rs +27 -10
  50. package/contracts/oapps/sac-manager/src/tests/sac_manager/view_functions.rs +0 -15
  51. package/contracts/oapps/sac-manager/src/tests/test_helper.rs +19 -28
  52. package/contracts/upgrader/src/lib.rs +5 -2
  53. package/contracts/utils/src/auth.rs +6 -2
  54. package/contracts/utils/src/errors.rs +18 -0
  55. package/contracts/utils/src/lib.rs +1 -0
  56. package/contracts/utils/src/multisig.rs +5 -1
  57. package/contracts/utils/src/ownable.rs +1 -1
  58. package/contracts/utils/src/rbac.rs +428 -0
  59. package/contracts/utils/src/tests/auth.rs +2 -2
  60. package/contracts/utils/src/tests/mod.rs +1 -0
  61. package/contracts/utils/src/tests/multisig.rs +2 -2
  62. package/contracts/utils/src/tests/ownable.rs +4 -5
  63. package/contracts/utils/src/tests/rbac.rs +559 -0
  64. package/contracts/utils/src/tests/ttl_configurable.rs +5 -6
  65. package/contracts/utils/src/tests/upgradeable.rs +4 -5
  66. package/contracts/workers/worker/src/worker.rs +1 -1
  67. package/package.json +3 -3
  68. package/sdk/.turbo/turbo-test.log +368 -366
  69. package/sdk/dist/generated/bml.d.ts +53 -3
  70. package/sdk/dist/generated/bml.js +27 -3
  71. package/sdk/dist/generated/counter.d.ts +55 -5
  72. package/sdk/dist/generated/counter.js +28 -4
  73. package/sdk/dist/generated/dvn.d.ts +55 -5
  74. package/sdk/dist/generated/dvn.js +28 -4
  75. package/sdk/dist/generated/dvn_fee_lib.d.ts +55 -5
  76. package/sdk/dist/generated/dvn_fee_lib.js +28 -4
  77. package/sdk/dist/generated/endpoint.d.ts +55 -5
  78. package/sdk/dist/generated/endpoint.js +28 -4
  79. package/sdk/dist/generated/executor.d.ts +55 -5
  80. package/sdk/dist/generated/executor.js +28 -4
  81. package/sdk/dist/generated/executor_fee_lib.d.ts +55 -5
  82. package/sdk/dist/generated/executor_fee_lib.js +28 -4
  83. package/sdk/dist/generated/executor_helper.d.ts +53 -3
  84. package/sdk/dist/generated/executor_helper.js +27 -3
  85. package/sdk/dist/generated/layerzero_view.d.ts +55 -5
  86. package/sdk/dist/generated/layerzero_view.js +28 -4
  87. package/sdk/dist/generated/oft.d.ts +55 -5
  88. package/sdk/dist/generated/oft.js +28 -4
  89. package/sdk/dist/generated/price_feed.d.ts +55 -5
  90. package/sdk/dist/generated/price_feed.js +28 -4
  91. package/sdk/dist/generated/sac_manager.d.ts +213 -687
  92. package/sdk/dist/generated/sac_manager.js +57 -239
  93. package/sdk/dist/generated/sml.d.ts +55 -5
  94. package/sdk/dist/generated/sml.js +28 -4
  95. package/sdk/dist/generated/treasury.d.ts +55 -5
  96. package/sdk/dist/generated/treasury.js +28 -4
  97. package/sdk/dist/generated/uln302.d.ts +55 -5
  98. package/sdk/dist/generated/uln302.js +28 -4
  99. package/sdk/dist/generated/upgrader.d.ts +53 -3
  100. package/sdk/dist/generated/upgrader.js +27 -3
  101. package/sdk/package.json +1 -1
  102. package/sdk/test/oft-sml.test.ts +10 -9
  103. package/sdk/test/{sac-manager-redistribution.test.ts → sac-manager.test.ts} +49 -25
  104. package/contracts/oapps/sac-manager/src/errors.rs +0 -14
  105. package/contracts/oapps/sac-manager/src/tests/sac_manager/set_minter.rs +0 -69
@@ -0,0 +1,49 @@
1
+ //! SAC Admin Wrapper trait definition.
2
+ //!
3
+ //! Defines the admin operations that can be performed on a Stellar Asset Contract (SAC).
4
+
5
+ use common_macros::contract_trait;
6
+ use soroban_sdk::{Address, Env};
7
+
8
+ #[contract_trait]
9
+ pub trait SACAdminWrapper {
10
+ /// Sets the administrator to the specified address `new_admin`.
11
+ ///
12
+ /// # Arguments
13
+ ///
14
+ /// * `env` - The Soroban environment.
15
+ /// * `new_admin` - The address which will be the administrator of the token contract.
16
+ /// * `operator` - The address authorizing the invocation.
17
+ fn set_admin(env: &Env, new_admin: &Address, operator: &Address);
18
+
19
+ /// Sets whether the account is authorized to use its balance.
20
+ /// If `authorize` is true, `id` can use its balance; otherwise it is blacklisted.
21
+ ///
22
+ /// # Arguments
23
+ ///
24
+ /// * `env` - The Soroban environment.
25
+ /// * `id` - The address being (de-)authorized.
26
+ /// * `authorize` - Whether `id` can use its balance.
27
+ /// * `operator` - The address authorizing the invocation.
28
+ fn set_authorized(env: &Env, id: &Address, authorize: bool, operator: &Address);
29
+
30
+ /// Clawback `amount` from `from` account. The amount is burned in the clawback process.
31
+ ///
32
+ /// # Arguments
33
+ ///
34
+ /// * `env` - The Soroban environment.
35
+ /// * `from` - The address holding the balance to claw back from.
36
+ /// * `amount` - The amount of tokens to claw back.
37
+ /// * `operator` - The address authorizing the invocation.
38
+ fn clawback(env: &Env, from: &Address, amount: i128, operator: &Address);
39
+
40
+ /// Mints `amount` to `to`.
41
+ ///
42
+ /// # Arguments
43
+ ///
44
+ /// * `env` - The Soroban environment.
45
+ /// * `to` - The address which will receive the minted tokens.
46
+ /// * `amount` - The amount of tokens to be minted.
47
+ /// * `operator` - The address authorizing the invocation.
48
+ fn mint(env: &Env, to: &Address, amount: i128, operator: &Address);
49
+ }
@@ -1,8 +1,8 @@
1
1
  #![no_std]
2
2
 
3
- mod errors;
3
+ mod interfaces;
4
4
 
5
- pub use errors::*;
5
+ pub use interfaces::{SACAdminWrapper, SACAdminWrapperClient};
6
6
 
7
7
  cfg_if::cfg_if! {
8
8
  // Include implementation when NOT in library mode, OR when testutils is enabled (for tests)
@@ -11,7 +11,7 @@ cfg_if::cfg_if! {
11
11
  mod sac_manager;
12
12
 
13
13
  // Export the contract and client for testing purposes
14
- pub use sac_manager::{SacManager, SacManagerClient};
14
+ pub use sac_manager::{SACManager, SACManagerClient};
15
15
  }
16
16
  }
17
17
 
@@ -2,19 +2,30 @@
2
2
  //!
3
3
  //! This contract becomes the admin of a SAC and provides:
4
4
  //! - Mintable interface for OFT (mint on credit only; OFT burns on the token directly)
5
- //! - Admin operations (clawback, set_admin, set_authorized)
6
- //! - Upgradeable (owner-authorized)
5
+ //! - Role-based access control operations (clawback, set_admin, set_authorized)
7
6
  //!
8
7
  //! ## Authorization Model
9
8
  //!
10
- //! - **Owner** (via Ownable): The admin address. Can do everything (upgrades, TTL, admin ops, set_minter).
11
- //! - **Minters**: Stored list of addresses. Only an address in Minters can call mint via Mintable with `operation: minter_address`.
12
-
13
- use crate::{errors::SacManagerError, storage::SacManagerStorage};
14
- use common_macros::{contract_impl, lz_contract, only_auth};
15
- use oft::Mintable;
16
- use soroban_sdk::{assert_with_error, token::StellarAssetClient, Address, Env, Vec};
17
- use utils::ownable::OwnableInitializer;
9
+ //! - **Owner** (via Ownable): The deployer/admin address. Can manage TTL and grant/revoke roles.
10
+ //! - **RBAC roles**: Access is enforced by role.
11
+ //! - `ADMIN_MANAGER_ROLE`: set_admin
12
+ //! - `MINTER_ROLE`: mint (e.g. for OFT credit)
13
+ //! - `BLACKLISTER_ROLE`: set_authorized
14
+ //! - `CLAWBACK_ROLE`: clawback
15
+
16
+ use crate::{interfaces::SACAdminWrapper, storage::SACManagerStorage};
17
+ use common_macros::{contract_impl, lz_contract, only_role};
18
+ use soroban_sdk::{token::StellarAssetClient, Address, Env};
19
+ use utils::rbac::RoleBasedAccessControl;
20
+
21
+ /// Role that can set the admin
22
+ const ADMIN_MANAGER_ROLE: &str = "ADMIN_MGR";
23
+ /// Role that can mint tokens
24
+ const MINTER_ROLE: &str = "MINTER";
25
+ /// Role that can blacklist users
26
+ const BLACKLISTER_ROLE: &str = "BLKLISTR";
27
+ /// Role that can clawback tokens from users
28
+ const CLAWBACK_ROLE: &str = "CLAWBACK";
18
29
 
19
30
  // =========================================================================
20
31
  // SAC Manager Contract
@@ -24,92 +35,53 @@ use utils::ownable::OwnableInitializer;
24
35
  ///
25
36
  /// Manages a SAC as its admin, forwarding token actions to
26
37
  /// the underlying SAC while enforcing access control.
27
- #[lz_contract(upgradeable(no_migration))]
28
- pub struct SacManager;
38
+ #[lz_contract]
39
+ pub struct SACManager;
29
40
 
30
41
  #[contract_impl]
31
- impl SacManager {
42
+ impl SACManager {
32
43
  /// Constructs the SAC manager contract.
33
44
  ///
34
45
  /// # Arguments
35
46
  /// * `sac_token` - The underlying Stellar Asset Contract address
36
- /// * `owner` - The initial owner address (for upgrades, owner ops)
37
- ///
38
- /// Minters can be set separately via `set_minter` after construction.
47
+ /// * `owner` - The initial owner address (for TTL management, role grants)
39
48
  pub fn __constructor(env: &Env, sac_token: &Address, owner: &Address) {
40
49
  Self::init_owner(env, owner);
41
- SacManagerStorage::set_sac_token(env, sac_token);
50
+ SACManagerStorage::set_sac_token(env, sac_token);
42
51
  }
43
52
 
44
- // =========================================================================
45
- // SAC Admin Operations
46
- // =========================================================================
47
-
48
- /// Delegates to the underlying SAC to clawback `amount` from `from` account.
49
- #[only_auth]
50
- pub fn clawback(env: &Env, from: &Address, amount: i128) {
51
- sac_client(env).clawback(from, &amount);
53
+ /// Returns the underlying SAC (Stellar Asset Contract) address.
54
+ pub fn underlying_sac(env: &Env) -> Address {
55
+ SACManagerStorage::sac_token(env).unwrap()
52
56
  }
57
+ }
53
58
 
54
- /// Delegates to the underlying SAC `set_admin` to release the admin role from the current contract to `to`.
55
- #[only_auth]
56
- pub fn release_sac_admin(env: &Env, to: &Address) {
57
- sac_client(env).set_admin(to);
59
+ #[contract_impl(contracttrait)]
60
+ impl SACAdminWrapper for SACManager {
61
+ #[only_role(operator, ADMIN_MANAGER_ROLE)]
62
+ fn set_admin(env: &Env, new_admin: &Address, operator: &Address) {
63
+ sac_client(env).set_admin(new_admin);
58
64
  }
59
65
 
60
- /// Delegates to the underlying SAC `set_authorized` to set whether `id` is authorized to use its balance.
61
- #[only_auth]
62
- pub fn set_authorized(env: &Env, id: &Address, authorize: bool) {
66
+ #[only_role(operator, BLACKLISTER_ROLE)]
67
+ fn set_authorized(env: &Env, id: &Address, authorize: bool, operator: &Address) {
63
68
  sac_client(env).set_authorized(id, &authorize);
64
69
  }
65
70
 
66
- /// Adds (`active = true`) or removes (`active = false`) a minter.
67
- #[only_auth]
68
- pub fn set_minter(env: &Env, minter: &Address, active: bool) {
69
- let mut minters = SacManagerStorage::minters(env);
70
- let minter_index = minters.first_index_of(minter);
71
- if active {
72
- assert_with_error!(env, minter_index.is_none(), SacManagerError::AlreadyMinter);
73
- minters.push_back(minter.clone());
74
- } else {
75
- minters.remove(minter_index.unwrap_or_panic(env, SacManagerError::MinterNotFound));
76
- }
77
- SacManagerStorage::set_minters(env, &minters);
78
- }
79
-
80
- // =========================================================================
81
- // View Functions
82
- // =========================================================================
83
-
84
- /// Returns the underlying SAC (Stellar Asset Contract) address.
85
- pub fn underlying_sac(env: &Env) -> Address {
86
- SacManagerStorage::sac_token(env).unwrap()
87
- }
88
-
89
- /// Returns the list of addresses authorized to call mint.
90
- pub fn minters(env: &Env) -> Vec<Address> {
91
- SacManagerStorage::minters(env)
71
+ #[only_role(operator, CLAWBACK_ROLE)]
72
+ fn clawback(env: &Env, from: &Address, amount: i128, operator: &Address) {
73
+ sac_client(env).clawback(from, &amount);
92
74
  }
93
- }
94
-
95
- // =========================================================================
96
- // Mintable Implementation (OFT mint on credit)
97
- // =========================================================================
98
-
99
- #[contract_impl]
100
- impl Mintable for SacManager {
101
- fn mint(env: &Env, to: &Address, amount: i128, operation: &Address) {
102
- assert_with_error!(env, Self::minters(env).contains(operation), SacManagerError::Unauthorized);
103
- operation.require_auth();
104
75
 
76
+ #[only_role(operator, MINTER_ROLE)]
77
+ fn mint(env: &Env, to: &Address, amount: i128, operator: &Address) {
105
78
  sac_client(env).mint(to, &amount);
106
79
  }
107
80
  }
108
81
 
109
- // =========================================================================
110
- // Helper Functions
111
- // =========================================================================
82
+ #[contract_impl(contracttrait)]
83
+ impl RoleBasedAccessControl for SACManager {}
112
84
 
113
85
  fn sac_client(env: &Env) -> StellarAssetClient<'_> {
114
- StellarAssetClient::new(env, &SacManager::underlying_sac(env))
86
+ StellarAssetClient::new(env, &SACManager::underlying_sac(env))
115
87
  }
@@ -3,18 +3,11 @@
3
3
  //! This file contains the core storage.
4
4
 
5
5
  use common_macros::storage;
6
- use soroban_sdk::{Address, Vec};
6
+ use soroban_sdk::Address;
7
7
 
8
- /// Core storage for the SacManager contract.
9
- /// Contains essential state.
10
8
  #[storage]
11
- pub enum SacManagerStorage {
9
+ pub enum SACManagerStorage {
12
10
  /// The underlying SAC (Stellar Asset Contract) address
13
11
  #[instance(Address)]
14
12
  SacToken,
15
-
16
- /// Addresses authorized to call mint (e.g. OFT or other minters).
17
- #[persistent(Vec<Address>)]
18
- #[default(Vec::new(env))]
19
- Minters,
20
13
  }
@@ -1,15 +1,13 @@
1
1
  //! Clawback Integration Tests
2
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.
3
+ //! Operator must hold CLAWBACK_ROLE. SAC must have AUTH_CLAWBACK_ENABLED.
6
4
 
7
5
  use super::test_helper::mock_clawback_auth;
8
6
  use crate::tests::test_helper::{mock_oft_mint_auth, TestSetup};
9
7
  use soroban_sdk::testutils::IssuerFlags;
10
8
 
11
9
  // =========================================================================
12
- // clawback Tests (owner only)
10
+ // clawback Tests
13
11
  // =========================================================================
14
12
 
15
13
  #[test]
@@ -25,7 +23,7 @@ fn test_clawback_by_owner() {
25
23
  assert_eq!(setup.sac_client.balance(&user), 1000);
26
24
 
27
25
  mock_clawback_auth(&setup, &setup.owner, &user, 500_i128);
28
- setup.sac_manager_client.clawback(&user, &500);
26
+ setup.sac_manager_client.clawback(&user, &500, &setup.owner);
29
27
  assert_eq!(setup.sac_client.balance(&user), 500);
30
28
  }
31
29
 
@@ -41,7 +39,7 @@ fn test_clawback_full_balance() {
41
39
  setup.sac_manager_client.mint(&user, &1000, &setup.minter);
42
40
 
43
41
  mock_clawback_auth(&setup, &setup.owner, &user, 1000_i128);
44
- setup.sac_manager_client.clawback(&user, &1000);
42
+ setup.sac_manager_client.clawback(&user, &1000, &setup.owner);
45
43
  assert_eq!(setup.sac_client.balance(&user), 0);
46
44
  }
47
45
 
@@ -57,18 +55,18 @@ fn test_clawback_fails_when_amount_exceeds_balance() {
57
55
  setup.sac_manager_client.mint(&user, &100, &setup.minter);
58
56
 
59
57
  mock_clawback_auth(&setup, &setup.owner, &user, 200_i128);
60
- let result = setup.sac_manager_client.try_clawback(&user, &200);
58
+ let result = setup.sac_manager_client.try_clawback(&user, &200, &setup.owner);
61
59
  assert!(result.is_err());
62
60
  }
63
61
 
64
62
  #[test]
65
- fn test_clawback_by_non_owner_fails() {
63
+ fn test_clawback_operator_without_role_fails() {
66
64
  let setup = TestSetup::new().with_manager_as_sac_admin().build();
67
65
  let user = setup.generate_address();
68
66
  let random = setup.generate_address();
69
67
 
70
68
  mock_clawback_auth(&setup, &random, &user, 500_i128);
71
- let result = setup.sac_manager_client.try_clawback(&user, &500);
69
+ let result = setup.sac_manager_client.try_clawback(&user, &500, &random);
72
70
  assert!(result.is_err());
73
71
  }
74
72
 
@@ -82,5 +80,5 @@ fn test_clawback_fails_without_auth() {
82
80
  let setup = TestSetup::new().build();
83
81
  let user = setup.generate_address();
84
82
 
85
- setup.sac_manager_client.clawback(&user, &300);
83
+ setup.sac_manager_client.clawback(&user, &300, &setup.owner);
86
84
  }
@@ -1,13 +1,11 @@
1
1
  //! Mint (Mintable) Integration Tests
2
2
  //!
3
- //! Tests minter-originated mint via Mintable::mint(..., operation: minter),
4
- //! authorization (operation must be in minters, operation must auth), and error cases.
3
+ //! Operator must hold MINTER_ROLE and authorize the call.
5
4
 
6
- use crate::errors::SacManagerError;
7
5
  use crate::tests::test_helper::{mock_auth, mock_oft_mint_auth, TestSetup};
8
6
 
9
7
  // =========================================================================
10
- // Mint success — minter calls mint
8
+ // Mint success — operator with MINTER_ROLE calls mint
11
9
  // =========================================================================
12
10
 
13
11
  #[test]
@@ -21,31 +19,28 @@ fn test_mint_by_minter() {
21
19
  }
22
20
 
23
21
  // =========================================================================
24
- // Mint error casesoperation not in minters / non-minter
22
+ // Mint role authoperator without MINTER_ROLE fails
25
23
  // =========================================================================
26
24
 
27
25
  #[test]
28
- fn test_mint_fails_when_operation_not_in_minters() {
29
- let setup = TestSetup::new().with_empty_minters().build();
30
- let recipient = setup.generate_address();
31
-
32
- let result = setup.sac_manager_client.try_mint(&recipient, &1000, &setup.minter);
33
- assert_eq!(result.err().unwrap().unwrap(), SacManagerError::Unauthorized.into());
34
- }
35
-
36
- #[test]
37
- fn test_mint_by_non_minter_fails() {
26
+ fn test_mint_operator_without_role_fails() {
38
27
  let setup = TestSetup::new().with_manager_as_sac_admin().build();
39
28
  let recipient = setup.generate_address();
40
29
  let random = setup.generate_address();
41
30
 
42
- mock_auth(&setup.env, &setup.sac_manager, &random, "mint", (&recipient, 1000_i128, &random));
31
+ mock_auth(
32
+ &setup.env,
33
+ &setup.sac_manager,
34
+ &random,
35
+ "mint",
36
+ (&recipient, 1000_i128, &random),
37
+ );
43
38
  let result = setup.sac_manager_client.try_mint(&recipient, &1000, &random);
44
- assert_eq!(result.err().unwrap().unwrap(), SacManagerError::Unauthorized.into());
39
+ assert!(result.is_err());
45
40
  }
46
41
 
47
42
  // =========================================================================
48
- // Mint auth tests operation must authorize
43
+ // Mint auth — operator must authorize
49
44
  // =========================================================================
50
45
 
51
46
  #[test]
@@ -2,6 +2,5 @@ mod clawback;
2
2
  mod mint;
3
3
  mod set_admin;
4
4
  mod set_authorized;
5
- mod set_minter;
6
5
  mod test_helper;
7
6
  mod view_functions;
@@ -1,36 +1,46 @@
1
- //! release_sac_admin Integration Tests
1
+ //! set_admin Integration Tests
2
+ //!
3
+ //! Tests that set_admin requires ADMIN_MANAGER_ROLE on the operator.
2
4
 
3
- use super::test_helper::mock_release_sac_admin_auth;
5
+ use super::test_helper::mock_set_admin_auth;
4
6
  use crate::tests::test_helper::TestSetup;
5
7
 
6
8
  // =========================================================================
7
- // release_sac_admin Tests
9
+ // set_admin Tests
8
10
  // =========================================================================
9
11
 
10
12
  #[test]
11
- fn test_release_sac_admin() {
13
+ fn test_set_admin_by_owner() {
12
14
  let setup = TestSetup::new().with_manager_as_sac_admin().build();
13
15
  let new_admin = setup.generate_address();
14
16
 
15
- // Current SAC admin is the manager (configured by test setup).
16
17
  assert_eq!(setup.sac_client.admin(), setup.sac_manager);
17
18
 
18
- // Owner can change SAC admin
19
- mock_release_sac_admin_auth(&setup, &new_admin);
20
- setup.sac_manager_client.release_sac_admin(&new_admin);
19
+ mock_set_admin_auth(&setup, &setup.owner, &new_admin);
20
+ setup.sac_manager_client.set_admin(&new_admin, &setup.owner);
21
21
  assert_eq!(setup.sac_client.admin(), new_admin);
22
22
  }
23
23
 
24
24
  // =========================================================================
25
- // release_sac_admin Auth Tests
25
+ // set_admin Role Auth Tests
26
26
  // =========================================================================
27
27
 
28
+ #[test]
29
+ fn test_set_admin_operator_without_role_fails() {
30
+ let setup = TestSetup::new().with_manager_as_sac_admin().build();
31
+ let new_admin = setup.generate_address();
32
+ let random = setup.generate_address();
33
+
34
+ mock_set_admin_auth(&setup, &random, &new_admin);
35
+ let result = setup.sac_manager_client.try_set_admin(&new_admin, &random);
36
+ assert!(result.is_err());
37
+ }
38
+
28
39
  #[test]
29
40
  #[should_panic(expected = "Error(Auth, InvalidAction)")]
30
- fn test_release_sac_admin_without_auth() {
41
+ fn test_set_admin_without_auth() {
31
42
  let setup = TestSetup::new().build();
32
43
  let new_admin = setup.generate_address();
33
44
 
34
- // Should panic because owner doesn't authorize the call
35
- setup.sac_manager_client.release_sac_admin(&new_admin);
45
+ setup.sac_manager_client.set_admin(&new_admin, &setup.owner);
36
46
  }
@@ -1,6 +1,6 @@
1
1
  //! set_authorized Integration Tests
2
2
  //!
3
- //! Requires revocable issuer flag on the SAC before authorization can be changed.
3
+ //! Requires revocable issuer flag on the SAC. Operator must hold BLACKLISTER_ROLE.
4
4
 
5
5
  use super::test_helper::mock_set_authorized_auth;
6
6
  use crate::tests::test_helper::TestSetup;
@@ -15,29 +15,39 @@ fn test_set_authorized_by_owner() {
15
15
  let setup = TestSetup::new().with_manager_as_sac_admin().build();
16
16
  let user = setup.generate_address();
17
17
 
18
- // Enable issuer flag required by SAC for set_authorized.
19
18
  setup.sac_contract.issuer().set_flag(IssuerFlags::RevocableFlag);
20
19
  assert!(setup.sac_client.authorized(&user));
21
20
 
22
- mock_set_authorized_auth(&setup, &user, false);
23
- setup.sac_manager_client.set_authorized(&user, &false);
21
+ mock_set_authorized_auth(&setup, &setup.owner, &user, false);
22
+ setup.sac_manager_client.set_authorized(&user, &false, &setup.owner);
24
23
  assert!(!setup.sac_client.authorized(&user));
25
24
 
26
- mock_set_authorized_auth(&setup, &user, true);
27
- setup.sac_manager_client.set_authorized(&user, &true);
25
+ mock_set_authorized_auth(&setup, &setup.owner, &user, true);
26
+ setup.sac_manager_client.set_authorized(&user, &true, &setup.owner);
28
27
  assert!(setup.sac_client.authorized(&user));
29
28
  }
30
29
 
31
30
  // =========================================================================
32
- // set_authorized Auth Tests
31
+ // set_authorized Role Auth Tests
33
32
  // =========================================================================
34
33
 
34
+ #[test]
35
+ fn test_set_authorized_operator_without_role_fails() {
36
+ let setup = TestSetup::new().with_manager_as_sac_admin().build();
37
+ let user = setup.generate_address();
38
+ let random = setup.generate_address();
39
+
40
+ setup.sac_contract.issuer().set_flag(IssuerFlags::RevocableFlag);
41
+ mock_set_authorized_auth(&setup, &random, &user, false);
42
+ let result = setup.sac_manager_client.try_set_authorized(&user, &false, &random);
43
+ assert!(result.is_err());
44
+ }
45
+
35
46
  #[test]
36
47
  #[should_panic(expected = "Error(Auth, InvalidAction)")]
37
48
  fn test_set_authorized_without_auth() {
38
49
  let setup = TestSetup::new().build();
39
50
  let user = setup.generate_address();
40
51
 
41
- // Should panic because owner doesn't authorize the call
42
- setup.sac_manager_client.set_authorized(&user, &false);
52
+ setup.sac_manager_client.set_authorized(&user, &false, &setup.owner);
43
53
  }
@@ -1,18 +1,35 @@
1
1
  use crate::tests::test_helper::{mock_auth, TestSetup};
2
2
  use soroban_sdk::Address;
3
3
 
4
- pub fn mock_clawback_auth(setup: &TestSetup, sender: &Address, from: &Address, amount: i128) {
5
- mock_auth(&setup.env, &setup.sac_manager, sender, "clawback", (from, amount));
4
+ /// Mock auth for `clawback(from, amount, operator)` operator must hold CLAWBACK_ROLE.
5
+ pub fn mock_clawback_auth(setup: &TestSetup, operator: &Address, from: &Address, amount: i128) {
6
+ mock_auth(
7
+ &setup.env,
8
+ &setup.sac_manager,
9
+ operator,
10
+ "clawback",
11
+ (from, amount, operator),
12
+ );
6
13
  }
7
14
 
8
- pub fn mock_set_authorized_auth(setup: &TestSetup, user: &Address, authorize: bool) {
9
- mock_auth(&setup.env, &setup.sac_manager, &setup.owner, "set_authorized", (user, authorize));
15
+ /// Mock auth for `set_authorized(id, authorize, operator)` — operator must hold BLACKLISTER_ROLE.
16
+ pub fn mock_set_authorized_auth(setup: &TestSetup, operator: &Address, user: &Address, authorize: bool) {
17
+ mock_auth(
18
+ &setup.env,
19
+ &setup.sac_manager,
20
+ operator,
21
+ "set_authorized",
22
+ (user, authorize, operator),
23
+ );
10
24
  }
11
25
 
12
- pub fn mock_release_sac_admin_auth(setup: &TestSetup, new_admin: &Address) {
13
- mock_auth(&setup.env, &setup.sac_manager, &setup.owner, "release_sac_admin", (new_admin,));
14
- }
15
-
16
- pub fn mock_set_minter_auth(setup: &TestSetup, minter: &Address, active: bool) {
17
- mock_auth(&setup.env, &setup.sac_manager, &setup.owner, "set_minter", (minter, active));
26
+ /// Mock auth for `set_admin(new_admin, operator)` — operator must hold ADMIN_MANAGER_ROLE.
27
+ pub fn mock_set_admin_auth(setup: &TestSetup, operator: &Address, new_admin: &Address) {
28
+ mock_auth(
29
+ &setup.env,
30
+ &setup.sac_manager,
31
+ operator,
32
+ "set_admin",
33
+ (new_admin, operator),
34
+ );
18
35
  }
@@ -11,18 +11,3 @@ fn test_underlying_sac() {
11
11
  let setup = TestSetup::new().build();
12
12
  assert_eq!(setup.sac_manager_client.underlying_sac(), setup.sac);
13
13
  }
14
-
15
- #[test]
16
- fn test_minters() {
17
- let setup = TestSetup::new().build();
18
- let minters = setup.sac_manager_client.minters();
19
- assert_eq!(minters.len(), 1);
20
- assert_eq!(minters.get(0), Some(setup.minter.clone()));
21
- }
22
-
23
- #[test]
24
- fn test_minters_empty_when_not_set() {
25
- let setup = TestSetup::new().with_empty_minters().build();
26
- let minters = setup.sac_manager_client.minters();
27
- assert_eq!(minters.len(), 0);
28
- }