@layerzerolabs/protocol-stellar-v2 0.2.20 → 0.2.21
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 +783 -802
- package/.turbo/turbo-lint.log +320 -157
- package/.turbo/turbo-test.log +1414 -1457
- package/Cargo.lock +109 -108
- package/Cargo.toml +32 -18
- package/contracts/common-macros/Cargo.toml +7 -7
- package/contracts/common-macros/src/auth.rs +18 -37
- package/contracts/common-macros/src/contract_ttl.rs +2 -2
- package/contracts/common-macros/src/lib.rs +27 -10
- package/contracts/common-macros/src/lz_contract.rs +38 -7
- package/contracts/common-macros/src/storage.rs +251 -292
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_multisig_code.snap +6 -12
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_ownable_code.snap +12 -17
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +2 -7
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__upgradeable__snapshot_generated_upgradeable_code.snap +20 -9
- package/contracts/common-macros/src/tests/upgradeable.rs +26 -4
- package/contracts/common-macros/src/ttl_configurable.rs +2 -10
- package/contracts/common-macros/src/ttl_extendable.rs +2 -10
- package/contracts/common-macros/src/upgradeable.rs +56 -15
- package/contracts/common-macros/src/utils.rs +0 -9
- package/contracts/endpoint-v2/src/lib.rs +3 -2
- package/contracts/endpoint-v2/src/tests/endpoint_v2/clear.rs +2 -2
- package/contracts/endpoint-v2/src/tests/endpoint_v2/lz_receive_alert.rs +3 -3
- package/contracts/endpoint-v2/src/tests/endpoint_v2/send.rs +4 -4
- package/contracts/endpoint-v2/src/tests/endpoint_v2/set_delegate.rs +17 -5
- package/contracts/endpoint-v2/src/tests/endpoint_v2/set_zro.rs +4 -4
- package/contracts/endpoint-v2/src/tests/endpoint_v2/verify.rs +2 -2
- package/contracts/endpoint-v2/src/tests/message_lib_manager/register_library.rs +2 -2
- package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_lib_timeout.rs +6 -6
- package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_library.rs +67 -37
- package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_send_library.rs +5 -5
- package/contracts/endpoint-v2/src/tests/message_lib_manager/set_receive_library.rs +44 -54
- package/contracts/endpoint-v2/src/tests/message_lib_manager/set_receive_library_timeout.rs +7 -7
- package/contracts/endpoint-v2/src/tests/message_lib_manager/set_send_library.rs +8 -8
- package/contracts/endpoint-v2/src/tests/messaging_channel/burn.rs +3 -3
- package/contracts/endpoint-v2/src/tests/messaging_channel/nilify.rs +4 -4
- package/contracts/endpoint-v2/src/tests/messaging_channel/skip.rs +3 -3
- package/contracts/endpoint-v2/src/tests/messaging_composer/clear_compose.rs +2 -2
- package/contracts/endpoint-v2/src/tests/messaging_composer/lz_compose_alert.rs +3 -3
- package/contracts/endpoint-v2/src/tests/messaging_composer/send_compose.rs +2 -2
- package/contracts/layerzero-views/Cargo.toml +0 -1
- package/contracts/layerzero-views/src/layerzero_view.rs +1 -13
- package/contracts/macro-integration-tests/Cargo.toml +5 -15
- package/contracts/macro-integration-tests/tests/runtime/oapp/mod.rs +48 -0
- package/contracts/macro-integration-tests/tests/runtime/oapp/oapp_core.rs +170 -0
- package/contracts/macro-integration-tests/tests/runtime/oapp/options_type3.rs +154 -0
- package/contracts/macro-integration-tests/tests/runtime/oapp/receiver.rs +338 -0
- package/contracts/macro-integration-tests/tests/runtime/oapp/sender.rs +435 -0
- package/contracts/macro-integration-tests/tests/runtime.rs +1 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/custom_wrong_value.rs +8 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/custom_wrong_value.stderr +5 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/missing_lz_receive_internal.rs +8 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/missing_lz_receive_internal.stderr +71 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/non_struct_input.rs +10 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/non_struct_input.stderr +5 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/unknown_custom_option.rs +8 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/unknown_custom_option.stderr +5 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/wrong_key.rs +8 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/wrong_key.stderr +5 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/pass/custom_all.rs +38 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/pass/custom_single_trait.rs +96 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/pass/minimal_contract.rs +64 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/pass/struct_with_fields.rs +46 -0
- package/contracts/macro-integration-tests/tests/ui/ownable/fail/only_auth_missing_env.stderr +8 -0
- package/contracts/macro-integration-tests/tests/ui/ownable/pass/namespacing_and_imports.rs +1 -1
- package/contracts/macro-integration-tests/tests/ui/ownable/pass/only_auth_env_param_variants.rs +1 -1
- package/contracts/macro-integration-tests/tests/ui_oapp.rs +11 -0
- package/contracts/message-libs/message-lib-common/Cargo.toml +0 -1
- package/contracts/message-libs/message-lib-common/src/errors.rs +1 -1
- package/contracts/message-libs/treasury/Cargo.toml +0 -2
- package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +2 -2
- package/contracts/message-libs/uln-302/src/tests/receive_uln302/effective_receive_uln_config.rs +2 -2
- package/contracts/message-libs/uln-302/src/tests/receive_uln302/set_default_receive_uln_configs.rs +2 -2
- package/contracts/message-libs/uln-302/src/tests/receive_uln302/verify.rs +2 -2
- package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_executor_config.rs +2 -2
- package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_send_uln_config.rs +2 -2
- package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +7 -27
- package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_executor_configs.rs +2 -2
- package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_send_uln_configs.rs +2 -2
- package/contracts/oapps/counter/Cargo.toml +4 -6
- package/contracts/oapps/counter/integration_tests/utils.rs +19 -12
- package/contracts/oapps/oapp/src/errors.rs +1 -1
- package/contracts/oapps/oapp/src/interfaces/mod.rs +3 -0
- package/contracts/oapps/oapp/src/interfaces/oapp_msg_inspector.rs +47 -0
- package/contracts/oapps/oapp/src/lib.rs +1 -0
- package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +4 -4
- package/contracts/oapps/oapp/src/oapp_core.rs +5 -5
- package/contracts/oapps/oapp/src/oapp_options_type3.rs +12 -4
- package/contracts/oapps/oapp/src/oapp_receiver.rs +14 -9
- package/contracts/oapps/oapp/src/tests/mod.rs +4 -4
- package/contracts/oapps/oapp/src/tests/{test_oapp_core.rs → oapp_core.rs} +4 -4
- package/contracts/oapps/oapp/src/tests/{test_oapp_options_type3.rs → oapp_options_type3.rs} +3 -4
- package/contracts/oapps/oapp-macros/Cargo.toml +8 -4
- package/contracts/oapps/oapp-macros/src/generators.rs +9 -34
- package/contracts/oapps/oapp-macros/src/lib.rs +3 -0
- package/contracts/oapps/oapp-macros/src/tests/mod.rs +2 -0
- package/contracts/oapps/oapp-macros/src/tests/oapp.rs +88 -0
- package/contracts/oapps/oapp-macros/src/tests/parse_custom_impls.rs +86 -0
- package/contracts/oapps/oapp-macros/src/tests/snapshots/oapp_macros__tests__oapp__snapshot_generate_oapp.snap +103 -0
- package/contracts/oapps/oft/integration-tests/utils.rs +28 -8
- package/contracts/oapps/oft/src/extensions/oft_fee.rs +136 -74
- package/contracts/oapps/oft/src/extensions/pausable.rs +44 -10
- package/contracts/oapps/oft/src/extensions/rate_limiter.rs +170 -130
- package/contracts/oapps/oft/src/oft.rs +19 -12
- package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +1 -1
- package/contracts/oapps/oft/src/oft_types/mint_burn.rs +1 -1
- package/contracts/oapps/oft-core/Cargo.toml +1 -4
- package/contracts/oapps/oft-core/integration-tests/setup.rs +2 -2
- package/contracts/oapps/oft-core/integration-tests/utils.rs +21 -3
- package/contracts/oapps/oft-core/src/errors.rs +3 -2
- package/contracts/oapps/oft-core/src/events.rs +6 -0
- package/contracts/oapps/oft-core/src/lib.rs +1 -1
- package/contracts/oapps/oft-core/src/oft_core.rs +115 -60
- package/contracts/oapps/oft-core/src/storage.rs +7 -3
- package/contracts/oapps/oft-core/src/tests/mod.rs +1 -0
- package/contracts/oapps/oft-core/src/tests/test_decimals.rs +37 -2
- package/contracts/oapps/oft-core/src/tests/test_lz_receive.rs +2 -2
- package/contracts/oapps/oft-core/src/tests/test_msg_inspector.rs +323 -0
- package/contracts/oapps/oft-core/src/tests/test_send.rs +2 -2
- package/contracts/oapps/oft-core/src/tests/test_utils.rs +59 -14
- package/contracts/utils/Cargo.toml +0 -1
- package/contracts/utils/src/errors.rs +1 -1
- package/contracts/utils/src/multisig.rs +17 -8
- package/contracts/utils/src/ownable.rs +6 -6
- package/contracts/utils/src/testing_utils.rs +124 -54
- package/contracts/utils/src/tests/multisig.rs +12 -12
- package/contracts/utils/src/tests/ownable.rs +6 -6
- package/contracts/utils/src/tests/testing_utils.rs +50 -167
- package/contracts/utils/src/tests/ttl_configurable.rs +5 -5
- package/contracts/utils/src/tests/upgradeable.rs +1 -1
- package/contracts/utils/src/ttl_configurable.rs +10 -4
- package/contracts/utils/src/upgradeable.rs +5 -5
- package/contracts/workers/dvn/Cargo.toml +5 -6
- package/contracts/workers/dvn/src/dvn.rs +2 -12
- package/contracts/workers/dvn-fee-lib/Cargo.toml +1 -1
- package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +37 -19
- package/contracts/workers/dvn-fee-lib/src/lib.rs +12 -2
- package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +15 -13
- package/contracts/workers/executor/Cargo.toml +3 -0
- package/contracts/workers/executor/src/executor.rs +2 -12
- package/contracts/workers/executor/src/lib.rs +2 -2
- package/contracts/workers/executor/src/tests/auth.rs +394 -0
- package/contracts/workers/executor/src/tests/executor.rs +410 -0
- package/contracts/workers/executor/src/tests/mod.rs +3 -0
- package/contracts/workers/executor/src/tests/setup.rs +250 -0
- package/contracts/workers/executor-fee-lib/Cargo.toml +5 -0
- package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +1 -12
- package/contracts/workers/executor-fee-lib/src/lib.rs +8 -2
- package/contracts/workers/executor-helper/Cargo.toml +0 -1
- package/contracts/workers/price-feed/Cargo.toml +5 -0
- package/contracts/workers/price-feed/src/lib.rs +9 -4
- package/contracts/workers/price-feed/src/price_feed.rs +1 -11
- package/contracts/workers/worker/src/errors.rs +1 -1
- package/contracts/workers/worker/src/tests/setup.rs +1 -1
- package/contracts/workers/worker/src/tests/worker.rs +55 -41
- package/contracts/workers/worker/src/worker.rs +34 -25
- package/docs/error-spec.md +55 -0
- package/docs/layerzero-v2-on-stellar.md +447 -0
- package/docs/oapp-guide.md +212 -0
- package/docs/oft-guide.md +314 -0
- package/package.json +3 -3
- package/sdk/.turbo/turbo-test.log +260 -257
- package/sdk/dist/generated/bml.d.ts +3 -3
- package/sdk/dist/generated/bml.js +4 -4
- package/sdk/dist/generated/counter.d.ts +295 -295
- package/sdk/dist/generated/counter.js +43 -43
- package/sdk/dist/generated/dvn.d.ts +91 -91
- package/sdk/dist/generated/dvn.js +24 -24
- package/sdk/dist/generated/dvn_fee_lib.d.ts +92 -92
- package/sdk/dist/generated/dvn_fee_lib.js +25 -25
- package/sdk/dist/generated/endpoint.d.ts +99 -99
- package/sdk/dist/generated/endpoint.js +16 -16
- package/sdk/dist/generated/executor.d.ts +91 -91
- package/sdk/dist/generated/executor.js +24 -24
- package/sdk/dist/generated/executor_fee_lib.d.ts +92 -92
- package/sdk/dist/generated/executor_fee_lib.js +25 -25
- package/sdk/dist/generated/executor_helper.d.ts +3 -3
- package/sdk/dist/generated/executor_helper.js +4 -4
- package/sdk/dist/generated/layerzero_view.d.ts +186 -186
- package/sdk/dist/generated/layerzero_view.js +35 -35
- package/sdk/dist/generated/oft.d.ts +366 -352
- package/sdk/dist/generated/oft.js +74 -79
- package/sdk/dist/generated/price_feed.d.ts +198 -198
- package/sdk/dist/generated/price_feed.js +39 -39
- package/sdk/dist/generated/sml.d.ts +99 -99
- package/sdk/dist/generated/sml.js +16 -16
- package/sdk/dist/generated/treasury.d.ts +99 -99
- package/sdk/dist/generated/treasury.js +16 -16
- package/sdk/dist/generated/uln302.d.ts +99 -99
- package/sdk/dist/generated/uln302.js +16 -16
- package/sdk/dist/generated/upgrader.d.ts +3 -3
- package/sdk/dist/generated/upgrader.js +3 -3
- package/sdk/package.json +1 -1
- package/sdk/test/suites/localnet.ts +84 -20
- package/contracts/ERROR_SPEC.md +0 -51
- package/contracts/endpoint-v2/ARCHITECTURE.md +0 -233
- /package/contracts/oapps/oapp/src/tests/{test_oapp_receiver.rs → oapp_receiver.rs} +0 -0
- /package/contracts/oapps/oapp/src/tests/{test_oapp_sender.rs → oapp_sender.rs} +0 -0
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
//! OFT - traits and implementations for Omnichain Fungible Tokens.
|
|
2
2
|
//!
|
|
3
3
|
//! This module provides:
|
|
4
|
-
//! - `OFTInternal`: Internal methods NOT exposed as contract entrypoints (`__debit`, `__credit`, `__initialize_oft`, etc.)
|
|
4
|
+
//! - `OFTInternal`: Internal methods NOT exposed as contract entrypoints (`__debit`, `__credit`, `__initialize_oft`, `__receive`, etc.)
|
|
5
5
|
//! - `OFTCore`: Public methods exposed as contract entrypoints (using `#[contracttrait]`)
|
|
6
6
|
//! - `impl_oft_lz_receive!`: Macro to implement `LzReceiveInternal` with default OFT receive logic
|
|
7
|
-
//! - Helper functions: `lz_receive` for handling incoming cross-chain transfers
|
|
8
7
|
//!
|
|
9
8
|
//! ## Usage
|
|
10
9
|
//!
|
|
@@ -48,14 +47,15 @@ use crate::{
|
|
|
48
47
|
self as oft_core,
|
|
49
48
|
codec::{oft_compose_msg_codec::OFTComposeMsg, oft_msg_codec::OFTMessage},
|
|
50
49
|
errors::OFTError,
|
|
51
|
-
events::{self, OFTSent},
|
|
50
|
+
events::{self, MsgInspectorSet, OFTSent},
|
|
52
51
|
storage::OFTStorage,
|
|
53
52
|
types::{self, OFTFeeDetail, OFTLimit, OFTReceipt, SendParam},
|
|
54
53
|
utils as oft_utils,
|
|
55
54
|
};
|
|
56
|
-
use common_macros::contract_trait;
|
|
55
|
+
use common_macros::{contract_trait, only_auth};
|
|
57
56
|
use endpoint_v2::{MessagingComposerClient, MessagingFee, MessagingReceipt};
|
|
58
57
|
use oapp::{
|
|
58
|
+
interfaces::OAppMsgInspectorClient,
|
|
59
59
|
oapp_core::{initialize_oapp, OAppCore},
|
|
60
60
|
oapp_options_type3::OAppOptionsType3,
|
|
61
61
|
oapp_receiver::OAppReceiver,
|
|
@@ -120,7 +120,7 @@ pub trait OFTInternal: OAppCore + OAppReceiver + OAppSenderInternal + OAppOption
|
|
|
120
120
|
|
|
121
121
|
// Initialize OFT storage
|
|
122
122
|
OFTStorage::set_token(env, token);
|
|
123
|
-
OFTStorage::
|
|
123
|
+
OFTStorage::set_decimals_diff(env, &(local_decimals - shared_decimals));
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
// =========================================================================
|
|
@@ -167,6 +167,8 @@ pub trait OFTInternal: OAppCore + OAppReceiver + OAppSenderInternal + OAppOption
|
|
|
167
167
|
/// # Returns
|
|
168
168
|
/// A tuple of (transfer limits, fee details, estimated receipt)
|
|
169
169
|
fn __quote_oft(env: &Env, send_param: &SendParam) -> (OFTLimit, Vec<OFTFeeDetail>, OFTReceipt) {
|
|
170
|
+
assert_with_error!(env, send_param.amount_ld >= 0, OFTError::InvalidAmount);
|
|
171
|
+
|
|
170
172
|
let limit = OFTLimit { min_amount_ld: 0, max_amount_ld: i128::MAX };
|
|
171
173
|
let fee_details = vec![env];
|
|
172
174
|
let oft_receipt = Self::__debit_view(env, send_param.amount_ld, send_param.min_amount_ld, send_param.dst_eid);
|
|
@@ -183,6 +185,8 @@ pub trait OFTInternal: OAppCore + OAppReceiver + OAppSenderInternal + OAppOption
|
|
|
183
185
|
/// # Returns
|
|
184
186
|
/// The messaging fee required for the transfer
|
|
185
187
|
fn __quote_send(env: &Env, from: &Address, send_param: &SendParam, pay_in_zro: bool) -> MessagingFee {
|
|
188
|
+
assert_with_error!(env, send_param.amount_ld >= 0, OFTError::InvalidAmount);
|
|
189
|
+
|
|
186
190
|
let OFTReceipt { amount_received_ld, .. } =
|
|
187
191
|
Self::__debit_view(env, send_param.amount_ld, send_param.min_amount_ld, send_param.dst_eid);
|
|
188
192
|
|
|
@@ -214,6 +218,8 @@ pub trait OFTInternal: OAppCore + OAppReceiver + OAppSenderInternal + OAppOption
|
|
|
214
218
|
) -> (MessagingReceipt, OFTReceipt) {
|
|
215
219
|
from.require_auth();
|
|
216
220
|
|
|
221
|
+
assert_with_error!(env, send_param.amount_ld >= 0, OFTError::InvalidAmount);
|
|
222
|
+
|
|
217
223
|
let oft_receipt = Self::__debit(env, from, send_param.amount_ld, send_param.min_amount_ld, send_param.dst_eid);
|
|
218
224
|
|
|
219
225
|
let (msg, options) = Self::__build_msg_and_options(env, from, send_param, oft_receipt.amount_received_ld);
|
|
@@ -261,10 +267,13 @@ pub trait OFTInternal: OAppCore + OAppReceiver + OAppSenderInternal + OAppOption
|
|
|
261
267
|
|
|
262
268
|
/// Builds OFT message and combines options for cross-chain transfer.
|
|
263
269
|
///
|
|
270
|
+
/// If a message inspector is set, it will be called to validate the message and options.
|
|
271
|
+
/// The inspector should panic if the message or options are invalid.
|
|
272
|
+
///
|
|
264
273
|
/// # Arguments
|
|
265
274
|
/// * `from` - The address initiating the transfer
|
|
266
275
|
/// * `send_param` - The send parameters including destination, recipient, and options
|
|
267
|
-
/// * `
|
|
276
|
+
/// * `amount_receive_ld` - The amount to be received in local decimals (after dust removal)
|
|
268
277
|
///
|
|
269
278
|
/// # Returns
|
|
270
279
|
/// A tuple of (encoded message, combined options)
|
|
@@ -272,20 +281,26 @@ pub trait OFTInternal: OAppCore + OAppReceiver + OAppSenderInternal + OAppOption
|
|
|
272
281
|
env: &Env,
|
|
273
282
|
from: &Address,
|
|
274
283
|
send_param: &SendParam,
|
|
275
|
-
|
|
284
|
+
amount_receive_ld: i128,
|
|
276
285
|
) -> (Bytes, Bytes) {
|
|
277
286
|
let has_compose = !send_param.compose_msg.is_empty();
|
|
278
287
|
let conversion_rate = Self::__decimal_conversion_rate(env);
|
|
279
288
|
let (msg, _) = OFTMessage {
|
|
280
289
|
send_to: send_param.to.clone(),
|
|
281
|
-
amount_sd: oft_utils::to_sd(env,
|
|
290
|
+
amount_sd: oft_utils::to_sd(env, amount_receive_ld, conversion_rate),
|
|
282
291
|
compose_from: if has_compose { Some(oft_utils::address_payload(from)) } else { None },
|
|
283
292
|
compose_msg: if has_compose { Some(send_param.compose_msg.clone()) } else { None },
|
|
284
293
|
}
|
|
285
294
|
.encode(env);
|
|
286
295
|
let msg_type = if has_compose { types::SEND_AND_CALL } else { types::SEND };
|
|
296
|
+
let options = Self::combine_options(env, send_param.dst_eid, msg_type, &send_param.extra_options);
|
|
297
|
+
|
|
298
|
+
// Optionally inspect message and options if inspector is set
|
|
299
|
+
if let Some(inspector) = Self::__msg_inspector(env) {
|
|
300
|
+
OAppMsgInspectorClient::new(env, &inspector).inspect(&env.current_contract_address(), &msg, &options);
|
|
301
|
+
}
|
|
287
302
|
|
|
288
|
-
(msg,
|
|
303
|
+
(msg, options)
|
|
289
304
|
}
|
|
290
305
|
|
|
291
306
|
// ----- Storage Accessors -----
|
|
@@ -297,15 +312,81 @@ pub trait OFTInternal: OAppCore + OAppReceiver + OAppSenderInternal + OAppOption
|
|
|
297
312
|
|
|
298
313
|
/// Retrieves the decimal conversion rate used for cross-chain normalization.
|
|
299
314
|
fn __decimal_conversion_rate(env: &Env) -> i128 {
|
|
300
|
-
OFTStorage::
|
|
315
|
+
let decimals_diff = OFTStorage::decimals_diff(env).unwrap_or_panic(env, OFTError::NotInitialized);
|
|
316
|
+
10_i128.pow(decimals_diff)
|
|
301
317
|
}
|
|
302
318
|
|
|
303
319
|
/// Retrieves the shared decimals used for cross-chain normalization.
|
|
304
320
|
fn __shared_decimals(env: &Env) -> u32 {
|
|
305
|
-
let
|
|
306
|
-
let
|
|
321
|
+
let local_decimals = TokenClient::new(env, &Self::__token(env)).decimals();
|
|
322
|
+
let decimals_diff = OFTStorage::decimals_diff(env).unwrap_or_panic(env, OFTError::NotInitialized);
|
|
323
|
+
local_decimals - decimals_diff
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/// Returns the message inspector address if set.
|
|
327
|
+
fn __msg_inspector(env: &Env) -> Option<Address> {
|
|
328
|
+
OFTStorage::msg_inspector(env)
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/// Sets or removes the message inspector address.
|
|
332
|
+
///
|
|
333
|
+
/// The message inspector is an optional contract that validates outgoing messages
|
|
334
|
+
/// and options before they are sent cross-chain. If set, the inspector's `inspect`
|
|
335
|
+
/// method will be called during `send` and `quote_send` operations.
|
|
336
|
+
///
|
|
337
|
+
/// # Arguments
|
|
338
|
+
/// * `inspector` - The address of the inspector contract, or None to remove
|
|
339
|
+
fn __set_msg_inspector(env: &Env, inspector: &Option<Address>) {
|
|
340
|
+
OFTStorage::set_or_remove_msg_inspector(env, inspector);
|
|
341
|
+
MsgInspectorSet { inspector: inspector.clone() }.publish(env);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// ----- Receive Handler -----
|
|
345
|
+
|
|
346
|
+
/// Handles incoming cross-chain OFT transfer from LayerZero endpoint.
|
|
347
|
+
///
|
|
348
|
+
/// Credits tokens to the recipient and optionally queues a compose message.
|
|
349
|
+
/// Override this method to implement custom receive logic (e.g., pausable, rate limiting).
|
|
350
|
+
///
|
|
351
|
+
/// # Arguments
|
|
352
|
+
/// * `origin` - The origin information (source chain, sender, nonce)
|
|
353
|
+
/// * `guid` - The unique message identifier
|
|
354
|
+
/// * `message` - The encoded OFT message payload
|
|
355
|
+
/// * `extra_data` - Additional data (unused in default implementation)
|
|
356
|
+
/// * `executor` - The address of the executor handling the message (unused in default implementation)
|
|
357
|
+
/// * `value` - The native token value sent with the message (unused in default implementation)
|
|
358
|
+
fn __receive(
|
|
359
|
+
env: &Env,
|
|
360
|
+
origin: &endpoint_v2::Origin,
|
|
361
|
+
guid: &soroban_sdk::BytesN<32>,
|
|
362
|
+
message: &Bytes,
|
|
363
|
+
_extra_data: &Bytes,
|
|
364
|
+
_executor: &Address,
|
|
365
|
+
_value: i128,
|
|
366
|
+
) {
|
|
367
|
+
let oft_msg = OFTMessage::decode(message);
|
|
368
|
+
let send_to = oft_utils::resolve_address(env, &oft_msg.send_to);
|
|
369
|
+
|
|
307
370
|
let conversion_rate = Self::__decimal_conversion_rate(env);
|
|
308
|
-
|
|
371
|
+
let amount_received_ld =
|
|
372
|
+
Self::__credit(env, &send_to, oft_utils::to_ld(oft_msg.amount_sd, conversion_rate), origin.src_eid);
|
|
373
|
+
|
|
374
|
+
if oft_msg.is_composed() {
|
|
375
|
+
let compose_msg = OFTComposeMsg {
|
|
376
|
+
nonce: origin.nonce,
|
|
377
|
+
src_eid: origin.src_eid,
|
|
378
|
+
amount_ld: amount_received_ld,
|
|
379
|
+
compose_from: oft_msg.compose_from.unwrap(),
|
|
380
|
+
compose_msg: oft_msg.compose_msg.unwrap(),
|
|
381
|
+
}
|
|
382
|
+
.encode(env);
|
|
383
|
+
|
|
384
|
+
let endpoint_client = MessagingComposerClient::new(env, &Self::endpoint(env));
|
|
385
|
+
endpoint_client.send_compose(&env.current_contract_address(), &send_to, guid, &0, &compose_msg);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
events::OFTReceived { guid: guid.clone(), src_eid: origin.src_eid, to: send_to, amount_received_ld }
|
|
389
|
+
.publish(env);
|
|
309
390
|
}
|
|
310
391
|
}
|
|
311
392
|
|
|
@@ -352,6 +433,24 @@ pub trait OFTCore: OFTInternal {
|
|
|
352
433
|
false
|
|
353
434
|
}
|
|
354
435
|
|
|
436
|
+
/// Returns the message inspector address if set.
|
|
437
|
+
fn msg_inspector(env: &soroban_sdk::Env) -> Option<soroban_sdk::Address> {
|
|
438
|
+
Self::__msg_inspector(env)
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/// Sets or removes the message inspector address.
|
|
442
|
+
///
|
|
443
|
+
/// The message inspector is an optional contract that validates outgoing messages
|
|
444
|
+
/// and options before they are sent cross-chain. If set, the inspector's `inspect`
|
|
445
|
+
/// method will be called during `send` and `quote_send` operations.
|
|
446
|
+
///
|
|
447
|
+
/// # Arguments
|
|
448
|
+
/// * `inspector` - The address of the inspector contract, or None to remove
|
|
449
|
+
#[only_auth]
|
|
450
|
+
fn set_msg_inspector(env: &soroban_sdk::Env, inspector: &Option<soroban_sdk::Address>) {
|
|
451
|
+
Self::__set_msg_inspector(env, inspector);
|
|
452
|
+
}
|
|
453
|
+
|
|
355
454
|
/// Quotes an OFT transfer without executing.
|
|
356
455
|
///
|
|
357
456
|
/// # Returns
|
|
@@ -397,8 +496,8 @@ pub trait OFTCore: OFTInternal {
|
|
|
397
496
|
/// Implements `LzReceiveInternal` for an OFT contract using the default OFT receive logic.
|
|
398
497
|
///
|
|
399
498
|
/// This macro generates the boilerplate `LzReceiveInternal` implementation that delegates
|
|
400
|
-
/// to `
|
|
401
|
-
/// to the recipient, and optionally queuing compose messages.
|
|
499
|
+
/// to `OFTInternal::__receive`, which handles decoding the OFT message, crediting
|
|
500
|
+
/// tokens to the recipient, and optionally queuing compose messages.
|
|
402
501
|
///
|
|
403
502
|
/// # Usage
|
|
404
503
|
///
|
|
@@ -428,52 +527,8 @@ macro_rules! impl_oft_lz_receive {
|
|
|
428
527
|
executor: &soroban_sdk::Address,
|
|
429
528
|
value: i128,
|
|
430
529
|
) {
|
|
431
|
-
oft_core::
|
|
530
|
+
<Self as oft_core::OFTInternal>::__receive(env, origin, guid, message, extra_data, executor, value)
|
|
432
531
|
}
|
|
433
532
|
}
|
|
434
533
|
};
|
|
435
534
|
}
|
|
436
|
-
|
|
437
|
-
/// Handles incoming cross-chain OFT transfer from LayerZero endpoint.
|
|
438
|
-
///
|
|
439
|
-
/// Credits tokens to the recipient and optionally queues a compose message.
|
|
440
|
-
///
|
|
441
|
-
/// # Arguments
|
|
442
|
-
/// * `executor` - The address of the executor handling the message (unused in default implementation)
|
|
443
|
-
/// * `origin` - The origin information (source chain, sender, nonce)
|
|
444
|
-
/// * `guid` - The unique message identifier
|
|
445
|
-
/// * `message` - The encoded OFT message payload
|
|
446
|
-
/// * `extra_data` - Additional data (unused in default implementation)
|
|
447
|
-
/// * `value` - The native token value sent with the message (unused in default implementation)
|
|
448
|
-
pub fn lz_receive<T: OFTInternal>(
|
|
449
|
-
env: &soroban_sdk::Env,
|
|
450
|
-
_executor: &soroban_sdk::Address,
|
|
451
|
-
origin: &endpoint_v2::Origin,
|
|
452
|
-
guid: &soroban_sdk::BytesN<32>,
|
|
453
|
-
message: &soroban_sdk::Bytes,
|
|
454
|
-
_extra_data: &soroban_sdk::Bytes,
|
|
455
|
-
_value: i128,
|
|
456
|
-
) {
|
|
457
|
-
let oft_msg = OFTMessage::decode(message);
|
|
458
|
-
let send_to = oft_utils::resolve_address(env, &oft_msg.send_to);
|
|
459
|
-
|
|
460
|
-
let conversion_rate = T::__decimal_conversion_rate(env);
|
|
461
|
-
let amount_received_ld =
|
|
462
|
-
T::__credit(env, &send_to, oft_utils::to_ld(oft_msg.amount_sd, conversion_rate), origin.src_eid);
|
|
463
|
-
|
|
464
|
-
if oft_msg.is_composed() {
|
|
465
|
-
let compose_msg = OFTComposeMsg {
|
|
466
|
-
nonce: origin.nonce,
|
|
467
|
-
src_eid: origin.src_eid,
|
|
468
|
-
amount_ld: amount_received_ld,
|
|
469
|
-
compose_from: oft_msg.compose_from.unwrap(),
|
|
470
|
-
compose_msg: oft_msg.compose_msg.unwrap(),
|
|
471
|
-
}
|
|
472
|
-
.encode(env);
|
|
473
|
-
|
|
474
|
-
let endpoint_client = MessagingComposerClient::new(env, &T::endpoint(env));
|
|
475
|
-
endpoint_client.send_compose(&env.current_contract_address(), &send_to, guid, &0, &compose_msg);
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
events::OFTReceived { guid: guid.clone(), src_eid: origin.src_eid, to: send_to, amount_received_ld }.publish(env);
|
|
479
|
-
}
|
|
@@ -3,11 +3,15 @@ use soroban_sdk::Address;
|
|
|
3
3
|
|
|
4
4
|
#[storage]
|
|
5
5
|
pub enum OFTStorage {
|
|
6
|
-
/// The
|
|
7
|
-
#[instance(
|
|
8
|
-
|
|
6
|
+
/// The difference between local and shared decimals (local_decimals - shared_decimals)
|
|
7
|
+
#[instance(u32)]
|
|
8
|
+
DecimalsDiff,
|
|
9
9
|
|
|
10
10
|
/// The address of the underlying token contract
|
|
11
11
|
#[instance(Address)]
|
|
12
12
|
Token,
|
|
13
|
+
|
|
14
|
+
/// The optional message inspector contract address
|
|
15
|
+
#[instance(Address)]
|
|
16
|
+
MsgInspector,
|
|
13
17
|
}
|
|
@@ -17,7 +17,7 @@ fn test_decimal_conversion_rate() {
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
#[test]
|
|
20
|
-
#[should_panic(expected = "Error(Contract, #
|
|
20
|
+
#[should_panic(expected = "Error(Contract, #3001)")] // InvalidLocalDecimals
|
|
21
21
|
fn test_invalid_local_decimals() {
|
|
22
22
|
let env = Env::default();
|
|
23
23
|
OFTTestSetupBuilder::new(&env).with_token_decimals(5).with_shared_decimals(6).build();
|
|
@@ -34,7 +34,7 @@ fn test_to_ld_overflow() {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
#[test]
|
|
37
|
-
#[should_panic(expected = "Error(Contract, #
|
|
37
|
+
#[should_panic(expected = "Error(Contract, #3003)")] // Overflow
|
|
38
38
|
fn test_to_sd_overflow() {
|
|
39
39
|
let env = Env::default();
|
|
40
40
|
|
|
@@ -87,3 +87,38 @@ fn test_to_sd_truncates_dust() {
|
|
|
87
87
|
// 20 LD → 2 SD (exact)
|
|
88
88
|
assert_eq!(to_sd(&env, 20, conversion_rate), 2);
|
|
89
89
|
}
|
|
90
|
+
|
|
91
|
+
// ==================== Shared Decimals Tests ====================
|
|
92
|
+
|
|
93
|
+
#[test]
|
|
94
|
+
fn test_shared_decimals_default() {
|
|
95
|
+
let env = Env::default();
|
|
96
|
+
let setup = OFTTestSetup::new(&env);
|
|
97
|
+
|
|
98
|
+
// Default setup: 7 local decimals, 6 shared decimals
|
|
99
|
+
let shared = setup.oft.shared_decimals();
|
|
100
|
+
assert_eq!(shared, setup.shared_decimals);
|
|
101
|
+
assert_eq!(shared, 6);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
#[test]
|
|
105
|
+
fn test_shared_decimals_equal_to_local() {
|
|
106
|
+
let env = Env::default();
|
|
107
|
+
// When shared_decimals == local_decimals, conversion_rate = 1
|
|
108
|
+
let setup = OFTTestSetupBuilder::new(&env).with_token_decimals(8).with_shared_decimals(8).build();
|
|
109
|
+
|
|
110
|
+
let shared = setup.oft.shared_decimals();
|
|
111
|
+
assert_eq!(shared, 8);
|
|
112
|
+
assert_eq!(setup.oft.decimal_conversion_rate(), 1);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
#[test]
|
|
116
|
+
fn test_shared_decimals_large_difference() {
|
|
117
|
+
let env = Env::default();
|
|
118
|
+
// 18 local decimals, 6 shared decimals → conversion_rate = 10^12
|
|
119
|
+
let setup = OFTTestSetupBuilder::new(&env).with_token_decimals(18).with_shared_decimals(6).build();
|
|
120
|
+
|
|
121
|
+
let shared = setup.oft.shared_decimals();
|
|
122
|
+
assert_eq!(shared, 6);
|
|
123
|
+
assert_eq!(setup.oft.decimal_conversion_rate(), 10_i128.pow(12));
|
|
124
|
+
}
|
|
@@ -9,7 +9,7 @@ use crate::{
|
|
|
9
9
|
};
|
|
10
10
|
use endpoint_v2::LayerZeroReceiverClient;
|
|
11
11
|
use soroban_sdk::{testutils::Address as _, Address, Bytes, BytesN, Env};
|
|
12
|
-
use utils::testing_utils::
|
|
12
|
+
use utils::testing_utils::assert_contains_event;
|
|
13
13
|
|
|
14
14
|
// Helper function to reduce code duplication for lz_receive tests
|
|
15
15
|
fn run_lz_receive_test(setup: &OFTTestSetup, recipient: &Address, amount_sd: u64) {
|
|
@@ -37,7 +37,7 @@ fn run_lz_receive_test(setup: &OFTTestSetup, recipient: &Address, amount_sd: u64
|
|
|
37
37
|
let conversion_rate = setup.oft.decimal_conversion_rate();
|
|
38
38
|
let expected_amount_ld = (amount_sd as i128) * conversion_rate;
|
|
39
39
|
setup.lz_receive(&executor, &origin, &guid, &message, &extra_data, 0);
|
|
40
|
-
|
|
40
|
+
assert_contains_event(
|
|
41
41
|
env,
|
|
42
42
|
&setup.oft.address,
|
|
43
43
|
OFTReceived { guid: guid.clone(), src_eid, to: recipient.clone(), amount_received_ld: expected_amount_ld },
|