@layerzerolabs/protocol-stellar-v2 0.2.15 → 0.2.18

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 (257) hide show
  1. package/.turbo/turbo-build.log +350 -309
  2. package/.turbo/turbo-lint.log +146 -108
  3. package/.turbo/turbo-test.log +1423 -1238
  4. package/Cargo.lock +12 -0
  5. package/Cargo.toml +3 -0
  6. package/contracts/ERROR_SPEC.md +44 -0
  7. package/contracts/common-macros/src/auth.rs +113 -0
  8. package/contracts/common-macros/src/contract_ttl.rs +84 -0
  9. package/contracts/common-macros/src/lib.rs +181 -30
  10. package/contracts/common-macros/src/lz_contract.rs +83 -0
  11. package/contracts/common-macros/src/tests/{ownable.rs → auth.rs} +48 -15
  12. package/contracts/common-macros/src/tests/contract_ttl.rs +662 -0
  13. package/contracts/common-macros/src/tests/mod.rs +2 -2
  14. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_multisig_code.snap +20 -0
  15. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_ownable_code.snap +24 -0
  16. package/contracts/common-macros/src/tests/snapshots/{common_macros__tests__ownable__snapshot_only_owner_preserves_function_signature.snap → common_macros__tests__auth__snapshot_only_auth_preserves_function_signature.snap} +4 -4
  17. package/contracts/common-macros/src/tests/snapshots/{common_macros__tests__contract_impl__snapshot_generated_contract_impl_code.snap → common_macros__tests__contract_ttl__snapshot_generated_contractimpl_code.snap} +3 -3
  18. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__contract_ttl__snapshot_generated_contracttrait_code.snap +69 -0
  19. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +7 -21
  20. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__upgradeable__snapshot_generated_upgradeable_code.snap +2 -2
  21. package/contracts/common-macros/src/ttl_configurable.rs +19 -34
  22. package/contracts/common-macros/src/ttl_extendable.rs +36 -0
  23. package/contracts/common-macros/src/upgradeable.rs +5 -5
  24. package/contracts/common-macros/src/utils.rs +9 -0
  25. package/contracts/endpoint-v2/src/constants.rs +4 -4
  26. package/contracts/endpoint-v2/src/endpoint_v2.rs +38 -40
  27. package/contracts/endpoint-v2/src/errors.rs +4 -3
  28. package/contracts/endpoint-v2/src/events.rs +1 -1
  29. package/contracts/endpoint-v2/src/message_lib_manager.rs +18 -5
  30. package/contracts/endpoint-v2/src/messaging_channel.rs +11 -1
  31. package/contracts/endpoint-v2/src/messaging_composer.rs +11 -1
  32. package/contracts/endpoint-v2/src/storage.rs +1 -1
  33. package/contracts/endpoint-v2/src/tests/endpoint_v2/pay_messaging_fees.rs +3 -3
  34. package/contracts/endpoint-v2/src/tests/endpoint_v2/quote.rs +1 -1
  35. package/contracts/endpoint-v2/src/tests/endpoint_v2/require_oapp_auth.rs +2 -2
  36. package/contracts/endpoint-v2/src/tests/endpoint_v2/send.rs +3 -3
  37. package/contracts/endpoint-v2/src/tests/endpoint_v2/set_zro.rs +4 -4
  38. package/contracts/endpoint-v2/src/tests/message_lib_manager/require_receive_lib_for_eid.rs +3 -3
  39. package/contracts/endpoint-v2/src/tests/message_lib_manager/require_registered.rs +1 -1
  40. package/contracts/endpoint-v2/src/tests/message_lib_manager/require_send_lib_for_eid.rs +3 -3
  41. package/contracts/endpoint-v2/src/tests/message_lib_manager/require_supported_eid.rs +1 -1
  42. package/contracts/endpoint-v2/src/tests/messaging_channel/clear_payload.rs +4 -4
  43. package/contracts/endpoint-v2/src/tests/messaging_channel/inbound.rs +1 -1
  44. package/contracts/layerzero-views/src/layerzero_view.rs +3 -6
  45. package/contracts/macro-integration-tests/tests/runtime/ownable/mod.rs +2 -2
  46. package/contracts/macro-integration-tests/tests/runtime/ownable/{only_owner_guard.rs → only_auth_guard.rs} +1 -1
  47. package/contracts/macro-integration-tests/tests/runtime/ttl_configurable/configuration.rs +1 -1
  48. package/contracts/macro-integration-tests/tests/runtime/ttl_configurable/freeze.rs +1 -1
  49. package/contracts/macro-integration-tests/tests/runtime/ttl_configurable/mod.rs +0 -1
  50. package/contracts/macro-integration-tests/tests/ui/ownable/fail/{only_owner_missing_env.rs → only_auth_missing_env.rs} +3 -3
  51. package/contracts/macro-integration-tests/tests/ui/ownable/fail/{only_owner_missing_env.stderr → only_auth_missing_env.stderr} +4 -4
  52. package/contracts/macro-integration-tests/tests/ui/ownable/pass/namespacing_and_imports.rs +2 -3
  53. package/contracts/macro-integration-tests/tests/ui/ownable/pass/{only_owner_env_param_variants.rs → only_auth_env_param_variants.rs} +9 -9
  54. package/contracts/macro-integration-tests/tests/ui/ttl_configurable/pass/minimal_contract.rs +6 -6
  55. package/contracts/message-libs/message-lib-common/src/errors.rs +7 -2
  56. package/contracts/message-libs/message-lib-common/src/tests/packet_codec_v1/decode_packet_header.rs +3 -3
  57. package/contracts/message-libs/message-lib-common/src/tests/worker_options/append_lz_receive_option.rs +1 -2
  58. package/contracts/message-libs/message-lib-common/src/tests/worker_options/append_native_drop_option.rs +1 -2
  59. package/contracts/message-libs/message-lib-common/src/tests/worker_options/convert_legacy_options.rs +9 -9
  60. package/contracts/message-libs/message-lib-common/src/tests/worker_options/extract_type_3_options.rs +1 -1
  61. package/contracts/message-libs/message-lib-common/src/tests/worker_options/left_pad_to_bytes32.rs +1 -1
  62. package/contracts/message-libs/message-lib-common/src/tests/worker_options/split_worker_options.rs +2 -2
  63. package/contracts/message-libs/simple-message-lib/src/simple_message_lib.rs +7 -9
  64. package/contracts/message-libs/treasury/src/errors.rs +2 -2
  65. package/contracts/message-libs/treasury/src/events.rs +1 -1
  66. package/contracts/message-libs/treasury/src/interfaces/zro_fee_lib.rs +2 -2
  67. package/contracts/message-libs/treasury/src/storage.rs +1 -1
  68. package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +1 -1
  69. package/contracts/message-libs/treasury/src/treasury.rs +14 -16
  70. package/contracts/message-libs/uln-302/src/receive_uln.rs +13 -2
  71. package/contracts/message-libs/uln-302/src/send_uln.rs +23 -3
  72. package/contracts/message-libs/uln-302/src/uln302.rs +6 -24
  73. package/contracts/oapps/counter/Cargo.toml +14 -1
  74. package/contracts/oapps/counter/integration_tests/mod.rs +4 -1
  75. package/contracts/oapps/counter/integration_tests/{setup.rs → setup_sml.rs} +48 -80
  76. package/contracts/oapps/counter/integration_tests/setup_uln.rs +997 -0
  77. package/contracts/oapps/counter/integration_tests/signing.rs +62 -0
  78. package/contracts/oapps/counter/integration_tests/test_with_sml.rs +24 -55
  79. package/contracts/oapps/counter/integration_tests/test_with_uln.rs +314 -0
  80. package/contracts/oapps/counter/integration_tests/utils.rs +196 -53
  81. package/contracts/oapps/counter/src/counter.rs +67 -43
  82. package/contracts/oapps/counter/src/tests/mod.rs +0 -13
  83. package/contracts/oapps/counter/src/tests/test_counter.rs +5 -7
  84. package/contracts/oapps/oapp/src/errors.rs +5 -1
  85. package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +93 -78
  86. package/contracts/oapps/oapp/src/oapp_core.rs +36 -21
  87. package/contracts/oapps/oapp/src/oapp_options_type3.rs +48 -12
  88. package/contracts/oapps/oapp/src/oapp_receiver.rs +106 -41
  89. package/contracts/oapps/oapp/src/oapp_sender.rs +26 -34
  90. package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +9 -8
  91. package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +25 -17
  92. package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +7 -7
  93. package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +14 -15
  94. package/contracts/oapps/oapp-macros/src/generators.rs +128 -0
  95. package/contracts/oapps/oapp-macros/src/lib.rs +113 -56
  96. package/contracts/oapps/oft/integration-tests/setup.rs +25 -7
  97. package/contracts/oapps/oft/src/errors.rs +6 -1
  98. package/contracts/oapps/oft/src/extensions/oft_fee.rs +8 -8
  99. package/contracts/oapps/oft/src/extensions/pausable.rs +4 -4
  100. package/contracts/oapps/oft/src/extensions/rate_limiter.rs +5 -5
  101. package/contracts/oapps/oft/src/lib.rs +4 -2
  102. package/contracts/oapps/oft/src/oft.rs +24 -64
  103. package/contracts/oapps/oft/src/oft_impl.rs +201 -0
  104. package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +1 -3
  105. package/contracts/oapps/oft/src/oft_types/mint_burn.rs +1 -4
  106. package/contracts/oapps/oft/src/storage.rs +2 -0
  107. package/contracts/oapps/oft/src/tests/extensions/setup.rs +36 -22
  108. package/contracts/oapps/oft/src/tests/extensions/test_oft_fee.rs +5 -3
  109. package/contracts/oapps/oft/src/tests/extensions/test_pausable.rs +5 -3
  110. package/contracts/oapps/oft/src/tests/extensions/test_rate_limiter.rs +5 -3
  111. package/contracts/oapps/oft/src/tests/test_decimals.rs +2 -2
  112. package/contracts/oapps/oft/src/tests/test_oft_msg_codec.rs +1 -2
  113. package/contracts/oapps/oft/src/tests/test_utils.rs +45 -23
  114. package/contracts/oapps/oft/src/types.rs +20 -0
  115. package/contracts/oapps/oft-std/integration-tests/setup.rs +4 -2
  116. package/contracts/oapps/oft-std/src/oft.rs +24 -6
  117. package/contracts/upgrader/src/lib.rs +4 -4
  118. package/contracts/utils/src/auth.rs +44 -0
  119. package/contracts/utils/src/errors.rs +27 -5
  120. package/contracts/utils/src/lib.rs +3 -0
  121. package/contracts/utils/src/multisig.rs +211 -0
  122. package/contracts/utils/src/ownable.rs +12 -10
  123. package/contracts/utils/src/tests/buffer_reader.rs +6 -6
  124. package/contracts/utils/src/tests/buffer_writer.rs +6 -6
  125. package/contracts/utils/src/tests/bytes_ext.rs +2 -4
  126. package/contracts/utils/src/tests/mod.rs +1 -0
  127. package/contracts/utils/src/tests/multisig.rs +731 -0
  128. package/contracts/utils/src/tests/option_ext.rs +2 -5
  129. package/contracts/utils/src/tests/ownable.rs +16 -5
  130. package/contracts/utils/src/tests/ttl_configurable.rs +27 -16
  131. package/contracts/utils/src/tests/upgradeable.rs +4 -2
  132. package/contracts/utils/src/ttl_configurable.rs +23 -8
  133. package/contracts/utils/src/ttl_extendable.rs +27 -0
  134. package/contracts/utils/src/upgradeable.rs +2 -0
  135. package/contracts/workers/dvn/Cargo.toml +1 -1
  136. package/contracts/workers/dvn/src/auth.rs +7 -7
  137. package/contracts/workers/dvn/src/dvn.rs +10 -38
  138. package/contracts/workers/dvn/src/errors.rs +0 -7
  139. package/contracts/workers/dvn/src/events.rs +1 -14
  140. package/contracts/workers/dvn/src/interfaces/dvn.rs +2 -2
  141. package/contracts/workers/dvn/src/interfaces/mod.rs +0 -2
  142. package/contracts/workers/dvn/src/storage.rs +3 -13
  143. package/contracts/workers/dvn/src/tests/auth.rs +4 -4
  144. package/contracts/workers/dvn/src/tests/dvn.rs +1 -2
  145. package/contracts/workers/dvn/src/tests/multisig/set_signer.rs +7 -8
  146. package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +11 -8
  147. package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +11 -12
  148. package/contracts/workers/dvn/src/tests/setup.rs +5 -5
  149. package/contracts/workers/dvn-fee-lib/Cargo.toml +1 -1
  150. package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +3 -6
  151. package/contracts/workers/executor/src/auth.rs +80 -16
  152. package/contracts/workers/executor/src/executor.rs +5 -31
  153. package/contracts/workers/executor/src/storage.rs +2 -9
  154. package/contracts/workers/executor-fee-lib/Cargo.toml +1 -1
  155. package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +3 -6
  156. package/contracts/workers/executor-helper/Cargo.toml +1 -1
  157. package/contracts/workers/executor-helper/src/executor_helper.rs +53 -73
  158. package/contracts/workers/price-feed/Cargo.toml +1 -1
  159. package/contracts/workers/price-feed/src/price_feed.rs +7 -10
  160. package/contracts/workers/worker/src/errors.rs +4 -0
  161. package/contracts/workers/worker/src/tests/worker.rs +7 -6
  162. package/contracts/workers/worker/src/worker.rs +20 -16
  163. package/package.json +8 -5
  164. package/sdk/.turbo/turbo-build.log +1 -0
  165. package/sdk/.turbo/turbo-test.log +1009 -0
  166. package/sdk/dist/generated/bml.d.ts +65 -8
  167. package/sdk/dist/generated/bml.js +70 -34
  168. package/sdk/dist/generated/counter.d.ts +167 -42
  169. package/sdk/dist/generated/counter.js +86 -45
  170. package/sdk/dist/generated/dvn.d.ts +282 -229
  171. package/sdk/dist/generated/dvn.js +119 -81
  172. package/sdk/dist/generated/dvn_fee_lib.d.ts +142 -67
  173. package/sdk/dist/generated/dvn_fee_lib.js +64 -24
  174. package/sdk/dist/generated/endpoint.d.ts +97 -22
  175. package/sdk/dist/generated/endpoint.js +75 -37
  176. package/sdk/dist/generated/executor.d.ts +117 -85
  177. package/sdk/dist/generated/executor.js +102 -59
  178. package/sdk/dist/generated/executor_fee_lib.d.ts +162 -78
  179. package/sdk/dist/generated/executor_fee_lib.js +104 -57
  180. package/sdk/dist/generated/executor_helper.d.ts +133 -21
  181. package/sdk/dist/generated/executor_helper.js +99 -50
  182. package/sdk/dist/generated/oft_std.d.ts +233 -55
  183. package/sdk/dist/generated/oft_std.js +99 -54
  184. package/sdk/dist/generated/price_feed.d.ts +142 -67
  185. package/sdk/dist/generated/price_feed.js +64 -24
  186. package/sdk/dist/generated/sml.d.ts +113 -32
  187. package/sdk/dist/generated/sml.js +93 -49
  188. package/sdk/dist/generated/treasury.d.ts +896 -0
  189. package/sdk/dist/generated/treasury.js +219 -0
  190. package/sdk/dist/generated/uln302.d.ts +113 -32
  191. package/sdk/dist/generated/uln302.js +93 -49
  192. package/sdk/dist/generated/upgrader.d.ts +2 -2
  193. package/sdk/dist/generated/upgrader.js +1 -1
  194. package/sdk/dist/index.d.ts +2 -0
  195. package/sdk/dist/index.js +3 -0
  196. package/sdk/dist/wasm/blocked-message-lib.d.ts +1 -0
  197. package/sdk/dist/wasm/blocked-message-lib.js +2 -0
  198. package/sdk/dist/wasm/counter.d.ts +1 -0
  199. package/sdk/dist/wasm/counter.js +2 -0
  200. package/sdk/dist/wasm/dvn-fee-lib.d.ts +1 -0
  201. package/sdk/dist/wasm/dvn-fee-lib.js +2 -0
  202. package/sdk/dist/wasm/dvn.d.ts +1 -0
  203. package/sdk/dist/wasm/dvn.js +2 -0
  204. package/sdk/dist/wasm/endpoint-v2.d.ts +1 -0
  205. package/sdk/dist/wasm/endpoint-v2.js +2 -0
  206. package/sdk/dist/wasm/executor-fee-lib.d.ts +1 -0
  207. package/sdk/dist/wasm/executor-fee-lib.js +2 -0
  208. package/sdk/dist/wasm/executor-helper.d.ts +1 -0
  209. package/sdk/dist/wasm/executor-helper.js +2 -0
  210. package/sdk/dist/wasm/executor.d.ts +1 -0
  211. package/sdk/dist/wasm/executor.js +2 -0
  212. package/sdk/dist/wasm/layerzero-views.d.ts +1 -0
  213. package/sdk/dist/wasm/layerzero-views.js +2 -0
  214. package/sdk/dist/wasm/oft-std.d.ts +1 -0
  215. package/sdk/dist/wasm/oft-std.js +2 -0
  216. package/sdk/dist/wasm/price-feed.d.ts +1 -0
  217. package/sdk/dist/wasm/price-feed.js +2 -0
  218. package/sdk/dist/wasm/simple-message-lib.d.ts +1 -0
  219. package/sdk/dist/wasm/simple-message-lib.js +2 -0
  220. package/sdk/dist/wasm/treasury.d.ts +1 -0
  221. package/sdk/dist/wasm/treasury.js +2 -0
  222. package/sdk/dist/wasm/uln302.d.ts +1 -0
  223. package/sdk/dist/wasm/uln302.js +2 -0
  224. package/sdk/dist/wasm/upgrader.d.ts +1 -0
  225. package/sdk/dist/wasm/upgrader.js +2 -0
  226. package/sdk/dist/wasm.d.ts +15 -0
  227. package/sdk/dist/wasm.js +15 -0
  228. package/sdk/package.json +4 -2
  229. package/sdk/src/index.ts +4 -0
  230. package/sdk/test/counter-sml.test.ts +376 -0
  231. package/sdk/test/counter-uln.test.ts +493 -0
  232. package/sdk/test/{oft.test.ts → oft-sml.test.ts} +185 -310
  233. package/sdk/test/suites/constants.ts +22 -2
  234. package/sdk/test/suites/globalSetup.ts +450 -0
  235. package/sdk/test/suites/localnet.ts +23 -6
  236. package/sdk/test/upgrader.test.ts +7 -16
  237. package/sdk/test/utils.ts +558 -85
  238. package/sdk/vitest.config.ts +21 -0
  239. package/tools/ts-bindings-gen/src/main.rs +1 -0
  240. package/turbo.json +2 -0
  241. package/contracts/common-macros/src/contract_impl.rs +0 -52
  242. package/contracts/common-macros/src/ownable.rs +0 -41
  243. package/contracts/common-macros/src/tests/contract_impl.rs +0 -386
  244. package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_generated_ownable_code.snap +0 -12
  245. package/contracts/macro-integration-tests/tests/runtime/ttl_configurable/extend_instance_ttl.rs +0 -50
  246. package/contracts/oapps/oapp-macros/src/oapp_core.rs +0 -41
  247. package/contracts/oapps/oapp-macros/src/oapp_full.rs +0 -21
  248. package/contracts/oapps/oapp-macros/src/oapp_options_type3.rs +0 -31
  249. package/contracts/oapps/oapp-macros/src/oapp_receiver.rs +0 -48
  250. package/contracts/oapps/oapp-macros/src/oapp_sender.rs +0 -21
  251. package/contracts/oapps/oapp-macros/src/util.rs +0 -107
  252. package/contracts/oapps/oft/src/constants.rs +0 -5
  253. package/contracts/oapps/oft/src/default_oft_impl.rs +0 -152
  254. package/contracts/workers/dvn/src/interfaces/multisig.rs +0 -56
  255. package/contracts/workers/dvn/src/multisig.rs +0 -157
  256. package/sdk/test/index.test.ts +0 -375
  257. /package/sdk/test/suites/{testUpgradeable.ts → dummyContractClient.ts} +0 -0
@@ -2,17 +2,19 @@
2
2
  //!
3
3
  //! This module provides common test contracts and helpers used across multiple test files.
4
4
 
5
- use crate::codec::oft_msg_codec::OFTMessage;
6
- use crate::oft::OFTClient;
7
- use crate::types::{OFTReceipt, SendParam};
5
+ use crate::{
6
+ codec::oft_msg_codec::OFTMessage,
7
+ oft::OFTClient,
8
+ types::{OFTReceipt, SendParam},
9
+ };
8
10
  use endpoint_v2::{LayerZeroReceiverClient, MessagingFee, MessagingParams, MessagingReceipt, Origin};
9
11
  use oapp::oapp_core::OAppCoreClient;
10
- use soroban_sdk::{address_payload::AddressPayload, log, String};
11
12
  use soroban_sdk::{
12
- bytes, contract, contractimpl, symbol_short,
13
+ address_payload::AddressPayload,
14
+ bytes, contract, contractimpl, log, symbol_short,
13
15
  testutils::{Address as _, MockAuth, MockAuthInvoke},
14
16
  token::{StellarAssetClient, TokenClient},
15
- Address, Bytes, BytesN, Env, IntoVal, Symbol,
17
+ Address, Bytes, BytesN, Env, IntoVal, String, Symbol,
16
18
  };
17
19
  use stellar_macros::default_impl;
18
20
  use stellar_tokens::fungible::{Base, FungibleToken};
@@ -104,9 +106,13 @@ pub fn create_origin(src_eid: u32, sender: &BytesN<32>, nonce: u64) -> Origin {
104
106
  mod test_mint_burn_oft {
105
107
  extern crate self as oft;
106
108
 
107
- use crate::oft::{oft_initialize, OFTInternal, OFT};
109
+ use crate::initialize_oft;
110
+ use crate::oft::{OFTInternal, OFT};
111
+ use crate::oft_impl;
108
112
  use crate::types::OFTReceipt;
109
- use soroban_sdk::{contractimpl, Address, Env};
113
+ use endpoint_v2::Origin;
114
+ use oapp::oapp_receiver::LzReceiveInternal;
115
+ use soroban_sdk::{contractimpl, Address, Bytes, BytesN, Env};
110
116
 
111
117
  #[oapp_macros::oapp]
112
118
  pub struct TestMintBurnOFT;
@@ -121,13 +127,27 @@ mod test_mint_burn_oft {
121
127
  delegate: &Option<Address>,
122
128
  shared_decimals: u32,
123
129
  ) {
124
- oft_initialize::<Self>(env, owner, token, endpoint, delegate, shared_decimals)
130
+ initialize_oft::<Self>(env, owner, token, endpoint, delegate, shared_decimals)
125
131
  }
126
132
  }
127
133
 
128
134
  #[contractimpl(contracttrait)]
129
135
  impl OFT for TestMintBurnOFT {}
130
136
 
137
+ impl LzReceiveInternal for TestMintBurnOFT {
138
+ fn __lz_receive(
139
+ env: &Env,
140
+ origin: &Origin,
141
+ guid: &BytesN<32>,
142
+ message: &Bytes,
143
+ extra_data: &Bytes,
144
+ executor: &Address,
145
+ value: i128,
146
+ ) {
147
+ oft_impl::lz_receive::<Self>(env, executor, origin, guid, message, extra_data, value)
148
+ }
149
+ }
150
+
131
151
  impl OFTInternal for TestMintBurnOFT {
132
152
  fn __debit(env: &Env, sender: &Address, amount_ld: i128, min_amount_ld: i128, dst_eid: u32) -> OFTReceipt {
133
153
  crate::oft_types::mint_burn::debit::<Self>(env, sender, amount_ld, min_amount_ld, dst_eid)
@@ -143,15 +163,15 @@ pub use test_mint_burn_oft::TestMintBurnOFT;
143
163
  mod test_lock_unlock_oft {
144
164
  extern crate self as oft;
145
165
 
146
- use crate::oft::{oft_initialize, OFTInternal, OFT};
166
+ use crate::initialize_oft;
167
+ use crate::oft::{OFTInternal, OFT};
168
+ use crate::oft_impl;
147
169
  use crate::types::OFTReceipt;
148
170
  use endpoint_v2::Origin;
149
- use oapp::oapp_receiver::OAppReceiver;
150
- use oapp_macros::oapp_manual_impl;
171
+ use oapp::oapp_receiver::{LzReceiveInternal, OAppReceiver};
151
172
  use soroban_sdk::{contractimpl, Address, Bytes, BytesN, Env};
152
173
 
153
- #[oapp_macros::oapp]
154
- #[oapp_manual_impl(receiver)]
174
+ #[oapp_macros::oapp(custom = [receiver])]
155
175
  pub struct TestLockUnlockOFT;
156
176
 
157
177
  #[contractimpl]
@@ -164,29 +184,31 @@ mod test_lock_unlock_oft {
164
184
  delegate: &Option<Address>,
165
185
  shared_decimals: u32,
166
186
  ) {
167
- oft_initialize::<Self>(env, owner, token, endpoint, delegate, shared_decimals)
187
+ initialize_oft::<Self>(env, owner, token, endpoint, delegate, shared_decimals)
168
188
  }
169
189
  }
170
190
 
171
191
  #[contractimpl(contracttrait)]
172
192
  impl OFT for TestLockUnlockOFT {}
173
193
 
174
- #[contractimpl(contracttrait)]
175
- impl OAppReceiver for TestLockUnlockOFT {
176
- fn lz_receive(
194
+ impl LzReceiveInternal for TestLockUnlockOFT {
195
+ fn __lz_receive(
177
196
  env: &Env,
178
- executor: &Address,
179
197
  origin: &Origin,
180
198
  guid: &BytesN<32>,
181
199
  message: &Bytes,
182
200
  extra_data: &Bytes,
201
+ executor: &Address,
183
202
  value: i128,
184
203
  ) {
185
- oapp::oapp_receiver::verify_and_clear_payload::<Self>(env, executor, origin, guid, message, value);
186
- Self::__lz_receive(env, executor, origin, guid, message, extra_data, value);
204
+ oft_impl::lz_receive::<Self>(env, executor, origin, guid, message, extra_data, value)
187
205
  }
188
206
  }
189
207
 
208
+ // Custom receiver to demonstrate overriding next_nonce or other methods
209
+ #[contractimpl(contracttrait)]
210
+ impl OAppReceiver for TestLockUnlockOFT {}
211
+
190
212
  impl OFTInternal for TestLockUnlockOFT {
191
213
  fn __debit(env: &Env, sender: &Address, amount_ld: i128, min_amount_ld: i128, dst_eid: u32) -> OFTReceipt {
192
214
  crate::oft_types::lock_unlock::debit::<Self>(env, sender, amount_ld, min_amount_ld, dst_eid)
@@ -265,12 +287,12 @@ impl MockEndpointWithCompose {
265
287
  env.storage().instance().set(&symbol_short!("zro"), &zro_token);
266
288
  }
267
289
 
268
- /// Returns the native token address (required by OAppSender)
290
+ /// Returns the native token address (required by OAppSenderInternal)
269
291
  pub fn native_token(env: Env) -> Address {
270
292
  env.storage().instance().get(&symbol_short!("ntk")).unwrap()
271
293
  }
272
294
 
273
- /// Returns the ZRO token address (required by OAppSender)
295
+ /// Returns the ZRO token address (required by OAppSenderInternal)
274
296
  pub fn zro(env: Env) -> Option<Address> {
275
297
  env.storage().instance().get(&symbol_short!("zro"))
276
298
  }
@@ -1,15 +1,28 @@
1
1
  use soroban_sdk::{contracttype, Bytes, BytesN};
2
2
 
3
+ /// Message type for simple OFT send
4
+ pub const SEND: u32 = 1;
5
+
6
+ /// Message type for OFT send with compose functionality
7
+ pub const SEND_AND_CALL: u32 = 2;
8
+
3
9
  /// Parameters for sending OFT tokens cross-chain
4
10
  #[contracttype]
5
11
  #[derive(Clone, PartialEq, Eq, Debug)]
6
12
  pub struct SendParam {
13
+ /// The destination endpoint ID
7
14
  pub dst_eid: u32,
15
+ /// The recipient address on the destination chain (32 bytes)
8
16
  pub to: BytesN<32>,
17
+ /// The amount to send in local decimals
9
18
  pub amount_ld: i128,
19
+ /// The minimum amount to receive in local decimals (slippage protection)
10
20
  pub min_amount_ld: i128,
21
+ /// Additional options for the LayerZero message (Optional)
11
22
  pub extra_options: Bytes,
23
+ /// Compose message to execute on the destination (Optional)
12
24
  pub compose_msg: Bytes,
25
+ /// OFT command for custom behavior (Optional)
13
26
  pub oft_cmd: Bytes,
14
27
  }
15
28
 
@@ -17,7 +30,9 @@ pub struct SendParam {
17
30
  #[contracttype]
18
31
  #[derive(Clone, PartialEq, Eq, Debug)]
19
32
  pub struct OFTLimit {
33
+ /// The minimum amount to send in local decimals
20
34
  pub min_amount_ld: i128,
35
+ /// The maximum amount to send in local decimals
21
36
  pub max_amount_ld: i128,
22
37
  }
23
38
 
@@ -25,7 +40,9 @@ pub struct OFTLimit {
25
40
  #[contracttype]
26
41
  #[derive(Clone, PartialEq, Eq, Debug)]
27
42
  pub struct OFTReceipt {
43
+ /// The amount sent in local decimals
28
44
  pub amount_sent_ld: i128,
45
+ /// The amount received in local decimals on the remote
29
46
  pub amount_received_ld: i128,
30
47
  }
31
48
 
@@ -33,6 +50,9 @@ pub struct OFTReceipt {
33
50
  #[contracttype]
34
51
  #[derive(Clone, PartialEq, Eq, Debug)]
35
52
  pub struct OFTFeeDetail {
53
+ /// The amount of the fee in local decimals. Positive values represent fees charged,
54
+ /// while negative values represent rewards given.
36
55
  pub fee_amount_ld: i128,
56
+ /// The description of the fee
37
57
  pub description: Bytes,
38
58
  }
@@ -5,8 +5,10 @@
5
5
  extern crate self as oft_std;
6
6
  extern crate std;
7
7
 
8
- use crate::integration_tests::utils::{address_to_peer_bytes32, peer_bytes32_to_address};
9
- use crate::oft::{OFTMode, OFTStd, OFTStdClient};
8
+ use crate::{
9
+ integration_tests::utils::{address_to_peer_bytes32, peer_bytes32_to_address},
10
+ oft::{OFTMode, OFTStd, OFTStdClient},
11
+ };
10
12
  use endpoint_v2::{EndpointV2, EndpointV2Client};
11
13
  use simple_message_lib::{SimpleMessageLib, SimpleMessageLibClient};
12
14
  use soroban_sdk::{
@@ -1,20 +1,23 @@
1
1
  use common_macros::{contract_impl, storage};
2
+ use endpoint_v2::Origin;
3
+ use oapp::oapp_receiver::LzReceiveInternal;
2
4
  use oapp_macros::oapp;
3
5
  use oft::{
4
- default_oft_impl::{default_quote_oft, default_quote_send},
5
6
  errors::OFTError,
6
7
  extensions::{
7
8
  oft_fee::{OFTFee, OFTFeeInternal},
8
9
  pausable::{OFTPausable, OFTPausableInternal},
9
10
  rate_limiter::{Direction, RateLimiter, RateLimiterInternal},
10
11
  },
11
- oft::{oft_initialize, OFTInternal, OFT},
12
+ initialize_oft,
13
+ oft::{OFTInternal, OFT},
14
+ oft_impl,
12
15
  oft_types::{lock_unlock, mint_burn},
13
16
  storage::OFTStorage,
14
17
  types::{OFTFeeDetail, OFTLimit, OFTReceipt, SendParam},
15
18
  utils::remove_dust,
16
19
  };
17
- use soroban_sdk::{assert_with_error, contracttype, Address, Env, Vec};
20
+ use soroban_sdk::{assert_with_error, contracttype, Address, Bytes, BytesN, Env, Vec};
18
21
 
19
22
  /// The mode of operation for the OFT contract
20
23
  #[contracttype]
@@ -47,7 +50,7 @@ impl OFTStd {
47
50
  shared_decimals: u32,
48
51
  mode: OFTMode,
49
52
  ) {
50
- oft_initialize::<Self>(env, owner, token, endpoint, delegate, shared_decimals);
53
+ initialize_oft::<Self>(env, owner, token, endpoint, delegate, shared_decimals);
51
54
  OFTStdStorage::set_mode(env, &mode);
52
55
  }
53
56
 
@@ -57,12 +60,27 @@ impl OFTStd {
57
60
  }
58
61
  }
59
62
 
63
+ /// LzReceiveInternal implementation using default OFT receive logic
64
+ impl LzReceiveInternal for OFTStd {
65
+ fn __lz_receive(
66
+ env: &Env,
67
+ origin: &Origin,
68
+ guid: &BytesN<32>,
69
+ message: &Bytes,
70
+ extra_data: &Bytes,
71
+ executor: &Address,
72
+ value: i128,
73
+ ) {
74
+ oft_impl::lz_receive::<Self>(env, executor, origin, guid, message, extra_data, value)
75
+ }
76
+ }
77
+
60
78
  /// OFT trait implementation for standard OFT with extensions
61
79
  #[contract_impl(contracttrait)]
62
80
  impl OFT for OFTStd {
63
81
  fn quote_oft(env: &Env, send_param: &SendParam) -> (OFTLimit, Vec<OFTFeeDetail>, OFTReceipt) {
64
82
  Self::__assert_not_paused(env);
65
- let (_, fee_details, oft_receipt) = default_quote_oft::<Self>(env, send_param);
83
+ let (_, fee_details, oft_receipt) = oft_impl::quote_oft::<Self>(env, send_param);
66
84
  let capacity = Self::rate_limit_capacity(env, &Direction::Outbound, send_param.dst_eid);
67
85
  let oft_limit = OFTLimit { min_amount_ld: 0, max_amount_ld: capacity };
68
86
  (oft_limit, fee_details, oft_receipt)
@@ -70,7 +88,7 @@ impl OFT for OFTStd {
70
88
 
71
89
  fn quote_send(env: &Env, sender: &Address, send_param: &SendParam, pay_in_zro: bool) -> endpoint_v2::MessagingFee {
72
90
  Self::__assert_not_paused(env);
73
- default_quote_send::<Self>(env, sender, send_param, pay_in_zro)
91
+ oft_impl::quote_send::<Self>(env, sender, send_param, pay_in_zro)
74
92
  }
75
93
  }
76
94
 
@@ -10,8 +10,8 @@
10
10
  //! ## Security Model
11
11
  //!
12
12
  //! The Upgrader is a permissionless utility - anyone can call it, but security is enforced
13
- //! by the target contract's ownership checks. When you call `upgrader.upgrade()`, the target
14
- //! contract's `#[only_owner]` guard ensures only the target's owner can successfully upgrade it.
13
+ //! by the target contract's authorization checks. When you call `upgrader.upgrade()`, the target
14
+ //! contract's `#[only_auth]` guard ensures only the target's authorizer can successfully upgrade it.
15
15
  //!
16
16
  //! ## Usage
17
17
  //!
@@ -53,8 +53,8 @@ pub struct Upgrader;
53
53
  impl Upgrader {
54
54
  /// Upgrade a target contract and run its migration in a single transaction
55
55
  ///
56
- /// The caller must be authorized as the owner of the target contract.
57
- /// This is enforced by the target contract's `#[only_owner]` check.
56
+ /// The caller must be authorized as the authorizer of the target contract.
57
+ /// This is enforced by the target contract's `#[only_auth]` check.
58
58
  ///
59
59
  /// This is useful for atomic upgrades where you want to ensure the migration
60
60
  /// happens immediately after the upgrade, or the entire operation fails.
@@ -0,0 +1,44 @@
1
+ //! Base authorization trait for owner-protected operations.
2
+ //!
3
+ //! The `Auth` trait provides a common interface for authorization that can be
4
+ //! implemented by different access control patterns (e.g., single owner, multisig).
5
+
6
+ use soroban_sdk::{contractclient, Address, Env};
7
+
8
+ // ===========================================================================
9
+ // Auth trait
10
+ // ===========================================================================
11
+
12
+ /// Base trait for authorization.
13
+ ///
14
+ /// Provides the authorizer address for owner-protected operations. This trait
15
+ /// is implemented by both `Ownable` (external owner) and `Multisig` (self-owning).
16
+ #[contractclient(name = "AuthClient")]
17
+ pub trait Auth: Sized {
18
+ /// Returns the address that authorizes owner-protected operations.
19
+ ///
20
+ /// For `Ownable` contracts, this returns the stored owner address.
21
+ /// For `Multisig` contracts, this returns the contract's own address
22
+ /// (self-owning pattern).
23
+ fn authorizer(env: &Env) -> Address;
24
+ }
25
+
26
+ // ===========================================================================
27
+ // Auth helper functions
28
+ // ===========================================================================
29
+
30
+ /// Enforces authorization from the authorizer and returns the authorizer address.
31
+ ///
32
+ /// Panics if the authorizer has not provided authorization for this invocation.
33
+ pub fn enforce_auth<T: Auth>(env: &Env) -> Address {
34
+ let authorizer = T::authorizer(env);
35
+ authorizer.require_auth();
36
+ authorizer
37
+ }
38
+
39
+ /// Requires authorization from the authorizer.
40
+ ///
41
+ /// Panics if the authorizer has not provided authorization for this invocation.
42
+ pub fn require_auth<T: Auth>(env: &Env) {
43
+ let _ = enforce_auth::<T>(env);
44
+ }
@@ -1,35 +1,57 @@
1
1
  use common_macros::contract_error;
2
2
 
3
+ // Utils library error codes: 1000-1099
4
+ // See ERROR_SPEC.md for allocation rules
5
+
6
+ /// BufferReaderError: 1000-1009
3
7
  #[contract_error]
4
8
  pub enum BufferReaderError {
5
9
  InvalidLength = 1000,
6
10
  InvalidAddressPayload,
7
11
  }
8
12
 
13
+ /// BufferWriterError: 1010-1019
9
14
  #[contract_error]
10
15
  pub enum BufferWriterError {
11
- InvalidAddressPayload = 1100,
16
+ InvalidAddressPayload = 1010,
12
17
  }
13
18
 
19
+ /// TtlConfigurableError: 1020-1029
14
20
  #[contract_error]
15
21
  pub enum TtlConfigurableError {
16
- InvalidTtlConfig = 1200,
22
+ InvalidTtlConfig = 1020,
17
23
  TtlConfigFrozen,
18
24
  TtlConfigAlreadyFrozen,
19
25
  }
20
26
 
27
+ /// OwnableError: 1030-1039
21
28
  #[contract_error]
22
29
  pub enum OwnableError {
23
- OwnerAlreadySet = 1300,
30
+ OwnerAlreadySet = 1030,
24
31
  OwnerNotSet,
25
32
  }
26
33
 
34
+ /// BytesExtError: 1040-1049
27
35
  #[contract_error]
28
36
  pub enum BytesExtError {
29
- LengthMismatch = 1400,
37
+ LengthMismatch = 1040,
30
38
  }
31
39
 
40
+ /// UpgradeableError: 1050-1059
32
41
  #[contract_error]
33
42
  pub enum UpgradeableError {
34
- MigrationNotAllowed = 1500,
43
+ MigrationNotAllowed = 1050,
44
+ }
45
+
46
+ /// MultisigError: 1060-1069
47
+ #[contract_error]
48
+ pub enum MultisigError {
49
+ AlreadyInitialized = 1060,
50
+ InvalidSigner,
51
+ SignatureError,
52
+ SignerAlreadyExists,
53
+ SignerNotFound,
54
+ TotalSignersLessThanThreshold,
55
+ UnsortedSigners,
56
+ ZeroThreshold,
35
57
  }
@@ -1,12 +1,15 @@
1
1
  #![no_std]
2
2
 
3
+ pub mod auth;
3
4
  pub mod buffer_reader;
4
5
  pub mod buffer_writer;
5
6
  pub mod bytes_ext;
6
7
  pub mod errors;
8
+ pub mod multisig;
7
9
  pub mod option_ext;
8
10
  pub mod ownable;
9
11
  pub mod ttl_configurable;
12
+ pub mod ttl_extendable;
10
13
  pub mod upgradeable;
11
14
 
12
15
  #[cfg(test)]
@@ -0,0 +1,211 @@
1
+ use crate::{
2
+ self as utils, // Alias for #[storage] macro's generated `utils::ttl_configurable` path
3
+ auth::{self, Auth},
4
+ errors::MultisigError,
5
+ };
6
+ use common_macros::{contract_trait, storage};
7
+ use soroban_sdk::{assert_with_error, contractevent, Bytes, BytesN, Env, Vec};
8
+
9
+ // ===========================================================================
10
+ // Multisig events
11
+ // ===========================================================================
12
+
13
+ /// Event emitted when a signer is added or removed.
14
+ #[contractevent]
15
+ #[derive(Clone, Debug, Eq, PartialEq)]
16
+ pub struct SignerSet {
17
+ #[topic]
18
+ pub signer: BytesN<20>,
19
+ pub active: bool,
20
+ }
21
+
22
+ /// Event emitted when the signature threshold is changed.
23
+ #[contractevent]
24
+ #[derive(Clone, Debug, Eq, PartialEq)]
25
+ pub struct ThresholdSet {
26
+ pub threshold: u32,
27
+ }
28
+
29
+ // ===========================================================================
30
+ // Multisig storage
31
+ // ===========================================================================
32
+
33
+ /// Storage keys for Multisig.
34
+ #[storage]
35
+ pub enum MultisigStorage {
36
+ #[persistent(Vec<BytesN<20>>)]
37
+ #[default(Vec::new(env))]
38
+ Signers,
39
+
40
+ #[instance(u32)]
41
+ #[default(0)]
42
+ Threshold,
43
+ }
44
+
45
+ // ===========================================================================
46
+ // Multisig trait with default implementation
47
+ // ===========================================================================
48
+
49
+ /// Trait for contracts with secp256k1 multisig signature verification.
50
+ ///
51
+ /// Extends `Auth` to provide self-owning authorization. Contracts implementing
52
+ /// `Multisig` should implement `Auth::authorizer()` to return `env.current_contract_address()`,
53
+ /// allowing the multisig quorum to serve as the authorizer for owner-protected operations.
54
+ #[contract_trait]
55
+ pub trait Multisig: Auth {
56
+ // ===========================================================================
57
+ // Mutation functions, only callable by the contract itself
58
+ // ===========================================================================
59
+
60
+ /// Adds or removes a signer from the multisig. Requires owner authorization.
61
+ fn set_signer(env: &Env, signer: &BytesN<20>, active: bool) {
62
+ auth::require_auth::<Self>(env);
63
+ match active {
64
+ true => add_signer(env, signer),
65
+ false => remove_signer(env, signer),
66
+ }
67
+ }
68
+
69
+ /// Sets the signature threshold (quorum). Requires owner authorization.
70
+ fn set_threshold(env: &Env, threshold: u32) {
71
+ auth::require_auth::<Self>(env);
72
+ set_threshold(env, threshold);
73
+ }
74
+
75
+ // ===========================================================================
76
+ // View functions
77
+ // ===========================================================================
78
+
79
+ /// Returns all registered signers.
80
+ fn get_signers(env: &Env) -> Vec<BytesN<20>> {
81
+ MultisigStorage::signers(env)
82
+ }
83
+
84
+ /// Returns the total number of registered signers.
85
+ fn total_signers(env: &Env) -> u32 {
86
+ MultisigStorage::signers(env).len()
87
+ }
88
+
89
+ /// Checks if an address is a registered signer.
90
+ fn is_signer(env: &Env, signer: &BytesN<20>) -> bool {
91
+ MultisigStorage::signers(env).iter().any(|s| &s == signer)
92
+ }
93
+
94
+ /// Returns the current signature threshold (quorum).
95
+ fn threshold(env: &Env) -> u32 {
96
+ MultisigStorage::threshold(env)
97
+ }
98
+
99
+ // ===========================================================================
100
+ // Verification functions
101
+ // ===========================================================================
102
+
103
+ /// Verifies signatures against the configured threshold.
104
+ fn verify_signatures(env: &Env, digest: &BytesN<32>, signatures: &Vec<BytesN<65>>) {
105
+ Self::verify_n_signatures(env, digest, signatures, MultisigStorage::threshold(env));
106
+ }
107
+
108
+ /// Verifies signatures against a custom threshold.
109
+ fn verify_n_signatures(env: &Env, digest: &BytesN<32>, signatures: &Vec<BytesN<65>>, threshold: u32) {
110
+ assert_with_error!(env, threshold > 0, MultisigError::ZeroThreshold);
111
+ assert_with_error!(env, signatures.len() >= threshold, MultisigError::SignatureError);
112
+
113
+ let signers = MultisigStorage::signers(env);
114
+ let mut last_signer: Option<BytesN<20>> = None;
115
+ for signature in signatures.iter() {
116
+ let signer = recover_signer(env, digest, &signature);
117
+
118
+ assert_with_error!(
119
+ env,
120
+ last_signer.as_ref().is_none_or(|last| &signer > last),
121
+ MultisigError::UnsortedSigners
122
+ );
123
+ assert_with_error!(env, signers.iter().any(|s| s == signer), MultisigError::SignerNotFound);
124
+
125
+ last_signer = Some(signer);
126
+ }
127
+ }
128
+ }
129
+
130
+ // ===========================================================================
131
+ // Public helper functions
132
+ // ===========================================================================
133
+
134
+ /// Initializes multisig with signers and threshold. Called from contract constructors.
135
+ pub fn init_multisig(env: &Env, signers: &Vec<BytesN<20>>, threshold: u32) {
136
+ assert_with_error!(env, !MultisigStorage::has_signers(env), MultisigError::AlreadyInitialized);
137
+
138
+ signers.iter().for_each(|signer| add_signer(env, &signer));
139
+ set_threshold(env, threshold);
140
+ }
141
+
142
+ /// Recovers Ethereum-style signer address from secp256k1 signature (65 bytes: r + s + v).
143
+ pub fn recover_signer(env: &Env, digest: &BytesN<32>, signature: &BytesN<65>) -> BytesN<20> {
144
+ let sig_bytes: Bytes = signature.into();
145
+ let v = sig_bytes.get(64).unwrap();
146
+ let recovery_id = if (27..=30).contains(&v) { v - 27 } else { v };
147
+ let sig_rs: BytesN<64> = sig_bytes.slice(0..64).try_into().unwrap();
148
+
149
+ let public_key = env.crypto_hazmat().secp256k1_recover(digest, &sig_rs, recovery_id as u32);
150
+
151
+ Bytes::from(env.crypto().keccak256(&Bytes::from(public_key).slice(1..65))).slice(12..32).try_into().unwrap()
152
+ }
153
+
154
+ // ===========================================================================
155
+ // Private helper functions
156
+ // ===========================================================================
157
+
158
+ /// Adds a new signer to the multisig.
159
+ fn add_signer(env: &Env, signer: &BytesN<20>) {
160
+ // Not allowed to add zero address as signer
161
+ assert_with_error!(env, signer != &BytesN::from_array(env, &[0u8; 20]), MultisigError::InvalidSigner);
162
+ // Not allowed to add same signer twice
163
+ let mut signers = MultisigStorage::signers(env);
164
+ assert_with_error!(env, !signers.iter().any(|s| &s == signer), MultisigError::SignerAlreadyExists);
165
+
166
+ // Add signer to list
167
+ signers.push_back(signer.clone());
168
+ MultisigStorage::set_signers(env, &signers);
169
+
170
+ SignerSet { signer: signer.clone(), active: true }.publish(env);
171
+ }
172
+
173
+ /// Removes a signer from the multisig.
174
+ fn remove_signer(env: &Env, signer: &BytesN<20>) {
175
+ let mut signers = MultisigStorage::signers(env);
176
+ let index = signers.first_index_of(signer);
177
+ // Not allowed to remove non-existent signer
178
+ assert_with_error!(env, index.is_some(), MultisigError::SignerNotFound);
179
+
180
+ // Remove signer from list
181
+ signers.remove(index.unwrap());
182
+
183
+ // Not allowed to remove signer if it would violate the threshold
184
+ assert_with_error!(
185
+ env,
186
+ signers.len() >= MultisigStorage::threshold(env),
187
+ MultisigError::TotalSignersLessThanThreshold
188
+ );
189
+
190
+ // Update signers list
191
+ MultisigStorage::set_signers(env, &signers);
192
+
193
+ SignerSet { signer: signer.clone(), active: false }.publish(env);
194
+ }
195
+
196
+ /// Sets the signature threshold (quorum).
197
+ fn set_threshold(env: &Env, threshold: u32) {
198
+ // Not allowed to set threshold to zero
199
+ assert_with_error!(env, threshold > 0, MultisigError::ZeroThreshold);
200
+ // Not allowed to set threshold to greater than the number of signers
201
+ assert_with_error!(
202
+ env,
203
+ MultisigStorage::signers(env).len() >= threshold,
204
+ MultisigError::TotalSignersLessThanThreshold
205
+ );
206
+
207
+ // Update threshold
208
+ MultisigStorage::set_threshold(env, &threshold);
209
+
210
+ ThresholdSet { threshold }.publish(env);
211
+ }