-
Notifications
You must be signed in to change notification settings - Fork 13
/
MarketParameter.sol
167 lines (138 loc) · 7.4 KB
/
MarketParameter.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.13;
import "@equilibria/root/token/types/Token18.sol";
import "@equilibria/root/number/types/UFixed6.sol";
import "@equilibria/root/utilization/types/UJumpRateUtilizationCurve6.sol";
import "@equilibria/root/pid/types/PController6.sol";
import "../interfaces/IOracleProvider.sol";
import "../interfaces/IPayoffProvider.sol";
import "./ProtocolParameter.sol";
/// @dev MarketParameter type
struct MarketParameter {
/// @dev The fee that is taken out of funding
UFixed6 fundingFee;
/// @dev The fee that is taken out of interest
UFixed6 interestFee;
/// @dev The fee that is taken out of maker and taker fees
UFixed6 positionFee;
/// @dev The share of the collected fees that is paid to the oracle
UFixed6 oracleFee;
/// @dev The share of the collected fees that is paid to the risk coordinator
UFixed6 riskFee;
/// @dev The maximum amount of orders that can be pending at one time globally
uint256 maxPendingGlobal;
/// @dev The maximum amount of orders that can be pending at one time per account
uint256 maxPendingLocal;
/// @dev The rate at which the makers receives rewards (share / sec)
UFixed6 makerRewardRate;
/// @dev The rate at which the longs receives rewards (share / sec)
UFixed6 longRewardRate;
/// @dev The rate at which the shorts receives rewards (share / sec)
UFixed6 shortRewardRate;
/// @dev The fixed fee that is charge whenever an oracle request occurs
UFixed6 settlementFee;
/// @dev Whether longs and shorts can always close even when they'd put the market into socialization
bool takerCloseAlways;
/// @dev Whether makers can always close even when they'd put the market into socialization
bool makerCloseAlways;
/// @dev Whether the market is in close-only mode
bool closed;
}
struct MarketParameterStorage { uint256 slot0; uint256 slot1; }
using MarketParameterStorageLib for MarketParameterStorage global;
/// @dev Manually encodes and decodes the MarketParameter struct into storage.
///
/// struct StoredMarketParameter {
/// /* slot 0 */
/// uint24 fundingFee; // <= 1677%
/// uint24 interestFee; // <= 1677%
/// uint24 positionFee; // <= 1677%
/// uint24 oracleFee; // <= 1677%
/// uint24 riskFee; // <= 1677%
/// uint16 maxPendingGlobal; // <= 65k
/// uint16 maxPendingLocal; // <= 65k
/// uint48 settlementFee; // <= 281m
/// uint8 flags;
///
/// /* slot 1 */
/// uint40 makerRewardRate; // <= 281m / s
/// uint40 longRewardRate; // <= 281m / s
/// uint40 shortRewardRate; // <= 281m / s
/// }
///
library MarketParameterStorageLib {
error MarketParameterStorageInvalidError();
function read(MarketParameterStorage storage self) internal view returns (MarketParameter memory) {
(uint256 slot0, uint256 slot1) = (self.slot0, self.slot1);
uint256 flags = uint256(slot0) >> (256 - 8);
(bool takerCloseAlways, bool makerCloseAlways, bool closed) =
(flags & 0x01 == 0x01, flags & 0x02 == 0x02, flags & 0x04 == 0x04);
return MarketParameter(
UFixed6.wrap(uint256(slot0 << (256 - 24)) >> (256 - 24)),
UFixed6.wrap(uint256(slot0 << (256 - 24 - 24)) >> (256 - 24)),
UFixed6.wrap(uint256(slot0 << (256 - 24 - 24 - 24)) >> (256 - 24)),
UFixed6.wrap(uint256(slot0 << (256 - 24 - 24 - 24 - 24)) >> (256 - 24)),
UFixed6.wrap(uint256(slot0 << (256 - 24 - 24 - 24 - 24 - 24)) >> (256 - 24)),
uint256(slot0 << (256 - 24 - 24 - 24 - 24 - 24 - 16)) >> (256 - 16),
uint256(slot0 << (256 - 24 - 24 - 24 - 24 - 24 - 16 - 16)) >> (256 - 16),
UFixed6.wrap(uint256(slot1 << (256 - 40)) >> (256 - 40)),
UFixed6.wrap(uint256(slot1 << (256 - 40 - 40)) >> (256 - 40)),
UFixed6.wrap(uint256(slot1 << (256 - 40 - 40 - 40)) >> (256 - 40)),
UFixed6.wrap(uint256(slot0 << (256 - 24 - 24 - 24 - 24 - 24 - 16 - 16 - 48)) >> (256 - 48)),
takerCloseAlways,
makerCloseAlways,
closed
);
}
function validate(
MarketParameter memory self,
ProtocolParameter memory protocolParameter,
Token18 reward
) internal pure {
if (self.settlementFee.gt(protocolParameter.maxFeeAbsolute)) revert MarketParameterStorageInvalidError();
if (self.fundingFee.max(self.interestFee).max(self.positionFee).gt(protocolParameter.maxCut))
revert MarketParameterStorageInvalidError();
if (self.oracleFee.add(self.riskFee).gt(UFixed6Lib.ONE)) revert MarketParameterStorageInvalidError();
if (
reward.isZero() &&
(!self.makerRewardRate.isZero() || !self.longRewardRate.isZero() || !self.shortRewardRate.isZero())
) revert MarketParameterStorageInvalidError();
}
function validateAndStore(
MarketParameterStorage storage self,
MarketParameter memory newValue,
ProtocolParameter memory protocolParameter,
Token18 reward
) internal {
validate(newValue, protocolParameter, reward);
if (newValue.maxPendingGlobal > uint256(type(uint16).max)) revert MarketParameterStorageInvalidError();
if (newValue.maxPendingLocal > uint256(type(uint16).max)) revert MarketParameterStorageInvalidError();
if (newValue.makerRewardRate.gt(UFixed6.wrap(type(uint40).max))) revert MarketParameterStorageInvalidError();
if (newValue.longRewardRate.gt(UFixed6.wrap(type(uint40).max))) revert MarketParameterStorageInvalidError();
if (newValue.shortRewardRate.gt(UFixed6.wrap(type(uint40).max))) revert MarketParameterStorageInvalidError();
_store(self, newValue);
}
function _store(MarketParameterStorage storage self, MarketParameter memory newValue) internal {
uint256 flags = (newValue.takerCloseAlways ? 0x01 : 0x00) |
(newValue.makerCloseAlways ? 0x02 : 0x00) |
(newValue.closed ? 0x04 : 0x00);
uint256 encoded0 =
uint256(UFixed6.unwrap(newValue.fundingFee) << (256 - 24)) >> (256 - 24) |
uint256(UFixed6.unwrap(newValue.interestFee) << (256 - 24)) >> (256 - 24 - 24) |
uint256(UFixed6.unwrap(newValue.positionFee) << (256 - 24)) >> (256 - 24 - 24 - 24) |
uint256(UFixed6.unwrap(newValue.oracleFee) << (256 - 24)) >> (256 - 24 - 24 - 24 - 24) |
uint256(UFixed6.unwrap(newValue.riskFee) << (256 - 24)) >> (256 - 24 - 24 - 24 - 24 - 24) |
uint256(newValue.maxPendingGlobal << (256 - 16)) >> (256 - 24 - 24 - 24 - 24 - 24 - 16) |
uint256(newValue.maxPendingLocal << (256 - 16)) >> (256 - 24 - 24 - 24 - 24 - 24 - 16 - 16) |
uint256(UFixed6.unwrap(newValue.settlementFee) << (256 - 48)) >> (256 - 24 - 24 - 24 - 24 - 24 - 16 - 16 - 48) |
uint256(flags << (256 - 8)) >> (256 - 24 - 24 - 24 - 24 - 24 - 32 - 32 - 32 - 32 - 8);
uint256 encoded1 =
uint256(UFixed6.unwrap(newValue.makerRewardRate) << (256 - 40)) >> (256 - 40) |
uint256(UFixed6.unwrap(newValue.longRewardRate) << (256 - 40)) >> (256 - 40 - 40) |
uint256(UFixed6.unwrap(newValue.shortRewardRate) << (256 - 40)) >> (256 - 40 - 40 - 40);
assembly {
sstore(self.slot, encoded0)
sstore(add(self.slot, 1), encoded1)
}
}
}