Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add get_targeted_long #882

Merged
merged 12 commits into from
Apr 5, 2024
1 change: 1 addition & 0 deletions crates/hyperdrive-math/src/long.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ mod close;
mod fees;
mod max;
mod open;
mod targeted;
15 changes: 9 additions & 6 deletions crates/hyperdrive-math/src/long/max.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ impl State {
self.max_long_guess(absolute_max_base_amount, checkpoint_exposure);
let mut maybe_solvency = self.solvency_after_long(
max_base_amount,
self.calculate_open_long(max_base_amount),
self.calculate_open_long(max_base_amount).unwrap(),
checkpoint_exposure,
);
if maybe_solvency.is_none() {
Expand Down Expand Up @@ -121,7 +121,7 @@ impl State {
let possible_max_base_amount = max_base_amount + solvency / maybe_derivative.unwrap();
maybe_solvency = self.solvency_after_long(
possible_max_base_amount,
self.calculate_open_long(possible_max_base_amount),
self.calculate_open_long(possible_max_base_amount).unwrap(),
checkpoint_exposure,
);
if let Some(s) = maybe_solvency {
Expand Down Expand Up @@ -340,7 +340,7 @@ impl State {
/// It's possible that the pool is insolvent after opening a long. In this
/// case, we return `None` since the fixed point library can't represent
/// negative numbers.
fn solvency_after_long(
pub(super) fn solvency_after_long(
&self,
base_amount: FixedPoint,
bond_amount: FixedPoint,
Expand Down Expand Up @@ -380,7 +380,10 @@ impl State {
/// This derivative is negative since solvency decreases as more longs are
/// opened. We use the negation of the derivative to stay in the positive
/// domain, which allows us to use the fixed point library.
fn solvency_after_long_derivative(&self, base_amount: FixedPoint) -> Option<FixedPoint> {
pub(super) fn solvency_after_long_derivative(
&self,
base_amount: FixedPoint,
) -> Option<FixedPoint> {
let maybe_derivative = self.long_amount_derivative(base_amount);
maybe_derivative.map(|derivative| {
(derivative
Expand Down Expand Up @@ -419,7 +422,7 @@ impl State {
/// $$
/// c'(x) = \phi_{c} \cdot \left( \tfrac{1}{p} - 1 \right)
/// $$
fn long_amount_derivative(&self, base_amount: FixedPoint) -> Option<FixedPoint> {
pub(super) fn long_amount_derivative(&self, base_amount: FixedPoint) -> Option<FixedPoint> {
let share_amount = base_amount / self.vault_share_price();
let inner =
self.initial_vault_share_price() * (self.effective_share_reserves() + share_amount);
Expand Down Expand Up @@ -624,7 +627,7 @@ mod tests {
let spot_price_after_long = bob
.get_state()
.await?
.calculate_spot_price_after_long(max_long, None);
.calculate_spot_price_after_long(max_long, None)?;
bob.open_long(max_long, None, None).await?;

// One of three things should be true after opening the long:
Expand Down
31 changes: 16 additions & 15 deletions crates/hyperdrive-math/src/long/open.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use eyre::{eyre, Result};
use fixed_point::FixedPoint;

use crate::{calculate_rate_given_fixed_price, State, YieldSpace};
Expand All @@ -22,7 +23,7 @@ impl State {
/// \right) \right)^{1 - t_s}
/// \right)^{\tfrac{1}{1 - t_s}}
/// $$
pub fn calculate_open_long<F: Into<FixedPoint>>(&self, base_amount: F) -> FixedPoint {
pub fn calculate_open_long<F: Into<FixedPoint>>(&self, base_amount: F) -> Result<FixedPoint> {
let base_amount = base_amount.into();

if base_amount < self.config.minimum_transaction_amount.into() {
Expand All @@ -35,14 +36,15 @@ impl State {

// Throw an error if opening the long would result in negative interest.
let ending_spot_price =
self.calculate_spot_price_after_long(base_amount, long_amount.into());
self.calculate_spot_price_after_long(base_amount, long_amount.into())?;
let max_spot_price = self.calculate_max_spot_price();
if ending_spot_price > max_spot_price {
// TODO would be nice to return a `Result` here instead of a panic.
panic!("InsufficientLiquidity: Negative Interest");
return Err(eyre!(
"calculate_open_long: InsufficientLiquidity: Negative Interest",
));
dpaiton marked this conversation as resolved.
Show resolved Hide resolved
}

long_amount - self.open_long_curve_fees(base_amount)
Ok(long_amount - self.open_long_curve_fees(base_amount))
}

/// Calculates the spot price after opening a Hyperdrive long.
Expand All @@ -51,17 +53,17 @@ impl State {
&self,
base_amount: FixedPoint,
bond_amount: Option<FixedPoint>,
) -> FixedPoint {
) -> Result<FixedPoint> {
let bond_amount = match bond_amount {
Some(bond_amount) => bond_amount,
None => self.calculate_open_long(base_amount),
None => self.calculate_open_long(base_amount)?,
};
let mut state: State = self.clone();
state.info.bond_reserves -= bond_amount.into();
state.info.share_reserves += (base_amount / state.vault_share_price()
- self.open_long_governance_fee(base_amount) / state.vault_share_price())
.into();
state.calculate_spot_price()
Ok(state.calculate_spot_price())
}

/// Calculate the spot rate after a long has been opened.
Expand All @@ -70,17 +72,16 @@ impl State {
&self,
base_amount: FixedPoint,
bond_amount: Option<FixedPoint>,
) -> FixedPoint {
calculate_rate_given_fixed_price(
self.calculate_spot_price_after_long(base_amount, bond_amount),
) -> Result<FixedPoint> {
Ok(calculate_rate_given_fixed_price(
self.calculate_spot_price_after_long(base_amount, bond_amount)?,
self.position_duration(),
)
))
}
}

#[cfg(test)]
mod tests {
use eyre::Result;
use fixed_point_macros::fixed;
use rand::{thread_rng, Rng};
use test_utils::{
Expand Down Expand Up @@ -124,7 +125,7 @@ mod tests {
let expected_spot_price = bob
.get_state()
.await?
.calculate_spot_price_after_long(base_paid, None);
.calculate_spot_price_after_long(base_paid, None)?;

// Open the long.
bob.open_long(base_paid, None, None).await?;
Expand Down Expand Up @@ -188,7 +189,7 @@ mod tests {
let expected_spot_rate = bob
.get_state()
.await?
.calculate_spot_rate_after_long(base_paid, None);
.calculate_spot_rate_after_long(base_paid, None)?;

// Open the long.
bob.open_long(base_paid, None, None).await?;
Expand Down
Loading
Loading