Overview
ETH Balance
0.06 ETH
Eth Value
$197.18 (@ $3,286.35/ETH)More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 93 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Exchange Bond To... | 12279129 | 1371 days ago | IN | 0 ETH | 0.04685064 | ||||
Exchange Erc20To... | 12268006 | 1373 days ago | IN | 0 ETH | 0.02658478 | ||||
Exchange Erc20To... | 12267586 | 1373 days ago | IN | 0 ETH | 0.01987432 | ||||
Exchange Erc20To... | 12266894 | 1373 days ago | IN | 0 ETH | 0.02240141 | ||||
Exchange Erc20To... | 12263035 | 1374 days ago | IN | 0 ETH | 0.03106715 | ||||
Exchange Bond To... | 12262069 | 1374 days ago | IN | 0 ETH | 0.04480881 | ||||
Exchange Erc20To... | 12261805 | 1374 days ago | IN | 0 ETH | 0.09280495 | ||||
Exchange Bond To... | 12260835 | 1374 days ago | IN | 0 ETH | 0.0248846 | ||||
Exchange Erc20To... | 12258270 | 1374 days ago | IN | 0 ETH | 0.03645861 | ||||
Exchange Bond To... | 12256780 | 1375 days ago | IN | 0 ETH | 0.03658794 | ||||
Exchange Erc20To... | 12254812 | 1375 days ago | IN | 0 ETH | 0.02909673 | ||||
Exchange Erc20To... | 12251458 | 1375 days ago | IN | 0 ETH | 0.0583083 | ||||
Exchange Bond To... | 12250814 | 1375 days ago | IN | 0 ETH | 0.01975617 | ||||
Exchange Bond To... | 12250808 | 1375 days ago | IN | 0 ETH | 0.02235726 | ||||
Exchange Bond To... | 12249526 | 1376 days ago | IN | 0 ETH | 0.03643333 | ||||
Exchange Bond To... | 12243229 | 1377 days ago | IN | 0 ETH | 0.01527841 | ||||
Exchange Bond To... | 12240876 | 1377 days ago | IN | 0 ETH | 0.02268536 | ||||
Exchange Erc20To... | 12238285 | 1377 days ago | IN | 0 ETH | 0.02635566 | ||||
Exchange Bond To... | 12235868 | 1378 days ago | IN | 0 ETH | 0.02489071 | ||||
Exchange Erc20To... | 12222100 | 1380 days ago | IN | 0 ETH | 0.01548945 | ||||
Exchange Erc20To... | 12218891 | 1380 days ago | IN | 0 ETH | 0.01425195 | ||||
Exchange Erc20To... | 12218776 | 1380 days ago | IN | 0 ETH | 0.01796985 | ||||
Deposit Eth | 12217014 | 1381 days ago | IN | 0.01 ETH | 0.00184912 | ||||
Deposit Eth | 12217002 | 1381 days ago | IN | 0.05 ETH | 0.00286912 | ||||
Withdraw Eth | 12216968 | 1381 days ago | IN | 0 ETH | 0.0016579 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
12216968 | 1381 days ago | 0.02 ETH |
Loading...
Loading
Contract Name:
GeneralizedDotc
Compiler Version
v0.6.6+commit.6c089d02
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2021-03-12 */ pragma solidity 0.6.6; // File: @openzeppelin/contracts/GSN/Context.sol /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } function _msgSender() internal view virtual returns (address payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol /** * @dev Interface of the ERC20 standard as defined in the EIP. */ 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 /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: @openzeppelin/contracts/utils/Address.sol /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } } // File: @openzeppelin/contracts/token/ERC20/ERC20.sol /** * @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 {ERC20MinterPauser}. * * 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; using Address for address; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for {name} and {symbol}, initializes {decimals} with * a default value of 18. * * To select a different value for {decimals}, use {_setupDecimals}. * * All three of these values are immutable: they can only be set once during * construction. */ constructor (string memory name, string memory symbol) public { _name = name; _symbol = symbol; _decimals = 18; } /** * @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. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * 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; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view override 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 virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override 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 virtual override 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 virtual 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 virtual 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 virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); _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 virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _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 virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); _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 virtual { 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 Sets {decimals} to a value other than the default one of 18. * * WARNING: This function should only be called from the constructor. Most * applications that interact with token contracts will not expect * {decimals} to ever change, and may work incorrectly if it does. */ function _setupDecimals(uint8 decimals_) internal { _decimals = decimals_; } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } } // File: contracts/oracle/LatestPriceOracleInterface.sol pragma solidity 0.6.6; /** * @dev Interface of the price oracle. */ interface LatestPriceOracleInterface { /** * @dev Returns `true`if oracle is working. */ function isWorking() external returns (bool); /** * @dev Returns the last updated price. Decimals is 8. **/ function latestPrice() external returns (uint256); /** * @dev Returns the timestamp of the last updated price. */ function latestTimestamp() external returns (uint256); } // File: contracts/oracle/PriceOracleInterface.sol pragma solidity 0.6.6; /** * @dev Interface of the price oracle. */ interface PriceOracleInterface is LatestPriceOracleInterface { /** * @dev Returns the latest id. The id start from 1 and increments by 1. */ function latestId() external returns (uint256); /** * @dev Returns the historical price specified by `id`. Decimals is 8. */ function getPrice(uint256 id) external returns (uint256); /** * @dev Returns the timestamp of historical price specified by `id`. */ function getTimestamp(uint256 id) external returns (uint256); } // File: contracts/oracle/OracleInterface.sol pragma solidity 0.6.6; // Oracle referenced by OracleProxy must implement this interface. interface OracleInterface is PriceOracleInterface { function getVolatility() external returns (uint256); function lastCalculatedVolatility() external view returns (uint256); } // File: contracts/oracle/VolatilityOracleInterface.sol pragma solidity 0.6.6; interface VolatilityOracleInterface { function getVolatility(uint64 untilMaturity) external view returns (uint64 volatilityE8); } // File: contracts/util/TransferETHInterface.sol pragma solidity 0.6.6; interface TransferETHInterface { receive() external payable; event LogTransferETH(address indexed from, address indexed to, uint256 value); } // File: contracts/bondToken/BondTokenInterface.sol pragma solidity 0.6.6; interface BondTokenInterface is IERC20 { event LogExpire(uint128 rateNumerator, uint128 rateDenominator, bool firstTime); function mint(address account, uint256 amount) external returns (bool success); function expire(uint128 rateNumerator, uint128 rateDenominator) external returns (bool firstTime); function simpleBurn(address account, uint256 amount) external returns (bool success); function burn(uint256 amount) external returns (bool success); function burnAll() external returns (uint256 amount); function getRate() external view returns (uint128 rateNumerator, uint128 rateDenominator); } // File: contracts/bondMaker/BondMakerInterface.sol pragma solidity 0.6.6; interface BondMakerInterface { event LogNewBond( bytes32 indexed bondID, address indexed bondTokenAddress, uint256 indexed maturity, bytes32 fnMapID ); event LogNewBondGroup( uint256 indexed bondGroupID, uint256 indexed maturity, uint64 indexed sbtStrikePrice, bytes32[] bondIDs ); event LogIssueNewBonds( uint256 indexed bondGroupID, address indexed issuer, uint256 amount ); event LogReverseBondGroupToCollateral( uint256 indexed bondGroupID, address indexed owner, uint256 amount ); event LogExchangeEquivalentBonds( address indexed owner, uint256 indexed inputBondGroupID, uint256 indexed outputBondGroupID, uint256 amount ); event LogLiquidateBond( bytes32 indexed bondID, uint128 rateNumerator, uint128 rateDenominator ); function registerNewBond(uint256 maturity, bytes calldata fnMap) external returns ( bytes32 bondID, address bondTokenAddress, bytes32 fnMapID ); function registerNewBondGroup( bytes32[] calldata bondIDList, uint256 maturity ) external returns (uint256 bondGroupID); function reverseBondGroupToCollateral(uint256 bondGroupID, uint256 amount) external returns (bool success); function exchangeEquivalentBonds( uint256 inputBondGroupID, uint256 outputBondGroupID, uint256 amount, bytes32[] calldata exceptionBonds ) external returns (bool); function liquidateBond(uint256 bondGroupID, uint256 oracleHintID) external returns (uint256 totalPayment); function collateralAddress() external view returns (address); function oracleAddress() external view returns (PriceOracleInterface); function feeTaker() external view returns (address); function decimalsOfBond() external view returns (uint8); function decimalsOfOraclePrice() external view returns (uint8); function maturityScale() external view returns (uint256); function nextBondGroupID() external view returns (uint256); function getBond(bytes32 bondID) external view returns ( address bondAddress, uint256 maturity, uint64 solidStrikePrice, bytes32 fnMapID ); function getFnMap(bytes32 fnMapID) external view returns (bytes memory fnMap); function getBondGroup(uint256 bondGroupID) external view returns (bytes32[] memory bondIDs, uint256 maturity); function generateFnMapID(bytes calldata fnMap) external view returns (bytes32 fnMapID); function generateBondID(uint256 maturity, bytes calldata fnMap) external view returns (bytes32 bondID); } // File: contracts/bondPricer/Enums.sol pragma solidity 0.6.6; /** Pure SBT: ___________ / / / / LBT Shape: / / / / ______/ SBT Shape: ______ / / _______/ Triangle: /\ / \ / \ _______/ \________ */ enum BondType {NONE, PURE_SBT, SBT_SHAPE, LBT_SHAPE, TRIANGLE} // File: contracts/bondPricer/BondPricerInterface.sol pragma solidity 0.6.6; interface BondPricerInterface { /** * @notice Calculate bond price and leverage by black-scholes formula. * @param bondType type of target bond. * @param points coodinates of polyline which is needed for price calculation * @param spotPrice is a oracle price. * @param volatilityE8 is a oracle volatility. * @param untilMaturity Remaining period of target bond in second **/ function calcPriceAndLeverage( BondType bondType, uint256[] calldata points, int256 spotPrice, int256 volatilityE8, int256 untilMaturity ) external view returns (uint256 price, uint256 leverageE8); } // File: @openzeppelin/contracts/math/SignedSafeMath.sol /** * @title SignedSafeMath * @dev Signed math operations with safety checks that revert on error. */ library SignedSafeMath { int256 constant private _INT256_MIN = -2**255; /** * @dev Multiplies two signed integers, reverts on overflow. */ function mul(int256 a, int256 b) internal pure returns (int256) { // 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; } require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow"); int256 c = a * b; require(c / a == b, "SignedSafeMath: multiplication overflow"); return c; } /** * @dev Integer division of two signed integers truncating the quotient, reverts on division by zero. */ function div(int256 a, int256 b) internal pure returns (int256) { require(b != 0, "SignedSafeMath: division by zero"); require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow"); int256 c = a / b; return c; } /** * @dev Subtracts two signed integers, reverts on overflow. */ function sub(int256 a, int256 b) internal pure returns (int256) { int256 c = a - b; require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow"); return c; } /** * @dev Adds two signed integers, reverts on overflow. */ function add(int256 a, int256 b) internal pure returns (int256) { int256 c = a + b; require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow"); return c; } } // File: @openzeppelin/contracts/utils/SafeCast.sol /** * @dev Wrappers over Solidity's uintXX casting operators with added overflow * checks. * * Downcasting from uint256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such 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. * * Can be combined with {SafeMath} to extend it to smaller types, by performing * all math on `uint256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits. */ function toUint8(uint256 value) internal pure returns (uint8) { require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { require(value < 2**255, "SafeCast: value doesn't fit in an int256"); return int256(value); } } // File: contracts/math/UseSafeMath.sol pragma solidity 0.6.6; /** * @notice ((a - 1) / b) + 1 = (a + b -1) / b * for example a.add(10**18 -1).div(10**18) = a.sub(1).div(10**18) + 1 */ library SafeMathDivRoundUp { using SafeMath for uint256; function divRoundUp( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { if (a == 0) { return 0; } require(b > 0, errorMessage); return ((a - 1) / b) + 1; } function divRoundUp(uint256 a, uint256 b) internal pure returns (uint256) { return divRoundUp(a, b, "SafeMathDivRoundUp: modulo by zero"); } } /** * @title UseSafeMath * @dev One can use SafeMath for not only uint256 but also uin64 or uint16, * and also can use SafeCast for uint256. * For example: * uint64 a = 1; * uint64 b = 2; * a = a.add(b).toUint64() // `a` become 3 as uint64 * In addition, one can use SignedSafeMath and SafeCast.toUint256(int256) for int256. * In the case of the operation to the uint64 value, one needs to cast the value into int256 in * advance to use `sub` as SignedSafeMath.sub not SafeMath.sub. * For example: * int256 a = 1; * uint64 b = 2; * int256 c = 3; * a = a.add(int256(b).sub(c)); // `a` becomes 0 as int256 * b = a.toUint256().toUint64(); // `b` becomes 0 as uint64 */ abstract contract UseSafeMath { using SafeMath for uint256; using SafeMathDivRoundUp for uint256; using SafeMath for uint64; using SafeMathDivRoundUp for uint64; using SafeMath for uint16; using SignedSafeMath for int256; using SafeCast for uint256; using SafeCast for int256; } // File: contracts/util/Polyline.sol pragma solidity 0.6.6; contract Polyline is UseSafeMath { struct Point { uint64 x; // Value of the x-axis of the x-y plane uint64 y; // Value of the y-axis of the x-y plane } struct LineSegment { Point left; // The left end of the line definition range Point right; // The right end of the line definition range } /** * @notice Return the value of y corresponding to x on the given line. line in the form of * a rational number (numerator / denominator). * If you treat a line as a line segment instead of a line, you should run * includesDomain(line, x) to check whether x is included in the line's domain or not. * @dev To guarantee accuracy, the bit length of the denominator must be greater than or equal * to the bit length of x, and the bit length of the numerator must be greater than or equal * to the sum of the bit lengths of x and y. */ function _mapXtoY(LineSegment memory line, uint64 x) internal pure returns (uint128 numerator, uint64 denominator) { int256 x1 = int256(line.left.x); int256 y1 = int256(line.left.y); int256 x2 = int256(line.right.x); int256 y2 = int256(line.right.y); require(x2 > x1, "must be left.x < right.x"); denominator = uint64(x2 - x1); // Calculate y = ((x2 - x) * y1 + (x - x1) * y2) / (x2 - x1) // in the form of a fraction (numerator / denominator). int256 n = (x - x1) * y2 + (x2 - x) * y1; require(n >= 0, "underflow n"); require(n < 2**128, "system error: overflow n"); numerator = uint128(n); } /** * @notice Checking that a line segment is a valid format. */ function assertLineSegment(LineSegment memory segment) internal pure { uint64 x1 = segment.left.x; uint64 x2 = segment.right.x; require(x1 < x2, "must be left.x < right.x"); } /** * @notice Checking that a polyline is a valid format. */ function assertPolyline(LineSegment[] memory polyline) internal pure { uint256 numOfSegment = polyline.length; require(numOfSegment != 0, "polyline must not be empty array"); LineSegment memory leftSegment = polyline[0]; // mutable int256 gradientNumerator = int256(leftSegment.right.y) - int256(leftSegment.left.y); // mutable int256 gradientDenominator = int256(leftSegment.right.x) - int256(leftSegment.left.x); // mutable // The beginning of the first line segment's domain is 0. require( leftSegment.left.x == uint64(0), "the x coordinate of left end of the first segment must be 0" ); // The value of y when x is 0 is 0. require( leftSegment.left.y == uint64(0), "the y coordinate of left end of the first segment must be 0" ); // Making sure that the first line segment is a correct format. assertLineSegment(leftSegment); // The end of the domain of a segment and the beginning of the domain of the adjacent // segment must coincide. LineSegment memory rightSegment; // mutable for (uint256 i = 1; i < numOfSegment; i++) { rightSegment = polyline[i]; // Make sure that the i-th line segment is a correct format. assertLineSegment(rightSegment); // Checking that the x-coordinates are same. require( leftSegment.right.x == rightSegment.left.x, "given polyline has an undefined domain." ); // Checking that the y-coordinates are same. require( leftSegment.right.y == rightSegment.left.y, "given polyline is not a continuous function" ); int256 nextGradientNumerator = int256(rightSegment.right.y) - int256(rightSegment.left.y); int256 nextGradientDenominator = int256(rightSegment.right.x) - int256(rightSegment.left.x); require( nextGradientNumerator * gradientDenominator != nextGradientDenominator * gradientNumerator, "the sequential segments must not have the same gradient" ); leftSegment = rightSegment; gradientNumerator = nextGradientNumerator; gradientDenominator = nextGradientDenominator; } // rightSegment is lastSegment // About the last line segment. require( gradientNumerator >= 0 && gradientNumerator <= gradientDenominator, "the gradient of last line segment must be non-negative, and equal to or less than 1" ); } /** * @notice zip a LineSegment structure to uint256 * @return zip uint256( 0 ... 0 | x1 | y1 | x2 | y2 ) */ function zipLineSegment(LineSegment memory segment) internal pure returns (uint256 zip) { uint256 x1U256 = uint256(segment.left.x) << (64 + 64 + 64); // uint64 uint256 y1U256 = uint256(segment.left.y) << (64 + 64); // uint64 uint256 x2U256 = uint256(segment.right.x) << 64; // uint64 uint256 y2U256 = uint256(segment.right.y); // uint64 zip = x1U256 | y1U256 | x2U256 | y2U256; } /** * @notice unzip uint256 to a LineSegment structure */ function unzipLineSegment(uint256 zip) internal pure returns (LineSegment memory) { uint64 x1 = uint64(zip >> (64 + 64 + 64)); uint64 y1 = uint64(zip >> (64 + 64)); uint64 x2 = uint64(zip >> 64); uint64 y2 = uint64(zip); return LineSegment({ left: Point({x: x1, y: y1}), right: Point({x: x2, y: y2}) }); } /** * @notice unzip the fnMap to uint256[]. */ function decodePolyline(bytes memory fnMap) internal pure returns (uint256[] memory) { return abi.decode(fnMap, (uint256[])); } } // File: contracts/bondPricer/DetectBondShape.sol pragma solidity 0.6.6; contract DetectBondShape is Polyline { /** * @notice Detect bond type by polyline of bond. * @param bondID bondID of target bond token * @param submittedType if this parameter is BondType.NONE, this function checks up all bond types. Otherwise this function checks up only one bond type. * @param success whether bond detection succeeded or notice * @param points coodinates of polyline which is needed for price calculation **/ function getBondTypeByID( BondMakerInterface bondMaker, bytes32 bondID, BondType submittedType ) public view returns ( bool success, BondType, uint256[] memory points ) { (, , , bytes32 fnMapID) = bondMaker.getBond(bondID); bytes memory fnMap = bondMaker.getFnMap(fnMapID); return _getBondType(fnMap, submittedType); } /** * @notice Detect bond type by polyline of bond. * @param fnMap Function mapping of target bond token * @param submittedType If this parameter is BondType.NONE, this function checks up all bond types. Otherwise this function checks up only one bond type. * @param success Whether bond detection succeeded or not * @param points Coodinates of polyline which are needed for price calculation **/ function getBondType(bytes calldata fnMap, BondType submittedType) external pure returns ( bool success, BondType, uint256[] memory points ) { uint256[] memory polyline = decodePolyline(fnMap); LineSegment[] memory segments = new LineSegment[](polyline.length); for (uint256 i = 0; i < polyline.length; i++) { segments[i] = unzipLineSegment(polyline[i]); } assertPolyline(segments); return _getBondType(fnMap, submittedType); } function _getBondType(bytes memory fnMap, BondType submittedType) internal pure returns ( bool success, BondType, uint256[] memory points ) { if (submittedType == BondType.NONE) { (success, points) = _isSBT(fnMap); if (success) { return (success, BondType.PURE_SBT, points); } (success, points) = _isSBTShape(fnMap); if (success) { return (success, BondType.SBT_SHAPE, points); } (success, points) = _isLBTShape(fnMap); if (success) { return (success, BondType.LBT_SHAPE, points); } (success, points) = _isTriangle(fnMap); if (success) { return (success, BondType.TRIANGLE, points); } return (false, BondType.NONE, points); } else if (submittedType == BondType.PURE_SBT) { (success, points) = _isSBT(fnMap); if (success) { return (success, BondType.PURE_SBT, points); } } else if (submittedType == BondType.SBT_SHAPE) { (success, points) = _isSBTShape(fnMap); if (success) { return (success, BondType.SBT_SHAPE, points); } } else if (submittedType == BondType.LBT_SHAPE) { (success, points) = _isLBTShape(fnMap); if (success) { return (success, BondType.LBT_SHAPE, points); } } else if (submittedType == BondType.TRIANGLE) { (success, points) = _isTriangle(fnMap); if (success) { return (success, BondType.TRIANGLE, points); } } return (false, BondType.NONE, points); } function _isLBTShape(bytes memory fnMap) internal pure returns (bool isOk, uint256[] memory points) { uint256[] memory zippedLines = decodePolyline(fnMap); if (zippedLines.length != 2) { return (false, points); } LineSegment memory secondLine = unzipLineSegment(zippedLines[1]); if ( secondLine.left.x != 0 && secondLine.left.y == 0 && secondLine.right.x > secondLine.left.x && secondLine.right.y != 0 ) { uint256[] memory _lines = new uint256[](3); _lines[0] = secondLine.left.x; _lines[1] = secondLine.right.x; _lines[2] = secondLine.right.y; return (true, _lines); } return (false, points); } function _isTriangle(bytes memory fnMap) internal pure returns (bool isOk, uint256[] memory points) { uint256[] memory zippedLines = decodePolyline(fnMap); if (zippedLines.length != 4) { return (false, points); } LineSegment memory secondLine = unzipLineSegment(zippedLines[1]); LineSegment memory thirdLine = unzipLineSegment(zippedLines[2]); LineSegment memory forthLine = unzipLineSegment(zippedLines[3]); if ( secondLine.left.x != 0 && secondLine.left.y == 0 && secondLine.right.x > secondLine.left.x && secondLine.right.y != 0 && thirdLine.right.x > secondLine.right.x && thirdLine.right.y == 0 && forthLine.right.x > thirdLine.right.x && forthLine.right.y == 0 ) { uint256[] memory _lines = new uint256[](4); _lines[0] = secondLine.left.x; _lines[1] = secondLine.right.x; _lines[2] = secondLine.right.y; _lines[3] = thirdLine.right.x; return (true, _lines); } return (false, points); } function _isSBTShape(bytes memory fnMap) internal pure returns (bool isOk, uint256[] memory points) { uint256[] memory zippedLines = decodePolyline(fnMap); if (zippedLines.length != 3) { return (false, points); } LineSegment memory secondLine = unzipLineSegment(zippedLines[1]); LineSegment memory thirdLine = unzipLineSegment(zippedLines[2]); if ( secondLine.left.x != 0 && secondLine.left.y == 0 && secondLine.right.x > secondLine.left.x && secondLine.right.y != 0 && thirdLine.right.x > secondLine.right.x && thirdLine.right.y == secondLine.right.y ) { uint256[] memory _lines = new uint256[](3); _lines[0] = secondLine.left.x; _lines[1] = secondLine.right.x; _lines[2] = secondLine.right.y; return (true, _lines); } return (false, points); } function _isSBT(bytes memory fnMap) internal pure returns (bool isOk, uint256[] memory points) { uint256[] memory zippedLines = decodePolyline(fnMap); if (zippedLines.length != 2) { return (false, points); } LineSegment memory secondLine = unzipLineSegment(zippedLines[1]); if ( secondLine.left.x != 0 && secondLine.left.y == secondLine.left.x && secondLine.right.x > secondLine.left.x && secondLine.right.y == secondLine.left.y ) { uint256[] memory _lines = new uint256[](1); _lines[0] = secondLine.left.x; return (true, _lines); } return (false, points); } } // File: contracts/util/Time.sol pragma solidity 0.6.6; abstract contract Time { function _getBlockTimestampSec() internal view returns (uint256 unixtimesec) { unixtimesec = block.timestamp; // solhint-disable-line not-rely-on-time } } // File: contracts/generalizedDotc/BondExchange.sol pragma solidity 0.6.6; abstract contract BondExchange is UseSafeMath, Time { uint256 internal constant MIN_EXCHANGE_RATE_E8 = 0.000001 * 10**8; uint256 internal constant MAX_EXCHANGE_RATE_E8 = 1000000 * 10**8; int256 internal constant MAX_SPREAD_E8 = 10**8; // 100% /** * @dev the sum of decimalsOfBond of the bondMaker. * This value is constant by the restriction of `_assertBondMakerDecimals`. */ uint8 internal constant DECIMALS_OF_BOND = 8; /** * @dev the sum of decimalsOfOraclePrice of the bondMaker. * This value is constant by the restriction of `_assertBondMakerDecimals`. */ uint8 internal constant DECIMALS_OF_ORACLE_PRICE = 8; BondMakerInterface internal immutable _bondMakerContract; PriceOracleInterface internal immutable _priceOracleContract; VolatilityOracleInterface internal immutable _volatilityOracleContract; LatestPriceOracleInterface internal immutable _volumeCalculator; DetectBondShape internal immutable _bondShapeDetector; /** * @param bondMakerAddress is a bond maker contract. * @param volumeCalculatorAddress is a contract to convert the unit of a strike price to USD. */ constructor( BondMakerInterface bondMakerAddress, VolatilityOracleInterface volatilityOracleAddress, LatestPriceOracleInterface volumeCalculatorAddress, DetectBondShape bondShapeDetector ) public { _assertBondMakerDecimals(bondMakerAddress); _bondMakerContract = bondMakerAddress; _priceOracleContract = bondMakerAddress.oracleAddress(); _volatilityOracleContract = VolatilityOracleInterface( volatilityOracleAddress ); _volumeCalculator = volumeCalculatorAddress; _bondShapeDetector = bondShapeDetector; } function bondMakerAddress() external view returns (BondMakerInterface) { return _bondMakerContract; } function volumeCalculatorAddress() external view returns (LatestPriceOracleInterface) { return _volumeCalculator; } /** * @dev Get the latest price (USD) and historical volatility using oracle. * If the oracle is not working, `latestPrice` reverts. * @return priceE8 (10^-8 USD) */ function _getLatestPrice(LatestPriceOracleInterface oracle) internal returns (uint256 priceE8) { return oracle.latestPrice(); } /** * @dev Get the implied volatility using oracle. * @return volatilityE8 (10^-8) */ function _getVolatility( VolatilityOracleInterface oracle, uint64 untilMaturity ) internal view returns (uint256 volatilityE8) { return oracle.getVolatility(untilMaturity); } /** * @dev Returns bond tokenaddress, maturity, */ function _getBond(BondMakerInterface bondMaker, bytes32 bondID) internal view returns ( ERC20 bondToken, uint256 maturity, uint256 sbtStrikePrice, bytes32 fnMapID ) { address bondTokenAddress; (bondTokenAddress, maturity, sbtStrikePrice, fnMapID) = bondMaker .getBond(bondID); // Revert if `bondTokenAddress` is zero. bondToken = ERC20(bondTokenAddress); } /** * @dev Removes a decimal gap from the first argument. */ function _applyDecimalGap( uint256 baseAmount, uint8 decimalsOfBase, uint8 decimalsOfQuote ) internal pure returns (uint256 quoteAmount) { uint256 n; uint256 d; if (decimalsOfBase > decimalsOfQuote) { d = decimalsOfBase - decimalsOfQuote; } else if (decimalsOfBase < decimalsOfQuote) { n = decimalsOfQuote - decimalsOfBase; } // The consequent multiplication would overflow under extreme and non-blocking circumstances. require(n < 19 && d < 19, "decimal gap needs to be lower than 19"); return baseAmount.mul(10**n).div(10**d); } function _calcBondPriceAndSpread( BondPricerInterface bondPricer, bytes32 bondID, int16 feeBaseE4 ) internal returns (uint256 bondPriceE8, int256 spreadE8) { (, uint256 maturity, , ) = _getBond(_bondMakerContract, bondID); ( bool isKnownBondType, BondType bondType, uint256[] memory points ) = _bondShapeDetector.getBondTypeByID( _bondMakerContract, bondID, BondType.NONE ); require(isKnownBondType, "cannot calculate the price of this bond"); uint256 untilMaturity = maturity.sub( _getBlockTimestampSec(), "the bond should not have expired" ); uint256 oraclePriceE8 = _getLatestPrice(_priceOracleContract); uint256 oracleVolatilityE8 = _getVolatility( _volatilityOracleContract, untilMaturity.toUint64() ); uint256 leverageE8; (bondPriceE8, leverageE8) = bondPricer.calcPriceAndLeverage( bondType, points, oraclePriceE8.toInt256(), oracleVolatilityE8.toInt256(), untilMaturity.toInt256() ); spreadE8 = _calcSpread(oracleVolatilityE8, leverageE8, feeBaseE4); } function _calcSpread( uint256 oracleVolatilityE8, uint256 leverageE8, int16 feeBaseE4 ) internal pure returns (int256 spreadE8) { uint256 volE8 = oracleVolatilityE8 < 10**8 ? 10**8 : oracleVolatilityE8 > 2 * 10**8 ? 2 * 10**8 : oracleVolatilityE8; uint256 volTimesLevE16 = volE8 * leverageE8; // assert(volTimesLevE16 < 200 * 10**16); spreadE8 = (feeBaseE4 * ( feeBaseE4 < 0 || volTimesLevE16 < 10**16 ? 10**16 : volTimesLevE16 ) .toInt256()) / 10**12; spreadE8 = spreadE8 > MAX_SPREAD_E8 ? MAX_SPREAD_E8 : spreadE8; } /** * @dev Calculate the exchange volume on the USD basis. */ function _calcUsdPrice(uint256 amount) internal returns (uint256) { return amount.mul(_getLatestPrice(_volumeCalculator)) / 10**8; } /** * @dev Restirct the bond maker. */ function _assertBondMakerDecimals(BondMakerInterface bondMaker) internal view { require( bondMaker.decimalsOfOraclePrice() == DECIMALS_OF_ORACLE_PRICE, "the decimals of oracle price must be 8" ); require( bondMaker.decimalsOfBond() == DECIMALS_OF_BOND, "the decimals of bond token must be 8" ); } function _assertExpectedPriceRange( uint256 actualAmount, uint256 expectedAmount, uint256 range ) internal pure { if (expectedAmount != 0) { require( actualAmount.mul(1000 + range).div(1000) >= expectedAmount, "out of expected price range" ); } } } // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: contracts/generalizedDotc/BondVsErc20Exchange.sol pragma solidity 0.6.6; abstract contract BondVsErc20Exchange is BondExchange { using SafeERC20 for ERC20; struct VsErc20Pool { address seller; ERC20 swapPairToken; LatestPriceOracleInterface swapPairOracle; BondPricerInterface bondPricer; int16 feeBaseE4; bool isBondSale; } mapping(bytes32 => VsErc20Pool) internal _vsErc20Pool; event LogCreateErc20ToBondPool( bytes32 indexed poolID, address indexed seller, address indexed swapPairAddress ); event LogCreateBondToErc20Pool( bytes32 indexed poolID, address indexed seller, address indexed swapPairAddress ); event LogUpdateVsErc20Pool( bytes32 indexed poolID, address swapPairOracleAddress, address bondPricerAddress, int16 feeBase // decimal: 4 ); event LogDeleteVsErc20Pool(bytes32 indexed poolID); event LogExchangeErc20ToBond( address indexed buyer, bytes32 indexed bondID, bytes32 indexed poolID, uint256 bondAmount, // decimal: 8 uint256 swapPairAmount, // decimal: ERC20.decimals() uint256 volume // USD, decimal: 8 ); event LogExchangeBondToErc20( address indexed buyer, bytes32 indexed bondID, bytes32 indexed poolID, uint256 bondAmount, // decimal: 8 uint256 swapPairAmount, // decimal: ERC20.decimals() uint256 volume // USD, decimal: 8 ); /** * @dev Reverts when the pool ID does not exist. */ modifier isExsistentVsErc20Pool(bytes32 poolID) { require( _vsErc20Pool[poolID].seller != address(0), "the exchange pair does not exist" ); _; } /** * @notice Exchange buyer's ERC20 token to the seller's bond. * @dev Ensure the seller has approved sufficient bonds and * you approve ERC20 token to pay before executing this function. * @param bondID is the target bond ID. * @param poolID is the target pool ID. * @param swapPairAmount is the exchange pair token amount to pay. * @param expectedAmount is the bond amount to receive. * @param range (decimal: 3) */ function exchangeErc20ToBond( bytes32 bondID, bytes32 poolID, uint256 swapPairAmount, uint256 expectedAmount, uint256 range ) external returns (uint256 bondAmount) { bondAmount = _exchangeErc20ToBond( msg.sender, bondID, poolID, swapPairAmount ); // assert(bondAmount != 0); _assertExpectedPriceRange(bondAmount, expectedAmount, range); } /** * @notice Exchange buyer's bond to the seller's ERC20 token. * @dev Ensure the seller has approved sufficient ERC20 token and * you approve bonds to pay before executing this function. * @param bondID is the target bond ID. * @param poolID is the target pool ID. * @param bondAmount is the bond amount to pay. * @param expectedAmount is the exchange pair token amount to receive. * @param range (decimal: 3) */ function exchangeBondToErc20( bytes32 bondID, bytes32 poolID, uint256 bondAmount, uint256 expectedAmount, uint256 range ) external returns (uint256 swapPairAmount) { swapPairAmount = _exchangeBondToErc20( msg.sender, bondID, poolID, bondAmount ); // assert(swapPairAmount != 0); _assertExpectedPriceRange(swapPairAmount, expectedAmount, range); } /** * @notice Returns the exchange rate including spread. */ function calcRateBondToErc20(bytes32 bondID, bytes32 poolID) external returns (uint256 rateE8) { (rateE8, , , ) = _calcRateBondToErc20(bondID, poolID); } /** * @notice Returns pool ID generated by the immutable pool settings. */ function generateVsErc20PoolID( address seller, address swapPairAddress, bool isBondSale ) external view returns (bytes32 poolID) { return _generateVsErc20PoolID(seller, swapPairAddress, isBondSale); } /** * @notice Register a new vsErc20Pool. */ function createVsErc20Pool( ERC20 swapPairAddress, LatestPriceOracleInterface swapPairOracleAddress, BondPricerInterface bondPricerAddress, int16 feeBaseE4, bool isBondSale ) external returns (bytes32 poolID) { return _createVsErc20Pool( msg.sender, swapPairAddress, swapPairOracleAddress, bondPricerAddress, feeBaseE4, isBondSale ); } /** * @notice Update the mutable pool settings. */ function updateVsErc20Pool( bytes32 poolID, LatestPriceOracleInterface swapPairOracleAddress, BondPricerInterface bondPricerAddress, int16 feeBaseE4 ) external { require( _vsErc20Pool[poolID].seller == msg.sender, "not the owner of the pool ID" ); _updateVsErc20Pool( poolID, swapPairOracleAddress, bondPricerAddress, feeBaseE4 ); } /** * @notice Delete the pool settings. */ function deleteVsErc20Pool(bytes32 poolID) external { require( _vsErc20Pool[poolID].seller == msg.sender, "not the owner of the pool ID" ); _deleteVsErc20Pool(poolID); } /** * @notice Returns the pool settings. */ function getVsErc20Pool(bytes32 poolID) external view returns ( address seller, ERC20 swapPairAddress, LatestPriceOracleInterface swapPairOracleAddress, BondPricerInterface bondPricerAddress, int16 feeBaseE4, bool isBondSale ) { return _getVsErc20Pool(poolID); } /** * @dev Exchange buyer's ERC20 token to the seller's bond. * Ensure the seller has approved sufficient bonds and * buyer approve ERC20 token to pay before executing this function. * @param buyer is the buyer address. * @param bondID is the target bond ID. * @param poolID is the target pool ID. * @param swapPairAmount is the exchange pair token amount to pay. * @return bondAmount is the received bond amount. */ function _exchangeErc20ToBond( address buyer, bytes32 bondID, bytes32 poolID, uint256 swapPairAmount ) internal returns (uint256 bondAmount) { ( address seller, ERC20 swapPairToken, , , , bool isBondSale ) = _getVsErc20Pool(poolID); require(isBondSale, "This pool is for buying bond"); (ERC20 bondToken, , , ) = _getBond(_bondMakerContract, bondID); require(address(bondToken) != address(0), "the bond is not registered"); uint256 volumeE8; { ( uint256 rateE8, , uint256 swapPairPriceE8, ) = _calcRateBondToErc20(bondID, poolID); require( rateE8 > MIN_EXCHANGE_RATE_E8, "exchange rate is too small" ); require( rateE8 < MAX_EXCHANGE_RATE_E8, "exchange rate is too large" ); uint8 decimalsOfSwapPair = swapPairToken.decimals(); bondAmount = _applyDecimalGap( swapPairAmount, decimalsOfSwapPair, DECIMALS_OF_BOND + 8 ) / rateE8; require(bondAmount != 0, "must transfer non-zero bond amount"); volumeE8 = swapPairPriceE8.mul(swapPairAmount).div( 10**uint256(decimalsOfSwapPair) ); } require( bondToken.transferFrom(seller, buyer, bondAmount), "fail to transfer bonds" ); swapPairToken.safeTransferFrom(buyer, seller, swapPairAmount); emit LogExchangeErc20ToBond( buyer, bondID, poolID, bondAmount, swapPairAmount, volumeE8 ); } /** * @dev Exchange buyer's bond to the seller's ERC20 token. * Ensure the seller has approved sufficient ERC20 token and * buyer approve bonds to pay before executing this function. * @param buyer is the buyer address. * @param bondID is the target bond ID. * @param poolID is the target pool ID. * @param bondAmount is the bond amount to pay. * @return swapPairAmount is the received swap pair token amount. */ function _exchangeBondToErc20( address buyer, bytes32 bondID, bytes32 poolID, uint256 bondAmount ) internal returns (uint256 swapPairAmount) { ( address seller, ERC20 swapPairToken, , , , bool isBondSale ) = _getVsErc20Pool(poolID); require(!isBondSale, "This pool is not for buying bond"); (ERC20 bondToken, , , ) = _getBond(_bondMakerContract, bondID); require(address(bondToken) != address(0), "the bond is not registered"); uint256 volumeE8; { (uint256 rateE8, uint256 bondPriceE8, , ) = _calcRateBondToErc20( bondID, poolID ); require( rateE8 > MIN_EXCHANGE_RATE_E8, "exchange rate is too small" ); require( rateE8 < MAX_EXCHANGE_RATE_E8, "exchange rate is too large" ); uint8 decimalsOfSwapPair = swapPairToken.decimals(); swapPairAmount = _applyDecimalGap( bondAmount.mul(rateE8), DECIMALS_OF_BOND + 8, decimalsOfSwapPair ); require(swapPairAmount != 0, "must transfer non-zero token amount"); volumeE8 = bondPriceE8.mul(bondAmount).div( 10**uint256(DECIMALS_OF_BOND) ); } require( bondToken.transferFrom(buyer, seller, bondAmount), "fail to transfer bonds" ); swapPairToken.safeTransferFrom(seller, buyer, swapPairAmount); emit LogExchangeBondToErc20( buyer, bondID, poolID, bondAmount, swapPairAmount, volumeE8 ); } function _calcRateBondToErc20(bytes32 bondID, bytes32 poolID) internal returns ( uint256 rateE8, uint256 bondPriceE8, uint256 swapPairPriceE8, int256 spreadE8 ) { ( , , LatestPriceOracleInterface erc20Oracle, BondPricerInterface bondPricer, int16 feeBaseE4, bool isBondSale ) = _getVsErc20Pool(poolID); swapPairPriceE8 = _getLatestPrice(erc20Oracle); (bondPriceE8, spreadE8) = _calcBondPriceAndSpread( bondPricer, bondID, feeBaseE4 ); bondPriceE8 = _calcUsdPrice(bondPriceE8); rateE8 = bondPriceE8.mul(10**8).div( swapPairPriceE8, "ERC20 oracle price must be non-zero" ); // `spreadE8` is less than 0.15 * 10**8. if (isBondSale) { rateE8 = rateE8.mul(uint256(10**8 + spreadE8)) / 10**8; } else { rateE8 = rateE8.mul(10**8) / uint256(10**8 + spreadE8); } } function _generateVsErc20PoolID( address seller, address swapPairAddress, bool isBondSale ) internal view returns (bytes32 poolID) { return keccak256( abi.encode( "Bond vs ERC20 exchange", address(this), seller, swapPairAddress, isBondSale ) ); } function _setVsErc20Pool( bytes32 poolID, address seller, ERC20 swapPairToken, LatestPriceOracleInterface swapPairOracle, BondPricerInterface bondPricer, int16 feeBaseE4, bool isBondSale ) internal { require(seller != address(0), "the pool ID already exists"); require( address(swapPairToken) != address(0), "swapPairToken should be non-zero address" ); require( address(swapPairOracle) != address(0), "swapPairOracle should be non-zero address" ); require( address(bondPricer) != address(0), "bondPricer should be non-zero address" ); _vsErc20Pool[poolID] = VsErc20Pool({ seller: seller, swapPairToken: swapPairToken, swapPairOracle: swapPairOracle, bondPricer: bondPricer, feeBaseE4: feeBaseE4, isBondSale: isBondSale }); } function _createVsErc20Pool( address seller, ERC20 swapPairToken, LatestPriceOracleInterface swapPairOracle, BondPricerInterface bondPricer, int16 feeBaseE4, bool isBondSale ) internal returns (bytes32 poolID) { poolID = _generateVsErc20PoolID( seller, address(swapPairToken), isBondSale ); require( _vsErc20Pool[poolID].seller == address(0), "the pool ID already exists" ); { uint256 price = _getLatestPrice(swapPairOracle); require( price != 0, "swapPairOracle has latestPrice() function which returns non-zero value" ); } _setVsErc20Pool( poolID, seller, swapPairToken, swapPairOracle, bondPricer, feeBaseE4, isBondSale ); if (isBondSale) { emit LogCreateErc20ToBondPool( poolID, seller, address(swapPairToken) ); } else { emit LogCreateBondToErc20Pool( poolID, seller, address(swapPairToken) ); } emit LogUpdateVsErc20Pool( poolID, address(swapPairOracle), address(bondPricer), feeBaseE4 ); } function _updateVsErc20Pool( bytes32 poolID, LatestPriceOracleInterface swapPairOracle, BondPricerInterface bondPricer, int16 feeBaseE4 ) internal isExsistentVsErc20Pool(poolID) { ( address seller, ERC20 swapPairToken, , , , bool isBondSale ) = _getVsErc20Pool(poolID); _setVsErc20Pool( poolID, seller, swapPairToken, swapPairOracle, bondPricer, feeBaseE4, isBondSale ); emit LogUpdateVsErc20Pool( poolID, address(swapPairOracle), address(bondPricer), feeBaseE4 ); } function _deleteVsErc20Pool(bytes32 poolID) internal isExsistentVsErc20Pool(poolID) { delete _vsErc20Pool[poolID]; emit LogDeleteVsErc20Pool(poolID); } function _getVsErc20Pool(bytes32 poolID) internal view isExsistentVsErc20Pool(poolID) returns ( address seller, ERC20 swapPairToken, LatestPriceOracleInterface swapPairOracle, BondPricerInterface bondPricer, int16 feeBaseE4, bool isBondSale ) { VsErc20Pool memory exchangePair = _vsErc20Pool[poolID]; seller = exchangePair.seller; swapPairToken = exchangePair.swapPairToken; swapPairOracle = exchangePair.swapPairOracle; bondPricer = exchangePair.bondPricer; feeBaseE4 = exchangePair.feeBaseE4; isBondSale = exchangePair.isBondSale; } } // File: contracts/util/TransferETH.sol pragma solidity 0.6.6; abstract contract TransferETH is TransferETHInterface { receive() external payable override { emit LogTransferETH(msg.sender, address(this), msg.value); } function _hasSufficientBalance(uint256 amount) internal view returns (bool ok) { address thisContract = address(this); return amount <= thisContract.balance; } /** * @notice transfer `amount` ETH to the `recipient` account with emitting log */ function _transferETH( address payable recipient, uint256 amount, string memory errorMessage ) internal { require(_hasSufficientBalance(amount), errorMessage); (bool success, ) = recipient.call{value: amount}(""); // solhint-disable-line avoid-low-level-calls require(success, "transferring Ether failed"); emit LogTransferETH(address(this), recipient, amount); } function _transferETH(address payable recipient, uint256 amount) internal { _transferETH(recipient, amount, "TransferETH: transfer amount exceeds balance"); } } // File: contracts/generalizedDotc/BondVsEthExchange.sol pragma solidity 0.6.6; abstract contract BondVsEthExchange is BondExchange, TransferETH { uint8 internal constant DECIMALS_OF_ETH = 18; struct VsEthPool { address seller; LatestPriceOracleInterface ethOracle; BondPricerInterface bondPricer; int16 feeBaseE4; bool isBondSale; } mapping(bytes32 => VsEthPool) internal _vsEthPool; mapping(address => uint256) internal _depositedEth; event LogCreateEthToBondPool( bytes32 indexed poolID, address indexed seller ); event LogCreateBondToEthPool( bytes32 indexed poolID, address indexed seller ); event LogUpdateVsEthPool( bytes32 indexed poolID, address ethOracleAddress, address bondPricerAddress, int16 feeBase // decimal: 4 ); event LogDeleteVsEthPool(bytes32 indexed poolID); event LogExchangeEthToBond( address indexed buyer, bytes32 indexed bondID, bytes32 indexed poolID, uint256 bondAmount, // decimal: 8 uint256 swapPairAmount, // decimal: 18 uint256 volume // USD, decimal: 8 ); event LogExchangeBondToEth( address indexed buyer, bytes32 indexed bondID, bytes32 indexed poolID, uint256 bondAmount, // decimal: 8 uint256 swapPairAmount, // decimal: 18 uint256 volume // USD, decimal: 8 ); /** * @dev Reverts when the pool ID does not exist. */ modifier isExsistentVsEthPool(bytes32 poolID) { require( _vsEthPool[poolID].seller != address(0), "the exchange pair does not exist" ); _; } /** * @notice Exchange buyer's ETH to the seller's bond. * @dev Ensure the seller has approved sufficient bonds and * you deposit ETH to pay before executing this function. * @param bondID is the target bond ID. * @param poolID is the target pool ID. * @param ethAmount is the exchange pair token amount to pay. * @param expectedAmount is the bond amount to receive. * @param range (decimal: 3) */ function exchangeEthToBond( bytes32 bondID, bytes32 poolID, uint256 ethAmount, uint256 expectedAmount, uint256 range ) external returns (uint256 bondAmount) { bondAmount = _exchangeEthToBond(msg.sender, bondID, poolID, ethAmount); // assert(bondAmount != 0); _assertExpectedPriceRange(bondAmount, expectedAmount, range); } /** * @notice Exchange buyer's bond to the seller's ETH. * @dev Ensure the seller has deposited sufficient ETH and * you approve bonds to pay before executing this function. * @param bondID is the target bond ID. * @param poolID is the target pool ID. * @param bondAmount is the bond amount to pay. * @param expectedAmount is the ETH amount to receive. * @param range (decimal: 3) */ function exchangeBondToEth( bytes32 bondID, bytes32 poolID, uint256 bondAmount, uint256 expectedAmount, uint256 range ) external returns (uint256 ethAmount) { ethAmount = _exchangeBondToEth(msg.sender, bondID, poolID, bondAmount); // assert(ethAmount != 0); _assertExpectedPriceRange(ethAmount, expectedAmount, range); } /** * @notice Returns the exchange rate including spread. */ function calcRateBondToEth(bytes32 bondID, bytes32 poolID) external returns (uint256 rateE8) { (rateE8, , , ) = _calcRateBondToEth(bondID, poolID); } /** * @notice Returns pool ID generated by the immutable pool settings. */ function generateVsEthPoolID(address seller, bool isBondSale) external view returns (bytes32 poolID) { return _generateVsEthPoolID(seller, isBondSale); } /** * @notice Register a new vsEthPool. */ function createVsEthPool( LatestPriceOracleInterface ethOracleAddress, BondPricerInterface bondPricerAddress, int16 feeBaseE4, bool isBondSale ) external returns (bytes32 poolID) { return _createVsEthPool( msg.sender, ethOracleAddress, bondPricerAddress, feeBaseE4, isBondSale ); } /** * @notice Update the mutable pool settings. */ function updateVsEthPool( bytes32 poolID, LatestPriceOracleInterface ethOracleAddress, BondPricerInterface bondPricerAddress, int16 feeBaseE4 ) external { require( _vsEthPool[poolID].seller == msg.sender, "not the owner of the pool ID" ); _updateVsEthPool( poolID, ethOracleAddress, bondPricerAddress, feeBaseE4 ); } /** * @notice Delete the pool settings. */ function deleteVsEthPool(bytes32 poolID) external { require( _vsEthPool[poolID].seller == msg.sender, "not the owner of the pool ID" ); _deleteVsEthPool(poolID); } /** * @notice Returns the pool settings. */ function getVsEthPool(bytes32 poolID) external view returns ( address seller, LatestPriceOracleInterface ethOracleAddress, BondPricerInterface bondPricerAddress, int16 feeBaseE4, bool isBondSale ) { return _getVsEthPool(poolID); } /** * @notice Transfer ETH to this contract and allow this contract to pay ETH when exchanging. */ function depositEth() external payable { _addEthAllowance(msg.sender, msg.value); } /** * @notice Withdraw all deposited ETH. */ function withdrawEth() external returns (uint256 amount) { amount = _depositedEth[msg.sender]; _transferEthFrom(msg.sender, msg.sender, amount); } /** * @notice Returns deposited ETH amount. */ function ethAllowance(address owner) external view returns (uint256 amount) { amount = _depositedEth[owner]; } /** * @dev Exchange buyer's ETH to the seller's bond. * Ensure the seller has approved sufficient bonds and * buyer deposit ETH to pay before executing this function. * @param buyer is the buyer address. * @param bondID is the target bond ID. * @param poolID is the target pool ID. * @param swapPairAmount is the exchange pair token amount to pay. * @return bondAmount is the received bond amount. */ function _exchangeEthToBond( address buyer, bytes32 bondID, bytes32 poolID, uint256 swapPairAmount ) internal returns (uint256 bondAmount) { (address seller, , , , bool isBondSale) = _getVsEthPool(poolID); require(isBondSale, "This pool is for buying bond"); (ERC20 bondToken, , , ) = _getBond(_bondMakerContract, bondID); require(address(bondToken) != address(0), "the bond is not registered"); uint256 volumeE8; { (uint256 rateE8, , uint256 swapPairPriceE8, ) = _calcRateBondToEth( bondID, poolID ); require( rateE8 > MIN_EXCHANGE_RATE_E8, "exchange rate is too small" ); require( rateE8 < MAX_EXCHANGE_RATE_E8, "exchange rate is too large" ); bondAmount = _applyDecimalGap( swapPairAmount, DECIMALS_OF_ETH, DECIMALS_OF_BOND + 8 ) / rateE8; require(bondAmount != 0, "must transfer non-zero bond amount"); volumeE8 = swapPairPriceE8.mul(swapPairAmount).div( 10**uint256(DECIMALS_OF_ETH) ); } require( bondToken.transferFrom(seller, buyer, bondAmount), "fail to transfer bonds" ); _transferEthFrom(buyer, seller, swapPairAmount); emit LogExchangeEthToBond( buyer, bondID, poolID, bondAmount, swapPairAmount, volumeE8 ); } /** * @dev Exchange buyer's bond to the seller's ETH. * Ensure the seller has deposited sufficient ETH and * buyer approve bonds to pay before executing this function. * @param buyer is the buyer address. * @param bondID is the target bond ID. * @param poolID is the target pool ID. * @param bondAmount is the bond amount to pay. * @return swapPairAmount is the received ETH amount. */ function _exchangeBondToEth( address buyer, bytes32 bondID, bytes32 poolID, uint256 bondAmount ) internal returns (uint256 swapPairAmount) { (address seller, , , , bool isBondSale) = _getVsEthPool(poolID); require(!isBondSale, "This pool is not for buying bond"); (ERC20 bondToken, , , ) = _getBond(_bondMakerContract, bondID); require(address(bondToken) != address(0), "the bond is not registered"); uint256 volumeE8; { (uint256 rateE8, uint256 bondPriceE8, , ) = _calcRateBondToEth( bondID, poolID ); require( rateE8 > MIN_EXCHANGE_RATE_E8, "exchange rate is too small" ); require( rateE8 < MAX_EXCHANGE_RATE_E8, "exchange rate is too large" ); swapPairAmount = _applyDecimalGap( bondAmount.mul(rateE8), DECIMALS_OF_BOND + 8, DECIMALS_OF_ETH ); require(swapPairAmount != 0, "must transfer non-zero token amount"); volumeE8 = bondPriceE8.mul(bondAmount).div( 10**uint256(DECIMALS_OF_BOND) ); } require( bondToken.transferFrom(buyer, seller, bondAmount), "fail to transfer bonds" ); _transferEthFrom(seller, buyer, swapPairAmount); emit LogExchangeBondToEth( buyer, bondID, poolID, bondAmount, swapPairAmount, volumeE8 ); } function _calcRateBondToEth(bytes32 bondID, bytes32 poolID) internal returns ( uint256 rateE8, uint256 bondPriceE8, uint256 swapPairPriceE8, int256 spreadE8 ) { ( , LatestPriceOracleInterface ethOracle, BondPricerInterface bondPricer, int16 feeBaseE4, bool isBondSale ) = _getVsEthPool(poolID); swapPairPriceE8 = _getLatestPrice(ethOracle); (bondPriceE8, spreadE8) = _calcBondPriceAndSpread( bondPricer, bondID, feeBaseE4 ); bondPriceE8 = _calcUsdPrice(bondPriceE8); rateE8 = bondPriceE8.mul(10**8).div( swapPairPriceE8, "ERC20 oracle price must be non-zero" ); // `spreadE8` is less than 0.15 * 10**8. if (isBondSale) { rateE8 = rateE8.mul(uint256(10**8 + spreadE8)) / 10**8; } else { rateE8 = rateE8.mul(uint256(10**8 - spreadE8)) / 10**8; } } function _generateVsEthPoolID(address seller, bool isBondSale) internal view returns (bytes32 poolID) { return keccak256( abi.encode( "Bond vs ETH exchange", address(this), seller, isBondSale ) ); } function _setVsEthPool( bytes32 poolID, address seller, LatestPriceOracleInterface ethOracle, BondPricerInterface bondPricer, int16 feeBaseE4, bool isBondSale ) internal { require(seller != address(0), "the pool ID already exists"); require( address(ethOracle) != address(0), "ethOracle should be non-zero address" ); require( address(bondPricer) != address(0), "bondPricer should be non-zero address" ); _vsEthPool[poolID] = VsEthPool({ seller: seller, ethOracle: ethOracle, bondPricer: bondPricer, feeBaseE4: feeBaseE4, isBondSale: isBondSale }); } function _createVsEthPool( address seller, LatestPriceOracleInterface ethOracle, BondPricerInterface bondPricer, int16 feeBaseE4, bool isBondSale ) internal returns (bytes32 poolID) { poolID = _generateVsEthPoolID(seller, isBondSale); require( _vsEthPool[poolID].seller == address(0), "the pool ID already exists" ); { uint256 price = ethOracle.latestPrice(); require( price != 0, "ethOracle has latestPrice() function which returns non-zero value" ); } _setVsEthPool( poolID, seller, ethOracle, bondPricer, feeBaseE4, isBondSale ); if (isBondSale) { emit LogCreateEthToBondPool(poolID, seller); } else { emit LogCreateBondToEthPool(poolID, seller); } emit LogUpdateVsEthPool( poolID, address(ethOracle), address(bondPricer), feeBaseE4 ); } function _updateVsEthPool( bytes32 poolID, LatestPriceOracleInterface ethOracle, BondPricerInterface bondPricer, int16 feeBaseE4 ) internal isExsistentVsEthPool(poolID) { (address seller, , , , bool isBondSale) = _getVsEthPool(poolID); _setVsEthPool( poolID, seller, ethOracle, bondPricer, feeBaseE4, isBondSale ); emit LogUpdateVsEthPool( poolID, address(ethOracle), address(bondPricer), feeBaseE4 ); } function _deleteVsEthPool(bytes32 poolID) internal isExsistentVsEthPool(poolID) { delete _vsEthPool[poolID]; emit LogDeleteVsEthPool(poolID); } function _getVsEthPool(bytes32 poolID) internal view isExsistentVsEthPool(poolID) returns ( address seller, LatestPriceOracleInterface ethOracle, BondPricerInterface bondPricer, int16 feeBaseE4, bool isBondSale ) { VsEthPool memory exchangePair = _vsEthPool[poolID]; seller = exchangePair.seller; ethOracle = exchangePair.ethOracle; bondPricer = exchangePair.bondPricer; feeBaseE4 = exchangePair.feeBaseE4; isBondSale = exchangePair.isBondSale; } function _transferEthFrom( address sender, address recipient, uint256 amount ) internal { _subEthAllowance(sender, amount); _transferETH(payable(recipient), amount); } function _addEthAllowance(address sender, uint256 amount) internal { _depositedEth[sender] += amount; require(_depositedEth[sender] >= amount, "overflow allowance"); } function _subEthAllowance(address owner, uint256 amount) internal { require(_depositedEth[owner] >= amount, "insufficient allowance"); _depositedEth[owner] -= amount; } } // File: contracts/generalizedDotc/BondVsBondExchange.sol pragma solidity 0.6.6; abstract contract BondVsBondExchange is BondExchange { /** * @dev the sum of decimalsOfBond and decimalsOfOraclePrice of the bondMaker. * This value is constant by the restriction of `_assertBondMakerDecimals`. */ uint8 internal constant DECIMALS_OF_BOND_VALUE = DECIMALS_OF_BOND + DECIMALS_OF_ORACLE_PRICE; struct VsBondPool { address seller; BondMakerInterface bondMakerForUser; VolatilityOracleInterface volatilityOracle; BondPricerInterface bondPricerForUser; BondPricerInterface bondPricer; int16 feeBaseE4; } mapping(bytes32 => VsBondPool) internal _vsBondPool; event LogCreateBondToBondPool( bytes32 indexed poolID, address indexed seller, address indexed bondMakerForUser ); event LogUpdateVsBondPool( bytes32 indexed poolID, address bondPricerForUser, address bondPricer, int16 feeBase // decimal: 4 ); event LogDeleteVsBondPool(bytes32 indexed poolID); event LogExchangeBondToBond( address indexed buyer, bytes32 indexed bondID, bytes32 indexed poolID, uint256 bondAmount, // decimal: 8 uint256 swapPairAmount, // USD, decimal: 8 uint256 volume // USD, decimal: 8 ); /** * @dev Reverts when the pool ID does not exist. */ modifier isExsistentVsBondPool(bytes32 poolID) { require( _vsBondPool[poolID].seller != address(0), "the exchange pair does not exist" ); _; } /** * @notice Exchange the seller's bond to buyer's multiple bonds. * @dev Ensure the seller has approved sufficient bonds and * Approve bonds to pay before executing this function. * @param bondID is the target bond ID. * @param poolID is the target pool ID. * @param amountInDollarsE8 is the exchange pair token amount to pay. (decimals: 8) * @param expectedAmount is the bond amount to receive. (decimals: 8) * @param range (decimal: 3) */ function exchangeBondToBond( bytes32 bondID, bytes32 poolID, bytes32[] calldata bondIDs, uint256 amountInDollarsE8, uint256 expectedAmount, uint256 range ) external returns (uint256 bondAmount) { uint256 amountInDollars = _applyDecimalGap( amountInDollarsE8, 8, DECIMALS_OF_BOND_VALUE ); bondAmount = _exchangeBondToBond( msg.sender, bondID, poolID, bondIDs, amountInDollars ); _assertExpectedPriceRange(bondAmount, expectedAmount, range); } /** * @notice Returns the exchange rate including spread. */ function calcRateBondToUsd(bytes32 bondID, bytes32 poolID) external returns (uint256 rateE8) { (rateE8, , , ) = _calcRateBondToUsd(bondID, poolID); } /** * @notice Returns pool ID generated by the immutable pool settings. */ function generateVsBondPoolID(address seller, address bondMakerForUser) external view returns (bytes32 poolID) { return _generateVsBondPoolID(seller, bondMakerForUser); } /** * @notice Register a new vsBondPool. */ function createVsBondPool( BondMakerInterface bondMakerForUserAddress, VolatilityOracleInterface volatilityOracleAddress, BondPricerInterface bondPricerForUserAddress, BondPricerInterface bondPricerAddress, int16 feeBaseE4 ) external returns (bytes32 poolID) { return _createVsBondPool( msg.sender, bondMakerForUserAddress, volatilityOracleAddress, bondPricerForUserAddress, bondPricerAddress, feeBaseE4 ); } /** * @notice Update the mutable pool settings. */ function updateVsBondPool( bytes32 poolID, VolatilityOracleInterface volatilityOracleAddress, BondPricerInterface bondPricerForUserAddress, BondPricerInterface bondPricerAddress, int16 feeBaseE4 ) external { require( _vsBondPool[poolID].seller == msg.sender, "not the owner of the pool ID" ); _updateVsBondPool( poolID, volatilityOracleAddress, bondPricerForUserAddress, bondPricerAddress, feeBaseE4 ); } /** * @notice Delete the pool settings. */ function deleteVsBondPool(bytes32 poolID) external { require( _vsBondPool[poolID].seller == msg.sender, "not the owner of the pool ID" ); _deleteVsBondPool(poolID); } /** * @notice Returns the pool settings. */ function getVsBondPool(bytes32 poolID) external view returns ( address seller, BondMakerInterface bondMakerForUserAddress, VolatilityOracleInterface volatilityOracle, BondPricerInterface bondPricerForUserAddress, BondPricerInterface bondPricerAddress, int16 feeBaseE4, bool isBondSale ) { return _getVsBondPool(poolID); } /** * @notice Returns the total approved bond amount in U.S. dollars. * Unnecessary bond must not be included in bondIDs. */ function totalBondAllowance( bytes32 poolID, bytes32[] calldata bondIDs, uint256 maturityBorder, address owner ) external returns (uint256 allowanceInDollarsE8) { ( , BondMakerInterface bondMakerForUser, VolatilityOracleInterface volatilityOracle, BondPricerInterface bondPricerForUser, , , ) = _getVsBondPool(poolID); uint256 allowanceInDollars = _totalBondAllowance( bondMakerForUser, volatilityOracle, bondPricerForUser, bondIDs, maturityBorder, owner ); allowanceInDollarsE8 = _applyDecimalGap( allowanceInDollars, DECIMALS_OF_BOND_VALUE, 8 ); } /** * @dev Exchange the seller's bond to buyer's multiple bonds. * Ensure the seller has approved sufficient bonds and * buyer approve bonds to pay before executing this function. * @param buyer is the buyer address. * @param bondID is the target bond ID. * @param poolID is the target pool ID. * @param amountInDollars is the exchange pair token amount to pay. (decimals: 16) * @return bondAmount is the received bond amount. */ function _exchangeBondToBond( address buyer, bytes32 bondID, bytes32 poolID, bytes32[] memory bondIDs, uint256 amountInDollars ) internal returns (uint256 bondAmount) { require(bondIDs.length != 0, "must input bonds for payment"); BondMakerInterface bondMakerForUser; { bool isBondSale; (, bondMakerForUser, , , , , isBondSale) = _getVsBondPool(poolID); require(isBondSale, "This pool is for buying bond"); } (ERC20 bondToken, uint256 maturity, , ) = _getBond( _bondMakerContract, bondID ); require(address(bondToken) != address(0), "the bond is not registered"); { (uint256 rateE8, , , ) = _calcRateBondToUsd(bondID, poolID); require( rateE8 > MIN_EXCHANGE_RATE_E8, "exchange rate is too small" ); require( rateE8 < MAX_EXCHANGE_RATE_E8, "exchange rate is too large" ); bondAmount = _applyDecimalGap( amountInDollars, DECIMALS_OF_BOND_VALUE, bondToken.decimals() + 8 ) / rateE8; require(bondAmount != 0, "must transfer non-zero bond amount"); } { ( address seller, , VolatilityOracleInterface volatilityOracle, BondPricerInterface bondPricerForUser, , , ) = _getVsBondPool(poolID); require( bondToken.transferFrom(seller, buyer, bondAmount), "fail to transfer bonds" ); address buyerTmp = buyer; // avoid `stack too deep` error uint256 amountInDollarsTmp = amountInDollars; // avoid `stack too deep` error require( _batchTransferBondFrom( bondMakerForUser, volatilityOracle, bondPricerForUser, bondIDs, maturity, buyerTmp, seller, amountInDollarsTmp ), "fail to transfer ERC20 token" ); } uint256 volumeE8 = _applyDecimalGap( amountInDollars, DECIMALS_OF_BOND_VALUE, 8 ); emit LogExchangeBondToBond( buyer, bondID, poolID, bondAmount, amountInDollars, volumeE8 ); } function _calcRateBondToUsd(bytes32 bondID, bytes32 poolID) internal returns ( uint256 rateE8, uint256 bondPriceE8, uint256 swapPairPriceE8, int256 spreadE8 ) { ( , , , , BondPricerInterface bondPricer, int16 feeBaseE4, ) = _getVsBondPool(poolID); (bondPriceE8, spreadE8) = _calcBondPriceAndSpread( bondPricer, bondID, feeBaseE4 ); bondPriceE8 = _calcUsdPrice(bondPriceE8); swapPairPriceE8 = 10**8; rateE8 = bondPriceE8.mul(uint256(10**8 + spreadE8)) / 10**8; } function _generateVsBondPoolID(address seller, address bondMakerForUser) internal view returns (bytes32 poolID) { return keccak256( abi.encode( "Bond vs SBT exchange", address(this), seller, bondMakerForUser ) ); } function _setVsBondPool( bytes32 poolID, address seller, BondMakerInterface bondMakerForUser, VolatilityOracleInterface volatilityOracle, BondPricerInterface bondPricerForUser, BondPricerInterface bondPricer, int16 feeBaseE4 ) internal { require(seller != address(0), "the pool ID already exists"); require( address(bondMakerForUser) != address(0), "bondMakerForUser should be non-zero address" ); require( address(bondPricerForUser) != address(0), "bondPricerForUser should be non-zero address" ); require( address(bondPricer) != address(0), "bondPricer should be non-zero address" ); _assertBondMakerDecimals(bondMakerForUser); _vsBondPool[poolID] = VsBondPool({ seller: seller, bondMakerForUser: bondMakerForUser, volatilityOracle: volatilityOracle, bondPricerForUser: bondPricerForUser, bondPricer: bondPricer, feeBaseE4: feeBaseE4 }); } function _createVsBondPool( address seller, BondMakerInterface bondMakerForUser, VolatilityOracleInterface volatilityOracle, BondPricerInterface bondPricerForUser, BondPricerInterface bondPricer, int16 feeBaseE4 ) internal returns (bytes32 poolID) { poolID = _generateVsBondPoolID(seller, address(bondMakerForUser)); require( _vsBondPool[poolID].seller == address(0), "the pool ID already exists" ); _assertBondMakerDecimals(bondMakerForUser); _setVsBondPool( poolID, seller, bondMakerForUser, volatilityOracle, bondPricerForUser, bondPricer, feeBaseE4 ); emit LogCreateBondToBondPool(poolID, seller, address(bondMakerForUser)); emit LogUpdateVsBondPool( poolID, address(bondPricerForUser), address(bondPricer), feeBaseE4 ); } function _updateVsBondPool( bytes32 poolID, VolatilityOracleInterface volatilityOracle, BondPricerInterface bondPricerForUser, BondPricerInterface bondPricer, int16 feeBaseE4 ) internal isExsistentVsBondPool(poolID) { ( address seller, BondMakerInterface bondMakerForUser, , , , , ) = _getVsBondPool(poolID); _setVsBondPool( poolID, seller, bondMakerForUser, volatilityOracle, bondPricerForUser, bondPricer, feeBaseE4 ); emit LogUpdateVsBondPool( poolID, address(bondPricerForUser), address(bondPricer), feeBaseE4 ); } function _deleteVsBondPool(bytes32 poolID) internal isExsistentVsBondPool(poolID) { delete _vsBondPool[poolID]; emit LogDeleteVsBondPool(poolID); } function _getVsBondPool(bytes32 poolID) internal view isExsistentVsBondPool(poolID) returns ( address seller, BondMakerInterface bondMakerForUser, VolatilityOracleInterface volatilityOracle, BondPricerInterface bondPricerForUser, BondPricerInterface bondPricer, int16 feeBaseE4, bool isBondSale ) { VsBondPool memory exchangePair = _vsBondPool[poolID]; seller = exchangePair.seller; bondMakerForUser = exchangePair.bondMakerForUser; volatilityOracle = exchangePair.volatilityOracle; bondPricerForUser = exchangePair.bondPricerForUser; bondPricer = exchangePair.bondPricer; feeBaseE4 = exchangePair.feeBaseE4; isBondSale = true; } /** * @dev Transfer multiple bonds in one method. * Unnecessary bonds can be included in bondIDs. */ function _batchTransferBondFrom( BondMakerInterface bondMaker, VolatilityOracleInterface volatilityOracle, BondPricerInterface bondPricer, bytes32[] memory bondIDs, uint256 maturityBorder, address sender, address recipient, uint256 amountInDollars ) internal returns (bool ok) { uint256 oraclePriceE8 = _getLatestPrice(bondMaker.oracleAddress()); uint256 rest = amountInDollars; // mutable for (uint256 i = 0; i < bondIDs.length; i++) { ERC20 bond; uint256 oracleVolE8; { uint256 maturity; (bond, maturity, , ) = _getBond(bondMaker, bondIDs[i]); if (maturity > maturityBorder) continue; // skip transaction uint256 untilMaturity = maturity.sub( _getBlockTimestampSec(), "the bond should not have expired" ); oracleVolE8 = _getVolatility( volatilityOracle, untilMaturity.toUint64() ); } uint256 allowance = bond.allowance(sender, address(this)); if (allowance == 0) continue; // skip transaction BondMakerInterface bondMakerTmp = bondMaker; // avoid `stack too deep` error BondPricerInterface bondPricerTmp = bondPricer; // avoid `stack too deep` error bytes32 bondIDTmp = bondIDs[i]; // avoid `stack too deep` error uint256 bondPrice = _calcBondPrice( bondMakerTmp, bondPricerTmp, bondIDTmp, oraclePriceE8, oracleVolE8 ); if (bondPrice == 0) continue; // skip transaction if (rest <= allowance.mul(bondPrice)) { // assert(ceil(rest / bondPrice) <= allowance); return bond.transferFrom( sender, recipient, rest.divRoundUp(bondPrice) ); } require( bond.transferFrom(sender, recipient, allowance), "fail to transfer bonds" ); rest -= allowance * bondPrice; } revert("insufficient bond allowance"); } /** * @dev Returns the total approved bond amount in U.S. dollars. * Unnecessary bond must not be included in bondIDs. */ function _totalBondAllowance( BondMakerInterface bondMaker, VolatilityOracleInterface volatilityOracle, BondPricerInterface bondPricer, bytes32[] memory bondIDs, uint256 maturityBorder, address sender ) internal returns (uint256 allowanceInDollars) { uint256 oraclePriceE8 = _getLatestPrice(bondMaker.oracleAddress()); for (uint256 i = 0; i < bondIDs.length; i++) { ERC20 bond; uint256 oracleVolE8; { uint256 maturity; (bond, maturity, , ) = _getBond(bondMaker, bondIDs[i]); if (maturity > maturityBorder) continue; // skip uint256 untilMaturity = maturity.sub( _getBlockTimestampSec(), "the bond should not have expired" ); oracleVolE8 = _getVolatility( volatilityOracle, untilMaturity.toUint64() ); } uint256 balance = bond.balanceOf(sender); require(balance != 0, "includes no bond balance"); uint256 allowance = bond.allowance(sender, address(this)); require(allowance != 0, "includes no approved bond"); uint256 bondPrice = _calcBondPrice( bondMaker, bondPricer, bondIDs[i], oraclePriceE8, oracleVolE8 ); require(bondPrice != 0, "includes worthless bond"); allowanceInDollars = allowanceInDollars.add( allowance.mul(bondPrice) ); } } /** * @dev Calculate bond price by bond ID. */ function _calcBondPrice( BondMakerInterface bondMaker, BondPricerInterface bondPricer, bytes32 bondID, uint256 oraclePriceE8, uint256 oracleVolatilityE8 ) internal view returns (uint256) { int256 untilMaturity; { (, uint256 maturity, , ) = _getBond(bondMaker, bondID); untilMaturity = maturity .sub( _getBlockTimestampSec(), "the bond should not have expired" ) .toInt256(); } BondType bondType; uint256[] memory points; { bool isKnownBondType; (isKnownBondType, bondType, points) = _bondShapeDetector .getBondTypeByID(bondMaker, bondID, BondType.NONE); if (!isKnownBondType) { revert("unknown bond type"); // return 0; } } try bondPricer.calcPriceAndLeverage( bondType, points, oraclePriceE8.toInt256(), oracleVolatilityE8.toInt256(), untilMaturity ) returns (uint256 bondPriceE8, uint256) { return bondPriceE8; } catch { return 0; } } } // File: contracts/generalizedDotc/GeneralizedDotc.sol pragma solidity 0.6.6; contract GeneralizedDotc is BondVsBondExchange, BondVsErc20Exchange, BondVsEthExchange { constructor( BondMakerInterface bondMakerAddress, VolatilityOracleInterface volatilityOracleAddress, LatestPriceOracleInterface volumeCalculatorAddress, DetectBondShape bondShapeDetector ) public BondExchange( bondMakerAddress, volatilityOracleAddress, volumeCalculatorAddress, bondShapeDetector ) {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract BondMakerInterface","name":"bondMakerAddress","type":"address"},{"internalType":"contract VolatilityOracleInterface","name":"volatilityOracleAddress","type":"address"},{"internalType":"contract LatestPriceOracleInterface","name":"volumeCalculatorAddress","type":"address"},{"internalType":"contract DetectBondShape","name":"bondShapeDetector","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"address","name":"bondMakerForUser","type":"address"}],"name":"LogCreateBondToBondPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"address","name":"swapPairAddress","type":"address"}],"name":"LogCreateBondToErc20Pool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":true,"internalType":"address","name":"seller","type":"address"}],"name":"LogCreateBondToEthPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"address","name":"swapPairAddress","type":"address"}],"name":"LogCreateErc20ToBondPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":true,"internalType":"address","name":"seller","type":"address"}],"name":"LogCreateEthToBondPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"}],"name":"LogDeleteVsBondPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"}],"name":"LogDeleteVsErc20Pool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"}],"name":"LogDeleteVsEthPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"bondID","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"bondAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"swapPairAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"volume","type":"uint256"}],"name":"LogExchangeBondToBond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"bondID","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"bondAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"swapPairAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"volume","type":"uint256"}],"name":"LogExchangeBondToErc20","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"bondID","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"bondAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"swapPairAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"volume","type":"uint256"}],"name":"LogExchangeBondToEth","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"bondID","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"bondAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"swapPairAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"volume","type":"uint256"}],"name":"LogExchangeErc20ToBond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"bytes32","name":"bondID","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"bondAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"swapPairAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"volume","type":"uint256"}],"name":"LogExchangeEthToBond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"LogTransferETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":false,"internalType":"address","name":"bondPricerForUser","type":"address"},{"indexed":false,"internalType":"address","name":"bondPricer","type":"address"},{"indexed":false,"internalType":"int16","name":"feeBase","type":"int16"}],"name":"LogUpdateVsBondPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":false,"internalType":"address","name":"swapPairOracleAddress","type":"address"},{"indexed":false,"internalType":"address","name":"bondPricerAddress","type":"address"},{"indexed":false,"internalType":"int16","name":"feeBase","type":"int16"}],"name":"LogUpdateVsErc20Pool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":false,"internalType":"address","name":"ethOracleAddress","type":"address"},{"indexed":false,"internalType":"address","name":"bondPricerAddress","type":"address"},{"indexed":false,"internalType":"int16","name":"feeBase","type":"int16"}],"name":"LogUpdateVsEthPool","type":"event"},{"inputs":[],"name":"bondMakerAddress","outputs":[{"internalType":"contract BondMakerInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"},{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"name":"calcRateBondToErc20","outputs":[{"internalType":"uint256","name":"rateE8","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"},{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"name":"calcRateBondToEth","outputs":[{"internalType":"uint256","name":"rateE8","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"},{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"name":"calcRateBondToUsd","outputs":[{"internalType":"uint256","name":"rateE8","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract BondMakerInterface","name":"bondMakerForUserAddress","type":"address"},{"internalType":"contract VolatilityOracleInterface","name":"volatilityOracleAddress","type":"address"},{"internalType":"contract BondPricerInterface","name":"bondPricerForUserAddress","type":"address"},{"internalType":"contract BondPricerInterface","name":"bondPricerAddress","type":"address"},{"internalType":"int16","name":"feeBaseE4","type":"int16"}],"name":"createVsBondPool","outputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"swapPairAddress","type":"address"},{"internalType":"contract LatestPriceOracleInterface","name":"swapPairOracleAddress","type":"address"},{"internalType":"contract BondPricerInterface","name":"bondPricerAddress","type":"address"},{"internalType":"int16","name":"feeBaseE4","type":"int16"},{"internalType":"bool","name":"isBondSale","type":"bool"}],"name":"createVsErc20Pool","outputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract LatestPriceOracleInterface","name":"ethOracleAddress","type":"address"},{"internalType":"contract BondPricerInterface","name":"bondPricerAddress","type":"address"},{"internalType":"int16","name":"feeBaseE4","type":"int16"},{"internalType":"bool","name":"isBondSale","type":"bool"}],"name":"createVsEthPool","outputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"name":"deleteVsBondPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"name":"deleteVsErc20Pool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"name":"deleteVsEthPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositEth","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ethAllowance","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"},{"internalType":"bytes32","name":"poolID","type":"bytes32"},{"internalType":"bytes32[]","name":"bondIDs","type":"bytes32[]"},{"internalType":"uint256","name":"amountInDollarsE8","type":"uint256"},{"internalType":"uint256","name":"expectedAmount","type":"uint256"},{"internalType":"uint256","name":"range","type":"uint256"}],"name":"exchangeBondToBond","outputs":[{"internalType":"uint256","name":"bondAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"},{"internalType":"bytes32","name":"poolID","type":"bytes32"},{"internalType":"uint256","name":"bondAmount","type":"uint256"},{"internalType":"uint256","name":"expectedAmount","type":"uint256"},{"internalType":"uint256","name":"range","type":"uint256"}],"name":"exchangeBondToErc20","outputs":[{"internalType":"uint256","name":"swapPairAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"},{"internalType":"bytes32","name":"poolID","type":"bytes32"},{"internalType":"uint256","name":"bondAmount","type":"uint256"},{"internalType":"uint256","name":"expectedAmount","type":"uint256"},{"internalType":"uint256","name":"range","type":"uint256"}],"name":"exchangeBondToEth","outputs":[{"internalType":"uint256","name":"ethAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"},{"internalType":"bytes32","name":"poolID","type":"bytes32"},{"internalType":"uint256","name":"swapPairAmount","type":"uint256"},{"internalType":"uint256","name":"expectedAmount","type":"uint256"},{"internalType":"uint256","name":"range","type":"uint256"}],"name":"exchangeErc20ToBond","outputs":[{"internalType":"uint256","name":"bondAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"},{"internalType":"bytes32","name":"poolID","type":"bytes32"},{"internalType":"uint256","name":"ethAmount","type":"uint256"},{"internalType":"uint256","name":"expectedAmount","type":"uint256"},{"internalType":"uint256","name":"range","type":"uint256"}],"name":"exchangeEthToBond","outputs":[{"internalType":"uint256","name":"bondAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"seller","type":"address"},{"internalType":"address","name":"bondMakerForUser","type":"address"}],"name":"generateVsBondPoolID","outputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"seller","type":"address"},{"internalType":"address","name":"swapPairAddress","type":"address"},{"internalType":"bool","name":"isBondSale","type":"bool"}],"name":"generateVsErc20PoolID","outputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"seller","type":"address"},{"internalType":"bool","name":"isBondSale","type":"bool"}],"name":"generateVsEthPoolID","outputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"name":"getVsBondPool","outputs":[{"internalType":"address","name":"seller","type":"address"},{"internalType":"contract BondMakerInterface","name":"bondMakerForUserAddress","type":"address"},{"internalType":"contract VolatilityOracleInterface","name":"volatilityOracle","type":"address"},{"internalType":"contract BondPricerInterface","name":"bondPricerForUserAddress","type":"address"},{"internalType":"contract BondPricerInterface","name":"bondPricerAddress","type":"address"},{"internalType":"int16","name":"feeBaseE4","type":"int16"},{"internalType":"bool","name":"isBondSale","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"name":"getVsErc20Pool","outputs":[{"internalType":"address","name":"seller","type":"address"},{"internalType":"contract ERC20","name":"swapPairAddress","type":"address"},{"internalType":"contract LatestPriceOracleInterface","name":"swapPairOracleAddress","type":"address"},{"internalType":"contract BondPricerInterface","name":"bondPricerAddress","type":"address"},{"internalType":"int16","name":"feeBaseE4","type":"int16"},{"internalType":"bool","name":"isBondSale","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"name":"getVsEthPool","outputs":[{"internalType":"address","name":"seller","type":"address"},{"internalType":"contract LatestPriceOracleInterface","name":"ethOracleAddress","type":"address"},{"internalType":"contract BondPricerInterface","name":"bondPricerAddress","type":"address"},{"internalType":"int16","name":"feeBaseE4","type":"int16"},{"internalType":"bool","name":"isBondSale","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"},{"internalType":"bytes32[]","name":"bondIDs","type":"bytes32[]"},{"internalType":"uint256","name":"maturityBorder","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"totalBondAllowance","outputs":[{"internalType":"uint256","name":"allowanceInDollarsE8","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"},{"internalType":"contract VolatilityOracleInterface","name":"volatilityOracleAddress","type":"address"},{"internalType":"contract BondPricerInterface","name":"bondPricerForUserAddress","type":"address"},{"internalType":"contract BondPricerInterface","name":"bondPricerAddress","type":"address"},{"internalType":"int16","name":"feeBaseE4","type":"int16"}],"name":"updateVsBondPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"},{"internalType":"contract LatestPriceOracleInterface","name":"swapPairOracleAddress","type":"address"},{"internalType":"contract BondPricerInterface","name":"bondPricerAddress","type":"address"},{"internalType":"int16","name":"feeBaseE4","type":"int16"}],"name":"updateVsErc20Pool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"},{"internalType":"contract LatestPriceOracleInterface","name":"ethOracleAddress","type":"address"},{"internalType":"contract BondPricerInterface","name":"bondPricerAddress","type":"address"},{"internalType":"int16","name":"feeBaseE4","type":"int16"}],"name":"updateVsEthPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"volumeCalculatorAddress","outputs":[{"internalType":"contract LatestPriceOracleInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawEth","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6101206040523480156200001257600080fd5b5060405162005f2838038062005f28833981810160405260808110156200003857600080fd5b50805160208201516040830151606090930151919290918383838362000067846001600160e01b036200012216565b836001600160a01b03166080816001600160a01b031660601b81525050836001600160a01b031663a89ae4ba6040518163ffffffff1660e01b815260040160206040518083038186803b158015620000be57600080fd5b505afa158015620000d3573d6000803e3d6000fd5b505050506040513d6020811015620000ea57600080fd5b50516001600160601b0319606091821b811660a05293811b841660c05291821b831660e052901b166101005250620002b59350505050565b600860ff16816001600160a01b031663d0d6153a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200016157600080fd5b505afa15801562000176573d6000803e3d6000fd5b505050506040513d60208110156200018d57600080fd5b505160ff1614620001ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602681526020018062005ede6026913960400191505060405180910390fd5b600860ff16816001600160a01b031663f08e2a336040518163ffffffff1660e01b815260040160206040518083038186803b1580156200022957600080fd5b505afa1580156200023e573d6000803e3d6000fd5b505050506040513d60208110156200025557600080fd5b505160ff1614620002b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018062005f046024913960400191505060405180910390fd5b50565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c615bad6200033160003980613f885280614c9c525080610aa6528061434b5250806141f45250806141c75250806109e952806111055280611ac95280611fb25280612b3a52806133585280613f575280613fb75250615bad6000f3fe6080604052600436106101c65760003560e01c80638a43a1a4116100f7578063ca6aaecb11610095578063dc10d97f11610064578063dc10d97f146108e9578063dcf288771461095d578063e64851201461098d578063faf279ea146109b757610204565b8063ca6aaecb146107c4578063ccb63b7014610809578063d23070c11461085b578063d78f308d146108a757610204565b8063a291bace116100d1578063a291bace14610671578063b6263c421461069b578063bbd114f91461072e578063bd42c7061461077057610204565b80638a43a1a4146105b857806393e492a1146105e2578063a0ef91df1461065c57610204565b8063439370b1116101645780635a6969341161013e5780635a696934146104925780635c4776c4146104d457806361a72d6d1461052057806378f286d91461056257610204565b8063439370b1146103e2578063460522f4146103ec578063488abbfc1461045757610204565b806318c681fd116101a057806318c681fd1461031c5780631b1839ab1461034c578063241d92291461036157806338360dee146103af57610204565b80630b1a3554146102095780630f48fd481461023a57806311ed6077146102e157610204565b3661020457604080513481529051309133917fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9181900360200190a3005b600080fd5b34801561021557600080fd5b5061021e6109e7565b604080516001600160a01b039092168252519081900360200190f35b34801561024657600080fd5b506102cf600480360360c081101561025d57600080fd5b81359160208101359181019060608101604082013564010000000081111561028457600080fd5b82018360208201111561029657600080fd5b803590602001918460208302840111640100000000831117156102b857600080fd5b919350915080359060208101359060400135610a0c565b60408051918252519081900360200190f35b3480156102ed57600080fd5b506102cf6004803603604081101561030457600080fd5b506001600160a01b0381351690602001351515610a78565b34801561032857600080fd5b506102cf6004803603604081101561033f57600080fd5b5080359060200135610a8d565b34801561035857600080fd5b5061021e610aa4565b34801561036d57600080fd5b506102cf6004803603608081101561038457600080fd5b506001600160a01b038135811691602081013590911690604081013560010b90606001351515610ac8565b3480156103bb57600080fd5b506102cf600480360360208110156103d257600080fd5b50356001600160a01b0316610ae0565b6103ea610afb565b005b3480156103f857600080fd5b506104166004803603602081101561040f57600080fd5b5035610b07565b604080516001600160a01b03968716815294861660208601529290941683830152600190810b900b6060830152911515608082015290519081900360a00190f35b34801561046357600080fd5b506102cf6004803603604081101561047a57600080fd5b506001600160a01b0381358116916020013516610b2a565b34801561049e57600080fd5b506102cf600480360360a08110156104b557600080fd5b5080359060208101359060408101359060608101359060800135610b36565b3480156104e057600080fd5b506103ea600480360360808110156104f757600080fd5b508035906001600160a01b0360208201358116916040810135909116906060013560010b610b51565b34801561052c57600080fd5b506102cf600480360360a081101561054357600080fd5b5080359060208101359060408101359060608101359060800135610bce565b34801561056e57600080fd5b506102cf600480360360a081101561058557600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135909116906080013560010b610bdc565b3480156105c457600080fd5b506103ea600480360360208110156105db57600080fd5b5035610bf6565b3480156105ee57600080fd5b5061060c6004803603602081101561060557600080fd5b5035610c6d565b604080516001600160a01b039889168152968816602088015294871686860152928616606086015294166080840152600193840b90930b60a083015291151560c082015290519081900360e00190f35b34801561066857600080fd5b506102cf610c98565b34801561067d57600080fd5b506103ea6004803603602081101561069457600080fd5b5035610cb4565b3480156106a757600080fd5b506102cf600480360360808110156106be57600080fd5b813591908101906040810160208201356401000000008111156106e057600080fd5b8201836020820111156106f257600080fd5b8035906020019184602083028401116401000000008311171561071457600080fd5b9193509150803590602001356001600160a01b0316610d28565b34801561073a57600080fd5b506102cf600480360360a081101561075157600080fd5b5080359060208101359060408101359060608101359060800135610da3565b34801561077c57600080fd5b506102cf600480360360a081101561079357600080fd5b506001600160a01b038135811691602081013582169160408201351690606081013560010b90608001351515610db1565b3480156107d057600080fd5b506102cf600480360360608110156107e757600080fd5b506001600160a01b038135811691602081013590911690604001351515610dc1565b34801561081557600080fd5b506103ea600480360360a081101561082c57600080fd5b508035906001600160a01b0360208201358116916040810135821691606082013516906080013560010b610dd8565b34801561086757600080fd5b506103ea6004803603608081101561087e57600080fd5b508035906001600160a01b0360208201358116916040810135909116906060013560010b610e57565b3480156108b357600080fd5b506102cf600480360360a08110156108ca57600080fd5b5080359060208101359060408101359060608101359060800135610ece565b3480156108f557600080fd5b506109136004803603602081101561090c57600080fd5b5035610edc565b604080516001600160a01b039788168152958716602087015293861685850152919094166060840152600193840b90930b608083015291151560a082015290519081900360c00190f35b34801561096957600080fd5b506102cf6004803603604081101561098057600080fd5b5080359060200135610f02565b34801561099957600080fd5b506103ea600480360360208110156109b057600080fd5b5035610f0e565b3480156109c357600080fd5b506102cf600480360360408110156109da57600080fd5b5080359060200135610f82565b7f00000000000000000000000000000000000000000000000000000000000000005b90565b600080610a1c8560086010610f8e565b9050610a5f338a8a8a8a80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250889250611038915050565b9150610a6c8285856114f0565b50979650505050505050565b6000610a848383611567565b90505b92915050565b6000610a9983836115e1565b509195945050505050565b7f000000000000000000000000000000000000000000000000000000000000000090565b6000610ad73386868686611646565b95945050505050565b6001600160a01b031660009081526003602052604090205490565b610b053334611848565b565b6000806000806000610b18866118c0565b939a9299509097509550909350915050565b6000610a8483836119de565b6000610b4433878787611a58565b9050610ad78184846114f0565b6000848152600260205260409020546001600160a01b03163314610bbc576040805162461bcd60e51b815260206004820152601c60248201527f6e6f7420746865206f776e6572206f662074686520706f6f6c20494400000000604482015290519081900360640190fd5b610bc884848484611e5d565b50505050565b6000610b4433878787611f44565b6000610bec3387878787876122c9565b9695505050505050565b6000818152600260205260409020546001600160a01b03163314610c61576040805162461bcd60e51b815260206004820152601c60248201527f6e6f7420746865206f776e6572206f662074686520706f6f6c20494400000000604482015290519081900360640190fd5b610c6a816123f7565b50565b6000806000806000806000610c81886124f9565b959e949d50929b5090995097509550909350915050565b3360008181526003602052604090205490610a09908083612614565b6000818152600160205260409020546001600160a01b03163314610d1f576040805162461bcd60e51b815260206004820152601c60248201527f6e6f7420746865206f776e6572206f662074686520706f6f6c20494400000000604482015290519081900360640190fd5b610c6a81612628565b600080600080610d37896124f9565b505050935093509350506000610d868484848c8c808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508e92508d91506127369050565b9050610d958160106008610f8e565b9a9950505050505050505050565b6000610b4433878787612ac8565b6000610bec338787878787612ed2565b6000610dce84848461308f565b90505b9392505050565b6000858152602081905260409020546001600160a01b03163314610e43576040805162461bcd60e51b815260206004820152601c60248201527f6e6f7420746865206f776e6572206f662074686520706f6f6c20494400000000604482015290519081900360640190fd5b610e508585858585613111565b5050505050565b6000848152600160205260409020546001600160a01b03163314610ec2576040805162461bcd60e51b815260206004820152601c60248201527f6e6f7420746865206f776e6572206f662074686520706f6f6c20494400000000604482015290519081900360640190fd5b610bc8848484846131fc565b6000610b44338787876132e9565b600080600080600080610eee87613671565b949c939b5091995097509550909350915050565b6000610a9983836137a1565b6000818152602081905260409020546001600160a01b03163314610f79576040805162461bcd60e51b815260206004820152601c60248201527f6e6f7420746865206f776e6572206f662074686520706f6f6c20494400000000604482015290519081900360640190fd5b610c6a81613888565b6000610a99838361399c565b60008060008360ff168560ff161115610fad575060ff83850316610fc4565b8360ff168560ff161015610fc45784840360ff1691505b601382108015610fd45750601381105b61100f5760405162461bcd60e51b81526004018080602001828103825260258152602001806158466025913960400191505060405180910390fd5b610bec81600a0a61102c84600a0a89613a4790919063ffffffff16565b9063ffffffff613aa016565b6000825160001415611091576040805162461bcd60e51b815260206004820152601c60248201527f6d75737420696e70757420626f6e647320666f72207061796d656e7400000000604482015290519081900360640190fd5b60008061109d866124f9565b9497509395508594506110fc9350505050576040805162461bcd60e51b815260206004820152601c60248201527f5468697320706f6f6c20697320666f7220627579696e6720626f6e6400000000604482015290519081900360640190fd5b5060008061112a7f000000000000000000000000000000000000000000000000000000000000000089613ae2565b509193509150506001600160a01b03821661118c576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b600061119889896115e1565b5050509050606481116111f2576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f20736d616c6c000000000000604482015290519081900360640190fd5b655af3107a4000811061124c576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f206c61726765000000000000604482015290519081900360640190fd5b806112c28760088001866001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561128e57600080fd5b505afa1580156112a2573d6000803e3d6000fd5b505050506040513d60208110156112b857600080fd5b5051600801610f8e565b816112c957fe5b049450846113085760405162461bcd60e51b8152600401808060200182810382526022815260200180615b2a6022913960400191505060405180910390fd5b5060008060006113178a6124f9565b50505093509350509250846001600160a01b03166323b872dd848e8a6040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b15801561139b57600080fd5b505af11580156113af573d6000803e3d6000fd5b505050506040513d60208110156113c557600080fd5b5051611418576040805162461bcd60e51b815260206004820152601660248201527f6661696c20746f207472616e7366657220626f6e647300000000000000000000604482015290519081900360640190fd5b8b8861142a8885858e8a878b88613b87565b61147b576040805162461bcd60e51b815260206004820152601c60248201527f6661696c20746f207472616e7366657220455243323020746f6b656e00000000604482015290519081900360640190fd5b5050505050600061149186600880016008610f8e565b6040805187815260208101899052808201839052905191925089918b916001600160a01b038e16917fd993461e2ed05e160d9d91ad5dddc245e8fd8606ef3b59a6a4544a6b5f438b609181900360600190a45050505095945050505050565b8115611562578161150f6103e861102c8685830163ffffffff613a4716565b1015611562576040805162461bcd60e51b815260206004820152601b60248201527f6f7574206f662065787065637465642070726963652072616e67650000000000604482015290519081900360640190fd5b505050565b6040805130818301526001600160a01b03939093166060840152901515608080840191909152602080840191909152601460a08401527f426f6e64207673204554482065786368616e676500000000000000000000000060c0808501919091528251808503909101815260e0909301909152815191012090565b6000806000806000806115f3876124f9565b509550955050505050611607828983613f4d565b90955092506116158561433c565b94506305f5e1009350836116318685830163ffffffff613a4716565b8161163857fe5b049550505092959194509250565b60006116528683611567565b6000818152600260205260409020549091506001600160a01b0316156116bf576040805162461bcd60e51b815260206004820152601a60248201527f74686520706f6f6c20494420616c726561647920657869737473000000000000604482015290519081900360640190fd5b6000856001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156116fc57600080fd5b505af1158015611710573d6000803e3d6000fd5b505050506040513d602081101561172657600080fd5b50519050806117665760405162461bcd60e51b8152600401808060200182810382526041815260200180615a4c6041913960600191505060405180910390fd5b5061177581878787878761438a565b81156117b6576040516001600160a01b0387169082907fff21af9ef13c15bda11c8778f12d707fc45e46295475a179bfc6edaa8302cc4290600090a36117ed565b6040516001600160a01b0387169082907f7830c5d14d54770e26085fb8c75218966810a41f896d2e81a59ad6e5fd358a7390600090a35b604080516001600160a01b03808816825286166020820152600185810b900b81830152905182917fa45c688b2c8530361470c35643e00bb252b627c331f3f04491631591ac20ffe3919081900360600190a295945050505050565b6001600160a01b038216600090815260036020526040902080548201908190558111156118bc576040805162461bcd60e51b815260206004820152601260248201527f6f766572666c6f7720616c6c6f77616e63650000000000000000000000000000604482015290519081900360640190fd5b5050565b600081815260026020526040812054819081908190819086906001600160a01b0316611933576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b61193b6157b7565b5050506000948552505060026020818152604094859020855160a08101875281546001600160a01b0390811680835260018085015483169584018690529390950154908116978201889052740100000000000000000000000000000000000000008104830b830b90920b6060820181905276010000000000000000000000000000000000000000000090920460ff16151560809091018190529296919594509250565b6040805130818301526001600160a01b03938416606082015291909216608080830191909152602080830191909152601460a08301527f426f6e64207673205342542065786368616e676500000000000000000000000060c0808401919091528351808403909101815260e0909201909252805191012090565b600080600080611a6786613671565b95505050509250925080611ac2576040805162461bcd60e51b815260206004820152601c60248201527f5468697320706f6f6c20697320666f7220627579696e6720626f6e6400000000604482015290519081900360640190fd5b6000611aee7f000000000000000000000000000000000000000000000000000000000000000089613ae2565b5091925050506001600160a01b038116611b4f576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b6000806000611b5e8b8b6137a1565b50925050915060648211611bb9576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f20736d616c6c000000000000604482015290519081900360640190fd5b655af3107a40008210611c13576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f206c61726765000000000000604482015290519081900360640190fd5b6000866001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015611c4e57600080fd5b505afa158015611c62573d6000803e3d6000fd5b505050506040513d6020811015611c7857600080fd5b5051905082611c898b836010610f8e565b81611c9057fe5b04985088611ccf5760405162461bcd60e51b8152600401808060200182810382526022815260200180615b2a6022913960400191505060405180910390fd5b611ce960ff8216600a0a61102c848d63ffffffff613a4716565b9350505050816001600160a01b03166323b872dd868c896040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015611d6857600080fd5b505af1158015611d7c573d6000803e3d6000fd5b505050506040513d6020811015611d9257600080fd5b5051611de5576040805162461bcd60e51b815260206004820152601660248201527f6661696c20746f207472616e7366657220626f6e647300000000000000000000604482015290519081900360640190fd5b611e006001600160a01b0385168b878a63ffffffff6145a216565b6040805187815260208101899052808201839052905189918b916001600160a01b038e16917ff200e0baecbcae9dad1b97ab97511a8c8aeee481b3bf835ce0157bba421ce320919081900360600190a45050505050949350505050565b60008481526002602052604090205484906001600160a01b0316611ec8576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b600080611ed4876118c0565b94505050509150611ee987838888888661438a565b604080516001600160a01b03808916825287166020820152600186810b900b81830152905188917fa45c688b2c8530361470c35643e00bb252b627c331f3f04491631591ac20ffe3919081900360600190a250505050505050565b6000806000611f52856118c0565b9450505050915080611fab576040805162461bcd60e51b815260206004820152601c60248201527f5468697320706f6f6c20697320666f7220627579696e6720626f6e6400000000604482015290519081900360640190fd5b6000611fd77f000000000000000000000000000000000000000000000000000000000000000088613ae2565b5091925050506001600160a01b038116612038576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b60008060006120478a8a61399c565b509250509150606482116120a2576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f20736d616c6c000000000000604482015290519081900360640190fd5b655af3107a400082106120fc576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f206c61726765000000000000604482015290519081900360640190fd5b8161210a8960126010610f8e565b8161211157fe5b049650866121505760405162461bcd60e51b8152600401808060200182810382526022815260200180615b2a6022913960400191505060405180910390fd5b61216c670de0b6b3a764000061102c838b63ffffffff613a4716565b604080517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b0389811660048301528e81166024830152604482018b9052915192955090861693506323b872dd92506064808201926020929091908290030181600087803b1580156121e557600080fd5b505af11580156121f9573d6000803e3d6000fd5b505050506040513d602081101561220f57600080fd5b5051612262576040805162461bcd60e51b815260206004820152601660248201527f6661696c20746f207472616e7366657220626f6e647300000000000000000000604482015290519081900360640190fd5b61226d898588612614565b6040805186815260208101889052808201839052905188918a916001600160a01b038d16917fcc3d7a17c2ae4f2fdf5afc9e62cfb5860e4c8f4d86c9e02602223f4eebdf9637919081900360600190a450505050949350505050565b60006122d587876119de565b6000818152602081905260409020549091506001600160a01b031615612342576040805162461bcd60e51b815260206004820152601a60248201527f74686520706f6f6c20494420616c726561647920657869737473000000000000604482015290519081900360640190fd5b61234b8661462a565b61235a8188888888888861477c565b856001600160a01b0316876001600160a01b0316827fc123eddaddec0f57780eb14c17886c4931a5304c25284c9a4ca8de01dc33d50360405160405180910390a4604080516001600160a01b03808716825285166020820152600184810b900b81830152905182917fcc1c455a31b9815a3e0c1a2fcd096b2cccc50534bdc41a4c1dbdd3fb4b3c5afb919081900360600190a29695505050505050565b60008181526002602052604090205481906001600160a01b0316612462576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b600082815260026020819052604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168255600182018054909116905590910180547fffffffffffffffffff00000000000000000000000000000000000000000000001690555183917fba8b1b1bd3050c32112db02c33208fcc66f00fc4b1ac205e4306ff362757ca3091a25050565b60008181526020819052604081205481908190819081908190819088906001600160a01b0316612570576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b6125786157e5565b50505060009687525050506020848152604094859020855160c08101875281546001600160a01b039081168083526001808501548316958401869052600285015483169984018a905260038501548316606085018190526004909501549283166080850181905274010000000000000000000000000000000000000000909304810b810b810b60a0909401849052909994989750929550935091565b61261e83826149c9565b6115628282614a59565b60008181526001602052604090205481906001600160a01b0316612693576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b600082815260016020819052604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168255928101805484169055600281018054909316909255600390910180547fffffffffffffffffff00000000000000000000000000000000000000000000001690555183917f2a9cad2d961f676aa1003ee81f580c7b4382e3d4d186d6725acd9116c84022ac91a25050565b6000806127a6886001600160a01b031663a89ae4ba6040518163ffffffff1660e01b815260040160206040518083038186803b15801561277557600080fd5b505afa158015612789573d6000803e3d6000fd5b505050506040513d602081101561279f57600080fd5b5051614a7c565b905060005b8551811015612abc5760008060006127d68c8a86815181106127c957fe5b6020026020010151613ae2565b50919450915050878111156127ed57505050612ab4565b600061283c6127fa614aeb565b6040805180820190915260208082527f74686520626f6e642073686f756c64206e6f74206861766520657870697265649082015284919063ffffffff614aef16565b90506128508c61284b83614b86565b614bd3565b925050506000826001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156128ac57600080fd5b505afa1580156128c0573d6000803e3d6000fd5b505050506040513d60208110156128d657600080fd5b505190508061292c576040805162461bcd60e51b815260206004820152601860248201527f696e636c75646573206e6f20626f6e642062616c616e63650000000000000000604482015290519081900360640190fd5b604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152306024830152915160009286169163dd62ed3e916044808301926020929190829003018186803b15801561299657600080fd5b505afa1580156129aa573d6000803e3d6000fd5b505050506040513d60208110156129c057600080fd5b5051905080612a16576040805162461bcd60e51b815260206004820152601960248201527f696e636c75646573206e6f20617070726f76656420626f6e6400000000000000604482015290519081900360640190fd5b6000612a388e8d8d8981518110612a2957fe5b60200260200101518a88614c6a565b905080612a8c576040805162461bcd60e51b815260206004820152601760248201527f696e636c7564657320776f7274686c65737320626f6e64000000000000000000604482015290519081900360640190fd5b612aac612a9f838363ffffffff613a4716565b899063ffffffff614f8716565b975050505050505b6001016127ab565b50509695505050505050565b600080600080612ad786613671565b9550505050925092508015612b33576040805162461bcd60e51b815260206004820181905260248201527f5468697320706f6f6c206973206e6f7420666f7220627579696e6720626f6e64604482015290519081900360640190fd5b6000612b5f7f000000000000000000000000000000000000000000000000000000000000000089613ae2565b5091925050506001600160a01b038116612bc0576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b6000806000612bcf8b8b6137a1565b50509150915060648211612c2a576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f20736d616c6c000000000000604482015290519081900360640190fd5b655af3107a40008210612c84576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f206c61726765000000000000604482015290519081900360640190fd5b6000866001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612cbf57600080fd5b505afa158015612cd3573d6000803e3d6000fd5b505050506040513d6020811015612ce957600080fd5b50519050612d08612d008b8563ffffffff613a4716565b601083610f8e565b985088612d465760405162461bcd60e51b81526004018080602001828103825260238152602001806159b06023913960400191505060405180910390fd5b612d5e6305f5e10061102c848d63ffffffff613a4716565b9350505050816001600160a01b03166323b872dd8b878a6040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015612ddd57600080fd5b505af1158015612df1573d6000803e3d6000fd5b505050506040513d6020811015612e0757600080fd5b5051612e5a576040805162461bcd60e51b815260206004820152601660248201527f6661696c20746f207472616e7366657220626f6e647300000000000000000000604482015290519081900360640190fd5b612e756001600160a01b038516868c8963ffffffff6145a216565b6040805188815260208101889052808201839052905189918b916001600160a01b038e16917f56bdd348ec3a30de53e5accb23689b87d92f38aff2892c44a2cb656ba8987702919081900360600190a45050505050949350505050565b6000612edf87878461308f565b6000818152600160205260409020549091506001600160a01b031615612f4c576040805162461bcd60e51b815260206004820152601a60248201527f74686520706f6f6c20494420616c726561647920657869737473000000000000604482015290519081900360640190fd5b6000612f5786614a7c565b905080612f955760405162461bcd60e51b815260040180806020018281038252604681526020018061586b6046913960600191505060405180910390fd5b50612fa581888888888888614fe1565b8115612ff157856001600160a01b0316876001600160a01b0316827f056478b0052e7cd0f5b36aae475ed2dae889099db5f84648a9a8b29b051b90bc60405160405180910390a4613033565b856001600160a01b0316876001600160a01b0316827fa10c9970baeb202d378cccfc7b179865e64a3d92c5e75cefae0f0ae885416ed160405160405180910390a45b604080516001600160a01b03808816825286166020820152600185810b900b81830152905182917f164211b1dbb064ab8f2b34d7c1ea6d5ad1b94a2f54e104251b8833ffecaf6b2a919081900360600190a29695505050505050565b6040805130818301526001600160a01b039485166060820152929093166080830152151560a080830191909152602080830191909152601660c08301527f426f6e642076732045524332302065786368616e67650000000000000000000060e08084019190915283518084039091018152610100909201909252805191012090565b60008581526020819052604090205485906001600160a01b031661317c576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b600080613188886124f9565b5050505050915091506131a08883838a8a8a8a61477c565b604080516001600160a01b03808916825287166020820152600186810b900b81830152905189917fcc1c455a31b9815a3e0c1a2fcd096b2cccc50534bdc41a4c1dbdd3fb4b3c5afb919081900360600190a25050505050505050565b60008481526001602052604090205484906001600160a01b0316613267576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b600080600061327588613671565b95505050509250925061328d8884848a8a8a87614fe1565b604080516001600160a01b03808a16825288166020820152600187810b900b81830152905189917f164211b1dbb064ab8f2b34d7c1ea6d5ad1b94a2f54e104251b8833ffecaf6b2a919081900360600190a25050505050505050565b60008060006132f7856118c0565b945050505091508015613351576040805162461bcd60e51b815260206004820181905260248201527f5468697320706f6f6c206973206e6f7420666f7220627579696e6720626f6e64604482015290519081900360640190fd5b600061337d7f000000000000000000000000000000000000000000000000000000000000000088613ae2565b5091925050506001600160a01b0381166133de576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b60008060006133ed8a8a61399c565b50509150915060648211613448576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f20736d616c6c000000000000604482015290519081900360640190fd5b655af3107a400082106134a2576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f206c61726765000000000000604482015290519081900360640190fd5b6134be6134b5898463ffffffff613a4716565b60106012610f8e565b9650866134fc5760405162461bcd60e51b81526004018080602001828103825260238152602001806159b06023913960400191505060405180910390fd5b6135146305f5e10061102c838b63ffffffff613a4716565b604080517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b038e811660048301528981166024830152604482018c9052915192955090861693506323b872dd92506064808201926020929091908290030181600087803b15801561358d57600080fd5b505af11580156135a1573d6000803e3d6000fd5b505050506040513d60208110156135b757600080fd5b505161360a576040805162461bcd60e51b815260206004820152601660248201527f6661696c20746f207472616e7366657220626f6e647300000000000000000000604482015290519081900360640190fd5b613615848a87612614565b6040805187815260208101879052808201839052905188918a916001600160a01b038d16917f619a69796a0814903d4d55b21b24c8dd06691f79c76317bb938c51d893e8b1fa919081900360600190a450505050949350505050565b6000818152600160205260408120548190819081908190819087906001600160a01b03166136e6576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b6136ee6157e5565b5050506000958652505060016020818152604095869020865160c08101885281546001600160a01b03908116808352838601548216948301859052600284015482169983018a905260039093015490811660608301819052740100000000000000000000000000000000000000008204860b860b90950b6080830181905276010000000000000000000000000000000000000000000090910460ff16151560a09092018290529198929796509294509250565b6000806000806000806000806137b689613671565b955095509550955050506137c984614a7c565b95506137d6838b84613f4d565b90975094506137e48761433c565b9650613824866040518060600160405280602381526020016158fb602391396138178a6305f5e10063ffffffff613a4716565b919063ffffffff61525e16565b97508015613852576305f5e1006138438987830163ffffffff613a4716565b8161384a57fe5b04975061387b565b846305f5e100016138706305f5e1008a613a4790919063ffffffff16565b8161387757fe5b0497505b5050505092959194509250565b60008181526020819052604090205481906001600160a01b03166138f3576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b60008281526020819052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811682556001820180548216905560028201805482169055600382018054909116905560040180547fffffffffffffffffffff000000000000000000000000000000000000000000001690555183917ff44bf4d5e31bd57a2b12f891c33cc0884bc44746beed2864d577e1505a28f3e291a25050565b6000806000806000806000806139b1896118c0565b9450945094509450506139c384614a7c565b95506139d0838b84613f4d565b90975094506139de8761433c565b9650613a11866040518060600160405280602381526020016158fb602391396138178a6305f5e10063ffffffff613a4716565b97508015613a30576305f5e1006138438987830163ffffffff613a4716565b6305f5e1006138708987830363ffffffff613a4716565b600082613a5657506000610a87565b82820282848281613a6357fe5b0414610a845760405162461bcd60e51b81526004018080602001828103825260218152602001806159696021913960400191505060405180910390fd5b6000610a8483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061525e565b6000806000806000866001600160a01b03166326d6c97b876040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b158015613b2e57600080fd5b505afa158015613b42573d6000803e3d6000fd5b505050506040513d6080811015613b5857600080fd5b50805160208201516040830151606090930151919a90995067ffffffffffffffff909216975095509350505050565b600080613bc68a6001600160a01b031663a89ae4ba6040518163ffffffff1660e01b815260040160206040518083038186803b15801561277557600080fd5b90508260005b8851811015613ef3576000806000613bea8f8d86815181106127c957fe5b509194509150508a811115613c0157505050613eeb565b6000613c0e6127fa614aeb565b9050613c1d8f61284b83614b86565b604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081526001600160a01b038e81166004830152306024830152915192955060009450908616925063dd62ed3e916044808301926020929190829003018186803b158015613c8d57600080fd5b505afa158015613ca1573d6000803e3d6000fd5b505050506040513d6020811015613cb757600080fd5b5051905080613cc857505050613eeb565b8b518f908e906000908f9088908110613cdd57fe5b602002602001015190506000613cf68484848d8a614c6a565b905080613d095750505050505050613eeb565b613d19858263ffffffff613a4716565b8911613de6576001600160a01b0387166323b872dd8f8f613d408d8663ffffffff6152c316565b6040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015613da857600080fd5b505af1158015613dbc573d6000803e3d6000fd5b505050506040513d6020811015613dd257600080fd5b50519a50613f419950505050505050505050565b866001600160a01b03166323b872dd8f8f886040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015613e6057600080fd5b505af1158015613e74573d6000803e3d6000fd5b505050506040513d6020811015613e8a57600080fd5b5051613edd576040805162461bcd60e51b815260206004820152601660248201527f6661696c20746f207472616e7366657220626f6e647300000000000000000000604482015290519081900360640190fd5b939093029096039550505050505b600101613bcc565b506040805162461bcd60e51b815260206004820152601b60248201527f696e73756666696369656e7420626f6e6420616c6c6f77616e63650000000000604482015290519081900360640190fd5b98975050505050505050565b6000806000613f7c7f000000000000000000000000000000000000000000000000000000000000000086613ae2565b505091505060008060607f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637e91c2e37f00000000000000000000000000000000000000000000000000000000000000008a60006040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b0316815260200183815260200182600481111561401657fe5b60ff168152602001935050505060006040518083038186803b15801561403b57600080fd5b505afa15801561404f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052606081101561409657600080fd5b815160208301516040808501805191519395929483019291846401000000008211156140c157600080fd5b9083019060208201858111156140d657600080fd5b82518660208202830111640100000000821117156140f357600080fd5b82525081516020918201928201910280838360005b83811015614120578181015183820152602001614108565b505050509050016040525050509250925092508261416f5760405162461bcd60e51b8152600401808060200182810382526027815260200180615b036027913960400191505060405180910390fd5b60006141be61417c614aeb565b6040805180820190915260208082527f74686520626f6e642073686f756c64206e6f74206861766520657870697265649082015287919063ffffffff614aef16565b905060006141eb7f0000000000000000000000000000000000000000000000000000000000000000614a7c565b9050600061421c7f000000000000000000000000000000000000000000000000000000000000000061284b85614b86565b905060008c6001600160a01b031663c29d90b5878761423a876152e8565b614243876152e8565b61424c8a6152e8565b6040518663ffffffff1660e01b81526004018086600481111561426b57fe5b60ff16815260200180602001858152602001848152602001838152602001828103825286818151815260200191508051906020019060200280838360005b838110156142c15781810151838201526020016142a9565b505050509050019650505050505050604080518083038186803b1580156142e757600080fd5b505afa1580156142fb573d6000803e3d6000fd5b505050506040513d604081101561431157600080fd5b508051602090910151909a50905061432a82828d615348565b98505050505050505050935093915050565b60006305f5e10061437c61436f7f0000000000000000000000000000000000000000000000000000000000000000614a7c565b849063ffffffff613a4716565b8161438357fe5b0492915050565b6001600160a01b0385166143e5576040805162461bcd60e51b815260206004820152601a60248201527f74686520706f6f6c20494420616c726561647920657869737473000000000000604482015290519081900360640190fd5b6001600160a01b03841661442a5760405162461bcd60e51b81526004018080602001828103825260248152602001806159fc6024913960400191505060405180910390fd5b6001600160a01b03831661446f5760405162461bcd60e51b81526004018080602001828103825260258152602001806159446025913960400191505060405180910390fd5b6040805160a0810182526001600160a01b0396871681529486166020808701918252948716868301908152600194850b60608801908152931515608088019081526000998a5260029687905292909820955186549088167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216178755905186850180549189169183169190911790559651949093018054915193511515760100000000000000000000000000000000000000000000027fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff9490930b61ffff1674010000000000000000000000000000000000000000027fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff959096169190961617929092169290921791909116179055565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052610bc89085906153e5565b600860ff16816001600160a01b031663d0d6153a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561466857600080fd5b505afa15801561467c573d6000803e3d6000fd5b505050506040513d602081101561469257600080fd5b505160ff16146146d35760405162461bcd60e51b815260040180806020018281038252602681526020018061591e6026913960400191505060405180910390fd5b600860ff16816001600160a01b031663f08e2a336040518163ffffffff1660e01b815260040160206040518083038186803b15801561471157600080fd5b505afa158015614725573d6000803e3d6000fd5b505050506040513d602081101561473b57600080fd5b505160ff1614610c6a5760405162461bcd60e51b8152600401808060200182810382526024815260200180615adf6024913960400191505060405180910390fd5b6001600160a01b0386166147d7576040805162461bcd60e51b815260206004820152601a60248201527f74686520706f6f6c20494420616c726561647920657869737473000000000000604482015290519081900360640190fd5b6001600160a01b03851661481c5760405162461bcd60e51b815260040180806020018281038252602b81526020018061581b602b913960400191505060405180910390fd5b6001600160a01b0383166148615760405162461bcd60e51b815260040180806020018281038252602c815260200180615b4c602c913960400191505060405180910390fd5b6001600160a01b0382166148a65760405162461bcd60e51b81526004018080602001828103825260258152602001806159446025913960400191505060405180910390fd5b6148af8561462a565b6040805160c0810182526001600160a01b03978816815295871660208088019182529588168783019081529488166060880190815293881660808801908152600193840b60a0890190815260009a8b52968a905291909820955186549088167fffffffffffffffffffffffff000000000000000000000000000000000000000091821617875597518683018054918916918a1691909117905592516002860180549188169189169190911790559051600385018054918716918816919091179055905160049093018054925190910b61ffff1674010000000000000000000000000000000000000000027fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff93909416919094161716179055565b6001600160a01b038216600090815260036020526040902054811115614a36576040805162461bcd60e51b815260206004820152601660248201527f696e73756666696369656e7420616c6c6f77616e636500000000000000000000604482015290519081900360640190fd5b6001600160a01b0390911660009081526003602052604090208054919091039055565b6118bc82826040518060600160405280602c8152602001615a20602c91396155bb565b6000816001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614ab957600080fd5b505af1158015614acd573d6000803e3d6000fd5b505050506040513d6020811015614ae357600080fd5b505192915050565b4290565b60008184841115614b7e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614b43578181015183820152602001614b2b565b50505050905090810190601f168015614b705780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000680100000000000000008210614bcf5760405162461bcd60e51b815260040180806020018281038252602681526020018061598a6026913960400191505060405180910390fd5b5090565b6000826001600160a01b031663c8f3e555836040518263ffffffff1660e01b8152600401808267ffffffffffffffff1667ffffffffffffffff16815260200191505060206040518083038186803b158015614c2d57600080fd5b505afa158015614c41573d6000803e3d6000fd5b505050506040513d6020811015614c5757600080fd5b505167ffffffffffffffff169392505050565b6000806000614c798887613ae2565b5050915050614c91614c8c6127fa614aeb565b6152e8565b9150506000606060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637e91c2e38b8a60006040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001838152602001826004811115614d0a57fe5b60ff168152602001935050505060006040518083038186803b158015614d2f57600080fd5b505afa158015614d43573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526060811015614d8a57600080fd5b81516020830151604080850180519151939592948301929184640100000000821115614db557600080fd5b908301906020820185811115614dca57600080fd5b8251866020820283011164010000000082111715614de757600080fd5b82525081516020918201928201910280838360005b83811015614e14578181015183820152602001614dfc565b5050505090500160405250505080945081955082935050505080614e7f576040805162461bcd60e51b815260206004820152601160248201527f756e6b6e6f776e20626f6e642074797065000000000000000000000000000000604482015290519081900360640190fd5b50876001600160a01b031663c29d90b58383614e9a8a6152e8565b614ea38a6152e8565b886040518663ffffffff1660e01b815260040180866004811115614ec357fe5b60ff16815260200180602001858152602001848152602001838152602001828103825286818151815260200191508051906020019060200280838360005b83811015614f19578181015183820152602001614f01565b505050509050019650505050505050604080518083038186803b158015614f3f57600080fd5b505afa925050508015614f6b57506040513d6040811015614f5f57600080fd5b50805160209091015160015b614f7b5760009350505050610ad7565b509350610ad792505050565b600082820183811015610a84576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b03861661503c576040805162461bcd60e51b815260206004820152601a60248201527f74686520706f6f6c20494420616c726561647920657869737473000000000000604482015290519081900360640190fd5b6001600160a01b0385166150815760405162461bcd60e51b81526004018080602001828103825260288152602001806158b16028913960400191505060405180910390fd5b6001600160a01b0384166150c65760405162461bcd60e51b81526004018080602001828103825260298152602001806159d36029913960400191505060405180910390fd5b6001600160a01b03831661510b5760405162461bcd60e51b81526004018080602001828103825260258152602001806159446025913960400191505060405180910390fd5b6040805160c0810182526001600160a01b039788168152958716602080880191825295881687830190815294881660608801908152600194850b6080890190815293151560a0890190815260009a8b529685905291909820955186549088167fffffffffffffffffffffffff000000000000000000000000000000000000000091821617875597518684018054918916918a169190911790559251600286018054918816918916919091179055915160039094018054925193511515760100000000000000000000000000000000000000000000027fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff9490920b61ffff1674010000000000000000000000000000000000000000027fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff959096169290961691909117929092169290921791909116179055565b600081836152ad5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614b43578181015183820152602001614b2b565b5060008385816152b957fe5b0495945050505050565b6000610a8483836040518060600160405280602281526020016158d9602291396156fe565b60007f80000000000000000000000000000000000000000000000000000000000000008210614bcf5760405162461bcd60e51b8152600401808060200182810382526028815260200180615a8d6028913960400191505060405180910390fd5b6000806305f5e100851061537257630bebc2008511615367578461536d565b630bebc2005b615378565b6305f5e1005b905083810264e8d4a510006153b66000600187900b128061539f5750662386f26fc1000083105b6153a95782614c8c565b662386f26fc100006152e8565b8560010b02816153c257fe5b0592506305f5e10083136153d65782610bec565b6305f5e1009695505050505050565b6153f7826001600160a01b0316615774565b615448576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106154a457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101615467565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114615506576040519150601f19603f3d011682016040523d82523d6000602084013e61550b565b606091505b509150915081615562576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115610bc85780806020019051602081101561557e57600080fd5b5051610bc85760405162461bcd60e51b815260040180806020018281038252602a815260200180615ab5602a913960400191505060405180910390fd5b6155c4826157b0565b81906156115760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614b43578181015183820152602001614b2b565b506040516000906001600160a01b0385169084908381818185875af1925050503d806000811461565d576040519150601f19603f3d011682016040523d82523d6000602084013e615662565b606091505b50509050806156b8576040805162461bcd60e51b815260206004820152601960248201527f7472616e7366657272696e67204574686572206661696c656400000000000000604482015290519081900360640190fd5b6040805184815290516001600160a01b0386169130917fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9181900360200190a350505050565b60008361570d57506000610dd1565b818361575a5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614b43578181015183820152602001614b2b565b5082600185038161576757fe5b0460010190509392505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906157a857508115155b949350505050565b3031101590565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091529056fe626f6e644d616b6572466f72557365722073686f756c64206265206e6f6e2d7a65726f2061646472657373646563696d616c20676170206e6565647320746f206265206c6f776572207468616e20313973776170506169724f7261636c6520686173206c6174657374507269636528292066756e6374696f6e2077686963682072657475726e73206e6f6e2d7a65726f2076616c75657377617050616972546f6b656e2073686f756c64206265206e6f6e2d7a65726f2061646472657373536166654d617468446976526f756e6455703a206d6f64756c6f206279207a65726f4552433230206f7261636c65207072696365206d757374206265206e6f6e2d7a65726f74686520646563696d616c73206f66206f7261636c65207072696365206d7573742062652038626f6e645072696365722073686f756c64206265206e6f6e2d7a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7753616665436173743a2076616c756520646f65736e27742066697420696e20363420626974736d757374207472616e73666572206e6f6e2d7a65726f20746f6b656e20616d6f756e7473776170506169724f7261636c652073686f756c64206265206e6f6e2d7a65726f20616464726573736574684f7261636c652073686f756c64206265206e6f6e2d7a65726f20616464726573735472616e736665724554483a207472616e7366657220616d6f756e7420657863656564732062616c616e63656574684f7261636c6520686173206c6174657374507269636528292066756e6374696f6e2077686963682072657475726e73206e6f6e2d7a65726f2076616c756553616665436173743a2076616c756520646f65736e27742066697420696e20616e20696e743235365361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656474686520646563696d616c73206f6620626f6e6420746f6b656e206d757374206265203863616e6e6f742063616c63756c61746520746865207072696365206f66207468697320626f6e646d757374207472616e73666572206e6f6e2d7a65726f20626f6e6420616d6f756e74626f6e64507269636572466f72557365722073686f756c64206265206e6f6e2d7a65726f2061646472657373a26469706673582212207d46b6e6ab3d17a7a0bf149999e36885cb46e29bb984f9b0fb8158d023d86fd164736f6c6343000606003374686520646563696d616c73206f66206f7261636c65207072696365206d757374206265203874686520646563696d616c73206f6620626f6e6420746f6b656e206d7573742062652038000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0000000000000000000000000c8bbb8d57cebf834dc429ec4d65dd23ed0d65a87000000000000000000000000ad491f460d8ee6df3335e8af48de33e0468cd8c9000000000000000000000000a0d773221ca923fb48a0cf1b8309496d198cbfa1
Deployed Bytecode
0x6080604052600436106101c65760003560e01c80638a43a1a4116100f7578063ca6aaecb11610095578063dc10d97f11610064578063dc10d97f146108e9578063dcf288771461095d578063e64851201461098d578063faf279ea146109b757610204565b8063ca6aaecb146107c4578063ccb63b7014610809578063d23070c11461085b578063d78f308d146108a757610204565b8063a291bace116100d1578063a291bace14610671578063b6263c421461069b578063bbd114f91461072e578063bd42c7061461077057610204565b80638a43a1a4146105b857806393e492a1146105e2578063a0ef91df1461065c57610204565b8063439370b1116101645780635a6969341161013e5780635a696934146104925780635c4776c4146104d457806361a72d6d1461052057806378f286d91461056257610204565b8063439370b1146103e2578063460522f4146103ec578063488abbfc1461045757610204565b806318c681fd116101a057806318c681fd1461031c5780631b1839ab1461034c578063241d92291461036157806338360dee146103af57610204565b80630b1a3554146102095780630f48fd481461023a57806311ed6077146102e157610204565b3661020457604080513481529051309133917fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9181900360200190a3005b600080fd5b34801561021557600080fd5b5061021e6109e7565b604080516001600160a01b039092168252519081900360200190f35b34801561024657600080fd5b506102cf600480360360c081101561025d57600080fd5b81359160208101359181019060608101604082013564010000000081111561028457600080fd5b82018360208201111561029657600080fd5b803590602001918460208302840111640100000000831117156102b857600080fd5b919350915080359060208101359060400135610a0c565b60408051918252519081900360200190f35b3480156102ed57600080fd5b506102cf6004803603604081101561030457600080fd5b506001600160a01b0381351690602001351515610a78565b34801561032857600080fd5b506102cf6004803603604081101561033f57600080fd5b5080359060200135610a8d565b34801561035857600080fd5b5061021e610aa4565b34801561036d57600080fd5b506102cf6004803603608081101561038457600080fd5b506001600160a01b038135811691602081013590911690604081013560010b90606001351515610ac8565b3480156103bb57600080fd5b506102cf600480360360208110156103d257600080fd5b50356001600160a01b0316610ae0565b6103ea610afb565b005b3480156103f857600080fd5b506104166004803603602081101561040f57600080fd5b5035610b07565b604080516001600160a01b03968716815294861660208601529290941683830152600190810b900b6060830152911515608082015290519081900360a00190f35b34801561046357600080fd5b506102cf6004803603604081101561047a57600080fd5b506001600160a01b0381358116916020013516610b2a565b34801561049e57600080fd5b506102cf600480360360a08110156104b557600080fd5b5080359060208101359060408101359060608101359060800135610b36565b3480156104e057600080fd5b506103ea600480360360808110156104f757600080fd5b508035906001600160a01b0360208201358116916040810135909116906060013560010b610b51565b34801561052c57600080fd5b506102cf600480360360a081101561054357600080fd5b5080359060208101359060408101359060608101359060800135610bce565b34801561056e57600080fd5b506102cf600480360360a081101561058557600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135909116906080013560010b610bdc565b3480156105c457600080fd5b506103ea600480360360208110156105db57600080fd5b5035610bf6565b3480156105ee57600080fd5b5061060c6004803603602081101561060557600080fd5b5035610c6d565b604080516001600160a01b039889168152968816602088015294871686860152928616606086015294166080840152600193840b90930b60a083015291151560c082015290519081900360e00190f35b34801561066857600080fd5b506102cf610c98565b34801561067d57600080fd5b506103ea6004803603602081101561069457600080fd5b5035610cb4565b3480156106a757600080fd5b506102cf600480360360808110156106be57600080fd5b813591908101906040810160208201356401000000008111156106e057600080fd5b8201836020820111156106f257600080fd5b8035906020019184602083028401116401000000008311171561071457600080fd5b9193509150803590602001356001600160a01b0316610d28565b34801561073a57600080fd5b506102cf600480360360a081101561075157600080fd5b5080359060208101359060408101359060608101359060800135610da3565b34801561077c57600080fd5b506102cf600480360360a081101561079357600080fd5b506001600160a01b038135811691602081013582169160408201351690606081013560010b90608001351515610db1565b3480156107d057600080fd5b506102cf600480360360608110156107e757600080fd5b506001600160a01b038135811691602081013590911690604001351515610dc1565b34801561081557600080fd5b506103ea600480360360a081101561082c57600080fd5b508035906001600160a01b0360208201358116916040810135821691606082013516906080013560010b610dd8565b34801561086757600080fd5b506103ea6004803603608081101561087e57600080fd5b508035906001600160a01b0360208201358116916040810135909116906060013560010b610e57565b3480156108b357600080fd5b506102cf600480360360a08110156108ca57600080fd5b5080359060208101359060408101359060608101359060800135610ece565b3480156108f557600080fd5b506109136004803603602081101561090c57600080fd5b5035610edc565b604080516001600160a01b039788168152958716602087015293861685850152919094166060840152600193840b90930b608083015291151560a082015290519081900360c00190f35b34801561096957600080fd5b506102cf6004803603604081101561098057600080fd5b5080359060200135610f02565b34801561099957600080fd5b506103ea600480360360208110156109b057600080fd5b5035610f0e565b3480156109c357600080fd5b506102cf600480360360408110156109da57600080fd5b5080359060200135610f82565b7f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef05b90565b600080610a1c8560086010610f8e565b9050610a5f338a8a8a8a80806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250889250611038915050565b9150610a6c8285856114f0565b50979650505050505050565b6000610a848383611567565b90505b92915050565b6000610a9983836115e1565b509195945050505050565b7f000000000000000000000000ad491f460d8ee6df3335e8af48de33e0468cd8c990565b6000610ad73386868686611646565b95945050505050565b6001600160a01b031660009081526003602052604090205490565b610b053334611848565b565b6000806000806000610b18866118c0565b939a9299509097509550909350915050565b6000610a8483836119de565b6000610b4433878787611a58565b9050610ad78184846114f0565b6000848152600260205260409020546001600160a01b03163314610bbc576040805162461bcd60e51b815260206004820152601c60248201527f6e6f7420746865206f776e6572206f662074686520706f6f6c20494400000000604482015290519081900360640190fd5b610bc884848484611e5d565b50505050565b6000610b4433878787611f44565b6000610bec3387878787876122c9565b9695505050505050565b6000818152600260205260409020546001600160a01b03163314610c61576040805162461bcd60e51b815260206004820152601c60248201527f6e6f7420746865206f776e6572206f662074686520706f6f6c20494400000000604482015290519081900360640190fd5b610c6a816123f7565b50565b6000806000806000806000610c81886124f9565b959e949d50929b5090995097509550909350915050565b3360008181526003602052604090205490610a09908083612614565b6000818152600160205260409020546001600160a01b03163314610d1f576040805162461bcd60e51b815260206004820152601c60248201527f6e6f7420746865206f776e6572206f662074686520706f6f6c20494400000000604482015290519081900360640190fd5b610c6a81612628565b600080600080610d37896124f9565b505050935093509350506000610d868484848c8c808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508e92508d91506127369050565b9050610d958160106008610f8e565b9a9950505050505050505050565b6000610b4433878787612ac8565b6000610bec338787878787612ed2565b6000610dce84848461308f565b90505b9392505050565b6000858152602081905260409020546001600160a01b03163314610e43576040805162461bcd60e51b815260206004820152601c60248201527f6e6f7420746865206f776e6572206f662074686520706f6f6c20494400000000604482015290519081900360640190fd5b610e508585858585613111565b5050505050565b6000848152600160205260409020546001600160a01b03163314610ec2576040805162461bcd60e51b815260206004820152601c60248201527f6e6f7420746865206f776e6572206f662074686520706f6f6c20494400000000604482015290519081900360640190fd5b610bc8848484846131fc565b6000610b44338787876132e9565b600080600080600080610eee87613671565b949c939b5091995097509550909350915050565b6000610a9983836137a1565b6000818152602081905260409020546001600160a01b03163314610f79576040805162461bcd60e51b815260206004820152601c60248201527f6e6f7420746865206f776e6572206f662074686520706f6f6c20494400000000604482015290519081900360640190fd5b610c6a81613888565b6000610a99838361399c565b60008060008360ff168560ff161115610fad575060ff83850316610fc4565b8360ff168560ff161015610fc45784840360ff1691505b601382108015610fd45750601381105b61100f5760405162461bcd60e51b81526004018080602001828103825260258152602001806158466025913960400191505060405180910390fd5b610bec81600a0a61102c84600a0a89613a4790919063ffffffff16565b9063ffffffff613aa016565b6000825160001415611091576040805162461bcd60e51b815260206004820152601c60248201527f6d75737420696e70757420626f6e647320666f72207061796d656e7400000000604482015290519081900360640190fd5b60008061109d866124f9565b9497509395508594506110fc9350505050576040805162461bcd60e51b815260206004820152601c60248201527f5468697320706f6f6c20697320666f7220627579696e6720626f6e6400000000604482015290519081900360640190fd5b5060008061112a7f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef089613ae2565b509193509150506001600160a01b03821661118c576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b600061119889896115e1565b5050509050606481116111f2576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f20736d616c6c000000000000604482015290519081900360640190fd5b655af3107a4000811061124c576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f206c61726765000000000000604482015290519081900360640190fd5b806112c28760088001866001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b15801561128e57600080fd5b505afa1580156112a2573d6000803e3d6000fd5b505050506040513d60208110156112b857600080fd5b5051600801610f8e565b816112c957fe5b049450846113085760405162461bcd60e51b8152600401808060200182810382526022815260200180615b2a6022913960400191505060405180910390fd5b5060008060006113178a6124f9565b50505093509350509250846001600160a01b03166323b872dd848e8a6040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b15801561139b57600080fd5b505af11580156113af573d6000803e3d6000fd5b505050506040513d60208110156113c557600080fd5b5051611418576040805162461bcd60e51b815260206004820152601660248201527f6661696c20746f207472616e7366657220626f6e647300000000000000000000604482015290519081900360640190fd5b8b8861142a8885858e8a878b88613b87565b61147b576040805162461bcd60e51b815260206004820152601c60248201527f6661696c20746f207472616e7366657220455243323020746f6b656e00000000604482015290519081900360640190fd5b5050505050600061149186600880016008610f8e565b6040805187815260208101899052808201839052905191925089918b916001600160a01b038e16917fd993461e2ed05e160d9d91ad5dddc245e8fd8606ef3b59a6a4544a6b5f438b609181900360600190a45050505095945050505050565b8115611562578161150f6103e861102c8685830163ffffffff613a4716565b1015611562576040805162461bcd60e51b815260206004820152601b60248201527f6f7574206f662065787065637465642070726963652072616e67650000000000604482015290519081900360640190fd5b505050565b6040805130818301526001600160a01b03939093166060840152901515608080840191909152602080840191909152601460a08401527f426f6e64207673204554482065786368616e676500000000000000000000000060c0808501919091528251808503909101815260e0909301909152815191012090565b6000806000806000806115f3876124f9565b509550955050505050611607828983613f4d565b90955092506116158561433c565b94506305f5e1009350836116318685830163ffffffff613a4716565b8161163857fe5b049550505092959194509250565b60006116528683611567565b6000818152600260205260409020549091506001600160a01b0316156116bf576040805162461bcd60e51b815260206004820152601a60248201527f74686520706f6f6c20494420616c726561647920657869737473000000000000604482015290519081900360640190fd5b6000856001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156116fc57600080fd5b505af1158015611710573d6000803e3d6000fd5b505050506040513d602081101561172657600080fd5b50519050806117665760405162461bcd60e51b8152600401808060200182810382526041815260200180615a4c6041913960600191505060405180910390fd5b5061177581878787878761438a565b81156117b6576040516001600160a01b0387169082907fff21af9ef13c15bda11c8778f12d707fc45e46295475a179bfc6edaa8302cc4290600090a36117ed565b6040516001600160a01b0387169082907f7830c5d14d54770e26085fb8c75218966810a41f896d2e81a59ad6e5fd358a7390600090a35b604080516001600160a01b03808816825286166020820152600185810b900b81830152905182917fa45c688b2c8530361470c35643e00bb252b627c331f3f04491631591ac20ffe3919081900360600190a295945050505050565b6001600160a01b038216600090815260036020526040902080548201908190558111156118bc576040805162461bcd60e51b815260206004820152601260248201527f6f766572666c6f7720616c6c6f77616e63650000000000000000000000000000604482015290519081900360640190fd5b5050565b600081815260026020526040812054819081908190819086906001600160a01b0316611933576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b61193b6157b7565b5050506000948552505060026020818152604094859020855160a08101875281546001600160a01b0390811680835260018085015483169584018690529390950154908116978201889052740100000000000000000000000000000000000000008104830b830b90920b6060820181905276010000000000000000000000000000000000000000000090920460ff16151560809091018190529296919594509250565b6040805130818301526001600160a01b03938416606082015291909216608080830191909152602080830191909152601460a08301527f426f6e64207673205342542065786368616e676500000000000000000000000060c0808401919091528351808403909101815260e0909201909252805191012090565b600080600080611a6786613671565b95505050509250925080611ac2576040805162461bcd60e51b815260206004820152601c60248201527f5468697320706f6f6c20697320666f7220627579696e6720626f6e6400000000604482015290519081900360640190fd5b6000611aee7f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef089613ae2565b5091925050506001600160a01b038116611b4f576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b6000806000611b5e8b8b6137a1565b50925050915060648211611bb9576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f20736d616c6c000000000000604482015290519081900360640190fd5b655af3107a40008210611c13576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f206c61726765000000000000604482015290519081900360640190fd5b6000866001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015611c4e57600080fd5b505afa158015611c62573d6000803e3d6000fd5b505050506040513d6020811015611c7857600080fd5b5051905082611c898b836010610f8e565b81611c9057fe5b04985088611ccf5760405162461bcd60e51b8152600401808060200182810382526022815260200180615b2a6022913960400191505060405180910390fd5b611ce960ff8216600a0a61102c848d63ffffffff613a4716565b9350505050816001600160a01b03166323b872dd868c896040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015611d6857600080fd5b505af1158015611d7c573d6000803e3d6000fd5b505050506040513d6020811015611d9257600080fd5b5051611de5576040805162461bcd60e51b815260206004820152601660248201527f6661696c20746f207472616e7366657220626f6e647300000000000000000000604482015290519081900360640190fd5b611e006001600160a01b0385168b878a63ffffffff6145a216565b6040805187815260208101899052808201839052905189918b916001600160a01b038e16917ff200e0baecbcae9dad1b97ab97511a8c8aeee481b3bf835ce0157bba421ce320919081900360600190a45050505050949350505050565b60008481526002602052604090205484906001600160a01b0316611ec8576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b600080611ed4876118c0565b94505050509150611ee987838888888661438a565b604080516001600160a01b03808916825287166020820152600186810b900b81830152905188917fa45c688b2c8530361470c35643e00bb252b627c331f3f04491631591ac20ffe3919081900360600190a250505050505050565b6000806000611f52856118c0565b9450505050915080611fab576040805162461bcd60e51b815260206004820152601c60248201527f5468697320706f6f6c20697320666f7220627579696e6720626f6e6400000000604482015290519081900360640190fd5b6000611fd77f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef088613ae2565b5091925050506001600160a01b038116612038576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b60008060006120478a8a61399c565b509250509150606482116120a2576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f20736d616c6c000000000000604482015290519081900360640190fd5b655af3107a400082106120fc576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f206c61726765000000000000604482015290519081900360640190fd5b8161210a8960126010610f8e565b8161211157fe5b049650866121505760405162461bcd60e51b8152600401808060200182810382526022815260200180615b2a6022913960400191505060405180910390fd5b61216c670de0b6b3a764000061102c838b63ffffffff613a4716565b604080517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b0389811660048301528e81166024830152604482018b9052915192955090861693506323b872dd92506064808201926020929091908290030181600087803b1580156121e557600080fd5b505af11580156121f9573d6000803e3d6000fd5b505050506040513d602081101561220f57600080fd5b5051612262576040805162461bcd60e51b815260206004820152601660248201527f6661696c20746f207472616e7366657220626f6e647300000000000000000000604482015290519081900360640190fd5b61226d898588612614565b6040805186815260208101889052808201839052905188918a916001600160a01b038d16917fcc3d7a17c2ae4f2fdf5afc9e62cfb5860e4c8f4d86c9e02602223f4eebdf9637919081900360600190a450505050949350505050565b60006122d587876119de565b6000818152602081905260409020549091506001600160a01b031615612342576040805162461bcd60e51b815260206004820152601a60248201527f74686520706f6f6c20494420616c726561647920657869737473000000000000604482015290519081900360640190fd5b61234b8661462a565b61235a8188888888888861477c565b856001600160a01b0316876001600160a01b0316827fc123eddaddec0f57780eb14c17886c4931a5304c25284c9a4ca8de01dc33d50360405160405180910390a4604080516001600160a01b03808716825285166020820152600184810b900b81830152905182917fcc1c455a31b9815a3e0c1a2fcd096b2cccc50534bdc41a4c1dbdd3fb4b3c5afb919081900360600190a29695505050505050565b60008181526002602052604090205481906001600160a01b0316612462576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b600082815260026020819052604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168255600182018054909116905590910180547fffffffffffffffffff00000000000000000000000000000000000000000000001690555183917fba8b1b1bd3050c32112db02c33208fcc66f00fc4b1ac205e4306ff362757ca3091a25050565b60008181526020819052604081205481908190819081908190819088906001600160a01b0316612570576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b6125786157e5565b50505060009687525050506020848152604094859020855160c08101875281546001600160a01b039081168083526001808501548316958401869052600285015483169984018a905260038501548316606085018190526004909501549283166080850181905274010000000000000000000000000000000000000000909304810b810b810b60a0909401849052909994989750929550935091565b61261e83826149c9565b6115628282614a59565b60008181526001602052604090205481906001600160a01b0316612693576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b600082815260016020819052604080832080547fffffffffffffffffffffffff00000000000000000000000000000000000000009081168255928101805484169055600281018054909316909255600390910180547fffffffffffffffffff00000000000000000000000000000000000000000000001690555183917f2a9cad2d961f676aa1003ee81f580c7b4382e3d4d186d6725acd9116c84022ac91a25050565b6000806127a6886001600160a01b031663a89ae4ba6040518163ffffffff1660e01b815260040160206040518083038186803b15801561277557600080fd5b505afa158015612789573d6000803e3d6000fd5b505050506040513d602081101561279f57600080fd5b5051614a7c565b905060005b8551811015612abc5760008060006127d68c8a86815181106127c957fe5b6020026020010151613ae2565b50919450915050878111156127ed57505050612ab4565b600061283c6127fa614aeb565b6040805180820190915260208082527f74686520626f6e642073686f756c64206e6f74206861766520657870697265649082015284919063ffffffff614aef16565b90506128508c61284b83614b86565b614bd3565b925050506000826001600160a01b03166370a08231886040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156128ac57600080fd5b505afa1580156128c0573d6000803e3d6000fd5b505050506040513d60208110156128d657600080fd5b505190508061292c576040805162461bcd60e51b815260206004820152601860248201527f696e636c75646573206e6f20626f6e642062616c616e63650000000000000000604482015290519081900360640190fd5b604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081526001600160a01b038981166004830152306024830152915160009286169163dd62ed3e916044808301926020929190829003018186803b15801561299657600080fd5b505afa1580156129aa573d6000803e3d6000fd5b505050506040513d60208110156129c057600080fd5b5051905080612a16576040805162461bcd60e51b815260206004820152601960248201527f696e636c75646573206e6f20617070726f76656420626f6e6400000000000000604482015290519081900360640190fd5b6000612a388e8d8d8981518110612a2957fe5b60200260200101518a88614c6a565b905080612a8c576040805162461bcd60e51b815260206004820152601760248201527f696e636c7564657320776f7274686c65737320626f6e64000000000000000000604482015290519081900360640190fd5b612aac612a9f838363ffffffff613a4716565b899063ffffffff614f8716565b975050505050505b6001016127ab565b50509695505050505050565b600080600080612ad786613671565b9550505050925092508015612b33576040805162461bcd60e51b815260206004820181905260248201527f5468697320706f6f6c206973206e6f7420666f7220627579696e6720626f6e64604482015290519081900360640190fd5b6000612b5f7f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef089613ae2565b5091925050506001600160a01b038116612bc0576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b6000806000612bcf8b8b6137a1565b50509150915060648211612c2a576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f20736d616c6c000000000000604482015290519081900360640190fd5b655af3107a40008210612c84576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f206c61726765000000000000604482015290519081900360640190fd5b6000866001600160a01b031663313ce5676040518163ffffffff1660e01b815260040160206040518083038186803b158015612cbf57600080fd5b505afa158015612cd3573d6000803e3d6000fd5b505050506040513d6020811015612ce957600080fd5b50519050612d08612d008b8563ffffffff613a4716565b601083610f8e565b985088612d465760405162461bcd60e51b81526004018080602001828103825260238152602001806159b06023913960400191505060405180910390fd5b612d5e6305f5e10061102c848d63ffffffff613a4716565b9350505050816001600160a01b03166323b872dd8b878a6040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015612ddd57600080fd5b505af1158015612df1573d6000803e3d6000fd5b505050506040513d6020811015612e0757600080fd5b5051612e5a576040805162461bcd60e51b815260206004820152601660248201527f6661696c20746f207472616e7366657220626f6e647300000000000000000000604482015290519081900360640190fd5b612e756001600160a01b038516868c8963ffffffff6145a216565b6040805188815260208101889052808201839052905189918b916001600160a01b038e16917f56bdd348ec3a30de53e5accb23689b87d92f38aff2892c44a2cb656ba8987702919081900360600190a45050505050949350505050565b6000612edf87878461308f565b6000818152600160205260409020549091506001600160a01b031615612f4c576040805162461bcd60e51b815260206004820152601a60248201527f74686520706f6f6c20494420616c726561647920657869737473000000000000604482015290519081900360640190fd5b6000612f5786614a7c565b905080612f955760405162461bcd60e51b815260040180806020018281038252604681526020018061586b6046913960600191505060405180910390fd5b50612fa581888888888888614fe1565b8115612ff157856001600160a01b0316876001600160a01b0316827f056478b0052e7cd0f5b36aae475ed2dae889099db5f84648a9a8b29b051b90bc60405160405180910390a4613033565b856001600160a01b0316876001600160a01b0316827fa10c9970baeb202d378cccfc7b179865e64a3d92c5e75cefae0f0ae885416ed160405160405180910390a45b604080516001600160a01b03808816825286166020820152600185810b900b81830152905182917f164211b1dbb064ab8f2b34d7c1ea6d5ad1b94a2f54e104251b8833ffecaf6b2a919081900360600190a29695505050505050565b6040805130818301526001600160a01b039485166060820152929093166080830152151560a080830191909152602080830191909152601660c08301527f426f6e642076732045524332302065786368616e67650000000000000000000060e08084019190915283518084039091018152610100909201909252805191012090565b60008581526020819052604090205485906001600160a01b031661317c576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b600080613188886124f9565b5050505050915091506131a08883838a8a8a8a61477c565b604080516001600160a01b03808916825287166020820152600186810b900b81830152905189917fcc1c455a31b9815a3e0c1a2fcd096b2cccc50534bdc41a4c1dbdd3fb4b3c5afb919081900360600190a25050505050505050565b60008481526001602052604090205484906001600160a01b0316613267576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b600080600061327588613671565b95505050509250925061328d8884848a8a8a87614fe1565b604080516001600160a01b03808a16825288166020820152600187810b900b81830152905189917f164211b1dbb064ab8f2b34d7c1ea6d5ad1b94a2f54e104251b8833ffecaf6b2a919081900360600190a25050505050505050565b60008060006132f7856118c0565b945050505091508015613351576040805162461bcd60e51b815260206004820181905260248201527f5468697320706f6f6c206973206e6f7420666f7220627579696e6720626f6e64604482015290519081900360640190fd5b600061337d7f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef088613ae2565b5091925050506001600160a01b0381166133de576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b60008060006133ed8a8a61399c565b50509150915060648211613448576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f20736d616c6c000000000000604482015290519081900360640190fd5b655af3107a400082106134a2576040805162461bcd60e51b815260206004820152601a60248201527f65786368616e6765207261746520697320746f6f206c61726765000000000000604482015290519081900360640190fd5b6134be6134b5898463ffffffff613a4716565b60106012610f8e565b9650866134fc5760405162461bcd60e51b81526004018080602001828103825260238152602001806159b06023913960400191505060405180910390fd5b6135146305f5e10061102c838b63ffffffff613a4716565b604080517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b038e811660048301528981166024830152604482018c9052915192955090861693506323b872dd92506064808201926020929091908290030181600087803b15801561358d57600080fd5b505af11580156135a1573d6000803e3d6000fd5b505050506040513d60208110156135b757600080fd5b505161360a576040805162461bcd60e51b815260206004820152601660248201527f6661696c20746f207472616e7366657220626f6e647300000000000000000000604482015290519081900360640190fd5b613615848a87612614565b6040805187815260208101879052808201839052905188918a916001600160a01b038d16917f619a69796a0814903d4d55b21b24c8dd06691f79c76317bb938c51d893e8b1fa919081900360600190a450505050949350505050565b6000818152600160205260408120548190819081908190819087906001600160a01b03166136e6576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b6136ee6157e5565b5050506000958652505060016020818152604095869020865160c08101885281546001600160a01b03908116808352838601548216948301859052600284015482169983018a905260039093015490811660608301819052740100000000000000000000000000000000000000008204860b860b90950b6080830181905276010000000000000000000000000000000000000000000090910460ff16151560a09092018290529198929796509294509250565b6000806000806000806000806137b689613671565b955095509550955050506137c984614a7c565b95506137d6838b84613f4d565b90975094506137e48761433c565b9650613824866040518060600160405280602381526020016158fb602391396138178a6305f5e10063ffffffff613a4716565b919063ffffffff61525e16565b97508015613852576305f5e1006138438987830163ffffffff613a4716565b8161384a57fe5b04975061387b565b846305f5e100016138706305f5e1008a613a4790919063ffffffff16565b8161387757fe5b0497505b5050505092959194509250565b60008181526020819052604090205481906001600160a01b03166138f3576040805162461bcd60e51b815260206004820181905260248201527f7468652065786368616e6765207061697220646f6573206e6f74206578697374604482015290519081900360640190fd5b60008281526020819052604080822080547fffffffffffffffffffffffff000000000000000000000000000000000000000090811682556001820180548216905560028201805482169055600382018054909116905560040180547fffffffffffffffffffff000000000000000000000000000000000000000000001690555183917ff44bf4d5e31bd57a2b12f891c33cc0884bc44746beed2864d577e1505a28f3e291a25050565b6000806000806000806000806139b1896118c0565b9450945094509450506139c384614a7c565b95506139d0838b84613f4d565b90975094506139de8761433c565b9650613a11866040518060600160405280602381526020016158fb602391396138178a6305f5e10063ffffffff613a4716565b97508015613a30576305f5e1006138438987830163ffffffff613a4716565b6305f5e1006138708987830363ffffffff613a4716565b600082613a5657506000610a87565b82820282848281613a6357fe5b0414610a845760405162461bcd60e51b81526004018080602001828103825260218152602001806159696021913960400191505060405180910390fd5b6000610a8483836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061525e565b6000806000806000866001600160a01b03166326d6c97b876040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b158015613b2e57600080fd5b505afa158015613b42573d6000803e3d6000fd5b505050506040513d6080811015613b5857600080fd5b50805160208201516040830151606090930151919a90995067ffffffffffffffff909216975095509350505050565b600080613bc68a6001600160a01b031663a89ae4ba6040518163ffffffff1660e01b815260040160206040518083038186803b15801561277557600080fd5b90508260005b8851811015613ef3576000806000613bea8f8d86815181106127c957fe5b509194509150508a811115613c0157505050613eeb565b6000613c0e6127fa614aeb565b9050613c1d8f61284b83614b86565b604080517fdd62ed3e0000000000000000000000000000000000000000000000000000000081526001600160a01b038e81166004830152306024830152915192955060009450908616925063dd62ed3e916044808301926020929190829003018186803b158015613c8d57600080fd5b505afa158015613ca1573d6000803e3d6000fd5b505050506040513d6020811015613cb757600080fd5b5051905080613cc857505050613eeb565b8b518f908e906000908f9088908110613cdd57fe5b602002602001015190506000613cf68484848d8a614c6a565b905080613d095750505050505050613eeb565b613d19858263ffffffff613a4716565b8911613de6576001600160a01b0387166323b872dd8f8f613d408d8663ffffffff6152c316565b6040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015613da857600080fd5b505af1158015613dbc573d6000803e3d6000fd5b505050506040513d6020811015613dd257600080fd5b50519a50613f419950505050505050505050565b866001600160a01b03166323b872dd8f8f886040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b031681526020018281526020019350505050602060405180830381600087803b158015613e6057600080fd5b505af1158015613e74573d6000803e3d6000fd5b505050506040513d6020811015613e8a57600080fd5b5051613edd576040805162461bcd60e51b815260206004820152601660248201527f6661696c20746f207472616e7366657220626f6e647300000000000000000000604482015290519081900360640190fd5b939093029096039550505050505b600101613bcc565b506040805162461bcd60e51b815260206004820152601b60248201527f696e73756666696369656e7420626f6e6420616c6c6f77616e63650000000000604482015290519081900360640190fd5b98975050505050505050565b6000806000613f7c7f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef086613ae2565b505091505060008060607f000000000000000000000000a0d773221ca923fb48a0cf1b8309496d198cbfa16001600160a01b0316637e91c2e37f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef08a60006040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b0316815260200183815260200182600481111561401657fe5b60ff168152602001935050505060006040518083038186803b15801561403b57600080fd5b505afa15801561404f573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201604052606081101561409657600080fd5b815160208301516040808501805191519395929483019291846401000000008211156140c157600080fd5b9083019060208201858111156140d657600080fd5b82518660208202830111640100000000821117156140f357600080fd5b82525081516020918201928201910280838360005b83811015614120578181015183820152602001614108565b505050509050016040525050509250925092508261416f5760405162461bcd60e51b8152600401808060200182810382526027815260200180615b036027913960400191505060405180910390fd5b60006141be61417c614aeb565b6040805180820190915260208082527f74686520626f6e642073686f756c64206e6f74206861766520657870697265649082015287919063ffffffff614aef16565b905060006141eb7f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d614a7c565b9050600061421c7f000000000000000000000000c8bbb8d57cebf834dc429ec4d65dd23ed0d65a8761284b85614b86565b905060008c6001600160a01b031663c29d90b5878761423a876152e8565b614243876152e8565b61424c8a6152e8565b6040518663ffffffff1660e01b81526004018086600481111561426b57fe5b60ff16815260200180602001858152602001848152602001838152602001828103825286818151815260200191508051906020019060200280838360005b838110156142c15781810151838201526020016142a9565b505050509050019650505050505050604080518083038186803b1580156142e757600080fd5b505afa1580156142fb573d6000803e3d6000fd5b505050506040513d604081101561431157600080fd5b508051602090910151909a50905061432a82828d615348565b98505050505050505050935093915050565b60006305f5e10061437c61436f7f000000000000000000000000ad491f460d8ee6df3335e8af48de33e0468cd8c9614a7c565b849063ffffffff613a4716565b8161438357fe5b0492915050565b6001600160a01b0385166143e5576040805162461bcd60e51b815260206004820152601a60248201527f74686520706f6f6c20494420616c726561647920657869737473000000000000604482015290519081900360640190fd5b6001600160a01b03841661442a5760405162461bcd60e51b81526004018080602001828103825260248152602001806159fc6024913960400191505060405180910390fd5b6001600160a01b03831661446f5760405162461bcd60e51b81526004018080602001828103825260258152602001806159446025913960400191505060405180910390fd5b6040805160a0810182526001600160a01b0396871681529486166020808701918252948716868301908152600194850b60608801908152931515608088019081526000998a5260029687905292909820955186549088167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216178755905186850180549189169183169190911790559651949093018054915193511515760100000000000000000000000000000000000000000000027fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff9490930b61ffff1674010000000000000000000000000000000000000000027fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff959096169190961617929092169290921791909116179055565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052610bc89085906153e5565b600860ff16816001600160a01b031663d0d6153a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561466857600080fd5b505afa15801561467c573d6000803e3d6000fd5b505050506040513d602081101561469257600080fd5b505160ff16146146d35760405162461bcd60e51b815260040180806020018281038252602681526020018061591e6026913960400191505060405180910390fd5b600860ff16816001600160a01b031663f08e2a336040518163ffffffff1660e01b815260040160206040518083038186803b15801561471157600080fd5b505afa158015614725573d6000803e3d6000fd5b505050506040513d602081101561473b57600080fd5b505160ff1614610c6a5760405162461bcd60e51b8152600401808060200182810382526024815260200180615adf6024913960400191505060405180910390fd5b6001600160a01b0386166147d7576040805162461bcd60e51b815260206004820152601a60248201527f74686520706f6f6c20494420616c726561647920657869737473000000000000604482015290519081900360640190fd5b6001600160a01b03851661481c5760405162461bcd60e51b815260040180806020018281038252602b81526020018061581b602b913960400191505060405180910390fd5b6001600160a01b0383166148615760405162461bcd60e51b815260040180806020018281038252602c815260200180615b4c602c913960400191505060405180910390fd5b6001600160a01b0382166148a65760405162461bcd60e51b81526004018080602001828103825260258152602001806159446025913960400191505060405180910390fd5b6148af8561462a565b6040805160c0810182526001600160a01b03978816815295871660208088019182529588168783019081529488166060880190815293881660808801908152600193840b60a0890190815260009a8b52968a905291909820955186549088167fffffffffffffffffffffffff000000000000000000000000000000000000000091821617875597518683018054918916918a1691909117905592516002860180549188169189169190911790559051600385018054918716918816919091179055905160049093018054925190910b61ffff1674010000000000000000000000000000000000000000027fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff93909416919094161716179055565b6001600160a01b038216600090815260036020526040902054811115614a36576040805162461bcd60e51b815260206004820152601660248201527f696e73756666696369656e7420616c6c6f77616e636500000000000000000000604482015290519081900360640190fd5b6001600160a01b0390911660009081526003602052604090208054919091039055565b6118bc82826040518060600160405280602c8152602001615a20602c91396155bb565b6000816001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614ab957600080fd5b505af1158015614acd573d6000803e3d6000fd5b505050506040513d6020811015614ae357600080fd5b505192915050565b4290565b60008184841115614b7e5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015614b43578181015183820152602001614b2b565b50505050905090810190601f168015614b705780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000680100000000000000008210614bcf5760405162461bcd60e51b815260040180806020018281038252602681526020018061598a6026913960400191505060405180910390fd5b5090565b6000826001600160a01b031663c8f3e555836040518263ffffffff1660e01b8152600401808267ffffffffffffffff1667ffffffffffffffff16815260200191505060206040518083038186803b158015614c2d57600080fd5b505afa158015614c41573d6000803e3d6000fd5b505050506040513d6020811015614c5757600080fd5b505167ffffffffffffffff169392505050565b6000806000614c798887613ae2565b5050915050614c91614c8c6127fa614aeb565b6152e8565b9150506000606060007f000000000000000000000000a0d773221ca923fb48a0cf1b8309496d198cbfa16001600160a01b0316637e91c2e38b8a60006040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001838152602001826004811115614d0a57fe5b60ff168152602001935050505060006040518083038186803b158015614d2f57600080fd5b505afa158015614d43573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526060811015614d8a57600080fd5b81516020830151604080850180519151939592948301929184640100000000821115614db557600080fd5b908301906020820185811115614dca57600080fd5b8251866020820283011164010000000082111715614de757600080fd5b82525081516020918201928201910280838360005b83811015614e14578181015183820152602001614dfc565b5050505090500160405250505080945081955082935050505080614e7f576040805162461bcd60e51b815260206004820152601160248201527f756e6b6e6f776e20626f6e642074797065000000000000000000000000000000604482015290519081900360640190fd5b50876001600160a01b031663c29d90b58383614e9a8a6152e8565b614ea38a6152e8565b886040518663ffffffff1660e01b815260040180866004811115614ec357fe5b60ff16815260200180602001858152602001848152602001838152602001828103825286818151815260200191508051906020019060200280838360005b83811015614f19578181015183820152602001614f01565b505050509050019650505050505050604080518083038186803b158015614f3f57600080fd5b505afa925050508015614f6b57506040513d6040811015614f5f57600080fd5b50805160209091015160015b614f7b5760009350505050610ad7565b509350610ad792505050565b600082820183811015610a84576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6001600160a01b03861661503c576040805162461bcd60e51b815260206004820152601a60248201527f74686520706f6f6c20494420616c726561647920657869737473000000000000604482015290519081900360640190fd5b6001600160a01b0385166150815760405162461bcd60e51b81526004018080602001828103825260288152602001806158b16028913960400191505060405180910390fd5b6001600160a01b0384166150c65760405162461bcd60e51b81526004018080602001828103825260298152602001806159d36029913960400191505060405180910390fd5b6001600160a01b03831661510b5760405162461bcd60e51b81526004018080602001828103825260258152602001806159446025913960400191505060405180910390fd5b6040805160c0810182526001600160a01b039788168152958716602080880191825295881687830190815294881660608801908152600194850b6080890190815293151560a0890190815260009a8b529685905291909820955186549088167fffffffffffffffffffffffff000000000000000000000000000000000000000091821617875597518684018054918916918a169190911790559251600286018054918816918916919091179055915160039094018054925193511515760100000000000000000000000000000000000000000000027fffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffff9490920b61ffff1674010000000000000000000000000000000000000000027fffffffffffffffffffff0000ffffffffffffffffffffffffffffffffffffffff959096169290961691909117929092169290921791909116179055565b600081836152ad5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614b43578181015183820152602001614b2b565b5060008385816152b957fe5b0495945050505050565b6000610a8483836040518060600160405280602281526020016158d9602291396156fe565b60007f80000000000000000000000000000000000000000000000000000000000000008210614bcf5760405162461bcd60e51b8152600401808060200182810382526028815260200180615a8d6028913960400191505060405180910390fd5b6000806305f5e100851061537257630bebc2008511615367578461536d565b630bebc2005b615378565b6305f5e1005b905083810264e8d4a510006153b66000600187900b128061539f5750662386f26fc1000083105b6153a95782614c8c565b662386f26fc100006152e8565b8560010b02816153c257fe5b0592506305f5e10083136153d65782610bec565b6305f5e1009695505050505050565b6153f7826001600160a01b0316615774565b615448576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106154a457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101615467565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114615506576040519150601f19603f3d011682016040523d82523d6000602084013e61550b565b606091505b509150915081615562576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115610bc85780806020019051602081101561557e57600080fd5b5051610bc85760405162461bcd60e51b815260040180806020018281038252602a815260200180615ab5602a913960400191505060405180910390fd5b6155c4826157b0565b81906156115760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614b43578181015183820152602001614b2b565b506040516000906001600160a01b0385169084908381818185875af1925050503d806000811461565d576040519150601f19603f3d011682016040523d82523d6000602084013e615662565b606091505b50509050806156b8576040805162461bcd60e51b815260206004820152601960248201527f7472616e7366657272696e67204574686572206661696c656400000000000000604482015290519081900360640190fd5b6040805184815290516001600160a01b0386169130917fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9181900360200190a350505050565b60008361570d57506000610dd1565b818361575a5760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315614b43578181015183820152602001614b2b565b5082600185038161576757fe5b0460010190509392505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4708181148015906157a857508115155b949350505050565b3031101590565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a08101919091529056fe626f6e644d616b6572466f72557365722073686f756c64206265206e6f6e2d7a65726f2061646472657373646563696d616c20676170206e6565647320746f206265206c6f776572207468616e20313973776170506169724f7261636c6520686173206c6174657374507269636528292066756e6374696f6e2077686963682072657475726e73206e6f6e2d7a65726f2076616c75657377617050616972546f6b656e2073686f756c64206265206e6f6e2d7a65726f2061646472657373536166654d617468446976526f756e6455703a206d6f64756c6f206279207a65726f4552433230206f7261636c65207072696365206d757374206265206e6f6e2d7a65726f74686520646563696d616c73206f66206f7261636c65207072696365206d7573742062652038626f6e645072696365722073686f756c64206265206e6f6e2d7a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7753616665436173743a2076616c756520646f65736e27742066697420696e20363420626974736d757374207472616e73666572206e6f6e2d7a65726f20746f6b656e20616d6f756e7473776170506169724f7261636c652073686f756c64206265206e6f6e2d7a65726f20616464726573736574684f7261636c652073686f756c64206265206e6f6e2d7a65726f20616464726573735472616e736665724554483a207472616e7366657220616d6f756e7420657863656564732062616c616e63656574684f7261636c6520686173206c6174657374507269636528292066756e6374696f6e2077686963682072657475726e73206e6f6e2d7a65726f2076616c756553616665436173743a2076616c756520646f65736e27742066697420696e20616e20696e743235365361666545524332303a204552433230206f7065726174696f6e20646964206e6f74207375636365656474686520646563696d616c73206f6620626f6e6420746f6b656e206d757374206265203863616e6e6f742063616c63756c61746520746865207072696365206f66207468697320626f6e646d757374207472616e73666572206e6f6e2d7a65726f20626f6e6420616d6f756e74626f6e64507269636572466f72557365722073686f756c64206265206e6f6e2d7a65726f2061646472657373a26469706673582212207d46b6e6ab3d17a7a0bf149999e36885cb46e29bb984f9b0fb8158d023d86fd164736f6c63430006060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0000000000000000000000000c8bbb8d57cebf834dc429ec4d65dd23ed0d65a87000000000000000000000000ad491f460d8ee6df3335e8af48de33e0468cd8c9000000000000000000000000a0d773221ca923fb48a0cf1b8309496d198cbfa1
-----Decoded View---------------
Arg [0] : bondMakerAddress (address): 0xDA6FC5625E617bB92F5359921D43321cEbC6BEf0
Arg [1] : volatilityOracleAddress (address): 0xc8BBb8d57CEbF834DC429ec4D65DD23eD0d65a87
Arg [2] : volumeCalculatorAddress (address): 0xad491f460d8Ee6DF3335E8AF48de33E0468Cd8C9
Arg [3] : bondShapeDetector (address): 0xA0d773221cA923fb48A0Cf1B8309496D198CbfA1
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0
Arg [1] : 000000000000000000000000c8bbb8d57cebf834dc429ec4d65dd23ed0d65a87
Arg [2] : 000000000000000000000000ad491f460d8ee6df3335e8af48de33e0468cd8c9
Arg [3] : 000000000000000000000000a0d773221ca923fb48a0cf1b8309496d198cbfa1
Deployed Bytecode Sourcemap
119461:538:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80826:52;;;80868:9;80826:52;;;;80861:4;;80841:10;;80826:52;;;;;;;;;119461:538;;12:1:-1;9;2:12;54166:115:0;;5:9:-1;2:2;;;27:1;24;17:12;2:2;54166:115:0;;;:::i;:::-;;;;-1:-1:-1;;;;;54166:115:0;;;;;;;;;;;;;;100546:654;;5:9:-1;2:2;;;27:1;24;17:12;2:2;100546:654:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;100546:654:0;;;;;;;;;;;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;100546:654:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;100546:654:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;100546:654:0;;-1:-1:-1;100546:654:0;-1:-1:-1;100546:654:0;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;85709:199;;5:9:-1;2:2;;;27:1;24;17:12;2:2;85709:199:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;85709:199:0;;;;;;;;;;:::i;101286:186::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;101286:186:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;101286:186:0;;;;;;;:::i;54289:161::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;54289:161:0;;;:::i;85976:447::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;85976:447:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;;85976:447:0;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;88219:156::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;88219:156:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;88219:156:0;-1:-1:-1;;;;;88219:156:0;;:::i;87811:97::-;;;:::i;:::-;;87337:350;;5:9:-1;2:2;;;27:1;24;17:12;2:2;87337:350:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;87337:350:0;;:::i;:::-;;;;-1:-1:-1;;;;;87337:350:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101572:216;;5:9:-1;2:2;;;27:1;24;17:12;2:2;101572:216:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;101572:216:0;;;;;;;;;;:::i;65884:481::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;65884:481:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;65884:481:0;;;;;;;;;;;;;;;;;;;;;;:::i;86499:478::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;86499:478:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;86499:478:0;;;-1:-1:-1;;;;;86499:478:0;;;;;;;;;;;;;;;;;;;;;:::i;84080:404::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;84080:404:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;84080:404:0;;;;;;;;;;;;;;;;;;;;;;:::i;101857:600::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;101857:600:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;;101857:600:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;87045:223::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;87045:223:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;87045:223:0;;:::i;103484:467::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;103484:467:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;103484:467:0;;:::i;:::-;;;;-1:-1:-1;;;;;103484:467:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87978:169;;5:9:-1;2:2;;;27:1;24;17:12;2:2;87978:169:0;;;:::i;69194:229::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;69194:229:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;69194:229:0;;:::i;104107:846::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;104107:846:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;104107:846:0;;;;;;;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;104107:846:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;104107:846:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;104107:846:0;;-1:-1:-1;104107:846:0;-1:-1:-1;104107:846:0;;;;;;-1:-1:-1;;;;;104107:846:0;;:::i;66847:489::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;66847:489:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;66847:489:0;;;;;;;;;;;;;;;;;;;;;;:::i;68029:527::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;68029:527:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;;;;;;68029:527:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;67712:247::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;67712:247:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;;;;;67712:247:0;;;;;;;;;;;;;;;;;;;:::i;102533:588::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;102533:588:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;102533:588:0;;;-1:-1:-1;;;;;102533:588:0;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;68632:494::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;68632:494:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;68632:494:0;;;-1:-1:-1;;;;;68632:494:0;;;;;;;;;;;;;;;;;;;;;:::i;84935:402::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;84935:402:0;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;84935:402:0;;;;;;;;;;;;;;;;;;;;;;:::i;69492:395::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;69492:395:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;69492:395:0;;:::i;:::-;;;;-1:-1:-1;;;;;69492:395:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67422:190;;5:9:-1;2:2;;;27:1;24;17:12;2:2;67422:190:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;67422:190:0;;;;;;;:::i;103189:226::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;103189:226:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;103189:226:0;;:::i;85423:186::-;;5:9:-1;2:2;;;27:1;24;17:12;2:2;85423:186:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;85423:186:0;;;;;;;:::i;54166:115::-;54255:18;54166:115;;:::o;100546:654::-;100779:18;;100836:112;100867:17;100899:1;98703:52;100836:16;:112::i;:::-;100810:138;;100972:149;101006:10;101031:6;101052;101073:7;;100972:149;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;101095:15:0;;-1:-1:-1;100972:19:0;;-1:-1:-1;;100972:149:0:i;:::-;100959:162;;101132:60;101158:10;101170:14;101186:5;101132:25;:60::i;:::-;100546:654;;;;;;;;;;:::o;85709:199::-;85821:14;85860:40;85881:6;85889:10;85860:20;:40::i;:::-;85853:47;;85709:199;;;;;:::o;101286:186::-;101381:14;101430:34;101449:6;101457;101430:18;:34::i;:::-;-1:-1:-1;101413:51:0;;101286:186;-1:-1:-1;;;;;101286:186:0:o;54289:161::-;54425:17;54289:161;:::o;85976:447::-;86180:14;86227:188;86262:10;86291:16;86326:17;86362:9;86390:10;86227:16;:188::i;:::-;86207:208;85976:447;-1:-1:-1;;;;;85976:447:0:o;88219:156::-;-1:-1:-1;;;;;88347:20:0;88306:14;88347:20;;;:13;:20;;;;;;;88219:156::o;87811:97::-;87861:39;87878:10;87890:9;87861:16;:39::i;:::-;87811:97::o;87337:350::-;87439:14;87468:43;87526:37;87578:15;87608;87658:21;87672:6;87658:13;:21::i;:::-;87651:28;;;;-1:-1:-1;87651:28:0;;-1:-1:-1;87651:28:0;-1:-1:-1;87651:28:0;;-1:-1:-1;87337:350:0;-1:-1:-1;;87337:350:0:o;101572:216::-;101694:14;101733:47;101755:6;101763:16;101733:21;:47::i;65884:481::-;66078:18;66122:127;66157:10;66182:6;66203;66224:14;66122:20;:127::i;:::-;66109:140;;66297:60;66323:10;66335:14;66351:5;66297:25;:60::i;86499:478::-;86726:18;;;;:10;:18;;;;;:25;-1:-1:-1;;;;;86726:25:0;86755:10;86726:39;86704:117;;;;;-1:-1:-1;;;86704:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;86834:135;86865:6;86886:16;86917:17;86949:9;86834:16;:135::i;:::-;86499:478;;;;:::o;84080:404::-;84267:18;84311:57;84330:10;84342:6;84350;84358:9;84311:18;:57::i;101857:600::-;102150:14;102197:252;102233:10;102262:23;102304;102346:24;102389:17;102425:9;102197:17;:252::i;:::-;102177:272;101857:600;-1:-1:-1;;;;;;101857:600:0:o;87045:223::-;87128:18;;;;:10;:18;;;;;:25;-1:-1:-1;;;;;87128:25:0;87157:10;87128:39;87106:117;;;;;-1:-1:-1;;;87106:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;87236:24;87253:6;87236:16;:24::i;:::-;87045:223;:::o;103484:467::-;103587:14;103616:42;103673;103730:44;103789:37;103841:15;103871;103921:22;103936:6;103921:14;:22::i;:::-;103914:29;;;;-1:-1:-1;103914:29:0;;-1:-1:-1;103914:29:0;;-1:-1:-1;103914:29:0;-1:-1:-1;103914:29:0;-1:-1:-1;103914:29:0;;-1:-1:-1;103484:467:0;-1:-1:-1;;103484:467:0:o;87978:169::-;88069:10;88019:14;88055:25;;;:13;:25;;;;;;;88091:48;;88069:10;88055:25;88091:16;:48::i;69194:229::-;69279:20;;;;:12;:20;;;;;:27;-1:-1:-1;;;;;69279:27:0;69310:10;69279:41;69257:119;;;;;-1:-1:-1;;;69257:119:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;69389:26;69408:6;69389:18;:26::i;104107:846::-;104279:28;104350:35;104400:42;104457:37;104541:22;104556:6;104541:14;:22::i;:::-;104320:243;;;;;;;;;;104574:26;104603:195;104637:16;104668;104699:17;104731:7;;104603:195;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;104753:14:0;;-1:-1:-1;104782:5:0;;-1:-1:-1;104603:19:0;;-1:-1:-1;104603:195:0:i;:::-;104574:224;-1:-1:-1;104832:113:0;104574:224;98703:52;53006:1;104832:16;:113::i;:::-;104809:136;104107:846;-1:-1:-1;;;;;;;;;;104107:846:0:o;66847:489::-;67037:22;67089:123;67124:10;67149:6;67170;67191:10;67089:20;:123::i;68029:527::-;68272:14;68319:229;68356:10;68385:15;68419:21;68459:17;68495:9;68523:10;68319:18;:229::i;67712:247::-;67858:14;67892:59;67915:6;67923:15;67940:10;67892:22;:59::i;:::-;67885:66;;67712:247;;;;;;:::o;102533:588::-;102822:11;:19;;;;;;;;;;:26;-1:-1:-1;;;;;102822:26:0;102852:10;102822:40;102800:118;;;;;-1:-1:-1;;;102800:118:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;102931:182;102963:6;102984:23;103022:24;103061:17;103093:9;102931:17;:182::i;:::-;102533:588;;;;;:::o;68632:494::-;68866:20;;;;:12;:20;;;;;:27;-1:-1:-1;;;;;68866:27:0;68897:10;68866:41;68844:119;;;;;-1:-1:-1;;;68844:119:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;68976:142;69009:6;69030:21;69066:17;69098:9;68976:18;:142::i;84935:402::-;85123:17;85165:58;85184:10;85196:6;85204;85212:10;85165:18;:58::i;69492:395::-;69596:14;69625:21;69661:48;69724:37;69776:15;69806;69856:23;69872:6;69856:15;:23::i;:::-;69849:30;;;;-1:-1:-1;69849:30:0;;-1:-1:-1;69849:30:0;-1:-1:-1;69849:30:0;-1:-1:-1;69849:30:0;;-1:-1:-1;69492:395:0;-1:-1:-1;;69492:395:0:o;67422:190::-;67519:14;67568:36;67589:6;67597;67568:20;:36::i;103189:226::-;103273:11;:19;;;;;;;;;;:26;-1:-1:-1;;;;;103273:26:0;103303:10;103273:40;103251:118;;;;;-1:-1:-1;;;103251:118:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;103382:25;103400:6;103382:17;:25::i;85423:186::-;85518:14;85567:34;85586:6;85594;85567:18;:34::i;55812:669::-;55960:19;55992:9;56012;56055:15;56038:32;;:14;:32;;;56034:208;;;-1:-1:-1;56087:36:0;56091:32;;;56087:36;56034:208;;;56162:15;56145:32;;:14;:32;;;56141:101;;;56216:14;56198:15;:32;56194:36;;;;56141:101;56369:2;56365:1;:6;:16;;;;;56379:2;56375:1;:6;56365:16;56357:66;;;;-1:-1:-1;;;56357:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56441:32;56471:1;56467:2;:5;56441:21;56460:1;56456:2;:5;56441:10;:14;;:21;;;;:::i;:::-;:25;:32;:25;:32;:::i;105450:2784::-;105647:18;105686:7;:14;105704:1;105686:19;;105678:60;;;;;-1:-1:-1;;;105678:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;105751:35;105812:15;105885:22;105900:6;105885:14;:22::i;:::-;105842:65;;-1:-1:-1;105842:65:0;;-1:-1:-1;105842:65:0;;-1:-1:-1;105922:51:0;;-1:-1:-1;;;;105922:51:0;;;;-1:-1:-1;;;105922:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;105450:2784;105998:15;106015:16;106039:73;106062:18;106095:6;106039:8;:73::i;:::-;-1:-1:-1;105997:115:0;;-1:-1:-1;105997:115:0;-1:-1:-1;;;;;;;106131:32:0;;106123:71;;;;;-1:-1:-1;;;106123:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;106223:14;106247:34;106266:6;106274;106247:18;:34::i;:::-;106222:59;;;;;52424:16;106322:6;:29;106296:117;;;;;-1:-1:-1;;;106296:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;52496:15;106454:6;:29;106428:117;;;;;-1:-1:-1;;;106428:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;106775:6;106590:165;106629:15;53006:1;52782;98703:52;106712:9;-1:-1:-1;;;;;106712:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;106712:20:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;106712:20:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;106712:20:0;106735:1;106712:24;106590:16;:165::i;:::-;:191;;;;;;;-1:-1:-1;106804:15:0;106796:62;;;;-1:-1:-1;;;106796:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105450:2784;106916:14;106968:42;107029:37;107125:22;107140:6;107125:14;:22::i;:::-;106897:250;;;;;;;;;;107188:9;-1:-1:-1;;;;;107188:22:0;;107211:6;107219:5;107226:10;107188:49;;;;;;;;;;;;;-1:-1:-1;;;;;107188:49:0;-1:-1:-1;;;;;107188:49:0;;;;;;-1:-1:-1;;;;;107188:49:0;-1:-1:-1;;;;;107188:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;107188:49:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;107188:49:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;107188:49:0;107162:133;;;;;-1:-1:-1;;;107162:133:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;107331:5;107412:15;107500:321;107545:16;107584;107623:17;107663:7;107693:8;107331:5;107755:6;107412:15;107500:22;:321::i;:::-;107474:411;;;;;-1:-1:-1;;;107474:411:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;105450:2784;;;;;107909:16;107928:110;107959:15;53006:1;52782;98703:52;108026:1;107928:16;:110::i;:::-;108054:172;;;;;;;;;;;;;;;;;;;;107909:129;;-1:-1:-1;108131:6:0;;108110;;-1:-1:-1;;;;;108054:172:0;;;;;;;;;;;;105450:2784;;;;;;;;;;;:::o;59340:361::-;59499:19;;59495:199;;59605:14;59561:40;59596:4;59561:30;:12;59578;;;59561:30;:16;:30;:::i;:40::-;:58;;59535:147;;;;;-1:-1:-1;;;59535:147:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;59340:361;;;:::o;93864:388::-;94057:172;;;94143:4;94057:172;;;;-1:-1:-1;;;;;94057:172:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;94057:172:0;;;;;;;94029:215;;;;;;93864:388::o;108242:732::-;108352:14;108381:19;108415:23;108453:15;108571:30;108616:15;108648:22;108663:6;108648:14;:22::i;:::-;108496:174;;;;;;;;;108707:104;108745:10;108770:6;108791:9;108707:23;:104::i;:::-;108681:130;;-1:-1:-1;108681:130:0;-1:-1:-1;108836:26:0;108681:130;108836:13;:26::i;:::-;108822:40;-1:-1:-1;108891:5:0;;-1:-1:-1;108891:5:0;108916:42;108822:40;108940:16;;;108916:42;:15;:42;:::i;:::-;:50;;;;;;108907:59;;108242:732;;;;;;;;;:::o;95062:1166::-;95278:14;95314:40;95335:6;95343:10;95314:20;:40::i;:::-;95424:1;95387:18;;;:10;:18;;;;;:25;95305:49;;-1:-1:-1;;;;;;95387:25:0;:39;95365:115;;;;;-1:-1:-1;;;95365:115:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;95508:13;95524:9;-1:-1:-1;;;;;95524:21:0;;:23;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;95524:23:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;95524:23:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;95524:23:0;;-1:-1:-1;95588:10:0;95562:137;;;;-1:-1:-1;;;95562:137:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95062:1166;95723:164;95751:6;95772;95793:9;95817:10;95842:9;95866:10;95723:13;:164::i;:::-;95904:10;95900:162;;;95936:38;;-1:-1:-1;;;;;95936:38:0;;;95959:6;;95936:38;;;;;95900:162;;;96012:38;;-1:-1:-1;;;;;96012:38:0;;;96035:6;;96012:38;;;;;95900:162;96079:141;;;-1:-1:-1;;;;;96079:141:0;;;;;;;;;;;;;;;;;;;;;;;96112:6;;96079:141;;;;;;;;;;95062:1166;;;;;;;:::o;97927:190::-;-1:-1:-1;;;;;98005:21:0;;;;;;:13;:21;;;;;:31;;;;;;;;98055;-1:-1:-1;98055:31:0;98047:62;;;;;-1:-1:-1;;;98047:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;97927:190;;:::o;97069:620::-;97210:14;83496:18;;;:10;:18;;;;;:25;97210:14;;;;;;;;97170:6;;-1:-1:-1;;;;;83496:25:0;83474:121;;;;;-1:-1:-1;;;83474:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97408:29:::1;;:::i;:::-;-1:-1:-1::0;;;97440:18:0::1;::::0;;;-1:-1:-1;;97440:10:0::1;:18;::::0;;;;;;;;97408:50;;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;97408:50:0;;::::1;::::0;;;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;;;;::::1;::::0;;;::::1;::::0;;;;;;;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;;;;::::1;;;;;::::0;;;;;;;;;;;;-1:-1:-1;97408:50:0;-1:-1:-1;97069:620:0:o;108982:404::-;109185:178;;;109271:4;109185:178;;;;-1:-1:-1;;;;;109185:178:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;109185:178:0;;;;;;;109157:221;;;;;;108982:404::o;70371:1972::-;70533:18;70579:14;70608:19;70687:15;70716:23;70732:6;70716:15;:23::i;:::-;70564:175;;;;;;;;;70758:10;70750:51;;;;;-1:-1:-1;;;70750:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;70815:15;70840:36;70849:18;70869:6;70840:8;:36::i;:::-;-1:-1:-1;70814:62:0;;-1:-1:-1;;;;;;;;70895:32:0;;70887:71;;;;;-1:-1:-1;;;70887:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;70971:16;71032:14;71084:23;71128:36;71149:6;71157;71128:20;:36::i;:::-;71013:151;;;;;;52424:16;71205:6;:29;71179:117;;;;;-1:-1:-1;;;71179:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;52496:15;71337:6;:29;71311:117;;;;;-1:-1:-1;;;71311:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;71443:24;71470:13;-1:-1:-1;;;;;71470:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;71470:24:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;71470:24:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;71470:24:0;;-1:-1:-1;71715:6:0;71539:156;71578:14;71470:24;71656:20;71539:16;:156::i;:::-;:182;;;;;;;-1:-1:-1;71744:15:0;71736:62;;;;-1:-1:-1;;;71736:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71824:104;71886:27;;;71882:2;:31;71824:35;:15;71844:14;71824:35;:19;:35;:::i;:104::-;71813:115;;70371:1972;;;71974:9;-1:-1:-1;;;;;71974:22:0;;71997:6;72005:5;72012:10;71974:49;;;;;;;;;;;;;-1:-1:-1;;;;;71974:49:0;-1:-1:-1;;;;;71974:49:0;;;;;;-1:-1:-1;;;;;71974:49:0;-1:-1:-1;;;;;71974:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;71974:49:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;71974:49:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;71974:49:0;71952:121;;;;;-1:-1:-1;;;71952:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;72084:61;-1:-1:-1;;;;;72084:30:0;;72115:5;72122:6;72130:14;72084:61;:30;:61;:::i;:::-;72163:172;;;;;;;;;;;;;;;;;;;;72241:6;;72220;;-1:-1:-1;;;;;72163:172:0;;;;;;;;;;;;;70371:1972;;;;;;;;;;;:::o;96236:626::-;83533:1;83496:18;;;:10;:18;;;;;:25;96438:6;;-1:-1:-1;;;;;83496:25:0;83474:121;;;;;-1:-1:-1;;;83474:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96458:14:::1;96480:15:::0;96499:21:::1;96513:6;96499:13;:21::i;:::-;96457:63;;;;;;;96531:164;96559:6;96580;96601:9;96625:10;96650:9;96674:10;96531:13;:164::i;:::-;96713:141;::::0;;-1:-1:-1;;;;;96713:141:0;;::::1;::::0;;;::::1;;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;96746:6;;96713:141:::1;::::0;;;;;;;;::::1;83606:1;;96236:626:::0;;;;;:::o;88843:1750::-;89003:18;89035:14;89057:15;89076:21;89090:6;89076:13;:21::i;:::-;89034:63;;;;;;;89116:10;89108:51;;;;;-1:-1:-1;;;89108:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;89173:15;89198:36;89207:18;89227:6;89198:8;:36::i;:::-;-1:-1:-1;89172:62:0;;-1:-1:-1;;;;;;;;89253:32:0;;89245:71;;;;;-1:-1:-1;;;89245:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;89329:16;89372:14;89390:23;89419:83;89456:6;89481;89419:18;:83::i;:::-;89371:131;;;;;;52424:16;89543:6;:29;89517:117;;;;;-1:-1:-1;;;89517:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;52496:15;89675:6;:29;89649:117;;;;;-1:-1:-1;;;89649:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;89984:6;89811:153;89850:14;82012:2;89925:20;89811:16;:153::i;:::-;:179;;;;;;;-1:-1:-1;90013:15:0;90005:62;;;;-1:-1:-1;;;90005:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90093:101;90151:28;90093:35;:15;90113:14;90093:35;:19;:35;:::i;:101::-;90240:49;;;;;;-1:-1:-1;;;;;90240:49:0;;;;;;;;;;;;;;;;;;;;;;90082:112;;-1:-1:-1;90240:22:0;;;;-1:-1:-1;90240:22:0;;-1:-1:-1;90240:49:0;;;;;;;;;;;;;;;-1:-1:-1;90240:22:0;:49;;;2:2:-1;;;;27:1;24;17:12;2:2;90240:49:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;90240:49:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;90240:49:0;90218:121;;;;;-1:-1:-1;;;90218:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;90350:47;90367:5;90374:6;90382:14;90350:16;:47::i;:::-;90415:170;;;;;;;;;;;;;;;;;;;;90491:6;;90470;;-1:-1:-1;;;;;90415:170:0;;;;;;;;;;;;;88843:1750;;;;;;;;;;:::o;110562:1044::-;110853:14;110889:56;110911:6;110927:16;110889:21;:56::i;:::-;111016:1;110978:19;;;;;;;;;;:26;110880:65;;-1:-1:-1;;;;;;110978:26:0;:40;110956:116;;;;;-1:-1:-1;;;110956:116:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;111085:42;111110:16;111085:24;:42::i;:::-;111138:210;111167:6;111188;111209:16;111240;111271:17;111303:10;111328:9;111138:14;:210::i;:::-;111414:16;-1:-1:-1;;;;;111366:66:0;111398:6;-1:-1:-1;;;;;111366:66:0;111390:6;111366:66;;;;;;;;;;111448:150;;;-1:-1:-1;;;;;111448:150:0;;;;;;;;;;;;;;;;;;;;;;;111482:6;;111448:150;;;;;;;;;;110562:1044;;;;;;;;:::o;96870:191::-;83533:1;83496:18;;;:10;:18;;;;;:25;96960:6;;-1:-1:-1;;;;;83496:25:0;83474:121;;;;;-1:-1:-1;;;83474:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96991:18:::1;::::0;;;:10:::1;:18;::::0;;;;;;;96984:25;;;;;::::1;::::0;;;;::::1;::::0;;;;::::1;::::0;;;;::::1;::::0;;;;;;97027:26;97002:6;;97027:26:::1;::::0;::::1;96870:191:::0;;:::o;112677:847::-;112820:14;99916:19;;;;;;;;;;:26;112820:14;;;;;;;;;;;;112780:6;;-1:-1:-1;;;;;99916:26:0;99894:122;;;;;-1:-1:-1;;;99894:122:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;113126:30:::1;;:::i;:::-;-1:-1:-1::0;;;113159:11:0::1;:19:::0;;;-1:-1:-1;;;113159:19:0::1;::::0;;;;;;;;113126:52;;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;113126:52:0;;::::1;::::0;;;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;;;;;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;;;;;;;;;;-1:-1:-1;113126:52:0;;-1:-1:-1;113126:52:0;-1:-1:-1;113126:52:0;112677:847::o;97697:222::-;97828:32;97845:6;97853;97828:16;:32::i;:::-;97871:40;97892:9;97904:6;97871:12;:40::i;79698:199::-;65316:1;65277:20;;;:12;:20;;;;;:27;79792:6;;-1:-1:-1;;;;;65277:27:0;65255:123;;;;;-1:-1:-1;;;65255:123:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79823:20:::1;::::0;;;:12:::1;:20;::::0;;;;;;;79816:27;;;;;::::1;::::0;;;;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;;;;79861:28;79836:6;;79861:28:::1;::::0;::::1;79698:199:::0;;:::o;116238:1713::-;116518:26;116557:21;116581:42;116597:9;-1:-1:-1;;;;;116597:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;116597:25:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;116597:25:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;116597:25:0;116581:15;:42::i;:::-;116557:66;-1:-1:-1;116641:9:0;116636:1308;116660:7;:14;116656:1;:18;116636:1308;;;116696:10;116721:19;116774:16;116832:31;116841:9;116852:7;116860:1;116852:10;;;;;;;;;;;;;;116832:8;:31::i;:::-;-1:-1:-1;116809:54:0;;-1:-1:-1;116809:54:0;-1:-1:-1;;116886:25:0;;;116882:39;;;116913:8;;;;;116882:39;116948:21;116972:134;117007:23;:21;:23::i;:::-;116972:134;;;;;;;;;;;;;;;;;;:8;;:134;;:12;:134;:::i;:::-;116948:158;;117139:119;117176:16;117215:24;:13;:22;:24::i;:::-;117139:14;:119::i;:::-;117125:133;;116636:1308;;117290:15;117308:4;-1:-1:-1;;;;;117308:14:0;;117323:6;117308:22;;;;;;;;;;;;;-1:-1:-1;;;;;117308:22:0;-1:-1:-1;;;;;117308:22:0;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;117308:22:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;117308:22:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;117308:22:0;;-1:-1:-1;117353:12:0;117345:49;;;;;-1:-1:-1;;;117345:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;117431:37;;;;;;-1:-1:-1;;;;;117431:37:0;;;;;;;117462:4;117431:37;;;;;;117411:17;;117431:14;;;;;:37;;;;;;;;;;;;;;:14;:37;;;2:2:-1;;;;27:1;24;17:12;2:2;117431:37:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;117431:37:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;117431:37:0;;-1:-1:-1;117491:14:0;117483:52;;;;;-1:-1:-1;;;117483:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;117552:17;117572:177;117605:9;117633:10;117662:7;117670:1;117662:10;;;;;;;;;;;;;;117691:13;117723:11;117572:14;:177::i;:::-;117552:197;-1:-1:-1;117772:14:0;117764:50;;;;;-1:-1:-1;;;117764:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;117852:80;117893:24;:9;117907;117893:24;:13;:24;:::i;:::-;117852:18;;:80;:22;:80;:::i;:::-;117831:101;;116636:1308;;;;;;116676:3;;116636:1308;;;;116238:1713;;;;;;;;;:::o;72823:1903::-;72981:22;73031:14;73060:19;73139:15;73168:23;73184:6;73168:15;:23::i;:::-;73016:175;;;;;;;;;73211:10;73210:11;73202:56;;;;;-1:-1:-1;;;73202:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73272:15;73297:36;73306:18;73326:6;73297:8;:36::i;:::-;-1:-1:-1;73271:62:0;;-1:-1:-1;;;;;;;;73352:32:0;;73344:71;;;;;-1:-1:-1;;;73344:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;73428:16;73471:14;73487:19;73514:85;73553:6;73578;73514:20;:85::i;:::-;73470:129;;;;;;52424:16;73640:6;:29;73614:117;;;;;-1:-1:-1;;;73614:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;52496:15;73772:6;:29;73746:117;;;;;-1:-1:-1;;;73746:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;73878:24;73905:13;-1:-1:-1;;;;;73905:22:0;;:24;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;73905:24:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;73905:24:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;73905:24:0;;-1:-1:-1;73961:148:0;73996:22;:10;74011:6;73996:22;:14;:22;:::i;:::-;74037:20;74076:18;73961:16;:148::i;:::-;73944:165;-1:-1:-1;74132:19:0;74124:67;;;;-1:-1:-1;;;74124:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74217:94;74267:29;74217:27;:11;74233:10;74217:27;:15;:27;:::i;:94::-;74206:105;;72823:1903;;;74357:9;-1:-1:-1;;;;;74357:22:0;;74380:5;74387:6;74395:10;74357:49;;;;;;;;;;;;;-1:-1:-1;;;;;74357:49:0;-1:-1:-1;;;;;74357:49:0;;;;;;-1:-1:-1;;;;;74357:49:0;-1:-1:-1;;;;;74357:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;74357:49:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;74357:49:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;74357:49:0;74335:121;;;;;-1:-1:-1;;;74335:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;74467:61;-1:-1:-1;;;;;74467:30:0;;74498:6;74506:5;74513:14;74467:61;:30;:61;:::i;:::-;74546:172;;;;;;;;;;;;;;;;;;;;74624:6;;74603;;-1:-1:-1;;;;;74546:172:0;;;;;;;;;;;;;72823:1903;;;;;;;;;;;:::o;77373:1520::-;77626:14;77662:116;77699:6;77728:13;77757:10;77662:22;:116::i;:::-;77850:1;77811:20;;;:12;:20;;;;;:27;77653:125;;-1:-1:-1;;;;;;77811:27:0;:41;77789:117;;;;;-1:-1:-1;;;77789:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;77934:13;77950:31;77966:14;77950:15;:31::i;:::-;77934:47;-1:-1:-1;78022:10:0;77996:142;;;;-1:-1:-1;;;77996:142:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77373:1520;78162:199;78192:6;78213;78234:13;78262:14;78291:10;78316:9;78340:10;78162:15;:199::i;:::-;78378:10;78374:346;;;78511:13;-1:-1:-1;;;;;78410:130:0;78478:6;-1:-1:-1;;;;;78410:130:0;78453:6;78410:130;;;;;;;;;;78374:346;;;78679:13;-1:-1:-1;;;;;78578:130:0;78646:6;-1:-1:-1;;;;;78578:130:0;78621:6;78578:130;;;;;;;;;;78374:346;78737:148;;;-1:-1:-1;;;;;78737:148:0;;;;;;;;;;;;;;;;;;;;;;;78772:6;;78737:148;;;;;;;;;;77373:1520;;;;;;;;:::o;75865:457::-;76087:212;;;76175:4;76087:212;;;;-1:-1:-1;;;;;76087:212:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;76087:212:0;;;;;;;76059:255;;;;;;75865:457::o;111614:852::-;99954:1;99916:19;;;;;;;;;;:26;111872:6;;-1:-1:-1;;;;;99916:26:0;99894:122;;;;;-1:-1:-1;;;99894:122:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;111906:14:::1;111935:35:::0;112047:22:::1;112062:6;112047:14;:22::i;:::-;111891:178;;;;;;;;;112080:210;112109:6;112130;112151:16;112182;112213:17;112245:10;112270:9;112080:14;:210::i;:::-;112308:150;::::0;;-1:-1:-1;;;;;112308:150:0;;::::1;::::0;;;::::1;;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;112342:6;;112308:150:::1;::::0;;;;;;;;::::1;100027:1;;111614:852:::0;;;;;;:::o;78901:789::-;65316:1;65277:20;;;:12;:20;;;;;:27;79112:6;;-1:-1:-1;;;;;65277:27:0;65255:123;;;;;-1:-1:-1;;;65255:123:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79146:14:::1;79175:19:::0;79254:15:::1;79283:23;79299:6;79283:15;:23::i;:::-;79131:175;;;;;;;;;79317:199;79347:6;79368;79389:13;79417:14;79446:10;79471:9;79495:10;79317:15;:199::i;:::-;79534:148;::::0;;-1:-1:-1;;;;;79534:148:0;;::::1;::::0;;;::::1;;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;79569:6;;79534:148:::1;::::0;;;;;;;;::::1;65389:1;;;78901:789:::0;;;;;:::o;91046:1702::-;91202:22;91238:14;91260:15;91279:21;91293:6;91279:13;:21::i;:::-;91237:63;;;;;;;91320:10;91319:11;91311:56;;;;;-1:-1:-1;;;91311:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91381:15;91406:36;91415:18;91435:6;91406:8;:36::i;:::-;-1:-1:-1;91380:62:0;;-1:-1:-1;;;;;;;;91461:32:0;;91453:71;;;;;-1:-1:-1;;;91453:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;91537:16;91580:14;91596:19;91623:83;91660:6;91685;91623:18;:83::i;:::-;91579:127;;;;;;52424:16;91747:6;:29;91721:117;;;;;-1:-1:-1;;;91721:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;52496:15;91879:6;:29;91853:117;;;;;-1:-1:-1;;;91853:117:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;92002:145;92037:22;:10;92052:6;92037:22;:14;:22;:::i;:::-;92078:20;82012:2;92002:16;:145::i;:::-;91985:162;-1:-1:-1;92170:19:0;92162:67;;;;-1:-1:-1;;;92162:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92255:94;92305:29;92255:27;:11;92271:10;92255:27;:15;:27;:::i;:94::-;92395:49;;;;;;-1:-1:-1;;;;;92395:49:0;;;;;;;;;;;;;;;;;;;;;;92244:105;;-1:-1:-1;92395:22:0;;;;-1:-1:-1;92395:22:0;;-1:-1:-1;92395:49:0;;;;;;;;;;;;;;;-1:-1:-1;92395:22:0;:49;;;2:2:-1;;;;27:1;24;17:12;2:2;92395:49:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;92395:49:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;92395:49:0;92373:121;;;;;-1:-1:-1;;;92373:121:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;92505:47;92522:6;92530:5;92537:14;92505:16;:47::i;:::-;92570:170;;;;;;;;;;;;;;;;;;;;92646:6;;92625;;-1:-1:-1;;;;;92570:170:0;;;;;;;;;;;;;91046:1702;;;;;;;;;;:::o;79905:730::-;80050:14;65277:20;;;:12;:20;;;;;:27;80050:14;;;;;;;;;;80010:6;;-1:-1:-1;;;;;65277:27:0;65255:123;;;;;-1:-1:-1;;;65255:123:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80287:31:::1;;:::i;:::-;-1:-1:-1::0;;;80321:20:0::1;::::0;;;-1:-1:-1;;80321:12:0::1;:20;::::0;;;;;;;;80287:54;;::::1;::::0;::::1;::::0;;;;-1:-1:-1;;;;;80287:54:0;;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;;;;;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;;;;::::1;;;;;::::0;;;;;;;;;;;;-1:-1:-1;80287:54:0;;-1:-1:-1;80287:54:0;-1:-1:-1;79905:730:0:o;74734:1123::-;74846:14;74875:19;74909:23;74947:15;75035:38;75088:30;75133:15;75163;75192:23;75208:6;75192:15;:23::i;:::-;74990:225;;;;;;;;;;75244:28;75260:11;75244:15;:28::i;:::-;75226:46;;75309:104;75347:10;75372:6;75393:9;75309:23;:104::i;:::-;75283:130;;-1:-1:-1;75283:130:0;-1:-1:-1;75438:26:0;75283:130;75438:13;:26::i;:::-;75424:40;;75484:119;75525:15;75484:119;;;;;;;;;;;;;;;;;:22;:11;75500:5;75484:22;:15;:22;:::i;:::-;:26;:119;;:26;:119;:::i;:::-;75475:128;;75670:10;75666:184;;;75746:5;75706:37;:6;75725:16;;;75706:37;:10;:37;:::i;:::-;:45;;;;;;75697:54;;75666:184;;;75829:8;75821:5;:16;75793:17;75804:5;75793:6;:10;;:17;;;;:::i;:::-;:45;;;;;;75784:54;;75666:184;74734:1123;;;;;;;;;;;:::o;112474:195::-;99954:1;99916:19;;;;;;;;;;:26;112566:6;;-1:-1:-1;;;;;99916:26:0;99894:122;;;;;-1:-1:-1;;;99894:122:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;112597:11:::1;:19:::0;;;::::1;::::0;;;;;;;112590:26;;;;;::::1;::::0;;;;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;::::1;;::::0;;;;;;112634:27;112609:6;;112634:27:::1;::::0;::::1;112474:195:::0;;:::o;92756:1100::-;92866:14;92895:19;92929:23;92967:15;93040:36;93091:30;93136:15;93166;93195:21;93209:6;93195:13;:21::i;:::-;93010:206;;;;;;;;;93245:26;93261:9;93245:15;:26::i;:::-;93227:44;;93308:104;93346:10;93371:6;93392:9;93308:23;:104::i;:::-;93282:130;;-1:-1:-1;93282:130:0;-1:-1:-1;93437:26:0;93282:130;93437:13;:26::i;:::-;93423:40;;93483:119;93524:15;93483:119;;;;;;;;;;;;;;;;;:22;:11;93499:5;93483:22;:15;:22;:::i;:119::-;93474:128;;93669:10;93665:184;;;93745:5;93705:37;:6;93724:16;;;93705:37;:10;:37;:::i;93665:184::-;93832:5;93792:37;:6;93811:16;;;93792:37;:10;:37;:::i;6157:471::-;6215:7;6460:6;6456:47;;-1:-1:-1;6490:1:0;6483:8;;6456:47;6527:5;;;6531:1;6527;:5;:1;6551:5;;;;;:10;6543:56;;;;-1:-1:-1;;;6543:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7096:132;7154:7;7181:39;7185:1;7188;7181:39;;;;;;;;;;;;;;;;;:3;:39::i;55221:505::-;55349:15;55379:16;55410:22;55447:15;55490:24;55581:9;-1:-1:-1;;;;;55581:31:0;;55613:6;55581:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;55581:39:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;55581:39:0;;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;55581:39:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;55525:95:0;;;;;-1:-1:-1;55581:39:0;-1:-1:-1;55221:505:0;-1:-1:-1;;;;55221:505:0:o;113656:2429::-;114001:7;114021:21;114045:42;114061:9;-1:-1:-1;;;;;114061:23:0;;:25;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;114045:42:0;114021:66;-1:-1:-1;114115:15:0;114100:12;114152:1876;114176:7;:14;114172:1;:18;114152:1876;;;114212:10;114237:19;114290:16;114348:31;114357:9;114368:7;114376:1;114368:10;;;;;;;114348:31;-1:-1:-1;114325:54:0;;-1:-1:-1;114325:54:0;-1:-1:-1;;114402:25:0;;;114398:39;;;114429:8;;;;;114398:39;114476:21;114500:134;114535:23;:21;:23::i;114500:134::-;114476:158;;114667:119;114704:16;114743:24;:13;:22;:24::i;114667:119::-;114838:37;;;;;;-1:-1:-1;;;;;114838:37:0;;;;;;;114869:4;114838:37;;;;;;114653:133;;-1:-1:-1;114818:17:0;;-1:-1:-1;114838:14:0;;;;-1:-1:-1;114838:14:0;;:37;;;;;;;;;;;;;;:14;:37;;;2:2:-1;;;;27:1;24;17:12;2:2;114838:37:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;114838:37:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;114838:37:0;;-1:-1:-1;114894:14:0;114890:28;;114910:8;;;;;114890:28;115158:10;;114989:9;;115081:10;;114955:31;;115158:7;;115166:1;;115158:10;;;;;;;;;;;;115138:30;;115215:17;115235:182;115268:12;115299:13;115331:9;115359:13;115391:11;115235:14;:182::i;:::-;115215:202;-1:-1:-1;115436:14:0;115432:28;;115452:8;;;;;;;;;115432:28;115509:24;:9;115523;115509:24;:13;:24;:::i;:::-;115501:4;:32;115497:328;;-1:-1:-1;;;;;115647:17:0;;;115691:6;115724:9;115760:26;:4;115776:9;115760:26;:15;:26;:::i;:::-;115647:162;;;;;;;;;;;;;-1:-1:-1;;;;;115647:162:0;-1:-1:-1;;;;;115647:162:0;;;;;;-1:-1:-1;;;;;115647:162:0;-1:-1:-1;;;;;115647:162:0;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;115647:162:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;115647:162:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;115647:162:0;;-1:-1:-1;115619:190:0;;-1:-1:-1;;;;;;;;;;115619:190:0;115497:328;115867:4;-1:-1:-1;;;;;115867:17:0;;115885:6;115893:9;115904;115867:47;;;;;;;;;;;;;-1:-1:-1;;;;;115867:47:0;-1:-1:-1;;;;;115867:47:0;;;;;;-1:-1:-1;;;;;115867:47:0;-1:-1:-1;;;;;115867:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;115867:47:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;115867:47:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;115867:47:0;115841:131;;;;;-1:-1:-1;;;115841:131:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;115995:21;;;;115987:29;;;;-1:-1:-1;;;;;114152:1876:0;114192:3;;114152:1876;;;-1:-1:-1;116040:37:0;;;-1:-1:-1;;;116040:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;113656:2429;;;;;;;;;;;:::o;56489:1322::-;56639:19;56660:15;56691:16;56715:36;56724:18;56744:6;56715:8;:36::i;:::-;56688:63;;;;;56777:20;56812:17;56844:23;56881:18;-1:-1:-1;;;;;56881:34:0;;56930:18;56963:6;56984:13;56881:127;;;;;;;;;;;;;-1:-1:-1;;;;;56881:127:0;-1:-1:-1;;;;;56881:127:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;56881:127:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;56881:127:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;56881:127:0;80:15:-1;;;97:9;76:31;65:43;;120:4;113:20;15:2;7:11;;4:2;;;31:1;28;21:12;4:2;56881:127:0;;;;;;;;;;;;;;;;;;;;;;;19:11:-1;11:20;;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;261:11;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;56881:127:0;;421:4:-1;412:14;;;;56881:127:0;;;;;412:14:-1;56881:127:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;56881:127:0;;;;;;;;;;;56762:246;;;;;;57027:15;57019:67;;;;-1:-1:-1;;;57019:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57099:21;57123:110;57150:23;:21;:23::i;:::-;57123:110;;;;;;;;;;;;;;;;;;:8;;:110;;:12;:110;:::i;:::-;57099:134;;57244:21;57268:37;57284:20;57268:15;:37::i;:::-;57244:61;;57316:26;57345:104;57374:25;57414:24;:13;:22;:24::i;57345:104::-;57316:133;;57462:18;57519:10;-1:-1:-1;;;;;57519:31:0;;57565:8;57588:6;57609:24;:13;:22;:24::i;:::-;57648:29;:18;:27;:29::i;:::-;57692:24;:13;:22;:24::i;:::-;57519:208;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;57519:208:0;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;57519:208:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;57519:208:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;57519:208:0;;;;;;;;;-1:-1:-1;57519:208:0;-1:-1:-1;57749:54:0;57761:18;57519:208;57793:9;57749:11;:54::i;:::-;57738:65;;56489:1322;;;;;;;;;;;;;;:::o;58710:146::-;58767:7;58843:5;58794:46;58805:34;58821:17;58805:15;:34::i;:::-;58794:6;;:46;:10;:46;:::i;:::-;:54;;;;;;;58710:146;-1:-1:-1;;58710:146:0:o;94260:794::-;-1:-1:-1;;;;;94508:20:0;;94500:59;;;;;-1:-1:-1;;;94500:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;94592:32:0;;94570:118;;;;-1:-1:-1;;;94570:118:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;94721:33:0;;94699:120;;;;-1:-1:-1;;;94699:120:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94851:195;;;;;;;;-1:-1:-1;;;;;94851:195:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;94830:18:0;;;:10;:18;;;;;;;;:216;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94260:794::o;60523:205::-;60651:68;;;-1:-1:-1;;;;;60651:68:0;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;60651:68:0;;;;;;;;25:18:-1;;61:17;;60651:68:0;182:15:-1;60674:27:0;179:29:-1;160:49;;60624:96:0;;60644:5;;60624:19;:96::i;58920:412::-;53006:1;59054:61;;:9;-1:-1:-1;;;;;59054:31:0;;:33;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;59054:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;59054:33:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;59054:33:0;:61;;;59032:149;;;;-1:-1:-1;;;59032:149:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;52782:1;59214:46;;:9;-1:-1:-1;;;;;59214:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;59214:26:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;59214:26:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;59214:26:0;:46;;;59192:132;;;;-1:-1:-1;;;59192:132:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;109394:1160;-1:-1:-1;;;;;109717:20:0;;109709:59;;;;;-1:-1:-1;;;109709:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;109801:39:0;;109779:132;;;;-1:-1:-1;;;109779:132:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;109944:40:0;;109922:134;;;;-1:-1:-1;;;109922:134:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;110089:33:0;;110067:120;;;;-1:-1:-1;;;110067:120:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110198:42;110223:16;110198:24;:42::i;:::-;110273:273;;;;;;;;-1:-1:-1;;;;;110273:273:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;110251:19:0;;;;;;;;;;;:295;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;109394:1160::o;98125:191::-;-1:-1:-1;;;;;98210:20:0;;;;;;:13;:20;;;;;;:30;-1:-1:-1;98210:30:0;98202:65;;;;;-1:-1:-1;;;98202:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;98278:20:0;;;;;;;:13;:20;;;;;:30;;;;;;;;98125:191::o;81629:172::-;81714:79;81727:9;81738:6;81714:79;;;;;;;;;;;;;;;;;:12;:79::i;54653:164::-;54749:15;54789:6;-1:-1:-1;;;;;54789:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;54789:20:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;54789:20:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;54789:20:0;;54653:164;-1:-1:-1;;54653:164:0:o;52046:166::-;52148:15;;52046:166::o;5714:192::-;5800:7;5836:12;5828:6;;;;5820:29;;;;-1:-1:-1;;;5820:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;5820:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5872:5:0;;;5714:192::o;33685:179::-;33741:6;33776:5;33768;:13;33760:65;;;;-1:-1:-1;;;33760:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;33850:5:0;33685:179::o;54934:211::-;55062:20;55102:6;-1:-1:-1;;;;;55102:20:0;;55123:13;55102:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;55102:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;55102:35:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;55102:35:0;55095:42;;;54934:211;-1:-1:-1;;;54934:211:0:o;118023:1341::-;118251:7;118271:20;118320:16;118344:27;118353:9;118364:6;118344:8;:27::i;:::-;118317:54;;;;;118402:169;:140;118451:23;:21;:23::i;118402:140::-;:167;:169::i;:::-;118386:185;;118023:1341;118595:17;118623:23;118672:20;118745:18;-1:-1:-1;;;;;118745:52:0;;118798:9;118809:6;118817:13;118745:86;;;;;;;;;;;;;-1:-1:-1;;;;;118745:86:0;-1:-1:-1;;;;;118745:86:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;118745:86:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;118745:86:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;118745:86:0;80:15:-1;;;97:9;76:31;65:43;;120:4;113:20;15:2;7:11;;4:2;;;31:1;28;21:12;4:2;118745:86:0;;;;;;;;;;;;;;;;;;;;;;;19:11:-1;11:20;;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;261:11;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;118745:86:0;;421:4:-1;412:14;;;;118745:86:0;;;;;412:14:-1;118745:86:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;118745:86:0;;;;;;;;;;;118707:124;;;;;;;;;;;;118851:15;118846:114;;118887:27;;;-1:-1:-1;;;118887:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;118846:114;118023:1341;119000:10;-1:-1:-1;;;;;119000:31:0;;119050:8;119077:6;119102:24;:13;:22;:24::i;:::-;119145:29;:18;:27;:29::i;:::-;119193:13;119000:221;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;119000:221:0;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;119000:221:0;;;;;;;;;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;119000:221:0;;;;;;;;;118983:374;;119344:1;119337:8;;;;;;;118983:374;-1:-1:-1;119292:11:0;-1:-1:-1;119285:18:0;;-1:-1:-1;;;119285:18:0;4827:181;4885:7;4917:5;;;4941:6;;;;4933:46;;;;;-1:-1:-1;;;4933:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;76330:1035;-1:-1:-1;;;;;76615:20:0;;76607:59;;;;;-1:-1:-1;;;76607:59:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;76699:36:0;;76677:126;;;;-1:-1:-1;;;76677:126:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;76836:37:0;;76814:128;;;;-1:-1:-1;;;76814:128:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;76975:33:0;;76953:120;;;;-1:-1:-1;;;76953:120:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77107:250;;;;;;;;-1:-1:-1;;;;;77107:250:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;77084:20:0;;;;;;;;;;;:273;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;76330:1035::o;7716:345::-;7802:7;7904:12;7897:5;7889:28;;;;-1:-1:-1;;;7889:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;7889:28:0;;7928:9;7944:1;7940;:5;;;;;;;7716:345;-1:-1:-1;;;;;7716:345:0:o;36572:154::-;36637:7;36664:54;36675:1;36678;36664:54;;;;;;;;;;;;;;;;;:10;:54::i;35826:181::-;35882:6;35917;35909:5;:14;35901:67;;;;-1:-1:-1;;;35901:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;57819:804;57962:15;57990:13;58027:5;58006:18;:26;:152;;58090:9;58069:18;:30;:89;;58140:18;58069:89;;;58115:9;58069:89;58006:152;;;58048:5;58006:152;57990:168;-1:-1:-1;58194:18:0;;;58536:6;58328:191;58169:22;58351:13;;;;;;:40;;;58385:6;58368:14;:23;58351:40;:116;;58453:14;58351:116;;;58419:6;58328:189;:191::i;:::-;58299:9;:220;;;58298:244;;;;;;58274:268;;52561:5;58564:8;:24;:51;;58607:8;58564:51;;;52561:5;58553:62;57819:804;-1:-1:-1;;;;;;57819:804:0:o;62382:1115::-;62987:27;62995:5;-1:-1:-1;;;;;62987:25:0;;:27::i;:::-;62979:71;;;;;-1:-1:-1;;;62979:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;63124:12;63138:23;63173:5;-1:-1:-1;;;;;63165:19:0;63185:4;63165:25;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;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;;;63165:25:0;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;63123:67:0;;;;63209:7;63201:52;;;;;-1:-1:-1;;;63201:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63270:17;;:21;63266:224;;63412:10;63401:30;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;63401:30:0;63393:85;;;;-1:-1:-1;;;63393:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81185:436;81340:29;81362:6;81340:21;:29::i;:::-;81371:12;81332:52;;;;;-1:-1:-1;;;81332:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;81332:52:0;-1:-1:-1;81414:33:0;;81396:12;;-1:-1:-1;;;;;81414:14:0;;;81436:6;;81396:12;81414:33;81396:12;81414:33;81436:6;81414:14;:33;;;;;;;12:1:-1;19;14:27;;;;67:4;61:11;56:16;;134:4;130:9;123:4;105:16;101:27;97:43;94:1;90:51;84:4;77:65;157:16;154:1;147:27;211:16;208:1;201:4;198:1;194:12;179:49;5:228;;14:27;32:4;27:9;;5:228;;81395:52:0;;;81512:7;81504:45;;;;;-1:-1:-1;;;81504:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;81565:48;;;;;;;;-1:-1:-1;;;;;81565:48:0;;;81588:4;;81565:48;;;;;;;;;81185:436;;;;:::o;36289:275::-;36416:7;36440:6;36436:47;;-1:-1:-1;36470:1:0;36463:8;;36436:47;36508:12;36501:5;36493:28;;;;-1:-1:-1;;;36493:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;36493:28:0;;36550:1;36545;36541;:5;36540:11;;;;;;36555:1;36539:17;36532:24;;36289:275;;;;;:::o;10037:619::-;10097:4;10565:20;;10408:66;10605:23;;;;;;:42;;-1:-1:-1;10632:15:0;;;10605:42;10597:51;10037:619;-1:-1:-1;;;;10037:619:0:o;80894:182::-;81015:4;81048:20;-1:-1:-1;81038:30:0;;80894:182::o;119461:538::-;;;;;;;;;-1:-1:-1;119461:538:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;-1:-1:-1;119461:538:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o
Swarm Source
ipfs://7d46b6e6ab3d17a7a0bf149999e36885cb46e29bb984f9b0fb8158d023d86fd1
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | Ether (ETH) | 100.00% | $3,285.12 | 0.06 | $197.11 |
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.