@layerzerolabs/protocol-stellar-v2 0.2.51 → 0.2.52
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 +281 -185
- package/.turbo/turbo-lint.log +69 -70
- package/.turbo/turbo-test.log +2010 -1754
- package/Cargo.lock +16 -0
- package/Cargo.toml +1 -0
- package/contracts/oapps/console-oft/Cargo.toml +30 -0
- package/contracts/oapps/console-oft/integration-tests/extensions/mod.rs +5 -0
- package/contracts/oapps/console-oft/integration-tests/extensions/test_combined.rs +90 -0
- package/contracts/oapps/console-oft/integration-tests/extensions/test_oft_fee.rs +186 -0
- package/contracts/oapps/console-oft/integration-tests/extensions/test_ownership.rs +161 -0
- package/contracts/oapps/console-oft/integration-tests/extensions/test_pausable.rs +154 -0
- package/contracts/oapps/console-oft/integration-tests/extensions/test_rate_limiter.rs +479 -0
- package/contracts/oapps/console-oft/integration-tests/mod.rs +3 -0
- package/contracts/oapps/console-oft/integration-tests/setup.rs +303 -0
- package/contracts/oapps/console-oft/integration-tests/utils.rs +685 -0
- package/contracts/oapps/console-oft/src/errors.rs +7 -0
- package/contracts/oapps/console-oft/src/extensions/mod.rs +3 -0
- package/contracts/oapps/console-oft/src/extensions/oft_fee.rs +239 -0
- package/contracts/oapps/console-oft/src/extensions/pausable.rs +185 -0
- package/contracts/oapps/console-oft/src/extensions/rate_limiter.rs +478 -0
- package/contracts/oapps/console-oft/src/interfaces/mintable.rs +14 -0
- package/contracts/oapps/console-oft/src/interfaces/mod.rs +3 -0
- package/contracts/oapps/console-oft/src/lib.rs +26 -0
- package/contracts/oapps/console-oft/src/oft.rs +208 -0
- package/contracts/oapps/console-oft/src/oft_access_control.rs +93 -0
- package/contracts/oapps/console-oft/src/oft_types/lock_unlock.rs +50 -0
- package/contracts/oapps/console-oft/src/oft_types/mint_burn.rs +50 -0
- package/contracts/oapps/console-oft/src/oft_types/mod.rs +24 -0
- package/contracts/oapps/console-oft/src/tests/extensions/mod.rs +3 -0
- package/contracts/oapps/console-oft/src/tests/extensions/oft_fee.rs +255 -0
- package/contracts/oapps/console-oft/src/tests/extensions/pausable.rs +212 -0
- package/contracts/oapps/console-oft/src/tests/extensions/rate_limiter.rs +992 -0
- package/contracts/oapps/console-oft/src/tests/mod.rs +2 -0
- package/contracts/oapps/console-oft/src/tests/oft_types/lock_unlock.rs +185 -0
- package/contracts/oapps/console-oft/src/tests/oft_types/mod.rs +1 -0
- package/contracts/oapps/oft/src/extensions/oft_fee.rs +5 -2
- package/contracts/oapps/oft/src/tests/extensions/oft_fee.rs +1 -1
- package/contracts/oapps/sac-manager/src/sac_manager.rs +8 -0
- package/contracts/workers/worker/src/worker.rs +8 -1
- package/docs/oft-guide.md +2 -2
- package/package.json +4 -4
- package/sdk/.turbo/turbo-test.log +356 -422
- package/sdk/dist/generated/dvn.d.ts +9 -3
- package/sdk/dist/generated/dvn.js +4 -4
- package/sdk/dist/generated/executor.d.ts +9 -3
- package/sdk/dist/generated/executor.js +4 -4
- package/sdk/package.json +1 -1
- package/sdk/test/oft-sml.test.ts +22 -41
- package/sdk/test/sac-manager.test.ts +23 -22
- package/sdk/test/secp256k1.ts +59 -0
- package/sdk/test/suites/constants.ts +5 -1
- package/sdk/test/suites/deploy.ts +14 -8
- package/sdk/test/suites/globalSetup.ts +144 -60
- package/sdk/test/suites/localnet.ts +20 -25
- package/sdk/test/utils.ts +1 -61
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
extern crate std;
|
|
2
|
+
|
|
3
|
+
use crate::oft_types::lock_unlock;
|
|
4
|
+
use endpoint_v2::Origin;
|
|
5
|
+
use oapp::oapp_receiver::{LzReceiveInternal, OAppReceiver};
|
|
6
|
+
use oft_core::{OFTCore, OFTInternal, OFTReceipt};
|
|
7
|
+
use soroban_sdk::{
|
|
8
|
+
contract, contractimpl, contracttype,
|
|
9
|
+
testutils::Address as _,
|
|
10
|
+
token::{StellarAssetClient, TokenClient},
|
|
11
|
+
Address, Bytes, BytesN, Env,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// Mock Contracts
|
|
16
|
+
// ============================================================================
|
|
17
|
+
|
|
18
|
+
#[contract]
|
|
19
|
+
struct DummyEndpoint;
|
|
20
|
+
|
|
21
|
+
#[derive(Clone)]
|
|
22
|
+
#[contracttype]
|
|
23
|
+
enum DummyEndpointDataKey {
|
|
24
|
+
Delegate(Address),
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
#[contractimpl]
|
|
28
|
+
impl DummyEndpoint {
|
|
29
|
+
pub fn set_delegate(env: Env, oapp: &Address, delegate: &Option<Address>) {
|
|
30
|
+
let key = DummyEndpointDataKey::Delegate(oapp.clone());
|
|
31
|
+
match delegate {
|
|
32
|
+
Some(d) => env.storage().persistent().set(&key, d),
|
|
33
|
+
None => env.storage().persistent().remove(&key),
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// LockUnlock OFT Harness Contract
|
|
40
|
+
// ============================================================================
|
|
41
|
+
|
|
42
|
+
#[common_macros::lz_contract]
|
|
43
|
+
#[oapp_macros::oapp(custom = [receiver])]
|
|
44
|
+
pub struct LockUnlockHarnessOFT;
|
|
45
|
+
|
|
46
|
+
#[contractimpl]
|
|
47
|
+
impl LockUnlockHarnessOFT {
|
|
48
|
+
pub fn __constructor(
|
|
49
|
+
env: &Env,
|
|
50
|
+
token: &Address,
|
|
51
|
+
owner: &Address,
|
|
52
|
+
endpoint: &Address,
|
|
53
|
+
delegate: &Address,
|
|
54
|
+
shared_decimals: u32,
|
|
55
|
+
) {
|
|
56
|
+
Self::__initialize_oft(env, token, shared_decimals, owner, endpoint, delegate);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
pub fn debit(env: Env, sender: Address, amount_ld: i128, min_amount_ld: i128, dst_eid: u32) -> OFTReceipt {
|
|
60
|
+
let (amount_sent_ld, amount_received_ld) =
|
|
61
|
+
<Self as OFTInternal>::__debit(&env, &sender, amount_ld, min_amount_ld, dst_eid);
|
|
62
|
+
OFTReceipt { amount_sent_ld, amount_received_ld }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
pub fn credit(env: Env, to: Address, amount_ld: i128, src_eid: u32) -> i128 {
|
|
66
|
+
<Self as OFTInternal>::__credit(&env, &to, amount_ld, src_eid)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
#[contractimpl(contracttrait)]
|
|
71
|
+
impl OFTCore for LockUnlockHarnessOFT {}
|
|
72
|
+
|
|
73
|
+
impl LzReceiveInternal for LockUnlockHarnessOFT {
|
|
74
|
+
fn __lz_receive(
|
|
75
|
+
env: &Env,
|
|
76
|
+
origin: &Origin,
|
|
77
|
+
guid: &BytesN<32>,
|
|
78
|
+
message: &Bytes,
|
|
79
|
+
extra_data: &Bytes,
|
|
80
|
+
executor: &Address,
|
|
81
|
+
value: i128,
|
|
82
|
+
) {
|
|
83
|
+
<Self as OFTInternal>::__receive(env, origin, guid, message, extra_data, executor, value)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#[contractimpl(contracttrait)]
|
|
88
|
+
impl OAppReceiver for LockUnlockHarnessOFT {}
|
|
89
|
+
|
|
90
|
+
impl OFTInternal for LockUnlockHarnessOFT {
|
|
91
|
+
fn __debit(env: &Env, sender: &Address, amount_ld: i128, min_amount_ld: i128, dst_eid: u32) -> (i128, i128) {
|
|
92
|
+
let target = Self::token(env);
|
|
93
|
+
lock_unlock::debit::<Self>(env, &target, sender, amount_ld, min_amount_ld, dst_eid)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
fn __credit(env: &Env, to: &Address, amount_ld: i128, src_eid: u32) -> i128 {
|
|
97
|
+
let target = Self::token(env);
|
|
98
|
+
lock_unlock::credit::<Self>(env, &target, to, amount_ld, src_eid)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// ============================================================================
|
|
103
|
+
// Test Setup
|
|
104
|
+
// ============================================================================
|
|
105
|
+
|
|
106
|
+
struct TestSetup {
|
|
107
|
+
env: Env,
|
|
108
|
+
client: LockUnlockHarnessOFTClient<'static>,
|
|
109
|
+
oft_address: Address,
|
|
110
|
+
token: Address,
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
fn setup() -> TestSetup {
|
|
114
|
+
let env = Env::default();
|
|
115
|
+
// Enable mock_all_auths_allowing_non_root_auth for all tests to bypass authorization checks
|
|
116
|
+
// including sub-contract invocations like token transfers
|
|
117
|
+
env.mock_all_auths_allowing_non_root_auth();
|
|
118
|
+
|
|
119
|
+
let token_admin = Address::generate(&env);
|
|
120
|
+
let sac = env.register_stellar_asset_contract_v2(token_admin.clone());
|
|
121
|
+
let token = sac.address();
|
|
122
|
+
let endpoint = env.register(DummyEndpoint, ());
|
|
123
|
+
|
|
124
|
+
let owner = Address::generate(&env);
|
|
125
|
+
let delegate = owner.clone();
|
|
126
|
+
let shared_decimals: u32 = 6;
|
|
127
|
+
|
|
128
|
+
let oft_address = env.register(LockUnlockHarnessOFT, (&token, &owner, &endpoint, &delegate, &shared_decimals));
|
|
129
|
+
let client = LockUnlockHarnessOFTClient::new(&env, &oft_address);
|
|
130
|
+
|
|
131
|
+
TestSetup { env, client, oft_address, token }
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// ============================================================================
|
|
135
|
+
// Tests
|
|
136
|
+
// ============================================================================
|
|
137
|
+
|
|
138
|
+
#[test]
|
|
139
|
+
fn test_debit_transfers_to_contract() {
|
|
140
|
+
let TestSetup { env, client, oft_address, token, .. } = setup();
|
|
141
|
+
|
|
142
|
+
let sender = Address::generate(&env);
|
|
143
|
+
|
|
144
|
+
// Auth is automatically mocked by mock_all_auths_allowing_non_root_auth
|
|
145
|
+
StellarAssetClient::new(&env, &token).mint(&sender, &1_000_000i128);
|
|
146
|
+
|
|
147
|
+
let token_client = TokenClient::new(&env, &token);
|
|
148
|
+
let sender_before = token_client.balance(&sender);
|
|
149
|
+
let contract_before = token_client.balance(&oft_address);
|
|
150
|
+
|
|
151
|
+
// With shared_decimals=6 and typical SAC decimals=7, conversion_rate=10 => 105 -> 100.
|
|
152
|
+
// debit transfers from sender to OFT contract
|
|
153
|
+
let amount_ld = 105i128;
|
|
154
|
+
|
|
155
|
+
let receipt = client.debit(&sender, &amount_ld, &0i128, &999u32);
|
|
156
|
+
assert_eq!(receipt.amount_sent_ld, receipt.amount_received_ld);
|
|
157
|
+
|
|
158
|
+
// LockUnlock transfers `amount_received_ld` from sender -> contract.
|
|
159
|
+
assert_eq!(token_client.balance(&sender), sender_before - receipt.amount_received_ld);
|
|
160
|
+
assert_eq!(token_client.balance(&oft_address), contract_before + receipt.amount_received_ld);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
#[test]
|
|
164
|
+
fn test_credit_transfers_from_contract() {
|
|
165
|
+
let TestSetup { env, client, oft_address, token, .. } = setup();
|
|
166
|
+
|
|
167
|
+
let recipient = Address::generate(&env);
|
|
168
|
+
|
|
169
|
+
// Auth is automatically mocked by mock_all_auths_allowing_non_root_auth
|
|
170
|
+
StellarAssetClient::new(&env, &token).mint(&oft_address, &1_000_000i128);
|
|
171
|
+
|
|
172
|
+
let token_client = TokenClient::new(&env, &token);
|
|
173
|
+
let contract_before = token_client.balance(&oft_address);
|
|
174
|
+
let recipient_before = token_client.balance(&recipient);
|
|
175
|
+
|
|
176
|
+
// credit transfers from OFT contract to recipient
|
|
177
|
+
let amount = 123i128;
|
|
178
|
+
|
|
179
|
+
let credited = client.credit(&recipient, &amount, &1u32);
|
|
180
|
+
assert_eq!(credited, amount);
|
|
181
|
+
|
|
182
|
+
// LockUnlock transfers `amount` from contract -> recipient.
|
|
183
|
+
assert_eq!(token_client.balance(&oft_address), contract_before - amount);
|
|
184
|
+
assert_eq!(token_client.balance(&recipient), recipient_before + amount);
|
|
185
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
mod lock_unlock;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
use common_macros::{contract_error, contract_trait, only_role, storage};
|
|
2
2
|
use soroban_sdk::{assert_with_error, contractevent, token::TokenClient, Address, Env};
|
|
3
|
-
use utils::{
|
|
3
|
+
use utils::{
|
|
4
|
+
option_ext::OptionExt,
|
|
5
|
+
rbac::{RoleBasedAccessControl, AUTHORIZER},
|
|
6
|
+
};
|
|
4
7
|
|
|
5
|
-
/// Role for fee configuration (set_default_fee_bps, set_fee_bps
|
|
8
|
+
/// Role for fee configuration (set_default_fee_bps, set_fee_bps).
|
|
6
9
|
pub const FEE_CONFIG_MANAGER_ROLE: &str = "FEE_CONFIG_MANAGER_ROLE";
|
|
7
10
|
|
|
8
11
|
/// Base fee in basis points (10,000 BPS = 100%)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
extern crate std;
|
|
2
2
|
|
|
3
|
-
use crate::extensions::oft_fee::{OFTFee, OFTFeeError, OFTFeeInternal};
|
|
4
3
|
use crate::extensions::oft_fee::FEE_CONFIG_MANAGER_ROLE;
|
|
4
|
+
use crate::extensions::oft_fee::{OFTFee, OFTFeeError, OFTFeeInternal};
|
|
5
5
|
use soroban_sdk::{
|
|
6
6
|
contract, contractimpl,
|
|
7
7
|
testutils::{Address as _, MockAuth, MockAuthInvoke},
|
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
//! - Mintable interface for OFT (mint on credit only; OFT burns on the token directly)
|
|
5
5
|
//! - Role-based access control operations (clawback, set_admin, set_authorized)
|
|
6
6
|
//!
|
|
7
|
+
//! ## Trust Model Requirement
|
|
8
|
+
//!
|
|
9
|
+
//! **The issuer account must be locked (master weight set to 0).** In Stellar classic assets,
|
|
10
|
+
//! transfers from/to the issuer are equivalent to minting/burning. The issuer can always mint
|
|
11
|
+
//! more tokens and perform other classic operations directly, even when an explicit admin (this
|
|
12
|
+
//! contract) is set. If the issuer account is not locked, the RBAC model enforced by this
|
|
13
|
+
//! contract can be bypassed, breaking the trust model.
|
|
14
|
+
//!
|
|
7
15
|
//! ## Authorization Model
|
|
8
16
|
//!
|
|
9
17
|
//! - **Owner** (via Ownable): The deployer/admin address. Can manage TTL and grant/revoke roles.
|
|
@@ -46,6 +46,12 @@ pub trait Worker: Auth {
|
|
|
46
46
|
/// Admins can configure worker settings like fee multipliers, deposit addresses,
|
|
47
47
|
/// and supported option types.
|
|
48
48
|
///
|
|
49
|
+
/// **Address type requirement:** Admins used for execute/compose flows (Executor)
|
|
50
|
+
/// or custom account auth (DVN) must be Ed25519 accounts. Contract-type addresses
|
|
51
|
+
/// cannot participate in custom account authorization. Only Ed25519 account
|
|
52
|
+
/// addresses can sign for execute/compose and DVN admin operations. Contract-type
|
|
53
|
+
/// admins are not supported for these flows;
|
|
54
|
+
///
|
|
49
55
|
/// # Arguments
|
|
50
56
|
/// * `admin` - The address to set admin status for
|
|
51
57
|
/// * `active` - `true` to add admin, `false` to remove
|
|
@@ -306,7 +312,8 @@ pub trait Worker: Auth {
|
|
|
306
312
|
/// This function should be called only once to initialize the worker once.
|
|
307
313
|
///
|
|
308
314
|
/// # Arguments
|
|
309
|
-
/// * `admins` - Initial admin addresses (must not be empty)
|
|
315
|
+
/// * `admins` - Initial admin addresses (must not be empty). Admins used for
|
|
316
|
+
/// execute/compose or custom account auth must be Ed25519 (see `set_admin`).
|
|
310
317
|
/// * `message_libs` - Supported message library addresses
|
|
311
318
|
/// * `price_feed` - Price feed contract address
|
|
312
319
|
/// * `default_multiplier_bps` - Default fee multiplier in basis points
|
package/docs/oft-guide.md
CHANGED
|
@@ -256,7 +256,7 @@ impl OFTFeeInternal for MyOFT {}
|
|
|
256
256
|
|
|
257
257
|
// Override __debit_view to apply fee:
|
|
258
258
|
fn __debit_view(env: &Env, amount_ld: i128, min_amount_ld: i128, dst_eid: u32) -> OFTReceipt {
|
|
259
|
-
let fee = Self::
|
|
259
|
+
let fee = Self::__get_fee(env, dst_eid, amount_ld);
|
|
260
260
|
let amount_after_fee = amount_ld - fee;
|
|
261
261
|
// ... rest of logic
|
|
262
262
|
}
|
|
@@ -267,7 +267,7 @@ Usage:
|
|
|
267
267
|
```rust
|
|
268
268
|
oft.set_default_fee_bps(100); // 1% default fee (owner only)
|
|
269
269
|
oft.set_fee_bps(dst_eid, Some(50)); // 0.5% for specific destination
|
|
270
|
-
oft.
|
|
270
|
+
oft.set_fee_deposit(fee_addr); // Where fees go
|
|
271
271
|
```
|
|
272
272
|
|
|
273
273
|
### Rate limiter
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@layerzerolabs/protocol-stellar-v2",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.52",
|
|
4
4
|
"private": false,
|
|
5
5
|
"license": "LZBL-1.2",
|
|
6
6
|
"devDependencies": {
|
|
7
7
|
"@types/node": "^22.18.6",
|
|
8
8
|
"tsx": "^4.19.3",
|
|
9
9
|
"typescript": "^5.8.2",
|
|
10
|
-
"@layerzerolabs/
|
|
11
|
-
"@layerzerolabs/vm-tooling-stellar": "0.2.
|
|
12
|
-
"@layerzerolabs/
|
|
10
|
+
"@layerzerolabs/stellar-ts-bindings-gen": "0.2.52",
|
|
11
|
+
"@layerzerolabs/vm-tooling-stellar": "0.2.52",
|
|
12
|
+
"@layerzerolabs/common-node-utils": "0.2.52"
|
|
13
13
|
},
|
|
14
14
|
"publishConfig": {
|
|
15
15
|
"access": "restricted",
|