@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.
- package/.turbo/turbo-build.log +202 -194
- package/.turbo/turbo-lint.log +38 -38
- package/.turbo/turbo-test.log +891 -891
- package/Cargo.lock +1 -1
- package/contracts/common-macros/src/lib.rs +3 -36
- package/contracts/endpoint-v2/src/endpoint_v2.rs +4 -4
- package/contracts/endpoint-v2/src/events.rs +40 -22
- package/contracts/endpoint-v2/src/interfaces/message_lib.rs +2 -2
- package/contracts/endpoint-v2/src/interfaces/message_lib_manager.rs +2 -2
- package/contracts/endpoint-v2/src/interfaces/messaging_channel.rs +2 -2
- package/contracts/endpoint-v2/src/interfaces/messaging_composer.rs +2 -2
- package/contracts/endpoint-v2/src/interfaces/send_lib.rs +2 -2
- package/contracts/endpoint-v2/src/message_lib_manager.rs +3 -3
- package/contracts/endpoint-v2/src/messaging_channel.rs +1 -1
- package/contracts/endpoint-v2/src/messaging_composer.rs +1 -1
- package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_lib_timeout.rs +4 -8
- package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_library.rs +3 -7
- package/contracts/message-libs/{block-message-lib → blocked-message-lib}/Cargo.toml +1 -1
- package/contracts/message-libs/treasury/src/events.rs +9 -6
- package/contracts/message-libs/uln-302/src/events.rs +19 -11
- package/contracts/message-libs/uln-302/src/interfaces/receive_uln.rs +2 -2
- package/contracts/message-libs/uln-302/src/interfaces/send_uln.rs +2 -2
- package/contracts/message-libs/uln-302/src/receive_uln.rs +2 -2
- package/contracts/message-libs/uln-302/src/send_uln.rs +3 -3
- package/contracts/message-libs/uln-302/src/tests/receive_uln302/set_default_receive_uln_configs.rs +5 -5
- package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_send_uln_configs.rs +5 -5
- package/contracts/message-libs/uln-302/src/tests/setup.rs +3 -3
- package/contracts/message-libs/uln-302/src/types.rs +24 -24
- package/contracts/message-libs/uln-302/src/uln302.rs +1 -1
- package/contracts/oapps/counter/integration_tests/utils.rs +1 -1
- package/contracts/oapps/oapp/src/oapp_core.rs +4 -3
- package/contracts/oapps/oapp/src/oapp_options_type3.rs +4 -3
- package/contracts/oapps/oft/integration-tests/utils.rs +1 -1
- package/contracts/oapps/oft/src/events.rs +5 -4
- package/contracts/oapps/oft/src/extensions/oft_fee.rs +10 -6
- package/contracts/oapps/oft/src/extensions/pausable.rs +4 -4
- package/contracts/oapps/oft/src/extensions/rate_limiter.rs +8 -6
- package/contracts/utils/src/ownable.rs +6 -4
- package/contracts/utils/src/tests/testing_utils.rs +7 -5
- package/contracts/utils/src/ttl.rs +5 -4
- package/contracts/workers/dvn/src/auth.rs +59 -45
- package/contracts/workers/dvn/src/dvn.rs +84 -16
- package/contracts/workers/dvn/src/errors.rs +10 -13
- package/contracts/workers/dvn/src/events.rs +7 -5
- package/contracts/workers/dvn/src/interfaces/dvn.rs +29 -1
- package/contracts/workers/dvn/src/multisig.rs +94 -71
- package/contracts/workers/dvn/src/storage.rs +9 -12
- package/contracts/workers/dvn/src/tests/auth.rs +56 -26
- package/contracts/workers/dvn/src/tests/dvn.rs +37 -37
- package/contracts/workers/dvn/src/tests/multisig/set_signer.rs +8 -8
- package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +9 -9
- package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +6 -6
- package/contracts/workers/dvn/src/tests/setup.rs +5 -5
- package/contracts/workers/executor/src/auth.rs +93 -0
- package/contracts/workers/executor/src/events.rs +5 -4
- package/contracts/workers/executor/src/{lz_executor.rs → executor.rs} +25 -98
- package/contracts/workers/executor/src/interfaces/mod.rs +1 -1
- package/contracts/workers/executor/src/lib.rs +6 -5
- package/contracts/workers/worker/src/events.rs +23 -13
- package/contracts/workers/worker/src/worker.rs +32 -21
- package/package.json +3 -3
- package/sdk/dist/generated/bml.js +23 -23
- package/sdk/dist/generated/counter.js +25 -25
- package/sdk/dist/generated/endpoint.js +23 -23
- package/sdk/dist/generated/sml.js +23 -23
- package/sdk/dist/generated/uln302.d.ts +1 -1
- package/sdk/dist/generated/uln302.js +33 -33
- package/sdk/package.json +1 -1
- package/sdk/test/index.test.ts +1 -1
- package/sdk/test/oft.test.ts +847 -0
- package/sdk/test/suites/scan.ts +20 -4
- package/tools/ts-bindings-gen/src/main.rs +2 -1
- package/contracts/common-macros/src/event.rs +0 -16
- /package/contracts/message-libs/{block-message-lib → blocked-message-lib}/src/lib.rs +0 -0
package/contracts/message-libs/uln-302/src/tests/receive_uln302/set_default_receive_uln_configs.rs
CHANGED
|
@@ -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 {
|
|
21
|
-
SetDefaultUlnConfigParam {
|
|
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.
|
|
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 {
|
|
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 {
|
|
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);
|
package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_send_uln_configs.rs
CHANGED
|
@@ -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 {
|
|
22
|
-
SetDefaultUlnConfigParam {
|
|
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.
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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
|
-
|
|
116
|
-
env,
|
|
117
|
-
|
|
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
|
|
162
|
+
pub eid: u32,
|
|
163
163
|
/// The ULN configuration to set as default.
|
|
164
164
|
pub config: UlnConfig,
|
|
165
165
|
}
|
|
@@ -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, "
|
|
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::{
|
|
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
|
-
#[
|
|
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::{
|
|
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
|
-
#[
|
|
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, "
|
|
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
|
|
2
|
-
use soroban_sdk::{Address, BytesN};
|
|
1
|
+
use soroban_sdk::{contractevent, Address, BytesN};
|
|
3
2
|
|
|
4
|
-
#[
|
|
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
|
-
#[
|
|
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,
|
|
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
|
-
#[
|
|
30
|
+
#[contractevent]
|
|
31
|
+
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
31
32
|
pub struct DefaultFeeBpsSet {
|
|
32
33
|
pub fee_bps: u64,
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
#[
|
|
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
|
-
#[
|
|
43
|
+
#[contractevent]
|
|
44
|
+
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
42
45
|
pub struct FeeBpsUnset {
|
|
43
46
|
pub dst_eid: u32,
|
|
44
47
|
}
|
|
45
48
|
|
|
46
|
-
#[
|
|
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,
|
|
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
|
-
#[
|
|
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,
|
|
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
|
-
#[
|
|
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
|
-
#[
|
|
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
|
-
#[
|
|
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::
|
|
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
|
-
#[
|
|
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
|
-
#[
|
|
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
|
|
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
|
-
#[
|
|
8
|
+
#[contractevent]
|
|
9
|
+
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
10
10
|
pub struct TestEvent1 {
|
|
11
11
|
pub value: u32,
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
#[
|
|
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
|
-
#[
|
|
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
|
|
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
|
-
#[
|
|
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
|
-
#[
|
|
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
|
-
|
|
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
|
-
///
|
|
30
|
-
pub
|
|
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
|
|
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,
|
|
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
|
-
//
|
|
67
|
-
|
|
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
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
//
|
|
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
|
|
95
|
+
impl LzDVN {
|
|
96
96
|
/// Verifies that the admin signature is valid and from a registered admin.
|
|
97
97
|
///
|
|
98
98
|
/// # Arguments
|
|
99
|
-
/// * `
|
|
100
|
-
/// * `
|
|
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
|
|
105
|
+
fn verify_admin_signature(
|
|
106
106
|
env: &Env,
|
|
107
|
-
|
|
108
|
-
|
|
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(
|
|
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(
|
|
116
|
+
env.crypto().ed25519_verify(public_key, &signature_payload.clone().into(), signature);
|
|
117
117
|
|
|
118
118
|
Ok(())
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
///
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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
|
}
|