It was created 60 days before its expiration so on 03 Mar 2021when ETHUSD was about 1560 so this put was essentially betting on ETH loosing >18% in 2 months
This is interaction consisted of 2 token transfers: first 256.000 USDC are transferred from Contract Creator to the Opyn System and then 200 WETHUSDC 30-April-2021 1280Put USDC Collateral options are returned to it
The reason is obviously the options needs to be collateralized to avoid liquidation risk so since the Strike Price is 1280 USDC for 200 Options we get 256000 USDC
Let's analyze this more in-depth
It all starts calling Controller --> operate() passing the params to Mint an OToken for the Put Option
Technically, this check passes if one of the following conditions is True (note the || so Logical OR operator and the fact the 2 conditions are mutually exclusive)
Case 1 : _vault.collateralAssets[_index] == _collateralAsset
the collateral address _collateralAddress is already tracked and represented by _index
Case 2 : the _index corresponds to address(0) which essentially means the _collateralAddress is not tracked yet, but since it is whitelisted (remember the previous check) it just means it has not been used yet
so the only case this Tx fails is when a whitelisted collateral previously used and hence tracked is passed with an _index that does not match the one that already tracks it: essentially it should never happen since it would be a bug in the code elsewhere
So ultimately the changes made here by this function are
Line 1: the current amount of the collateral in the vault represented by _vault.collateralAmounts[_index] is increased by _amount
Line 2 : in case the asset is already tracked (so Case 1 of the check discussed above) this is just repetitive, but if it is not tracked (so Case of the check discussed above) then it starts tracking it
The _asset is then finally transferred in the Token Balance Sheet by calling the ERC20 safeTransferFrom() which ultimately transfers the taken from _user to address(this) so this contract for _amount amount
2.1.3 Summary
At this point the situation is
at ERC20 level, so in the _args.asset Balance Sheet, an amount _args.amounthas been transferred from_user` to this contract
at Opyn Level, there are 2 Balance Sheets that have been updated
the Vault so vaults[_args.owner][_args.vaultId] and
struct MintArgs {
// address of the account owner
address owner;
// index of the vault from which the asset will be minted
uint256 vaultId;
// address to which we transfer the minted oTokens
address to;
// oToken that is to be minted
address otoken;
// each vault can hold multiple short / long / collateral assets but we are restricting the scope to only 1 of each in this version
// in future versions this would be the index of the short / long / collateral asset that needs to be modified
uint256 index;
// amount of oTokens that is to be minted
uint256 amount;
}
NOTE
The otoken address is also used to reach the actual implementation of mintOtoken() which is the function that actually mints the token
2.2.1 Checks
2.2.1.1 Authorization
it is important to observe here in the function definition
So just looking at the interface we can say this function tracks the number of the specific Short=Put OTokens minted in the Vault using the already analysed _index pattern instead of the _shortOtoken address identifying the actual smart contract for the OToken given
1. Overview
Let's consider this token
WETHUSDC 30-April-2021 1280Put USDC Collateral
https://etherscan.io/token/0x18ebe982fd5a6f724837549c03f186438e90eee3
It represents an Opyn Option with
The confirmation of this can be found analysing the source code in the related Smart Contract
OToken.sol
It was created 60 days before its expiration so on 03 Mar 2021when ETHUSD was about 1560 so this put was essentially betting on ETH loosing >18% in 2 months
2. TX Analysis
This is its minting Tx
https://etherscan.io/tx/0x052a2a5cc5c43d2247ae238beb9bc0445d0850dd56cd53f4198cdc9d31e4aa66
The
Contract Creator
interacted with the smart contractUpgradeableProxy for Controller
that is a proxy forController
You can check this by looking at the internal TXs of this contract here and you can see it's interacting with the proxyUpgradableProxy for Controller
all the timeThis is interaction consisted of 2 token transfers: first 256.000 USDC are transferred from
Contract Creator
to the Opyn System and then 200WETHUSDC 30-April-2021 1280Put USDC Collateral
options are returned to itThe reason is obviously the options needs to be collateralized to avoid liquidation risk so since the Strike Price is 1280 USDC for 200 Options we get 256000 USDC
Let's analyze this more in-depth
It all starts calling
Controller --> operate()
passing the params to Mint an OToken for the Put OptionIt internally calls
Controller --> _runActions()
which acts as a proxy here for a bunch of actions2.1 Deposit Collateral
The related action is
Actions.ActionType.DepositCollateral
which calls here the_depositCollateral
so only a set of authorized users can call this method
2.1.1 Checks
2.1.1.1 VaultID Validity and Accessibility for
_args.owner
2.1.1.2 Being allowed to deposit collateral
2.1.1.3 Whitelisted Collateral
2.1.2 Changes
2.1.2.1 Increasing the collateral balance in a Vault
N x M
relationship between Owners and Vaults and it is modeled in thevaults
variableThe
addCollateral()
function interface is defined as followsNOTES
_index
is just a convenience variable: it is an internal index in the_vault.collateralAssets
which is an array tracking the collaterals||
so Logical OR operator and the fact the 2 conditions are mutually exclusive)_vault.collateralAssets[_index] == _collateralAsset
_collateralAddress
is already tracked and represented by_index
_index
corresponds toaddress(0)
which essentially means the_collateralAddress
is not tracked yet, but since it is whitelisted (remember the previous check) it just means it has not been used yet_index
that does not match the one that already tracks it: essentially it should never happen since it would be a bug in the code elsewhereSo ultimately the changes made here by this function are
_vault.collateralAmounts[_index]
is increased by_amount
2.1.2.2 Transferring the collateral
The
transferToPool()
function interface is defined as followsAfter a basic sanity check on
_amount > 0
shown herewhat happens is
_asset
represented inassetBalance[_asset]
is increased by_amount
_asset
is then finally transferred in the Token Balance Sheet by calling the ERC20safeTransferFrom()
which ultimately transfers the taken from_user
toaddress(this)
so this contract for_amount
amount2.1.3 Summary
At this point the situation is
at ERC20 level, so in the
_args.asset
Balance Sheet, an amount _args.amounthas been transferred from
_user` to this contractat Opyn Level, there are 2 Balance Sheets that have been updated
vaults[_args.owner][_args.vaultId]
andpool
which is defined asLink
so the address of the related smart contract is taken from the
addressbook
which is set at deployment time2.2 Minting the OToken
Actions.ActionType.MintShortOption
which callshere
the internal function called_mintOtken()
The args
_mintOtken()
requires are defined in themintArgs
structNOTE
otoken
address is also used to reach the actual implementation ofmintOtoken()
which is the function that actually mints the token2.2.1 Checks
2.2.1.1 Authorization
it is important to observe here in the function definition
Link
only a set of authorized users can call this method
2.2.1.2 Sanity check on the Vault
2.2.1.3 Otoken Whitelist Check
2.2.1.4 OToken Expiry Sanity Check
2.2.2 Changes
2.2.2.1 Tracking the number of Short OTokens
addShort()
function interface is defined here_index
pattern instead of the_shortOtoken
address identifying the actual smart contract for the OToken given2.2.2.2 Actual OToken Minting
OtokenInterface
to access themintOtoken() abstract
abstract method_args.otoken
related smart contract addressAppunto