@layerzerolabs/protocol-stellar-v2 0.2.19 → 0.2.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (249) hide show
  1. package/.turbo/turbo-build.log +795 -791
  2. package/.turbo/turbo-lint.log +325 -155
  3. package/.turbo/turbo-test.log +1398 -1277
  4. package/Cargo.lock +122 -111
  5. package/Cargo.toml +32 -16
  6. package/contracts/common-macros/Cargo.toml +7 -7
  7. package/contracts/common-macros/src/auth.rs +18 -37
  8. package/contracts/common-macros/src/contract_ttl.rs +18 -7
  9. package/contracts/common-macros/src/lib.rs +31 -14
  10. package/contracts/common-macros/src/lz_contract.rs +38 -7
  11. package/contracts/common-macros/src/storage.rs +251 -292
  12. package/contracts/common-macros/src/tests/contract_ttl.rs +1 -1
  13. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_multisig_code.snap +6 -12
  14. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_ownable_code.snap +12 -17
  15. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__contract_ttl__snapshot_generated_contractimpl_code.snap +2 -1
  16. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +2 -7
  17. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__upgradeable__snapshot_generated_upgradeable_code.snap +20 -14
  18. package/contracts/common-macros/src/tests/upgradeable.rs +26 -4
  19. package/contracts/common-macros/src/ttl_configurable.rs +2 -10
  20. package/contracts/common-macros/src/ttl_extendable.rs +2 -10
  21. package/contracts/common-macros/src/upgradeable.rs +61 -26
  22. package/contracts/common-macros/src/utils.rs +0 -9
  23. package/contracts/endpoint-v2/src/lib.rs +3 -2
  24. package/contracts/endpoint-v2/src/tests/endpoint_v2/clear.rs +2 -2
  25. package/contracts/endpoint-v2/src/tests/endpoint_v2/lz_receive_alert.rs +3 -3
  26. package/contracts/endpoint-v2/src/tests/endpoint_v2/send.rs +4 -4
  27. package/contracts/endpoint-v2/src/tests/endpoint_v2/set_delegate.rs +17 -5
  28. package/contracts/endpoint-v2/src/tests/endpoint_v2/set_zro.rs +4 -4
  29. package/contracts/endpoint-v2/src/tests/endpoint_v2/verify.rs +2 -2
  30. package/contracts/endpoint-v2/src/tests/message_lib_manager/register_library.rs +2 -2
  31. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_lib_timeout.rs +6 -6
  32. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_library.rs +67 -37
  33. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_send_library.rs +5 -5
  34. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_receive_library.rs +44 -54
  35. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_receive_library_timeout.rs +7 -7
  36. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_send_library.rs +8 -8
  37. package/contracts/endpoint-v2/src/tests/messaging_channel/burn.rs +3 -3
  38. package/contracts/endpoint-v2/src/tests/messaging_channel/nilify.rs +4 -4
  39. package/contracts/endpoint-v2/src/tests/messaging_channel/skip.rs +3 -3
  40. package/contracts/endpoint-v2/src/tests/messaging_composer/clear_compose.rs +2 -2
  41. package/contracts/endpoint-v2/src/tests/messaging_composer/lz_compose_alert.rs +3 -3
  42. package/contracts/endpoint-v2/src/tests/messaging_composer/send_compose.rs +2 -2
  43. package/contracts/layerzero-views/Cargo.toml +0 -1
  44. package/contracts/layerzero-views/src/layerzero_view.rs +1 -13
  45. package/contracts/macro-integration-tests/Cargo.toml +5 -15
  46. package/contracts/macro-integration-tests/tests/runtime/oapp/mod.rs +48 -0
  47. package/contracts/macro-integration-tests/tests/runtime/oapp/oapp_core.rs +170 -0
  48. package/contracts/macro-integration-tests/tests/runtime/oapp/options_type3.rs +154 -0
  49. package/contracts/macro-integration-tests/tests/runtime/oapp/receiver.rs +338 -0
  50. package/contracts/macro-integration-tests/tests/runtime/oapp/sender.rs +435 -0
  51. package/contracts/macro-integration-tests/tests/runtime.rs +1 -0
  52. package/contracts/macro-integration-tests/tests/ui/oapp/fail/custom_wrong_value.rs +8 -0
  53. package/contracts/macro-integration-tests/tests/ui/oapp/fail/custom_wrong_value.stderr +5 -0
  54. package/contracts/macro-integration-tests/tests/ui/oapp/fail/missing_lz_receive_internal.rs +8 -0
  55. package/contracts/macro-integration-tests/tests/ui/oapp/fail/missing_lz_receive_internal.stderr +71 -0
  56. package/contracts/macro-integration-tests/tests/ui/oapp/fail/non_struct_input.rs +10 -0
  57. package/contracts/macro-integration-tests/tests/ui/oapp/fail/non_struct_input.stderr +5 -0
  58. package/contracts/macro-integration-tests/tests/ui/oapp/fail/unknown_custom_option.rs +8 -0
  59. package/contracts/macro-integration-tests/tests/ui/oapp/fail/unknown_custom_option.stderr +5 -0
  60. package/contracts/macro-integration-tests/tests/ui/oapp/fail/wrong_key.rs +8 -0
  61. package/contracts/macro-integration-tests/tests/ui/oapp/fail/wrong_key.stderr +5 -0
  62. package/contracts/macro-integration-tests/tests/ui/oapp/pass/custom_all.rs +38 -0
  63. package/contracts/macro-integration-tests/tests/ui/oapp/pass/custom_single_trait.rs +96 -0
  64. package/contracts/macro-integration-tests/tests/ui/oapp/pass/minimal_contract.rs +64 -0
  65. package/contracts/macro-integration-tests/tests/ui/oapp/pass/struct_with_fields.rs +46 -0
  66. package/contracts/macro-integration-tests/tests/ui/ownable/fail/only_auth_missing_env.stderr +8 -0
  67. package/contracts/macro-integration-tests/tests/ui/ownable/pass/namespacing_and_imports.rs +1 -1
  68. package/contracts/macro-integration-tests/tests/ui/ownable/pass/only_auth_env_param_variants.rs +1 -1
  69. package/contracts/macro-integration-tests/tests/ui_oapp.rs +11 -0
  70. package/contracts/message-libs/message-lib-common/Cargo.toml +0 -1
  71. package/contracts/message-libs/message-lib-common/src/errors.rs +1 -1
  72. package/contracts/message-libs/treasury/Cargo.toml +0 -2
  73. package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +2 -2
  74. package/contracts/message-libs/uln-302/src/events.rs +4 -0
  75. package/contracts/message-libs/uln-302/src/send_uln.rs +22 -6
  76. package/contracts/message-libs/uln-302/src/tests/receive_uln302/effective_receive_uln_config.rs +2 -2
  77. package/contracts/message-libs/uln-302/src/tests/receive_uln302/set_default_receive_uln_configs.rs +2 -2
  78. package/contracts/message-libs/uln-302/src/tests/receive_uln302/verify.rs +2 -2
  79. package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_executor_config.rs +2 -2
  80. package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_send_uln_config.rs +2 -2
  81. package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +21 -67
  82. package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_executor_configs.rs +2 -2
  83. package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_send_uln_configs.rs +2 -2
  84. package/contracts/oapps/counter/Cargo.toml +5 -6
  85. package/contracts/oapps/counter/integration_tests/setup_uln.rs +1 -1
  86. package/contracts/oapps/counter/integration_tests/utils.rs +19 -12
  87. package/contracts/oapps/oapp/src/errors.rs +1 -1
  88. package/contracts/oapps/oapp/src/interfaces/mod.rs +3 -0
  89. package/contracts/oapps/oapp/src/interfaces/oapp_msg_inspector.rs +47 -0
  90. package/contracts/oapps/oapp/src/lib.rs +1 -0
  91. package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +4 -4
  92. package/contracts/oapps/oapp/src/oapp_core.rs +5 -5
  93. package/contracts/oapps/oapp/src/oapp_options_type3.rs +12 -4
  94. package/contracts/oapps/oapp/src/oapp_receiver.rs +14 -9
  95. package/contracts/oapps/oapp/src/tests/mod.rs +4 -4
  96. package/contracts/oapps/oapp/src/tests/oapp_core.rs +223 -0
  97. package/contracts/oapps/oapp/src/tests/oapp_options_type3.rs +240 -0
  98. package/contracts/oapps/oapp/src/tests/oapp_receiver.rs +381 -0
  99. package/contracts/oapps/oapp/src/tests/oapp_sender.rs +569 -0
  100. package/contracts/oapps/oapp-macros/Cargo.toml +8 -4
  101. package/contracts/oapps/oapp-macros/src/generators.rs +9 -34
  102. package/contracts/oapps/oapp-macros/src/lib.rs +3 -0
  103. package/contracts/oapps/oapp-macros/src/tests/mod.rs +2 -0
  104. package/contracts/oapps/oapp-macros/src/tests/oapp.rs +88 -0
  105. package/contracts/oapps/oapp-macros/src/tests/parse_custom_impls.rs +86 -0
  106. package/contracts/oapps/oapp-macros/src/tests/snapshots/oapp_macros__tests__oapp__snapshot_generate_oapp.snap +103 -0
  107. package/contracts/oapps/oft/integration-tests/utils.rs +28 -8
  108. package/contracts/oapps/oft/src/extensions/oft_fee.rs +153 -75
  109. package/contracts/oapps/oft/src/extensions/pausable.rs +61 -12
  110. package/contracts/oapps/oft/src/extensions/rate_limiter.rs +198 -134
  111. package/contracts/oapps/oft/src/oft.rs +45 -50
  112. package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +1 -1
  113. package/contracts/oapps/oft/src/oft_types/mint_burn.rs +4 -26
  114. package/contracts/oapps/oft-core/Cargo.toml +1 -4
  115. package/contracts/oapps/oft-core/integration-tests/setup.rs +3 -3
  116. package/contracts/oapps/oft-core/integration-tests/utils.rs +21 -3
  117. package/contracts/oapps/oft-core/src/errors.rs +3 -2
  118. package/contracts/oapps/oft-core/src/events.rs +6 -0
  119. package/contracts/oapps/oft-core/src/lib.rs +1 -1
  120. package/contracts/oapps/oft-core/src/oft_core.rs +341 -246
  121. package/contracts/oapps/oft-core/src/storage.rs +7 -3
  122. package/contracts/oapps/oft-core/src/tests/mod.rs +1 -0
  123. package/contracts/oapps/oft-core/src/tests/test_decimals.rs +37 -2
  124. package/contracts/oapps/oft-core/src/tests/test_lz_receive.rs +2 -2
  125. package/contracts/oapps/oft-core/src/tests/test_msg_inspector.rs +323 -0
  126. package/contracts/oapps/oft-core/src/tests/test_send.rs +2 -2
  127. package/contracts/oapps/oft-core/src/tests/test_utils.rs +61 -16
  128. package/contracts/upgrader/src/lib.rs +30 -57
  129. package/contracts/upgrader/src/tests/test_data/test_upgradeable_contract1.wasm +0 -0
  130. package/contracts/upgrader/src/tests/test_data/test_upgradeable_contract2.wasm +0 -0
  131. package/contracts/upgrader/src/tests/test_upgrader.rs +44 -35
  132. package/contracts/utils/Cargo.toml +0 -1
  133. package/contracts/utils/src/buffer_reader.rs +1 -0
  134. package/contracts/utils/src/errors.rs +4 -2
  135. package/contracts/utils/src/multisig.rs +17 -8
  136. package/contracts/utils/src/ownable.rs +6 -6
  137. package/contracts/utils/src/testing_utils.rs +124 -54
  138. package/contracts/utils/src/tests/multisig.rs +12 -12
  139. package/contracts/utils/src/tests/ownable.rs +6 -6
  140. package/contracts/utils/src/tests/testing_utils.rs +50 -167
  141. package/contracts/utils/src/tests/ttl_configurable.rs +5 -5
  142. package/contracts/utils/src/tests/upgradeable.rs +372 -175
  143. package/contracts/utils/src/ttl_configurable.rs +13 -7
  144. package/contracts/utils/src/upgradeable.rs +48 -23
  145. package/contracts/workers/dvn/Cargo.toml +6 -6
  146. package/contracts/workers/dvn/src/auth.rs +12 -42
  147. package/contracts/workers/dvn/src/dvn.rs +15 -40
  148. package/contracts/workers/dvn/src/errors.rs +0 -1
  149. package/contracts/workers/dvn/src/interfaces/dvn.rs +35 -0
  150. package/contracts/workers/dvn/src/lib.rs +4 -3
  151. package/contracts/workers/dvn/src/tests/auth.rs +1 -1
  152. package/contracts/workers/dvn/src/tests/dvn.rs +19 -15
  153. package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +2 -4
  154. package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +1 -3
  155. package/contracts/workers/dvn/src/tests/setup.rs +5 -9
  156. package/contracts/workers/dvn-fee-lib/Cargo.toml +2 -2
  157. package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +38 -22
  158. package/contracts/workers/dvn-fee-lib/src/lib.rs +12 -2
  159. package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +17 -16
  160. package/contracts/workers/executor/Cargo.toml +4 -0
  161. package/contracts/workers/executor/src/executor.rs +15 -36
  162. package/contracts/workers/executor/src/lib.rs +2 -2
  163. package/contracts/workers/executor/src/tests/auth.rs +394 -0
  164. package/contracts/workers/executor/src/tests/executor.rs +410 -0
  165. package/contracts/workers/executor/src/tests/mod.rs +3 -0
  166. package/contracts/workers/executor/src/tests/setup.rs +250 -0
  167. package/contracts/workers/executor-fee-lib/Cargo.toml +7 -1
  168. package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +62 -15
  169. package/contracts/workers/executor-fee-lib/src/executor_option.rs +28 -1
  170. package/contracts/workers/executor-fee-lib/src/lib.rs +11 -2
  171. package/contracts/workers/executor-fee-lib/src/tests/executor_fee_lib.rs +701 -0
  172. package/contracts/workers/executor-fee-lib/src/tests/executor_option.rs +370 -0
  173. package/contracts/workers/executor-fee-lib/src/tests/mod.rs +4 -0
  174. package/contracts/workers/executor-fee-lib/src/tests/setup.rs +60 -0
  175. package/contracts/workers/executor-helper/Cargo.toml +0 -1
  176. package/contracts/workers/executor-helper/src/lib.rs +3 -0
  177. package/contracts/workers/executor-helper/src/tests/executor_helper.rs +184 -0
  178. package/contracts/workers/executor-helper/src/tests/mod.rs +2 -0
  179. package/contracts/workers/executor-helper/src/tests/setup.rs +366 -0
  180. package/contracts/workers/fee-lib-interfaces/Cargo.toml +14 -0
  181. package/contracts/workers/{worker/src/interfaces/mod.rs → fee-lib-interfaces/src/lib.rs} +4 -3
  182. package/contracts/workers/price-feed/Cargo.toml +7 -1
  183. package/contracts/workers/price-feed/src/events.rs +1 -1
  184. package/contracts/workers/price-feed/src/lib.rs +12 -4
  185. package/contracts/workers/price-feed/src/price_feed.rs +5 -21
  186. package/contracts/workers/price-feed/src/storage.rs +1 -1
  187. package/contracts/workers/price-feed/src/tests/mod.rs +2 -0
  188. package/contracts/workers/price-feed/src/tests/price_feed.rs +869 -0
  189. package/contracts/workers/price-feed/src/tests/setup.rs +70 -0
  190. package/contracts/workers/price-feed/src/types.rs +1 -1
  191. package/contracts/workers/worker/src/errors.rs +1 -4
  192. package/contracts/workers/worker/src/lib.rs +0 -2
  193. package/contracts/workers/worker/src/storage.rs +32 -29
  194. package/contracts/workers/worker/src/tests/setup.rs +2 -8
  195. package/contracts/workers/worker/src/tests/worker.rs +96 -74
  196. package/contracts/workers/worker/src/worker.rs +75 -75
  197. package/docs/error-spec.md +55 -0
  198. package/docs/layerzero-v2-on-stellar.md +447 -0
  199. package/docs/oapp-guide.md +212 -0
  200. package/docs/oft-guide.md +314 -0
  201. package/package.json +3 -3
  202. package/sdk/.turbo/turbo-test.log +268 -263
  203. package/sdk/dist/generated/bml.d.ts +12 -4
  204. package/sdk/dist/generated/bml.js +9 -7
  205. package/sdk/dist/generated/counter.d.ts +306 -298
  206. package/sdk/dist/generated/counter.js +48 -46
  207. package/sdk/dist/generated/dvn.d.ts +450 -411
  208. package/sdk/dist/generated/dvn.js +66 -64
  209. package/sdk/dist/generated/dvn_fee_lib.d.ts +294 -338
  210. package/sdk/dist/generated/dvn_fee_lib.js +33 -64
  211. package/sdk/dist/generated/endpoint.d.ts +108 -100
  212. package/sdk/dist/generated/endpoint.js +21 -19
  213. package/sdk/dist/generated/executor.d.ts +414 -370
  214. package/sdk/dist/generated/executor.js +58 -55
  215. package/sdk/dist/generated/executor_fee_lib.d.ts +333 -377
  216. package/sdk/dist/generated/executor_fee_lib.js +34 -65
  217. package/sdk/dist/generated/executor_helper.d.ts +26 -190
  218. package/sdk/dist/generated/executor_helper.js +23 -28
  219. package/sdk/dist/generated/layerzero_view.d.ts +1271 -0
  220. package/sdk/dist/generated/layerzero_view.js +294 -0
  221. package/sdk/dist/generated/oft.d.ts +408 -385
  222. package/sdk/dist/generated/oft.js +89 -92
  223. package/sdk/dist/generated/price_feed.d.ts +385 -429
  224. package/sdk/dist/generated/price_feed.js +50 -81
  225. package/sdk/dist/generated/sml.d.ts +108 -100
  226. package/sdk/dist/generated/sml.js +21 -19
  227. package/sdk/dist/generated/treasury.d.ts +108 -100
  228. package/sdk/dist/generated/treasury.js +21 -19
  229. package/sdk/dist/generated/uln302.d.ts +108 -100
  230. package/sdk/dist/generated/uln302.js +23 -21
  231. package/sdk/dist/generated/upgrader.d.ts +189 -18
  232. package/sdk/dist/generated/upgrader.js +84 -4
  233. package/sdk/dist/index.d.ts +1 -0
  234. package/sdk/dist/index.js +2 -0
  235. package/sdk/package.json +1 -1
  236. package/sdk/src/index.ts +3 -0
  237. package/sdk/test/oft-sml.test.ts +4 -4
  238. package/sdk/test/suites/localnet.ts +84 -20
  239. package/sdk/test/upgrader.test.ts +2 -3
  240. package/tools/ts-bindings-gen/src/main.rs +2 -1
  241. package/contracts/ERROR_SPEC.md +0 -44
  242. package/contracts/endpoint-v2/ARCHITECTURE.md +0 -233
  243. package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +0 -175
  244. package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +0 -212
  245. package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +0 -153
  246. package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +0 -294
  247. /package/contracts/workers/{worker/src/interfaces → fee-lib-interfaces/src}/dvn_fee_lib.rs +0 -0
  248. /package/contracts/workers/{worker/src/interfaces → fee-lib-interfaces/src}/executor_fee_lib.rs +0 -0
  249. /package/contracts/workers/{worker/src/interfaces → fee-lib-interfaces/src}/price_feed.rs +0 -0
@@ -1,6 +1,6 @@
1
1
  use crate::{
2
2
  self as utils,
3
- auth::{require_auth, Auth},
3
+ auth::{self, Auth},
4
4
  errors::TtlConfigurableError,
5
5
  };
6
6
  use common_macros::contract_trait;
@@ -111,8 +111,12 @@ pub trait TtlConfigurable: Auth {
111
111
  /// # Panics
112
112
  /// - `TtlConfigFrozen` if configs are frozen
113
113
  /// - `InvalidTtlConfig` if validation fails
114
- fn set_ttl_configs(env: &Env, instance: &Option<TtlConfig>, persistent: &Option<TtlConfig>) {
115
- require_auth::<Self>(env);
114
+ fn set_ttl_configs(
115
+ env: &soroban_sdk::Env,
116
+ instance: &Option<utils::ttl_configurable::TtlConfig>,
117
+ persistent: &Option<utils::ttl_configurable::TtlConfig>,
118
+ ) {
119
+ auth::require_auth::<Self>(env);
116
120
  assert_with_error!(env, !Self::is_ttl_configs_frozen(env), TtlConfigurableError::TtlConfigFrozen);
117
121
 
118
122
  let max_ttl = u32::min(MAX_TTL, env.storage().max_ttl());
@@ -126,7 +130,9 @@ pub trait TtlConfigurable: Auth {
126
130
  }
127
131
 
128
132
  /// Returns the current TTL configs as (instance_config, persistent_config).
129
- fn ttl_configs(env: &Env) -> (Option<TtlConfig>, Option<TtlConfig>) {
133
+ fn ttl_configs(
134
+ env: &soroban_sdk::Env,
135
+ ) -> (Option<utils::ttl_configurable::TtlConfig>, Option<utils::ttl_configurable::TtlConfig>) {
130
136
  (TtlConfigStorage::instance(env), TtlConfigStorage::persistent(env))
131
137
  }
132
138
 
@@ -137,8 +143,8 @@ pub trait TtlConfigurable: Auth {
137
143
  ///
138
144
  /// # Panics
139
145
  /// - `TtlConfigAlreadyFrozen` if already frozen
140
- fn freeze_ttl_configs(env: &Env) {
141
- require_auth::<Self>(env);
146
+ fn freeze_ttl_configs(env: &soroban_sdk::Env) {
147
+ auth::require_auth::<Self>(env);
142
148
  assert_with_error!(env, !Self::is_ttl_configs_frozen(env), TtlConfigurableError::TtlConfigAlreadyFrozen);
143
149
 
144
150
  TtlConfigStorage::set_frozen(env, &true);
@@ -147,7 +153,7 @@ pub trait TtlConfigurable: Auth {
147
153
  }
148
154
 
149
155
  /// Returns whether TTL configs are frozen.
150
- fn is_ttl_configs_frozen(env: &Env) -> bool {
156
+ fn is_ttl_configs_frozen(env: &soroban_sdk::Env) -> bool {
151
157
  TtlConfigStorage::frozen(env)
152
158
  }
153
159
  }
@@ -1,20 +1,56 @@
1
- use crate::errors::UpgradeableError;
2
- use common_macros::storage;
3
- use soroban_sdk::{assert_with_error, BytesN, Env, FromVal, Val};
1
+ use crate::{
2
+ self as utils,
3
+ auth::{self, Auth},
4
+ errors::UpgradeableError,
5
+ option_ext::OptionExt,
6
+ };
7
+ use common_macros::{contract_trait, storage};
8
+ use soroban_sdk::{assert_with_error, xdr::FromXdr, Env};
4
9
 
5
10
  // ============================================
6
11
  // Upgradeable Interface
7
12
  // ============================================
8
13
 
9
14
  /// Trait for contracts with upgrade and migration support.
10
- pub trait Upgradeable: UpgradeableInternal {
15
+ #[contract_trait]
16
+ pub trait Upgradeable: UpgradeableInternal + Auth {
17
+ /// The type of data required for migration.
11
18
  /// Upgrades the contract to new WASM bytecode.
12
19
  /// Sets a migration flag that must be cleared by calling `migrate`.
13
- fn upgrade(env: &Env, new_wasm_hash: BytesN<32>);
20
+ fn upgrade(env: &soroban_sdk::Env, new_wasm_hash: &soroban_sdk::BytesN<32>) {
21
+ auth::require_auth::<Self>(env);
22
+ assert_with_error!(env, !Self::is_frozen(env), UpgradeableError::UpgradesFrozen);
23
+ UpgradeableStorage::set_migrating(env, &true);
24
+ env.deployer().update_current_contract_wasm(new_wasm_hash.clone());
25
+ }
14
26
 
15
27
  /// Runs migration logic after an upgrade.
16
28
  /// Can only be called when the migration flag is set by a previous `upgrade` call.
17
- fn migrate(env: &Env, migration_data: &Self::MigrationData);
29
+ fn migrate(env: &soroban_sdk::Env, migration_data: &soroban_sdk::Bytes) {
30
+ auth::require_auth::<Self>(env);
31
+ assert_with_error!(env, UpgradeableStorage::migrating(env), UpgradeableError::MigrationNotAllowed);
32
+
33
+ // Parse the migration data and call the internal migration logic
34
+ let parsed_data = Self::MigrationData::from_xdr(env, migration_data)
35
+ .ok()
36
+ .unwrap_or_panic(env, UpgradeableError::InvalidMigrationData);
37
+ Self::__migrate(env, &parsed_data);
38
+
39
+ // Clear the migration flag after migration is successful
40
+ UpgradeableStorage::set_migrating(env, &false);
41
+ }
42
+
43
+ /// Permanently freezes the contract, preventing any future upgrades.
44
+ /// This action is irreversible.
45
+ fn freeze(env: &soroban_sdk::Env) {
46
+ auth::require_auth::<Self>(env);
47
+ UpgradeableStorage::set_frozen(env, &true);
48
+ }
49
+
50
+ /// Returns whether the contract is frozen (upgrades disabled).
51
+ fn is_frozen(env: &soroban_sdk::Env) -> bool {
52
+ UpgradeableStorage::frozen(env)
53
+ }
18
54
  }
19
55
 
20
56
  /// Trait for defining contract-specific migration logic.
@@ -22,7 +58,7 @@ pub trait Upgradeable: UpgradeableInternal {
22
58
  pub trait UpgradeableInternal {
23
59
  /// The type of data required for migration.
24
60
  /// This is the type used as the `migration_data` parameter in `Upgradeable::migrate` for this contract.
25
- type MigrationData: FromVal<Env, Val>;
61
+ type MigrationData: FromXdr;
26
62
 
27
63
  /// Internal migration logic to be implemented by the contract.
28
64
  fn __migrate(env: &Env, migration_data: &Self::MigrationData);
@@ -36,21 +72,10 @@ pub trait UpgradeableInternal {
36
72
  #[storage]
37
73
  pub enum UpgradeableStorage {
38
74
  #[instance(bool)]
39
- Migrating,
40
- }
41
-
42
- /// Upgrades the contract to new WASM bytecode and sets the migration flag.
43
- pub fn upgrade(env: &Env, new_wasm_hash: BytesN<32>) {
44
- UpgradeableStorage::set_migrating(env, &true);
45
- env.deployer().update_current_contract_wasm(new_wasm_hash);
46
- }
75
+ #[default(false)]
76
+ Frozen,
47
77
 
48
- /// Runs migration logic after an upgrade.
49
- /// Can only be called when the migration flag is set by a previous `upgrade` call.
50
- pub fn migrate<T: UpgradeableInternal>(env: &Env, migration_data: &T::MigrationData) {
51
- assert_with_error!(env, UpgradeableStorage::migrating(env).unwrap_or(false), UpgradeableError::MigrationNotAllowed);
52
- UpgradeableStorage::set_migrating(env, &false);
53
- T::__migrate(env, migration_data);
78
+ #[instance(bool)]
79
+ #[default(false)]
80
+ Migrating,
54
81
  }
55
-
56
- // TODO (hanson): review and polish this
@@ -14,9 +14,10 @@ crate-type = ["cdylib", "rlib"]
14
14
  doctest = false
15
15
 
16
16
  [dependencies]
17
- cfg-if = "1.0"
17
+ cfg-if = { workspace = true }
18
18
  soroban-sdk = { workspace = true, features = ["hazmat-crypto"] }
19
19
  worker = { workspace = true }
20
+ fee-lib-interfaces = { workspace = true }
20
21
  message-lib-common = { workspace = true }
21
22
  utils = { workspace = true }
22
23
  common-macros = { workspace = true }
@@ -24,8 +25,7 @@ endpoint-v2 = { workspace = true, features = ["library"] }
24
25
 
25
26
  [dev-dependencies]
26
27
  soroban-sdk = { workspace = true, features = ["testutils"] }
27
- insta = { workspace = true }
28
- k256 = "0.13"
29
- sha3 = "0.10"
30
- rand = "0.8"
31
- ed25519-dalek = "2"
28
+ k256 = { workspace = true }
29
+ sha3 = { workspace = true }
30
+ rand = { workspace = true }
31
+ ed25519-dalek = { workspace = true }
@@ -1,43 +1,12 @@
1
1
  use super::*;
2
+ use crate::{Sender, TransactionAuthData};
2
3
  use soroban_sdk::{
3
4
  address_payload::AddressPayload,
4
5
  auth::{Context, CustomAccountInterface},
5
- contracttype,
6
6
  crypto::Hash,
7
7
  vec, Symbol,
8
8
  };
9
9
 
10
- // ============================================================================
11
- // Authentication Data Types
12
- // ============================================================================
13
-
14
- #[contracttype]
15
- #[derive(Clone, Debug, Eq, PartialEq)]
16
- pub enum Sender {
17
- /// No explicit sender (permissionless execution).
18
- None,
19
- /// A registered admin (ed25519) submitting the transaction.
20
- /// The tuple is `(public_key, signature)` where the signature covers the Soroban payload.
21
- Admin(BytesN<32>, BytesN<64>),
22
- }
23
-
24
- /// Authentication data for DVN contract transactions.
25
- ///
26
- /// This struct is used with Soroban's custom account interface to authorize
27
- /// transactions through a combination of admin signature and multisig quorum.
28
- #[contracttype]
29
- #[derive(Clone, Debug, Eq, PartialEq)]
30
- pub struct TransactionAuthData {
31
- /// Verifier ID - must match the DVN's configured VID.
32
- pub vid: u32,
33
- /// Expiration timestamp (ledger time) after which this auth is invalid.
34
- pub expiration: u64,
35
- /// Signatures from multisig signers (secp256k1, 65 bytes each).
36
- pub signatures: Vec<BytesN<65>>,
37
- /// Entity submitting the transaction (admin, or permissionless).
38
- pub sender: Sender,
39
- }
40
-
41
10
  // ============================================================================
42
11
  // Custom Account Interface Implementation
43
12
  // ============================================================================
@@ -64,14 +33,14 @@ impl CustomAccountInterface for LzDVN {
64
33
  return Err(DvnError::AuthDataExpired);
65
34
  }
66
35
 
67
- // 2. Admin verification (quorum_change_admin bypasses this - allows quorum-only admin changes)
68
- let requires_admin = !Self::is_invoking_quorum_change_admin(&env, &auth_contexts);
36
+ // 2. Admin verification (`set_admin` bypasses this - allows quorum-only admin changes)
37
+ let requires_admin = !Self::is_invoking_worker_set_admin(&env, &auth_contexts);
69
38
  if requires_admin {
70
39
  Self::verify_admin_signature(&env, &sender, &signature_payload)?;
71
40
  }
72
41
 
73
42
  // 3. Replay protection
74
- let calls = Self::collect_contract_calls(&env, &auth_contexts)?;
43
+ let calls = Self::extract_contract_calls(&env, &auth_contexts)?;
75
44
  let hash = Self::hash_call_data(&env, vid, expiration, &calls);
76
45
  if DvnStorage::used_hash(&env, &hash) {
77
46
  return Err(DvnError::HashAlreadyUsed);
@@ -110,24 +79,25 @@ impl LzDVN {
110
79
  }
111
80
 
112
81
  /// Collects contract calls from the auth contexts.
113
- fn collect_contract_calls(env: &Env, auth_contexts: &Vec<Context>) -> Result<Vec<Call>, DvnError> {
114
- auth_contexts.iter().try_fold(vec![env], |mut calls, context| {
82
+ fn extract_contract_calls(env: &Env, auth_contexts: &Vec<Context>) -> Result<Vec<Call>, DvnError> {
83
+ let mut calls = vec![env];
84
+ for context in auth_contexts.iter() {
115
85
  let Context::Contract(ctx) = context else {
116
86
  return Err(DvnError::NonContractInvoke);
117
87
  };
118
88
  calls.push_back(Call { to: ctx.contract, func: ctx.fn_name, args: ctx.args });
119
- Ok(calls)
120
- })
89
+ }
90
+ Ok(calls)
121
91
  }
122
92
 
123
- /// Checks if the first auth context is a call to `quorum_change_admin` on this contract.
93
+ /// Checks if the first auth context is a call to `set_admin` on this contract.
124
94
  ///
125
95
  /// Used to allow quorum-only admin changes without requiring existing admin authorization.
126
- fn is_invoking_quorum_change_admin(env: &Env, auth_contexts: &Vec<Context>) -> bool {
96
+ fn is_invoking_worker_set_admin(env: &Env, auth_contexts: &Vec<Context>) -> bool {
127
97
  auth_contexts.len() == 1
128
98
  && auth_contexts.first().is_some_and(|ctx| {
129
99
  let Context::Contract(c) = ctx else { return false };
130
- c.contract == env.current_contract_address() && c.fn_name == Symbol::new(env, "quorum_change_admin")
100
+ c.contract == env.current_contract_address() && c.fn_name == Symbol::new(env, "set_admin")
131
101
  })
132
102
  }
133
103
  }
@@ -8,21 +8,20 @@
8
8
  use crate::{errors::DvnError, events::SetDstConfig, storage::DvnStorage, Call, DstConfig, DstConfigParam, IDVN};
9
9
  use common_macros::{contract_impl, lz_contract};
10
10
  use endpoint_v2::FeeRecipient;
11
+ use fee_lib_interfaces::{DvnFeeLibClient, DvnFeeParams};
11
12
  use message_lib_common::interfaces::ILayerZeroDVN;
12
13
  use soroban_sdk::{xdr::ToXdr, Address, Bytes, BytesN, Env, Vec};
13
- use utils::{
14
- buffer_writer::BufferWriter, multisig, option_ext::OptionExt, ttl_configurable, upgradeable::UpgradeableInternal,
15
- };
14
+ use utils::{buffer_writer::BufferWriter, multisig, option_ext::OptionExt};
16
15
  use worker::{
17
- assert_acl, assert_not_paused, assert_supported_message_lib, init_worker, require_admin_auth, set_admin_by_admin,
18
- set_admin_by_owner, DvnFeeLibClient, DvnFeeParams, Worker,
16
+ assert_acl, assert_not_paused, assert_supported_message_lib, errors::WorkerError, init_worker, require_admin_auth,
17
+ set_admin_by_admin, Worker,
19
18
  };
20
19
 
21
20
  /// LayerZero DVN contract.
22
21
  ///
23
22
  /// Implements multisig-based verification with custom account authorization.
24
23
  /// The contract owns itself, allowing the multisig quorum to authorize operations.
25
- #[lz_contract(multisig, upgradeable)]
24
+ #[lz_contract(multisig, upgradeable(no_migration))]
26
25
  pub struct LzDVN;
27
26
 
28
27
  // ============================================================================
@@ -55,7 +54,6 @@ impl LzDVN {
55
54
  worker_fee_lib: &Address,
56
55
  deposit_address: &Address,
57
56
  ) {
58
- ttl_configurable::init_default_ttl_configs(env);
59
57
  multisig::init_multisig(env, signers, threshold);
60
58
  init_worker::<Self>(
61
59
  env,
@@ -79,22 +77,9 @@ impl LzDVN {
79
77
  /// * `caller` - The admin calling this function (must provide authorization)
80
78
  /// * `admin` - The address to set admin status for
81
79
  /// * `active` - `true` to add admin, `false` to remove
82
- pub fn set_admin(env: &Env, caller: &Address, admin: &Address, active: bool) {
80
+ pub fn set_admin_by_admin(env: &Env, caller: &Address, admin: &Address, active: bool) {
83
81
  set_admin_by_admin::<Self>(env, caller, admin, active);
84
82
  }
85
-
86
- /// Allows the quorum to add/remove admins without requiring an admin signature.
87
- ///
88
- /// This function bypasses the normal admin verification in `__check_auth`,
89
- /// requiring only multisig quorum signatures. Must be called as a single
90
- /// operation (cannot be bundled with other calls).
91
- ///
92
- /// # Arguments
93
- /// * `admin` - The address to set admin status for
94
- /// * `active` - `true` to add admin, `false` to remove
95
- pub fn quorum_change_admin(env: &Env, admin: &Address, active: bool) {
96
- set_admin_by_owner::<Self>(env, admin, active);
97
- }
98
83
  }
99
84
 
100
85
  // ============================================================================
@@ -106,9 +91,7 @@ impl IDVN for LzDVN {
106
91
  /// Sets destination chain configurations. Requires admin authorization.
107
92
  fn set_dst_config(env: &Env, admin: &Address, params: &Vec<DstConfigParam>) {
108
93
  require_admin_auth::<Self>(env, admin);
109
- for param in params {
110
- DvnStorage::set_dst_config(env, param.dst_eid, &param.config);
111
- }
94
+ params.iter().for_each(|param| DvnStorage::set_dst_config(env, param.dst_eid, &param.config));
112
95
 
113
96
  SetDstConfig { params: params.clone() }.publish(env);
114
97
  }
@@ -120,6 +103,7 @@ impl IDVN for LzDVN {
120
103
 
121
104
  /// Returns the Verifier ID for this DVN.
122
105
  fn vid(env: &Env) -> u32 {
106
+ // VID is always set during initialization, so unwrap is safe here
123
107
  DvnStorage::vid(env).unwrap()
124
108
  }
125
109
 
@@ -156,12 +140,14 @@ impl ILayerZeroDVN for LzDVN {
156
140
  assert_acl::<Self>(env, sender);
157
141
 
158
142
  let dst_config = Self::dst_config(env, dst_eid).unwrap_or_panic(env, DvnError::EidNotSupported);
143
+ let price_feed = Self::price_feed(env).unwrap_or_panic(env, WorkerError::PriceFeedNotSet);
144
+ let worker_fee_lib = Self::worker_fee_lib(env).unwrap_or_panic(env, WorkerError::WorkerFeeLibNotSet);
159
145
  let params = DvnFeeParams {
160
146
  sender: sender.clone(),
161
147
  dst_eid,
162
148
  confirmations,
163
149
  options: options.clone(),
164
- price_feed: Self::price_feed(env),
150
+ price_feed,
165
151
  default_multiplier_bps: Self::default_multiplier_bps(env),
166
152
  quorum: Self::threshold(env),
167
153
  gas: dst_config.gas,
@@ -169,7 +155,7 @@ impl ILayerZeroDVN for LzDVN {
169
155
  floor_margin_usd: dst_config.floor_margin_usd,
170
156
  };
171
157
 
172
- DvnFeeLibClient::new(env, &Self::worker_fee_lib(env)).get_fee(&env.current_contract_address(), &params)
158
+ DvnFeeLibClient::new(env, &worker_fee_lib).get_fee(&env.current_contract_address(), &params)
173
159
  }
174
160
 
175
161
  /// Assigns a verification job to this DVN and returns fee payment info.
@@ -190,7 +176,8 @@ impl ILayerZeroDVN for LzDVN {
190
176
  assert_supported_message_lib::<Self>(env, send_lib);
191
177
 
192
178
  let fee = Self::get_fee(env, send_lib, sender, dst_eid, packet_header, payload_hash, confirmations, options);
193
- FeeRecipient { amount: fee, to: Self::deposit_address(env) }
179
+ let deposit_address = Self::deposit_address(env).unwrap_or_panic(env, WorkerError::DepositAddressNotSet);
180
+ FeeRecipient { amount: fee, to: deposit_address }
194
181
  }
195
182
  }
196
183
 
@@ -202,21 +189,9 @@ impl ILayerZeroDVN for LzDVN {
202
189
  #[contract_impl(contracttrait)]
203
190
  impl Worker for LzDVN {}
204
191
 
205
- // ============================================================================
206
- // Upgradeable Implementation
207
- // ============================================================================
208
-
209
- impl UpgradeableInternal for LzDVN {
210
- type MigrationData = ();
211
-
212
- fn __migrate(_env: &Env, _migration_data: &Self::MigrationData) {
213
- // No migration logic needed for initial upgrade capability
214
- }
215
- }
216
-
217
192
  // ============================================================================
218
193
  // Include Auth Module
219
194
  // ============================================================================
220
195
 
221
196
  #[path = "auth.rs"]
222
- pub mod auth;
197
+ mod auth;
@@ -5,7 +5,6 @@ pub enum DvnError {
5
5
  AuthDataExpired,
6
6
  EidNotSupported,
7
7
  HashAlreadyUsed,
8
- InvalidInvocation,
9
8
  InvalidVid,
10
9
  NonContractInvoke,
11
10
  OnlyAdmin,
@@ -3,6 +3,41 @@ use soroban_sdk::{contractclient, contracttype, Address, BytesN, Env, Symbol, Va
3
3
  use utils::multisig::Multisig;
4
4
  use worker::Worker;
5
5
 
6
+ // ============================================================================
7
+ // Authentication Data Types
8
+ // ============================================================================
9
+
10
+ #[contracttype]
11
+ #[derive(Clone, Debug, Eq, PartialEq)]
12
+ pub enum Sender {
13
+ /// No explicit sender (permissionless execution).
14
+ None,
15
+ /// A registered admin (ed25519) submitting the transaction.
16
+ /// The tuple is `(public_key, signature)` where the signature covers the Soroban payload.
17
+ Admin(BytesN<32>, BytesN<64>),
18
+ }
19
+
20
+ /// Authentication data for DVN contract transactions.
21
+ ///
22
+ /// This struct is used with Soroban's custom account interface to authorize
23
+ /// transactions through a combination of admin signature and multisig quorum.
24
+ #[contracttype]
25
+ #[derive(Clone, Debug, Eq, PartialEq)]
26
+ pub struct TransactionAuthData {
27
+ /// Verifier ID - must match the DVN's configured VID.
28
+ pub vid: u32,
29
+ /// Expiration timestamp (ledger time) after which this auth is invalid.
30
+ pub expiration: u64,
31
+ /// Signatures from multisig signers (secp256k1, 65 bytes each).
32
+ pub signatures: Vec<BytesN<65>>,
33
+ /// Entity submitting the transaction (admin, or permissionless).
34
+ pub sender: Sender,
35
+ }
36
+
37
+ // ============================================================================
38
+ // Destination Configuration Types
39
+ // ============================================================================
40
+
6
41
  /// Configuration for a destination chain.
7
42
  ///
8
43
  /// Contains fee calculation parameters specific to each destination endpoint.
@@ -1,9 +1,10 @@
1
1
  #![no_std]
2
2
 
3
- pub mod errors;
3
+ mod errors;
4
4
  pub mod events;
5
- pub mod interfaces;
5
+ mod interfaces;
6
6
 
7
+ pub use errors::*;
7
8
  pub use interfaces::*;
8
9
 
9
10
  cfg_if::cfg_if! {
@@ -11,7 +12,7 @@ cfg_if::cfg_if! {
11
12
  mod storage;
12
13
  mod dvn;
13
14
 
14
- pub use dvn::*;
15
+ pub use dvn::{LzDVN, LzDVNClient};
15
16
  }
16
17
  }
17
18
 
@@ -1,7 +1,7 @@
1
1
  use crate::{
2
- dvn::auth::{Sender, TransactionAuthData},
3
2
  errors::DvnError,
4
3
  tests::setup::{TestSetup, VID},
4
+ Sender, TransactionAuthData,
5
5
  };
6
6
  use ed25519_dalek::{Signer, SigningKey};
7
7
  use rand::thread_rng;
@@ -1,12 +1,13 @@
1
1
  use crate::{dvn::LzDVN, tests::setup::TestSetup, DVNClient, DstConfig, DstConfigParam, IDVN};
2
2
  use endpoint_v2::FeeRecipient;
3
+ use fee_lib_interfaces::{DvnFeeParams, IDvnFeeLib};
3
4
  use message_lib_common::interfaces::ILayerZeroDVN;
4
5
  use soroban_sdk::{
5
6
  contract, contractimpl,
6
7
  testutils::{Address as _, AuthorizedFunction},
7
8
  vec, Address, Bytes, BytesN, Env, IntoVal, Symbol,
8
9
  };
9
- use worker::{DvnFeeParams, IDvnFeeLib, Worker};
10
+ use worker::Worker;
10
11
 
11
12
  fn with_contract<F, R>(setup: &TestSetup, f: F) -> R
12
13
  where
@@ -73,7 +74,7 @@ fn test_get_fee_missing_dst_config_panics() {
73
74
  }
74
75
 
75
76
  #[test]
76
- #[should_panic(expected = "Error(Contract, #1209)")] // WorkerError::NotAllowed
77
+ #[should_panic(expected = "Error(Contract, #1207)")] // WorkerError::NotAllowed
77
78
  fn test_get_fee_not_allowed_due_to_allowlist() {
78
79
  let setup = TestSetup::new(1);
79
80
  let allowed = new_addr(&setup.env);
@@ -166,7 +167,7 @@ fn test_pause_and_setters_happy_paths() {
166
167
  LzDVN::set_deposit_address(&setup.env, &admin, &other);
167
168
  });
168
169
  with_contract(&setup, || {
169
- assert_eq!(LzDVN::deposit_address(&setup.env), other);
170
+ assert_eq!(LzDVN::deposit_address(&setup.env), Some(other));
170
171
  });
171
172
 
172
173
  let pf = new_addr(&setup.env);
@@ -174,12 +175,12 @@ fn test_pause_and_setters_happy_paths() {
174
175
  LzDVN::set_price_feed(&setup.env, &admin, &pf);
175
176
  });
176
177
  with_contract(&setup, || {
177
- assert_eq!(LzDVN::price_feed(&setup.env), pf);
178
+ assert_eq!(LzDVN::price_feed(&setup.env), Some(pf));
178
179
  });
179
180
 
180
181
  let opts = Bytes::from_array(&setup.env, &[1, 2, 3]);
181
182
  with_contract(&setup, || {
182
- LzDVN::set_supported_option_types(&setup.env, &admin, 77, opts.clone());
183
+ LzDVN::set_supported_option_types(&setup.env, &admin, 77, &opts);
183
184
  });
184
185
  with_contract(&setup, || {
185
186
  assert_eq!(LzDVN::get_supported_option_types(&setup.env, 77), Some(opts));
@@ -190,7 +191,7 @@ fn test_pause_and_setters_happy_paths() {
190
191
  LzDVN::set_worker_fee_lib(&setup.env, &admin, &fee_lib);
191
192
  });
192
193
  with_contract(&setup, || {
193
- assert_eq!(LzDVN::worker_fee_lib(&setup.env), fee_lib);
194
+ assert_eq!(LzDVN::worker_fee_lib(&setup.env), Some(fee_lib));
194
195
  });
195
196
  }
196
197
 
@@ -278,7 +279,7 @@ fn test_set_admin_add() {
278
279
 
279
280
  // Add new admin by existing admin
280
281
  with_contract(&setup, || {
281
- LzDVN::set_admin(&setup.env, &existing_admin, &new_admin, true);
282
+ LzDVN::set_admin_by_admin(&setup.env, &existing_admin, &new_admin, true);
282
283
  });
283
284
 
284
285
  // Verify new_admin is now an admin
@@ -294,12 +295,12 @@ fn test_set_admin_remove() {
294
295
 
295
296
  // Add new admin first
296
297
  with_contract(&setup, || {
297
- LzDVN::set_admin(&setup.env, &existing_admin, &new_admin, true);
298
+ LzDVN::set_admin_by_admin(&setup.env, &existing_admin, &new_admin, true);
298
299
  });
299
300
 
300
301
  // Remove the new admin
301
302
  with_contract(&setup, || {
302
- LzDVN::set_admin(&setup.env, &existing_admin, &new_admin, false);
303
+ LzDVN::set_admin_by_admin(&setup.env, &existing_admin, &new_admin, false);
303
304
  });
304
305
 
305
306
  // Verify new_admin is no longer an admin
@@ -308,7 +309,7 @@ fn test_set_admin_remove() {
308
309
  }
309
310
 
310
311
  #[test]
311
- #[should_panic(expected = "Error(Contract, #1215)")] // WorkerError::Unauthorized
312
+ #[should_panic(expected = "Error(Contract, #1212)")] // WorkerError::Unauthorized
312
313
  fn test_set_admin_unauthorized() {
313
314
  let setup = TestSetup::new(1);
314
315
  let non_admin = new_addr(&setup.env);
@@ -316,20 +317,23 @@ fn test_set_admin_unauthorized() {
316
317
 
317
318
  // Attempt to add admin by non-admin should fail
318
319
  with_contract(&setup, || {
319
- LzDVN::set_admin(&setup.env, &non_admin, &new_admin, true);
320
+ LzDVN::set_admin_by_admin(&setup.env, &non_admin, &new_admin, true);
320
321
  });
321
322
  }
322
323
 
323
324
  #[test]
324
- #[should_panic(expected = "Error(Contract, #1204)")] // WorkerError::AttemptingToRemoveOnlyAdmin
325
- fn test_set_admin_cannot_remove_last_admin() {
325
+ fn test_set_admin_remove_last_admin() {
326
326
  let setup = TestSetup::new(1);
327
327
  let existing_admin = setup.admins.get(0).unwrap();
328
328
 
329
- // Attempt to remove the only admin should fail
329
+ // Removing the only admin is now allowed
330
330
  with_contract(&setup, || {
331
- LzDVN::set_admin(&setup.env, &existing_admin, &existing_admin, false);
331
+ LzDVN::set_admin_by_admin(&setup.env, &existing_admin, &existing_admin, false);
332
332
  });
333
+
334
+ // Verify admin is no longer an admin
335
+ let is_admin = with_contract(&setup, || LzDVN::is_admin(&setup.env, &existing_admin));
336
+ assert!(!is_admin);
333
337
  }
334
338
 
335
339
  #[contract]
@@ -13,10 +13,8 @@ fn random_signer(env: &Env) -> BytesN<20> {
13
13
  }
14
14
 
15
15
  fn register_dvn(env: &Env, signer_count: usize, threshold: u32) {
16
- let signers: Vec<BytesN<20>> = (0..signer_count).map(|_| random_signer(env)).fold(vec![env], |mut acc, s| {
17
- acc.push_back(s);
18
- acc
19
- });
16
+ let mut signers: Vec<BytesN<20>> = vec![env];
17
+ (0..signer_count).map(|_| random_signer(env)).for_each(|s| signers.push_back(s));
20
18
  let admins: Vec<Address> = vec![env, Address::generate(env)];
21
19
  let supported_msglibs: Vec<Address> = vec![env, Address::generate(env)];
22
20
  let price_feed: Address = Address::generate(env);
@@ -17,9 +17,7 @@ fn sorted_signatures(setup: &TestSetup, digest: &BytesN<32>) -> Vec<BytesN<65>>
17
17
  setup.key_pairs.iter().map(|kp| (kp.eth_address, kp.sign_bytes(&setup.env, digest))).collect();
18
18
  pairs.sort_by(|a, b| a.0.cmp(&b.0));
19
19
  let mut result: Vec<BytesN<65>> = vec![&setup.env];
20
- for (_, sig) in pairs {
21
- result.push_back(sig);
22
- }
20
+ pairs.into_iter().for_each(|(_, sig)| result.push_back(sig));
23
21
  result
24
22
  }
25
23