More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 157 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Create Options C... | 13226377 | 1047 days ago | IN | 0 ETH | 0.16891821 | ||||
Create Options C... | 13226296 | 1047 days ago | IN | 0 ETH | 0.16387643 | ||||
Create Options C... | 12973860 | 1086 days ago | IN | 0 ETH | 0.19502755 | ||||
Create Options C... | 12973735 | 1086 days ago | IN | 0 ETH | 0.17552533 | ||||
Create Options C... | 12756713 | 1120 days ago | IN | 0 ETH | 0.01950299 | ||||
Create Options C... | 12756536 | 1120 days ago | IN | 0 ETH | 0.01950293 | ||||
Create Options C... | 12557667 | 1151 days ago | IN | 0 ETH | 0.08581317 | ||||
Create Options C... | 12557642 | 1151 days ago | IN | 0 ETH | 0.09361408 | ||||
Create Options C... | 12317393 | 1188 days ago | IN | 0 ETH | 0.21063234 | ||||
Create Options C... | 12316836 | 1188 days ago | IN | 0 ETH | 0.19502935 | ||||
Create Options C... | 12111560 | 1220 days ago | IN | 0 ETH | 0.51136786 | ||||
Create Options C... | 12111308 | 1220 days ago | IN | 0 ETH | 0.47301381 | ||||
Create Options C... | 12111256 | 1220 days ago | IN | 0 ETH | 0.43001255 | ||||
Create Options C... | 11898837 | 1253 days ago | IN | 0 ETH | 0.34672707 | ||||
Create Options C... | 11883848 | 1255 days ago | IN | 0 ETH | 0.44551126 | ||||
Create Options C... | 11883787 | 1255 days ago | IN | 0 ETH | 0.49393487 | ||||
Create Options C... | 11883740 | 1255 days ago | IN | 0 ETH | 0.49219004 | ||||
Create Options C... | 11883573 | 1255 days ago | IN | 0 ETH | 0.42614121 | ||||
Create Options C... | 11747277 | 1276 days ago | IN | 0 ETH | 0.25181071 | ||||
Create Options C... | 11747246 | 1276 days ago | IN | 0 ETH | 0.25181071 | ||||
Create Options C... | 11707523 | 1282 days ago | IN | 0 ETH | 0.25180759 | ||||
Create Options C... | 11701242 | 1283 days ago | IN | 0 ETH | 0.18982477 | ||||
Create Options C... | 11655844 | 1290 days ago | IN | 0 ETH | 0.15108642 | ||||
Create Options C... | 11655788 | 1290 days ago | IN | 0 ETH | 0.17506655 | ||||
Create Options C... | 11610559 | 1297 days ago | IN | 0 ETH | 0.32929093 |
Latest 25 internal transactions (View All)
Advanced mode:
Loading...
Loading
This contract contains unverified libraries: StringComparator
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
OptionsFactory
Compiler Version
v0.5.10+commit.5a6ea5b1
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-03-17 */ // 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, uint256 payoutTokensReceived ); 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); uint256 payoutTokensReceived = uniswapSellOToken( oToken, payoutToken, oTokensToSell, receiver ); emit SellOTokens( msg.sender, receiver, oTokenAddress, payoutTokenAddress, oTokensToSell, payoutTokensReceived ); } /** * @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) { 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 (address(collateral) == address(strike)) { return 1; } else 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 ); } } // File: contracts/lib/StringComparator.sol pragma solidity 0.5.10; library StringComparator { function compareStrings (string memory a, string memory b) public pure returns (bool) { return keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))); } } // File: contracts/OptionsFactory.sol pragma solidity 0.5.10; contract OptionsFactory is Ownable { using StringComparator for string; // keys saved in front-end -- look at the docs if needed mapping(string => IERC20) public tokens; address[] public optionsContracts; // The contract which interfaces with the exchange OptionsExchange public optionsExchange; address public oracleAddress; event OptionsContractCreated(address addr); event AssetAdded(string indexed asset, address indexed addr); event AssetChanged(string indexed asset, address indexed addr); event AssetDeleted(string indexed asset); /** * @param _optionsExchangeAddr: The contract which interfaces with the exchange * @param _oracleAddress Address of the oracle */ constructor(OptionsExchange _optionsExchangeAddr, address _oracleAddress) public { optionsExchange = OptionsExchange(_optionsExchangeAddr); oracleAddress = _oracleAddress; } /** * @notice creates a new Option Contract * @param _collateralType The collateral asset. Eg. "ETH" * @param _collateralExp The number of decimals the collateral asset has * @param _underlyingType The underlying asset. Eg. "DAI" * @param _underlyingExp The precision of the underlying asset. Eg. (-18 if Dai) * @param _oTokenExchangeExp Units of underlying that 1 oToken protects * @param _strikePrice The amount of strike asset that will be paid out * @param _strikeExp The precision of the strike Price * @param _strikeAsset The asset in which the insurance is calculated * @param _expiry The time at which the insurance expires * @param _windowSize UNIX time. Exercise window is from `expiry - _windowSize` to `expiry`. */ function createOptionsContract( string memory _collateralType, int32 _collateralExp, string memory _underlyingType, int32 _underlyingExp, int32 _oTokenExchangeExp, uint256 _strikePrice, int32 _strikeExp, string memory _strikeAsset, uint256 _expiry, uint256 _windowSize ) public returns (address) { require(_expiry > block.timestamp, "Cannot create an expired option"); require(_windowSize <= _expiry, "Invalid _windowSize"); require( supportsAsset(_collateralType), "Collateral type not supported" ); require( supportsAsset(_underlyingType), "Underlying type not supported" ); require(supportsAsset(_strikeAsset), "Strike asset type not supported"); OptionsContract optionsContract = new oToken( tokens[_collateralType], _collateralExp, tokens[_underlyingType], _underlyingExp, _oTokenExchangeExp, _strikePrice, _strikeExp, tokens[_strikeAsset], _expiry, optionsExchange, oracleAddress, _windowSize ); optionsContracts.push(address(optionsContract)); emit OptionsContractCreated(address(optionsContract)); // Set the owner for the options contract. optionsContract.transferOwnership(owner()); return address(optionsContract); } /** * @notice The number of Option Contracts that the Factory contract has stored */ function getNumberOfOptionsContracts() public view returns (uint256) { return optionsContracts.length; } /** * @notice The owner of the Factory Contract can add a new asset to be supported * @dev admin don't add ETH. ETH is set to 0x0. * @param _asset The ticker symbol for the asset * @param _addr The address of the asset */ function addAsset(string memory _asset, address _addr) public onlyOwner { require(!supportsAsset(_asset), "Asset already added"); require(_addr != address(0), "Cannot set to address(0)"); tokens[_asset] = IERC20(_addr); emit AssetAdded(_asset, _addr); } /** * @notice The owner of the Factory Contract can change an existing asset's address * @param _asset The ticker symbol for the asset * @param _addr The address of the asset */ function changeAsset(string memory _asset, address _addr) public onlyOwner { require( tokens[_asset] != IERC20(0), "Trying to replace a non-existent asset" ); require(_addr != address(0), "Cannot set to address(0)"); tokens[_asset] = IERC20(_addr); emit AssetChanged(_asset, _addr); } /** * @notice The owner of the Factory Contract can delete an existing asset's address * @param _asset The ticker symbol for the asset */ function deleteAsset(string memory _asset) public onlyOwner { require( tokens[_asset] != IERC20(0), "Trying to delete a non-existent asset" ); tokens[_asset] = IERC20(0); emit AssetDeleted(_asset); } /** * @notice Check if the Factory contract supports a specific asset * @param _asset The ticker symbol for the asset */ function supportsAsset(string memory _asset) public view returns (bool) { if (_asset.compareStrings("ETH")) { return true; } return tokens[_asset] != IERC20(0); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"constant":true,"inputs":[{"name":"","type":"string"}],"name":"tokens","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_asset","type":"string"},{"name":"_addr","type":"address"}],"name":"changeAsset","outputs":[],"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":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getNumberOfOptionsContracts","outputs":[{"name":"","type":"uint256"}],"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":false,"inputs":[{"name":"_collateralType","type":"string"},{"name":"_collateralExp","type":"int32"},{"name":"_underlyingType","type":"string"},{"name":"_underlyingExp","type":"int32"},{"name":"_oTokenExchangeExp","type":"int32"},{"name":"_strikePrice","type":"uint256"},{"name":"_strikeExp","type":"int32"},{"name":"_strikeAsset","type":"string"},{"name":"_expiry","type":"uint256"},{"name":"_windowSize","type":"uint256"}],"name":"createOptionsContract","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"oracleAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_asset","type":"string"},{"name":"_addr","type":"address"}],"name":"addAsset","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_asset","type":"string"}],"name":"supportsAsset","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_asset","type":"string"}],"name":"deleteAsset","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"optionsContracts","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_optionsExchangeAddr","type":"address"},{"name":"_oracleAddress","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"addr","type":"address"}],"name":"OptionsContractCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"asset","type":"string"},{"indexed":true,"name":"addr","type":"address"}],"name":"AssetAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"asset","type":"string"},{"indexed":true,"name":"addr","type":"address"}],"name":"AssetChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"asset","type":"string"}],"name":"AssetDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]
Contract Creation Code
608060405234801561001057600080fd5b506040516160c03803806160c08339818101604052604081101561003357600080fd5b50805160209091015161004d6001600160e01b036100c616565b600080546001600160a01b0319166001600160a01b03928316178082556040519216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600380546001600160a01b039384166001600160a01b031991821617909155600480549290931691161790556100ca565b3390565b615fe7806100d96000396000f3fe60806040523480156200001157600080fd5b5060043610620001005760003560e01c8063a1b72d8a1162000099578063d37aefe8116200006f578063d37aefe81462000585578063e24aa37c146200062f578063eeafd00b14620006d9578063f2fde38b14620006f95762000100565b8063a1b72d8a14620002da578063a89ae4ba14620004c6578063adc02a6414620004d05762000100565b8063715018a611620000db578063715018a6146200028c578063857c26ff14620002965780638da5cb5b14620002b25780638f32d59b14620002bc5762000100565b806304c2320b14620001055780633670ffbe14620001cb5780633bd33f621462000282575b600080fd5b620001af600480360360208110156200011d57600080fd5b810190602081018135600160201b8111156200013857600080fd5b8201836020820111156200014b57600080fd5b803590602001918460018302840111600160201b831117156200016d57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955062000722945050505050565b604080516001600160a01b039092168252519081900360200190f35b6200028060048036036040811015620001e357600080fd5b810190602081018135600160201b811115620001fe57600080fd5b8201836020820111156200021157600080fd5b803590602001918460018302840111600160201b831117156200023357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b03169150620007489050565b005b620001af620009ab565b62000280620009ba565b620002a062000a4f565b60408051918252519081900360200190f35b620001af62000a55565b620002c662000a64565b604080519115158252519081900360200190f35b620001af6004803603610140811015620002f357600080fd5b810190602081018135600160201b8111156200030e57600080fd5b8201836020820111156200032157600080fd5b803590602001918460018302840111600160201b831117156200034357600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295843560030b959094909350604081019250602001359050600160201b811115620003a157600080fd5b820183602082011115620003b457600080fd5b803590602001918460018302840111600160201b83111715620003d657600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092958435600390810b966020870135820b9660408101359650606081013590920b945091925060a081019060800135600160201b8111156200044a57600080fd5b8201836020820111156200045d57600080fd5b803590602001918460018302840111600160201b831117156200047f57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550508235935050506020013562000a8a565b620001af62000fa2565b6200028060048036036040811015620004e857600080fd5b810190602081018135600160201b8111156200050357600080fd5b8201836020820111156200051657600080fd5b803590602001918460018302840111600160201b831117156200053857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b0316915062000fb19050565b620002c6600480360360208110156200059d57600080fd5b810190602081018135600160201b811115620005b857600080fd5b820183602082011115620005cb57600080fd5b803590602001918460018302840111600160201b83111715620005ed57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550620011ae945050505050565b62000280600480360360208110156200064757600080fd5b810190602081018135600160201b8111156200066257600080fd5b8201836020820111156200067557600080fd5b803590602001918460018302840111600160201b831117156200069757600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955062001344945050505050565b620001af60048036036020811015620006f157600080fd5b503562001550565b62000280600480360360208110156200071157600080fd5b50356001600160a01b031662001578565b80516020818301810180516001825292820191909301209152546001600160a01b031681565b6200075262000a64565b62000793576040805162461bcd60e51b8152602060048201819052602482015260008051602062005f6e833981519152604482015290519081900360640190fd5b60006001600160a01b03166001836040518082805190602001908083835b60208310620007d25780518252601f199092019160209182019101620007b1565b51815160209384036101000a60001901801990921691161790529201948552506040519384900301909220546001600160a01b0316929092141591506200084d90505760405162461bcd60e51b815260040180806020018281038252602681526020018062005f226026913960400191505060405180910390fd5b6001600160a01b038116620008a4576040805162461bcd60e51b815260206004820152601860248201527743616e6e6f742073657420746f206164647265737328302960401b604482015290519081900360640190fd5b806001836040518082805190602001908083835b60208310620008d95780518252601f199092019160209182019101620008b8565b51815160209384036101000a6000190180199092169116179052920194855250604051938490038101842080546001600160a01b0319166001600160a01b0396871617905586519486169487949350839250908401908083835b60208310620009545780518252601f19909201916020918201910162000933565b5181516020939093036101000a60001901801990911692169190911790526040519201829003822093507f6ce5d5a8378fe2e66e2858afeaf063b9f2d38f7e46f1313d95b102c635e11cf292506000919050a35050565b6003546001600160a01b031681565b620009c462000a64565b62000a05576040805162461bcd60e51b8152602060048201819052602482015260008051602062005f6e833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b60025490565b6000546001600160a01b031690565b600080546001600160a01b031662000a7b620015d1565b6001600160a01b031614905090565b600042831162000ae1576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742063726561746520616e2065787069726564206f7074696f6e00604482015290519081900360640190fd5b8282111562000b2d576040805162461bcd60e51b8152602060048201526013602482015272496e76616c6964205f77696e646f7753697a6560681b604482015290519081900360640190fd5b62000b388b620011ae565b62000b8a576040805162461bcd60e51b815260206004820152601d60248201527f436f6c6c61746572616c2074797065206e6f7420737570706f72746564000000604482015290519081900360640190fd5b62000b9589620011ae565b62000be7576040805162461bcd60e51b815260206004820152601d60248201527f556e6465726c79696e672074797065206e6f7420737570706f72746564000000604482015290519081900360640190fd5b62000bf284620011ae565b62000c44576040805162461bcd60e51b815260206004820152601f60248201527f537472696b652061737365742074797065206e6f7420737570706f7274656400604482015290519081900360640190fd5b600060018c6040518082805190602001908083835b6020831062000c7a5780518252601f19909201916020918201910162000c59565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a90046001600160a01b03168b60018c6040518082805190602001908083835b6020831062000cf65780518252601f19909201916020918201910162000cd5565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a90046001600160a01b03168b8b8b8b60018c6040518082805190602001908083835b6020831062000d755780518252601f19909201916020918201910162000d54565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a90046001600160a01b03168b600360009054906101000a90046001600160a01b0316600460009054906101000a90046001600160a01b03168d60405162000df89062001677565b6001600160a01b039c8d16815260039b8c0b8c0b6020820152998c166040808c0191909152988b0b8b0b60608b0152968a0b8a0b60808a015260a089019590955292880b90970b60c0870152871660e08601526101008501959095529385166101208401529290931661014082015261016081019190915290519081900361018001906000f08015801562000e91573d6000803e3d6000fd5b50600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0383166001600160a01b0319909116811790915560408051918252519192507f4fa983340a1832a8aff635de38049f79c112e361f89a49cf77f7d49501cabca6919081900360200190a1806001600160a01b031663f2fde38b62000f3062000a55565b6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050600060405180830381600087803b15801562000f7957600080fd5b505af115801562000f8e573d6000803e3d6000fd5b50929e9d5050505050505050505050505050565b6004546001600160a01b031681565b62000fbb62000a64565b62000ffc576040805162461bcd60e51b8152602060048201819052602482015260008051602062005f6e833981519152604482015290519081900360640190fd5b6200100782620011ae565b1562001050576040805162461bcd60e51b8152602060048201526013602482015272105cdcd95d08185b1c9958591e481859191959606a1b604482015290519081900360640190fd5b6001600160a01b038116620010a7576040805162461bcd60e51b815260206004820152601860248201527743616e6e6f742073657420746f206164647265737328302960401b604482015290519081900360640190fd5b806001836040518082805190602001908083835b60208310620010dc5780518252601f199092019160209182019101620010bb565b51815160209384036101000a6000190180199092169116179052920194855250604051938490038101842080546001600160a01b0319166001600160a01b0396871617905586519486169487949350839250908401908083835b60208310620011575780518252601f19909201916020918201910162001136565b5181516020939093036101000a60001901801990911692169190911790526040519201829003822093507f77780d19d6f850ec861d508f6035068d0b68fb9d334887c55393910e9b2951ea92506000919050a35050565b60408051635f69a5dd60e11b8152600481019182528251604482015282516000927395b49aa2bc21562d57a96e84c821e35ed2e5a1c19263bed34bba92869291829160248201916064019060208601908083838c5b838110156200121d57818101518382015260200162001203565b50505050905090810190601f1680156200124b5780820380516001836020036101000a031916815260200191505b50838103825260038152602001806208aa8960eb1b815250602001935050505060206040518083038186803b1580156200128457600080fd5b505af415801562001299573d6000803e3d6000fd5b505050506040513d6020811015620012b057600080fd5b505115620012c1575060016200133f565b60006001600160a01b03166001836040518082805190602001908083835b60208310620013005780518252601f199092019160209182019101620012df565b51815160209384036101000a60001901801990921691161790529201948552506040519384900301909220546001600160a01b03169290921415925050505b919050565b6200134e62000a64565b6200138f576040805162461bcd60e51b8152602060048201819052602482015260008051602062005f6e833981519152604482015290519081900360640190fd5b60006001600160a01b03166001826040518082805190602001908083835b60208310620013ce5780518252601f199092019160209182019101620013ad565b51815160209384036101000a60001901801990921691161790529201948552506040519384900301909220546001600160a01b0316929092141591506200144990505760405162461bcd60e51b815260040180806020018281038252602581526020018062005f8e6025913960400191505060405180910390fd5b60006001826040518082805190602001908083835b602083106200147f5780518252601f1990920191602091820191016200145e565b51815160209384036101000a6000190180199092169116179052920194855250604051938490038101842080546001600160a01b0319166001600160a01b0396909616959095179094555050825183928291908401908083835b60208310620014fa5780518252601f199092019160209182019101620014d9565b5181516020939093036101000a60001901801990911692169190911790526040519201829003822093507fa34d93a1951aca62c967cf6d17f05049fd27b41672a16e301805c4d93995b16392506000919050a250565b600281815481106200155e57fe5b6000918252602090912001546001600160a01b0316905081565b6200158262000a64565b620015c3576040805162461bcd60e51b8152602060048201819052602482015260008051602062005f6e833981519152604482015290519081900360640190fd5b620015ce81620015d5565b50565b3390565b6001600160a01b0381166200161c5760405162461bcd60e51b815260040180806020018281038252602681526020018062005f486026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b61489c80620016868339019056fe600a608081905260021960a081905260078290556008805463ffffffff1990811663fffffffd908117909255600060c081905260e08490526009558354811682179093556101f461010081905261012092909252600b91909155600c805483169091179055610180604052601061014081905260001961016052600d55600e805463ffffffff9083161790556016805490911663ffffffee1763ffffffff60201b191667ffffffee00000000179055348015620000bb57600080fd5b506040516200489c3803806200489c8339818101604052610180811015620000e257600080fd5b508051602082015160408301516060840151608085015160a086015160c087015160e08801516101008901516101208a01516101408b0151610160909b0151999a9899979896979596949593949293919290918b8b8b8b8b8b8b8b8b8b8b8b620001546001600160e01b03620005ec16565b600080546001600160a01b0319166001600160a01b03928316178082556040519216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38342106200020b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f43616e2774206465706c6f7920616e206578706972656420636f6e7472616374604482015290519081900360640190fd5b8381111562000266576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603c815260200180620047a0603c913960400191505060405180910390fd5b6200027a8b6001600160e01b03620005f016565b620002d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180620047dc602d913960400191505060405180910390fd5b620002e5896001600160e01b03620005f016565b6200033c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d8152602001806200486f602d913960400191505060405180910390fd5b62000350866001600160e01b03620005f016565b620003a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018062004840602f913960400191505060405180910390fd5b620003bb886001600160e01b03620005f016565b62000412576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526037815260200180620048096037913960400191505060405180910390fd5b8b601660086101000a8154816001600160a01b0302191690836001600160a01b031602179055508a601660006101000a81548163ffffffff021916908360030b63ffffffff16021790555089601760006101000a8154816001600160a01b0302191690836001600160a01b0316021790555088601660046101000a81548163ffffffff021916908360030b63ffffffff1602179055506040518060400160405280600181526020018960030b81525060116000820151816000015560208201518160010160006101000a81548163ffffffff021916908360030b63ffffffff16021790555090505060405180604001604052808881526020018760030b815250600f6000820151816000015560208201518160010160006101000a81548163ffffffff021916908360030b63ffffffff16021790555090505084601860006101000a8154816001600160a01b0302191690836001600160a01b031602179055508360158190555081601960006101000a8154816001600160a01b0302191690836001600160a01b0316021790555082600460006101000a8154816001600160a01b0302191690836001600160a01b031602179055508060138190555050505050505050505050505050505050505050505050505062000612565b3390565b6000601e8260030b131580156200060c5750601d198260030b12155b92915050565b61417e80620006226000396000f3fe6080604052600436106103975760003560e01c806390e64d13116101dc578063c52987cf11610102578063e184c9be116100a0578063ee1eab4f1161006f578063ee1eab4f14610ed3578063f2fde38b14610f0f578063f70a250814610f42578063faa2041f14610f7557610397565b8063e184c9be14610e35578063ea8c4bcf14610e4a578063eaa376b514610e7d578063ed1f41c314610ea757610397565b8063cfbea789116100dc578063cfbea78914610d86578063d8dfeb4514610db2578063dd62ed3e14610dc7578063dec44c0b14610e0257610397565b8063c52987cf14610cff578063c56749ce14610d14578063cdb4b5c214610d5357610397565b8063b2c2b13f1161017a578063b7b090ee11610149578063b7b090ee14610b4f578063b96661ba14610c85578063ba1be55414610cb1578063bcbaf48714610cc657610397565b8063b2c2b13f14610ae2578063b6e61c0814610b10578063b736554014610b25578063b76fdb6c14610b3a57610397565b80639ed3edf0116101b65780639ed3edf014610a46578063a457c2d714610a5b578063a9059cbb14610a94578063ad8f500814610acd57610397565b806390e64d13146109f657806395d89b4114610a0b5780639ce0725114610a2057610397565b806339509351116102c15780636fd865f91161025f5780638a5e8cc71161022e5780638a5e8cc7146109a25780638c765e94146109b75780638da5cb5b146109cc5780638f32d59b146109e157610397565b80636fd865f91461091b57806370a0823114610945578063715018a61461097857806386f547121461098d57610397565b806358b36dac1161029b57806358b36dac146107f55780635ca7c8a61461089d578063686c1e21146108dc5780636f307dc31461090657610397565b8063395093511461074c5780633bd33f621461078557806352f89fe3146107b657610397565b806318160ddd116103395780633226052d116103085780633226052d146106845780633237c158146106c3578063352ade55146106ed5780633667429f1461072057610397565b806318160ddd146105c65780631a0e21bd146105db57806323b872dd14610616578063313ce5671461065957610397565b8063095ea7b311610375578063095ea7b3146104d65780630d453efb146105235780630d6cd8aa146105565780630eb9af381461056b57610397565b806301b4a3c11461039c578063060ab2ea146103e757806306fdde031461044c575b600080fd5b3480156103a857600080fd5b506103d5600480360360408110156103bf57600080fd5b506001600160a01b038135169060200135610f8a565b60408051918252519081900360200190f35b3480156103f357600080fd5b506103fc61113e565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610438578181015183820152602001610420565b505050509050019250505060405180910390f35b34801561045857600080fd5b506104616111e5565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561049b578181015183820152602001610483565b50505050905090810190601f1680156104c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104e257600080fd5b5061050f600480360360408110156104f957600080fd5b506001600160a01b038135169060200135611273565b604080519115158252519081900360200190f35b34801561052f57600080fd5b5061050f6004803603602081101561054657600080fd5b50356001600160a01b0316611290565b34801561056257600080fd5b5061050f6112b5565b34801561057757600080fd5b5061059e6004803603602081101561058e57600080fd5b50356001600160a01b03166112e3565b6040805194855260208501939093528383019190915215156060830152519081900360800190f35b3480156105d257600080fd5b506103d5611317565b3480156105e757600080fd5b50610614600480360360408110156105fe57600080fd5b50803590602001356001600160a01b031661131d565b005b34801561062257600080fd5b5061050f6004803603606081101561063957600080fd5b506001600160a01b03813581169160208101359091169060400135611486565b34801561066557600080fd5b5061066e611513565b6040805160ff9092168252519081900360200190f35b34801561069057600080fd5b50610614600480360360608110156106a757600080fd5b50803590602081013590604001356001600160a01b031661151c565b3480156106cf57600080fd5b50610614600480360360208110156106e657600080fd5b5035611634565b3480156106f957600080fd5b50610702611824565b60408051928352600391820b90910b60208301528051918290030190f35b6106146004803603604081101561073657600080fd5b50803590602001356001600160a01b0316611830565b34801561075857600080fd5b5061050f6004803603604081101561076f57600080fd5b506001600160a01b038135169060200135611945565b34801561079157600080fd5b5061079a611999565b604080516001600160a01b039092168252519081900360200190f35b3480156107c257600080fd5b50610614600480360360608110156107d957600080fd5b50803590602081013590604001356001600160a01b03166119a8565b6106146004803603604081101561080b57600080fd5b81359190810190604081016020820135600160201b81111561082c57600080fd5b82018360208201111561083e57600080fd5b803590602001918460208302840111600160201b8311171561085f57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506119c1945050505050565b3480156108a957600080fd5b50610614600480360360608110156108c057600080fd5b50803590602081013590604001356001600160a01b0316611ad9565b3480156108e857600080fd5b506103d5600480360360208110156108ff57600080fd5b5035611aee565b34801561091257600080fd5b5061079a611b1c565b34801561092757600080fd5b506103d56004803603602081101561093e57600080fd5b5035611b2b565b34801561095157600080fd5b506103d56004803603602081101561096857600080fd5b50356001600160a01b0316611b6f565b34801561098457600080fd5b50610614611b8a565b34801561099957600080fd5b5061050f611c1b565b3480156109ae57600080fd5b5061079a611d88565b3480156109c357600080fd5b50610702611d97565b3480156109d857600080fd5b5061079a611da3565b3480156109ed57600080fd5b5061050f611db2565b348015610a0257600080fd5b5061050f611dd6565b348015610a1757600080fd5b50610461611ddf565b6103d560048036036020811015610a3657600080fd5b50356001600160a01b0316611e3a565b348015610a5257600080fd5b50610702611f74565b348015610a6757600080fd5b5061050f60048036036040811015610a7e57600080fd5b506001600160a01b038135169060200135611f80565b348015610aa057600080fd5b5061050f60048036036040811015610ab757600080fd5b506001600160a01b038135169060200135611fee565b348015610ad957600080fd5b5061079a612002565b348015610aee57600080fd5b50610af7612011565b60408051600392830b90920b8252519081900360200190f35b348015610b1c57600080fd5b50610af7612021565b348015610b3157600080fd5b5061070261202a565b348015610b4657600080fd5b50610614612036565b348015610b5b57600080fd5b5061061460048036036040811015610b7257600080fd5b810190602081018135600160201b811115610b8c57600080fd5b820183602082011115610b9e57600080fd5b803590602001918460018302840111600160201b83111715610bbf57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610c1157600080fd5b820183602082011115610c2357600080fd5b803590602001918460018302840111600160201b83111715610c4457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612142945050505050565b61061460048036036040811015610c9b57600080fd5b50803590602001356001600160a01b03166121d3565b348015610cbd57600080fd5b506107026121e7565b348015610cd257600080fd5b5061061460048036036040811015610ce957600080fd5b506001600160a01b0381351690602001356121f3565b348015610d0b57600080fd5b506107026124f7565b348015610d2057600080fd5b5061061460048036036060811015610d3757600080fd5b50803590602081013590604001356001600160a01b0316612503565b348015610d5f57600080fd5b5061050f60048036036020811015610d7657600080fd5b50356001600160a01b0316612517565b61061460048036036040811015610d9c57600080fd5b50803590602001356001600160a01b031661253c565b348015610dbe57600080fd5b5061079a612550565b348015610dd357600080fd5b506103d560048036036040811015610dea57600080fd5b506001600160a01b0381358116916020013516612566565b348015610e0e57600080fd5b506103d560048036036020811015610e2557600080fd5b50356001600160a01b0316612591565b348015610e4157600080fd5b506103d561265c565b348015610e5657600080fd5b5061061460048036036020811015610e6d57600080fd5b50356001600160a01b0316612662565b348015610e8957600080fd5b5061061460048036036020811015610ea057600080fd5b5035612704565b61061460048036036040811015610ebd57600080fd5b50803590602001356001600160a01b0316612806565b348015610edf57600080fd5b5061061460048036036080811015610ef657600080fd5b5080359060208101359060408101359060600135612819565b348015610f1b57600080fd5b5061061460048036036020811015610f3257600080fd5b50356001600160a01b03166129f1565b348015610f4e57600080fd5b5061050f60048036036020811015610f6557600080fd5b50356001600160a01b0316612a44565b348015610f8157600080fd5b50610614612a51565b6000610f94611dd6565b15610fd4576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b601654604080516323b872dd60e01b8152336004820152306024820152604481018590529051600160401b9092046001600160a01b0316916323b872dd916064808201926020929091908290030181600087803b15801561103457600080fd5b505af1158015611048573d6000803e3d6000fd5b505050506040513d602081101561105e57600080fd5b505161109b5760405162461bcd60e51b8152600401808060200182810382526027815260200180613e8b6027913960400191505060405180910390fd5b6110a483611290565b6110e3576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b604080516001600160a01b038516815260208101849052338183015290517f2199418ea9428ed3ff7d460860e1edaf5831452fa4ea0f8d1a60d63c603487829181900360600190a16111358383612b49565b90505b92915050565b6060806000805b6006548110156111dc576111796006828154811061115f57fe5b6000918252602090912001546001600160a01b0316611290565b156111d4576006818154811061118b57fe5b9060005260206000200160009054906101000a90046001600160a01b03168383815181106111b557fe5b6001600160a01b03909216602092830291909101909101526001909101905b600101611145565b50909150505b90565b601a805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561126b5780601f106112405761010080835404028352916020019161126b565b820191906000526020600020905b81548152906001019060200180831161124e57829003601f168201915b505050505081565b6000611287611280612bc8565b8484612bcc565b50600192915050565b6001600160a01b03811660009081526005602052604090206003015460ff165b919050565b60006112ce601354601554612cb890919063ffffffff16565b42101580156112de575060155442105b905090565b6001600160a01b03166000908152600560205260409020805460018201546002830154600390930154919390929160ff1690565b60035490565b611325611dd6565b15611365576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b61136e33611290565b6113ad576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b33600090815260056020526040812060018101549091906113d4908563ffffffff612cfa16565b90506113e4826000015482612d54565b611426576040805162461bcd60e51b815260206004820152600e60248201526d1d5b9cd85999481d1bc81b5a5b9d60921b604482015290519081900360640190fd5b600182018190556114378385612e59565b604080516001600160a01b038516815260208101869052338183015290517f5e5aaabf04e3760968ffb551bdf9708f4dbf95d53ad98539e91a56b125e88f089181900360600190a150505b5050565b6000611493848484612f4b565b6115098461149f612bc8565b61150485604051806060016040528060288152602001613ff6602891396001600160a01b038a166000908152600260205260408120906114dd612bc8565b6001600160a01b03168152602081019190915260400160002054919063ffffffff6130a916565b612bcc565b5060019392505050565b601c5460ff1681565b6115263383610f8a565b50611531833061131d565b600480546040805163095ea7b360e01b81526001600160a01b0390921692820192909252602481018590529051309163095ea7b39160448083019260209291908290030181600087803b15801561158757600080fd5b505af115801561159b573d6000803e3d6000fd5b505050506040513d60208110156115b157600080fd5b50506004805460408051637dafae5960e01b81526001600160a01b03858116948201949094523060248201526000604482018190526064820188905291519390921692637dafae5992608480820193929182900301818387803b15801561161757600080fd5b505af115801561162b573d6000803e3d6000fd5b50505050505050565b61163c611dd6565b1561167c576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b600081116116d1576040805162461bcd60e51b815260206004820152601a60248201527f43616e6e6f742072656d6f7665203020636f6c6c61746572616c000000000000604482015290519081900360640190fd5b6116da33611290565b611719576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b3360008181526005602052604090209061173290613140565b8211156117705760405162461bcd60e51b8152600401808060200182810382526027815260200180613fa26027913960400191505060405180910390fd5b8054600090611785908463ffffffff612cb816565b9050611795818360010154612d54565b6117d8576040805162461bcd60e51b815260206004820152600f60248201526e5661756c7420697320756e7361666560881b604482015290519081900360640190fd5b8082556117e5338461315b565b6040805184815233602082015281517f5a945309b3c58e9bb259128c2a530a6579dc75ac1d7d61b3db4c0b8305a16821929181900390910190a1505050565b600b54600c5460030b82565b611838611c1b565b5061184382306121d3565b600480546040805163095ea7b360e01b81526001600160a01b0390921692820192909252602481018490529051309163095ea7b39160448083019260209291908290030181600087803b15801561189957600080fd5b505af11580156118ad573d6000803e3d6000fd5b505050506040513d60208110156118c357600080fd5b50506004805460408051637dafae5960e01b81526001600160a01b03858116948201949094523060248201526000604482018190526064820187905291519390921692637dafae5992608480820193929182900301818387803b15801561192957600080fd5b505af115801561193d573d6000803e3d6000fd5b505050505050565b6000611287611952612bc8565b846115048560026000611963612bc8565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff612cfa16565b6004546001600160a01b031681565b6119b0611c1b565b506119bc838383611ad9565b505050565b60005b8151811015611a9b5760008282815181106119db57fe5b602002602001015190506119ee81611290565b611a295760405162461bcd60e51b815260040180806020018281038252602f81526020018061405f602f913960400191505060405180910390fd5b6001600160a01b038116600090815260056020526040902084611a4e57505050611482565b84816001015410611a6b57611a638583613246565b505050611482565b6001810154611a8190869063ffffffff612cb816565b9450611a91816001015483613246565b50506001016119c4565b5081156114825760405162461bcd60e51b815260040180806020018281038252602d815260200180613f1d602d913960400191505060405180910390fd5b611ae33383610f8a565b506119bc838261131d565b60408051808201909152600d548152600e54600390810b810b900b60208201526000906111389083906136a9565b6017546001600160a01b031681565b601654601254600091600160201b9004600390810b91810b91909103900b611b688367ffffffffffffffff808416600a0a1663ffffffff6137a416565b9392505050565b6001600160a01b031660009081526001602052604090205490565b611b92611db2565b611bd1576040805162461bcd60e51b8152602060048201819052602482015260008051602061401e833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000611c25611dd6565b15611c65576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b611c6e33611290565b15611cb8576040805162461bcd60e51b815260206004820152601560248201527415985d5b1d08185b1c9958591e4818dc99585d1959605a1b604482015290519081900360640190fd5b60408051608081018252600080825260208083018281528385018381526001606086018181523380875260058652888720975188559351878301559151600287015590516003909501805460ff1916951515959095179094556006805494850181559092527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f90920180546001600160a01b03191682179055825190815291517f66a872561db77eb92ef3079a44a5af00c68c3a09e0976814a95bd91721f57c2f9281900390910190a150600190565b6019546001600160a01b031681565b60075460085460030b82565b6000546001600160a01b031690565b600080546001600160a01b0316611dc7612bc8565b6001600160a01b031614905090565b60155442101590565b601b805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561126b5780601f106112405761010080835404028352916020019161126b565b6000611e44611dd6565b15611e84576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b601654611ea090600160401b90046001600160a01b0316612a44565b611edb5760405162461bcd60e51b8152600401808060200182810382526028815260200180613df66028913960400191505060405180910390fd5b611ee482611290565b611f23576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b604080516001600160a01b0384168152346020820152338183015290517ff24ce6016de57e90501829715846e26ac283a0aabfc160647e0ae8b05e0f433d9181900360600190a16111388234612b49565b600954600a5460030b82565b6000611287611f8d612bc8565b84611504856040518060600160405280602581526020016141256025913960026000611fb7612bc8565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff6130a916565b6000611287611ffb612bc8565b8484612f4b565b6018546001600160a01b031681565b601654600160201b900460030b81565b60165460030b81565b60115460125460030b82565b61203e611dd6565b6120795760405162461bcd60e51b8152600401808060200182810382526025815260200180613e666025913960400191505060405180910390fd5b61208233611290565b6120c1576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b33600081815260056020526040812080546002820180548484556001840185905593905590929091906120f4908361315b565b6120fe33826137fd565b6040805183815260208101839052338183015290517fe481532a3f7d078365ca0145442ed0a0a3e0443f3c0bae0c29cff131112678389181900360600190a1505050565b61214a611db2565b612189576040805162461bcd60e51b8152602060048201819052602482015260008051602061401e833981519152604482015290519081900360640190fd5b815161219c90601a906020850190613cae565b5080516121b090601b906020840190613cae565b50601254601c805460ff191660039290920b60000360ff16919091179055611482565b6121dc33611e3a565b50611482828261131d565b600d54600e5460030b82565b6121fb611dd6565b1561223b576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b61224482611290565b612283576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b6001600160a01b03821660009081526005602052604090206122a483612517565b6122e5576040805162461bcd60e51b815260206004820152600d60248201526c5661756c74206973207361666560981b604482015290519081900360640190fd5b336001600160a01b0384161415612343576040805162461bcd60e51b815260206004820181905260248201527f4f776e65722063616e2774206c6971756964617465207468656d73656c766573604482015290519081900360640190fd5b600061236883604051806040016040528060018152602001600060030b8152506138a3565b604080518082019091526007548152600854600390810b810b900b60208201529091506000906123999085906138a3565b905060006123ad838363ffffffff612cfa16565b600b5485549192506000916123c79163ffffffff6137a416565b600c549091506000600391820b90910b131561240257600c546123fb908290600390810b900b600a0a63ffffffff6137a416565b9050612426565b600c54612423908290600390810b600003900b600a0a63ffffffff61398516565b90505b808211156124655760405162461bcd60e51b8152600401808060200182810382526037815260200180613f4a6037913960400191505060405180910390fd5b8454612477908363ffffffff612cb816565b8555600185015461248e908763ffffffff612cb816565b600186015561249d33876139c7565b6124a7338361315b565b604080518381526001600160a01b0389166020820152338183015290517fcab8e1abb9f8235c6db895cf185336dc9461aecf477b98c1be83687ee549e66a9181900360600190a150505050505050565b600f5460105460030b82565b61250b611c1b565b50611531838330611ad9565b60008061253461252684613140565b61252f85613ac3565b612d54565b159392505050565b61254533611e3a565b50611843823061131d565b601654600160401b90046001600160a01b031681565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b600061259c82612517565b15612654576001600160a01b0382166000908152600560205260408120600c54600b5482549293926125f192600390810b8503900b600a0a916125e5919063ffffffff6137a416565b9063ffffffff61398516565b600854909150600390810b600003900b600a0a61260c613d2c565b60408051808201909152600754819061262b908563ffffffff612cfa16565b8152600854600390810b900b602090910152905061264983826136a9565b9450505050506112b0565b5060006112b0565b60155481565b61266a611db2565b6126a9576040805162461bcd60e51b8152602060048201819052602482015260008051602061401e833981519152604482015290519081900360640190fd5b6014805460009091556126bc828261315b565b604080516001600160a01b03841681526020810183905281517f88b171bb78d3ac5e1caa8e729dddce4e1322e84c80c093ebbe52507b62c77d98929181900390910190a15050565b61270c611dd6565b1561274c576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b61275533611290565b612794576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b33600090815260056020526040902060018101546127b8908363ffffffff612cb816565b60018201556127c733836139c7565b604080513381526020810184905281517fdf8cebdea6ef1fd20576b80bc951377c0e61e2a8169153a1f836673ccce80e62929181900390910190a15050565b61280e611c1b565b5061148282826121d3565b612821611db2565b612860576040805162461bcd60e51b8152602060048201819052602482015260008051602061401e833981519152604482015290519081900360640190fd5b60c88411156128a05760405162461bcd60e51b8152600401808060200182810382526025815260200180613ef86025913960400191505060405180910390fd5b6103e88311156128e15760405162461bcd60e51b815260040180806020018281038252602b815260200180613da9602b913960400191505060405180910390fd5b6064821115612937576040805162461bcd60e51b815260206004820181905260248201527f43616e27742068617665207472616e73616374696f6e20666565203e20313025604482015290519081900360640190fd5b600a8110156129775760405162461bcd60e51b8152600401808060200182810382526028815260200180613d816028913960400191505060405180910390fd5b6007849055600b8390556009829055600d8190557f3450d20c21ea671871fed271900cc8ff03badafa9b6fe2ff7f86991950e86b6b848484846129b8611da3565b6040805195865260208601949094528484019290925260608401526001600160a01b03166080830152519081900360a00190a150505050565b6129f9611db2565b612a38576040805162461bcd60e51b8152602060048201819052602482015260008051602061401e833981519152604482015290519081900360640190fd5b612a4181613ae1565b50565b6001600160a01b03161590565b612a5a33611290565b612a99576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b3360009081526005602052604090206002810154612af6576040805162461bcd60e51b81526020600482015260156024820152744e6f20756e6465726c79696e672062616c616e636560581b604482015290519081900360640190fd5b6002810180546000909155612b0b33826137fd565b6040805182815233602082015281517fea0bff65fa9380b944e9a761f9c6a665ad2d31e74706a52773ddb45c8a57c83d929181900390910190a15050565b6000612b53611dd6565b15612b93576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b6001600160a01b03831660009081526005602052604090208054612bbd908463ffffffff612cfa16565b908190559392505050565b3390565b6001600160a01b038316612c115760405162461bcd60e51b81526004018080602001828103825260248152602001806140b36024913960400191505060405180910390fd5b6001600160a01b038216612c565760405162461bcd60e51b8152600401808060200182810382526022815260200180613e446022913960400191505060405180910390fd5b6001600160a01b03808416600081815260026020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600061113583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506130a9565b600082820183811015611135576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600080612d75601660089054906101000a90046001600160a01b0316613b81565b601854909150600090612d90906001600160a01b0316613b81565b600f54600d54919250600091612dbe9190612db290889063ffffffff6137a416565b9063ffffffff6137a416565b601054600e54919250600391820b910b016000612de5846125e58a8863ffffffff6137a416565b601654909150600390810b90600090819085810b9084900b1215612e295782850360030b915083612e2087600a85900a63ffffffff6137a416565b11159050612e4b565b84830360030b9150612e4584600a84900a63ffffffff6137a416565b86111590505b9a9950505050505050505050565b6001600160a01b038216612eb4576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b600354612ec7908263ffffffff612cfa16565b6003556001600160a01b038216600090815260016020526040902054612ef3908263ffffffff612cfa16565b6001600160a01b03831660008181526001602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038316612f905760405162461bcd60e51b815260040180806020018281038252602581526020018061408e6025913960400191505060405180910390fd5b6001600160a01b038216612fd55760405162461bcd60e51b8152600401808060200182810382526023815260200180613d5e6023913960400191505060405180910390fd5b61301881604051806060016040528060268152602001613ed2602691396001600160a01b038616600090815260016020526040902054919063ffffffff6130a916565b6001600160a01b03808516600090815260016020526040808220939093559084168152205461304d908263ffffffff612cfa16565b6001600160a01b0380841660008181526001602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156131385760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156130fd5781810151838201526020016130e5565b50505050905090810190601f16801561312a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b031660009081526005602052604090205490565b60165461317790600160401b90046001600160a01b0316612a44565b156131b8576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156131b2573d6000803e3d6000fd5b50611482565b6016546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151600160401b9093049091169163a9059cbb916044808201926020929091908290030181600087803b15801561321657600080fd5b505af115801561322a573d6000803e3d6000fd5b505050506040513d602081101561324057600080fd5b50505050565b61324e6112b5565b6132895760405162461bcd60e51b815260040180806020018281038252602d815260200180613fc9602d913960400191505060405180910390fd5b61329281611290565b6132d1576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526005602052604090208261333b576040805162461bcd60e51b815260206004820152601860248201527f43616e27742065786572636973652030206f546f6b656e730000000000000000604482015290519081900360640190fd5b806001015483111561337e5760405162461bcd60e51b815260040180806020018281038252602e8152602001806140d7602e913960400191505060405180910390fd5b8261338833611b6f565b10156133d0576040805162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f756768206f546f6b656e7360701b604482015290519081900360640190fd5b60006133db84611b2b565b60028301549091506133f3908263ffffffff612cfa16565b600283015560408051808201909152600181526000602082018190529061341b9086906138a3565b604080518082019091526009548152600a54600390810b810b900b602082015290915060009061344c9087906138a3565b601454909150613462908263ffffffff612cfa16565b6014556000613477838363ffffffff612cfa16565b85549091508111156134d0576040805162461bcd60e51b815260206004820181905260248201527f5661756c7420756e64657277617465722c2063616e2774206578657263697365604482015290519081900360640190fd5b84546134e2908263ffffffff612cb816565b855560018501546134f9908863ffffffff612cb816565b6001860155601754613513906001600160a01b0316612a44565b1561356757833414613562576040805162461bcd60e51b8152602060048201526013602482015272496e636f7272656374206d73672e76616c756560681b604482015290519081900360640190fd5b61363e565b601754604080516323b872dd60e01b81523360048201523060248201526044810187905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b1580156135c157600080fd5b505af11580156135d5573d6000803e3d6000fd5b505050506040513d60208110156135eb57600080fd5b505161363e576040805162461bcd60e51b815260206004820152601c60248201527f436f756c64206e6f74207472616e7366657220696e20746f6b656e7300000000604482015290519081900360640190fd5b61364833886139c7565b613652338461315b565b604080518581526020810185905233818301526001600160a01b038816606082015290517ffa7bab37479e50a9b24a9412b879d400de9bcaa1e3a2b343e90bb370d85bbaa79181900360800190a150505050505050565b6000806136ca601660089054906101000a90046001600160a01b0316613b81565b6018549091506000906136e5906001600160a01b0316613b81565b600f5485519192506000916136ff9163ffffffff6137a416565b601054602087015191925060030b016000613724846125e58a8863ffffffff6137a416565b601654909150600390810b90600090819085810b9084900b12156137755782850360030b915061376e61376187600a85900a63ffffffff6137a416565b859063ffffffff61398516565b9050612e4b565b84830360030b9150613795866125e586600a86900a63ffffffff6137a416565b9b9a5050505050505050505050565b6000826137b357506000611138565b828202828482816137c057fe5b04146111355760405162461bcd60e51b8152600401808060200182810382526021815260200180613f816021913960400191505060405180910390fd5b601754613812906001600160a01b0316612a44565b1561384d576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156131b2573d6000803e3d6000fd5b6017546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561321657600080fd5b6000806138c4601660089054906101000a90046001600160a01b0316613b81565b6018549091506000906138df906001600160a01b0316613b81565b9050600061390782612db28760000151612db2600f600001548b6137a490919063ffffffff16565b6016546020870151601054929350600391820b92820b01919091039060009082900b811215613955578161394d866125e58663ffffffff808616600a0a8116906137a416565b91505061397a565b6000829003613976866125e58663ffffffff808616600a0a81169061398516565b9150505b979650505050505050565b600061113583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613c49565b6001600160a01b038216613a0c5760405162461bcd60e51b815260040180806020018281038252602181526020018061403e6021913960400191505060405180910390fd5b613a4f81604051806060016040528060228152602001613dd4602291396001600160a01b038516600090815260016020526040902054919063ffffffff6130a916565b6001600160a01b038316600090815260016020526040902055600354613a7b908263ffffffff612cb816565b6003556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b031660009081526005602052604090206001015490565b6001600160a01b038116613b265760405162461bcd60e51b8152600401808060200182810382526026815260200180613e1e6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6018546016546000916001600160a01b03908116600160401b909204161415613bac575060016112b0565b6001600160a01b038216613bc95750670de0b6b3a76400006112b0565b601954604080516341976e0960e01b81526001600160a01b038581166004830152915191909216916341976e09916024808301926020929190829003018186803b158015613c1657600080fd5b505afa158015613c2a573d6000803e3d6000fd5b505050506040513d6020811015613c4057600080fd5b505190506112b0565b60008183613c985760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156130fd5781810151838201526020016130e5565b506000838581613ca457fe5b0495945050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613cef57805160ff1916838001178555613d1c565b82800160010185558215613d1c579182015b82811115613d1c578251825591602001919060010190613d01565b50613d28929150613d43565b5090565b604080518082019091526000808252602082015290565b6111e291905b80821115613d285760008155600101613d4956fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737343616e27742068617665206d696e436f6c6c61746572616c697a6174696f6e526174696f203c203143616e2774206c6971756964617465206d6f7265207468616e2031303025206f6620746865207661756c7445524332303a206275726e20616d6f756e7420657863656564732062616c616e6365455448206973206e6f74207468652073706563696669656420636f6c6c61746572616c20747970654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737343616e277420636f6c6c65637420636f6c6c61746572616c20756e74696c20657870697279436f756c64206e6f74207472616e7366657220696e20636f6c6c61746572616c20746f6b656e735661756c7420646f6573206e6f7420657869737400000000000000000000000045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636543616e27742068617665203e323025206c69717569646174696f6e20696e63656e74697665537065636966696564207661756c7473206861766520696e73756666696369656e7420636f6c6c61746572616c43616e206f6e6c79206c6971756964617465206c69717569646174696f6e20666163746f7220617420616e7920676976656e2074696d65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e27742072656d6f7665206d6f726520636f6c6c61746572616c207468616e206f776e656443616e2774206578657263697365206f757473696465206f66207468652065786572636973652077696e646f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657245524332303a206275726e2066726f6d20746865207a65726f206164647265737343616e6e6f742065786572636973652066726f6d2061207661756c74207468617420646f65736e277420657869737445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737343616e2774206578657263697365206d6f7265206f546f6b656e73207468616e20746865206f776e6572206861734f7074696f6e7320636f6e74726163742065787069726564000000000000000045524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a7230582024408987c6dcfcda4c0e73ff0354366a3d057faa494c86e0ef89208047b75fda64736f6c634300050a003245786572636973652077696e646f772063616e2774206265206c6f6e676572207468616e2074686520636f6e74726163742773206c6966657370616e636f6c6c61746572616c206578706f6e656e74206e6f742077697468696e2065787065637465642072616e67656f546f6b656e2065786368616e67652072617465206578706f6e656e74206e6f742077697468696e2065787065637465642072616e6765737472696b65207072696365206578706f6e656e74206e6f742077697468696e2065787065637465642072616e6765756e6465726c79696e67206578706f6e656e74206e6f742077697468696e2065787065637465642072616e6765547279696e6720746f207265706c6163652061206e6f6e2d6578697374656e742061737365744f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572547279696e6720746f2064656c6574652061206e6f6e2d6578697374656e74206173736574a265627a7a72305820d9a46a063d97e32e28fc099c39433b9cf72eec6d7a6f22746ab882e885bc591c64736f6c634300050a003200000000000000000000000039246c4f3f6592c974ebc44f80ba6dc69b817c710000000000000000000000007054e08461e3ecb7718b63540addb3c3a1746415
Deployed Bytecode
0x60806040523480156200001157600080fd5b5060043610620001005760003560e01c8063a1b72d8a1162000099578063d37aefe8116200006f578063d37aefe81462000585578063e24aa37c146200062f578063eeafd00b14620006d9578063f2fde38b14620006f95762000100565b8063a1b72d8a14620002da578063a89ae4ba14620004c6578063adc02a6414620004d05762000100565b8063715018a611620000db578063715018a6146200028c578063857c26ff14620002965780638da5cb5b14620002b25780638f32d59b14620002bc5762000100565b806304c2320b14620001055780633670ffbe14620001cb5780633bd33f621462000282575b600080fd5b620001af600480360360208110156200011d57600080fd5b810190602081018135600160201b8111156200013857600080fd5b8201836020820111156200014b57600080fd5b803590602001918460018302840111600160201b831117156200016d57600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955062000722945050505050565b604080516001600160a01b039092168252519081900360200190f35b6200028060048036036040811015620001e357600080fd5b810190602081018135600160201b811115620001fe57600080fd5b8201836020820111156200021157600080fd5b803590602001918460018302840111600160201b831117156200023357600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b03169150620007489050565b005b620001af620009ab565b62000280620009ba565b620002a062000a4f565b60408051918252519081900360200190f35b620001af62000a55565b620002c662000a64565b604080519115158252519081900360200190f35b620001af6004803603610140811015620002f357600080fd5b810190602081018135600160201b8111156200030e57600080fd5b8201836020820111156200032157600080fd5b803590602001918460018302840111600160201b831117156200034357600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295843560030b959094909350604081019250602001359050600160201b811115620003a157600080fd5b820183602082011115620003b457600080fd5b803590602001918460018302840111600160201b83111715620003d657600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092958435600390810b966020870135820b9660408101359650606081013590920b945091925060a081019060800135600160201b8111156200044a57600080fd5b8201836020820111156200045d57600080fd5b803590602001918460018302840111600160201b831117156200047f57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550508235935050506020013562000a8a565b620001af62000fa2565b6200028060048036036040811015620004e857600080fd5b810190602081018135600160201b8111156200050357600080fd5b8201836020820111156200051657600080fd5b803590602001918460018302840111600160201b831117156200053857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550505090356001600160a01b0316915062000fb19050565b620002c6600480360360208110156200059d57600080fd5b810190602081018135600160201b811115620005b857600080fd5b820183602082011115620005cb57600080fd5b803590602001918460018302840111600160201b83111715620005ed57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550620011ae945050505050565b62000280600480360360208110156200064757600080fd5b810190602081018135600160201b8111156200066257600080fd5b8201836020820111156200067557600080fd5b803590602001918460018302840111600160201b831117156200069757600080fd5b91908080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092955062001344945050505050565b620001af60048036036020811015620006f157600080fd5b503562001550565b62000280600480360360208110156200071157600080fd5b50356001600160a01b031662001578565b80516020818301810180516001825292820191909301209152546001600160a01b031681565b6200075262000a64565b62000793576040805162461bcd60e51b8152602060048201819052602482015260008051602062005f6e833981519152604482015290519081900360640190fd5b60006001600160a01b03166001836040518082805190602001908083835b60208310620007d25780518252601f199092019160209182019101620007b1565b51815160209384036101000a60001901801990921691161790529201948552506040519384900301909220546001600160a01b0316929092141591506200084d90505760405162461bcd60e51b815260040180806020018281038252602681526020018062005f226026913960400191505060405180910390fd5b6001600160a01b038116620008a4576040805162461bcd60e51b815260206004820152601860248201527743616e6e6f742073657420746f206164647265737328302960401b604482015290519081900360640190fd5b806001836040518082805190602001908083835b60208310620008d95780518252601f199092019160209182019101620008b8565b51815160209384036101000a6000190180199092169116179052920194855250604051938490038101842080546001600160a01b0319166001600160a01b0396871617905586519486169487949350839250908401908083835b60208310620009545780518252601f19909201916020918201910162000933565b5181516020939093036101000a60001901801990911692169190911790526040519201829003822093507f6ce5d5a8378fe2e66e2858afeaf063b9f2d38f7e46f1313d95b102c635e11cf292506000919050a35050565b6003546001600160a01b031681565b620009c462000a64565b62000a05576040805162461bcd60e51b8152602060048201819052602482015260008051602062005f6e833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b60025490565b6000546001600160a01b031690565b600080546001600160a01b031662000a7b620015d1565b6001600160a01b031614905090565b600042831162000ae1576040805162461bcd60e51b815260206004820152601f60248201527f43616e6e6f742063726561746520616e2065787069726564206f7074696f6e00604482015290519081900360640190fd5b8282111562000b2d576040805162461bcd60e51b8152602060048201526013602482015272496e76616c6964205f77696e646f7753697a6560681b604482015290519081900360640190fd5b62000b388b620011ae565b62000b8a576040805162461bcd60e51b815260206004820152601d60248201527f436f6c6c61746572616c2074797065206e6f7420737570706f72746564000000604482015290519081900360640190fd5b62000b9589620011ae565b62000be7576040805162461bcd60e51b815260206004820152601d60248201527f556e6465726c79696e672074797065206e6f7420737570706f72746564000000604482015290519081900360640190fd5b62000bf284620011ae565b62000c44576040805162461bcd60e51b815260206004820152601f60248201527f537472696b652061737365742074797065206e6f7420737570706f7274656400604482015290519081900360640190fd5b600060018c6040518082805190602001908083835b6020831062000c7a5780518252601f19909201916020918201910162000c59565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a90046001600160a01b03168b60018c6040518082805190602001908083835b6020831062000cf65780518252601f19909201916020918201910162000cd5565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a90046001600160a01b03168b8b8b8b60018c6040518082805190602001908083835b6020831062000d755780518252601f19909201916020918201910162000d54565b6001836020036101000a038019825116818451168082178552505050505050905001915050908152602001604051809103902060009054906101000a90046001600160a01b03168b600360009054906101000a90046001600160a01b0316600460009054906101000a90046001600160a01b03168d60405162000df89062001677565b6001600160a01b039c8d16815260039b8c0b8c0b6020820152998c166040808c0191909152988b0b8b0b60608b0152968a0b8a0b60808a015260a089019590955292880b90970b60c0870152871660e08601526101008501959095529385166101208401529290931661014082015261016081019190915290519081900361018001906000f08015801562000e91573d6000803e3d6000fd5b50600280546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0180546001600160a01b0383166001600160a01b0319909116811790915560408051918252519192507f4fa983340a1832a8aff635de38049f79c112e361f89a49cf77f7d49501cabca6919081900360200190a1806001600160a01b031663f2fde38b62000f3062000a55565b6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050600060405180830381600087803b15801562000f7957600080fd5b505af115801562000f8e573d6000803e3d6000fd5b50929e9d5050505050505050505050505050565b6004546001600160a01b031681565b62000fbb62000a64565b62000ffc576040805162461bcd60e51b8152602060048201819052602482015260008051602062005f6e833981519152604482015290519081900360640190fd5b6200100782620011ae565b1562001050576040805162461bcd60e51b8152602060048201526013602482015272105cdcd95d08185b1c9958591e481859191959606a1b604482015290519081900360640190fd5b6001600160a01b038116620010a7576040805162461bcd60e51b815260206004820152601860248201527743616e6e6f742073657420746f206164647265737328302960401b604482015290519081900360640190fd5b806001836040518082805190602001908083835b60208310620010dc5780518252601f199092019160209182019101620010bb565b51815160209384036101000a6000190180199092169116179052920194855250604051938490038101842080546001600160a01b0319166001600160a01b0396871617905586519486169487949350839250908401908083835b60208310620011575780518252601f19909201916020918201910162001136565b5181516020939093036101000a60001901801990911692169190911790526040519201829003822093507f77780d19d6f850ec861d508f6035068d0b68fb9d334887c55393910e9b2951ea92506000919050a35050565b60408051635f69a5dd60e11b8152600481019182528251604482015282516000927395b49aa2bc21562d57a96e84c821e35ed2e5a1c19263bed34bba92869291829160248201916064019060208601908083838c5b838110156200121d57818101518382015260200162001203565b50505050905090810190601f1680156200124b5780820380516001836020036101000a031916815260200191505b50838103825260038152602001806208aa8960eb1b815250602001935050505060206040518083038186803b1580156200128457600080fd5b505af415801562001299573d6000803e3d6000fd5b505050506040513d6020811015620012b057600080fd5b505115620012c1575060016200133f565b60006001600160a01b03166001836040518082805190602001908083835b60208310620013005780518252601f199092019160209182019101620012df565b51815160209384036101000a60001901801990921691161790529201948552506040519384900301909220546001600160a01b03169290921415925050505b919050565b6200134e62000a64565b6200138f576040805162461bcd60e51b8152602060048201819052602482015260008051602062005f6e833981519152604482015290519081900360640190fd5b60006001600160a01b03166001826040518082805190602001908083835b60208310620013ce5780518252601f199092019160209182019101620013ad565b51815160209384036101000a60001901801990921691161790529201948552506040519384900301909220546001600160a01b0316929092141591506200144990505760405162461bcd60e51b815260040180806020018281038252602581526020018062005f8e6025913960400191505060405180910390fd5b60006001826040518082805190602001908083835b602083106200147f5780518252601f1990920191602091820191016200145e565b51815160209384036101000a6000190180199092169116179052920194855250604051938490038101842080546001600160a01b0319166001600160a01b0396909616959095179094555050825183928291908401908083835b60208310620014fa5780518252601f199092019160209182019101620014d9565b5181516020939093036101000a60001901801990911692169190911790526040519201829003822093507fa34d93a1951aca62c967cf6d17f05049fd27b41672a16e301805c4d93995b16392506000919050a250565b600281815481106200155e57fe5b6000918252602090912001546001600160a01b0316905081565b6200158262000a64565b620015c3576040805162461bcd60e51b8152602060048201819052602482015260008051602062005f6e833981519152604482015290519081900360640190fd5b620015ce81620015d5565b50565b3390565b6001600160a01b0381166200161c5760405162461bcd60e51b815260040180806020018281038252602681526020018062005f486026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b61489c80620016868339019056fe600a608081905260021960a081905260078290556008805463ffffffff1990811663fffffffd908117909255600060c081905260e08490526009558354811682179093556101f461010081905261012092909252600b91909155600c805483169091179055610180604052601061014081905260001961016052600d55600e805463ffffffff9083161790556016805490911663ffffffee1763ffffffff60201b191667ffffffee00000000179055348015620000bb57600080fd5b506040516200489c3803806200489c8339818101604052610180811015620000e257600080fd5b508051602082015160408301516060840151608085015160a086015160c087015160e08801516101008901516101208a01516101408b0151610160909b0151999a9899979896979596949593949293919290918b8b8b8b8b8b8b8b8b8b8b8b620001546001600160e01b03620005ec16565b600080546001600160a01b0319166001600160a01b03928316178082556040519216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a38342106200020b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f43616e2774206465706c6f7920616e206578706972656420636f6e7472616374604482015290519081900360640190fd5b8381111562000266576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603c815260200180620047a0603c913960400191505060405180910390fd5b6200027a8b6001600160e01b03620005f016565b620002d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d815260200180620047dc602d913960400191505060405180910390fd5b620002e5896001600160e01b03620005f016565b6200033c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602d8152602001806200486f602d913960400191505060405180910390fd5b62000350866001600160e01b03620005f016565b620003a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f81526020018062004840602f913960400191505060405180910390fd5b620003bb886001600160e01b03620005f016565b62000412576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526037815260200180620048096037913960400191505060405180910390fd5b8b601660086101000a8154816001600160a01b0302191690836001600160a01b031602179055508a601660006101000a81548163ffffffff021916908360030b63ffffffff16021790555089601760006101000a8154816001600160a01b0302191690836001600160a01b0316021790555088601660046101000a81548163ffffffff021916908360030b63ffffffff1602179055506040518060400160405280600181526020018960030b81525060116000820151816000015560208201518160010160006101000a81548163ffffffff021916908360030b63ffffffff16021790555090505060405180604001604052808881526020018760030b815250600f6000820151816000015560208201518160010160006101000a81548163ffffffff021916908360030b63ffffffff16021790555090505084601860006101000a8154816001600160a01b0302191690836001600160a01b031602179055508360158190555081601960006101000a8154816001600160a01b0302191690836001600160a01b0316021790555082600460006101000a8154816001600160a01b0302191690836001600160a01b031602179055508060138190555050505050505050505050505050505050505050505050505062000612565b3390565b6000601e8260030b131580156200060c5750601d198260030b12155b92915050565b61417e80620006226000396000f3fe6080604052600436106103975760003560e01c806390e64d13116101dc578063c52987cf11610102578063e184c9be116100a0578063ee1eab4f1161006f578063ee1eab4f14610ed3578063f2fde38b14610f0f578063f70a250814610f42578063faa2041f14610f7557610397565b8063e184c9be14610e35578063ea8c4bcf14610e4a578063eaa376b514610e7d578063ed1f41c314610ea757610397565b8063cfbea789116100dc578063cfbea78914610d86578063d8dfeb4514610db2578063dd62ed3e14610dc7578063dec44c0b14610e0257610397565b8063c52987cf14610cff578063c56749ce14610d14578063cdb4b5c214610d5357610397565b8063b2c2b13f1161017a578063b7b090ee11610149578063b7b090ee14610b4f578063b96661ba14610c85578063ba1be55414610cb1578063bcbaf48714610cc657610397565b8063b2c2b13f14610ae2578063b6e61c0814610b10578063b736554014610b25578063b76fdb6c14610b3a57610397565b80639ed3edf0116101b65780639ed3edf014610a46578063a457c2d714610a5b578063a9059cbb14610a94578063ad8f500814610acd57610397565b806390e64d13146109f657806395d89b4114610a0b5780639ce0725114610a2057610397565b806339509351116102c15780636fd865f91161025f5780638a5e8cc71161022e5780638a5e8cc7146109a25780638c765e94146109b75780638da5cb5b146109cc5780638f32d59b146109e157610397565b80636fd865f91461091b57806370a0823114610945578063715018a61461097857806386f547121461098d57610397565b806358b36dac1161029b57806358b36dac146107f55780635ca7c8a61461089d578063686c1e21146108dc5780636f307dc31461090657610397565b8063395093511461074c5780633bd33f621461078557806352f89fe3146107b657610397565b806318160ddd116103395780633226052d116103085780633226052d146106845780633237c158146106c3578063352ade55146106ed5780633667429f1461072057610397565b806318160ddd146105c65780631a0e21bd146105db57806323b872dd14610616578063313ce5671461065957610397565b8063095ea7b311610375578063095ea7b3146104d65780630d453efb146105235780630d6cd8aa146105565780630eb9af381461056b57610397565b806301b4a3c11461039c578063060ab2ea146103e757806306fdde031461044c575b600080fd5b3480156103a857600080fd5b506103d5600480360360408110156103bf57600080fd5b506001600160a01b038135169060200135610f8a565b60408051918252519081900360200190f35b3480156103f357600080fd5b506103fc61113e565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610438578181015183820152602001610420565b505050509050019250505060405180910390f35b34801561045857600080fd5b506104616111e5565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561049b578181015183820152602001610483565b50505050905090810190601f1680156104c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156104e257600080fd5b5061050f600480360360408110156104f957600080fd5b506001600160a01b038135169060200135611273565b604080519115158252519081900360200190f35b34801561052f57600080fd5b5061050f6004803603602081101561054657600080fd5b50356001600160a01b0316611290565b34801561056257600080fd5b5061050f6112b5565b34801561057757600080fd5b5061059e6004803603602081101561058e57600080fd5b50356001600160a01b03166112e3565b6040805194855260208501939093528383019190915215156060830152519081900360800190f35b3480156105d257600080fd5b506103d5611317565b3480156105e757600080fd5b50610614600480360360408110156105fe57600080fd5b50803590602001356001600160a01b031661131d565b005b34801561062257600080fd5b5061050f6004803603606081101561063957600080fd5b506001600160a01b03813581169160208101359091169060400135611486565b34801561066557600080fd5b5061066e611513565b6040805160ff9092168252519081900360200190f35b34801561069057600080fd5b50610614600480360360608110156106a757600080fd5b50803590602081013590604001356001600160a01b031661151c565b3480156106cf57600080fd5b50610614600480360360208110156106e657600080fd5b5035611634565b3480156106f957600080fd5b50610702611824565b60408051928352600391820b90910b60208301528051918290030190f35b6106146004803603604081101561073657600080fd5b50803590602001356001600160a01b0316611830565b34801561075857600080fd5b5061050f6004803603604081101561076f57600080fd5b506001600160a01b038135169060200135611945565b34801561079157600080fd5b5061079a611999565b604080516001600160a01b039092168252519081900360200190f35b3480156107c257600080fd5b50610614600480360360608110156107d957600080fd5b50803590602081013590604001356001600160a01b03166119a8565b6106146004803603604081101561080b57600080fd5b81359190810190604081016020820135600160201b81111561082c57600080fd5b82018360208201111561083e57600080fd5b803590602001918460208302840111600160201b8311171561085f57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506119c1945050505050565b3480156108a957600080fd5b50610614600480360360608110156108c057600080fd5b50803590602081013590604001356001600160a01b0316611ad9565b3480156108e857600080fd5b506103d5600480360360208110156108ff57600080fd5b5035611aee565b34801561091257600080fd5b5061079a611b1c565b34801561092757600080fd5b506103d56004803603602081101561093e57600080fd5b5035611b2b565b34801561095157600080fd5b506103d56004803603602081101561096857600080fd5b50356001600160a01b0316611b6f565b34801561098457600080fd5b50610614611b8a565b34801561099957600080fd5b5061050f611c1b565b3480156109ae57600080fd5b5061079a611d88565b3480156109c357600080fd5b50610702611d97565b3480156109d857600080fd5b5061079a611da3565b3480156109ed57600080fd5b5061050f611db2565b348015610a0257600080fd5b5061050f611dd6565b348015610a1757600080fd5b50610461611ddf565b6103d560048036036020811015610a3657600080fd5b50356001600160a01b0316611e3a565b348015610a5257600080fd5b50610702611f74565b348015610a6757600080fd5b5061050f60048036036040811015610a7e57600080fd5b506001600160a01b038135169060200135611f80565b348015610aa057600080fd5b5061050f60048036036040811015610ab757600080fd5b506001600160a01b038135169060200135611fee565b348015610ad957600080fd5b5061079a612002565b348015610aee57600080fd5b50610af7612011565b60408051600392830b90920b8252519081900360200190f35b348015610b1c57600080fd5b50610af7612021565b348015610b3157600080fd5b5061070261202a565b348015610b4657600080fd5b50610614612036565b348015610b5b57600080fd5b5061061460048036036040811015610b7257600080fd5b810190602081018135600160201b811115610b8c57600080fd5b820183602082011115610b9e57600080fd5b803590602001918460018302840111600160201b83111715610bbf57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295949360208101935035915050600160201b811115610c1157600080fd5b820183602082011115610c2357600080fd5b803590602001918460018302840111600160201b83111715610c4457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550612142945050505050565b61061460048036036040811015610c9b57600080fd5b50803590602001356001600160a01b03166121d3565b348015610cbd57600080fd5b506107026121e7565b348015610cd257600080fd5b5061061460048036036040811015610ce957600080fd5b506001600160a01b0381351690602001356121f3565b348015610d0b57600080fd5b506107026124f7565b348015610d2057600080fd5b5061061460048036036060811015610d3757600080fd5b50803590602081013590604001356001600160a01b0316612503565b348015610d5f57600080fd5b5061050f60048036036020811015610d7657600080fd5b50356001600160a01b0316612517565b61061460048036036040811015610d9c57600080fd5b50803590602001356001600160a01b031661253c565b348015610dbe57600080fd5b5061079a612550565b348015610dd357600080fd5b506103d560048036036040811015610dea57600080fd5b506001600160a01b0381358116916020013516612566565b348015610e0e57600080fd5b506103d560048036036020811015610e2557600080fd5b50356001600160a01b0316612591565b348015610e4157600080fd5b506103d561265c565b348015610e5657600080fd5b5061061460048036036020811015610e6d57600080fd5b50356001600160a01b0316612662565b348015610e8957600080fd5b5061061460048036036020811015610ea057600080fd5b5035612704565b61061460048036036040811015610ebd57600080fd5b50803590602001356001600160a01b0316612806565b348015610edf57600080fd5b5061061460048036036080811015610ef657600080fd5b5080359060208101359060408101359060600135612819565b348015610f1b57600080fd5b5061061460048036036020811015610f3257600080fd5b50356001600160a01b03166129f1565b348015610f4e57600080fd5b5061050f60048036036020811015610f6557600080fd5b50356001600160a01b0316612a44565b348015610f8157600080fd5b50610614612a51565b6000610f94611dd6565b15610fd4576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b601654604080516323b872dd60e01b8152336004820152306024820152604481018590529051600160401b9092046001600160a01b0316916323b872dd916064808201926020929091908290030181600087803b15801561103457600080fd5b505af1158015611048573d6000803e3d6000fd5b505050506040513d602081101561105e57600080fd5b505161109b5760405162461bcd60e51b8152600401808060200182810382526027815260200180613e8b6027913960400191505060405180910390fd5b6110a483611290565b6110e3576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b604080516001600160a01b038516815260208101849052338183015290517f2199418ea9428ed3ff7d460860e1edaf5831452fa4ea0f8d1a60d63c603487829181900360600190a16111358383612b49565b90505b92915050565b6060806000805b6006548110156111dc576111796006828154811061115f57fe5b6000918252602090912001546001600160a01b0316611290565b156111d4576006818154811061118b57fe5b9060005260206000200160009054906101000a90046001600160a01b03168383815181106111b557fe5b6001600160a01b03909216602092830291909101909101526001909101905b600101611145565b50909150505b90565b601a805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561126b5780601f106112405761010080835404028352916020019161126b565b820191906000526020600020905b81548152906001019060200180831161124e57829003601f168201915b505050505081565b6000611287611280612bc8565b8484612bcc565b50600192915050565b6001600160a01b03811660009081526005602052604090206003015460ff165b919050565b60006112ce601354601554612cb890919063ffffffff16565b42101580156112de575060155442105b905090565b6001600160a01b03166000908152600560205260409020805460018201546002830154600390930154919390929160ff1690565b60035490565b611325611dd6565b15611365576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b61136e33611290565b6113ad576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b33600090815260056020526040812060018101549091906113d4908563ffffffff612cfa16565b90506113e4826000015482612d54565b611426576040805162461bcd60e51b815260206004820152600e60248201526d1d5b9cd85999481d1bc81b5a5b9d60921b604482015290519081900360640190fd5b600182018190556114378385612e59565b604080516001600160a01b038516815260208101869052338183015290517f5e5aaabf04e3760968ffb551bdf9708f4dbf95d53ad98539e91a56b125e88f089181900360600190a150505b5050565b6000611493848484612f4b565b6115098461149f612bc8565b61150485604051806060016040528060288152602001613ff6602891396001600160a01b038a166000908152600260205260408120906114dd612bc8565b6001600160a01b03168152602081019190915260400160002054919063ffffffff6130a916565b612bcc565b5060019392505050565b601c5460ff1681565b6115263383610f8a565b50611531833061131d565b600480546040805163095ea7b360e01b81526001600160a01b0390921692820192909252602481018590529051309163095ea7b39160448083019260209291908290030181600087803b15801561158757600080fd5b505af115801561159b573d6000803e3d6000fd5b505050506040513d60208110156115b157600080fd5b50506004805460408051637dafae5960e01b81526001600160a01b03858116948201949094523060248201526000604482018190526064820188905291519390921692637dafae5992608480820193929182900301818387803b15801561161757600080fd5b505af115801561162b573d6000803e3d6000fd5b50505050505050565b61163c611dd6565b1561167c576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b600081116116d1576040805162461bcd60e51b815260206004820152601a60248201527f43616e6e6f742072656d6f7665203020636f6c6c61746572616c000000000000604482015290519081900360640190fd5b6116da33611290565b611719576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b3360008181526005602052604090209061173290613140565b8211156117705760405162461bcd60e51b8152600401808060200182810382526027815260200180613fa26027913960400191505060405180910390fd5b8054600090611785908463ffffffff612cb816565b9050611795818360010154612d54565b6117d8576040805162461bcd60e51b815260206004820152600f60248201526e5661756c7420697320756e7361666560881b604482015290519081900360640190fd5b8082556117e5338461315b565b6040805184815233602082015281517f5a945309b3c58e9bb259128c2a530a6579dc75ac1d7d61b3db4c0b8305a16821929181900390910190a1505050565b600b54600c5460030b82565b611838611c1b565b5061184382306121d3565b600480546040805163095ea7b360e01b81526001600160a01b0390921692820192909252602481018490529051309163095ea7b39160448083019260209291908290030181600087803b15801561189957600080fd5b505af11580156118ad573d6000803e3d6000fd5b505050506040513d60208110156118c357600080fd5b50506004805460408051637dafae5960e01b81526001600160a01b03858116948201949094523060248201526000604482018190526064820187905291519390921692637dafae5992608480820193929182900301818387803b15801561192957600080fd5b505af115801561193d573d6000803e3d6000fd5b505050505050565b6000611287611952612bc8565b846115048560026000611963612bc8565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff612cfa16565b6004546001600160a01b031681565b6119b0611c1b565b506119bc838383611ad9565b505050565b60005b8151811015611a9b5760008282815181106119db57fe5b602002602001015190506119ee81611290565b611a295760405162461bcd60e51b815260040180806020018281038252602f81526020018061405f602f913960400191505060405180910390fd5b6001600160a01b038116600090815260056020526040902084611a4e57505050611482565b84816001015410611a6b57611a638583613246565b505050611482565b6001810154611a8190869063ffffffff612cb816565b9450611a91816001015483613246565b50506001016119c4565b5081156114825760405162461bcd60e51b815260040180806020018281038252602d815260200180613f1d602d913960400191505060405180910390fd5b611ae33383610f8a565b506119bc838261131d565b60408051808201909152600d548152600e54600390810b810b900b60208201526000906111389083906136a9565b6017546001600160a01b031681565b601654601254600091600160201b9004600390810b91810b91909103900b611b688367ffffffffffffffff808416600a0a1663ffffffff6137a416565b9392505050565b6001600160a01b031660009081526001602052604090205490565b611b92611db2565b611bd1576040805162461bcd60e51b8152602060048201819052602482015260008051602061401e833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000611c25611dd6565b15611c65576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b611c6e33611290565b15611cb8576040805162461bcd60e51b815260206004820152601560248201527415985d5b1d08185b1c9958591e4818dc99585d1959605a1b604482015290519081900360640190fd5b60408051608081018252600080825260208083018281528385018381526001606086018181523380875260058652888720975188559351878301559151600287015590516003909501805460ff1916951515959095179094556006805494850181559092527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f90920180546001600160a01b03191682179055825190815291517f66a872561db77eb92ef3079a44a5af00c68c3a09e0976814a95bd91721f57c2f9281900390910190a150600190565b6019546001600160a01b031681565b60075460085460030b82565b6000546001600160a01b031690565b600080546001600160a01b0316611dc7612bc8565b6001600160a01b031614905090565b60155442101590565b601b805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561126b5780601f106112405761010080835404028352916020019161126b565b6000611e44611dd6565b15611e84576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b601654611ea090600160401b90046001600160a01b0316612a44565b611edb5760405162461bcd60e51b8152600401808060200182810382526028815260200180613df66028913960400191505060405180910390fd5b611ee482611290565b611f23576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b604080516001600160a01b0384168152346020820152338183015290517ff24ce6016de57e90501829715846e26ac283a0aabfc160647e0ae8b05e0f433d9181900360600190a16111388234612b49565b600954600a5460030b82565b6000611287611f8d612bc8565b84611504856040518060600160405280602581526020016141256025913960026000611fb7612bc8565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff6130a916565b6000611287611ffb612bc8565b8484612f4b565b6018546001600160a01b031681565b601654600160201b900460030b81565b60165460030b81565b60115460125460030b82565b61203e611dd6565b6120795760405162461bcd60e51b8152600401808060200182810382526025815260200180613e666025913960400191505060405180910390fd5b61208233611290565b6120c1576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b33600081815260056020526040812080546002820180548484556001840185905593905590929091906120f4908361315b565b6120fe33826137fd565b6040805183815260208101839052338183015290517fe481532a3f7d078365ca0145442ed0a0a3e0443f3c0bae0c29cff131112678389181900360600190a1505050565b61214a611db2565b612189576040805162461bcd60e51b8152602060048201819052602482015260008051602061401e833981519152604482015290519081900360640190fd5b815161219c90601a906020850190613cae565b5080516121b090601b906020840190613cae565b50601254601c805460ff191660039290920b60000360ff16919091179055611482565b6121dc33611e3a565b50611482828261131d565b600d54600e5460030b82565b6121fb611dd6565b1561223b576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b61224482611290565b612283576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b6001600160a01b03821660009081526005602052604090206122a483612517565b6122e5576040805162461bcd60e51b815260206004820152600d60248201526c5661756c74206973207361666560981b604482015290519081900360640190fd5b336001600160a01b0384161415612343576040805162461bcd60e51b815260206004820181905260248201527f4f776e65722063616e2774206c6971756964617465207468656d73656c766573604482015290519081900360640190fd5b600061236883604051806040016040528060018152602001600060030b8152506138a3565b604080518082019091526007548152600854600390810b810b900b60208201529091506000906123999085906138a3565b905060006123ad838363ffffffff612cfa16565b600b5485549192506000916123c79163ffffffff6137a416565b600c549091506000600391820b90910b131561240257600c546123fb908290600390810b900b600a0a63ffffffff6137a416565b9050612426565b600c54612423908290600390810b600003900b600a0a63ffffffff61398516565b90505b808211156124655760405162461bcd60e51b8152600401808060200182810382526037815260200180613f4a6037913960400191505060405180910390fd5b8454612477908363ffffffff612cb816565b8555600185015461248e908763ffffffff612cb816565b600186015561249d33876139c7565b6124a7338361315b565b604080518381526001600160a01b0389166020820152338183015290517fcab8e1abb9f8235c6db895cf185336dc9461aecf477b98c1be83687ee549e66a9181900360600190a150505050505050565b600f5460105460030b82565b61250b611c1b565b50611531838330611ad9565b60008061253461252684613140565b61252f85613ac3565b612d54565b159392505050565b61254533611e3a565b50611843823061131d565b601654600160401b90046001600160a01b031681565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b600061259c82612517565b15612654576001600160a01b0382166000908152600560205260408120600c54600b5482549293926125f192600390810b8503900b600a0a916125e5919063ffffffff6137a416565b9063ffffffff61398516565b600854909150600390810b600003900b600a0a61260c613d2c565b60408051808201909152600754819061262b908563ffffffff612cfa16565b8152600854600390810b900b602090910152905061264983826136a9565b9450505050506112b0565b5060006112b0565b60155481565b61266a611db2565b6126a9576040805162461bcd60e51b8152602060048201819052602482015260008051602061401e833981519152604482015290519081900360640190fd5b6014805460009091556126bc828261315b565b604080516001600160a01b03841681526020810183905281517f88b171bb78d3ac5e1caa8e729dddce4e1322e84c80c093ebbe52507b62c77d98929181900390910190a15050565b61270c611dd6565b1561274c576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b61275533611290565b612794576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b33600090815260056020526040902060018101546127b8908363ffffffff612cb816565b60018201556127c733836139c7565b604080513381526020810184905281517fdf8cebdea6ef1fd20576b80bc951377c0e61e2a8169153a1f836673ccce80e62929181900390910190a15050565b61280e611c1b565b5061148282826121d3565b612821611db2565b612860576040805162461bcd60e51b8152602060048201819052602482015260008051602061401e833981519152604482015290519081900360640190fd5b60c88411156128a05760405162461bcd60e51b8152600401808060200182810382526025815260200180613ef86025913960400191505060405180910390fd5b6103e88311156128e15760405162461bcd60e51b815260040180806020018281038252602b815260200180613da9602b913960400191505060405180910390fd5b6064821115612937576040805162461bcd60e51b815260206004820181905260248201527f43616e27742068617665207472616e73616374696f6e20666565203e20313025604482015290519081900360640190fd5b600a8110156129775760405162461bcd60e51b8152600401808060200182810382526028815260200180613d816028913960400191505060405180910390fd5b6007849055600b8390556009829055600d8190557f3450d20c21ea671871fed271900cc8ff03badafa9b6fe2ff7f86991950e86b6b848484846129b8611da3565b6040805195865260208601949094528484019290925260608401526001600160a01b03166080830152519081900360a00190a150505050565b6129f9611db2565b612a38576040805162461bcd60e51b8152602060048201819052602482015260008051602061401e833981519152604482015290519081900360640190fd5b612a4181613ae1565b50565b6001600160a01b03161590565b612a5a33611290565b612a99576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b3360009081526005602052604090206002810154612af6576040805162461bcd60e51b81526020600482015260156024820152744e6f20756e6465726c79696e672062616c616e636560581b604482015290519081900360640190fd5b6002810180546000909155612b0b33826137fd565b6040805182815233602082015281517fea0bff65fa9380b944e9a761f9c6a665ad2d31e74706a52773ddb45c8a57c83d929181900390910190a15050565b6000612b53611dd6565b15612b93576040805162461bcd60e51b81526020600482015260186024820152600080516020614105833981519152604482015290519081900360640190fd5b6001600160a01b03831660009081526005602052604090208054612bbd908463ffffffff612cfa16565b908190559392505050565b3390565b6001600160a01b038316612c115760405162461bcd60e51b81526004018080602001828103825260248152602001806140b36024913960400191505060405180910390fd5b6001600160a01b038216612c565760405162461bcd60e51b8152600401808060200182810382526022815260200180613e446022913960400191505060405180910390fd5b6001600160a01b03808416600081815260026020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600061113583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506130a9565b600082820183811015611135576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600080612d75601660089054906101000a90046001600160a01b0316613b81565b601854909150600090612d90906001600160a01b0316613b81565b600f54600d54919250600091612dbe9190612db290889063ffffffff6137a416565b9063ffffffff6137a416565b601054600e54919250600391820b910b016000612de5846125e58a8863ffffffff6137a416565b601654909150600390810b90600090819085810b9084900b1215612e295782850360030b915083612e2087600a85900a63ffffffff6137a416565b11159050612e4b565b84830360030b9150612e4584600a84900a63ffffffff6137a416565b86111590505b9a9950505050505050505050565b6001600160a01b038216612eb4576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b600354612ec7908263ffffffff612cfa16565b6003556001600160a01b038216600090815260016020526040902054612ef3908263ffffffff612cfa16565b6001600160a01b03831660008181526001602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6001600160a01b038316612f905760405162461bcd60e51b815260040180806020018281038252602581526020018061408e6025913960400191505060405180910390fd5b6001600160a01b038216612fd55760405162461bcd60e51b8152600401808060200182810382526023815260200180613d5e6023913960400191505060405180910390fd5b61301881604051806060016040528060268152602001613ed2602691396001600160a01b038616600090815260016020526040902054919063ffffffff6130a916565b6001600160a01b03808516600090815260016020526040808220939093559084168152205461304d908263ffffffff612cfa16565b6001600160a01b0380841660008181526001602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156131385760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156130fd5781810151838201526020016130e5565b50505050905090810190601f16801561312a5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6001600160a01b031660009081526005602052604090205490565b60165461317790600160401b90046001600160a01b0316612a44565b156131b8576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156131b2573d6000803e3d6000fd5b50611482565b6016546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151600160401b9093049091169163a9059cbb916044808201926020929091908290030181600087803b15801561321657600080fd5b505af115801561322a573d6000803e3d6000fd5b505050506040513d602081101561324057600080fd5b50505050565b61324e6112b5565b6132895760405162461bcd60e51b815260040180806020018281038252602d815260200180613fc9602d913960400191505060405180910390fd5b61329281611290565b6132d1576040805162461bcd60e51b81526020600482015260146024820152600080516020613eb2833981519152604482015290519081900360640190fd5b6001600160a01b03811660009081526005602052604090208261333b576040805162461bcd60e51b815260206004820152601860248201527f43616e27742065786572636973652030206f546f6b656e730000000000000000604482015290519081900360640190fd5b806001015483111561337e5760405162461bcd60e51b815260040180806020018281038252602e8152602001806140d7602e913960400191505060405180910390fd5b8261338833611b6f565b10156133d0576040805162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f756768206f546f6b656e7360701b604482015290519081900360640190fd5b60006133db84611b2b565b60028301549091506133f3908263ffffffff612cfa16565b600283015560408051808201909152600181526000602082018190529061341b9086906138a3565b604080518082019091526009548152600a54600390810b810b900b602082015290915060009061344c9087906138a3565b601454909150613462908263ffffffff612cfa16565b6014556000613477838363ffffffff612cfa16565b85549091508111156134d0576040805162461bcd60e51b815260206004820181905260248201527f5661756c7420756e64657277617465722c2063616e2774206578657263697365604482015290519081900360640190fd5b84546134e2908263ffffffff612cb816565b855560018501546134f9908863ffffffff612cb816565b6001860155601754613513906001600160a01b0316612a44565b1561356757833414613562576040805162461bcd60e51b8152602060048201526013602482015272496e636f7272656374206d73672e76616c756560681b604482015290519081900360640190fd5b61363e565b601754604080516323b872dd60e01b81523360048201523060248201526044810187905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b1580156135c157600080fd5b505af11580156135d5573d6000803e3d6000fd5b505050506040513d60208110156135eb57600080fd5b505161363e576040805162461bcd60e51b815260206004820152601c60248201527f436f756c64206e6f74207472616e7366657220696e20746f6b656e7300000000604482015290519081900360640190fd5b61364833886139c7565b613652338461315b565b604080518581526020810185905233818301526001600160a01b038816606082015290517ffa7bab37479e50a9b24a9412b879d400de9bcaa1e3a2b343e90bb370d85bbaa79181900360800190a150505050505050565b6000806136ca601660089054906101000a90046001600160a01b0316613b81565b6018549091506000906136e5906001600160a01b0316613b81565b600f5485519192506000916136ff9163ffffffff6137a416565b601054602087015191925060030b016000613724846125e58a8863ffffffff6137a416565b601654909150600390810b90600090819085810b9084900b12156137755782850360030b915061376e61376187600a85900a63ffffffff6137a416565b859063ffffffff61398516565b9050612e4b565b84830360030b9150613795866125e586600a86900a63ffffffff6137a416565b9b9a5050505050505050505050565b6000826137b357506000611138565b828202828482816137c057fe5b04146111355760405162461bcd60e51b8152600401808060200182810382526021815260200180613f816021913960400191505060405180910390fd5b601754613812906001600160a01b0316612a44565b1561384d576040516001600160a01b0383169082156108fc029083906000818181858888f193505050501580156131b2573d6000803e3d6000fd5b6017546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b15801561321657600080fd5b6000806138c4601660089054906101000a90046001600160a01b0316613b81565b6018549091506000906138df906001600160a01b0316613b81565b9050600061390782612db28760000151612db2600f600001548b6137a490919063ffffffff16565b6016546020870151601054929350600391820b92820b01919091039060009082900b811215613955578161394d866125e58663ffffffff808616600a0a8116906137a416565b91505061397a565b6000829003613976866125e58663ffffffff808616600a0a81169061398516565b9150505b979650505050505050565b600061113583836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613c49565b6001600160a01b038216613a0c5760405162461bcd60e51b815260040180806020018281038252602181526020018061403e6021913960400191505060405180910390fd5b613a4f81604051806060016040528060228152602001613dd4602291396001600160a01b038516600090815260016020526040902054919063ffffffff6130a916565b6001600160a01b038316600090815260016020526040902055600354613a7b908263ffffffff612cb816565b6003556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b6001600160a01b031660009081526005602052604090206001015490565b6001600160a01b038116613b265760405162461bcd60e51b8152600401808060200182810382526026815260200180613e1e6026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6018546016546000916001600160a01b03908116600160401b909204161415613bac575060016112b0565b6001600160a01b038216613bc95750670de0b6b3a76400006112b0565b601954604080516341976e0960e01b81526001600160a01b038581166004830152915191909216916341976e09916024808301926020929190829003018186803b158015613c1657600080fd5b505afa158015613c2a573d6000803e3d6000fd5b505050506040513d6020811015613c4057600080fd5b505190506112b0565b60008183613c985760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156130fd5781810151838201526020016130e5565b506000838581613ca457fe5b0495945050505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613cef57805160ff1916838001178555613d1c565b82800160010185558215613d1c579182015b82811115613d1c578251825591602001919060010190613d01565b50613d28929150613d43565b5090565b604080518082019091526000808252602082015290565b6111e291905b80821115613d285760008155600101613d4956fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737343616e27742068617665206d696e436f6c6c61746572616c697a6174696f6e526174696f203c203143616e2774206c6971756964617465206d6f7265207468616e2031303025206f6620746865207661756c7445524332303a206275726e20616d6f756e7420657863656564732062616c616e6365455448206973206e6f74207468652073706563696669656420636f6c6c61746572616c20747970654f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737343616e277420636f6c6c65637420636f6c6c61746572616c20756e74696c20657870697279436f756c64206e6f74207472616e7366657220696e20636f6c6c61746572616c20746f6b656e735661756c7420646f6573206e6f7420657869737400000000000000000000000045524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636543616e27742068617665203e323025206c69717569646174696f6e20696e63656e74697665537065636966696564207661756c7473206861766520696e73756666696369656e7420636f6c6c61746572616c43616e206f6e6c79206c6971756964617465206c69717569646174696f6e20666163746f7220617420616e7920676976656e2074696d65536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616e27742072656d6f7665206d6f726520636f6c6c61746572616c207468616e206f776e656443616e2774206578657263697365206f757473696465206f66207468652065786572636973652077696e646f7745524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657245524332303a206275726e2066726f6d20746865207a65726f206164647265737343616e6e6f742065786572636973652066726f6d2061207661756c74207468617420646f65736e277420657869737445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737343616e2774206578657263697365206d6f7265206f546f6b656e73207468616e20746865206f776e6572206861734f7074696f6e7320636f6e74726163742065787069726564000000000000000045524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a7230582024408987c6dcfcda4c0e73ff0354366a3d057faa494c86e0ef89208047b75fda64736f6c634300050a003245786572636973652077696e646f772063616e2774206265206c6f6e676572207468616e2074686520636f6e74726163742773206c6966657370616e636f6c6c61746572616c206578706f6e656e74206e6f742077697468696e2065787065637465642072616e67656f546f6b656e2065786368616e67652072617465206578706f6e656e74206e6f742077697468696e2065787065637465642072616e6765737472696b65207072696365206578706f6e656e74206e6f742077697468696e2065787065637465642072616e6765756e6465726c79696e67206578706f6e656e74206e6f742077697468696e2065787065637465642072616e6765547279696e6720746f207265706c6163652061206e6f6e2d6578697374656e742061737365744f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572547279696e6720746f2064656c6574652061206e6f6e2d6578697374656e74206173736574a265627a7a72305820d9a46a063d97e32e28fc099c39433b9cf72eec6d7a6f22746ab882e885bc591c64736f6c634300050a0032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000039246c4f3f6592c974ebc44f80ba6dc69b817c710000000000000000000000007054e08461e3ecb7718b63540addb3c3a1746415
-----Decoded View---------------
Arg [0] : _optionsExchangeAddr (address): 0x39246c4F3F6592C974EBC44F80bA6dC69b817c71
Arg [1] : _oracleAddress (address): 0x7054e08461e3eCb7718B63540adDB3c3A1746415
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000039246c4f3f6592c974ebc44f80ba6dc69b817c71
Arg [1] : 0000000000000000000000007054e08461e3ecb7718b63540addb3c3a1746415
Deployed Bytecode Sourcemap
84565:5519:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;84565:5519:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84711:39;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;84711:39:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;84711:39:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;84711:39: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;84711:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;84711:39:0;;-1:-1:-1;84711:39:0;;-1:-1:-1;;;;;84711:39:0:i;:::-;;;;-1:-1:-1;;;;;84711:39:0;;;;;;;;;;;;;;88921:362;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;88921:362:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;88921:362:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;88921:362: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;88921:362:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;88921:362:0;;-1:-1:-1;;;88921:362:0;;-1:-1:-1;;;;;88921:362:0;;-1:-1:-1;88921:362:0;;-1:-1:-1;88921:362:0:i;:::-;;84855:38;;;:::i;38138:140::-;;;:::i;88027:118::-;;;:::i;:::-;;;;;;;;;;;;;;;;37327:79;;;:::i;37693:94::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;86348:1569;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;86348:1569:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;86348:1569:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;86348:1569: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;86348:1569:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;86348:1569:0;;;;;;;;;;;-1:-1:-1;86348:1569:0;;;;-1:-1:-1;86348:1569:0;;;;-1:-1:-1;;;;5:28;;2:2;;;46:1;43;36:12;2:2;86348:1569:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;86348:1569: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;86348:1569:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;86348:1569:0;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;86348:1569:0;;;;;;;;-1:-1:-1;86348:1569:0;;-1:-1:-1;86348:1569:0;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;86348:1569:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;86348:1569: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;86348:1569:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;86348:1569:0;;-1:-1:-1;;86348:1569:0;;;-1:-1:-1;;;86348:1569:0;;;;:::i;84900:28::-;;;:::i;88410:296::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;88410:296:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;88410:296:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;88410:296: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;88410:296:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;88410:296:0;;-1:-1:-1;;;88410:296:0;;-1:-1:-1;;;;;88410:296:0;;-1:-1:-1;88410:296:0;;-1:-1:-1;88410:296:0:i;89872:209::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;89872:209:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;89872:209:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;89872:209: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;89872:209:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;89872:209:0;;-1:-1:-1;89872:209:0;;-1:-1:-1;;;;;89872:209:0:i;89452:268::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;89452:268:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;89452:268:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;89452:268: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;89452:268:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;89452:268:0;;-1:-1:-1;89452:268:0;;-1:-1:-1;;;;;89452:268:0:i;84757:33::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;84757:33:0;;:::i;38433:109::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38433:109:0;-1:-1:-1;;;;;38433:109:0;;:::i;84711:39::-;22:14:-1;;169:4;143:32;;;;;198:20;;84711:39:0;224:31:-1;;156:18;;;283;;;;273:49;328:32;;84711:39:0;-1:-1:-1;;;;;84711:39:0;;:::o;88921:362::-;37539:9;:7;:9::i;:::-;37531:54;;;;;-1:-1:-1;;;37531:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;37531:54:0;;;;;;;;;;;;;;;89054:1;-1:-1:-1;;;;;89029:27:0;:6;89036;89029:14;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;89029:14:0;;;;;-1:-1:-1;89029:14:0;;;;;;;;;;;-1:-1:-1;;;;;89029:14:0;:27;;;;;;-1:-1:-1;89007:115:0;;-1:-1:-1;89007:115:0;;;-1:-1:-1;;;89007:115:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;89141:19:0;;89133:56;;;;;-1:-1:-1;;;89133:56:0;;;;;;;;;;;;-1:-1:-1;;;89133:56:0;;;;;;;;;;;;;;;89226:5;89202:6;89209;89202:14;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;89202:14:0;;;;;-1:-1:-1;89202:14:0;;;;;;;;;;:30;;-1:-1:-1;;;;;;89202:30:0;-1:-1:-1;;;;;89202:30:0;;;;;;89248:27;;;;;;;;89202:14;-1:-1:-1;89202:14:0;;-1:-1:-1;89248:27:0;;;;;89202:14;89248:27;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;;;;365:33;;89248:27:0;;;;;;;;;;-1:-1:-1;89248:27:0;;-1:-1:-1;;;89248:27:0;-1:-1:-1;89248:27:0;88921:362;;:::o;84855:38::-;;;-1:-1:-1;;;;;84855:38:0;;:::o;38138:140::-;37539:9;:7;:9::i;:::-;37531:54;;;;;-1:-1:-1;;;37531:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;37531:54:0;;;;;;;;;;;;;;;38237:1;38221:6;;38200:40;;-1:-1:-1;;;;;38221:6:0;;;;38200:40;;38237:1;;38200:40;38268:1;38251:19;;-1:-1:-1;;;;;;38251:19:0;;;38138:140::o;88027:118::-;88114:16;:23;88027:118;:::o;37327:79::-;37365:7;37392:6;-1:-1:-1;;;;;37392:6:0;37327:79;:::o;37693:94::-;37733:4;37773:6;;-1:-1:-1;;;;;37773:6:0;37757:12;:10;:12::i;:::-;-1:-1:-1;;;;;37757:22:0;;37750:29;;37693:94;:::o;86348:1569::-;86730:7;86768:15;86758:7;:25;86750:69;;;;;-1:-1:-1;;;86750:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;86853:7;86838:11;:22;;86830:54;;;;;-1:-1:-1;;;86830:54:0;;;;;;;;;;;;-1:-1:-1;;;86830:54:0;;;;;;;;;;;;;;;86917:30;86931:15;86917:13;:30::i;:::-;86895:109;;;;;-1:-1:-1;;;86895:109:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;87037:30;87051:15;87037:13;:30::i;:::-;87015:109;;;;;-1:-1:-1;;;87015:109:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;87143:27;87157:12;87143:13;:27::i;:::-;87135:71;;;;;-1:-1:-1;;;87135:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;87219:31;87278:6;87285:15;87278:23;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;87278:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;87278:23:0;87316:14;87345:6;87352:15;87345:23;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;87345:23:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;87345:23:0;87383:14;87412:18;87445:12;87472:10;87497:6;87504:12;87497:20;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;87497:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;87497:20:0;87532:7;87554:15;;;;;;;;;-1:-1:-1;;;;;87554:15:0;87584:13;;;;;;;;;-1:-1:-1;;;;;87584:13:0;87612:11;87253:381;;;;;:::i;:::-;-1:-1:-1;;;;;87253:381:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;87253:381:0;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;87647:16:0;27:10:-1;;39:1;23:18;;45:23;;-1:-1;87647:47:0;;;;;;;;-1:-1:-1;;;;;87647:47:0;;-1:-1:-1;;;;;;87647:47:0;;;;;;;;87710:48;;;;;;;87219:415;;-1:-1:-1;87710:48:0;;;;;;87647:47;87710:48;;;87823:15;-1:-1:-1;;;;;87823:33:0;;87857:7;:5;:7::i;:::-;87823:42;;;;;;;;;;;;;-1:-1:-1;;;;;87823:42:0;-1:-1:-1;;;;;87823:42:0;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;87823:42:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;87893:15:0;;86348:1569;-1:-1:-1;;;;;;;;;;;;;;86348:1569:0:o;84900:28::-;;;-1:-1:-1;;;;;84900:28:0;;:::o;88410:296::-;37539:9;:7;:9::i;:::-;37531:54;;;;;-1:-1:-1;;;37531:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;37531:54:0;;;;;;;;;;;;;;;88502:21;88516:6;88502:13;:21::i;:::-;88501:22;88493:54;;;;;-1:-1:-1;;;88493:54:0;;;;;;;;;;;;-1:-1:-1;;;88493:54:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;88566:19:0;;88558:56;;;;;-1:-1:-1;;;88558:56:0;;;;;;;;;;;;-1:-1:-1;;;88558:56:0;;;;;;;;;;;;;;;88651:5;88627:6;88634;88627:14;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;88627:14:0;;;;;-1:-1:-1;88627:14:0;;;;;;;;;;:30;;-1:-1:-1;;;;;;88627:30:0;-1:-1:-1;;;;;88627:30:0;;;;;;88673:25;;;;;;;;88627:14;-1:-1:-1;88627:14:0;;-1:-1:-1;88673:25:0;;;;;88627:14;88673:25;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;;;;365:33;;88673:25:0;;;;;;;;;;-1:-1:-1;88673:25:0;;-1:-1:-1;;;88673:25:0;-1:-1:-1;88673:25:0;88410:296;;:::o;89872:209::-;89959:28;;;-1:-1:-1;;;89959:28:0;;;;;;;;;;;;;;;;89938:4;;89959:21;;;;:6;;:28;;;;;;;;;;;;;;;;;89938:4;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;89959:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;89959:28:0;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;89959:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;89959:28:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;89959:28:0;89955:72;;;-1:-1:-1;90011:4:0;90004:11;;89955:72;90071:1;-1:-1:-1;;;;;90046:27:0;:6;90053;90046:14;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;90046:14:0;;;;;-1:-1:-1;90046:14:0;;;;;;;;;;;-1:-1:-1;;;;;90046:14:0;:27;;;;;;-1:-1:-1;;;89872:209:0;;;;:::o;89452:268::-;37539:9;:7;:9::i;:::-;37531:54;;;;;-1:-1:-1;;;37531:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;37531:54:0;;;;;;;;;;;;;;;89570:1;-1:-1:-1;;;;;89545:27:0;:6;89552;89545:14;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;89545:14:0;;;;;-1:-1:-1;89545:14:0;;;;;;;;;;;-1:-1:-1;;;;;89545:14:0;:27;;;;;;-1:-1:-1;89523:114:0;;-1:-1:-1;89523:114:0;;;-1:-1:-1;;;89523:114:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89674:1;89650:6;89657;89650:14;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;89650:14:0;;;;;-1:-1:-1;89650:14:0;;;;;;;;;;:26;;-1:-1:-1;;;;;;89650:26:0;-1:-1:-1;;;;;89650:26:0;;;;;;;;;;;-1:-1:-1;;89692:20:0;;;;89650:14;;89692:20;;;;;89650:14;89692:20;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;;;;365:33;;89692:20:0;;;;;;;;;;-1:-1:-1;89692:20:0;;-1:-1:-1;;;89692:20:0;-1:-1:-1;89692:20:0;89452:268;:::o;84757:33::-;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;84757:33:0;;-1:-1:-1;84757:33:0;:::o;38433:109::-;37539:9;:7;:9::i;:::-;37531:54;;;;;-1:-1:-1;;;37531:54:0;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;37531:54:0;;;;;;;;;;;;;;;38506:28;38525:8;38506:18;:28::i;:::-;38433:109;:::o;858:98::-;938:10;858:98;:::o;38648:229::-;-1:-1:-1;;;;;38722:22:0;;38714:73;;;;-1:-1:-1;;;38714:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38824:6;;;38803:38;;-1:-1:-1;;;;;38803:38:0;;;;38824:6;;;38803:38;;;38852:6;:17;;-1:-1:-1;;;;;;38852:17:0;-1:-1:-1;;;;;38852:17:0;;;;;;;;;;38648:229::o;84565:5519::-;;;;;;;;:::o
Swarm Source
bzzr://d9a46a063d97e32e28fc099c39433b9cf72eec6d7a6f22746ab882e885bc591c
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.