@layerzerolabs/protocol-stellar-v2 0.2.20 → 0.2.22
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 +783 -802
- package/.turbo/turbo-lint.log +320 -157
- package/.turbo/turbo-test.log +1414 -1457
- package/Cargo.lock +109 -108
- package/Cargo.toml +32 -18
- package/contracts/common-macros/Cargo.toml +7 -7
- package/contracts/common-macros/src/auth.rs +18 -37
- package/contracts/common-macros/src/contract_ttl.rs +2 -2
- package/contracts/common-macros/src/lib.rs +27 -10
- package/contracts/common-macros/src/lz_contract.rs +38 -7
- package/contracts/common-macros/src/storage.rs +251 -292
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_multisig_code.snap +6 -12
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__auth__snapshot_generated_ownable_code.snap +12 -17
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__ttl_configurable__snapshot_generated_ttl_configurable_code.snap +2 -7
- package/contracts/common-macros/src/tests/snapshots/common_macros__tests__upgradeable__snapshot_generated_upgradeable_code.snap +20 -9
- package/contracts/common-macros/src/tests/upgradeable.rs +26 -4
- package/contracts/common-macros/src/ttl_configurable.rs +2 -10
- package/contracts/common-macros/src/ttl_extendable.rs +2 -10
- package/contracts/common-macros/src/upgradeable.rs +56 -15
- package/contracts/common-macros/src/utils.rs +0 -9
- package/contracts/endpoint-v2/src/lib.rs +3 -2
- package/contracts/endpoint-v2/src/tests/endpoint_v2/clear.rs +2 -2
- package/contracts/endpoint-v2/src/tests/endpoint_v2/lz_receive_alert.rs +3 -3
- package/contracts/endpoint-v2/src/tests/endpoint_v2/send.rs +4 -4
- package/contracts/endpoint-v2/src/tests/endpoint_v2/set_delegate.rs +17 -5
- package/contracts/endpoint-v2/src/tests/endpoint_v2/set_zro.rs +4 -4
- package/contracts/endpoint-v2/src/tests/endpoint_v2/verify.rs +2 -2
- package/contracts/endpoint-v2/src/tests/message_lib_manager/register_library.rs +2 -2
- package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_lib_timeout.rs +6 -6
- package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_receive_library.rs +67 -37
- package/contracts/endpoint-v2/src/tests/message_lib_manager/set_default_send_library.rs +5 -5
- package/contracts/endpoint-v2/src/tests/message_lib_manager/set_receive_library.rs +44 -54
- package/contracts/endpoint-v2/src/tests/message_lib_manager/set_receive_library_timeout.rs +7 -7
- package/contracts/endpoint-v2/src/tests/message_lib_manager/set_send_library.rs +8 -8
- package/contracts/endpoint-v2/src/tests/messaging_channel/burn.rs +3 -3
- package/contracts/endpoint-v2/src/tests/messaging_channel/nilify.rs +4 -4
- package/contracts/endpoint-v2/src/tests/messaging_channel/skip.rs +3 -3
- package/contracts/endpoint-v2/src/tests/messaging_composer/clear_compose.rs +2 -2
- package/contracts/endpoint-v2/src/tests/messaging_composer/lz_compose_alert.rs +3 -3
- package/contracts/endpoint-v2/src/tests/messaging_composer/send_compose.rs +2 -2
- package/contracts/layerzero-views/Cargo.toml +0 -1
- package/contracts/layerzero-views/src/layerzero_view.rs +1 -13
- package/contracts/macro-integration-tests/Cargo.toml +5 -15
- package/contracts/macro-integration-tests/tests/runtime/oapp/mod.rs +48 -0
- package/contracts/macro-integration-tests/tests/runtime/oapp/oapp_core.rs +170 -0
- package/contracts/macro-integration-tests/tests/runtime/oapp/options_type3.rs +154 -0
- package/contracts/macro-integration-tests/tests/runtime/oapp/receiver.rs +338 -0
- package/contracts/macro-integration-tests/tests/runtime/oapp/sender.rs +435 -0
- package/contracts/macro-integration-tests/tests/runtime.rs +1 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/custom_wrong_value.rs +8 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/custom_wrong_value.stderr +5 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/missing_lz_receive_internal.rs +8 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/missing_lz_receive_internal.stderr +71 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/non_struct_input.rs +10 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/non_struct_input.stderr +5 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/unknown_custom_option.rs +8 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/unknown_custom_option.stderr +5 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/wrong_key.rs +8 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/fail/wrong_key.stderr +5 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/pass/custom_all.rs +38 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/pass/custom_single_trait.rs +96 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/pass/minimal_contract.rs +64 -0
- package/contracts/macro-integration-tests/tests/ui/oapp/pass/struct_with_fields.rs +46 -0
- package/contracts/macro-integration-tests/tests/ui/ownable/fail/only_auth_missing_env.stderr +8 -0
- package/contracts/macro-integration-tests/tests/ui/ownable/pass/namespacing_and_imports.rs +1 -1
- package/contracts/macro-integration-tests/tests/ui/ownable/pass/only_auth_env_param_variants.rs +1 -1
- package/contracts/macro-integration-tests/tests/ui_oapp.rs +11 -0
- package/contracts/message-libs/message-lib-common/Cargo.toml +0 -1
- package/contracts/message-libs/message-lib-common/src/errors.rs +1 -1
- package/contracts/message-libs/treasury/Cargo.toml +0 -2
- package/contracts/message-libs/treasury/src/tests/treasury_tests.rs +2 -2
- package/contracts/message-libs/uln-302/src/tests/receive_uln302/effective_receive_uln_config.rs +2 -2
- package/contracts/message-libs/uln-302/src/tests/receive_uln302/set_default_receive_uln_configs.rs +2 -2
- package/contracts/message-libs/uln-302/src/tests/receive_uln302/verify.rs +2 -2
- package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_executor_config.rs +2 -2
- package/contracts/message-libs/uln-302/src/tests/send_uln302/effective_send_uln_config.rs +2 -2
- package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +7 -27
- package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_executor_configs.rs +2 -2
- package/contracts/message-libs/uln-302/src/tests/send_uln302/set_default_send_uln_configs.rs +2 -2
- package/contracts/oapps/counter/Cargo.toml +4 -6
- package/contracts/oapps/counter/integration_tests/utils.rs +19 -12
- package/contracts/oapps/oapp/src/errors.rs +1 -1
- package/contracts/oapps/oapp/src/interfaces/mod.rs +3 -0
- package/contracts/oapps/oapp/src/interfaces/oapp_msg_inspector.rs +47 -0
- package/contracts/oapps/oapp/src/lib.rs +1 -0
- package/contracts/oapps/oapp/src/macro_tests/test_macros.rs +4 -4
- package/contracts/oapps/oapp/src/oapp_core.rs +5 -5
- package/contracts/oapps/oapp/src/oapp_options_type3.rs +12 -4
- package/contracts/oapps/oapp/src/oapp_receiver.rs +14 -9
- package/contracts/oapps/oapp/src/tests/mod.rs +4 -4
- package/contracts/oapps/oapp/src/tests/{test_oapp_core.rs → oapp_core.rs} +4 -4
- package/contracts/oapps/oapp/src/tests/{test_oapp_options_type3.rs → oapp_options_type3.rs} +3 -4
- package/contracts/oapps/oapp-macros/Cargo.toml +8 -4
- package/contracts/oapps/oapp-macros/src/generators.rs +9 -34
- package/contracts/oapps/oapp-macros/src/lib.rs +3 -0
- package/contracts/oapps/oapp-macros/src/tests/mod.rs +2 -0
- package/contracts/oapps/oapp-macros/src/tests/oapp.rs +88 -0
- package/contracts/oapps/oapp-macros/src/tests/parse_custom_impls.rs +86 -0
- package/contracts/oapps/oapp-macros/src/tests/snapshots/oapp_macros__tests__oapp__snapshot_generate_oapp.snap +103 -0
- package/contracts/oapps/oft/integration-tests/utils.rs +28 -8
- package/contracts/oapps/oft/src/extensions/oft_fee.rs +136 -74
- package/contracts/oapps/oft/src/extensions/pausable.rs +44 -10
- package/contracts/oapps/oft/src/extensions/rate_limiter.rs +170 -130
- package/contracts/oapps/oft/src/oft.rs +19 -12
- package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +1 -1
- package/contracts/oapps/oft/src/oft_types/mint_burn.rs +1 -1
- package/contracts/oapps/oft-core/Cargo.toml +1 -4
- package/contracts/oapps/oft-core/integration-tests/setup.rs +2 -2
- package/contracts/oapps/oft-core/integration-tests/utils.rs +21 -3
- package/contracts/oapps/oft-core/src/errors.rs +3 -2
- package/contracts/oapps/oft-core/src/events.rs +6 -0
- package/contracts/oapps/oft-core/src/lib.rs +1 -1
- package/contracts/oapps/oft-core/src/oft_core.rs +115 -60
- package/contracts/oapps/oft-core/src/storage.rs +7 -3
- package/contracts/oapps/oft-core/src/tests/mod.rs +1 -0
- package/contracts/oapps/oft-core/src/tests/test_decimals.rs +37 -2
- package/contracts/oapps/oft-core/src/tests/test_lz_receive.rs +2 -2
- package/contracts/oapps/oft-core/src/tests/test_msg_inspector.rs +323 -0
- package/contracts/oapps/oft-core/src/tests/test_send.rs +2 -2
- package/contracts/oapps/oft-core/src/tests/test_utils.rs +59 -14
- package/contracts/utils/Cargo.toml +0 -1
- package/contracts/utils/src/errors.rs +1 -1
- package/contracts/utils/src/multisig.rs +17 -8
- package/contracts/utils/src/ownable.rs +6 -6
- package/contracts/utils/src/testing_utils.rs +124 -54
- package/contracts/utils/src/tests/multisig.rs +12 -12
- package/contracts/utils/src/tests/ownable.rs +6 -6
- package/contracts/utils/src/tests/testing_utils.rs +50 -167
- package/contracts/utils/src/tests/ttl_configurable.rs +5 -5
- package/contracts/utils/src/tests/upgradeable.rs +1 -1
- package/contracts/utils/src/ttl_configurable.rs +10 -4
- package/contracts/utils/src/upgradeable.rs +5 -5
- package/contracts/workers/dvn/Cargo.toml +5 -6
- package/contracts/workers/dvn/src/dvn.rs +2 -12
- package/contracts/workers/dvn-fee-lib/Cargo.toml +1 -1
- package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +37 -19
- package/contracts/workers/dvn-fee-lib/src/lib.rs +12 -2
- package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +15 -13
- package/contracts/workers/executor/Cargo.toml +3 -0
- package/contracts/workers/executor/src/executor.rs +2 -12
- package/contracts/workers/executor/src/lib.rs +2 -2
- package/contracts/workers/executor/src/tests/auth.rs +394 -0
- package/contracts/workers/executor/src/tests/executor.rs +410 -0
- package/contracts/workers/executor/src/tests/mod.rs +3 -0
- package/contracts/workers/executor/src/tests/setup.rs +250 -0
- package/contracts/workers/executor-fee-lib/Cargo.toml +5 -0
- package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +1 -12
- package/contracts/workers/executor-fee-lib/src/lib.rs +8 -2
- package/contracts/workers/executor-helper/Cargo.toml +0 -1
- package/contracts/workers/price-feed/Cargo.toml +5 -0
- package/contracts/workers/price-feed/src/lib.rs +9 -4
- package/contracts/workers/price-feed/src/price_feed.rs +1 -11
- package/contracts/workers/worker/src/errors.rs +1 -1
- package/contracts/workers/worker/src/tests/setup.rs +1 -1
- package/contracts/workers/worker/src/tests/worker.rs +55 -41
- package/contracts/workers/worker/src/worker.rs +34 -25
- package/docs/error-spec.md +55 -0
- package/docs/layerzero-v2-on-stellar.md +447 -0
- package/docs/oapp-guide.md +212 -0
- package/docs/oft-guide.md +314 -0
- package/package.json +3 -3
- package/sdk/.turbo/turbo-test.log +260 -257
- package/sdk/dist/generated/bml.d.ts +3 -3
- package/sdk/dist/generated/bml.js +4 -4
- package/sdk/dist/generated/counter.d.ts +295 -295
- package/sdk/dist/generated/counter.js +43 -43
- package/sdk/dist/generated/dvn.d.ts +91 -91
- package/sdk/dist/generated/dvn.js +24 -24
- package/sdk/dist/generated/dvn_fee_lib.d.ts +92 -92
- package/sdk/dist/generated/dvn_fee_lib.js +25 -25
- package/sdk/dist/generated/endpoint.d.ts +99 -99
- package/sdk/dist/generated/endpoint.js +16 -16
- package/sdk/dist/generated/executor.d.ts +91 -91
- package/sdk/dist/generated/executor.js +24 -24
- package/sdk/dist/generated/executor_fee_lib.d.ts +92 -92
- package/sdk/dist/generated/executor_fee_lib.js +25 -25
- package/sdk/dist/generated/executor_helper.d.ts +3 -3
- package/sdk/dist/generated/executor_helper.js +4 -4
- package/sdk/dist/generated/layerzero_view.d.ts +186 -186
- package/sdk/dist/generated/layerzero_view.js +35 -35
- package/sdk/dist/generated/oft.d.ts +366 -352
- package/sdk/dist/generated/oft.js +74 -79
- package/sdk/dist/generated/price_feed.d.ts +198 -198
- package/sdk/dist/generated/price_feed.js +39 -39
- package/sdk/dist/generated/sml.d.ts +99 -99
- package/sdk/dist/generated/sml.js +16 -16
- package/sdk/dist/generated/treasury.d.ts +99 -99
- package/sdk/dist/generated/treasury.js +16 -16
- package/sdk/dist/generated/uln302.d.ts +99 -99
- package/sdk/dist/generated/uln302.js +16 -16
- package/sdk/dist/generated/upgrader.d.ts +3 -3
- package/sdk/dist/generated/upgrader.js +3 -3
- package/sdk/package.json +1 -1
- package/sdk/test/suites/localnet.ts +84 -20
- package/contracts/ERROR_SPEC.md +0 -51
- package/contracts/endpoint-v2/ARCHITECTURE.md +0 -233
- /package/contracts/oapps/oapp/src/tests/{test_oapp_receiver.rs → oapp_receiver.rs} +0 -0
- /package/contracts/oapps/oapp/src/tests/{test_oapp_sender.rs → oapp_sender.rs} +0 -0
|
@@ -2,33 +2,32 @@ use crate::errors::DvnFeeLibError;
|
|
|
2
2
|
use common_macros::{contract_impl, lz_contract};
|
|
3
3
|
use fee_lib_interfaces::{DvnFeeParams, IDvnFeeLib, LayerZeroPriceFeedClient};
|
|
4
4
|
use soroban_sdk::{assert_with_error, Address, Env};
|
|
5
|
-
use utils::upgradeable::UpgradeableInternal;
|
|
6
5
|
|
|
7
6
|
// ============================================================================
|
|
8
7
|
// Constants
|
|
9
8
|
// ============================================================================
|
|
10
9
|
|
|
11
10
|
/// Basis points denominator (10000 = 100%).
|
|
12
|
-
|
|
11
|
+
const BPS_BASE: i128 = 10000;
|
|
13
12
|
|
|
14
13
|
/// Fixed bytes for execute function call.
|
|
15
|
-
|
|
14
|
+
const EXECUTE_FIXED_BYTES: u32 = 260;
|
|
16
15
|
|
|
17
16
|
/// Raw signature bytes length (65 bytes: 64 for signature + 1 for recovery ID).
|
|
18
|
-
|
|
17
|
+
const SIGNATURE_RAW_BYTES: u32 = 65;
|
|
19
18
|
|
|
20
19
|
/// Verify function bytes (padded).
|
|
21
|
-
|
|
20
|
+
const VERIFY_BYTES: u32 = 288;
|
|
22
21
|
|
|
23
22
|
/// Native token decimal rate for XLM (10^7 stroops per XLM).
|
|
24
|
-
|
|
23
|
+
const NATIVE_DECIMALS_RATE: u128 = 10_000_000;
|
|
25
24
|
|
|
26
25
|
/// DVN fee library contract for calculating DVN verification fees.
|
|
27
26
|
///
|
|
28
27
|
/// Provides fee calculation logic based on quorum size, destination gas costs,
|
|
29
28
|
/// and current gas prices from the price feed. Handles fee multipliers and
|
|
30
29
|
/// floor margins.
|
|
31
|
-
#[lz_contract(upgradeable)]
|
|
30
|
+
#[lz_contract(upgradeable(no_migration))]
|
|
32
31
|
pub struct DvnFeeLib;
|
|
33
32
|
|
|
34
33
|
#[contract_impl]
|
|
@@ -66,16 +65,6 @@ impl IDvnFeeLib for DvnFeeLib {
|
|
|
66
65
|
}
|
|
67
66
|
}
|
|
68
67
|
|
|
69
|
-
// ============================================================================
|
|
70
|
-
// Upgradeable Implementation
|
|
71
|
-
// ============================================================================
|
|
72
|
-
|
|
73
|
-
/// No migration logic needed for initial upgrade capability
|
|
74
|
-
impl UpgradeableInternal for DvnFeeLib {
|
|
75
|
-
type MigrationData = ();
|
|
76
|
-
fn __migrate(_env: &Env, _migration_data: &Self::MigrationData) {}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
68
|
// ============================================================================
|
|
80
69
|
// Internal Helper Functions
|
|
81
70
|
// ============================================================================
|
|
@@ -94,7 +83,7 @@ impl UpgradeableInternal for DvnFeeLib {
|
|
|
94
83
|
///
|
|
95
84
|
/// # Returns
|
|
96
85
|
/// Fee with premium applied (max of multiplier fee and margin fee).
|
|
97
|
-
|
|
86
|
+
fn apply_premium(
|
|
98
87
|
env: &Env,
|
|
99
88
|
fee: i128,
|
|
100
89
|
multiplier_bps: u32,
|
|
@@ -126,7 +115,7 @@ pub(crate) fn apply_premium(
|
|
|
126
115
|
///
|
|
127
116
|
/// # Returns
|
|
128
117
|
/// Total calldata size in bytes.
|
|
129
|
-
|
|
118
|
+
fn get_call_data_size(quorum: u32) -> u32 {
|
|
130
119
|
let mut total_signature_bytes = quorum * SIGNATURE_RAW_BYTES;
|
|
131
120
|
if !total_signature_bytes.is_multiple_of(32) {
|
|
132
121
|
total_signature_bytes = total_signature_bytes - (total_signature_bytes % 32) + 32;
|
|
@@ -139,3 +128,32 @@ fn safe_u128_to_i128(env: &Env, value: u128) -> i128 {
|
|
|
139
128
|
assert_with_error!(env, value <= i128::MAX as u128, DvnFeeLibError::Overflow);
|
|
140
129
|
value as i128
|
|
141
130
|
}
|
|
131
|
+
|
|
132
|
+
/// Test-only module exposing internal items for unit and integration tests.
|
|
133
|
+
#[cfg(test)]
|
|
134
|
+
pub(crate) mod test {
|
|
135
|
+
use super::*;
|
|
136
|
+
|
|
137
|
+
// Re-export constants for testing
|
|
138
|
+
pub const BPS_BASE: i128 = super::BPS_BASE;
|
|
139
|
+
pub const EXECUTE_FIXED_BYTES: u32 = super::EXECUTE_FIXED_BYTES;
|
|
140
|
+
pub const VERIFY_BYTES: u32 = super::VERIFY_BYTES;
|
|
141
|
+
pub const NATIVE_DECIMALS_RATE: u128 = super::NATIVE_DECIMALS_RATE;
|
|
142
|
+
|
|
143
|
+
/// Test-only wrapper for apply_premium to enable testing.
|
|
144
|
+
pub fn apply_premium_for_test(
|
|
145
|
+
env: &Env,
|
|
146
|
+
fee: i128,
|
|
147
|
+
multiplier_bps: u32,
|
|
148
|
+
default_multiplier_bps: u32,
|
|
149
|
+
floor_margin_usd: u128,
|
|
150
|
+
native_price_usd: u128,
|
|
151
|
+
) -> i128 {
|
|
152
|
+
super::apply_premium(env, fee, multiplier_bps, default_multiplier_bps, floor_margin_usd, native_price_usd)
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/// Test-only wrapper for get_call_data_size to enable testing.
|
|
156
|
+
pub fn get_call_data_size_for_test(quorum: u32) -> u32 {
|
|
157
|
+
super::get_call_data_size(quorum)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
#![no_std]
|
|
2
2
|
|
|
3
|
-
pub mod dvn_fee_lib;
|
|
4
3
|
pub mod errors;
|
|
5
4
|
|
|
6
|
-
|
|
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
|
+
mod dvn_fee_lib;
|
|
9
|
+
// Export the contract and client for testing purposes
|
|
10
|
+
pub use dvn_fee_lib::{DvnFeeLib, DvnFeeLibClient};
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Re-export test helpers module for integration tests
|
|
15
|
+
#[cfg(test)]
|
|
16
|
+
use dvn_fee_lib::test;
|
|
7
17
|
|
|
8
18
|
#[cfg(test)]
|
|
9
19
|
extern crate std;
|
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
use crate::
|
|
2
|
-
|
|
1
|
+
use crate::test::{
|
|
2
|
+
apply_premium_for_test, get_call_data_size_for_test, BPS_BASE, EXECUTE_FIXED_BYTES, NATIVE_DECIMALS_RATE,
|
|
3
|
+
VERIFY_BYTES,
|
|
3
4
|
};
|
|
5
|
+
use crate::DvnFeeLib;
|
|
4
6
|
use fee_lib_interfaces::{DvnFeeParams, FeeEstimate, IDvnFeeLib};
|
|
5
7
|
use soroban_sdk::{contract, contractimpl, testutils::Address as _, Address, Bytes, Env};
|
|
6
8
|
|
|
7
9
|
#[test]
|
|
8
10
|
fn get_call_data_size_pads_signatures() {
|
|
9
|
-
let size =
|
|
11
|
+
let size = get_call_data_size_for_test(1);
|
|
10
12
|
assert_eq!(size, EXECUTE_FIXED_BYTES + VERIFY_BYTES + 96 + 32);
|
|
11
13
|
|
|
12
|
-
let size =
|
|
14
|
+
let size = get_call_data_size_for_test(2);
|
|
13
15
|
assert_eq!(size, EXECUTE_FIXED_BYTES + VERIFY_BYTES + 160 + 32);
|
|
14
16
|
|
|
15
|
-
let size =
|
|
17
|
+
let size = get_call_data_size_for_test(32);
|
|
16
18
|
assert_eq!(size, EXECUTE_FIXED_BYTES + VERIFY_BYTES + 2080 + 32);
|
|
17
19
|
}
|
|
18
20
|
|
|
@@ -22,7 +24,7 @@ fn apply_premium_multiplier_only_both_zero() {
|
|
|
22
24
|
let fee = 1_000i128;
|
|
23
25
|
let multiplier_bps = 15_000u32;
|
|
24
26
|
// multiplier_bps is non-zero, so default_multiplier_bps is ignored
|
|
25
|
-
let result =
|
|
27
|
+
let result = apply_premium_for_test(&env, fee, multiplier_bps, 10_000, 0, 0);
|
|
26
28
|
assert_eq!(result, fee * multiplier_bps as i128 / BPS_BASE);
|
|
27
29
|
}
|
|
28
30
|
|
|
@@ -31,7 +33,7 @@ fn apply_premium_multiplier_only_native_price_zero() {
|
|
|
31
33
|
let env = Env::default();
|
|
32
34
|
let fee = 1_000i128;
|
|
33
35
|
let multiplier_bps = 15_000u32;
|
|
34
|
-
let result =
|
|
36
|
+
let result = apply_premium_for_test(&env, fee, multiplier_bps, 10_000, 100, 0);
|
|
35
37
|
assert_eq!(result, fee * multiplier_bps as i128 / BPS_BASE);
|
|
36
38
|
}
|
|
37
39
|
|
|
@@ -40,7 +42,7 @@ fn apply_premium_multiplier_only_floor_margin_zero() {
|
|
|
40
42
|
let env = Env::default();
|
|
41
43
|
let fee = 1_000i128;
|
|
42
44
|
let multiplier_bps = 15_000u32;
|
|
43
|
-
let result =
|
|
45
|
+
let result = apply_premium_for_test(&env, fee, multiplier_bps, 10_000, 0, NATIVE_DECIMALS_RATE);
|
|
44
46
|
assert_eq!(result, fee * multiplier_bps as i128 / BPS_BASE);
|
|
45
47
|
}
|
|
46
48
|
|
|
@@ -50,7 +52,7 @@ fn apply_premium_uses_default_when_multiplier_zero() {
|
|
|
50
52
|
let fee = 1_000i128;
|
|
51
53
|
let default_bps = 12_000u32;
|
|
52
54
|
// multiplier_bps is 0, so default_multiplier_bps should be used
|
|
53
|
-
let result =
|
|
55
|
+
let result = apply_premium_for_test(&env, fee, 0, default_bps, 0, 0);
|
|
54
56
|
assert_eq!(result, fee * default_bps as i128 / BPS_BASE);
|
|
55
57
|
}
|
|
56
58
|
|
|
@@ -62,7 +64,7 @@ fn apply_premium_floor_margin_wins() {
|
|
|
62
64
|
let floor_margin_usd = 10u128;
|
|
63
65
|
let native_price_usd = NATIVE_DECIMALS_RATE;
|
|
64
66
|
|
|
65
|
-
let result =
|
|
67
|
+
let result = apply_premium_for_test(&env, fee, multiplier_bps, 10_000, floor_margin_usd, native_price_usd);
|
|
66
68
|
assert_eq!(result, fee + floor_margin_usd as i128);
|
|
67
69
|
}
|
|
68
70
|
|
|
@@ -74,7 +76,7 @@ fn apply_premium_multiplier_wins_over_small_floor() {
|
|
|
74
76
|
let floor_margin_usd = 1u128;
|
|
75
77
|
let native_price_usd = NATIVE_DECIMALS_RATE;
|
|
76
78
|
|
|
77
|
-
let result =
|
|
79
|
+
let result = apply_premium_for_test(&env, fee, multiplier_bps, 10_000, floor_margin_usd, native_price_usd);
|
|
78
80
|
assert_eq!(result, 1_200);
|
|
79
81
|
}
|
|
80
82
|
|
|
@@ -281,7 +283,7 @@ fn apply_premium_panics_on_overflow() {
|
|
|
281
283
|
let env = Env::default();
|
|
282
284
|
let fee = i128::MAX / 2;
|
|
283
285
|
let multiplier_bps = 20_000u32;
|
|
284
|
-
|
|
286
|
+
apply_premium_for_test(&env, fee, multiplier_bps, 10_000, u128::MAX, 1);
|
|
285
287
|
}
|
|
286
288
|
|
|
287
289
|
#[test]
|
|
@@ -292,6 +294,6 @@ fn apply_premium_floor_margin_truncates() {
|
|
|
292
294
|
let floor_margin_usd = 1u128;
|
|
293
295
|
let native_price_usd = NATIVE_DECIMALS_RATE * 3 / 2;
|
|
294
296
|
|
|
295
|
-
let result =
|
|
297
|
+
let result = apply_premium_for_test(&env, fee, multiplier_bps, 10_000, floor_margin_usd, native_price_usd);
|
|
296
298
|
assert_eq!(result, 0);
|
|
297
299
|
}
|
|
@@ -26,5 +26,8 @@ endpoint-v2 = { workspace = true, features = ["library"] }
|
|
|
26
26
|
|
|
27
27
|
[dev-dependencies]
|
|
28
28
|
soroban-sdk = { workspace = true, features = ["testutils"] }
|
|
29
|
+
rand = { workspace = true }
|
|
30
|
+
ed25519-dalek = { workspace = true }
|
|
31
|
+
utils = { workspace = true, features = ["testutils"] }
|
|
29
32
|
|
|
30
33
|
|
|
@@ -10,14 +10,14 @@ use endpoint_v2::{FeeRecipient, LayerZeroEndpointV2Client, Origin};
|
|
|
10
10
|
use fee_lib_interfaces::{ExecutorFeeLibClient, FeeParams};
|
|
11
11
|
use message_lib_common::interfaces::ILayerZeroExecutor;
|
|
12
12
|
use soroban_sdk::{token::TokenClient, vec, Address, Bytes, BytesN, Env, Vec};
|
|
13
|
-
use utils::
|
|
13
|
+
use utils::option_ext::OptionExt;
|
|
14
14
|
use worker::{
|
|
15
15
|
assert_acl, assert_not_paused, assert_supported_message_lib, errors::WorkerError, init_worker, require_admin_auth,
|
|
16
16
|
Worker,
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
/// LayerZero Executor contract for cross-chain message execution.
|
|
20
|
-
#[lz_contract(upgradeable)]
|
|
20
|
+
#[lz_contract(upgradeable(no_migration))]
|
|
21
21
|
pub struct LzExecutor;
|
|
22
22
|
|
|
23
23
|
#[contract_impl]
|
|
@@ -194,16 +194,6 @@ impl ILayerZeroExecutor for LzExecutor {
|
|
|
194
194
|
#[contract_impl(contracttrait)]
|
|
195
195
|
impl Worker for LzExecutor {}
|
|
196
196
|
|
|
197
|
-
// ============================================================================
|
|
198
|
-
// Upgradeable Implementation
|
|
199
|
-
// ============================================================================
|
|
200
|
-
|
|
201
|
-
/// No migration logic needed for initial upgrade capability
|
|
202
|
-
impl UpgradeableInternal for LzExecutor {
|
|
203
|
-
type MigrationData = ();
|
|
204
|
-
fn __migrate(_env: &Env, _migration_data: &Self::MigrationData) {}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
197
|
// ============================================================================
|
|
208
198
|
// Include SubModules
|
|
209
199
|
// ============================================================================
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
use super::setup::{Ed25519KeyPair, TestSetup};
|
|
2
|
+
use crate::auth::ExecutorSignature;
|
|
3
|
+
use crate::errors::ExecutorError;
|
|
4
|
+
use soroban_sdk::auth::{Context, ContractContext, CreateContractHostFnContext};
|
|
5
|
+
use soroban_sdk::testutils::Address as _;
|
|
6
|
+
use soroban_sdk::{vec, Address, BytesN, Env, IntoVal, Symbol, Val, Vec};
|
|
7
|
+
|
|
8
|
+
fn mk_sig(setup: &TestSetup<'_>, admin_kp: &Ed25519KeyPair, payload: &BytesN<32>) -> ExecutorSignature {
|
|
9
|
+
ExecutorSignature {
|
|
10
|
+
public_key: admin_kp.public_key(&setup.env),
|
|
11
|
+
signature: admin_kp.sign_payload(&setup.env, payload),
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
fn contract_ctx(env: &Env, contract: Address, fn_name: &str, args: Vec<Val>) -> Context {
|
|
16
|
+
Context::Contract(ContractContext { contract, fn_name: Symbol::new(env, fn_name), args })
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
fn check_auth(
|
|
20
|
+
setup: &TestSetup<'_>,
|
|
21
|
+
payload: &BytesN<32>,
|
|
22
|
+
sig: ExecutorSignature,
|
|
23
|
+
auth_contexts: &Vec<Context>,
|
|
24
|
+
) -> Result<(), Result<ExecutorError, soroban_sdk::InvokeError>> {
|
|
25
|
+
setup.env.try_invoke_contract_check_auth::<ExecutorError>(
|
|
26
|
+
&setup.contract_id,
|
|
27
|
+
payload,
|
|
28
|
+
sig.into_val(&setup.env),
|
|
29
|
+
auth_contexts,
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
#[test]
|
|
34
|
+
fn test_check_auth_allows_lz_receive_value_zero_single_context() {
|
|
35
|
+
let env = Env::default();
|
|
36
|
+
let admin_kp = Ed25519KeyPair::generate();
|
|
37
|
+
let admin_addr = admin_kp.address(&env);
|
|
38
|
+
let setup = TestSetup::new_with_env_and_admin(env, &admin_addr);
|
|
39
|
+
|
|
40
|
+
let payload = BytesN::from_array(&setup.env, &[1u8; 32]);
|
|
41
|
+
let sig = mk_sig(&setup, &admin_kp, &payload);
|
|
42
|
+
|
|
43
|
+
// Executor auth expects `lz_receive`/`lz_compose` contexts and requires the last arg to be `value: i128`.
|
|
44
|
+
// Use value = 0 so only a single context is required.
|
|
45
|
+
let args: Vec<Val> = vec![&setup.env, 0i128.into_val(&setup.env)];
|
|
46
|
+
let oapp = Address::generate(&setup.env);
|
|
47
|
+
let auth_contexts: Vec<Context> = vec![&setup.env, contract_ctx(&setup.env, oapp, "lz_receive", args)];
|
|
48
|
+
|
|
49
|
+
let res = check_auth(&setup, &payload, sig, &auth_contexts);
|
|
50
|
+
assert!(res.is_ok(), "Expected success, got {:?}", res);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
#[test]
|
|
54
|
+
fn test_check_auth_allows_lz_compose_value_zero_single_context() {
|
|
55
|
+
let env = Env::default();
|
|
56
|
+
let admin_kp = Ed25519KeyPair::generate();
|
|
57
|
+
let admin_addr = admin_kp.address(&env);
|
|
58
|
+
let setup = TestSetup::new_with_env_and_admin(env, &admin_addr);
|
|
59
|
+
|
|
60
|
+
let payload = BytesN::from_array(&setup.env, &[1u8; 32]);
|
|
61
|
+
let sig = mk_sig(&setup, &admin_kp, &payload);
|
|
62
|
+
|
|
63
|
+
let args: Vec<Val> = vec![&setup.env, 0i128.into_val(&setup.env)];
|
|
64
|
+
let composer = Address::generate(&setup.env);
|
|
65
|
+
let auth_contexts: Vec<Context> = vec![&setup.env, contract_ctx(&setup.env, composer, "lz_compose", args)];
|
|
66
|
+
|
|
67
|
+
let res = check_auth(&setup, &payload, sig, &auth_contexts);
|
|
68
|
+
assert!(res.is_ok(), "Expected success, got {:?}", res);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
#[test]
|
|
72
|
+
fn test_check_auth_allows_value_transfer_when_value_nonzero() {
|
|
73
|
+
let env = Env::default();
|
|
74
|
+
let admin_kp = Ed25519KeyPair::generate();
|
|
75
|
+
let admin_addr = admin_kp.address(&env);
|
|
76
|
+
let setup = TestSetup::new_with_env_and_admin(env, &admin_addr);
|
|
77
|
+
|
|
78
|
+
let payload = BytesN::from_array(&setup.env, &[1u8; 32]);
|
|
79
|
+
let sig = mk_sig(&setup, &admin_kp, &payload);
|
|
80
|
+
|
|
81
|
+
let value: i128 = 123;
|
|
82
|
+
let oapp = Address::generate(&setup.env);
|
|
83
|
+
let exec_args: Vec<Val> = vec![&setup.env, value.into_val(&setup.env)];
|
|
84
|
+
|
|
85
|
+
let from = Address::generate(&setup.env);
|
|
86
|
+
let to = Address::generate(&setup.env);
|
|
87
|
+
let transfer_args: Vec<Val> =
|
|
88
|
+
vec![&setup.env, from.into_val(&setup.env), to.into_val(&setup.env), value.into_val(&setup.env)];
|
|
89
|
+
|
|
90
|
+
let auth_contexts: Vec<Context> = vec![
|
|
91
|
+
&setup.env,
|
|
92
|
+
contract_ctx(&setup.env, oapp, "lz_receive", exec_args),
|
|
93
|
+
contract_ctx(&setup.env, setup.native_token.clone(), "transfer", transfer_args),
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
let res = check_auth(&setup, &payload, sig, &auth_contexts);
|
|
97
|
+
assert!(res.is_ok(), "Expected success, got {:?}", res);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
#[test]
|
|
101
|
+
fn test_check_auth_allows_alert_calls_only_on_endpoint() {
|
|
102
|
+
let env = Env::default();
|
|
103
|
+
let admin_kp = Ed25519KeyPair::generate();
|
|
104
|
+
let admin_addr = admin_kp.address(&env);
|
|
105
|
+
let setup = TestSetup::new_with_env_and_admin(env, &admin_addr);
|
|
106
|
+
|
|
107
|
+
let payload = BytesN::from_array(&setup.env, &[1u8; 32]);
|
|
108
|
+
let sig = mk_sig(&setup, &admin_kp, &payload);
|
|
109
|
+
|
|
110
|
+
let empty_args: Vec<Val> = Vec::new(&setup.env);
|
|
111
|
+
for fn_name in ["lz_receive_alert", "lz_compose_alert"] {
|
|
112
|
+
let contexts: Vec<Context> =
|
|
113
|
+
vec![&setup.env, contract_ctx(&setup.env, setup.endpoint.clone(), fn_name, empty_args.clone())];
|
|
114
|
+
let res = check_auth(&setup, &payload, sig.clone(), &contexts);
|
|
115
|
+
assert!(res.is_ok(), "Expected success for {fn_name}, got {:?}", res);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
#[test]
|
|
120
|
+
fn test_check_auth_rejects_signature_mismatch() {
|
|
121
|
+
let env = Env::default();
|
|
122
|
+
let admin_kp = Ed25519KeyPair::generate();
|
|
123
|
+
let admin_addr = admin_kp.address(&env);
|
|
124
|
+
let setup = TestSetup::new_with_env_and_admin(env, &admin_addr);
|
|
125
|
+
|
|
126
|
+
let payload = BytesN::from_array(&setup.env, &[1u8; 32]);
|
|
127
|
+
let other_kp = Ed25519KeyPair::generate();
|
|
128
|
+
|
|
129
|
+
// Admin pubkey is registered, but signature is produced by a different key.
|
|
130
|
+
let sig = ExecutorSignature {
|
|
131
|
+
public_key: admin_kp.public_key(&setup.env),
|
|
132
|
+
signature: other_kp.sign_payload(&setup.env, &payload),
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
let oapp = Address::generate(&setup.env);
|
|
136
|
+
let args: Vec<Val> = vec![&setup.env, 0i128.into_val(&setup.env)];
|
|
137
|
+
let contexts: Vec<Context> = vec![&setup.env, contract_ctx(&setup.env, oapp, "lz_receive", args)];
|
|
138
|
+
|
|
139
|
+
let res = check_auth(&setup, &payload, sig, &contexts);
|
|
140
|
+
assert!(matches!(res, Err(Err(_))), "Expected host error, got {:?}", res);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
#[test]
|
|
144
|
+
fn test_check_auth_rejects_non_admin() {
|
|
145
|
+
let env = Env::default();
|
|
146
|
+
let admin_kp = Ed25519KeyPair::generate();
|
|
147
|
+
let admin_addr = admin_kp.address(&env);
|
|
148
|
+
let setup = TestSetup::new_with_env_and_admin(env, &admin_addr);
|
|
149
|
+
|
|
150
|
+
let payload = BytesN::from_array(&setup.env, &[1u8; 32]);
|
|
151
|
+
let oapp = Address::generate(&setup.env);
|
|
152
|
+
let args: Vec<Val> = vec![&setup.env, 0i128.into_val(&setup.env)];
|
|
153
|
+
let contexts: Vec<Context> = vec![&setup.env, contract_ctx(&setup.env, oapp, "lz_receive", args)];
|
|
154
|
+
|
|
155
|
+
// Unauthorized: signer not in admins list
|
|
156
|
+
let non_admin_kp = Ed25519KeyPair::generate();
|
|
157
|
+
let sig = ExecutorSignature {
|
|
158
|
+
public_key: non_admin_kp.public_key(&setup.env),
|
|
159
|
+
signature: non_admin_kp.sign_payload(&setup.env, &payload),
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
let res = check_auth(&setup, &payload, sig, &contexts);
|
|
163
|
+
assert_eq!(res, Err(Ok(ExecutorError::Unauthorized)));
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
#[test]
|
|
167
|
+
fn test_check_auth_rejects_empty_or_too_many_contexts() {
|
|
168
|
+
let env = Env::default();
|
|
169
|
+
let admin_kp = Ed25519KeyPair::generate();
|
|
170
|
+
let admin_addr = admin_kp.address(&env);
|
|
171
|
+
let setup = TestSetup::new_with_env_and_admin(env, &admin_addr);
|
|
172
|
+
|
|
173
|
+
let payload = BytesN::from_array(&setup.env, &[1u8; 32]);
|
|
174
|
+
let sig = mk_sig(&setup, &admin_kp, &payload);
|
|
175
|
+
|
|
176
|
+
// Empty contexts
|
|
177
|
+
let empty: Vec<Context> = Vec::new(&setup.env);
|
|
178
|
+
assert_eq!(check_auth(&setup, &payload, sig.clone(), &empty), Err(Ok(ExecutorError::UnauthorizedContext)));
|
|
179
|
+
|
|
180
|
+
// Too many contexts (>2)
|
|
181
|
+
let oapp = Address::generate(&setup.env);
|
|
182
|
+
let args0: Vec<Val> = vec![&setup.env, 0i128.into_val(&setup.env)];
|
|
183
|
+
let too_many: Vec<Context> = vec![
|
|
184
|
+
&setup.env,
|
|
185
|
+
contract_ctx(&setup.env, oapp.clone(), "lz_receive", args0.clone()),
|
|
186
|
+
contract_ctx(&setup.env, oapp.clone(), "lz_receive", args0.clone()),
|
|
187
|
+
contract_ctx(&setup.env, oapp, "lz_receive", args0),
|
|
188
|
+
];
|
|
189
|
+
assert_eq!(check_auth(&setup, &payload, sig, &too_many), Err(Ok(ExecutorError::UnauthorizedContext)));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
#[test]
|
|
193
|
+
fn test_check_auth_rejects_non_contract_first_context() {
|
|
194
|
+
let env = Env::default();
|
|
195
|
+
let admin_kp = Ed25519KeyPair::generate();
|
|
196
|
+
let admin_addr = admin_kp.address(&env);
|
|
197
|
+
let setup = TestSetup::new_with_env_and_admin(env, &admin_addr);
|
|
198
|
+
|
|
199
|
+
let payload = BytesN::from_array(&setup.env, &[1u8; 32]);
|
|
200
|
+
let sig = mk_sig(&setup, &admin_kp, &payload);
|
|
201
|
+
|
|
202
|
+
let create_ctx: Vec<Context> = vec![
|
|
203
|
+
&setup.env,
|
|
204
|
+
Context::CreateContractHostFn(CreateContractHostFnContext {
|
|
205
|
+
executable: soroban_sdk::auth::ContractExecutable::Wasm(BytesN::from_array(&setup.env, &[2u8; 32])),
|
|
206
|
+
salt: BytesN::from_array(&setup.env, &[3u8; 32]),
|
|
207
|
+
}),
|
|
208
|
+
];
|
|
209
|
+
assert_eq!(check_auth(&setup, &payload, sig, &create_ctx), Err(Ok(ExecutorError::UnauthorizedContext)));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
#[test]
|
|
213
|
+
fn test_check_auth_rejects_invalid_execute_fn_name() {
|
|
214
|
+
let env = Env::default();
|
|
215
|
+
let admin_kp = Ed25519KeyPair::generate();
|
|
216
|
+
let admin_addr = admin_kp.address(&env);
|
|
217
|
+
let setup = TestSetup::new_with_env_and_admin(env, &admin_addr);
|
|
218
|
+
|
|
219
|
+
let payload = BytesN::from_array(&setup.env, &[1u8; 32]);
|
|
220
|
+
let sig = mk_sig(&setup, &admin_kp, &payload);
|
|
221
|
+
|
|
222
|
+
let oapp = Address::generate(&setup.env);
|
|
223
|
+
let bad_fn: Vec<Context> =
|
|
224
|
+
vec![&setup.env, contract_ctx(&setup.env, oapp, "not_allowed", vec![&setup.env, 0i128.into_val(&setup.env)])];
|
|
225
|
+
assert_eq!(check_auth(&setup, &payload, sig, &bad_fn), Err(Ok(ExecutorError::UnauthorizedContext)));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
#[test]
|
|
229
|
+
fn test_check_auth_rejects_invalid_alert_contexts() {
|
|
230
|
+
let env = Env::default();
|
|
231
|
+
let admin_kp = Ed25519KeyPair::generate();
|
|
232
|
+
let admin_addr = admin_kp.address(&env);
|
|
233
|
+
let setup = TestSetup::new_with_env_and_admin(env, &admin_addr);
|
|
234
|
+
|
|
235
|
+
let payload = BytesN::from_array(&setup.env, &[1u8; 32]);
|
|
236
|
+
let sig = mk_sig(&setup, &admin_kp, &payload);
|
|
237
|
+
|
|
238
|
+
let oapp = Address::generate(&setup.env);
|
|
239
|
+
|
|
240
|
+
// Alert fn must target endpoint and must be the only context
|
|
241
|
+
let bad_alert_contract: Vec<Context> =
|
|
242
|
+
vec![&setup.env, contract_ctx(&setup.env, oapp.clone(), "lz_receive_alert", Vec::new(&setup.env))];
|
|
243
|
+
assert_eq!(
|
|
244
|
+
check_auth(&setup, &payload, sig.clone(), &bad_alert_contract),
|
|
245
|
+
Err(Ok(ExecutorError::UnauthorizedContext))
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
let bad_alert_extra_ctx: Vec<Context> = vec![
|
|
249
|
+
&setup.env,
|
|
250
|
+
contract_ctx(&setup.env, setup.endpoint.clone(), "lz_receive_alert", Vec::new(&setup.env)),
|
|
251
|
+
contract_ctx(&setup.env, oapp, "lz_receive", vec![&setup.env, 0i128.into_val(&setup.env)]),
|
|
252
|
+
];
|
|
253
|
+
assert_eq!(check_auth(&setup, &payload, sig, &bad_alert_extra_ctx), Err(Ok(ExecutorError::UnauthorizedContext)));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
#[test]
|
|
257
|
+
fn test_check_auth_rejects_execute_missing_or_wrong_value_type() {
|
|
258
|
+
let env = Env::default();
|
|
259
|
+
let admin_kp = Ed25519KeyPair::generate();
|
|
260
|
+
let admin_addr = admin_kp.address(&env);
|
|
261
|
+
let setup = TestSetup::new_with_env_and_admin(env, &admin_addr);
|
|
262
|
+
|
|
263
|
+
let payload = BytesN::from_array(&setup.env, &[1u8; 32]);
|
|
264
|
+
let sig = mk_sig(&setup, &admin_kp, &payload);
|
|
265
|
+
|
|
266
|
+
let oapp = Address::generate(&setup.env);
|
|
267
|
+
|
|
268
|
+
// Execute path requires last arg to be i128 value
|
|
269
|
+
let missing_value: Vec<Context> =
|
|
270
|
+
vec![&setup.env, contract_ctx(&setup.env, oapp.clone(), "lz_receive", Vec::new(&setup.env))];
|
|
271
|
+
assert_eq!(check_auth(&setup, &payload, sig.clone(), &missing_value), Err(Ok(ExecutorError::UnauthorizedContext)));
|
|
272
|
+
|
|
273
|
+
let wrong_value_type: Vec<Context> = vec![
|
|
274
|
+
&setup.env,
|
|
275
|
+
contract_ctx(
|
|
276
|
+
&setup.env,
|
|
277
|
+
oapp,
|
|
278
|
+
"lz_receive",
|
|
279
|
+
vec![&setup.env, Symbol::new(&setup.env, "not_i128").into_val(&setup.env)],
|
|
280
|
+
),
|
|
281
|
+
];
|
|
282
|
+
assert_eq!(check_auth(&setup, &payload, sig, &wrong_value_type), Err(Ok(ExecutorError::UnauthorizedContext)));
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
#[test]
|
|
286
|
+
fn test_check_auth_rejects_value_zero_with_extra_context() {
|
|
287
|
+
let env = Env::default();
|
|
288
|
+
let admin_kp = Ed25519KeyPair::generate();
|
|
289
|
+
let admin_addr = admin_kp.address(&env);
|
|
290
|
+
let setup = TestSetup::new_with_env_and_admin(env, &admin_addr);
|
|
291
|
+
|
|
292
|
+
let payload = BytesN::from_array(&setup.env, &[1u8; 32]);
|
|
293
|
+
let sig = mk_sig(&setup, &admin_kp, &payload);
|
|
294
|
+
|
|
295
|
+
let oapp = Address::generate(&setup.env);
|
|
296
|
+
let value_zero_with_transfer: Vec<Context> = vec![
|
|
297
|
+
&setup.env,
|
|
298
|
+
contract_ctx(&setup.env, oapp, "lz_receive", vec![&setup.env, 0i128.into_val(&setup.env)]),
|
|
299
|
+
contract_ctx(
|
|
300
|
+
&setup.env,
|
|
301
|
+
setup.native_token.clone(),
|
|
302
|
+
"transfer",
|
|
303
|
+
vec![
|
|
304
|
+
&setup.env,
|
|
305
|
+
Address::generate(&setup.env).into_val(&setup.env),
|
|
306
|
+
Address::generate(&setup.env).into_val(&setup.env),
|
|
307
|
+
1i128.into_val(&setup.env),
|
|
308
|
+
],
|
|
309
|
+
),
|
|
310
|
+
];
|
|
311
|
+
assert_eq!(
|
|
312
|
+
check_auth(&setup, &payload, sig, &value_zero_with_transfer),
|
|
313
|
+
Err(Ok(ExecutorError::UnauthorizedContext))
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
#[test]
|
|
318
|
+
fn test_check_auth_rejects_value_nonzero_missing_transfer_context() {
|
|
319
|
+
let env = Env::default();
|
|
320
|
+
let admin_kp = Ed25519KeyPair::generate();
|
|
321
|
+
let admin_addr = admin_kp.address(&env);
|
|
322
|
+
let setup = TestSetup::new_with_env_and_admin(env, &admin_addr);
|
|
323
|
+
|
|
324
|
+
let payload = BytesN::from_array(&setup.env, &[1u8; 32]);
|
|
325
|
+
let sig = mk_sig(&setup, &admin_kp, &payload);
|
|
326
|
+
|
|
327
|
+
let oapp = Address::generate(&setup.env);
|
|
328
|
+
let value_nonzero_missing_transfer: Vec<Context> =
|
|
329
|
+
vec![&setup.env, contract_ctx(&setup.env, oapp, "lz_receive", vec![&setup.env, 1i128.into_val(&setup.env)])];
|
|
330
|
+
assert_eq!(
|
|
331
|
+
check_auth(&setup, &payload, sig, &value_nonzero_missing_transfer),
|
|
332
|
+
Err(Ok(ExecutorError::UnauthorizedContext))
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
#[test]
|
|
337
|
+
fn test_check_auth_rejects_invalid_transfer_context() {
|
|
338
|
+
let env = Env::default();
|
|
339
|
+
let admin_kp = Ed25519KeyPair::generate();
|
|
340
|
+
let admin_addr = admin_kp.address(&env);
|
|
341
|
+
let setup = TestSetup::new_with_env_and_admin(env, &admin_addr);
|
|
342
|
+
|
|
343
|
+
let payload = BytesN::from_array(&setup.env, &[1u8; 32]);
|
|
344
|
+
let sig = mk_sig(&setup, &admin_kp, &payload);
|
|
345
|
+
|
|
346
|
+
let oapp = Address::generate(&setup.env);
|
|
347
|
+
let base_exec: Context = contract_ctx(&setup.env, oapp, "lz_receive", vec![&setup.env, 5i128.into_val(&setup.env)]);
|
|
348
|
+
let transfer_args: Vec<Val> = vec![
|
|
349
|
+
&setup.env,
|
|
350
|
+
Address::generate(&setup.env).into_val(&setup.env),
|
|
351
|
+
Address::generate(&setup.env).into_val(&setup.env),
|
|
352
|
+
5i128.into_val(&setup.env),
|
|
353
|
+
];
|
|
354
|
+
|
|
355
|
+
// Wrong transfer fn name
|
|
356
|
+
let wrong_transfer_fn: Vec<Context> = vec![
|
|
357
|
+
&setup.env,
|
|
358
|
+
base_exec.clone(),
|
|
359
|
+
contract_ctx(&setup.env, setup.native_token.clone(), "not_transfer", transfer_args.clone()),
|
|
360
|
+
];
|
|
361
|
+
assert_eq!(
|
|
362
|
+
check_auth(&setup, &payload, sig.clone(), &wrong_transfer_fn),
|
|
363
|
+
Err(Ok(ExecutorError::UnauthorizedContext))
|
|
364
|
+
);
|
|
365
|
+
|
|
366
|
+
// Wrong transfer contract
|
|
367
|
+
let wrong_transfer_contract: Vec<Context> = vec![
|
|
368
|
+
&setup.env,
|
|
369
|
+
base_exec.clone(),
|
|
370
|
+
contract_ctx(&setup.env, Address::generate(&setup.env), "transfer", transfer_args.clone()),
|
|
371
|
+
];
|
|
372
|
+
assert_eq!(
|
|
373
|
+
check_auth(&setup, &payload, sig.clone(), &wrong_transfer_contract),
|
|
374
|
+
Err(Ok(ExecutorError::UnauthorizedContext))
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
// Wrong transfer amount (must match value)
|
|
378
|
+
let wrong_transfer_amount: Vec<Context> = vec![
|
|
379
|
+
&setup.env,
|
|
380
|
+
base_exec,
|
|
381
|
+
contract_ctx(
|
|
382
|
+
&setup.env,
|
|
383
|
+
setup.native_token.clone(),
|
|
384
|
+
"transfer",
|
|
385
|
+
vec![
|
|
386
|
+
&setup.env,
|
|
387
|
+
Address::generate(&setup.env).into_val(&setup.env),
|
|
388
|
+
Address::generate(&setup.env).into_val(&setup.env),
|
|
389
|
+
6i128.into_val(&setup.env),
|
|
390
|
+
],
|
|
391
|
+
),
|
|
392
|
+
];
|
|
393
|
+
assert_eq!(check_auth(&setup, &payload, sig, &wrong_transfer_amount), Err(Ok(ExecutorError::UnauthorizedContext)));
|
|
394
|
+
}
|