@layerzerolabs/protocol-stellar-v2 0.2.8 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/.turbo/turbo-build.log +443 -302
  2. package/.turbo/turbo-lint.log +118 -96
  3. package/.turbo/turbo-test.log +853 -731
  4. package/Cargo.lock +120 -37
  5. package/Cargo.toml +8 -5
  6. package/contracts/common-macros/src/contract_impl.rs +44 -0
  7. package/contracts/common-macros/src/lib.rs +86 -40
  8. package/contracts/common-macros/src/ownable.rs +24 -32
  9. package/contracts/common-macros/src/storage.rs +95 -120
  10. package/contracts/common-macros/src/tests/contract_impl.rs +289 -0
  11. package/contracts/common-macros/src/tests/mod.rs +9 -0
  12. package/contracts/common-macros/src/tests/ownable.rs +151 -0
  13. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__contract_impl__snapshot_generated_contract_impl_code.snap +85 -0
  14. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_generated_ownable_code.snap +30 -0
  15. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_only_owner_preserves_function_signature.snap +9 -0
  16. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__storage__snapshot_generated_storage_code.snap +1072 -0
  17. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +45 -0
  18. package/contracts/common-macros/src/tests/storage.rs +485 -0
  19. package/contracts/common-macros/src/tests/test_helpers.rs +93 -0
  20. package/contracts/common-macros/src/tests/ttl_configurable.rs +34 -0
  21. package/contracts/common-macros/src/ttl_configurable.rs +31 -14
  22. package/contracts/common-macros/src/utils.rs +27 -0
  23. package/contracts/endpoint-v2/ARCHITECTURE.md +4 -4
  24. package/contracts/endpoint-v2/src/endpoint_v2.rs +18 -15
  25. package/contracts/endpoint-v2/src/interfaces/message_lib.rs +2 -3
  26. package/contracts/endpoint-v2/src/interfaces/message_lib_manager.rs +5 -3
  27. package/contracts/endpoint-v2/src/interfaces/messaging_channel.rs +2 -2
  28. package/contracts/endpoint-v2/src/interfaces/messaging_composer.rs +2 -2
  29. package/contracts/endpoint-v2/src/interfaces/send_lib.rs +4 -4
  30. package/contracts/endpoint-v2/src/lib.rs +6 -5
  31. package/contracts/endpoint-v2/src/message_lib_manager.rs +14 -6
  32. package/contracts/endpoint-v2/src/messaging_channel.rs +6 -2
  33. package/contracts/endpoint-v2/src/messaging_composer.rs +6 -2
  34. package/contracts/endpoint-v2/src/storage.rs +10 -7
  35. package/contracts/endpoint-v2/src/tests/endpoint_v2/pay_messaging_fees.rs +16 -16
  36. package/contracts/endpoint-v2/src/tests/endpoint_v2/ttl_config.rs +46 -46
  37. package/contracts/endpoint-v2/src/tests/mock.rs +2 -2
  38. package/contracts/endpoint-v2/src/util.rs +8 -2
  39. package/contracts/message-libs/block-message-lib/Cargo.toml +1 -0
  40. package/contracts/message-libs/block-message-lib/src/lib.rs +5 -5
  41. package/contracts/message-libs/message-lib-common/src/errors.rs +8 -8
  42. package/contracts/message-libs/message-lib-common/src/interfaces/dvn.rs +0 -1
  43. package/contracts/message-libs/message-lib-common/src/interfaces/mod.rs +3 -3
  44. package/contracts/message-libs/message-lib-common/src/lib.rs +0 -2
  45. package/contracts/message-libs/message-lib-common/src/packet_codec_v1.rs +4 -6
  46. package/contracts/message-libs/message-lib-common/src/tests/packet_codec_v1.rs +2 -2
  47. package/contracts/message-libs/message-lib-common/src/tests/worker_options.rs +11 -11
  48. package/contracts/message-libs/message-lib-common/src/worker_options.rs +10 -16
  49. package/contracts/message-libs/simple-message-lib/src/errors.rs +0 -4
  50. package/contracts/message-libs/simple-message-lib/src/simple_message_lib.rs +49 -34
  51. package/contracts/message-libs/simple-message-lib/src/storage.rs +3 -7
  52. package/contracts/message-libs/simple-message-lib/src/test.rs +3 -3
  53. package/contracts/message-libs/treasury/src/storage.rs +1 -2
  54. package/contracts/message-libs/treasury/src/tests/setup.rs +3 -2
  55. package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +0 -13
  56. package/contracts/message-libs/treasury/src/treasury.rs +18 -21
  57. package/contracts/message-libs/uln-302/Cargo.toml +1 -0
  58. package/contracts/message-libs/uln-302/src/interfaces/mod.rs +4 -4
  59. package/contracts/message-libs/uln-302/src/interfaces/{receive.rs → receive_uln.rs} +3 -3
  60. package/contracts/message-libs/uln-302/src/interfaces/{send.rs → send_uln.rs} +8 -80
  61. package/contracts/message-libs/uln-302/src/lib.rs +5 -4
  62. package/contracts/message-libs/uln-302/src/{receive.rs → receive_uln.rs} +20 -12
  63. package/contracts/message-libs/uln-302/src/{send.rs → send_uln.rs} +19 -13
  64. package/contracts/message-libs/uln-302/src/storage.rs +1 -2
  65. package/contracts/message-libs/uln-302/src/tests/config/uln_config.rs +3 -2
  66. package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +30 -30
  67. package/contracts/message-libs/uln-302/src/tests/setup.rs +12 -11
  68. package/contracts/message-libs/uln-302/src/tests/uln302/set_config.rs +1 -1
  69. package/contracts/message-libs/uln-302/src/{config_validation.rs → types.rs} +79 -11
  70. package/contracts/message-libs/uln-302/src/uln302.rs +15 -10
  71. package/contracts/oapp-macros/Cargo.toml +2 -8
  72. package/contracts/oapp-macros/src/lib.rs +57 -311
  73. package/contracts/oapp-macros/src/oapp_core.rs +23 -32
  74. package/contracts/oapp-macros/src/oapp_full.rs +8 -2
  75. package/contracts/oapp-macros/src/oapp_options_type3.rs +21 -36
  76. package/contracts/oapp-macros/src/oapp_receiver.rs +38 -57
  77. package/contracts/oapp-macros/src/oapp_sender.rs +12 -14
  78. package/contracts/oapp-macros/src/util.rs +14 -10
  79. package/contracts/oapps/counter/Cargo.toml +2 -1
  80. package/contracts/oapps/counter/integration_tests/utils.rs +4 -4
  81. package/contracts/oapps/counter/src/codec.rs +8 -9
  82. package/contracts/oapps/counter/src/counter.rs +156 -147
  83. package/contracts/oapps/counter/src/storage.rs +1 -2
  84. package/contracts/oapps/counter/src/tests/test_codec.rs +5 -5
  85. package/contracts/oapps/counter/src/tests/test_counter.rs +11 -13
  86. package/contracts/oapps/oapp/Cargo.toml +1 -0
  87. package/contracts/oapps/oapp/src/errors.rs +1 -1
  88. package/contracts/oapps/oapp/src/lib.rs +3 -0
  89. package/contracts/oapps/oapp/src/macro_tests/mod.rs +1 -0
  90. package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +312 -0
  91. package/contracts/oapps/oapp/src/oapp_core.rs +52 -53
  92. package/contracts/oapps/oapp/src/oapp_options_type3.rs +18 -28
  93. package/contracts/oapps/oapp/src/oapp_receiver.rs +82 -31
  94. package/contracts/oapps/oapp/src/oapp_sender.rs +55 -13
  95. package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +16 -3
  96. package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +33 -8
  97. package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +6 -9
  98. package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +28 -15
  99. package/contracts/oapps/oft/Cargo.toml +27 -0
  100. package/contracts/oapps/oft/integration-tests/mod.rs +3 -0
  101. package/contracts/oapps/oft/integration-tests/setup.rs +320 -0
  102. package/contracts/oapps/oft/integration-tests/test_with_sml.rs +155 -0
  103. package/contracts/oapps/oft/integration-tests/utils.rs +201 -0
  104. package/contracts/oapps/oft/src/codec/mod.rs +2 -0
  105. package/contracts/oapps/oft/src/codec/oft_compose_msg_codec.rs +55 -0
  106. package/contracts/oapps/oft/src/codec/oft_msg_codec.rs +62 -0
  107. package/contracts/oapps/oft/src/constants.rs +5 -0
  108. package/contracts/oapps/oft/src/errors.rs +8 -0
  109. package/contracts/oapps/oft/src/events.rs +19 -0
  110. package/contracts/oapps/oft/src/interfaces/mint_burn_token.rs +23 -0
  111. package/contracts/oapps/oft/src/interfaces/mod.rs +3 -0
  112. package/contracts/oapps/oft/src/lib.rs +22 -0
  113. package/contracts/oapps/oft/src/macro_tests/mod.rs +2 -0
  114. package/contracts/oapps/oft/src/macro_tests/test_all_default.rs +41 -0
  115. package/contracts/oapps/oft/src/macro_tests/test_override.rs +83 -0
  116. package/contracts/oapps/oft/src/oft.rs +320 -0
  117. package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +50 -0
  118. package/contracts/oapps/oft/src/oft_types/mint_burn.rs +50 -0
  119. package/contracts/oapps/oft/src/oft_types/mod.rs +10 -0
  120. package/contracts/oapps/oft/src/storage.rs +11 -0
  121. package/contracts/oapps/oft/src/tests/mod.rs +13 -0
  122. package/contracts/oapps/oft/src/tests/test_decimals.rs +89 -0
  123. package/contracts/oapps/oft/src/tests/test_lz_receive.rs +282 -0
  124. package/contracts/oapps/oft/src/tests/test_oft_compose_msg_codec.rs +68 -0
  125. package/contracts/oapps/oft/src/tests/test_oft_msg_codec.rs +136 -0
  126. package/contracts/oapps/oft/src/tests/test_oft_version.rs +13 -0
  127. package/contracts/oapps/oft/src/tests/test_quote_oft.rs +159 -0
  128. package/contracts/oapps/oft/src/tests/test_quote_send.rs +195 -0
  129. package/contracts/oapps/oft/src/tests/test_resolve_address.rs +37 -0
  130. package/contracts/oapps/oft/src/tests/test_send.rs +915 -0
  131. package/contracts/oapps/oft/src/tests/test_token.rs +47 -0
  132. package/contracts/oapps/oft/src/tests/test_utils.rs +789 -0
  133. package/contracts/oapps/oft/src/types.rs +38 -0
  134. package/contracts/oapps/oft/src/utils.rs +67 -0
  135. package/contracts/oapps/oft-mint-burn/Cargo.toml +26 -0
  136. package/contracts/oapps/oft-mint-burn/src/lib.rs +3 -0
  137. package/contracts/oapps/oft-mint-burn/src/oft.rs +28 -0
  138. package/contracts/oapps/oft-mint-burn/src/tests/mod.rs +1 -0
  139. package/contracts/utils/src/buffer_reader.rs +8 -9
  140. package/contracts/utils/src/buffer_writer.rs +11 -5
  141. package/contracts/utils/src/errors.rs +5 -5
  142. package/contracts/utils/src/ownable.rs +14 -6
  143. package/contracts/utils/src/testing_utils.rs +11 -1
  144. package/contracts/utils/src/tests/buffer_reader.rs +491 -730
  145. package/contracts/utils/src/tests/buffer_writer.rs +336 -148
  146. package/contracts/utils/src/tests/bytes_ext.rs +125 -40
  147. package/contracts/utils/src/tests/mod.rs +3 -0
  148. package/contracts/utils/src/tests/ownable.rs +379 -27
  149. package/contracts/utils/src/tests/test_helper.rs +47 -0
  150. package/contracts/utils/src/tests/testing_utils.rs +555 -0
  151. package/contracts/utils/src/tests/ttl.rs +421 -0
  152. package/contracts/utils/src/ttl.rs +29 -89
  153. package/contracts/workers/dvn/Cargo.toml +31 -0
  154. package/contracts/workers/dvn/src/auth.rs +66 -0
  155. package/contracts/workers/dvn/src/dvn.rs +143 -0
  156. package/contracts/workers/dvn/src/errors.rs +21 -0
  157. package/contracts/workers/dvn/src/events.rs +19 -0
  158. package/contracts/workers/dvn/src/interfaces/dvn.rs +12 -0
  159. package/contracts/workers/dvn/src/interfaces/mod.rs +5 -0
  160. package/contracts/workers/dvn/src/interfaces/multisig.rs +15 -0
  161. package/contracts/workers/dvn/src/lib.rs +24 -0
  162. package/contracts/workers/dvn/src/multisig.rs +127 -0
  163. package/contracts/workers/dvn/src/storage.rs +35 -0
  164. package/contracts/workers/dvn/src/tests/auth.rs +237 -0
  165. package/contracts/workers/dvn/src/tests/dvn.rs +349 -0
  166. package/contracts/workers/dvn/src/tests/key_pair.rs +66 -0
  167. package/contracts/workers/dvn/src/tests/mod.rs +5 -0
  168. package/contracts/workers/dvn/src/tests/multisig/mod.rs +3 -0
  169. package/contracts/workers/dvn/src/tests/multisig/set_signer.rs +133 -0
  170. package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +108 -0
  171. package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +109 -0
  172. package/contracts/workers/dvn/src/tests/setup.rs +109 -0
  173. package/contracts/workers/dvn/src/types.rs +26 -0
  174. package/contracts/workers/dvn-fee-lib/Cargo.toml +24 -0
  175. package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +113 -0
  176. package/contracts/workers/dvn-fee-lib/src/errors.rs +8 -0
  177. package/contracts/workers/dvn-fee-lib/src/lib.rs +17 -0
  178. package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +282 -0
  179. package/contracts/workers/dvn-fee-lib/src/tests/mod.rs +1 -0
  180. package/contracts/workers/executor/Cargo.toml +10 -7
  181. package/contracts/workers/executor/src/errors.rs +8 -0
  182. package/contracts/workers/executor/src/events.rs +4 -7
  183. package/contracts/workers/executor/src/interfaces/executor.rs +72 -22
  184. package/contracts/workers/executor/src/interfaces/mod.rs +0 -2
  185. package/contracts/workers/executor/src/lib.rs +16 -7
  186. package/contracts/workers/executor/src/lz_executor.rs +308 -0
  187. package/contracts/workers/executor/src/storage.rs +24 -16
  188. package/contracts/workers/executor-fee-lib/Cargo.toml +22 -0
  189. package/contracts/workers/executor-fee-lib/src/errors.rs +15 -0
  190. package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +215 -0
  191. package/contracts/workers/executor-fee-lib/src/executor_option.rs +203 -0
  192. package/contracts/workers/executor-fee-lib/src/lib.rs +7 -0
  193. package/contracts/workers/executor-helper/Cargo.toml +29 -0
  194. package/contracts/workers/executor-helper/src/executor_helper.rs +161 -0
  195. package/contracts/workers/executor-helper/src/lib.rs +11 -0
  196. package/contracts/workers/{worker-common → worker}/Cargo.toml +1 -4
  197. package/contracts/workers/worker/src/errors.rs +24 -0
  198. package/contracts/workers/worker/src/events.rs +62 -0
  199. package/contracts/workers/worker/src/interfaces/dvn_fee_lib.rs +75 -0
  200. package/contracts/workers/worker/src/interfaces/executor_fee_lib.rs +84 -0
  201. package/contracts/workers/{worker-common → worker}/src/interfaces/mod.rs +2 -2
  202. package/contracts/workers/worker/src/interfaces/price_feed.rs +85 -0
  203. package/contracts/workers/worker/src/lib.rs +14 -0
  204. package/contracts/workers/worker/src/storage.rs +63 -0
  205. package/contracts/workers/worker/src/worker.rs +459 -0
  206. package/package.json +3 -3
  207. package/sdk/dist/generated/bml.d.ts +88 -17
  208. package/sdk/dist/generated/bml.js +62 -16
  209. package/sdk/dist/generated/counter.d.ts +281 -102
  210. package/sdk/dist/generated/counter.js +93 -41
  211. package/sdk/dist/generated/endpoint.d.ts +128 -105
  212. package/sdk/dist/generated/endpoint.js +47 -45
  213. package/sdk/dist/generated/sml.d.ts +212 -69
  214. package/sdk/dist/generated/sml.js +103 -53
  215. package/sdk/dist/generated/uln302.d.ts +270 -173
  216. package/sdk/dist/generated/uln302.js +112 -64
  217. package/sdk/package.json +11 -11
  218. package/sdk/test/index.test.ts +147 -42
  219. package/sdk/test/suites/constants.ts +7 -3
  220. package/sdk/test/suites/deploy.ts +65 -42
  221. package/sdk/test/suites/localnet.ts +2 -2
  222. package/sdk/test/suites/scan.ts +28 -25
  223. package/sdk/test/utils.ts +199 -0
  224. package/sdk/tsconfig.json +93 -95
  225. package/tools/ts-bindings-gen/src/main.rs +2 -0
  226. package/contracts/common-macros/src/snapshots/common_macros__tests__tests__snapshot_generated_storage_code.snap +0 -310
  227. package/contracts/common-macros/src/tests.rs +0 -287
  228. package/contracts/oapp-macros/tests/test_macros.rs +0 -522
  229. package/contracts/workers/executor/src/executor.rs +0 -347
  230. package/contracts/workers/executor/src/interfaces/types.rs +0 -51
  231. package/contracts/workers/worker-common/src/constants.rs +0 -17
  232. package/contracts/workers/worker-common/src/errors.rs +0 -6
  233. package/contracts/workers/worker-common/src/events.rs +0 -34
  234. package/contracts/workers/worker-common/src/interfaces/executor_fee_lib.rs +0 -35
  235. package/contracts/workers/worker-common/src/interfaces/price_feed.rs +0 -40
  236. package/contracts/workers/worker-common/src/interfaces/worker.rs +0 -60
  237. package/contracts/workers/worker-common/src/lib.rs +0 -19
  238. package/contracts/workers/worker-common/src/storage.rs +0 -32
  239. 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,5 @@
1
+ /// Message type for simple OFT send
2
+ pub const SEND: u32 = 1;
3
+
4
+ /// Message type for OFT send with compose functionality
5
+ pub const SEND_AND_CALL: u32 = 2;
@@ -0,0 +1,8 @@
1
+ use common_macros::contract_error;
2
+
3
+ #[contract_error]
4
+ pub enum OFTError {
5
+ InvalidLocalDecimals = 2100,
6
+ Overflow,
7
+ SlippageExceeded,
8
+ }
@@ -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,3 @@
1
+ mod mint_burn_token;
2
+
3
+ pub use mint_burn_token::*;
@@ -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,2 @@
1
+ pub mod test_all_default;
2
+ pub mod test_override;
@@ -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
+ }