@layerzerolabs/protocol-stellar-v2 0.2.18 → 0.2.20
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 +303 -253
- package/.turbo/turbo-lint.log +66 -65
- package/.turbo/turbo-test.log +1312 -1282
- package/Cargo.lock +21 -8
- package/Cargo.toml +2 -0
- package/contracts/ERROR_SPEC.md +9 -2
- package/contracts/common-macros/src/contract_ttl.rs +18 -7
- package/contracts/common-macros/src/lib.rs +4 -4
- package/contracts/common-macros/src/tests/contract_ttl.rs +1 -1
- 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__upgradeable__snapshot_generated_upgradeable_code.snap +7 -12
- package/contracts/common-macros/src/upgradeable.rs +15 -21
- package/contracts/message-libs/uln-302/src/events.rs +4 -0
- package/contracts/message-libs/uln-302/src/send_uln.rs +23 -7
- package/contracts/message-libs/uln-302/src/tests/send_uln302/send.rs +38 -64
- package/contracts/oapps/counter/Cargo.toml +1 -0
- package/contracts/oapps/counter/integration_tests/setup_uln.rs +1 -1
- package/contracts/oapps/oapp/src/oapp_receiver.rs +1 -1
- package/contracts/oapps/oapp/src/tests/test_oapp_core.rs +113 -65
- package/contracts/oapps/oapp/src/tests/test_oapp_options_type3.rs +111 -82
- package/contracts/oapps/oapp/src/tests/test_oapp_receiver.rs +293 -65
- package/contracts/oapps/oapp/src/tests/test_oapp_sender.rs +331 -56
- package/contracts/oapps/oft/Cargo.toml +10 -7
- package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/test_oft_fee.rs +3 -4
- package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/test_pausable.rs +2 -3
- package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/test_rate_limiter.rs +1 -1
- package/contracts/oapps/oft/integration-tests/mod.rs +1 -1
- package/contracts/oapps/oft/integration-tests/setup.rs +28 -127
- package/contracts/oapps/oft/integration-tests/utils.rs +254 -21
- package/contracts/oapps/oft/src/extensions/oft_fee.rs +23 -8
- package/contracts/oapps/oft/src/extensions/pausable.rs +19 -4
- package/contracts/oapps/oft/src/extensions/rate_limiter.rs +52 -28
- package/contracts/oapps/oft/src/lib.rs +10 -14
- package/contracts/oapps/oft/src/oft.rs +143 -193
- package/contracts/oapps/oft/src/oft_types/lock_unlock.rs +9 -11
- package/contracts/oapps/oft/src/oft_types/mint_burn.rs +12 -14
- package/contracts/oapps/oft/src/oft_types/mod.rs +13 -0
- package/contracts/oapps/{oft-std → oft-core}/Cargo.toml +6 -4
- package/contracts/oapps/{oft-std → oft-core}/integration-tests/mod.rs +1 -1
- package/contracts/oapps/{oft-std → oft-core}/integration-tests/setup.rs +126 -29
- package/contracts/oapps/{oft → oft-core}/integration-tests/test_with_sml.rs +3 -3
- package/contracts/oapps/oft-core/integration-tests/utils.rs +201 -0
- package/contracts/oapps/oft-core/src/lib.rs +18 -0
- package/contracts/oapps/oft-core/src/oft_core.rs +479 -0
- package/contracts/oapps/{oft → oft-core}/src/tests/mod.rs +0 -2
- package/contracts/oapps/{oft → oft-core}/src/tests/test_lz_receive.rs +7 -7
- package/contracts/oapps/{oft → oft-core}/src/tests/test_oft_msg_codec.rs +4 -4
- package/contracts/oapps/{oft → oft-core}/src/tests/test_resolve_address.rs +3 -3
- package/contracts/oapps/{oft → oft-core}/src/tests/test_utils.rs +46 -27
- package/contracts/oapps/{oft → oft-core}/src/utils.rs +1 -1
- 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/src/buffer_reader.rs +1 -0
- package/contracts/utils/src/errors.rs +8 -2
- package/contracts/utils/src/ownable.rs +125 -3
- package/contracts/utils/src/tests/option_ext.rs +1 -1
- package/contracts/utils/src/tests/ownable.rs +445 -7
- package/contracts/utils/src/tests/ttl_configurable.rs +2 -2
- package/contracts/utils/src/tests/upgradeable.rs +372 -175
- package/contracts/utils/src/ttl_configurable.rs +3 -3
- package/contracts/utils/src/upgradeable.rs +48 -23
- package/contracts/workers/dvn/Cargo.toml +1 -0
- package/contracts/workers/dvn/src/auth.rs +12 -42
- package/contracts/workers/dvn/src/dvn.rs +16 -31
- 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 +1 -1
- package/contracts/workers/dvn-fee-lib/src/dvn_fee_lib.rs +3 -5
- package/contracts/workers/dvn-fee-lib/src/tests/dvn_fee_lib.rs +2 -3
- package/contracts/workers/executor/Cargo.toml +1 -0
- package/contracts/workers/executor/src/executor.rs +15 -26
- package/contracts/workers/executor-fee-lib/Cargo.toml +2 -1
- package/contracts/workers/executor-fee-lib/src/executor_fee_lib.rs +63 -5
- package/contracts/workers/executor-fee-lib/src/executor_option.rs +28 -1
- package/contracts/workers/executor-fee-lib/src/lib.rs +3 -0
- 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/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 +2 -1
- package/contracts/workers/price-feed/src/events.rs +1 -1
- package/contracts/workers/price-feed/src/lib.rs +3 -0
- package/contracts/workers/price-feed/src/price_feed.rs +6 -12
- 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 +0 -3
- 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 +1 -7
- package/contracts/workers/worker/src/tests/worker.rs +50 -42
- package/contracts/workers/worker/src/worker.rs +49 -58
- package/package.json +4 -5
- package/sdk/.turbo/turbo-test.log +229 -217
- package/sdk/dist/generated/bml.d.ts +39 -1
- package/sdk/dist/generated/bml.js +33 -8
- package/sdk/dist/generated/counter.d.ts +131 -3
- package/sdk/dist/generated/counter.js +41 -10
- package/sdk/dist/generated/dvn.d.ts +431 -362
- package/sdk/dist/generated/dvn.js +80 -55
- package/sdk/dist/generated/dvn_fee_lib.d.ts +327 -251
- package/sdk/dist/generated/dvn_fee_lib.js +55 -57
- package/sdk/dist/generated/endpoint.d.ts +131 -3
- package/sdk/dist/generated/endpoint.js +41 -10
- package/sdk/dist/generated/executor.d.ts +503 -339
- package/sdk/dist/generated/executor.js +80 -48
- package/sdk/dist/generated/executor_fee_lib.d.ts +395 -319
- package/sdk/dist/generated/executor_fee_lib.js +54 -56
- package/sdk/dist/generated/executor_helper.d.ts +53 -187
- package/sdk/dist/generated/executor_helper.js +47 -29
- 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 +1851 -0
- package/sdk/dist/generated/oft.js +347 -0
- package/sdk/dist/generated/price_feed.d.ts +329 -253
- package/sdk/dist/generated/price_feed.js +55 -57
- package/sdk/dist/generated/sml.d.ts +131 -3
- package/sdk/dist/generated/sml.js +41 -10
- package/sdk/dist/generated/treasury.d.ts +131 -3
- package/sdk/dist/generated/treasury.js +41 -10
- package/sdk/dist/generated/uln302.d.ts +131 -3
- package/sdk/dist/generated/uln302.js +43 -12
- package/sdk/dist/generated/upgrader.d.ts +201 -15
- package/sdk/dist/generated/upgrader.js +99 -1
- package/sdk/dist/index.d.ts +2 -2
- package/sdk/dist/index.js +3 -3
- package/sdk/package.json +3 -2
- package/sdk/src/index.ts +3 -3
- package/sdk/test/oft-sml.test.ts +20 -20
- package/sdk/test/upgrader.test.ts +2 -3
- package/sdk/turbo.json +8 -0
- package/tools/ts-bindings-gen/Cargo.toml +2 -0
- package/tools/ts-bindings-gen/src/main.rs +53 -5
- package/turbo.json +0 -2
- package/contracts/oapps/oft/src/interfaces/mint_burn_token.rs +0 -23
- package/contracts/oapps/oft/src/interfaces/mod.rs +0 -3
- package/contracts/oapps/oft/src/oft_impl.rs +0 -201
- package/contracts/oapps/oft/src/tests/extensions/mod.rs +0 -11
- package/contracts/oapps/oft/src/tests/extensions/setup.rs +0 -917
- package/contracts/oapps/oft/src/tests/extensions/test_oft_fee.rs +0 -751
- package/contracts/oapps/oft/src/tests/extensions/test_pausable.rs +0 -434
- package/contracts/oapps/oft/src/tests/extensions/test_rate_limiter.rs +0 -1080
- package/contracts/oapps/oft-std/integration-tests/utils.rs +0 -427
- package/contracts/oapps/oft-std/src/lib.rs +0 -16
- package/contracts/oapps/oft-std/src/oft.rs +0 -174
- package/sdk/dist/generated/oft_std.d.ts +0 -1722
- package/sdk/dist/generated/oft_std.js +0 -316
- package/sdk/dist/wasm/blocked-message-lib.d.ts +0 -1
- package/sdk/dist/wasm/blocked-message-lib.js +0 -2
- package/sdk/dist/wasm/counter.d.ts +0 -1
- package/sdk/dist/wasm/counter.js +0 -2
- package/sdk/dist/wasm/dvn-fee-lib.d.ts +0 -1
- package/sdk/dist/wasm/dvn-fee-lib.js +0 -2
- package/sdk/dist/wasm/dvn.d.ts +0 -1
- package/sdk/dist/wasm/dvn.js +0 -2
- package/sdk/dist/wasm/endpoint-v2.d.ts +0 -1
- package/sdk/dist/wasm/endpoint-v2.js +0 -2
- package/sdk/dist/wasm/executor-fee-lib.d.ts +0 -1
- package/sdk/dist/wasm/executor-fee-lib.js +0 -2
- package/sdk/dist/wasm/executor-helper.d.ts +0 -1
- package/sdk/dist/wasm/executor-helper.js +0 -2
- package/sdk/dist/wasm/executor.d.ts +0 -1
- package/sdk/dist/wasm/executor.js +0 -2
- package/sdk/dist/wasm/layerzero-views.d.ts +0 -1
- package/sdk/dist/wasm/layerzero-views.js +0 -2
- package/sdk/dist/wasm/oft-std.d.ts +0 -1
- package/sdk/dist/wasm/oft-std.js +0 -2
- package/sdk/dist/wasm/price-feed.d.ts +0 -1
- package/sdk/dist/wasm/price-feed.js +0 -2
- package/sdk/dist/wasm/simple-message-lib.d.ts +0 -1
- package/sdk/dist/wasm/simple-message-lib.js +0 -2
- package/sdk/dist/wasm/treasury.d.ts +0 -1
- package/sdk/dist/wasm/treasury.js +0 -2
- package/sdk/dist/wasm/uln302.d.ts +0 -1
- package/sdk/dist/wasm/uln302.js +0 -2
- package/sdk/dist/wasm/upgrader.d.ts +0 -1
- package/sdk/dist/wasm/upgrader.js +0 -2
- package/sdk/dist/wasm.d.ts +0 -15
- package/sdk/dist/wasm.js +0 -15
- /package/contracts/oapps/{oft-std → oft}/integration-tests/extensions/mod.rs +0 -0
- /package/contracts/oapps/{oft → oft-core}/src/codec/mod.rs +0 -0
- /package/contracts/oapps/{oft → oft-core}/src/codec/oft_compose_msg_codec.rs +0 -0
- /package/contracts/oapps/{oft → oft-core}/src/codec/oft_msg_codec.rs +0 -0
- /package/contracts/oapps/{oft → oft-core}/src/errors.rs +0 -0
- /package/contracts/oapps/{oft → oft-core}/src/events.rs +0 -0
- /package/contracts/oapps/{oft → oft-core}/src/storage.rs +0 -0
- /package/contracts/oapps/{oft → oft-core}/src/tests/test_decimals.rs +0 -0
- /package/contracts/oapps/{oft → oft-core}/src/tests/test_oft_compose_msg_codec.rs +0 -0
- /package/contracts/oapps/{oft → oft-core}/src/tests/test_oft_version.rs +0 -0
- /package/contracts/oapps/{oft → oft-core}/src/tests/test_quote_oft.rs +0 -0
- /package/contracts/oapps/{oft → oft-core}/src/tests/test_quote_send.rs +0 -0
- /package/contracts/oapps/{oft → oft-core}/src/tests/test_send.rs +0 -0
- /package/contracts/oapps/{oft → oft-core}/src/tests/test_token.rs +0 -0
- /package/contracts/oapps/{oft → oft-core}/src/types.rs +0 -0
- /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,869 @@
|
|
|
1
|
+
use super::setup::TestSetup;
|
|
2
|
+
use crate::errors::PriceFeedError;
|
|
3
|
+
use crate::types::{ArbitrumPriceExt, ModelType, SetEidToModelTypeParam, UpdatePrice, UpdatePriceExt};
|
|
4
|
+
use fee_lib_interfaces::Price;
|
|
5
|
+
use soroban_sdk::{testutils::Address as _, vec, Address};
|
|
6
|
+
|
|
7
|
+
// =============================================================================
|
|
8
|
+
// Construction
|
|
9
|
+
// =============================================================================
|
|
10
|
+
|
|
11
|
+
#[test]
|
|
12
|
+
fn test_constructor_sets_owner_and_price_updater() {
|
|
13
|
+
let setup = TestSetup::new();
|
|
14
|
+
|
|
15
|
+
assert_eq!(setup.client.owner(), Some(setup.owner.clone()));
|
|
16
|
+
assert_eq!(setup.client.is_price_updater(&setup.price_updater), true);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
#[test]
|
|
20
|
+
fn test_constructor_sets_default_values() {
|
|
21
|
+
let setup = TestSetup::new();
|
|
22
|
+
|
|
23
|
+
// Default price ratio denominator is 1e20
|
|
24
|
+
assert_eq!(setup.client.get_price_ratio_denominator(), 10u128.pow(20));
|
|
25
|
+
|
|
26
|
+
// Default Arbitrum compression percent is 47
|
|
27
|
+
assert_eq!(setup.client.arbitrum_compression_percent(), 47);
|
|
28
|
+
|
|
29
|
+
// Default native price USD is 0
|
|
30
|
+
assert_eq!(setup.client.native_token_price_usd(), 0);
|
|
31
|
+
|
|
32
|
+
// Default Arbitrum price ext
|
|
33
|
+
let arb_ext = setup.client.arbitrum_price_ext();
|
|
34
|
+
assert_eq!(arb_ext.gas_per_l2_tx, 0);
|
|
35
|
+
assert_eq!(arb_ext.gas_per_l1_calldata_byte, 0);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// =============================================================================
|
|
39
|
+
// ILayerZeroPriceFeed (Trait Impl) - view fns
|
|
40
|
+
// =============================================================================
|
|
41
|
+
|
|
42
|
+
#[test]
|
|
43
|
+
fn test_get_price_returns_none_for_unconfigured_eid() {
|
|
44
|
+
let setup = TestSetup::new();
|
|
45
|
+
assert_eq!(setup.client.get_price(&999), None);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// =============================================================================
|
|
49
|
+
// ILayerZeroPriceFeed (Trait Impl) - estimate_fee_by_eid
|
|
50
|
+
// =============================================================================
|
|
51
|
+
|
|
52
|
+
#[test]
|
|
53
|
+
#[should_panic(expected = "Error(Auth, InvalidAction)")]
|
|
54
|
+
fn test_estimate_fee_by_eid_requires_fee_lib_auth() {
|
|
55
|
+
let setup = TestSetup::new();
|
|
56
|
+
let fee_lib = Address::generate(&setup.env);
|
|
57
|
+
|
|
58
|
+
// Set up price so only fee_lib.require_auth() can fail.
|
|
59
|
+
let price = setup.default_test_price();
|
|
60
|
+
setup.setup_default_price(1, &price);
|
|
61
|
+
|
|
62
|
+
// No mock_auths for fee_lib.require_auth()
|
|
63
|
+
setup.client.estimate_fee_by_eid(&fee_lib, &1, &100, &100_000);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#[test]
|
|
67
|
+
fn test_estimate_fee_by_eid_default_model() {
|
|
68
|
+
let setup = TestSetup::new();
|
|
69
|
+
let fee_lib = Address::generate(&setup.env);
|
|
70
|
+
|
|
71
|
+
// Reference values:
|
|
72
|
+
// - EID: 101
|
|
73
|
+
// - calldata_size: 1000
|
|
74
|
+
// - gas: 500
|
|
75
|
+
let price = Price { price_ratio: 10u128.pow(20), gas_price_in_unit: 1_000_000_000, gas_per_byte: 16 };
|
|
76
|
+
setup.setup_default_price(101, &price);
|
|
77
|
+
|
|
78
|
+
// Authorize fee_lib
|
|
79
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, 101u32, 1000u32, 500u128));
|
|
80
|
+
let estimate = setup.client.estimate_fee_by_eid(&fee_lib, &101, &1000, &500);
|
|
81
|
+
|
|
82
|
+
// Expected fee (default model):
|
|
83
|
+
// gas_for_calldata = calldata_size * gas_per_byte
|
|
84
|
+
// = 1000 * 16
|
|
85
|
+
// = 16_000
|
|
86
|
+
// remote_fee = (gas_for_calldata + gas) * gas_price_in_unit
|
|
87
|
+
// = (16_000 + 500) * 1_000_000_000
|
|
88
|
+
// = 16_500 * 1_000_000_000
|
|
89
|
+
// = 16_500_000_000_000
|
|
90
|
+
// fee = (remote_fee * price_ratio) / price_ratio_denominator
|
|
91
|
+
// = (16_500_000_000_000 * 1e20) / 1e20
|
|
92
|
+
// = 16_500_000_000_000
|
|
93
|
+
|
|
94
|
+
assert_eq!(estimate.total_gas_fee, 16_500_000_000_000 as i128);
|
|
95
|
+
assert_eq!(estimate.price_ratio, price.price_ratio);
|
|
96
|
+
assert_eq!(estimate.price_ratio_denominator, 10u128.pow(20));
|
|
97
|
+
assert_eq!(estimate.native_price_usd, 0);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
#[test]
|
|
101
|
+
fn test_estimate_fee_by_eid_includes_native_price_usd_and_denominator() {
|
|
102
|
+
let setup = TestSetup::new();
|
|
103
|
+
let fee_lib = Address::generate(&setup.env);
|
|
104
|
+
|
|
105
|
+
// Change denominator from the default and ensure it's reflected in FeeEstimate.
|
|
106
|
+
let denom = 10u128.pow(18);
|
|
107
|
+
setup.mock_owner_auth("set_price_ratio_denominator", (denom,));
|
|
108
|
+
setup.client.set_price_ratio_denominator(&denom);
|
|
109
|
+
|
|
110
|
+
// Set native token USD price and ensure it's reflected in FeeEstimate.
|
|
111
|
+
let price_usd = 1234 * 10u128.pow(18);
|
|
112
|
+
setup.mock_price_updater_auth("set_native_token_price_usd", (&setup.price_updater, price_usd));
|
|
113
|
+
setup.client.set_native_token_price_usd(&setup.price_updater, &price_usd);
|
|
114
|
+
|
|
115
|
+
// Use price_ratio == denom so fee math stays 1:1 and easy to validate.
|
|
116
|
+
let price = Price { price_ratio: denom, gas_price_in_unit: 1_000_000, gas_per_byte: 16 };
|
|
117
|
+
setup.setup_default_price(1, &price);
|
|
118
|
+
|
|
119
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, 1u32, 10u32, 1_000u128));
|
|
120
|
+
let estimate = setup.client.estimate_fee_by_eid(&fee_lib, &1, &10, &1_000);
|
|
121
|
+
|
|
122
|
+
assert_eq!(estimate.price_ratio_denominator, denom);
|
|
123
|
+
assert_eq!(estimate.native_price_usd, price_usd);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
#[test]
|
|
127
|
+
fn test_estimate_fee_by_eid_with_different_price_ratio() {
|
|
128
|
+
let setup = TestSetup::new();
|
|
129
|
+
let fee_lib = Address::generate(&setup.env);
|
|
130
|
+
|
|
131
|
+
// Set up price with 2:1 price ratio (destination token worth 2x source token)
|
|
132
|
+
let price = Price {
|
|
133
|
+
price_ratio: 2 * 10u128.pow(20), // 2x ratio
|
|
134
|
+
gas_price_in_unit: 1_000_000,
|
|
135
|
+
gas_per_byte: 16,
|
|
136
|
+
};
|
|
137
|
+
setup.setup_default_price(1, &price);
|
|
138
|
+
|
|
139
|
+
// Authorize fee_lib
|
|
140
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, 1u32, 100u32, 100_000u128));
|
|
141
|
+
let estimate = setup.client.estimate_fee_by_eid(&fee_lib, &1, &100, &100_000);
|
|
142
|
+
|
|
143
|
+
// Fee should be 2x compared to 1:1 ratio:
|
|
144
|
+
// gas_for_calldata = calldata_size * gas_per_byte
|
|
145
|
+
// = 100 * 16
|
|
146
|
+
// = 1_600
|
|
147
|
+
// remote_fee = (gas_for_calldata + gas) * gas_price_in_unit
|
|
148
|
+
// = (1_600 + 100_000) * 1_000_000
|
|
149
|
+
// = 101_600 * 1_000_000
|
|
150
|
+
// = 101_600_000_000
|
|
151
|
+
// fee = (remote_fee * price_ratio) / price_ratio_denominator
|
|
152
|
+
// = (101_600_000_000 * (2 * 1e20)) / 1e20
|
|
153
|
+
// = 203_200_000_000
|
|
154
|
+
let gas_for_calldata = 100u128 * 16;
|
|
155
|
+
let remote_fee = (gas_for_calldata + 100_000) * 1_000_000;
|
|
156
|
+
let expected_fee = (remote_fee * price.price_ratio) / 10u128.pow(20);
|
|
157
|
+
|
|
158
|
+
assert_eq!(estimate.total_gas_fee, expected_fee as i128);
|
|
159
|
+
assert_eq!(estimate.price_ratio, price.price_ratio);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
#[test]
|
|
163
|
+
fn test_estimate_fee_by_eid_rejects_missing_price() {
|
|
164
|
+
let setup = TestSetup::new();
|
|
165
|
+
let fee_lib = Address::generate(&setup.env);
|
|
166
|
+
|
|
167
|
+
// No price set for EID 999
|
|
168
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, 999u32, 100u32, 100_000u128));
|
|
169
|
+
assert_eq!(
|
|
170
|
+
setup.client.try_estimate_fee_by_eid(&fee_lib, &999, &100, &100_000).unwrap_err().unwrap(),
|
|
171
|
+
PriceFeedError::NoPrice.into()
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// =============================================================================
|
|
176
|
+
// ILayerZeroPriceFeed - estimate_fee_by_eid (Arbitrum Model)
|
|
177
|
+
// =============================================================================
|
|
178
|
+
|
|
179
|
+
#[test]
|
|
180
|
+
fn test_estimate_fee_by_eid_arbitrum_model_hardcoded_eid() {
|
|
181
|
+
let setup = TestSetup::new();
|
|
182
|
+
let fee_lib = Address::generate(&setup.env);
|
|
183
|
+
|
|
184
|
+
// EID 110 is hardcoded as Arbitrum
|
|
185
|
+
let arb_price = Price { price_ratio: 10u128.pow(20), gas_price_in_unit: 10_000_000, gas_per_byte: 16 };
|
|
186
|
+
setup.setup_default_price(110, &arb_price);
|
|
187
|
+
|
|
188
|
+
// Set Arbitrum-specific parameters
|
|
189
|
+
let arb_ext = ArbitrumPriceExt { gas_per_l2_tx: 4176, gas_per_l1_calldata_byte: 29 };
|
|
190
|
+
let update = UpdatePriceExt { eid: 110, price: arb_price.clone(), extend: arb_ext.clone() };
|
|
191
|
+
setup.mock_price_updater_auth("set_price_for_arbitrum", (&setup.price_updater, &update));
|
|
192
|
+
setup.client.set_price_for_arbitrum(&setup.price_updater, &update);
|
|
193
|
+
|
|
194
|
+
// Authorize fee_lib
|
|
195
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, 110u32, 1000u32, 500u128));
|
|
196
|
+
let estimate = setup.client.estimate_fee_by_eid(&fee_lib, &110, &1000, &500);
|
|
197
|
+
|
|
198
|
+
// Expected fee (Arbitrum model):
|
|
199
|
+
// compressed_size = floor(calldata_size * compression_percent / 100)
|
|
200
|
+
// = floor((1000 * 47) / 100)
|
|
201
|
+
// = floor(470)
|
|
202
|
+
// = 470
|
|
203
|
+
// l1_calldata_gas = compressed_size * gas_per_l1_calldata_byte
|
|
204
|
+
// = 470 * 29
|
|
205
|
+
// = 13_630
|
|
206
|
+
// l2_calldata_gas = calldata_size * gas_per_byte
|
|
207
|
+
// = 1000 * 16
|
|
208
|
+
// = 16_000
|
|
209
|
+
// total_gas = gas + gas_per_l2_tx + l1_calldata_gas + l2_calldata_gas
|
|
210
|
+
// = 500 + 4_176 + 13_630 + 16_000
|
|
211
|
+
// = 34_306
|
|
212
|
+
// fee = (total_gas * gas_price_in_unit * price_ratio) / price_ratio_denominator
|
|
213
|
+
// = (34_306 * 10_000_000 * 1e20) / 1e20
|
|
214
|
+
// = 34_306 * 10_000_000
|
|
215
|
+
// = 343_060_000_000
|
|
216
|
+
|
|
217
|
+
assert_eq!(estimate.total_gas_fee, 343_060_000_000 as i128);
|
|
218
|
+
|
|
219
|
+
assert_eq!(estimate.price_ratio, arb_price.price_ratio);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
#[test]
|
|
223
|
+
fn test_estimate_fee_by_eid_arbitrum_model_hardcoded_eid_10143() {
|
|
224
|
+
let setup = TestSetup::new();
|
|
225
|
+
let fee_lib = Address::generate(&setup.env);
|
|
226
|
+
|
|
227
|
+
// EID 10143 is hardcoded as Arbitrum (same model selection path as 110).
|
|
228
|
+
// Use the same inputs as `test_estimate_fee_by_eid_arbitrum_model_hardcoded_eid`
|
|
229
|
+
// so the computed fee should be identical.
|
|
230
|
+
let arb_price = Price { price_ratio: 10u128.pow(20), gas_price_in_unit: 10_000_000, gas_per_byte: 16 };
|
|
231
|
+
|
|
232
|
+
let arb_ext = ArbitrumPriceExt { gas_per_l2_tx: 4176, gas_per_l1_calldata_byte: 29 };
|
|
233
|
+
let update = UpdatePriceExt { eid: 10143, price: arb_price.clone(), extend: arb_ext };
|
|
234
|
+
setup.mock_price_updater_auth("set_price_for_arbitrum", (&setup.price_updater, &update));
|
|
235
|
+
setup.client.set_price_for_arbitrum(&setup.price_updater, &update);
|
|
236
|
+
|
|
237
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, 10143u32, 1000u32, 500u128));
|
|
238
|
+
let estimate = setup.client.estimate_fee_by_eid(&fee_lib, &10143, &1000, &500);
|
|
239
|
+
|
|
240
|
+
assert_eq!(estimate.total_gas_fee, 343_060_000_000 as i128);
|
|
241
|
+
assert_eq!(estimate.price_ratio, arb_price.price_ratio);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
#[test]
|
|
245
|
+
fn test_estimate_fee_by_eid_arbitrum_model_uses_updated_compression_percent() {
|
|
246
|
+
let setup = TestSetup::new();
|
|
247
|
+
let fee_lib = Address::generate(&setup.env);
|
|
248
|
+
|
|
249
|
+
// Choose parameters so fee is driven purely by compression percent.
|
|
250
|
+
// gas=0, gas_per_l2_tx=0, gas_per_byte=0, gas_price_in_unit=1
|
|
251
|
+
let denom = setup.client.get_price_ratio_denominator();
|
|
252
|
+
let arb_price = Price { price_ratio: denom, gas_price_in_unit: 1, gas_per_byte: 0 };
|
|
253
|
+
setup.setup_default_price(110, &arb_price);
|
|
254
|
+
|
|
255
|
+
let arb_ext = ArbitrumPriceExt { gas_per_l2_tx: 0, gas_per_l1_calldata_byte: 100 };
|
|
256
|
+
let update = UpdatePriceExt { eid: 110, price: arb_price.clone(), extend: arb_ext };
|
|
257
|
+
setup.mock_price_updater_auth("set_price_for_arbitrum", (&setup.price_updater, &update));
|
|
258
|
+
setup.client.set_price_for_arbitrum(&setup.price_updater, &update);
|
|
259
|
+
|
|
260
|
+
// compression=0 => L1 calldata fee is 0 => total fee is 0
|
|
261
|
+
setup.mock_owner_auth("set_arbitrum_compression_percent", (0u128,));
|
|
262
|
+
setup.client.set_arbitrum_compression_percent(&0u128);
|
|
263
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, 110u32, 100u32, 0u128));
|
|
264
|
+
let est0 = setup.client.estimate_fee_by_eid(&fee_lib, &110, &100, &0);
|
|
265
|
+
assert_eq!(est0.total_gas_fee, 0);
|
|
266
|
+
|
|
267
|
+
// compression=100 => L1 calldata gas = (100 * 100 / 100) * 100 = 10_000
|
|
268
|
+
setup.mock_owner_auth("set_arbitrum_compression_percent", (100u128,));
|
|
269
|
+
setup.client.set_arbitrum_compression_percent(&100u128);
|
|
270
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, 110u32, 100u32, 0u128));
|
|
271
|
+
let est100 = setup.client.estimate_fee_by_eid(&fee_lib, &110, &100, &0);
|
|
272
|
+
assert_eq!(est100.total_gas_fee, 10_000);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
#[test]
|
|
276
|
+
fn test_estimate_fee_by_eid_arbitrum_model_configured_eid() {
|
|
277
|
+
let setup = TestSetup::new();
|
|
278
|
+
let fee_lib = Address::generate(&setup.env);
|
|
279
|
+
|
|
280
|
+
// Configure EID 200 as ArbStack
|
|
281
|
+
let params = vec![&setup.env, SetEidToModelTypeParam { dst_eid: 200, model_type: ModelType::ArbStack }];
|
|
282
|
+
setup.mock_owner_auth("set_eid_to_model_type", (¶ms,));
|
|
283
|
+
setup.client.set_eid_to_model_type(¶ms);
|
|
284
|
+
|
|
285
|
+
// Set price for EID 200
|
|
286
|
+
// Use the same parameters as `test_estimate_fee_by_eid_arbitrum_model_hardcoded_eid`
|
|
287
|
+
// so the expected fee is deterministic and validates the Arbitrum-model math path.
|
|
288
|
+
let arb_price = Price { price_ratio: 10u128.pow(20), gas_price_in_unit: 10_000_000, gas_per_byte: 16 };
|
|
289
|
+
setup.setup_default_price(200, &arb_price);
|
|
290
|
+
|
|
291
|
+
// Set Arbitrum-specific parameters
|
|
292
|
+
let arb_ext = ArbitrumPriceExt { gas_per_l2_tx: 4176, gas_per_l1_calldata_byte: 29 };
|
|
293
|
+
let update = UpdatePriceExt { eid: 200, price: arb_price.clone(), extend: arb_ext };
|
|
294
|
+
setup.mock_price_updater_auth("set_price_for_arbitrum", (&setup.price_updater, &update));
|
|
295
|
+
setup.client.set_price_for_arbitrum(&setup.price_updater, &update);
|
|
296
|
+
|
|
297
|
+
// Authorize fee_lib
|
|
298
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, 200u32, 1000u32, 500u128));
|
|
299
|
+
let estimate = setup.client.estimate_fee_by_eid(&fee_lib, &200, &1000, &500);
|
|
300
|
+
|
|
301
|
+
// Should use Arbitrum model (same expected fee as the hardcoded Arbitrum test)
|
|
302
|
+
assert_eq!(estimate.total_gas_fee, 343_060_000_000 as i128);
|
|
303
|
+
assert_eq!(estimate.price_ratio, arb_price.price_ratio);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// =============================================================================
|
|
307
|
+
// ILayerZeroPriceFeed - estimate_fee_by_eid (Optimism Model)
|
|
308
|
+
// =============================================================================
|
|
309
|
+
|
|
310
|
+
#[test]
|
|
311
|
+
fn test_estimate_fee_by_eid_optimism_model_hardcoded_eid() {
|
|
312
|
+
let setup = TestSetup::new();
|
|
313
|
+
let fee_lib = Address::generate(&setup.env);
|
|
314
|
+
|
|
315
|
+
// EID 111 is hardcoded as Optimism
|
|
316
|
+
// Need to set up both L1 (Ethereum) and L2 (Optimism) prices
|
|
317
|
+
|
|
318
|
+
let eth_price = Price { price_ratio: 10u128.pow(20), gas_price_in_unit: 646_718_991, gas_per_byte: 8 };
|
|
319
|
+
setup.setup_default_price(101, ð_price);
|
|
320
|
+
|
|
321
|
+
// Optimism price
|
|
322
|
+
let op_price = Price { price_ratio: 10u128.pow(20), gas_price_in_unit: 2_231_118, gas_per_byte: 16 };
|
|
323
|
+
setup.setup_default_price(111, &op_price);
|
|
324
|
+
|
|
325
|
+
// Authorize fee_lib
|
|
326
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, 111u32, 1000u32, 500u128));
|
|
327
|
+
let estimate = setup.client.estimate_fee_by_eid(&fee_lib, &111, &1000, &500);
|
|
328
|
+
|
|
329
|
+
// Expected fee (Optimism model):
|
|
330
|
+
// l1_fee = ((calldata_size * eth_gas_per_byte) + 3188) * eth_gas_price
|
|
331
|
+
// = ((1000 * 8) + 3188) * 646_718_991
|
|
332
|
+
// = (8_000 + 3_188) * 646_718_991
|
|
333
|
+
// = 11_188 * 646_718_991
|
|
334
|
+
// = 7_235_492_071_308
|
|
335
|
+
// l2_fee = ((calldata_size * op_gas_per_byte) + gas) * op_gas_price
|
|
336
|
+
// = ((1000 * 16) + 500) * 2_231_118
|
|
337
|
+
// = (16_000 + 500) * 2_231_118
|
|
338
|
+
// = 16_500 * 2_231_118
|
|
339
|
+
// = 36_813_447_000
|
|
340
|
+
// total_fee = (l1_fee * eth_price_ratio / denom) + (l2_fee * op_price_ratio / denom)
|
|
341
|
+
// = (7_235_492_071_308 * 1e20 / 1e20) + (36_813_447_000 * 1e20 / 1e20)
|
|
342
|
+
// = 7_235_492_071_308 + 36_813_447_000
|
|
343
|
+
// = 7_272_305_518_308
|
|
344
|
+
|
|
345
|
+
assert_eq!(estimate.total_gas_fee, 7_272_305_518_308 as i128);
|
|
346
|
+
assert_eq!(estimate.price_ratio, op_price.price_ratio);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
#[test]
|
|
350
|
+
fn test_estimate_fee_by_eid_optimism_model_goerli() {
|
|
351
|
+
let setup = TestSetup::new();
|
|
352
|
+
let fee_lib = Address::generate(&setup.env);
|
|
353
|
+
|
|
354
|
+
// EID 10132 is hardcoded as Optimism Goerli
|
|
355
|
+
// L1 lookup should be 10121 (Ethereum Goerli)
|
|
356
|
+
|
|
357
|
+
// Ethereum Goerli price
|
|
358
|
+
let eth_price = Price { price_ratio: 10u128.pow(20), gas_price_in_unit: 646_718_991, gas_per_byte: 8 };
|
|
359
|
+
setup.setup_default_price(10121, ð_price);
|
|
360
|
+
|
|
361
|
+
// Optimism Goerli price
|
|
362
|
+
let op_price = Price { price_ratio: 10u128.pow(20), gas_price_in_unit: 2_231_118, gas_per_byte: 16 };
|
|
363
|
+
setup.setup_default_price(10132, &op_price);
|
|
364
|
+
|
|
365
|
+
// Authorize fee_lib
|
|
366
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, 10132u32, 1000u32, 500u128));
|
|
367
|
+
let estimate = setup.client.estimate_fee_by_eid(&fee_lib, &10132, &1000, &500);
|
|
368
|
+
|
|
369
|
+
// Deterministic expected fee (Optimism model):
|
|
370
|
+
// L1 uses Ethereum Goerli (10121) with +3188 overhead, L2 uses Optimism Goerli (10132).
|
|
371
|
+
assert_eq!(estimate.total_gas_fee, 7_272_305_518_308 as i128);
|
|
372
|
+
assert_eq!(estimate.price_ratio, op_price.price_ratio);
|
|
373
|
+
}
|
|
374
|
+
#[test]
|
|
375
|
+
fn test_estimate_fee_by_eid_optimism_model_configured_eid() {
|
|
376
|
+
let setup = TestSetup::new();
|
|
377
|
+
let fee_lib = Address::generate(&setup.env);
|
|
378
|
+
|
|
379
|
+
// Configure EID 300 as OpStack
|
|
380
|
+
let params = vec![&setup.env, SetEidToModelTypeParam { dst_eid: 300, model_type: ModelType::OpStack }];
|
|
381
|
+
setup.mock_owner_auth("set_eid_to_model_type", (¶ms,));
|
|
382
|
+
setup.client.set_eid_to_model_type(¶ms);
|
|
383
|
+
|
|
384
|
+
// Set up Ethereum price (EID 101 used for mainnet L1 lookup)
|
|
385
|
+
let eth_price = Price { price_ratio: 10u128.pow(20), gas_price_in_unit: 646_718_991, gas_per_byte: 8 };
|
|
386
|
+
setup.setup_default_price(101, ð_price);
|
|
387
|
+
|
|
388
|
+
// Set up Optimism price for EID 300
|
|
389
|
+
let op_price = Price { price_ratio: 10u128.pow(20), gas_price_in_unit: 2_231_118, gas_per_byte: 16 };
|
|
390
|
+
setup.setup_default_price(300, &op_price);
|
|
391
|
+
|
|
392
|
+
// Compare configured OpStack EID (300) to hardcoded Optimism EID (111).
|
|
393
|
+
// With identical L1/L2 prices and inputs, the fee must match if we are on the Optimism path.
|
|
394
|
+
setup.setup_default_price(111, &op_price);
|
|
395
|
+
|
|
396
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, 300u32, 1000u32, 500u128));
|
|
397
|
+
let estimate_300 = setup.client.estimate_fee_by_eid(&fee_lib, &300, &1000, &500);
|
|
398
|
+
|
|
399
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, 111u32, 1000u32, 500u128));
|
|
400
|
+
let estimate_111 = setup.client.estimate_fee_by_eid(&fee_lib, &111, &1000, &500);
|
|
401
|
+
|
|
402
|
+
assert_eq!(estimate_300.total_gas_fee, estimate_111.total_gas_fee);
|
|
403
|
+
assert_eq!(estimate_300.price_ratio, estimate_111.price_ratio);
|
|
404
|
+
assert_eq!(estimate_300.price_ratio, op_price.price_ratio);
|
|
405
|
+
assert_eq!(estimate_300.total_gas_fee, 7_272_305_518_308 as i128);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
#[test]
|
|
409
|
+
fn test_estimate_fee_by_eid_uses_modulo_for_model_type_and_price_lookup_non_hardcoded() {
|
|
410
|
+
let setup = TestSetup::new();
|
|
411
|
+
let fee_lib = Address::generate(&setup.env);
|
|
412
|
+
|
|
413
|
+
// Pick a non-hardcoded EID so the "configured model type" branch is used.
|
|
414
|
+
// 42_345 % 30_000 == 12_345.
|
|
415
|
+
let base_eid: u32 = 12_345;
|
|
416
|
+
let dst_eid: u32 = 42_345;
|
|
417
|
+
|
|
418
|
+
// Configure base EID as OpStack.
|
|
419
|
+
let params = vec![&setup.env, SetEidToModelTypeParam { dst_eid: base_eid, model_type: ModelType::OpStack }];
|
|
420
|
+
setup.mock_owner_auth("set_eid_to_model_type", (¶ms,));
|
|
421
|
+
setup.client.set_eid_to_model_type(¶ms);
|
|
422
|
+
|
|
423
|
+
// For 12_345 (>= 10_000 and < 20_000), L1 lookup id is 10_161 per contract logic.
|
|
424
|
+
let l1_lookup: u32 = 10_161;
|
|
425
|
+
let eth_price = Price { price_ratio: 10u128.pow(20), gas_price_in_unit: 10_000_000_000, gas_per_byte: 16 };
|
|
426
|
+
setup.setup_default_price(l1_lookup, ð_price);
|
|
427
|
+
|
|
428
|
+
// L2 price for base_eid (the modulo'd EID that gets used for lookup).
|
|
429
|
+
let l2_price = Price { price_ratio: 10u128.pow(20), gas_price_in_unit: 1_000_000, gas_per_byte: 16 };
|
|
430
|
+
setup.setup_default_price(base_eid, &l2_price);
|
|
431
|
+
|
|
432
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, dst_eid, 100u32, 100_000u128));
|
|
433
|
+
let estimate_dst = setup.client.estimate_fee_by_eid(&fee_lib, &dst_eid, &100, &100_000);
|
|
434
|
+
|
|
435
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, base_eid, 100u32, 100_000u128));
|
|
436
|
+
let estimate_base = setup.client.estimate_fee_by_eid(&fee_lib, &base_eid, &100, &100_000);
|
|
437
|
+
|
|
438
|
+
// The contract reduces dst_eid modulo 30_000 before model selection and price lookup.
|
|
439
|
+
assert_eq!(estimate_dst.total_gas_fee, estimate_base.total_gas_fee);
|
|
440
|
+
assert_eq!(estimate_dst.price_ratio, estimate_base.price_ratio);
|
|
441
|
+
assert_eq!(estimate_dst.price_ratio, l2_price.price_ratio);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// =============================================================================
|
|
445
|
+
// ILayerZeroPriceFeed - estimate_fee_by_eid (EID modulo 30000)
|
|
446
|
+
// =============================================================================
|
|
447
|
+
|
|
448
|
+
#[test]
|
|
449
|
+
fn test_estimate_fee_by_eid_modulo_30000() {
|
|
450
|
+
let setup = TestSetup::new();
|
|
451
|
+
let fee_lib = Address::generate(&setup.env);
|
|
452
|
+
|
|
453
|
+
// EID 30110 is treated as 110 (Arbitrum) after modulo 30000
|
|
454
|
+
// The price lookup uses the modulo'd EID (110), so we set price for EID 110
|
|
455
|
+
let arb_price = Price { price_ratio: 10u128.pow(20), gas_price_in_unit: 100_000, gas_per_byte: 8 };
|
|
456
|
+
setup.setup_default_price(110, &arb_price);
|
|
457
|
+
|
|
458
|
+
// Set Arbitrum-specific parameters (stored globally, not per-EID)
|
|
459
|
+
let arb_ext = ArbitrumPriceExt { gas_per_l2_tx: 50_000, gas_per_l1_calldata_byte: 16 };
|
|
460
|
+
let update = UpdatePriceExt { eid: 110, price: arb_price.clone(), extend: arb_ext };
|
|
461
|
+
setup.mock_price_updater_auth("set_price_for_arbitrum", (&setup.price_updater, &update));
|
|
462
|
+
setup.client.set_price_for_arbitrum(&setup.price_updater, &update);
|
|
463
|
+
|
|
464
|
+
// Authorize fee_lib for EID 30110 (the original EID in the call)
|
|
465
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, 30110u32, 100u32, 100_000u128));
|
|
466
|
+
let estimate_30110 = setup.client.estimate_fee_by_eid(&fee_lib, &30110, &100, &100_000);
|
|
467
|
+
|
|
468
|
+
setup.mock_auth(&fee_lib, "estimate_fee_by_eid", (&fee_lib, 110u32, 100u32, 100_000u128));
|
|
469
|
+
let estimate_110 = setup.client.estimate_fee_by_eid(&fee_lib, &110, &100, &100_000);
|
|
470
|
+
|
|
471
|
+
// Should use Arbitrum model because 30110 % 30000 = 110
|
|
472
|
+
assert_eq!(estimate_30110.total_gas_fee, estimate_110.total_gas_fee);
|
|
473
|
+
assert_eq!(estimate_30110.price_ratio, estimate_110.price_ratio);
|
|
474
|
+
assert_eq!(estimate_30110.price_ratio, arb_price.price_ratio);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
#[test]
|
|
478
|
+
fn test_estimate_fee_by_eid_rejects_when_fee_exceeds_i128_max() {
|
|
479
|
+
let setup = TestSetup::new();
|
|
480
|
+
let fee_lib = Address::generate(&setup.env);
|
|
481
|
+
|
|
482
|
+
// Avoid auth-mock brittleness for this pure arithmetic/overflow test.
|
|
483
|
+
setup.env.mock_all_auths();
|
|
484
|
+
|
|
485
|
+
// Use denominator=1 and price_ratio=1 so we avoid u128 overflow in
|
|
486
|
+
// `remote_fee * price_ratio` while still being able to exceed i128::MAX.
|
|
487
|
+
setup.client.set_price_ratio_denominator(&1u128);
|
|
488
|
+
|
|
489
|
+
let price = Price { price_ratio: 1u128, gas_price_in_unit: 1u64, gas_per_byte: 0 };
|
|
490
|
+
let prices = vec![&setup.env, UpdatePrice { eid: 1, price: price.clone() }];
|
|
491
|
+
setup.client.set_price(&setup.price_updater, &prices);
|
|
492
|
+
|
|
493
|
+
// With calldata_size=0 and gas_per_byte=0:
|
|
494
|
+
// remote_fee = gas * 1 == gas, and fee == remote_fee (since denom=1, ratio=1).
|
|
495
|
+
let gas: u128 = (i128::MAX as u128) + 1;
|
|
496
|
+
assert_eq!(
|
|
497
|
+
setup.client.try_estimate_fee_by_eid(&fee_lib, &1, &0, &gas).unwrap_err().unwrap(),
|
|
498
|
+
PriceFeedError::Overflow.into()
|
|
499
|
+
);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
// =============================================================================
|
|
503
|
+
// Owner Functions
|
|
504
|
+
// =============================================================================
|
|
505
|
+
|
|
506
|
+
#[test]
|
|
507
|
+
fn test_set_price_updater_add_and_remove() {
|
|
508
|
+
let setup = TestSetup::new();
|
|
509
|
+
let new_updater = Address::generate(&setup.env);
|
|
510
|
+
|
|
511
|
+
// Add new price updater
|
|
512
|
+
setup.mock_owner_auth("set_price_updater", (&new_updater, true));
|
|
513
|
+
setup.client.set_price_updater(&new_updater, &true);
|
|
514
|
+
assert_eq!(setup.client.is_price_updater(&new_updater), true);
|
|
515
|
+
|
|
516
|
+
// Remove price updater
|
|
517
|
+
setup.mock_owner_auth("set_price_updater", (&new_updater, false));
|
|
518
|
+
setup.client.set_price_updater(&new_updater, &false);
|
|
519
|
+
assert_eq!(setup.client.is_price_updater(&new_updater), false);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
#[test]
|
|
523
|
+
#[should_panic(expected = "Error(Auth, InvalidAction)")]
|
|
524
|
+
fn test_set_price_updater_requires_owner_auth() {
|
|
525
|
+
let setup = TestSetup::new();
|
|
526
|
+
let new_updater = Address::generate(&setup.env);
|
|
527
|
+
|
|
528
|
+
// No mock_auths -> owner.require_auth() must fail
|
|
529
|
+
setup.client.set_price_updater(&new_updater, &true);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
#[test]
|
|
533
|
+
fn test_set_price_ratio_denominator_success() {
|
|
534
|
+
let setup = TestSetup::new();
|
|
535
|
+
let new_denominator = 100_000_000u128;
|
|
536
|
+
|
|
537
|
+
setup.mock_owner_auth("set_price_ratio_denominator", (new_denominator,));
|
|
538
|
+
setup.client.set_price_ratio_denominator(&new_denominator);
|
|
539
|
+
|
|
540
|
+
assert_eq!(setup.client.get_price_ratio_denominator(), new_denominator);
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
#[test]
|
|
544
|
+
fn test_set_price_ratio_denominator_rejects_zero() {
|
|
545
|
+
let setup = TestSetup::new();
|
|
546
|
+
|
|
547
|
+
setup.mock_owner_auth("set_price_ratio_denominator", (0u128,));
|
|
548
|
+
assert_eq!(
|
|
549
|
+
setup.client.try_set_price_ratio_denominator(&0).unwrap_err().unwrap(),
|
|
550
|
+
PriceFeedError::InvalidDenominator.into()
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
#[test]
|
|
555
|
+
#[should_panic(expected = "Error(Auth, InvalidAction)")]
|
|
556
|
+
fn test_set_price_ratio_denominator_requires_owner_auth() {
|
|
557
|
+
let setup = TestSetup::new();
|
|
558
|
+
let new_denominator = 10u128.pow(18);
|
|
559
|
+
|
|
560
|
+
// No mock_auths
|
|
561
|
+
setup.client.set_price_ratio_denominator(&new_denominator);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
#[test]
|
|
565
|
+
fn test_set_arbitrum_compression_percent_success() {
|
|
566
|
+
let setup = TestSetup::new();
|
|
567
|
+
let new_percent = 50u128;
|
|
568
|
+
|
|
569
|
+
setup.mock_owner_auth("set_arbitrum_compression_percent", (new_percent,));
|
|
570
|
+
setup.client.set_arbitrum_compression_percent(&new_percent);
|
|
571
|
+
|
|
572
|
+
assert_eq!(setup.client.arbitrum_compression_percent(), new_percent);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
#[test]
|
|
576
|
+
#[should_panic(expected = "Error(Auth, InvalidAction)")]
|
|
577
|
+
fn test_set_arbitrum_compression_percent_requires_owner_auth() {
|
|
578
|
+
let setup = TestSetup::new();
|
|
579
|
+
let new_percent = 50u128;
|
|
580
|
+
|
|
581
|
+
// No mock_auths
|
|
582
|
+
setup.client.set_arbitrum_compression_percent(&new_percent);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
#[test]
|
|
586
|
+
fn test_set_eid_to_model_type_success() {
|
|
587
|
+
let setup = TestSetup::new();
|
|
588
|
+
|
|
589
|
+
let params = vec![
|
|
590
|
+
&setup.env,
|
|
591
|
+
SetEidToModelTypeParam { dst_eid: 100, model_type: ModelType::OpStack },
|
|
592
|
+
SetEidToModelTypeParam { dst_eid: 200, model_type: ModelType::ArbStack },
|
|
593
|
+
];
|
|
594
|
+
|
|
595
|
+
setup.mock_owner_auth("set_eid_to_model_type", (¶ms,));
|
|
596
|
+
setup.client.set_eid_to_model_type(¶ms);
|
|
597
|
+
|
|
598
|
+
assert_eq!(setup.client.eid_to_model_type(&100), ModelType::OpStack);
|
|
599
|
+
assert_eq!(setup.client.eid_to_model_type(&200), ModelType::ArbStack);
|
|
600
|
+
// Unconfigured EID returns Default
|
|
601
|
+
assert_eq!(setup.client.eid_to_model_type(&300), ModelType::Default);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
#[test]
|
|
605
|
+
#[should_panic(expected = "Error(Auth, InvalidAction)")]
|
|
606
|
+
fn test_set_eid_to_model_type_requires_owner_auth() {
|
|
607
|
+
let setup = TestSetup::new();
|
|
608
|
+
|
|
609
|
+
let params = vec![&setup.env, SetEidToModelTypeParam { dst_eid: 100, model_type: ModelType::OpStack }];
|
|
610
|
+
|
|
611
|
+
// No mock_auths
|
|
612
|
+
setup.client.set_eid_to_model_type(¶ms);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// =============================================================================
|
|
616
|
+
// Price Updater Functions
|
|
617
|
+
// =============================================================================
|
|
618
|
+
|
|
619
|
+
#[test]
|
|
620
|
+
fn test_set_price_with_price_updater() {
|
|
621
|
+
let setup = TestSetup::new();
|
|
622
|
+
|
|
623
|
+
let price = setup.new_price(10u128.pow(20), 1_000_000, 16);
|
|
624
|
+
let prices = vec![&setup.env, UpdatePrice { eid: 1, price: price.clone() }];
|
|
625
|
+
|
|
626
|
+
setup.mock_price_updater_auth("set_price", (&setup.price_updater, &prices));
|
|
627
|
+
setup.client.set_price(&setup.price_updater, &prices);
|
|
628
|
+
|
|
629
|
+
assert_eq!(setup.client.get_price(&1), Some(price));
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
#[test]
|
|
633
|
+
fn test_set_price_with_owner() {
|
|
634
|
+
let setup = TestSetup::new();
|
|
635
|
+
|
|
636
|
+
let price = setup.new_price(10u128.pow(20), 2_000_000, 32);
|
|
637
|
+
let prices = vec![&setup.env, UpdatePrice { eid: 2, price: price.clone() }];
|
|
638
|
+
|
|
639
|
+
// Owner can also set prices
|
|
640
|
+
setup.mock_owner_auth("set_price", (&setup.owner, &prices));
|
|
641
|
+
setup.client.set_price(&setup.owner, &prices);
|
|
642
|
+
|
|
643
|
+
assert_eq!(setup.client.get_price(&2), Some(price));
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
#[test]
|
|
647
|
+
fn test_set_price_multiple_eids() {
|
|
648
|
+
let setup = TestSetup::new();
|
|
649
|
+
|
|
650
|
+
let price1 = setup.new_price(10u128.pow(20), 1_000_000_000, 16);
|
|
651
|
+
let price2 = setup.new_price(2 * 10u128.pow(20), 2_000_000_000, 32);
|
|
652
|
+
let prices = vec![
|
|
653
|
+
&setup.env,
|
|
654
|
+
UpdatePrice { eid: 101, price: price1.clone() },
|
|
655
|
+
UpdatePrice { eid: 102, price: price2.clone() },
|
|
656
|
+
];
|
|
657
|
+
|
|
658
|
+
setup.mock_price_updater_auth("set_price", (&setup.price_updater, &prices));
|
|
659
|
+
setup.client.set_price(&setup.price_updater, &prices);
|
|
660
|
+
|
|
661
|
+
assert_eq!(setup.client.get_price(&101), Some(price1));
|
|
662
|
+
assert_eq!(setup.client.get_price(&102), Some(price2));
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
#[test]
|
|
666
|
+
fn test_set_price_rejects_non_price_updater() {
|
|
667
|
+
let setup = TestSetup::new();
|
|
668
|
+
|
|
669
|
+
let non_updater = Address::generate(&setup.env);
|
|
670
|
+
let price = setup.default_test_price();
|
|
671
|
+
let prices = vec![&setup.env, UpdatePrice { eid: 1, price }];
|
|
672
|
+
|
|
673
|
+
setup.mock_auth(&non_updater, "set_price", (&non_updater, &prices));
|
|
674
|
+
assert_eq!(
|
|
675
|
+
setup.client.try_set_price(&non_updater, &prices).unwrap_err().unwrap(),
|
|
676
|
+
PriceFeedError::OnlyPriceUpdater.into()
|
|
677
|
+
);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
#[test]
|
|
681
|
+
#[should_panic(expected = "Error(Auth, InvalidAction)")]
|
|
682
|
+
fn test_set_price_requires_caller_auth_even_if_price_updater() {
|
|
683
|
+
let setup = TestSetup::new();
|
|
684
|
+
|
|
685
|
+
let price = setup.default_test_price();
|
|
686
|
+
let prices = vec![&setup.env, UpdatePrice { eid: 1, price }];
|
|
687
|
+
|
|
688
|
+
// price_updater is active, but no mock_auths -> caller.require_auth() must fail.
|
|
689
|
+
setup.client.set_price(&setup.price_updater, &prices);
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
#[test]
|
|
693
|
+
fn test_set_price_for_arbitrum_success() {
|
|
694
|
+
let setup = TestSetup::new();
|
|
695
|
+
|
|
696
|
+
let price = setup.new_price(10u128.pow(20), 500_000, 8);
|
|
697
|
+
let arb_ext = ArbitrumPriceExt { gas_per_l2_tx: 100_000, gas_per_l1_calldata_byte: 16 };
|
|
698
|
+
let update = UpdatePriceExt { eid: 110, price: price.clone(), extend: arb_ext.clone() };
|
|
699
|
+
|
|
700
|
+
setup.mock_price_updater_auth("set_price_for_arbitrum", (&setup.price_updater, &update));
|
|
701
|
+
setup.client.set_price_for_arbitrum(&setup.price_updater, &update);
|
|
702
|
+
|
|
703
|
+
assert_eq!(setup.client.get_price(&110), Some(price));
|
|
704
|
+
assert_eq!(setup.client.arbitrum_price_ext(), arb_ext);
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
#[test]
|
|
708
|
+
fn test_set_price_for_arbitrum_overwrites_arbitrum_price_ext() {
|
|
709
|
+
let setup = TestSetup::new();
|
|
710
|
+
|
|
711
|
+
let price = setup.default_test_price();
|
|
712
|
+
let ext1 = ArbitrumPriceExt { gas_per_l2_tx: 1, gas_per_l1_calldata_byte: 2 };
|
|
713
|
+
let upd1 = UpdatePriceExt { eid: 110, price: price.clone(), extend: ext1.clone() };
|
|
714
|
+
setup.mock_price_updater_auth("set_price_for_arbitrum", (&setup.price_updater, &upd1));
|
|
715
|
+
setup.client.set_price_for_arbitrum(&setup.price_updater, &upd1);
|
|
716
|
+
assert_eq!(setup.client.arbitrum_price_ext(), ext1);
|
|
717
|
+
|
|
718
|
+
let ext2 = ArbitrumPriceExt { gas_per_l2_tx: 999, gas_per_l1_calldata_byte: 888 };
|
|
719
|
+
let upd2 = UpdatePriceExt { eid: 110, price, extend: ext2.clone() };
|
|
720
|
+
setup.mock_price_updater_auth("set_price_for_arbitrum", (&setup.price_updater, &upd2));
|
|
721
|
+
setup.client.set_price_for_arbitrum(&setup.price_updater, &upd2);
|
|
722
|
+
assert_eq!(setup.client.arbitrum_price_ext(), ext2);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
#[test]
|
|
726
|
+
fn test_set_price_for_arbitrum_rejects_non_price_updater() {
|
|
727
|
+
let setup = TestSetup::new();
|
|
728
|
+
|
|
729
|
+
let non_updater = Address::generate(&setup.env);
|
|
730
|
+
let price = setup.default_test_price();
|
|
731
|
+
let arb_ext = ArbitrumPriceExt { gas_per_l2_tx: 100_000, gas_per_l1_calldata_byte: 16 };
|
|
732
|
+
let update = UpdatePriceExt { eid: 110, price, extend: arb_ext };
|
|
733
|
+
|
|
734
|
+
setup.mock_auth(&non_updater, "set_price_for_arbitrum", (&non_updater, &update));
|
|
735
|
+
assert_eq!(
|
|
736
|
+
setup.client.try_set_price_for_arbitrum(&non_updater, &update).unwrap_err().unwrap(),
|
|
737
|
+
PriceFeedError::OnlyPriceUpdater.into()
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
#[test]
|
|
742
|
+
#[should_panic(expected = "Error(Auth, InvalidAction)")]
|
|
743
|
+
fn test_set_price_for_arbitrum_requires_caller_auth_even_if_price_updater() {
|
|
744
|
+
let setup = TestSetup::new();
|
|
745
|
+
|
|
746
|
+
let price = setup.default_test_price();
|
|
747
|
+
let arb_ext = ArbitrumPriceExt { gas_per_l2_tx: 100_000, gas_per_l1_calldata_byte: 16 };
|
|
748
|
+
let update = UpdatePriceExt { eid: 110, price, extend: arb_ext };
|
|
749
|
+
|
|
750
|
+
// price_updater is active, but no mock_auths -> caller.require_auth() must fail.
|
|
751
|
+
setup.client.set_price_for_arbitrum(&setup.price_updater, &update);
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
#[test]
|
|
755
|
+
fn test_set_native_token_price_usd_success() {
|
|
756
|
+
let setup = TestSetup::new();
|
|
757
|
+
let price_usd = 2500 * 10u128.pow(18); // $2500 scaled
|
|
758
|
+
|
|
759
|
+
setup.mock_price_updater_auth("set_native_token_price_usd", (&setup.price_updater, price_usd));
|
|
760
|
+
setup.client.set_native_token_price_usd(&setup.price_updater, &price_usd);
|
|
761
|
+
|
|
762
|
+
assert_eq!(setup.client.native_token_price_usd(), price_usd);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
#[test]
|
|
766
|
+
fn test_set_native_token_price_usd_with_owner() {
|
|
767
|
+
let setup = TestSetup::new();
|
|
768
|
+
let price_usd = 3000 * 10u128.pow(18);
|
|
769
|
+
|
|
770
|
+
setup.mock_owner_auth("set_native_token_price_usd", (&setup.owner, price_usd));
|
|
771
|
+
setup.client.set_native_token_price_usd(&setup.owner, &price_usd);
|
|
772
|
+
|
|
773
|
+
assert_eq!(setup.client.native_token_price_usd(), price_usd);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
#[test]
|
|
777
|
+
fn test_set_native_token_price_usd_rejects_non_price_updater() {
|
|
778
|
+
let setup = TestSetup::new();
|
|
779
|
+
|
|
780
|
+
let non_updater = Address::generate(&setup.env);
|
|
781
|
+
let price_usd = 2500 * 10u128.pow(18);
|
|
782
|
+
|
|
783
|
+
setup.mock_auth(&non_updater, "set_native_token_price_usd", (&non_updater, price_usd));
|
|
784
|
+
assert_eq!(
|
|
785
|
+
setup.client.try_set_native_token_price_usd(&non_updater, &price_usd).unwrap_err().unwrap(),
|
|
786
|
+
PriceFeedError::OnlyPriceUpdater.into()
|
|
787
|
+
);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
#[test]
|
|
791
|
+
#[should_panic(expected = "Error(Auth, InvalidAction)")]
|
|
792
|
+
fn test_set_native_token_price_usd_requires_caller_auth_even_if_price_updater() {
|
|
793
|
+
let setup = TestSetup::new();
|
|
794
|
+
let price_usd = 2500 * 10u128.pow(18);
|
|
795
|
+
|
|
796
|
+
// price_updater is active, but no mock_auths -> caller.require_auth() must fail.
|
|
797
|
+
setup.client.set_native_token_price_usd(&setup.price_updater, &price_usd);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// =============================================================================
|
|
801
|
+
// View Functions
|
|
802
|
+
// =============================================================================
|
|
803
|
+
|
|
804
|
+
#[test]
|
|
805
|
+
fn test_is_price_updater_returns_false_for_unknown_address() {
|
|
806
|
+
let setup = TestSetup::new();
|
|
807
|
+
let unknown = Address::generate(&setup.env);
|
|
808
|
+
|
|
809
|
+
assert_eq!(setup.client.is_price_updater(&unknown), false);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// =============================================================================
|
|
813
|
+
// Edge Cases
|
|
814
|
+
// =============================================================================
|
|
815
|
+
|
|
816
|
+
#[test]
|
|
817
|
+
fn test_price_update_overwrites_previous() {
|
|
818
|
+
let setup = TestSetup::new();
|
|
819
|
+
|
|
820
|
+
let price1 = setup.new_price(10u128.pow(20), 1_000_000, 16);
|
|
821
|
+
setup.setup_default_price(1, &price1);
|
|
822
|
+
assert_eq!(setup.client.get_price(&1), Some(price1));
|
|
823
|
+
|
|
824
|
+
// Update to new price
|
|
825
|
+
let price2 = setup.new_price(2 * 10u128.pow(20), 2_000_000, 32);
|
|
826
|
+
setup.setup_default_price(1, &price2);
|
|
827
|
+
assert_eq!(setup.client.get_price(&1), Some(price2));
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
#[test]
|
|
831
|
+
fn test_multiple_price_updaters() {
|
|
832
|
+
let setup = TestSetup::new();
|
|
833
|
+
|
|
834
|
+
// Add a second price updater
|
|
835
|
+
let updater2 = Address::generate(&setup.env);
|
|
836
|
+
setup.mock_owner_auth("set_price_updater", (&updater2, true));
|
|
837
|
+
setup.client.set_price_updater(&updater2, &true);
|
|
838
|
+
|
|
839
|
+
// Both updaters should be able to set prices
|
|
840
|
+
let price1 = setup.new_price(10u128.pow(20), 1_000_000, 16);
|
|
841
|
+
let prices1 = vec![&setup.env, UpdatePrice { eid: 1, price: price1.clone() }];
|
|
842
|
+
setup.mock_price_updater_auth("set_price", (&setup.price_updater, &prices1));
|
|
843
|
+
setup.client.set_price(&setup.price_updater, &prices1);
|
|
844
|
+
assert_eq!(setup.client.get_price(&1), Some(price1));
|
|
845
|
+
|
|
846
|
+
let price2 = setup.new_price(2 * 10u128.pow(20), 2_000_000, 32);
|
|
847
|
+
let prices2 = vec![&setup.env, UpdatePrice { eid: 2, price: price2.clone() }];
|
|
848
|
+
setup.mock_auth(&updater2, "set_price", (&updater2, &prices2));
|
|
849
|
+
setup.client.set_price(&updater2, &prices2);
|
|
850
|
+
assert_eq!(setup.client.get_price(&2), Some(price2));
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
#[test]
|
|
854
|
+
fn test_removed_price_updater_cannot_set_price() {
|
|
855
|
+
let setup = TestSetup::new();
|
|
856
|
+
|
|
857
|
+
// Remove the price updater
|
|
858
|
+
setup.mock_owner_auth("set_price_updater", (&setup.price_updater, false));
|
|
859
|
+
setup.client.set_price_updater(&setup.price_updater, &false);
|
|
860
|
+
|
|
861
|
+
// Try to set price - should fail
|
|
862
|
+
let price = setup.default_test_price();
|
|
863
|
+
let prices = vec![&setup.env, UpdatePrice { eid: 1, price }];
|
|
864
|
+
setup.mock_price_updater_auth("set_price", (&setup.price_updater, &prices));
|
|
865
|
+
assert_eq!(
|
|
866
|
+
setup.client.try_set_price(&setup.price_updater, &prices).unwrap_err().unwrap(),
|
|
867
|
+
PriceFeedError::OnlyPriceUpdater.into()
|
|
868
|
+
);
|
|
869
|
+
}
|