hyperdrive_math/long/fees.rs
1use ethers::types::U256;
2use eyre::Result;
3use fixedpointmath::{fixed, FixedPoint};
4
5use crate::State;
6
7impl State {
8 /// Calculates the curve fee paid when opening longs with a given base amount.
9 ///
10 /// The open long curve fee, `$\Phi_{c,ol}(\Delta x)$`, is paid in bonds and
11 /// is given by:
12 ///
13 /// ```math
14 /// \Phi_{c,ol}(\Delta x) = \phi_c
15 /// \cdot \left( \tfrac{1}{p} - 1 \right) \cdot \Delta x
16 /// ```
17 pub fn open_long_curve_fee(&self, base_amount: FixedPoint<U256>) -> Result<FixedPoint<U256>> {
18 // NOTE: Round up to overestimate the curve fee.
19 Ok(self
20 .curve_fee()
21 .mul_up(fixed!(1e18).div_up(self.calculate_spot_price()?) - fixed!(1e18))
22 .mul_up(base_amount))
23 }
24
25 /// Calculates the governance fee paid when opening longs with a given base
26 /// amount.
27 ///
28 /// The open long governance fee, `$\Phi_{g,ol}(\Delta x)$`, is paid in base
29 /// and is given by:
30 ///
31 /// ```math
32 /// \Phi_{g,ol}(\Delta x) = \phi_g \cdot p \cdot \Phi_{c,ol}(\Delta x)
33 /// ```
34 pub fn open_long_governance_fee(
35 &self,
36 base_amount: FixedPoint<U256>,
37 maybe_curve_fee: Option<FixedPoint<U256>>,
38 ) -> Result<FixedPoint<U256>> {
39 let curve_fee = match maybe_curve_fee {
40 Some(maybe_curve_fee) => maybe_curve_fee,
41 None => self.open_long_curve_fee(base_amount)?,
42 };
43 // NOTE: Round down to underestimate the governance curve fee.
44 Ok(curve_fee
45 .mul_down(self.governance_lp_fee())
46 .mul_down(self.calculate_spot_price()?))
47 }
48
49 /// Calculates the curve fee paid when closing longs for a given bond
50 /// amount.
51 ///
52 /// The the close long curve fee, `$\Phi_{c,cl}(\Delta y)$`, is paid in
53 /// shares and is given by:
54 ///
55 /// ```math
56 /// \Phi_{c,cl}(\Delta y) =
57 /// \frac{\phi_c \cdot (1 - p) \cdot \Delta y \cdot t}{c}
58 /// ```
59 ///
60 /// where `$t$` is the normalized time remaining until bond maturity.
61 pub fn close_long_curve_fee(
62 &self,
63 bond_amount: FixedPoint<U256>,
64 maturity_time: U256,
65 current_time: U256,
66 ) -> Result<FixedPoint<U256>> {
67 let normalized_time_remaining =
68 self.calculate_normalized_time_remaining(maturity_time, current_time);
69 // NOTE: Round up to overestimate the curve fee.
70 Ok(self
71 .curve_fee()
72 .mul_up(fixed!(1e18) - self.calculate_spot_price()?)
73 .mul_up(bond_amount)
74 .mul_div_up(normalized_time_remaining, self.vault_share_price()))
75 }
76
77 /// Calculates the flat fee paid when closing longs for a given bond amount.
78 ///
79 /// The close long flat fee, `$\Phi_{f,cl}(\Delta y)$`, is paid in shares
80 /// and is given by:
81 ///
82 /// ```math
83 /// \Phi_{f,cl}(\Delta y) = \frac{\Delta y \cdot (1 - t) \cdot \phi_f)}{c}
84 /// ```
85 ///
86 /// where `$t$` is the normalized time remaining until bond maturity.
87 pub fn close_long_flat_fee(
88 &self,
89 bond_amount: FixedPoint<U256>,
90 maturity_time: U256,
91 current_time: U256,
92 ) -> FixedPoint<U256> {
93 let normalized_time_remaining =
94 self.calculate_normalized_time_remaining(maturity_time, current_time);
95 // NOTE: Round up to overestimate the flat fee.
96 bond_amount
97 .mul_div_up(
98 fixed!(1e18) - normalized_time_remaining,
99 self.vault_share_price(),
100 )
101 .mul_up(self.flat_fee())
102 }
103}