Skip to content

Commit

Permalink
Merge pull request #163 from opynfinance/feature/pause-functionality
Browse files Browse the repository at this point in the history
Pause functionality
  • Loading branch information
haythem96 authored Aug 18, 2020
2 parents dbd4946 + 3b6dbcb commit d056d53
Show file tree
Hide file tree
Showing 20 changed files with 109 additions and 165 deletions.
37 changes: 37 additions & 0 deletions contracts/OptionsContract.sol
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ contract OptionsContract is Ownable, ERC20 {
// The number of decimals of the contract
uint8 public decimals;

// the state of the option contract, if true then all option functionalities are paused other than removing collateral
bool internal isPaused;

/**
* @param _collateral The collateral asset
* @param _collExp The precision of the collateral (-18 if ETH)
Expand Down Expand Up @@ -209,6 +212,11 @@ contract OptionsContract is Ownable, ERC20 {
uint256 amountUnderlying,
address payable vaultOwner
);
event OptionStateUpdated(
bool oldState,
bool newState,
uint256 updateTimestamp
);

/**
* @dev Throws if called Options contract is expired.
Expand Down Expand Up @@ -303,6 +311,27 @@ contract OptionsContract is Ownable, ERC20 {
emit TransferFee(_address, fees);
}

/**
* @notice Can only be called by owner. Used to pause and restart the option contract.
* @dev can not restart an already running option, and can not pause an already paused option
* @param _isPaused The option contract state, if true then pause the contract, if false then restart contract
*/
function setIsPaused(bool _isPaused) external onlyOwner {
require(_isPaused != isPaused, "Option contract already in that state");

emit OptionStateUpdated(isPaused, _isPaused, now);

isPaused = _isPaused;
}

/**
* @notice Get option contract state. If option is paused should return true, else false.
* @return option contract state
*/
function isSystemPaused() public view returns (bool) {
return isPaused;
}

/**
* @notice Checks if a `owner` has already created a Vault
* @param _owner The address of the supposed owner
Expand All @@ -316,6 +345,7 @@ contract OptionsContract is Ownable, ERC20 {
* @notice Creates a new empty Vault and sets the owner of the vault to be the msg.sender.
*/
function openVault() public notExpired returns (bool) {
require(!isSystemPaused(), "Option contract is paused");
require(!hasVault(msg.sender), "Vault already created");

vaults[msg.sender] = Vault(0, 0, 0, true);
Expand Down Expand Up @@ -343,6 +373,7 @@ contract OptionsContract is Ownable, ERC20 {
notExpired
returns (uint256)
{
require(!isSystemPaused(), "Option contract is paused");
require(isETH(collateral), "ETH is not the specified collateral type");
require(hasVault(vaultOwner), "Vault does not exist");

Expand All @@ -369,6 +400,7 @@ contract OptionsContract is Ownable, ERC20 {
notExpired
returns (uint256)
{
require(!isSystemPaused(), "Option contract is paused");
require(
collateral.transferFrom(msg.sender, address(this), amt),
"OptionsContract: transfer collateral failed."
Expand Down Expand Up @@ -423,7 +455,9 @@ contract OptionsContract is Ownable, ERC20 {
uint256 oTokensToExercise,
address payable[] memory vaultsToExerciseFrom
) public payable {
require(!isSystemPaused(), "Option contract is paused");
require(oTokensToExercise > 0, "Can't exercise 0 oTokens");

for (uint256 i = 0; i < vaultsToExerciseFrom.length; i++) {
address payable vaultOwner = vaultsToExerciseFrom[i];
require(
Expand Down Expand Up @@ -477,6 +511,7 @@ contract OptionsContract is Ownable, ERC20 {
public
notExpired
{
require(!isSystemPaused(), "Option contract is paused");
//check that we're properly collateralized to mint this number, then call _mint(address account, uint256 amount)
require(hasVault(msg.sender), "Vault does not exist");

Expand Down Expand Up @@ -532,6 +567,7 @@ contract OptionsContract is Ownable, ERC20 {
* @dev only want to call this function before expiry. After expiry, no benefit to calling it.
*/
function burnOTokens(uint256 amtToBurn) external notExpired {
require(!isSystemPaused(), "Option contract is paused");
require(hasVault(msg.sender), "Vault does not exist");

Vault storage vault = vaults[msg.sender];
Expand Down Expand Up @@ -642,6 +678,7 @@ contract OptionsContract is Ownable, ERC20 {
external
notExpired
{
require(!isSystemPaused(), "Option contract is paused");
require(hasVault(vaultOwner), "Vault does not exist");

Vault storage vault = vaults[vaultOwner];
Expand Down
50 changes: 8 additions & 42 deletions contracts/OptionsFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ contract OptionsFactory is Ownable {
address public oracleAddress;

event OptionsContractCreated(address addr);
event AssetAdded(string indexed asset, address indexed addr);
event AssetChanged(string indexed asset, address indexed addr);
event AssetDeleted(string indexed asset);
event AssetUpdated(
string indexed asset,
address indexed oldAddr,
address indexed newAddr
);

/**
* @param _optionsExchangeAddr: The contract which interfaces with the exchange
Expand Down Expand Up @@ -102,53 +104,17 @@ contract OptionsFactory is Ownable {
}

/**
* @notice The owner of the Factory Contract can add a new asset to be supported
* @dev admin don't add ETH. ETH is set to 0x0.
* @notice The owner of the Factory Contract can update an asset's address, by adding it, changing the address or removing the asset
* @param _asset The ticker symbol for the asset
* @param _addr The address of the asset
*/
function addAsset(string calldata _asset, address _addr)
function updateAsset(string calldata _asset, address _addr)
external
onlyOwner
{
require(!supportsAsset(_asset), "Asset already added");
require(_addr != address(0), "Cannot set to address(0)");
emit AssetUpdated(_asset, address(tokens[_asset]), _addr);

tokens[_asset] = IERC20(_addr);
emit AssetAdded(_asset, _addr);
}

/**
* @notice The owner of the Factory Contract can change an existing asset's address
* @param _asset The ticker symbol for the asset
* @param _addr The address of the asset
*/
function changeAsset(string calldata _asset, address _addr)
external
onlyOwner
{
require(
tokens[_asset] != IERC20(0),
"Trying to replace a non-existent asset"
);
require(_addr != address(0), "Cannot set to address(0)");

tokens[_asset] = IERC20(_addr);
emit AssetChanged(_asset, _addr);
}

/**
* @notice The owner of the Factory Contract can delete an existing asset's address
* @param _asset The ticker symbol for the asset
*/
function deleteAsset(string calldata _asset) external onlyOwner {
require(
tokens[_asset] != IERC20(0),
"Trying to delete a non-existent asset"
);

tokens[_asset] = IERC20(0);
emit AssetDeleted(_asset);
}

/**
Expand Down
18 changes: 9 additions & 9 deletions docs/OptionsFactory.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ event AssetDeleted(string indexed asset);
- [(OptionsExchange _optionsExchangeAddr, address _oracleAddress)](#)
- [createOptionsContract(string _collateralType, int32 _collateralExp, string _underlyingType, int32 _underlyingExp, int32 _oTokenExchangeExp, uint256 _strikePrice, int32 _strikeExp, string _strikeAsset, uint256 _expiry, uint256 _windowSize)](#createoptionscontract)
- [getNumberOfOptionsContracts()](#getnumberofoptionscontracts)
- [addAsset(string _asset, address _addr)](#addasset)
- [changeAsset(string _asset, address _addr)](#changeasset)
- [deleteAsset(string _asset)](#deleteasset)
- [updateAsset(string _asset, address _addr)](#updateAsset)
- [updateAsset(string _asset, address _addr)](#updateAsset)
- [updateAsset(string _asset)](#updateAsset)
- [supportsAsset(string _asset)](#supportsasset)

###
Expand Down Expand Up @@ -87,12 +87,12 @@ returns(uint256)
| Name | Type | Description |
| ------------- |------------- | -----|

### addAsset
### updateAsset

The owner of the Factory Contract can add a new asset to be supported

```js
function addAsset(string _asset, address _addr) external nonpayable onlyOwner
function updateAsset(string _asset, address _addr) external nonpayable onlyOwner
```

**Arguments**
Expand All @@ -102,12 +102,12 @@ function addAsset(string _asset, address _addr) external nonpayable onlyOwner
| _asset | string | The ticker symbol for the asset |
| _addr | address | The address of the asset |

### changeAsset
### updateAsset

The owner of the Factory Contract can change an existing asset's address

```js
function changeAsset(string _asset, address _addr) external nonpayable onlyOwner
function updateAsset(string _asset, address _addr) external nonpayable onlyOwner
```

**Arguments**
Expand All @@ -117,12 +117,12 @@ function changeAsset(string _asset, address _addr) external nonpayable onlyOwner
| _asset | string | The ticker symbol for the asset |
| _addr | address | The address of the asset |

### deleteAsset
### updateAsset

The owner of the Factory Contract can delete an existing asset's address

```js
function deleteAsset(string _asset) external nonpayable onlyOwner
function updateAsset(string _asset) external nonpayable onlyOwner
```

**Arguments**
Expand Down
10 changes: 5 additions & 5 deletions migrations/3_add_assests.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ module.exports = async function (deployer) {
// const testToken2 = await deployer.deploy(ERC20);

// // add assets
// await optionsFactory.addAsset('DAI', testDAI.address)
// await optionsFactory.addAsset('USDC', testUSDC.address)
// await optionsFactory.addAsset('TKN', testToken1.address)
// await optionsFactory.updateAsset('DAI', testDAI.address)
// await optionsFactory.updateAsset('USDC', testUSDC.address)
// await optionsFactory.updateAsset('TKN', testToken1.address)

// // change asset
// await optionsFactory.changeAsset('TKN', testToken2.address)
// await optionsFactory.updateAsset('TKN', testToken2.address)

// // delete asset
// await optionsFactory.deleteAsset('TKN')
// await optionsFactory.updateAsset('TKN')
};
4 changes: 2 additions & 2 deletions test/add-remove-liquidate-burn.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ contract('OptionsContract', accounts => {
// Deploy the Options Factory contract and add assets to it
optionsFactory = await OptionsFactory.deployed();

await optionsFactory.addAsset('DAI', dai.address);
await optionsFactory.addAsset('USDC', usdc.address);
await optionsFactory.updateAsset('DAI', dai.address);
await optionsFactory.updateAsset('USDC', usdc.address);

// const windowSize = expiry;
const now = (await time.latest()).toNumber();
Expand Down
4 changes: 2 additions & 2 deletions test/exercise-add-remove-liquidate-exersice.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ contract('OptionsContract', accounts => {
// Deploy the Options Factory contract and add assets to it
optionsFactory = await OptionsFactory.deployed();

await optionsFactory.addAsset('DAI', dai.address);
await optionsFactory.updateAsset('DAI', dai.address);
// TODO: deploy a mock USDC and get its address
await optionsFactory.addAsset('USDC', usdc.address);
await optionsFactory.updateAsset('USDC', usdc.address);

// Create the unexpired options contract
const optionsContractResult = await optionsFactory.createOptionsContract(
Expand Down
4 changes: 2 additions & 2 deletions test/exercise-erc20-collateral.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ contract(
// Deploy the Options Factory contract and add assets to it
optionsFactory = await OptionsFactory.deployed();

await optionsFactory.addAsset('USDC', usdc.address);
await optionsFactory.addAsset('WETH', weth.address);
await optionsFactory.updateAsset('USDC', usdc.address);
await optionsFactory.updateAsset('WETH', weth.address);

// Create the unexpired options contract
const optionsContractResult = await optionsFactory.createOptionsContract(
Expand Down
2 changes: 1 addition & 1 deletion test/exercise-eth-collateral.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ contract(
// Deploy the Options Factory contract and add assets to it
optionsFactory = await OptionsFactory.deployed();

await optionsFactory.addAsset('USDC', usdc.address);
await optionsFactory.updateAsset('USDC', usdc.address);

// Create the unexpired options contract
const optionsContractResult = await optionsFactory.createOptionsContract(
Expand Down
4 changes: 2 additions & 2 deletions test/liquidate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ contract('OptionsContract', accounts => {
// Deploy the Options Factory contract and add assets to it
optionsFactory = await OptionsFactory.deployed();

await optionsFactory.addAsset('DAI', dai.address);
await optionsFactory.updateAsset('DAI', dai.address);
// TODO: deploy a mock USDC and get its address
await optionsFactory.addAsset('USDC', usdc.address);
await optionsFactory.updateAsset('USDC', usdc.address);

// Create the unexpired options contract
const optionsContractResult = await optionsFactory.createOptionsContract(
Expand Down
4 changes: 2 additions & 2 deletions test/miltiple-exercise.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ contract('OptionsContract', accounts => {
// Deploy the Options Factory contract and add assets to it
optionsFactory = await OptionsFactory.deployed();

await optionsFactory.addAsset('DAI', dai.address);
await optionsFactory.updateAsset('DAI', dai.address);
// TODO: deploy a mock USDC and get its address
await optionsFactory.addAsset('USDC', usdc.address);
await optionsFactory.updateAsset('USDC', usdc.address);

// Create the unexpired options contract
const optionsContractResult = await optionsFactory.createOptionsContract(
Expand Down
6 changes: 3 additions & 3 deletions test/optionsContract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ contract('OptionsContract', accounts => {
// Deploy the Options Factory contract and add assets to it
optionsFactory = await OptionsFactory.deployed();

await optionsFactory.addAsset('WETH', weth.address);
await optionsFactory.addAsset('DAI', dai.address);
await optionsFactory.addAsset('USDC', usdc.address);
await optionsFactory.updateAsset('WETH', weth.address);
await optionsFactory.updateAsset('DAI', dai.address);
await optionsFactory.updateAsset('USDC', usdc.address);

// Create the unexpired options contract
let optionsContractResult = await optionsFactory.createOptionsContract(
Expand Down
Loading

0 comments on commit d056d53

Please sign in to comment.