@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
|
@@ -0,0 +1,115 @@
|
|
|
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
|
+
//! - 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)
|
|
7
|
+
//!
|
|
8
|
+
//! ## Authorization Model
|
|
9
|
+
//!
|
|
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;
|
|
18
|
+
|
|
19
|
+
// =========================================================================
|
|
20
|
+
// SAC Manager Contract
|
|
21
|
+
// =========================================================================
|
|
22
|
+
|
|
23
|
+
/// SAC Manager Contract
|
|
24
|
+
///
|
|
25
|
+
/// Manages a SAC as its admin, forwarding token actions to
|
|
26
|
+
/// the underlying SAC while enforcing access control.
|
|
27
|
+
#[lz_contract(upgradeable(no_migration))]
|
|
28
|
+
pub struct SacManager;
|
|
29
|
+
|
|
30
|
+
#[contract_impl]
|
|
31
|
+
impl SacManager {
|
|
32
|
+
/// Constructs the SAC manager contract.
|
|
33
|
+
///
|
|
34
|
+
/// # Arguments
|
|
35
|
+
/// * `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.
|
|
39
|
+
pub fn __constructor(env: &Env, sac_token: &Address, owner: &Address) {
|
|
40
|
+
Self::init_owner(env, owner);
|
|
41
|
+
SacManagerStorage::set_sac_token(env, sac_token);
|
|
42
|
+
}
|
|
43
|
+
|
|
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);
|
|
52
|
+
}
|
|
53
|
+
|
|
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);
|
|
58
|
+
}
|
|
59
|
+
|
|
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) {
|
|
63
|
+
sac_client(env).set_authorized(id, &authorize);
|
|
64
|
+
}
|
|
65
|
+
|
|
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)
|
|
92
|
+
}
|
|
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
|
+
|
|
105
|
+
sac_client(env).mint(to, &amount);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// =========================================================================
|
|
110
|
+
// Helper Functions
|
|
111
|
+
// =========================================================================
|
|
112
|
+
|
|
113
|
+
fn sac_client(env: &Env) -> StellarAssetClient<'_> {
|
|
114
|
+
StellarAssetClient::new(env, &SacManager::underlying_sac(env))
|
|
115
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//! Storage definitions for the SAC manager contract.
|
|
2
|
+
//!
|
|
3
|
+
//! This file contains the core storage.
|
|
4
|
+
|
|
5
|
+
use common_macros::storage;
|
|
6
|
+
use soroban_sdk::{Address, Vec};
|
|
7
|
+
|
|
8
|
+
/// Core storage for the SacManager contract.
|
|
9
|
+
/// Contains essential state.
|
|
10
|
+
#[storage]
|
|
11
|
+
pub enum SacManagerStorage {
|
|
12
|
+
/// The underlying SAC (Stellar Asset Contract) address
|
|
13
|
+
#[instance(Address)]
|
|
14
|
+
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
|
+
}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
//! Token Wrapper Tests
|
|
2
2
|
//!
|
|
3
3
|
//! Test modules organized by source module:
|
|
4
|
-
//! - `supply_control`: Tests for supply control extension (controllers, mint, burn, rate limits)
|
|
5
|
-
//! - `redistribution`: Tests for redistribution extension (feature flag settings)
|
|
6
4
|
//! - `sac_manager`: Tests for the main SAC manager contract (admin, authorized, clawback, mint/burn, views)
|
|
7
5
|
|
|
8
6
|
#![cfg(test)]
|
|
9
7
|
|
|
10
8
|
mod test_helper;
|
|
11
9
|
|
|
12
|
-
mod redistribution;
|
|
13
10
|
mod sac_manager;
|
|
14
|
-
mod supply_control;
|
|
@@ -0,0 +1,86 @@
|
|
|
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
|
+
use super::test_helper::mock_clawback_auth;
|
|
8
|
+
use crate::tests::test_helper::{mock_oft_mint_auth, TestSetup};
|
|
9
|
+
use soroban_sdk::testutils::IssuerFlags;
|
|
10
|
+
|
|
11
|
+
// =========================================================================
|
|
12
|
+
// clawback Tests (owner only)
|
|
13
|
+
// =========================================================================
|
|
14
|
+
|
|
15
|
+
#[test]
|
|
16
|
+
fn test_clawback_by_owner() {
|
|
17
|
+
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
18
|
+
let user = setup.generate_address();
|
|
19
|
+
|
|
20
|
+
setup.sac_contract.issuer().set_flag(IssuerFlags::RevocableFlag);
|
|
21
|
+
setup.sac_contract.issuer().set_flag(IssuerFlags::ClawbackEnabledFlag);
|
|
22
|
+
|
|
23
|
+
mock_oft_mint_auth(&setup, &user, 1000_i128);
|
|
24
|
+
setup.sac_manager_client.mint(&user, &1000, &setup.minter);
|
|
25
|
+
assert_eq!(setup.sac_client.balance(&user), 1000);
|
|
26
|
+
|
|
27
|
+
mock_clawback_auth(&setup, &setup.owner, &user, 500_i128);
|
|
28
|
+
setup.sac_manager_client.clawback(&user, &500);
|
|
29
|
+
assert_eq!(setup.sac_client.balance(&user), 500);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
#[test]
|
|
33
|
+
fn test_clawback_full_balance() {
|
|
34
|
+
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
35
|
+
let user = setup.generate_address();
|
|
36
|
+
|
|
37
|
+
setup.sac_contract.issuer().set_flag(IssuerFlags::RevocableFlag);
|
|
38
|
+
setup.sac_contract.issuer().set_flag(IssuerFlags::ClawbackEnabledFlag);
|
|
39
|
+
|
|
40
|
+
mock_oft_mint_auth(&setup, &user, 1000_i128);
|
|
41
|
+
setup.sac_manager_client.mint(&user, &1000, &setup.minter);
|
|
42
|
+
|
|
43
|
+
mock_clawback_auth(&setup, &setup.owner, &user, 1000_i128);
|
|
44
|
+
setup.sac_manager_client.clawback(&user, &1000);
|
|
45
|
+
assert_eq!(setup.sac_client.balance(&user), 0);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
#[test]
|
|
49
|
+
fn test_clawback_fails_when_amount_exceeds_balance() {
|
|
50
|
+
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
51
|
+
let user = setup.generate_address();
|
|
52
|
+
|
|
53
|
+
setup.sac_contract.issuer().set_flag(IssuerFlags::RevocableFlag);
|
|
54
|
+
setup.sac_contract.issuer().set_flag(IssuerFlags::ClawbackEnabledFlag);
|
|
55
|
+
|
|
56
|
+
mock_oft_mint_auth(&setup, &user, 100_i128);
|
|
57
|
+
setup.sac_manager_client.mint(&user, &100, &setup.minter);
|
|
58
|
+
|
|
59
|
+
mock_clawback_auth(&setup, &setup.owner, &user, 200_i128);
|
|
60
|
+
let result = setup.sac_manager_client.try_clawback(&user, &200);
|
|
61
|
+
assert!(result.is_err());
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
#[test]
|
|
65
|
+
fn test_clawback_by_non_owner_fails() {
|
|
66
|
+
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
67
|
+
let user = setup.generate_address();
|
|
68
|
+
let random = setup.generate_address();
|
|
69
|
+
|
|
70
|
+
mock_clawback_auth(&setup, &random, &user, 500_i128);
|
|
71
|
+
let result = setup.sac_manager_client.try_clawback(&user, &500);
|
|
72
|
+
assert!(result.is_err());
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// =========================================================================
|
|
76
|
+
// clawback Auth Tests
|
|
77
|
+
// =========================================================================
|
|
78
|
+
|
|
79
|
+
#[test]
|
|
80
|
+
#[should_panic(expected = "Error(Auth, InvalidAction)")]
|
|
81
|
+
fn test_clawback_fails_without_auth() {
|
|
82
|
+
let setup = TestSetup::new().build();
|
|
83
|
+
let user = setup.generate_address();
|
|
84
|
+
|
|
85
|
+
setup.sac_manager_client.clawback(&user, &300);
|
|
86
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
//! Mint (Mintable) Integration Tests
|
|
2
|
+
//!
|
|
3
|
+
//! Tests minter-originated mint via Mintable::mint(..., operation: minter),
|
|
4
|
+
//! authorization (operation must be in minters, operation must auth), and error cases.
|
|
5
|
+
|
|
6
|
+
use crate::errors::SacManagerError;
|
|
7
|
+
use crate::tests::test_helper::{mock_auth, mock_oft_mint_auth, TestSetup};
|
|
8
|
+
|
|
9
|
+
// =========================================================================
|
|
10
|
+
// Mint success — minter calls mint
|
|
11
|
+
// =========================================================================
|
|
12
|
+
|
|
13
|
+
#[test]
|
|
14
|
+
fn test_mint_by_minter() {
|
|
15
|
+
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
16
|
+
let recipient = setup.generate_address();
|
|
17
|
+
|
|
18
|
+
mock_oft_mint_auth(&setup, &recipient, 1000_i128);
|
|
19
|
+
setup.sac_manager_client.mint(&recipient, &1000, &setup.minter);
|
|
20
|
+
assert_eq!(setup.sac_client.balance(&recipient), 1000);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// =========================================================================
|
|
24
|
+
// Mint error cases — operation not in minters / non-minter
|
|
25
|
+
// =========================================================================
|
|
26
|
+
|
|
27
|
+
#[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() {
|
|
38
|
+
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
39
|
+
let recipient = setup.generate_address();
|
|
40
|
+
let random = setup.generate_address();
|
|
41
|
+
|
|
42
|
+
mock_auth(&setup.env, &setup.sac_manager, &random, "mint", (&recipient, 1000_i128, &random));
|
|
43
|
+
let result = setup.sac_manager_client.try_mint(&recipient, &1000, &random);
|
|
44
|
+
assert_eq!(result.err().unwrap().unwrap(), SacManagerError::Unauthorized.into());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// =========================================================================
|
|
48
|
+
// Mint auth tests — operation must authorize
|
|
49
|
+
// =========================================================================
|
|
50
|
+
|
|
51
|
+
#[test]
|
|
52
|
+
#[should_panic(expected = "Error(Auth, InvalidAction)")]
|
|
53
|
+
fn test_mint_fails_without_minter_auth() {
|
|
54
|
+
let setup = TestSetup::new().with_manager_as_sac_admin().build();
|
|
55
|
+
let recipient = setup.generate_address();
|
|
56
|
+
|
|
57
|
+
setup.sac_manager_client.mint(&recipient, &1000, &setup.minter);
|
|
58
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
//! set_minter Integration Tests
|
|
2
|
+
|
|
3
|
+
use super::test_helper::mock_set_minter_auth;
|
|
4
|
+
use crate::errors::SacManagerError;
|
|
5
|
+
use crate::tests::test_helper::TestSetup;
|
|
6
|
+
|
|
7
|
+
// =========================================================================
|
|
8
|
+
// set_minter Tests
|
|
9
|
+
// =========================================================================
|
|
10
|
+
|
|
11
|
+
#[test]
|
|
12
|
+
fn test_set_minter_add_when_empty() {
|
|
13
|
+
let setup = TestSetup::new().with_empty_minters().build();
|
|
14
|
+
let new_minter = setup.generate_address();
|
|
15
|
+
|
|
16
|
+
mock_set_minter_auth(&setup, &new_minter, true);
|
|
17
|
+
setup.sac_manager_client.set_minter(&new_minter, &true);
|
|
18
|
+
let stored = setup.sac_manager_client.minters();
|
|
19
|
+
assert_eq!(stored.len(), 1);
|
|
20
|
+
assert_eq!(stored.get(0), Some(new_minter));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#[test]
|
|
24
|
+
fn test_set_minter_add_then_remove() {
|
|
25
|
+
let setup = TestSetup::new().build();
|
|
26
|
+
let new_minter = setup.generate_address();
|
|
27
|
+
|
|
28
|
+
mock_set_minter_auth(&setup, &new_minter, true);
|
|
29
|
+
setup.sac_manager_client.set_minter(&new_minter, &true);
|
|
30
|
+
assert_eq!(setup.sac_manager_client.minters().len(), 2);
|
|
31
|
+
|
|
32
|
+
mock_set_minter_auth(&setup, &new_minter, false);
|
|
33
|
+
setup.sac_manager_client.set_minter(&new_minter, &false);
|
|
34
|
+
let stored = setup.sac_manager_client.minters();
|
|
35
|
+
assert_eq!(stored.len(), 1);
|
|
36
|
+
assert_eq!(stored.get(0), Some(setup.minter.clone()));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
#[test]
|
|
40
|
+
fn test_set_minter_add_fails_if_already_active() {
|
|
41
|
+
let setup = TestSetup::new().build();
|
|
42
|
+
|
|
43
|
+
mock_set_minter_auth(&setup, &setup.minter, true);
|
|
44
|
+
let result = setup.sac_manager_client.try_set_minter(&setup.minter, &true);
|
|
45
|
+
assert_eq!(result.err().unwrap().unwrap(), SacManagerError::AlreadyMinter.into());
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
#[test]
|
|
49
|
+
fn test_set_minter_remove_fails_if_not_minter() {
|
|
50
|
+
let setup = TestSetup::new().build();
|
|
51
|
+
let random = setup.generate_address();
|
|
52
|
+
|
|
53
|
+
mock_set_minter_auth(&setup, &random, false);
|
|
54
|
+
let result = setup.sac_manager_client.try_set_minter(&random, &false);
|
|
55
|
+
assert_eq!(result.err().unwrap().unwrap(), SacManagerError::MinterNotFound.into());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// =========================================================================
|
|
59
|
+
// set_minter Auth Tests
|
|
60
|
+
// =========================================================================
|
|
61
|
+
|
|
62
|
+
#[test]
|
|
63
|
+
#[should_panic(expected = "Error(Auth, InvalidAction)")]
|
|
64
|
+
fn test_set_minter_without_auth() {
|
|
65
|
+
let setup = TestSetup::new().with_empty_minters().build();
|
|
66
|
+
let new_minter = setup.generate_address();
|
|
67
|
+
|
|
68
|
+
setup.sac_manager_client.set_minter(&new_minter, &true);
|
|
69
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
use crate::tests::test_helper::{mock_auth, TestSetup};
|
|
2
|
+
use soroban_sdk::Address;
|
|
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));
|
|
6
|
+
}
|
|
7
|
+
|
|
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));
|
|
10
|
+
}
|
|
11
|
+
|
|
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));
|
|
18
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//! View Functions Integration Tests
|
|
2
|
+
|
|
3
|
+
use crate::tests::test_helper::TestSetup;
|
|
4
|
+
|
|
5
|
+
// =========================================================================
|
|
6
|
+
// Core View Functions
|
|
7
|
+
// =========================================================================
|
|
8
|
+
|
|
9
|
+
#[test]
|
|
10
|
+
fn test_underlying_sac() {
|
|
11
|
+
let setup = TestSetup::new().build();
|
|
12
|
+
assert_eq!(setup.sac_manager_client.underlying_sac(), setup.sac);
|
|
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
|
+
}
|
|
@@ -25,19 +25,12 @@ use soroban_sdk::{
|
|
|
25
25
|
/// ```
|
|
26
26
|
pub struct TestSetupBuilder {
|
|
27
27
|
manager_as_sac_admin: bool,
|
|
28
|
-
|
|
29
|
-
supply_control_enabled: bool,
|
|
30
|
-
skip_oft_setup: bool,
|
|
28
|
+
skip_minters_setup: bool,
|
|
31
29
|
}
|
|
32
30
|
|
|
33
31
|
impl TestSetupBuilder {
|
|
34
32
|
fn new() -> Self {
|
|
35
|
-
Self {
|
|
36
|
-
manager_as_sac_admin: false,
|
|
37
|
-
redistribution_enabled: false,
|
|
38
|
-
supply_control_enabled: false,
|
|
39
|
-
skip_oft_setup: false,
|
|
40
|
-
}
|
|
33
|
+
Self { manager_as_sac_admin: false, skip_minters_setup: false }
|
|
41
34
|
}
|
|
42
35
|
|
|
43
36
|
/// Set the SacManager as SAC admin during setup.
|
|
@@ -46,22 +39,10 @@ impl TestSetupBuilder {
|
|
|
46
39
|
self
|
|
47
40
|
}
|
|
48
41
|
|
|
49
|
-
///
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
self
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/// Enable supply control at construction time.
|
|
56
|
-
pub fn with_supply_control_enabled(mut self) -> Self {
|
|
57
|
-
self.supply_control_enabled = true;
|
|
58
|
-
self
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/// Skip setting the OFT address during setup.
|
|
62
|
-
/// Use this to test `set_oft_address` auth or the once-only guard.
|
|
63
|
-
pub fn without_oft(mut self) -> Self {
|
|
64
|
-
self.skip_oft_setup = true;
|
|
42
|
+
/// Skip setting minters during setup.
|
|
43
|
+
/// Use this to test `set_minter` auth or mint when no minter is set.
|
|
44
|
+
pub fn with_empty_minters(mut self) -> Self {
|
|
45
|
+
self.skip_minters_setup = true;
|
|
65
46
|
self
|
|
66
47
|
}
|
|
67
48
|
|
|
@@ -71,26 +52,24 @@ impl TestSetupBuilder {
|
|
|
71
52
|
|
|
72
53
|
let owner = Address::generate(&env);
|
|
73
54
|
let oft = Address::generate(&env);
|
|
74
|
-
let sc_manager = Address::generate(&env);
|
|
75
55
|
let sac_contract = env.register_stellar_asset_contract_v2(owner.clone());
|
|
76
56
|
let sac = sac_contract.address();
|
|
77
57
|
|
|
78
|
-
let sac_manager =
|
|
79
|
-
env.register(SacManager, (&sac, &owner, self.redistribution_enabled, self.supply_control_enabled));
|
|
58
|
+
let sac_manager = env.register(SacManager, (&sac, &owner));
|
|
80
59
|
let sac_manager_client = SacManagerClient::new(&env, &sac_manager);
|
|
81
60
|
let sac_client = StellarAssetClient::new(&env, &sac);
|
|
82
61
|
|
|
83
|
-
if !self.
|
|
62
|
+
if !self.skip_minters_setup {
|
|
84
63
|
env.mock_auths(&[MockAuth {
|
|
85
64
|
address: &owner,
|
|
86
65
|
invoke: &MockAuthInvoke {
|
|
87
66
|
contract: &sac_manager,
|
|
88
|
-
fn_name: "
|
|
89
|
-
args: (
|
|
67
|
+
fn_name: "set_minter",
|
|
68
|
+
args: (oft.clone(), true).into_val(&env),
|
|
90
69
|
sub_invokes: &[],
|
|
91
70
|
},
|
|
92
71
|
}]);
|
|
93
|
-
sac_manager_client.
|
|
72
|
+
sac_manager_client.set_minter(&oft, &true);
|
|
94
73
|
}
|
|
95
74
|
|
|
96
75
|
if self.manager_as_sac_admin {
|
|
@@ -106,22 +85,10 @@ impl TestSetupBuilder {
|
|
|
106
85
|
sac_client.set_admin(&sac_manager);
|
|
107
86
|
}
|
|
108
87
|
|
|
109
|
-
// Set up supply controller manager (owner grants the role)
|
|
110
|
-
env.mock_auths(&[MockAuth {
|
|
111
|
-
address: &owner,
|
|
112
|
-
invoke: &MockAuthInvoke {
|
|
113
|
-
contract: &sac_manager,
|
|
114
|
-
fn_name: "set_supply_controller_manager",
|
|
115
|
-
args: (&sc_manager, true).into_val(&env),
|
|
116
|
-
sub_invokes: &[],
|
|
117
|
-
},
|
|
118
|
-
}]);
|
|
119
|
-
sac_manager_client.set_supply_controller_manager(&sc_manager, &true);
|
|
120
|
-
|
|
121
88
|
// Clear mock auths so test starts with clean auth state
|
|
122
89
|
env.mock_auths(&[]);
|
|
123
90
|
|
|
124
|
-
TestSetup { env, owner, oft,
|
|
91
|
+
TestSetup { env, owner, minter: oft, sac, sac_contract, sac_manager, sac_manager_client, sac_client }
|
|
125
92
|
}
|
|
126
93
|
}
|
|
127
94
|
|
|
@@ -133,8 +100,8 @@ impl TestSetupBuilder {
|
|
|
133
100
|
pub struct TestSetup<'a> {
|
|
134
101
|
pub env: Env,
|
|
135
102
|
pub owner: Address,
|
|
136
|
-
|
|
137
|
-
pub
|
|
103
|
+
/// Address used as a minter in default setup (in minters list).
|
|
104
|
+
pub minter: Address,
|
|
138
105
|
pub sac: Address,
|
|
139
106
|
pub sac_contract: StellarAssetContract,
|
|
140
107
|
pub sac_manager: Address,
|
|
@@ -174,17 +141,7 @@ pub fn mock_auth<A: IntoVal<Env, soroban_sdk::Vec<Val>>>(
|
|
|
174
141
|
}]);
|
|
175
142
|
}
|
|
176
143
|
|
|
177
|
-
/// Mock auth for `
|
|
178
|
-
pub fn mock_set_supply_controller_auth(
|
|
179
|
-
setup: &TestSetup,
|
|
180
|
-
sender: &Address,
|
|
181
|
-
controller: &Address,
|
|
182
|
-
config: &Option<crate::extensions::supply_control::SupplyControllerConfig>,
|
|
183
|
-
) {
|
|
184
|
-
mock_auth(&setup.env, &setup.sac_manager, sender, "set_supply_controller", (sender, controller, config.clone()));
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/// Mock auth for OFT-originated `mint`.
|
|
144
|
+
/// Mock auth for minter-originated `mint(to, amount, operation)`.
|
|
188
145
|
pub fn mock_oft_mint_auth(setup: &TestSetup, recipient: &Address, amount: i128) {
|
|
189
|
-
mock_auth(&setup.env, &setup.sac_manager, &setup.
|
|
146
|
+
mock_auth(&setup.env, &setup.sac_manager, &setup.minter, "mint", (recipient, amount, &setup.minter));
|
|
190
147
|
}
|
package/package.json
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@layerzerolabs/protocol-stellar-v2",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.34",
|
|
4
4
|
"private": false,
|
|
5
5
|
"devDependencies": {
|
|
6
6
|
"@types/node": "^22.18.6",
|
|
7
7
|
"tsx": "^4.19.3",
|
|
8
8
|
"typescript": "^5.8.2",
|
|
9
|
-
"@layerzerolabs/common-node-utils": "0.2.
|
|
10
|
-
"@layerzerolabs/vm-tooling-stellar": "0.2.
|
|
9
|
+
"@layerzerolabs/common-node-utils": "0.2.34",
|
|
10
|
+
"@layerzerolabs/vm-tooling-stellar": "0.2.34"
|
|
11
11
|
},
|
|
12
12
|
"publishConfig": {
|
|
13
13
|
"access": "restricted",
|
|
14
14
|
"registry": "https://registry.npmjs.org/"
|
|
15
15
|
},
|
|
16
|
+
"externalRepoConfig": {
|
|
17
|
+
"targets": [
|
|
18
|
+
"audit-external"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
16
21
|
"scripts": {
|
|
17
22
|
"build": "pnpm build:contracts && pnpm generate:sdk",
|
|
18
23
|
"build:contracts": "pnpm exec lz-tool stellar contract build",
|