Skip to content

Commit 8288a47

Browse files
author
justin j. moses
authored
Sip 44: System and synth disabling (Synthetixio#469)
1 parent 7151f8f commit 8288a47

40 files changed

+3143
-2229
lines changed

.solcover.js

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
module.exports = {
2-
port: 8545,
3-
skipFiles: ['test-helpers/PublicSafeDecimalMath.sol', 'test-helpers/PublicMath.sol'],
4-
client: require('ganache-cli'), // use ganache-cli version listed in dev deps
5-
providerOptions: {
6-
default_balance_ether: 10000000000000, // extra zero just in case (coverage consumes more gas)
7-
time: new Date("2019-03-06T00:00:00"),
8-
network_id: 55
9-
},
10-
mocha: {
11-
grep: "@cov-skip", // Find everything with this tag
12-
invert: true // Run the grep's inverse set.
13-
}
2+
port: 8545,
3+
skipFiles: ['test-helpers'],
4+
client: require('ganache-cli'), // use ganache-cli version listed in dev deps
5+
providerOptions: {
6+
default_balance_ether: 10000000000000, // extra zero just in case (coverage consumes more gas)
7+
time: new Date('2019-03-06T00:00:00'),
8+
network_id: 55,
9+
},
10+
mocha: {
11+
grep: '@cov-skip', // Find everything with this tag
12+
invert: true, // Run the grep's inverse set.
13+
},
1414
};

contracts/DappMaintenance.sol

-31
This file was deleted.

contracts/EtherCollateral.sol

+11-2
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import "openzeppelin-solidity/contracts/utils/ReentrancyGuard.sol";
44
import "./Owned.sol";
55
import "./Pausable.sol";
66
import "./SafeDecimalMath.sol";
7+
import "./interfaces/ISystemStatus.sol";
78
import "./interfaces/IFeePool.sol";
89
import "./interfaces/ISynth.sol";
910
import "./interfaces/IERC20.sol";
1011
import "./interfaces/IDepot.sol";
1112
import "./MixinResolver.sol";
1213

13-
1414
// https://docs.synthetix.io/contracts/EtherCollateral # TODO
1515
contract EtherCollateral is Owned, Pausable, ReentrancyGuard, MixinResolver {
1616
using SafeMath for uint256;
@@ -88,11 +88,12 @@ contract EtherCollateral is Owned, Pausable, ReentrancyGuard, MixinResolver {
8888

8989
/* ========== ADDRESS RESOLVER CONFIGURATION ========== */
9090

91+
bytes32 private constant CONTRACT_SYSTEMSTATUS = "SystemStatus";
9192
bytes32 private constant CONTRACT_SYNTHSETH = "SynthsETH";
9293
bytes32 private constant CONTRACT_SYNTHSUSD = "SynthsUSD";
9394
bytes32 private constant CONTRACT_DEPOT = "Depot";
9495

95-
bytes32[24] private addressesToCache = [CONTRACT_SYNTHSETH, CONTRACT_SYNTHSUSD, CONTRACT_DEPOT];
96+
bytes32[24] private addressesToCache = [CONTRACT_SYSTEMSTATUS, CONTRACT_SYNTHSETH, CONTRACT_SYNTHSUSD, CONTRACT_DEPOT];
9697

9798
// ========== CONSTRUCTOR ==========
9899
constructor(address _owner, address _resolver)
@@ -277,6 +278,8 @@ contract EtherCollateral is Owned, Pausable, ReentrancyGuard, MixinResolver {
277278
// ========== PUBLIC FUNCTIONS ==========
278279

279280
function openLoan() external payable notPaused nonReentrant returns (uint256 loanID) {
281+
systemStatus().requireIssuanceActive();
282+
280283
// Require ETH sent to be greater than minLoanSize
281284
require(msg.value >= minLoanSize, "Not enough ETH to create this loan. Please see the minLoanSize");
282285

@@ -334,6 +337,8 @@ contract EtherCollateral is Owned, Pausable, ReentrancyGuard, MixinResolver {
334337
// ========== PRIVATE FUNCTIONS ==========
335338

336339
function _closeLoan(address account, uint256 loanID) private {
340+
systemStatus().requireIssuanceActive();
341+
337342
// Get the loan from storage
338343
synthLoanStruct memory synthLoan = _getLoanFromStorage(account, loanID);
339344

@@ -417,6 +422,10 @@ contract EtherCollateral is Owned, Pausable, ReentrancyGuard, MixinResolver {
417422

418423
/* ========== INTERNAL VIEWS ========== */
419424

425+
function systemStatus() internal view returns (ISystemStatus) {
426+
return ISystemStatus(requireAndGetAddress(CONTRACT_SYSTEMSTATUS, "Missing SystemStatus address"));
427+
}
428+
420429
function synthsETH() internal view returns (ISynth) {
421430
return ISynth(requireAndGetAddress(CONTRACT_SYNTHSETH, "Missing SynthsETH address"));
422431
}

contracts/Exchanger.sol

+10-9
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,26 @@ import "./interfaces/IFeePool.sol";
1010
import "./interfaces/IIssuer.sol";
1111
import "./interfaces/IDelegateApprovals.sol";
1212

13-
1413
// https://docs.synthetix.io/contracts/Exchanger
1514
contract Exchanger is MixinResolver {
1615
using SafeMath for uint;
1716
using SafeDecimalMath for uint;
1817

19-
bool public exchangeEnabled;
20-
2118
bytes32 private constant sUSD = "sUSD";
2219

2320
uint public waitingPeriodSecs;
2421

2522
/* ========== ADDRESS RESOLVER CONFIGURATION ========== */
2623

24+
bytes32 private constant CONTRACT_SYSTEMSTATUS = "SystemStatus";
2725
bytes32 private constant CONTRACT_EXCHANGESTATE = "ExchangeState";
2826
bytes32 private constant CONTRACT_EXRATES = "ExchangeRates";
2927
bytes32 private constant CONTRACT_SYNTHETIX = "Synthetix";
3028
bytes32 private constant CONTRACT_FEEPOOL = "FeePool";
3129
bytes32 private constant CONTRACT_DELEGATEAPPROVALS = "DelegateApprovals";
3230

3331
bytes32[24] private addressesToCache = [
32+
CONTRACT_SYSTEMSTATUS,
3433
CONTRACT_EXCHANGESTATE,
3534
CONTRACT_EXRATES,
3635
CONTRACT_SYNTHETIX,
@@ -39,12 +38,15 @@ contract Exchanger is MixinResolver {
3938
];
4039

4140
constructor(address _owner, address _resolver) public MixinResolver(_owner, _resolver, addressesToCache) {
42-
exchangeEnabled = true;
4341
waitingPeriodSecs = 3 minutes;
4442
}
4543

4644
/* ========== VIEWS ========== */
4745

46+
function systemStatus() internal view returns (ISystemStatus) {
47+
return ISystemStatus(requireAndGetAddress(CONTRACT_SYSTEMSTATUS, "Missing SystemStatus address"));
48+
}
49+
4850
function exchangeState() internal view returns (IExchangeState) {
4951
return IExchangeState(requireAndGetAddress(CONTRACT_EXCHANGESTATE, "Missing ExchangeState address"));
5052
}
@@ -127,10 +129,6 @@ contract Exchanger is MixinResolver {
127129
waitingPeriodSecs = _waitingPeriodSecs;
128130
}
129131

130-
function setExchangeEnabled(bool _exchangeEnabled) external onlyOwner {
131-
exchangeEnabled = _exchangeEnabled;
132-
}
133-
134132
function calculateAmountAfterSettlement(address from, bytes32 currencyKey, uint amount, uint refunded)
135133
public
136134
view
@@ -195,7 +193,6 @@ contract Exchanger is MixinResolver {
195193
{
196194
require(sourceCurrencyKey != destinationCurrencyKey, "Can't be same synth");
197195
require(sourceAmount > 0, "Zero amount");
198-
require(exchangeEnabled, "Exchanging is disabled");
199196

200197
(, uint refunded, uint numEntriesSettled) = _internalSettle(from, sourceCurrencyKey);
201198

@@ -269,6 +266,10 @@ contract Exchanger is MixinResolver {
269266
{
270267
// Note: this function can be called by anyone on behalf of anyone else
271268

269+
systemStatus().requireExchangeActive();
270+
271+
systemStatus().requireSynthActive(currencyKey);
272+
272273
return _internalSettle(from, currencyKey);
273274
}
274275

contracts/FeePool.sol

+34-29
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import "./SelfDestructible.sol";
55
import "./SafeDecimalMath.sol";
66
import "./MixinResolver.sol";
77
import "./Synthetix.sol";
8+
import "./interfaces/ISystemStatus.sol";
89
import "./interfaces/ISynthetixEscrow.sol";
910
import "./interfaces/IExchangeRates.sol";
1011
import "./interfaces/ISynthetixState.sol";
@@ -16,7 +17,6 @@ import "./FeePoolState.sol";
1617
import "./FeePoolEternalStorage.sol";
1718
import "./DelegateApprovals.sol";
1819

19-
2020
// https://docs.synthetix.io/contracts/FeePool
2121
contract FeePool is Proxyable, SelfDestructible, LimitedSetup, MixinResolver {
2222
using SafeMath for uint;
@@ -69,6 +69,7 @@ contract FeePool is Proxyable, SelfDestructible, LimitedSetup, MixinResolver {
6969

7070
/* ========== ADDRESS RESOLVER CONFIGURATION ========== */
7171

72+
bytes32 private constant CONTRACT_SYSTEMSTATUS = "SystemStatus";
7273
bytes32 private constant CONTRACT_EXRATES = "ExchangeRates";
7374
bytes32 private constant CONTRACT_SYNTHETIX = "Synthetix";
7475
bytes32 private constant CONTRACT_FEEPOOLSTATE = "FeePoolState";
@@ -80,6 +81,7 @@ contract FeePool is Proxyable, SelfDestructible, LimitedSetup, MixinResolver {
8081
bytes32 private constant CONTRACT_DELEGATEAPPROVALS = "DelegateApprovals";
8182

8283
bytes32[24] private addressesToCache = [
84+
CONTRACT_SYSTEMSTATUS,
8385
CONTRACT_EXRATES,
8486
CONTRACT_SYNTHETIX,
8587
CONTRACT_FEEPOOLSTATE,
@@ -114,6 +116,10 @@ contract FeePool is Proxyable, SelfDestructible, LimitedSetup, MixinResolver {
114116

115117
/* ========== VIEWS ========== */
116118

119+
function systemStatus() internal view returns (ISystemStatus) {
120+
return ISystemStatus(requireAndGetAddress(CONTRACT_SYSTEMSTATUS, "Missing SystemStatus address"));
121+
}
122+
117123
function synthetix() internal view returns (ISynthetix) {
118124
return ISynthetix(requireAndGetAddress(CONTRACT_SYNTHETIX, "Missing Synthetix address"));
119125
}
@@ -251,6 +257,8 @@ contract FeePool is Proxyable, SelfDestructible, LimitedSetup, MixinResolver {
251257
function closeCurrentFeePeriod() external {
252258
require(_recentFeePeriodsStorage(0).startTime <= (now - feePeriodDuration), "Too early to close fee period");
253259

260+
systemStatus().requireIssuanceActive();
261+
254262
FeePeriod storage secondLastFeePeriod = _recentFeePeriodsStorage(FEE_PERIOD_LENGTH - 2);
255263
FeePeriod storage lastFeePeriod = _recentFeePeriodsStorage(FEE_PERIOD_LENGTH - 1);
256264

@@ -284,25 +292,27 @@ contract FeePool is Proxyable, SelfDestructible, LimitedSetup, MixinResolver {
284292
}
285293

286294
/**
287-
* @notice Claim fees for last period when available or not already withdrawn.
288-
*/
295+
* @notice Claim fees for last period when available or not already withdrawn.
296+
*/
289297
function claimFees() external optionalProxy returns (bool) {
290298
return _claimFees(messageSender);
291299
}
292300

293301
/**
294-
* @notice Delegated claimFees(). Call from the deletegated address
295-
* and the fees will be sent to the claimingForAddress.
296-
* approveClaimOnBehalf() must be called first to approve the deletage address
297-
* @param claimingForAddress The account you are claiming fees for
298-
*/
302+
* @notice Delegated claimFees(). Call from the deletegated address
303+
* and the fees will be sent to the claimingForAddress.
304+
* approveClaimOnBehalf() must be called first to approve the deletage address
305+
* @param claimingForAddress The account you are claiming fees for
306+
*/
299307
function claimOnBehalf(address claimingForAddress) external optionalProxy returns (bool) {
300308
require(delegateApprovals().canClaimFor(claimingForAddress, messageSender), "Not approved to claim on behalf");
301309

302310
return _claimFees(claimingForAddress);
303311
}
304312

305313
function _claimFees(address claimingAddress) internal returns (bool) {
314+
systemStatus().requireIssuanceActive();
315+
306316
uint rewardsPaid = 0;
307317
uint feesPaid = 0;
308318
uint availableFees;
@@ -345,8 +355,8 @@ contract FeePool is Proxyable, SelfDestructible, LimitedSetup, MixinResolver {
345355
}
346356

347357
/**
348-
* @notice Admin function to import the FeePeriod data from the previous contract
349-
*/
358+
* @notice Admin function to import the FeePeriod data from the previous contract
359+
*/
350360
function importFeePeriod(
351361
uint feePeriodIndex,
352362
uint feePeriodId,
@@ -371,10 +381,10 @@ contract FeePool is Proxyable, SelfDestructible, LimitedSetup, MixinResolver {
371381
}
372382

373383
/**
374-
* @notice Owner can escrow SNX. Owner to send the tokens to the RewardEscrow
375-
* @param account Address to escrow tokens for
376-
* @param quantity Amount of tokens to escrow
377-
*/
384+
* @notice Owner can escrow SNX. Owner to send the tokens to the RewardEscrow
385+
* @param account Address to escrow tokens for
386+
* @param quantity Amount of tokens to escrow
387+
*/
378388
function appendVestingEntry(address account, uint quantity) public optionalProxy_onlyOwner {
379389
// Transfer SNX from messageSender to the Reward Escrow
380390
synthetix().transferFrom(messageSender, rewardEscrow(), quantity);
@@ -462,10 +472,10 @@ contract FeePool is Proxyable, SelfDestructible, LimitedSetup, MixinResolver {
462472
}
463473

464474
/**
465-
* @notice Send the fees to claiming address.
466-
* @param account The address to send the fees to.
467-
* @param sUSDAmount The amount of fees priced in sUSD.
468-
*/
475+
* @notice Send the fees to claiming address.
476+
* @param account The address to send the fees to.
477+
* @param sUSDAmount The amount of fees priced in sUSD.
478+
*/
469479
function _payFees(address account, uint sUSDAmount) internal notFeeAddress(account) {
470480
// Checks not really possible but rather gaurds for the internal code.
471481
require(
@@ -491,10 +501,10 @@ contract FeePool is Proxyable, SelfDestructible, LimitedSetup, MixinResolver {
491501
}
492502

493503
/**
494-
* @notice Send the rewards to claiming address - will be locked in rewardEscrow.
495-
* @param account The address to send the fees to.
496-
* @param snxAmount The amount of SNX.
497-
*/
504+
* @notice Send the rewards to claiming address - will be locked in rewardEscrow.
505+
* @param account The address to send the fees to.
506+
* @param snxAmount The amount of SNX.
507+
*/
498508
function _payRewards(address account, uint snxAmount) internal notFeeAddress(account) {
499509
require(account != address(0), "Account can't be 0");
500510
require(account != address(this), "Can't send rewards to fee pool");
@@ -753,8 +763,8 @@ contract FeePool is Proxyable, SelfDestructible, LimitedSetup, MixinResolver {
753763
}
754764

755765
/**
756-
* @notice Calculate the collateral ratio before user is blocked from claiming.
757-
*/
766+
* @notice Calculate the collateral ratio before user is blocked from claiming.
767+
*/
758768
function getPenaltyThresholdRatio() public view returns (uint) {
759769
uint targetRatio = synthetixState().issuanceRatio();
760770

@@ -787,11 +797,6 @@ contract FeePool is Proxyable, SelfDestructible, LimitedSetup, MixinResolver {
787797
_;
788798
}
789799

790-
modifier onlyExchanger {
791-
require(msg.sender == address(exchanger()), "FeePool: Only Exchanger Authorised");
792-
_;
793-
}
794-
795800
modifier notFeeAddress(address account) {
796801
require(account != FEE_ADDRESS, "Fee address not allowed");
797802
_;

contracts/Issuer.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ contract Issuer is MixinResolver {
224224

225225
/**
226226
* @notice Store in the FeePool the users current debt value in the system.
227-
* @dev debtBalanceOf(messageSender, "sUSD") to be used with totalIssuedSynthsExcludeEtherCollateral("sUSD") to get
227+
* @dev debtBalanceOf(messageSender, "sUSD") to be used with totalIssuedSynthsExcludeEtherCollateral("sUSD") to get
228228
* users % of the system within a feePeriod.
229229
*/
230230
function _appendAccountIssuanceRecord(address from) internal {

contracts/Math.sol

+5-5
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ library Math {
99
using SafeDecimalMath for uint;
1010

1111
/**
12-
* @dev Uses "exponentiation by squaring" algorithm where cost is 0(logN)
13-
* vs 0(N) for naive repeated multiplication.
14-
* Calculates x^n with x as fixed-point and n as regular unsigned int.
15-
* Calculates to 18 digits of precision with SafeDecimalMath.unit()
16-
*/
12+
* @dev Uses "exponentiation by squaring" algorithm where cost is 0(logN)
13+
* vs 0(N) for naive repeated multiplication.
14+
* Calculates x^n with x as fixed-point and n as regular unsigned int.
15+
* Calculates to 18 digits of precision with SafeDecimalMath.unit()
16+
*/
1717
function powDecimal(uint x, uint n) internal pure returns (uint) {
1818
// https://mpark.github.io/programming/2014/08/18/exponentiation-by-squaring/
1919

0 commit comments

Comments
 (0)