Skip to content

Commit

Permalink
Merge pull request #180 from opynfinance/task/refactor-constructor
Browse files Browse the repository at this point in the history
Refactor constructor
  • Loading branch information
aparnakr authored Aug 19, 2020
2 parents 434e20b + 49315a7 commit 6454bf4
Show file tree
Hide file tree
Showing 24 changed files with 435 additions and 536 deletions.
64 changes: 31 additions & 33 deletions contracts/OptionsContract.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,14 @@ contract OptionsContract is Ownable, ERC20 {
// 10 is 0.01 i.e. 1% incentive.
Number public liquidationIncentive = Number(10, -3);

// 100 is egs. 0.1 i.e. 10%.
Number public transactionFee = Number(0, -3);

/* 500 is 0.5. Max amount that a Vault can be liquidated by i.e.
max collateral that can be taken in one function call */
Number public liquidationFactor = Number(500, -3);

/* 16 means 1.6. The minimum ratio of a Vault's collateral to insurance promised.
The ratio is calculated as below:
vault.collateral / (Vault.oTokensIssued * strikePrice) */
Number public minCollateralizationRatio = Number(16, -1);
Number public minCollateralizationRatio = Number(10, -1);

// The amount of insurance promised per oToken
Number public strikePrice;
Expand Down Expand Up @@ -99,43 +96,32 @@ contract OptionsContract is Ownable, ERC20 {

/**
* @param _collateral The collateral asset
* @param _collExp The precision of the collateral (-18 if ETH)
* @param _underlying The asset that is being protected
* @param _underlyingExp The precision of the underlying asset
* @param _oTokenExchangeExp The precision of the `amount of underlying` that 1 oToken protects
* @param _strikePrice The amount of strike asset that will be paid out per oToken
* @param _strikeExp The precision of the strike price.
* @param _strike The asset in which the insurance is calculated
* @param _expiry The time at which the insurance expires
* @param _oracleAddress The address of the oracle
* @param _windowSize UNIX time. Exercise window is from `expiry - _windowSize` to `expiry`.
* @param _oracleAddress The address of the oracle
*/
constructor(
IERC20 _collateral,
int32 _collExp,
IERC20 _underlying,
int32 _underlyingExp,
address _collateral,
address _underlying,
address _strike,
int32 _oTokenExchangeExp,
uint256 _strikePrice,
int32 _strikeExp,
IERC20 _strike,
uint256 _expiry,
address _oracleAddress,
uint256 _windowSize
uint256 _windowSize,
address _oracleAddress
) public {
require(block.timestamp < _expiry, "Can't deploy an expired contract");
require(
_windowSize <= _expiry,
"Exercise window can't be longer than the contract's lifespan"
);
require(
isWithinExponentRange(_collExp),
"collateral exponent not within expected range"
);
require(
isWithinExponentRange(_underlyingExp),
"underlying exponent not within expected range"
);

require(
isWithinExponentRange(_strikeExp),
"strike price exponent not within expected range"
Expand All @@ -150,15 +136,24 @@ contract OptionsContract is Ownable, ERC20 {
"OptionsContract: Can't use ETH as underlying."
);

collateral = _collateral;
collateralExp = _collExp;
collateral = IERC20(_collateral);
underlying = IERC20(_underlying);
strike = IERC20(_strike);

collateralExp = getAssetExp(_collateral);
underlyingExp = getAssetExp(_underlying);
require(
isWithinExponentRange(collateralExp),
"collateral exponent not within expected range"
);
require(
isWithinExponentRange(underlyingExp),
"underlying exponent not within expected range"
);

underlying = _underlying;
underlyingExp = _underlyingExp;
oTokenExchangeRate = Number(1, _oTokenExchangeExp);

strikePrice = Number(_strikePrice, _strikeExp);
strike = _strike;

expiry = _expiry;
oracle = OracleInterface(_oracleAddress);
Expand Down Expand Up @@ -203,7 +198,6 @@ contract OptionsContract is Ownable, ERC20 {
event UpdateParameters(
uint256 liquidationIncentive,
uint256 liquidationFactor,
uint256 transactionFee,
uint256 minCollateralizationRatio,
address owner
);
Expand Down Expand Up @@ -237,13 +231,11 @@ contract OptionsContract is Ownable, ERC20 {
* @notice Can only be called by owner. Used to update the fees, minCollateralizationRatio, etc
* @param _liquidationIncentive The incentive paid to liquidator. 10 is 0.01 i.e. 1% incentive.
* @param _liquidationFactor Max amount that a Vault can be liquidated by. 500 is 0.5.
* @param _transactionFee The fees paid to our protocol every time a execution happens. 100 is egs. 0.1 i.e. 10%.
* @param _minCollateralizationRatio The minimum ratio of a Vault's collateral to insurance promised. 16 means 1.6.
*/
function updateParameters(
uint256 _liquidationIncentive,
uint256 _liquidationFactor,
uint256 _transactionFee,
uint256 _minCollateralizationRatio
) external onlyOwner {
require(
Expand All @@ -254,21 +246,18 @@ contract OptionsContract is Ownable, ERC20 {
_liquidationFactor <= 1000,
"Can't liquidate more than 100% of the vault"
);
require(_transactionFee <= 100, "Can't have transaction fee > 10%");
require(
_minCollateralizationRatio >= 10,
"Can't have minCollateralizationRatio < 1"
);

liquidationIncentive.value = _liquidationIncentive;
liquidationFactor.value = _liquidationFactor;
transactionFee.value = _transactionFee;
minCollateralizationRatio.value = _minCollateralizationRatio;

emit UpdateParameters(
_liquidationIncentive,
_liquidationFactor,
_transactionFee,
_minCollateralizationRatio,
owner()
);
Expand Down Expand Up @@ -1052,6 +1041,15 @@ contract OptionsContract is Ownable, ERC20 {
);
}

/**
* @dev internal function to parse token decimals for constructor
* @param _asset the asset address
*/
function getAssetExp(address _asset) internal view returns (int32) {
if (_asset == address(0)) return -18;
return -1 * int32(ERC20Detailed(_asset).decimals());
}

/**
* @notice This function gets the price ETH (wei) to asset price.
* @param asset The address of the asset to get the price of
Expand Down
92 changes: 31 additions & 61 deletions contracts/OptionsFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,15 @@ import "./packages/IERC20.sol";
contract OptionsFactory is Ownable {
using StringComparator for string;

// keys saved in front-end -- look at the docs if needed
mapping(string => IERC20) public tokens;
mapping(address => bool) public whitelisted;
address[] public optionsContracts;

// The contract which interfaces with the exchange
OptionsExchange public optionsExchange;
address public oracleAddress;

event OptionsContractCreated(address addr);
event AssetUpdated(
string indexed asset,
address indexed oldAddr,
address indexed newAddr
);
event AssetWhitelisted(address indexed asset);

/**
* @param _optionsExchangeAddr: The contract which interfaces with the exchange
Expand All @@ -37,63 +32,55 @@ contract OptionsFactory is Ownable {

/**
* @notice creates a new Option Contract
* @param _collateralType The collateral asset. Eg. "ETH"
* @param _collateralExp The number of decimals the collateral asset has
* @param _underlyingType The underlying asset. Eg. "DAI"
* @param _underlyingExp The precision of the underlying asset. Eg. (-18 if Dai)
* @param _collateral The collateral asset. Eg. "ETH"
* @param _underlying The underlying asset. Eg. "DAI"
* @param _oTokenExchangeExp Units of underlying that 1 oToken protects
* @param _strikePrice The amount of strike asset that will be paid out
* @param _strikeExp The precision of the strike Price
* @param _strikeAsset The asset in which the insurance is calculated
* @param _strike The asset in which the insurance is calculated
* @param _expiry The time at which the insurance expires
* @param _windowSize UNIX time. Exercise window is from `expiry - _windowSize` to `expiry`.
*/
function createOptionsContract(
string calldata _collateralType,
int32 _collateralExp,
string calldata _underlyingType,
int32 _underlyingExp,
address _collateral,
address _underlying,
address _strike,
int32 _oTokenExchangeExp,
uint256 _strikePrice,
int32 _strikeExp,
string calldata _strikeAsset,
uint256 _expiry,
uint256 _windowSize
uint256 _windowSize,
string calldata _name,
string calldata _symbol
) external returns (address) {
require(whitelisted[_collateral], "Collateral not whitelisted.");
require(whitelisted[_underlying], "Underlying not whitelisted.");
require(whitelisted[_strike], "Strike not whitelisted.");

require(_expiry > block.timestamp, "Cannot create an expired option");
require(_windowSize <= _expiry, "Invalid _windowSize");
require(
supportsAsset(_collateralType),
"Collateral type not supported"
);
require(
supportsAsset(_underlyingType),
"Underlying type not supported"
);
require(supportsAsset(_strikeAsset), "Strike asset type not supported");

oToken optionsContract = new oToken(
tokens[_collateralType],
_collateralExp,
tokens[_underlyingType],
_underlyingExp,
oToken otoken = new oToken(
_collateral,
_underlying,
_strike,
_oTokenExchangeExp,
_strikePrice,
_strikeExp,
tokens[_strikeAsset],
_expiry,
_windowSize,
optionsExchange,
oracleAddress,
_windowSize
oracleAddress
);

optionsContracts.push(address(optionsContract));
emit OptionsContractCreated(address(optionsContract));
otoken.setDetails(_name, _symbol);

// Set the owner for the options contract.
optionsContract.transferOwnership(owner());
optionsContracts.push(address(otoken));
emit OptionsContractCreated(address(otoken));

return address(optionsContract);
// Set the owner for the options contract.
otoken.transferOwnership(owner());
return address(otoken);
}

/**
Expand All @@ -105,27 +92,10 @@ contract OptionsFactory is Ownable {

/**
* @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 updateAsset(string calldata _asset, address _addr)
external
onlyOwner
{
emit AssetUpdated(_asset, address(tokens[_asset]), _addr);

tokens[_asset] = IERC20(_addr);
}

/**
* @notice Check if the Factory contract supports a specific asset
* @param _asset The ticker symbol for the asset
* @param _asset The address for the asset
*/
function supportsAsset(string memory _asset) public view returns (bool) {
if (_asset.compareStrings("ETH")) {
return true;
}

return tokens[_asset] != IERC20(0);
function whitelistAsset(address _asset) external onlyOwner {
whitelisted[_asset] = true;
emit AssetWhitelisted(_asset);
}
}
22 changes: 8 additions & 14 deletions contracts/oToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ contract oToken is OptionsContract {

/**
* @param _collateral The collateral asset
* @param _collExp The precision of the collateral (-18 if ETH)
* @param _underlying The asset that is being protected
* @param _underlyingExp The precision of the underlying asset
* @param _oTokenExchangeExp The precision of the `amount of underlying` that 1 oToken protects
* @param _strikePrice The amount of strike asset that will be paid out
* @param _strikeExp The precision of the strike asset (-18 if ETH)
Expand All @@ -27,32 +25,28 @@ contract oToken is OptionsContract {
* @param _windowSize UNIX time. Exercise window is from `expiry - _windowSize` to `expiry`.
*/
constructor(
IERC20 _collateral,
int32 _collExp,
IERC20 _underlying,
int32 _underlyingExp,
address _collateral,
address _underlying,
address _strike,
int32 _oTokenExchangeExp,
uint256 _strikePrice,
int32 _strikeExp,
IERC20 _strike,
uint256 _expiry,
uint256 _windowSize,
OptionsExchange _optionsExchange,
address _oracleAddress,
uint256 _windowSize
address _oracleAddress
)
public
OptionsContract(
_collateral,
_collExp,
_underlying,
_underlyingExp,
_strike,
_oTokenExchangeExp,
_strikePrice,
_strikeExp,
_strike,
_expiry,
_oracleAddress,
_windowSize
_windowSize,
_oracleAddress
)
{
optionsExchange = _optionsExchange;
Expand Down
Loading

0 comments on commit 6454bf4

Please sign in to comment.