Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions contracts/FuturesMarket.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import "./SignedSafeDecimalMath.sol";

// Internal references
import "./interfaces/IExchangeRates.sol";
import "./interfaces/ISystemStatus.sol";
import "./interfaces/IERC20.sol";

/*
Expand Down Expand Up @@ -139,6 +140,7 @@ contract FuturesMarket is Owned, Proxyable, MixinFuturesMarketSettings, IFutures
bytes32 internal constant CONTRACT_EXRATES = "ExchangeRates";
bytes32 internal constant CONTRACT_FUTURESMARKETMANAGER = "FuturesMarketManager";
bytes32 internal constant CONTRACT_FUTURESMARKETSETTINGS = "FuturesMarketSettings";
bytes32 internal constant CONTRACT_SYSTEMSTATUS = "SystemStatus";

/* ========== CONSTRUCTOR ========== */

Expand Down Expand Up @@ -172,17 +174,22 @@ contract FuturesMarket is Owned, Proxyable, MixinFuturesMarketSettings, IFutures

function resolverAddressesRequired() public view returns (bytes32[] memory addresses) {
bytes32[] memory existingAddresses = MixinFuturesMarketSettings.resolverAddressesRequired();
bytes32[] memory newAddresses = new bytes32[](3);
bytes32[] memory newAddresses = new bytes32[](4);
newAddresses[0] = CONTRACT_EXRATES;
newAddresses[1] = CONTRACT_FUTURESMARKETMANAGER;
newAddresses[2] = CONTRACT_FUTURESMARKETSETTINGS;
newAddresses[3] = CONTRACT_SYSTEMSTATUS;
addresses = combineArrays(existingAddresses, newAddresses);
}

function _exchangeRates() internal view returns (IExchangeRates) {
return IExchangeRates(requireAndGetAddress(CONTRACT_EXRATES));
}

function systemStatus() internal view returns (ISystemStatus) {
return ISystemStatus(requireAndGetAddress(CONTRACT_SYSTEMSTATUS));
}

function _manager() internal view returns (IFuturesMarketManagerInternal) {
return IFuturesMarketManagerInternal(requireAndGetAddress(CONTRACT_FUTURESMARKETMANAGER));
}
Expand All @@ -195,14 +202,18 @@ contract FuturesMarket is Owned, Proxyable, MixinFuturesMarketSettings, IFutures

function _assetPrice(IExchangeRates exchangeRates) internal view returns (uint price, bool invalid) {
(uint _price, bool _invalid) = exchangeRates.rateAndInvalid(baseAsset);
// Ensure we catch uninitialised rates
return (_price, _invalid || _price == 0);
// Ensure we catch uninitialised rates or suspended state / synth
_invalid = _invalid || _price == 0 || systemStatus().synthSuspended(baseAsset);
return (_price, _invalid);
}

/*
* The current base price, reverting if it is invalid.
* The current base price, reverting if it is invalid, or if system or synth is suspended.
*/
function _assetPriceRequireNotInvalid() internal view returns (uint) {
function _assetPriceRequireChecks() internal view returns (uint) {
// check that synth is active, and wasn't suspended, revert with appropriate message
systemStatus().requireSynthActive(baseAsset);
// check if price is invalid
(uint price, bool invalid) = _assetPrice(_exchangeRates());
_revertIfError(invalid, Status.InvalidPrice);
return price;
Expand Down Expand Up @@ -920,7 +931,7 @@ contract FuturesMarket is Owned, Proxyable, MixinFuturesMarketSettings, IFutures
*/
function recomputeFunding() external returns (uint lastIndex) {
_revertIfError(msg.sender != _settings(), Status.NotPermitted);
return _recomputeFunding(_assetPriceRequireNotInvalid());
return _recomputeFunding(_assetPriceRequireChecks());
}

/*
Expand Down Expand Up @@ -1026,7 +1037,7 @@ contract FuturesMarket is Owned, Proxyable, MixinFuturesMarketSettings, IFutures
* Reverts on withdrawal if the amount to be withdrawn would expose an open position to liquidation.
*/
function transferMargin(int marginDelta) external optionalProxy {
uint price = _assetPriceRequireNotInvalid();
uint price = _assetPriceRequireChecks();
uint fundingIndex = _recomputeFunding(price);
_transferMargin(marginDelta, price, fundingIndex, messageSender);
}
Expand All @@ -1037,7 +1048,7 @@ contract FuturesMarket is Owned, Proxyable, MixinFuturesMarketSettings, IFutures
*/
function withdrawAllMargin() external optionalProxy {
address sender = messageSender;
uint price = _assetPriceRequireNotInvalid();
uint price = _assetPriceRequireChecks();
uint fundingIndex = _recomputeFunding(price);
int marginDelta = -int(_accessibleMargin(positions[sender], fundingIndex, price));
_transferMargin(marginDelta, price, fundingIndex, sender);
Expand Down Expand Up @@ -1102,7 +1113,7 @@ contract FuturesMarket is Owned, Proxyable, MixinFuturesMarketSettings, IFutures
* Reverts if the resulting position is too large, outside the max leverage, or is liquidating.
*/
function modifyPosition(int sizeDelta) external optionalProxy {
uint price = _assetPriceRequireNotInvalid();
uint price = _assetPriceRequireChecks();
uint fundingIndex = _recomputeFunding(price);
_modifyPosition(sizeDelta, price, fundingIndex, messageSender);
}
Expand All @@ -1126,7 +1137,7 @@ contract FuturesMarket is Owned, Proxyable, MixinFuturesMarketSettings, IFutures
uint minPrice,
uint maxPrice
) external optionalProxy {
uint price = _assetPriceRequireNotInvalid();
uint price = _assetPriceRequireChecks();
_revertIfPriceOutsideBounds(price, minPrice, maxPrice);
uint fundingIndex = _recomputeFunding(price);
_modifyPosition(sizeDelta, price, fundingIndex, messageSender);
Expand All @@ -1138,7 +1149,7 @@ contract FuturesMarket is Owned, Proxyable, MixinFuturesMarketSettings, IFutures
function closePosition() external optionalProxy {
int size = positions[messageSender].size;
_revertIfError(size == 0, Status.NoPositionOpen);
uint price = _assetPriceRequireNotInvalid();
uint price = _assetPriceRequireChecks();
_modifyPosition(-size, price, _recomputeFunding(price), messageSender);
}

Expand All @@ -1148,7 +1159,7 @@ contract FuturesMarket is Owned, Proxyable, MixinFuturesMarketSettings, IFutures
function closePositionWithPriceBounds(uint minPrice, uint maxPrice) external optionalProxy {
int size = positions[messageSender].size;
_revertIfError(size == 0, Status.NoPositionOpen);
uint price = _assetPriceRequireNotInvalid();
uint price = _assetPriceRequireChecks();
_revertIfPriceOutsideBounds(price, minPrice, maxPrice);
_modifyPosition(-size, price, _recomputeFunding(price), messageSender);
}
Expand Down Expand Up @@ -1193,7 +1204,7 @@ contract FuturesMarket is Owned, Proxyable, MixinFuturesMarketSettings, IFutures
* Upon liquidation, the position will be closed, and the liquidation fee minted into the liquidator's account.
*/
function liquidatePosition(address account) external optionalProxy {
uint price = _assetPriceRequireNotInvalid();
uint price = _assetPriceRequireChecks();
uint fundingIndex = _recomputeFunding(price);

uint liquidationFee = _liquidationFee();
Expand Down
8 changes: 8 additions & 0 deletions contracts/SystemStatus.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ contract SystemStatus is Owned, ISystemStatus {
_internalRequireSystemActive();
}

function systemSuspended() external view returns (bool) {
return systemSuspension.suspended;
}

function requireIssuanceActive() external view {
// Issuance requires the system be active
_internalRequireSystemActive();
Expand All @@ -55,6 +59,10 @@ contract SystemStatus is Owned, ISystemStatus {
_internalRequireSynthExchangeActive(currencyKey);
}

function synthSuspended(bytes32 currencyKey) external view returns (bool) {
return systemSuspension.suspended || synthSuspension[currencyKey].suspended;
}

function requireSynthActive(bytes32 currencyKey) external view {
// Synth exchange and transfer requires the system be active
_internalRequireSystemActive();
Expand Down
4 changes: 4 additions & 0 deletions contracts/interfaces/ISystemStatus.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ interface ISystemStatus {

function requireSystemActive() external view;

function systemSuspended() external view returns (bool);

function requireIssuanceActive() external view;

function requireExchangeActive() external view;
Expand All @@ -27,6 +29,8 @@ interface ISystemStatus {

function requireSynthActive(bytes32 currencyKey) external view;

function synthSuspended(bytes32 currencyKey) external view returns (bool);

function requireSynthsActive(bytes32 sourceCurrencyKey, bytes32 destinationCurrencyKey) external view;

function systemSuspension() external view returns (bool suspended, uint248 reason);
Expand Down
2 changes: 1 addition & 1 deletion publish/releases.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
},
{
"sip": 80,
"layer": "ovm",
"layer": "kovan-ovm",
"released": false,
"sources": [
"FuturesMarketBTC",
Expand Down
Loading