@layerzerolabs/protocol-stellar-v2 0.2.8 → 0.2.10
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 +443 -302
- package/.turbo/turbo-lint.log +118 -96
- package/.turbo/turbo-test.log +853 -731
- package/Cargo.lock +120 -37
- package/Cargo.toml +8 -5
- package/contracts/common-macros/src/contract_impl.rs +44 -0
- package/contracts/common-macros/src/lib.rs +86 -40
- package/contracts/common-macros/src/ownable.rs +24 -32
- package/contracts/common-macros/src/storage.rs +95 -120
- package/contracts/common-macros/src/tests/contract_impl.rs +289 -0
- package/contracts/common-macros/src/tests/mod.rs +9 -0
- package/contracts/common-macros/src/tests/ownable.rs +151 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__contract_impl__snapshot_generated_contract_impl_code.snap +85 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_generated_ownable_code.snap +30 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ownable__snapshot_only_owner_preserves_function_signature.snap +9 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__storage__snapshot_generated_storage_code.snap +1072 -0
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +45 -0
- package/contracts/common-macros/src/tests/storage.rs +485 -0
- package/contracts/common-macros/src/tests/test_helpers.rs +93 -0
- package/contracts/common-macros/src/tests/ttl_configurable.rs +34 -0
- package/contracts/common-macros/src/ttl_configurable.rs +31 -14
- package/contracts/common-macros/src/utils.rs +27 -0
- package/contracts/endpoint-v2/ARCHITECTURE.md +4 -4
- package/contracts/endpoint-v2/src/endpoint_v2.rs +18 -15
- package/contracts/endpoint-v2/src/interfaces/message_lib.rs +2 -3
- package/contracts/endpoint-v2/src/interfaces/message_lib_manager.rs +5 -3
- 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 +4 -4
- package/contracts/endpoint-v2/src/lib.rs +6 -5
- package/contracts/endpoint-v2/src/message_lib_manager.rs +14 -6
- package/contracts/endpoint-v2/src/messaging_channel.rs +6 -2
- package/contracts/endpoint-v2/src/messaging_composer.rs +6 -2
- package/contracts/endpoint-v2/src/storage.rs +10 -7
- package/contracts/endpoint-v2/src/tests/endpoint_v2/pay_messaging_fees.rs +16 -16
- package/contracts/endpoint-v2/src/tests/endpoint_v2/ttl_config.rs +46 -46
- package/contracts/endpoint-v2/src/tests/mock.rs +2 -2
- package/contracts/endpoint-v2/src/util.rs +8 -2
- package/contracts/message-libs/block-message-lib/Cargo.toml +1 -0
- package/contracts/message-libs/block-message-lib/src/lib.rs +5 -5
- package/contracts/message-libs/message-lib-common/src/errors.rs +8 -8
- package/contracts/message-libs/message-lib-common/src/interfaces/dvn.rs +0 -1
- package/contracts/message-libs/message-lib-common/src/interfaces/mod.rs +3 -3
- package/contracts/message-libs/message-lib-common/src/lib.rs +0 -2
- package/contracts/message-libs/message-lib-common/src/packet_codec_v1.rs +4 -6
- package/contracts/message-libs/message-lib-common/src/tests/packet_codec_v1.rs +2 -2
- package/contracts/message-libs/message-lib-common/src/tests/worker_options.rs +11 -11
- package/contracts/message-libs/message-lib-common/src/worker_options.rs +10 -16
- package/contracts/message-libs/simple-message-lib/src/errors.rs +0 -4
- package/contracts/message-libs/simple-message-lib/src/simple_message_lib.rs +49 -34
- package/contracts/message-libs/simple-message-lib/src/storage.rs +3 -7
- package/contracts/message-libs/simple-message-lib/src/test.rs +3 -3
- package/contracts/message-libs/treasury/src/storage.rs +1 -2
- package/contracts/message-libs/treasury/src/tests/setup.rs +3 -2
- package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +0 -13
- package/contracts/message-libs/treasury/src/treasury.rs +18 -21
- package/contracts/message-libs/uln-302/Cargo.toml +1 -0
- package/contracts/message-libs/uln-302/src/interfaces/mod.rs +4 -4
- package/contracts/message-libs/uln-302/src/interfaces/{receive.rs → receive_uln.rs} +3 -3
- package/contracts/message-libs/uln-302/src/interfaces/{send.rs → send_uln.rs} +8 -80
- package/contracts/message-libs/uln-302/src/lib.rs +5 -4
- package/contracts/message-libs/uln-302/src/{receive.rs → receive_uln.rs} +20 -12
- package/contracts/message-libs/uln-302/src/{send.rs → send_uln.rs} +19 -13
- package/contracts/message-libs/uln-302/src/storage.rs +1 -2
- package/contracts/message-libs/uln-302/src/tests/config/uln_config.rs +3 -2
- package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +30 -30
- package/contracts/message-libs/uln-302/src/tests/setup.rs +12 -11
- package/contracts/message-libs/uln-302/src/tests/uln302/set_config.rs +1 -1
- package/contracts/message-libs/uln-302/src/{config_validation.rs → types.rs} +79 -11
- package/contracts/message-libs/uln-302/src/uln302.rs +15 -10
- package/contracts/oapp-macros/Cargo.toml +2 -8
- package/contracts/oapp-macros/src/lib.rs +57 -311
- package/contracts/oapp-macros/src/oapp_core.rs +23 -32
- package/contracts/oapp-macros/src/oapp_full.rs +8 -2
- package/contracts/oapp-macros/src/oapp_options_type3.rs +21 -36
- package/contracts/oapp-macros/src/oapp_receiver.rs +38 -57
- package/contracts/oapp-macros/src/oapp_sender.rs +12 -14
- package/contracts/oapp-macros/src/util.rs +14 -10
- package/contracts/oapps/counter/Cargo.toml +2 -1
- package/contracts/oapps/counter/integration_tests/utils.rs +4 -4
- package/contracts/oapps/counter/src/codec.rs +8 -9
- package/contracts/oapps/counter/src/counter.rs +156 -147
- package/contracts/oapps/counter/src/storage.rs +1 -2
- package/contracts/oapps/counter/src/tests/test_codec.rs +5 -5
- package/contracts/oapps/counter/src/tests/test_counter.rs +11 -13
- package/contracts/oapps/oapp/Cargo.toml +1 -0
- package/contracts/oapps/oapp/src/errors.rs +1 -1
- package/contracts/oapps/oapp/src/lib.rs +3 -0
- package/contracts/oapps/oapp/src/macro_tests/mod.rs +1 -0
- package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +312 -0
- package/contracts/oapps/oapp/src/oapp_core.rs +52 -53
- package/contracts/oapps/oapp/src/oapp_options_type3.rs +18 -28
- package/contracts/oapps/oapp/src/oapp_receiver.rs +82 -31
- package/contracts/oapps/oapp/src/oapp_sender.rs +55 -13
- package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +16 -3
- package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +33 -8
- package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +6 -9
- package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +28 -15
- package/contracts/oapps/oft/Cargo.toml +27 -0
- package/contracts/oapps/oft/integration-tests/mod.rs +3 -0
- package/contracts/oapps/oft/integration-tests/setup.rs +320 -0
- package/contracts/oapps/oft/integration-tests/test_with_sml.rs +155 -0
- package/contracts/oapps/oft/integration-tests/utils.rs +201 -0
- package/contracts/oapps/oft/src/codec/mod.rs +2 -0
- package/contracts/oapps/oft/src/codec/oft_compose_msg_codec.rs +55 -0
- package/contracts/oapps/oft/src/codec/oft_msg_codec.rs +62 -0
- package/contracts/oapps/oft/src/constants.rs +5 -0
- package/contracts/oapps/oft/src/errors.rs +8 -0
- package/contracts/oapps/oft/src/events.rs +19 -0
- package/contracts/oapps/oft/src/interfaces/mint_burn_token.rs +23 -0
- package/contracts/oapps/oft/src/interfaces/mod.rs +3 -0
- package/contracts/oapps/oft/src/lib.rs +22 -0
- package/contracts/oapps/oft/src/macro_tests/mod.rs +2 -0
- package/contracts/oapps/oft/src/macro_tests/test_all_default.rs +41 -0
- package/contracts/oapps/oft/src/macro_tests/test_override.rs +83 -0
- package/contracts/oapps/oft/src/oft.rs +320 -0
- package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +50 -0
- package/contracts/oapps/oft/src/oft_types/mint_burn.rs +50 -0
- package/contracts/oapps/oft/src/oft_types/mod.rs +10 -0
- package/contracts/oapps/oft/src/storage.rs +11 -0
- package/contracts/oapps/oft/src/tests/mod.rs +13 -0
- package/contracts/oapps/oft/src/tests/test_decimals.rs +89 -0
- package/contracts/oapps/oft/src/tests/test_lz_receive.rs +282 -0
- package/contracts/oapps/oft/src/tests/test_oft_compose_msg_codec.rs +68 -0
- package/contracts/oapps/oft/src/tests/test_oft_msg_codec.rs +136 -0
- package/contracts/oapps/oft/src/tests/test_oft_version.rs +13 -0
- package/contracts/oapps/oft/src/tests/test_quote_oft.rs +159 -0
- package/contracts/oapps/oft/src/tests/test_quote_send.rs +195 -0
- package/contracts/oapps/oft/src/tests/test_resolve_address.rs +37 -0
- package/contracts/oapps/oft/src/tests/test_send.rs +915 -0
- package/contracts/oapps/oft/src/tests/test_token.rs +47 -0
- package/contracts/oapps/oft/src/tests/test_utils.rs +789 -0
- package/contracts/oapps/oft/src/types.rs +38 -0
- package/contracts/oapps/oft/src/utils.rs +67 -0
- package/contracts/oapps/oft-mint-burn/Cargo.toml +26 -0
- package/contracts/oapps/oft-mint-burn/src/lib.rs +3 -0
- package/contracts/oapps/oft-mint-burn/src/oft.rs +28 -0
- package/contracts/oapps/oft-mint-burn/src/tests/mod.rs +1 -0
- package/contracts/utils/src/buffer_reader.rs +8 -9
- package/contracts/utils/src/buffer_writer.rs +11 -5
- package/contracts/utils/src/errors.rs +5 -5
- package/contracts/utils/src/ownable.rs +14 -6
- package/contracts/utils/src/testing_utils.rs +11 -1
- package/contracts/utils/src/tests/buffer_reader.rs +491 -730
- package/contracts/utils/src/tests/buffer_writer.rs +336 -148
- package/contracts/utils/src/tests/bytes_ext.rs +125 -40
- package/contracts/utils/src/tests/mod.rs +3 -0
- package/contracts/utils/src/tests/ownable.rs +379 -27
- package/contracts/utils/src/tests/test_helper.rs +47 -0
- package/contracts/utils/src/tests/testing_utils.rs +555 -0
- package/contracts/utils/src/tests/ttl.rs +421 -0
- package/contracts/utils/src/ttl.rs +29 -89
- package/contracts/workers/dvn/Cargo.toml +31 -0
- package/contracts/workers/dvn/src/auth.rs +66 -0
- package/contracts/workers/dvn/src/dvn.rs +143 -0
- package/contracts/workers/dvn/src/errors.rs +21 -0
- package/contracts/workers/dvn/src/events.rs +19 -0
- package/contracts/workers/dvn/src/interfaces/dvn.rs +12 -0
- package/contracts/workers/dvn/src/interfaces/mod.rs +5 -0
- package/contracts/workers/dvn/src/interfaces/multisig.rs +15 -0
- package/contracts/workers/dvn/src/lib.rs +24 -0
- package/contracts/workers/dvn/src/multisig.rs +127 -0
- package/contracts/workers/dvn/src/storage.rs +35 -0
- package/contracts/workers/dvn/src/tests/auth.rs +237 -0
- package/contracts/workers/dvn/src/tests/dvn.rs +349 -0
- package/contracts/workers/dvn/src/tests/key_pair.rs +66 -0
- package/contracts/workers/dvn/src/tests/mod.rs +5 -0
- package/contracts/workers/dvn/src/tests/multisig/mod.rs +3 -0
- package/contracts/workers/dvn/src/tests/multisig/set_signer.rs +133 -0
- package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +108 -0
- package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +109 -0
- package/contracts/workers/dvn/src/tests/setup.rs +109 -0
- package/contracts/workers/dvn/src/types.rs +26 -0
- package/contracts/workers/dvn-fee-lib/Cargo.toml +24 -0
- package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +113 -0
- package/contracts/workers/dvn-fee-lib/src/errors.rs +8 -0
- package/contracts/workers/dvn-fee-lib/src/lib.rs +17 -0
- package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +282 -0
- package/contracts/workers/dvn-fee-lib/src/tests/mod.rs +1 -0
- package/contracts/workers/executor/Cargo.toml +10 -7
- package/contracts/workers/executor/src/errors.rs +8 -0
- package/contracts/workers/executor/src/events.rs +4 -7
- package/contracts/workers/executor/src/interfaces/executor.rs +72 -22
- package/contracts/workers/executor/src/interfaces/mod.rs +0 -2
- package/contracts/workers/executor/src/lib.rs +16 -7
- package/contracts/workers/executor/src/lz_executor.rs +308 -0
- package/contracts/workers/executor/src/storage.rs +24 -16
- package/contracts/workers/executor-fee-lib/Cargo.toml +22 -0
- package/contracts/workers/executor-fee-lib/src/errors.rs +15 -0
- package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +215 -0
- package/contracts/workers/executor-fee-lib/src/executor_option.rs +203 -0
- package/contracts/workers/executor-fee-lib/src/lib.rs +7 -0
- package/contracts/workers/executor-helper/Cargo.toml +29 -0
- package/contracts/workers/executor-helper/src/executor_helper.rs +161 -0
- package/contracts/workers/executor-helper/src/lib.rs +11 -0
- package/contracts/workers/{worker-common → worker}/Cargo.toml +1 -4
- package/contracts/workers/worker/src/errors.rs +24 -0
- package/contracts/workers/worker/src/events.rs +62 -0
- package/contracts/workers/worker/src/interfaces/dvn_fee_lib.rs +75 -0
- package/contracts/workers/worker/src/interfaces/executor_fee_lib.rs +84 -0
- package/contracts/workers/{worker-common → worker}/src/interfaces/mod.rs +2 -2
- package/contracts/workers/worker/src/interfaces/price_feed.rs +85 -0
- package/contracts/workers/worker/src/lib.rs +14 -0
- package/contracts/workers/worker/src/storage.rs +63 -0
- package/contracts/workers/worker/src/worker.rs +459 -0
- package/package.json +3 -3
- package/sdk/dist/generated/bml.d.ts +88 -17
- package/sdk/dist/generated/bml.js +62 -16
- package/sdk/dist/generated/counter.d.ts +281 -102
- package/sdk/dist/generated/counter.js +93 -41
- package/sdk/dist/generated/endpoint.d.ts +128 -105
- package/sdk/dist/generated/endpoint.js +47 -45
- package/sdk/dist/generated/sml.d.ts +212 -69
- package/sdk/dist/generated/sml.js +103 -53
- package/sdk/dist/generated/uln302.d.ts +270 -173
- package/sdk/dist/generated/uln302.js +112 -64
- package/sdk/package.json +11 -11
- package/sdk/test/index.test.ts +147 -42
- package/sdk/test/suites/constants.ts +7 -3
- package/sdk/test/suites/deploy.ts +65 -42
- package/sdk/test/suites/localnet.ts +2 -2
- package/sdk/test/suites/scan.ts +28 -25
- package/sdk/test/utils.ts +199 -0
- package/sdk/tsconfig.json +93 -95
- package/tools/ts-bindings-gen/src/main.rs +2 -0
- package/contracts/common-macros/src/snapshots/common_macros__tests__tests__snapshot_generated_storage_code.snap +0 -310
- package/contracts/common-macros/src/tests.rs +0 -287
- package/contracts/oapp-macros/tests/test_macros.rs +0 -522
- package/contracts/workers/executor/src/executor.rs +0 -347
- package/contracts/workers/executor/src/interfaces/types.rs +0 -51
- package/contracts/workers/worker-common/src/constants.rs +0 -17
- package/contracts/workers/worker-common/src/errors.rs +0 -6
- package/contracts/workers/worker-common/src/events.rs +0 -34
- package/contracts/workers/worker-common/src/interfaces/executor_fee_lib.rs +0 -35
- package/contracts/workers/worker-common/src/interfaces/price_feed.rs +0 -40
- package/contracts/workers/worker-common/src/interfaces/worker.rs +0 -60
- package/contracts/workers/worker-common/src/lib.rs +0 -19
- package/contracts/workers/worker-common/src/storage.rs +0 -32
- package/contracts/workers/worker-common/src/worker_common.rs +0 -166
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
use crate::{errors::ExecutorFeeLibError, executor_option};
|
|
2
|
+
use common_macros::contract_impl;
|
|
3
|
+
use soroban_sdk::{assert_with_error, contract, Address, Bytes, Env};
|
|
4
|
+
use worker::{FeeParams, IExecutorFeeLib, LayerZeroPriceFeedClient};
|
|
5
|
+
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Constants
|
|
8
|
+
// ============================================================================
|
|
9
|
+
|
|
10
|
+
/// V1 endpoint ID threshold. EIDs below this are V1 endpoints with restrictions.
|
|
11
|
+
const V1_EID_THRESHOLD: u32 = 30000;
|
|
12
|
+
|
|
13
|
+
/// Basis points denominator (10000 = 100%).
|
|
14
|
+
const BPS_DENOMINATOR: i128 = 10000;
|
|
15
|
+
|
|
16
|
+
/// Overhead percentage for ordered execution (102 = 2% overhead).
|
|
17
|
+
const ORDERED_EXECUTION_OVERHEAD_PERCENT: u128 = 102;
|
|
18
|
+
|
|
19
|
+
/// Native token decimal rate for XLM (10^7 stroops per XLM).
|
|
20
|
+
const NATIVE_DECIMALS_RATE: u128 = 10_000_000;
|
|
21
|
+
|
|
22
|
+
/// ExecutorFeeLib contract for calculating executor fees.
|
|
23
|
+
///
|
|
24
|
+
/// Provides fee calculation logic based on executor options, destination configuration,
|
|
25
|
+
/// and current gas prices from the price feed. Handles fee multipliers, margins, and
|
|
26
|
+
/// native token value conversions.
|
|
27
|
+
#[contract]
|
|
28
|
+
pub struct ExecutorFeeLib;
|
|
29
|
+
|
|
30
|
+
#[contract_impl]
|
|
31
|
+
impl ExecutorFeeLib {
|
|
32
|
+
// ========================================================================
|
|
33
|
+
// Internal Functions
|
|
34
|
+
// ========================================================================
|
|
35
|
+
|
|
36
|
+
/// Decodes executor options and calculates total gas and native value.
|
|
37
|
+
///
|
|
38
|
+
/// Parses encoded executor options, accumulates gas requirements (including
|
|
39
|
+
/// compose calls and ordered execution overhead), and returns the total native
|
|
40
|
+
/// value and gas needed.
|
|
41
|
+
///
|
|
42
|
+
/// # Arguments
|
|
43
|
+
/// * `options` - Encoded executor options bytes
|
|
44
|
+
/// * `dst_eid` - Destination endpoint ID
|
|
45
|
+
/// * `lz_receive_base_gas` - Base gas for lzReceive execution
|
|
46
|
+
/// * `lz_compose_base_gas` - Base gas per lzCompose call
|
|
47
|
+
/// * `native_cap` - Maximum allowed native token value
|
|
48
|
+
///
|
|
49
|
+
/// # Returns
|
|
50
|
+
/// Tuple of (total_native_value, total_gas).
|
|
51
|
+
fn decode_executor_options(
|
|
52
|
+
env: &Env,
|
|
53
|
+
options: &Bytes,
|
|
54
|
+
dst_eid: u32,
|
|
55
|
+
lz_receive_base_gas: u64,
|
|
56
|
+
lz_compose_base_gas: u64,
|
|
57
|
+
native_cap: u128,
|
|
58
|
+
) -> (u128, u128) {
|
|
59
|
+
let options_agg = executor_option::parse_executor_options(env, options, Self::is_v1_eid(dst_eid), native_cap);
|
|
60
|
+
|
|
61
|
+
let mut total_gas = (lz_receive_base_gas as u128)
|
|
62
|
+
+ options_agg.total_gas
|
|
63
|
+
+ ((lz_compose_base_gas as u128) * (options_agg.num_lz_compose as u128));
|
|
64
|
+
|
|
65
|
+
if options_agg.ordered {
|
|
66
|
+
total_gas = (total_gas * ORDERED_EXECUTION_OVERHEAD_PERCENT) / 100;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
(options_agg.total_value, total_gas)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/// Returns the effective multiplier in basis points.
|
|
73
|
+
///
|
|
74
|
+
/// Uses destination-specific multiplier if set, otherwise falls back to default multiplier.
|
|
75
|
+
///
|
|
76
|
+
/// # Arguments
|
|
77
|
+
/// * `params` - Fee parameters containing multiplier settings
|
|
78
|
+
///
|
|
79
|
+
/// # Returns
|
|
80
|
+
/// Effective multiplier in basis points.
|
|
81
|
+
fn get_effective_multiplier_bps(params: &FeeParams) -> u32 {
|
|
82
|
+
if params.multiplier_bps == 0 {
|
|
83
|
+
params.default_multiplier_bps
|
|
84
|
+
} else {
|
|
85
|
+
params.multiplier_bps
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/// Applies premium (multiplier and margin) to gas fee.
|
|
90
|
+
///
|
|
91
|
+
/// Calculates fee with multiplier and floor margin, returning the maximum of both
|
|
92
|
+
/// to ensure profitability.
|
|
93
|
+
///
|
|
94
|
+
/// # Arguments
|
|
95
|
+
/// * `fee` - Base gas fee
|
|
96
|
+
/// * `multiplier_bps` - Fee multiplier in basis points
|
|
97
|
+
/// * `margin_usd` - Minimum margin in USD (scaled)
|
|
98
|
+
/// * `native_price_usd` - Native token price in USD (scaled)
|
|
99
|
+
///
|
|
100
|
+
/// # Returns
|
|
101
|
+
/// Fee with premium applied (max of multiplier fee and margin fee).
|
|
102
|
+
fn apply_premium_to_gas(fee: i128, multiplier_bps: u32, margin_usd: u128, native_price_usd: u128) -> i128 {
|
|
103
|
+
let fee_with_multiplier = (fee * multiplier_bps as i128) / BPS_DENOMINATOR;
|
|
104
|
+
|
|
105
|
+
if native_price_usd == 0 || margin_usd == 0 {
|
|
106
|
+
return fee_with_multiplier;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
let fee_with_margin = ((margin_usd * NATIVE_DECIMALS_RATE) / native_price_usd) as i128 + fee;
|
|
110
|
+
|
|
111
|
+
fee_with_margin.max(fee_with_multiplier)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/// Converts native value and applies premium multiplier.
|
|
115
|
+
///
|
|
116
|
+
/// Converts value using price ratio and applies multiplier in basis points.
|
|
117
|
+
///
|
|
118
|
+
/// # Arguments
|
|
119
|
+
/// * `value` - Native value to convert
|
|
120
|
+
/// * `ratio` - Price ratio numerator
|
|
121
|
+
/// * `denom` - Price ratio denominator
|
|
122
|
+
/// * `multiplier_bps` - Fee multiplier in basis points
|
|
123
|
+
///
|
|
124
|
+
/// # Returns
|
|
125
|
+
/// Converted and multiplied value, or 0 if input value is 0.
|
|
126
|
+
fn convert_and_apply_premium_to_value(value: u128, ratio: u128, denom: u128, multiplier_bps: u32) -> i128 {
|
|
127
|
+
if value == 0 {
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
let converted = (value * ratio) / denom;
|
|
131
|
+
((converted * multiplier_bps as u128) / BPS_DENOMINATOR as u128) as i128
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/// Checks if an endpoint ID is a V1 endpoint.
|
|
135
|
+
///
|
|
136
|
+
/// V1 endpoints (EID < 30000) have restrictions on executor options.
|
|
137
|
+
///
|
|
138
|
+
/// # Arguments
|
|
139
|
+
/// * `eid` - Endpoint ID to check
|
|
140
|
+
///
|
|
141
|
+
/// # Returns
|
|
142
|
+
/// `true` if the endpoint is a V1 endpoint, `false` otherwise.
|
|
143
|
+
fn is_v1_eid(eid: u32) -> bool {
|
|
144
|
+
eid < V1_EID_THRESHOLD
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// ============================================================================
|
|
149
|
+
// IExecutorFeeLib Implementation
|
|
150
|
+
// ============================================================================
|
|
151
|
+
|
|
152
|
+
#[contract_impl]
|
|
153
|
+
impl IExecutorFeeLib for ExecutorFeeLib {
|
|
154
|
+
/// Calculates the total execution fee for a cross-chain message.
|
|
155
|
+
///
|
|
156
|
+
/// Decodes executor options, estimates gas fees from the price feed, applies
|
|
157
|
+
/// multipliers and margins, and converts native token values. Returns the
|
|
158
|
+
/// total fee in native tokens.
|
|
159
|
+
///
|
|
160
|
+
/// # Arguments
|
|
161
|
+
/// * `executor` - Executor contract address (unused, kept for interface compatibility)
|
|
162
|
+
/// * `params` - Fee calculation parameters
|
|
163
|
+
///
|
|
164
|
+
/// # Returns
|
|
165
|
+
/// Total execution fee in native tokens.
|
|
166
|
+
///
|
|
167
|
+
/// # Errors
|
|
168
|
+
/// * `EidNotSupported` - If destination endpoint is not supported (lz_receive_base_gas is 0)
|
|
169
|
+
/// * Various executor option parsing errors (see `parse_executor_options`)
|
|
170
|
+
fn get_fee(env: &Env, _executor: &Address, params: &FeeParams) -> i128 {
|
|
171
|
+
assert_with_error!(env, params.lz_receive_base_gas != 0, ExecutorFeeLibError::EidNotSupported);
|
|
172
|
+
|
|
173
|
+
let (total_value, total_gas) = Self::decode_executor_options(
|
|
174
|
+
env,
|
|
175
|
+
¶ms.options,
|
|
176
|
+
params.dst_eid,
|
|
177
|
+
params.lz_receive_base_gas,
|
|
178
|
+
params.lz_compose_base_gas,
|
|
179
|
+
params.native_cap,
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
let fee_estimate = LayerZeroPriceFeedClient::new(env, ¶ms.price_feed).estimate_fee_by_eid(
|
|
183
|
+
&env.current_contract_address(),
|
|
184
|
+
¶ms.dst_eid,
|
|
185
|
+
¶ms.calldata_size,
|
|
186
|
+
&total_gas,
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
let multiplier_bps = Self::get_effective_multiplier_bps(params);
|
|
190
|
+
|
|
191
|
+
let mut fee = Self::apply_premium_to_gas(
|
|
192
|
+
fee_estimate.total_gas_fee,
|
|
193
|
+
multiplier_bps,
|
|
194
|
+
params.floor_margin_usd,
|
|
195
|
+
fee_estimate.native_price_usd,
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
fee += Self::convert_and_apply_premium_to_value(
|
|
199
|
+
total_value,
|
|
200
|
+
fee_estimate.price_ratio,
|
|
201
|
+
fee_estimate.price_ratio_denominator,
|
|
202
|
+
multiplier_bps,
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
fee
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/// Returns the version of the fee library.
|
|
209
|
+
///
|
|
210
|
+
/// # Returns
|
|
211
|
+
/// Tuple of (major_version, minor_version).
|
|
212
|
+
fn version(_env: &Env) -> (u64, u32) {
|
|
213
|
+
(1, 1)
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
use crate::errors::ExecutorFeeLibError;
|
|
2
|
+
use message_lib_common::worker_options::{EXECUTOR_OPTION_TYPE_LZRECEIVE, EXECUTOR_OPTION_TYPE_NATIVE_DROP};
|
|
3
|
+
use soroban_sdk::{assert_with_error, panic_with_error, Bytes, BytesN, Env};
|
|
4
|
+
use utils::buffer_reader::BufferReader;
|
|
5
|
+
|
|
6
|
+
pub const EXECUTOR_OPTION_TYPE_LZCOMPOSE: u8 = 3;
|
|
7
|
+
pub const EXECUTOR_OPTION_TYPE_ORDERED_EXECUTION: u8 = 4;
|
|
8
|
+
|
|
9
|
+
/// Aggregated executor options parsed from encoded option bytes.
|
|
10
|
+
///
|
|
11
|
+
/// Contains the accumulated values from all executor options for fee calculation.
|
|
12
|
+
/// This structure is built by iterating through all encoded options and summing
|
|
13
|
+
/// gas requirements and native token values.
|
|
14
|
+
pub struct ExecutorOptionsAgg {
|
|
15
|
+
/// Total native token value to transfer (from lzReceive value + nativeDrop + lzCompose value).
|
|
16
|
+
pub total_value: u128,
|
|
17
|
+
/// Total gas required (from lzReceive gas + lzCompose gas).
|
|
18
|
+
pub total_gas: u128,
|
|
19
|
+
/// Whether ordered execution is requested (messages must be delivered in sequence).
|
|
20
|
+
pub ordered: bool,
|
|
21
|
+
/// Number of lzCompose calls to execute.
|
|
22
|
+
pub num_lz_compose: u64,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// ============================================================================
|
|
26
|
+
// Main Parsing Function
|
|
27
|
+
// ============================================================================
|
|
28
|
+
|
|
29
|
+
/// Parses executor options from encoded bytes and returns aggregated values.
|
|
30
|
+
///
|
|
31
|
+
/// Iterates through all encoded options, decoding each based on its type and
|
|
32
|
+
/// accumulating gas, value, and other parameters for fee calculation.
|
|
33
|
+
///
|
|
34
|
+
/// # Arguments
|
|
35
|
+
/// * `options` - Encoded executor options bytes
|
|
36
|
+
/// * `is_v1_eid` - Whether destination is a V1 endpoint (< 30000), which has restrictions
|
|
37
|
+
/// * `native_cap` - Maximum allowed native token value transfer
|
|
38
|
+
///
|
|
39
|
+
/// # Returns
|
|
40
|
+
/// `ExecutorOptionsAgg` containing accumulated gas, value, compose count, and ordered flag.
|
|
41
|
+
///
|
|
42
|
+
/// # Errors
|
|
43
|
+
/// * `NoOptions` - If options bytes are empty
|
|
44
|
+
/// * `UnsupportedOptionType` - If an unknown option type is encountered or V1 restrictions violated
|
|
45
|
+
/// * `ZeroLzReceiveGasProvided` - If no lzReceive gas is specified
|
|
46
|
+
/// * `ZeroLzComposeGasProvided` - If lzCompose has zero gas
|
|
47
|
+
/// * `NativeAmountExceedsCap` - If total native value exceeds the cap
|
|
48
|
+
pub fn parse_executor_options(env: &Env, options: &Bytes, is_v1_eid: bool, native_cap: u128) -> ExecutorOptionsAgg {
|
|
49
|
+
// Assert that options are not empty (No executor options provided)
|
|
50
|
+
assert_with_error!(env, !options.is_empty(), ExecutorFeeLibError::NoOptions);
|
|
51
|
+
|
|
52
|
+
let mut reader = BufferReader::new(options);
|
|
53
|
+
|
|
54
|
+
let mut agg_options = ExecutorOptionsAgg { total_value: 0, total_gas: 0, ordered: false, num_lz_compose: 0 };
|
|
55
|
+
|
|
56
|
+
let mut lz_receive_gas: u128 = 0;
|
|
57
|
+
|
|
58
|
+
while reader.remaining_len() > 0 {
|
|
59
|
+
let (option_type, option_data) = next_executor_option(&mut reader);
|
|
60
|
+
|
|
61
|
+
match option_type {
|
|
62
|
+
EXECUTOR_OPTION_TYPE_LZRECEIVE => {
|
|
63
|
+
let (gas, value) = decode_lz_receive_option(env, &option_data);
|
|
64
|
+
// endpoint v1 does not support lzReceive with value
|
|
65
|
+
assert_with_error!(env, !(is_v1_eid && value > 0), ExecutorFeeLibError::UnsupportedOptionType);
|
|
66
|
+
lz_receive_gas += gas;
|
|
67
|
+
agg_options.total_value += value;
|
|
68
|
+
}
|
|
69
|
+
EXECUTOR_OPTION_TYPE_NATIVE_DROP => {
|
|
70
|
+
let (amount, _) = decode_native_drop_option(env, &option_data);
|
|
71
|
+
agg_options.total_value += amount;
|
|
72
|
+
}
|
|
73
|
+
EXECUTOR_OPTION_TYPE_LZCOMPOSE => {
|
|
74
|
+
// endpoint v1 does not support lzCompose
|
|
75
|
+
assert_with_error!(env, !is_v1_eid, ExecutorFeeLibError::UnsupportedOptionType);
|
|
76
|
+
let (_, gas, value) = decode_lz_compose_option(env, &option_data);
|
|
77
|
+
assert_with_error!(env, gas != 0, ExecutorFeeLibError::ZeroLzComposeGasProvided);
|
|
78
|
+
agg_options.total_gas += gas;
|
|
79
|
+
agg_options.total_value += value;
|
|
80
|
+
agg_options.num_lz_compose += 1;
|
|
81
|
+
}
|
|
82
|
+
EXECUTOR_OPTION_TYPE_ORDERED_EXECUTION => {
|
|
83
|
+
assert_with_error!(env, option_data.is_empty(), ExecutorFeeLibError::InvalidExecutorOptions);
|
|
84
|
+
agg_options.ordered = true;
|
|
85
|
+
}
|
|
86
|
+
_ => {
|
|
87
|
+
panic_with_error!(env, ExecutorFeeLibError::UnsupportedOptionType);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Validate
|
|
93
|
+
assert_with_error!(env, agg_options.total_value <= native_cap, ExecutorFeeLibError::NativeAmountExceedsCap);
|
|
94
|
+
assert_with_error!(env, lz_receive_gas != 0, ExecutorFeeLibError::ZeroLzReceiveGasProvided);
|
|
95
|
+
|
|
96
|
+
agg_options.total_gas += lz_receive_gas;
|
|
97
|
+
agg_options
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ============================================================================
|
|
101
|
+
// Option Extraction
|
|
102
|
+
// ============================================================================
|
|
103
|
+
|
|
104
|
+
/// Extracts the next executor option from the options byte stream.
|
|
105
|
+
///
|
|
106
|
+
/// Option format: [worker_id: u8][option_size: u16][option_type: u8][option_data: bytes]
|
|
107
|
+
///
|
|
108
|
+
/// Parses the binary format to extract the option type and data, skipping the worker_id
|
|
109
|
+
/// which identifies which worker this option is intended for.
|
|
110
|
+
///
|
|
111
|
+
/// # Arguments
|
|
112
|
+
/// * `reader` - Buffer reader positioned at the start of an option
|
|
113
|
+
///
|
|
114
|
+
/// # Returns
|
|
115
|
+
/// Tuple of (option_type, option_data) where option_data excludes the option_type byte.
|
|
116
|
+
fn next_executor_option(reader: &mut BufferReader) -> (u8, Bytes) {
|
|
117
|
+
// Skip worker_id (1 byte) - identifies which worker this option is for
|
|
118
|
+
let _worker_id = reader.read_u8();
|
|
119
|
+
|
|
120
|
+
// Read option_size (2 bytes) - includes option_type + option_data
|
|
121
|
+
let option_size = reader.read_u16();
|
|
122
|
+
|
|
123
|
+
// Read option_type (1 byte)
|
|
124
|
+
let option_type = reader.read_u8();
|
|
125
|
+
|
|
126
|
+
// Read option_data (option_size - 1 bytes, since option_size includes option_type)
|
|
127
|
+
let option_data = reader.read_bytes((option_size - 1) as u32);
|
|
128
|
+
|
|
129
|
+
(option_type, option_data)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ============================================================================
|
|
133
|
+
// Option Decoding Functions
|
|
134
|
+
// ============================================================================
|
|
135
|
+
|
|
136
|
+
/// Decodes an lzReceive option.
|
|
137
|
+
///
|
|
138
|
+
/// Format: [gas: u128] (16 bytes) or [gas: u128][value: u128] (32 bytes)
|
|
139
|
+
///
|
|
140
|
+
/// # Arguments
|
|
141
|
+
/// * `option` - The option data bytes (without option_type)
|
|
142
|
+
///
|
|
143
|
+
/// # Returns
|
|
144
|
+
/// Tuple of (gas, value) where value is 0 if not specified.
|
|
145
|
+
///
|
|
146
|
+
/// # Errors
|
|
147
|
+
/// * `InvalidLzReceiveOption` - If option length is not 16 or 32 bytes.
|
|
148
|
+
fn decode_lz_receive_option(env: &Env, option: &Bytes) -> (u128, u128) {
|
|
149
|
+
let len = option.len();
|
|
150
|
+
assert_with_error!(env, len == 16 || len == 32, ExecutorFeeLibError::InvalidLzReceiveOption);
|
|
151
|
+
|
|
152
|
+
let mut reader = BufferReader::new(option);
|
|
153
|
+
let gas = reader.read_u128();
|
|
154
|
+
let value = if len == 32 { reader.read_u128() } else { 0 };
|
|
155
|
+
|
|
156
|
+
(gas, value)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/// Decodes a native drop option.
|
|
160
|
+
///
|
|
161
|
+
/// Format: [amount: u128][receiver: bytes32] (48 bytes)
|
|
162
|
+
///
|
|
163
|
+
/// # Arguments
|
|
164
|
+
/// * `option` - The option data bytes (without option_type)
|
|
165
|
+
///
|
|
166
|
+
/// # Returns
|
|
167
|
+
/// Tuple of (amount, receiver) for the native token transfer.
|
|
168
|
+
///
|
|
169
|
+
/// # Errors
|
|
170
|
+
/// * `InvalidNativeDropOption` - If option length is not 48 bytes.
|
|
171
|
+
fn decode_native_drop_option(env: &Env, option: &Bytes) -> (u128, BytesN<32>) {
|
|
172
|
+
assert_with_error!(env, option.len() == 48, ExecutorFeeLibError::InvalidNativeDropOption);
|
|
173
|
+
|
|
174
|
+
let mut reader = BufferReader::new(option);
|
|
175
|
+
let amount = reader.read_u128();
|
|
176
|
+
let receiver = reader.read_bytes_n::<32>();
|
|
177
|
+
|
|
178
|
+
(amount, receiver)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/// Decodes an lzCompose option.
|
|
182
|
+
///
|
|
183
|
+
/// Format: [index: u16][gas: u128] (18 bytes) or [index: u16][gas: u128][value: u128] (34 bytes)
|
|
184
|
+
///
|
|
185
|
+
/// # Arguments
|
|
186
|
+
/// * `option` - The option data bytes (without option_type)
|
|
187
|
+
///
|
|
188
|
+
/// # Returns
|
|
189
|
+
/// Tuple of (index, gas, value) where value is 0 if not specified.
|
|
190
|
+
///
|
|
191
|
+
/// # Errors
|
|
192
|
+
/// * `InvalidLzComposeOption` - If option length is not 18 or 34 bytes.
|
|
193
|
+
fn decode_lz_compose_option(env: &Env, option: &Bytes) -> (u16, u128, u128) {
|
|
194
|
+
let len = option.len();
|
|
195
|
+
assert_with_error!(env, len == 18 || len == 34, ExecutorFeeLibError::InvalidLzComposeOption);
|
|
196
|
+
|
|
197
|
+
let mut reader = BufferReader::new(option);
|
|
198
|
+
let index = reader.read_u16();
|
|
199
|
+
let gas = reader.read_u128();
|
|
200
|
+
let value = if len == 34 { reader.read_u128() } else { 0 };
|
|
201
|
+
|
|
202
|
+
(index, gas, value)
|
|
203
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "executor-helper"
|
|
3
|
+
version.workspace = true
|
|
4
|
+
edition.workspace = true
|
|
5
|
+
license.workspace = true
|
|
6
|
+
publish = false
|
|
7
|
+
|
|
8
|
+
[lib]
|
|
9
|
+
crate-type = ["cdylib"]
|
|
10
|
+
doctest = false
|
|
11
|
+
|
|
12
|
+
[features]
|
|
13
|
+
library = []
|
|
14
|
+
testutils = []
|
|
15
|
+
|
|
16
|
+
[dependencies]
|
|
17
|
+
cfg-if = { workspace = true }
|
|
18
|
+
soroban-sdk = { workspace = true }
|
|
19
|
+
# workspace dependencies
|
|
20
|
+
common-macros = { workspace = true }
|
|
21
|
+
utils = { workspace = true }
|
|
22
|
+
worker = { workspace = true }
|
|
23
|
+
endpoint-v2 = { workspace = true, features = ["library"] }
|
|
24
|
+
executor = { workspace = true, features = ["library"] }
|
|
25
|
+
|
|
26
|
+
[dev-dependencies]
|
|
27
|
+
soroban-sdk = { workspace = true, features = ["testutils"] }
|
|
28
|
+
|
|
29
|
+
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
//! ABA-safe entry point for cross-chain message execution on Stellar.
|
|
2
|
+
//! Prevents reentry into the Executor during OApp Atomic Batch Actions.
|
|
3
|
+
|
|
4
|
+
use endpoint_v2::{
|
|
5
|
+
LayerZeroComposerClient, LayerZeroEndpointV2Client, LayerZeroReceiverClient, MessagingComposerClient, Origin,
|
|
6
|
+
};
|
|
7
|
+
use executor::{ExecutorClient, NativeDropParams};
|
|
8
|
+
use common_macros::contract_impl;
|
|
9
|
+
use soroban_sdk::{contract, contracttype, token::TokenClient, Address, Bytes, BytesN, Env, Vec};
|
|
10
|
+
|
|
11
|
+
/// Parameters for `lz_receive` execution.
|
|
12
|
+
#[contracttype]
|
|
13
|
+
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
14
|
+
pub struct ExecutionParams {
|
|
15
|
+
pub receiver: Address,
|
|
16
|
+
pub origin: Origin,
|
|
17
|
+
pub guid: BytesN<32>,
|
|
18
|
+
pub message: Bytes,
|
|
19
|
+
pub extra_data: Bytes,
|
|
20
|
+
pub value: i128,
|
|
21
|
+
pub gas_limit: i128,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/// Parameters for `lz_compose` execution.
|
|
25
|
+
#[contracttype]
|
|
26
|
+
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
27
|
+
pub struct ComposeParams {
|
|
28
|
+
pub from: Address,
|
|
29
|
+
pub to: Address,
|
|
30
|
+
pub guid: BytesN<32>,
|
|
31
|
+
pub index: u32,
|
|
32
|
+
pub message: Bytes,
|
|
33
|
+
pub extra_data: Bytes,
|
|
34
|
+
pub value: i128,
|
|
35
|
+
pub gas_limit: i128,
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
#[contract]
|
|
39
|
+
pub struct ExecutorHelper;
|
|
40
|
+
|
|
41
|
+
#[contract_impl]
|
|
42
|
+
impl ExecutorHelper {
|
|
43
|
+
/// Executes `lz_receive` on the target OApp; falls back to `lz_receive_alert` on failure.
|
|
44
|
+
pub fn execute(env: &Env, executor: &Address, params: &ExecutionParams, value_payer: &Address) {
|
|
45
|
+
if params.value > 0 {
|
|
46
|
+
value_payer.require_auth();
|
|
47
|
+
}
|
|
48
|
+
Self::execute_internal(env, executor, params, value_payer);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/// Executes `lz_compose` on the target composer; falls back to `lz_compose_alert` on failure.
|
|
52
|
+
pub fn compose(env: &Env, executor: &Address, params: &ComposeParams, value_payer: &Address) {
|
|
53
|
+
executor.require_auth();
|
|
54
|
+
|
|
55
|
+
let endpoint = if params.value > 0 {
|
|
56
|
+
let ep = ExecutorClient::new(env, executor).endpoint();
|
|
57
|
+
value_payer.require_auth();
|
|
58
|
+
transfer_value(env, &ep, value_payer, executor, params.value);
|
|
59
|
+
Some(ep)
|
|
60
|
+
} else {
|
|
61
|
+
None
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
let result = LayerZeroComposerClient::new(env, ¶ms.to).try_lz_compose(
|
|
65
|
+
executor,
|
|
66
|
+
¶ms.from,
|
|
67
|
+
¶ms.guid,
|
|
68
|
+
¶ms.index,
|
|
69
|
+
¶ms.message,
|
|
70
|
+
¶ms.extra_data,
|
|
71
|
+
¶ms.value,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
if result.is_err() {
|
|
75
|
+
let ep = endpoint.unwrap_or_else(|| ExecutorClient::new(env, executor).endpoint());
|
|
76
|
+
MessagingComposerClient::new(env, &ep).lz_compose_alert(
|
|
77
|
+
executor,
|
|
78
|
+
¶ms.from,
|
|
79
|
+
¶ms.to,
|
|
80
|
+
¶ms.guid,
|
|
81
|
+
¶ms.index,
|
|
82
|
+
¶ms.gas_limit,
|
|
83
|
+
¶ms.value,
|
|
84
|
+
¶ms.message,
|
|
85
|
+
¶ms.extra_data,
|
|
86
|
+
&Bytes::new(env),
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/// Delegates `native_drop` to the executor contract.
|
|
92
|
+
pub fn native_drop(
|
|
93
|
+
env: &Env,
|
|
94
|
+
executor: &Address,
|
|
95
|
+
admin: &Address,
|
|
96
|
+
origin: &Origin,
|
|
97
|
+
dst_eid: u32,
|
|
98
|
+
oapp: &Address,
|
|
99
|
+
params: &Vec<NativeDropParams>,
|
|
100
|
+
) {
|
|
101
|
+
admin.require_auth();
|
|
102
|
+
ExecutorClient::new(env, executor).native_drop(admin, origin, &dst_eid, oapp, params);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/// Executes `native_drop` followed by `lz_receive`.
|
|
106
|
+
pub fn native_drop_and_execute(
|
|
107
|
+
env: &Env,
|
|
108
|
+
executor: &Address,
|
|
109
|
+
admin: &Address,
|
|
110
|
+
origin: &Origin,
|
|
111
|
+
dst_eid: u32,
|
|
112
|
+
oapp: &Address,
|
|
113
|
+
native_drop_params: &Vec<NativeDropParams>,
|
|
114
|
+
execute_params: &ExecutionParams,
|
|
115
|
+
) {
|
|
116
|
+
Self::native_drop(env, executor, admin, origin, dst_eid, oapp, native_drop_params);
|
|
117
|
+
Self::execute_internal(env, executor, execute_params, admin); // admin already authed above
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
fn execute_internal(env: &Env, executor: &Address, params: &ExecutionParams, value_payer: &Address) {
|
|
121
|
+
executor.require_auth();
|
|
122
|
+
|
|
123
|
+
let endpoint = if params.value > 0 {
|
|
124
|
+
let ep = ExecutorClient::new(env, executor).endpoint();
|
|
125
|
+
transfer_value(env, &ep, value_payer, executor, params.value);
|
|
126
|
+
Some(ep)
|
|
127
|
+
} else {
|
|
128
|
+
None
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
let result = LayerZeroReceiverClient::new(env, ¶ms.receiver).try_lz_receive(
|
|
132
|
+
executor,
|
|
133
|
+
¶ms.origin,
|
|
134
|
+
¶ms.guid,
|
|
135
|
+
¶ms.message,
|
|
136
|
+
¶ms.extra_data,
|
|
137
|
+
¶ms.value,
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
if result.is_err() {
|
|
141
|
+
let ep = endpoint.unwrap_or_else(|| ExecutorClient::new(env, executor).endpoint());
|
|
142
|
+
LayerZeroEndpointV2Client::new(env, &ep).lz_receive_alert(
|
|
143
|
+
executor,
|
|
144
|
+
¶ms.origin,
|
|
145
|
+
¶ms.receiver,
|
|
146
|
+
¶ms.guid,
|
|
147
|
+
¶ms.gas_limit,
|
|
148
|
+
¶ms.value,
|
|
149
|
+
¶ms.message,
|
|
150
|
+
¶ms.extra_data,
|
|
151
|
+
&Bytes::new(env),
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
#[inline]
|
|
158
|
+
fn transfer_value(env: &Env, endpoint: &Address, payer: &Address, executor: &Address, value: i128) {
|
|
159
|
+
let native_token = LayerZeroEndpointV2Client::new(env, endpoint).native_token();
|
|
160
|
+
TokenClient::new(env, &native_token).transfer(payer, executor, &value);
|
|
161
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#![no_std]
|
|
2
|
+
|
|
3
|
+
mod executor_helper;
|
|
4
|
+
|
|
5
|
+
cfg_if::cfg_if! {
|
|
6
|
+
// Include implementation when NOT in library mode, OR when testutils is enabled (for tests)
|
|
7
|
+
if #[cfg(any(not(feature = "library"), feature = "testutils"))] {
|
|
8
|
+
|
|
9
|
+
pub use executor_helper::*;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
[package]
|
|
2
|
-
name = "worker
|
|
2
|
+
name = "worker"
|
|
3
3
|
version.workspace = true
|
|
4
4
|
edition.workspace = true
|
|
5
5
|
license.workspace = true
|
|
@@ -13,6 +13,3 @@ doctest = false
|
|
|
13
13
|
soroban-sdk = { workspace = true }
|
|
14
14
|
utils = { workspace = true }
|
|
15
15
|
common-macros = { workspace = true }
|
|
16
|
-
stellar-access = { workspace = true }
|
|
17
|
-
stellar-macros = { workspace = true }
|
|
18
|
-
stellar-contract-utils = { workspace = true }
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
use common_macros::contract_error;
|
|
2
|
+
|
|
3
|
+
#[contract_error]
|
|
4
|
+
pub enum WorkerError {
|
|
5
|
+
AdminAlreadyExists = 1200,
|
|
6
|
+
AdminNotFound,
|
|
7
|
+
AlreadyOnAllowlist,
|
|
8
|
+
AlreadyOnDenylist,
|
|
9
|
+
AttemptingToRemoveOnlyAdmin,
|
|
10
|
+
DepositAddressNotSet,
|
|
11
|
+
MessageLibAlreadySupported,
|
|
12
|
+
MessageLibNotSupported,
|
|
13
|
+
NoAdminsProvided,
|
|
14
|
+
NotAllowed,
|
|
15
|
+
NotOnAllowlist,
|
|
16
|
+
NotOnDenylist,
|
|
17
|
+
PauseStatusUnchanged,
|
|
18
|
+
PriceFeedNotSet,
|
|
19
|
+
ReInitialize,
|
|
20
|
+
Unauthorized,
|
|
21
|
+
UnsupportedMessageLib,
|
|
22
|
+
WorkerFeeLibNotSet,
|
|
23
|
+
WorkerIsPaused,
|
|
24
|
+
}
|