Skip to content

Commit

Permalink
Merge pull request #463 from equilibria-xyz/ed/58-maxStaleAfter
Browse files Browse the repository at this point in the history
Fix for coordinator setting staleAfter too high
  • Loading branch information
EdNoepel authored Oct 7, 2024
2 parents 9ca7886 + e9eeb98 commit 4d7aeb8
Show file tree
Hide file tree
Showing 17 changed files with 86 additions and 5 deletions.
1 change: 1 addition & 0 deletions packages/perennial-account/test/helpers/setupHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ async function deployMarketFactory(
minEfficiency: parse6decimal('0.1'),
referralFee: 0,
minScale: parse6decimal('0.001'),
maxStaleAfter: 7200,
})

return marketFactory
Expand Down
1 change: 1 addition & 0 deletions packages/perennial-deploy/tasks/multisig_ops/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -576,4 +576,5 @@ export const NewProtocolParameter: ProtocolParameterStruct = {
minMaintenance: 4000,
minEfficiency: 250000,
referralFee: 0,
maxStaleAfter: 172800, // 2 days
}
1 change: 1 addition & 0 deletions packages/perennial-deploy/util/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const DEFAULT_PROTOCOL_PARAMETER = {
minMaintenance: utils.parseUnits('0.004', 6), // 0.4%
minEfficiency: utils.parseUnits('0.25', 6), // 25%
referralFee: 0,
maxStaleAfter: 7200, // 2 hours
}

export const DEFAULT_MARKET_PARAMETER = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ export async function deployProtocol(chainlinkContext?: ChainlinkContext): Promi
minEfficiency: parse6decimal('0.1'),
referralFee: 0,
minScale: parse6decimal('0.001'),
maxStaleAfter: 7200,
})
await oracleFactory.connect(owner).register(chainlink.oracleFactory.address)
const oracle = IOracle__factory.connect(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ testOracles.forEach(testOracle => {
minEfficiency: parse6decimal('0.1'),
referralFee: 0,
minScale: parse6decimal('0.001'),
maxStaleAfter: 7200,
})

const riskParameter = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ testOracles.forEach(testOracle => {
minEfficiency: parse6decimal('0.1'),
referralFee: 0,
minScale: parse6decimal('0.001'),
maxStaleAfter: 7200,
})

const riskParameter = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ testOracles.forEach(testOracle => {
minEfficiency: parse6decimal('0.1'),
referralFee: 0,
minScale: parse6decimal('0.001'),
maxStaleAfter: 7200,
})

const riskParameter = {
Expand Down
1 change: 1 addition & 0 deletions packages/perennial-order/test/helpers/arbitrumHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ async function deployMarketFactory(
minEfficiency: parse6decimal('0.1'),
referralFee: 0,
minScale: parse6decimal('0.001'),
maxStaleAfter: 7200,
})

return marketFactory
Expand Down
13 changes: 10 additions & 3 deletions packages/perennial/contracts/types/ProtocolParameter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ struct ProtocolParameter {

/// @dev The minimum ratio between scale vs makerLimit / efficiencyLimit
UFixed6 minScale;

/// @dev The maximum for parameter restricting maximum time between oracle version and update
uint256 maxStaleAfter;
}
struct StoredProtocolParameter {
/* slot 0 (28) */
/* slot 0 (31) */
uint24 maxFee; // <= 1677%
uint48 maxFeeAbsolute; // <= 281m
uint24 maxCut; // <= 1677%
Expand All @@ -39,6 +42,7 @@ struct StoredProtocolParameter {
uint24 minEfficiency; // <= 1677%
uint24 referralFee; // <= 1677%
uint24 minScale; // <= 1677%
uint24 maxStaleAfter; // <= 4660 hours
}
struct ProtocolParameterStorage { StoredProtocolParameter value; } // SECURITY: must remain at (1) slots
using ProtocolParameterStorageLib for ProtocolParameterStorage global;
Expand All @@ -58,7 +62,8 @@ library ProtocolParameterStorageLib {
UFixed6.wrap(uint256(value.minMaintenance)),
UFixed6.wrap(uint256(value.minEfficiency)),
UFixed6.wrap(uint256(value.referralFee)),
UFixed6.wrap(uint256(value.minScale))
UFixed6.wrap(uint256(value.minScale)),
uint24(value.maxStaleAfter)
);
}

Expand All @@ -76,6 +81,7 @@ library ProtocolParameterStorageLib {
if (newValue.maxRate.gt(UFixed6.wrap(type(uint32).max / 2))) revert ProtocolParameterStorageInvalidError();
if (newValue.minMaintenance.gt(UFixed6.wrap(type(uint24).max))) revert ProtocolParameterStorageInvalidError();
if (newValue.minEfficiency.gt(UFixed6.wrap(type(uint24).max))) revert ProtocolParameterStorageInvalidError();
if (newValue.maxStaleAfter > uint256(type(uint24).max)) revert ProtocolParameterStorageInvalidError();

self.value = StoredProtocolParameter(
uint24(UFixed6.unwrap(newValue.maxFee)),
Expand All @@ -85,7 +91,8 @@ library ProtocolParameterStorageLib {
uint24(UFixed6.unwrap(newValue.minMaintenance)),
uint24(UFixed6.unwrap(newValue.minEfficiency)),
uint24(UFixed6.unwrap(newValue.referralFee)),
uint24(UFixed6.unwrap(newValue.minScale))
uint24(UFixed6.unwrap(newValue.minScale)),
uint24(newValue.maxStaleAfter)
);
}
}
2 changes: 2 additions & 0 deletions packages/perennial/contracts/types/RiskParameter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ library RiskParameterStorageLib {
.gt(protocolParameter.maxRate)
) revert RiskParameterStorageInvalidError();

if (self.staleAfter > protocolParameter.maxStaleAfter) revert RiskParameterStorageInvalidError();

if (self.maintenance.lt(protocolParameter.minMaintenance)) revert RiskParameterStorageInvalidError();

if (self.margin.lt(self.maintenance)) revert RiskParameterStorageInvalidError();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export async function deployProtocol(chainlinkContext?: ChainlinkContext): Promi
minEfficiency: parse6decimal('0.1'),
referralFee: 0,
minScale: parse6decimal('0.001'),
maxStaleAfter: 172800, // 2 days
})
await oracleFactory.connect(owner).register(chainlink.oracleFactory.address)
await oracleFactory.connect(owner).updateParameter({
Expand Down
23 changes: 23 additions & 0 deletions packages/perennial/test/unit/market/Market.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: 0,
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})
factory.oracleFactory.returns(oracleFactorySigner.address)

Expand Down Expand Up @@ -16465,6 +16466,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

oracle.at.whenCalledWith(ORACLE_VERSION_2.timestamp).returns([ORACLE_VERSION_2, INITIALIZED_ORACLE_RECEIPT])
Expand Down Expand Up @@ -16526,6 +16528,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

oracle.at.whenCalledWith(ORACLE_VERSION_2.timestamp).returns([ORACLE_VERSION_2, INITIALIZED_ORACLE_RECEIPT])
Expand Down Expand Up @@ -18092,6 +18095,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -20042,6 +20046,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const riskParameter = { ...(await market.riskParameter()) }
Expand Down Expand Up @@ -20166,6 +20171,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const riskParameter = { ...(await market.riskParameter()) }
Expand Down Expand Up @@ -20330,6 +20336,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const riskParameter = { ...(await market.riskParameter()) }
Expand Down Expand Up @@ -20501,6 +20508,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -20746,6 +20754,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -20992,6 +21001,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -21238,6 +21248,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -21483,6 +21494,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -21828,6 +21840,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -22079,6 +22092,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -22340,6 +22354,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -22601,6 +22616,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -22863,6 +22879,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -23125,6 +23142,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -23393,6 +23411,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -23662,6 +23681,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -23719,6 +23739,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -23776,6 +23797,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const marketParameter = { ...(await market.parameter()) }
Expand Down Expand Up @@ -23850,6 +23872,7 @@ describe('Market', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.20'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 14400,
})

const riskParameter = { ...(await market.riskParameter()) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ describe('MarketFactory', () => {
minEfficiency: parse6decimal('0.1'),
referralFee: parse6decimal('0.2'),
minScale: parse6decimal('0.001'),
maxStaleAfter: 3600,
}

it('updates the parameters', async () => {
Expand All @@ -353,6 +354,7 @@ describe('MarketFactory', () => {
expect(parameter.minEfficiency).to.equal(newParameter.minEfficiency)
expect(parameter.referralFee).to.equal(newParameter.referralFee)
expect(parameter.minScale).to.equal(newParameter.minScale)
expect(parameter.maxStaleAfter).to.equal(newParameter.maxStaleAfter)
})

it('reverts if not owner', async () => {
Expand Down
1 change: 1 addition & 0 deletions packages/perennial/test/unit/types/Global.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ function generateProtocolParameter(protocolFee: BigNumberish): ProtocolParameter
minEfficiency: 0,
referralFee: 0,
minScale: 0,
maxStaleAfter: 172800, // 2 days
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/perennial/test/unit/types/MarketParameter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const PROTOCOL_PARAMETER: ProtocolParameterStruct = {
minEfficiency: 0,
referralFee: 0,
minScale: parse6decimal('0.1'),
maxStaleAfter: 172800, // 2 days
}

describe('MarketParameter', () => {
Expand Down
23 changes: 23 additions & 0 deletions packages/perennial/test/unit/types/ProtocolParameter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const VALID_PROTOCOL_PARAMETER: ProtocolParameterStruct = {
minEfficiency: 8,
referralFee: 9,
minScale: 10,
maxStaleAfter: 11,
}

describe('ProtocolParameter', () => {
Expand All @@ -46,6 +47,7 @@ describe('ProtocolParameter', () => {
expect(value.minEfficiency).to.equal(8)
expect(value.referralFee).to.equal(9)
expect(value.minScale).to.equal(10)
expect(value.maxStaleAfter).to.equal(11)
})

context('.maxFee', async () => {
Expand Down Expand Up @@ -212,5 +214,26 @@ describe('ProtocolParameter', () => {
).to.be.revertedWithCustomError(protocolParameter, 'ProtocolParameterStorageInvalidError')
})
})

context('.maxStaleAfter', async () => {
const STORAGE_SIZE = 24
it('saves if in range', async () => {
await protocolParameter.validateAndStore({
...VALID_PROTOCOL_PARAMETER,
maxStaleAfter: BigNumber.from(2).pow(STORAGE_SIZE).sub(1),
})
const value = await protocolParameter.read()
expect(value.maxStaleAfter).to.equal(BigNumber.from(2).pow(STORAGE_SIZE).sub(1))
})

it('reverts if out of range', async () => {
await expect(
protocolParameter.validateAndStore({
...VALID_PROTOCOL_PARAMETER,
maxStaleAfter: BigNumber.from(2).pow(STORAGE_SIZE),
}),
).to.be.revertedWithCustomError(protocolParameter, 'ProtocolParameterStorageInvalidError')
})
})
})
})
Loading

0 comments on commit 4d7aeb8

Please sign in to comment.