Skip to content

Commit

Permalink
parameter invariant cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
kbrizzle committed Jul 18, 2023
1 parent 1d4bac3 commit c931370
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 73 deletions.
50 changes: 3 additions & 47 deletions packages/perennial/contracts/Market.sol
Original file line number Diff line number Diff line change
Expand Up @@ -119,60 +119,16 @@ contract Market is IMarket, Instance {
/// @notice Updates the parameter set of the market
/// @param newParameter The new parameter set
function updateParameter(MarketParameter memory newParameter) external onlyOwner {
ProtocolParameter memory protocolParameter = IMarketFactory(address(factory())).parameter();

if (newParameter.fundingFee.gt(protocolParameter.maxCut)) revert MarketInvalidMarketParameterError(1);
if (newParameter.interestFee.gt(protocolParameter.maxCut)) revert MarketInvalidMarketParameterError(2);
if (newParameter.positionFee.gt(protocolParameter.maxCut)) revert MarketInvalidMarketParameterError(3);
if (newParameter.settlementFee.gt(protocolParameter.maxFeeAbsolute))
revert MarketInvalidMarketParameterError(4);
if (newParameter.oracleFee.add(newParameter.riskFee).gt(UFixed6Lib.ONE))
revert MarketInvalidMarketParameterError(5);
if (reward.isZero() && (
!newParameter.makerRewardRate.isZero() ||
!newParameter.longRewardRate.isZero() ||
!newParameter.shortRewardRate.isZero()
)) revert MarketInvalidMarketParameterError(6);

newParameter.validate(IMarketFactory(address(factory())).parameter(), reward);
_parameter.store(newParameter);
emit ParameterUpdated(newParameter);
}

/// @notice Updates the risk parameter set of the market
/// @param newRiskParameter The new risk parameter set
function updateRiskParameter(RiskParameter memory newRiskParameter) external onlyCoordinator {
ProtocolParameter memory protocolParameter = IMarketFactory(address(factory())).parameter();

if (newRiskParameter.maintenance.lt(protocolParameter.minMaintenance))
revert MarketInvalidRiskParameterError(1);
if (newRiskParameter.takerFee.gt(protocolParameter.maxFee)) revert MarketInvalidRiskParameterError(2);
if (newRiskParameter.takerSkewFee.gt(protocolParameter.maxFee)) revert MarketInvalidRiskParameterError(3);
if (newRiskParameter.takerImpactFee.gt(protocolParameter.maxFee)) revert MarketInvalidRiskParameterError(4);
if (newRiskParameter.makerFee.gt(protocolParameter.maxFee)) revert MarketInvalidRiskParameterError(5);
if (newRiskParameter.makerImpactFee.gt(protocolParameter.maxFee)) revert MarketInvalidRiskParameterError(6);
if (newRiskParameter.efficiencyLimit.lt(protocolParameter.minEfficiency))
revert MarketInvalidRiskParameterError(7);
if (newRiskParameter.liquidationFee.gt(protocolParameter.maxCut)) revert MarketInvalidRiskParameterError(8);
if (newRiskParameter.minLiquidationFee.gt(protocolParameter.maxFeeAbsolute))
revert MarketInvalidRiskParameterError(9);
if (newRiskParameter.maxLiquidationFee.gt(protocolParameter.maxFeeAbsolute))
revert MarketInvalidRiskParameterError(10);
if (newRiskParameter.utilizationCurve.minRate.gt(protocolParameter.maxRate))
revert MarketInvalidRiskParameterError(11);
if (newRiskParameter.utilizationCurve.maxRate.gt(protocolParameter.maxRate))
revert MarketInvalidRiskParameterError(12);
if (newRiskParameter.utilizationCurve.targetRate.gt(protocolParameter.maxRate))
revert MarketInvalidRiskParameterError(13);
if (newRiskParameter.utilizationCurve.targetUtilization.gt(UFixed6Lib.ONE))
revert MarketInvalidRiskParameterError(14);
if (newRiskParameter.pController.max.gt(protocolParameter.maxRate))
revert MarketInvalidRiskParameterError(15);
if (
newRiskParameter.minMaintenance.gt(protocolParameter.maxFeeAbsolute) ||
newRiskParameter.minMaintenance.lt(newRiskParameter.minLiquidationFee)
) revert MarketInvalidRiskParameterError(16);

_updateRiskParameter(newRiskParameter);
newRiskParameter.validate(IMarketFactory(address(factory())).parameter());
_updateRiskParameter(newRiskParameter); // TODO: unpack
}

/// @notice Updates the reward token of the market
Expand Down
26 changes: 25 additions & 1 deletion packages/perennial/contracts/types/MarketParameter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ pragma solidity ^0.8.13;

import "@equilibria/perennial-v2-payoff/contracts/interfaces/IPayoffProvider.sol";
import "@equilibria/perennial-v2-oracle/contracts/interfaces/IOracleProvider.sol";
import "@equilibria/root/token/types/Token18.sol";
import "@equilibria/root/number/types/UFixed6.sol";
import "@equilibria/root/curve/types/UJumpRateUtilizationCurve6.sol";
import "@equilibria/root-v2/contracts/PController6.sol";
import "./ProtocolParameter.sol";

/// @dev MarketParameter type
struct MarketParameter {
Expand All @@ -22,7 +24,7 @@ struct MarketParameter {
bool makerCloseAlways;
bool closed;
}

using MarketParameterLib for MarketParameter global;
struct StoredMarketParameter {
uint24 fundingFee; // <= 1677%
uint24 interestFee; // <= 1677%
Expand All @@ -38,6 +40,28 @@ struct StoredMarketParameter {
struct MarketParameterStorage { StoredMarketParameter value; }
using MarketParameterStorageLib for MarketParameterStorage global;

library MarketParameterLib {
error MarketInvalidMarketParameterError(uint256 code);

function validate(
MarketParameter memory self,
ProtocolParameter memory protocolParameter,
Token18 reward
) internal pure {
if (self.settlementFee.gt(protocolParameter.maxFeeAbsolute)) revert MarketInvalidMarketParameterError(2);

if (self.fundingFee.max(self.interestFee).max(self.positionFee).gt(protocolParameter.maxCut))
revert MarketInvalidMarketParameterError(3);

if (self.oracleFee.add(self.riskFee).gt(UFixed6Lib.ONE)) revert MarketInvalidMarketParameterError(8);

if (
reward.isZero() &&
(!self.makerRewardRate.isZero() || !self.longRewardRate.isZero() || !self.shortRewardRate.isZero())
) revert MarketInvalidMarketParameterError(9);
}
}

library MarketParameterStorageLib {
error MarketParameterStorageInvalidError();

Expand Down
34 changes: 33 additions & 1 deletion packages/perennial/contracts/types/RiskParameter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "@equilibria/perennial-v2-oracle/contracts/interfaces/IOracleProvider.sol
import "@equilibria/root/number/types/UFixed6.sol";
import "@equilibria/root/curve/types/UJumpRateUtilizationCurve6.sol";
import "@equilibria/root-v2/contracts/PController6.sol";
import "./ProtocolParameter.sol";

/// @dev RiskParameter type
struct RiskParameter {
Expand All @@ -27,7 +28,7 @@ struct RiskParameter {
uint256 staleAfter;
bool makerReceiveOnly;
}

using RiskParameterLib for RiskParameter global;
struct StoredRiskParameter {
/* slot 1 */
uint48 makerLimit; // <= 281m
Expand Down Expand Up @@ -59,6 +60,37 @@ struct StoredRiskParameter {
struct RiskParameterStorage { StoredRiskParameter value; }
using RiskParameterStorageLib for RiskParameterStorage global;

library RiskParameterLib {
error MarketInvalidRiskParameterError(uint256 code);

function validate(RiskParameter memory self, ProtocolParameter memory protocolParameter) internal pure {
if (
self.takerFee.max(self.takerSkewFee).max(self.takerImpactFee).max(self.makerFee).max(self.makerImpactFee)
.gt(protocolParameter.maxFee)
) revert MarketInvalidRiskParameterError(1);

if (
self.minLiquidationFee.max(self.maxLiquidationFee).max(self.minMaintenance)
.gt(protocolParameter.maxFeeAbsolute)
) revert MarketInvalidRiskParameterError(2);

if (self.liquidationFee.gt(protocolParameter.maxCut)) revert MarketInvalidRiskParameterError(3);

if (
self.utilizationCurve.minRate.max(self.utilizationCurve.maxRate).max(self.utilizationCurve.targetRate).max(self.pController.max)
.gt(protocolParameter.maxRate)
) revert MarketInvalidRiskParameterError(4);

if (self.maintenance.lt(protocolParameter.minMaintenance)) revert MarketInvalidRiskParameterError(5);

if (self.efficiencyLimit.lt(protocolParameter.minEfficiency)) revert MarketInvalidRiskParameterError(6);

if (self.utilizationCurve.targetUtilization.gt(UFixed6Lib.ONE)) revert MarketInvalidRiskParameterError(7);

if (self.minMaintenance.lt(self.minLiquidationFee)) revert MarketInvalidRiskParameterError(8);
}
}

library RiskParameterStorageLib {
error RiskParameterStorageInvalidError();

Expand Down
48 changes: 24 additions & 24 deletions packages/perennial/test/unit/market/Market.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateParameter(newMarketParameter))
.to.revertedWithCustomError(market, 'MarketInvalidMarketParameterError')
.withArgs(4)
.withArgs(2)
})
})

Expand Down Expand Up @@ -570,7 +570,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateParameter(newMarketParameter))
.to.revertedWithCustomError(market, 'MarketInvalidMarketParameterError')
.withArgs(1)
.withArgs(3)
})

it('interestFee -> fail', async () => {
Expand All @@ -581,7 +581,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateParameter(newMarketParameter))
.to.revertedWithCustomError(market, 'MarketInvalidMarketParameterError')
.withArgs(2)
.withArgs(3)
})

it('positionFee -> fail', async () => {
Expand Down Expand Up @@ -618,7 +618,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateParameter(newMarketParameter))
.to.revertedWithCustomError(market, 'MarketInvalidMarketParameterError')
.withArgs(5)
.withArgs(8)
})
})

Expand All @@ -644,7 +644,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateParameter(newMarketParameter))
.to.revertedWithCustomError(market, 'MarketInvalidMarketParameterError')
.withArgs(6)
.withArgs(9)
})

it('longRewardRate -> fail', async () => {
Expand All @@ -656,7 +656,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateParameter(newMarketParameter))
.to.revertedWithCustomError(market, 'MarketInvalidMarketParameterError')
.withArgs(6)
.withArgs(9)
})

it('shortRewardRate -> fail', async () => {
Expand All @@ -668,7 +668,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateParameter(newMarketParameter))
.to.revertedWithCustomError(market, 'MarketInvalidMarketParameterError')
.withArgs(6)
.withArgs(9)
})
})

Expand Down Expand Up @@ -806,7 +806,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(2)
.withArgs(1)
})

it('takerSkewFee -> fail', async () => {
Expand All @@ -817,7 +817,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(3)
.withArgs(1)
})

it('takerImpactFee -> fail', async () => {
Expand All @@ -828,7 +828,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(4)
.withArgs(1)
})

it('makerFee -> fail', async () => {
Expand All @@ -839,7 +839,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(5)
.withArgs(1)
})

it('makerImpactFee -> fail', async () => {
Expand All @@ -850,7 +850,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(6)
.withArgs(1)
})
})

Expand All @@ -877,7 +877,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(9)
.withArgs(2)
})

it('maxLiquidationFee -> fail', async () => {
Expand All @@ -888,7 +888,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(10)
.withArgs(2)
})

it('minMaintenance -> fail', async () => {
Expand All @@ -899,7 +899,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(16)
.withArgs(2)
})
})

Expand All @@ -924,7 +924,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(8)
.withArgs(3)
})
})

Expand Down Expand Up @@ -961,7 +961,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(11)
.withArgs(4)
})

it('utilizationCurve.maxRate -> fail', async () => {
Expand All @@ -975,7 +975,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(12)
.withArgs(4)
})

it('utilizationCurve.targetRate -> fail', async () => {
Expand All @@ -989,7 +989,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(13)
.withArgs(4)
})

it('pController.max -> fail', async () => {
Expand All @@ -1003,7 +1003,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(15)
.withArgs(4)
})
})

Expand All @@ -1028,7 +1028,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(1)
.withArgs(5)
})
})

Expand All @@ -1053,7 +1053,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(7)
.withArgs(6)
})
})

Expand Down Expand Up @@ -1082,7 +1082,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(14)
.withArgs(7)
})
})

Expand Down Expand Up @@ -1117,7 +1117,7 @@ describe('Market', () => {
}
await expect(market.connect(owner).updateRiskParameter(newRiskParameter))
.to.revertedWithCustomError(market, 'MarketInvalidRiskParameterError')
.withArgs(16)
.withArgs(8)
})
})

Expand Down

0 comments on commit c931370

Please sign in to comment.