Source Code
Overview
HYPE Balance
HYPE Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Initialize | 10903619 | 167 days ago | IN | 0 HYPE | 0.00002217 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0xC3E597c5...dB0d5C7b5 The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
ControllerLogic
Compiler Version
v0.6.10+commit.00c0fcaf
Optimization Enabled:
Yes with 200 runs
Other Settings:
istanbul EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
/**
* SPDX-License-Identifier: UNLICENSED
*/
pragma solidity =0.6.10;
pragma experimental ABIEncoderV2;
import {OwnableUpgradeSafe} from "../packages/oz/upgradeability/OwnableUpgradeSafe.sol";
import {ReentrancyGuardUpgradeSafe} from "../packages/oz/upgradeability/ReentrancyGuardUpgradeSafe.sol";
import {Initializable} from "../packages/oz/upgradeability/Initializable.sol";
import {SafeMath} from "../packages/oz/SafeMath.sol";
import {MarginVault} from "../libs/MarginVault.sol";
import {Actions} from "../libs/Actions.sol";
import {ERC20Interface} from "../interfaces/ERC20Interface.sol";
import {AddressBookInterface} from "../interfaces/AddressBookInterface.sol";
import {OtokenInterface} from "../interfaces/OtokenInterface.sol";
import {MarginCalculatorInterface} from "../interfaces/MarginCalculatorInterface.sol";
import {OracleInterface} from "../interfaces/OracleInterface.sol";
import {WhitelistInterface} from "../interfaces/WhitelistInterface.sol";
import {MarginPoolInterface} from "../interfaces/MarginPoolInterface.sol";
import {ControllerInterface} from "../interfaces/ControllerInterface.sol";
/**
* @title Settlement
* @author Rysk Finance
* @notice Contract that handles logic for the Controller on a modified version of Opyn's Gamma protocol
* An extension of the Controller to avoid contract size issues. Error list can be found in Controller.sol
* Main functions callable by Controller
*/
contract ControllerLogic is Initializable, OwnableUpgradeSafe, ReentrancyGuardUpgradeSafe {
using MarginVault for MarginVault.Vault;
using SafeMath for uint256;
AddressBookInterface public addressbook;
WhitelistInterface public whitelist;
MarginCalculatorInterface public calculator;
OracleInterface public oracle;
ControllerInterface public controller;
MarginPoolInterface public pool;
///@dev scale used in MarginCalculator
uint256 internal constant BASE = 8;
///@dev the number of seconds an ITM option is redeemable for after its expiry before the vault is settleable and collateral claimable.
uint256 public redeemTimePeriod;
/// @notice emits an event when a long oToken is deposited into a vault
event LongOtokenDeposited(
address indexed otoken,
address indexed accountOwner,
address indexed from,
uint256 vaultId,
uint256 amount
);
/// @notice emits an event when a long oToken is withdrawn from a vault
event LongOtokenWithdrawed(
address indexed otoken,
address indexed AccountOwner,
address indexed to,
uint256 vaultId,
uint256 amount
);
/// @notice emits an event when a collateral asset is deposited into a vault
event CollateralAssetDeposited(
address indexed asset,
address indexed accountOwner,
address indexed from,
uint256 vaultId,
uint256 amount
);
/// @notice emits an event when a collateral asset is withdrawn from a vault
event CollateralAssetWithdrawed(
address indexed asset,
address indexed AccountOwner,
address indexed to,
uint256 vaultId,
uint256 amount
);
/// @notice emits an event when a short oToken is minted from a vault
event ShortOtokenMinted(
address indexed otoken,
address indexed AccountOwner,
address indexed to,
uint256 vaultId,
uint256 amount
);
/// @notice emits an event when a short oToken is burned
event ShortOtokenBurned(
address indexed otoken,
address indexed AccountOwner,
address indexed from,
uint256 vaultId,
uint256 amount
);
/// @notice emits an event when a vault is settled
event VaultSettled(
address indexed accountOwner,
address indexed oTokenAddress,
address to,
uint256 payout,
uint256 vaultId,
uint256 indexed vaultType
);
/// @notice emits an event when an oToken is redeemed
event Redeem(
address indexed otoken,
address indexed redeemer,
address indexed receiver,
address collateralAsset,
uint256 otokenBurned,
uint256 payout
);
struct SettleMem {
address collateral;
address underlying;
address strike;
uint256 expiry;
uint256 collateralPayout;
uint256 strikePayout;
uint256 strikeCount;
uint256 shortAmount;
bool isValidVault;
uint256 collateralRedemptionBalance;
uint256 receivingAssetBalance;
uint256 otokenQuantity;
uint256 underlyingExpiryPrice;
uint256 collateralExpiryPrice;
}
/**
* @notice check if the sender is the Controller module
*/
modifier onlyController() {
require(
msg.sender == AddressBookInterface(addressbook).getController(),
"ControllerLogic: Sender is not Controller"
);
_;
}
/**
* @notice initalize the deployed contract
* @param _addressbook addressbook module
* @param _owner account owner address
*/
function initialize(address _addressbook, address _owner) external initializer {
require(_addressbook != address(0), "C7");
require(_owner != address(0), "C8");
__Ownable_init(_owner);
__ReentrancyGuard_init_unchained();
addressbook = AddressBookInterface(_addressbook);
redeemTimePeriod = 3600;
}
/**
* @dev updates the configuration of the controller. can only be called by the owner
*/
function refreshConfiguration() external onlyOwner {
_refreshConfigInternal();
}
/**
* @notice get an oToken's payout/cash value after expiry, in the collateral asset
* @param _otoken oToken address
* @param _amount amount of the oToken to calculate the payout for, always represented in 1e8
* @return amount of collateral to pay out
*/
function getPayout(address _otoken, uint256 _amount) public view returns (uint256) {
return calculator.getExpiredPayoutRate(_otoken).mul(_amount).div(10**BASE);
}
/**
* @notice set ITM option redemption time period
* @dev can only be called by owner
* @param _redeemTimePeriod number of seconds an ITM option is redeemable for after its expiry
*/
function setRedeemTimePeriod(uint256 _redeemTimePeriod) external onlyOwner {
require(_redeemTimePeriod > 0, "C38");
redeemTimePeriod = _redeemTimePeriod;
}
function handleDepositLong(Actions.DepositArgs memory _args) external onlyController {
require(whitelist.isWhitelistedOtoken(_args.asset), "C17");
OtokenInterface otoken = OtokenInterface(_args.asset);
require(now < otoken.expiryTimestamp(), "C18");
// dont allow deposit longs for physically settled type 2 vaults and physically settled otokens
require(!otoken.isPhysicallySettled(), "C43");
(, uint256 typeVault, ) = controller.getVaultWithDetails(_args.owner, _args.vaultId);
require(typeVault != 2, "C43");
controller.updateVault(2, _args.owner, _args.vaultId, _args.asset, _args.amount);
pool.transferToPool(_args.asset, _args.from, _args.amount);
emit LongOtokenDeposited(_args.asset, _args.owner, _args.from, _args.vaultId, _args.amount);
}
function handleWithdrawLong(Actions.WithdrawArgs memory _args) external onlyController {
OtokenInterface otoken = OtokenInterface(_args.asset);
require(now < otoken.expiryTimestamp(), "C19");
controller.updateVault(3, _args.owner, _args.vaultId, _args.asset, _args.amount);
pool.transferToUser(_args.asset, _args.to, _args.amount);
emit LongOtokenWithdrawed(_args.asset, _args.owner, _args.to, _args.vaultId, _args.amount);
}
function handleDepositCollateral(Actions.DepositArgs memory _args) external onlyController {
require(whitelist.isWhitelistedCollateral(_args.asset), "C21");
(, uint256 typeVault, ) = controller.getVaultWithDetails(_args.owner, _args.vaultId);
if (typeVault == 1) {
controller.increaseNakedPoolBalance(_args.asset, _args.amount);
require(controller.getNakedPoolBalance(_args.asset) <= controller.getNakedCap(_args.asset), "C37");
}
controller.updateVault(4, _args.owner, _args.vaultId, _args.asset, _args.amount);
pool.transferToPool(_args.asset, _args.from, _args.amount);
emit CollateralAssetDeposited(_args.asset, _args.owner, _args.from, _args.vaultId, _args.amount);
}
function handleWithdrawCollateral(Actions.WithdrawArgs memory _args) external onlyController {
(MarginVault.Vault memory vault, uint256 typeVault, ) = controller.getVaultWithDetails(
_args.owner,
_args.vaultId
);
if (_isNotEmpty(vault.shortOtokens)) {
OtokenInterface otoken = OtokenInterface(vault.shortOtokens[0]);
require(now < otoken.expiryTimestamp(), "C22");
}
if (typeVault == 1) {
controller.reduceNakedPoolBalance(_args.asset, _args.amount);
}
controller.updateVault(5, _args.owner, _args.vaultId, _args.asset, _args.amount);
pool.transferToUser(_args.asset, _args.to, _args.amount);
emit CollateralAssetWithdrawed(_args.asset, _args.owner, _args.to, _args.vaultId, _args.amount);
}
function handleMintOtoken(Actions.MintArgs memory _args, uint256 vaultType) external onlyController {
require(whitelist.isWhitelistedOtoken(_args.otoken), "C23");
OtokenInterface otoken = OtokenInterface(_args.otoken);
require(now < otoken.expiryTimestamp(), "C24");
if (vaultType == 2) {
// this is a physically settled vault
require(otoken.isPhysicallySettled(), "C40");
// increase oTokenQuantity by _args.amount
if(otoken.isPut()) {
// each put is collateralised with the strikePrice amount of collateral asset. so increase collateralBalance by strikePrice per oToken, scaled to collateral decimals
// _args.amount is in e8, strikePrice is in e8, so multiply by collateral asset decimals and divide by e16 to convert to collateral asset decimals
pool.updateRedemptionBalance(
_args.otoken,
int256(_args.amount),
false,
int256(_args.amount.mul(otoken.strikePrice()).mul(10**uint256(ERC20Interface(otoken.collateralAsset()).decimals())).div(1e16))
);
} else {
// each call is collateralised with 1 full collateral asset, so increase collateralBalance by 1 per oToken, scaled to collateral decimals
// _args.amount is in e8, so multiply by collateral asset decimals and divide by e8 to convert to collateral asset decimals
pool.updateRedemptionBalance(
_args.otoken,
int256(_args.amount),
false,
int256(_args.amount.mul(10**uint256(ERC20Interface(otoken.collateralAsset()).decimals())).div(1e8))
);
}
} else {
// this is not a physically settled vault
require(!otoken.isPhysicallySettled(), "C40");
}
controller.updateVault(0, _args.owner, _args.vaultId, _args.otoken, _args.amount);
otoken.mintOtoken(_args.to, _args.amount);
emit ShortOtokenMinted(_args.otoken, _args.owner, _args.to, _args.vaultId, _args.amount);
}
function handleBurnOtoken(Actions.BurnArgs memory _args, uint256 vaultType) external onlyController {
OtokenInterface otoken = OtokenInterface(_args.otoken);
// do not allow burning expired otoken
require(now < otoken.expiryTimestamp(), "C26");
if (vaultType == 2) {
// this is a physically settled vault
require(otoken.isPhysicallySettled(), "C40");
if(otoken.isPut()) {
// decrease oTokenQuantity by number of otokens being burned
// each put is collateralised with the strikePrice amount of collateral asset, so decrease collateralBalance by strikePrice per oToken, scaled to collateral decimals
// _args.amount is in e8, strikePrice is in e8, so multiply by collateral asset decimals and divide by e16 to convert to collateral asset decimals
pool.updateRedemptionBalance(
_args.otoken,
-int256(_args.amount),
false,
-int256(_args.amount.mul(otoken.strikePrice()).mul(10**uint256(ERC20Interface(otoken.collateralAsset()).decimals())).div(1e16))
);
} else {
// decrease oTokenQuantity by number of otokens being burned
// each call is collateralised with 1 full collateral asset, so decrease collateralBalance by 1 per oToken, scaled to collateral decimals
// _args.amount is in e8, so multiply by collateral asset decimals and divide by e8 to convert to collateral asset decimals
pool.updateRedemptionBalance(
_args.otoken,
-int256(_args.amount),
false,
-int256(_args.amount.mul(10**uint256(ERC20Interface(otoken.collateralAsset()).decimals())).div(1e8))
);
}
} else {
// this is not a physically settled vault
require(!otoken.isPhysicallySettled(), "C40");
}
// remove otoken from vault
controller.updateVault(1, _args.owner, _args.vaultId, _args.otoken, _args.amount);
// burn otoken
otoken.burnOtoken(_args.from, _args.amount);
emit ShortOtokenBurned(_args.otoken, _args.owner, _args.from, _args.vaultId, _args.amount);
}
function handleRedeem(Actions.RedeemArgs memory _args, address sender) external onlyController {
OtokenInterface otoken = OtokenInterface(_args.otoken);
// check that otoken to redeem is whitelisted
require(whitelist.isWhitelistedOtoken(_args.otoken), "C27");
(address collateral, address underlying, address strike, uint256 expiry) = _getOtokenDetails(address(otoken));
// only allow redeeming expired otoken
require(now >= expiry, "C28");
require(controller.canSettleAssets(underlying, strike, collateral, expiry), "C29");
if (otoken.isPhysicallySettled()) {
// must be within the redeem time period
require(now < expiry + redeemTimePeriod, "C39");
uint256 strikePrice = otoken.strikePrice();
(uint256 underlyingExpiryPrice,) = oracle.getExpiryPrice(underlying, expiry);
(uint256 collateralExpiryPrice,) = oracle.getExpiryPrice(collateral, expiry);
// get the amount of capital needed to exercise.
// for calls this is strikeAsset, for puts it is underlyingAsset
uint256 strikePayment = calculator.getStrikePaymentAmount(_args.otoken, _args.amount);
if(otoken.isPut()) {
// check put is ITM
require(underlyingExpiryPrice < strikePrice, "C45");
// take the underlying asset payment
_removeExcessCollateralFromRedemptionBalances(otoken, strikePrice, underlyingExpiryPrice, collateralExpiryPrice);
pool.transferToPool(otoken.underlyingAsset(), _args.receiver, strikePayment);
} else {
// check call is ITM
require(underlyingExpiryPrice > strikePrice, "C45");
_removeExcessCollateralFromRedemptionBalances(otoken, strikePrice, underlyingExpiryPrice, collateralExpiryPrice);
// take the strike asset payment
pool.transferToPool(otoken.strikeAsset(), _args.receiver, strikePayment);
}
pool.updateRedemptionBalance(_args.otoken, 0, true, int256(strikePayment));
}
uint256 payout = getPayout(_args.otoken, _args.amount);
otoken.burnOtoken(sender, _args.amount);
pool.transferToUser(collateral, _args.receiver, payout);
if (otoken.isPhysicallySettled()) {
pool.updateRedemptionBalance(_args.otoken, 0, false, -int256(payout));
}
emit Redeem(_args.otoken, sender, _args.receiver, collateral, _args.amount, payout);
}
function handleSettle(Actions.SettleVaultArgs memory _args) external onlyController {
(MarginVault.Vault memory vault, uint256 typeVault, ) = controller.getVaultWithDetails(
_args.owner,
_args.vaultId
);
// check if there is short or long otoken in vault
// do not allow settling vault that have no short or long otoken
// if there is a long otoken, burn it
// store otoken address outside of this scope
bool hasShort = _isNotEmpty(vault.shortOtokens);
bool hasLong = _isNotEmpty(vault.longOtokens);
require(hasShort || hasLong, "C30");
OtokenInterface otoken = hasShort ? OtokenInterface(vault.shortOtokens[0]) : OtokenInterface(vault.longOtokens[0]);
if (hasLong) {
OtokenInterface longOtoken = OtokenInterface(vault.longOtokens[0]);
longOtoken.burnOtoken(address(pool), vault.longAmounts[0]);
}
SettleMem memory settleMem;
( settleMem.collateral, settleMem.underlying, settleMem.strike, settleMem.expiry) = _getOtokenDetails(address(otoken));
// do not allow settling vault with un-expired otoken
if (typeVault == 2) {
require(now >= settleMem.expiry + redeemTimePeriod, "C41");
} else {
require(now >= settleMem.expiry, "C31");
}
require(controller.canSettleAssets(settleMem.underlying, settleMem.strike, settleMem.collateral, settleMem.expiry), "C29");
// this returns any overcollateralisation in the ITM scenario (this includes any amount caused by "overcollateralised" collateral as well as more collateral than was needed
// and returns the exact collateral amount in the case of OTM
(settleMem.collateralPayout, settleMem.isValidVault) = calculator.getExcessCollateral(vault, typeVault);
// require that vault is valid (has excess collateral) before settling
// to avoid allowing settling undercollateralized naked margin vault
// if physically settled vault past its redeem time period, no collateral is required because no more redeems can happen so vault is always valid
// however if calculator.getExcessCollateral returns not valid, settleMem.collateralPayout will be equal to the collateral deficit in the vault
// we do not want to add this to the payout of settlement since it is a deficit, not an excess, so set to zero.
if (
typeVault == 2 && !settleMem.isValidVault
) {
settleMem.isValidVault = true;
settleMem.collateralPayout = 0;
}
require(settleMem.isValidVault, "C32");
// for physically settled vaults, payout is calculated differently
if (typeVault == 2) {
uint256 strikePrice = otoken.strikePrice();
(settleMem.underlyingExpiryPrice,) = oracle.getExpiryPrice(settleMem.underlying, settleMem.expiry);
(settleMem.collateralExpiryPrice,) = oracle.getExpiryPrice(settleMem.collateral, settleMem.expiry);
_removeExcessCollateralFromRedemptionBalances(
otoken,
strikePrice,
settleMem.underlyingExpiryPrice,
settleMem.collateralExpiryPrice
);
(settleMem.collateralRedemptionBalance, settleMem.receivingAssetBalance, settleMem.otokenQuantity) = pool.getRedemptionBalance(address(otoken));
settleMem.shortAmount = vault.shortAmounts[0];
// CALLS:
// strike payment is number of options in vault * strike price, converted to strike decimals
// strikePrice denominatd in e8, shortAmount denominated in e8
// strikePrice * shortAmount * e2 = e18
// divide by (18 - strike decimals) to convert to strike decimals
// assumes strike asset decimals <= 18
// PUTS:
// strike payment is number of options in vault, converted to underying decimals
// shortAmount * e10 = e18
// divide by (18 - underlying decimals) to convert to underlying decimals
settleMem.strikePayout = otoken.isPut() ?
settleMem.shortAmount.mul(1e10).div(10**(18 - uint256(ERC20Interface(settleMem.underlying).decimals()))) :
(strikePrice.mul(settleMem.shortAmount).mul(1e2)).div(10**(18 - uint256(ERC20Interface(settleMem.strike).decimals()))
);
// From here there are three scenarios that can happen:
// 0. (IF OTM) There is no strike asset in the pool. Meaning the user should receive their payment in collateral + any collateral they have from overcollateralisation
// 1. (IF ITM and no strike asset in the pool) Meaning the user should receive their payment in collateral + any collateral they have from overcollateralisation
// 2. (IF ITM not enough strike asset in the pool to pay the strike payment) Meaning the user should receive any remaining strike asset, their remaining payment in collateral + any collateral they have from overcollateralisation
// 3. (IF ITM and there is enough strike asset in the pool to pay the strike payment) Meaning the user should receive their payment in strike + any collateral they have from overcollateralization
if (settleMem.receivingAssetBalance == 0) {
// this is scenario 0 or 1
settleMem.strikePayout = 0;
// each remaining otoken to settle gets an equal share of collateralRedemptionBalance, (for OTM options this is zero)
uint256 vaultShareOfCollateralRedemptionBalance = settleMem.collateralRedemptionBalance.mul(settleMem.shortAmount).div(settleMem.otokenQuantity);
settleMem.collateralPayout += vaultShareOfCollateralRedemptionBalance;
pool.updateRedemptionBalance(address(otoken), -int256(settleMem.shortAmount), false, -int256(vaultShareOfCollateralRedemptionBalance));
} else if (settleMem.strikePayout > settleMem.receivingAssetBalance) {
// this is scenario 2
settleMem.strikePayout = settleMem.receivingAssetBalance;
// find how many options worth of strike payment is in the pool
// CALLS: get receivingAssetBalance and convert to e18 notation then divide by strikePrice * 1e2 (e10) to get e8 value.
// PUTS: get receivingAssetBalance and convert to e8 notation
// assumes strike asset decimals <= 18
settleMem.strikeCount = otoken.isPut() ?
settleMem.receivingAssetBalance.mul(10**(18 - uint256(ERC20Interface(settleMem.underlying).decimals()))).div(1e10) :
settleMem.receivingAssetBalance.mul(10**(18 - uint256(ERC20Interface(settleMem.strike).decimals()))).div(strikePrice.mul(1e2));
// we can get the amount the user is owed in collateral asset by subtracting the strikeCount from the shortAmounts
uint256 contractsLeft = settleMem.shortAmount.sub(settleMem.strikeCount);
// divide collateralRedemptionBalance by total number of options to split between (otokenQuantity - strikeCount) and multiply by contractsLeft
uint256 vaultShareOfCollateralRedemptionBalance = settleMem.collateralRedemptionBalance.mul(contractsLeft).div(settleMem.otokenQuantity.sub(settleMem.strikeCount));
// the collateral payout is whatever it already was + the share of the collateralRedemptionBalance
settleMem.collateralPayout += vaultShareOfCollateralRedemptionBalance;
pool.updateRedemptionBalance(address(otoken), -int256(settleMem.strikeCount), true, -int256(settleMem.strikePayout));
pool.updateRedemptionBalance(address(otoken), -int256(contractsLeft), false, -int256(vaultShareOfCollateralRedemptionBalance));
} else {
// this is scenario 3
pool.updateRedemptionBalance(address(otoken), -int256(settleMem.shortAmount), true, -int256(settleMem.strikePayout));
}
}
controller.updateVault(6, _args.owner, _args.vaultId, address(0), 0);
if (typeVault == 1) {
controller.reduceNakedPoolBalance(settleMem.collateral, settleMem.collateralPayout);
}
pool.transferToUser(settleMem.collateral, _args.to, settleMem.collateralPayout);
if (settleMem.strikePayout > 0) {
pool.transferToUser(otoken.isPut() ? otoken.underlyingAsset() : otoken.strikeAsset(), _args.to, settleMem.strikePayout);
}
uint256 vaultId = _args.vaultId;
address payoutRecipient = _args.to;
emit VaultSettled(_args.owner, address(otoken), payoutRecipient, settleMem.collateralPayout, vaultId, typeVault);
}
function _removeExcessCollateralFromRedemptionBalances(
OtokenInterface otoken,
uint256 strikePrice,
uint256 underlyingExpiryPrice,
uint256 collateralExpiryPrice
) internal {
// now that we know the expiry price of the collateral and underlying assets, we can remove excess collateralRedemptionBalance from the pool
// this simplifies settlement calculations because whatever remains can be split equally between any options that are not able to receive strike asset settlement
(uint256 collateralRedemptionBalance, , uint256 otokenQuantity) = pool.getRedemptionBalance(address(otoken));
uint256 totalExcessInPool;
if(
otoken.isPut() && underlyingExpiryPrice >= strikePrice ||
!otoken.isPut() && underlyingExpiryPrice <= strikePrice
){
// options expired OTM
// no receiving asset consideration, vaults receive all their collateral back
// set collateralRedemptionBalance to 0 since calculator.getExcessCollateral handles this case (because short options are worthless)
// return if already set to 0
if (collateralRedemptionBalance == 0) return;
totalExcessInPool = collateralRedemptionBalance;
} else if(otoken.isPut()) {
// dont need to handle ITM put cases because collateralAsset == strikeAsset, so fully collateralised with no excess.
return;
} else if(!otoken.isPut()) {
// ITM calls
// first, check to see if this has already been done. We only want to do it once, the first time a settle OR redeem is done.
// if is has NOT been done, collateralRedemptionBalance == otokenQuantity (accounting for decimals).
// so we can return if this is not the case because it has already been done
uint256 otokenQuantityCollateralDecimals = otokenQuantity.mul(10**uint256(ERC20Interface(otoken.collateralAsset()).decimals())).div(1e8);
if (collateralRedemptionBalance != otokenQuantityCollateralDecimals) return;
// calls expired ITM
// excess collateral for each option in pool is 1 - underlyingPrice/collateralPrice
// if underlyingPrice >= collateralPrice, there is no excess: set to 0
totalExcessInPool = underlyingExpiryPrice < collateralExpiryPrice ?
otokenQuantityCollateralDecimals.sub(otokenQuantityCollateralDecimals.mul(underlyingExpiryPrice).div(collateralExpiryPrice)) :
0;
}
// reduce value in redemptionBalancePool
pool.updateRedemptionBalance(
address(otoken),
0,
false,
-int(totalExcessInPool)
);
}
/**
* @dev get otoken detail, from both otoken versions
*/
function _getOtokenDetails(address _otoken)
internal
view
returns (
address,
address,
address,
uint256
)
{
OtokenInterface otoken = OtokenInterface(_otoken);
try otoken.getOtokenDetails() returns (
address collateral,
address underlying,
address strike,
uint256,
uint256 expiry,
bool,
bool
) {
return (collateral, underlying, strike, expiry);
} catch {
return (otoken.collateralAsset(), otoken.underlyingAsset(), otoken.strikeAsset(), otoken.expiryTimestamp());
}
}
function _isNotEmpty(address[] memory _array) internal pure returns (bool) {
return (_array.length > 0) && (_array[0] != address(0));
}
/**
* @dev updates the internal configuration of the controller
*/
function _refreshConfigInternal() internal {
whitelist = WhitelistInterface(addressbook.getWhitelist());
controller = ControllerInterface(addressbook.getController());
oracle = OracleInterface(addressbook.getOracle());
calculator = MarginCalculatorInterface(addressbook.getMarginCalculator());
pool = MarginPoolInterface(addressbook.getMarginPool());
}
}// SPDX-License-Identifier: MIT
// openzeppelin-contracts-upgradeable v3.0.0
pragma solidity ^0.6.0;
import "./GSN/ContextUpgradeable.sol";
import "./Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
contract OwnableUpgradeSafe is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init(address _sender) internal initializer {
__Context_init_unchained();
__Ownable_init_unchained(_sender);
}
function __Ownable_init_unchained(address _sender) internal initializer {
_owner = _sender;
emit OwnershipTransferred(address(0), _sender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// openzeppelin-contracts-upgradeable v3.0.0
pragma solidity ^0.6.0;
import "./Initializable.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
contract ReentrancyGuardUpgradeSafe is Initializable {
bool private _notEntered;
function __ReentrancyGuard_init() internal initializer {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal initializer {
// Storing an initial non-zero value makes deployment a bit more
// expensive, but in exchange the refund on every call to nonReentrant
// will be lower in amount. Since refunds are capped to a percetange of
// the total transaction's gas, it is best to keep them low in cases
// like this one, to increase the likelihood of the full refund coming
// into effect.
_notEntered = true;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_notEntered, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_notEntered = false;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_notEntered = true;
}
uint256[49] private __gap;
}// SPDX-License-Identifier: MIT
// openzeppelin-contracts-upgradeable v3.0.0
/* solhint-disable */
pragma solidity >=0.4.24 <0.7.0;
/**
* @title Initializable
*
* @dev Helper contract to support initializer functions. To use it, replace
* the constructor with a function that has the `initializer` modifier.
* WARNING: Unlike constructors, initializer functions must be manually
* invoked. This applies both to deploying an Initializable contract, as well
* as extending an Initializable contract via inheritance.
* WARNING: When used with inheritance, manual care must be taken to not invoke
* a parent initializer twice, or ensure that all initializers are idempotent,
* because this is not dealt with automatically as with constructors.
*/
contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private initializing;
/**
* @dev Modifier to use in the initializer function of a contract.
*/
modifier initializer() {
require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
initialized = true;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
/// @dev Returns true if and only if the function is running in the constructor
function isConstructor() private view returns (bool) {
// extcodesize checks the size of the code stored in an address, and
// address returns the current address. Since the code is still not
// deployed when running a constructor, any checks on its code size will
// yield zero, making it an effective way to detect if a contract is
// under construction or not.
address self = address(this);
uint256 cs;
assembly {
cs := extcodesize(self)
}
return cs == 0;
}
// Reserved storage space to allow for layout changes in the future.
uint256[50] private ______gap;
}// SPDX-License-Identifier: MIT
// openzeppelin-contracts v3.1.0
/* solhint-disable */
pragma solidity ^0.6.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}/**
* SPDX-License-Identifier: UNLICENSED
*/
pragma solidity =0.6.10;
pragma experimental ABIEncoderV2;
import {SafeMath} from "../packages/oz/SafeMath.sol";
/**
* MarginVault Error Codes
* V1: invalid short otoken amount
* V2: invalid short otoken index
* V3: short otoken address mismatch
* V4: invalid long otoken amount
* V5: invalid long otoken index
* V6: long otoken address mismatch
* V7: invalid collateral amount
* V8: invalid collateral token index
* V9: collateral token address mismatch
*/
/**
* @title MarginVault
* @author Opyn Team
* @notice A library that provides the Controller with a Vault struct and the functions that manipulate vaults.
* Vaults describe discrete position combinations of long options, short options, and collateral assets that a user can have.
*/
library MarginVault {
using SafeMath for uint256;
// vault is a struct of 6 arrays that describe a position a user has, a user can have multiple vaults.
struct Vault {
// addresses of oTokens a user has shorted (i.e. written) against this vault
address[] shortOtokens;
// addresses of oTokens a user has bought and deposited in this vault
// user can be long oTokens without opening a vault (e.g. by buying on a DEX)
// generally, long oTokens will be 'deposited' in vaults to act as collateral in order to write oTokens against (i.e. in spreads)
address[] longOtokens;
// addresses of other ERC-20s a user has deposited as collateral in this vault
address[] collateralAssets;
// quantity of oTokens minted/written for each oToken address in shortOtokens
uint256[] shortAmounts;
// quantity of oTokens owned and held in the vault for each oToken address in longOtokens
uint256[] longAmounts;
// quantity of ERC-20 deposited as collateral in the vault for each ERC-20 address in collateralAssets
uint256[] collateralAmounts;
}
// vaultLiquidationDetails is a struct of 3 variables that store the series address, short amount liquidated and collateral transferred for
// a given liquidation
struct VaultLiquidationDetails {
address series;
uint128 shortAmount;
uint128 collateralAmount;
}
/**
* @dev increase the short oToken balance in a vault when a new oToken is minted
* @param _vault vault to add or increase the short position in
* @param _shortOtoken address of the _shortOtoken being minted from the user's vault
* @param _amount number of _shortOtoken being minted from the user's vault
* @param _index index of _shortOtoken in the user's vault.shortOtokens array
*/
function addShort(
Vault storage _vault,
address _shortOtoken,
uint256 _amount,
uint256 _index
) external {
require(_amount > 0, "V1");
// valid indexes in any array are between 0 and array.length - 1.
// if adding an amount to an preexisting short oToken, check that _index is in the range of 0->length-1
if ((_index == _vault.shortOtokens.length) && (_index == _vault.shortAmounts.length)) {
_vault.shortOtokens.push(_shortOtoken);
_vault.shortAmounts.push(_amount);
} else {
require((_index < _vault.shortOtokens.length) && (_index < _vault.shortAmounts.length), "V2");
address existingShort = _vault.shortOtokens[_index];
require((existingShort == _shortOtoken) || (existingShort == address(0)), "V3");
_vault.shortAmounts[_index] = _vault.shortAmounts[_index].add(_amount);
_vault.shortOtokens[_index] = _shortOtoken;
}
}
/**
* @dev decrease the short oToken balance in a vault when an oToken is burned
* @param _vault vault to decrease short position in
* @param _shortOtoken address of the _shortOtoken being reduced in the user's vault
* @param _amount number of _shortOtoken being reduced in the user's vault
* @param _index index of _shortOtoken in the user's vault.shortOtokens array
*/
function removeShort(
Vault storage _vault,
address _shortOtoken,
uint256 _amount,
uint256 _index
) external {
// check that the removed short oToken exists in the vault at the specified index
require(_index < _vault.shortOtokens.length, "V2");
require(_vault.shortOtokens[_index] == _shortOtoken, "V3");
uint256 newShortAmount = _vault.shortAmounts[_index].sub(_amount);
if (newShortAmount == 0) {
delete _vault.shortOtokens[_index];
}
_vault.shortAmounts[_index] = newShortAmount;
}
/**
* @dev increase the long oToken balance in a vault when an oToken is deposited
* @param _vault vault to add a long position to
* @param _longOtoken address of the _longOtoken being added to the user's vault
* @param _amount number of _longOtoken the protocol is adding to the user's vault
* @param _index index of _longOtoken in the user's vault.longOtokens array
*/
function addLong(
Vault storage _vault,
address _longOtoken,
uint256 _amount,
uint256 _index
) external {
require(_amount > 0, "V4");
// valid indexes in any array are between 0 and array.length - 1.
// if adding an amount to an preexisting short oToken, check that _index is in the range of 0->length-1
if ((_index == _vault.longOtokens.length) && (_index == _vault.longAmounts.length)) {
_vault.longOtokens.push(_longOtoken);
_vault.longAmounts.push(_amount);
} else {
require((_index < _vault.longOtokens.length) && (_index < _vault.longAmounts.length), "V5");
address existingLong = _vault.longOtokens[_index];
require((existingLong == _longOtoken) || (existingLong == address(0)), "V6");
_vault.longAmounts[_index] = _vault.longAmounts[_index].add(_amount);
_vault.longOtokens[_index] = _longOtoken;
}
}
/**
* @dev decrease the long oToken balance in a vault when an oToken is withdrawn
* @param _vault vault to remove a long position from
* @param _longOtoken address of the _longOtoken being removed from the user's vault
* @param _amount number of _longOtoken the protocol is removing from the user's vault
* @param _index index of _longOtoken in the user's vault.longOtokens array
*/
function removeLong(
Vault storage _vault,
address _longOtoken,
uint256 _amount,
uint256 _index
) external {
// check that the removed long oToken exists in the vault at the specified index
require(_index < _vault.longOtokens.length, "V5");
require(_vault.longOtokens[_index] == _longOtoken, "V6");
uint256 newLongAmount = _vault.longAmounts[_index].sub(_amount);
if (newLongAmount == 0) {
delete _vault.longOtokens[_index];
}
_vault.longAmounts[_index] = newLongAmount;
}
/**
* @dev increase the collateral balance in a vault
* @param _vault vault to add collateral to
* @param _collateralAsset address of the _collateralAsset being added to the user's vault
* @param _amount number of _collateralAsset being added to the user's vault
* @param _index index of _collateralAsset in the user's vault.collateralAssets array
*/
function addCollateral(
Vault storage _vault,
address _collateralAsset,
uint256 _amount,
uint256 _index
) external {
require(_amount > 0, "V7");
// valid indexes in any array are between 0 and array.length - 1.
// if adding an amount to an preexisting short oToken, check that _index is in the range of 0->length-1
if ((_index == _vault.collateralAssets.length) && (_index == _vault.collateralAmounts.length)) {
_vault.collateralAssets.push(_collateralAsset);
_vault.collateralAmounts.push(_amount);
} else {
require((_index < _vault.collateralAssets.length) && (_index < _vault.collateralAmounts.length), "V8");
address existingCollateral = _vault.collateralAssets[_index];
require((existingCollateral == _collateralAsset) || (existingCollateral == address(0)), "V9");
_vault.collateralAmounts[_index] = _vault.collateralAmounts[_index].add(_amount);
_vault.collateralAssets[_index] = _collateralAsset;
}
}
/**
* @dev decrease the collateral balance in a vault
* @param _vault vault to remove collateral from
* @param _collateralAsset address of the _collateralAsset being removed from the user's vault
* @param _amount number of _collateralAsset being removed from the user's vault
* @param _index index of _collateralAsset in the user's vault.collateralAssets array
*/
function removeCollateral(
Vault storage _vault,
address _collateralAsset,
uint256 _amount,
uint256 _index
) external {
// check that the removed collateral exists in the vault at the specified index
require(_index < _vault.collateralAssets.length, "V8");
require(_vault.collateralAssets[_index] == _collateralAsset, "V9");
uint256 newCollateralAmount = _vault.collateralAmounts[_index].sub(_amount);
if (newCollateralAmount == 0) {
delete _vault.collateralAssets[_index];
}
_vault.collateralAmounts[_index] = newCollateralAmount;
}
}/**
* SPDX-License-Identifier: UNLICENSED
*/
pragma solidity 0.6.10;
import {MarginVault} from "./MarginVault.sol";
/**
* @title Actions
* @author Opyn Team
* @notice A library that provides a ActionArgs struct, sub types of Action structs, and functions to parse ActionArgs into specific Actions.
* errorCode
* A1 can only parse arguments for open vault actions
* A2 cannot open vault for an invalid account
* A3 cannot open vault with an invalid type
* A4 can only parse arguments for mint actions
* A5 cannot mint from an invalid account
* A6 can only parse arguments for burn actions
* A7 cannot burn from an invalid account
* A8 can only parse arguments for deposit actions
* A9 cannot deposit to an invalid account
* A10 can only parse arguments for withdraw actions
* A11 cannot withdraw from an invalid account
* A12 cannot withdraw to an invalid account
* A13 can only parse arguments for redeem actions
* A14 cannot redeem to an invalid account
* A15 can only parse arguments for settle vault actions
* A16 cannot settle vault for an invalid account
* A17 cannot withdraw payout to an invalid account
* A18 can only parse arguments for liquidate action
* A19 cannot liquidate vault for an invalid account owner
* A20 cannot send collateral to an invalid account
* A21 cannot parse liquidate action with no round id
* A22 can only parse arguments for call actions
* A23 target address cannot be address(0)
*/
library Actions {
// possible actions that can be performed
enum ActionType {
OpenVault,
MintShortOption,
BurnShortOption,
DepositLongOption,
WithdrawLongOption,
DepositCollateral,
WithdrawCollateral,
SettleVault,
Redeem,
Call,
Liquidate
}
struct ActionArgs {
// type of action that is being performed on the system
ActionType actionType;
// address of the account owner
address owner;
// address which we move assets from or to (depending on the action type)
address secondAddress;
// asset that is to be transfered
address asset;
// index of the vault that is to be modified (if any)
uint256 vaultId;
// amount of asset that is to be transfered
uint256 amount;
// 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;
// any other data that needs to be passed in for arbitrary function calls
bytes data;
}
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;
}
struct BurnArgs {
// 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;
// oToken that is to be burned
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 burned
uint256 amount;
}
struct OpenVaultArgs {
// address of the account owner
address owner;
// vault id to create
uint256 vaultId;
// vault type, 0 for spread/max loss and 1 for naked margin vault, 2 for physially settled
uint256 vaultType;
}
struct DepositArgs {
// 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;
// asset that is to be deposited
address asset;
// 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 asset that is to be deposited
uint256 amount;
}
struct RedeemArgs {
// address to which we pay out the oToken proceeds
address receiver;
// oToken that is to be redeemed
address otoken;
// amount of oTokens that is to be redeemed
uint256 amount;
}
struct WithdrawArgs {
// address of the account owner
address owner;
// index of the vault from which the asset will be withdrawn
uint256 vaultId;
// address to which we transfer the asset
address to;
// asset that is to be withdrawn
address asset;
// 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 asset that is to be withdrawn
uint256 amount;
}
struct SettleVaultArgs {
// address of the account owner
address owner;
// index of the vault to which is to be settled
uint256 vaultId;
// address to which we transfer the remaining collateral
address to;
}
struct LiquidateArgs {
// address of the vault owner to liquidate
address owner;
// address of the liquidated collateral receiver
address receiver;
// vault id to liquidate
uint256 vaultId;
// amount of debt(otoken) to repay
uint256 amount;
// chainlink round id
uint256 roundId;
}
/**
* @notice parses the passed in action arguments to get the arguments for an open vault action
* @param _args general action arguments structure
* @return arguments for a open vault action
*/
function _parseOpenVaultArgs(ActionArgs memory _args) internal pure returns (OpenVaultArgs memory) {
require(_args.actionType == ActionType.OpenVault, "A1");
require(_args.owner != address(0), "A2");
// if not _args.data included, vault type will be 0 by default
uint256 vaultType;
if (_args.data.length == 32) {
// decode vault type from _args.data
vaultType = abi.decode(_args.data, (uint256));
}
// for now we only have 3 vault types
require(vaultType < 3, "A3");
return OpenVaultArgs({owner: _args.owner, vaultId: _args.vaultId, vaultType: vaultType});
}
/**
* @notice parses the passed in action arguments to get the arguments for a mint action
* @param _args general action arguments structure
* @return arguments for a mint action
*/
function _parseMintArgs(ActionArgs memory _args) internal pure returns (MintArgs memory) {
require(_args.actionType == ActionType.MintShortOption, "A4");
require(_args.owner != address(0), "A5");
return
MintArgs({
owner: _args.owner,
vaultId: _args.vaultId,
to: _args.secondAddress,
otoken: _args.asset,
index: _args.index,
amount: _args.amount
});
}
/**
* @notice parses the passed in action arguments to get the arguments for a burn action
* @param _args general action arguments structure
* @return arguments for a burn action
*/
function _parseBurnArgs(ActionArgs memory _args) internal pure returns (BurnArgs memory) {
require(_args.actionType == ActionType.BurnShortOption, "A6");
require(_args.owner != address(0), "A7");
return
BurnArgs({
owner: _args.owner,
vaultId: _args.vaultId,
from: _args.secondAddress,
otoken: _args.asset,
index: _args.index,
amount: _args.amount
});
}
/**
* @notice parses the passed in action arguments to get the arguments for a deposit action
* @param _args general action arguments structure
* @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.owner != address(0), "A9");
return
DepositArgs({
owner: _args.owner,
vaultId: _args.vaultId,
from: _args.secondAddress,
asset: _args.asset,
index: _args.index,
amount: _args.amount
});
}
/**
* @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.owner != address(0), "A11");
require(_args.secondAddress != address(0), "A12");
return
WithdrawArgs({
owner: _args.owner,
vaultId: _args.vaultId,
to: _args.secondAddress,
asset: _args.asset,
index: _args.index,
amount: _args.amount
});
}
/**
* @notice parses the passed in action arguments to get the arguments for an redeem action
* @param _args general action arguments structure
* @return arguments for a redeem action
*/
function _parseRedeemArgs(ActionArgs memory _args) internal pure returns (RedeemArgs memory) {
require(_args.actionType == ActionType.Redeem, "A13");
require(_args.secondAddress != address(0), "A14");
return RedeemArgs({receiver: _args.secondAddress, otoken: _args.asset, amount: _args.amount});
}
/**
* @notice parses the passed in action arguments to get the arguments for a settle vault action
* @param _args general action arguments structure
* @return arguments for a settle vault action
*/
function _parseSettleVaultArgs(ActionArgs memory _args) internal pure returns (SettleVaultArgs memory) {
require(_args.actionType == ActionType.SettleVault, "A15");
require(_args.owner != address(0), "A16");
require(_args.secondAddress != address(0), "A17");
return SettleVaultArgs({owner: _args.owner, vaultId: _args.vaultId, to: _args.secondAddress});
}
function _parseLiquidateArgs(ActionArgs memory _args) internal pure returns (LiquidateArgs memory) {
require(_args.actionType == ActionType.Liquidate, "A18");
require(_args.owner != address(0), "A19");
require(_args.secondAddress != address(0), "A20");
require(_args.data.length == 32, "A21");
// decode chainlink round id from _args.data
uint256 roundId = abi.decode(_args.data, (uint256));
return
LiquidateArgs({
owner: _args.owner,
receiver: _args.secondAddress,
vaultId: _args.vaultId,
amount: _args.amount,
roundId: roundId
});
}
}/**
* SPDX-License-Identifier: UNLICENSED
*/
pragma solidity 0.6.10;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface ERC20Interface {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
function decimals() external view returns (uint8);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.10;
interface AddressBookInterface {
/* Getters */
function getOtokenImpl() external view returns (address);
function getOtokenFactory() external view returns (address);
function getWhitelist() external view returns (address);
function getController() external view returns (address);
function getOracle() external view returns (address);
function getMarginPool() external view returns (address);
function getMarginCalculator() external view returns (address);
function getControllerLogic() external view returns (address);
function getLiquidationManager() external view returns (address);
function getAddress(bytes32 _id) external view returns (address);
function getKeeper() external view returns (address);
/* Setters */
function setOtokenImpl(address _otokenImpl) external;
function setOtokenFactory(address _factory) external;
function setOracleImpl(address _otokenImpl) external;
function setWhitelist(address _whitelist) external;
function setController(address _controller) external;
function setMarginPool(address _marginPool) external;
function setMarginCalculator(address _calculator) external;
function setControllerLogic(address _settlement) external;
function setLiquidationManager(address _liquidationManager) external;
function setAddress(bytes32 _id, address _newImpl) external;
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.10;
interface OtokenInterface {
function addressBook() external view returns (address);
function underlyingAsset() external view returns (address);
function strikeAsset() external view returns (address);
function collateralAsset() external view returns (address);
function strikePrice() external view returns (uint256);
function expiryTimestamp() external view returns (uint256);
function isPut() external view returns (bool);
function isPhysicallySettled() external view returns (bool);
function init(
address _addressBook,
address _underlyingAsset,
address _strikeAsset,
address _collateralAsset,
uint256 _strikePrice,
uint256 _expiry,
bool _isPut,
bool _isPhysicallySettled
) external;
function getOtokenDetails()
external
view
returns (
address,
address,
address,
uint256,
uint256,
bool,
bool
);
function mintOtoken(address account, uint256 amount) external;
function burnOtoken(address account, uint256 amount) external;
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.10;
pragma experimental ABIEncoderV2;
import {MarginVault} from "../libs/MarginVault.sol";
interface MarginCalculatorInterface {
function addressBook() external view returns (address);
function getExpiredPayoutRate(address _otoken) external view returns (uint256);
function getStrikePaymentAmount(address _otoken, uint256 _amount) external view returns (uint256);
function getExcessCollateral(MarginVault.Vault calldata _vault, uint256 _vaultType)
external
view
returns (uint256 netValue, bool isExcess);
function isLiquidatable(MarginVault.Vault memory _vault, uint256 _vaultType)
external
view
returns (
bool,
uint256,
uint256
);
function getFeeInformation() external view returns (uint256, address);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.10;
interface OracleInterface {
function isLockingPeriodOver(address _asset, uint256 _expiryTimestamp) external view returns (bool);
function isDisputePeriodOver(address _asset, uint256 _expiryTimestamp) external view returns (bool);
function getExpiryPrice(address _asset, uint256 _expiryTimestamp) external view returns (uint256, bool);
function getDisputer() external view returns (address);
function getPricer(address _asset) external view returns (address);
function getPrice(address _asset) external view returns (uint256);
function getPricerLockingPeriod(address _pricer) external view returns (uint256);
function getPricerDisputePeriod(address _pricer) external view returns (uint256);
function getChainlinkRoundData(address _asset, uint80 _roundId) external view returns (uint256, uint256);
// Non-view function
function setAssetPricer(address _asset, address _pricer) external;
function setLockingPeriod(address _pricer, uint256 _lockingPeriod) external;
function setDisputePeriod(address _pricer, uint256 _disputePeriod) external;
function setExpiryPrice(
address _asset,
uint256 _expiryTimestamp,
uint256 _price
) external;
function disputeExpiryPrice(
address _asset,
uint256 _expiryTimestamp,
uint256 _price
) external;
function setDisputer(address _disputer) external;
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.10;
interface WhitelistInterface {
/* View functions */
function addressBook() external view returns (address);
function isWhitelistedProduct(
address _underlying,
address _strike,
address _collateral,
bool _isPut
) external view returns (bool);
function isWhitelistedCollateral(address _collateral) external view returns (bool);
function isCoveredWhitelistedCollateral(
address _collateral,
address _underlying,
bool _isPut
) external view returns (bool);
function isNakedWhitelistedCollateral(
address _collateral,
address _underlying,
bool _isPut
) external view returns (bool);
function isWhitelistedOtoken(address _otoken) external view returns (bool);
function isWhitelistedCallee(address _callee) external view returns (bool);
/* Admin / factory only functions */
function whitelistProduct(
address _underlying,
address _strike,
address _collateral,
bool _isPut
) external;
function blacklistProduct(
address _underlying,
address _strike,
address _collateral,
bool _isPut
) external;
function whitelistCollateral(address _collateral) external;
function blacklistCollateral(address _collateral) external;
function whitelistCoveredCollateral(
address _collateral,
address _underlying,
bool _isPut
) external;
function whitelistNakedCollateral(
address _collateral,
address _underlying,
bool _isPut
) external;
function whitelistOtoken(address _otoken) external;
function blacklistOtoken(address _otoken) external;
function whitelistCallee(address _callee) external;
function blacklistCallee(address _callee) external;
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.10;
interface MarginPoolInterface {
/* Getters */
function addressBook() external view returns (address);
function farmer() external view returns (address);
function getStoredBalance(address _asset) external view returns (uint256);
/* Admin-only functions */
function setFarmer(address _farmer) external;
function farm(
address _asset,
address _receiver,
uint256 _amount
) external;
/* Controller-only functions */
function transferToPool(
address _asset,
address _user,
uint256 _amount
) external;
function transferToUser(
address _asset,
address _user,
uint256 _amount
) external;
function batchTransferToPool(
address[] calldata _asset,
address[] calldata _user,
uint256[] calldata _amount
) external;
function batchTransferToUser(
address[] calldata _asset,
address[] calldata _user,
uint256[] calldata _amount
) external;
function updateRedemptionBalance(
address _otoken,
int256 _otokenAmount,
bool _isStrikeAsset,
int256 _assetAmount
) external;
function getRedemptionBalance(address _otoken)
external
view
returns (
uint256,
uint256,
uint256
);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.6.10;
pragma experimental ABIEncoderV2;
import {MarginVault} from "../libs/MarginVault.sol";
interface ControllerInterface {
function getNakedCap(address _asset) external view returns (uint256);
function getNakedPoolBalance(address _asset) external view returns (uint256);
function getVaultWithDetails(address, uint256)
external
view
returns (
MarginVault.Vault memory,
uint256,
uint256
);
function canSettleAssets(
address _underlying,
address _strike,
address _collateral,
uint256 _expiry
) external view returns (bool);
function removeVaultCollateral(
address _owner,
uint256 _vaultId,
address _asset,
uint256 _amount
) external;
function updateVault(
uint8 _action,
address _owner,
uint256 _vaultId,
address _asset,
uint256 _amount
) external;
function increaseNakedPoolBalance(address _asset, uint256 _amount) external;
function reduceNakedPoolBalance(address _asset, uint256 _amount) external;
function deleteVault(address, uint256) external;
function redeemTimePeriod() external view returns (uint256);
}// SPDX-License-Identifier: MIT
// openzeppelin-contracts-upgradeable v3.0.0
pragma solidity >=0.6.0 <0.8.0;
import "../Initializable.sol";
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {}
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
uint256[50] private __gap;
}{
"remappings": [
"@ensdomains/=node_modules/@ensdomains/",
"@openzeppelin/=node_modules/@openzeppelin/",
"@solidity-parser/=node_modules/solhint/node_modules/@solidity-parser/",
"eth-gas-reporter/=node_modules/eth-gas-reporter/",
"truffle/=node_modules/truffle/",
"forge-std/=lib/forge-std/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "istanbul",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"accountOwner","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CollateralAssetDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"address","name":"AccountOwner","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"CollateralAssetWithdrawed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"otoken","type":"address"},{"indexed":true,"internalType":"address","name":"accountOwner","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LongOtokenDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"otoken","type":"address"},{"indexed":true,"internalType":"address","name":"AccountOwner","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LongOtokenWithdrawed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"otoken","type":"address"},{"indexed":true,"internalType":"address","name":"redeemer","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"collateralAsset","type":"address"},{"indexed":false,"internalType":"uint256","name":"otokenBurned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payout","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"otoken","type":"address"},{"indexed":true,"internalType":"address","name":"AccountOwner","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ShortOtokenBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"otoken","type":"address"},{"indexed":true,"internalType":"address","name":"AccountOwner","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ShortOtokenMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"accountOwner","type":"address"},{"indexed":true,"internalType":"address","name":"oTokenAddress","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"payout","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"vaultType","type":"uint256"}],"name":"VaultSettled","type":"event"},{"inputs":[],"name":"addressbook","outputs":[{"internalType":"contract AddressBookInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calculator","outputs":[{"internalType":"contract MarginCalculatorInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"contract ControllerInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_otoken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"getPayout","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"otoken","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Actions.BurnArgs","name":"_args","type":"tuple"},{"internalType":"uint256","name":"vaultType","type":"uint256"}],"name":"handleBurnOtoken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Actions.DepositArgs","name":"_args","type":"tuple"}],"name":"handleDepositCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Actions.DepositArgs","name":"_args","type":"tuple"}],"name":"handleDepositLong","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"otoken","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Actions.MintArgs","name":"_args","type":"tuple"},{"internalType":"uint256","name":"vaultType","type":"uint256"}],"name":"handleMintOtoken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"otoken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Actions.RedeemArgs","name":"_args","type":"tuple"},{"internalType":"address","name":"sender","type":"address"}],"name":"handleRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"internalType":"struct Actions.SettleVaultArgs","name":"_args","type":"tuple"}],"name":"handleSettle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Actions.WithdrawArgs","name":"_args","type":"tuple"}],"name":"handleWithdrawCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"vaultId","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct Actions.WithdrawArgs","name":"_args","type":"tuple"}],"name":"handleWithdrawLong","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_addressbook","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract OracleInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"contract MarginPoolInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redeemTimePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refreshConfiguration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_redeemTimePeriod","type":"uint256"}],"name":"setRedeemTimePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"whitelist","outputs":[{"internalType":"contract WhitelistInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
0x608060405234801561001057600080fd5b506159c780620000216000396000f3fe608060405234801561001057600080fd5b50600436106101425760003560e01c806393e59dc1116100b8578063cd291bc61161007c578063cd291bc614610244578063ce3e39c014610257578063f2fde38b1461025f578063f4d1c98b14610272578063f77c479114610285578063f91ee2a61461028d57610142565b806393e59dc1146101fb578063a31634df14610203578063b1668b8d14610216578063b46cd0a914610229578063c2d8cfea1461023157610142565b8063646810831161010a57806364681083146101c05780636af48086146101c857806370dc320c146101db578063715018a6146101e35780637dc0d1d0146101eb5780638da5cb5b146101f357610142565b8063020046941461014757806316f0115b1461015c57806333b77c5e1461017a578063485cc9551461018d578063565eea19146101a0575b600080fd5b61015a61015536600461508d565b6102a0565b005b610164611321565b604051610171919061531b565b60405180910390f35b61015a610188366004614fe3565b611330565b61015a61019b366004614edc565b611b90565b6101b36101ae366004614f9c565b611c93565b6040516101719190615910565b61015a611d2d565b61015a6101d636600461500d565b611d6c565b61016461213c565b61015a61214b565b6101646121ca565b6101646121d9565b6101646121e8565b61015a610211366004615207565b6121f7565b61015a610224366004614fe3565b612251565b6101b361281f565b61015a61023f366004615028565b612825565b61015a61025236600461500d565b613256565b61016461372a565b61015a61026d366004614ea4565b613739565b61015a61028036600461500d565b6137f0565b610164613c67565b61015a61029b36600461500d565b613c76565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156102ee57600080fd5b505afa158015610302573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103269190614ec0565b6001600160a01b0316336001600160a01b03161461035f5760405162461bcd60e51b81526004016103569061567c565b60405180910390fd5b610367614c97565b60cd54825160208401516040516313b55f7d60e31b81526000936001600160a01b031692639daafbe89261039d926004016153a5565b60006040518083038186803b1580156103b557600080fd5b505afa1580156103c9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103f191908101906150d9565b509150915060006104058360000151613f11565b905060006104168460200151613f11565b905081806104215750805b61043d5760405162461bcd60e51b815260040161035690615787565b60008261046257846020015160008151811061045557fe5b6020026020010151610478565b8451805160009061046f57fe5b60200260200101515b9050811561052c576000856020015160008151811061049357fe5b60200260200101519050806001600160a01b03166356d878f760ce60009054906101000a90046001600160a01b031688608001516000815181106104d357fe5b60200260200101516040518363ffffffff1660e01b81526004016104f89291906153a5565b600060405180830381600087803b15801561051257600080fd5b505af1158015610526573d6000803e3d6000fd5b50505050505b610534614ccd565b61053d82613f4f565b60608501526001600160a01b039081166040850152908116602084015216815260028514156105935760cf5481606001510142101561058e5760405162461bcd60e51b815260040161035690615576565b6105b7565b80606001514210156105b75760405162461bcd60e51b81526004016103569061553c565b60cd5460208201516040808401518451606086015192516314b93faf60e01b81526001600160a01b03909516946314b93faf946105fa949093929160040161532f565b60206040518083038186803b15801561061257600080fd5b505afa158015610626573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064a9190614fc7565b6106665760405162461bcd60e51b81526004016103569061576a565b60cb5460405163cd43fbfb60e01b81526001600160a01b039091169063cd43fbfb906106989089908990600401615851565b604080518083038186803b1580156106af57600080fd5b505afa1580156106c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e79190615237565b151561010083015260808201526002851480156107075750806101000151155b1561071c576001610100820152600060808201525b80610100015161073e5760405162461bcd60e51b8152600401610356906154e5565b8460021415610f83576000826001600160a01b031663c52987cf6040518163ffffffff1660e01b815260040160206040518083038186803b15801561078257600080fd5b505afa158015610796573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ba919061521f565b60cc54602084015160608501516040516301957f8160e01b81529394506001600160a01b03909216926301957f81926107f692916004016153a5565b604080518083038186803b15801561080d57600080fd5b505afa158015610821573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108459190615237565b5061018083015260cc54825160608401516040516301957f8160e01b81526001600160a01b03909316926301957f81926108839290916004016153a5565b604080518083038186803b15801561089a57600080fd5b505afa1580156108ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d29190615237565b506101a083018190526101808301516108ee91859184916141b6565b60ce54604051635d5286ff60e01b81526001600160a01b0390911690635d5286ff9061091e90869060040161531b565b60606040518083038186803b15801561093657600080fd5b505afa15801561094a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096e919061525b565b6101608501526101408401526101208301526060870151805160009061099057fe5b60200260200101518260e0018181525050826001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b1580156109da57600080fd5b505afa1580156109ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a129190614fc7565b610ad057610acb82604001516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610a5657600080fd5b505afa158015610a6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8e9190615288565b60ff16601203600a0a610abf6064610ab38660e001518661460d90919063ffffffff16565b9063ffffffff61460d16565b9063ffffffff61464716565b610b6d565b610b6d82602001516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610b1057600080fd5b505afa158015610b24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b489190615288565b60ff16601203600a0a610abf6402540be4008560e0015161460d90919063ffffffff16565b60a0830152610140820151610c2f57600060a0830181905261016083015160e0840151610120850151610bab9291610abf919063ffffffff61460d16565b6080840180518201905260ce5460e0850151604051638c0fb97b60e01b81529293506001600160a01b0390911691638c0fb97b91610bf79188916000908103918782039060040161537d565b600060405180830381600087803b158015610c1157600080fd5b505af1158015610c25573d6000803e3d6000fd5b5050505050610f81565b8161014001518260a001511115610f08578161014001518260a0018181525050826001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b158015610c8857600080fd5b505afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc09190614fc7565b610d7057610d6b610cd882606463ffffffff61460d16565b610abf84604001516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610d1857600080fd5b505afa158015610d2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d509190615288565b6101408601519060ff16601203600a0a63ffffffff61460d16565b610db9565b610db96402540be400610abf84602001516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610d1857600080fd5b60c0830181905260e0830151600091610dd8919063ffffffff61468916565b90506000610e11610dfb8560c0015186610160015161468990919063ffffffff16565b610120860151610abf908563ffffffff61460d16565b6080850180518201905260ce5460c086015160a0870151604051638c0fb97b60e01b81529394506001600160a01b0390921692638c0fb97b92610e63928a92600091820392600192039060040161537d565b600060405180830381600087803b158015610e7d57600080fd5b505af1158015610e91573d6000803e3d6000fd5b505060ce54604051638c0fb97b60e01b81526001600160a01b039091169250638c0fb97b9150610ecf9088906000878103918782039060040161537d565b600060405180830381600087803b158015610ee957600080fd5b505af1158015610efd573d6000803e3d6000fd5b505050505050610f81565b60ce5460e083015160a0840151604051638c0fb97b60e01b81526001600160a01b0390931692638c0fb97b92610f4e92889260009283039260019290039060040161537d565b600060405180830381600087803b158015610f6857600080fd5b505af1158015610f7c573d6000803e3d6000fd5b505050505b505b60cd54875160208901516040516380f0d75160e01b81526001600160a01b03909316926380f0d75192610fc09260069260009081906004016153df565b600060405180830381600087803b158015610fda57600080fd5b505af1158015610fee573d6000803e3d6000fd5b5050505084600114156110655760cd54815160808301516040516315db745960e31b81526001600160a01b039093169263aedba2c8926110329290916004016153a5565b600060405180830381600087803b15801561104c57600080fd5b505af1158015611060573d6000803e3d6000fd5b505050505b60ce5481516040808a01516080850151915163fa93b2a560e01b81526001600160a01b039094169363fa93b2a5936110a293909291600401615359565b600060405180830381600087803b1580156110bc57600080fd5b505af11580156110d0573d6000803e3d6000fd5b5050505060a0810151156112b95760ce60009054906101000a90046001600160a01b03166001600160a01b031663fa93b2a5836001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b15801561113b57600080fd5b505afa15801561114f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111739190614fc7565b6111ed57836001600160a01b03166317d69bc86040518163ffffffff1660e01b815260040160206040518083038186803b1580156111b057600080fd5b505afa1580156111c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e89190614ec0565b61125e565b836001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561122657600080fd5b505afa15801561123a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125e9190614ec0565b89604001518460a001516040518463ffffffff1660e01b815260040161128693929190615359565b600060405180830381600087803b1580156112a057600080fd5b505af11580156112b4573d6000803e3d6000fd5b505050505b6020870151604080890151895160808501519251919289926001600160a01b038089169316917f522cda7dd0677ee4c9512efd8aa92af93de64b4c2fe2f8bfe7a9234a655a9bf59161130e91879189906153be565b60405180910390a4505050505050505050565b60ce546001600160a01b031681565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561137e57600080fd5b505afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b69190614ec0565b6001600160a01b0316336001600160a01b0316146113e65760405162461bcd60e51b81526004016103569061567c565b60ca5460608301516040516302328d7360e31b81526001600160a01b03909216916311946b98916114199160040161531b565b60206040518083038186803b15801561143157600080fd5b505afa158015611445573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114699190614fc7565b6114855760405162461bcd60e51b815260040161035690615502565b600082606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c757600080fd5b505afa1580156114db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ff919061521f565b421061151d5760405162461bcd60e51b8152600401610356906155af565b81600214156119b357806001600160a01b031663504592cd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561155f57600080fd5b505afa158015611573573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115979190614fc7565b6115b35760405162461bcd60e51b815260040161035690615482565b806001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b1580156115ec57600080fd5b505afa158015611600573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116249190614fc7565b156118295760ce60009054906101000a90046001600160a01b03166001600160a01b0316638c0fb97b84606001518560a0015160006117d3662386f26fc10000610abf886001600160a01b031663aabaecd66040518163ffffffff1660e01b815260040160206040518083038186803b1580156116a057600080fd5b505afa1580156116b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d89190614ec0565b6001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561171057600080fd5b505afa158015611724573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117489190615288565b60ff16600a0a610ab38a6001600160a01b031663c52987cf6040518163ffffffff1660e01b815260040160206040518083038186803b15801561178a57600080fd5b505afa15801561179e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c2919061521f565b60a08e01519063ffffffff61460d16565b6040518563ffffffff1660e01b81526004016117f2949392919061537d565b600060405180830381600087803b15801561180c57600080fd5b505af1158015611820573d6000803e3d6000fd5b505050506119ae565b60ce60009054906101000a90046001600160a01b03166001600160a01b0316638c0fb97b84606001518560a00151600061195c6305f5e100610abf886001600160a01b031663aabaecd66040518163ffffffff1660e01b815260040160206040518083038186803b15801561189d57600080fd5b505afa1580156118b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d59190614ec0565b6001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561190d57600080fd5b505afa158015611921573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119459190615288565b60a08c01519060ff16600a0a63ffffffff61460d16565b6040518563ffffffff1660e01b815260040161197b949392919061537d565b600060405180830381600087803b15801561199557600080fd5b505af11580156119a9573d6000803e3d6000fd5b505050505b611a41565b806001600160a01b031663504592cd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156119ec57600080fd5b505afa158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190614fc7565b15611a415760405162461bcd60e51b815260040161035690615482565b60cd5483516020850151606086015160a08701516040516380f0d75160e01b81526001600160a01b03909516946380f0d75194611a8794600094919390926004016153df565b600060405180830381600087803b158015611aa157600080fd5b505af1158015611ab5573d6000803e3d6000fd5b50505060408085015160a0860151915163051b0a4160e41b81526001600160a01b03851693506351b0a41092611aee92916004016153a5565b600060405180830381600087803b158015611b0857600080fd5b505af1158015611b1c573d6000803e3d6000fd5b5050505082604001516001600160a01b031683600001516001600160a01b031684606001516001600160a01b03167f4d7f96086c92b2f9a254ad21548b1c1f2d99502c7949508866349b96bb1a8d8a86602001518760a00151604051611b83929190615919565b60405180910390a4505050565b600054610100900460ff1680611ba95750611ba96146cb565b80611bb7575060005460ff16155b611bd35760405162461bcd60e51b8152600401610356906156c5565b600054610100900460ff16158015611bfe576000805460ff1961ff0019909116610100171660011790555b6001600160a01b038316611c245760405162461bcd60e51b815260040161035690615593565b6001600160a01b038216611c4a5760405162461bcd60e51b815260040161035690615818565b611c53826146d1565b611c5b614766565b60c980546001600160a01b0319166001600160a01b038516179055610e1060cf558015611c8e576000805461ff00191690555b505050565b60cb54604051630478409360e41b8152600091611d24916305f5e10091610abf9186916001600160a01b031690634784093090611cd4908a9060040161531b565b60206040518083038186803b158015611cec57600080fd5b505afa158015611d00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab3919061521f565b90505b92915050565b611d356147f6565b6065546001600160a01b03908116911614611d625760405162461bcd60e51b815260040161035690615647565b611d6a6147fa565b565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b158015611dba57600080fd5b505afa158015611dce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df29190614ec0565b6001600160a01b0316336001600160a01b031614611e225760405162461bcd60e51b81526004016103569061567c565b611e2a614c97565b60cd54825160208401516040516313b55f7d60e31b81526000936001600160a01b031692639daafbe892611e60926004016153a5565b60006040518083038186803b158015611e7857600080fd5b505afa158015611e8c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611eb491908101906150d9565b5091509150611ec68260000151613f11565b15611f795760008260000151600081518110611ede57fe5b60200260200101519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b158015611f2157600080fd5b505afa158015611f35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f59919061521f565b4210611f775760405162461bcd60e51b815260040161035690615713565b505b8060011415611fef5760cd54606084015160a08501516040516315db745960e31b81526001600160a01b039093169263aedba2c892611fbc9290916004016153a5565b600060405180830381600087803b158015611fd657600080fd5b505af1158015611fea573d6000803e3d6000fd5b505050505b60cd5483516020850151606086015160a08701516040516380f0d75160e01b81526001600160a01b03909516946380f0d7519461203594600594919390926004016153df565b600060405180830381600087803b15801561204f57600080fd5b505af1158015612063573d6000803e3d6000fd5b505060ce54606086015160408088015160a0890151915163fa93b2a560e01b81526001600160a01b03909416955063fa93b2a594506120a793909190600401615359565b600060405180830381600087803b1580156120c157600080fd5b505af11580156120d5573d6000803e3d6000fd5b5050505082604001516001600160a01b031683600001516001600160a01b031684606001516001600160a01b03167ffe86f7694b6c54a528acbe27be61dd4a85e9a89aeef7f650a1b439045ccee5a486602001518760a00151604051611b83929190615919565b60c9546001600160a01b031681565b6121536147f6565b6065546001600160a01b039081169116146121805760405162461bcd60e51b815260040161035690615647565b6065546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3606580546001600160a01b0319169055565b60cc546001600160a01b031681565b6065546001600160a01b031690565b60ca546001600160a01b031681565b6121ff6147f6565b6065546001600160a01b0390811691161461222c5760405162461bcd60e51b815260040161035690615647565b6000811161224c5760405162461bcd60e51b81526004016103569061574d565b60cf55565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561229f57600080fd5b505afa1580156122b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d79190614ec0565b6001600160a01b0316336001600160a01b0316146123075760405162461bcd60e51b81526004016103569061567c565b600082606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b15801561234957600080fd5b505afa15801561235d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612381919061521f565b421061239f5760405162461bcd60e51b815260040161035690615465565b816002141561264f57806001600160a01b031663504592cd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156123e157600080fd5b505afa1580156123f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124199190614fc7565b6124355760405162461bcd60e51b815260040161035690615482565b806001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b15801561246e57600080fd5b505afa158015612482573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a69190614fc7565b1561257e5760ce60009054906101000a90046001600160a01b03166001600160a01b0316638c0fb97b84606001518560a001516000036000612525662386f26fc10000610abf886001600160a01b031663aabaecd66040518163ffffffff1660e01b815260040160206040518083038186803b1580156116a057600080fd5b6000036040518563ffffffff1660e01b8152600401612547949392919061537d565b600060405180830381600087803b15801561256157600080fd5b505af1158015612575573d6000803e3d6000fd5b5050505061264a565b60ce60009054906101000a90046001600160a01b03166001600160a01b0316638c0fb97b84606001518560a0015160000360006125f56305f5e100610abf886001600160a01b031663aabaecd66040518163ffffffff1660e01b815260040160206040518083038186803b15801561189d57600080fd5b6000036040518563ffffffff1660e01b8152600401612617949392919061537d565b600060405180830381600087803b15801561263157600080fd5b505af1158015612645573d6000803e3d6000fd5b505050505b6126dd565b806001600160a01b031663504592cd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561268857600080fd5b505afa15801561269c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126c09190614fc7565b156126dd5760405162461bcd60e51b815260040161035690615482565b60cd5483516020850151606086015160a08701516040516380f0d75160e01b81526001600160a01b03909516946380f0d7519461272394600194919390926004016153df565b600060405180830381600087803b15801561273d57600080fd5b505af1158015612751573d6000803e3d6000fd5b50505060408085015160a086015191516356d878f760e01b81526001600160a01b03851693506356d878f79261278a92916004016153a5565b600060405180830381600087803b1580156127a457600080fd5b505af11580156127b8573d6000803e3d6000fd5b5050505082604001516001600160a01b031683600001516001600160a01b031684606001516001600160a01b03167fdd96b18f26fd9950581b9fd821fa907fc318845fc4d220b825a7b19bfdd174e886602001518760a00151604051611b83929190615919565b60cf5481565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561287357600080fd5b505afa158015612887573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128ab9190614ec0565b6001600160a01b0316336001600160a01b0316146128db5760405162461bcd60e51b81526004016103569061567c565b602082015160ca546040516302328d7360e31b81526001600160a01b03909116906311946b989061291090849060040161531b565b60206040518083038186803b15801561292857600080fd5b505afa15801561293c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129609190614fc7565b61297c5760405162461bcd60e51b8152600401610356906157fb565b60008060008061298b85613f4f565b9350935093509350804210156129b35760405162461bcd60e51b8152600401610356906157a4565b60cd546040516314b93faf60e01b81526001600160a01b03909116906314b93faf906129e990869086908990879060040161532f565b60206040518083038186803b158015612a0157600080fd5b505afa158015612a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a399190614fc7565b612a555760405162461bcd60e51b81526004016103569061576a565b846001600160a01b031663504592cd6040518163ffffffff1660e01b815260040160206040518083038186803b158015612a8e57600080fd5b505afa158015612aa2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac69190614fc7565b156130215760cf5481014210612aee5760405162461bcd60e51b8152600401610356906155cc565b6000856001600160a01b031663c52987cf6040518163ffffffff1660e01b815260040160206040518083038186803b158015612b2957600080fd5b505afa158015612b3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b61919061521f565b60cc546040516301957f8160e01b81529192506000916001600160a01b03909116906301957f8190612b9990889087906004016153a5565b604080518083038186803b158015612bb057600080fd5b505afa158015612bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be89190615237565b5060cc546040516301957f8160e01b81529192506000916001600160a01b03909116906301957f8190612c21908a9088906004016153a5565b604080518083038186803b158015612c3857600080fd5b505afa158015612c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c709190615237565b5060cb5460208c01516040808e0151905163135b896f60e11b81529394506000936001600160a01b03909316926326b712de92612cb19290916004016153a5565b60206040518083038186803b158015612cc957600080fd5b505afa158015612cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d01919061521f565b9050886001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b158015612d3c57600080fd5b505afa158015612d50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d749190614fc7565b15612e9657838310612d985760405162461bcd60e51b815260040161035690615730565b612da4898585856141b6565b60ce60009054906101000a90046001600160a01b03166001600160a01b031663dd2c99f78a6001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160206040518083038186803b158015612e0157600080fd5b505afa158015612e15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e399190614ec0565b8d516040516001600160e01b031960e085901b168152612e5f9291908690600401615359565b600060405180830381600087803b158015612e7957600080fd5b505af1158015612e8d573d6000803e3d6000fd5b50505050612faf565b838311612eb55760405162461bcd60e51b815260040161035690615730565b612ec1898585856141b6565b60ce60009054906101000a90046001600160a01b03166001600160a01b031663dd2c99f78a6001600160a01b03166317d69bc86040518163ffffffff1660e01b815260040160206040518083038186803b158015612f1e57600080fd5b505afa158015612f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f569190614ec0565b8d516040516001600160e01b031960e085901b168152612f7c9291908690600401615359565b600060405180830381600087803b158015612f9657600080fd5b505af1158015612faa573d6000803e3d6000fd5b505050505b60ce5460208c0151604051638c0fb97b60e01b81526001600160a01b0390921691638c0fb97b91612fea91600090600190879060040161537d565b600060405180830381600087803b15801561300457600080fd5b505af1158015613018573d6000803e3d6000fd5b50505050505050505b600061303588602001518960400151611c93565b9050856001600160a01b03166356d878f7888a604001516040518363ffffffff1660e01b81526004016130699291906153a5565b600060405180830381600087803b15801561308357600080fd5b505af1158015613097573d6000803e3d6000fd5b505060ce548a5160405163fa93b2a560e01b81526001600160a01b03909216935063fa93b2a592506130d0918991908690600401615359565b600060405180830381600087803b1580156130ea57600080fd5b505af11580156130fe573d6000803e3d6000fd5b50505050856001600160a01b031663504592cd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561313b57600080fd5b505afa15801561314f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131739190614fc7565b156131e75760ce546020890151604051638c0fb97b60e01b81526001600160a01b0390921691638c0fb97b916131b49160009081908782039060040161537d565b600060405180830381600087803b1580156131ce57600080fd5b505af11580156131e2573d6000803e3d6000fd5b505050505b87600001516001600160a01b0316876001600160a01b031689602001516001600160a01b03167f18fd144d7dbcbaa6f00fd47a84adc7dc3cc64a326ffa2dc7691a25e3837dba03888c6040015186604051613244939291906153be565b60405180910390a45050505050505050565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156132a457600080fd5b505afa1580156132b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132dc9190614ec0565b6001600160a01b0316336001600160a01b03161461330c5760405162461bcd60e51b81526004016103569061567c565b60ca54606082015160405163f9839d8960e01b81526001600160a01b039092169163f9839d899161333f9160040161531b565b60206040518083038186803b15801561335757600080fd5b505afa15801561336b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061338f9190614fc7565b6133ab5760405162461bcd60e51b815260040161035690615559565b60cd54815160208301516040516313b55f7d60e31b81526000936001600160a01b031692639daafbe8926133e1926004016153a5565b60006040518083038186803b1580156133f957600080fd5b505afa15801561340d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261343591908101906150d9565b5091505080600114156135d25760cd54606083015160a08401516040516335f9dc0960e11b81526001600160a01b0390931692636bf3b8129261347c9290916004016153a5565b600060405180830381600087803b15801561349657600080fd5b505af11580156134aa573d6000803e3d6000fd5b505060cd54606085015160405163632269d160e11b81526001600160a01b03909216935063c644d3a292506134e19160040161531b565b60206040518083038186803b1580156134f957600080fd5b505afa15801561350d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613531919061521f565b60cd546060840151604051636b36ea1f60e11b81526001600160a01b039092169163d66dd43e916135649160040161531b565b60206040518083038186803b15801561357c57600080fd5b505afa158015613590573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135b4919061521f565b11156135d25760405162461bcd60e51b81526004016103569061562a565b60cd5482516020840151606085015160a08601516040516380f0d75160e01b81526001600160a01b03909516946380f0d75194613617946004949193909285016153df565b600060405180830381600087803b15801561363157600080fd5b505af1158015613645573d6000803e3d6000fd5b505060ce54606085015160408087015160a0880151915163dd2c99f760e01b81526001600160a01b03909416955063dd2c99f7945061368993909190600401615359565b600060405180830381600087803b1580156136a357600080fd5b505af11580156136b7573d6000803e3d6000fd5b5050505081604001516001600160a01b031682600001516001600160a01b031683606001516001600160a01b03167fbfab88b861f171b7db714f00e5966131253918d55ddba816c3eb94657d10239085602001518660a0015160405161371e929190615919565b60405180910390a45050565b60cb546001600160a01b031681565b6137416147f6565b6065546001600160a01b0390811691161461376e5760405162461bcd60e51b815260040161035690615647565b6001600160a01b0381166137945760405162461bcd60e51b81526004016103569061549f565b6065546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3606580546001600160a01b0319166001600160a01b0392909216919091179055565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561383e57600080fd5b505afa158015613852573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138769190614ec0565b6001600160a01b0316336001600160a01b0316146138a65760405162461bcd60e51b81526004016103569061567c565b60ca5460608201516040516302328d7360e31b81526001600160a01b03909216916311946b98916138d99160040161531b565b60206040518083038186803b1580156138f157600080fd5b505afa158015613905573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139299190614fc7565b6139455760405162461bcd60e51b8152600401610356906157de565b600081606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b15801561398757600080fd5b505afa15801561399b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139bf919061521f565b42106139dd5760405162461bcd60e51b81526004016103569061551f565b806001600160a01b031663504592cd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613a1657600080fd5b505afa158015613a2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a4e9190614fc7565b15613a6b5760405162461bcd60e51b815260040161035690615834565b60cd54825160208401516040516313b55f7d60e31b81526000936001600160a01b031692639daafbe892613aa1926004016153a5565b60006040518083038186803b158015613ab957600080fd5b505afa158015613acd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613af591908101906150d9565b509150508060021415613b1a5760405162461bcd60e51b815260040161035690615834565b60cd5483516020850151606086015160a08701516040516380f0d75160e01b81526001600160a01b03909516946380f0d75194613b6094600294919390926004016153df565b600060405180830381600087803b158015613b7a57600080fd5b505af1158015613b8e573d6000803e3d6000fd5b505060ce54606086015160408088015160a0890151915163dd2c99f760e01b81526001600160a01b03909416955063dd2c99f79450613bd293909190600401615359565b600060405180830381600087803b158015613bec57600080fd5b505af1158015613c00573d6000803e3d6000fd5b5050505082604001516001600160a01b031683600001516001600160a01b031684606001516001600160a01b03167f2607e210004cef0ad6b3e6aedb778bffb03c1586f8dcf55d49afffde210d8bb186602001518760a00151604051611b83929190615919565b60cd546001600160a01b031681565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b158015613cc457600080fd5b505afa158015613cd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cfc9190614ec0565b6001600160a01b0316336001600160a01b031614613d2c5760405162461bcd60e51b81526004016103569061567c565b600081606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b158015613d6e57600080fd5b505afa158015613d82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613da6919061521f565b4210613dc45760405162461bcd60e51b8152600401610356906157c1565b60cd5482516020840151606085015160a08601516040516380f0d75160e01b81526001600160a01b03909516946380f0d75194613e0a94600394919390926004016153df565b600060405180830381600087803b158015613e2457600080fd5b505af1158015613e38573d6000803e3d6000fd5b505060ce54606085015160408087015160a0880151915163fa93b2a560e01b81526001600160a01b03909416955063fa93b2a59450613e7c93909190600401615359565b600060405180830381600087803b158015613e9657600080fd5b505af1158015613eaa573d6000803e3d6000fd5b5050505081604001516001600160a01b031682600001516001600160a01b031683606001516001600160a01b03167fbd023c53d293da163d185720d4274f4ddabc09d5304491a55abb296cc811d9fa85602001518660a0015160405161371e929190615919565b6000808251118015611d27575060006001600160a01b031682600081518110613f3657fe5b60200260200101516001600160a01b0316141592915050565b6000806000806000859050806001600160a01b031663af0968fc6040518163ffffffff1660e01b815260040160e06040518083038186803b158015613f9357600080fd5b505afa925050508015613fc3575060408051601f3d908101601f19168201909252613fc091810190614f14565b60015b61419957806001600160a01b031663aabaecd66040518163ffffffff1660e01b815260040160206040518083038186803b15801561400057600080fd5b505afa158015614014573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140389190614ec0565b816001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561407157600080fd5b505afa158015614085573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140a99190614ec0565b826001600160a01b03166317d69bc86040518163ffffffff1660e01b815260040160206040518083038186803b1580156140e257600080fd5b505afa1580156140f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061411a9190614ec0565b836001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b15801561415357600080fd5b505afa158015614167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061418b919061521f565b9450945094509450506141af565b509499509297509095509093506141af92505050565b9193509193565b60ce54604051635d5286ff60e01b815260009182916001600160a01b0390911690635d5286ff906141eb90899060040161531b565b60606040518083038186803b15801561420357600080fd5b505afa158015614217573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061423b919061525b565b92505091506000866001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b15801561427b57600080fd5b505afa15801561428f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142b39190614fc7565b80156142bf5750858510155b806143435750866001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b1580156142fe57600080fd5b505afa158015614312573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143369190614fc7565b1580156143435750858511155b1561435c578261435557505050614607565b5081614598565b866001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b15801561439557600080fd5b505afa1580156143a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143cd9190614fc7565b156143da57505050614607565b866001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b15801561441357600080fd5b505afa158015614427573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061444b9190614fc7565b6145985760006145506305f5e100610abf8a6001600160a01b031663aabaecd66040518163ffffffff1660e01b815260040160206040518083038186803b15801561449557600080fd5b505afa1580156144a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144cd9190614ec0565b6001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561450557600080fd5b505afa158015614519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061453d9190615288565b869060ff16600a0a63ffffffff61460d16565b90508084146145625750505050614607565b848610614570576000614594565b61459461458786610abf848a63ffffffff61460d16565b829063ffffffff61468916565b9150505b60ce54604051638c0fb97b60e01b81526001600160a01b0390911690638c0fb97b906145d1908a9060009081908782039060040161537d565b600060405180830381600087803b1580156145eb57600080fd5b505af11580156145ff573d6000803e3d6000fd5b505050505050505b50505050565b60008261461c57506000611d27565b8282028284828161462957fe5b0414611d245760405162461bcd60e51b8152600401610356906155e9565b6000611d2483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614ae6565b6000611d2483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614b1d565b303b1590565b600054610100900460ff16806146ea57506146ea6146cb565b806146f8575060005460ff16155b6147145760405162461bcd60e51b8152600401610356906156c5565b600054610100900460ff1615801561473f576000805460ff1961ff0019909116610100171660011790555b614747614b49565b61475082614bcb565b8015614762576000805461ff00191690555b5050565b600054610100900460ff168061477f575061477f6146cb565b8061478d575060005460ff16155b6147a95760405162461bcd60e51b8152600401610356906156c5565b600054610100900460ff161580156147d4576000805460ff1961ff0019909116610100171660011790555b6097805460ff1916600117905580156147f3576000805461ff00191690555b50565b3390565b60c960009054906101000a90046001600160a01b03166001600160a01b031663d01f63f56040518163ffffffff1660e01b815260040160206040518083038186803b15801561484857600080fd5b505afa15801561485c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148809190614ec0565b60ca80546001600160a01b0319166001600160a01b0392831617905560c95460408051633018205f60e01b815290519190921691633018205f916004808301926020929190829003018186803b1580156148d957600080fd5b505afa1580156148ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149119190614ec0565b60cd80546001600160a01b0319166001600160a01b0392831617905560c9546040805163419d8fe760e11b81529051919092169163833b1fce916004808301926020929190829003018186803b15801561496a57600080fd5b505afa15801561497e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149a29190614ec0565b60cc80546001600160a01b0319166001600160a01b0392831617905560c9546040805163cf28493f60e01b81529051919092169163cf28493f916004808301926020929190829003018186803b1580156149fb57600080fd5b505afa158015614a0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a339190614ec0565b60cb80546001600160a01b0319166001600160a01b0392831617905560c95460408051633aa431a160e11b8152905191909216916375486342916004808301926020929190829003018186803b158015614a8c57600080fd5b505afa158015614aa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ac49190614ec0565b60ce80546001600160a01b0319166001600160a01b0392909216919091179055565b60008183614b075760405162461bcd60e51b81526004016103569190615412565b506000838581614b1357fe5b0495945050505050565b60008184841115614b415760405162461bcd60e51b81526004016103569190615412565b505050900390565b600054610100900460ff1680614b625750614b626146cb565b80614b70575060005460ff16155b614b8c5760405162461bcd60e51b8152600401610356906156c5565b600054610100900460ff16158015614bb7576000805460ff1961ff0019909116610100171660011790555b80156147f3576000805461ff001916905550565b600054610100900460ff1680614be45750614be46146cb565b80614bf2575060005460ff16155b614c0e5760405162461bcd60e51b8152600401610356906156c5565b600054610100900460ff16158015614c39576000805460ff1961ff0019909116610100171660011790555b606580546001600160a01b0319166001600160a01b0384169081179091556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015614762576000805461ff00191690555050565b6040518060c001604052806060815260200160608152602001606081526020016060815260200160608152602001606081525090565b604051806101c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160001515815260200160008152602001600081526020016000815260200160008152602001600081525090565b600082601f830112614d69578081fd5b8151614d7c614d778261594e565b615927565b818152915060208083019084810181840286018201871015614d9d57600080fd5b60005b84811015614dc5578151614db38161596e565b84529282019290820190600101614da0565b505050505092915050565b600082601f830112614de0578081fd5b8151614dee614d778261594e565b818152915060208083019084810181840286018201871015614e0f57600080fd5b60005b84811015614dc557815184529282019290820190600101614e12565b600060c08284031215614e3f578081fd5b614e4960c0615927565b90508135614e568161596e565b8152602082810135908201526040820135614e708161596e565b60408201526060820135614e838161596e565b806060830152506080820135608082015260a082013560a082015292915050565b600060208284031215614eb5578081fd5b8135611d248161596e565b600060208284031215614ed1578081fd5b8151611d248161596e565b60008060408385031215614eee578081fd5b8235614ef98161596e565b91506020830135614f098161596e565b809150509250929050565b600080600080600080600060e0888a031215614f2e578283fd5b8751614f398161596e565b6020890151909750614f4a8161596e565b6040890151909650614f5b8161596e565b80955050606088015193506080880151925060a0880151614f7b81615983565b60c0890151909250614f8c81615983565b8091505092959891949750929550565b60008060408385031215614fae578182fd5b8235614fb98161596e565b946020939093013593505050565b600060208284031215614fd8578081fd5b8151611d2481615983565b60008060e08385031215614ff5578182fd5b614fff8484614e2e565b9460c0939093013593505050565b600060c0828403121561501e578081fd5b611d248383614e2e565b600080828403608081121561503b578283fd5b6060811215615048578283fd5b506150536060615927565b833561505e8161596e565b8152602084013561506e8161596e565b60208201526040848101359082015291506060830135614f098161596e565b60006060828403121561509e578081fd5b6150a86060615927565b82356150b38161596e565b81526020838101359082015260408301356150cd8161596e565b60408201529392505050565b6000806000606084860312156150ed578081fd5b835167ffffffffffffffff80821115615104578283fd5b81860160c08189031215615116578384fd5b61512060c0615927565b9250805182811115615130578485fd5b61513c89828401614d59565b845250602081015182811115615150578485fd5b61515c89828401614d59565b602085015250604081015182811115615173578485fd5b61517f89828401614d59565b604085015250606081015182811115615196578485fd5b6151a289828401614dd0565b6060850152506080810151828111156151b9578485fd5b6151c589828401614dd0565b60808501525060a0810151828111156151dc578485fd5b6151e889828401614dd0565b60a0850152505050602085015160409095015190969495509392505050565b600060208284031215615218578081fd5b5035919050565b600060208284031215615230578081fd5b5051919050565b60008060408385031215615249578182fd5b825191506020830151614f0981615983565b60008060006060848603121561526f578081fd5b8351925060208401519150604084015190509250925092565b600060208284031215615299578081fd5b815160ff81168114611d24578182fd5b6000815180845260208085019450808401835b838110156152e15781516001600160a01b0316875295820195908201906001016152bc565b509495945050505050565b6000815180845260208085019450808401835b838110156152e1578151875295820195908201906001016152ff565b6001600160a01b0391909116815260200190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03949094168452602084019290925215156040830152606082015260800190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039390931683526020830191909152604082015260600190565b60ff9590951685526001600160a01b03938416602086015260408501929092529091166060830152608082015260a00190565b6000602080835283518082850152825b8181101561543e57858101830151858201604001528201615422565b8181111561544f5783604083870101525b50601f01601f1916929092016040019392505050565b60208082526003908201526221991b60e91b604082015260600190565b60208082526003908201526204334360ec1b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526003908201526221999960e91b604082015260600190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243333160e81b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b60208082526003908201526243343160e81b604082015260600190565b602080825260029082015261433760f01b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526003908201526243333960e81b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526003908201526243333760e81b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f436f6e74726f6c6c65724c6f6769633a2053656e646572206973206e6f74204360408201526837b73a3937b63632b960b91b606082015260800190565b6020808252602e908201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560408201526d195b881a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526243343560e81b604082015260600190565b60208082526003908201526208666760eb1b604082015260600190565b60208082526003908201526243323960e81b604082015260600190565b60208082526003908201526204333360ec1b604082015260600190565b60208082526003908201526208664760eb1b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b60208082526003908201526243323760e81b604082015260600190565b602080825260029082015261086760f31b604082015260600190565b60208082526003908201526243343360e81b604082015260600190565b600060408252835160c0604084015261586e6101008401826152a9565b60208601519150603f198085830301606086015261588c82846152a9565b60408801519350818682030160808701526158a781856152a9565b92505060608701519250808583030160a08601526158c582846152ec565b60808801519350818682030160c08701526158e081856152ec565b92505060a08701519250808583030160e0860152506158ff81836152ec565b925050508260208301529392505050565b90815260200190565b918252602082015260400190565b60405181810167ffffffffffffffff8111828210171561594657600080fd5b604052919050565b600067ffffffffffffffff821115615964578081fd5b5060209081020190565b6001600160a01b03811681146147f357600080fd5b80151581146147f357600080fdfea26469706673582212208220fde52c8948960a12eb21fc54f3927cd977a8455b47029f204d4d5fa63d3164736f6c634300060a0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101425760003560e01c806393e59dc1116100b8578063cd291bc61161007c578063cd291bc614610244578063ce3e39c014610257578063f2fde38b1461025f578063f4d1c98b14610272578063f77c479114610285578063f91ee2a61461028d57610142565b806393e59dc1146101fb578063a31634df14610203578063b1668b8d14610216578063b46cd0a914610229578063c2d8cfea1461023157610142565b8063646810831161010a57806364681083146101c05780636af48086146101c857806370dc320c146101db578063715018a6146101e35780637dc0d1d0146101eb5780638da5cb5b146101f357610142565b8063020046941461014757806316f0115b1461015c57806333b77c5e1461017a578063485cc9551461018d578063565eea19146101a0575b600080fd5b61015a61015536600461508d565b6102a0565b005b610164611321565b604051610171919061531b565b60405180910390f35b61015a610188366004614fe3565b611330565b61015a61019b366004614edc565b611b90565b6101b36101ae366004614f9c565b611c93565b6040516101719190615910565b61015a611d2d565b61015a6101d636600461500d565b611d6c565b61016461213c565b61015a61214b565b6101646121ca565b6101646121d9565b6101646121e8565b61015a610211366004615207565b6121f7565b61015a610224366004614fe3565b612251565b6101b361281f565b61015a61023f366004615028565b612825565b61015a61025236600461500d565b613256565b61016461372a565b61015a61026d366004614ea4565b613739565b61015a61028036600461500d565b6137f0565b610164613c67565b61015a61029b36600461500d565b613c76565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156102ee57600080fd5b505afa158015610302573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103269190614ec0565b6001600160a01b0316336001600160a01b03161461035f5760405162461bcd60e51b81526004016103569061567c565b60405180910390fd5b610367614c97565b60cd54825160208401516040516313b55f7d60e31b81526000936001600160a01b031692639daafbe89261039d926004016153a5565b60006040518083038186803b1580156103b557600080fd5b505afa1580156103c9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103f191908101906150d9565b509150915060006104058360000151613f11565b905060006104168460200151613f11565b905081806104215750805b61043d5760405162461bcd60e51b815260040161035690615787565b60008261046257846020015160008151811061045557fe5b6020026020010151610478565b8451805160009061046f57fe5b60200260200101515b9050811561052c576000856020015160008151811061049357fe5b60200260200101519050806001600160a01b03166356d878f760ce60009054906101000a90046001600160a01b031688608001516000815181106104d357fe5b60200260200101516040518363ffffffff1660e01b81526004016104f89291906153a5565b600060405180830381600087803b15801561051257600080fd5b505af1158015610526573d6000803e3d6000fd5b50505050505b610534614ccd565b61053d82613f4f565b60608501526001600160a01b039081166040850152908116602084015216815260028514156105935760cf5481606001510142101561058e5760405162461bcd60e51b815260040161035690615576565b6105b7565b80606001514210156105b75760405162461bcd60e51b81526004016103569061553c565b60cd5460208201516040808401518451606086015192516314b93faf60e01b81526001600160a01b03909516946314b93faf946105fa949093929160040161532f565b60206040518083038186803b15801561061257600080fd5b505afa158015610626573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064a9190614fc7565b6106665760405162461bcd60e51b81526004016103569061576a565b60cb5460405163cd43fbfb60e01b81526001600160a01b039091169063cd43fbfb906106989089908990600401615851565b604080518083038186803b1580156106af57600080fd5b505afa1580156106c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106e79190615237565b151561010083015260808201526002851480156107075750806101000151155b1561071c576001610100820152600060808201525b80610100015161073e5760405162461bcd60e51b8152600401610356906154e5565b8460021415610f83576000826001600160a01b031663c52987cf6040518163ffffffff1660e01b815260040160206040518083038186803b15801561078257600080fd5b505afa158015610796573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ba919061521f565b60cc54602084015160608501516040516301957f8160e01b81529394506001600160a01b03909216926301957f81926107f692916004016153a5565b604080518083038186803b15801561080d57600080fd5b505afa158015610821573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108459190615237565b5061018083015260cc54825160608401516040516301957f8160e01b81526001600160a01b03909316926301957f81926108839290916004016153a5565b604080518083038186803b15801561089a57600080fd5b505afa1580156108ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108d29190615237565b506101a083018190526101808301516108ee91859184916141b6565b60ce54604051635d5286ff60e01b81526001600160a01b0390911690635d5286ff9061091e90869060040161531b565b60606040518083038186803b15801561093657600080fd5b505afa15801561094a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061096e919061525b565b6101608501526101408401526101208301526060870151805160009061099057fe5b60200260200101518260e0018181525050826001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b1580156109da57600080fd5b505afa1580156109ee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a129190614fc7565b610ad057610acb82604001516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610a5657600080fd5b505afa158015610a6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8e9190615288565b60ff16601203600a0a610abf6064610ab38660e001518661460d90919063ffffffff16565b9063ffffffff61460d16565b9063ffffffff61464716565b610b6d565b610b6d82602001516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610b1057600080fd5b505afa158015610b24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b489190615288565b60ff16601203600a0a610abf6402540be4008560e0015161460d90919063ffffffff16565b60a0830152610140820151610c2f57600060a0830181905261016083015160e0840151610120850151610bab9291610abf919063ffffffff61460d16565b6080840180518201905260ce5460e0850151604051638c0fb97b60e01b81529293506001600160a01b0390911691638c0fb97b91610bf79188916000908103918782039060040161537d565b600060405180830381600087803b158015610c1157600080fd5b505af1158015610c25573d6000803e3d6000fd5b5050505050610f81565b8161014001518260a001511115610f08578161014001518260a0018181525050826001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b158015610c8857600080fd5b505afa158015610c9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc09190614fc7565b610d7057610d6b610cd882606463ffffffff61460d16565b610abf84604001516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610d1857600080fd5b505afa158015610d2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d509190615288565b6101408601519060ff16601203600a0a63ffffffff61460d16565b610db9565b610db96402540be400610abf84602001516001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015610d1857600080fd5b60c0830181905260e0830151600091610dd8919063ffffffff61468916565b90506000610e11610dfb8560c0015186610160015161468990919063ffffffff16565b610120860151610abf908563ffffffff61460d16565b6080850180518201905260ce5460c086015160a0870151604051638c0fb97b60e01b81529394506001600160a01b0390921692638c0fb97b92610e63928a92600091820392600192039060040161537d565b600060405180830381600087803b158015610e7d57600080fd5b505af1158015610e91573d6000803e3d6000fd5b505060ce54604051638c0fb97b60e01b81526001600160a01b039091169250638c0fb97b9150610ecf9088906000878103918782039060040161537d565b600060405180830381600087803b158015610ee957600080fd5b505af1158015610efd573d6000803e3d6000fd5b505050505050610f81565b60ce5460e083015160a0840151604051638c0fb97b60e01b81526001600160a01b0390931692638c0fb97b92610f4e92889260009283039260019290039060040161537d565b600060405180830381600087803b158015610f6857600080fd5b505af1158015610f7c573d6000803e3d6000fd5b505050505b505b60cd54875160208901516040516380f0d75160e01b81526001600160a01b03909316926380f0d75192610fc09260069260009081906004016153df565b600060405180830381600087803b158015610fda57600080fd5b505af1158015610fee573d6000803e3d6000fd5b5050505084600114156110655760cd54815160808301516040516315db745960e31b81526001600160a01b039093169263aedba2c8926110329290916004016153a5565b600060405180830381600087803b15801561104c57600080fd5b505af1158015611060573d6000803e3d6000fd5b505050505b60ce5481516040808a01516080850151915163fa93b2a560e01b81526001600160a01b039094169363fa93b2a5936110a293909291600401615359565b600060405180830381600087803b1580156110bc57600080fd5b505af11580156110d0573d6000803e3d6000fd5b5050505060a0810151156112b95760ce60009054906101000a90046001600160a01b03166001600160a01b031663fa93b2a5836001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b15801561113b57600080fd5b505afa15801561114f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111739190614fc7565b6111ed57836001600160a01b03166317d69bc86040518163ffffffff1660e01b815260040160206040518083038186803b1580156111b057600080fd5b505afa1580156111c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e89190614ec0565b61125e565b836001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561122657600080fd5b505afa15801561123a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061125e9190614ec0565b89604001518460a001516040518463ffffffff1660e01b815260040161128693929190615359565b600060405180830381600087803b1580156112a057600080fd5b505af11580156112b4573d6000803e3d6000fd5b505050505b6020870151604080890151895160808501519251919289926001600160a01b038089169316917f522cda7dd0677ee4c9512efd8aa92af93de64b4c2fe2f8bfe7a9234a655a9bf59161130e91879189906153be565b60405180910390a4505050505050505050565b60ce546001600160a01b031681565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561137e57600080fd5b505afa158015611392573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b69190614ec0565b6001600160a01b0316336001600160a01b0316146113e65760405162461bcd60e51b81526004016103569061567c565b60ca5460608301516040516302328d7360e31b81526001600160a01b03909216916311946b98916114199160040161531b565b60206040518083038186803b15801561143157600080fd5b505afa158015611445573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114699190614fc7565b6114855760405162461bcd60e51b815260040161035690615502565b600082606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114c757600080fd5b505afa1580156114db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ff919061521f565b421061151d5760405162461bcd60e51b8152600401610356906155af565b81600214156119b357806001600160a01b031663504592cd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561155f57600080fd5b505afa158015611573573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115979190614fc7565b6115b35760405162461bcd60e51b815260040161035690615482565b806001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b1580156115ec57600080fd5b505afa158015611600573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116249190614fc7565b156118295760ce60009054906101000a90046001600160a01b03166001600160a01b0316638c0fb97b84606001518560a0015160006117d3662386f26fc10000610abf886001600160a01b031663aabaecd66040518163ffffffff1660e01b815260040160206040518083038186803b1580156116a057600080fd5b505afa1580156116b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d89190614ec0565b6001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561171057600080fd5b505afa158015611724573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117489190615288565b60ff16600a0a610ab38a6001600160a01b031663c52987cf6040518163ffffffff1660e01b815260040160206040518083038186803b15801561178a57600080fd5b505afa15801561179e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c2919061521f565b60a08e01519063ffffffff61460d16565b6040518563ffffffff1660e01b81526004016117f2949392919061537d565b600060405180830381600087803b15801561180c57600080fd5b505af1158015611820573d6000803e3d6000fd5b505050506119ae565b60ce60009054906101000a90046001600160a01b03166001600160a01b0316638c0fb97b84606001518560a00151600061195c6305f5e100610abf886001600160a01b031663aabaecd66040518163ffffffff1660e01b815260040160206040518083038186803b15801561189d57600080fd5b505afa1580156118b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d59190614ec0565b6001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561190d57600080fd5b505afa158015611921573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119459190615288565b60a08c01519060ff16600a0a63ffffffff61460d16565b6040518563ffffffff1660e01b815260040161197b949392919061537d565b600060405180830381600087803b15801561199557600080fd5b505af11580156119a9573d6000803e3d6000fd5b505050505b611a41565b806001600160a01b031663504592cd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156119ec57600080fd5b505afa158015611a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a249190614fc7565b15611a415760405162461bcd60e51b815260040161035690615482565b60cd5483516020850151606086015160a08701516040516380f0d75160e01b81526001600160a01b03909516946380f0d75194611a8794600094919390926004016153df565b600060405180830381600087803b158015611aa157600080fd5b505af1158015611ab5573d6000803e3d6000fd5b50505060408085015160a0860151915163051b0a4160e41b81526001600160a01b03851693506351b0a41092611aee92916004016153a5565b600060405180830381600087803b158015611b0857600080fd5b505af1158015611b1c573d6000803e3d6000fd5b5050505082604001516001600160a01b031683600001516001600160a01b031684606001516001600160a01b03167f4d7f96086c92b2f9a254ad21548b1c1f2d99502c7949508866349b96bb1a8d8a86602001518760a00151604051611b83929190615919565b60405180910390a4505050565b600054610100900460ff1680611ba95750611ba96146cb565b80611bb7575060005460ff16155b611bd35760405162461bcd60e51b8152600401610356906156c5565b600054610100900460ff16158015611bfe576000805460ff1961ff0019909116610100171660011790555b6001600160a01b038316611c245760405162461bcd60e51b815260040161035690615593565b6001600160a01b038216611c4a5760405162461bcd60e51b815260040161035690615818565b611c53826146d1565b611c5b614766565b60c980546001600160a01b0319166001600160a01b038516179055610e1060cf558015611c8e576000805461ff00191690555b505050565b60cb54604051630478409360e41b8152600091611d24916305f5e10091610abf9186916001600160a01b031690634784093090611cd4908a9060040161531b565b60206040518083038186803b158015611cec57600080fd5b505afa158015611d00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ab3919061521f565b90505b92915050565b611d356147f6565b6065546001600160a01b03908116911614611d625760405162461bcd60e51b815260040161035690615647565b611d6a6147fa565b565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b158015611dba57600080fd5b505afa158015611dce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611df29190614ec0565b6001600160a01b0316336001600160a01b031614611e225760405162461bcd60e51b81526004016103569061567c565b611e2a614c97565b60cd54825160208401516040516313b55f7d60e31b81526000936001600160a01b031692639daafbe892611e60926004016153a5565b60006040518083038186803b158015611e7857600080fd5b505afa158015611e8c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611eb491908101906150d9565b5091509150611ec68260000151613f11565b15611f795760008260000151600081518110611ede57fe5b60200260200101519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b158015611f2157600080fd5b505afa158015611f35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f59919061521f565b4210611f775760405162461bcd60e51b815260040161035690615713565b505b8060011415611fef5760cd54606084015160a08501516040516315db745960e31b81526001600160a01b039093169263aedba2c892611fbc9290916004016153a5565b600060405180830381600087803b158015611fd657600080fd5b505af1158015611fea573d6000803e3d6000fd5b505050505b60cd5483516020850151606086015160a08701516040516380f0d75160e01b81526001600160a01b03909516946380f0d7519461203594600594919390926004016153df565b600060405180830381600087803b15801561204f57600080fd5b505af1158015612063573d6000803e3d6000fd5b505060ce54606086015160408088015160a0890151915163fa93b2a560e01b81526001600160a01b03909416955063fa93b2a594506120a793909190600401615359565b600060405180830381600087803b1580156120c157600080fd5b505af11580156120d5573d6000803e3d6000fd5b5050505082604001516001600160a01b031683600001516001600160a01b031684606001516001600160a01b03167ffe86f7694b6c54a528acbe27be61dd4a85e9a89aeef7f650a1b439045ccee5a486602001518760a00151604051611b83929190615919565b60c9546001600160a01b031681565b6121536147f6565b6065546001600160a01b039081169116146121805760405162461bcd60e51b815260040161035690615647565b6065546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3606580546001600160a01b0319169055565b60cc546001600160a01b031681565b6065546001600160a01b031690565b60ca546001600160a01b031681565b6121ff6147f6565b6065546001600160a01b0390811691161461222c5760405162461bcd60e51b815260040161035690615647565b6000811161224c5760405162461bcd60e51b81526004016103569061574d565b60cf55565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561229f57600080fd5b505afa1580156122b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d79190614ec0565b6001600160a01b0316336001600160a01b0316146123075760405162461bcd60e51b81526004016103569061567c565b600082606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b15801561234957600080fd5b505afa15801561235d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612381919061521f565b421061239f5760405162461bcd60e51b815260040161035690615465565b816002141561264f57806001600160a01b031663504592cd6040518163ffffffff1660e01b815260040160206040518083038186803b1580156123e157600080fd5b505afa1580156123f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124199190614fc7565b6124355760405162461bcd60e51b815260040161035690615482565b806001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b15801561246e57600080fd5b505afa158015612482573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a69190614fc7565b1561257e5760ce60009054906101000a90046001600160a01b03166001600160a01b0316638c0fb97b84606001518560a001516000036000612525662386f26fc10000610abf886001600160a01b031663aabaecd66040518163ffffffff1660e01b815260040160206040518083038186803b1580156116a057600080fd5b6000036040518563ffffffff1660e01b8152600401612547949392919061537d565b600060405180830381600087803b15801561256157600080fd5b505af1158015612575573d6000803e3d6000fd5b5050505061264a565b60ce60009054906101000a90046001600160a01b03166001600160a01b0316638c0fb97b84606001518560a0015160000360006125f56305f5e100610abf886001600160a01b031663aabaecd66040518163ffffffff1660e01b815260040160206040518083038186803b15801561189d57600080fd5b6000036040518563ffffffff1660e01b8152600401612617949392919061537d565b600060405180830381600087803b15801561263157600080fd5b505af1158015612645573d6000803e3d6000fd5b505050505b6126dd565b806001600160a01b031663504592cd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561268857600080fd5b505afa15801561269c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126c09190614fc7565b156126dd5760405162461bcd60e51b815260040161035690615482565b60cd5483516020850151606086015160a08701516040516380f0d75160e01b81526001600160a01b03909516946380f0d7519461272394600194919390926004016153df565b600060405180830381600087803b15801561273d57600080fd5b505af1158015612751573d6000803e3d6000fd5b50505060408085015160a086015191516356d878f760e01b81526001600160a01b03851693506356d878f79261278a92916004016153a5565b600060405180830381600087803b1580156127a457600080fd5b505af11580156127b8573d6000803e3d6000fd5b5050505082604001516001600160a01b031683600001516001600160a01b031684606001516001600160a01b03167fdd96b18f26fd9950581b9fd821fa907fc318845fc4d220b825a7b19bfdd174e886602001518760a00151604051611b83929190615919565b60cf5481565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561287357600080fd5b505afa158015612887573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128ab9190614ec0565b6001600160a01b0316336001600160a01b0316146128db5760405162461bcd60e51b81526004016103569061567c565b602082015160ca546040516302328d7360e31b81526001600160a01b03909116906311946b989061291090849060040161531b565b60206040518083038186803b15801561292857600080fd5b505afa15801561293c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129609190614fc7565b61297c5760405162461bcd60e51b8152600401610356906157fb565b60008060008061298b85613f4f565b9350935093509350804210156129b35760405162461bcd60e51b8152600401610356906157a4565b60cd546040516314b93faf60e01b81526001600160a01b03909116906314b93faf906129e990869086908990879060040161532f565b60206040518083038186803b158015612a0157600080fd5b505afa158015612a15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a399190614fc7565b612a555760405162461bcd60e51b81526004016103569061576a565b846001600160a01b031663504592cd6040518163ffffffff1660e01b815260040160206040518083038186803b158015612a8e57600080fd5b505afa158015612aa2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac69190614fc7565b156130215760cf5481014210612aee5760405162461bcd60e51b8152600401610356906155cc565b6000856001600160a01b031663c52987cf6040518163ffffffff1660e01b815260040160206040518083038186803b158015612b2957600080fd5b505afa158015612b3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b61919061521f565b60cc546040516301957f8160e01b81529192506000916001600160a01b03909116906301957f8190612b9990889087906004016153a5565b604080518083038186803b158015612bb057600080fd5b505afa158015612bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be89190615237565b5060cc546040516301957f8160e01b81529192506000916001600160a01b03909116906301957f8190612c21908a9088906004016153a5565b604080518083038186803b158015612c3857600080fd5b505afa158015612c4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c709190615237565b5060cb5460208c01516040808e0151905163135b896f60e11b81529394506000936001600160a01b03909316926326b712de92612cb19290916004016153a5565b60206040518083038186803b158015612cc957600080fd5b505afa158015612cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d01919061521f565b9050886001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b158015612d3c57600080fd5b505afa158015612d50573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d749190614fc7565b15612e9657838310612d985760405162461bcd60e51b815260040161035690615730565b612da4898585856141b6565b60ce60009054906101000a90046001600160a01b03166001600160a01b031663dd2c99f78a6001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160206040518083038186803b158015612e0157600080fd5b505afa158015612e15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e399190614ec0565b8d516040516001600160e01b031960e085901b168152612e5f9291908690600401615359565b600060405180830381600087803b158015612e7957600080fd5b505af1158015612e8d573d6000803e3d6000fd5b50505050612faf565b838311612eb55760405162461bcd60e51b815260040161035690615730565b612ec1898585856141b6565b60ce60009054906101000a90046001600160a01b03166001600160a01b031663dd2c99f78a6001600160a01b03166317d69bc86040518163ffffffff1660e01b815260040160206040518083038186803b158015612f1e57600080fd5b505afa158015612f32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f569190614ec0565b8d516040516001600160e01b031960e085901b168152612f7c9291908690600401615359565b600060405180830381600087803b158015612f9657600080fd5b505af1158015612faa573d6000803e3d6000fd5b505050505b60ce5460208c0151604051638c0fb97b60e01b81526001600160a01b0390921691638c0fb97b91612fea91600090600190879060040161537d565b600060405180830381600087803b15801561300457600080fd5b505af1158015613018573d6000803e3d6000fd5b50505050505050505b600061303588602001518960400151611c93565b9050856001600160a01b03166356d878f7888a604001516040518363ffffffff1660e01b81526004016130699291906153a5565b600060405180830381600087803b15801561308357600080fd5b505af1158015613097573d6000803e3d6000fd5b505060ce548a5160405163fa93b2a560e01b81526001600160a01b03909216935063fa93b2a592506130d0918991908690600401615359565b600060405180830381600087803b1580156130ea57600080fd5b505af11580156130fe573d6000803e3d6000fd5b50505050856001600160a01b031663504592cd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561313b57600080fd5b505afa15801561314f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131739190614fc7565b156131e75760ce546020890151604051638c0fb97b60e01b81526001600160a01b0390921691638c0fb97b916131b49160009081908782039060040161537d565b600060405180830381600087803b1580156131ce57600080fd5b505af11580156131e2573d6000803e3d6000fd5b505050505b87600001516001600160a01b0316876001600160a01b031689602001516001600160a01b03167f18fd144d7dbcbaa6f00fd47a84adc7dc3cc64a326ffa2dc7691a25e3837dba03888c6040015186604051613244939291906153be565b60405180910390a45050505050505050565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b1580156132a457600080fd5b505afa1580156132b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132dc9190614ec0565b6001600160a01b0316336001600160a01b03161461330c5760405162461bcd60e51b81526004016103569061567c565b60ca54606082015160405163f9839d8960e01b81526001600160a01b039092169163f9839d899161333f9160040161531b565b60206040518083038186803b15801561335757600080fd5b505afa15801561336b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061338f9190614fc7565b6133ab5760405162461bcd60e51b815260040161035690615559565b60cd54815160208301516040516313b55f7d60e31b81526000936001600160a01b031692639daafbe8926133e1926004016153a5565b60006040518083038186803b1580156133f957600080fd5b505afa15801561340d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261343591908101906150d9565b5091505080600114156135d25760cd54606083015160a08401516040516335f9dc0960e11b81526001600160a01b0390931692636bf3b8129261347c9290916004016153a5565b600060405180830381600087803b15801561349657600080fd5b505af11580156134aa573d6000803e3d6000fd5b505060cd54606085015160405163632269d160e11b81526001600160a01b03909216935063c644d3a292506134e19160040161531b565b60206040518083038186803b1580156134f957600080fd5b505afa15801561350d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613531919061521f565b60cd546060840151604051636b36ea1f60e11b81526001600160a01b039092169163d66dd43e916135649160040161531b565b60206040518083038186803b15801561357c57600080fd5b505afa158015613590573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135b4919061521f565b11156135d25760405162461bcd60e51b81526004016103569061562a565b60cd5482516020840151606085015160a08601516040516380f0d75160e01b81526001600160a01b03909516946380f0d75194613617946004949193909285016153df565b600060405180830381600087803b15801561363157600080fd5b505af1158015613645573d6000803e3d6000fd5b505060ce54606085015160408087015160a0880151915163dd2c99f760e01b81526001600160a01b03909416955063dd2c99f7945061368993909190600401615359565b600060405180830381600087803b1580156136a357600080fd5b505af11580156136b7573d6000803e3d6000fd5b5050505081604001516001600160a01b031682600001516001600160a01b031683606001516001600160a01b03167fbfab88b861f171b7db714f00e5966131253918d55ddba816c3eb94657d10239085602001518660a0015160405161371e929190615919565b60405180910390a45050565b60cb546001600160a01b031681565b6137416147f6565b6065546001600160a01b0390811691161461376e5760405162461bcd60e51b815260040161035690615647565b6001600160a01b0381166137945760405162461bcd60e51b81526004016103569061549f565b6065546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3606580546001600160a01b0319166001600160a01b0392909216919091179055565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b15801561383e57600080fd5b505afa158015613852573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138769190614ec0565b6001600160a01b0316336001600160a01b0316146138a65760405162461bcd60e51b81526004016103569061567c565b60ca5460608201516040516302328d7360e31b81526001600160a01b03909216916311946b98916138d99160040161531b565b60206040518083038186803b1580156138f157600080fd5b505afa158015613905573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139299190614fc7565b6139455760405162461bcd60e51b8152600401610356906157de565b600081606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b15801561398757600080fd5b505afa15801561399b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139bf919061521f565b42106139dd5760405162461bcd60e51b81526004016103569061551f565b806001600160a01b031663504592cd6040518163ffffffff1660e01b815260040160206040518083038186803b158015613a1657600080fd5b505afa158015613a2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a4e9190614fc7565b15613a6b5760405162461bcd60e51b815260040161035690615834565b60cd54825160208401516040516313b55f7d60e31b81526000936001600160a01b031692639daafbe892613aa1926004016153a5565b60006040518083038186803b158015613ab957600080fd5b505afa158015613acd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613af591908101906150d9565b509150508060021415613b1a5760405162461bcd60e51b815260040161035690615834565b60cd5483516020850151606086015160a08701516040516380f0d75160e01b81526001600160a01b03909516946380f0d75194613b6094600294919390926004016153df565b600060405180830381600087803b158015613b7a57600080fd5b505af1158015613b8e573d6000803e3d6000fd5b505060ce54606086015160408088015160a0890151915163dd2c99f760e01b81526001600160a01b03909416955063dd2c99f79450613bd293909190600401615359565b600060405180830381600087803b158015613bec57600080fd5b505af1158015613c00573d6000803e3d6000fd5b5050505082604001516001600160a01b031683600001516001600160a01b031684606001516001600160a01b03167f2607e210004cef0ad6b3e6aedb778bffb03c1586f8dcf55d49afffde210d8bb186602001518760a00151604051611b83929190615919565b60cd546001600160a01b031681565b60c960009054906101000a90046001600160a01b03166001600160a01b0316633018205f6040518163ffffffff1660e01b815260040160206040518083038186803b158015613cc457600080fd5b505afa158015613cd8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cfc9190614ec0565b6001600160a01b0316336001600160a01b031614613d2c5760405162461bcd60e51b81526004016103569061567c565b600081606001519050806001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b158015613d6e57600080fd5b505afa158015613d82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613da6919061521f565b4210613dc45760405162461bcd60e51b8152600401610356906157c1565b60cd5482516020840151606085015160a08601516040516380f0d75160e01b81526001600160a01b03909516946380f0d75194613e0a94600394919390926004016153df565b600060405180830381600087803b158015613e2457600080fd5b505af1158015613e38573d6000803e3d6000fd5b505060ce54606085015160408087015160a0880151915163fa93b2a560e01b81526001600160a01b03909416955063fa93b2a59450613e7c93909190600401615359565b600060405180830381600087803b158015613e9657600080fd5b505af1158015613eaa573d6000803e3d6000fd5b5050505081604001516001600160a01b031682600001516001600160a01b031683606001516001600160a01b03167fbd023c53d293da163d185720d4274f4ddabc09d5304491a55abb296cc811d9fa85602001518660a0015160405161371e929190615919565b6000808251118015611d27575060006001600160a01b031682600081518110613f3657fe5b60200260200101516001600160a01b0316141592915050565b6000806000806000859050806001600160a01b031663af0968fc6040518163ffffffff1660e01b815260040160e06040518083038186803b158015613f9357600080fd5b505afa925050508015613fc3575060408051601f3d908101601f19168201909252613fc091810190614f14565b60015b61419957806001600160a01b031663aabaecd66040518163ffffffff1660e01b815260040160206040518083038186803b15801561400057600080fd5b505afa158015614014573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140389190614ec0565b816001600160a01b0316637158da7c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561407157600080fd5b505afa158015614085573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140a99190614ec0565b826001600160a01b03166317d69bc86040518163ffffffff1660e01b815260040160206040518083038186803b1580156140e257600080fd5b505afa1580156140f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061411a9190614ec0565b836001600160a01b031663ade6e2aa6040518163ffffffff1660e01b815260040160206040518083038186803b15801561415357600080fd5b505afa158015614167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061418b919061521f565b9450945094509450506141af565b509499509297509095509093506141af92505050565b9193509193565b60ce54604051635d5286ff60e01b815260009182916001600160a01b0390911690635d5286ff906141eb90899060040161531b565b60606040518083038186803b15801561420357600080fd5b505afa158015614217573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061423b919061525b565b92505091506000866001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b15801561427b57600080fd5b505afa15801561428f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142b39190614fc7565b80156142bf5750858510155b806143435750866001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b1580156142fe57600080fd5b505afa158015614312573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143369190614fc7565b1580156143435750858511155b1561435c578261435557505050614607565b5081614598565b866001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b15801561439557600080fd5b505afa1580156143a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143cd9190614fc7565b156143da57505050614607565b866001600160a01b031663f3c274a66040518163ffffffff1660e01b815260040160206040518083038186803b15801561441357600080fd5b505afa158015614427573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061444b9190614fc7565b6145985760006145506305f5e100610abf8a6001600160a01b031663aabaecd66040518163ffffffff1660e01b815260040160206040518083038186803b15801561449557600080fd5b505afa1580156144a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144cd9190614ec0565b6001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561450557600080fd5b505afa158015614519573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061453d9190615288565b869060ff16600a0a63ffffffff61460d16565b90508084146145625750505050614607565b848610614570576000614594565b61459461458786610abf848a63ffffffff61460d16565b829063ffffffff61468916565b9150505b60ce54604051638c0fb97b60e01b81526001600160a01b0390911690638c0fb97b906145d1908a9060009081908782039060040161537d565b600060405180830381600087803b1580156145eb57600080fd5b505af11580156145ff573d6000803e3d6000fd5b505050505050505b50505050565b60008261461c57506000611d27565b8282028284828161462957fe5b0414611d245760405162461bcd60e51b8152600401610356906155e9565b6000611d2483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614ae6565b6000611d2483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250614b1d565b303b1590565b600054610100900460ff16806146ea57506146ea6146cb565b806146f8575060005460ff16155b6147145760405162461bcd60e51b8152600401610356906156c5565b600054610100900460ff1615801561473f576000805460ff1961ff0019909116610100171660011790555b614747614b49565b61475082614bcb565b8015614762576000805461ff00191690555b5050565b600054610100900460ff168061477f575061477f6146cb565b8061478d575060005460ff16155b6147a95760405162461bcd60e51b8152600401610356906156c5565b600054610100900460ff161580156147d4576000805460ff1961ff0019909116610100171660011790555b6097805460ff1916600117905580156147f3576000805461ff00191690555b50565b3390565b60c960009054906101000a90046001600160a01b03166001600160a01b031663d01f63f56040518163ffffffff1660e01b815260040160206040518083038186803b15801561484857600080fd5b505afa15801561485c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148809190614ec0565b60ca80546001600160a01b0319166001600160a01b0392831617905560c95460408051633018205f60e01b815290519190921691633018205f916004808301926020929190829003018186803b1580156148d957600080fd5b505afa1580156148ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149119190614ec0565b60cd80546001600160a01b0319166001600160a01b0392831617905560c9546040805163419d8fe760e11b81529051919092169163833b1fce916004808301926020929190829003018186803b15801561496a57600080fd5b505afa15801561497e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149a29190614ec0565b60cc80546001600160a01b0319166001600160a01b0392831617905560c9546040805163cf28493f60e01b81529051919092169163cf28493f916004808301926020929190829003018186803b1580156149fb57600080fd5b505afa158015614a0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a339190614ec0565b60cb80546001600160a01b0319166001600160a01b0392831617905560c95460408051633aa431a160e11b8152905191909216916375486342916004808301926020929190829003018186803b158015614a8c57600080fd5b505afa158015614aa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614ac49190614ec0565b60ce80546001600160a01b0319166001600160a01b0392909216919091179055565b60008183614b075760405162461bcd60e51b81526004016103569190615412565b506000838581614b1357fe5b0495945050505050565b60008184841115614b415760405162461bcd60e51b81526004016103569190615412565b505050900390565b600054610100900460ff1680614b625750614b626146cb565b80614b70575060005460ff16155b614b8c5760405162461bcd60e51b8152600401610356906156c5565b600054610100900460ff16158015614bb7576000805460ff1961ff0019909116610100171660011790555b80156147f3576000805461ff001916905550565b600054610100900460ff1680614be45750614be46146cb565b80614bf2575060005460ff16155b614c0e5760405162461bcd60e51b8152600401610356906156c5565b600054610100900460ff16158015614c39576000805460ff1961ff0019909116610100171660011790555b606580546001600160a01b0319166001600160a01b0384169081179091556040516000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38015614762576000805461ff00191690555050565b6040518060c001604052806060815260200160608152602001606081526020016060815260200160608152602001606081525090565b604051806101c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160001515815260200160008152602001600081526020016000815260200160008152602001600081525090565b600082601f830112614d69578081fd5b8151614d7c614d778261594e565b615927565b818152915060208083019084810181840286018201871015614d9d57600080fd5b60005b84811015614dc5578151614db38161596e565b84529282019290820190600101614da0565b505050505092915050565b600082601f830112614de0578081fd5b8151614dee614d778261594e565b818152915060208083019084810181840286018201871015614e0f57600080fd5b60005b84811015614dc557815184529282019290820190600101614e12565b600060c08284031215614e3f578081fd5b614e4960c0615927565b90508135614e568161596e565b8152602082810135908201526040820135614e708161596e565b60408201526060820135614e838161596e565b806060830152506080820135608082015260a082013560a082015292915050565b600060208284031215614eb5578081fd5b8135611d248161596e565b600060208284031215614ed1578081fd5b8151611d248161596e565b60008060408385031215614eee578081fd5b8235614ef98161596e565b91506020830135614f098161596e565b809150509250929050565b600080600080600080600060e0888a031215614f2e578283fd5b8751614f398161596e565b6020890151909750614f4a8161596e565b6040890151909650614f5b8161596e565b80955050606088015193506080880151925060a0880151614f7b81615983565b60c0890151909250614f8c81615983565b8091505092959891949750929550565b60008060408385031215614fae578182fd5b8235614fb98161596e565b946020939093013593505050565b600060208284031215614fd8578081fd5b8151611d2481615983565b60008060e08385031215614ff5578182fd5b614fff8484614e2e565b9460c0939093013593505050565b600060c0828403121561501e578081fd5b611d248383614e2e565b600080828403608081121561503b578283fd5b6060811215615048578283fd5b506150536060615927565b833561505e8161596e565b8152602084013561506e8161596e565b60208201526040848101359082015291506060830135614f098161596e565b60006060828403121561509e578081fd5b6150a86060615927565b82356150b38161596e565b81526020838101359082015260408301356150cd8161596e565b60408201529392505050565b6000806000606084860312156150ed578081fd5b835167ffffffffffffffff80821115615104578283fd5b81860160c08189031215615116578384fd5b61512060c0615927565b9250805182811115615130578485fd5b61513c89828401614d59565b845250602081015182811115615150578485fd5b61515c89828401614d59565b602085015250604081015182811115615173578485fd5b61517f89828401614d59565b604085015250606081015182811115615196578485fd5b6151a289828401614dd0565b6060850152506080810151828111156151b9578485fd5b6151c589828401614dd0565b60808501525060a0810151828111156151dc578485fd5b6151e889828401614dd0565b60a0850152505050602085015160409095015190969495509392505050565b600060208284031215615218578081fd5b5035919050565b600060208284031215615230578081fd5b5051919050565b60008060408385031215615249578182fd5b825191506020830151614f0981615983565b60008060006060848603121561526f578081fd5b8351925060208401519150604084015190509250925092565b600060208284031215615299578081fd5b815160ff81168114611d24578182fd5b6000815180845260208085019450808401835b838110156152e15781516001600160a01b0316875295820195908201906001016152bc565b509495945050505050565b6000815180845260208085019450808401835b838110156152e1578151875295820195908201906001016152ff565b6001600160a01b0391909116815260200190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03949094168452602084019290925215156040830152606082015260800190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039390931683526020830191909152604082015260600190565b60ff9590951685526001600160a01b03938416602086015260408501929092529091166060830152608082015260a00190565b6000602080835283518082850152825b8181101561543e57858101830151858201604001528201615422565b8181111561544f5783604083870101525b50601f01601f1916929092016040019392505050565b60208082526003908201526221991b60e91b604082015260600190565b60208082526003908201526204334360ec1b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526003908201526221999960e91b604082015260600190565b60208082526003908201526243323360e81b604082015260600190565b60208082526003908201526208662760eb1b604082015260600190565b60208082526003908201526243333160e81b604082015260600190565b60208082526003908201526243323160e81b604082015260600190565b60208082526003908201526243343160e81b604082015260600190565b602080825260029082015261433760f01b604082015260600190565b60208082526003908201526210cc8d60ea1b604082015260600190565b60208082526003908201526243333960e81b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526003908201526243333760e81b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f436f6e74726f6c6c65724c6f6769633a2053656e646572206973206e6f74204360408201526837b73a3937b63632b960b91b606082015260800190565b6020808252602e908201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560408201526d195b881a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526003908201526221991960e91b604082015260600190565b60208082526003908201526243343560e81b604082015260600190565b60208082526003908201526208666760eb1b604082015260600190565b60208082526003908201526243323960e81b604082015260600190565b60208082526003908201526204333360ec1b604082015260600190565b60208082526003908201526208664760eb1b604082015260600190565b60208082526003908201526243313960e81b604082015260600190565b60208082526003908201526243313760e81b604082015260600190565b60208082526003908201526243323760e81b604082015260600190565b602080825260029082015261086760f31b604082015260600190565b60208082526003908201526243343360e81b604082015260600190565b600060408252835160c0604084015261586e6101008401826152a9565b60208601519150603f198085830301606086015261588c82846152a9565b60408801519350818682030160808701526158a781856152a9565b92505060608701519250808583030160a08601526158c582846152ec565b60808801519350818682030160c08701526158e081856152ec565b92505060a08701519250808583030160e0860152506158ff81836152ec565b925050508260208301529392505050565b90815260200190565b918252602082015260400190565b60405181810167ffffffffffffffff8111828210171561594657600080fd5b604052919050565b600067ffffffffffffffff821115615964578081fd5b5060209081020190565b6001600160a01b03811681146147f357600080fd5b80151581146147f357600080fdfea26469706673582212208220fde52c8948960a12eb21fc54f3927cd977a8455b47029f204d4d5fa63d3164736f6c634300060a0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in HYPE
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.