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

max short cleanup #193

Draft
wants to merge 38 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
cb26810
add retries to txns to account for anvil failure
dpaiton Dec 3, 2024
6e314ad
add test tolerance
dpaiton Dec 3, 2024
ee0901d
bump up tolerance
dpaiton Dec 3, 2024
0c8ed69
increase tolerance
dpaiton Dec 3, 2024
4452746
fix typo
dpaiton Dec 3, 2024
11a6ce7
add retry loop
dpaiton Dec 3, 2024
542afc2
fix import
dpaiton Dec 3, 2024
2ff99c3
clone logs before filtering
dpaiton Dec 3, 2024
4d8c79e
bump hyperdrive to 1.0.20
dpaiton Nov 26, 2024
49e9fbb
ignore build.rs
dpaiton Nov 27, 2024
51df4eb
add adminController argument to deploy fn
dpaiton Nov 27, 2024
43ff243
add instructions for debugging
dpaiton Dec 2, 2024
fd89887
fix test
dpaiton Dec 2, 2024
208cb2e
fix registry to deploy & initialize
dpaiton Dec 2, 2024
f3e75a5
code cleanup
dpaiton Dec 2, 2024
804b1b4
deploy factory in test deploy
dpaiton Dec 2, 2024
b71ee2f
update factory config to match Hyperdrive factory.ts deployer defaults
dpaiton Dec 2, 2024
21e504c
add test tolerance
dpaiton Dec 2, 2024
1e98853
clean up comments for consistency
dpaiton Oct 2, 2024
28b4d7b
add a failing test
dpaiton Nov 24, 2024
ce396b4
update docstring
dpaiton Nov 24, 2024
44fcbf0
rename fn
dpaiton Nov 24, 2024
1e4d839
calc_spot_price_up
dpaiton Nov 24, 2024
cd9394e
move calculate to own fn
dpaiton Nov 24, 2024
c6edcf3
solvency_after_short cleanup & comments on checks.
dpaiton Nov 24, 2024
338eb4c
more iterations so the test passes
dpaiton Nov 24, 2024
b6a9857
adds docs to explain final share reserves
dpaiton Nov 24, 2024
c852acf
move min share calc to own fn
dpaiton Nov 24, 2024
0272fd7
rework the abs max short guess fn
dpaiton Nov 24, 2024
6053dad
put this back
dpaiton Nov 25, 2024
b148198
remove test
dpaiton Nov 25, 2024
12f2a29
lint fixes; update hyperdrivetypes
dpaiton Nov 25, 2024
cf542a2
add failing test
dpaiton Dec 4, 2024
d238ae6
remove spot price argument
dpaiton Dec 4, 2024
f2d377b
skips 51% of tests
dpaiton Dec 4, 2024
194071a
fix test
dpaiton Dec 4, 2024
d563ede
abs max short
dpaiton Nov 24, 2024
2751b01
parity test will not pass until we update solidity
dpaiton Dec 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ test/Generated.t.sol
# Rust
target/
crates/hyperdrive-wrappers/debug/
crates/hyperdrive-wrappers/build.rs
.rustc_info.json

# Crash Reports
Expand Down
5 changes: 4 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,7 @@ For code owners who wish to publish a release, make sure to follow these guideli
2. From the updated `main` branch, make a new tag with `git tag vX.Y.Z`.
3. Push that tag to the remote repository with `git push --tags`.
4. Go to the `releases` tab in Github and add the new tag as a release.
5. Click the "Generate Release Notes" button to generate release notes.
5. Click the "Generate Release Notes" button to generate release notes.

## Debugging
To point tests to a local Anvil instance, use the environment variable `HYPERDRIVE_ETHEREUM_URL`.
12 changes: 6 additions & 6 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ members = [

[workspace.package]
name = "hyperdrive-rs"
version = "0.18.1"
version = "0.20.0"
authors = [
"Alex Towle <alex@delv.tech>",
"Dylan Paiton <dylan@delv.tech>",
Expand All @@ -29,9 +29,9 @@ repository = "https://github.com/delvtech/hyperdrive-rs"
description = "API for simulating Hyperdrive smart contract transactions."

[workspace.dependencies]
fixedpointmath = { version = "0.18.1", path="crates/fixedpointmath" }
hyperdrive-wrappers = { version = "0.18.1", path="crates/hyperdrive-wrappers" }
hyperdrive-math = { version = "0.18.1", path="crates/hyperdrive-math" }
fixedpointmath = { version = "0.20.0", path="crates/fixedpointmath" }
hyperdrive-wrappers = { version = "0.20.0", path="crates/hyperdrive-wrappers" }
hyperdrive-math = { version = "0.20.0", path="crates/hyperdrive-math" }

[workspace.lints.clippy]
comparison_chain = "allow"
Expand Down
2 changes: 1 addition & 1 deletion bindings/hyperdrivepy/src/hyperdrive_state_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl HyperdriveState {
}

pub fn calculate_spot_price(&self) -> PyResult<String> {
let result_fp = self.state.calculate_spot_price().map_err(|err| {
let result_fp = self.state.calculate_spot_price_down().map_err(|err| {
PyErr::new::<PyValueError, _>(format!("calculate_spot_price: {}", err))
})?;
let result = U256::from(result_fp).to_string();
Expand Down
2 changes: 1 addition & 1 deletion bindings/hyperdrivepy/tests/wrapper_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import hyperdrivepy
import pytest
from hyperdrivetypes.types.IHyperdriveTypes import Fees, PoolConfig, PoolInfo
from hyperdrivetypes.types.IHyperdrive import Fees, PoolConfig, PoolInfo

POOL_CONFIG = PoolConfig(
baseToken="0x1234567890abcdef1234567890abcdef12345678",
Expand Down
19 changes: 12 additions & 7 deletions crates/hyperdrive-math/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,15 +126,20 @@ impl State {
Self { config, info }
}

/// Calculates the pool's spot price.
pub fn calculate_spot_price(&self) -> Result<FixedPoint<U256>> {
YieldSpace::calculate_spot_price(self)
/// Calculates the pool's spot price, rounding down.
pub fn calculate_spot_price_down(&self) -> Result<FixedPoint<U256>> {
YieldSpace::calculate_spot_price_down(self)
}

/// Calculates the pool's spot price, rounding up.
pub fn calculate_spot_price_up(&self) -> Result<FixedPoint<U256>> {
YieldSpace::calculate_spot_price_up(self)
}

/// Calculate the pool's current spot (aka "fixed") rate.
pub fn calculate_spot_rate(&self) -> Result<FixedPoint<U256>> {
Ok(calculate_rate_given_fixed_price(
self.calculate_spot_price()?,
self.calculate_spot_price_down()?,
self.position_duration(),
))
}
Expand Down Expand Up @@ -364,8 +369,8 @@ mod tests {
state.info.shorts_outstanding = uint256!(0);
state.info.short_average_maturity_time = uint256!(0);
// Make sure we're still solvent
if state.calculate_spot_price()? < state.calculate_min_spot_price()?
|| state.calculate_spot_price()? > fixed!(1e18)
if state.calculate_spot_price_down()? < state.calculate_min_spot_price()?
|| state.calculate_spot_price_down()? > fixed!(1e18)
|| state.calculate_solvency().is_err()
{
continue;
Expand Down Expand Up @@ -403,7 +408,7 @@ mod tests {
new_state.info.share_reserves = target_share_reserves.into();
new_state.info.bond_reserves = target_bond_reserves.into();
if new_state.calculate_solvency().is_err()
|| new_state.calculate_spot_price()? > fixed!(1e18)
|| new_state.calculate_spot_price_down()? > fixed!(1e18)
{
continue;
}
Expand Down
4 changes: 2 additions & 2 deletions crates/hyperdrive-math/src/long/close.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl State {
) -> Result<FixedPoint<U256>> {
let bond_amount = bond_amount.into();

let spot_price = self.calculate_spot_price()?;
let spot_price = self.calculate_spot_price_down()?;
if spot_price > fixed!(1e18) {
return Err(eyre!("Negative fixed interest!"));
}
Expand Down Expand Up @@ -231,7 +231,7 @@ mod tests {
// Ensure curve_fee is smaller than spot_price to avoid overflows
// on the hyperdrive valuation, as that'd mean having to pay a larger
// amount of fees than the current value of the long.
let spot_price = state.calculate_spot_price()?;
let spot_price = state.calculate_spot_price_down()?;
if state.curve_fee() * (fixed!(1e18) - spot_price) > spot_price {
continue;
}
Expand Down
6 changes: 3 additions & 3 deletions crates/hyperdrive-math/src/long/fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ impl State {
// NOTE: Round up to overestimate the curve fee.
Ok(self
.curve_fee()
.mul_up(fixed!(1e18).div_up(self.calculate_spot_price()?) - fixed!(1e18))
.mul_up(fixed!(1e18).div_up(self.calculate_spot_price_down()?) - fixed!(1e18))
.mul_up(base_amount))
}

Expand All @@ -43,7 +43,7 @@ impl State {
// NOTE: Round down to underestimate the governance curve fee.
Ok(curve_fee
.mul_down(self.governance_lp_fee())
.mul_down(self.calculate_spot_price()?))
.mul_down(self.calculate_spot_price_down()?))
}

/// Calculates the curve fee paid when closing longs for a given bond
Expand All @@ -69,7 +69,7 @@ impl State {
// NOTE: Round up to overestimate the curve fee.
Ok(self
.curve_fee()
.mul_up(fixed!(1e18) - self.calculate_spot_price()?)
.mul_up(fixed!(1e18) - self.calculate_spot_price_down()?)
.mul_up(bond_amount)
.mul_div_up(normalized_time_remaining, self.vault_share_price()))
}
Expand Down
13 changes: 7 additions & 6 deletions crates/hyperdrive-math/src/long/max.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl State {
/ (fixed!(1e18)
+ self
.curve_fee()
.mul_up(fixed!(1e18).div_up(self.calculate_spot_price()?) - fixed!(1e18)))
.mul_up(fixed!(1e18).div_up(self.calculate_spot_price_down()?) - fixed!(1e18)))
.mul_up(fixed!(1e18) - self.flat_fee()))
}

Expand Down Expand Up @@ -208,7 +208,8 @@ impl State {
+ self
.curve_fee()
.mul_up(
fixed!(1e18).div_up(self.calculate_spot_price()?) - fixed!(1e18),
fixed!(1e18).div_up(self.calculate_spot_price_down()?)
- fixed!(1e18),
)
.mul_up(fixed!(1e18) - self.flat_fee()))
.div_up(fixed!(1e18) - self.flat_fee()))
Expand All @@ -226,7 +227,7 @@ impl State {
//
// y_t = inner * ((1 + curveFee * (1 / p_0 - 1) * (1 - flatFee)) / (1 - flatFee)) ** (1 / t_s)
let fee_adjustment = self.curve_fee()
* (fixed!(1e18) / self.calculate_spot_price()? - fixed!(1e18))
* (fixed!(1e18) / self.calculate_spot_price_down()? - fixed!(1e18))
* (fixed!(1e18) - self.flat_fee());
let target_bond_reserves = ((fixed!(1e18) + fee_adjustment)
/ (fixed!(1e18) - self.flat_fee()))
Expand Down Expand Up @@ -265,7 +266,7 @@ impl State {
) -> Result<FixedPoint<U256>> {
// Calculate an initial estimate of the max long by using the spot price as
// our conservative price.
let spot_price = self.calculate_spot_price()?;
let spot_price = self.calculate_spot_price_down()?;
let guess = self.max_long_estimate(spot_price, spot_price, checkpoint_exposure)?;

// We know that the spot price is 1 when the absolute max base amount is
Expand Down Expand Up @@ -426,7 +427,7 @@ impl State {
base_amount: FixedPoint<U256>,
) -> Result<FixedPoint<U256>> {
let derivative = self.calculate_open_long_derivative(base_amount)?;
let spot_price = self.calculate_spot_price()?;
let spot_price = self.calculate_spot_price_down()?;
Ok(
(derivative
+ self.governance_lp_fee() * self.curve_fee() * (fixed!(1e18) - spot_price)
Expand Down Expand Up @@ -485,7 +486,7 @@ mod tests {
state.info.share_adjustment,
)?
.into(),
state.calculate_spot_price()?.into(),
state.calculate_spot_price_down()?.into(),
)
.call()
.await
Expand Down
6 changes: 3 additions & 3 deletions crates/hyperdrive-math/src/long/open.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl State {

// Finish computing the derivative.
derivative -=
self.curve_fee() * ((fixed!(1e18) / self.calculate_spot_price()?) - fixed!(1e18));
self.curve_fee() * ((fixed!(1e18) / self.calculate_spot_price_down()?) - fixed!(1e18));

Ok(derivative)
}
Expand Down Expand Up @@ -155,7 +155,7 @@ impl State {
) -> Result<FixedPoint<U256>> {
let state =
self.calculate_pool_state_after_open_long(base_amount, maybe_bond_pool_delta)?;
state.calculate_spot_price()
state.calculate_spot_price_down()
}

/// Calculate the spot rate after a long has been opened.
Expand Down Expand Up @@ -336,7 +336,7 @@ mod tests {
// Verify that the predicted spot price is equal to the ending spot
// price. These won't be exactly equal because the vault share price
// increases between the prediction and opening the long.
let actual_spot_price = bob.get_state().await?.calculate_spot_price()?;
let actual_spot_price = bob.get_state().await?.calculate_spot_price_down()?;
let delta = if actual_spot_price > expected_spot_price {
actual_spot_price - expected_spot_price
} else {
Expand Down
6 changes: 3 additions & 3 deletions crates/hyperdrive-math/src/long/targeted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ impl State {
// g'(x) = \phi_g \phi_c (1 - p_0)
let gov_fee_derivative = self.governance_lp_fee()
* self.curve_fee()
* (fixed!(1e18) - self.calculate_spot_price()?);
* (fixed!(1e18) - self.calculate_spot_price_down()?);

// a(x) = mu * (z_{e,0} + 1/c (x - g(x))
let inner_numerator = self.mu()
Expand Down Expand Up @@ -401,7 +401,7 @@ impl State {
}
let share_delta = ending_share_reserves - self.share_reserves();
let fees = fixed!(1e18)
- (fixed!(1e18) - self.calculate_spot_price()?)
- (fixed!(1e18) - self.calculate_spot_price_down()?)
* self.curve_fee()
* self.governance_lp_fee();
let base_delta = self.vault_share_price().mul_div_down(share_delta, fees);
Expand Down Expand Up @@ -620,7 +620,7 @@ mod tests {

// Check that our resulting price is under the max
let current_state = alice.get_state().await?;
let spot_price_after_long = current_state.calculate_spot_price()?;
let spot_price_after_long = current_state.calculate_spot_price_down()?;
assert!(
max_spot_price_before_long > spot_price_after_long,
"Resulting price is greater than the max."
Expand Down
18 changes: 16 additions & 2 deletions crates/hyperdrive-math/src/lp/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ mod tests {
use crate::test_utils::agent::HyperdriveMathAgent;

#[tokio::test]
async fn fuzz_test_calculate_remove_liquidity() -> Result<()> {
async fn fuzz_sol_calculate_remove_liquidity() -> Result<()> {
let test_tolerance = fixed!(1e9);
// Spawn a test chain and create two agents -- Alice and Bob.
let mut rng = thread_rng();
let chain = TestChain::new().await?;
Expand Down Expand Up @@ -352,7 +353,20 @@ mod tests {
Ok((rust_amount, rust_withdrawal_shares, rust_final_state)) => {
let (sol_amount, sol_withdrawal_shares) = tx_result?;
// Assert amounts redeemed match between rust and solidity.
assert!(rust_amount == sol_amount.into());
let sol_amount = FixedPoint::from(sol_amount);
let error = if rust_amount > sol_amount {
rust_amount - sol_amount
} else {
sol_amount - rust_amount
};
assert!(
error <= test_tolerance,
"abs(rust_amount={:#?} - sol_amount={:#?})={:#?} <= {:#?}",
rust_amount,
sol_amount,
error,
test_tolerance
);

// Assert withdrawal shares results match between rust and
// solidity
Expand Down
10 changes: 5 additions & 5 deletions crates/hyperdrive-math/src/short/close.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ impl State {
Ok(fixed!(1e18)
- self
.curve_fee()
.mul_up(fixed!(1e18) - self.calculate_spot_price()?))
.mul_up(fixed!(1e18) - self.calculate_spot_price_down()?))
}

/// Calculates the amount of shares the trader will receive after fees for closing a short
Expand Down Expand Up @@ -224,7 +224,7 @@ impl State {
let mut state: State = self.clone();
state.info.bond_reserves -= bond_reserves_delta.into();
state.info.share_reserves += share_curve_delta.into();
state.calculate_spot_price()?
state.calculate_spot_price_down()?
};
let max_spot_price = self.calculate_close_short_max_spot_price()?;
if short_curve_spot_price > max_spot_price {
Expand All @@ -244,7 +244,7 @@ impl State {
let mut state: State = self.clone();
state.info.bond_reserves -= bond_reserves_delta.into();
state.info.share_reserves += share_curve_delta_with_fees.into();
state.calculate_spot_price()?
state.calculate_spot_price_down()?
};
if share_curve_delta_with_fees_spot_price > fixed!(1e18) {
return Err(eyre!("InsufficientLiquidity: Negative Interest"));
Expand Down Expand Up @@ -293,7 +293,7 @@ impl State {
let open_vault_share_price = open_vault_share_price.into();
let close_vault_share_price = close_vault_share_price.into();

let spot_price = self.calculate_spot_price()?;
let spot_price = self.calculate_spot_price_down()?;
if spot_price > fixed!(1e18) {
return Err(eyre!("Negative fixed interest!"));
}
Expand Down Expand Up @@ -513,7 +513,7 @@ mod tests {
let state = rng.gen::<State>();
let result = state.calculate_close_short(
(state.config.minimum_transaction_amount - 10).into(),
state.calculate_spot_price()?,
state.calculate_spot_price_down()?,
state.vault_share_price(),
0.into(),
0.into(),
Expand Down
Loading
Loading