@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.
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
@@ -6,21 +6,24 @@ license.workspace = true
6
6
  publish = false
7
7
 
8
8
  [lib]
9
- crate-type = ["cdylib"]
9
+ crate-type = ["cdylib", "rlib"]
10
10
  doctest = false
11
11
 
12
+ [features]
13
+ library = []
14
+ testutils = []
15
+
12
16
  [dependencies]
17
+ cfg-if = { workspace = true }
13
18
  soroban-sdk = { workspace = true }
14
- endpoint-v2 = { workspace = true, features = ["library"] }
19
+ # workspace dependencies
15
20
  utils = { workspace = true }
16
- worker-common = { workspace = true }
17
- stellar-access = { workspace = true }
18
- stellar-macros = { workspace = true }
19
- stellar-contract-utils = { workspace = true }
21
+ worker = { workspace = true }
20
22
  common-macros = { workspace = true }
21
23
  message-lib-common = { workspace = true }
24
+ endpoint-v2 = { workspace = true, features = ["library"] }
22
25
 
23
26
  [dev-dependencies]
24
27
  soroban-sdk = { workspace = true, features = ["testutils"] }
25
- message-lib-common = { workspace = true, features = ["testutils"] }
28
+
26
29
 
@@ -0,0 +1,8 @@
1
+ use common_macros::contract_error;
2
+
3
+ #[contract_error]
4
+ pub enum ExecutorError {
5
+ EidNotSupported,
6
+ Unauthorized,
7
+ UnauthorizedContext,
8
+ }
@@ -1,18 +1,15 @@
1
+ use common_macros::event;
1
2
  use endpoint_v2::Origin;
2
- use soroban_sdk::{contractevent, Address, Vec};
3
+ use soroban_sdk::{Address, Vec};
3
4
 
4
5
  use crate::interfaces::{NativeDropParams, SetDstConfigParam};
5
6
 
6
- // === Executor Events ===
7
-
8
- #[contractevent(topics = ["DstConfigSet"])]
9
- #[derive(Clone, Eq, PartialEq)]
7
+ #[event]
10
8
  pub struct DstConfigSet {
11
9
  pub params: Vec<SetDstConfigParam>,
12
10
  }
13
11
 
14
- #[contractevent(topics = ["NativeDropApplied"])]
15
- #[derive(Clone, Eq, PartialEq)]
12
+ #[event]
16
13
  pub struct NativeDropApplied {
17
14
  pub origin: Origin,
18
15
  pub dst_eid: u32,
@@ -1,28 +1,81 @@
1
1
  use endpoint_v2::Origin;
2
- use message_lib_common::ILayerZeroExecutor;
3
- use soroban_sdk::{contractclient, Address, Env, Vec};
4
- use worker_common::IWorker;
2
+ use message_lib_common::interfaces::ILayerZeroExecutor;
3
+ use soroban_sdk::{contractclient, contracttype, Address, Env, Vec};
4
+ use worker::Worker;
5
5
 
6
- use crate::{
7
- interfaces::{DstConfig, ExecutionParams, NativeDropParams, SetDstConfigParam},
8
- ComposeParams,
9
- };
6
+ /// Destination chain configuration for executor fee calculation.
7
+ ///
8
+ /// Contains gas costs and fee parameters specific to each destination chain.
9
+ /// These parameters are used by the fee library to calculate accurate execution fees.
10
+ #[contracttype]
11
+ #[derive(Clone, Debug, Eq, PartialEq)]
12
+ pub struct DstConfig {
13
+ /// Base gas cost for lzReceive execution on the destination chain.
14
+ pub lz_receive_base_gas: u64,
15
+ /// Fee multiplier in basis points for this destination (0 = use default multiplier).
16
+ pub multiplier_bps: u32,
17
+ /// Minimum fee margin in USD (scaled) to ensure profitability.
18
+ pub floor_margin_usd: u128,
19
+ /// Maximum native token value that can be transferred to the destination.
20
+ pub native_cap: u128,
21
+ /// Base gas cost per lzCompose call on the destination chain.
22
+ pub lz_compose_base_gas: u64,
23
+ }
10
24
 
11
- /// IExecutor - Main executor interface that combines multiple executor capabilities
12
- /// Inherits from: IWorker and includes LayerZero execution methods
13
- #[contractclient(name = "ExecutorClient")]
14
- pub trait IExecutor: IWorker + ILayerZeroExecutor {
15
- // === Destination Configuration ===
25
+ /// Parameters for setting destination configuration.
26
+ ///
27
+ /// Used when configuring executor settings for a specific destination chain.
28
+ #[contracttype]
29
+ #[derive(Clone, Debug, Eq, PartialEq)]
30
+ pub struct SetDstConfigParam {
31
+ /// Destination endpoint ID (chain identifier).
32
+ pub dst_eid: u32,
33
+ /// Configuration for the destination chain.
34
+ pub dst_config: DstConfig,
35
+ }
16
36
 
17
- /// Get destination configuration for a specific endpoint
18
- fn dst_config(env: &Env, dst_eid: u32) -> Option<DstConfig>;
37
+ /// Parameters for a native token drop.
38
+ ///
39
+ /// Used to specify native token transfers as part of executor options.
40
+ #[contracttype]
41
+ #[derive(Clone, Debug, Eq, PartialEq)]
42
+ pub struct NativeDropParams {
43
+ /// Receiver address for the native token transfer.
44
+ pub receiver: Address,
45
+ /// Amount of native tokens to transfer.
46
+ pub amount: i128,
47
+ }
19
48
 
20
- /// Set destination configurations (admin only)
49
+ // ============================================================================
50
+ // IExecutor Trait
51
+ // ============================================================================
52
+
53
+ #[contractclient(name = "ExecutorClient")]
54
+ pub trait IExecutor: Worker + ILayerZeroExecutor {
55
+ /// Sets destination-specific configurations for multiple endpoints.
56
+ ///
57
+ /// # Arguments
58
+ /// * `admin` - Admin address (must provide authorization)
59
+ /// * `params` - Vector of (dst_eid, DstConfig) pairs to set
21
60
  fn set_dst_config(env: &Env, admin: &Address, params: &Vec<SetDstConfigParam>);
22
61
 
23
- // === Execution Functions ===
62
+ /// Returns the destination configuration for a specific endpoint.
63
+ ///
64
+ /// # Arguments
65
+ /// * `dst_eid` - Destination endpoint ID (chain identifier)
66
+ fn dst_config(env: &Env, dst_eid: u32) -> DstConfig;
24
67
 
25
- /// Execute native token drops
68
+ /// Native token drops.
69
+ ///
70
+ /// Transfers native tokens to each receiver specified in the parameters and
71
+ /// tracks the success/failure status of each transfer.
72
+ ///
73
+ /// # Arguments
74
+ /// * `admin` - Admin address (must provide authorization)
75
+ /// * `origin` - Origin of the message
76
+ /// * `dst_eid` - Destination endpoint ID (chain identifier)
77
+ /// * `oapp` - OApp address
78
+ /// * `native_drop_params` - Vector of (receiver, amount) pairs to transfer
26
79
  fn native_drop(
27
80
  env: &Env,
28
81
  admin: &Address,
@@ -32,9 +85,6 @@ pub trait IExecutor: IWorker + ILayerZeroExecutor {
32
85
  native_drop_params: &Vec<NativeDropParams>,
33
86
  );
34
87
 
35
- /// Execute v2 message
36
- fn execute(env: &Env, admin: &Address, execution_params: &ExecutionParams);
37
-
38
- /// Compose v2 message
39
- fn compose(env: &Env, admin: &Address, compose_params: &ComposeParams);
88
+ /// Returns the endpoint address.
89
+ fn endpoint(env: &Env) -> Address;
40
90
  }
@@ -1,5 +1,3 @@
1
1
  pub mod executor;
2
- pub mod types;
3
2
 
4
3
  pub use executor::*;
5
- pub use types::*;
@@ -1,10 +1,19 @@
1
1
  #![no_std]
2
2
 
3
- pub mod events;
4
- pub mod executor;
5
- pub mod interfaces;
6
- pub mod storage;
7
-
8
- pub use events::*;
9
- pub use executor::*;
3
+ mod interfaces;
10
4
  pub use interfaces::*;
5
+
6
+ cfg_if::cfg_if! {
7
+ // Include implementation when NOT in library mode, OR when testutils is enabled (for tests)
8
+ if #[cfg(any(not(feature = "library"), feature = "testutils"))] {
9
+ mod errors;
10
+ mod events;
11
+ mod storage;
12
+ mod lz_executor;
13
+
14
+ pub use lz_executor::{LzExecutor, LzExecutorClient, WhitelistEntry};
15
+ }
16
+ }
17
+
18
+ // #[cfg(test)]
19
+ // mod tests;
@@ -0,0 +1,308 @@
1
+ use crate::{
2
+ errors::ExecutorError,
3
+ events::{DstConfigSet, NativeDropApplied},
4
+ interfaces::{DstConfig, IExecutor, SetDstConfigParam},
5
+ storage::ExecutorStorage,
6
+ NativeDropParams,
7
+ };
8
+ use common_macros::{contract_impl, only_owner, ttl_configurable};
9
+ use endpoint_v2::{FeeRecipient, LayerZeroEndpointV2Client, Origin};
10
+ use message_lib_common::interfaces::ILayerZeroExecutor;
11
+ use soroban_sdk::{
12
+ address_payload::AddressPayload,
13
+ auth::{Context, CustomAccountInterface},
14
+ contract, contractimpl, contracttype,
15
+ crypto::Hash,
16
+ token::TokenClient,
17
+ vec, Address, Bytes, BytesN, Env, Symbol, Vec,
18
+ };
19
+ use utils::option_ext::OptionExt;
20
+ use utils::ownable::Ownable;
21
+ use worker::{
22
+ assert_acl, assert_not_paused, assert_supported_message_lib, init_worker, require_admin_auth, ExecutorFeeLibClient,
23
+ FeeParams, Worker, set_admin_by_owner,
24
+ };
25
+
26
+ /// Signature data for Custom Account authorization.
27
+ /// Contains the admin's public key and their Ed25519 signature over the authorization payload.
28
+ #[contracttype]
29
+ #[derive(Clone, Debug, Eq, PartialEq)]
30
+ pub struct ExecutorSignature {
31
+ /// Admin's Ed25519 public key (32 bytes) - must correspond to a registered admin
32
+ pub public_key: BytesN<32>,
33
+ /// Ed25519 signature (64 bytes) over the signature_payload
34
+ pub signature: BytesN<64>,
35
+ }
36
+
37
+ /// Whitelist entry for authorized (contract, function) pairs.
38
+ ///
39
+ /// Used to configure which contracts and functions can trigger Executor authorization.
40
+ #[contracttype]
41
+ #[derive(Clone, Debug, Eq, PartialEq)]
42
+ pub struct WhitelistEntry {
43
+ /// Contract address that is allowed to call the function.
44
+ pub contract: Address,
45
+ /// Function name that is whitelisted for this contract.
46
+ pub fn_name: Symbol,
47
+ }
48
+
49
+ /// LayerZero Executor contract for cross-chain message execution.
50
+ #[contract]
51
+ #[ttl_configurable]
52
+ pub struct LzExecutor;
53
+
54
+ #[contract_impl]
55
+ impl LzExecutor {
56
+ /// Initializes the executor contract.
57
+ ///
58
+ /// Sets up ownership, worker configuration, endpoint address, and whitelisted functions.
59
+ ///
60
+ /// # Arguments
61
+ /// * `endpoint` - LayerZero Endpoint V2 contract address
62
+ /// * `owner` - Contract owner address
63
+ /// * `admins` - Initial admin addresses (must not be empty)
64
+ /// * `message_libs` - Supported message library addresses (e.g., ULN302)
65
+ /// * `price_feed` - Price feed contract address for fee calculations
66
+ /// * `default_multiplier_bps` - Default fee multiplier in basis points (10000 = 1x)
67
+ /// * `whitelist` - Initial whitelisted (contract, function) pairs for authorization
68
+ pub fn __constructor(
69
+ env: &Env,
70
+ endpoint: &Address,
71
+ owner: &Address,
72
+ admins: &Vec<Address>,
73
+ message_libs: &Vec<Address>,
74
+ price_feed: &Address,
75
+ default_multiplier_bps: u32,
76
+ whitelist: &Vec<WhitelistEntry>,
77
+ ) {
78
+ Self::init_owner(env, owner);
79
+ init_worker::<Self>(env, admins, message_libs, price_feed, default_multiplier_bps);
80
+ ExecutorStorage::set_endpoint(env, endpoint);
81
+
82
+ // Set initial whitelisted functions
83
+ for entry in whitelist.iter() {
84
+ ExecutorStorage::set_whitelisted_fn(env, &entry.contract, &entry.fn_name, &true);
85
+ }
86
+ }
87
+
88
+ /// Sets whether a (contract, function) pair is whitelisted.
89
+ /// When `allowed` is false, the entry is removed from storage to save space.
90
+ ///
91
+ /// Only the contract owner can call this function.
92
+ #[only_owner]
93
+ pub fn set_whitelisted_fn(env: &Env, contract: &Address, fn_name: &Symbol, allowed: bool) {
94
+ let value = if allowed { Some(true) } else { None };
95
+ ExecutorStorage::set_or_remove_whitelisted_fn(env, contract, fn_name, &value);
96
+ }
97
+
98
+ /// Returns whether a (contract, function) pair is whitelisted.
99
+ pub fn is_whitelisted_fn(env: &Env, contract: &Address, fn_name: &Symbol) -> bool {
100
+ ExecutorStorage::has_whitelisted_fn(env, contract, fn_name)
101
+ }
102
+
103
+ /// Withdraws a token from the contract to a specified address.
104
+ ///
105
+ /// # Arguments
106
+ /// * `token` - The token contract address
107
+ /// * `to` - The recipient address
108
+ /// * `amount` - The amount to withdraw
109
+ pub fn withdraw_token(env: &Env, admin: &Address, token: &Address, to: &Address, amount: i128) {
110
+ require_admin_auth::<Self>(env, admin);
111
+ TokenClient::new(env, token).transfer(&env.current_contract_address(), to, &amount);
112
+ }
113
+
114
+ /// Sets admin status for an address. Requires owner authorization.
115
+ ///
116
+ /// This is the multisig/quorum path for admin management.
117
+ ///
118
+ /// # Arguments
119
+ /// * `admin` - The address to set admin status for
120
+ /// * `active` - Whether the address should be an admin
121
+ pub fn set_admin(env: &Env, admin: &Address, active: bool) {
122
+ set_admin_by_owner::<Self>(env, admin, active);
123
+ }
124
+ }
125
+
126
+ // ============================================================================
127
+ // IExecutor implementation
128
+ // ============================================================================
129
+
130
+ #[contract_impl]
131
+ impl IExecutor for LzExecutor {
132
+ /// Sets destination-specific configurations for multiple endpoints.
133
+ fn set_dst_config(env: &Env, admin: &Address, params: &Vec<SetDstConfigParam>) {
134
+ require_admin_auth::<Self>(env, admin);
135
+
136
+ for param in params {
137
+ ExecutorStorage::set_dst_config(env, param.dst_eid, &param.dst_config);
138
+ }
139
+ DstConfigSet { params: params.clone() }.publish(env);
140
+ }
141
+
142
+ /// Returns the destination configuration for a specific endpoint.
143
+ fn dst_config(env: &Env, dst_eid: u32) -> DstConfig {
144
+ ExecutorStorage::dst_config(env, dst_eid).unwrap_or_panic(env, ExecutorError::EidNotSupported)
145
+ }
146
+
147
+ /// Native token drops.
148
+ ///
149
+ /// Transfers native tokens to each receiver specified in the parameters and
150
+ /// tracks the success/failure status of each transfer.
151
+ fn native_drop(
152
+ env: &Env,
153
+ admin: &Address,
154
+ origin: &Origin,
155
+ dst_eid: u32,
156
+ oapp: &Address,
157
+ native_drop_params: &Vec<NativeDropParams>,
158
+ ) {
159
+ require_admin_auth::<Self>(env, admin);
160
+
161
+ let endpoint_client = LayerZeroEndpointV2Client::new(env, &Self::endpoint(env));
162
+ let token_client = TokenClient::new(env, &endpoint_client.native_token());
163
+
164
+ // Transfer native tokens from admin to each receiver and track success/failure
165
+ let mut success = vec![env];
166
+ for param in native_drop_params {
167
+ success.push_back(token_client.try_transfer(admin, &param.receiver, &param.amount).is_ok());
168
+ }
169
+
170
+ // Emit event with transfer results
171
+ NativeDropApplied {
172
+ origin: origin.clone(),
173
+ dst_eid,
174
+ oapp: oapp.clone(),
175
+ native_drop_params: native_drop_params.clone(),
176
+ success,
177
+ }
178
+ .publish(env);
179
+ }
180
+
181
+ /// Returns the endpoint address from storage.
182
+ fn endpoint(env: &Env) -> Address {
183
+ ExecutorStorage::endpoint(env).unwrap()
184
+ }
185
+ }
186
+
187
+ // ============================================================================
188
+ // ILayerZeroExecutor implementation (send-flow)
189
+ // ============================================================================
190
+
191
+ #[contract_impl]
192
+ impl ILayerZeroExecutor for LzExecutor {
193
+ /// Assigns a job to the executor and returns fee recipient information.
194
+ fn assign_job(
195
+ env: &Env,
196
+ send_lib: &Address,
197
+ sender: &Address,
198
+ dst_eid: u32,
199
+ calldata_size: u32,
200
+ options: &Bytes,
201
+ ) -> FeeRecipient {
202
+ send_lib.require_auth();
203
+ assert_supported_message_lib::<Self>(env, send_lib);
204
+ // `get_fee` already asserts not_paused and acl, so we don't need to do it here again
205
+
206
+ let fee = Self::get_fee(env, send_lib, sender, dst_eid, calldata_size, options);
207
+ FeeRecipient { amount: fee, to: Self::deposit_address(env) }
208
+ }
209
+
210
+ /// Calculates the execution fee for a cross-chain message.
211
+ fn get_fee(
212
+ env: &Env,
213
+ _send_lib: &Address,
214
+ sender: &Address,
215
+ dst_eid: u32,
216
+ calldata_size: u32,
217
+ options: &Bytes,
218
+ ) -> i128 {
219
+ assert_not_paused::<Self>(env);
220
+ assert_acl::<Self>(env, sender);
221
+
222
+ let dst_config = Self::dst_config(env, dst_eid);
223
+ let fee_params = FeeParams {
224
+ sender: sender.clone(),
225
+ dst_eid,
226
+ calldata_size,
227
+ options: options.clone(),
228
+ price_feed: Self::price_feed(env),
229
+ default_multiplier_bps: Self::default_multiplier_bps(env),
230
+ lz_receive_base_gas: dst_config.lz_receive_base_gas,
231
+ lz_compose_base_gas: dst_config.lz_compose_base_gas,
232
+ floor_margin_usd: dst_config.floor_margin_usd,
233
+ native_cap: dst_config.native_cap,
234
+ multiplier_bps: dst_config.multiplier_bps,
235
+ };
236
+
237
+ ExecutorFeeLibClient::new(env, &Self::worker_fee_lib(env)).get_fee(&env.current_contract_address(), &fee_params)
238
+ }
239
+ }
240
+
241
+ // ============================================================================
242
+ // CustomAccountInterface implementation, used for receive-flow execution
243
+ // ============================================================================
244
+
245
+ #[contractimpl]
246
+ impl CustomAccountInterface for LzExecutor {
247
+ type Signature = ExecutorSignature;
248
+ type Error = ExecutorError;
249
+
250
+ /// Verifies authorization for the executor contract.
251
+ ///
252
+ /// The public key must correspond to a registered admin and must have signed the signature_payload.
253
+ /// Uses Ed25519 signature verification.
254
+ /// Only whitelisted function calls are authorized.
255
+ fn __check_auth(
256
+ env: Env,
257
+ signature_payload: Hash<32>,
258
+ auth_data: Self::Signature,
259
+ auth_contexts: Vec<Context>,
260
+ ) -> Result<(), Self::Error> {
261
+ Self::verify_admin_signature(&env, &signature_payload, &auth_data)?;
262
+ Self::validate_auth_contexts(&env, &auth_contexts)?;
263
+ Ok(())
264
+ }
265
+ }
266
+
267
+ impl LzExecutor {
268
+ /// Verifies that the signature is from a registered admin.
269
+ ///
270
+ /// Converts the public key to an address, checks admin registration,
271
+ /// and verifies the Ed25519 signature over the payload.
272
+ fn verify_admin_signature(
273
+ env: &Env,
274
+ signature_payload: &Hash<32>,
275
+ auth_data: &ExecutorSignature,
276
+ ) -> Result<(), ExecutorError> {
277
+ let admin = Address::from_payload(env, AddressPayload::AccountIdPublicKeyEd25519(auth_data.public_key.clone()));
278
+ if !Self::is_admin(env, &admin) {
279
+ return Err(ExecutorError::Unauthorized);
280
+ }
281
+ env.crypto().ed25519_verify(&auth_data.public_key, &signature_payload.clone().into(), &auth_data.signature);
282
+ Ok(())
283
+ }
284
+
285
+ /// Validates that the first auth context is a whitelisted (contract, function) pair.
286
+ /// Sub-invocations are trusted since they're controlled by the whitelisted contract.
287
+ fn validate_auth_contexts(env: &Env, contexts: &Vec<Context>) -> Result<(), ExecutorError> {
288
+ let first_context = contexts.first().ok_or(ExecutorError::UnauthorizedContext)?;
289
+
290
+ match first_context {
291
+ Context::Contract(contract_context) => {
292
+ // Check if (contract, fn_name) pair is whitelisted
293
+ if !Self::is_whitelisted_fn(env, &contract_context.contract, &contract_context.fn_name) {
294
+ return Err(ExecutorError::UnauthorizedContext);
295
+ }
296
+ }
297
+ // Contract creation is not allowed
298
+ Context::CreateContractHostFn(_) | Context::CreateContractWithCtorHostFn(_) => {
299
+ return Err(ExecutorError::UnauthorizedContext);
300
+ }
301
+ }
302
+
303
+ Ok(())
304
+ }
305
+ }
306
+
307
+ #[contractimpl(contracttrait)]
308
+ impl Worker for LzExecutor {}
@@ -1,23 +1,31 @@
1
- use crate::interfaces::DstConfig;
2
1
  use common_macros::storage;
3
- use soroban_sdk::Address;
4
- use utils::ttl::DefaultTtlConfigProvider;
2
+ use soroban_sdk::{Address, Symbol};
5
3
 
6
- // ============================================================================
7
- // Executor Storage
8
- // ============================================================================
4
+ use crate::DstConfig;
9
5
 
10
- #[storage(DefaultTtlConfigProvider)]
11
- pub enum ExecutorData {
12
- /// Endpoint V2 address
6
+ /// Storage keys for the Executor contract.
7
+ ///
8
+ /// Manages persistent storage for destination configurations and instance storage
9
+ /// for the endpoint address and whitelisted functions.
10
+ #[storage]
11
+ pub enum ExecutorStorage {
12
+ /// Destination chain configuration indexed by endpoint ID.
13
+ ///
14
+ /// Stores `DstConfig` for each destination endpoint, containing gas costs,
15
+ /// fee multipliers, and native caps.
16
+ #[persistent(DstConfig)]
17
+ DstConfig { eid: u32 },
18
+
19
+ /// LayerZero Endpoint V2 contract address.
20
+ ///
21
+ /// Used for receive-flow operations to interact with the endpoint.
13
22
  #[instance(Address)]
14
23
  Endpoint,
15
24
 
16
- /// Local endpoint ID (EID)
17
- #[instance(u32)]
18
- LocalEid,
19
-
20
- /// Destination configuration per EID
21
- #[persistent(DstConfig)]
22
- DstConfig { eid: u32 },
25
+ /// Whitelisted function for a specific contract.
26
+ ///
27
+ /// Only whitelisted (contract, function) pairs can trigger Executor authorization.
28
+ /// This allows fine-grained control over which contracts can call which functions.
29
+ #[instance(bool)]
30
+ WhitelistedFn { contract: Address, fn_name: Symbol },
23
31
  }
@@ -0,0 +1,22 @@
1
+ [package]
2
+ name = "executor-fee-lib"
3
+ version.workspace = true
4
+ edition.workspace = true
5
+ license.workspace = true
6
+ publish = false
7
+
8
+ [lib]
9
+ crate-type = ["cdylib"]
10
+ doctest = false
11
+
12
+ [dependencies]
13
+ soroban-sdk = { workspace = true }
14
+ # workspace dependencies
15
+ utils = { workspace = true }
16
+ worker = { workspace = true }
17
+ common-macros = { workspace = true }
18
+ message-lib-common = { workspace = true }
19
+
20
+ [dev-dependencies]
21
+ soroban-sdk = { workspace = true, features = ["testutils"] }
22
+
@@ -0,0 +1,15 @@
1
+ use common_macros::contract_error;
2
+
3
+ #[contract_error]
4
+ pub enum ExecutorFeeLibError {
5
+ NoOptions,
6
+ UnsupportedOptionType,
7
+ ZeroLzReceiveGasProvided,
8
+ ZeroLzComposeGasProvided,
9
+ NativeAmountExceedsCap,
10
+ InvalidLzReceiveOption,
11
+ InvalidNativeDropOption,
12
+ InvalidLzComposeOption,
13
+ InvalidExecutorOptions,
14
+ EidNotSupported,
15
+ }