@@ -18,6 +18,7 @@ import "./interfaces/IEtherCollateral.sol";
18
18
import "./interfaces/IEtherCollateralsUSD.sol " ;
19
19
import "./interfaces/IERC20.sol " ;
20
20
import "./interfaces/ICollateralManager.sol " ;
21
+ import "./interfaces/IEtherWrapper.sol " ;
21
22
22
23
// https://docs.synthetix.io/contracts/source/contracts/debtcache
23
24
contract BaseDebtCache is Owned , MixinSystemSettings , IDebtCache {
@@ -43,21 +44,23 @@ contract BaseDebtCache is Owned, MixinSystemSettings, IDebtCache {
43
44
bytes32 private constant CONTRACT_ETHERCOLLATERAL = "EtherCollateral " ;
44
45
bytes32 private constant CONTRACT_ETHERCOLLATERAL_SUSD = "EtherCollateralsUSD " ;
45
46
bytes32 private constant CONTRACT_COLLATERALMANAGER = "CollateralManager " ;
47
+ bytes32 private constant CONTRACT_ETHER_WRAPPER = "EtherWrapper " ;
46
48
47
49
constructor (address _owner , address _resolver ) public Owned (_owner) MixinSystemSettings (_resolver) {}
48
50
49
51
/* ========== VIEWS ========== */
50
52
51
53
function resolverAddressesRequired () public view returns (bytes32 [] memory addresses ) {
52
54
bytes32 [] memory existingAddresses = MixinSystemSettings.resolverAddressesRequired ();
53
- bytes32 [] memory newAddresses = new bytes32 [](7 );
55
+ bytes32 [] memory newAddresses = new bytes32 [](8 );
54
56
newAddresses[0 ] = CONTRACT_ISSUER;
55
57
newAddresses[1 ] = CONTRACT_EXCHANGER;
56
58
newAddresses[2 ] = CONTRACT_EXRATES;
57
59
newAddresses[3 ] = CONTRACT_SYSTEMSTATUS;
58
60
newAddresses[4 ] = CONTRACT_ETHERCOLLATERAL;
59
61
newAddresses[5 ] = CONTRACT_ETHERCOLLATERAL_SUSD;
60
62
newAddresses[6 ] = CONTRACT_COLLATERALMANAGER;
63
+ newAddresses[7 ] = CONTRACT_ETHER_WRAPPER;
61
64
addresses = combineArrays (existingAddresses, newAddresses);
62
65
}
63
66
@@ -89,6 +92,10 @@ contract BaseDebtCache is Owned, MixinSystemSettings, IDebtCache {
89
92
return ICollateralManager (requireAndGetAddress (CONTRACT_COLLATERALMANAGER));
90
93
}
91
94
95
+ function etherWrapper () internal view returns (IEtherWrapper) {
96
+ return IEtherWrapper (requireAndGetAddress (CONTRACT_ETHER_WRAPPER));
97
+ }
98
+
92
99
function debtSnapshotStaleTime () external view returns (uint ) {
93
100
return getDebtSnapshotStaleTime ();
94
101
}
@@ -120,59 +127,48 @@ contract BaseDebtCache is Owned, MixinSystemSettings, IDebtCache {
120
127
return _cacheStale (_cacheTimestamp);
121
128
}
122
129
123
- function _issuedSynthValues (bytes32 [] memory currencyKeys , uint [] memory rates ) internal view returns (uint [] memory ) {
130
+ function _issuedSynthValues (bytes32 [] memory currencyKeys , uint [] memory rates )
131
+ internal
132
+ view
133
+ returns (uint [] memory values )
134
+ {
124
135
uint numValues = currencyKeys.length ;
125
- uint [] memory values = new uint [](numValues);
136
+ values = new uint [](numValues);
126
137
ISynth[] memory synths = issuer ().getSynths (currencyKeys);
127
138
128
139
for (uint i = 0 ; i < numValues; i++ ) {
129
- bytes32 key = currencyKeys[i];
130
140
address synthAddress = address (synths[i]);
131
141
require (synthAddress != address (0 ), "Synth does not exist " );
132
142
uint supply = IERC20 (synthAddress).totalSupply ();
133
-
134
- if (collateralManager ().isSynthManaged (key)) {
135
- uint collateralIssued = collateralManager ().long (key);
136
-
137
- // this is an edge case --
138
- // if a synth other than sUSD is only issued by non SNX collateral
139
- // the long value will exceed the supply if there was a minting fee,
140
- // so we check explicitly and 0 it out to prevent
141
- // a safesub overflow.
142
-
143
- if (collateralIssued > supply) {
144
- supply = 0 ;
145
- } else {
146
- supply = supply.sub (collateralIssued);
147
- }
148
- }
149
-
150
- bool isSUSD = key == sUSD;
151
- if (isSUSD || key == sETH) {
152
- IEtherCollateral etherCollateralContract =
153
- isSUSD ? IEtherCollateral (address (etherCollateralsUSD ())) : etherCollateral ();
154
- uint etherCollateralSupply = etherCollateralContract.totalIssuedSynths ();
155
- supply = supply.sub (etherCollateralSupply);
156
- }
157
-
158
143
values[i] = supply.multiplyDecimalRound (rates[i]);
159
144
}
160
- return values;
145
+
146
+ return (values);
161
147
}
162
148
163
149
function _currentSynthDebts (bytes32 [] memory currencyKeys )
164
150
internal
165
151
view
166
- returns (uint [] memory snxIssuedDebts , bool anyRateIsInvalid )
152
+ returns (
153
+ uint [] memory snxIssuedDebts ,
154
+ uint _excludedDebt ,
155
+ bool anyRateIsInvalid
156
+ )
167
157
{
168
158
(uint [] memory rates , bool isInvalid ) = exchangeRates ().ratesAndInvalidForCurrencies (currencyKeys);
169
- return (_issuedSynthValues (currencyKeys, rates), isInvalid);
159
+ uint [] memory values = _issuedSynthValues (currencyKeys, rates);
160
+ (uint excludedDebt , bool isAnyNonSnxDebtRateInvalid ) = _totalNonSnxBackedDebt ();
161
+ return (values, excludedDebt, isInvalid || isAnyNonSnxDebtRateInvalid);
170
162
}
171
163
172
164
function currentSynthDebts (bytes32 [] calldata currencyKeys )
173
165
external
174
166
view
175
- returns (uint [] memory debtValues , bool anyRateIsInvalid )
167
+ returns (
168
+ uint [] memory debtValues ,
169
+ uint excludedDebt ,
170
+ bool anyRateIsInvalid
171
+ )
176
172
{
177
173
return _currentSynthDebts (currencyKeys);
178
174
}
@@ -190,22 +186,53 @@ contract BaseDebtCache is Owned, MixinSystemSettings, IDebtCache {
190
186
return _cachedSynthDebts (currencyKeys);
191
187
}
192
188
189
+ // Returns the total sUSD debt backed by non-SNX collateral.
190
+ function totalNonSnxBackedDebt () external view returns (uint excludedDebt , bool isInvalid ) {
191
+ return _totalNonSnxBackedDebt ();
192
+ }
193
+
194
+ function _totalNonSnxBackedDebt () internal view returns (uint excludedDebt , bool isInvalid ) {
195
+ // Calculate excluded debt.
196
+ // 1. Ether Collateral.
197
+ excludedDebt = excludedDebt.add (etherCollateralsUSD ().totalIssuedSynths ()); // Ether-backed sUSD
198
+
199
+ uint etherCollateralTotalIssuedSynths = etherCollateral ().totalIssuedSynths ();
200
+ // We check the supply > 0 as on L2, we may not yet have up-to-date rates for sETH.
201
+ if (etherCollateralTotalIssuedSynths > 0 ) {
202
+ (uint sETHRate , bool sETHRateIsInvalid ) = exchangeRates ().rateAndInvalid (sETH);
203
+ isInvalid = isInvalid || sETHRateIsInvalid;
204
+ excludedDebt = excludedDebt.add (etherCollateralTotalIssuedSynths.multiplyDecimalRound (sETHRate)); // Ether-backed sETH
205
+ }
206
+
207
+ // 2. MultiCollateral long debt + short debt.
208
+ (uint longValue , bool anyTotalLongRateIsInvalid ) = collateralManager ().totalLong ();
209
+ (uint shortValue , bool anyTotalShortRateIsInvalid ) = collateralManager ().totalShort ();
210
+ isInvalid = isInvalid || anyTotalLongRateIsInvalid || anyTotalShortRateIsInvalid;
211
+ excludedDebt = excludedDebt.add (longValue).add (shortValue);
212
+
213
+ // 3. EtherWrapper.
214
+ // Subtract sETH and sUSD issued by EtherWrapper.
215
+ excludedDebt = excludedDebt.add (etherWrapper ().totalIssuedSynths ());
216
+
217
+ return (excludedDebt, isInvalid);
218
+ }
219
+
193
220
function _currentDebt () internal view returns (uint debt , bool anyRateIsInvalid ) {
194
- (uint [] memory values , bool isInvalid ) = _currentSynthDebts (issuer ().availableCurrencyKeys ());
221
+ bytes32 [] memory currencyKeys = issuer ().availableCurrencyKeys ();
222
+ (uint [] memory rates , bool isInvalid ) = exchangeRates ().ratesAndInvalidForCurrencies (currencyKeys);
223
+
224
+ // Sum all issued synth values based on their supply.
225
+ uint [] memory values = _issuedSynthValues (currencyKeys, rates);
226
+ (uint excludedDebt , bool isAnyNonSnxDebtRateInvalid ) = _totalNonSnxBackedDebt ();
227
+
195
228
uint numValues = values.length ;
196
229
uint total;
197
230
for (uint i; i < numValues; i++ ) {
198
231
total = total.add (values[i]);
199
232
}
233
+ total = total < excludedDebt ? 0 : total.sub (excludedDebt);
200
234
201
- // subtract the USD value of all shorts.
202
- (uint susdValue , bool shortInvalid ) = collateralManager ().totalShort ();
203
-
204
- total = total.sub (susdValue);
205
-
206
- isInvalid = isInvalid || shortInvalid;
207
-
208
- return (total, isInvalid);
235
+ return (total, isInvalid || isAnyNonSnxDebtRateInvalid);
209
236
}
210
237
211
238
function currentDebt () external view returns (uint debt , bool anyRateIsInvalid ) {
0 commit comments