@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.
- package/.turbo/turbo-build.log +350 -309
- package/.turbo/turbo-lint.log +146 -108
- package/.turbo/turbo-test.log +1423 -1238
- package/Cargo.lock +12 -0
- package/Cargo.toml +3 -0
- package/contracts/ERROR_SPEC.md +44 -0
- package/contracts/common-macros/src/auth.rs +113 -0
- package/contracts/common-macros/src/contract_ttl.rs +84 -0
- package/contracts/common-macros/src/lib.rs +181 -30
- package/contracts/common-macros/src/lz_contract.rs +83 -0
- package/contracts/common-macros/src/tests/{ownable.rs → auth.rs} +48 -15
- package/contracts/common-macros/src/tests/contract_ttl.rs +662 -0
- package/contracts/common-macros/src/tests/mod.rs +2 -2
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_multisig_code.snap +20 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_ownable_code.snap +24 -0
- 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
- 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
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__contract_ttl__snapshot_generated_contracttrait_code.snap +69 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +7 -21
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__upgradeable__snapshot_generated_upgradeable_code.snap +2 -2
- package/contracts/common-macros/src/ttl_configurable.rs +19 -34
- package/contracts/common-macros/src/ttl_extendable.rs +36 -0
- package/contracts/common-macros/src/upgradeable.rs +5 -5
- package/contracts/common-macros/src/utils.rs +9 -0
- package/contracts/endpoint-v2/src/constants.rs +4 -4
- package/contracts/endpoint-v2/src/endpoint_v2.rs +38 -40
- package/contracts/endpoint-v2/src/errors.rs +4 -3
- package/contracts/endpoint-v2/src/events.rs +1 -1
- package/contracts/endpoint-v2/src/message_lib_manager.rs +18 -5
- package/contracts/endpoint-v2/src/messaging_channel.rs +11 -1
- package/contracts/endpoint-v2/src/messaging_composer.rs +11 -1
- package/contracts/endpoint-v2/src/storage.rs +1 -1
- package/contracts/endpoint-v2/src/tests/endpoint_v2/pay_messaging_fees.rs +3 -3
- package/contracts/endpoint-v2/src/tests/endpoint_v2/quote.rs +1 -1
- package/contracts/endpoint-v2/src/tests/endpoint_v2/require_oapp_auth.rs +2 -2
- package/contracts/endpoint-v2/src/tests/endpoint_v2/send.rs +3 -3
- package/contracts/endpoint-v2/src/tests/endpoint_v2/set_zro.rs +4 -4
- package/contracts/endpoint-v2/src/tests/message_lib_manager/require_receive_lib_for_eid.rs +3 -3
- package/contracts/endpoint-v2/src/tests/message_lib_manager/require_registered.rs +1 -1
- package/contracts/endpoint-v2/src/tests/message_lib_manager/require_send_lib_for_eid.rs +3 -3
- package/contracts/endpoint-v2/src/tests/message_lib_manager/require_supported_eid.rs +1 -1
- package/contracts/endpoint-v2/src/tests/messaging_channel/clear_payload.rs +4 -4
- package/contracts/endpoint-v2/src/tests/messaging_channel/inbound.rs +1 -1
- package/contracts/layerzero-views/src/layerzero_view.rs +3 -6
- package/contracts/macro-integration-tests/tests/runtime/ownable/mod.rs +2 -2
- package/contracts/macro-integration-tests/tests/runtime/ownable/{only_owner_guard.rs → only_auth_guard.rs} +1 -1
- package/contracts/macro-integration-tests/tests/runtime/ttl_configurable/configuration.rs +1 -1
- package/contracts/macro-integration-tests/tests/runtime/ttl_configurable/freeze.rs +1 -1
- package/contracts/macro-integration-tests/tests/runtime/ttl_configurable/mod.rs +0 -1
- package/contracts/macro-integration-tests/tests/ui/ownable/fail/{only_owner_missing_env.rs → only_auth_missing_env.rs} +3 -3
- package/contracts/macro-integration-tests/tests/ui/ownable/fail/{only_owner_missing_env.stderr → only_auth_missing_env.stderr} +4 -4
- package/contracts/macro-integration-tests/tests/ui/ownable/pass/namespacing_and_imports.rs +2 -3
- package/contracts/macro-integration-tests/tests/ui/ownable/pass/{only_owner_env_param_variants.rs → only_auth_env_param_variants.rs} +9 -9
- package/contracts/macro-integration-tests/tests/ui/ttl_configurable/pass/minimal_contract.rs +6 -6
- package/contracts/message-libs/message-lib-common/src/errors.rs +7 -2
- package/contracts/message-libs/message-lib-common/src/tests/packet_codec_v1/decode_packet_header.rs +3 -3
- package/contracts/message-libs/message-lib-common/src/tests/worker_options/append_lz_receive_option.rs +1 -2
- package/contracts/message-libs/message-lib-common/src/tests/worker_options/append_native_drop_option.rs +1 -2
- package/contracts/message-libs/message-lib-common/src/tests/worker_options/convert_legacy_options.rs +9 -9
- package/contracts/message-libs/message-lib-common/src/tests/worker_options/extract_type_3_options.rs +1 -1
- package/contracts/message-libs/message-lib-common/src/tests/worker_options/left_pad_to_bytes32.rs +1 -1
- package/contracts/message-libs/message-lib-common/src/tests/worker_options/split_worker_options.rs +2 -2
- package/contracts/message-libs/simple-message-lib/src/simple_message_lib.rs +7 -9
- package/contracts/message-libs/treasury/src/errors.rs +2 -2
- package/contracts/message-libs/treasury/src/events.rs +1 -1
- package/contracts/message-libs/treasury/src/interfaces/zro_fee_lib.rs +2 -2
- package/contracts/message-libs/treasury/src/storage.rs +1 -1
- package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +1 -1
- package/contracts/message-libs/treasury/src/treasury.rs +14 -16
- package/contracts/message-libs/uln-302/src/receive_uln.rs +13 -2
- package/contracts/message-libs/uln-302/src/send_uln.rs +23 -3
- package/contracts/message-libs/uln-302/src/uln302.rs +6 -24
- package/contracts/oapps/counter/Cargo.toml +14 -1
- package/contracts/oapps/counter/integration_tests/mod.rs +4 -1
- package/contracts/oapps/counter/integration_tests/{setup.rs → setup_sml.rs} +48 -80
- package/contracts/oapps/counter/integration_tests/setup_uln.rs +997 -0
- package/contracts/oapps/counter/integration_tests/signing.rs +62 -0
- package/contracts/oapps/counter/integration_tests/test_with_sml.rs +24 -55
- package/contracts/oapps/counter/integration_tests/test_with_uln.rs +314 -0
- package/contracts/oapps/counter/integration_tests/utils.rs +196 -53
- package/contracts/oapps/counter/src/counter.rs +67 -43
- package/contracts/oapps/counter/src/tests/mod.rs +0 -13
- package/contracts/oapps/counter/src/tests/test_counter.rs +5 -7
- package/contracts/oapps/oapp/src/errors.rs +5 -1
- package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +93 -78
- package/contracts/oapps/oapp/src/oapp_core.rs +36 -21
- package/contracts/oapps/oapp/src/oapp_options_type3.rs +48 -12
- package/contracts/oapps/oapp/src/oapp_receiver.rs +106 -41
- package/contracts/oapps/oapp/src/oapp_sender.rs +26 -34
- package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +9 -8
- package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +25 -17
- package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +7 -7
- package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +14 -15
- package/contracts/oapps/oapp-macros/src/generators.rs +128 -0
- package/contracts/oapps/oapp-macros/src/lib.rs +113 -56
- package/contracts/oapps/oft/integration-tests/setup.rs +25 -7
- package/contracts/oapps/oft/src/errors.rs +6 -1
- package/contracts/oapps/oft/src/extensions/oft_fee.rs +8 -8
- package/contracts/oapps/oft/src/extensions/pausable.rs +4 -4
- package/contracts/oapps/oft/src/extensions/rate_limiter.rs +5 -5
- package/contracts/oapps/oft/src/lib.rs +4 -2
- package/contracts/oapps/oft/src/oft.rs +24 -64
- package/contracts/oapps/oft/src/oft_impl.rs +201 -0
- package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +1 -3
- package/contracts/oapps/oft/src/oft_types/mint_burn.rs +1 -4
- package/contracts/oapps/oft/src/storage.rs +2 -0
- package/contracts/oapps/oft/src/tests/extensions/setup.rs +36 -22
- package/contracts/oapps/oft/src/tests/extensions/test_oft_fee.rs +5 -3
- package/contracts/oapps/oft/src/tests/extensions/test_pausable.rs +5 -3
- package/contracts/oapps/oft/src/tests/extensions/test_rate_limiter.rs +5 -3
- package/contracts/oapps/oft/src/tests/test_decimals.rs +2 -2
- package/contracts/oapps/oft/src/tests/test_oft_msg_codec.rs +1 -2
- package/contracts/oapps/oft/src/tests/test_utils.rs +45 -23
- package/contracts/oapps/oft/src/types.rs +20 -0
- package/contracts/oapps/oft-std/integration-tests/setup.rs +4 -2
- package/contracts/oapps/oft-std/src/oft.rs +24 -6
- package/contracts/upgrader/src/lib.rs +4 -4
- package/contracts/utils/src/auth.rs +44 -0
- package/contracts/utils/src/errors.rs +27 -5
- package/contracts/utils/src/lib.rs +3 -0
- package/contracts/utils/src/multisig.rs +211 -0
- package/contracts/utils/src/ownable.rs +12 -10
- package/contracts/utils/src/tests/buffer_reader.rs +6 -6
- package/contracts/utils/src/tests/buffer_writer.rs +6 -6
- package/contracts/utils/src/tests/bytes_ext.rs +2 -4
- package/contracts/utils/src/tests/mod.rs +1 -0
- package/contracts/utils/src/tests/multisig.rs +731 -0
- package/contracts/utils/src/tests/option_ext.rs +2 -5
- package/contracts/utils/src/tests/ownable.rs +16 -5
- package/contracts/utils/src/tests/ttl_configurable.rs +27 -16
- package/contracts/utils/src/tests/upgradeable.rs +4 -2
- package/contracts/utils/src/ttl_configurable.rs +23 -8
- package/contracts/utils/src/ttl_extendable.rs +27 -0
- package/contracts/utils/src/upgradeable.rs +2 -0
- package/contracts/workers/dvn/Cargo.toml +1 -1
- package/contracts/workers/dvn/src/auth.rs +7 -7
- package/contracts/workers/dvn/src/dvn.rs +10 -38
- package/contracts/workers/dvn/src/errors.rs +0 -7
- package/contracts/workers/dvn/src/events.rs +1 -14
- package/contracts/workers/dvn/src/interfaces/dvn.rs +2 -2
- package/contracts/workers/dvn/src/interfaces/mod.rs +0 -2
- package/contracts/workers/dvn/src/storage.rs +3 -13
- package/contracts/workers/dvn/src/tests/auth.rs +4 -4
- package/contracts/workers/dvn/src/tests/dvn.rs +1 -2
- package/contracts/workers/dvn/src/tests/multisig/set_signer.rs +7 -8
- package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +11 -8
- package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +11 -12
- package/contracts/workers/dvn/src/tests/setup.rs +5 -5
- package/contracts/workers/dvn-fee-lib/Cargo.toml +1 -1
- package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +3 -6
- package/contracts/workers/executor/src/auth.rs +80 -16
- package/contracts/workers/executor/src/executor.rs +5 -31
- package/contracts/workers/executor/src/storage.rs +2 -9
- package/contracts/workers/executor-fee-lib/Cargo.toml +1 -1
- package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +3 -6
- package/contracts/workers/executor-helper/Cargo.toml +1 -1
- package/contracts/workers/executor-helper/src/executor_helper.rs +53 -73
- package/contracts/workers/price-feed/Cargo.toml +1 -1
- package/contracts/workers/price-feed/src/price_feed.rs +7 -10
- package/contracts/workers/worker/src/errors.rs +4 -0
- package/contracts/workers/worker/src/tests/worker.rs +7 -6
- package/contracts/workers/worker/src/worker.rs +20 -16
- package/package.json +8 -5
- package/sdk/.turbo/turbo-build.log +1 -0
- package/sdk/.turbo/turbo-test.log +1009 -0
- package/sdk/dist/generated/bml.d.ts +65 -8
- package/sdk/dist/generated/bml.js +70 -34
- package/sdk/dist/generated/counter.d.ts +167 -42
- package/sdk/dist/generated/counter.js +86 -45
- package/sdk/dist/generated/dvn.d.ts +282 -229
- package/sdk/dist/generated/dvn.js +119 -81
- package/sdk/dist/generated/dvn_fee_lib.d.ts +142 -67
- package/sdk/dist/generated/dvn_fee_lib.js +64 -24
- package/sdk/dist/generated/endpoint.d.ts +97 -22
- package/sdk/dist/generated/endpoint.js +75 -37
- package/sdk/dist/generated/executor.d.ts +117 -85
- package/sdk/dist/generated/executor.js +102 -59
- package/sdk/dist/generated/executor_fee_lib.d.ts +162 -78
- package/sdk/dist/generated/executor_fee_lib.js +104 -57
- package/sdk/dist/generated/executor_helper.d.ts +133 -21
- package/sdk/dist/generated/executor_helper.js +99 -50
- package/sdk/dist/generated/oft_std.d.ts +233 -55
- package/sdk/dist/generated/oft_std.js +99 -54
- package/sdk/dist/generated/price_feed.d.ts +142 -67
- package/sdk/dist/generated/price_feed.js +64 -24
- package/sdk/dist/generated/sml.d.ts +113 -32
- package/sdk/dist/generated/sml.js +93 -49
- package/sdk/dist/generated/treasury.d.ts +896 -0
- package/sdk/dist/generated/treasury.js +219 -0
- package/sdk/dist/generated/uln302.d.ts +113 -32
- package/sdk/dist/generated/uln302.js +93 -49
- package/sdk/dist/generated/upgrader.d.ts +2 -2
- package/sdk/dist/generated/upgrader.js +1 -1
- package/sdk/dist/index.d.ts +2 -0
- package/sdk/dist/index.js +3 -0
- package/sdk/dist/wasm/blocked-message-lib.d.ts +1 -0
- package/sdk/dist/wasm/blocked-message-lib.js +2 -0
- package/sdk/dist/wasm/counter.d.ts +1 -0
- package/sdk/dist/wasm/counter.js +2 -0
- package/sdk/dist/wasm/dvn-fee-lib.d.ts +1 -0
- package/sdk/dist/wasm/dvn-fee-lib.js +2 -0
- package/sdk/dist/wasm/dvn.d.ts +1 -0
- package/sdk/dist/wasm/dvn.js +2 -0
- package/sdk/dist/wasm/endpoint-v2.d.ts +1 -0
- package/sdk/dist/wasm/endpoint-v2.js +2 -0
- package/sdk/dist/wasm/executor-fee-lib.d.ts +1 -0
- package/sdk/dist/wasm/executor-fee-lib.js +2 -0
- package/sdk/dist/wasm/executor-helper.d.ts +1 -0
- package/sdk/dist/wasm/executor-helper.js +2 -0
- package/sdk/dist/wasm/executor.d.ts +1 -0
- package/sdk/dist/wasm/executor.js +2 -0
- package/sdk/dist/wasm/layerzero-views.d.ts +1 -0
- package/sdk/dist/wasm/layerzero-views.js +2 -0
- package/sdk/dist/wasm/oft-std.d.ts +1 -0
- package/sdk/dist/wasm/oft-std.js +2 -0
- package/sdk/dist/wasm/price-feed.d.ts +1 -0
- package/sdk/dist/wasm/price-feed.js +2 -0
- package/sdk/dist/wasm/simple-message-lib.d.ts +1 -0
- package/sdk/dist/wasm/simple-message-lib.js +2 -0
- package/sdk/dist/wasm/treasury.d.ts +1 -0
- package/sdk/dist/wasm/treasury.js +2 -0
- package/sdk/dist/wasm/uln302.d.ts +1 -0
- package/sdk/dist/wasm/uln302.js +2 -0
- package/sdk/dist/wasm/upgrader.d.ts +1 -0
- package/sdk/dist/wasm/upgrader.js +2 -0
- package/sdk/dist/wasm.d.ts +15 -0
- package/sdk/dist/wasm.js +15 -0
- package/sdk/package.json +4 -2
- package/sdk/src/index.ts +4 -0
- package/sdk/test/counter-sml.test.ts +376 -0
- package/sdk/test/counter-uln.test.ts +493 -0
- package/sdk/test/{oft.test.ts → oft-sml.test.ts} +185 -310
- package/sdk/test/suites/constants.ts +22 -2
- package/sdk/test/suites/globalSetup.ts +450 -0
- package/sdk/test/suites/localnet.ts +23 -6
- package/sdk/test/upgrader.test.ts +7 -16
- package/sdk/test/utils.ts +558 -85
- package/sdk/vitest.config.ts +21 -0
- package/tools/ts-bindings-gen/src/main.rs +1 -0
- package/turbo.json +2 -0
- package/contracts/common-macros/src/contract_impl.rs +0 -52
- package/contracts/common-macros/src/ownable.rs +0 -41
- package/contracts/common-macros/src/tests/contract_impl.rs +0 -386
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_generated_ownable_code.snap +0 -12
- package/contracts/macro-integration-tests/tests/runtime/ttl_configurable/extend_instance_ttl.rs +0 -50
- package/contracts/oapps/oapp-macros/src/oapp_core.rs +0 -41
- package/contracts/oapps/oapp-macros/src/oapp_full.rs +0 -21
- package/contracts/oapps/oapp-macros/src/oapp_options_type3.rs +0 -31
- package/contracts/oapps/oapp-macros/src/oapp_receiver.rs +0 -48
- package/contracts/oapps/oapp-macros/src/oapp_sender.rs +0 -21
- package/contracts/oapps/oapp-macros/src/util.rs +0 -107
- package/contracts/oapps/oft/src/constants.rs +0 -5
- package/contracts/oapps/oft/src/default_oft_impl.rs +0 -152
- package/contracts/workers/dvn/src/interfaces/multisig.rs +0 -56
- package/contracts/workers/dvn/src/multisig.rs +0 -157
- package/sdk/test/index.test.ts +0 -375
- /package/sdk/test/suites/{testUpgradeable.ts → dummyContractClient.ts} +0 -0
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
use heck::ToSnakeCase;
|
|
2
|
-
use proc_macro2::TokenStream;
|
|
3
|
-
use quote::quote;
|
|
4
|
-
use syn::Ident;
|
|
5
|
-
|
|
6
|
-
/// Generates the `OAppReceiver` trait implementation.
|
|
7
|
-
///
|
|
8
|
-
/// When `manual_impl_receiver` is false, generates `lz_receive` that calls
|
|
9
|
-
/// `verify_and_clear_payload` then delegates to the user's `__lz_receive` method.
|
|
10
|
-
pub fn generate_impl(name: &Ident, manual_impl_receiver: bool) -> TokenStream {
|
|
11
|
-
// Use a distinct module name to avoid conflicts with oapp_core's module
|
|
12
|
-
let impl_mod = syn::Ident::new(&format!("__oapp_receiver_impl_{}", name.to_string().to_snake_case()), name.span());
|
|
13
|
-
|
|
14
|
-
let receiver_impl = (!manual_impl_receiver).then(|| {
|
|
15
|
-
quote! {
|
|
16
|
-
// OAppReceiver implementation
|
|
17
|
-
// This generates contract entry points that are callable via LayerZeroReceiverClient
|
|
18
|
-
// because the function names match ILayerZeroReceiver's interface.
|
|
19
|
-
#[doc(hidden)]
|
|
20
|
-
mod #impl_mod {
|
|
21
|
-
use super::*;
|
|
22
|
-
use soroban_sdk::{Address, Bytes, BytesN, Env};
|
|
23
|
-
use endpoint_v2::Origin;
|
|
24
|
-
use oapp::oapp_receiver::OAppReceiver;
|
|
25
|
-
|
|
26
|
-
#[soroban_sdk::contractimpl(contracttrait)]
|
|
27
|
-
impl OAppReceiver for #name {
|
|
28
|
-
fn lz_receive(
|
|
29
|
-
env: &soroban_sdk::Env,
|
|
30
|
-
executor: &soroban_sdk::Address,
|
|
31
|
-
origin: &endpoint_v2::Origin,
|
|
32
|
-
guid: &soroban_sdk::BytesN<32>,
|
|
33
|
-
message: &soroban_sdk::Bytes,
|
|
34
|
-
extra_data: &soroban_sdk::Bytes,
|
|
35
|
-
value: i128,
|
|
36
|
-
) {
|
|
37
|
-
oapp::oapp_receiver::verify_and_clear_payload::<Self>(env, executor, origin, guid, message, value);
|
|
38
|
-
Self::__lz_receive(env, executor, origin, guid, message, extra_data, value)
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
quote! {
|
|
46
|
-
#receiver_impl
|
|
47
|
-
}
|
|
48
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
use proc_macro2::TokenStream;
|
|
2
|
-
use quote::quote;
|
|
3
|
-
use syn::Ident;
|
|
4
|
-
|
|
5
|
-
/// Generates the `OAppSender` trait implementation.
|
|
6
|
-
///
|
|
7
|
-
/// When `manual_impl_sender` is false, generates an empty `impl OAppSender`
|
|
8
|
-
/// that uses the trait's default implementations for `lz_quote` and `lz_send`...
|
|
9
|
-
pub fn generate_impl(name: &Ident, manual_impl_sender: bool) -> TokenStream {
|
|
10
|
-
let sender_impl = (!manual_impl_sender).then(|| {
|
|
11
|
-
quote! {
|
|
12
|
-
use oapp::oapp_sender::OAppSender as _;
|
|
13
|
-
|
|
14
|
-
impl oapp::oapp_sender::OAppSender for #name {}
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
quote! {
|
|
19
|
-
#sender_impl
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
use proc_macro::TokenStream;
|
|
2
|
-
use proc_macro2::Ident;
|
|
3
|
-
use syn::{
|
|
4
|
-
parse::{Parse, ParseStream},
|
|
5
|
-
punctuated::Punctuated,
|
|
6
|
-
Error, ItemStruct, Token,
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
/// Configuration for which OApp trait implementations should be manually provided by the user.
|
|
10
|
-
///
|
|
11
|
-
/// This struct is parsed from the `#[oapp_manual_impl(...)]` attribute and controls
|
|
12
|
-
/// which default trait implementations are generated by the macros.
|
|
13
|
-
///
|
|
14
|
-
/// # Fields
|
|
15
|
-
/// * `core` - If `true`, the user must manually implement `OAppCore`
|
|
16
|
-
/// * `sender` - If `true`, the user must manually implement `OAppSender`
|
|
17
|
-
/// * `receiver` - If `true`, the user must manually implement `OAppReceiver` trait entirely
|
|
18
|
-
/// * `options_type3` - If `true`, the user must manually implement `OAppOptionsType3`
|
|
19
|
-
///
|
|
20
|
-
/// # Receiver Manual Implementation
|
|
21
|
-
/// When `receiver` is `true`, the macro will NOT generate `impl OAppReceiver`. The user
|
|
22
|
-
/// must manually implement the entire `OAppReceiver` trait, including `lz_receive`,
|
|
23
|
-
/// `next_nonce`, `allow_initialize_path`, and `is_compose_msg_sender`.
|
|
24
|
-
///
|
|
25
|
-
/// This is useful when you need to customize methods like `next_nonce` (e.g., for ordered delivery).
|
|
26
|
-
#[derive(Debug, Clone, Copy, Default)]
|
|
27
|
-
pub struct ManualImplConfig {
|
|
28
|
-
pub core: bool,
|
|
29
|
-
pub sender: bool,
|
|
30
|
-
pub receiver: bool,
|
|
31
|
-
pub options_type3: bool,
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
impl ManualImplConfig {
|
|
35
|
-
/// Parses configuration from the `#[oapp_manual_impl(...)]` attribute arguments.
|
|
36
|
-
///
|
|
37
|
-
/// Accepts a comma-separated list of identifiers: `core`, `sender`, `receiver`, `options_type3`.
|
|
38
|
-
/// Returns an error if any invalid identifier is provided.
|
|
39
|
-
fn from_attr(input: ParseStream) -> syn::Result<Self> {
|
|
40
|
-
let idents = Punctuated::<syn::Ident, Token![,]>::parse_terminated(input)?;
|
|
41
|
-
|
|
42
|
-
let mut cfg = ManualImplConfig::default();
|
|
43
|
-
|
|
44
|
-
for ident in idents {
|
|
45
|
-
match ident.to_string().as_str() {
|
|
46
|
-
"core" => cfg.core = true,
|
|
47
|
-
"sender" => cfg.sender = true,
|
|
48
|
-
"receiver" => cfg.receiver = true,
|
|
49
|
-
"options_type3" => cfg.options_type3 = true,
|
|
50
|
-
_ => {
|
|
51
|
-
return Err(Error::new(
|
|
52
|
-
ident.span(),
|
|
53
|
-
"invalid value for oapp_manual_impl: expected one of `core`, `sender`, `receiver`, `options_type3`",
|
|
54
|
-
));
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
Ok(cfg)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
impl Parse for ManualImplConfig {
|
|
64
|
-
fn parse(input: ParseStream) -> syn::Result<Self> {
|
|
65
|
-
ManualImplConfig::from_attr(input)
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/// Parses a struct definition and extracts manual implementation configuration.
|
|
70
|
-
///
|
|
71
|
-
/// This function is used by all OApp macros to:
|
|
72
|
-
/// 1. Parse the annotated item as a struct
|
|
73
|
-
/// 2. Extract the struct name
|
|
74
|
-
/// 3. Parse any `#[oapp_manual_impl(...)]` attributes to determine configuration
|
|
75
|
-
///
|
|
76
|
-
/// # Returns
|
|
77
|
-
/// A tuple containing:
|
|
78
|
-
/// * The struct identifier
|
|
79
|
-
/// * The complete struct definition
|
|
80
|
-
/// * The manual implementation configuration
|
|
81
|
-
///
|
|
82
|
-
/// # Errors
|
|
83
|
-
/// Returns a compile error if:
|
|
84
|
-
/// * The item is not a struct
|
|
85
|
-
/// * The `#[oapp_manual_impl(...)]` attribute has invalid syntax
|
|
86
|
-
pub fn parse_struct(item: TokenStream) -> Result<(Ident, ItemStruct, ManualImplConfig), TokenStream> {
|
|
87
|
-
let item_struct = syn::parse::<ItemStruct>(item).map_err(|e| e.to_compile_error())?;
|
|
88
|
-
let name = item_struct.ident.clone();
|
|
89
|
-
|
|
90
|
-
let mut cfg = ManualImplConfig::default();
|
|
91
|
-
// TODO: match at most once oapp_manual_impl attribute
|
|
92
|
-
for attr in item_struct.attrs.iter() {
|
|
93
|
-
if attr.path().is_ident("oapp_manual_impl") {
|
|
94
|
-
match attr.parse_args::<ManualImplConfig>() {
|
|
95
|
-
Ok(parsed) => {
|
|
96
|
-
cfg = parsed;
|
|
97
|
-
}
|
|
98
|
-
Err(e) => {
|
|
99
|
-
return Err(e.to_compile_error().into());
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
break;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
Ok((name, item_struct, cfg))
|
|
107
|
-
}
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
//! Default OFT implementations.
|
|
2
|
-
//!
|
|
3
|
-
//! This module provides default standalone functions for common OFT operations that can be
|
|
4
|
-
//! reused by trait implementations.
|
|
5
|
-
|
|
6
|
-
use crate::{
|
|
7
|
-
codec::{oft_compose_msg_codec::OFTComposeMsg, oft_msg_codec::OFTMessage},
|
|
8
|
-
constants,
|
|
9
|
-
errors::OFTError,
|
|
10
|
-
events,
|
|
11
|
-
events::OFTSent,
|
|
12
|
-
storage::OFTStorage,
|
|
13
|
-
types::{OFTFeeDetail, OFTLimit, OFTReceipt, SendParam},
|
|
14
|
-
utils::{address_to_bytes32, remove_dust, resolve_address, to_ld, to_sd},
|
|
15
|
-
};
|
|
16
|
-
use endpoint_v2::{MessagingComposerClient, MessagingFee, MessagingReceipt, Origin};
|
|
17
|
-
use oapp::oapp_options_type3::OAppOptionsType3;
|
|
18
|
-
use soroban_sdk::{assert_with_error, vec, Address, Bytes, BytesN, Env, Vec};
|
|
19
|
-
|
|
20
|
-
/// Calculates debit amounts without executing (view function).
|
|
21
|
-
pub fn default_debit_view(env: &Env, amount_ld: i128, min_amount_ld: i128, _dst_eid: u32) -> OFTReceipt {
|
|
22
|
-
let conversion_rate = OFTStorage::decimal_conversion_rate(env).unwrap();
|
|
23
|
-
let amount_sent_ld = remove_dust(amount_ld, conversion_rate);
|
|
24
|
-
let amount_received_ld = amount_sent_ld;
|
|
25
|
-
|
|
26
|
-
assert_with_error!(env, amount_received_ld >= min_amount_ld, OFTError::SlippageExceeded);
|
|
27
|
-
|
|
28
|
-
OFTReceipt { amount_sent_ld, amount_received_ld }
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/// Builds OFT message and combines options for cross-chain transfer.
|
|
32
|
-
pub fn default_build_msg_and_options<T>(
|
|
33
|
-
env: &Env,
|
|
34
|
-
sender: &Address,
|
|
35
|
-
send_param: &SendParam,
|
|
36
|
-
amount_ld: i128,
|
|
37
|
-
) -> (Bytes, Bytes)
|
|
38
|
-
where
|
|
39
|
-
T: OAppOptionsType3,
|
|
40
|
-
{
|
|
41
|
-
let has_compose = !send_param.compose_msg.is_empty();
|
|
42
|
-
let conversion_rate = OFTStorage::decimal_conversion_rate(env).unwrap();
|
|
43
|
-
let msg = OFTMessage {
|
|
44
|
-
send_to: send_param.to.clone(),
|
|
45
|
-
amount_sd: to_sd(env, amount_ld, conversion_rate),
|
|
46
|
-
compose_from: if has_compose { Some(address_to_bytes32(sender)) } else { None },
|
|
47
|
-
compose_msg: if has_compose { Some(send_param.compose_msg.clone()) } else { None },
|
|
48
|
-
};
|
|
49
|
-
let (msg, _) = msg.encode(env);
|
|
50
|
-
let msg_type = if has_compose { constants::SEND_AND_CALL } else { constants::SEND };
|
|
51
|
-
|
|
52
|
-
(msg, T::combine_options(env, send_param.dst_eid, msg_type, &send_param.extra_options))
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/// Handles OFT receive logic.
|
|
56
|
-
pub fn default_lz_receive<T>(
|
|
57
|
-
env: &Env,
|
|
58
|
-
_executor: &Address,
|
|
59
|
-
origin: &Origin,
|
|
60
|
-
guid: &BytesN<32>,
|
|
61
|
-
message: &Bytes,
|
|
62
|
-
_extra_data: &Bytes,
|
|
63
|
-
_value: i128,
|
|
64
|
-
) where
|
|
65
|
-
T: crate::oft::OFTInternal,
|
|
66
|
-
{
|
|
67
|
-
let oft_msg = OFTMessage::decode(message);
|
|
68
|
-
let send_to = resolve_address(env, &oft_msg.send_to);
|
|
69
|
-
|
|
70
|
-
let conversion_rate = OFTStorage::decimal_conversion_rate(env).unwrap();
|
|
71
|
-
let amount_received_ld = T::__credit(env, &send_to, to_ld(oft_msg.amount_sd, conversion_rate), origin.src_eid);
|
|
72
|
-
|
|
73
|
-
if oft_msg.is_composed() {
|
|
74
|
-
let compose_msg = OFTComposeMsg {
|
|
75
|
-
nonce: origin.nonce,
|
|
76
|
-
src_eid: origin.src_eid,
|
|
77
|
-
amount_ld: amount_received_ld,
|
|
78
|
-
compose_from: oft_msg.compose_from.unwrap(),
|
|
79
|
-
compose_msg: oft_msg.compose_msg.unwrap(),
|
|
80
|
-
}
|
|
81
|
-
.encode(env);
|
|
82
|
-
|
|
83
|
-
let endpoint = MessagingComposerClient::new(env, &T::endpoint(env));
|
|
84
|
-
endpoint.send_compose(&env.current_contract_address(), &send_to, guid, &0, &compose_msg);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
events::OFTReceived { guid: guid.clone(), src_eid: origin.src_eid, to: send_to, amount_received_ld }.publish(env);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/// Quotes an OFT transfer without executing.
|
|
91
|
-
/// Returns (OFTLimit, fee details, receipt with estimated amounts).
|
|
92
|
-
pub fn default_quote_oft<T>(env: &Env, send_param: &SendParam) -> (OFTLimit, Vec<OFTFeeDetail>, OFTReceipt)
|
|
93
|
-
where
|
|
94
|
-
T: crate::oft::OFTInternal,
|
|
95
|
-
{
|
|
96
|
-
let oft_receipt = T::__debit_view(env, send_param.amount_ld, send_param.min_amount_ld, send_param.dst_eid);
|
|
97
|
-
let oft_fee_details = if oft_receipt.amount_sent_ld > oft_receipt.amount_received_ld {
|
|
98
|
-
vec![
|
|
99
|
-
env,
|
|
100
|
-
OFTFeeDetail {
|
|
101
|
-
fee_amount_ld: oft_receipt.amount_sent_ld - oft_receipt.amount_received_ld,
|
|
102
|
-
description: Bytes::from_array(env, b"OFT Fee"),
|
|
103
|
-
},
|
|
104
|
-
]
|
|
105
|
-
} else {
|
|
106
|
-
vec![env]
|
|
107
|
-
};
|
|
108
|
-
(OFTLimit { min_amount_ld: 0, max_amount_ld: i128::MAX }, oft_fee_details, oft_receipt)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/// Quotes a send operation including LayerZero messaging fees.
|
|
112
|
-
pub fn default_quote_send<T>(env: &Env, sender: &Address, send_param: &SendParam, pay_in_zro: bool) -> MessagingFee
|
|
113
|
-
where
|
|
114
|
-
T: crate::oft::OFT,
|
|
115
|
-
{
|
|
116
|
-
let OFTReceipt { amount_received_ld, .. } =
|
|
117
|
-
T::__debit_view(env, send_param.amount_ld, send_param.min_amount_ld, send_param.dst_eid);
|
|
118
|
-
|
|
119
|
-
let (msg, options) = default_build_msg_and_options::<T>(env, sender, send_param, amount_received_ld);
|
|
120
|
-
T::lz_quote(env, send_param.dst_eid, &msg, &options, pay_in_zro)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/// Sends tokens cross-chain to another endpoint.
|
|
124
|
-
/// Sender must be authenticated. Returns (MessagingReceipt, OFTReceipt).
|
|
125
|
-
pub fn default_send<T>(
|
|
126
|
-
env: &Env,
|
|
127
|
-
sender: &Address,
|
|
128
|
-
send_param: &SendParam,
|
|
129
|
-
fee: &MessagingFee,
|
|
130
|
-
refund_address: &Address,
|
|
131
|
-
) -> (MessagingReceipt, OFTReceipt)
|
|
132
|
-
where
|
|
133
|
-
T: crate::oft::OFT,
|
|
134
|
-
{
|
|
135
|
-
sender.require_auth();
|
|
136
|
-
|
|
137
|
-
let oft_receipt = T::__debit(env, sender, send_param.amount_ld, send_param.min_amount_ld, send_param.dst_eid);
|
|
138
|
-
|
|
139
|
-
let (msg, options) = default_build_msg_and_options::<T>(env, sender, send_param, oft_receipt.amount_received_ld);
|
|
140
|
-
let msg_receipt = T::lz_send(env, sender, send_param.dst_eid, &msg, &options, fee, refund_address);
|
|
141
|
-
|
|
142
|
-
OFTSent {
|
|
143
|
-
guid: msg_receipt.guid.clone(),
|
|
144
|
-
dst_eid: send_param.dst_eid,
|
|
145
|
-
from: sender.clone(),
|
|
146
|
-
amount_sent_ld: oft_receipt.amount_sent_ld,
|
|
147
|
-
amount_received_ld: oft_receipt.amount_received_ld,
|
|
148
|
-
}
|
|
149
|
-
.publish(env);
|
|
150
|
-
|
|
151
|
-
(msg_receipt, oft_receipt)
|
|
152
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
use soroban_sdk::{contractclient, BytesN, Env, Vec};
|
|
2
|
-
|
|
3
|
-
/// Length of an ECDSA signature (64 bytes) plus recovery ID (1 byte).
|
|
4
|
-
pub const SIGNATURE_LENGTH: usize = 65;
|
|
5
|
-
|
|
6
|
-
/// Multisig interface for threshold-based signature verification.
|
|
7
|
-
///
|
|
8
|
-
/// Provides functionality to manage signers and verify that a sufficient
|
|
9
|
-
/// number of valid signatures (meeting the threshold) have signed a message.
|
|
10
|
-
#[contractclient(name = "MultiSigClient")]
|
|
11
|
-
pub trait IMultisig {
|
|
12
|
-
/// Adds or removes a signer from the multisig.
|
|
13
|
-
///
|
|
14
|
-
/// # Arguments
|
|
15
|
-
/// * `signer` - The 20-byte signer address (derived from secp256k1 public key)
|
|
16
|
-
/// * `active` - `true` to add, `false` to remove
|
|
17
|
-
fn set_signer(env: &Env, signer: &BytesN<20>, active: bool);
|
|
18
|
-
|
|
19
|
-
/// Returns all registered signers.
|
|
20
|
-
fn get_signers(env: &Env) -> Vec<BytesN<20>>;
|
|
21
|
-
|
|
22
|
-
/// Returns the total number of registered signers.
|
|
23
|
-
fn total_signers(env: &Env) -> u32;
|
|
24
|
-
|
|
25
|
-
/// Checks if an address is a registered signer.
|
|
26
|
-
fn is_signer(env: &Env, signer: &BytesN<20>) -> bool;
|
|
27
|
-
|
|
28
|
-
/// Returns the current signature threshold (quorum).
|
|
29
|
-
fn threshold(env: &Env) -> u32;
|
|
30
|
-
|
|
31
|
-
/// Sets the signature threshold (quorum).
|
|
32
|
-
///
|
|
33
|
-
/// The threshold must be greater than 0 and not exceed total signers.
|
|
34
|
-
fn set_threshold(env: &Env, threshold: u32);
|
|
35
|
-
|
|
36
|
-
/// Verifies signatures against the configured threshold.
|
|
37
|
-
///
|
|
38
|
-
/// # Arguments
|
|
39
|
-
/// * `hash` - The 32-byte message hash that was signed
|
|
40
|
-
/// * `signatures` - List of signatures to verify
|
|
41
|
-
///
|
|
42
|
-
/// # Panics
|
|
43
|
-
/// If fewer than `threshold` valid signatures from registered signers are provided.
|
|
44
|
-
fn verify_signatures(env: &Env, hash: &BytesN<32>, signatures: &Vec<BytesN<SIGNATURE_LENGTH>>);
|
|
45
|
-
|
|
46
|
-
/// Verifies signatures against a custom threshold.
|
|
47
|
-
///
|
|
48
|
-
/// # Arguments
|
|
49
|
-
/// * `hash` - The 32-byte message hash that was signed
|
|
50
|
-
/// * `signatures` - List of signatures to verify
|
|
51
|
-
/// * `threshold` - Custom threshold to use instead of the configured one
|
|
52
|
-
///
|
|
53
|
-
/// # Panics
|
|
54
|
-
/// If fewer than `threshold` valid signatures from registered signers are provided.
|
|
55
|
-
fn verify_n_signatures(env: &Env, hash: &BytesN<32>, signatures: &Vec<BytesN<SIGNATURE_LENGTH>>, threshold: u32);
|
|
56
|
-
}
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
//! Multisig functionality for the DVN contract.
|
|
2
|
-
//!
|
|
3
|
-
//! Provides secp256k1-based multisig signature verification using Ethereum-style
|
|
4
|
-
//! 20-byte addresses derived from recovered public keys.
|
|
5
|
-
|
|
6
|
-
use super::*;
|
|
7
|
-
|
|
8
|
-
use crate::{
|
|
9
|
-
errors::DvnError,
|
|
10
|
-
events::{SignerSet, ThresholdSet},
|
|
11
|
-
storage::DvnStorage,
|
|
12
|
-
};
|
|
13
|
-
use common_macros::only_owner;
|
|
14
|
-
use soroban_sdk::assert_with_error;
|
|
15
|
-
|
|
16
|
-
// ============================================================================
|
|
17
|
-
// IMultisig Implementation
|
|
18
|
-
// ============================================================================
|
|
19
|
-
|
|
20
|
-
#[contract_impl]
|
|
21
|
-
impl IMultisig for LzDVN {
|
|
22
|
-
/// Adds or removes a signer. Requires multisig approval.
|
|
23
|
-
#[only_owner]
|
|
24
|
-
fn set_signer(env: &Env, signer: &BytesN<20>, active: bool) {
|
|
25
|
-
if active {
|
|
26
|
-
Self::add_signer(env, signer);
|
|
27
|
-
} else {
|
|
28
|
-
Self::remove_signer(env, signer);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/// Updates the signature threshold. Requires multisig approval.
|
|
33
|
-
#[only_owner]
|
|
34
|
-
fn set_threshold(env: &Env, threshold: u32) {
|
|
35
|
-
assert_with_error!(env, threshold > 0, DvnError::ZeroThreshold);
|
|
36
|
-
assert_with_error!(env, Self::total_signers(env) >= threshold, DvnError::TotalSignersLessThanThreshold);
|
|
37
|
-
|
|
38
|
-
DvnStorage::set_threshold(env, &threshold);
|
|
39
|
-
|
|
40
|
-
ThresholdSet { threshold }.publish(env);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// ================================================================
|
|
44
|
-
// View Functions
|
|
45
|
-
// ================================================================
|
|
46
|
-
|
|
47
|
-
/// Returns the list of all registered signers.
|
|
48
|
-
fn get_signers(env: &Env) -> Vec<BytesN<20>> {
|
|
49
|
-
DvnStorage::signers(env)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/// Returns the total number of registered signers.
|
|
53
|
-
fn total_signers(env: &Env) -> u32 {
|
|
54
|
-
DvnStorage::signers(env).len()
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/// Checks if an address is a registered signer.
|
|
58
|
-
fn is_signer(env: &Env, signer: &BytesN<20>) -> bool {
|
|
59
|
-
DvnStorage::signers(env).iter().any(|s| &s == signer)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/// Returns the current signature threshold.
|
|
63
|
-
fn threshold(env: &Env) -> u32 {
|
|
64
|
-
DvnStorage::threshold(env)
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/// Verifies signatures against the current threshold.
|
|
68
|
-
fn verify_signatures(env: &Env, hash: &BytesN<32>, signatures: &Vec<BytesN<65>>) {
|
|
69
|
-
Self::verify_n_signatures(env, hash, signatures, Self::threshold(env));
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/// Verifies that at least `threshold` valid signatures exist for the given hash.
|
|
73
|
-
///
|
|
74
|
-
/// Signatures must be:
|
|
75
|
-
/// - From registered signers
|
|
76
|
-
/// - Sorted by signer address (ascending, no duplicates)
|
|
77
|
-
fn verify_n_signatures(env: &Env, hash: &BytesN<32>, signatures: &Vec<BytesN<65>>, threshold: u32) {
|
|
78
|
-
assert_with_error!(env, threshold > 0, DvnError::ZeroThreshold);
|
|
79
|
-
assert_with_error!(env, signatures.len() >= threshold, DvnError::SignatureError);
|
|
80
|
-
|
|
81
|
-
let mut last_signer: Option<BytesN<20>> = None;
|
|
82
|
-
signatures.iter().for_each(|signature| {
|
|
83
|
-
let signer = Self::recover_signer(env, hash, &signature);
|
|
84
|
-
|
|
85
|
-
// Signers must be strictly increasing (ensures no duplicates)
|
|
86
|
-
assert_with_error!(env, last_signer.as_ref().is_none_or(|last| &signer > last), DvnError::UnsortedSigners);
|
|
87
|
-
assert_with_error!(env, Self::is_signer(env, &signer), DvnError::SignerNotFound);
|
|
88
|
-
|
|
89
|
-
last_signer = Some(signer);
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// ============================================================================
|
|
95
|
-
// Internal Functions
|
|
96
|
-
// ============================================================================
|
|
97
|
-
|
|
98
|
-
impl LzDVN {
|
|
99
|
-
/// Initializes the multisig with a set of signers and threshold.
|
|
100
|
-
/// Called during contract construction.
|
|
101
|
-
pub(super) fn init_multisig(env: &Env, signers: &Vec<BytesN<20>>, threshold: u32) {
|
|
102
|
-
signers.iter().for_each(|signer| Self::add_signer(env, &signer));
|
|
103
|
-
Self::set_threshold(env, threshold);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/// Adds a new signer to the multisig.
|
|
107
|
-
///
|
|
108
|
-
/// # Errors
|
|
109
|
-
/// - `InvalidSigner` if the signer is the zero address
|
|
110
|
-
/// - `SignerAlreadyExists` if the signer is already registered
|
|
111
|
-
fn add_signer(env: &Env, signer: &BytesN<20>) {
|
|
112
|
-
let zero_signer = BytesN::from_array(env, &[0u8; 20]);
|
|
113
|
-
assert_with_error!(env, signer != &zero_signer, DvnError::InvalidSigner);
|
|
114
|
-
|
|
115
|
-
let mut signers = Self::get_signers(env);
|
|
116
|
-
assert_with_error!(env, !signers.iter().any(|s| &s == signer), DvnError::SignerAlreadyExists);
|
|
117
|
-
signers.push_back(signer.clone());
|
|
118
|
-
DvnStorage::set_signers(env, &signers);
|
|
119
|
-
|
|
120
|
-
SignerSet { signer: signer.clone(), active: true }.publish(env);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/// Removes a signer from the multisig.
|
|
124
|
-
///
|
|
125
|
-
/// # Errors
|
|
126
|
-
/// - `SignerNotFound` if the signer is not registered
|
|
127
|
-
/// - `TotalSignersLessThanThreshold` if removal would violate threshold constraint
|
|
128
|
-
fn remove_signer(env: &Env, signer: &BytesN<20>) {
|
|
129
|
-
let mut signers = Self::get_signers(env);
|
|
130
|
-
let index = signers.first_index_of(signer);
|
|
131
|
-
assert_with_error!(env, index.is_some(), DvnError::SignerNotFound);
|
|
132
|
-
|
|
133
|
-
signers.remove(index.unwrap());
|
|
134
|
-
|
|
135
|
-
// Ensure removal doesn't violate threshold constraint
|
|
136
|
-
assert_with_error!(env, signers.len() >= Self::threshold(env), DvnError::TotalSignersLessThanThreshold);
|
|
137
|
-
DvnStorage::set_signers(env, &signers);
|
|
138
|
-
|
|
139
|
-
SignerSet { signer: signer.clone(), active: false }.publish(env);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/// Recovers the Ethereum-style signer address from a secp256k1 signature.
|
|
143
|
-
///
|
|
144
|
-
/// The signature format is 65 bytes: r (32) + s (32) + v (1).
|
|
145
|
-
/// Returns the last 20 bytes of keccak256(uncompressed_pubkey[1..65]).
|
|
146
|
-
fn recover_signer(env: &Env, digest: &BytesN<32>, signature: &BytesN<65>) -> BytesN<20> {
|
|
147
|
-
let sig_bytes: Bytes = signature.into();
|
|
148
|
-
let v = sig_bytes.get(64).unwrap();
|
|
149
|
-
let recovery_id = if (27..=30).contains(&v) { v - 27 } else { v };
|
|
150
|
-
let sig_rs: BytesN<64> = sig_bytes.slice(0..64).try_into().unwrap();
|
|
151
|
-
|
|
152
|
-
let public_key = env.crypto_hazmat().secp256k1_recover(digest, &sig_rs, recovery_id as u32);
|
|
153
|
-
|
|
154
|
-
// Derive Ethereum address: keccak256(pubkey[1..65])[12..32]
|
|
155
|
-
Bytes::from(env.crypto().keccak256(&Bytes::from(public_key).slice(1..65))).slice(12..32).try_into().unwrap()
|
|
156
|
-
}
|
|
157
|
-
}
|