-
Notifications
You must be signed in to change notification settings - Fork 15
/
Initialize.sol
280 lines (238 loc) · 10.6 KB
/
Initialize.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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
// SPDX-License-Identifier: MIT
pragma solidity 0.8.23;
import {IPool} from "@aave/interfaces/IPool.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {IWETH} from "@src/interfaces/IWETH.sol";
import {Math} from "@src/libraries/Math.sol";
import {CREDIT_POSITION_ID_START, DEBT_POSITION_ID_START} from "@src/libraries/LoanLibrary.sol";
import {PERCENT} from "@src/libraries/Math.sol";
import {IPriceFeed} from "@src/oracle/IPriceFeed.sol";
import {NonTransferrableScaledToken} from "@src/token/NonTransferrableScaledToken.sol";
import {NonTransferrableToken} from "@src/token/NonTransferrableToken.sol";
import {State} from "@src/SizeStorage.sol";
import {Errors} from "@src/libraries/Errors.sol";
import {Events} from "@src/libraries/Events.sol";
// See SizeStorage.sol for the definitions of the structs below
struct InitializeFeeConfigParams {
uint256 swapFeeAPR;
uint256 fragmentationFee;
uint256 liquidationRewardPercent;
uint256 overdueCollateralProtocolPercent;
uint256 collateralProtocolPercent;
address feeRecipient;
}
struct InitializeRiskConfigParams {
uint256 crOpening;
uint256 crLiquidation;
uint256 minimumCreditBorrowAToken;
uint256 borrowATokenCap;
uint256 minTenor;
uint256 maxTenor;
}
struct InitializeOracleParams {
address priceFeed;
uint64 variablePoolBorrowRateStaleRateInterval;
}
struct InitializeDataParams {
address weth;
address underlyingCollateralToken;
address underlyingBorrowToken;
address variablePool;
}
/// @title Initialize
/// @custom:security-contact [email protected]
/// @author Size (https://size.credit/)
/// @notice Contains the logic to initialize the protocol
/// @dev The collateralToken (e.g. szETH), borrowAToken (e.g. szaUSDC), and debtToken (e.g. szDebt) are created in the `executeInitialize` function
library Initialize {
/// @notice Validates the owner address
/// @param owner The owner address
function validateOwner(address owner) internal pure {
if (owner == address(0)) {
revert Errors.NULL_ADDRESS();
}
}
/// @notice Validates the parameters for the fee configuration
/// @param f The fee configuration parameters
function validateInitializeFeeConfigParams(InitializeFeeConfigParams memory f) internal pure {
// validate swapFeeAPR
// N/A
// validate fragmentationFee
// N/A
// validate liquidationRewardPercent
// N/A
// validate overdueCollateralProtocolPercent
if (f.overdueCollateralProtocolPercent > PERCENT) {
revert Errors.INVALID_COLLATERAL_PERCENTAGE_PREMIUM(f.overdueCollateralProtocolPercent);
}
// validate collateralProtocolPercent
if (f.collateralProtocolPercent > PERCENT) {
revert Errors.INVALID_COLLATERAL_PERCENTAGE_PREMIUM(f.collateralProtocolPercent);
}
// validate feeRecipient
if (f.feeRecipient == address(0)) {
revert Errors.NULL_ADDRESS();
}
}
/// @notice Validates the parameters for the risk configuration
/// @param r The risk configuration parameters
function validateInitializeRiskConfigParams(InitializeRiskConfigParams memory r) internal pure {
// validate crOpening
if (r.crOpening < PERCENT) {
revert Errors.INVALID_COLLATERAL_RATIO(r.crOpening);
}
// validate crLiquidation
if (r.crLiquidation < PERCENT) {
revert Errors.INVALID_COLLATERAL_RATIO(r.crLiquidation);
}
if (r.crOpening <= r.crLiquidation) {
revert Errors.INVALID_LIQUIDATION_COLLATERAL_RATIO(r.crOpening, r.crLiquidation);
}
// validate minimumCreditBorrowAToken
if (r.minimumCreditBorrowAToken == 0) {
revert Errors.NULL_AMOUNT();
}
// validate underlyingBorrowTokenCap
// N/A
// validate minTenor
if (r.minTenor == 0) {
revert Errors.NULL_AMOUNT();
}
if (r.maxTenor <= r.minTenor) {
revert Errors.INVALID_MAXIMUM_TENOR(r.maxTenor);
}
}
/// @notice Validates the parameters for the oracle configuration
/// @param o The oracle configuration parameters
function validateInitializeOracleParams(InitializeOracleParams memory o) internal view {
// validate priceFeed
if (o.priceFeed == address(0)) {
revert Errors.NULL_ADDRESS();
}
// slither-disable-next-line unused-return
IPriceFeed(o.priceFeed).getPrice();
// validate variablePoolBorrowRateStaleRateInterval
// N/A
}
/// @notice Validates the parameters for the data configuration
/// @param d The data configuration parameters
function validateInitializeDataParams(InitializeDataParams memory d) internal view {
// validate underlyingCollateralToken
if (d.underlyingCollateralToken == address(0)) {
revert Errors.NULL_ADDRESS();
}
if (IERC20Metadata(d.underlyingCollateralToken).decimals() > 18) {
revert Errors.INVALID_DECIMALS(IERC20Metadata(d.underlyingCollateralToken).decimals());
}
// validate underlyingBorrowToken
if (d.underlyingBorrowToken == address(0)) {
revert Errors.NULL_ADDRESS();
}
if (IERC20Metadata(d.underlyingBorrowToken).decimals() > 18) {
revert Errors.INVALID_DECIMALS(IERC20Metadata(d.underlyingBorrowToken).decimals());
}
// validate variablePool
if (d.variablePool == address(0)) {
revert Errors.NULL_ADDRESS();
}
}
/// @notice Validates the parameters for the initialization
/// @param owner The owner address
/// @param f The fee configuration parameters
/// @param r The risk configuration parameters
/// @param o The oracle configuration parameters
/// @param d The data configuration parameters
function validateInitialize(
State storage,
address owner,
InitializeFeeConfigParams memory f,
InitializeRiskConfigParams memory r,
InitializeOracleParams memory o,
InitializeDataParams memory d
) external view {
validateOwner(owner);
validateInitializeFeeConfigParams(f);
validateInitializeRiskConfigParams(r);
validateInitializeOracleParams(o);
validateInitializeDataParams(d);
}
/// @notice Executes the initialization of the fee configuration
/// @param state The state
/// @param f The fee configuration parameters
function executeInitializeFeeConfig(State storage state, InitializeFeeConfigParams memory f) internal {
state.feeConfig.swapFeeAPR = f.swapFeeAPR;
state.feeConfig.fragmentationFee = f.fragmentationFee;
state.feeConfig.liquidationRewardPercent = f.liquidationRewardPercent;
state.feeConfig.overdueCollateralProtocolPercent = f.overdueCollateralProtocolPercent;
state.feeConfig.collateralProtocolPercent = f.collateralProtocolPercent;
state.feeConfig.feeRecipient = f.feeRecipient;
}
/// @notice Executes the initialization of the risk configuration
/// @param state The state
/// @param r The risk configuration parameters
function executeInitializeRiskConfig(State storage state, InitializeRiskConfigParams memory r) internal {
state.riskConfig.crOpening = r.crOpening;
state.riskConfig.crLiquidation = r.crLiquidation;
state.riskConfig.minimumCreditBorrowAToken = r.minimumCreditBorrowAToken;
state.riskConfig.borrowATokenCap = r.borrowATokenCap;
state.riskConfig.minTenor = r.minTenor;
state.riskConfig.maxTenor = r.maxTenor;
}
/// @notice Executes the initialization of the oracle configuration
/// @param state The state
/// @param o The oracle configuration parameters
function executeInitializeOracle(State storage state, InitializeOracleParams memory o) internal {
state.oracle.priceFeed = IPriceFeed(o.priceFeed);
state.oracle.variablePoolBorrowRateStaleRateInterval = o.variablePoolBorrowRateStaleRateInterval;
}
/// @notice Executes the initialization of the data configuration
/// @param state The state
/// @param d The data configuration parameters
function executeInitializeData(State storage state, InitializeDataParams memory d) internal {
state.data.nextDebtPositionId = DEBT_POSITION_ID_START;
state.data.nextCreditPositionId = CREDIT_POSITION_ID_START;
state.data.weth = IWETH(d.weth);
state.data.underlyingCollateralToken = IERC20Metadata(d.underlyingCollateralToken);
state.data.underlyingBorrowToken = IERC20Metadata(d.underlyingBorrowToken);
state.data.variablePool = IPool(d.variablePool);
state.data.collateralToken = new NonTransferrableToken(
address(this),
string.concat("Size ", IERC20Metadata(state.data.underlyingCollateralToken).name()),
string.concat("sz", IERC20Metadata(state.data.underlyingCollateralToken).symbol()),
IERC20Metadata(state.data.underlyingCollateralToken).decimals()
);
state.data.borrowAToken = new NonTransferrableScaledToken(
state.data.variablePool,
state.data.underlyingBorrowToken,
address(this),
string.concat("Size Scaled ", IERC20Metadata(state.data.underlyingBorrowToken).name()),
string.concat("sza", IERC20Metadata(state.data.underlyingBorrowToken).symbol()),
IERC20Metadata(state.data.underlyingBorrowToken).decimals()
);
state.data.debtToken = new NonTransferrableToken(
address(this),
string.concat("Size Debt ", IERC20Metadata(state.data.underlyingBorrowToken).name()),
string.concat("szDebt", IERC20Metadata(state.data.underlyingBorrowToken).symbol()),
IERC20Metadata(state.data.underlyingBorrowToken).decimals()
);
}
/// @notice Executes the initialization of the protocol
/// @param state The state
/// @param f The fee configuration parameters
/// @param r The risk configuration parameters
/// @param o The oracle configuration parameters
/// @param d The data configuration parameters
function executeInitialize(
State storage state,
InitializeFeeConfigParams memory f,
InitializeRiskConfigParams memory r,
InitializeOracleParams memory o,
InitializeDataParams memory d
) external {
executeInitializeFeeConfig(state, f);
executeInitializeRiskConfig(state, r);
executeInitializeOracle(state, o);
executeInitializeData(state, d);
emit Events.Initialize(f, r, o, d);
}
}