balancer_maths_rust/hooks/directional_fee/
mod.rs1use crate::common::maths::div_down_fixed;
2use crate::common::types::HookStateBase;
3use crate::hooks::types::{DynamicSwapFeeResult, HookState};
4use crate::hooks::{DefaultHook, HookBase, HookConfig};
5use num_bigint::BigInt;
6use num_traits::Zero;
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10pub struct DirectionalFeeHookState {
11 pub hook_type: String,
12}
13
14impl Default for DirectionalFeeHookState {
15 fn default() -> Self {
16 Self {
17 hook_type: "DirectionalFee".to_string(),
18 }
19 }
20}
21
22impl HookStateBase for DirectionalFeeHookState {
23 fn hook_type(&self) -> &str {
24 &self.hook_type
25 }
26}
27
28pub struct DirectionalFeeHook {
29 config: HookConfig,
30}
31
32impl DirectionalFeeHook {
33 pub fn new() -> Self {
34 let config = HookConfig {
35 should_call_compute_dynamic_swap_fee: true,
36 ..Default::default()
37 };
38 Self { config }
39 }
40}
41
42impl HookBase for DirectionalFeeHook {
43 fn hook_type(&self) -> &str {
44 "DirectionalFee"
45 }
46 fn config(&self) -> &HookConfig {
47 &self.config
48 }
49
50 fn on_compute_dynamic_swap_fee(
51 &self,
52 swap_params: &crate::common::types::SwapParams,
53 static_swap_fee_percentage: &BigInt,
54 _hook_state: &HookState,
55 ) -> DynamicSwapFeeResult {
56 let balance_in = &swap_params.balances_live_scaled_18[swap_params.token_in_index];
57 let balance_out = &swap_params.balances_live_scaled_18[swap_params.token_out_index];
58 let amount = &swap_params.amount_scaled_18;
59
60 let final_balance_in = balance_in + amount;
62 let final_balance_out = balance_out - amount;
63
64 let calculated = if final_balance_in > final_balance_out {
65 let diff = &final_balance_in - &final_balance_out;
66 let total = final_balance_in + final_balance_out;
67 match div_down_fixed(&diff, &total) {
68 Ok(v) => v,
69 Err(_) => BigInt::zero(),
70 }
71 } else {
72 BigInt::zero()
73 };
74
75 let dynamic_swap_fee = if calculated > *static_swap_fee_percentage {
76 calculated
77 } else {
78 static_swap_fee_percentage.clone()
79 };
80
81 DynamicSwapFeeResult {
82 success: true,
83 dynamic_swap_fee,
84 }
85 }
86
87 fn on_before_add_liquidity(
89 &self,
90 kind: crate::common::types::AddLiquidityKind,
91 max_amounts_in_scaled_18: &[BigInt],
92 min_bpt_amount_out: &BigInt,
93 balances_scaled_18: &[BigInt],
94 hook_state: &HookState,
95 ) -> crate::hooks::types::BeforeAddLiquidityResult {
96 DefaultHook::new().on_before_add_liquidity(
97 kind,
98 max_amounts_in_scaled_18,
99 min_bpt_amount_out,
100 balances_scaled_18,
101 hook_state,
102 )
103 }
104 fn on_after_add_liquidity(
105 &self,
106 kind: crate::common::types::AddLiquidityKind,
107 amounts_in_scaled_18: &[BigInt],
108 amounts_in_raw: &[BigInt],
109 bpt_amount_out: &BigInt,
110 balances_scaled_18: &[BigInt],
111 hook_state: &HookState,
112 ) -> crate::hooks::types::AfterAddLiquidityResult {
113 DefaultHook::new().on_after_add_liquidity(
114 kind,
115 amounts_in_scaled_18,
116 amounts_in_raw,
117 bpt_amount_out,
118 balances_scaled_18,
119 hook_state,
120 )
121 }
122 fn on_before_remove_liquidity(
123 &self,
124 kind: crate::common::types::RemoveLiquidityKind,
125 max_bpt_amount_in: &BigInt,
126 min_amounts_out_scaled_18: &[BigInt],
127 balances_scaled_18: &[BigInt],
128 hook_state: &HookState,
129 ) -> crate::hooks::types::BeforeRemoveLiquidityResult {
130 DefaultHook::new().on_before_remove_liquidity(
131 kind,
132 max_bpt_amount_in,
133 min_amounts_out_scaled_18,
134 balances_scaled_18,
135 hook_state,
136 )
137 }
138 fn on_after_remove_liquidity(
139 &self,
140 kind: crate::common::types::RemoveLiquidityKind,
141 bpt_amount_in: &BigInt,
142 amounts_out_scaled_18: &[BigInt],
143 amounts_out_raw: &[BigInt],
144 balances_scaled_18: &[BigInt],
145 hook_state: &HookState,
146 ) -> crate::hooks::types::AfterRemoveLiquidityResult {
147 DefaultHook::new().on_after_remove_liquidity(
148 kind,
149 bpt_amount_in,
150 amounts_out_scaled_18,
151 amounts_out_raw,
152 balances_scaled_18,
153 hook_state,
154 )
155 }
156 fn on_before_swap(
157 &self,
158 swap_params: &crate::common::types::SwapParams,
159 hook_state: &HookState,
160 ) -> crate::hooks::types::BeforeSwapResult {
161 DefaultHook::new().on_before_swap(swap_params, hook_state)
162 }
163 fn on_after_swap(
164 &self,
165 after_swap_params: &crate::hooks::types::AfterSwapParams,
166 hook_state: &HookState,
167 ) -> crate::hooks::types::AfterSwapResult {
168 DefaultHook::new().on_after_swap(after_swap_params, hook_state)
169 }
170}
171
172impl Default for DirectionalFeeHook {
173 fn default() -> Self {
174 Self::new()
175 }
176}