hyperdrive_math/short/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 shorts with a given bond amount.
9 ///
10 /// The open short curve fee, `$\Phi_{c,os}(\Delta y)$`, is paid in base and
11 /// is given by:
12 ///
13 /// ```math
14 /// \Phi_{c,os}(\Delta y) = \phi_c \cdot (1 - p) \cdot \Delta y
15 /// ```
16 pub fn open_short_curve_fee(&self, bond_amount: FixedPoint<U256>) -> Result<FixedPoint<U256>> {
17 // NOTE: Round up to overestimate the curve fee.
18 Ok(self
19 .curve_fee()
20 .mul_up(fixed!(1e18) - self.calculate_spot_price()?)
21 .mul_up(bond_amount))
22 }
23
24 /// Calculates the governance fee paid when opening shorts with a given bond
25 /// amount.
26 ///
27 /// The open short governance fee, `$\Phi_{g,os}(\Delta y)$`, is paid in
28 /// base and is given by:
29 ///
30 /// ```math
31 /// \Phi_{g,os}(\Delta y) = \phi_g \cdot \Phi_{c,os}(\Delta y)
32 /// ```
33 pub fn open_short_governance_fee(
34 &self,
35 bond_amount: FixedPoint<U256>,
36 maybe_curve_fee: Option<FixedPoint<U256>>,
37 ) -> Result<FixedPoint<U256>> {
38 let curve_fee = match maybe_curve_fee {
39 Some(maybe_curve_fee) => maybe_curve_fee,
40 None => self.open_short_curve_fee(bond_amount)?,
41 };
42 // NOTE: Round down to underestimate the governance fee.
43 Ok(curve_fee.mul_down(self.governance_lp_fee()))
44 }
45
46 /// Calculates the curve fee paid when opening shorts with a given bond
47 /// amount.
48 ///
49 /// The close short curve fee, `$\Phi_{c,cs}(\Delta y)$`, is paid in shares
50 /// and is given by:
51 ///
52 /// ```math
53 /// \Phi_{c,cs}(\Delta y) = \frac{\phi_c \cdot (1-p) \cdot \Delta y \cdot t}{c}
54 /// ```
55 ///
56 /// where $t$ is the normalized time remaining until bond maturity.
57 pub fn close_short_curve_fee(
58 &self,
59 bond_amount: FixedPoint<U256>,
60 maturity_time: U256,
61 current_time: U256,
62 ) -> Result<FixedPoint<U256>> {
63 let normalized_time_remaining =
64 self.calculate_normalized_time_remaining(maturity_time, current_time);
65 // NOTE: Round up to overestimate the curve fee.
66 Ok(self
67 .curve_fee()
68 .mul_up(fixed!(1e18) - self.calculate_spot_price()?)
69 .mul_up(bond_amount)
70 .mul_div_up(normalized_time_remaining, self.vault_share_price()))
71 }
72
73 /// Calculate the governance fee paid when closing shorts with a given bond
74 /// amount.
75 ///
76 /// The close short governance fee, `$\Phi_{g,cs}(\Delta y)$`, is paid in
77 /// shares and is given by:
78 ///
79 /// ```math
80 /// \Phi_{g,cs}(\Delta y) = \Phi_{c,cs}(\Delta y) * \phi_g
81 /// ```
82 ///
83 /// NOTE: Round down to underestimate the governance curve fee
84 pub fn close_short_governance_fee(
85 &self,
86 bond_amount: FixedPoint<U256>,
87 maturity_time: U256,
88 current_time: U256,
89 maybe_curve_fee: Option<FixedPoint<U256>>,
90 ) -> Result<FixedPoint<U256>> {
91 let curve_fee = match maybe_curve_fee {
92 Some(maybe_curve_fee) => maybe_curve_fee,
93 None => self.close_short_curve_fee(bond_amount, maturity_time, current_time)?,
94 };
95 // NOTE: Round down to underestimate the governance fee.
96 Ok(curve_fee.mul_down(self.governance_lp_fee()))
97 }
98
99 /// Calculate the flat fee paid when closing shorts with a given bond
100 /// amount.
101 ///
102 /// The close short flat fee, `$\Phi_{f,cs}(\Delta y)$`, is paid in shares
103 /// and is given by:
104 ///
105 /// ```math
106 /// \Phi_{f,cs}(\Delta y) = \frac{\Delta y \cdot (1 - t) \cdot \phi_f}{c}
107 /// ```
108 ///
109 /// where `$t$` is the normalized time remaining until bond maturity.
110 pub fn close_short_flat_fee(
111 &self,
112 bond_amount: FixedPoint<U256>,
113 maturity_time: U256,
114 current_time: U256,
115 ) -> FixedPoint<U256> {
116 let normalized_time_remaining =
117 self.calculate_normalized_time_remaining(maturity_time, current_time);
118 // NOTE: Round up to overestimate the flat fee.
119 bond_amount
120 .mul_div_up(
121 fixed!(1e18) - normalized_time_remaining,
122 self.vault_share_price(),
123 )
124 .mul_up(self.flat_fee())
125 }
126}