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