ERC-20
Overview
Max Total Supply
1,107,523.61715148 ERC20 ***
Holders
40
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 8 Decimals)
Balance
37,038.69108265 ERC20 ***Value
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Source Code Verified (Exact Match)
Contract Name:
oToken
Compiler Version
v0.5.10+commit.5a6ea5b1
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-02-11 */ // File: @openzeppelin/contracts/GSN/Context.sol pragma solidity ^0.5.0; /* * @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. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @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); /** * @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); } // File: @openzeppelin/contracts/math/SafeMath.sol pragma solidity ^0.5.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. * * _Available since v2.4.0._ */ 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. * * _Available since v2.4.0._ */ 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. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: @openzeppelin/contracts/token/ERC20/ERC20.sol pragma solidity ^0.5.0; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20Mintable}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for `sender`'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal { require(account != address(0), "ERC20: mint to the zero address"); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal { require(account != address(0), "ERC20: burn from the zero address"); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Destroys `amount` tokens from `account`.`amount` is then deducted * from the caller's allowance. * * See {_burn} and {_approve}. */ function _burnFrom(address account, uint256 amount) internal { _burn(account, amount); _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance")); } } // File: contracts/lib/CompoundOracleInterface.sol pragma solidity ^0.5.0; // AT MAINNET ADDRESS: 0x02557a5E05DeFeFFD4cAe6D83eA3d173B272c904 contract CompoundOracleInterface { // returns asset:eth -- to get USDC:eth, have to do 10**24/result, constructor() public { } /** * @notice retrieves price of an asset * @dev function to get price for an asset * @param asset Asset for which to get the price * @return uint mantissa of asset price (scaled by 1e18) or zero if unset or contract paused */ function getPrice(address asset) public view returns (uint); function getUnderlyingPrice(ERC20 cToken) public view returns (uint); // function getPrice(address asset) public view returns (uint) { // return 527557000000000; // } } // File: contracts/lib/UniswapExchangeInterface.sol pragma solidity 0.5.10; // Solidity Interface contract UniswapExchangeInterface { // Address of ERC20 token sold on this exchange function tokenAddress() external view returns (address token); // Address of Uniswap Factory function factoryAddress() external view returns (address factory); // Provide Liquidity function addLiquidity(uint256 min_liquidity, uint256 max_tokens, uint256 deadline) external payable returns (uint256); function removeLiquidity(uint256 amount, uint256 min_eth, uint256 min_tokens, uint256 deadline) external returns (uint256, uint256); // Get Prices function getEthToTokenInputPrice(uint256 eth_sold) external view returns (uint256 tokens_bought); function getEthToTokenOutputPrice(uint256 tokens_bought) external view returns (uint256 eth_sold); function getTokenToEthInputPrice(uint256 tokens_sold) external view returns (uint256 eth_bought); function getTokenToEthOutputPrice(uint256 eth_bought) external view returns (uint256 tokens_sold); // Trade ETH to ERC20 function ethToTokenSwapInput(uint256 min_tokens, uint256 deadline) external payable returns (uint256 tokens_bought); function ethToTokenTransferInput(uint256 min_tokens, uint256 deadline, address recipient) external payable returns (uint256 tokens_bought); function ethToTokenSwapOutput(uint256 tokens_bought, uint256 deadline) external payable returns (uint256 eth_sold); function ethToTokenTransferOutput(uint256 tokens_bought, uint256 deadline, address recipient) external payable returns (uint256 eth_sold); // Trade ERC20 to ETH function tokenToEthSwapInput(uint256 tokens_sold, uint256 min_eth, uint256 deadline) external returns (uint256 eth_bought); function tokenToEthTransferInput(uint256 tokens_sold, uint256 min_eth, uint256 deadline, address recipient) external returns (uint256 eth_bought); function tokenToEthSwapOutput(uint256 eth_bought, uint256 max_tokens, uint256 deadline) external returns (uint256 tokens_sold); function tokenToEthTransferOutput(uint256 eth_bought, uint256 max_tokens, uint256 deadline, address recipient) external returns (uint256 tokens_sold); // Trade ERC20 to ERC20 function tokenToTokenSwapInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address token_addr) external returns (uint256 tokens_bought); function tokenToTokenTransferInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address recipient, address token_addr) external returns (uint256 tokens_bought); function tokenToTokenSwapOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address token_addr) external returns (uint256 tokens_sold); function tokenToTokenTransferOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address recipient, address token_addr) external returns (uint256 tokens_sold); // Trade ERC20 to Custom Pool function tokenToExchangeSwapInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address exchange_addr) external returns (uint256 tokens_bought); function tokenToExchangeTransferInput(uint256 tokens_sold, uint256 min_tokens_bought, uint256 min_eth_bought, uint256 deadline, address recipient, address exchange_addr) external returns (uint256 tokens_bought); function tokenToExchangeSwapOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address exchange_addr) external returns (uint256 tokens_sold); function tokenToExchangeTransferOutput(uint256 tokens_bought, uint256 max_tokens_sold, uint256 max_eth_sold, uint256 deadline, address recipient, address exchange_addr) external returns (uint256 tokens_sold); // ERC20 comaptibility for liquidity tokens bytes32 public name; bytes32 public symbol; uint256 public decimals; function transfer(address _to, uint256 _value) external returns (bool); function transferFrom(address _from, address _to, uint256 value) external returns (bool); function approve(address _spender, uint256 _value) external returns (bool); function allowance(address _owner, address _spender) external view returns (uint256); function balanceOf(address _owner) external view returns (uint256); function totalSupply() external view returns (uint256); // Never use function setup(address token_addr) external; } // File: contracts/lib/UniswapFactoryInterface.sol pragma solidity 0.5.10; // Solidity Interface contract UniswapFactoryInterface { // Public Variables address public exchangeTemplate; uint256 public tokenCount; // // Create Exchange function createExchange(address token) external returns (address exchange); // Get Exchange and Token Info function getExchange(address token) external view returns (address exchange); function getToken(address exchange) external view returns (address token); function getTokenWithId(uint256 tokenId) external view returns (address token); // Never use function initializeFactory(address template) external; // function createExchange(address token) external returns (address exchange) { // return 0x06D014475F84Bb45b9cdeD1Cf3A1b8FE3FbAf128; // } // // Get Exchange and Token Info // function getExchange(address token) external view returns (address exchange){ // return 0x06D014475F84Bb45b9cdeD1Cf3A1b8FE3FbAf128; // } // function getToken(address exchange) external view returns (address token) { // return 0x06D014475F84Bb45b9cdeD1Cf3A1b8FE3FbAf128; // } // function getTokenWithId(uint256 tokenId) external view returns (address token) { // return 0x06D014475F84Bb45b9cdeD1Cf3A1b8FE3FbAf128; // } } // File: contracts/OptionsUtils.sol pragma solidity 0.5.10; contract OptionsUtils { // defauls are for mainnet UniswapFactoryInterface public UNISWAP_FACTORY; CompoundOracleInterface public COMPOUND_ORACLE; constructor(address _uniswapFactory, address _compoundOracle) public { UNISWAP_FACTORY = UniswapFactoryInterface(_uniswapFactory); COMPOUND_ORACLE = CompoundOracleInterface(_compoundOracle); } // TODO: for now gets Uniswap, later update to get other exchanges function getExchange(address _token) public view returns (UniswapExchangeInterface) { if (address(UNISWAP_FACTORY.getExchange(_token)) == address(0)) { revert("No payout exchange"); } UniswapExchangeInterface exchange = UniswapExchangeInterface( UNISWAP_FACTORY.getExchange(_token) ); return exchange; } function isETH(IERC20 _ierc20) public pure returns (bool) { return _ierc20 == IERC20(0); } } // File: contracts/OptionsExchange.sol pragma solidity 0.5.10; contract OptionsExchange { uint256 constant LARGE_BLOCK_SIZE = 1651753129000; uint256 constant LARGE_APPROVAL_NUMBER = 10**30; UniswapFactoryInterface public UNISWAP_FACTORY; constructor(address _uniswapFactory) public { UNISWAP_FACTORY = UniswapFactoryInterface(_uniswapFactory); } /*** Events ***/ event SellOTokens( address seller, address payable receiver, address oTokenAddress, address payoutTokenAddress, uint256 oTokensToSell ); event BuyOTokens( address buyer, address payable receiver, address oTokenAddress, address paymentTokenAddress, uint256 oTokensToBuy, uint256 premiumPaid ); /** * @notice This function sells oTokens on Uniswap and sends back payoutTokens to the receiver * @param receiver The address to send the payout tokens back to * @param oTokenAddress The address of the oToken to sell * @param payoutTokenAddress The address of the token to receive the premiums in * @param oTokensToSell The number of oTokens to sell */ function sellOTokens( address payable receiver, address oTokenAddress, address payoutTokenAddress, uint256 oTokensToSell ) public { // @note: first need to bootstrap the uniswap exchange to get the address. IERC20 oToken = IERC20(oTokenAddress); IERC20 payoutToken = IERC20(payoutTokenAddress); oToken.transferFrom(msg.sender, address(this), oTokensToSell); uniswapSellOToken(oToken, payoutToken, oTokensToSell, receiver); emit SellOTokens( msg.sender, receiver, oTokenAddress, payoutTokenAddress, oTokensToSell ); } /** * @notice This function buys oTokens on Uniswap and using paymentTokens from the receiver * @param receiver The address to send the oTokens back to * @param oTokenAddress The address of the oToken to buy * @param paymentTokenAddress The address of the token to pay the premiums in * @param oTokensToBuy The number of oTokens to buy */ function buyOTokens( address payable receiver, address oTokenAddress, address paymentTokenAddress, uint256 oTokensToBuy ) public payable { IERC20 oToken = IERC20(oTokenAddress); IERC20 paymentToken = IERC20(paymentTokenAddress); uniswapBuyOToken(paymentToken, oToken, oTokensToBuy, receiver); } /** * @notice This function calculates the amount of premiums that the seller * will receive if they sold oTokens on Uniswap * @param oTokenAddress The address of the oToken to sell * @param payoutTokenAddress The address of the token to receive the premiums in * @param oTokensToSell The number of oTokens to sell */ function premiumReceived( address oTokenAddress, address payoutTokenAddress, uint256 oTokensToSell ) public view returns (uint256) { // get the amount of ETH that will be paid out if oTokensToSell is sold. UniswapExchangeInterface oTokenExchange = getExchange(oTokenAddress); uint256 ethReceived = oTokenExchange.getTokenToEthInputPrice( oTokensToSell ); if (!isETH(IERC20(payoutTokenAddress))) { // get the amount of payout tokens that will be received if the ethRecieved is sold. UniswapExchangeInterface payoutExchange = getExchange( payoutTokenAddress ); return payoutExchange.getEthToTokenInputPrice(ethReceived); } return ethReceived; } /** * @notice This function calculates the premiums to be paid if a buyer wants to * buy oTokens on Uniswap * @param oTokenAddress The address of the oToken to buy * @param paymentTokenAddress The address of the token to pay the premiums in * @param oTokensToBuy The number of oTokens to buy */ function premiumToPay( address oTokenAddress, address paymentTokenAddress, uint256 oTokensToBuy ) public view returns (uint256) { // get the amount of ETH that needs to be paid for oTokensToBuy. UniswapExchangeInterface oTokenExchange = getExchange(oTokenAddress); uint256 ethToPay = oTokenExchange.getEthToTokenOutputPrice( oTokensToBuy ); if (!isETH(IERC20(paymentTokenAddress))) { // get the amount of paymentTokens that needs to be paid to get the desired ethToPay. UniswapExchangeInterface paymentTokenExchange = getExchange( paymentTokenAddress ); return paymentTokenExchange.getTokenToEthOutputPrice(ethToPay); } return ethToPay; } function uniswapSellOToken( IERC20 oToken, IERC20 payoutToken, uint256 _amt, address payable _transferTo ) internal returns (uint256) { require(!isETH(oToken), "Can only sell oTokens"); UniswapExchangeInterface exchange = getExchange(address(oToken)); if (isETH(payoutToken)) { //Token to ETH oToken.approve(address(exchange), _amt); return exchange.tokenToEthTransferInput( _amt, 1, LARGE_BLOCK_SIZE, _transferTo ); } else { //Token to Token oToken.approve(address(exchange), _amt); return exchange.tokenToTokenTransferInput( _amt, 1, 1, LARGE_BLOCK_SIZE, _transferTo, address(payoutToken) ); } } function uniswapBuyOToken( IERC20 paymentToken, IERC20 oToken, uint256 _amt, address payable _transferTo ) public returns (uint256) { require(!isETH(oToken), "Can only buy oTokens"); if (!isETH(paymentToken)) { UniswapExchangeInterface exchange = getExchange( address(paymentToken) ); uint256 paymentTokensToTransfer = premiumToPay( address(oToken), address(paymentToken), _amt ); paymentToken.transferFrom( msg.sender, address(this), paymentTokensToTransfer ); // Token to Token paymentToken.approve(address(exchange), LARGE_APPROVAL_NUMBER); emit BuyOTokens( msg.sender, _transferTo, address(oToken), address(paymentToken), _amt, paymentTokensToTransfer ); return exchange.tokenToTokenTransferInput( paymentTokensToTransfer, 1, 1, LARGE_BLOCK_SIZE, _transferTo, address(oToken) ); } else { // ETH to Token UniswapExchangeInterface exchange = UniswapExchangeInterface( UNISWAP_FACTORY.getExchange(address(oToken)) ); uint256 ethToTransfer = exchange.getEthToTokenOutputPrice(_amt); emit BuyOTokens( msg.sender, _transferTo, address(oToken), address(paymentToken), _amt, ethToTransfer ); return exchange.ethToTokenTransferOutput.value(ethToTransfer)( _amt, LARGE_BLOCK_SIZE, _transferTo ); } } function getExchange(address _token) internal view returns (UniswapExchangeInterface) { UniswapExchangeInterface exchange = UniswapExchangeInterface( UNISWAP_FACTORY.getExchange(_token) ); if (address(exchange) == address(0)) { revert("No payout exchange"); } return exchange; } function isETH(IERC20 _ierc20) internal pure returns (bool) { return _ierc20 == IERC20(0); } function() external payable { // to get ether from uniswap exchanges } } // File: @openzeppelin/contracts/token/ERC20/ERC20Detailed.sol pragma solidity ^0.5.0; /** * @dev Optional functions from the ERC20 standard. */ contract ERC20Detailed is IERC20 { string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of * these values are immutable: they can only be set once during * construction. */ constructor (string memory name, string memory symbol, uint8 decimals) public { _name = name; _symbol = symbol; _decimals = decimals; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } } // File: @openzeppelin/contracts/ownership/Ownable.sol pragma solidity ^0.5.0; /** * @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. * * 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 Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { _owner = _msgSender(); emit OwnershipTransferred(address(0), _owner); } /** * @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(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _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 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 onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File: contracts/OptionsContract.sol pragma solidity 0.5.10; /** * @title Opyn's Options Contract * @author Opyn */ contract OptionsContract is Ownable, ERC20 { using SafeMath for uint256; /* represents floting point numbers, where number = value * 10 ** exponent i.e 0.1 = 10 * 10 ** -3 */ struct Number { uint256 value; int32 exponent; } // Keeps track of the weighted collateral and weighted debt for each vault. struct Vault { uint256 collateral; uint256 oTokensIssued; uint256 underlying; bool owned; } OptionsExchange public optionsExchange; mapping(address => Vault) internal vaults; address payable[] internal vaultOwners; // 10 is 0.01 i.e. 1% incentive. Number public liquidationIncentive = Number(10, -3); // 100 is egs. 0.1 i.e. 10%. Number public transactionFee = Number(0, -3); /* 500 is 0.5. Max amount that a Vault can be liquidated by i.e. max collateral that can be taken in one function call */ Number public liquidationFactor = Number(500, -3); /* 16 means 1.6. The minimum ratio of a Vault's collateral to insurance promised. The ratio is calculated as below: vault.collateral / (Vault.oTokensIssued * strikePrice) */ Number public minCollateralizationRatio = Number(16, -1); // The amount of insurance promised per oToken Number public strikePrice; // The amount of underlying that 1 oToken protects. Number public oTokenExchangeRate; /* UNIX time. Exercise period starts at `(expiry - windowSize)` and ends at `expiry` */ uint256 internal windowSize; /* The total fees accumulated in the contract any time liquidate or exercise is called */ uint256 internal totalFee; // The time of expiry of the options contract uint256 public expiry; // The precision of the collateral int32 public collateralExp = -18; // The precision of the underlying int32 public underlyingExp = -18; // The collateral asset IERC20 public collateral; // The asset being protected by the insurance IERC20 public underlying; // The asset in which insurance is denominated in. IERC20 public strike; // The Oracle used for the contract CompoundOracleInterface public COMPOUND_ORACLE; // The name of the contract string public name; // The symbol of the contract string public symbol; // The number of decimals of the contract uint8 public decimals; /** * @param _collateral The collateral asset * @param _collExp The precision of the collateral (-18 if ETH) * @param _underlying The asset that is being protected * @param _underlyingExp The precision of the underlying asset * @param _oTokenExchangeExp The precision of the `amount of underlying` that 1 oToken protects * @param _strikePrice The amount of strike asset that will be paid out per oToken * @param _strikeExp The precision of the strike price. * @param _strike The asset in which the insurance is calculated * @param _expiry The time at which the insurance expires * @param _optionsExchange The contract which interfaces with the exchange + oracle * @param _oracleAddress The address of the oracle * @param _windowSize UNIX time. Exercise window is from `expiry - _windowSize` to `expiry`. */ constructor( IERC20 _collateral, int32 _collExp, IERC20 _underlying, int32 _underlyingExp, int32 _oTokenExchangeExp, uint256 _strikePrice, int32 _strikeExp, IERC20 _strike, uint256 _expiry, OptionsExchange _optionsExchange, address _oracleAddress, uint256 _windowSize ) public { require(block.timestamp < _expiry, "Can't deploy an expired contract"); require( _windowSize <= _expiry, "Exercise window can't be longer than the contract's lifespan" ); require( isWithinExponentRange(_collExp), "collateral exponent not within expected range" ); require( isWithinExponentRange(_underlyingExp), "underlying exponent not within expected range" ); require( isWithinExponentRange(_strikeExp), "strike price exponent not within expected range" ); require( isWithinExponentRange(_oTokenExchangeExp), "oToken exchange rate exponent not within expected range" ); collateral = _collateral; collateralExp = _collExp; underlying = _underlying; underlyingExp = _underlyingExp; oTokenExchangeRate = Number(1, _oTokenExchangeExp); strikePrice = Number(_strikePrice, _strikeExp); strike = _strike; expiry = _expiry; COMPOUND_ORACLE = CompoundOracleInterface(_oracleAddress); optionsExchange = _optionsExchange; windowSize = _windowSize; } /*** Events ***/ event VaultOpened(address payable vaultOwner); event ETHCollateralAdded( address payable vaultOwner, uint256 amount, address payer ); event ERC20CollateralAdded( address payable vaultOwner, uint256 amount, address payer ); event IssuedOTokens( address issuedTo, uint256 oTokensIssued, address payable vaultOwner ); event Liquidate( uint256 amtCollateralToPay, address payable vaultOwner, address payable liquidator ); event Exercise( uint256 amtUnderlyingToPay, uint256 amtCollateralToPay, address payable exerciser, address payable vaultExercisedFrom ); event RedeemVaultBalance( uint256 amtCollateralRedeemed, uint256 amtUnderlyingRedeemed, address payable vaultOwner ); event BurnOTokens(address payable vaultOwner, uint256 oTokensBurned); event RemoveCollateral(uint256 amtRemoved, address payable vaultOwner); event UpdateParameters( uint256 liquidationIncentive, uint256 liquidationFactor, uint256 transactionFee, uint256 minCollateralizationRatio, address owner ); event TransferFee(address payable to, uint256 fees); event RemoveUnderlying( uint256 amountUnderlying, address payable vaultOwner ); /** * @dev Throws if called Options contract is expired. */ modifier notExpired() { require(!hasExpired(), "Options contract expired"); _; } /** * @notice This function gets the array of vaultOwners */ function getVaultOwners() public view returns (address payable[] memory) { address payable[] memory owners; uint256 index = 0; for (uint256 i = 0; i < vaultOwners.length; i++) { if (hasVault(vaultOwners[i])) { owners[index] = vaultOwners[i]; index++; } } return owners; } /** * @notice Can only be called by owner. Used to update the fees, minminCollateralizationRatio, etc * @param _liquidationIncentive The incentive paid to liquidator. 10 is 0.01 i.e. 1% incentive. * @param _liquidationFactor Max amount that a Vault can be liquidated by. 500 is 0.5. * @param _transactionFee The fees paid to our protocol every time a execution happens. 100 is egs. 0.1 i.e. 10%. * @param _minCollateralizationRatio The minimum ratio of a Vault's collateral to insurance promised. 16 means 1.6. */ function updateParameters( uint256 _liquidationIncentive, uint256 _liquidationFactor, uint256 _transactionFee, uint256 _minCollateralizationRatio ) public onlyOwner { require( _liquidationIncentive <= 200, "Can't have >20% liquidation incentive" ); require( _liquidationFactor <= 1000, "Can't liquidate more than 100% of the vault" ); require(_transactionFee <= 100, "Can't have transaction fee > 10%"); require( _minCollateralizationRatio >= 10, "Can't have minCollateralizationRatio < 1" ); liquidationIncentive.value = _liquidationIncentive; liquidationFactor.value = _liquidationFactor; transactionFee.value = _transactionFee; minCollateralizationRatio.value = _minCollateralizationRatio; emit UpdateParameters( _liquidationIncentive, _liquidationFactor, _transactionFee, _minCollateralizationRatio, owner() ); } /** * @notice Can only be called by owner. Used to set the name, symbol and decimals of the contract * @param _name The name of the contract * @param _symbol The symbol of the contract */ function setDetails(string memory _name, string memory _symbol) public onlyOwner { name = _name; symbol = _symbol; decimals = uint8(-1 * oTokenExchangeRate.exponent); require( decimals >= 0, "1 oToken cannot protect less than the smallest unit of the asset" ); } /** * @notice Can only be called by owner. Used to take out the protocol fees from the contract. * @param _address The address to send the fee to. */ function transferFee(address payable _address) public onlyOwner { uint256 fees = totalFee; totalFee = 0; transferCollateral(_address, fees); emit TransferFee(_address, fees); } /** * @notice Checks if a `owner` has already created a Vault * @param owner The address of the supposed owner * @return true or false */ function hasVault(address payable owner) public view returns (bool) { return vaults[owner].owned; } /** * @notice Creates a new empty Vault and sets the owner of the vault to be the msg.sender. */ function openVault() public notExpired returns (bool) { require(!hasVault(msg.sender), "Vault already created"); vaults[msg.sender] = Vault(0, 0, 0, true); vaultOwners.push(msg.sender); emit VaultOpened(msg.sender); return true; } /** * @notice If the collateral type is ETH, anyone can call this function any time before * expiry to increase the amount of collateral in a Vault. Will fail if ETH is not the * collateral asset. * Remember that adding ETH collateral even if no oTokens have been created can put the owner at a * risk of losing the collateral if an exercise event happens. * Ensure that you issue and immediately sell oTokens to allow the owner to earn premiums. * (Either call the createAndSell function in the oToken contract or batch the * addERC20Collateral, issueOTokens and sell transactions and ensure they happen atomically to protect * the end user). * @param vaultOwner the index of the Vault to which collateral will be added. */ function addETHCollateral(address payable vaultOwner) public payable notExpired returns (uint256) { require(isETH(collateral), "ETH is not the specified collateral type"); require(hasVault(vaultOwner), "Vault does not exist"); emit ETHCollateralAdded(vaultOwner, msg.value, msg.sender); return _addCollateral(vaultOwner, msg.value); } /** * @notice If the collateral type is any ERC20, anyone can call this function any time before * expiry to increase the amount of collateral in a Vault. Can only transfer in the collateral asset. * Will fail if ETH is the collateral asset. * The user has to allow the contract to handle their ERC20 tokens on his behalf before these * functions are called. * Remember that adding ERC20 collateral even if no oTokens have been created can put the owner at a * risk of losing the collateral. Ensure that you issue and immediately sell the oTokens! * (Either call the createAndSell function in the oToken contract or batch the * addERC20Collateral, issueOTokens and sell transactions and ensure they happen atomically to protect * the end user). * @param vaultOwner the index of the Vault to which collateral will be added. * @param amt the amount of collateral to be transferred in. */ function addERC20Collateral(address payable vaultOwner, uint256 amt) public notExpired returns (uint256) { require( collateral.transferFrom(msg.sender, address(this), amt), "Could not transfer in collateral tokens" ); require(hasVault(vaultOwner), "Vault does not exist"); emit ERC20CollateralAdded(vaultOwner, amt, msg.sender); return _addCollateral(vaultOwner, amt); } /** * @notice Returns the amount of underlying to be transferred during an exercise call */ function underlyingRequiredToExercise(uint256 oTokensToExercise) public view returns (uint256) { uint64 underlyingPerOTokenExp = uint64( oTokenExchangeRate.exponent - underlyingExp ); return oTokensToExercise.mul(10**underlyingPerOTokenExp); } /** * @notice Returns true if exercise can be called */ function isExerciseWindow() public view returns (bool) { return ((block.timestamp >= expiry.sub(windowSize)) && (block.timestamp < expiry)); } /** * @notice Returns true if the oToken contract has expired */ function hasExpired() public view returns (bool) { return (block.timestamp >= expiry); } /** * @notice Called by anyone holding the oTokens and underlying during the * exercise window i.e. from `expiry - windowSize` time to `expiry` time. The caller * transfers in their oTokens and corresponding amount of underlying and gets * `strikePrice * oTokens` amount of collateral out. The collateral paid out is taken from * the each vault owner starting with the first and iterating until the oTokens to exercise * are found. * NOTE: This uses a for loop and hence could run out of gas if the array passed in is too big! * @param oTokensToExercise the number of oTokens being exercised. * @param vaultsToExerciseFrom the array of vaults to exercise from. */ function exercise( uint256 oTokensToExercise, address payable[] memory vaultsToExerciseFrom ) public payable { for (uint256 i = 0; i < vaultsToExerciseFrom.length; i++) { address payable vaultOwner = vaultsToExerciseFrom[i]; require( hasVault(vaultOwner), "Cannot exercise from a vault that doesn't exist" ); Vault storage vault = vaults[vaultOwner]; if (oTokensToExercise == 0) { return; } else if (vault.oTokensIssued >= oTokensToExercise) { _exercise(oTokensToExercise, vaultOwner); return; } else { oTokensToExercise = oTokensToExercise.sub(vault.oTokensIssued); _exercise(vault.oTokensIssued, vaultOwner); } } require( oTokensToExercise == 0, "Specified vaults have insufficient collateral" ); } /** * @notice This function allows the vault owner to remove their share of underlying after an exercise */ function removeUnderlying() public { require(hasVault(msg.sender), "Vault does not exist"); Vault storage vault = vaults[msg.sender]; require(vault.underlying > 0, "No underlying balance"); uint256 underlyingToTransfer = vault.underlying; vault.underlying = 0; transferUnderlying(msg.sender, underlyingToTransfer); emit RemoveUnderlying(underlyingToTransfer, msg.sender); } /** * @notice This function is called to issue the option tokens. Remember that issuing oTokens even if they * haven't been sold can put the owner at a risk of not making premiums on the oTokens. Ensure that you * issue and immidiately sell the oTokens! (Either call the createAndSell function in the oToken contract * of batch the issueOTokens transaction with a sell transaction and ensure it happens atomically). * @dev The owner of a Vault should only be able to have a max of * repo.collateral * collateralToStrike / (minminCollateralizationRatio * strikePrice) tokens issued. * @param oTokensToIssue The number of o tokens to issue * @param receiver The address to send the oTokens to */ function issueOTokens(uint256 oTokensToIssue, address receiver) public notExpired { //check that we're properly collateralized to mint this number, then call _mint(address account, uint256 amount) require(hasVault(msg.sender), "Vault does not exist"); Vault storage vault = vaults[msg.sender]; // checks that the vault is sufficiently collateralized uint256 newOTokensBalance = vault.oTokensIssued.add(oTokensToIssue); require(isSafe(vault.collateral, newOTokensBalance), "unsafe to mint"); // issue the oTokens vault.oTokensIssued = newOTokensBalance; _mint(receiver, oTokensToIssue); emit IssuedOTokens(receiver, oTokensToIssue, msg.sender); return; } /** * @notice Returns the vault for a given address * @param vaultOwner the owner of the Vault to return */ function getVault(address payable vaultOwner) public view returns (uint256, uint256, uint256, bool) { Vault storage vault = vaults[vaultOwner]; return ( vault.collateral, vault.oTokensIssued, vault.underlying, vault.owned ); } /** * @notice Returns true if the given ERC20 is ETH. * @param _ierc20 the ERC20 asset. */ function isETH(IERC20 _ierc20) public pure returns (bool) { return _ierc20 == IERC20(0); } /** * @notice allows the owner to burn their oTokens to increase the collateralization ratio of * their vault. * @param amtToBurn number of oTokens to burn * @dev only want to call this function before expiry. After expiry, no benefit to calling it. */ function burnOTokens(uint256 amtToBurn) public notExpired { require(hasVault(msg.sender), "Vault does not exist"); Vault storage vault = vaults[msg.sender]; vault.oTokensIssued = vault.oTokensIssued.sub(amtToBurn); _burn(msg.sender, amtToBurn); emit BurnOTokens(msg.sender, amtToBurn); } /** * @notice allows the owner to remove excess collateral from the vault before expiry. Removing collateral lowers * the collateralization ratio of the vault. * @param amtToRemove Amount of collateral to remove in 10^-18. */ function removeCollateral(uint256 amtToRemove) public notExpired { require(amtToRemove > 0, "Cannot remove 0 collateral"); require(hasVault(msg.sender), "Vault does not exist"); Vault storage vault = vaults[msg.sender]; require( amtToRemove <= getCollateral(msg.sender), "Can't remove more collateral than owned" ); // check that vault will remain safe after removing collateral uint256 newCollateralBalance = vault.collateral.sub(amtToRemove); require( isSafe(newCollateralBalance, vault.oTokensIssued), "Vault is unsafe" ); // remove the collateral vault.collateral = newCollateralBalance; transferCollateral(msg.sender, amtToRemove); emit RemoveCollateral(amtToRemove, msg.sender); } /** * @notice after expiry, each vault holder can get back their proportional share of collateral * from vaults that they own. * @dev The owner gets all of their collateral back if no exercise event took their collateral. */ function redeemVaultBalance() public { require(hasExpired(), "Can't collect collateral until expiry"); require(hasVault(msg.sender), "Vault does not exist"); // pay out owner their share Vault storage vault = vaults[msg.sender]; // To deal with lower precision uint256 collateralToTransfer = vault.collateral; uint256 underlyingToTransfer = vault.underlying; vault.collateral = 0; vault.oTokensIssued = 0; vault.underlying = 0; transferCollateral(msg.sender, collateralToTransfer); transferUnderlying(msg.sender, underlyingToTransfer); emit RedeemVaultBalance( collateralToTransfer, underlyingToTransfer, msg.sender ); } /** * This function returns the maximum amount of collateral liquidatable if the given vault is unsafe * @param vaultOwner The index of the vault to be liquidated */ function maxOTokensLiquidatable(address payable vaultOwner) public view returns (uint256) { if (isUnsafe(vaultOwner)) { Vault storage vault = vaults[vaultOwner]; uint256 maxCollateralLiquidatable = vault .collateral .mul(liquidationFactor.value) .div(10**uint256(-liquidationFactor.exponent)); uint256 one = 10**uint256(-liquidationIncentive.exponent); Number memory liqIncentive = Number( liquidationIncentive.value.add(one), liquidationIncentive.exponent ); return calculateOTokens(maxCollateralLiquidatable, liqIncentive); } else { return 0; } } /** * @notice This function can be called by anyone who notices a vault is undercollateralized. * The caller gets a reward for reducing the amount of oTokens in circulation. * @dev Liquidator comes with _oTokens. They get _oTokens * strikePrice * (incentive + fee) * amount of collateral out. They can liquidate a max of liquidationFactor * vault.collateral out * in one function call i.e. partial liquidations. * @param vaultOwner The index of the vault to be liquidated * @param oTokensToLiquidate The number of oTokens being taken out of circulation */ function liquidate(address payable vaultOwner, uint256 oTokensToLiquidate) public notExpired { require(hasVault(vaultOwner), "Vault does not exist"); Vault storage vault = vaults[vaultOwner]; // cannot liquidate a safe vault. require(isUnsafe(vaultOwner), "Vault is safe"); // Owner can't liquidate themselves require(msg.sender != vaultOwner, "Owner can't liquidate themselves"); uint256 amtCollateral = calculateCollateralToPay( oTokensToLiquidate, Number(1, 0) ); uint256 amtIncentive = calculateCollateralToPay( oTokensToLiquidate, liquidationIncentive ); uint256 amtCollateralToPay = amtCollateral.add(amtIncentive); // calculate the maximum amount of collateral that can be liquidated uint256 maxCollateralLiquidatable = vault.collateral.mul( liquidationFactor.value ); if (liquidationFactor.exponent > 0) { maxCollateralLiquidatable = maxCollateralLiquidatable.mul( 10**uint256(liquidationFactor.exponent) ); } else { maxCollateralLiquidatable = maxCollateralLiquidatable.div( 10**uint256(-1 * liquidationFactor.exponent) ); } require( amtCollateralToPay <= maxCollateralLiquidatable, "Can only liquidate liquidation factor at any given time" ); // deduct the collateral and oTokensIssued vault.collateral = vault.collateral.sub(amtCollateralToPay); vault.oTokensIssued = vault.oTokensIssued.sub(oTokensToLiquidate); // transfer the collateral and burn the _oTokens _burn(msg.sender, oTokensToLiquidate); transferCollateral(msg.sender, amtCollateralToPay); emit Liquidate(amtCollateralToPay, vaultOwner, msg.sender); } /** * @notice checks if a vault is unsafe. If so, it can be liquidated * @param vaultOwner The number of the vault to check * @return true or false */ function isUnsafe(address payable vaultOwner) public view returns (bool) { bool stillUnsafe = !isSafe( getCollateral(vaultOwner), getOTokensIssued(vaultOwner) ); return stillUnsafe; } /** * @notice This function returns if an -30 <= exponent <= 30 */ function isWithinExponentRange(int32 val) internal pure returns (bool) { return ((val <= 30) && (val >= -30)); } /** * @notice This function calculates and returns the amount of collateral in the vault */ function getCollateral(address payable vaultOwner) internal view returns (uint256) { Vault storage vault = vaults[vaultOwner]; return vault.collateral; } /** * @notice This function calculates and returns the amount of puts issued by the Vault */ function getOTokensIssued(address payable vaultOwner) internal view returns (uint256) { Vault storage vault = vaults[vaultOwner]; return vault.oTokensIssued; } /** * @notice Called by anyone holding the oTokens and underlying during the * exercise window i.e. from `expiry - windowSize` time to `expiry` time. The caller * transfers in their oTokens and corresponding amount of underlying and gets * `strikePrice * oTokens` amount of collateral out. The collateral paid out is taken from * the specified vault holder. At the end of the expiry window, the vault holder can redeem their balance * of collateral. The vault owner can withdraw their underlying at any time. * The user has to allow the contract to handle their oTokens and underlying on his behalf before these functions are called. * @param oTokensToExercise the number of oTokens being exercised. * @param vaultToExerciseFrom the address of the vaultOwner to take collateral from. * @dev oTokenExchangeRate is the number of underlying tokens that 1 oToken protects. */ function _exercise( uint256 oTokensToExercise, address payable vaultToExerciseFrom ) internal { // 1. before exercise window: revert require( isExerciseWindow(), "Can't exercise outside of the exercise window" ); require(hasVault(vaultToExerciseFrom), "Vault does not exist"); Vault storage vault = vaults[vaultToExerciseFrom]; require(oTokensToExercise > 0, "Can't exercise 0 oTokens"); // Check correct amount of oTokens passed in) require( oTokensToExercise <= vault.oTokensIssued, "Can't exercise more oTokens than the owner has" ); // Ensure person calling has enough oTokens require( balanceOf(msg.sender) >= oTokensToExercise, "Not enough oTokens" ); // 1. Check sufficient underlying // 1.1 update underlying balances uint256 amtUnderlyingToPay = underlyingRequiredToExercise( oTokensToExercise ); vault.underlying = vault.underlying.add(amtUnderlyingToPay); // 2. Calculate Collateral to pay // 2.1 Payout enough collateral to get (strikePrice * oTokens) amount of collateral uint256 amtCollateralToPay = calculateCollateralToPay( oTokensToExercise, Number(1, 0) ); // 2.2 Take a small fee on every exercise uint256 amtFee = calculateCollateralToPay( oTokensToExercise, transactionFee ); totalFee = totalFee.add(amtFee); uint256 totalCollateralToPay = amtCollateralToPay.add(amtFee); require( totalCollateralToPay <= vault.collateral, "Vault underwater, can't exercise" ); // 3. Update collateral + oToken balances vault.collateral = vault.collateral.sub(totalCollateralToPay); vault.oTokensIssued = vault.oTokensIssued.sub(oTokensToExercise); // 4. Transfer in underlying, burn oTokens + pay out collateral // 4.1 Transfer in underlying if (isETH(underlying)) { require(msg.value == amtUnderlyingToPay, "Incorrect msg.value"); } else { require( underlying.transferFrom( msg.sender, address(this), amtUnderlyingToPay ), "Could not transfer in tokens" ); } // 4.2 burn oTokens _burn(msg.sender, oTokensToExercise); // 4.3 Pay out collateral transferCollateral(msg.sender, amtCollateralToPay); emit Exercise( amtUnderlyingToPay, amtCollateralToPay, msg.sender, vaultToExerciseFrom ); } /** * @notice adds `_amt` collateral to `vaultOwner` and returns the new balance of the vault * @param vaultOwner the index of the vault * @param amt the amount of collateral to add */ function _addCollateral(address payable vaultOwner, uint256 amt) internal notExpired returns (uint256) { Vault storage vault = vaults[vaultOwner]; vault.collateral = vault.collateral.add(amt); return vault.collateral; } /** * @notice checks if a hypothetical vault is safe with the given collateralAmt and oTokensIssued * @param collateralAmt The amount of collateral the hypothetical vault has * @param oTokensIssued The amount of oTokens generated by the hypothetical vault * @return true or false */ function isSafe(uint256 collateralAmt, uint256 oTokensIssued) internal view returns (bool) { // get price from Oracle uint256 collateralToEthPrice = getPrice(address(collateral)); uint256 strikeToEthPrice = getPrice(address(strike)); // check `oTokensIssued * minCollateralizationRatio * strikePrice <= collAmt * collateralToStrikePrice` uint256 leftSideVal = oTokensIssued .mul(minCollateralizationRatio.value) .mul(strikePrice.value); int32 leftSideExp = minCollateralizationRatio.exponent + strikePrice.exponent; uint256 rightSideVal = (collateralAmt.mul(collateralToEthPrice)).div( strikeToEthPrice ); int32 rightSideExp = collateralExp; uint256 exp = 0; bool stillSafe = false; if (rightSideExp < leftSideExp) { exp = uint256(leftSideExp - rightSideExp); stillSafe = leftSideVal.mul(10**exp) <= rightSideVal; } else { exp = uint256(rightSideExp - leftSideExp); stillSafe = leftSideVal <= rightSideVal.mul(10**exp); } return stillSafe; } /** * This function returns the maximum amount of oTokens that can safely be issued against the specified amount of collateral. * @param collateralAmt The amount of collateral against which oTokens will be issued. */ function maxOTokensIssuable(uint256 collateralAmt) public view returns (uint256) { return calculateOTokens(collateralAmt, minCollateralizationRatio); } /** * @notice This function is used to calculate the amount of tokens that can be issued. * @dev The amount of oTokens is determined by: * oTokensIssued <= collateralAmt * collateralToStrikePrice / (proportion * strikePrice) * @param collateralAmt The amount of collateral * @param proportion The proportion of the collateral to pay out. If 100% of collateral * should be paid out, pass in Number(1, 0). The proportion might be less than 100% if * you are calculating fees. */ function calculateOTokens(uint256 collateralAmt, Number memory proportion) internal view returns (uint256) { // get price from Oracle uint256 collateralToEthPrice = getPrice(address(collateral)); uint256 strikeToEthPrice = getPrice(address(strike)); // oTokensIssued <= collAmt * collateralToStrikePrice / (proportion * strikePrice) uint256 denomVal = proportion.value.mul(strikePrice.value); int32 denomExp = proportion.exponent + strikePrice.exponent; uint256 numeratorVal = (collateralAmt.mul(collateralToEthPrice)).div( strikeToEthPrice ); int32 numeratorExp = collateralExp; uint256 exp = 0; uint256 numOptions = 0; if (numeratorExp < denomExp) { exp = uint256(denomExp - numeratorExp); numOptions = numeratorVal.div(denomVal.mul(10**exp)); } else { exp = uint256(numeratorExp - denomExp); numOptions = numeratorVal.mul(10**exp).div(denomVal); } return numOptions; } /** * @notice This function calculates the amount of collateral to be paid out. * @dev The amount of collateral to paid out is determined by: * (proportion * strikePrice * strikeToCollateralPrice * oTokens) amount of collateral. * @param _oTokens The number of oTokens. * @param proportion The proportion of the collateral to pay out. If 100% of collateral * should be paid out, pass in Number(1, 0). The proportion might be less than 100% if * you are calculating fees. */ function calculateCollateralToPay( uint256 _oTokens, Number memory proportion ) internal view returns (uint256) { // Get price from oracle uint256 collateralToEthPrice = getPrice(address(collateral)); uint256 strikeToEthPrice = getPrice(address(strike)); // calculate how much should be paid out uint256 amtCollateralToPayInEthNum = _oTokens .mul(strikePrice.value) .mul(proportion.value) .mul(strikeToEthPrice); int32 amtCollateralToPayExp = strikePrice.exponent + proportion.exponent - collateralExp; uint256 amtCollateralToPay = 0; if (amtCollateralToPayExp > 0) { uint32 exp = uint32(amtCollateralToPayExp); amtCollateralToPay = amtCollateralToPayInEthNum.mul(10**exp).div( collateralToEthPrice ); } else { uint32 exp = uint32(-1 * amtCollateralToPayExp); amtCollateralToPay = (amtCollateralToPayInEthNum.div(10**exp)).div( collateralToEthPrice ); } return amtCollateralToPay; } /** * @notice This function transfers `amt` collateral to `_addr` * @param _addr The address to send the collateral to * @param _amt The amount of the collateral to pay out. */ function transferCollateral(address payable _addr, uint256 _amt) internal { if (isETH(collateral)) { _addr.transfer(_amt); } else { collateral.transfer(_addr, _amt); } } /** * @notice This function transfers `amt` underlying to `_addr` * @param _addr The address to send the underlying to * @param _amt The amount of the underlying to pay out. */ function transferUnderlying(address payable _addr, uint256 _amt) internal { if (isETH(underlying)) { _addr.transfer(_amt); } else { underlying.transfer(_addr, _amt); } } /** * @notice This function gets the price ETH (wei) to asset price. * @param asset The address of the asset to get the price of */ function getPrice(address asset) internal view returns (uint256) { if (asset == address(0)) { return (10**18); } else { return COMPOUND_ORACLE.getPrice(asset); } } } // File: contracts/oToken.sol pragma solidity 0.5.10; /** * @title Opyn's Options Contract * @author Opyn */ contract oToken is OptionsContract { /** * @param _collateral The collateral asset * @param _collExp The precision of the collateral (-18 if ETH) * @param _underlying The asset that is being protected * @param _underlyingExp The precision of the underlying asset * @param _oTokenExchangeExp The precision of the `amount of underlying` that 1 oToken protects * @param _strikePrice The amount of strike asset that will be paid out * @param _strikeExp The precision of the strike asset (-18 if ETH) * @param _strike The asset in which the insurance is calculated * @param _expiry The time at which the insurance expires * @param _optionsExchange The contract which interfaces with the exchange + oracle * @param _oracleAddress The address of the oracle * @param _windowSize UNIX time. Exercise window is from `expiry - _windowSize` to `expiry`. */ constructor( IERC20 _collateral, int32 _collExp, IERC20 _underlying, int32 _underlyingExp, int32 _oTokenExchangeExp, uint256 _strikePrice, int32 _strikeExp, IERC20 _strike, uint256 _expiry, OptionsExchange _optionsExchange, address _oracleAddress, uint256 _windowSize ) public OptionsContract( _collateral, _collExp, _underlying, _underlyingExp, _oTokenExchangeExp, _strikePrice, _strikeExp, _strike, _expiry, _optionsExchange, _oracleAddress, _windowSize ) {} /** * @notice opens a Vault, adds ETH collateral, and mints new oTokens in one step * Remember that creating oTokens can put the owner at a risk of losing the collateral * if an exercise event happens. * The sell function provides the owner a chance to earn premiums. * Ensure that you create and immediately sell oTokens atmoically. * @param amtToCreate number of oTokens to create * @param receiver address to send the Options to */ function createETHCollateralOption(uint256 amtToCreate, address receiver) external payable { openVault(); addETHCollateralOption(amtToCreate, receiver); } /** * @notice adds ETH collateral, and mints new oTokens in one step to an existing Vault * Remember that creating oTokens can put the owner at a risk of losing the collateral * if an exercise event happens. * The sell function provides the owner a chance to earn premiums. * Ensure that you create and immediately sell oTokens atmoically. * @param amtToCreate number of oTokens to create * @param receiver address to send the Options to */ function addETHCollateralOption(uint256 amtToCreate, address receiver) public payable { addETHCollateral(msg.sender); issueOTokens(amtToCreate, receiver); } /** * @notice opens a Vault, adds ETH collateral, mints new oTokens and sell in one step * @param amtToCreate number of oTokens to create * @param receiver address to receive the premiums */ function createAndSellETHCollateralOption( uint256 amtToCreate, address payable receiver ) external payable { openVault(); addETHCollateralOption(amtToCreate, address(this)); this.approve(address(optionsExchange), amtToCreate); optionsExchange.sellOTokens( receiver, address(this), address(0), amtToCreate ); } /** * @notice adds ETH collateral to an existing Vault, and mints new oTokens and sells the oTokens in one step * @param amtToCreate number of oTokens to create * @param receiver address to send the Options to */ function addAndSellETHCollateralOption( uint256 amtToCreate, address payable receiver ) public payable { addETHCollateral(msg.sender); issueOTokens(amtToCreate, address(this)); this.approve(address(optionsExchange), amtToCreate); optionsExchange.sellOTokens( receiver, address(this), address(0), amtToCreate ); } /** * @notice opens a Vault, adds ERC20 collateral, and mints new oTokens in one step * Remember that creating oTokens can put the owner at a risk of losing the collateral * if an exercise event happens. * The sell function provides the owner a chance to earn premiums. * Ensure that you create and immediately sell oTokens atmoically. * @param amtToCreate number of oTokens to create * @param amtCollateral amount of collateral added * @param receiver address to send the Options to */ function createERC20CollateralOption( uint256 amtToCreate, uint256 amtCollateral, address receiver ) external { openVault(); addERC20CollateralOption(amtToCreate, amtCollateral, receiver); } /** * @notice adds ERC20 collateral, and mints new oTokens in one step * Remember that creating oTokens can put the owner at a risk of losing the collateral * if an exercise event happens. * The sell function provides the owner a chance to earn premiums. * Ensure that you create and immediately sell oTokens atmoically. * @param amtToCreate number of oTokens to create * @param amtCollateral amount of collateral added * @param receiver address to send the Options to */ function addERC20CollateralOption( uint256 amtToCreate, uint256 amtCollateral, address receiver ) public { addERC20Collateral(msg.sender, amtCollateral); issueOTokens(amtToCreate, receiver); } /** * @notice opens a Vault, adds ERC20 collateral, mints new oTokens and sells the oTokens in one step * @param amtToCreate number of oTokens to create * @param amtCollateral amount of collateral added * @param receiver address to send the Options to */ function createAndSellERC20CollateralOption( uint256 amtToCreate, uint256 amtCollateral, address payable receiver ) external { openVault(); addERC20CollateralOption(amtToCreate, amtCollateral, address(this)); this.approve(address(optionsExchange), amtToCreate); optionsExchange.sellOTokens( receiver, address(this), address(0), amtToCreate ); } /** * @notice adds ERC20 collateral, mints new oTokens and sells the oTokens in one step * @param amtToCreate number of oTokens to create * @param amtCollateral amount of collateral added * @param receiver address to send the Options to */ function addAndSellERC20CollateralOption( uint256 amtToCreate, uint256 amtCollateral, address payable receiver ) public { addERC20Collateral(msg.sender, amtCollateral); issueOTokens(amtToCreate, address(this)); this.approve(address(optionsExchange), amtToCreate); optionsExchange.sellOTokens( receiver, address(this), address(0), amtToCreate ); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"constant":false,"inputs":[{"name":"vaultOwner","type":"address"},{"name":"amt","type":"uint256"}],"name":"addERC20Collateral","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getVaultOwners","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"amount","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"hasVault","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isExerciseWindow","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"vaultOwner","type":"address"}],"name":"getVault","outputs":[{"name":"","type":"uint256"},{"name":"","type":"uint256"},{"name":"","type":"uint256"},{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"oTokensToIssue","type":"uint256"},{"name":"receiver","type":"address"}],"name":"issueOTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"sender","type":"address"},{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"amtToCreate","type":"uint256"},{"name":"amtCollateral","type":"uint256"},{"name":"receiver","type":"address"}],"name":"addAndSellERC20CollateralOption","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amtToRemove","type":"uint256"}],"name":"removeCollateral","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"liquidationFactor","outputs":[{"name":"value","type":"uint256"},{"name":"exponent","type":"int32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"amtToCreate","type":"uint256"},{"name":"receiver","type":"address"}],"name":"createAndSellETHCollateralOption","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"optionsExchange","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"amtToCreate","type":"uint256"},{"name":"amtCollateral","type":"uint256"},{"name":"receiver","type":"address"}],"name":"createERC20CollateralOption","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"oTokensToExercise","type":"uint256"},{"name":"vaultsToExerciseFrom","type":"address[]"}],"name":"exercise","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"amtToCreate","type":"uint256"},{"name":"amtCollateral","type":"uint256"},{"name":"receiver","type":"address"}],"name":"addERC20CollateralOption","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"collateralAmt","type":"uint256"}],"name":"maxOTokensIssuable","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"underlying","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"oTokensToExercise","type":"uint256"}],"name":"underlyingRequiredToExercise","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"openVault","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"COMPOUND_ORACLE","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"liquidationIncentive","outputs":[{"name":"value","type":"uint256"},{"name":"exponent","type":"int32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"hasExpired","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"vaultOwner","type":"address"}],"name":"addETHCollateral","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"transactionFee","outputs":[{"name":"value","type":"uint256"},{"name":"exponent","type":"int32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"strike","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"underlyingExp","outputs":[{"name":"","type":"int32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"collateralExp","outputs":[{"name":"","type":"int32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oTokenExchangeRate","outputs":[{"name":"value","type":"uint256"},{"name":"exponent","type":"int32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"redeemVaultBalance","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_symbol","type":"string"}],"name":"setDetails","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amtToCreate","type":"uint256"},{"name":"receiver","type":"address"}],"name":"addETHCollateralOption","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"minCollateralizationRatio","outputs":[{"name":"value","type":"uint256"},{"name":"exponent","type":"int32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"vaultOwner","type":"address"},{"name":"oTokensToLiquidate","type":"uint256"}],"name":"liquidate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"strikePrice","outputs":[{"name":"value","type":"uint256"},{"name":"exponent","type":"int32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"amtToCreate","type":"uint256"},{"name":"amtCollateral","type":"uint256"},{"name":"receiver","type":"address"}],"name":"createAndSellERC20CollateralOption","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"vaultOwner","type":"address"}],"name":"isUnsafe","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"amtToCreate","type":"uint256"},{"name":"receiver","type":"address"}],"name":"addAndSellETHCollateralOption","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"collateral","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"vaultOwner","type":"address"}],"name":"maxOTokensLiquidatable","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"expiry","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"transferFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amtToBurn","type":"uint256"}],"name":"burnOTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amtToCreate","type":"uint256"},{"name":"receiver","type":"address"}],"name":"createETHCollateralOption","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_liquidationIncentive","type":"uint256"},{"name":"_liquidationFactor","type":"uint256"},{"name":"_transactionFee","type":"uint256"},{"name":"_minCollateralizationRatio","type":"uint256"}],"name":"updateParameters","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_ierc20","type":"address"}],"name":"isETH","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"removeUnderlying","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_collateral","type":"address"},{"name":"_collExp","type":"int32"},{"name":"_underlying","type":"address"},{"name":"_underlyingExp","type":"int32"},{"name":"_oTokenExchangeExp","type":"int32"},{"name":"_strikePrice","type":"uint256"},{"name":"_strikeExp","type":"int32"},{"name":"_strike","type":"address"},{"name":"_expiry","type":"uint256"},{"name":"_optionsExchange","type":"address"},{"name":"_oracleAddress","type":"address"},{"name":"_windowSize","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"vaultOwner","type":"address"}],"name":"VaultOpened","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"vaultOwner","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"payer","type":"address"}],"name":"ETHCollateralAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"vaultOwner","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"payer","type":"address"}],"name":"ERC20CollateralAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"issuedTo","type":"address"},{"indexed":false,"name":"oTokensIssued","type":"uint256"},{"indexed":false,"name":"vaultOwner","type":"address"}],"name":"IssuedOTokens","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amtCollateralToPay","type":"uint256"},{"indexed":false,"name":"vaultOwner","type":"address"},{"indexed":false,"name":"liquidator","type":"address"}],"name":"Liquidate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amtUnderlyingToPay","type":"uint256"},{"indexed":false,"name":"amtCollateralToPay","type":"uint256"},{"indexed":false,"name":"exerciser","type":"address"},{"indexed":false,"name":"vaultExercisedFrom","type":"address"}],"name":"Exercise","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amtCollateralRedeemed","type":"uint256"},{"indexed":false,"name":"amtUnderlyingRedeemed","type":"uint256"},{"indexed":false,"name":"vaultOwner","type":"address"}],"name":"RedeemVaultBalance","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"vaultOwner","type":"address"},{"indexed":false,"name":"oTokensBurned","type":"uint256"}],"name":"BurnOTokens","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amtRemoved","type":"uint256"},{"indexed":false,"name":"vaultOwner","type":"address"}],"name":"RemoveCollateral","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"liquidationIncentive","type":"uint256"},{"indexed":false,"name":"liquidationFactor","type":"uint256"},{"indexed":false,"name":"transactionFee","type":"uint256"},{"indexed":false,"name":"minCollateralizationRatio","type":"uint256"},{"indexed":false,"name":"owner","type":"address"}],"name":"UpdateParameters","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"to","type":"address"},{"indexed":false,"name":"fees","type":"uint256"}],"name":"TransferFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amountUnderlying","type":"uint256"},{"indexed":false,"name":"vaultOwner","type":"address"}],"name":"RemoveUnderlying","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]
Contract Creation Code
600a608081905260021960a081905260078290556008805463ffffffff1990811663fffffffd908117909255600060c081905260e08490526009558354811682179093556101f461010081905261012092909252600b91909155600c805483169091179055610180604052601061014081905260001961016052600d55600e805463ffffffff9083161790556016805490911663ffffffee1763ffffffff60201b191667ffffffee00000000179055348015620000bb57600080fd5b5060405162004873380380620048738339818101604052610180811015620000e257600080fd5b508051602082015160408301516060840151608085015160a086015160c087015160e08801516101008901516101208a01516101408b0151610160909b0151999a9899979896979596949593949293919290918b8b8b8b8b8b8b8b8b8b8b8b620001546001600160e01b03620005ec16565b600080546001600160a01b0319166001600160a01b03928316178082556040519216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38342106200020b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f43616e2774206465706c6f7920616e206578706972656420636f6e7472616374604482015290519081900360640190fd5b8381111562000266576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603c81526020018062004777603c913960400191505060405180910390fd5b6200027a8b6001600160e01b03620005f016565b620002d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180620047b3602d913960400191505060405180910390fd5b620002e5896001600160e01b03620005f016565b6200033c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d81526020018062004846602d913960400191505060405180910390fd5b62000350866001600160e01b03620005f016565b620003a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018062004817602f913960400191505060405180910390fd5b620003bb886001600160e01b03620005f016565b62000412576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526037815260200180620047e06037913960400191505060405180910390fd5b8b601660086101000a8154816001600160a01b0302191690836001600160a01b031602179055508a601660006101000a81548163ffffffff021916908360030b63ffffffff16021790555089601760006101000a8154816001600160a01b0302191690836001600160a01b0316021790555088601660046101000a81548163ffffffff021916908360030b63ffffffff1602179055506040518060400160405280600181526020018960030b81525060116000820151816000015560208201518160010160006101000a81548163ffffffff021916908360030b63ffffffff16021790555090505060405180604001604052808881526020018760030b815250600f6000820151816000015560208201518160010160006101000a81548163ffffffff021916908360030b63ffffffff16021790555090505084601860006101000a8154816001600160a01b0302191690836001600160a01b031602179055508360158190555081601960006101000a8154816001600160a01b0302191690836001600160a01b0316021790555082600460006101000a8154816001600160a01b0302191690836001600160a01b031602179055508060138190555050505050505050505050505050505050505050505050505062000612565b3390565b6000601e8260030b131580156200060c5750601d198260030b12155b92915050565b61415580620006226000396000f3fe6080604052600436106103975760003560e01c806390e64d13116101dc578063c52987cf11610102578063e184c9be116100a0578063ee1eab4f1161006f578063ee1eab4f14610ed3578063f2fde38b14610f0f578063f70a250814610f42578063faa2041f14610f7557610397565b8063e184c9be14610e35578063ea8c4bcf14610e4a578063eaa376b514610e7d578063ed1f41c314610ea757610397565b8063cfbea789116100dc578063cfbea78914610d86578063d8dfeb4514610db2578063dd62ed3e14610dc7578063dec44c0b14610e0257610397565b8063c52987cf14610cff578063c56749ce14610d14578063cdb4b5c214610d5357610397565b8063b2c2b13f1161017a578063b7b090ee11610149578063b7b090ee14610b4f578063b96661ba14610c85578063ba1be55414610cb1578063bcbaf48714610cc657610397565b8063b2c2b13f14610ae2578063b6e61c0814610b10578063b736554014610b25578063b76fdb6c14610b3a57610397565b80639ed3edf0116101b65780639ed3edf014610a46578063a457c2d714610a5b578063a9059cbb14610a94578063ad8f500814610acd57610397565b806390e64d13146109f657806395d89b4114610a0b5780639ce0725114610a2057610397565b806339509351116102c15780636fd865f91161025f5780638a5e8cc71161022e5780638a5e8cc7146109a25780638c765e94146109b75780638da5cb5b146109cc5780638f32d59b146109e157610397565b80636fd865f91461091b57806370a0823114610945578063715018a61461097857806386f547121461098d57610397565b806358b36dac1161029b57806358b36dac146107f55780635ca7c8a61461089d578063686c1e21146108dc5780636f307dc31461090657610397565b8063395093511461074c5780633bd33f621461078557806352f89fe3146107b657610397565b806318160ddd116103395780633226052d116103085780633226052d146106845780633237c158146106c3578063352ade55146106ed5780633667429f1461072057610397565b806318160ddd146105c65780631a0e21bd146105db57806323b872dd14610616578063313ce5671461065957610397565b8063095ea7b311610375578063095ea7b3146104d65780630d453efb146105235780630d6cd8aa146105565780630eb9af381461056b57610397565b806301b4a3c11461039c578063060ab2ea146103e757806306fdde031461044c575b600080fd5b3480156103a857600080fd5b506103d5600480360360408110156103bf57600080fd5b506001600160a01b038135169060200135610f8a565b60408051918252519081900360200190f35b3480156103f357600080fd5b506103fc61113e565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610438578181015183820152602001610420565b505050509050019250505060405180910390f35b34801561045857600080fd5b506104616111e5565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561049b578181015183820152602001610483565b50505050905090810190601f1680156104c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104e257600080fd5b5061050f600480360360408110156104f957600080fd5b506001600160a01b038135169060200135611273565b604080519115158252519081900360200190f35b34801561052f57600080fd5b5061050f6004803603602081101561054657600080fd5b50356001600160a01b0316611290565b34801561056257600080fd5b5061050f6112b5565b34801561057757600080fd5b5061059e6004803603602081101561058e57600080fd5b50356001600160a01b03166112e3565b6040805194855260208501939093528383019190915215156060830152519081900360800190f35b3480156105d257600080fd5b506103d5611317565b3480156105e757600080fd5b50610614600480360360408110156105fe57600080fd5b50803590602001356001600160a01b031661131d565b005b34801561062257600080fd5b5061050f6004803603606081101561063957600080fd5b506001600160a01b03813581169160208101359091169060400135611486565b34801561066557600080fd5b5061066e611513565b6040805160ff9092168252519081900360200190f35b34801561069057600080fd5b50610614600480360360608110156106a757600080fd5b50803590602081013590604001356001600160a01b031661151c565b3480156106cf57600080fd5b50610614600480360360208110156106e657600080fd5b5035611634565b3480156106f957600080fd5b50610702611824565b60408051928352600391820b90910b60208301528051918290030190f35b6106146004803603604081101561073657600080fd5b50803590602001356001600160a01b0316611830565b34801561075857600080fd5b5061050f6004803603604081101561076f57600080fd5b506001600160a01b038135169060200135611945565b34801561079157600080fd5b5061079a611999565b604080516001600160a01b039092168252519081900360200190f35b3480156107c257600080fd5b50610614600480360360608110156107d957600080fd5b50803590602081013590604001356001600160a01b03166119a8565b6106146004803603604081101561080b57600080fd5b81359190810190604081016020820135600160201b81111561082c57600080fd5b82018360208201111561083e57600080fd5b803590602001918460208302840111600160201b8311171561085f57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506119c1945050505050565b3480156108a957600080fd5b50610614600480360360608110156108c057600080fd5b50803590602081013590604001356001600160a01b0316611ad9565b3480156108e857600080fd5b506103d5600480360360208110156108ff57600080fd5b5035611aee565b34801561091257600080fd5b5061079a611b1c565b34801561092757600080fd5b506103d56004803603602081101561093e57600080fd5b5035611b2b565b34801561095157600080fd5b506103d56004803603602081101561096857600080fd5b50356001600160a01b0316611b6f565b34801561098457600080fd5b50610614611b8a565b34801561099957600080fd5b5061050f611c1b565b3480156109ae57600080fd5b5061079a611d88565b3480156109c357600080fd5b50610702611d97565b3480156109d857600080fd5b5061079a611da3565b3480156109ed57600080fd5b5061050f611db2565b348015610a0257600080fd5b5061050f611dd6565b348015610a1757600080fd5b50610461611ddf565b6103d560048036036020811015610a3657600080fd5b50356001600160a01b0316611e3a565b348015610a5257600080fd5b50610702611f74565b348015610a6757600080fd5b5061050f60048036036040811015610a7e57600080fd5b506001600160a01b038135169060200135611f80565b348015610aa057600080fd5b5061050f60048036036040811015610ab757600080fd5b506001600160a01b038135169060200135611fee565b348015610ad957600080fd5b5061079a612002565b348015610aee57600080fd5b50610af7612011565b60408051600392830b90920b8252519081900360200190f35b348015610b1c57600080fd5b50610af7612021565b348015610b3157600080fd5b5061070261202a565b348015610b4657600080fd5b50610614612036565b348015610b5b57600080fd5b5061061460048036036040811015610b7257600080fd5b810190602081018135600160201b811115610b8c57600080fd5b820183602082011115610b9e57600080fd5b803590602001918460018302840111600160201b83111715610bbf57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610c1157600080fd5b820183602082011115610c2357600080fd5b803590602001918460018302840111600160201b83111715610c4457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612142945050505050565b61061460048036036040811015610c9b57600080fd5b50803590602001356001600160a01b03166121d3565b348015610cbd57600080fd5b506107026121e7565b348015610cd257600080fd5b5061061460048036036040811015610ce957600080fd5b506001600160a01b0381351690602001356121f3565b348015610d0b57600080fd5b506107026124f7565b348015610d2057600080fd5b5061061460048036036060811015610d3757600080fd5b50803590602081013590604001356001600160a01b0316612503565b348015610d5f57600080fd5b5061050f60048036036020811015610d7657600080fd5b50356001600160a01b0316612517565b61061460048036036040811015610d9c57600080fd5b50803590602001356001600160a01b031661253c565b348015610dbe57600080fd5b5061079a612550565b348015610dd357600080fd5b506103d560048036036040811015610dea57600080fd5b506001600160a01b0381358116916020013516612566565b348015610e0e57600080fd5b506103d560048036036020811015610e2557600080fd5b50356001600160a01b0316612591565b348015610e4157600080fd5b506103d561265c565b348015610e5657600080fd5b5061061460048036036020811015610e6d57600080fd5b50356001600160a01b0316612662565b348015610e8957600080fd5b5061061460048036036020811015610ea057600080fd5b5035612704565b61061460048036036040811015610ebd57600080fd5b50803590602001356001600160a01b0316612806565b348015610edf57600080fd5b5061061460048036036080811015610ef657600080fd5b5080359060208101359060408101359060600135612819565b348015610f1b57600080fd5b5061061460048036036020811015610f3257600080fd5b50356001600160a01b03166129f1565b348015610f4e57600080fd5b5061050f60048036036020811015610f6557600080fd5b50356001600160a01b0316612a44565b348015610f8157600080fd5b50610614612a51565b6000610f94611dd6565b15610fd4576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b601654604080516323b872dd60e01b8152336004820152306024820152604481018590529051600160401b9092046001600160a01b0316916323b872dd916064808201926020929091908290030181600087803b15801561103457600080fd5b505af1158015611048573d6000803e3d6000fd5b505050506040513d602081101561105e57600080fd5b505161109b5760405162461bcd60e51b8152600401808060200182810382526027815260200180613e626027913960400191505060405180910390fd5b6110a483611290565b6110e3576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b604080516001600160a01b038516815260208101849052338183015290517f2199418ea9428ed3ff7d460860e1edaf5831452fa4ea0f8d1a60d63c603487829181900360600190a16111358383612b49565b90505b92915050565b6060806000805b6006548110156111dc576111796006828154811061115f57fe5b6000918252602090912001546001600160a01b0316611290565b156111d4576006818154811061118b57fe5b9060005260206000200160009054906101000a90046001600160a01b03168383815181106111b557fe5b6001600160a01b03909216602092830291909101909101526001909101905b600101611145565b50909150505b90565b601a805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561126b5780601f106112405761010080835404028352916020019161126b565b820191906000526020600020905b81548152906001019060200180831161124e57829003601f168201915b505050505081565b6000611287611280612bc8565b8484612bcc565b50600192915050565b6001600160a01b03811660009081526005602052604090206003015460ff165b919050565b60006112ce601354601554612cb890919063ffffffff16565b42101580156112de575060155442105b905090565b6001600160a01b03166000908152600560205260409020805460018201546002830154600390930154919390929160ff1690565b60035490565b611325611dd6565b15611365576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b61136e33611290565b6113ad576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b33600090815260056020526040812060018101549091906113d4908563ffffffff612cfa16565b90506113e4826000015482612d54565b611426576040805162461bcd60e51b815260206004820152600e60248201526d1d5b9cd85999481d1bc81b5a5b9d60921b604482015290519081900360640190fd5b600182018190556114378385612e59565b604080516001600160a01b038516815260208101869052338183015290517f5e5aaabf04e3760968ffb551bdf9708f4dbf95d53ad98539e91a56b125e88f089181900360600190a150505b5050565b6000611493848484612f4b565b6115098461149f612bc8565b61150485604051806060016040528060288152602001613fcd602891396001600160a01b038a166000908152600260205260408120906114dd612bc8565b6001600160a01b03168152602081019190915260400160002054919063ffffffff6130a916565b612bcc565b5060019392505050565b601c5460ff1681565b6115263383610f8a565b50611531833061131d565b600480546040805163095ea7b360e01b81526001600160a01b0390921692820192909252602481018590529051309163095ea7b39160448083019260209291908290030181600087803b15801561158757600080fd5b505af115801561159b573d6000803e3d6000fd5b505050506040513d60208110156115b157600080fd5b50506004805460408051637dafae5960e01b81526001600160a01b03858116948201949094523060248201526000604482018190526064820188905291519390921692637dafae5992608480820193929182900301818387803b15801561161757600080fd5b505af115801561162b573d6000803e3d6000fd5b50505050505050565b61163c611dd6565b1561167c576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b600081116116d1576040805162461bcd60e51b815260206004820152601a60248201527f43616e6e6f742072656d6f7665203020636f6c6c61746572616c000000000000604482015290519081900360640190fd5b6116da33611290565b611719576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b3360008181526005602052604090209061173290613140565b8211156117705760405162461bcd60e51b8152600401808060200182810382526027815260200180613f796027913960400191505060405180910390fd5b8054600090611785908463ffffffff612cb816565b9050611795818360010154612d54565b6117d8576040805162461bcd60e51b815260206004820152600f60248201526e5661756c7420697320756e7361666560881b604482015290519081900360640190fd5b8082556117e5338461315b565b6040805184815233602082015281517f5a945309b3c58e9bb259128c2a530a6579dc75ac1d7d61b3db4c0b8305a16821929181900390910190a1505050565b600b54600c5460030b82565b611838611c1b565b5061184382306121d3565b600480546040805163095ea7b360e01b81526001600160a01b0390921692820192909252602481018490529051309163095ea7b39160448083019260209291908290030181600087803b15801561189957600080fd5b505af11580156118ad573d6000803e3d6000fd5b505050506040513d60208110156118c357600080fd5b50506004805460408051637dafae5960e01b81526001600160a01b03858116948201949094523060248201526000604482018190526064820187905291519390921692637dafae5992608480820193929182900301818387803b15801561192957600080fd5b505af115801561193d573d6000803e3d6000fd5b505050505050565b6000611287611952612bc8565b846115048560026000611963612bc8565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff612cfa16565b6004546001600160a01b031681565b6119b0611c1b565b506119bc838383611ad9565b505050565b60005b8151811015611a9b5760008282815181106119db57fe5b602002602001015190506119ee81611290565b611a295760405162461bcd60e51b815260040180806020018281038252602f815260200180614036602f913960400191505060405180910390fd5b6001600160a01b038116600090815260056020526040902084611a4e57505050611482565b84816001015410611a6b57611a638583613246565b505050611482565b6001810154611a8190869063ffffffff612cb816565b9450611a91816001015483613246565b50506001016119c4565b5081156114825760405162461bcd60e51b815260040180806020018281038252602d815260200180613ef4602d913960400191505060405180910390fd5b611ae33383610f8a565b506119bc838261131d565b60408051808201909152600d548152600e54600390810b810b900b60208201526000906111389083906136a9565b6017546001600160a01b031681565b601654601254600091600160201b9004600390810b91810b91909103900b611b688367ffffffffffffffff808416600a0a1663ffffffff6137a416565b9392505050565b6001600160a01b031660009081526001602052604090205490565b611b92611db2565b611bd1576040805162461bcd60e51b81526020600482018190526024820152600080516020613ff5833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000611c25611dd6565b15611c65576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b611c6e33611290565b15611cb8576040805162461bcd60e51b815260206004820152601560248201527415985d5b1d08185b1c9958591e4818dc99585d1959605a1b604482015290519081900360640190fd5b60408051608081018252600080825260208083018281528385018381526001606086018181523380875260058652888720975188559351878301559151600287015590516003909501805460ff1916951515959095179094556006805494850181559092527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f90920180546001600160a01b03191682179055825190815291517f66a872561db77eb92ef3079a44a5af00c68c3a09e0976814a95bd91721f57c2f9281900390910190a150600190565b6019546001600160a01b031681565b60075460085460030b82565b6000546001600160a01b031690565b600080546001600160a01b0316611dc7612bc8565b6001600160a01b031614905090565b60155442101590565b601b805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561126b5780601f106112405761010080835404028352916020019161126b565b6000611e44611dd6565b15611e84576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b601654611ea090600160401b90046001600160a01b0316612a44565b611edb5760405162461bcd60e51b8152600401808060200182810382526028815260200180613dcd6028913960400191505060405180910390fd5b611ee482611290565b611f23576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b604080516001600160a01b0384168152346020820152338183015290517ff24ce6016de57e90501829715846e26ac283a0aabfc160647e0ae8b05e0f433d9181900360600190a16111388234612b49565b600954600a5460030b82565b6000611287611f8d612bc8565b84611504856040518060600160405280602581526020016140fc6025913960026000611fb7612bc8565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff6130a916565b6000611287611ffb612bc8565b8484612f4b565b6018546001600160a01b031681565b601654600160201b900460030b81565b60165460030b81565b60115460125460030b82565b61203e611dd6565b6120795760405162461bcd60e51b8152600401808060200182810382526025815260200180613e3d6025913960400191505060405180910390fd5b61208233611290565b6120c1576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b33600081815260056020526040812080546002820180548484556001840185905593905590929091906120f4908361315b565b6120fe33826137fd565b6040805183815260208101839052338183015290517fe481532a3f7d078365ca0145442ed0a0a3e0443f3c0bae0c29cff131112678389181900360600190a1505050565b61214a611db2565b612189576040805162461bcd60e51b81526020600482018190526024820152600080516020613ff5833981519152604482015290519081900360640190fd5b815161219c90601a906020850190613c85565b5080516121b090601b906020840190613c85565b50601254601c805460ff191660039290920b60000360ff16919091179055611482565b6121dc33611e3a565b50611482828261131d565b600d54600e5460030b82565b6121fb611dd6565b1561223b576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b61224482611290565b612283576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b6001600160a01b03821660009081526005602052604090206122a483612517565b6122e5576040805162461bcd60e51b815260206004820152600d60248201526c5661756c74206973207361666560981b604482015290519081900360640190fd5b336001600160a01b0384161415612343576040805162461bcd60e51b815260206004820181905260248201527f4f776e65722063616e2774206c6971756964617465207468656d73656c766573604482015290519081900360640190fd5b600061236883604051806040016040528060018152602001600060030b8152506138a3565b604080518082019091526007548152600854600390810b810b900b60208201529091506000906123999085906138a3565b905060006123ad838363ffffffff612cfa16565b600b5485549192506000916123c79163ffffffff6137a416565b600c549091506000600391820b90910b131561240257600c546123fb908290600390810b900b600a0a63ffffffff6137a416565b9050612426565b600c54612423908290600390810b600003900b600a0a63ffffffff61398516565b90505b808211156124655760405162461bcd60e51b8152600401808060200182810382526037815260200180613f216037913960400191505060405180910390fd5b8454612477908363ffffffff612cb816565b8555600185015461248e908763ffffffff612cb816565b600186015561249d33876139c7565b6124a7338361315b565b604080518381526001600160a01b0389166020820152338183015290517fcab8e1abb9f8235c6db895cf185336dc9461aecf477b98c1be83687ee549e66a9181900360600190a150505050505050565b600f5460105460030b82565b61250b611c1b565b50611531838330611ad9565b60008061253461252684613140565b61252f85613ac3565b612d54565b159392505050565b61254533611e3a565b50611843823061131d565b601654600160401b90046001600160a01b031681565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b600061259c82612517565b15612654576001600160a01b0382166000908152600560205260408120600c54600b5482549293926125f192600390810b8503900b600a0a916125e5919063ffffffff6137a416565b9063ffffffff61398516565b600854909150600390810b600003900b600a0a61260c613d03565b60408051808201909152600754819061262b908563ffffffff612cfa16565b8152600854600390810b900b602090910152905061264983826136a9565b9450505050506112b0565b5060006112b0565b60155481565b61266a611db2565b6126a9576040805162461bcd60e51b81526020600482018190526024820152600080516020613ff5833981519152604482015290519081900360640190fd5b6014805460009091556126bc828261315b565b604080516001600160a01b03841681526020810183905281517f88b171bb78d3ac5e1caa8e729dddce4e1322e84c80c093ebbe52507b62c77d98929181900390910190a15050565b61270c611dd6565b1561274c576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b61275533611290565b612794576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b33600090815260056020526040902060018101546127b8908363ffffffff612cb816565b60018201556127c733836139c7565b604080513381526020810184905281517fdf8cebdea6ef1fd20576b80bc951377c0e61e2a8169153a1f836673ccce80e62929181900390910190a15050565b61280e611c1b565b5061148282826121d3565b612821611db2565b612860576040805162461bcd60e51b81526020600482018190526024820152600080516020613ff5833981519152604482015290519081900360640190fd5b60c88411156128a05760405162461bcd60e51b8152600401808060200182810382526025815260200180613ecf6025913960400191505060405180910390fd5b6103e88311156128e15760405162461bcd60e51b815260040180806020018281038252602b815260200180613d80602b913960400191505060405180910390fd5b6064821115612937576040805162461bcd60e51b815260206004820181905260248201527f43616e27742068617665207472616e73616374696f6e20666565203e20313025604482015290519081900360640190fd5b600a8110156129775760405162461bcd60e51b8152600401808060200182810382526028815260200180613d586028913960400191505060405180910390fd5b6007849055600b8390556009829055600d8190557f3450d20c21ea671871fed271900cc8ff03badafa9b6fe2ff7f86991950e86b6b848484846129b8611da3565b6040805195865260208601949094528484019290925260608401526001600160a01b03166080830152519081900360a00190a150505050565b6129f9611db2565b612a38576040805162461bcd60e51b81526020600482018190526024820152600080516020613ff5833981519152604482015290519081900360640190fd5b612a4181613ae1565b50565b6001600160a01b03161590565b612a5a33611290565b612a99576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b3360009081526005602052604090206002810154612af6576040805162461bcd60e51b81526020600482015260156024820152744e6f20756e6465726c79696e672062616c616e636560581b604482015290519081900360640190fd5b6002810180546000909155612b0b33826137fd565b6040805182815233602082015281517fea0bff65fa9380b944e9a761f9c6a665ad2d31e74706a52773ddb45c8a57c83d929181900390910190a15050565b6000612b53611dd6565b15612b93576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b6001600160a01b03831660009081526005602052604090208054612bbd908463ffffffff612cfa16565b908190559392505050565b3390565b6001600160a01b038316612c115760405162461bcd60e51b815260040180806020018281038252602481526020018061408a6024913960400191505060405180910390fd5b6001600160a01b038216612c565760405162461bcd60e51b8152600401808060200182810382526022815260200180613e1b6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260026020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600061113583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506130a9565b600082820183811015611135576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600080612d75601660089054906101000a90046001600160a01b0316613b81565b601854909150600090612d90906001600160a01b0316613b81565b600f54600d54919250600091612dbe9190612db290889063ffffffff6137a416565b9063ffffffff6137a416565b601054600e54919250600391820b910b016000612de5846125e58a8863ffffffff6137a416565b601654909150600390810b90600090819085810b9084900b1215612e295782850360030b915083612e2087600a85900a63ffffffff6137a416565b11159050612e4b565b84830360030b9150612e4584600a84900a63ffffffff6137a416565b86111590505b9a9950505050505050505050565b6001600160a01b038216612eb4576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b600354612ec7908263ffffffff612cfa16565b6003556001600160a01b038216600090815260016020526040902054612ef3908263ffffffff612cfa16565b6001600160a01b03831660008181526001602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038316612f905760405162461bcd60e51b81526004018080602001828103825260258152602001806140656025913960400191505060405180910390fd5b6001600160a01b038216612fd55760405162461bcd60e51b8152600401808060200182810382526023815260200180613d356023913960400191505060405180910390fd5b61301881604051806060016040528060268152602001613ea9602691396001600160a01b038616600090815260016020526040902054919063ffffffff6130a916565b6001600160a01b03808516600090815260016020526040808220939093559084168152205461304d908263ffffffff612cfa16565b6001600160a01b0380841660008181526001602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156131385760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156130fd5781810151838201526020016130e5565b50505050905090810190601f16801561312a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b031660009081526005602052604090205490565b60165461317790600160401b90046001600160a01b0316612a44565b156131b8576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156131b2573d6000803e3d6000fd5b50611482565b6016546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151600160401b9093049091169163a9059cbb916044808201926020929091908290030181600087803b15801561321657600080fd5b505af115801561322a573d6000803e3d6000fd5b505050506040513d602081101561324057600080fd5b50505050565b61324e6112b5565b6132895760405162461bcd60e51b815260040180806020018281038252602d815260200180613fa0602d913960400191505060405180910390fd5b61329281611290565b6132d1576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526005602052604090208261333b576040805162461bcd60e51b815260206004820152601860248201527f43616e27742065786572636973652030206f546f6b656e730000000000000000604482015290519081900360640190fd5b806001015483111561337e5760405162461bcd60e51b815260040180806020018281038252602e8152602001806140ae602e913960400191505060405180910390fd5b8261338833611b6f565b10156133d0576040805162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f756768206f546f6b656e7360701b604482015290519081900360640190fd5b60006133db84611b2b565b60028301549091506133f3908263ffffffff612cfa16565b600283015560408051808201909152600181526000602082018190529061341b9086906138a3565b604080518082019091526009548152600a54600390810b810b900b602082015290915060009061344c9087906138a3565b601454909150613462908263ffffffff612cfa16565b6014556000613477838363ffffffff612cfa16565b85549091508111156134d0576040805162461bcd60e51b815260206004820181905260248201527f5661756c7420756e64657277617465722c2063616e2774206578657263697365604482015290519081900360640190fd5b84546134e2908263ffffffff612cb816565b855560018501546134f9908863ffffffff612cb816565b6001860155601754613513906001600160a01b0316612a44565b1561356757833414613562576040805162461bcd60e51b8152602060048201526013602482015272496e636f7272656374206d73672e76616c756560681b604482015290519081900360640190fd5b61363e565b601754604080516323b872dd60e01b81523360048201523060248201526044810187905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b1580156135c157600080fd5b505af11580156135d5573d6000803e3d6000fd5b505050506040513d60208110156135eb57600080fd5b505161363e576040805162461bcd60e51b815260206004820152601c60248201527f436f756c64206e6f74207472616e7366657220696e20746f6b656e7300000000604482015290519081900360640190fd5b61364833886139c7565b613652338461315b565b604080518581526020810185905233818301526001600160a01b038816606082015290517ffa7bab37479e50a9b24a9412b879d400de9bcaa1e3a2b343e90bb370d85bbaa79181900360800190a150505050505050565b6000806136ca601660089054906101000a90046001600160a01b0316613b81565b6018549091506000906136e5906001600160a01b0316613b81565b600f5485519192506000916136ff9163ffffffff6137a416565b601054602087015191925060030b016000613724846125e58a8863ffffffff6137a416565b601654909150600390810b90600090819085810b9084900b12156137755782850360030b915061376e61376187600a85900a63ffffffff6137a416565b859063ffffffff61398516565b9050612e4b565b84830360030b9150613795866125e586600a86900a63ffffffff6137a416565b9b9a5050505050505050505050565b6000826137b357506000611138565b828202828482816137c057fe5b04146111355760405162461bcd60e51b8152600401808060200182810382526021815260200180613f586021913960400191505060405180910390fd5b601754613812906001600160a01b0316612a44565b1561384d576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156131b2573d6000803e3d6000fd5b6017546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561321657600080fd5b6000806138c4601660089054906101000a90046001600160a01b0316613b81565b6018549091506000906138df906001600160a01b0316613b81565b9050600061390782612db28760000151612db2600f600001548b6137a490919063ffffffff16565b6016546020870151601054929350600391820b92820b01919091039060009082900b811215613955578161394d866125e58663ffffffff808616600a0a8116906137a416565b91505061397a565b6000829003613976866125e58663ffffffff808616600a0a81169061398516565b9150505b979650505050505050565b600061113583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613c20565b6001600160a01b038216613a0c5760405162461bcd60e51b81526004018080602001828103825260218152602001806140156021913960400191505060405180910390fd5b613a4f81604051806060016040528060228152602001613dab602291396001600160a01b038516600090815260016020526040902054919063ffffffff6130a916565b6001600160a01b038316600090815260016020526040902055600354613a7b908263ffffffff612cb816565b6003556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b031660009081526005602052604090206001015490565b6001600160a01b038116613b265760405162461bcd60e51b8152600401808060200182810382526026815260200180613df56026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b038216613ba05750670de0b6b3a76400006112b0565b601954604080516341976e0960e01b81526001600160a01b038581166004830152915191909216916341976e09916024808301926020929190829003018186803b158015613bed57600080fd5b505afa158015613c01573d6000803e3d6000fd5b505050506040513d6020811015613c1757600080fd5b505190506112b0565b60008183613c6f5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156130fd5781810151838201526020016130e5565b506000838581613c7b57fe5b0495945050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613cc657805160ff1916838001178555613cf3565b82800160010185558215613cf3579182015b82811115613cf3578251825591602001919060010190613cd8565b50613cff929150613d1a565b5090565b604080518082019091526000808252602082015290565b6111e291905b80821115613cff5760008155600101613d2056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737343616e27742068617665206d696e436f6c6c61746572616c697a6174696f6e526174696f203c203143616e2774206c6971756964617465206d6f7265207468616e2031303025206f6620746865207661756c7445524332303a206275726e20616d6f756e7420657863656564732062616c616e6365455448206973206e6f74207468652073706563696669656420636f6c6c61746572616c20747970654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737343616e277420636f6c6c65637420636f6c6c61746572616c20756e74696c20657870697279436f756c64206e6f74207472616e7366657220696e20636f6c6c61746572616c20746f6b656e735661756c7420646f6573206e6f7420657869737400000000000000000000000045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636543616e27742068617665203e323025206c69717569646174696f6e20696e63656e74697665537065636966696564207661756c7473206861766520696e73756666696369656e7420636f6c6c61746572616c43616e206f6e6c79206c6971756964617465206c69717569646174696f6e20666163746f7220617420616e7920676976656e2074696d65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e27742072656d6f7665206d6f726520636f6c6c61746572616c207468616e206f776e656443616e2774206578657263697365206f757473696465206f66207468652065786572636973652077696e646f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657245524332303a206275726e2066726f6d20746865207a65726f206164647265737343616e6e6f742065786572636973652066726f6d2061207661756c74207468617420646f65736e277420657869737445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737343616e2774206578657263697365206d6f7265206f546f6b656e73207468616e20746865206f776e6572206861734f7074696f6e7320636f6e74726163742065787069726564000000000000000045524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a7230582078d274c261df68e9d5018737bd71b890ed72cabfe0e584eb1d201ad752666c9564736f6c634300050a003245786572636973652077696e646f772063616e2774206265206c6f6e676572207468616e2074686520636f6e74726163742773206c6966657370616e636f6c6c61746572616c206578706f6e656e74206e6f742077697468696e2065787065637465642072616e67656f546f6b656e2065786368616e67652072617465206578706f6e656e74206e6f742077697468696e2065787065637465642072616e6765737472696b65207072696365206578706f6e656e74206e6f742077697468696e2065787065637465642072616e6765756e6465726c79696e67206578706f6e656e74206e6f742077697468696e2065787065637465642072616e67650000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee0000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e3643fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000000000000002fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000602322000000000000000000000000005778f2824a114f6115dc74d432685d33362160170000000000000000000000007054e08461e3ecb7718b63540addb3c3a17464150000000000000000000000000000000000000000000000000000000060232200
Deployed Bytecode
0x6080604052600436106103975760003560e01c806390e64d13116101dc578063c52987cf11610102578063e184c9be116100a0578063ee1eab4f1161006f578063ee1eab4f14610ed3578063f2fde38b14610f0f578063f70a250814610f42578063faa2041f14610f7557610397565b8063e184c9be14610e35578063ea8c4bcf14610e4a578063eaa376b514610e7d578063ed1f41c314610ea757610397565b8063cfbea789116100dc578063cfbea78914610d86578063d8dfeb4514610db2578063dd62ed3e14610dc7578063dec44c0b14610e0257610397565b8063c52987cf14610cff578063c56749ce14610d14578063cdb4b5c214610d5357610397565b8063b2c2b13f1161017a578063b7b090ee11610149578063b7b090ee14610b4f578063b96661ba14610c85578063ba1be55414610cb1578063bcbaf48714610cc657610397565b8063b2c2b13f14610ae2578063b6e61c0814610b10578063b736554014610b25578063b76fdb6c14610b3a57610397565b80639ed3edf0116101b65780639ed3edf014610a46578063a457c2d714610a5b578063a9059cbb14610a94578063ad8f500814610acd57610397565b806390e64d13146109f657806395d89b4114610a0b5780639ce0725114610a2057610397565b806339509351116102c15780636fd865f91161025f5780638a5e8cc71161022e5780638a5e8cc7146109a25780638c765e94146109b75780638da5cb5b146109cc5780638f32d59b146109e157610397565b80636fd865f91461091b57806370a0823114610945578063715018a61461097857806386f547121461098d57610397565b806358b36dac1161029b57806358b36dac146107f55780635ca7c8a61461089d578063686c1e21146108dc5780636f307dc31461090657610397565b8063395093511461074c5780633bd33f621461078557806352f89fe3146107b657610397565b806318160ddd116103395780633226052d116103085780633226052d146106845780633237c158146106c3578063352ade55146106ed5780633667429f1461072057610397565b806318160ddd146105c65780631a0e21bd146105db57806323b872dd14610616578063313ce5671461065957610397565b8063095ea7b311610375578063095ea7b3146104d65780630d453efb146105235780630d6cd8aa146105565780630eb9af381461056b57610397565b806301b4a3c11461039c578063060ab2ea146103e757806306fdde031461044c575b600080fd5b3480156103a857600080fd5b506103d5600480360360408110156103bf57600080fd5b506001600160a01b038135169060200135610f8a565b60408051918252519081900360200190f35b3480156103f357600080fd5b506103fc61113e565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610438578181015183820152602001610420565b505050509050019250505060405180910390f35b34801561045857600080fd5b506104616111e5565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561049b578181015183820152602001610483565b50505050905090810190601f1680156104c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104e257600080fd5b5061050f600480360360408110156104f957600080fd5b506001600160a01b038135169060200135611273565b604080519115158252519081900360200190f35b34801561052f57600080fd5b5061050f6004803603602081101561054657600080fd5b50356001600160a01b0316611290565b34801561056257600080fd5b5061050f6112b5565b34801561057757600080fd5b5061059e6004803603602081101561058e57600080fd5b50356001600160a01b03166112e3565b6040805194855260208501939093528383019190915215156060830152519081900360800190f35b3480156105d257600080fd5b506103d5611317565b3480156105e757600080fd5b50610614600480360360408110156105fe57600080fd5b50803590602001356001600160a01b031661131d565b005b34801561062257600080fd5b5061050f6004803603606081101561063957600080fd5b506001600160a01b03813581169160208101359091169060400135611486565b34801561066557600080fd5b5061066e611513565b6040805160ff9092168252519081900360200190f35b34801561069057600080fd5b50610614600480360360608110156106a757600080fd5b50803590602081013590604001356001600160a01b031661151c565b3480156106cf57600080fd5b50610614600480360360208110156106e657600080fd5b5035611634565b3480156106f957600080fd5b50610702611824565b60408051928352600391820b90910b60208301528051918290030190f35b6106146004803603604081101561073657600080fd5b50803590602001356001600160a01b0316611830565b34801561075857600080fd5b5061050f6004803603604081101561076f57600080fd5b506001600160a01b038135169060200135611945565b34801561079157600080fd5b5061079a611999565b604080516001600160a01b039092168252519081900360200190f35b3480156107c257600080fd5b50610614600480360360608110156107d957600080fd5b50803590602081013590604001356001600160a01b03166119a8565b6106146004803603604081101561080b57600080fd5b81359190810190604081016020820135600160201b81111561082c57600080fd5b82018360208201111561083e57600080fd5b803590602001918460208302840111600160201b8311171561085f57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506119c1945050505050565b3480156108a957600080fd5b50610614600480360360608110156108c057600080fd5b50803590602081013590604001356001600160a01b0316611ad9565b3480156108e857600080fd5b506103d5600480360360208110156108ff57600080fd5b5035611aee565b34801561091257600080fd5b5061079a611b1c565b34801561092757600080fd5b506103d56004803603602081101561093e57600080fd5b5035611b2b565b34801561095157600080fd5b506103d56004803603602081101561096857600080fd5b50356001600160a01b0316611b6f565b34801561098457600080fd5b50610614611b8a565b34801561099957600080fd5b5061050f611c1b565b3480156109ae57600080fd5b5061079a611d88565b3480156109c357600080fd5b50610702611d97565b3480156109d857600080fd5b5061079a611da3565b3480156109ed57600080fd5b5061050f611db2565b348015610a0257600080fd5b5061050f611dd6565b348015610a1757600080fd5b50610461611ddf565b6103d560048036036020811015610a3657600080fd5b50356001600160a01b0316611e3a565b348015610a5257600080fd5b50610702611f74565b348015610a6757600080fd5b5061050f60048036036040811015610a7e57600080fd5b506001600160a01b038135169060200135611f80565b348015610aa057600080fd5b5061050f60048036036040811015610ab757600080fd5b506001600160a01b038135169060200135611fee565b348015610ad957600080fd5b5061079a612002565b348015610aee57600080fd5b50610af7612011565b60408051600392830b90920b8252519081900360200190f35b348015610b1c57600080fd5b50610af7612021565b348015610b3157600080fd5b5061070261202a565b348015610b4657600080fd5b50610614612036565b348015610b5b57600080fd5b5061061460048036036040811015610b7257600080fd5b810190602081018135600160201b811115610b8c57600080fd5b820183602082011115610b9e57600080fd5b803590602001918460018302840111600160201b83111715610bbf57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610c1157600080fd5b820183602082011115610c2357600080fd5b803590602001918460018302840111600160201b83111715610c4457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612142945050505050565b61061460048036036040811015610c9b57600080fd5b50803590602001356001600160a01b03166121d3565b348015610cbd57600080fd5b506107026121e7565b348015610cd257600080fd5b5061061460048036036040811015610ce957600080fd5b506001600160a01b0381351690602001356121f3565b348015610d0b57600080fd5b506107026124f7565b348015610d2057600080fd5b5061061460048036036060811015610d3757600080fd5b50803590602081013590604001356001600160a01b0316612503565b348015610d5f57600080fd5b5061050f60048036036020811015610d7657600080fd5b50356001600160a01b0316612517565b61061460048036036040811015610d9c57600080fd5b50803590602001356001600160a01b031661253c565b348015610dbe57600080fd5b5061079a612550565b348015610dd357600080fd5b506103d560048036036040811015610dea57600080fd5b506001600160a01b0381358116916020013516612566565b348015610e0e57600080fd5b506103d560048036036020811015610e2557600080fd5b50356001600160a01b0316612591565b348015610e4157600080fd5b506103d561265c565b348015610e5657600080fd5b5061061460048036036020811015610e6d57600080fd5b50356001600160a01b0316612662565b348015610e8957600080fd5b5061061460048036036020811015610ea057600080fd5b5035612704565b61061460048036036040811015610ebd57600080fd5b50803590602001356001600160a01b0316612806565b348015610edf57600080fd5b5061061460048036036080811015610ef657600080fd5b5080359060208101359060408101359060600135612819565b348015610f1b57600080fd5b5061061460048036036020811015610f3257600080fd5b50356001600160a01b03166129f1565b348015610f4e57600080fd5b5061050f60048036036020811015610f6557600080fd5b50356001600160a01b0316612a44565b348015610f8157600080fd5b50610614612a51565b6000610f94611dd6565b15610fd4576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b601654604080516323b872dd60e01b8152336004820152306024820152604481018590529051600160401b9092046001600160a01b0316916323b872dd916064808201926020929091908290030181600087803b15801561103457600080fd5b505af1158015611048573d6000803e3d6000fd5b505050506040513d602081101561105e57600080fd5b505161109b5760405162461bcd60e51b8152600401808060200182810382526027815260200180613e626027913960400191505060405180910390fd5b6110a483611290565b6110e3576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b604080516001600160a01b038516815260208101849052338183015290517f2199418ea9428ed3ff7d460860e1edaf5831452fa4ea0f8d1a60d63c603487829181900360600190a16111358383612b49565b90505b92915050565b6060806000805b6006548110156111dc576111796006828154811061115f57fe5b6000918252602090912001546001600160a01b0316611290565b156111d4576006818154811061118b57fe5b9060005260206000200160009054906101000a90046001600160a01b03168383815181106111b557fe5b6001600160a01b03909216602092830291909101909101526001909101905b600101611145565b50909150505b90565b601a805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561126b5780601f106112405761010080835404028352916020019161126b565b820191906000526020600020905b81548152906001019060200180831161124e57829003601f168201915b505050505081565b6000611287611280612bc8565b8484612bcc565b50600192915050565b6001600160a01b03811660009081526005602052604090206003015460ff165b919050565b60006112ce601354601554612cb890919063ffffffff16565b42101580156112de575060155442105b905090565b6001600160a01b03166000908152600560205260409020805460018201546002830154600390930154919390929160ff1690565b60035490565b611325611dd6565b15611365576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b61136e33611290565b6113ad576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b33600090815260056020526040812060018101549091906113d4908563ffffffff612cfa16565b90506113e4826000015482612d54565b611426576040805162461bcd60e51b815260206004820152600e60248201526d1d5b9cd85999481d1bc81b5a5b9d60921b604482015290519081900360640190fd5b600182018190556114378385612e59565b604080516001600160a01b038516815260208101869052338183015290517f5e5aaabf04e3760968ffb551bdf9708f4dbf95d53ad98539e91a56b125e88f089181900360600190a150505b5050565b6000611493848484612f4b565b6115098461149f612bc8565b61150485604051806060016040528060288152602001613fcd602891396001600160a01b038a166000908152600260205260408120906114dd612bc8565b6001600160a01b03168152602081019190915260400160002054919063ffffffff6130a916565b612bcc565b5060019392505050565b601c5460ff1681565b6115263383610f8a565b50611531833061131d565b600480546040805163095ea7b360e01b81526001600160a01b0390921692820192909252602481018590529051309163095ea7b39160448083019260209291908290030181600087803b15801561158757600080fd5b505af115801561159b573d6000803e3d6000fd5b505050506040513d60208110156115b157600080fd5b50506004805460408051637dafae5960e01b81526001600160a01b03858116948201949094523060248201526000604482018190526064820188905291519390921692637dafae5992608480820193929182900301818387803b15801561161757600080fd5b505af115801561162b573d6000803e3d6000fd5b50505050505050565b61163c611dd6565b1561167c576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b600081116116d1576040805162461bcd60e51b815260206004820152601a60248201527f43616e6e6f742072656d6f7665203020636f6c6c61746572616c000000000000604482015290519081900360640190fd5b6116da33611290565b611719576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b3360008181526005602052604090209061173290613140565b8211156117705760405162461bcd60e51b8152600401808060200182810382526027815260200180613f796027913960400191505060405180910390fd5b8054600090611785908463ffffffff612cb816565b9050611795818360010154612d54565b6117d8576040805162461bcd60e51b815260206004820152600f60248201526e5661756c7420697320756e7361666560881b604482015290519081900360640190fd5b8082556117e5338461315b565b6040805184815233602082015281517f5a945309b3c58e9bb259128c2a530a6579dc75ac1d7d61b3db4c0b8305a16821929181900390910190a1505050565b600b54600c5460030b82565b611838611c1b565b5061184382306121d3565b600480546040805163095ea7b360e01b81526001600160a01b0390921692820192909252602481018490529051309163095ea7b39160448083019260209291908290030181600087803b15801561189957600080fd5b505af11580156118ad573d6000803e3d6000fd5b505050506040513d60208110156118c357600080fd5b50506004805460408051637dafae5960e01b81526001600160a01b03858116948201949094523060248201526000604482018190526064820187905291519390921692637dafae5992608480820193929182900301818387803b15801561192957600080fd5b505af115801561193d573d6000803e3d6000fd5b505050505050565b6000611287611952612bc8565b846115048560026000611963612bc8565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff612cfa16565b6004546001600160a01b031681565b6119b0611c1b565b506119bc838383611ad9565b505050565b60005b8151811015611a9b5760008282815181106119db57fe5b602002602001015190506119ee81611290565b611a295760405162461bcd60e51b815260040180806020018281038252602f815260200180614036602f913960400191505060405180910390fd5b6001600160a01b038116600090815260056020526040902084611a4e57505050611482565b84816001015410611a6b57611a638583613246565b505050611482565b6001810154611a8190869063ffffffff612cb816565b9450611a91816001015483613246565b50506001016119c4565b5081156114825760405162461bcd60e51b815260040180806020018281038252602d815260200180613ef4602d913960400191505060405180910390fd5b611ae33383610f8a565b506119bc838261131d565b60408051808201909152600d548152600e54600390810b810b900b60208201526000906111389083906136a9565b6017546001600160a01b031681565b601654601254600091600160201b9004600390810b91810b91909103900b611b688367ffffffffffffffff808416600a0a1663ffffffff6137a416565b9392505050565b6001600160a01b031660009081526001602052604090205490565b611b92611db2565b611bd1576040805162461bcd60e51b81526020600482018190526024820152600080516020613ff5833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000611c25611dd6565b15611c65576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b611c6e33611290565b15611cb8576040805162461bcd60e51b815260206004820152601560248201527415985d5b1d08185b1c9958591e4818dc99585d1959605a1b604482015290519081900360640190fd5b60408051608081018252600080825260208083018281528385018381526001606086018181523380875260058652888720975188559351878301559151600287015590516003909501805460ff1916951515959095179094556006805494850181559092527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f90920180546001600160a01b03191682179055825190815291517f66a872561db77eb92ef3079a44a5af00c68c3a09e0976814a95bd91721f57c2f9281900390910190a150600190565b6019546001600160a01b031681565b60075460085460030b82565b6000546001600160a01b031690565b600080546001600160a01b0316611dc7612bc8565b6001600160a01b031614905090565b60155442101590565b601b805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561126b5780601f106112405761010080835404028352916020019161126b565b6000611e44611dd6565b15611e84576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b601654611ea090600160401b90046001600160a01b0316612a44565b611edb5760405162461bcd60e51b8152600401808060200182810382526028815260200180613dcd6028913960400191505060405180910390fd5b611ee482611290565b611f23576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b604080516001600160a01b0384168152346020820152338183015290517ff24ce6016de57e90501829715846e26ac283a0aabfc160647e0ae8b05e0f433d9181900360600190a16111388234612b49565b600954600a5460030b82565b6000611287611f8d612bc8565b84611504856040518060600160405280602581526020016140fc6025913960026000611fb7612bc8565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff6130a916565b6000611287611ffb612bc8565b8484612f4b565b6018546001600160a01b031681565b601654600160201b900460030b81565b60165460030b81565b60115460125460030b82565b61203e611dd6565b6120795760405162461bcd60e51b8152600401808060200182810382526025815260200180613e3d6025913960400191505060405180910390fd5b61208233611290565b6120c1576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b33600081815260056020526040812080546002820180548484556001840185905593905590929091906120f4908361315b565b6120fe33826137fd565b6040805183815260208101839052338183015290517fe481532a3f7d078365ca0145442ed0a0a3e0443f3c0bae0c29cff131112678389181900360600190a1505050565b61214a611db2565b612189576040805162461bcd60e51b81526020600482018190526024820152600080516020613ff5833981519152604482015290519081900360640190fd5b815161219c90601a906020850190613c85565b5080516121b090601b906020840190613c85565b50601254601c805460ff191660039290920b60000360ff16919091179055611482565b6121dc33611e3a565b50611482828261131d565b600d54600e5460030b82565b6121fb611dd6565b1561223b576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b61224482611290565b612283576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b6001600160a01b03821660009081526005602052604090206122a483612517565b6122e5576040805162461bcd60e51b815260206004820152600d60248201526c5661756c74206973207361666560981b604482015290519081900360640190fd5b336001600160a01b0384161415612343576040805162461bcd60e51b815260206004820181905260248201527f4f776e65722063616e2774206c6971756964617465207468656d73656c766573604482015290519081900360640190fd5b600061236883604051806040016040528060018152602001600060030b8152506138a3565b604080518082019091526007548152600854600390810b810b900b60208201529091506000906123999085906138a3565b905060006123ad838363ffffffff612cfa16565b600b5485549192506000916123c79163ffffffff6137a416565b600c549091506000600391820b90910b131561240257600c546123fb908290600390810b900b600a0a63ffffffff6137a416565b9050612426565b600c54612423908290600390810b600003900b600a0a63ffffffff61398516565b90505b808211156124655760405162461bcd60e51b8152600401808060200182810382526037815260200180613f216037913960400191505060405180910390fd5b8454612477908363ffffffff612cb816565b8555600185015461248e908763ffffffff612cb816565b600186015561249d33876139c7565b6124a7338361315b565b604080518381526001600160a01b0389166020820152338183015290517fcab8e1abb9f8235c6db895cf185336dc9461aecf477b98c1be83687ee549e66a9181900360600190a150505050505050565b600f5460105460030b82565b61250b611c1b565b50611531838330611ad9565b60008061253461252684613140565b61252f85613ac3565b612d54565b159392505050565b61254533611e3a565b50611843823061131d565b601654600160401b90046001600160a01b031681565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b600061259c82612517565b15612654576001600160a01b0382166000908152600560205260408120600c54600b5482549293926125f192600390810b8503900b600a0a916125e5919063ffffffff6137a416565b9063ffffffff61398516565b600854909150600390810b600003900b600a0a61260c613d03565b60408051808201909152600754819061262b908563ffffffff612cfa16565b8152600854600390810b900b602090910152905061264983826136a9565b9450505050506112b0565b5060006112b0565b60155481565b61266a611db2565b6126a9576040805162461bcd60e51b81526020600482018190526024820152600080516020613ff5833981519152604482015290519081900360640190fd5b6014805460009091556126bc828261315b565b604080516001600160a01b03841681526020810183905281517f88b171bb78d3ac5e1caa8e729dddce4e1322e84c80c093ebbe52507b62c77d98929181900390910190a15050565b61270c611dd6565b1561274c576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b61275533611290565b612794576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b33600090815260056020526040902060018101546127b8908363ffffffff612cb816565b60018201556127c733836139c7565b604080513381526020810184905281517fdf8cebdea6ef1fd20576b80bc951377c0e61e2a8169153a1f836673ccce80e62929181900390910190a15050565b61280e611c1b565b5061148282826121d3565b612821611db2565b612860576040805162461bcd60e51b81526020600482018190526024820152600080516020613ff5833981519152604482015290519081900360640190fd5b60c88411156128a05760405162461bcd60e51b8152600401808060200182810382526025815260200180613ecf6025913960400191505060405180910390fd5b6103e88311156128e15760405162461bcd60e51b815260040180806020018281038252602b815260200180613d80602b913960400191505060405180910390fd5b6064821115612937576040805162461bcd60e51b815260206004820181905260248201527f43616e27742068617665207472616e73616374696f6e20666565203e20313025604482015290519081900360640190fd5b600a8110156129775760405162461bcd60e51b8152600401808060200182810382526028815260200180613d586028913960400191505060405180910390fd5b6007849055600b8390556009829055600d8190557f3450d20c21ea671871fed271900cc8ff03badafa9b6fe2ff7f86991950e86b6b848484846129b8611da3565b6040805195865260208601949094528484019290925260608401526001600160a01b03166080830152519081900360a00190a150505050565b6129f9611db2565b612a38576040805162461bcd60e51b81526020600482018190526024820152600080516020613ff5833981519152604482015290519081900360640190fd5b612a4181613ae1565b50565b6001600160a01b03161590565b612a5a33611290565b612a99576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b3360009081526005602052604090206002810154612af6576040805162461bcd60e51b81526020600482015260156024820152744e6f20756e6465726c79696e672062616c616e636560581b604482015290519081900360640190fd5b6002810180546000909155612b0b33826137fd565b6040805182815233602082015281517fea0bff65fa9380b944e9a761f9c6a665ad2d31e74706a52773ddb45c8a57c83d929181900390910190a15050565b6000612b53611dd6565b15612b93576040805162461bcd60e51b815260206004820152601860248201526000805160206140dc833981519152604482015290519081900360640190fd5b6001600160a01b03831660009081526005602052604090208054612bbd908463ffffffff612cfa16565b908190559392505050565b3390565b6001600160a01b038316612c115760405162461bcd60e51b815260040180806020018281038252602481526020018061408a6024913960400191505060405180910390fd5b6001600160a01b038216612c565760405162461bcd60e51b8152600401808060200182810382526022815260200180613e1b6022913960400191505060405180910390fd5b6001600160a01b03808416600081815260026020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600061113583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506130a9565b600082820183811015611135576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600080612d75601660089054906101000a90046001600160a01b0316613b81565b601854909150600090612d90906001600160a01b0316613b81565b600f54600d54919250600091612dbe9190612db290889063ffffffff6137a416565b9063ffffffff6137a416565b601054600e54919250600391820b910b016000612de5846125e58a8863ffffffff6137a416565b601654909150600390810b90600090819085810b9084900b1215612e295782850360030b915083612e2087600a85900a63ffffffff6137a416565b11159050612e4b565b84830360030b9150612e4584600a84900a63ffffffff6137a416565b86111590505b9a9950505050505050505050565b6001600160a01b038216612eb4576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b600354612ec7908263ffffffff612cfa16565b6003556001600160a01b038216600090815260016020526040902054612ef3908263ffffffff612cfa16565b6001600160a01b03831660008181526001602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038316612f905760405162461bcd60e51b81526004018080602001828103825260258152602001806140656025913960400191505060405180910390fd5b6001600160a01b038216612fd55760405162461bcd60e51b8152600401808060200182810382526023815260200180613d356023913960400191505060405180910390fd5b61301881604051806060016040528060268152602001613ea9602691396001600160a01b038616600090815260016020526040902054919063ffffffff6130a916565b6001600160a01b03808516600090815260016020526040808220939093559084168152205461304d908263ffffffff612cfa16565b6001600160a01b0380841660008181526001602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156131385760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156130fd5781810151838201526020016130e5565b50505050905090810190601f16801561312a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b031660009081526005602052604090205490565b60165461317790600160401b90046001600160a01b0316612a44565b156131b8576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156131b2573d6000803e3d6000fd5b50611482565b6016546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151600160401b9093049091169163a9059cbb916044808201926020929091908290030181600087803b15801561321657600080fd5b505af115801561322a573d6000803e3d6000fd5b505050506040513d602081101561324057600080fd5b50505050565b61324e6112b5565b6132895760405162461bcd60e51b815260040180806020018281038252602d815260200180613fa0602d913960400191505060405180910390fd5b61329281611290565b6132d1576040805162461bcd60e51b81526020600482015260146024820152600080516020613e89833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526005602052604090208261333b576040805162461bcd60e51b815260206004820152601860248201527f43616e27742065786572636973652030206f546f6b656e730000000000000000604482015290519081900360640190fd5b806001015483111561337e5760405162461bcd60e51b815260040180806020018281038252602e8152602001806140ae602e913960400191505060405180910390fd5b8261338833611b6f565b10156133d0576040805162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f756768206f546f6b656e7360701b604482015290519081900360640190fd5b60006133db84611b2b565b60028301549091506133f3908263ffffffff612cfa16565b600283015560408051808201909152600181526000602082018190529061341b9086906138a3565b604080518082019091526009548152600a54600390810b810b900b602082015290915060009061344c9087906138a3565b601454909150613462908263ffffffff612cfa16565b6014556000613477838363ffffffff612cfa16565b85549091508111156134d0576040805162461bcd60e51b815260206004820181905260248201527f5661756c7420756e64657277617465722c2063616e2774206578657263697365604482015290519081900360640190fd5b84546134e2908263ffffffff612cb816565b855560018501546134f9908863ffffffff612cb816565b6001860155601754613513906001600160a01b0316612a44565b1561356757833414613562576040805162461bcd60e51b8152602060048201526013602482015272496e636f7272656374206d73672e76616c756560681b604482015290519081900360640190fd5b61363e565b601754604080516323b872dd60e01b81523360048201523060248201526044810187905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b1580156135c157600080fd5b505af11580156135d5573d6000803e3d6000fd5b505050506040513d60208110156135eb57600080fd5b505161363e576040805162461bcd60e51b815260206004820152601c60248201527f436f756c64206e6f74207472616e7366657220696e20746f6b656e7300000000604482015290519081900360640190fd5b61364833886139c7565b613652338461315b565b604080518581526020810185905233818301526001600160a01b038816606082015290517ffa7bab37479e50a9b24a9412b879d400de9bcaa1e3a2b343e90bb370d85bbaa79181900360800190a150505050505050565b6000806136ca601660089054906101000a90046001600160a01b0316613b81565b6018549091506000906136e5906001600160a01b0316613b81565b600f5485519192506000916136ff9163ffffffff6137a416565b601054602087015191925060030b016000613724846125e58a8863ffffffff6137a416565b601654909150600390810b90600090819085810b9084900b12156137755782850360030b915061376e61376187600a85900a63ffffffff6137a416565b859063ffffffff61398516565b9050612e4b565b84830360030b9150613795866125e586600a86900a63ffffffff6137a416565b9b9a5050505050505050505050565b6000826137b357506000611138565b828202828482816137c057fe5b04146111355760405162461bcd60e51b8152600401808060200182810382526021815260200180613f586021913960400191505060405180910390fd5b601754613812906001600160a01b0316612a44565b1561384d576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156131b2573d6000803e3d6000fd5b6017546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561321657600080fd5b6000806138c4601660089054906101000a90046001600160a01b0316613b81565b6018549091506000906138df906001600160a01b0316613b81565b9050600061390782612db28760000151612db2600f600001548b6137a490919063ffffffff16565b6016546020870151601054929350600391820b92820b01919091039060009082900b811215613955578161394d866125e58663ffffffff808616600a0a8116906137a416565b91505061397a565b6000829003613976866125e58663ffffffff808616600a0a81169061398516565b9150505b979650505050505050565b600061113583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613c20565b6001600160a01b038216613a0c5760405162461bcd60e51b81526004018080602001828103825260218152602001806140156021913960400191505060405180910390fd5b613a4f81604051806060016040528060228152602001613dab602291396001600160a01b038516600090815260016020526040902054919063ffffffff6130a916565b6001600160a01b038316600090815260016020526040902055600354613a7b908263ffffffff612cb816565b6003556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b031660009081526005602052604090206001015490565b6001600160a01b038116613b265760405162461bcd60e51b8152600401808060200182810382526026815260200180613df56026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b60006001600160a01b038216613ba05750670de0b6b3a76400006112b0565b601954604080516341976e0960e01b81526001600160a01b038581166004830152915191909216916341976e09916024808301926020929190829003018186803b158015613bed57600080fd5b505afa158015613c01573d6000803e3d6000fd5b505050506040513d6020811015613c1757600080fd5b505190506112b0565b60008183613c6f5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156130fd5781810151838201526020016130e5565b506000838581613c7b57fe5b0495945050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613cc657805160ff1916838001178555613cf3565b82800160010185558215613cf3579182015b82811115613cf3578251825591602001919060010190613cd8565b50613cff929150613d1a565b5090565b604080518082019091526000808252602082015290565b6111e291905b80821115613cff5760008155600101613d2056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737343616e27742068617665206d696e436f6c6c61746572616c697a6174696f6e526174696f203c203143616e2774206c6971756964617465206d6f7265207468616e2031303025206f6620746865207661756c7445524332303a206275726e20616d6f756e7420657863656564732062616c616e6365455448206973206e6f74207468652073706563696669656420636f6c6c61746572616c20747970654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737343616e277420636f6c6c65637420636f6c6c61746572616c20756e74696c20657870697279436f756c64206e6f74207472616e7366657220696e20636f6c6c61746572616c20746f6b656e735661756c7420646f6573206e6f7420657869737400000000000000000000000045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636543616e27742068617665203e323025206c69717569646174696f6e20696e63656e74697665537065636966696564207661756c7473206861766520696e73756666696369656e7420636f6c6c61746572616c43616e206f6e6c79206c6971756964617465206c69717569646174696f6e20666163746f7220617420616e7920676976656e2074696d65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e27742072656d6f7665206d6f726520636f6c6c61746572616c207468616e206f776e656443616e2774206578657263697365206f757473696465206f66207468652065786572636973652077696e646f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657245524332303a206275726e2066726f6d20746865207a65726f206164647265737343616e6e6f742065786572636973652066726f6d2061207661756c74207468617420646f65736e277420657869737445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737343616e2774206578657263697365206d6f7265206f546f6b656e73207468616e20746865206f776e6572206861734f7074696f6e7320636f6e74726163742065787069726564000000000000000045524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a7230582078d274c261df68e9d5018737bd71b890ed72cabfe0e584eb1d201ad752666c9564736f6c634300050a0032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee0000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e3643fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000000000000000000000000000000000000000000000000000000000002fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000602322000000000000000000000000005778f2824a114f6115dc74d432685d33362160170000000000000000000000007054e08461e3ecb7718b63540addb3c3a17464150000000000000000000000000000000000000000000000000000000060232200
-----Decoded View---------------
Arg [0] : _collateral (address): 0x0000000000000000000000000000000000000000
Arg [1] : _collExp (int32): -18
Arg [2] : _underlying (address): 0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643
Arg [3] : _underlyingExp (int32): -8
Arg [4] : _oTokenExchangeExp (int32): -8
Arg [5] : _strikePrice (uint256): 2
Arg [6] : _strikeExp (int32): -10
Arg [7] : _strike (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [8] : _expiry (uint256): 1612915200
Arg [9] : _optionsExchange (address): 0x5778f2824a114F6115dc74d432685d3336216017
Arg [10] : _oracleAddress (address): 0x7054e08461e3eCb7718B63540adDB3c3A1746415
Arg [11] : _windowSize (uint256): 1612915200
-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [1] : ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee
Arg [2] : 0000000000000000000000005d3a536e4d6dbd6114cc1ead35777bab948e3643
Arg [3] : fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8
Arg [4] : fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [6] : fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6
Arg [7] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [8] : 0000000000000000000000000000000000000000000000000000000060232200
Arg [9] : 0000000000000000000000005778f2824a114f6115dc74d432685d3336216017
Arg [10] : 0000000000000000000000007054e08461e3ecb7718b63540addb3c3a1746415
Arg [11] : 0000000000000000000000000000000000000000000000000000000060232200
Deployed Bytecode Sourcemap
76403:7558:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51596:480;;8:9:-1;5:2;;;30:1;27;20:12;5:2;51596:480:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;51596:480:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;45645:383;;8:9:-1;5:2;;;30:1;27;20:12;5:2;45645:383:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;45645:383:0;;;;;;;;;;;;;;;;;41188:18;;8:9:-1;5:2;;;30:1;27;20:12;5:2;41188:18:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;41188:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12136:152;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12136:152:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;12136:152:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;48878:113;;8:9:-1;5:2;;;30:1;27;20:12;5:2;48878:113:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;48878:113:0;-1:-1:-1;;;;;48878:113:0;;:::i;52594:169::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52594:169:0;;;:::i;56975:342::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56975:342:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;56975:342:0;-1:-1:-1;;;;;56975:342:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11157:91;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11157:91:0;;;:::i;56048:788::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56048:788:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;56048:788:0;;;;;;-1:-1:-1;;;;;56048:788:0;;:::i;:::-;;12760:304;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12760:304:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;12760:304:0;;;;;;;;;;;;;;;;;:::i;41327:21::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;41327:21:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;83478:480;;8:9:-1;5:2;;;30:1;27;20:12;5:2;83478:480:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;83478:480:0;;;;;;;;;;;-1:-1:-1;;;;;83478:480:0;;:::i;58445:870::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;58445:870:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;58445:870:0;;:::i;39825:49::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;39825:49:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;79712:435;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;79712:435:0;;;;;;-1:-1:-1;;;;;79712:435:0;;:::i;13473:210::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;13473:210:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;13473:210:0;;;;;;;;:::i;39364:38::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;39364:38:0;;;:::i;:::-;;;;-1:-1:-1;;;;;39364:38:0;;;;;;;;;;;;;;81388:245;;8:9:-1;5:2;;;30:1;27;20:12;5:2;81388:245:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;81388:245:0;;;;;;;;;;;-1:-1:-1;;;;;81388:245:0;;:::i;53692:1013::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;53692:1013:0;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;53692:1013:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;53692:1013:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;53692:1013:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;53692:1013:0;;-1:-1:-1;53692:1013:0;;-1:-1:-1;;;;;53692:1013:0:i;82172:247::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;82172:247:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;82172:247:0;;;;;;;;;;;-1:-1:-1;;;;;82172:247:0;;:::i;71420:199::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;71420:199:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;71420:199:0;;:::i;40940:24::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;40940:24:0;;;:::i;52193:320::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52193:320:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;52193:320:0;;:::i;11311:110::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11311:110:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11311:110:0;-1:-1:-1;;;;;11311:110:0;;:::i;37970:140::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;37970:140:0;;;:::i;49113:284::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;49113:284:0;;;:::i;41099:46::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;41099:46:0;;;:::i;39546:51::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;39546:51:0;;;:::i;37159:79::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;37159:79:0;;;:::i;37525:94::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;37525:94:0;;;:::i;52853:102::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;52853:102:0;;;:::i;41251:20::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;41251:20:0;;;:::i;50201:418::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;50201:418:0;-1:-1:-1;;;;;50201:418:0;;:::i;39640:44::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;39640:44:0;;;:::i;14186:261::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;14186:261:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;14186:261:0;;;;;;;;:::i;11634:158::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11634:158:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;11634:158:0;;;;;;;;:::i;41029:20::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;41029:20:0;;;:::i;40786:32::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;40786:32:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;40705;;8:9:-1;5:2;;;30:1;27;20:12;5:2;40705:32:0;;;:::i;40280:::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;40280:32:0;;;:::i;59577:800::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59577:800:0;;;:::i;47942:361::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;47942:361:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;47942:361:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;47942:361:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;47942:361:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;47942:361:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;47942:361:0;;;;;;;;-1:-1:-1;47942:361:0;;-1:-1:-1;;;;;5:28;;2:2;;;46:1;43;36:12;2:2;47942:361:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;47942:361:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;-1:-1;;;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;47942:361:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;47942:361:0;;-1:-1:-1;47942:361:0;;-1:-1:-1;;;;;47942:361:0:i;79282:202::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;79282:202:0;;;;;;-1:-1:-1;;;;;79282:202:0;;:::i;40072:56::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;40072:56:0;;;:::i;61981:1984::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;61981:1984:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;61981:1984:0;;;;;;;;:::i;40189:25::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;40189:25:0;;;:::i;82717:478::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;82717:478:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;82717:478:0;;;;;;;;;;;-1:-1:-1;;;;;82717:478:0;;:::i;64153:241::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;64153:241:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;64153:241:0;-1:-1:-1;;;;;64153:241:0;;:::i;80397:437::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;80397:437:0;;;;;;-1:-1:-1;;;;;80397:437:0;;:::i;40856:24::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;40856:24:0;;;:::i;11855:134::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11855:134:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;11855:134:0;;;;;;;;;;:::i;60574:790::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;60574:790:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;60574:790:0;-1:-1:-1;;;;;60574:790:0;;:::i;40635:21::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;40635:21:0;;;:::i;48484:219::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;48484:219:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;48484:219:0;-1:-1:-1;;;;;48484:219:0;;:::i;57839:343::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;57839:343:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;57839:343:0;;:::i;78580:200::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;78580:200:0;;;;;;-1:-1:-1;;;;;78580:200:0;;:::i;46591:1126::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;46591:1126:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;46591:1126:0;;;;;;;;;;;;;;;;;:::i;38265:109::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;38265:109:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38265:109:0;-1:-1:-1;;;;;38265:109:0;;:::i;57439:104::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;57439:104:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;57439:104:0;-1:-1:-1;;;;;57439:104:0;;:::i;54838:449::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;54838:449:0;;;:::i;51596:480::-;51719:7;45498:12;:10;:12::i;:::-;45497:13;45489:50;;;;;-1:-1:-1;;;45489:50:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;45489:50:0;;;;;;;;;;;;;;;51766:10;;:55;;;-1:-1:-1;;;51766:55:0;;51790:10;51766:55;;;;51810:4;51766:55;;;;;;;;;;;;-1:-1:-1;;;51766:10:0;;;-1:-1:-1;;;;;51766:10:0;;:23;;:55;;;;;;;;;;;;;;;-1:-1:-1;51766:10:0;:55;;;5:2:-1;;;;30:1;27;20:12;5:2;51766:55:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;51766:55:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;51766:55:0;51744:144;;;;-1:-1:-1;;;51744:144:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51907:20;51916:10;51907:8;:20::i;:::-;51899:53;;;;;-1:-1:-1;;;51899:53:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;51899:53:0;;;;;;;;;;;;;;;51970:49;;;-1:-1:-1;;;;;51970:49:0;;;;;;;;;;52008:10;51970:49;;;;;;;;;;;;;;;52037:31;52052:10;52064:3;52037:14;:31::i;:::-;52030:38;;45550:1;51596:480;;;;:::o;45645:383::-;45692:24;;45771:13;;45799:196;45823:11;:18;45819:22;;45799:196;;;45867:24;45876:11;45888:1;45876:14;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;45876:14:0;45867:8;:24::i;:::-;45863:121;;;45928:11;45940:1;45928:14;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;45928:14:0;45912:6;45919:5;45912:13;;;;;;;;-1:-1:-1;;;;;45912:30:0;;;:13;;;;;;;;;;;:30;45961:7;;;;;45863:121;45843:3;;45799:196;;;-1:-1:-1;46014:6:0;;-1:-1:-1;;45645:383:0;;:::o;41188:18::-;;;;;;;;;;;;;;;-1:-1:-1;;41188:18:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;12136:152::-;12202:4;12219:39;12228:12;:10;:12::i;:::-;12242:7;12251:6;12219:8;:39::i;:::-;-1:-1:-1;12276:4:0;12136:152;;;;:::o;48878:113::-;-1:-1:-1;;;;;48964:13:0;;48940:4;48964:13;;;:6;:13;;;;;:19;;;;;48878:113;;;;:::o;52594:169::-;52643:4;52688:22;52699:10;;52688:6;;:10;;:22;;;;:::i;:::-;52669:15;:41;;52668:86;;;;;52747:6;;52729:15;:24;52668:86;52660:95;;52594:169;:::o;56975:342::-;-1:-1:-1;;;;;57140:18:0;57069:7;57140:18;;;:6;:18;;;;;57191:16;;57222:19;;;;57256:16;;;;57287:11;;;;;57191:16;;57222:19;;57256:16;57287:11;;;56975:342::o;11157:91::-;11228:12;;11157:91;:::o;56048:788::-;45498:12;:10;:12::i;:::-;45497:13;45489:50;;;;;-1:-1:-1;;;45489:50:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;45489:50:0;;;;;;;;;;;;;;;56294:20;56303:10;56294:8;:20::i;:::-;56286:53;;;;;-1:-1:-1;;;56286:53:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;56286:53:0;;;;;;;;;;;;;;;56381:10;56352:19;56374:18;;;:6;:18;;;;;56498:19;;;;56374:18;;56352:19;56498:39;;56522:14;56498:39;:23;:39;:::i;:::-;56470:67;;56556:43;56563:5;:16;;;56581:17;56556:6;:43::i;:::-;56548:70;;;;;-1:-1:-1;;;56548:70:0;;;;;;;;;;;;-1:-1:-1;;;56548:70:0;;;;;;;;;;;;;;;56661:19;;;:39;;;56711:31;56717:8;56727:14;56711:5;:31::i;:::-;56760:51;;;-1:-1:-1;;;;;56760:51:0;;;;;;;;;;56800:10;56760:51;;;;;;;;;;;;;;;56822:7;;45550:1;56048:788;;:::o;12760:304::-;12849:4;12866:36;12876:6;12884:9;12895:6;12866:9;:36::i;:::-;12913:121;12922:6;12930:12;:10;:12::i;:::-;12944:89;12982:6;12944:89;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;12944:19:0;;;;;;:11;:19;;;;;;12964:12;:10;:12::i;:::-;-1:-1:-1;;;;;12944:33:0;;;;;;;;;;;;-1:-1:-1;12944:33:0;;;:89;;:37;:89;:::i;:::-;12913:8;:121::i;:::-;-1:-1:-1;13052:4:0;12760:304;;;;;:::o;41327:21::-;;;;;;:::o;83478:480::-;83641:45;83660:10;83672:13;83641:18;:45::i;:::-;;83697:40;83710:11;83731:4;83697:12;:40::i;:::-;83769:15;;;83748:51;;;-1:-1:-1;;;83748:51:0;;-1:-1:-1;;;;;83769:15:0;;;83748:51;;;;;;;;;;;;;;;:4;;:12;;:51;;;;;;;;;;;;;;-1:-1:-1;83748:4:0;:51;;;5:2:-1;;;;30:1;27;20:12;5:2;83748:51:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;83748:51:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;83810:15:0;;;:140;;;-1:-1:-1;;;83810:140:0;;-1:-1:-1;;;;;83810:140:0;;;;;;;;;;83883:4;83810:140;;;;:15;:140;;;;;;;;;;;;;;:15;;;;;:27;;:140;;;;;:15;:140;;;;;;:15;;:140;;;5:2:-1;;;;30:1;27;20:12;5:2;83810:140:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;83810:140:0;;;;83478:480;;;:::o;58445:870::-;45498:12;:10;:12::i;:::-;45497:13;45489:50;;;;;-1:-1:-1;;;45489:50:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;45489:50:0;;;;;;;;;;;;;;;58543:1;58529:11;:15;58521:54;;;;;-1:-1:-1;;;58521:54:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;58594:20;58603:10;58594:8;:20::i;:::-;58586:53;;;;;-1:-1:-1;;;58586:53:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;58586:53:0;;;;;;;;;;;;;;;58681:10;58652:19;58674:18;;;:6;:18;;;;;;58740:25;;:13;:25::i;:::-;58725:11;:40;;58703:129;;;;-1:-1:-1;;;58703:129:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58948:16;;58917:28;;58948:33;;58969:11;58948:33;:20;:33;:::i;:::-;58917:64;;59016:49;59023:20;59045:5;:19;;;59016:6;:49::i;:::-;58994:114;;;;;-1:-1:-1;;;58994:114:0;;;;;;;;;;;;-1:-1:-1;;;58994:114:0;;;;;;;;;;;;;;;59155:39;;;59205:43;59224:10;59236:11;59205:18;:43::i;:::-;59266:41;;;;;;59296:10;59266:41;;;;;;;;;;;;;;;;;45550:1;;58445:870;:::o;39825:49::-;;;;;;;;:::o;79712:435::-;79854:11;:9;:11::i;:::-;;79876:50;79899:11;79920:4;79876:22;:50::i;:::-;79958:15;;;79937:51;;;-1:-1:-1;;;79937:51:0;;-1:-1:-1;;;;;79958:15:0;;;79937:51;;;;;;;;;;;;;;;:4;;:12;;:51;;;;;;;;;;;;;;-1:-1:-1;79937:4:0;:51;;;5:2:-1;;;;30:1;27;20:12;5:2;79937:51:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;79937:51:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;79999:15:0;;;:140;;;-1:-1:-1;;;79999:140:0;;-1:-1:-1;;;;;79999:140:0;;;;;;;;;;80072:4;79999:140;;;;:15;:140;;;;;;;;;;;;;;:15;;;;;:27;;:140;;;;;:15;:140;;;;;;:15;;:140;;;5:2:-1;;;;30:1;27;20:12;5:2;79999:140:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;79999:140:0;;;;79712:435;;:::o;13473:210::-;13553:4;13570:83;13579:12;:10;:12::i;:::-;13593:7;13602:50;13641:10;13602:11;:25;13614:12;:10;:12::i;:::-;-1:-1:-1;;;;;13602:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;13602:25:0;;;:34;;;;;;;;;;;:50;:38;:50;:::i;39364:38::-;;;-1:-1:-1;;;;;39364:38:0;;:::o;81388:245::-;81541:11;:9;:11::i;:::-;;81563:62;81588:11;81601:13;81616:8;81563:24;:62::i;:::-;81388:245;;;:::o;53692:1013::-;53840:9;53835:735;53859:20;:27;53855:1;:31;53835:735;;;53908:26;53937:20;53958:1;53937:23;;;;;;;;;;;;;;53908:52;;54001:20;54010:10;54001:8;:20::i;:::-;53975:129;;;;-1:-1:-1;;;53975:129:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;54141:18:0;;54119:19;54141:18;;;:6;:18;;;;;54178:22;54174:385;;54221:7;;;;;54174:385;54276:17;54253:5;:19;;;:40;54249:310;;54314:40;54324:17;54343:10;54314:9;:40::i;:::-;54373:7;;;;;54249:310;54462:19;;;;54440:42;;:17;;:42;:21;:42;:::i;:::-;54420:62;;54501:42;54511:5;:19;;;54532:10;54501:9;:42::i;:::-;-1:-1:-1;;53888:3:0;;53835:735;;;-1:-1:-1;54602:22:0;;54580:117;;;;-1:-1:-1;;;54580:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82172:247;82320:45;82339:10;82351:13;82320:18;:45::i;:::-;;82376:35;82389:11;82402:8;82376:12;:35::i;71420:199::-;71551:58;;;;;;;;;71583:25;71551:58;;;;;;;;;;;;;;;;;71519:7;;71551:58;;71568:13;;71551:16;:58::i;40940:24::-;;;-1:-1:-1;;;;;40940:24:0;;:::o;52193:320::-;52414:13;;52384:27;;52306:7;;-1:-1:-1;;;52414:13:0;;;;;;52384:27;;;:43;;;;52363:75;;52456:49;:17;52478:26;;;;:2;:26;52456:49;;:21;:49;:::i;:::-;52449:56;52193:320;-1:-1:-1;;;52193:320:0:o;11311:110::-;-1:-1:-1;;;;;11395:18:0;11368:7;11395:18;;;:9;:18;;;;;;;11311:110::o;37970:140::-;37371:9;:7;:9::i;:::-;37363:54;;;;;-1:-1:-1;;;37363:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;37363:54:0;;;;;;;;;;;;;;;38069:1;38053:6;;38032:40;;-1:-1:-1;;;;;38053:6:0;;;;38032:40;;38069:1;;38032:40;38100:1;38083:19;;-1:-1:-1;;;;;;38083:19:0;;;37970:140::o;49113:284::-;49161:4;45498:12;:10;:12::i;:::-;45497:13;45489:50;;;;;-1:-1:-1;;;45489:50:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;45489:50:0;;;;;;;;;;;;;;;49187:20;49196:10;49187:8;:20::i;:::-;49186:21;49178:55;;;;;-1:-1:-1;;;49178:55:0;;;;;;;;;;;;-1:-1:-1;;;49178:55:0;;;;;;;;;;;;;;;49267:20;;;;;;;;-1:-1:-1;49267:20:0;;;;;;;;;;;;;;;;49282:4;49267:20;;;;;;49253:10;49246:18;;;:6;:18;;;;;:41;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;49246:41:0;;;;;;;;;;;49298:11;27:10:-1;;23:18;;;45:23;;49298:28:0;;;;;;;;;-1:-1:-1;;;;;;49298:28:0;;;;;49344:23;;;;;;;;;;;;;;;;;-1:-1:-1;49385:4:0;49113:284;:::o;41099:46::-;;;-1:-1:-1;;;;;41099:46:0;;:::o;39546:51::-;;;;;;;;:::o;37159:79::-;37197:7;37224:6;-1:-1:-1;;;;;37224:6:0;37159:79;:::o;37525:94::-;37565:4;37605:6;;-1:-1:-1;;;;;37605:6:0;37589:12;:10;:12::i;:::-;-1:-1:-1;;;;;37589:22:0;;37582:29;;37525:94;:::o;52853:102::-;52940:6;;52921:15;:25;;52853:102;:::o;41251:20::-;;;;;;;;;;;;;;;-1:-1:-1;;41251:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50201:418;50326:7;45498:12;:10;:12::i;:::-;45497:13;45489:50;;;;;-1:-1:-1;;;45489:50:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;45489:50:0;;;;;;;;;;;;;;;50365:10;;50359:17;;-1:-1:-1;;;50365:10:0;;-1:-1:-1;;;;;50365:10:0;50359:5;:17::i;:::-;50351:70;;;;-1:-1:-1;;;50351:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50440:20;50449:10;50440:8;:20::i;:::-;50432:53;;;;;-1:-1:-1;;;50432:53:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;50432:53:0;;;;;;;;;;;;;;;50503;;;-1:-1:-1;;;;;50503:53:0;;;;50534:9;50503:53;;;;50545:10;50503:53;;;;;;;;;;;;;;;50574:37;50589:10;50601:9;50574:14;:37::i;39640:44::-;;;;;;;;:::o;14186:261::-;14271:4;14288:129;14297:12;:10;:12::i;:::-;14311:7;14320:96;14359:15;14320:96;;;;;;;;;;;;;;;;;:11;:25;14332:12;:10;:12::i;:::-;-1:-1:-1;;;;;14320:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;14320:25:0;;;:34;;;;;;;;;;;:96;;:38;:96;:::i;11634:158::-;11703:4;11720:42;11730:12;:10;:12::i;:::-;11744:9;11755:6;11720:9;:42::i;41029:20::-;;;-1:-1:-1;;;;;41029:20:0;;:::o;40786:32::-;;;-1:-1:-1;;;40786:32:0;;;;;:::o;40705:::-;;;;;;:::o;40280:::-;;;;;;;;:::o;59577:800::-;59633:12;:10;:12::i;:::-;59625:62;;;;-1:-1:-1;;;59625:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59706:20;59715:10;59706:8;:20::i;:::-;59698:53;;;;;-1:-1:-1;;;59698:53:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;59698:53:0;;;;;;;;;;;;;;;59831:10;59802:19;59824:18;;;:6;:18;;;;;59927:16;;59985;;;;;60014:20;;;-1:-1:-1;60045:19:0;;:23;;;60079:20;;;59824:18;;59927:16;;59985;60112:52;;59927:16;60112:18;:52::i;:::-;60175;60194:10;60206:20;60175:18;:52::i;:::-;60245:124;;;;;;;;;;;;60348:10;60245:124;;;;;;;;;;;;;;;59577:800;;;:::o;47942:361::-;37371:9;:7;:9::i;:::-;37363:54;;;;;-1:-1:-1;;;37363:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;37363:54:0;;;;;;;;;;;;;;;48057:12;;;;:4;;:12;;;;;:::i;:::-;-1:-1:-1;48080:16:0;;;;:6;;:16;;;;;:::i;:::-;-1:-1:-1;48129:27:0;;48107:8;:50;;-1:-1:-1;;48107:50:0;48129:27;;;;;;48124:32;48107:50;;;;;;;;48168:127;;79282:202;79402:28;79419:10;79402:16;:28::i;:::-;;79441:35;79454:11;79467:8;79441:12;:35::i;40072:56::-;;;;;;;;:::o;61981:1984::-;45498:12;:10;:12::i;:::-;45497:13;45489:50;;;;;-1:-1:-1;;;45489:50:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;45489:50:0;;;;;;;;;;;;;;;62116:20;62125:10;62116:8;:20::i;:::-;62108:53;;;;;-1:-1:-1;;;62108:53:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;62108:53:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;62196:18:0;;62174:19;62196:18;;;:6;:18;;;;;62278:20;62203:10;62278:8;:20::i;:::-;62270:46;;;;;-1:-1:-1;;;62270:46:0;;;;;;;;;;;;-1:-1:-1;;;62270:46:0;;;;;;;;;;;;;;;62382:10;-1:-1:-1;;;;;62382:24:0;;;;62374:69;;;;;-1:-1:-1;;;62374:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62456:21;62480:95;62519:18;62552:12;;;;;;;;62559:1;62552:12;;;;62562:1;62552:12;;;;;62480:24;:95::i;:::-;62609:103;;;;;;;;;62681:20;62609:103;;;;;;;;;;;;;;;;;62456:119;;-1:-1:-1;62586:20:0;;62609:103;;62648:18;;62609:24;:103::i;:::-;62586:126;-1:-1:-1;62723:26:0;62752:31;:13;62586:126;62752:31;:17;:31;:::i;:::-;62945:17;:23;62910:16;;62723:60;;-1:-1:-1;62874:33:0;;62910:69;;;:20;:69;:::i;:::-;62996:26;;62874:105;;-1:-1:-1;63025:1:0;62996:26;;;;:30;;;;62992:361;;;63131:26;;63071:102;;:25;;63131:26;;;;63123:35;;63119:2;:39;63071:102;:29;:102;:::i;:::-;63043:130;;62992:361;;;63299:26;;63234:107;;:25;;63299:26;;;;;63294:31;63286:40;;63282:2;:44;63234:107;:29;:107;:::i;:::-;63206:135;;62992:361;63409:25;63387:18;:47;;63365:152;;;;-1:-1:-1;;;63365:152:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63601:16;;:40;;63622:18;63601:40;:20;:40;:::i;:::-;63582:59;;63674:19;;;;:43;;63698:18;63674:43;:23;:43;:::i;:::-;63652:19;;;:65;63788:37;63794:10;63806:18;63788:5;:37::i;:::-;63836:50;63855:10;63867:18;63836;:50::i;:::-;63904:53;;;;;;-1:-1:-1;;;;;63904:53:0;;;;;;63946:10;63904:53;;;;;;;;;;;;;;;45550:1;;;;;61981:1984;;:::o;40189:25::-;;;;;;;;:::o;82717:478::-;82885:11;:9;:11::i;:::-;;82907:67;82932:11;82945:13;82968:4;82907:24;:67::i;64153:241::-;64220:4;64237:16;64257:100;64278:25;64292:10;64278:13;:25::i;:::-;64318:28;64335:10;64318:16;:28::i;:::-;64257:6;:100::i;:::-;64256:101;;64153:241;-1:-1:-1;;;64153:241:0:o;80397:437::-;80534:28;80551:10;80534:16;:28::i;:::-;;80573:40;80586:11;80607:4;80573:12;:40::i;40856:24::-;;;-1:-1:-1;;;40856:24:0;;-1:-1:-1;;;;;40856:24:0;;:::o;11855:134::-;-1:-1:-1;;;;;11954:18:0;;;11927:7;11954:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;11855:134::o;60574:790::-;60682:7;60711:20;60720:10;60711:8;:20::i;:::-;60707:650;;;-1:-1:-1;;;;;60770:18:0;;60748:19;60770:18;;;:6;:18;;;;;60956:26;;:17;60896:23;60839:34;;60770:18;;60748:19;60839:145;;60956:26;;;;60955:27;;60947:36;;60943:2;:40;;60839:81;;:34;:81;:56;:81;:::i;:::-;:103;:145;:103;:145;:::i;:::-;61028:29;;60803:181;;-1:-1:-1;61028:29:0;;;;61001:11;61027:30;61019:39;;61015:2;:43;61073:26;;:::i;:::-;61102:123;;;;;;;;;61127:20;:26;61102:123;;61127:35;;61158:3;61127:35;:30;:35;:::i;:::-;61102:123;;61181:29;;;;;;61102:123;;;;;;;61073:152;-1:-1:-1;61247:57:0;61264:25;61073:152;61247:16;:57::i;:::-;61240:64;;;;;;;;60707:650;-1:-1:-1;61344:1:0;61337:8;;40635:21;;;;:::o;48484:219::-;37371:9;:7;:9::i;:::-;37363:54;;;;;-1:-1:-1;;;37363:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;37363:54:0;;;;;;;;;;;;;;;48574:8;;;48559:12;48593;;;48616:34;48635:8;48574;48616:18;:34::i;:::-;48668:27;;;-1:-1:-1;;;;;48668:27:0;;;;;;;;;;;;;;;;;;;;;;;37428:1;48484:219;:::o;57839:343::-;45498:12;:10;:12::i;:::-;45497:13;45489:50;;;;;-1:-1:-1;;;45489:50:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;45489:50:0;;;;;;;;;;;;;;;57916:20;57925:10;57916:8;:20::i;:::-;57908:53;;;;;-1:-1:-1;;;57908:53:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;57908:53:0;;;;;;;;;;;;;;;58003:10;57974:19;57996:18;;;:6;:18;;;;;58049:19;;;;:34;;58073:9;58049:34;:23;:34;:::i;:::-;58027:19;;;:56;58094:28;58100:10;58112:9;58094:5;:28::i;:::-;58140:34;;;58152:10;58140:34;;;;;;;;;;;;;;;;;;;;;45550:1;57839:343;:::o;78580:200::-;78705:11;:9;:11::i;:::-;;78727:45;78750:11;78763:8;78727:22;:45::i;46591:1126::-;37371:9;:7;:9::i;:::-;37363:54;;;;;-1:-1:-1;;;37363:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;37363:54:0;;;;;;;;;;;;;;;46855:3;46830:21;:28;;46808:115;;;;-1:-1:-1;;;46808:115:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46978:4;46956:18;:26;;46934:119;;;;-1:-1:-1;;;46934:119:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47091:3;47072:15;:22;;47064:67;;;;;-1:-1:-1;;;47064:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47194:2;47164:26;:32;;47142:122;;;;-1:-1:-1;;;47142:122:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47277:20;:50;;;47338:17;:44;;;47393:14;:38;;;47442:25;:60;;;47520:189;47306:21;47364:18;47416:15;47476:26;47691:7;:5;:7::i;:::-;47520:189;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;47520:189:0;;;;;;;;;;;;;;46591:1126;;;;:::o;38265:109::-;37371:9;:7;:9::i;:::-;37363:54;;;;;-1:-1:-1;;;37363:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;37363:54:0;;;;;;;;;;;;;;;38338:28;38357:8;38338:18;:28::i;:::-;38265:109;:::o;57439:104::-;-1:-1:-1;;;;;57515:20:0;;;57439:104::o;54838:449::-;54892:20;54901:10;54892:8;:20::i;:::-;54884:53;;;;;-1:-1:-1;;;54884:53:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;54884:53:0;;;;;;;;;;;;;;;54977:10;54948:19;54970:18;;;:6;:18;;;;;55009:16;;;;55001:54;;;;;-1:-1:-1;;;55001:54:0;;;;;;;;;;;;-1:-1:-1;;;55001:54:0;;;;;;;;;;;;;;;55099:16;;;;;55068:28;55126:20;;;55159:52;55178:10;55099:16;55159:18;:52::i;:::-;55227:50;;;;;;55266:10;55227:50;;;;;;;;;;;;;;;;;54838:449;;:::o;69334:285::-;69455:7;45498:12;:10;:12::i;:::-;45497:13;45489:50;;;;;-1:-1:-1;;;45489:50:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;45489:50:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;69502:18:0;;69480:19;69502:18;;;:6;:18;;;;;69550:16;;:25;;69571:3;69550:25;:20;:25;:::i;:::-;69531:44;;;;;69334:285;-1:-1:-1;;;69334:285:0:o;858:98::-;938:10;858:98;:::o;17118:338::-;-1:-1:-1;;;;;17212:19:0;;17204:68;;;;-1:-1:-1;;;17204:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;17291:21:0;;17283:68;;;;-1:-1:-1;;;17283:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;17364:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;17416:32;;;;;;;;;;;;;;;;;17118:338;;;:::o;5445:136::-;5503:7;5530:43;5534:1;5537;5530:43;;;;;;;;;;;;;;;;;:3;:43::i;4989:181::-;5047:7;5079:5;;;5103:6;;;;5095:46;;;;;-1:-1:-1;;;5095:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;69945:1227;70057:4;70113:28;70144:29;70161:10;;;;;;;;;-1:-1:-1;;;;;70161:10:0;70144:8;:29::i;:::-;70228:6;;70113:60;;-1:-1:-1;70184:24:0;;70211:25;;-1:-1:-1;;;;;70228:6:0;70211:8;:25::i;:::-;70467:11;:17;70416:25;:31;70184:52;;-1:-1:-1;70362:19:0;;70384:101;;70467:17;70384:64;;:13;;:64;:31;:64;:::i;:::-;:82;:101;:82;:101;:::i;:::-;70566:20;;70516:34;;70362:123;;-1:-1:-1;70566:20:0;70516:34;;;70566:20;;70516:70;70496:17;70622:87;70682:16;70623:39;:13;70641:20;70623:39;:17;:39;:::i;70622:87::-;70741:13;;70599:110;;-1:-1:-1;70741:13:0;;;;;70720:18;;;;70832:26;;;;;;;;70828:308;;;70889:26;;;70881:35;;;-1:-1:-1;70971:12:0;70943:24;:11;70959:2;:7;;;70943:24;:15;:24;:::i;:::-;:40;;70931:52;;70828:308;;;71030:26;;;71022:35;;;-1:-1:-1;71099:25:0;:12;71116:2;:7;;;71099:25;:16;:25;:::i;:::-;71084:11;:40;;71072:52;;70828:308;71155:9;69945:1227;-1:-1:-1;;;;;;;;;;69945:1227:0:o;15689:308::-;-1:-1:-1;;;;;15765:21:0;;15757:65;;;;;-1:-1:-1;;;15757:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;15850:12;;:24;;15867:6;15850:24;:16;:24;:::i;:::-;15835:12;:39;-1:-1:-1;;;;;15906:18:0;;;;;;:9;:18;;;;;;:30;;15929:6;15906:30;:22;:30;:::i;:::-;-1:-1:-1;;;;;15885:18:0;;;;;;:9;:18;;;;;;;;:51;;;;15952:37;;;;;;;15885:18;;;;15952:37;;;;;;;;;;15689:308;;:::o;14937:471::-;-1:-1:-1;;;;;15035:20:0;;15027:70;;;;-1:-1:-1;;;15027:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;15116:23:0;;15108:71;;;;-1:-1:-1;;;15108:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15212;15234:6;15212:71;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;15212:17:0;;;;;;:9;:17;;;;;;;:71;;:21;:71;:::i;:::-;-1:-1:-1;;;;;15192:17:0;;;;;;;:9;:17;;;;;;:91;;;;15317:20;;;;;;;:32;;15342:6;15317:32;:24;:32;:::i;:::-;-1:-1:-1;;;;;15294:20:0;;;;;;;:9;:20;;;;;;;;;:55;;;;15365:35;;;;;;;15294:20;;15365:35;;;;;;;;;;;;;14937:471;;;:::o;5918:192::-;6004:7;6040:12;6032:6;;;;6024:29;;;;-1:-1:-1;;;6024:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;6024:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;6076:5:0;;;5918:192::o;64728:208::-;-1:-1:-1;;;;;64876:18:0;64829:7;64876:18;;;:6;:18;;;;;64912:16;;64728:208::o;75218:227::-;75313:10;;75307:17;;-1:-1:-1;;;75313:10:0;;-1:-1:-1;;;;;75313:10:0;75307:5;:17::i;:::-;75303:135;;;75341:20;;-1:-1:-1;;;;;75341:14:0;;;:20;;;;;75356:4;;75341:20;;;;75356:4;75341:14;:20;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;75341:20:0;75303:135;;;75394:10;;:32;;;-1:-1:-1;;;75394:32:0;;-1:-1:-1;;;;;75394:32:0;;;;;;;;;;;;;;;-1:-1:-1;;;75394:10:0;;;;;;;:19;;:32;;;;;;;;;;;;;;;-1:-1:-1;75394:10:0;:32;;;5:2:-1;;;;30:1;27;20:12;5:2;75394:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;75394:32:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;75218:227:0;;:::o;66218:2894::-;66414:18;:16;:18::i;:::-;66392:113;;;;-1:-1:-1;;;66392:113:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66526:29;66535:19;66526:8;:29::i;:::-;66518:62;;;;;-1:-1:-1;;;66518:62:0;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;66518:62:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;66615:27:0;;66593:19;66615:27;;;:6;:27;;;;;66661:21;66653:58;;;;;-1:-1:-1;;;66653:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;66820:5;:19;;;66799:17;:40;;66777:136;;;;-1:-1:-1;;;66777:136:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67024:17;66999:21;67009:10;66999:9;:21::i;:::-;:42;;66977:110;;;;;-1:-1:-1;;;66977:110:0;;;;;;;;;;;;-1:-1:-1;;;66977:110:0;;;;;;;;;;;;;;;67186:26;67215:71;67258:17;67215:28;:71::i;:::-;67316:16;;;;67186:100;;-1:-1:-1;67316:40:0;;67186:100;67316:40;:20;:40;:::i;:::-;67297:16;;;:59;67605:12;;;;;;;;;67612:1;67605:12;;67505:26;67605:12;;;;;;67505:26;67534:94;;67573:17;;67534:24;:94::i;:::-;67709:96;;;;;;;;;67780:14;67709:96;;;;;;;;;;;;;;;;;67505:123;;-1:-1:-1;67692:14:0;;67709:96;;67748:17;;67709:24;:96::i;:::-;67827:8;;67692:113;;-1:-1:-1;67827:20:0;;67692:113;67827:20;:12;:20;:::i;:::-;67816:8;:31;67860:28;67891:30;:18;67914:6;67891:30;:22;:30;:::i;:::-;67978:16;;67860:61;;-1:-1:-1;67954:40:0;;;67932:122;;;;;-1:-1:-1;;;67932:122:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68137:16;;:42;;68158:20;68137:42;:20;:42;:::i;:::-;68118:61;;68212:19;;;;:42;;68236:17;68212:42;:23;:42;:::i;:::-;68190:19;;;:64;68389:10;;68383:17;;-1:-1:-1;;;;;68389:10:0;68383:5;:17::i;:::-;68379:388;;;68438:18;68425:9;:31;68417:63;;;;;-1:-1:-1;;;68417:63:0;;;;;;;;;;;;-1:-1:-1;;;68417:63:0;;;;;;;;;;;;;;;68379:388;;;68539:10;;:152;;;-1:-1:-1;;;68539:152:0;;68585:10;68539:152;;;;68626:4;68539:152;;;;;;;;;;;;-1:-1:-1;;;;;68539:10:0;;;;:23;;:152;;;;;;;;;;;;;;;:10;;:152;;;5:2:-1;;;;30:1;27;20:12;5:2;68539:152:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;68539:152:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;68539:152:0;68513:242;;;;;-1:-1:-1;;;68513:242:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;68806:36;68812:10;68824:17;68806:5;:36::i;:::-;68890:50;68909:10;68921:18;68890;:50::i;:::-;68958:144;;;;;;;;;;;;69047:10;68958:144;;;;-1:-1:-1;;;;;68958:144:0;;;;;;;;;;;;;;;;;66218:2894;;;;;;;:::o;72158:1119::-;72283:7;72342:28;72373:29;72390:10;;;;;;;;;-1:-1:-1;;;;;72390:10:0;72373:8;:29::i;:::-;72457:6;;72342:60;;-1:-1:-1;72413:24:0;;72440:25;;-1:-1:-1;;;;;72457:6:0;72440:8;:25::i;:::-;72611:11;:17;72590:16;;72413:52;;-1:-1:-1;72571:16:0;;72590:39;;;:20;:39;:::i;:::-;72679:20;;72657:19;;;;72571:58;;-1:-1:-1;72679:20:0;;72657:42;72640:14;72735:87;72795:16;72736:39;:13;72754:20;72736:39;:17;:39;:::i;72735:87::-;72854:13;;72712:110;;-1:-1:-1;72854:13:0;;;;;72833:18;;;;72945:23;;;;;;;;72941:299;;;72999:23;;;72991:32;;;-1:-1:-1;73051:39:0;73068:21;:8;73081:2;:7;;;73068:21;:12;:21;:::i;:::-;73051:12;;:39;:16;:39;:::i;:::-;73038:52;;72941:299;;;73137:23;;;73129:32;;;-1:-1:-1;73189:39:0;73219:8;73189:25;:12;73206:2;:7;;;73189:25;:16;:25;:::i;:39::-;73176:52;72158:1119;-1:-1:-1;;;;;;;;;;;72158:1119:0:o;6361:471::-;6419:7;6664:6;6660:47;;-1:-1:-1;6694:1:0;6687:8;;6660:47;6731:5;;;6735:1;6731;:5;:1;6755:5;;;;;:10;6747:56;;;;-1:-1:-1;;;6747:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75659:227;75754:10;;75748:17;;-1:-1:-1;;;;;75754:10:0;75748:5;:17::i;:::-;75744:135;;;75782:20;;-1:-1:-1;;;;;75782:14:0;;;:20;;;;;75797:4;;75782:20;;;;75797:4;75782:14;:20;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;75744:135:0;75835:10;;:32;;;-1:-1:-1;;;75835:32:0;;-1:-1:-1;;;;;75835:32:0;;;;;;;;;;;;;;;:10;;;;;:19;;:32;;;;;;;;;;;;;;:10;;:32;;;5:2:-1;;;;30:1;27;20:12;73812:1192:0;73938:7;73992:28;74023:29;74040:10;;;;;;;;;-1:-1:-1;;;;;74040:10:0;74023:8;:29::i;:::-;74107:6;;73992:60;;-1:-1:-1;74063:24:0;;74090:25;;-1:-1:-1;;;;;74107:6:0;74090:8;:25::i;:::-;74063:52;;74178:34;74215:117;74315:16;74215:81;74279:10;:16;;;74215:45;74242:11;:17;;;74215:8;:26;;:45;;;;:::i;:117::-;74444:13;;74409:19;;;;74373:20;;74178:154;;-1:-1:-1;74444:13:0;;;;74373:20;;;:55;:84;;;;;74343:27;;74513:25;;;;-1:-1:-1;74509:448:0;;;74575:21;74633:97;74695:20;74633:39;:26;74664:7;;;;:2;:7;74633:39;;;:30;:39;:::i;:97::-;74612:118;;74509:448;;;;74763:10;74783:26;;;74846:99;74910:20;74847:39;:26;74878:7;;;;:2;:7;74847:39;;;:30;:39;:::i;74846:99::-;74825:120;;74509:448;;74976:18;73812:1192;-1:-1:-1;;;;;;;73812:1192:0:o;7300:132::-;7358:7;7385:39;7389:1;7392;7385:39;;;;;;;;;;;;;;;;;:3;:39::i;16330:348::-;-1:-1:-1;;;;;16406:21:0;;16398:67;;;;-1:-1:-1;;;16398:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16499:68;16522:6;16499:68;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;16499:18:0;;;;;;:9;:18;;;;;;;:68;;:22;:68;:::i;:::-;-1:-1:-1;;;;;16478:18:0;;;;;;:9;:18;;;;;:89;16593:12;;:24;;16610:6;16593:24;:16;:24;:::i;:::-;16578:12;:39;16633:37;;;;;;;;16659:1;;-1:-1:-1;;;;;16633:37:0;;;;;;;;;;;;16330:348;;:::o;65053:214::-;-1:-1:-1;;;;;65204:18:0;65157:7;65204:18;;;:6;:18;;;;;65240:19;;;;65053:214::o;38480:229::-;-1:-1:-1;;;;;38554:22:0;;38546:73;;;;-1:-1:-1;;;38546:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38656:6;;;38635:38;;-1:-1:-1;;;;;38635:38:0;;;;38656:6;;;38635:38;;;38684:6;:17;;-1:-1:-1;;;;;;38684:17:0;-1:-1:-1;;;;;38684:17:0;;;;;;;;;;38480:229::o;76049:221::-;76105:7;-1:-1:-1;;;;;76129:19:0;;76125:138;;-1:-1:-1;76173:6:0;76165:15;;76125:138;76220:15;;:31;;;-1:-1:-1;;;76220:31:0;;-1:-1:-1;;;;;76220:31:0;;;;;;;;;:15;;;;;:24;;:31;;;;;;;;;;;;;;:15;:31;;;5:2:-1;;;;30:1;27;20:12;5:2;76220:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;76220:31:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;76220:31:0;;-1:-1:-1;76213:38:0;;7962:345;8048:7;8150:12;8143:5;8135:28;;;;-1:-1:-1;;;8135:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;8135:28:0;;8174:9;8190:1;8186;:5;;;;;;;7962:345;-1:-1:-1;;;;;7962:345:0:o;76403:7558::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;76403:7558:0;;;-1:-1:-1;76403:7558:0;:::i;:::-;;;:::o;:::-;;;;;;;;;;-1:-1:-1;76403:7558:0;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;
Swarm Source
bzzr://78d274c261df68e9d5018737bd71b890ed72cabfe0e584eb1d201ad752666c95
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.