-
Notifications
You must be signed in to change notification settings - Fork 15
/
MarketState.sol
144 lines (130 loc) · 4.8 KB
/
MarketState.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
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.20;
import { AuthRole } from '../interfaces/WildcatStructsAndEnums.sol';
import './MathUtils.sol';
import './SafeCastLib.sol';
import './FeeMath.sol';
using MarketStateLib for MarketState global;
using MarketStateLib for Account global;
using FeeMath for MarketState global;
struct MarketState {
bool isClosed;
uint128 maxTotalSupply;
uint128 accruedProtocolFees;
// Underlying assets reserved for withdrawals which have been paid
// by the borrower but not yet executed.
uint128 normalizedUnclaimedWithdrawals;
// Scaled token supply (divided by scaleFactor)
uint104 scaledTotalSupply;
// Scaled token amount in withdrawal batches that have not been
// paid by borrower yet.
uint104 scaledPendingWithdrawals;
uint32 pendingWithdrawalExpiry;
// Whether market is currently delinquent (liquidity under requirement)
bool isDelinquent;
// Seconds borrower has been delinquent
uint32 timeDelinquent;
// Annual interest rate accrued to lenders, in basis points
uint16 annualInterestBips;
// Percentage of outstanding balance that must be held in liquid reserves
uint16 reserveRatioBips;
// Ratio between internal balances and underlying token amounts
uint112 scaleFactor;
uint32 lastInterestAccruedTimestamp;
}
struct Account {
AuthRole approval;
uint104 scaledBalance;
}
library MarketStateLib {
using MathUtils for uint256;
using SafeCastLib for uint256;
/**
* @dev Returns the normalized total supply of the market.
*/
function totalSupply(MarketState memory state) internal pure returns (uint256) {
return state.normalizeAmount(state.scaledTotalSupply);
}
/**
* @dev Returns the maximum amount of tokens that can be deposited without
* reaching the maximum total supply.
*/
function maximumDeposit(MarketState memory state) internal pure returns (uint256) {
return uint256(state.maxTotalSupply).satSub(state.totalSupply());
}
/**
* @dev Normalize an amount of scaled tokens using the current scale factor.
*/
function normalizeAmount(
MarketState memory state,
uint256 amount
) internal pure returns (uint256) {
return amount.rayMul(state.scaleFactor);
}
/**
* @dev Scale an amount of normalized tokens using the current scale factor.
*/
function scaleAmount(MarketState memory state, uint256 amount) internal pure returns (uint256) {
return amount.rayDiv(state.scaleFactor);
}
/**
* @dev Collateralization requirement is:
* - 100% of all pending (unpaid) withdrawals
* - 100% of all unclaimed (paid) withdrawals
* - reserve ratio times the outstanding debt (supply - pending withdrawals)
* - accrued protocol fees
*/
function liquidityRequired(
MarketState memory state
) internal pure returns (uint256 _liquidityRequired) {
uint256 scaledWithdrawals = state.scaledPendingWithdrawals;
uint256 scaledRequiredReserves = (state.scaledTotalSupply - scaledWithdrawals).bipMul(
state.reserveRatioBips
) + scaledWithdrawals;
return
state.normalizeAmount(scaledRequiredReserves) +
state.accruedProtocolFees +
state.normalizedUnclaimedWithdrawals;
}
/**
* @dev Returns the amount of underlying assets that can be withdrawn
* for protocol fees. The only debts with higher priority are
* processed withdrawals that have not been executed.
*/
function withdrawableProtocolFees(
MarketState memory state,
uint256 totalAssets
) internal pure returns (uint128) {
uint256 totalAvailableAssets = totalAssets - state.normalizedUnclaimedWithdrawals;
return uint128(MathUtils.min(totalAvailableAssets, state.accruedProtocolFees));
}
/**
* @dev Returns the amount of underlying assets that can be borrowed.
*
* The borrower must maintain sufficient assets in the market to
* cover 100% of pending withdrawals, 100% of previously processed
* withdrawals (before they are executed), and the reserve ratio
* times the outstanding debt (deposits not pending withdrawal).
*
* Any underlying assets in the market above this amount can be borrowed.
*/
function borrowableAssets(
MarketState memory state,
uint256 totalAssets
) internal pure returns (uint256) {
return totalAssets.satSub(state.liquidityRequired());
}
function hasPendingExpiredBatch(MarketState memory state) internal view returns (bool result) {
uint256 expiry = state.pendingWithdrawalExpiry;
assembly {
// Equivalent to expiry > 0 && expiry <= block.timestamp
result := gt(timestamp(), sub(expiry, 1))
}
}
function totalDebts(MarketState memory state) internal pure returns (uint256) {
return
state.normalizeAmount(state.scaledTotalSupply) +
state.normalizedUnclaimedWithdrawals +
state.accruedProtocolFees;
}
}