@layerzerolabs/protocol-stellar-v2 0.2.19 → 0.2.21
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 +795 -791
- package/.turbo/turbo-lint.log +325 -155
- package/.turbo/turbo-test.log +1398 -1277
- package/Cargo.lock +122 -111
- package/Cargo.toml +32 -16
- 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 +18 -7
- package/contracts/common-macros/src/lib.rs +31 -14
- 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/contract_ttl.rs +1 -1
- 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__contract_ttl__snapshot_generated_contractimpl_code.snap +2 -1
- 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 -14
- 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 +61 -26
- 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/events.rs +4 -0
- package/contracts/message-libs/uln-302/src/send_uln.rs +22 -6
- 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 +21 -67
- 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 +5 -6
- package/contracts/oapps/counter/integration_tests/setup_uln.rs +1 -1
- 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/oapp_core.rs +223 -0
- package/contracts/oapps/oapp/src/tests/oapp_options_type3.rs +240 -0
- package/contracts/oapps/oapp/src/tests/oapp_receiver.rs +381 -0
- package/contracts/oapps/oapp/src/tests/oapp_sender.rs +569 -0
- 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 +153 -75
- package/contracts/oapps/oft/src/extensions/pausable.rs +61 -12
- package/contracts/oapps/oft/src/extensions/rate_limiter.rs +198 -134
- package/contracts/oapps/oft/src/oft.rs +45 -50
- package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +1 -1
- package/contracts/oapps/oft/src/oft_types/mint_burn.rs +4 -26
- package/contracts/oapps/oft-core/Cargo.toml +1 -4
- package/contracts/oapps/oft-core/integration-tests/setup.rs +3 -3
- 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 +341 -246
- 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 +61 -16
- package/contracts/upgrader/src/lib.rs +30 -57
- package/contracts/upgrader/src/tests/test_data/test_upgradeable_contract1.wasm +0 -0
- package/contracts/upgrader/src/tests/test_data/test_upgradeable_contract2.wasm +0 -0
- package/contracts/upgrader/src/tests/test_upgrader.rs +44 -35
- package/contracts/utils/Cargo.toml +0 -1
- package/contracts/utils/src/buffer_reader.rs +1 -0
- package/contracts/utils/src/errors.rs +4 -2
- 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 +372 -175
- package/contracts/utils/src/ttl_configurable.rs +13 -7
- package/contracts/utils/src/upgradeable.rs +48 -23
- package/contracts/workers/dvn/Cargo.toml +6 -6
- package/contracts/workers/dvn/src/auth.rs +12 -42
- package/contracts/workers/dvn/src/dvn.rs +15 -40
- package/contracts/workers/dvn/src/errors.rs +0 -1
- package/contracts/workers/dvn/src/interfaces/dvn.rs +35 -0
- package/contracts/workers/dvn/src/lib.rs +4 -3
- package/contracts/workers/dvn/src/tests/auth.rs +1 -1
- package/contracts/workers/dvn/src/tests/dvn.rs +19 -15
- package/contracts/workers/dvn/src/tests/multisig/set_threshold.rs +2 -4
- package/contracts/workers/dvn/src/tests/multisig/verify_signatures.rs +1 -3
- package/contracts/workers/dvn/src/tests/setup.rs +5 -9
- package/contracts/workers/dvn-fee-lib/Cargo.toml +2 -2
- package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +38 -22
- package/contracts/workers/dvn-fee-lib/src/lib.rs +12 -2
- package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +17 -16
- package/contracts/workers/executor/Cargo.toml +4 -0
- package/contracts/workers/executor/src/executor.rs +15 -36
- 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 +7 -1
- package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +62 -15
- package/contracts/workers/executor-fee-lib/src/executor_option.rs +28 -1
- package/contracts/workers/executor-fee-lib/src/lib.rs +11 -2
- package/contracts/workers/executor-fee-lib/src/tests/executor_fee_lib.rs +701 -0
- package/contracts/workers/executor-fee-lib/src/tests/executor_option.rs +370 -0
- package/contracts/workers/executor-fee-lib/src/tests/mod.rs +4 -0
- package/contracts/workers/executor-fee-lib/src/tests/setup.rs +60 -0
- package/contracts/workers/executor-helper/Cargo.toml +0 -1
- package/contracts/workers/executor-helper/src/lib.rs +3 -0
- package/contracts/workers/executor-helper/src/tests/executor_helper.rs +184 -0
- package/contracts/workers/executor-helper/src/tests/mod.rs +2 -0
- package/contracts/workers/executor-helper/src/tests/setup.rs +366 -0
- package/contracts/workers/fee-lib-interfaces/Cargo.toml +14 -0
- package/contracts/workers/{worker/src/interfaces/mod.rs → fee-lib-interfaces/src/lib.rs} +4 -3
- package/contracts/workers/price-feed/Cargo.toml +7 -1
- package/contracts/workers/price-feed/src/events.rs +1 -1
- package/contracts/workers/price-feed/src/lib.rs +12 -4
- package/contracts/workers/price-feed/src/price_feed.rs +5 -21
- package/contracts/workers/price-feed/src/storage.rs +1 -1
- package/contracts/workers/price-feed/src/tests/mod.rs +2 -0
- package/contracts/workers/price-feed/src/tests/price_feed.rs +869 -0
- package/contracts/workers/price-feed/src/tests/setup.rs +70 -0
- package/contracts/workers/price-feed/src/types.rs +1 -1
- package/contracts/workers/worker/src/errors.rs +1 -4
- package/contracts/workers/worker/src/lib.rs +0 -2
- package/contracts/workers/worker/src/storage.rs +32 -29
- package/contracts/workers/worker/src/tests/setup.rs +2 -8
- package/contracts/workers/worker/src/tests/worker.rs +96 -74
- package/contracts/workers/worker/src/worker.rs +75 -75
- 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 +268 -263
- package/sdk/dist/generated/bml.d.ts +12 -4
- package/sdk/dist/generated/bml.js +9 -7
- package/sdk/dist/generated/counter.d.ts +306 -298
- package/sdk/dist/generated/counter.js +48 -46
- package/sdk/dist/generated/dvn.d.ts +450 -411
- package/sdk/dist/generated/dvn.js +66 -64
- package/sdk/dist/generated/dvn_fee_lib.d.ts +294 -338
- package/sdk/dist/generated/dvn_fee_lib.js +33 -64
- package/sdk/dist/generated/endpoint.d.ts +108 -100
- package/sdk/dist/generated/endpoint.js +21 -19
- package/sdk/dist/generated/executor.d.ts +414 -370
- package/sdk/dist/generated/executor.js +58 -55
- package/sdk/dist/generated/executor_fee_lib.d.ts +333 -377
- package/sdk/dist/generated/executor_fee_lib.js +34 -65
- package/sdk/dist/generated/executor_helper.d.ts +26 -190
- package/sdk/dist/generated/executor_helper.js +23 -28
- package/sdk/dist/generated/layerzero_view.d.ts +1271 -0
- package/sdk/dist/generated/layerzero_view.js +294 -0
- package/sdk/dist/generated/oft.d.ts +408 -385
- package/sdk/dist/generated/oft.js +89 -92
- package/sdk/dist/generated/price_feed.d.ts +385 -429
- package/sdk/dist/generated/price_feed.js +50 -81
- package/sdk/dist/generated/sml.d.ts +108 -100
- package/sdk/dist/generated/sml.js +21 -19
- package/sdk/dist/generated/treasury.d.ts +108 -100
- package/sdk/dist/generated/treasury.js +21 -19
- package/sdk/dist/generated/uln302.d.ts +108 -100
- package/sdk/dist/generated/uln302.js +23 -21
- package/sdk/dist/generated/upgrader.d.ts +189 -18
- package/sdk/dist/generated/upgrader.js +84 -4
- package/sdk/dist/index.d.ts +1 -0
- package/sdk/dist/index.js +2 -0
- package/sdk/package.json +1 -1
- package/sdk/src/index.ts +3 -0
- package/sdk/test/oft-sml.test.ts +4 -4
- package/sdk/test/suites/localnet.ts +84 -20
- package/sdk/test/upgrader.test.ts +2 -3
- package/tools/ts-bindings-gen/src/main.rs +2 -1
- package/contracts/ERROR_SPEC.md +0 -44
- package/contracts/endpoint-v2/ARCHITECTURE.md +0 -233
- package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +0 -175
- package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +0 -212
- package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +0 -153
- package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +0 -294
- /package/contracts/workers/{worker/src/interfaces → fee-lib-interfaces/src}/dvn_fee_lib.rs +0 -0
- /package/contracts/workers/{worker/src/interfaces → fee-lib-interfaces/src}/executor_fee_lib.rs +0 -0
- /package/contracts/workers/{worker/src/interfaces → fee-lib-interfaces/src}/price_feed.rs +0 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
use quote::quote;
|
|
2
|
+
|
|
3
|
+
// ============================================
|
|
4
|
+
// Snapshot Tests: OApp Code Generation
|
|
5
|
+
// ============================================
|
|
6
|
+
|
|
7
|
+
#[test]
|
|
8
|
+
fn snapshot_generate_oapp() {
|
|
9
|
+
let input = quote! {
|
|
10
|
+
pub struct MyOApp;
|
|
11
|
+
};
|
|
12
|
+
let item_struct: syn::ItemStruct = syn::parse2(input).expect("failed to parse struct");
|
|
13
|
+
|
|
14
|
+
let all_defaults = {
|
|
15
|
+
let result = crate::generators::generate_oapp(item_struct.clone(), crate::CustomImpls::default());
|
|
16
|
+
prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
let custom_core_only = {
|
|
20
|
+
let result = crate::generators::generate_oapp(
|
|
21
|
+
item_struct.clone(),
|
|
22
|
+
crate::CustomImpls { core: true, sender: false, receiver: false, options_type3: false },
|
|
23
|
+
);
|
|
24
|
+
prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
let custom_sender_only = {
|
|
28
|
+
let result = crate::generators::generate_oapp(
|
|
29
|
+
item_struct.clone(),
|
|
30
|
+
crate::CustomImpls { core: false, sender: true, receiver: false, options_type3: false },
|
|
31
|
+
);
|
|
32
|
+
prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
let custom_receiver_only = {
|
|
36
|
+
let result = crate::generators::generate_oapp(
|
|
37
|
+
item_struct.clone(),
|
|
38
|
+
crate::CustomImpls { core: false, sender: false, receiver: true, options_type3: false },
|
|
39
|
+
);
|
|
40
|
+
prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
let custom_options_type3_only = {
|
|
44
|
+
let result = crate::generators::generate_oapp(
|
|
45
|
+
item_struct.clone(),
|
|
46
|
+
crate::CustomImpls { core: false, sender: false, receiver: false, options_type3: true },
|
|
47
|
+
);
|
|
48
|
+
prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
let custom_all = {
|
|
52
|
+
let result = crate::generators::generate_oapp(
|
|
53
|
+
item_struct.clone(),
|
|
54
|
+
crate::CustomImpls { core: true, sender: true, receiver: true, options_type3: true },
|
|
55
|
+
);
|
|
56
|
+
prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
let preserves_struct_attributes_and_fields = {
|
|
60
|
+
let fancy_input = quote! {
|
|
61
|
+
#[derive(Clone, Debug)]
|
|
62
|
+
pub struct FancyOApp {
|
|
63
|
+
pub x: u32,
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
let fancy_struct: syn::ItemStruct = syn::parse2(fancy_input).expect("failed to parse struct");
|
|
67
|
+
let result = crate::generators::generate_oapp(fancy_struct, crate::CustomImpls::default());
|
|
68
|
+
prettyplease::unparse(&syn::parse2::<syn::File>(result).expect("failed to parse generated code"))
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
let combined = format!(
|
|
72
|
+
"// === Default (no custom impls) ===\n\n{}\n\n\
|
|
73
|
+
// === custom = [core] ===\n\n{}\n\n\
|
|
74
|
+
// === custom = [sender] ===\n\n{}\n\n\
|
|
75
|
+
// === custom = [receiver] ===\n\n{}\n\n\
|
|
76
|
+
// === custom = [options_type3] ===\n\n{}\n\n\
|
|
77
|
+
// === custom = [core, sender, receiver, options_type3] ===\n\n{}\n\n\
|
|
78
|
+
// === Struct attributes + fields are preserved ===\n\n{}",
|
|
79
|
+
all_defaults,
|
|
80
|
+
custom_core_only,
|
|
81
|
+
custom_sender_only,
|
|
82
|
+
custom_receiver_only,
|
|
83
|
+
custom_options_type3_only,
|
|
84
|
+
custom_all,
|
|
85
|
+
preserves_struct_attributes_and_fields
|
|
86
|
+
);
|
|
87
|
+
insta::assert_snapshot!(combined);
|
|
88
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
use quote::quote;
|
|
2
|
+
|
|
3
|
+
// ============================================
|
|
4
|
+
// Unit Tests: #[oapp(custom = [...])] parsing
|
|
5
|
+
// ============================================
|
|
6
|
+
|
|
7
|
+
#[test]
|
|
8
|
+
fn test_custom_impls_parse_empty_is_default() {
|
|
9
|
+
let parsed: crate::CustomImpls = syn::parse2(quote! {}).expect("failed to parse empty attrs");
|
|
10
|
+
assert!(!parsed.core);
|
|
11
|
+
assert!(!parsed.sender);
|
|
12
|
+
assert!(!parsed.receiver);
|
|
13
|
+
assert!(!parsed.options_type3);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
#[test]
|
|
17
|
+
fn test_custom_impls_parse_valid_all_list() {
|
|
18
|
+
let parsed: crate::CustomImpls =
|
|
19
|
+
syn::parse2(quote! { custom = [core, sender, receiver, options_type3] }).expect("failed to parse attrs");
|
|
20
|
+
assert!(parsed.core);
|
|
21
|
+
assert!(parsed.sender);
|
|
22
|
+
assert!(parsed.receiver);
|
|
23
|
+
assert!(parsed.options_type3);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
#[test]
|
|
27
|
+
fn test_custom_impls_parse_empty_custom_list_is_default() {
|
|
28
|
+
let parsed: crate::CustomImpls = syn::parse2(quote! { custom = [] }).expect("failed to parse attrs");
|
|
29
|
+
assert!(!parsed.core);
|
|
30
|
+
assert!(!parsed.sender);
|
|
31
|
+
assert!(!parsed.receiver);
|
|
32
|
+
assert!(!parsed.options_type3);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
#[test]
|
|
36
|
+
fn test_custom_impls_allows_trailing_comma() {
|
|
37
|
+
let parsed: crate::CustomImpls = syn::parse2(quote! { custom = [core,] }).expect("failed to parse attrs");
|
|
38
|
+
assert!(parsed.core);
|
|
39
|
+
assert!(!parsed.sender);
|
|
40
|
+
assert!(!parsed.receiver);
|
|
41
|
+
assert!(!parsed.options_type3);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
#[test]
|
|
45
|
+
fn test_custom_impls_allows_duplicates() {
|
|
46
|
+
// Duplicates are harmless and should not cause parsing to fail.
|
|
47
|
+
let parsed: crate::CustomImpls =
|
|
48
|
+
syn::parse2(quote! { custom = [core, core, receiver, receiver] }).expect("failed to parse attrs");
|
|
49
|
+
assert!(parsed.core);
|
|
50
|
+
assert!(!parsed.sender);
|
|
51
|
+
assert!(parsed.receiver);
|
|
52
|
+
assert!(!parsed.options_type3);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
#[test]
|
|
56
|
+
fn test_custom_impls_rejects_wrong_key() {
|
|
57
|
+
let err = syn::parse2::<crate::CustomImpls>(quote! { nope = [core] }).expect_err("expected parse failure");
|
|
58
|
+
assert!(err.to_string().contains("expected `custom`"), "unexpected error: {err}");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
#[test]
|
|
62
|
+
fn test_custom_impls_rejects_unknown_ident() {
|
|
63
|
+
let err =
|
|
64
|
+
syn::parse2::<crate::CustomImpls>(quote! { custom = [core, not_a_real_option] }).expect_err("expected failure");
|
|
65
|
+
assert!(
|
|
66
|
+
err.to_string().contains("expected one of `core`, `sender`, `receiver`, `options_type3`"),
|
|
67
|
+
"unexpected error: {err}"
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
#[test]
|
|
72
|
+
fn test_custom_impls_rejects_trailing_tokens_after_list() {
|
|
73
|
+
// `syn::parse2` expects the parser to consume the full stream.
|
|
74
|
+
syn::parse2::<crate::CustomImpls>(quote! { custom = [core] extra })
|
|
75
|
+
.expect_err("expected parse failure due to trailing tokens");
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
#[test]
|
|
79
|
+
fn test_custom_impls_rejects_missing_equals() {
|
|
80
|
+
syn::parse2::<crate::CustomImpls>(quote! { custom [core] }).expect_err("expected parse failure (missing `=`)");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
#[test]
|
|
84
|
+
fn test_custom_impls_rejects_non_bracketed_list() {
|
|
85
|
+
syn::parse2::<crate::CustomImpls>(quote! { custom = (core) }).expect_err("expected parse failure (not `[...]`)");
|
|
86
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
source: contracts/oapps/oapp-macros/src/tests/oapp.rs
|
|
3
|
+
assertion_line: 87
|
|
4
|
+
expression: combined
|
|
5
|
+
---
|
|
6
|
+
// === Default (no custom impls) ===
|
|
7
|
+
|
|
8
|
+
#[common_macros::lz_contract]
|
|
9
|
+
pub struct MyOApp;
|
|
10
|
+
use oapp::oapp_core::OAppCore as _;
|
|
11
|
+
#[soroban_sdk::contractimpl(contracttrait)]
|
|
12
|
+
impl oapp::oapp_core::OAppCore for MyOApp {}
|
|
13
|
+
use oapp::oapp_sender::OAppSenderInternal as _;
|
|
14
|
+
impl oapp::oapp_sender::OAppSenderInternal for MyOApp {}
|
|
15
|
+
use oapp::oapp_receiver::OAppReceiver as _;
|
|
16
|
+
#[soroban_sdk::contractimpl(contracttrait)]
|
|
17
|
+
impl oapp::oapp_receiver::OAppReceiver for MyOApp {}
|
|
18
|
+
use oapp::oapp_options_type3::OAppOptionsType3 as _;
|
|
19
|
+
#[soroban_sdk::contractimpl(contracttrait)]
|
|
20
|
+
impl oapp::oapp_options_type3::OAppOptionsType3 for MyOApp {}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
// === custom = [core] ===
|
|
24
|
+
|
|
25
|
+
#[common_macros::lz_contract]
|
|
26
|
+
pub struct MyOApp;
|
|
27
|
+
use oapp::oapp_sender::OAppSenderInternal as _;
|
|
28
|
+
impl oapp::oapp_sender::OAppSenderInternal for MyOApp {}
|
|
29
|
+
use oapp::oapp_receiver::OAppReceiver as _;
|
|
30
|
+
#[soroban_sdk::contractimpl(contracttrait)]
|
|
31
|
+
impl oapp::oapp_receiver::OAppReceiver for MyOApp {}
|
|
32
|
+
use oapp::oapp_options_type3::OAppOptionsType3 as _;
|
|
33
|
+
#[soroban_sdk::contractimpl(contracttrait)]
|
|
34
|
+
impl oapp::oapp_options_type3::OAppOptionsType3 for MyOApp {}
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
// === custom = [sender] ===
|
|
38
|
+
|
|
39
|
+
#[common_macros::lz_contract]
|
|
40
|
+
pub struct MyOApp;
|
|
41
|
+
use oapp::oapp_core::OAppCore as _;
|
|
42
|
+
#[soroban_sdk::contractimpl(contracttrait)]
|
|
43
|
+
impl oapp::oapp_core::OAppCore for MyOApp {}
|
|
44
|
+
use oapp::oapp_receiver::OAppReceiver as _;
|
|
45
|
+
#[soroban_sdk::contractimpl(contracttrait)]
|
|
46
|
+
impl oapp::oapp_receiver::OAppReceiver for MyOApp {}
|
|
47
|
+
use oapp::oapp_options_type3::OAppOptionsType3 as _;
|
|
48
|
+
#[soroban_sdk::contractimpl(contracttrait)]
|
|
49
|
+
impl oapp::oapp_options_type3::OAppOptionsType3 for MyOApp {}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
// === custom = [receiver] ===
|
|
53
|
+
|
|
54
|
+
#[common_macros::lz_contract]
|
|
55
|
+
pub struct MyOApp;
|
|
56
|
+
use oapp::oapp_core::OAppCore as _;
|
|
57
|
+
#[soroban_sdk::contractimpl(contracttrait)]
|
|
58
|
+
impl oapp::oapp_core::OAppCore for MyOApp {}
|
|
59
|
+
use oapp::oapp_sender::OAppSenderInternal as _;
|
|
60
|
+
impl oapp::oapp_sender::OAppSenderInternal for MyOApp {}
|
|
61
|
+
use oapp::oapp_options_type3::OAppOptionsType3 as _;
|
|
62
|
+
#[soroban_sdk::contractimpl(contracttrait)]
|
|
63
|
+
impl oapp::oapp_options_type3::OAppOptionsType3 for MyOApp {}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
// === custom = [options_type3] ===
|
|
67
|
+
|
|
68
|
+
#[common_macros::lz_contract]
|
|
69
|
+
pub struct MyOApp;
|
|
70
|
+
use oapp::oapp_core::OAppCore as _;
|
|
71
|
+
#[soroban_sdk::contractimpl(contracttrait)]
|
|
72
|
+
impl oapp::oapp_core::OAppCore for MyOApp {}
|
|
73
|
+
use oapp::oapp_sender::OAppSenderInternal as _;
|
|
74
|
+
impl oapp::oapp_sender::OAppSenderInternal for MyOApp {}
|
|
75
|
+
use oapp::oapp_receiver::OAppReceiver as _;
|
|
76
|
+
#[soroban_sdk::contractimpl(contracttrait)]
|
|
77
|
+
impl oapp::oapp_receiver::OAppReceiver for MyOApp {}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
// === custom = [core, sender, receiver, options_type3] ===
|
|
81
|
+
|
|
82
|
+
#[common_macros::lz_contract]
|
|
83
|
+
pub struct MyOApp;
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
// === Struct attributes + fields are preserved ===
|
|
87
|
+
|
|
88
|
+
#[common_macros::lz_contract]
|
|
89
|
+
#[derive(Clone, Debug)]
|
|
90
|
+
pub struct FancyOApp {
|
|
91
|
+
pub x: u32,
|
|
92
|
+
}
|
|
93
|
+
use oapp::oapp_core::OAppCore as _;
|
|
94
|
+
#[soroban_sdk::contractimpl(contracttrait)]
|
|
95
|
+
impl oapp::oapp_core::OAppCore for FancyOApp {}
|
|
96
|
+
use oapp::oapp_sender::OAppSenderInternal as _;
|
|
97
|
+
impl oapp::oapp_sender::OAppSenderInternal for FancyOApp {}
|
|
98
|
+
use oapp::oapp_receiver::OAppReceiver as _;
|
|
99
|
+
#[soroban_sdk::contractimpl(contracttrait)]
|
|
100
|
+
impl oapp::oapp_receiver::OAppReceiver for FancyOApp {}
|
|
101
|
+
use oapp::oapp_options_type3::OAppOptionsType3 as _;
|
|
102
|
+
#[soroban_sdk::contractimpl(contracttrait)]
|
|
103
|
+
impl oapp::oapp_options_type3::OAppOptionsType3 for FancyOApp {}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//! Utility functions for OFT-STD integration tests.
|
|
2
2
|
|
|
3
|
-
use crate::extensions::rate_limiter::Direction;
|
|
3
|
+
use crate::extensions::rate_limiter::{Direction, RateLimitConfig};
|
|
4
4
|
use crate::integration_tests::setup::{decode_packet, ChainSetup};
|
|
5
5
|
use endpoint_v2::{MessagingFee, Origin, OutboundPacket};
|
|
6
6
|
use message_lib_common::packet_codec_v1;
|
|
@@ -254,10 +254,28 @@ pub fn try_lz_receive(
|
|
|
254
254
|
|
|
255
255
|
// returns (encoded_payload, options, send_library)
|
|
256
256
|
pub fn scan_packet_sent_event(env: &Env, endpoint: &Address) -> Option<(Bytes, Bytes, Address)> {
|
|
257
|
+
use soroban_sdk::TryFromVal;
|
|
258
|
+
|
|
257
259
|
let mut packet = None;
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
260
|
+
let events = env.events().all().filter_by_contract(endpoint);
|
|
261
|
+
for event in events.events().iter() {
|
|
262
|
+
let v0 = match &event.body {
|
|
263
|
+
soroban_sdk::xdr::ContractEventBody::V0(v0) => v0,
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
// Check if this is a packet_sent event by looking at topics
|
|
267
|
+
let mut is_packet_sent = false;
|
|
268
|
+
for topic in v0.topics.iter() {
|
|
269
|
+
if let Ok(sym) = Symbol::try_from_val(env, topic) {
|
|
270
|
+
if sym == Symbol::new(env, "packet_sent") {
|
|
271
|
+
is_packet_sent = true;
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if is_packet_sent {
|
|
278
|
+
let data: Val = Val::try_from_val(env, &v0.data).unwrap();
|
|
261
279
|
let map: Map<Symbol, Val> = data.into_val(env);
|
|
262
280
|
|
|
263
281
|
let encoded_payload: Bytes = map.get(Symbol::new(env, "encoded_packet")).unwrap().into_val(env);
|
|
@@ -359,16 +377,17 @@ pub fn set_default_fee_bps(env: &Env, chain: &ChainSetup<'_>, fee_bps: u64) {
|
|
|
359
377
|
}
|
|
360
378
|
|
|
361
379
|
pub fn set_fee_bps(env: &Env, chain: &ChainSetup<'_>, dst_eid: u32, fee_bps: u64) {
|
|
380
|
+
let fee_bps_opt = Some(fee_bps);
|
|
362
381
|
env.mock_auths(&[MockAuth {
|
|
363
382
|
address: &chain.owner,
|
|
364
383
|
invoke: &MockAuthInvoke {
|
|
365
384
|
contract: &chain.oft.address,
|
|
366
385
|
fn_name: "set_fee_bps",
|
|
367
|
-
args: (&dst_eid, &
|
|
386
|
+
args: (&dst_eid, &fee_bps_opt).into_val(env),
|
|
368
387
|
sub_invokes: &[],
|
|
369
388
|
},
|
|
370
389
|
}]);
|
|
371
|
-
chain.oft.set_fee_bps(&dst_eid, &
|
|
390
|
+
chain.oft.set_fee_bps(&dst_eid, &fee_bps_opt);
|
|
372
391
|
}
|
|
373
392
|
|
|
374
393
|
// ============================================================================
|
|
@@ -383,16 +402,17 @@ pub fn set_rate_limit(
|
|
|
383
402
|
limit: i128,
|
|
384
403
|
window_seconds: u64,
|
|
385
404
|
) {
|
|
405
|
+
let config = Some(RateLimitConfig { limit, window_seconds });
|
|
386
406
|
env.mock_auths(&[MockAuth {
|
|
387
407
|
address: &chain.owner,
|
|
388
408
|
invoke: &MockAuthInvoke {
|
|
389
409
|
contract: &chain.oft.address,
|
|
390
410
|
fn_name: "set_rate_limit",
|
|
391
|
-
args: (direction, &dst_eid, &
|
|
411
|
+
args: (direction, &dst_eid, &config).into_val(env),
|
|
392
412
|
sub_invokes: &[],
|
|
393
413
|
},
|
|
394
414
|
}]);
|
|
395
|
-
chain.oft.set_rate_limit(direction, &dst_eid, &
|
|
415
|
+
chain.oft.set_rate_limit(direction, &dst_eid, &config);
|
|
396
416
|
}
|
|
397
417
|
|
|
398
418
|
pub fn rate_limit_capacity(chain: &ChainSetup<'_>, direction: &Direction, eid: u32) -> i128 {
|
|
@@ -1,32 +1,48 @@
|
|
|
1
1
|
use common_macros::{contract_error, contract_trait, only_auth, storage};
|
|
2
2
|
use soroban_sdk::{assert_with_error, contractevent, token::TokenClient, Address, Env};
|
|
3
|
-
use utils::{
|
|
3
|
+
use utils::{auth::Auth, option_ext::OptionExt};
|
|
4
4
|
|
|
5
5
|
/// Base fee in basis points (10,000 BPS = 100%)
|
|
6
6
|
/// Used as denominator in fee calculations
|
|
7
7
|
const BASE_FEE_BPS: u64 = 10_000;
|
|
8
8
|
|
|
9
|
+
// =========================================================================
|
|
10
|
+
// Storage
|
|
11
|
+
// =========================================================================
|
|
12
|
+
|
|
9
13
|
#[storage]
|
|
10
14
|
pub enum OFTFeeStorage {
|
|
15
|
+
/// Default fee rate in basis points (0-10,000, where 10,000 = 100%)
|
|
16
|
+
/// Applied to destinations without specific fee configuration
|
|
17
|
+
/// No fee is charged(default to 0) by default
|
|
11
18
|
#[instance(u64)]
|
|
12
19
|
#[default(0)]
|
|
13
20
|
DefaultFeeBps,
|
|
14
21
|
|
|
22
|
+
/// Destination-specific fee rates mapped by endpoint ID (eid)
|
|
15
23
|
#[persistent(u64)]
|
|
16
24
|
FeeBps { eid: u32 },
|
|
17
25
|
|
|
26
|
+
/// Address where collected fees will be deposited
|
|
18
27
|
#[instance(Address)]
|
|
19
28
|
FeeDepositAddress,
|
|
20
29
|
}
|
|
21
30
|
|
|
31
|
+
// =========================================================================
|
|
32
|
+
// Errors
|
|
33
|
+
// =========================================================================
|
|
34
|
+
|
|
22
35
|
#[contract_error]
|
|
23
36
|
pub enum OFTFeeError {
|
|
24
|
-
InvalidFeeBps =
|
|
37
|
+
InvalidFeeBps = 3100,
|
|
25
38
|
InvalidFeeDepositAddress,
|
|
26
|
-
NotFound,
|
|
27
39
|
SameValue,
|
|
28
40
|
}
|
|
29
41
|
|
|
42
|
+
// =========================================================================
|
|
43
|
+
// Events
|
|
44
|
+
// =========================================================================
|
|
45
|
+
|
|
30
46
|
#[contractevent]
|
|
31
47
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
32
48
|
pub struct DefaultFeeBpsSet {
|
|
@@ -37,13 +53,8 @@ pub struct DefaultFeeBpsSet {
|
|
|
37
53
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
38
54
|
pub struct FeeBpsSet {
|
|
39
55
|
pub dst_eid: u32,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
#[contractevent]
|
|
44
|
-
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
45
|
-
pub struct FeeBpsUnset {
|
|
46
|
-
pub dst_eid: u32,
|
|
56
|
+
/// The fee rate in basis points, or None if the fee is removed
|
|
57
|
+
pub fee_bps: Option<u64>,
|
|
47
58
|
}
|
|
48
59
|
|
|
49
60
|
#[contractevent]
|
|
@@ -52,72 +63,70 @@ pub struct FeeDepositAddressSet {
|
|
|
52
63
|
pub fee_deposit_address: Address,
|
|
53
64
|
}
|
|
54
65
|
|
|
66
|
+
// =========================================================================
|
|
67
|
+
// Trait With Default Implementations
|
|
68
|
+
// =========================================================================
|
|
69
|
+
|
|
55
70
|
#[contract_trait]
|
|
56
|
-
pub trait OFTFee: OFTFeeInternal +
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
let current_default = OFTFeeStorage::default_fee_bps(env);
|
|
61
|
-
assert_with_error!(env, current_default != default_fee_bps, OFTFeeError::SameValue);
|
|
62
|
-
OFTFeeStorage::set_default_fee_bps(env, &default_fee_bps);
|
|
63
|
-
DefaultFeeBpsSet { fee_bps: default_fee_bps }.publish(env);
|
|
64
|
-
}
|
|
71
|
+
pub trait OFTFee: OFTFeeInternal + Auth {
|
|
72
|
+
// =========================================================================
|
|
73
|
+
// Management Functions
|
|
74
|
+
// =========================================================================
|
|
65
75
|
|
|
76
|
+
/// Sets the default fee rate in basis points.
|
|
66
77
|
#[only_auth]
|
|
67
|
-
fn
|
|
68
|
-
|
|
69
|
-
if OFTFeeStorage::has_fee_bps(env, dst_eid) {
|
|
70
|
-
let current_fee_bps = OFTFeeStorage::fee_bps(env, dst_eid).unwrap();
|
|
71
|
-
assert_with_error!(env, current_fee_bps != fee_bps, OFTFeeError::SameValue);
|
|
72
|
-
}
|
|
73
|
-
OFTFeeStorage::set_fee_bps(env, dst_eid, &fee_bps);
|
|
74
|
-
FeeBpsSet { dst_eid, fee_bps }.publish(env);
|
|
78
|
+
fn set_default_fee_bps(env: &soroban_sdk::Env, default_fee_bps: u64) {
|
|
79
|
+
Self::__set_default_fee_bps(env, default_fee_bps);
|
|
75
80
|
}
|
|
76
81
|
|
|
82
|
+
/// Sets or removes the fee rate for a specific destination endpoint.
|
|
83
|
+
///
|
|
84
|
+
/// # Arguments
|
|
85
|
+
/// * `dst_eid` - The destination endpoint ID
|
|
86
|
+
/// * `fee_bps` - The fee rate (0-10,000), or None to remove the fee configuration
|
|
77
87
|
#[only_auth]
|
|
78
|
-
fn
|
|
79
|
-
|
|
80
|
-
OFTFeeStorage::remove_fee_bps(env, dst_eid);
|
|
81
|
-
FeeBpsUnset { dst_eid }.publish(env);
|
|
88
|
+
fn set_fee_bps(env: &soroban_sdk::Env, dst_eid: u32, fee_bps: Option<u64>) {
|
|
89
|
+
Self::__set_fee_bps(env, dst_eid, fee_bps);
|
|
82
90
|
}
|
|
83
91
|
|
|
92
|
+
/// Sets the address where collected fees will be deposited.
|
|
84
93
|
#[only_auth]
|
|
85
|
-
fn set_fee_deposit_address(env: &Env, fee_deposit_address: Address) {
|
|
86
|
-
|
|
87
|
-
assert_with_error!(env, current_address != fee_deposit_address, OFTFeeError::SameValue);
|
|
88
|
-
}
|
|
89
|
-
OFTFeeStorage::set_fee_deposit_address(env, &fee_deposit_address);
|
|
90
|
-
FeeDepositAddressSet { fee_deposit_address }.publish(env);
|
|
94
|
+
fn set_fee_deposit_address(env: &soroban_sdk::Env, fee_deposit_address: soroban_sdk::Address) {
|
|
95
|
+
Self::__set_fee_deposit_address(env, &fee_deposit_address);
|
|
91
96
|
}
|
|
92
97
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
98
|
+
// =========================================================================
|
|
99
|
+
// View Functions
|
|
100
|
+
// =========================================================================
|
|
96
101
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
} else {
|
|
101
|
-
OFTFeeStorage::default_fee_bps(env)
|
|
102
|
-
}
|
|
102
|
+
/// Returns the default fee rate in basis points.
|
|
103
|
+
fn default_fee_bps(env: &soroban_sdk::Env) -> u64 {
|
|
104
|
+
Self::__default_fee_bps(env)
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
/// Returns the fee rate for a specific destination, if set.
|
|
108
|
+
fn fee_bps(env: &soroban_sdk::Env, dst_eid: u32) -> Option<u64> {
|
|
109
|
+
Self::__fee_bps(env, dst_eid)
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
/// Returns the effective fee rate for a destination (destination-specific or default).
|
|
113
|
+
fn effective_fee_bps(env: &soroban_sdk::Env, dst_eid: u32) -> u64 {
|
|
114
|
+
Self::__effective_fee_bps(env, dst_eid)
|
|
111
115
|
}
|
|
112
116
|
|
|
113
|
-
|
|
114
|
-
|
|
117
|
+
/// Returns the fee deposit address.
|
|
118
|
+
fn fee_deposit_address(env: &soroban_sdk::Env) -> soroban_sdk::Address {
|
|
119
|
+
Self::__fee_deposit_address(env)
|
|
115
120
|
}
|
|
116
121
|
}
|
|
117
122
|
|
|
118
123
|
/// Internal trait for OFT fee operations used by OFT hooks.
|
|
119
|
-
/// Contains only truly internal methods that are called from
|
|
124
|
+
/// Contains only truly internal methods that are called from OFTInternal implementations.
|
|
120
125
|
pub trait OFTFeeInternal {
|
|
126
|
+
// =========================================================================
|
|
127
|
+
// OFT Hooks
|
|
128
|
+
// =========================================================================
|
|
129
|
+
|
|
121
130
|
/// Calculates the fee amount for a given transfer (read-only).
|
|
122
131
|
/// Used internally by `__debit_view` to calculate the fee.
|
|
123
132
|
///
|
|
@@ -128,40 +137,109 @@ pub trait OFTFeeInternal {
|
|
|
128
137
|
/// # Returns
|
|
129
138
|
/// The fee amount to be deducted
|
|
130
139
|
fn __fee_view(env: &Env, dst_eid: u32, amount_ld: i128) -> i128 {
|
|
131
|
-
|
|
132
|
-
let fee_bps = if OFTFeeStorage::has_fee_bps(env, dst_eid) {
|
|
133
|
-
OFTFeeStorage::fee_bps(env, dst_eid).unwrap()
|
|
134
|
-
} else {
|
|
135
|
-
OFTFeeStorage::default_fee_bps(env)
|
|
136
|
-
};
|
|
140
|
+
let fee_bps = Self::__effective_fee_bps(env, dst_eid);
|
|
137
141
|
if fee_bps == 0 {
|
|
138
142
|
return 0;
|
|
139
143
|
}
|
|
144
|
+
|
|
140
145
|
// Check that fee deposit address is set (required for fee collection)
|
|
141
|
-
assert_with_error!(
|
|
142
|
-
|
|
143
|
-
OFTFeeStorage::fee_deposit_address(env).is_some(),
|
|
144
|
-
OFTFeeError::InvalidFeeDepositAddress
|
|
145
|
-
);
|
|
146
|
+
assert_with_error!(env, OFTFeeStorage::has_fee_deposit_address(env), OFTFeeError::InvalidFeeDepositAddress);
|
|
147
|
+
|
|
146
148
|
(amount_ld * fee_bps as i128) / BASE_FEE_BPS as i128
|
|
147
149
|
}
|
|
148
150
|
|
|
149
|
-
/// Charges the fee by transferring the fee amount from sender to the fee deposit address.
|
|
150
|
-
/// Used internally by `__debit` to collect the fee
|
|
151
|
+
/// Charges the fee by transferring the fee amount from the sender to the fee deposit address.
|
|
152
|
+
/// Used internally by `__debit` to collect the fee.
|
|
151
153
|
///
|
|
152
154
|
/// # Arguments
|
|
153
155
|
/// * `token` - The token address to transfer
|
|
154
|
-
/// * `
|
|
156
|
+
/// * `from` - The address to transfer fee from
|
|
155
157
|
/// * `fee_amount` - The fee amount to transfer
|
|
156
|
-
fn __charge_fee(env: &Env, token: &Address,
|
|
158
|
+
fn __charge_fee(env: &Env, token: &Address, from: &Address, fee_amount: i128) {
|
|
157
159
|
if fee_amount != 0 {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
160
|
+
let fee_deposit = Self::__fee_deposit_address(env);
|
|
161
|
+
TokenClient::new(env, token).transfer(from, &fee_deposit, &fee_amount);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// =========================================================================
|
|
166
|
+
// Management Functions
|
|
167
|
+
// =========================================================================
|
|
168
|
+
|
|
169
|
+
/// Sets the default fee rate in basis points.
|
|
170
|
+
///
|
|
171
|
+
/// # Arguments
|
|
172
|
+
/// * `default_fee_bps` - The default fee rate (0-10,000, where 10,000 = 100%)
|
|
173
|
+
fn __set_default_fee_bps(env: &Env, default_fee_bps: u64) {
|
|
174
|
+
assert_with_error!(env, default_fee_bps <= BASE_FEE_BPS, OFTFeeError::InvalidFeeBps);
|
|
175
|
+
|
|
176
|
+
let current_default = Self::__default_fee_bps(env);
|
|
177
|
+
assert_with_error!(env, current_default != default_fee_bps, OFTFeeError::SameValue);
|
|
178
|
+
|
|
179
|
+
OFTFeeStorage::set_default_fee_bps(env, &default_fee_bps);
|
|
180
|
+
|
|
181
|
+
DefaultFeeBpsSet { fee_bps: default_fee_bps }.publish(env);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/// Sets or removes the fee rate for a specific destination endpoint.
|
|
185
|
+
///
|
|
186
|
+
/// # Arguments
|
|
187
|
+
/// * `dst_eid` - The destination endpoint ID
|
|
188
|
+
/// * `fee_bps` - The fee rate (0-10,000), or None to remove the fee configuration
|
|
189
|
+
fn __set_fee_bps(env: &Env, dst_eid: u32, fee_bps: Option<u64>) {
|
|
190
|
+
let current_fee_bps = Self::__fee_bps(env, dst_eid);
|
|
191
|
+
assert_with_error!(env, current_fee_bps != fee_bps, OFTFeeError::SameValue);
|
|
192
|
+
|
|
193
|
+
match fee_bps {
|
|
194
|
+
Some(bps) => {
|
|
195
|
+
assert_with_error!(env, bps <= BASE_FEE_BPS, OFTFeeError::InvalidFeeBps);
|
|
196
|
+
OFTFeeStorage::set_fee_bps(env, dst_eid, &bps);
|
|
197
|
+
}
|
|
198
|
+
None => {
|
|
199
|
+
OFTFeeStorage::remove_fee_bps(env, dst_eid);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
FeeBpsSet { dst_eid, fee_bps }.publish(env);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/// Sets the address where collected fees will be deposited.
|
|
207
|
+
///
|
|
208
|
+
/// # Arguments
|
|
209
|
+
/// * `fee_deposit_address` - The address to deposit fees to
|
|
210
|
+
fn __set_fee_deposit_address(env: &Env, fee_deposit_address: &Address) {
|
|
211
|
+
if let Some(current_address) = OFTFeeStorage::fee_deposit_address(env) {
|
|
212
|
+
assert_with_error!(env, current_address != *fee_deposit_address, OFTFeeError::SameValue);
|
|
213
|
+
}
|
|
214
|
+
OFTFeeStorage::set_fee_deposit_address(env, fee_deposit_address);
|
|
215
|
+
FeeDepositAddressSet { fee_deposit_address: fee_deposit_address.clone() }.publish(env);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// =========================================================================
|
|
219
|
+
// View Functions
|
|
220
|
+
// =========================================================================
|
|
221
|
+
|
|
222
|
+
/// Returns the effective fee rate for a destination (destination-specific or default).
|
|
223
|
+
fn __effective_fee_bps(env: &Env, dst_eid: u32) -> u64 {
|
|
224
|
+
if OFTFeeStorage::has_fee_bps(env, dst_eid) {
|
|
225
|
+
OFTFeeStorage::fee_bps(env, dst_eid).unwrap()
|
|
226
|
+
} else {
|
|
227
|
+
OFTFeeStorage::default_fee_bps(env)
|
|
165
228
|
}
|
|
166
229
|
}
|
|
230
|
+
|
|
231
|
+
/// Returns the default fee rate in basis points.
|
|
232
|
+
fn __default_fee_bps(env: &Env) -> u64 {
|
|
233
|
+
OFTFeeStorage::default_fee_bps(env)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/// Returns the fee rate for a specific destination, if set.
|
|
237
|
+
fn __fee_bps(env: &Env, dst_eid: u32) -> Option<u64> {
|
|
238
|
+
OFTFeeStorage::fee_bps(env, dst_eid)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/// Returns the fee deposit address.
|
|
242
|
+
fn __fee_deposit_address(env: &Env) -> Address {
|
|
243
|
+
OFTFeeStorage::fee_deposit_address(env).unwrap_or_panic(env, OFTFeeError::InvalidFeeDepositAddress)
|
|
244
|
+
}
|
|
167
245
|
}
|