@layerzerolabs/protocol-stellar-v2 0.2.11 → 0.2.13

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 (74) hide show
  1. package/.turbo/turbo-build.log +202 -194
  2. package/.turbo/turbo-lint.log +38 -38
  3. package/.turbo/turbo-test.log +891 -891
  4. package/Cargo.lock +1 -1
  5. package/contracts/common-macros/src/lib.rs +3 -36
  6. package/contracts/endpoint-v2/src/endpoint_v2.rs +4 -4
  7. package/contracts/endpoint-v2/src/events.rs +40 -22
  8. package/contracts/endpoint-v2/src/interfaces/message_lib.rs +2 -2
  9. package/contracts/endpoint-v2/src/interfaces/message_lib_manager.rs +2 -2
  10. package/contracts/endpoint-v2/src/interfaces/messaging_channel.rs +2 -2
  11. package/contracts/endpoint-v2/src/interfaces/messaging_composer.rs +2 -2
  12. package/contracts/endpoint-v2/src/interfaces/send_lib.rs +2 -2
  13. package/contracts/endpoint-v2/src/message_lib_manager.rs +3 -3
  14. package/contracts/endpoint-v2/src/messaging_channel.rs +1 -1
  15. package/contracts/endpoint-v2/src/messaging_composer.rs +1 -1
  16. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_lib_timeout.rs +4 -8
  17. package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_library.rs +3 -7
  18. package/contracts/message-libs/{block-message-lib → blocked-message-lib}/Cargo.toml +1 -1
  19. package/contracts/message-libs/treasury/src/events.rs +9 -6
  20. package/contracts/message-libs/uln-302/src/events.rs +19 -11
  21. package/contracts/message-libs/uln-302/src/interfaces/receive_uln.rs +2 -2
  22. package/contracts/message-libs/uln-302/src/interfaces/send_uln.rs +2 -2
  23. package/contracts/message-libs/uln-302/src/receive_uln.rs +2 -2
  24. package/contracts/message-libs/uln-302/src/send_uln.rs +3 -3
  25. package/contracts/message-libs/uln-302/src/tests/receive_uln302/set_default_receive_uln_configs.rs +5 -5
  26. package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_send_uln_configs.rs +5 -5
  27. package/contracts/message-libs/uln-302/src/tests/setup.rs +3 -3
  28. package/contracts/message-libs/uln-302/src/types.rs +24 -24
  29. package/contracts/message-libs/uln-302/src/uln302.rs +1 -1
  30. package/contracts/oapps/counter/integration_tests/utils.rs +1 -1
  31. package/contracts/oapps/oapp/src/oapp_core.rs +4 -3
  32. package/contracts/oapps/oapp/src/oapp_options_type3.rs +4 -3
  33. package/contracts/oapps/oft/integration-tests/utils.rs +1 -1
  34. package/contracts/oapps/oft/src/events.rs +5 -4
  35. package/contracts/oapps/oft/src/extensions/oft_fee.rs +10 -6
  36. package/contracts/oapps/oft/src/extensions/pausable.rs +4 -4
  37. package/contracts/oapps/oft/src/extensions/rate_limiter.rs +8 -6
  38. package/contracts/utils/src/ownable.rs +6 -4
  39. package/contracts/utils/src/tests/testing_utils.rs +7 -5
  40. package/contracts/utils/src/ttl.rs +5 -4
  41. package/contracts/workers/dvn/src/auth.rs +59 -45
  42. package/contracts/workers/dvn/src/dvn.rs +84 -16
  43. package/contracts/workers/dvn/src/errors.rs +10 -13
  44. package/contracts/workers/dvn/src/events.rs +7 -5
  45. package/contracts/workers/dvn/src/interfaces/dvn.rs +29 -1
  46. package/contracts/workers/dvn/src/multisig.rs +94 -71
  47. package/contracts/workers/dvn/src/storage.rs +9 -12
  48. package/contracts/workers/dvn/src/tests/auth.rs +56 -26
  49. package/contracts/workers/dvn/src/tests/dvn.rs +37 -37
  50. package/contracts/workers/dvn/src/tests/multisig/set_signer.rs +8 -8
  51. package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +9 -9
  52. package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +6 -6
  53. package/contracts/workers/dvn/src/tests/setup.rs +5 -5
  54. package/contracts/workers/executor/src/auth.rs +93 -0
  55. package/contracts/workers/executor/src/events.rs +5 -4
  56. package/contracts/workers/executor/src/{lz_executor.rs → executor.rs} +25 -98
  57. package/contracts/workers/executor/src/interfaces/mod.rs +1 -1
  58. package/contracts/workers/executor/src/lib.rs +6 -5
  59. package/contracts/workers/worker/src/events.rs +23 -13
  60. package/contracts/workers/worker/src/worker.rs +32 -21
  61. package/package.json +3 -3
  62. package/sdk/dist/generated/bml.js +23 -23
  63. package/sdk/dist/generated/counter.js +25 -25
  64. package/sdk/dist/generated/endpoint.js +23 -23
  65. package/sdk/dist/generated/sml.js +23 -23
  66. package/sdk/dist/generated/uln302.d.ts +1 -1
  67. package/sdk/dist/generated/uln302.js +33 -33
  68. package/sdk/package.json +1 -1
  69. package/sdk/test/index.test.ts +1 -1
  70. package/sdk/test/oft.test.ts +847 -0
  71. package/sdk/test/suites/scan.ts +20 -4
  72. package/tools/ts-bindings-gen/src/main.rs +2 -1
  73. package/contracts/common-macros/src/event.rs +0 -16
  74. /package/contracts/message-libs/{block-message-lib → blocked-message-lib}/src/lib.rs +0 -0
@@ -17,8 +17,8 @@ fn test_set_default_receive_uln_configs() {
17
17
 
18
18
  let oapp_receive_uln_configs = vec![
19
19
  &env,
20
- SetDefaultUlnConfigParam { dst_eid: 100, config: UlnConfig::generate(&env, 1, 1, 3, 1) },
21
- SetDefaultUlnConfigParam { dst_eid: 101, config: UlnConfig::generate(&env, 2, 1, 3, 1) },
20
+ SetDefaultUlnConfigParam { eid: 100, config: UlnConfig::generate(&env, 1, 1, 3, 1) },
21
+ SetDefaultUlnConfigParam { eid: 101, config: UlnConfig::generate(&env, 2, 1, 3, 1) },
22
22
  ];
23
23
 
24
24
  env.mock_auths(&[MockAuth {
@@ -37,7 +37,7 @@ fn test_set_default_receive_uln_configs() {
37
37
 
38
38
  let uln302_receive_client = ReceiveUln302Client::new(&env, &uln302.address);
39
39
  for config in oapp_receive_uln_configs.clone() {
40
- assert_eq!(uln302_receive_client.default_receive_uln_config(&config.dst_eid), Some(config.config));
40
+ assert_eq!(uln302_receive_client.default_receive_uln_config(&config.eid), Some(config.config));
41
41
  }
42
42
  }
43
43
 
@@ -47,7 +47,7 @@ fn test_set_default_receive_uln_configs_authorization() {
47
47
  let TestSetup { env, uln302, .. } = setup();
48
48
 
49
49
  let oapp_receive_uln_configs =
50
- vec![&env, SetDefaultUlnConfigParam { dst_eid: 100, config: UlnConfig::generate(&env, 1, 1, 3, 1) }];
50
+ vec![&env, SetDefaultUlnConfigParam { eid: 100, config: UlnConfig::generate(&env, 1, 1, 3, 1) }];
51
51
 
52
52
  uln302.set_default_receive_uln_configs(&oapp_receive_uln_configs);
53
53
  }
@@ -58,7 +58,7 @@ fn test_set_default_receive_uln_configs_assert_default_config() {
58
58
 
59
59
  let mut config = UlnConfig::generate(&env, 1, 1, 3, 1);
60
60
  config.required_dvns.push_back(config.required_dvns.get(0).unwrap().clone());
61
- let oapp_receive_uln_configs = vec![&env, SetDefaultUlnConfigParam { dst_eid: 100, config }];
61
+ let oapp_receive_uln_configs = vec![&env, SetDefaultUlnConfigParam { eid: 100, config }];
62
62
 
63
63
  env.mock_all_auths();
64
64
  let result = uln302.try_set_default_receive_uln_configs(&oapp_receive_uln_configs);
@@ -18,8 +18,8 @@ fn test_set_default_send_uln_configs() {
18
18
 
19
19
  let oapp_send_uln_configs = vec![
20
20
  &env,
21
- SetDefaultUlnConfigParam { dst_eid: 100, config: UlnConfig::generate(&env, 1, 1, 3, 1) },
22
- SetDefaultUlnConfigParam { dst_eid: 101, config: UlnConfig::generate(&env, 2, 1, 3, 1) },
21
+ SetDefaultUlnConfigParam { eid: 100, config: UlnConfig::generate(&env, 1, 1, 3, 1) },
22
+ SetDefaultUlnConfigParam { eid: 101, config: UlnConfig::generate(&env, 2, 1, 3, 1) },
23
23
  ];
24
24
 
25
25
  env.mock_auths(&[MockAuth {
@@ -38,7 +38,7 @@ fn test_set_default_send_uln_configs() {
38
38
 
39
39
  let uln302_send_client = SendUln302Client::new(&env, &uln302.address);
40
40
  for config in oapp_send_uln_configs.clone() {
41
- assert_eq!(uln302_send_client.default_send_uln_config(&config.dst_eid), Some(config.config));
41
+ assert_eq!(uln302_send_client.default_send_uln_config(&config.eid), Some(config.config));
42
42
  }
43
43
  }
44
44
 
@@ -48,7 +48,7 @@ fn test_set_default_send_uln_configs_authorization() {
48
48
  let TestSetup { env, uln302, .. } = setup();
49
49
 
50
50
  let oapp_send_uln_configs =
51
- vec![&env, SetDefaultUlnConfigParam { dst_eid: 100, config: UlnConfig::generate(&env, 1, 1, 3, 1) }];
51
+ vec![&env, SetDefaultUlnConfigParam { eid: 100, config: UlnConfig::generate(&env, 1, 1, 3, 1) }];
52
52
 
53
53
  uln302.set_default_send_uln_configs(&oapp_send_uln_configs);
54
54
  }
@@ -59,7 +59,7 @@ fn test_set_default_send_uln_configs_assert_default_config() {
59
59
 
60
60
  let mut config = UlnConfig::generate(&env, 1, 1, 3, 1);
61
61
  config.required_dvns.push_back(config.required_dvns.get(0).unwrap().clone());
62
- let oapp_send_uln_configs = vec![&env, SetDefaultUlnConfigParam { dst_eid: 100, config }];
62
+ let oapp_send_uln_configs = vec![&env, SetDefaultUlnConfigParam { eid: 100, config }];
63
63
 
64
64
  env.mock_all_auths();
65
65
  let result = uln302.try_set_default_send_uln_configs(&oapp_send_uln_configs);
@@ -1,6 +1,6 @@
1
+ use common_macros::contract_impl;
1
2
  use endpoint_v2::{FeeRecipient, MessageLibClient, MessageLibManagerClient, Origin, SetConfigParam};
2
3
  use message_lib_common::interfaces::{ILayerZeroDVN, ILayerZeroExecutor, ILayerZeroTreasury};
3
- use common_macros::contract_impl;
4
4
  use soroban_sdk::{
5
5
  contract, log, symbol_short,
6
6
  testutils::{Address as _, MockAuth, MockAuthInvoke},
@@ -212,7 +212,7 @@ impl<'a> TestSetup<'a> {
212
212
  }
213
213
 
214
214
  pub fn set_default_send_uln_config(&self, eid: u32, config: UlnConfig) {
215
- let params = vec![&self.env, SetDefaultUlnConfigParam { dst_eid: eid, config }];
215
+ let params = vec![&self.env, SetDefaultUlnConfigParam { eid, config }];
216
216
  self.env.mock_auths(&[MockAuth {
217
217
  address: &self.owner,
218
218
  invoke: &MockAuthInvoke {
@@ -226,7 +226,7 @@ impl<'a> TestSetup<'a> {
226
226
  }
227
227
 
228
228
  pub fn set_default_receive_uln_config(&self, eid: u32, config: UlnConfig) {
229
- let params = vec![&self.env, SetDefaultUlnConfigParam { dst_eid: eid, config }];
229
+ let params = vec![&self.env, SetDefaultUlnConfigParam { eid, config }];
230
230
  self.env.mock_auths(&[MockAuth {
231
231
  address: &self.owner,
232
232
  invoke: &MockAuthInvoke {
@@ -23,6 +23,23 @@ pub struct UlnConfig {
23
23
  }
24
24
 
25
25
  impl UlnConfig {
26
+ /// Creates a new UlnConfig with default values.
27
+ pub fn default(env: &Env) -> Self {
28
+ UlnConfig { confirmations: 0, required_dvns: vec![&env], optional_dvns: vec![&env], optional_dvn_threshold: 0 }
29
+ }
30
+
31
+ /// Validates a UlnConfig for using as a default config.
32
+ ///
33
+ /// Performs comprehensive validation including:
34
+ /// - Required DVNs validation (no duplicates, within limits)
35
+ /// - Optional DVNs validation (no duplicates, within limits, valid threshold)
36
+ /// - At least one DVN requirement (either required or optional with threshold > 0)
37
+ pub fn validate_default_config(&self, env: &Env) {
38
+ self.validate_required_dvns(env);
39
+ self.validate_optional_dvns(env);
40
+ self.validate_at_least_one_dvn(env);
41
+ }
42
+
26
43
  /// Validates the required DVNs configuration.
27
44
  ///
28
45
  /// Checks:
@@ -50,18 +67,6 @@ impl UlnConfig {
50
67
  );
51
68
  }
52
69
 
53
- /// Validates a UlnConfig for using as a default config.
54
- ///
55
- /// Performs comprehensive validation including:
56
- /// - Required DVNs validation (no duplicates, within limits)
57
- /// - Optional DVNs validation (no duplicates, within limits, valid threshold)
58
- /// - At least one DVN requirement (either required or optional with threshold > 0)
59
- pub fn validate_default_config(&self, env: &Env) {
60
- self.validate_required_dvns(env);
61
- self.validate_optional_dvns(env);
62
- self.validate_at_least_one_dvn(env);
63
- }
64
-
65
70
  /// Validates that the configuration has at least one DVN for verification.
66
71
  ///
67
72
  /// A valid configuration must have either:
@@ -97,12 +102,7 @@ impl OAppUlnConfig {
97
102
  use_default_confirmations: true,
98
103
  use_default_required_dvns: true,
99
104
  use_default_optional_dvns: true,
100
- uln_config: UlnConfig {
101
- confirmations: 0,
102
- required_dvns: vec![&env],
103
- optional_dvns: vec![&env],
104
- optional_dvn_threshold: 0,
105
- },
105
+ uln_config: UlnConfig::default(env),
106
106
  }
107
107
  }
108
108
 
@@ -112,11 +112,9 @@ impl OAppUlnConfig {
112
112
  /// - When using defaults, corresponding config values must be empty/zero
113
113
  /// - When not using defaults, the provided values must be valid
114
114
  pub fn validate_oapp_config(&self, env: &Env) {
115
- assert_with_error!(
116
- env,
117
- !self.use_default_confirmations || self.uln_config.confirmations == 0,
118
- Uln302Error::InvalidConfirmations
119
- );
115
+ if self.use_default_confirmations {
116
+ assert_with_error!(env, self.uln_config.confirmations == 0, Uln302Error::InvalidConfirmations);
117
+ }
120
118
 
121
119
  if self.use_default_required_dvns {
122
120
  assert_with_error!(env, self.uln_config.required_dvns.is_empty(), Uln302Error::InvalidRequiredDVNs);
@@ -139,11 +137,13 @@ impl OAppUlnConfig {
139
137
  pub fn apply_default_config(&self, default_config: &UlnConfig) -> UlnConfig {
140
138
  let confirmations =
141
139
  if self.use_default_confirmations { default_config.confirmations } else { self.uln_config.confirmations };
140
+
142
141
  let required_dvns = if self.use_default_required_dvns {
143
142
  default_config.required_dvns.clone()
144
143
  } else {
145
144
  self.uln_config.required_dvns.clone()
146
145
  };
146
+
147
147
  let (optional_dvns, optional_dvn_threshold) = if self.use_default_optional_dvns {
148
148
  (default_config.optional_dvns.clone(), default_config.optional_dvn_threshold)
149
149
  } else {
@@ -159,7 +159,7 @@ impl OAppUlnConfig {
159
159
  #[derive(Clone, Eq, PartialEq, Debug)]
160
160
  pub struct SetDefaultUlnConfigParam {
161
161
  /// The destination endpoint ID (for send) or source endpoint ID (for receive).
162
- pub dst_eid: u32,
162
+ pub eid: u32,
163
163
  /// The ULN configuration to set as default.
164
164
  pub config: UlnConfig,
165
165
  }
@@ -54,7 +54,7 @@ impl Uln302 {
54
54
  }
55
55
  }
56
56
 
57
- #[contract_impl(contracttrait)]
57
+ #[contract_impl]
58
58
  impl IMessageLib for Uln302 {
59
59
  /// Sets OApp-specific configuration parameters for the message library.
60
60
  ///
@@ -128,7 +128,7 @@ pub fn lz_compose(env: &Env, chain: &ChainSetup<'_>, executor: &Address, packet:
128
128
  pub fn scan_packet_sent_event(env: &Env, endpoint: &Address) -> Option<(Bytes, Bytes, Address)> {
129
129
  let mut packet = None;
130
130
  for (emitter, topics, data) in env.events().all() {
131
- let packet_sent_symbol = Symbol::new(env, "PacketSent").to_val();
131
+ let packet_sent_symbol = Symbol::new(env, "packet_sent").to_val();
132
132
  if emitter == *endpoint && topics.contains(packet_sent_symbol) {
133
133
  let map: Map<Symbol, Val> = data.into_val(env);
134
134
 
@@ -1,6 +1,6 @@
1
- use common_macros::{event, only_owner, storage};
1
+ use common_macros::{only_owner, storage};
2
2
  use endpoint_v2::LayerZeroEndpointV2Client;
3
- use soroban_sdk::{contracttrait, Address, BytesN, Env};
3
+ use soroban_sdk::{contractevent, contracttrait, Address, BytesN, Env};
4
4
  use utils::ownable::Ownable;
5
5
  use utils::ownable::OwnableInitializer;
6
6
 
@@ -30,7 +30,8 @@ pub enum OAppCoreStorage {
30
30
  Peer { eid: u32 },
31
31
  }
32
32
 
33
- #[event]
33
+ #[contractevent]
34
+ #[derive(Clone, Debug, Eq, PartialEq)]
34
35
  pub struct PeerSet {
35
36
  pub eid: u32,
36
37
  pub peer: Option<BytesN<32>>,
@@ -1,6 +1,6 @@
1
1
  use crate::errors::OAppError;
2
- use common_macros::{event, only_owner, storage};
3
- use soroban_sdk::{assert_with_error, contracttrait, contracttype, panic_with_error, Bytes, Env, Vec};
2
+ use common_macros::{only_owner, storage};
3
+ use soroban_sdk::{assert_with_error, contractevent, contracttrait, contracttype, panic_with_error, Bytes, Env, Vec};
4
4
  use utils::ownable::Ownable;
5
5
 
6
6
  pub const OPTION_TYPE3: u32 = 3;
@@ -20,7 +20,8 @@ pub enum OAppOptionsType3Storage {
20
20
  EnforcedOptions { eid: u32, msg_type: u32 },
21
21
  }
22
22
 
23
- #[event]
23
+ #[contractevent]
24
+ #[derive(Clone, Debug, Eq, PartialEq)]
24
25
  pub struct EnforcedOptionSet {
25
26
  pub enforced_option_params: Vec<EnforcedOptionParam>,
26
27
  }
@@ -157,7 +157,7 @@ pub fn lz_compose(
157
157
  pub fn scan_packet_sent_event(env: &Env, endpoint: &Address) -> Option<(Bytes, Bytes, Address)> {
158
158
  let mut packet = None;
159
159
  for (emitter, topics, data) in env.events().all() {
160
- let packet_sent_symbol = Symbol::new(env, "PacketSent").to_val();
160
+ let packet_sent_symbol = Symbol::new(env, "packet_sent").to_val();
161
161
  if emitter == *endpoint && topics.contains(packet_sent_symbol) {
162
162
  let map: Map<Symbol, Val> = data.into_val(env);
163
163
 
@@ -1,7 +1,7 @@
1
- use common_macros::event;
2
- use soroban_sdk::{Address, BytesN};
1
+ use soroban_sdk::{contractevent, Address, BytesN};
3
2
 
4
- #[event]
3
+ #[contractevent]
4
+ #[derive(Clone, Debug, Eq, PartialEq)]
5
5
  pub struct OFTSent {
6
6
  pub guid: BytesN<32>,
7
7
  pub dst_eid: u32,
@@ -10,7 +10,8 @@ pub struct OFTSent {
10
10
  pub amount_received_ld: i128,
11
11
  }
12
12
 
13
- #[event]
13
+ #[contractevent]
14
+ #[derive(Clone, Debug, Eq, PartialEq)]
14
15
  pub struct OFTReceived {
15
16
  pub guid: BytesN<32>,
16
17
  pub src_eid: u32,
@@ -1,5 +1,5 @@
1
- use common_macros::{contract_error, event, only_owner, storage};
2
- use soroban_sdk::{assert_with_error, contracttrait, token::TokenClient, Address, Env};
1
+ use common_macros::{contract_error, only_owner, storage};
2
+ use soroban_sdk::{assert_with_error, contractevent, contracttrait, token::TokenClient, Address, Env};
3
3
  use utils::{option_ext::OptionExt, ownable::Ownable};
4
4
 
5
5
  /// Base fee in basis points (10,000 BPS = 100%)
@@ -27,23 +27,27 @@ pub enum OFTFeeError {
27
27
  SameValue,
28
28
  }
29
29
 
30
- #[event]
30
+ #[contractevent]
31
+ #[derive(Clone, Debug, Eq, PartialEq)]
31
32
  pub struct DefaultFeeBpsSet {
32
33
  pub fee_bps: u64,
33
34
  }
34
35
 
35
- #[event]
36
+ #[contractevent]
37
+ #[derive(Clone, Debug, Eq, PartialEq)]
36
38
  pub struct FeeBpsSet {
37
39
  pub dst_eid: u32,
38
40
  pub fee_bps: u64,
39
41
  }
40
42
 
41
- #[event]
43
+ #[contractevent]
44
+ #[derive(Clone, Debug, Eq, PartialEq)]
42
45
  pub struct FeeBpsUnset {
43
46
  pub dst_eid: u32,
44
47
  }
45
48
 
46
- #[event]
49
+ #[contractevent]
50
+ #[derive(Clone, Debug, Eq, PartialEq)]
47
51
  pub struct FeeDepositAddressSet {
48
52
  pub fee_deposit_address: Address,
49
53
  }
@@ -1,5 +1,5 @@
1
- use common_macros::{contract_error, event, only_owner, storage};
2
- use soroban_sdk::{assert_with_error, contracttrait, Env};
1
+ use common_macros::{contract_error, only_owner, storage};
2
+ use soroban_sdk::{assert_with_error, contractevent, contracttrait, Env};
3
3
  use utils::ownable::Ownable;
4
4
 
5
5
  #[storage]
@@ -15,7 +15,8 @@ pub enum OFTPausableError {
15
15
  PauseStatusUnchanged,
16
16
  }
17
17
 
18
- #[event]
18
+ #[contractevent]
19
+ #[derive(Clone, Debug, Eq, PartialEq)]
19
20
  pub struct PausedSet {
20
21
  pub paused: bool,
21
22
  }
@@ -47,4 +48,3 @@ pub trait OFTPausableInternal {
47
48
  assert_with_error!(env, !OFTPausableStorage::paused(env), OFTPausableError::Paused);
48
49
  }
49
50
  }
50
-
@@ -1,5 +1,5 @@
1
- use common_macros::{contract_error, event, only_owner, storage};
2
- use soroban_sdk::{assert_with_error, contracttrait, contracttype, panic_with_error, Env};
1
+ use common_macros::{contract_error, only_owner, storage};
2
+ use soroban_sdk::{assert_with_error, contractevent, contracttrait, contracttype, panic_with_error, Env};
3
3
  use utils::ownable::Ownable;
4
4
 
5
5
  #[contracttype]
@@ -34,7 +34,8 @@ pub enum RateLimitError {
34
34
  SameValue,
35
35
  }
36
36
 
37
- #[event]
37
+ #[contractevent]
38
+ #[derive(Clone, Debug, Eq, PartialEq)]
38
39
  pub struct RateLimitSet {
39
40
  pub direction: Direction,
40
41
  pub eid: u32,
@@ -42,7 +43,8 @@ pub struct RateLimitSet {
42
43
  pub window_seconds: u64,
43
44
  }
44
45
 
45
- #[event]
46
+ #[contractevent]
47
+ #[derive(Clone, Debug, Eq, PartialEq)]
46
48
  pub struct RateLimitUpdated {
47
49
  pub direction: Direction,
48
50
  pub eid: u32,
@@ -50,7 +52,8 @@ pub struct RateLimitUpdated {
50
52
  pub window_seconds: u64,
51
53
  }
52
54
 
53
- #[event]
55
+ #[contractevent]
56
+ #[derive(Clone, Debug, Eq, PartialEq)]
54
57
  pub struct RateLimitUnset {
55
58
  pub direction: Direction,
56
59
  pub eid: u32,
@@ -195,4 +198,3 @@ pub trait RateLimiterInternal {
195
198
  RateLimitStorage::set_rate_limit(env, direction, eid, &rate_limit);
196
199
  }
197
200
  }
198
-
@@ -1,7 +1,7 @@
1
1
  use crate::errors::OwnableError;
2
2
  use crate::option_ext::OptionExt;
3
- use common_macros::{event, storage};
4
- use soroban_sdk::{assert_with_error, contractclient, Address, Env};
3
+ use common_macros::storage;
4
+ use soroban_sdk::{assert_with_error, contractclient, contractevent, Address, Env};
5
5
 
6
6
  // ============================================
7
7
  // Ownable Initializer Interface
@@ -44,14 +44,16 @@ pub fn require_owner_auth<T: Ownable>(env: &Env) {
44
44
  }
45
45
 
46
46
  /// Event emitted when ownership is transferred.
47
- #[event]
47
+ #[contractevent]
48
+ #[derive(Clone, Debug, Eq, PartialEq)]
48
49
  pub struct OwnershipTransferred {
49
50
  pub old_owner: Address,
50
51
  pub new_owner: Address,
51
52
  }
52
53
 
53
54
  /// Event emitted when ownership is renounced.
54
- #[event]
55
+ #[contractevent]
56
+ #[derive(Clone, Debug, Eq, PartialEq)]
55
57
  pub struct OwnershipRenounced {
56
58
  pub old_owner: Address,
57
59
  }
@@ -1,23 +1,25 @@
1
1
  use crate::testing_utils::{assert_event, assert_events, ExpectedEvent, IntoExpectedEvent};
2
- use common_macros::event;
3
- use soroban_sdk::{contract, contractimpl, testutils::Address as _, Address, Env, IntoVal, Val, Vec};
2
+ use soroban_sdk::{contract, contractevent, contractimpl, testutils::Address as _, Address, Env, IntoVal, Val, Vec};
4
3
 
5
4
  // ============================================
6
5
  // Test Fixtures
7
6
  // ============================================
8
7
 
9
- #[event]
8
+ #[contractevent]
9
+ #[derive(Clone, Debug, Eq, PartialEq)]
10
10
  pub struct TestEvent1 {
11
11
  pub value: u32,
12
12
  }
13
13
 
14
- #[event]
14
+ #[contractevent]
15
+ #[derive(Clone, Debug, Eq, PartialEq)]
15
16
  pub struct TestEvent2 {
16
17
  pub name: u32,
17
18
  pub count: u64,
18
19
  }
19
20
 
20
- #[event]
21
+ #[contractevent]
22
+ #[derive(Clone, Debug, Eq, PartialEq)]
21
23
  pub struct TestEvent3 {
22
24
  pub address: Address,
23
25
  }
@@ -1,6 +1,5 @@
1
1
  use crate::errors::TtlError;
2
- use common_macros::event;
3
- use soroban_sdk::{assert_with_error, contractclient, contracttype, Env};
2
+ use soroban_sdk::{assert_with_error, contractclient, contractevent, contracttype, Env};
4
3
 
5
4
  /// Number of ledgers per day (~5 second ledger close time).
6
5
  pub const LEDGERS_PER_DAY: u32 = (24 * 3600) / 5;
@@ -111,12 +110,14 @@ impl TtlConfigurable for DefaultTtlConfigurable {
111
110
  // ============================================
112
111
 
113
112
  /// Event emitted when TTL configs are set.
114
- #[event]
113
+ #[contractevent]
114
+ #[derive(Clone, Debug, Eq, PartialEq)]
115
115
  pub struct TtlConfigsSet {
116
116
  pub instance: Option<TtlConfig>,
117
117
  pub persistent: Option<TtlConfig>,
118
118
  }
119
119
 
120
120
  /// Event emitted when TTL configs are frozen.
121
- #[event]
121
+ #[contractevent]
122
+ #[derive(Clone, Debug, Eq, PartialEq)]
122
123
  pub struct TtlConfigsFrozen {}
@@ -5,14 +5,23 @@ use soroban_sdk::{
5
5
  auth::{Context, CustomAccountInterface},
6
6
  contractimpl, contracttype,
7
7
  crypto::Hash,
8
- xdr::ToXdr,
8
+ vec, Symbol,
9
9
  };
10
- use utils::buffer_writer::BufferWriter;
11
10
 
12
11
  // ============================================================================
13
12
  // Authentication Data Types
14
13
  // ============================================================================
15
14
 
15
+ #[contracttype]
16
+ #[derive(Clone, Debug, Eq, PartialEq)]
17
+ pub enum Sender {
18
+ /// No explicit sender (permissionless execution).
19
+ None,
20
+ /// A registered admin (ed25519) submitting the transaction.
21
+ /// The tuple is `(public_key, signature)` where the signature covers the Soroban payload.
22
+ Admin(BytesN<32>, BytesN<64>),
23
+ }
24
+
16
25
  /// Authentication data for DVN contract transactions.
17
26
  ///
18
27
  /// This struct is used with Soroban's custom account interface to authorize
@@ -26,10 +35,8 @@ pub struct TransactionAuthData {
26
35
  pub expiration: u64,
27
36
  /// Signatures from multisig signers (secp256k1, 65 bytes each).
28
37
  pub signatures: Vec<BytesN<65>>,
29
- /// Admin's Ed25519 public key (32 bytes).
30
- pub admin: BytesN<32>,
31
- /// Admin's Ed25519 signature over the signature payload (64 bytes).
32
- pub admin_signature: BytesN<64>,
38
+ /// Entity submitting the transaction (admin, or permissionless).
39
+ pub sender: Sender,
33
40
  }
34
41
 
35
42
  // ============================================================================
@@ -37,51 +44,44 @@ pub struct TransactionAuthData {
37
44
  // ============================================================================
38
45
 
39
46
  #[contractimpl]
40
- impl CustomAccountInterface for Dvn {
47
+ impl CustomAccountInterface for LzDVN {
41
48
  type Signature = TransactionAuthData;
42
49
  type Error = DvnError;
43
50
 
44
51
  /// Validates authorization for DVN contract operations.
45
- ///
46
- /// This implements Soroban's custom account interface, allowing the DVN
47
- /// contract to act as its own account with multisig authorization.
48
- ///
49
- /// # Validation Steps
50
- /// 1. Verify the admin signature is from a registered admin
51
- /// 2. Check the VID matches the contract's configured VID
52
- /// 3. Ensure the auth data hasn't expired
53
- /// 4. Verify the auth contexts hash hasn't been used (replay protection)
54
- /// 5. Verify multisig signatures meet the threshold
55
52
  fn __check_auth(
56
53
  env: Env,
57
54
  signature_payload: Hash<32>,
58
55
  auth_data: Self::Signature,
59
56
  auth_contexts: Vec<Context>,
60
57
  ) -> Result<(), Self::Error> {
61
- let TransactionAuthData { vid, expiration, signatures, admin, admin_signature } = auth_data;
62
-
63
- // Verify the admin signature is valid and from a registered admin.
64
- Self::verify_admin(&env, &admin, &admin_signature, &signature_payload)?;
58
+ let TransactionAuthData { vid, expiration, signatures, sender } = auth_data;
65
59
 
66
- // Verify the VID matches the contract's configured VID.
67
- let stored_vid = Self::vid(&env);
68
- if vid != stored_vid {
60
+ // 1. Check VID and expiration
61
+ if vid != Self::vid(&env) {
69
62
  return Err(DvnError::InvalidVid);
70
63
  }
71
- // Ensure the auth data hasn't expired.
72
64
  if expiration <= env.ledger().timestamp() {
73
65
  return Err(DvnError::AuthDataExpired);
74
66
  }
75
67
 
76
- // Compute the hash of the auth data for replay protection.
77
- let hash = Self::hash_auth_data(&env, vid, expiration, &auth_contexts);
78
- // Verify the hash hasn't been used (replay protection) and set it as used.
68
+ // 2. Admin verification (skip for quorum_change_admin)
69
+ if !Self::is_invoking_quorum_change_admin(&env, &auth_contexts) {
70
+ let Sender::Admin(public_key, signature) = sender else {
71
+ return Err(DvnError::OnlyAdmin);
72
+ };
73
+ Self::verify_admin_signature(&env, &public_key, &signature, &signature_payload)?;
74
+ }
75
+
76
+ // 3. Replay protection
77
+ let calls = Self::extract_execution_calls(&env, &auth_contexts)?;
78
+ let hash = Self::hash_call_data(&env, vid, expiration, &calls);
79
79
  if DvnStorage::used_hash(&env, &hash) {
80
80
  return Err(DvnError::HashAlreadyUsed);
81
81
  }
82
82
  DvnStorage::set_used_hash(&env, &hash, &true);
83
83
 
84
- // Verify the multisig signatures meet the threshold.
84
+ // 4. Multisig verification (most expensive - do last)
85
85
  Self::verify_signatures(&env, &hash, &signatures);
86
86
 
87
87
  Ok(())
@@ -92,39 +92,53 @@ impl CustomAccountInterface for Dvn {
92
92
  // Internal Helper Functions
93
93
  // ============================================================================
94
94
 
95
- impl Dvn {
95
+ impl LzDVN {
96
96
  /// Verifies that the admin signature is valid and from a registered admin.
97
97
  ///
98
98
  /// # Arguments
99
- /// * `admin` - The admin's Ed25519 public key
100
- /// * `admin_signature` - The admin's signature over the signature payload
99
+ /// * `public_key` - The admin's Ed25519 public key (32 bytes)
100
+ /// * `signature` - The admin's signature over the signature payload (64 bytes)
101
101
  /// * `signature_payload` - The payload that was signed
102
102
  ///
103
103
  /// # Errors
104
104
  /// Returns `DvnError::OnlyAdmin` if the signer is not a registered admin.
105
- fn verify_admin(
105
+ fn verify_admin_signature(
106
106
  env: &Env,
107
- admin: &BytesN<32>,
108
- admin_signature: &BytesN<64>,
107
+ public_key: &BytesN<32>,
108
+ signature: &BytesN<64>,
109
109
  signature_payload: &Hash<32>,
110
110
  ) -> Result<(), DvnError> {
111
- let admin_address = Address::from_payload(env, AddressPayload::AccountIdPublicKeyEd25519(admin.clone()));
111
+ let admin_address = Address::from_payload(env, AddressPayload::AccountIdPublicKeyEd25519(public_key.clone()));
112
112
  if !Self::is_admin(env, &admin_address) {
113
113
  return Err(DvnError::OnlyAdmin);
114
114
  }
115
115
 
116
- env.crypto().ed25519_verify(admin, &signature_payload.clone().into(), admin_signature);
116
+ env.crypto().ed25519_verify(public_key, &signature_payload.clone().into(), signature);
117
117
 
118
118
  Ok(())
119
119
  }
120
120
 
121
- /// Computes the hash of auth data for replay protection.
122
- ///
123
- /// Creates a unique hash from the VID, expiration, and auth contexts
124
- /// to prevent the same authorization from being used multiple times.
125
- fn hash_auth_data(env: &Env, vid: u32, expiration: u64, auth_contexts: &Vec<Context>) -> BytesN<32> {
126
- let mut writer = BufferWriter::new(env);
127
- let data = writer.write_u32(vid).write_u64(expiration).write_bytes(&auth_contexts.to_xdr(env)).to_bytes();
128
- env.crypto().keccak256(&data).into()
121
+ /// Extracts the execution calls from the auth contexts.
122
+ fn extract_execution_calls(env: &Env, auth_contexts: &Vec<Context>) -> Result<Vec<Call>, DvnError> {
123
+ auth_contexts.iter().try_fold(vec![env], |mut calls, context| {
124
+ let Context::Contract(ctx) = context else {
125
+ return Err(DvnError::NonContractInvoke);
126
+ };
127
+ calls.push_back(Call { to: ctx.contract, func: ctx.fn_name, args: ctx.args });
128
+ Ok(calls)
129
+ })
130
+ }
131
+
132
+ /// Checks if the auth context is for `quorum_change_admin` on this contract.
133
+ /// This function doesn't require admin verification (quorum-only).
134
+ fn is_invoking_quorum_change_admin(env: &Env, auth_contexts: &Vec<Context>) -> bool {
135
+ // Must be exactly one call (no bundling with other operations)
136
+ if auth_contexts.len() != 1 {
137
+ return false;
138
+ }
139
+ let Context::Contract(ctx) = auth_contexts.first().unwrap() else {
140
+ return false;
141
+ };
142
+ ctx.contract == env.current_contract_address() && ctx.fn_name == Symbol::new(env, "quorum_change_admin")
129
143
  }
130
144
  }