Skip to content

Commit

Permalink
bugfix time stretch
Browse files Browse the repository at this point in the history
  • Loading branch information
dpaiton committed Jan 17, 2024
1 parent b94b2da commit bd47634
Showing 1 changed file with 17 additions and 16 deletions.
33 changes: 17 additions & 16 deletions crates/hyperdrive-math/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ use fixed_point_macros::{fixed, uint256};

pub fn get_time_stretch(mut rate: FixedPoint, position_duration: FixedPoint) -> FixedPoint {
let seconds_in_a_year = FixedPoint::from(U256::from(60 * 60 * 24 * 365));
let annualized_time = position_duration / seconds_in_a_year;
rate = (U256::from(rate) * uint256!(100)).into();
// Calculate the benchmark time stretch. This time stretch is tuned for
// a position duration of 1 year.
let time_stretch = fixed!(1e18) / (fixed!(5.24592e18) / (fixed!(0.04665e18) * rate));
let time_stretch = fixed!(5.24592e18)
/ (fixed!(0.04665e18) * FixedPoint::from(U256::from(rate) * uint256!(100)));
let time_stretch = fixed!(1e18) / time_stretch;
// if the position duration is 1 year, we can return the benchmark
if annualized_time == fixed!(1e18) {
if position_duration == seconds_in_a_year {
return time_stretch;
}

Expand All @@ -33,6 +33,8 @@ pub fn get_time_stretch(mut rate: FixedPoint, position_duration: FixedPoint) ->
// p = ratio ** timeStretch
// =>
// timeStretch = ln(p) / ln(ratio)
let target_spot_price =
fixed!(1e18) / (fixed!(1e18) + rate.mul_div_down(position_duration, seconds_in_a_year));
let benchmark_reserve_ratio = fixed!(1e18)
/ calculate_initial_bond_reserves(
fixed!(1e18),
Expand All @@ -41,16 +43,12 @@ pub fn get_time_stretch(mut rate: FixedPoint, position_duration: FixedPoint) ->
seconds_in_a_year,
time_stretch,
);
let target_spot_price = fixed!(1e18) / (fixed!(1e18) * annualized_time);
// target spot price and benchmark reserve ratio will have negative ln,
// but since we are dividing them we can cast to positive before converting types
// TODO: implement FixedPoint `neg` pub fn to support "-"
let new_time_stretch = U256::from(FixedPoint::from(-FixedPoint::ln(I256::from(
target_spot_price,
)))) / U256::from(FixedPoint::from(-FixedPoint::ln(I256::from(
benchmark_reserve_ratio,
))));
new_time_stretch.into()
let new_time_stretch = FixedPoint::from(-FixedPoint::ln(I256::from(target_spot_price)))
/ FixedPoint::from(-FixedPoint::ln(I256::from(benchmark_reserve_ratio)));
new_time_stretch
}

pub fn get_effective_share_reserves(
Expand Down Expand Up @@ -117,15 +115,18 @@ mod tests {
let chain = TestChainWithMocks::new(1).await?;
let mock = chain.mock_hyperdrive_math();
// Fuzz the rust and solidity implementations against each other.
let apr = fixed!(0.05e18); // 5%
let seconds_in_a_year = U256::from(60 * 60 * 24 * 365);
let seconds_in_ten_years = U256::from(10 * 60 * 60 * 24 * 365);
let seconds_in_a_day = U256::from(60 * 60);
let mut rng = thread_rng();
for _ in 0..*FAST_FUZZ_RUNS {
// Get the current state of the mock contract
let state = rng.gen::<State>();
let actual_t = get_time_stretch(apr, seconds_in_a_year.into());
let position_duration = rng.gen_range(
FixedPoint::from(seconds_in_a_day)..=FixedPoint::from(seconds_in_ten_years),
);
let apr = rng.gen_range(fixed!(0.001e18)..=fixed!(10.0e18));
let actual_t = get_time_stretch(apr, position_duration);
match mock
.calculate_time_stretch(apr.into(), seconds_in_a_year)
.calculate_time_stretch(apr.into(), position_duration.into())
.call()
.await
{
Expand Down

0 comments on commit bd47634

Please sign in to comment.