Skip to content

Commit 5573825

Browse files
Merge pull request #1074 from Moonwalker-rgb/fix/1027-fees-strategy-tests
test(fees): cover strategy selection and fallback
2 parents a21159b + 24ce364 commit 5573825

1 file changed

Lines changed: 132 additions & 0 deletions

File tree

contracts/fees/src/tests.rs

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,138 @@ mod fee_tests {
214214
assert_eq!(fee, 1000);
215215
}
216216

217+
// ========== Strategy selection tests (Issue #1027) ==========
218+
219+
/// Config with a wide clamp range so the strategy formula, not the
220+
/// min/max bounds, drives the result.
221+
fn strategy_config(method: FeeCalculationMethod, base_fee: u128) -> FeeConfig {
222+
FeeConfig {
223+
base_fee,
224+
min_fee: 0,
225+
max_fee: u128::MAX,
226+
congestion_sensitivity: 100,
227+
demand_factor_bp: BasisPoints::new(0),
228+
calculation_method: method,
229+
last_updated: 0,
230+
}
231+
}
232+
233+
fn strategy_context(congestion_index: u32, operation: FeeOperation) -> FeeContext {
234+
FeeContext {
235+
congestion_index,
236+
demand_factor_bp: BasisPoints::new(0),
237+
operation,
238+
}
239+
}
240+
241+
/// Fixed strategy ignores congestion and demand entirely.
242+
#[ink::test]
243+
fn test_fee_calculator_selects_fixed_strategy() {
244+
let config = strategy_config(FeeCalculationMethod::Fixed, 2_000);
245+
let fee = FeeCalculator::calculate(
246+
&config,
247+
&strategy_context(100, FeeOperation::RegisterProperty),
248+
);
249+
assert_eq!(fee, 2_000);
250+
}
251+
252+
/// Dynamic strategy scales with congestion: at 0 congestion it returns
253+
/// the base fee, at full congestion it adds the congestion premium.
254+
#[ink::test]
255+
fn test_fee_calculator_selects_dynamic_strategy() {
256+
let config = strategy_config(FeeCalculationMethod::Dynamic, 1_000);
257+
258+
// At rest: multiplier is exactly 10_000 bp → base fee.
259+
let at_rest = FeeCalculator::calculate(
260+
&config,
261+
&strategy_context(0, FeeOperation::RegisterProperty),
262+
);
263+
assert_eq!(at_rest, 1_000);
264+
265+
// Full congestion with sensitivity 100 adds
266+
// 100 * 100 * (300 - 100) / 10_000 = 200 bp.
267+
let congested = FeeCalculator::calculate(
268+
&config,
269+
&strategy_context(100, FeeOperation::RegisterProperty),
270+
);
271+
assert_eq!(congested, 1_020);
272+
}
273+
274+
/// Tiered strategy selects the multiplier from the operation type.
275+
#[ink::test]
276+
fn test_fee_calculator_selects_tiered_strategy() {
277+
let config = strategy_config(FeeCalculationMethod::Tiered, 1_000);
278+
279+
assert_eq!(
280+
FeeCalculator::calculate(&config, &strategy_context(0, FeeOperation::RegisterProperty)),
281+
2_000
282+
);
283+
assert_eq!(
284+
FeeCalculator::calculate(&config, &strategy_context(0, FeeOperation::TransferProperty)),
285+
1_500
286+
);
287+
assert_eq!(
288+
FeeCalculator::calculate(&config, &strategy_context(0, FeeOperation::CreateEscrow)),
289+
1_200
290+
);
291+
assert_eq!(
292+
FeeCalculator::calculate(
293+
&config,
294+
&strategy_context(0, FeeOperation::PremiumListingBid)
295+
),
296+
2_500
297+
);
298+
// Operations without a dedicated tier fall back to the 1x tier.
299+
assert_eq!(
300+
FeeCalculator::calculate(&config, &strategy_context(0, FeeOperation::OracleUpdate)),
301+
1_000
302+
);
303+
}
304+
305+
/// Exponential strategy squares the congestion factor.
306+
#[ink::test]
307+
fn test_fee_calculator_selects_exponential_strategy() {
308+
let config = strategy_config(FeeCalculationMethod::Exponential, 1_000);
309+
310+
// No congestion → base fee.
311+
let at_rest = FeeCalculator::calculate(
312+
&config,
313+
&strategy_context(0, FeeOperation::RegisterProperty),
314+
);
315+
assert_eq!(at_rest, 1_000);
316+
317+
// At congestion 10: factor = 10 * 10 * 100 / 100 = 100 bp.
318+
let low = FeeCalculator::calculate(
319+
&config,
320+
&strategy_context(10, FeeOperation::RegisterProperty),
321+
);
322+
assert_eq!(low, 1_010);
323+
324+
// Squaring makes congestion 100 ten times the 10-unit factor:
325+
// 100 * 100 * 100 / 100 = 10_000 bp → 2x base.
326+
let high = FeeCalculator::calculate(
327+
&config,
328+
&strategy_context(100, FeeOperation::RegisterProperty),
329+
);
330+
assert_eq!(high, 2_000);
331+
}
332+
333+
/// Operations without a dedicated config fall back to the default config,
334+
/// so strategy selection uses the default calculation method.
335+
#[ink::test]
336+
fn test_get_config_falls_back_to_default_strategy() {
337+
let contract = FeeManager::new(1000, 100, 100_000);
338+
339+
let default = contract.default_config();
340+
assert_eq!(default.calculation_method, FeeCalculationMethod::Dynamic);
341+
342+
// No operation-specific config has been set: the fallback must be the
343+
// default config, and the fee must come from the default strategy.
344+
assert_eq!(contract.get_config(FeeOperation::TransferProperty), default);
345+
let fee = contract.calculate_fee(FeeOperation::TransferProperty);
346+
assert_eq!(fee, FeeCalculator::calculate(&default, &strategy_context(0, FeeOperation::TransferProperty)));
347+
}
348+
217349

218350
// ========== Dynamic fee model tests (Issue #508) ==========
219351

0 commit comments

Comments
 (0)