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}