Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/margin vault visibility issue #476

Closed
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
130 changes: 25 additions & 105 deletions contracts/core/Controller.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {OracleInterface} from "../interfaces/OracleInterface.sol";
import {WhitelistInterface} from "../interfaces/WhitelistInterface.sol";
import {MarginPoolInterface} from "../interfaces/MarginPoolInterface.sol";
import {CalleeInterface} from "../interfaces/CalleeInterface.sol";
import {forwards} from "../libs/ForwardLib.sol";

/**
* Controller Error Codes
Expand Down Expand Up @@ -644,18 +645,14 @@ contract Controller is Initializable, OwnableUpgradeSafe, ReentrancyGuardUpgrade

if (actionType == Actions.ActionType.OpenVault) {
_openVault(Actions._parseOpenVaultArgs(action));
} else if (actionType == Actions.ActionType.DepositLongOption) {
_depositLong(Actions._parseDepositArgs(action));
} else if (actionType == Actions.ActionType.WithdrawLongOption) {
_withdrawLong(Actions._parseWithdrawArgs(action));
} else if (actionType == Actions.ActionType.MintForward) {
_mintForward(Actions._parseMintForwardArgs(action));
} else if (actionType == Actions.ActionType.BurnForward) {
_burnForward(Actions._parseBurnForwardArgs(action));
} else if (actionType == Actions.ActionType.DepositCollateral) {
_depositCollateral(Actions._parseDepositArgs(action));
} else if (actionType == Actions.ActionType.WithdrawCollateral) {
_withdrawCollateral(Actions._parseWithdrawArgs(action));
} else if (actionType == Actions.ActionType.MintShortOption) {
_mintOtoken(Actions._parseMintArgs(action));
} else if (actionType == Actions.ActionType.BurnShortOption) {
_burnOtoken(Actions._parseBurnArgs(action));
} else if (actionType == Actions.ActionType.Redeem) {
_redeem(Actions._parseRedeemArgs(action));
} else if (actionType == Actions.ActionType.SettleVault) {
Expand All @@ -679,6 +676,13 @@ contract Controller is Initializable, OwnableUpgradeSafe, ReentrancyGuardUpgrade
(MarginVault.Vault memory vault, uint256 typeVault, ) = getVaultWithDetails(_owner, _vaultId);
(, bool isValidVault) = calculator.getExcessCollateral(vault, typeVault);

// vault can only have maximum of 1 long oToken 1 short otoken
// and the amounts of both must be identical
require(vault.longAmounts.length <= 1, "C14");
require(vault.shortAmounts.length <= 1, "C14");
require(vault.longAmounts.length == vault.shortAmounts.length, "C14");
require(vault.longAmounts[0] == vault.shortAmounts[0], "C14");

require(isValidVault, "C14");
}

Expand All @@ -704,63 +708,32 @@ contract Controller is Initializable, OwnableUpgradeSafe, ReentrancyGuardUpgrade
}

/**
* @notice deposit a long oToken into a vault
* @dev only the account owner or operator can deposit a long oToken, cannot be called when system is partiallyPaused or fullyPaused
* @notice mint a forward into the vault by deposit a longOtoken and Minting a short option
* @dev only the account owner or operater can deposit a long forward, cannot be called when system is partiallyPaused or fullyPaused
* @param _args DepositArgs structure
*/
function _depositLong(Actions.DepositArgs memory _args)
*
**/
function _mintForward(Actions.depositForwardArgs memory _args)
internal
notPartiallyPaused
onlyAuthorized(msg.sender, _args.owner)
{
require(_checkVaultId(_args.owner, _args.vaultId), "C35");
// only allow vault owner or vault operator to deposit long otoken
require((_args.from == msg.sender) || (_args.from == _args.owner), "C16");

require(whitelist.isWhitelistedOtoken(_args.asset), "C17");

OtokenInterface otoken = OtokenInterface(_args.asset);

require(now < otoken.expiryTimestamp(), "C18");

vaults[_args.owner][_args.vaultId].addLong(_args.asset, _args.amount, _args.index);

MarginPoolInterface(_getPool(vaultType[_args.owner][_args.vaultId])).transferToPool(
_args.asset,
_args.from,
_args.amount
);

emit LongOtokenDeposited(_args.asset, _args.owner, _args.from, _args.vaultId, _args.amount);
forwards._mintForward(_args, whitelist, vaults[_args.owner][_args.vaultId], vaultType[_args.owner][_args.vaultId], pool, borrowablePool, accountVaultCounter[_args.owner]);
}

/**
* @notice withdraw a long oToken from a vault
* @dev only the account owner or operator can withdraw a long oToken, cannot be called when system is partiallyPaused or fullyPaused
* @param _args WithdrawArgs structure
*/
function _withdrawLong(Actions.WithdrawArgs memory _args)
* @notice burn forwards to reduce or remove the minted oToken obligation and long recorded in a vault
* @dev only the account owner or operator can burn an oToken, cannot be called when system is partiallyPaused or fullyPaused
* @param _args MintArgs structure
*/
function _burnForward(Actions.BurnForwardArgs memory _args)
internal
notPartiallyPaused
onlyAuthorized(msg.sender, _args.owner)
{
require(_checkVaultId(_args.owner, _args.vaultId), "C35");

OtokenInterface otoken = OtokenInterface(_args.asset);

require(now < otoken.expiryTimestamp(), "C19");

vaults[_args.owner][_args.vaultId].removeLong(_args.asset, _args.amount, _args.index);

MarginPoolInterface(_getPool(vaultType[_args.owner][_args.vaultId])).transferToUser(
_args.asset,
_args.to,
_args.amount
);

emit LongOtokenWithdrawed(_args.asset, _args.owner, _args.to, _args.vaultId, _args.amount);
forwards._burnForward(_args, whitelist, vaults[_args.owner][_args.vaultId], vaultType[_args.owner][_args.vaultId], pool,borrowablePool, accountVaultCounter[_args.owner]);
}

/**
* @notice deposit a collateral asset into a vault
* @dev only the account owner or operator can deposit collateral, cannot be called when system is partiallyPaused or fullyPaused
Expand Down Expand Up @@ -831,59 +804,6 @@ contract Controller is Initializable, OwnableUpgradeSafe, ReentrancyGuardUpgrade
emit CollateralAssetWithdrawed(_args.asset, _args.owner, _args.to, _args.vaultId, _args.amount);
}

/**
* @notice mint short oTokens from a vault which creates an obligation that is recorded in the vault
* @dev only the account owner or operator can mint an oToken, cannot be called when system is partiallyPaused or fullyPaused
* @param _args MintArgs structure
*/
function _mintOtoken(Actions.MintArgs memory _args)
internal
notPartiallyPaused
onlyAuthorized(msg.sender, _args.owner)
{
require(_checkVaultId(_args.owner, _args.vaultId), "C35");
require(whitelist.isWhitelistedOtoken(_args.otoken), "C23");

OtokenInterface otoken = OtokenInterface(_args.otoken);

require(now < otoken.expiryTimestamp(), "C24");

vaults[_args.owner][_args.vaultId].addShort(_args.otoken, _args.amount, _args.index);

otoken.mintOtoken(_args.to, _args.amount);

emit ShortOtokenMinted(_args.otoken, _args.owner, _args.to, _args.vaultId, _args.amount);
}

/**
* @notice burn oTokens to reduce or remove the minted oToken obligation recorded in a vault
* @dev only the account owner or operator can burn an oToken, cannot be called when system is partiallyPaused or fullyPaused
* @param _args MintArgs structure
*/
function _burnOtoken(Actions.BurnArgs memory _args)
internal
notPartiallyPaused
onlyAuthorized(msg.sender, _args.owner)
{
// check that vault id is valid for this vault owner
require(_checkVaultId(_args.owner, _args.vaultId), "C35");
// only allow vault owner or vault operator to burn otoken
require((_args.from == msg.sender) || (_args.from == _args.owner), "C25");

OtokenInterface otoken = OtokenInterface(_args.otoken);

// do not allow burning expired otoken
require(now < otoken.expiryTimestamp(), "C26");

// remove otoken from vault
vaults[_args.owner][_args.vaultId].removeShort(_args.otoken, _args.amount, _args.index);

// burn otoken
otoken.burnOtoken(_args.from, _args.amount);

emit ShortOtokenBurned(_args.otoken, _args.owner, _args.from, _args.vaultId, _args.amount);
}

/**
* @notice redeem an oToken after expiry, receiving the payout of the oToken in the collateral asset
* @dev cannot be called when system is fullyPaused
Expand Down
4 changes: 1 addition & 3 deletions contracts/core/Oracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,7 @@ contract Oracle is Ownable {
* @return True if dispute period is over, False if not
*/
function isDisputePeriodOver(address _asset, uint256 _expiryTimestamp) public view returns (bool) {
uint256 price = stablePrice[_asset];

if (price == 0) {
if (stablePrice[_asset] == 0) {
// check if the pricer has a price for this expiry timestamp
Price memory price = storedPrice[_asset][_expiryTimestamp];
if (price.timestamp == 0) {
Expand Down
106 changes: 91 additions & 15 deletions contracts/libs/Actions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,8 @@ library Actions {
// possible actions that can be performed
enum ActionType {
OpenVault,
MintShortOption,
BurnShortOption,
DepositLongOption,
WithdrawLongOption,
MintForward,
BurnForward,
DepositCollateral,
WithdrawCollateral,
SettleVault,
Expand All @@ -58,7 +56,8 @@ library Actions {
// address which we move assets from or to (depending on the action type)
address secondAddress;
// asset that is to be transfered
address asset;
address asset; // long otoken
address shortAsset; // short otoken
// index of the vault that is to be modified (if any)
uint256 vaultId;
// amount of asset that is to be transfered
Expand Down Expand Up @@ -127,6 +126,25 @@ library Actions {
uint256 amount;
}

struct depositForwardArgs {
// address of the account owner
address owner;
// index of the vault to which the asset will be added
uint256 vaultId;
// address from which we transfer the asset
address from;
// oToken that is to be minted for the short leg
address to;
// asset that is to be deposited
address asset;
// oToken that is to be deposited for the short leg
address otoken;
// amount of asset that is to be deposited
uint256 amount;
// left in for legacy compat
uint256 index;
}

struct RedeemArgs {
// address to which we pay out the oToken proceeds
address receiver;
Expand All @@ -152,6 +170,25 @@ library Actions {
uint256 amount;
}

struct BurnForwardArgs {
// address of the account owner
address owner;
// index of the vault from which the oToken will be burned
uint256 vaultId;
// address from which we transfer the oTokens
address from;
// adddress to withdraw the longOtoken to
address to;
// asset that is to be withdrawn
address asset;
// oToken that is to be withdrawn from the short leg
address otoken;
// amount of oTokens that is to be burned
uint256 amount;
// left in for legacy compat
uint256 index;
}

struct SettleVaultArgs {
// address of the account owner
address owner;
Expand Down Expand Up @@ -210,7 +247,7 @@ library Actions {
* @return arguments for a mint action
*/
function _parseMintArgs(ActionArgs memory _args) internal pure returns (MintArgs memory) {
require(_args.actionType == ActionType.MintShortOption, "A4");
require(_args.actionType == ActionType.MintForward, "A4");
require(_args.owner != address(0), "A5");

return
Expand All @@ -230,7 +267,7 @@ library Actions {
* @return arguments for a burn action
*/
function _parseBurnArgs(ActionArgs memory _args) internal pure returns (BurnArgs memory) {
require(_args.actionType == ActionType.BurnShortOption, "A6");
require(_args.actionType == ActionType.BurnForward, "A6");
require(_args.owner != address(0), "A7");

return
Expand All @@ -250,10 +287,7 @@ library Actions {
* @return arguments for a deposit action
*/
function _parseDepositArgs(ActionArgs memory _args) internal pure returns (DepositArgs memory) {
require(
(_args.actionType == ActionType.DepositLongOption) || (_args.actionType == ActionType.DepositCollateral),
"A8"
);
require((_args.actionType == ActionType.DepositCollateral), "A8");
require(_args.owner != address(0), "A9");

return
Expand All @@ -267,16 +301,35 @@ library Actions {
});
}

/**
* @notice parses the pass in action args to get the arguments for a mint forward action
* @param _args general action arguments structure
* @return arguments for a deposit forward action
*/
function _parseMintForwardArgs(ActionArgs memory _args) internal pure returns (depositForwardArgs memory) {
require(_args.actionType == ActionType.MintForward, "A8");
require(_args.owner != address(0), "A9");

return
depositForwardArgs({
owner: _args.owner,
vaultId: _args.vaultId,
from: _args.secondAddress,
to: _args.asset,
asset: _args.asset,
otoken: _args.shortAsset,
amount: _args.amount,
index: _args.index
});
}

/**
* @notice parses the passed in action arguments to get the arguments for a withdraw action
* @param _args general action arguments structure
* @return arguments for a withdraw action
*/
function _parseWithdrawArgs(ActionArgs memory _args) internal pure returns (WithdrawArgs memory) {
require(
(_args.actionType == ActionType.WithdrawLongOption) || (_args.actionType == ActionType.WithdrawCollateral),
"A10"
);
require((_args.actionType == ActionType.WithdrawCollateral), "A10");
require(_args.owner != address(0), "A11");
require(_args.secondAddress != address(0), "A12");

Expand All @@ -291,6 +344,29 @@ library Actions {
});
}

/**
* @notice parses the passed in action arguments to get the arguments for a burn forward action
* @param _args general action arguments structure
* @return arguments for a burn forward action
*/
function _parseBurnForwardArgs(ActionArgs memory _args) internal pure returns (BurnForwardArgs memory) {
require(_args.actionType == ActionType.BurnForward, "A10");
require(_args.owner != address(0), "A11");
require(_args.secondAddress != address(0), "A12");

return
BurnForwardArgs({
owner: _args.owner,
vaultId: _args.vaultId,
from: _args.secondAddress,
to: _args.secondAddress,
asset: _args.asset,
otoken: _args.asset,
amount: _args.amount,
index: _args.index
});
}

/**
* @notice parses the passed in action arguments to get the arguments for an redeem action
* @param _args general action arguments structure
Expand Down
Loading