Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 6 additions & 1 deletion contracts/src/external/HyperdriveTarget0.sol
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,12 @@ abstract contract HyperdriveTarget0 is
timeStretch: _timeStretch,
governance: _governance,
feeCollector: _feeCollector,
fees: IHyperdrive.Fees(_curveFee, _flatFee, _governanceFee)
fees: IHyperdrive.Fees(
_curveFee,
_flatFee,
_governanceLPFee,
_governanceZombieFee
)
})
)
);
Expand Down
23 changes: 17 additions & 6 deletions contracts/src/factory/HyperdriveFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,11 @@ contract HyperdriveFactory {
/// @dev The maximum flat fee that can be used as a factory default.
uint256 internal immutable maxFlatFee;

/// @dev The maximum governance fee that can be used as a factory default.
uint256 internal immutable maxGovernanceFee;
/// @dev The maximum governance LP fee that can be used as a factory default.
uint256 internal immutable maxGovernanceLPFee;

/// @dev The maximum governance zombie fee that can be used as a factory default.
uint256 internal immutable maxGovernanceZombieFee;

/// @dev The defaultPausers used when new instances are deployed.
address[] internal _defaultPausers;
Expand Down Expand Up @@ -118,14 +121,21 @@ contract HyperdriveFactory {
// constraint.
maxCurveFee = _factoryConfig.maxFees.curve;
maxFlatFee = _factoryConfig.maxFees.flat;
maxGovernanceFee = _factoryConfig.maxFees.governance;
if (maxCurveFee > ONE || maxFlatFee > ONE || maxGovernanceFee > ONE) {
maxGovernanceLPFee = _factoryConfig.maxFees.governanceLP;
maxGovernanceZombieFee = _factoryConfig.maxFees.governanceZombie;
if (
maxCurveFee > ONE ||
maxFlatFee > ONE ||
maxGovernanceLPFee > ONE ||
maxGovernanceZombieFee > ONE
) {
revert IHyperdrive.MaxFeeTooHigh();
}
if (
_factoryConfig.fees.curve > maxCurveFee ||
_factoryConfig.fees.flat > maxFlatFee ||
_factoryConfig.fees.governance > maxGovernanceFee
_factoryConfig.fees.governanceLP > maxGovernanceLPFee ||
_factoryConfig.fees.governanceZombie > maxGovernanceZombieFee
) {
revert IHyperdrive.FeeTooHigh();
}
Expand Down Expand Up @@ -198,7 +208,8 @@ contract HyperdriveFactory {
if (
_fees.curve > maxCurveFee ||
_fees.flat > maxFlatFee ||
_fees.governance > maxGovernanceFee
_fees.governanceLP > maxGovernanceLPFee ||
_fees.governanceZombie > maxGovernanceZombieFee
) {
revert IHyperdrive.FeeTooHigh();
}
Expand Down
4 changes: 3 additions & 1 deletion contracts/src/interfaces/IHyperdrive.sol
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ interface IHyperdrive is IHyperdriveRead, IHyperdriveCore, IMultiToken {
/// @dev The LP fee applied to the flat portion of a trade.
uint256 flat;
/// @dev The portion of the LP fee that goes to governance.
uint256 governance;
uint256 governanceLP;
/// @dev The portion of the zombie interest that goes to governance.
uint256 governanceZombie;
}

struct PoolConfig {
Expand Down
21 changes: 18 additions & 3 deletions contracts/src/internal/HyperdriveBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -350,12 +350,27 @@ abstract contract HyperdriveBase is HyperdriveStorage {
uint256 _newSharePrice
) internal {
if (_newSharePrice > _oldSharePrice && _oldSharePrice > 0) {
// Calculate the zombie interest to be collected in shares.
// dz * (c1 - c0)/c1
uint256 zombieInterest = _amount.mulDivDown(
_newSharePrice - _oldSharePrice,
_newSharePrice
);
_marketState.zombieShareReserves -= zombieInterest.toUint128();

// Calculate and collect the governance fee.
// The fee is calculated in terms of shares and paid to
// governance.
uint256 governanceZombieFeeCollected = zombieInterest.mulDown(
_governanceZombieFee
);
_governanceFeesAccrued += governanceZombieFeeCollected;

// The zombie interest that was collected (minus the fees paid to
// governance), are reinvested in the share reserves. The share
// adjustment is updated in lock-step to avoid changing the curve's
// k invariant.
zombieInterest -= governanceZombieFeeCollected;
_marketState.shareReserves += zombieInterest.toUint128();
_marketState.shareAdjustment += int128(zombieInterest.toUint128());
}
Expand Down Expand Up @@ -420,7 +435,7 @@ abstract contract HyperdriveBase is HyperdriveStorage {
// We leave the governance fee in terms of bonds:
// governanceCurveFee = curve_fee * p * phi_gov
// = bonds * phi_gov
governanceCurveFee = curveFee.mulDown(_governanceFee);
governanceCurveFee = curveFee.mulDown(_governanceLPFee);
}

/// @dev Calculates the fees that go to the LPs and governance.
Expand Down Expand Up @@ -469,7 +484,7 @@ abstract contract HyperdriveBase is HyperdriveStorage {
//
// governanceCurveFee = curve_fee * phi_gov
// = shares * phi_gov
governanceCurveFee = curveFee.mulDown(_governanceFee);
governanceCurveFee = curveFee.mulDown(_governanceLPFee);

// The flat portion of the fee is taken from the matured bonds.
// Since a matured bond is worth 1 base, it is appropriate to consider
Expand All @@ -493,7 +508,7 @@ abstract contract HyperdriveBase is HyperdriveStorage {
// The totalGovernanceFee is the sum of the curve and flat governance fees.
totalGovernanceFee =
governanceCurveFee +
flatFee.mulDown(_governanceFee);
flatFee.mulDown(_governanceLPFee);
}

/// @dev Converts input to base if necessary according to what is specified in options.
Expand Down
2 changes: 1 addition & 1 deletion contracts/src/internal/HyperdriveCheckpoint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ abstract contract HyperdriveCheckpoint is
// bond amount divided by the share price.
shareProceeds = _bondAmount.divDown(_sharePrice);
uint256 flatFee = shareProceeds.mulDown(_flatFee);
governanceFee = flatFee.mulDown(_governanceFee);
governanceFee = flatFee.mulDown(_governanceLPFee);

// If the position is a long, the share proceeds are removed from the
// share reserves. The proceeds are decreased by the flat fee because
Expand Down
10 changes: 7 additions & 3 deletions contracts/src/internal/HyperdriveStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ abstract contract HyperdriveStorage is ReentrancyGuard {
uint256 internal immutable _flatFee;

/// @dev The portion of the LP fee that goes to governance.
uint256 internal immutable _governanceFee;
uint256 internal immutable _governanceLPFee;

/// @dev The portion of the zombie interest that goes to governance.
uint256 internal immutable _governanceZombieFee;

/// Market State ///

Expand Down Expand Up @@ -164,13 +167,14 @@ abstract contract HyperdriveStorage is ReentrancyGuard {
if (
_config.fees.curve > 1e18 ||
_config.fees.flat > 1e18 ||
_config.fees.governance > 1e18
_config.fees.governanceLP > 1e18
) {
revert IHyperdrive.InvalidFeeAmounts();
}
_curveFee = _config.fees.curve;
_flatFee = _config.fees.flat;
_governanceFee = _config.fees.governance;
_governanceLPFee = _config.fees.governanceLP;
_governanceZombieFee = _config.fees.governanceZombie;

// Initialize the MultiToken immutables.
_linkerFactory = _config.linkerFactory;
Expand Down
14 changes: 12 additions & 2 deletions contracts/test/MockMultiToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,12 @@ contract MockMultiToken is HyperdriveMultiToken, MockHyperdriveBase {
timeStretch: HyperdriveUtils.calculateTimeStretch(0.05e18),
governance: address(0),
feeCollector: address(0),
fees: IHyperdrive.Fees({ curve: 0, flat: 0, governance: 0 })
fees: IHyperdrive.Fees({
curve: 0,
flat: 0,
governanceLP: 0,
governanceZombie: 0
})
})
)
{
Expand All @@ -79,7 +84,12 @@ contract MockMultiToken is HyperdriveMultiToken, MockHyperdriveBase {
timeStretch: HyperdriveUtils.calculateTimeStretch(0.05e18),
governance: address(0),
feeCollector: address(0),
fees: IHyperdrive.Fees({ curve: 0, flat: 0, governance: 0 })
fees: IHyperdrive.Fees({
curve: 0,
flat: 0,
governanceLP: 0,
governanceZombie: 0
})
})
)
);
Expand Down
7 changes: 4 additions & 3 deletions crates/hyperdrive-math/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ impl Distribution<State> for Standard {
fees: Fees {
curve: rng.gen_range(fixed!(0.0001e18)..=fixed!(0.2e18)).into(),
flat: rng.gen_range(fixed!(0.0001e18)..=fixed!(0.2e18)).into(),
governance: rng.gen_range(fixed!(0.0001e18)..=fixed!(0.2e18)).into(),
governance_lp: rng.gen_range(fixed!(0.0001e18)..=fixed!(0.2e18)).into(),
governance_zombie: rng.gen_range(fixed!(0.0001e18)..=fixed!(0.2e18)).into(),
},
initial_share_price: rng.gen_range(fixed!(0.5e18)..=fixed!(2.5e18)).into(),
minimum_share_reserves: rng.gen_range(fixed!(0.1e18)..=fixed!(1e18)).into(),
Expand Down Expand Up @@ -167,8 +168,8 @@ impl State {
self.config.fees.flat.into()
}

fn governance_fee(&self) -> FixedPoint {
self.config.fees.governance.into()
fn governance_lp_fee(&self) -> FixedPoint {
self.config.fees.governance_lp.into()
}

/// Info ///
Expand Down
2 changes: 1 addition & 1 deletion crates/hyperdrive-math/src/long/fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ impl State {
/// g(x) = \phi_{g} \cdot p \cdot c(x)
/// $$
pub fn open_long_governance_fee(&self, base_amount: FixedPoint) -> FixedPoint {
self.governance_fee() * self.get_spot_price() * self.open_long_curve_fees(base_amount)
self.governance_lp_fee() * self.get_spot_price() * self.open_long_curve_fees(base_amount)
}

/// Gets the curve fee paid by longs for a given bond amount.
Expand Down
10 changes: 6 additions & 4 deletions crates/hyperdrive-math/src/long/max.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ impl State {
let mut estimate = self.get_solvency() + checkpoint_exposure / self.share_price();
estimate = estimate.mul_div_down(self.share_price(), fixed!(2e18));
estimate /= fixed!(1e18) / estimate_price
+ self.governance_fee() * self.curve_fee() * (fixed!(1e18) - spot_price)
+ self.governance_lp_fee() * self.curve_fee() * (fixed!(1e18) - spot_price)
- fixed!(1e18)
- self.curve_fee() * (fixed!(1e18) / spot_price - fixed!(1e18));
estimate
Expand Down Expand Up @@ -375,7 +375,9 @@ impl State {
let maybe_derivative = self.long_amount_derivative(base_amount);
maybe_derivative.map(|derivative| {
(derivative
+ self.governance_fee() * self.curve_fee() * (fixed!(1e18) - self.get_spot_price())
+ self.governance_lp_fee()
* self.curve_fee()
* (fixed!(1e18) - self.get_spot_price())
- fixed!(1e18))
.mul_div_down(fixed!(1e18), self.share_price())
})
Expand Down Expand Up @@ -480,7 +482,7 @@ mod tests {
minimum_share_reserves: state.config.minimum_share_reserves,
curve_fee: state.config.fees.curve,
flat_fee: state.config.fees.flat,
governance_fee: state.config.fees.governance,
governance_lp_fee: state.config.fees.governance_lp,
},
get_effective_share_reserves(
state.info.share_reserves.into(),
Expand Down Expand Up @@ -544,7 +546,7 @@ mod tests {
minimum_share_reserves: state.config.minimum_share_reserves,
curve_fee: state.config.fees.curve,
flat_fee: state.config.fees.flat,
governance_fee: state.config.fees.governance,
governance_lp_fee: state.config.fees.governance_lp,
},
checkpoint_exposure,
uint256!(7),
Expand Down
2 changes: 1 addition & 1 deletion crates/hyperdrive-math/src/short/fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl State {
short_amount: FixedPoint,
spot_price: FixedPoint,
) -> FixedPoint {
self.governance_fee() * self.open_short_curve_fee(short_amount, spot_price)
self.governance_lp_fee() * self.open_short_curve_fee(short_amount, spot_price)
}

/// Gets the curve fee paid by shorts for a given bond amount.
Expand Down
11 changes: 6 additions & 5 deletions crates/hyperdrive-math/src/short/max.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ impl State {
FixedPoint::from(checkpoint_exposure.max(I256::zero())) / self.share_price();
(self.share_price() * (self.get_solvency() + checkpoint_exposure))
/ (estimate_price - self.curve_fee() * (fixed!(1e18) - spot_price)
+ self.governance_fee() * self.curve_fee() * (fixed!(1e18) - spot_price))
+ self.governance_lp_fee() * self.curve_fee() * (fixed!(1e18) - spot_price))
}

/// Gets the derivative of the short deposit function with respect to the
Expand Down Expand Up @@ -450,9 +450,10 @@ impl State {
spot_price: FixedPoint,
) -> Option<FixedPoint> {
let lhs = self.short_principal_derivative(short_amount);
let rhs =
self.curve_fee() * (fixed!(1e18) - spot_price) * (fixed!(1e18) - self.governance_fee())
/ self.share_price();
let rhs = self.curve_fee()
* (fixed!(1e18) - spot_price)
* (fixed!(1e18) - self.governance_lp_fee())
/ self.share_price();
if lhs >= rhs {
Some(lhs - rhs)
} else {
Expand Down Expand Up @@ -567,7 +568,7 @@ mod tests {
minimum_share_reserves: state.config.minimum_share_reserves,
curve_fee: state.config.fees.curve,
flat_fee: state.config.fees.flat,
governance_fee: state.config.fees.governance,
governance_lp_fee: state.config.fees.governance_lp,
},
checkpoint_exposure,
max_iterations.into(),
Expand Down
2 changes: 1 addition & 1 deletion crates/hyperdrive-math/src/short/open.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ mod tests {
minimum_share_reserves: state.config.minimum_share_reserves,
curve_fee: state.config.fees.curve,
flat_fee: state.config.fees.flat,
governance_fee: state.config.fees.governance,
governance_lp_fee: state.config.fees.governance_lp,
},
checkpoint_exposure,
max_iterations.into(),
Expand Down
6 changes: 4 additions & 2 deletions crates/test-utils/src/chain/test_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,8 @@ impl TestChain {
fees: Fees {
curve: uint256!(0.05e18),
flat: uint256!(0.0005e18),
governance: uint256!(0.15e18),
governance_lp: uint256!(0.15e18),
governance_zombie: uint256!(0.15e18),
},
};
let target0 = ERC4626Target0::deploy(client.clone(), (config.clone(), pool.address()))?
Expand Down Expand Up @@ -613,7 +614,8 @@ mod tests {
Fees {
curve: uint256!(0.05e18),
flat: uint256!(0.0005e18),
governance: uint256!(0.15e18),
governance_lp: uint256!(0.15e18),
governance_zombie: uint256!(0.15e18),
}
);

Expand Down
Loading