@layerzerolabs/protocol-stellar-v2 0.2.8 → 0.2.10
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 +443 -302
- package/.turbo/turbo-lint.log +118 -96
- package/.turbo/turbo-test.log +853 -731
- package/Cargo.lock +120 -37
- package/Cargo.toml +8 -5
- package/contracts/common-macros/src/contract_impl.rs +44 -0
- package/contracts/common-macros/src/lib.rs +86 -40
- package/contracts/common-macros/src/ownable.rs +24 -32
- package/contracts/common-macros/src/storage.rs +95 -120
- package/contracts/common-macros/src/tests/contract_impl.rs +289 -0
- package/contracts/common-macros/src/tests/mod.rs +9 -0
- package/contracts/common-macros/src/tests/ownable.rs +151 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__contract_impl__snapshot_generated_contract_impl_code.snap +85 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_generated_ownable_code.snap +30 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_only_owner_preserves_function_signature.snap +9 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__storage__snapshot_generated_storage_code.snap +1072 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +45 -0
- package/contracts/common-macros/src/tests/storage.rs +485 -0
- package/contracts/common-macros/src/tests/test_helpers.rs +93 -0
- package/contracts/common-macros/src/tests/ttl_configurable.rs +34 -0
- package/contracts/common-macros/src/ttl_configurable.rs +31 -14
- package/contracts/common-macros/src/utils.rs +27 -0
- package/contracts/endpoint-v2/ARCHITECTURE.md +4 -4
- package/contracts/endpoint-v2/src/endpoint_v2.rs +18 -15
- package/contracts/endpoint-v2/src/interfaces/message_lib.rs +2 -3
- package/contracts/endpoint-v2/src/interfaces/message_lib_manager.rs +5 -3
- package/contracts/endpoint-v2/src/interfaces/messaging_channel.rs +2 -2
- package/contracts/endpoint-v2/src/interfaces/messaging_composer.rs +2 -2
- package/contracts/endpoint-v2/src/interfaces/send_lib.rs +4 -4
- package/contracts/endpoint-v2/src/lib.rs +6 -5
- package/contracts/endpoint-v2/src/message_lib_manager.rs +14 -6
- package/contracts/endpoint-v2/src/messaging_channel.rs +6 -2
- package/contracts/endpoint-v2/src/messaging_composer.rs +6 -2
- package/contracts/endpoint-v2/src/storage.rs +10 -7
- package/contracts/endpoint-v2/src/tests/endpoint_v2/pay_messaging_fees.rs +16 -16
- package/contracts/endpoint-v2/src/tests/endpoint_v2/ttl_config.rs +46 -46
- package/contracts/endpoint-v2/src/tests/mock.rs +2 -2
- package/contracts/endpoint-v2/src/util.rs +8 -2
- package/contracts/message-libs/block-message-lib/Cargo.toml +1 -0
- package/contracts/message-libs/block-message-lib/src/lib.rs +5 -5
- package/contracts/message-libs/message-lib-common/src/errors.rs +8 -8
- package/contracts/message-libs/message-lib-common/src/interfaces/dvn.rs +0 -1
- package/contracts/message-libs/message-lib-common/src/interfaces/mod.rs +3 -3
- package/contracts/message-libs/message-lib-common/src/lib.rs +0 -2
- package/contracts/message-libs/message-lib-common/src/packet_codec_v1.rs +4 -6
- package/contracts/message-libs/message-lib-common/src/tests/packet_codec_v1.rs +2 -2
- package/contracts/message-libs/message-lib-common/src/tests/worker_options.rs +11 -11
- package/contracts/message-libs/message-lib-common/src/worker_options.rs +10 -16
- package/contracts/message-libs/simple-message-lib/src/errors.rs +0 -4
- package/contracts/message-libs/simple-message-lib/src/simple_message_lib.rs +49 -34
- package/contracts/message-libs/simple-message-lib/src/storage.rs +3 -7
- package/contracts/message-libs/simple-message-lib/src/test.rs +3 -3
- package/contracts/message-libs/treasury/src/storage.rs +1 -2
- package/contracts/message-libs/treasury/src/tests/setup.rs +3 -2
- package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +0 -13
- package/contracts/message-libs/treasury/src/treasury.rs +18 -21
- package/contracts/message-libs/uln-302/Cargo.toml +1 -0
- package/contracts/message-libs/uln-302/src/interfaces/mod.rs +4 -4
- package/contracts/message-libs/uln-302/src/interfaces/{receive.rs → receive_uln.rs} +3 -3
- package/contracts/message-libs/uln-302/src/interfaces/{send.rs → send_uln.rs} +8 -80
- package/contracts/message-libs/uln-302/src/lib.rs +5 -4
- package/contracts/message-libs/uln-302/src/{receive.rs → receive_uln.rs} +20 -12
- package/contracts/message-libs/uln-302/src/{send.rs → send_uln.rs} +19 -13
- package/contracts/message-libs/uln-302/src/storage.rs +1 -2
- package/contracts/message-libs/uln-302/src/tests/config/uln_config.rs +3 -2
- package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +30 -30
- package/contracts/message-libs/uln-302/src/tests/setup.rs +12 -11
- package/contracts/message-libs/uln-302/src/tests/uln302/set_config.rs +1 -1
- package/contracts/message-libs/uln-302/src/{config_validation.rs → types.rs} +79 -11
- package/contracts/message-libs/uln-302/src/uln302.rs +15 -10
- package/contracts/oapp-macros/Cargo.toml +2 -8
- package/contracts/oapp-macros/src/lib.rs +57 -311
- package/contracts/oapp-macros/src/oapp_core.rs +23 -32
- package/contracts/oapp-macros/src/oapp_full.rs +8 -2
- package/contracts/oapp-macros/src/oapp_options_type3.rs +21 -36
- package/contracts/oapp-macros/src/oapp_receiver.rs +38 -57
- package/contracts/oapp-macros/src/oapp_sender.rs +12 -14
- package/contracts/oapp-macros/src/util.rs +14 -10
- package/contracts/oapps/counter/Cargo.toml +2 -1
- package/contracts/oapps/counter/integration_tests/utils.rs +4 -4
- package/contracts/oapps/counter/src/codec.rs +8 -9
- package/contracts/oapps/counter/src/counter.rs +156 -147
- package/contracts/oapps/counter/src/storage.rs +1 -2
- package/contracts/oapps/counter/src/tests/test_codec.rs +5 -5
- package/contracts/oapps/counter/src/tests/test_counter.rs +11 -13
- package/contracts/oapps/oapp/Cargo.toml +1 -0
- package/contracts/oapps/oapp/src/errors.rs +1 -1
- package/contracts/oapps/oapp/src/lib.rs +3 -0
- package/contracts/oapps/oapp/src/macro_tests/mod.rs +1 -0
- package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +312 -0
- package/contracts/oapps/oapp/src/oapp_core.rs +52 -53
- package/contracts/oapps/oapp/src/oapp_options_type3.rs +18 -28
- package/contracts/oapps/oapp/src/oapp_receiver.rs +82 -31
- package/contracts/oapps/oapp/src/oapp_sender.rs +55 -13
- package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +16 -3
- package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +33 -8
- package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +6 -9
- package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +28 -15
- package/contracts/oapps/oft/Cargo.toml +27 -0
- package/contracts/oapps/oft/integration-tests/mod.rs +3 -0
- package/contracts/oapps/oft/integration-tests/setup.rs +320 -0
- package/contracts/oapps/oft/integration-tests/test_with_sml.rs +155 -0
- package/contracts/oapps/oft/integration-tests/utils.rs +201 -0
- package/contracts/oapps/oft/src/codec/mod.rs +2 -0
- package/contracts/oapps/oft/src/codec/oft_compose_msg_codec.rs +55 -0
- package/contracts/oapps/oft/src/codec/oft_msg_codec.rs +62 -0
- package/contracts/oapps/oft/src/constants.rs +5 -0
- package/contracts/oapps/oft/src/errors.rs +8 -0
- package/contracts/oapps/oft/src/events.rs +19 -0
- package/contracts/oapps/oft/src/interfaces/mint_burn_token.rs +23 -0
- package/contracts/oapps/oft/src/interfaces/mod.rs +3 -0
- package/contracts/oapps/oft/src/lib.rs +22 -0
- package/contracts/oapps/oft/src/macro_tests/mod.rs +2 -0
- package/contracts/oapps/oft/src/macro_tests/test_all_default.rs +41 -0
- package/contracts/oapps/oft/src/macro_tests/test_override.rs +83 -0
- package/contracts/oapps/oft/src/oft.rs +320 -0
- package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +50 -0
- package/contracts/oapps/oft/src/oft_types/mint_burn.rs +50 -0
- package/contracts/oapps/oft/src/oft_types/mod.rs +10 -0
- package/contracts/oapps/oft/src/storage.rs +11 -0
- package/contracts/oapps/oft/src/tests/mod.rs +13 -0
- package/contracts/oapps/oft/src/tests/test_decimals.rs +89 -0
- package/contracts/oapps/oft/src/tests/test_lz_receive.rs +282 -0
- package/contracts/oapps/oft/src/tests/test_oft_compose_msg_codec.rs +68 -0
- package/contracts/oapps/oft/src/tests/test_oft_msg_codec.rs +136 -0
- package/contracts/oapps/oft/src/tests/test_oft_version.rs +13 -0
- package/contracts/oapps/oft/src/tests/test_quote_oft.rs +159 -0
- package/contracts/oapps/oft/src/tests/test_quote_send.rs +195 -0
- package/contracts/oapps/oft/src/tests/test_resolve_address.rs +37 -0
- package/contracts/oapps/oft/src/tests/test_send.rs +915 -0
- package/contracts/oapps/oft/src/tests/test_token.rs +47 -0
- package/contracts/oapps/oft/src/tests/test_utils.rs +789 -0
- package/contracts/oapps/oft/src/types.rs +38 -0
- package/contracts/oapps/oft/src/utils.rs +67 -0
- package/contracts/oapps/oft-mint-burn/Cargo.toml +26 -0
- package/contracts/oapps/oft-mint-burn/src/lib.rs +3 -0
- package/contracts/oapps/oft-mint-burn/src/oft.rs +28 -0
- package/contracts/oapps/oft-mint-burn/src/tests/mod.rs +1 -0
- package/contracts/utils/src/buffer_reader.rs +8 -9
- package/contracts/utils/src/buffer_writer.rs +11 -5
- package/contracts/utils/src/errors.rs +5 -5
- package/contracts/utils/src/ownable.rs +14 -6
- package/contracts/utils/src/testing_utils.rs +11 -1
- package/contracts/utils/src/tests/buffer_reader.rs +491 -730
- package/contracts/utils/src/tests/buffer_writer.rs +336 -148
- package/contracts/utils/src/tests/bytes_ext.rs +125 -40
- package/contracts/utils/src/tests/mod.rs +3 -0
- package/contracts/utils/src/tests/ownable.rs +379 -27
- package/contracts/utils/src/tests/test_helper.rs +47 -0
- package/contracts/utils/src/tests/testing_utils.rs +555 -0
- package/contracts/utils/src/tests/ttl.rs +421 -0
- package/contracts/utils/src/ttl.rs +29 -89
- package/contracts/workers/dvn/Cargo.toml +31 -0
- package/contracts/workers/dvn/src/auth.rs +66 -0
- package/contracts/workers/dvn/src/dvn.rs +143 -0
- package/contracts/workers/dvn/src/errors.rs +21 -0
- package/contracts/workers/dvn/src/events.rs +19 -0
- package/contracts/workers/dvn/src/interfaces/dvn.rs +12 -0
- package/contracts/workers/dvn/src/interfaces/mod.rs +5 -0
- package/contracts/workers/dvn/src/interfaces/multisig.rs +15 -0
- package/contracts/workers/dvn/src/lib.rs +24 -0
- package/contracts/workers/dvn/src/multisig.rs +127 -0
- package/contracts/workers/dvn/src/storage.rs +35 -0
- package/contracts/workers/dvn/src/tests/auth.rs +237 -0
- package/contracts/workers/dvn/src/tests/dvn.rs +349 -0
- package/contracts/workers/dvn/src/tests/key_pair.rs +66 -0
- package/contracts/workers/dvn/src/tests/mod.rs +5 -0
- package/contracts/workers/dvn/src/tests/multisig/mod.rs +3 -0
- package/contracts/workers/dvn/src/tests/multisig/set_signer.rs +133 -0
- package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +108 -0
- package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +109 -0
- package/contracts/workers/dvn/src/tests/setup.rs +109 -0
- package/contracts/workers/dvn/src/types.rs +26 -0
- package/contracts/workers/dvn-fee-lib/Cargo.toml +24 -0
- package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +113 -0
- package/contracts/workers/dvn-fee-lib/src/errors.rs +8 -0
- package/contracts/workers/dvn-fee-lib/src/lib.rs +17 -0
- package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +282 -0
- package/contracts/workers/dvn-fee-lib/src/tests/mod.rs +1 -0
- package/contracts/workers/executor/Cargo.toml +10 -7
- package/contracts/workers/executor/src/errors.rs +8 -0
- package/contracts/workers/executor/src/events.rs +4 -7
- package/contracts/workers/executor/src/interfaces/executor.rs +72 -22
- package/contracts/workers/executor/src/interfaces/mod.rs +0 -2
- package/contracts/workers/executor/src/lib.rs +16 -7
- package/contracts/workers/executor/src/lz_executor.rs +308 -0
- package/contracts/workers/executor/src/storage.rs +24 -16
- package/contracts/workers/executor-fee-lib/Cargo.toml +22 -0
- package/contracts/workers/executor-fee-lib/src/errors.rs +15 -0
- package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +215 -0
- package/contracts/workers/executor-fee-lib/src/executor_option.rs +203 -0
- package/contracts/workers/executor-fee-lib/src/lib.rs +7 -0
- package/contracts/workers/executor-helper/Cargo.toml +29 -0
- package/contracts/workers/executor-helper/src/executor_helper.rs +161 -0
- package/contracts/workers/executor-helper/src/lib.rs +11 -0
- package/contracts/workers/{worker-common → worker}/Cargo.toml +1 -4
- package/contracts/workers/worker/src/errors.rs +24 -0
- package/contracts/workers/worker/src/events.rs +62 -0
- package/contracts/workers/worker/src/interfaces/dvn_fee_lib.rs +75 -0
- package/contracts/workers/worker/src/interfaces/executor_fee_lib.rs +84 -0
- package/contracts/workers/{worker-common → worker}/src/interfaces/mod.rs +2 -2
- package/contracts/workers/worker/src/interfaces/price_feed.rs +85 -0
- package/contracts/workers/worker/src/lib.rs +14 -0
- package/contracts/workers/worker/src/storage.rs +63 -0
- package/contracts/workers/worker/src/worker.rs +459 -0
- package/package.json +3 -3
- package/sdk/dist/generated/bml.d.ts +88 -17
- package/sdk/dist/generated/bml.js +62 -16
- package/sdk/dist/generated/counter.d.ts +281 -102
- package/sdk/dist/generated/counter.js +93 -41
- package/sdk/dist/generated/endpoint.d.ts +128 -105
- package/sdk/dist/generated/endpoint.js +47 -45
- package/sdk/dist/generated/sml.d.ts +212 -69
- package/sdk/dist/generated/sml.js +103 -53
- package/sdk/dist/generated/uln302.d.ts +270 -173
- package/sdk/dist/generated/uln302.js +112 -64
- package/sdk/package.json +11 -11
- package/sdk/test/index.test.ts +147 -42
- package/sdk/test/suites/constants.ts +7 -3
- package/sdk/test/suites/deploy.ts +65 -42
- package/sdk/test/suites/localnet.ts +2 -2
- package/sdk/test/suites/scan.ts +28 -25
- package/sdk/test/utils.ts +199 -0
- package/sdk/tsconfig.json +93 -95
- package/tools/ts-bindings-gen/src/main.rs +2 -0
- package/contracts/common-macros/src/snapshots/common_macros__tests__tests__snapshot_generated_storage_code.snap +0 -310
- package/contracts/common-macros/src/tests.rs +0 -287
- package/contracts/oapp-macros/tests/test_macros.rs +0 -522
- package/contracts/workers/executor/src/executor.rs +0 -347
- package/contracts/workers/executor/src/interfaces/types.rs +0 -51
- package/contracts/workers/worker-common/src/constants.rs +0 -17
- package/contracts/workers/worker-common/src/errors.rs +0 -6
- package/contracts/workers/worker-common/src/events.rs +0 -34
- package/contracts/workers/worker-common/src/interfaces/executor_fee_lib.rs +0 -35
- package/contracts/workers/worker-common/src/interfaces/price_feed.rs +0 -40
- package/contracts/workers/worker-common/src/interfaces/worker.rs +0 -60
- package/contracts/workers/worker-common/src/lib.rs +0 -19
- package/contracts/workers/worker-common/src/storage.rs +0 -32
- package/contracts/workers/worker-common/src/worker_common.rs +0 -166
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
use soroban_sdk::{Bytes, BytesN, Env};
|
|
2
|
+
use utils::{buffer_reader::BufferReader, buffer_writer::BufferWriter};
|
|
3
|
+
|
|
4
|
+
/// Decoded compose message containing transfer context and payload execution
|
|
5
|
+
#[derive(Clone, Debug)]
|
|
6
|
+
pub struct OFTComposeMsg {
|
|
7
|
+
/// Unique sequence number for the cross-chain message packet
|
|
8
|
+
pub nonce: u64,
|
|
9
|
+
/// Source chain endpoint ID where the transfer originated
|
|
10
|
+
pub src_eid: u32,
|
|
11
|
+
/// Amount received in local decimals
|
|
12
|
+
pub amount_ld: i128,
|
|
13
|
+
/// Address that initiated the compose call on the source chain
|
|
14
|
+
pub compose_from: BytesN<32>,
|
|
15
|
+
/// Custom payload for compose logic execution
|
|
16
|
+
pub compose_msg: Bytes,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
impl OFTComposeMsg {
|
|
20
|
+
/// Encodes the OFTComposeMsg struct into Bytes.
|
|
21
|
+
///
|
|
22
|
+
/// # Arguments
|
|
23
|
+
/// * `env` - The Soroban environment
|
|
24
|
+
///
|
|
25
|
+
/// # Returns
|
|
26
|
+
/// Encoded bytes representation of the compose message
|
|
27
|
+
pub fn encode(&self, env: &Env) -> Bytes {
|
|
28
|
+
let mut writer = BufferWriter::new(env);
|
|
29
|
+
writer
|
|
30
|
+
.write_u64(self.nonce)
|
|
31
|
+
.write_u32(self.src_eid)
|
|
32
|
+
.write_i128(self.amount_ld)
|
|
33
|
+
.write_bytes_n(&self.compose_from)
|
|
34
|
+
.write_bytes(&self.compose_msg);
|
|
35
|
+
writer.to_bytes()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// Decodes Bytes into an OFTComposeMsg struct.
|
|
39
|
+
///
|
|
40
|
+
/// # Arguments
|
|
41
|
+
/// * `bytes` - The encoded bytes to decode
|
|
42
|
+
///
|
|
43
|
+
/// # Returns
|
|
44
|
+
/// Decoded OFTComposeMsg struct
|
|
45
|
+
pub fn decode(bytes: &Bytes) -> Self {
|
|
46
|
+
let mut reader = BufferReader::new(bytes);
|
|
47
|
+
let nonce = reader.read_u64();
|
|
48
|
+
let src_eid = reader.read_u32();
|
|
49
|
+
let amount_ld = reader.read_i128();
|
|
50
|
+
let compose_from = reader.read_bytes_n::<32>();
|
|
51
|
+
let compose_msg = reader.read_bytes_until_end();
|
|
52
|
+
|
|
53
|
+
OFTComposeMsg { nonce, src_eid, amount_ld, compose_from, compose_msg }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
use soroban_sdk::{Bytes, BytesN, Env};
|
|
2
|
+
use utils::{buffer_reader::BufferReader, buffer_writer::BufferWriter};
|
|
3
|
+
|
|
4
|
+
/// Decoded OFT message containing transfer details and optional compose data
|
|
5
|
+
#[derive(Clone, Debug)]
|
|
6
|
+
pub struct OFTMessage {
|
|
7
|
+
/// Recipient address on the destination chain
|
|
8
|
+
pub send_to: BytesN<32>,
|
|
9
|
+
/// Amount to transfer in shared decimals (normalized cross-chain format)
|
|
10
|
+
pub amount_sd: u64,
|
|
11
|
+
/// Address that initiated the compose call (optional)
|
|
12
|
+
pub compose_from: Option<BytesN<32>>,
|
|
13
|
+
/// Compose message payload for additional logic (optional)
|
|
14
|
+
pub compose_msg: Option<Bytes>,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
impl OFTMessage {
|
|
18
|
+
/// Returns true if this message includes compose functionality
|
|
19
|
+
pub fn is_composed(&self) -> bool {
|
|
20
|
+
self.compose_from.is_some() && self.compose_msg.as_ref().is_some_and(|msg| !msg.is_empty())
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/// Encodes the OFTMessage struct into Bytes.
|
|
24
|
+
///
|
|
25
|
+
/// # Returns
|
|
26
|
+
/// A tuple containing:
|
|
27
|
+
/// - Encoded bytes representation of the message
|
|
28
|
+
/// - Boolean indicating if compose functionality is included
|
|
29
|
+
pub fn encode(&self, env: &Env) -> (Bytes, bool) {
|
|
30
|
+
let has_compose = self.is_composed();
|
|
31
|
+
|
|
32
|
+
let mut writer = BufferWriter::new(env);
|
|
33
|
+
writer.write_bytes_n(&self.send_to).write_u64(self.amount_sd);
|
|
34
|
+
if has_compose {
|
|
35
|
+
// compose_from should already be set when compose is enabled
|
|
36
|
+
writer.write_bytes_n(self.compose_from.as_ref().unwrap()).write_bytes(self.compose_msg.as_ref().unwrap());
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
(writer.to_bytes(), has_compose)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/// Decodes Bytes into an OFTMessage struct.
|
|
43
|
+
///
|
|
44
|
+
/// # Arguments
|
|
45
|
+
/// * `message` - The encoded bytes to decode
|
|
46
|
+
///
|
|
47
|
+
/// # Returns
|
|
48
|
+
/// Decoded OFTMessage struct
|
|
49
|
+
pub fn decode(message: &Bytes) -> Self {
|
|
50
|
+
let mut reader = BufferReader::new(message);
|
|
51
|
+
let send_to = reader.read_bytes_n::<32>();
|
|
52
|
+
let amount_sd = reader.read_u64();
|
|
53
|
+
|
|
54
|
+
if reader.remaining_len() > 0 {
|
|
55
|
+
let compose_from = reader.read_bytes_n::<32>();
|
|
56
|
+
let compose_msg = reader.read_bytes_until_end();
|
|
57
|
+
OFTMessage { send_to, amount_sd, compose_from: Some(compose_from), compose_msg: Some(compose_msg) }
|
|
58
|
+
} else {
|
|
59
|
+
OFTMessage { send_to, amount_sd, compose_from: None, compose_msg: None }
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
use common_macros::event;
|
|
2
|
+
use soroban_sdk::{Address, BytesN};
|
|
3
|
+
|
|
4
|
+
#[event]
|
|
5
|
+
pub struct OFTSent {
|
|
6
|
+
pub guid: BytesN<32>,
|
|
7
|
+
pub dst_eid: u32,
|
|
8
|
+
pub from: Address,
|
|
9
|
+
pub amount_sent_ld: i128,
|
|
10
|
+
pub amount_received_ld: i128,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
#[event]
|
|
14
|
+
pub struct OFTReceived {
|
|
15
|
+
pub guid: BytesN<32>,
|
|
16
|
+
pub src_eid: u32,
|
|
17
|
+
pub to: Address,
|
|
18
|
+
pub amount_received_ld: i128,
|
|
19
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
use soroban_sdk::{contractclient, Address, Env};
|
|
2
|
+
|
|
3
|
+
/// Contract interface for mint and burn token operations.
|
|
4
|
+
///
|
|
5
|
+
/// This interface abstracts the token mint/burn functionality, allowing different
|
|
6
|
+
/// token implementations (e.g., StellarAssetContract, custom tokens) to be used
|
|
7
|
+
/// with the MintBurn OFT.
|
|
8
|
+
#[contractclient(name = "MintBurnTokenClient")]
|
|
9
|
+
pub trait MintBurnToken {
|
|
10
|
+
/// Mints tokens to the specified address.
|
|
11
|
+
///
|
|
12
|
+
/// # Parameters
|
|
13
|
+
/// * `to` - The address to mint tokens to
|
|
14
|
+
/// * `amount` - The amount of tokens to mint (must be non-negative)
|
|
15
|
+
fn mint(env: Env, to: Address, amount: i128);
|
|
16
|
+
|
|
17
|
+
/// Burns tokens from the specified address.
|
|
18
|
+
///
|
|
19
|
+
/// # Parameters
|
|
20
|
+
/// * `from` - The address to burn tokens from
|
|
21
|
+
/// * `amount` - The amount of tokens to burn (must be non-negative)
|
|
22
|
+
fn burn(env: Env, from: Address, amount: i128);
|
|
23
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#![no_std]
|
|
2
|
+
|
|
3
|
+
pub mod codec;
|
|
4
|
+
pub mod constants;
|
|
5
|
+
pub mod errors;
|
|
6
|
+
pub mod events;
|
|
7
|
+
pub mod interfaces;
|
|
8
|
+
pub mod oft;
|
|
9
|
+
pub mod oft_types;
|
|
10
|
+
pub mod storage;
|
|
11
|
+
pub mod types;
|
|
12
|
+
pub mod utils;
|
|
13
|
+
|
|
14
|
+
#[cfg(test)]
|
|
15
|
+
#[path = "../integration-tests/mod.rs"]
|
|
16
|
+
pub mod integration_tests;
|
|
17
|
+
|
|
18
|
+
#[cfg(test)]
|
|
19
|
+
pub mod macro_tests;
|
|
20
|
+
|
|
21
|
+
#[cfg(test)]
|
|
22
|
+
pub mod tests;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//! Test OFT with default `__lz_receive` pattern.
|
|
2
|
+
//!
|
|
3
|
+
//! This demonstrates the simplest OFT usage where:
|
|
4
|
+
//! - `#[oapp]` provides OApp functionality (including OAppOptionsType3)
|
|
5
|
+
//! - User implements `OFTInner` trait for internal methods (`__debit`, `__credit`)
|
|
6
|
+
//! - User implements `OFT` trait (with default implementations)
|
|
7
|
+
//! - Default `__lz_receive` is provided by `OFTInner` trait
|
|
8
|
+
|
|
9
|
+
extern crate self as oft;
|
|
10
|
+
|
|
11
|
+
use oft::oft::{OFTInner, OFT};
|
|
12
|
+
use oft::types::OFTReceipt;
|
|
13
|
+
use soroban_sdk::{contractimpl, Address};
|
|
14
|
+
|
|
15
|
+
#[oapp_macros::oapp]
|
|
16
|
+
pub struct TestOFT;
|
|
17
|
+
|
|
18
|
+
#[contractimpl(contracttrait)]
|
|
19
|
+
impl OFT for TestOFT {}
|
|
20
|
+
|
|
21
|
+
// Internal methods - NOT exposed as contract endpoints
|
|
22
|
+
impl OFTInner for TestOFT {
|
|
23
|
+
fn __debit(
|
|
24
|
+
_env: &soroban_sdk::Env,
|
|
25
|
+
_sender: &Address,
|
|
26
|
+
amount_ld: i128,
|
|
27
|
+
_min_amount_ld: i128,
|
|
28
|
+
_dst_eid: u32,
|
|
29
|
+
) -> OFTReceipt {
|
|
30
|
+
OFTReceipt { amount_sent_ld: amount_ld, amount_received_ld: amount_ld }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
fn __credit(_env: &soroban_sdk::Env, _to: &Address, amount_ld: i128, _src_eid: u32) -> i128 {
|
|
34
|
+
amount_ld
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
#[test]
|
|
39
|
+
fn test_all_default() {
|
|
40
|
+
assert!(true);
|
|
41
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
//! Test OFT with manual OApp implementations.
|
|
2
|
+
//!
|
|
3
|
+
//! This demonstrates overriding OApp traits while using the OFT pattern.
|
|
4
|
+
|
|
5
|
+
extern crate self as oft;
|
|
6
|
+
|
|
7
|
+
use endpoint_v2::{EndpointV2, Origin};
|
|
8
|
+
use oapp::{
|
|
9
|
+
oapp_core::{oapp_initialize, OAppCore},
|
|
10
|
+
oapp_options_type3::{EnforcedOptionParam, OAppOptionsType3},
|
|
11
|
+
oapp_receiver::OAppReceiver,
|
|
12
|
+
};
|
|
13
|
+
use common_macros::contract_impl;
|
|
14
|
+
use oapp_macros::oapp_manual_impl;
|
|
15
|
+
use oft::oft::{OFTInner, OFT};
|
|
16
|
+
use oft::types::OFTReceipt;
|
|
17
|
+
use soroban_sdk::{contractimpl, testutils::Address as _, Address, Bytes, BytesN, Env, Vec};
|
|
18
|
+
|
|
19
|
+
#[oapp_macros::oapp]
|
|
20
|
+
#[oapp_manual_impl(core, options_type3, receiver)]
|
|
21
|
+
pub struct TestOFT;
|
|
22
|
+
|
|
23
|
+
#[contract_impl]
|
|
24
|
+
impl TestOFT {
|
|
25
|
+
pub fn __constructor(env: &Env, owner: &Address, endpoint: &Address, delegate: &Option<Address>) {
|
|
26
|
+
oapp_initialize::<Self>(env, owner, endpoint, delegate);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Implement OAppReceiver trait with custom behavior
|
|
31
|
+
#[contractimpl(contracttrait)]
|
|
32
|
+
impl OAppReceiver for TestOFT {
|
|
33
|
+
fn lz_receive(
|
|
34
|
+
env: &Env,
|
|
35
|
+
executor: &Address,
|
|
36
|
+
origin: &Origin,
|
|
37
|
+
guid: &BytesN<32>,
|
|
38
|
+
message: &Bytes,
|
|
39
|
+
extra_data: &Bytes,
|
|
40
|
+
value: i128,
|
|
41
|
+
) {
|
|
42
|
+
oapp::oapp_receiver::verify_and_clear_payload::<Self>(env, executor, origin, guid, message, value);
|
|
43
|
+
Self::__lz_receive(env, executor, origin, guid, message, extra_data, value);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Implement OFTInner trait - NOT exposed as contract endpoints
|
|
48
|
+
impl OFTInner for TestOFT {
|
|
49
|
+
fn __debit(_env: &Env, _sender: &Address, amount_ld: i128, _min_amount_ld: i128, _dst_eid: u32) -> OFTReceipt {
|
|
50
|
+
OFTReceipt { amount_sent_ld: amount_ld, amount_received_ld: amount_ld }
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
fn __credit(_env: &Env, _to: &Address, amount_ld: i128, _src_eid: u32) -> i128 {
|
|
54
|
+
amount_ld
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
#[contractimpl(contracttrait)]
|
|
59
|
+
impl OAppCore for TestOFT {
|
|
60
|
+
fn oapp_version(_env: &Env) -> (u64, u64) {
|
|
61
|
+
(100, 1)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
#[contractimpl(contracttrait)]
|
|
66
|
+
impl OAppOptionsType3 for TestOFT {}
|
|
67
|
+
|
|
68
|
+
#[contractimpl(contracttrait)]
|
|
69
|
+
impl OFT for TestOFT {}
|
|
70
|
+
|
|
71
|
+
#[test]
|
|
72
|
+
fn test_macro_compiles() {
|
|
73
|
+
let env = Env::default();
|
|
74
|
+
let owner = Address::generate(&env);
|
|
75
|
+
let endpoint = env.register(EndpointV2, (&owner,));
|
|
76
|
+
let delegate: Option<Address> = None;
|
|
77
|
+
let oft = env.register(TestOFT, (&owner, &endpoint, &delegate));
|
|
78
|
+
|
|
79
|
+
let oft_client = TestOFTClient::new(&env, &oft);
|
|
80
|
+
let (major, minor) = oft_client.oapp_version();
|
|
81
|
+
assert_eq!(major, 100);
|
|
82
|
+
assert_eq!(minor, 1);
|
|
83
|
+
}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
//! OFT traits - the main interface for OFT contracts.
|
|
2
|
+
//!
|
|
3
|
+
//! This module provides two traits:
|
|
4
|
+
//! - `OFTInner`: Internal methods NOT exposed as contract endpoints (`__debit`, `__credit`, etc.)
|
|
5
|
+
//! - `OFT`: Public methods exposed as contract endpoints (using `#[contracttrait]`)
|
|
6
|
+
//!
|
|
7
|
+
//! ## Usage
|
|
8
|
+
//!
|
|
9
|
+
//! ```ignore
|
|
10
|
+
//! use oapp_macros::{oapp, oapp_options_type3};
|
|
11
|
+
//! use oft::oft::{oft_initialize, OFTInner, OFT};
|
|
12
|
+
//!
|
|
13
|
+
//! #[oapp]
|
|
14
|
+
//! pub struct MyOFT;
|
|
15
|
+
//!
|
|
16
|
+
//! #[contractimpl]
|
|
17
|
+
//! impl MyOFT {
|
|
18
|
+
//! pub fn __constructor(env: &Env, token: &Address, owner: &Address, endpoint: &Address, delegate: &Option<Address>) {
|
|
19
|
+
//! oft_initialize::<Self>(env, owner, token, endpoint, delegate)
|
|
20
|
+
//! }
|
|
21
|
+
//! }
|
|
22
|
+
//!
|
|
23
|
+
//! // Public methods - exposed as contract endpoints
|
|
24
|
+
//! #[contractimpl(contracttrait)]
|
|
25
|
+
//! impl OFT for MyOFT {}
|
|
26
|
+
//!
|
|
27
|
+
//! // Internal methods - NOT exposed as contract endpoints
|
|
28
|
+
//! // IMPORTANT: Do NOT use #[contractimpl] here to keep methods internal
|
|
29
|
+
//! impl OFTInner for MyOFT {
|
|
30
|
+
//! fn __debit(env: &Env, sender: &Address, amount_ld: i128, min_amount_ld: i128, dst_eid: u32) -> OFTReceipt {
|
|
31
|
+
//! // Your debit logic (e.g., burn or lock tokens)
|
|
32
|
+
//! oft::oft_types::mint_burn::debit::<Self>(env, sender, amount_ld, min_amount_ld, dst_eid)
|
|
33
|
+
//! }
|
|
34
|
+
//!
|
|
35
|
+
//! fn __credit(env: &Env, to: &Address, amount_ld: i128, src_eid: u32) -> i128 {
|
|
36
|
+
//! // Your credit logic (e.g., mint or unlock tokens)
|
|
37
|
+
//! oft::oft_types::mint_burn::credit::<Self>(env, to, amount_ld, src_eid)
|
|
38
|
+
//! }
|
|
39
|
+
//! }
|
|
40
|
+
//! ```
|
|
41
|
+
|
|
42
|
+
// Alias for the current crate, allowing `oft::types::SendParam` paths to work both
|
|
43
|
+
// inside this crate and in external crates implementing the OFT trait.
|
|
44
|
+
extern crate self as oft;
|
|
45
|
+
|
|
46
|
+
use crate::{
|
|
47
|
+
codec::{oft_compose_msg_codec::OFTComposeMsg, oft_msg_codec::OFTMessage},
|
|
48
|
+
constants,
|
|
49
|
+
errors::OFTError,
|
|
50
|
+
events::{self, OFTSent},
|
|
51
|
+
storage::OFTStorage,
|
|
52
|
+
types::OFTReceipt,
|
|
53
|
+
utils::{address_to_bytes32, remove_dust, resolve_address, to_ld, to_sd},
|
|
54
|
+
};
|
|
55
|
+
use endpoint_v2::{MessagingComposerClient, Origin};
|
|
56
|
+
use oapp::{
|
|
57
|
+
oapp_core::{oapp_initialize, OAppCore},
|
|
58
|
+
oapp_options_type3::OAppOptionsType3,
|
|
59
|
+
oapp_receiver::OAppReceiver,
|
|
60
|
+
oapp_sender::OAppSender,
|
|
61
|
+
};
|
|
62
|
+
use soroban_sdk::{assert_with_error, contracttrait, token::TokenClient, vec, Address, Bytes, BytesN, Env};
|
|
63
|
+
use utils::ownable::OwnableInitializer;
|
|
64
|
+
|
|
65
|
+
// =====================================================
|
|
66
|
+
// OFT Initialization
|
|
67
|
+
// =====================================================
|
|
68
|
+
|
|
69
|
+
/// Initializes the OFT contract with token, endpoint, and decimal configuration.
|
|
70
|
+
/// The `shared_decimals` must be <= token's local decimals.
|
|
71
|
+
pub fn oft_initialize<T: OFT + OwnableInitializer>(
|
|
72
|
+
env: &Env,
|
|
73
|
+
owner: &Address,
|
|
74
|
+
token: &Address,
|
|
75
|
+
endpoint: &Address,
|
|
76
|
+
delegate: &Option<Address>,
|
|
77
|
+
) {
|
|
78
|
+
// Initialize OApp (includes owner initialization)
|
|
79
|
+
oapp_initialize::<T>(env, owner, endpoint, delegate);
|
|
80
|
+
|
|
81
|
+
let local_decimals = TokenClient::new(env, token).decimals();
|
|
82
|
+
let shared_decimals = T::shared_decimals(env);
|
|
83
|
+
assert_with_error!(env, local_decimals >= shared_decimals, OFTError::InvalidLocalDecimals);
|
|
84
|
+
|
|
85
|
+
// Initialize OFT storage
|
|
86
|
+
OFTStorage::set_token(env, token);
|
|
87
|
+
OFTStorage::set_decimal_conversion_rate(env, &10_i128.pow(local_decimals - shared_decimals));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// =====================================================
|
|
91
|
+
// OFTInner Trait (NOT exposed as contract endpoints)
|
|
92
|
+
// =====================================================
|
|
93
|
+
|
|
94
|
+
/// Internal OFT trait containing methods that should NOT be exposed as contract endpoints.
|
|
95
|
+
///
|
|
96
|
+
/// **IMPORTANT**: Implement this trait WITHOUT the `#[contractimpl]` macro to keep
|
|
97
|
+
/// `__debit`, `__credit`, and other internal methods private to the contract.
|
|
98
|
+
///
|
|
99
|
+
/// ```ignore
|
|
100
|
+
/// // Correct - methods stay internal
|
|
101
|
+
/// impl OFTInner for MyOFT { ... }
|
|
102
|
+
///
|
|
103
|
+
/// // WRONG - would expose methods as endpoints
|
|
104
|
+
/// #[contractimpl]
|
|
105
|
+
/// impl OFTInner for MyOFT { ... }
|
|
106
|
+
/// ```
|
|
107
|
+
///
|
|
108
|
+
/// Internal OFT trait for token debit/credit operations.
|
|
109
|
+
///
|
|
110
|
+
/// This trait contains only the internal token operations. The OApp supertraits
|
|
111
|
+
/// are on `OFT` instead, keeping this trait focused on token logic.
|
|
112
|
+
pub trait OFTInner: OAppCore {
|
|
113
|
+
// =========================================================================
|
|
114
|
+
// Required Methods (no defaults - user MUST implement)
|
|
115
|
+
// =========================================================================
|
|
116
|
+
|
|
117
|
+
/// Debits tokens from sender for cross-chain transfer.
|
|
118
|
+
///
|
|
119
|
+
/// # Arguments
|
|
120
|
+
/// * `sender` - The address sending tokens
|
|
121
|
+
/// * `amount_ld` - Amount in local decimals to debit
|
|
122
|
+
/// * `min_amount_ld` - Minimum amount acceptable (slippage protection)
|
|
123
|
+
/// * `dst_eid` - Destination endpoint ID
|
|
124
|
+
///
|
|
125
|
+
/// # Returns
|
|
126
|
+
/// Receipt with amounts sent and received (after fees/dust removal)
|
|
127
|
+
fn __debit(env: &Env, sender: &Address, amount_ld: i128, min_amount_ld: i128, dst_eid: u32) -> OFTReceipt;
|
|
128
|
+
|
|
129
|
+
/// Credits tokens to recipient after receiving cross-chain transfer.
|
|
130
|
+
///
|
|
131
|
+
/// # Arguments
|
|
132
|
+
/// * `to` - The address to credit tokens to
|
|
133
|
+
/// * `amount_ld` - Amount in local decimals to credit
|
|
134
|
+
/// * `src_eid` - Source endpoint ID
|
|
135
|
+
///
|
|
136
|
+
/// # Returns
|
|
137
|
+
/// The amount actually credited
|
|
138
|
+
fn __credit(env: &Env, to: &Address, amount_ld: i128, src_eid: u32) -> i128;
|
|
139
|
+
|
|
140
|
+
// =========================================================================
|
|
141
|
+
// Optional Methods (have defaults - override as needed)
|
|
142
|
+
// =========================================================================
|
|
143
|
+
|
|
144
|
+
/// Calculates debit amounts without executing (view function).
|
|
145
|
+
fn __debit_view(env: &Env, amount_ld: i128, min_amount_ld: i128, _dst_eid: u32) -> OFTReceipt {
|
|
146
|
+
let conversion_rate = OFTStorage::decimal_conversion_rate(env).unwrap();
|
|
147
|
+
let amount_sent_ld = remove_dust(amount_ld, conversion_rate);
|
|
148
|
+
let amount_received_ld = amount_sent_ld;
|
|
149
|
+
|
|
150
|
+
assert_with_error!(env, amount_received_ld >= min_amount_ld, OFTError::SlippageExceeded);
|
|
151
|
+
|
|
152
|
+
OFTReceipt { amount_sent_ld, amount_received_ld }
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/// Builds OFT message and combines options for cross-chain transfer.
|
|
156
|
+
fn __build_msg_and_options(
|
|
157
|
+
env: &Env,
|
|
158
|
+
sender: &Address,
|
|
159
|
+
send_param: &oft::types::SendParam,
|
|
160
|
+
amount_ld: i128,
|
|
161
|
+
) -> (Bytes, Bytes)
|
|
162
|
+
where
|
|
163
|
+
Self: OAppOptionsType3,
|
|
164
|
+
{
|
|
165
|
+
let has_compose = !send_param.compose_msg.is_empty();
|
|
166
|
+
let conversion_rate = OFTStorage::decimal_conversion_rate(env).unwrap();
|
|
167
|
+
let msg = OFTMessage {
|
|
168
|
+
send_to: send_param.to.clone(),
|
|
169
|
+
amount_sd: to_sd(env, amount_ld, conversion_rate),
|
|
170
|
+
compose_from: if has_compose { Some(address_to_bytes32(sender)) } else { None },
|
|
171
|
+
compose_msg: if has_compose { Some(send_param.compose_msg.clone()) } else { None },
|
|
172
|
+
};
|
|
173
|
+
let (msg, _) = msg.encode(env);
|
|
174
|
+
let msg_type = if has_compose { constants::SEND_AND_CALL } else { constants::SEND };
|
|
175
|
+
|
|
176
|
+
(msg, Self::combine_options(env, send_param.dst_eid, msg_type, &send_param.extra_options))
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/// Handles OFT receive logic.
|
|
180
|
+
fn __lz_receive(
|
|
181
|
+
env: &Env,
|
|
182
|
+
_executor: &Address,
|
|
183
|
+
origin: &Origin,
|
|
184
|
+
guid: &BytesN<32>,
|
|
185
|
+
message: &Bytes,
|
|
186
|
+
_extra_data: &Bytes,
|
|
187
|
+
_value: i128,
|
|
188
|
+
) {
|
|
189
|
+
let oft_msg = OFTMessage::decode(message);
|
|
190
|
+
let send_to = resolve_address(env, &oft_msg.send_to);
|
|
191
|
+
|
|
192
|
+
let conversion_rate = OFTStorage::decimal_conversion_rate(env).unwrap();
|
|
193
|
+
let amount_received_ld =
|
|
194
|
+
Self::__credit(env, &send_to, to_ld(oft_msg.amount_sd, conversion_rate), origin.src_eid);
|
|
195
|
+
|
|
196
|
+
if oft_msg.is_composed() {
|
|
197
|
+
let compose_msg = OFTComposeMsg {
|
|
198
|
+
nonce: origin.nonce,
|
|
199
|
+
src_eid: origin.src_eid,
|
|
200
|
+
amount_ld: amount_received_ld,
|
|
201
|
+
compose_from: oft_msg.compose_from.unwrap(),
|
|
202
|
+
compose_msg: oft_msg.compose_msg.unwrap(),
|
|
203
|
+
}
|
|
204
|
+
.encode(env);
|
|
205
|
+
|
|
206
|
+
let endpoint = MessagingComposerClient::new(env, &Self::endpoint(env));
|
|
207
|
+
endpoint.send_compose(&env.current_contract_address(), &send_to, guid, &0, &compose_msg);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
events::OFTReceived { guid: guid.clone(), src_eid: origin.src_eid, to: send_to, amount_received_ld }
|
|
211
|
+
.publish(env);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// =====================================================
|
|
216
|
+
// OFT Trait (exposed as contract endpoints)
|
|
217
|
+
// =====================================================
|
|
218
|
+
|
|
219
|
+
/// The public OFT trait defining the cross-chain token transfer interface.
|
|
220
|
+
///
|
|
221
|
+
/// This trait is marked with `#[contracttrait]` so all its methods are exposed as
|
|
222
|
+
/// contract endpoints. Users implement this with `#[contractimpl(contracttrait)]`.
|
|
223
|
+
///
|
|
224
|
+
/// Internal methods like `__debit`, `__credit`, `__debit_view`, and `__build_msg_and_options`
|
|
225
|
+
/// are in the `OFTInner` trait and are NOT exposed as contract endpoints.
|
|
226
|
+
#[contracttrait(client_name = "OFTClient")]
|
|
227
|
+
pub trait OFT: OFTInner + OAppReceiver + OAppSender + OAppOptionsType3 {
|
|
228
|
+
/// Retrieves the token address associated with this OFT.
|
|
229
|
+
fn token(env: &Env) -> Address {
|
|
230
|
+
OFTStorage::token(env).unwrap()
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/// Returns OFT version as (major, minor).
|
|
234
|
+
fn oft_version(_env: &Env) -> (u64, u64) {
|
|
235
|
+
(1, 1)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/// Retrieves the shared decimals used for cross-chain normalization.
|
|
239
|
+
fn shared_decimals(_env: &Env) -> u32 {
|
|
240
|
+
6
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/// Retrieves the decimal conversion rate used for cross-chain normalization.
|
|
244
|
+
fn decimal_conversion_rate(env: &Env) -> i128 {
|
|
245
|
+
OFTStorage::decimal_conversion_rate(env).unwrap()
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/// Whether a separate token approval is required before sending.
|
|
249
|
+
///
|
|
250
|
+
/// Helps wallet implementers determine integration requirements.
|
|
251
|
+
///
|
|
252
|
+
/// # Returns
|
|
253
|
+
/// - `true` if a separate token approval step is required
|
|
254
|
+
/// - `false` if no separate approval is needed
|
|
255
|
+
fn approval_required(_env: &Env) -> bool {
|
|
256
|
+
false
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/// Quotes an OFT transfer without executing.
|
|
260
|
+
///
|
|
261
|
+
/// # Returns
|
|
262
|
+
/// (OFTLimit, fee details, receipt with estimated amounts)
|
|
263
|
+
fn quote_oft(
|
|
264
|
+
env: &Env,
|
|
265
|
+
send_param: &oft::types::SendParam,
|
|
266
|
+
) -> (oft::types::OFTLimit, soroban_sdk::Vec<oft::types::OFTFeeDetail>, oft::types::OFTReceipt) {
|
|
267
|
+
let oft_receipt = Self::__debit_view(env, send_param.amount_ld, send_param.min_amount_ld, send_param.dst_eid);
|
|
268
|
+
(oft::types::OFTLimit { min_amount_ld: 0, max_amount_ld: i128::MAX }, vec![env], oft_receipt)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/// Quotes a send operation including LayerZero messaging fees.
|
|
272
|
+
fn quote_send(
|
|
273
|
+
env: &Env,
|
|
274
|
+
sender: &Address,
|
|
275
|
+
send_param: &oft::types::SendParam,
|
|
276
|
+
pay_in_zro: bool,
|
|
277
|
+
) -> endpoint_v2::MessagingFee {
|
|
278
|
+
let oft::types::OFTReceipt { amount_received_ld, .. } =
|
|
279
|
+
Self::__debit_view(env, send_param.amount_ld, send_param.min_amount_ld, send_param.dst_eid);
|
|
280
|
+
|
|
281
|
+
let (msg, options) = Self::__build_msg_and_options(env, sender, send_param, amount_received_ld);
|
|
282
|
+
Self::lz_quote(env, send_param.dst_eid, &msg, &options, pay_in_zro)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/// Sends tokens cross-chain to another endpoint.
|
|
286
|
+
///
|
|
287
|
+
/// Sender must be authenticated.
|
|
288
|
+
///
|
|
289
|
+
/// # Returns
|
|
290
|
+
/// (MessagingReceipt, OFTReceipt)
|
|
291
|
+
fn send(
|
|
292
|
+
env: &Env,
|
|
293
|
+
sender: &Address,
|
|
294
|
+
send_param: &oft::types::SendParam,
|
|
295
|
+
fee: &endpoint_v2::MessagingFee,
|
|
296
|
+
refund_address: &Address,
|
|
297
|
+
) -> (endpoint_v2::MessagingReceipt, oft::types::OFTReceipt) {
|
|
298
|
+
sender.require_auth();
|
|
299
|
+
|
|
300
|
+
let oft_receipt =
|
|
301
|
+
Self::__debit(env, sender, send_param.amount_ld, send_param.min_amount_ld, send_param.dst_eid);
|
|
302
|
+
|
|
303
|
+
let (msg, options) = Self::__build_msg_and_options(env, sender, send_param, oft_receipt.amount_received_ld);
|
|
304
|
+
let msg_receipt = Self::lz_send(env, sender, send_param.dst_eid, &msg, &options, fee, refund_address);
|
|
305
|
+
|
|
306
|
+
OFTSent {
|
|
307
|
+
guid: msg_receipt.guid.clone(),
|
|
308
|
+
dst_eid: send_param.dst_eid,
|
|
309
|
+
from: sender.clone(),
|
|
310
|
+
amount_sent_ld: oft_receipt.amount_sent_ld,
|
|
311
|
+
amount_received_ld: oft_receipt.amount_received_ld,
|
|
312
|
+
}
|
|
313
|
+
.publish(env);
|
|
314
|
+
|
|
315
|
+
(msg_receipt, oft_receipt)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// NOTE: `next_nonce`, `lz_receive`, etc. are inherited from OAppReceiver supertrait.
|
|
319
|
+
// Do NOT redefine them here to avoid method conflicts.
|
|
320
|
+
}
|