Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
12269328 | 1246 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
SimpleAggregatorCollateralizedEth
Compiler Version
v0.7.1+commit.f4a555be
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2021-04-19 */ // File: contracts/BondToken_and_GDOTC/util/TransferETHInterface.sol // SPDX-License-Identifier: UNLICENSED pragma solidity 0.7.1; interface TransferETHInterface { receive() external payable; event LogTransferETH(address indexed from, address indexed to, uint256 value); } // 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: contracts/BondToken_and_GDOTC/bondToken/BondTokenInterface.sol 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/BondToken_and_GDOTC/oracle/LatestPriceOracleInterface.sol /** * @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/BondToken_and_GDOTC/oracle/PriceOracleInterface.sol /** * @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/BondToken_and_GDOTC/bondMaker/BondMakerInterface.sol 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/contracts/Interfaces/StrategyInterface.sol interface SimpleStrategyInterface { function calcNextMaturity() external view returns (uint256 nextTimeStamp); function calcCallStrikePrice( uint256 currentPriceE8, uint64 priceUnit, bool isReversedOracle ) external pure returns (uint256 callStrikePrice); function calcRoundPrice( uint256 price, uint64 priceUnit, uint8 divisor ) external pure returns (uint256 roundedPrice); function getTrancheBonds( BondMakerInterface bondMaker, address aggregatorAddress, uint256 issueBondGroupIdOrStrikePrice, uint256 price, uint256[] calldata bondGroupList, uint64 priceUnit, bool isReversedOracle ) external view returns ( uint256 issueAmount, uint256 ethAmount, uint256[2] memory IDAndAmountOfBurn ); function getCurrentStrikePrice( uint256 currentPriceE8, uint64 priceUnit, bool isReversedOracle ) external pure returns (uint256); function getCurrentSpread( address owner, address oracleAddress, bool isReversedOracle ) external view returns (int16); function registerCurrentFeeBase( int16 currentFeeBase, uint256 currentCollateralPerToken, uint256 nextCollateralPerToken, address owner, address oracleAddress, bool isReversedOracle ) external; } // File: contracts/contracts/Interfaces/SimpleAggragatorInterface.sol pragma experimental ABIEncoderV2; interface SimpleAggregatorInterface { struct TotalReward { uint64 term; uint64 value; } enum AggregatorPhase {BEFORE_START, ACTIVE, COOL_TIME, AFTER_MATURITY, EXPIRED} function renewMaturity() external; function removeLiquidity(uint128 amount) external returns (bool success); function settleTokens() external returns (uint256 unsentETH, uint256 unsentToken); function changeSpread() external; function liquidateBonds() external; function trancheBonds() external; function claimReward() external; function addSuitableBondGroup() external returns (uint256 bondGroupID); function getCollateralAddress() external view returns (address); function getCollateralAmount() external view returns (uint256); function getCollateralDecimal() external view returns (int16); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint256); function transfer(address _to, uint256 _value) external returns (bool success); function balanceOf(address _owner) external view returns (uint256 balance); function transferFrom( address _from, address _to, uint256 _value ) external returns (bool success); function approve(address _spender, uint256 _value) external returns (bool success); function allowance(address _owner, address _spender) external view returns (uint256 remaining); function getExpectedBalance(address user, bool hasReservation) external view returns (uint256 expectedBalance); function getCurrentPhase() external view returns (AggregatorPhase); function updateStartBondGroupId() external; function getInfo() external view returns ( address bondMaker, address strategy, address dotc, address bondPricerAddress, address oracleAddress, address rewardTokenAddress, address registratorAddress, address owner, bool reverseOracle, uint64 basePriceUnit, uint128 maxSupply ); function getCurrentStatus() external view returns ( uint256 term, int16 feeBase, uint32 uncheckbondGroupId, uint64 unit, uint64 trancheTime, bool isDanger ); function getTermInfo(uint256 term) external view returns ( uint64 maturity, uint64 solidStrikePrice, bytes32 SBTID ); function getBondGroupIDFromTermAndPrice(uint256 term, uint256 price) external view returns (uint256 bondGroupID); function getRewardAmount(address user) external view returns (uint64); function getTotalRewards() external view returns (TotalReward[] memory); function isTotalSupplySafe() external view returns (bool); function getTotalUnmovedAssets() external view returns (uint256, uint256); function totalShareData(uint256 term) external view returns (uint128 totalShare, uint128 totalCollateralPerToken); function getCollateralPerToken(uint256 term) external view returns (uint256); function getBondGroupIdFromStrikePrice(uint256 term, uint256 strikePrice) external view returns (uint256); function getBalanceData(address user) external view returns ( uint128 amount, uint64 term, uint64 rewardAmount ); function getIssuableBondGroups() external view returns (uint256[] memory); function getLiquidationData(uint256 term) external view returns ( bool isLiquidated, uint32 liquidatedBondGroupID, uint32 endBondGroupId ); } // File: contracts/contracts/Interfaces/VolatilityOracleInterface.sol interface VolatilityOracleInterface { function getVolatility(uint64 untilMaturity) external view returns (uint64 volatilityE8); } // File: contracts/BondToken_and_GDOTC/bondPricer/Enums.sol /** Pure SBT: ___________ / / / / LBT Shape: / / / / ______/ SBT Shape: ______ / / _______/ Triangle: /\ / \ / \ _______/ \________ */ enum BondType {NONE, PURE_SBT, SBT_SHAPE, LBT_SHAPE, TRIANGLE} // File: contracts/BondToken_and_GDOTC/bondPricer/BondPricerInterface.sol 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/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. */ abstract contract Context { 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/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) { 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"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return _functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); return _functionCallWithValue(target, data, value, errorMessage); } function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // 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 {ERC20PresetMinterPauser}. * * 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_) { _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 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/contracts/Interfaces/ExchangeInterface.sol interface ExchangeInterface { function changeSpread(int16 spread) external; function createVsBondPool( BondMakerInterface bondMakerForUserAddress, VolatilityOracleInterface volatilityOracleAddress, BondPricerInterface bondPricerForUserAddress, BondPricerInterface bondPricerAddress, int16 feeBaseE4 ) external returns (bytes32 poolID); function createVsErc20Pool( ERC20 swapPairAddress, LatestPriceOracleInterface swapPairOracleAddress, BondPricerInterface bondPricerAddress, int16 feeBaseE4, bool isBondSale ) external returns (bytes32 poolID); function createVsEthPool( LatestPriceOracleInterface ethOracleAddress, BondPricerInterface bondPricerAddress, int16 feeBaseE4, bool isBondSale ) external returns (bytes32 poolID); function updateVsBondPool( bytes32 poolID, VolatilityOracleInterface volatilityOracleAddress, BondPricerInterface bondPricerForUserAddress, BondPricerInterface bondPricerAddress, int16 feeBaseE4 ) external; function updateVsErc20Pool( bytes32 poolID, LatestPriceOracleInterface swapPairOracleAddress, BondPricerInterface bondPricerAddress, int16 feeBaseE4 ) external; function updateVsEthPool( bytes32 poolID, LatestPriceOracleInterface ethOracleAddress, BondPricerInterface bondPricerAddress, int16 feeBaseE4 ) external; function generateVsBondPoolID(address seller, address bondMakerForUser) external view returns (bytes32 poolID); function generateVsErc20PoolID( address seller, address swapPairAddress, bool isBondSale ) external view returns (bytes32 poolID); function generateVsEthPoolID(address seller, bool isBondSale) external view returns (bytes32 poolID); function withdrawEth() external; function depositEth() external payable; function ethAllowance(address owner) external view returns (uint256 amount); function bondMakerAddress() external view returns (BondMakerInterface); } // 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 Returns the multiplication of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot 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 Returns the integer division of two signed 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(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 Returns the subtraction of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot 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 Returns the addition of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot 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/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 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} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` 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 Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128) { require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\'t fit in 128 bits"); return int128(value); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64) { require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\'t fit in 64 bits"); return int64(value); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32) { require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\'t fit in 32 bits"); return int32(value); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16) { require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\'t fit in 16 bits"); return int16(value); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits. * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8) { require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\'t fit in 8 bits"); return int8(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/BondToken_and_GDOTC/math/UseSafeMath.sol /** * @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/BondToken_and_GDOTC/math/AdvancedMath.sol abstract contract AdvancedMath { /** * @dev sqrt(2*PI) * 10^8 */ int256 internal constant SQRT_2PI_E8 = 250662827; int256 internal constant PI_E8 = 314159265; int256 internal constant E_E8 = 271828182; int256 internal constant INV_E_E8 = 36787944; // 1/e int256 internal constant LOG2_E8 = 30102999; int256 internal constant LOG3_E8 = 47712125; int256 internal constant p = 23164190; int256 internal constant b1 = 31938153; int256 internal constant b2 = -35656378; int256 internal constant b3 = 178147793; int256 internal constant b4 = -182125597; int256 internal constant b5 = 133027442; /** * @dev Calcurate an approximate value of the square root of x by Babylonian method. */ function _sqrt(int256 x) internal pure returns (int256 y) { require(x >= 0, "cannot calculate the square root of a negative number"); int256 z = (x + 1) / 2; y = x; while (z < y) { y = z; z = (x / z + z) / 2; } } /** * @dev Returns log(x) for any positive x. */ function _logTaylor(int256 inputE4) internal pure returns (int256 outputE4) { require(inputE4 > 1, "input should be positive number"); int256 inputE8 = inputE4 * 10**4; // input x for _logTayler1 is adjusted to 1/e < x < 1. while (inputE8 < INV_E_E8) { inputE8 = (inputE8 * E_E8) / 10**8; outputE4 -= 10**4; } while (inputE8 > 10**8) { inputE8 = (inputE8 * INV_E_E8) / 10**8; outputE4 += 10**4; } outputE4 += _logTaylor1(inputE8 / 10**4 - 10**4); } /** * @notice Calculate an approximate value of the logarithm of input value by * Taylor expansion around 1. * @dev log(x + 1) = x - 1/2 x^2 + 1/3 x^3 - 1/4 x^4 + 1/5 x^5 * - 1/6 x^6 + 1/7 x^7 - 1/8 x^8 + ... */ function _logTaylor1(int256 inputE4) internal pure returns (int256 outputE4) { outputE4 = inputE4 - inputE4**2 / (2 * 10**4) + inputE4**3 / (3 * 10**8) - inputE4**4 / (4 * 10**12) + inputE4**5 / (5 * 10**16) - inputE4**6 / (6 * 10**20) + inputE4**7 / (7 * 10**24) - inputE4**8 / (8 * 10**28); } /** * @notice Calculate the cumulative distribution function of standard normal * distribution. * @dev Abramowitz and Stegun, Handbook of Mathematical Functions (1964) * http://people.math.sfu.ca/~cbm/aands/ */ function _calcPnorm(int256 inputE4) internal pure returns (int256 outputE8) { require(inputE4 < 440 * 10**4 && inputE4 > -440 * 10**4, "input is too large"); int256 _inputE4 = inputE4 > 0 ? inputE4 : inputE4 * (-1); int256 t = 10**16 / (10**8 + (p * _inputE4) / 10**4); int256 X2 = (inputE4 * inputE4) / 2; int256 exp2X2 = 10**8 + X2 + (X2**2 / (2 * 10**8)) + (X2**3 / (6 * 10**16)) + (X2**4 / (24 * 10**24)) + (X2**5 / (120 * 10**32)) + (X2**6 / (720 * 10**40)); int256 Z = (10**24 / exp2X2) / SQRT_2PI_E8; int256 y = (b5 * t) / 10**8; y = ((y + b4) * t) / 10**8; y = ((y + b3) * t) / 10**8; y = ((y + b2) * t) / 10**8; y = 10**8 - (Z * ((y + b1) * t)) / 10**16; return inputE4 > 0 ? y : 10**8 - y; } } // File: contracts/BondToken_and_GDOTC/bondPricer/GeneralizedPricing.sol /** * @dev The decimals of price, point, spotPrice and strikePrice are all the same. */ contract GeneralizedPricing is AdvancedMath { using SafeMath for uint256; /** * @dev sqrt(365*86400) * 10^8 */ int256 internal constant SQRT_YEAR_E8 = 5615.69229926 * 10**8; int256 internal constant MIN_ND1_E8 = 0.0001 * 10**8; int256 internal constant MAX_ND1_E8 = 0.9999 * 10**8; uint256 internal constant MAX_LEVERAGE_E8 = 1000 * 10**8; /** * @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 untilMaturity Remaining period of target bond in second **/ function calcPriceAndLeverage( BondType bondType, uint256[] memory points, int256 spotPrice, int256 volatilityE8, int256 untilMaturity ) public pure returns (uint256 price, uint256 leverageE8) { if (bondType == BondType.LBT_SHAPE) { (price, leverageE8) = _calcLbtShapePriceAndLeverage( points, spotPrice, volatilityE8, untilMaturity ); } else if (bondType == BondType.SBT_SHAPE) { (price, leverageE8) = _calcSbtShapePrice( points, spotPrice, volatilityE8, untilMaturity ); } else if (bondType == BondType.TRIANGLE) { (price, leverageE8) = _calcTrianglePrice( points, spotPrice, volatilityE8, untilMaturity ); } else if (bondType == BondType.PURE_SBT) { (price, leverageE8) = _calcPureSBTPrice(points, spotPrice, volatilityE8, untilMaturity); } } /** * @notice Calculate pure call option price and multiply incline of LBT. **/ function _calcLbtShapePriceAndLeverage( uint256[] memory points, int256 spotPrice, int256 volatilityE8, int256 untilMaturity ) internal pure returns (uint256 price, uint256 leverageE8) { require(points.length == 3, "3 coordinates is needed for LBT price calculation"); uint256 inclineE8 = (points[2].mul(10**8)).div(points[1].sub(points[0])); (uint256 callOptionPriceE8, int256 nd1E8) = calcCallOptionPrice( spotPrice, int256(points[0]), volatilityE8, untilMaturity ); price = (callOptionPriceE8 * inclineE8) / 10**8; leverageE8 = _calcLbtLeverage( uint256(spotPrice), price, (nd1E8 * int256(inclineE8)) / 10**8 ); } /** * @notice Calculate (etherPrice - call option price at strike price of SBT). **/ function _calcPureSBTPrice( uint256[] memory points, int256 spotPrice, int256 volatilityE8, int256 untilMaturity ) internal pure returns (uint256 price, uint256 leverageE8) { require(points.length == 1, "1 coordinate is needed for pure SBT price calculation"); (uint256 callOptionPrice1, int256 nd1E8) = calcCallOptionPrice( spotPrice, int256(points[0]), volatilityE8, untilMaturity ); price = uint256(spotPrice) > callOptionPrice1 ? (uint256(spotPrice) - callOptionPrice1) : 0; leverageE8 = _calcLbtLeverage(uint256(spotPrice), price, 10**8 - nd1E8); } /** * @notice Calculate (call option1 - call option2) * incline of SBT. ______ / / / / = / - / _______/ _______/ ___________/ SBT SHAPE BOND CALL OPTION 1 CALL OPTION 2 **/ function _calcSbtShapePrice( uint256[] memory points, int256 spotPrice, int256 volatilityE8, int256 untilMaturity ) internal pure returns (uint256 price, uint256 leverageE8) { require(points.length == 3, "3 coordinates is needed for SBT price calculation"); uint256 inclineE8 = (points[2].mul(10**8)).div(points[1].sub(points[0])); (uint256 callOptionPrice1, int256 nd11E8) = calcCallOptionPrice( spotPrice, int256(points[0]), volatilityE8, untilMaturity ); (uint256 callOptionPrice2, int256 nd12E8) = calcCallOptionPrice( spotPrice, int256(points[1]), volatilityE8, untilMaturity ); price = callOptionPrice1 > callOptionPrice2 ? (inclineE8 * (callOptionPrice1 - callOptionPrice2)) / 10**8 : 0; leverageE8 = _calcLbtLeverage( uint256(spotPrice), price, (int256(inclineE8) * (nd11E8 - nd12E8)) / 10**8 ); } /** * @notice Calculate (call option1 * left incline) - (call option2 * (left incline + right incline)) + (call option3 * right incline). / / / /\ / \ / \ / \ / \ = / - \ + _______/ \________ _______/ _______ \ __________________ \ \ \ \ **/ function _calcTrianglePrice( uint256[] memory points, int256 spotPrice, int256 volatilityE8, int256 untilMaturity ) internal pure returns (uint256 price, uint256 leverageE8) { require( points.length == 4, "4 coordinates is needed for triangle option price calculation" ); uint256 incline1E8 = (points[2].mul(10**8)).div(points[1].sub(points[0])); uint256 incline2E8 = (points[2].mul(10**8)).div(points[3].sub(points[1])); (uint256 callOptionPrice1, int256 nd11E8) = calcCallOptionPrice( spotPrice, int256(points[0]), volatilityE8, untilMaturity ); (uint256 callOptionPrice2, int256 nd12E8) = calcCallOptionPrice( spotPrice, int256(points[1]), volatilityE8, untilMaturity ); (uint256 callOptionPrice3, int256 nd13E8) = calcCallOptionPrice( spotPrice, int256(points[3]), volatilityE8, untilMaturity ); int256 nd1E8 = ((nd11E8 * int256(incline1E8)) + (nd13E8 * int256(incline2E8)) - (int256(incline1E8 + incline2E8) * nd12E8)) / 10**8; uint256 price12 = (callOptionPrice1 * incline1E8) + (callOptionPrice3 * incline2E8); price = price12 > (incline1E8 + incline2E8) * callOptionPrice2 ? (price12 - ((incline1E8 + incline2E8) * callOptionPrice2)) / 10**8 : 0; leverageE8 = _calcLbtLeverage(uint256(spotPrice), price, nd1E8); } /** * @dev calcCallOptionPrice() imposes the restrictions of strikePrice, spotPrice, nd1E8 and nd2E8. */ function _calcLbtPrice( int256 spotPrice, int256 strikePrice, int256 nd1E8, int256 nd2E8 ) internal pure returns (int256 lbtPrice) { int256 lowestPrice = (spotPrice > strikePrice) ? spotPrice - strikePrice : 0; lbtPrice = (spotPrice * nd1E8 - strikePrice * nd2E8) / 10**8; if (lbtPrice < lowestPrice) { lbtPrice = lowestPrice; } } /** * @dev calcCallOptionPrice() imposes the restrictions of spotPrice, lbtPrice and nd1E8. */ function _calcLbtLeverage( uint256 spotPrice, uint256 lbtPrice, int256 nd1E8 ) internal pure returns (uint256 lbtLeverageE8) { int256 modifiedNd1E8 = nd1E8 < MIN_ND1_E8 ? MIN_ND1_E8 : nd1E8 > MAX_ND1_E8 ? MAX_ND1_E8 : nd1E8; return lbtPrice != 0 ? (uint256(modifiedNd1E8) * spotPrice) / lbtPrice : MAX_LEVERAGE_E8; } /** * @notice Calculate pure call option price and N(d1) by black-scholes formula. * @param spotPrice is a oracle price. * @param strikePrice Strike price of call option * @param volatilityE8 is a oracle volatility. * @param untilMaturity Remaining period of target bond in second **/ function calcCallOptionPrice( int256 spotPrice, int256 strikePrice, int256 volatilityE8, int256 untilMaturity ) public pure returns (uint256 price, int256 nd1E8) { require(spotPrice > 0 && spotPrice < 10**13, "oracle price should be between 0 and 10^13"); require( volatilityE8 > 0 && volatilityE8 < 10 * 10**8, "oracle volatility should be between 0% and 1000%" ); require( untilMaturity > 0 && untilMaturity < 31536000, "the bond should not have expired and less than 1 year" ); require( strikePrice > 0 && strikePrice < 10**13, "strike price should be between 0 and 10^13" ); int256 spotPerStrikeE4 = (spotPrice * 10**4) / strikePrice; int256 sigE8 = (volatilityE8 * (_sqrt(untilMaturity)) * (10**8)) / SQRT_YEAR_E8; int256 logSigE4 = _logTaylor(spotPerStrikeE4); int256 d1E4 = ((logSigE4 * 10**8) / sigE8) + (sigE8 / (2 * 10**4)); nd1E8 = _calcPnorm(d1E4); int256 d2E4 = d1E4 - (sigE8 / 10**4); int256 nd2E8 = _calcPnorm(d2E4); price = uint256(_calcLbtPrice(spotPrice, strikePrice, nd1E8, nd2E8)); } } // File: contracts/BondToken_and_GDOTC/bondPricer/CustomGeneralizedPricing.sol abstract contract CustomGeneralizedPricing is BondPricerInterface { using SafeMath for uint256; GeneralizedPricing internal immutable _originalBondPricerAddress; constructor(address originalBondPricerAddress) { _originalBondPricerAddress = GeneralizedPricing(originalBondPricerAddress); } function calcPriceAndLeverage( BondType bondType, uint256[] calldata points, int256 spotPrice, int256 volatilityE8, int256 untilMaturity ) external view override returns (uint256 price, uint256 leverageE8) { (price, leverageE8) = _originalBondPricerAddress.calcPriceAndLeverage( bondType, points, spotPrice, volatilityE8, untilMaturity ); if (bondType == BondType.LBT_SHAPE) { require( _isAcceptableLbt(points, spotPrice, volatilityE8, untilMaturity, price, leverageE8), "the liquid bond is not acceptable" ); } else if (bondType == BondType.SBT_SHAPE) { require( _isAcceptableSbt(points, spotPrice, volatilityE8, untilMaturity, price, leverageE8), "the solid bond is not acceptable" ); } else if (bondType == BondType.TRIANGLE) { require( _isAcceptableTriangleBond( points, spotPrice, volatilityE8, untilMaturity, price, leverageE8 ), "the triangle bond is not acceptable" ); } else if (bondType == BondType.PURE_SBT) { require( _isAcceptablePureSbt( points, spotPrice, volatilityE8, untilMaturity, price, leverageE8 ), "the pure solid bond is not acceptable" ); } else { require( _isAcceptableOtherBond( points, spotPrice, volatilityE8, untilMaturity, price, leverageE8 ), "the bond is not acceptable" ); } } function originalBondPricer() external view returns (address originalBondPricerAddress) { originalBondPricerAddress = address(_originalBondPricerAddress); } function _isAcceptableLbt( uint256[] memory points, int256 spotPrice, int256 volatilityE8, int256 untilMaturity, uint256 bondPrice, uint256 bondLeverageE8 ) internal view virtual returns (bool); function _isAcceptableSbt( uint256[] memory points, int256 spotPrice, int256 volatilityE8, int256 untilMaturity, uint256 bondPrice, uint256 bondLeverageE8 ) internal view virtual returns (bool); function _isAcceptableTriangleBond( uint256[] memory points, int256 spotPrice, int256 volatilityE8, int256 untilMaturity, uint256 bondPrice, uint256 bondLeverageE8 ) internal view virtual returns (bool); function _isAcceptablePureSbt( uint256[] memory points, int256 spotPrice, int256 volatilityE8, int256 untilMaturity, uint256 bondPrice, uint256 bondLeverageE8 ) internal view virtual returns (bool); function _isAcceptableOtherBond( uint256[] memory points, int256 spotPrice, int256 volatilityE8, int256 untilMaturity, uint256 bondPrice, uint256 bondLeverageE8 ) internal view virtual returns (bool); } // File: @openzeppelin/contracts/access/Ownable.sol /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(_owner == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File: contracts/BondToken_and_GDOTC/util/Time.sol abstract contract Time { function _getBlockTimestampSec() internal view returns (uint256 unixtimesec) { unixtimesec = block.timestamp; // solhint-disable-line not-rely-on-time } } // File: contracts/contracts/SimpleAggregator/BondPricerWithAcceptableMaturity.sol contract BondPricerWithAcceptableMaturity is CustomGeneralizedPricing, Ownable, Time { using SafeMath for uint256; uint256 internal _acceptableMaturity; event LogUpdateAcceptableMaturity(uint256 acceptableMaturity); constructor(address originalBondPricerAddress) CustomGeneralizedPricing(originalBondPricerAddress) { _updateAcceptableMaturity(0); } function updateAcceptableMaturity(uint256 acceptableMaturity) external onlyOwner { _updateAcceptableMaturity(acceptableMaturity); } function getAcceptableMaturity() external view returns (uint256 acceptableMaturity) { acceptableMaturity = _acceptableMaturity; } function _updateAcceptableMaturity(uint256 acceptableMaturity) internal { _acceptableMaturity = acceptableMaturity; emit LogUpdateAcceptableMaturity(acceptableMaturity); } function _isAcceptableLbt( uint256[] memory, int256 etherPriceE8, int256 ethVolatilityE8, int256 untilMaturity, uint256, uint256 ) internal view override returns (bool) { _isAcceptable(etherPriceE8, ethVolatilityE8, untilMaturity); return true; } function _isAcceptableSbt( uint256[] memory, int256 etherPriceE8, int256 ethVolatilityE8, int256 untilMaturity, uint256, uint256 ) internal view override returns (bool) { _isAcceptable(etherPriceE8, ethVolatilityE8, untilMaturity); return true; } function _isAcceptableTriangleBond( uint256[] memory, int256 etherPriceE8, int256 ethVolatilityE8, int256 untilMaturity, uint256, uint256 ) internal view override returns (bool) { _isAcceptable(etherPriceE8, ethVolatilityE8, untilMaturity); return true; } function _isAcceptablePureSbt( uint256[] memory, int256 etherPriceE8, int256 ethVolatilityE8, int256 untilMaturity, uint256, uint256 ) internal view override returns (bool) { _isAcceptable(etherPriceE8, ethVolatilityE8, untilMaturity); return true; } function _isAcceptableOtherBond( uint256[] memory, int256, int256, int256, uint256, uint256 ) internal pure override returns (bool) { revert("the bond is not pure SBT type"); } /** * @notice Add this function to CustomGeneralizedPricing * When user sells bond which expired or whose maturity is after the aggregator's maturity, revert the transaction */ function _isAcceptable( int256 etherPriceE8, int256 ethVolatilityE8, int256 untilMaturity ) internal view { require( etherPriceE8 > 0 && etherPriceE8 < 100000 * 10**8, "ETH price should be between $0 and $100000" ); require( ethVolatilityE8 > 0 && ethVolatilityE8 < 10 * 10**8, "ETH volatility should be between 0% and 1000%" ); require(untilMaturity >= 0, "the bond has been expired"); require(untilMaturity <= 12 weeks, "the bond maturity must be less than 12 weeks"); require( _getBlockTimestampSec().add(uint256(untilMaturity)) <= _acceptableMaturity, "the bond maturity must not exceed the current maturity of aggregator" ); } } // File: contracts/contracts/Interfaces/BondRegistratorInterface.sol interface BondRegistratorInterface { struct Points { uint64 x1; uint64 y1; uint64 x2; uint64 y2; } function getFnMap(Points[] memory points) external pure returns (bytes memory fnMap); function registerSBT( BondMakerInterface bondMaker, uint64 sbtStrikePrice, uint64 maturity ) external returns (bytes32); function registerBondGroup( BondMakerInterface bondMaker, uint256 callStrikePrice, uint64 sbtStrikePrice, uint64 maturity, bytes32 SBTId ) external returns (uint256 bondGroupId); function registerBond( BondMakerInterface bondMaker, Points[] memory points, uint256 maturity ) external returns (bytes32); } // File: contracts/contracts/Interfaces/UseVolatilityOracle.sol contract UseVolatilityOracle { using SafeMath for uint256; using SafeCast for uint256; VolatilityOracleInterface volOracle; constructor(VolatilityOracleInterface _volOracle) { volOracle = _volOracle; } function _getVolatility(uint256 maturity) internal view returns (uint256) { return volOracle.getVolatility(maturity.sub(block.timestamp).toUint64()); } } // 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 IERC20;` 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)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ 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. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "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/contracts/SimpleAggregator/SimpleAggregator.sol abstract contract SimpleAggregator is SimpleAggregatorInterface, UseVolatilityOracle { using SafeMath for uint256; using SafeCast for uint256; using SafeERC20 for ERC20; struct ReceivedCollateral { uint128 term; uint128 value; } struct UnRemovedToken { uint128 term; uint128 value; } struct LiquidationData { uint32 endBondGroupId; uint32 liquidatedBondGroupID; bool isLiquidated; } struct TermInfo { uint64 maturity; uint64 strikePrice; bytes32 SBTId; } struct ShareData { uint128 totalShare; uint128 totalCollateralPerToken; } struct BalanceData { uint128 balance; uint64 rewardAmount; uint64 term; } uint256 constant INFINITY = uint256(-1); uint256 constant COOLTIME = 3600 * 24 * 3; SimpleStrategyInterface internal immutable STRATEGY; ExchangeInterface internal immutable DOTC; ERC20 internal immutable REWARD_TOKEN; BondPricerWithAcceptableMaturity internal immutable BOND_PRICER; LatestPriceOracleInterface internal immutable ORACLE; BondMakerInterface internal immutable BONDMAKER; BondRegistratorInterface internal immutable BOND_REGISTRATOR; address internal immutable OWNER; bool internal immutable REVERSE_ORACLE; int16 internal constant MAX_SUPPLY_DENUMERATOR = 8; uint64 internal immutable BASE_PRICE_UNIT; mapping(uint256 => TermInfo) internal termInfo; mapping(uint256 => uint256[]) internal issuableBondGroupIds; mapping(uint256 => mapping(uint256 => uint256)) internal strikePriceToBondGroup; TotalReward[] internal totalRewards; // Aggregator Status mapping(uint256 => LiquidationData) internal liquidationData; mapping(uint256 => ShareData) internal shareData; uint256 internal currentTerm; uint64 internal priceUnit; uint64 internal lastTrancheTime; uint32 internal startBondGroupId = 1; int16 internal currentFeeBase; bool internal isTotalSupplyDanger; mapping(address => ReceivedCollateral) internal receivedCollaterals; mapping(address => UnRemovedToken) internal unremovedTokens; mapping(address => BalanceData) internal balance; mapping(address => mapping(address => uint128)) internal allowances; uint8 public constant override decimals = 8; string public constant override symbol = "LASH"; string public constant override name = "LIEN_AGGREGATOR_SHARE"; mapping(uint256 => uint128) internal totalReceivedCollateral; mapping(uint256 => uint128) internal totalUnremovedTokens; event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); event SetAddLiquidity(address indexed user, uint256 indexed term, uint256 collateralAmount); event SetRemoveLiquidity(address indexed user, uint256 indexed term, uint256 tokenAmount); event SettleLiquidity( address indexed user, uint256 indexed term, uint256 collateralAmount, uint256 tokenAmount ); event TrancheBond( uint64 indexed issueBondGroupId, uint64 issueAmount, uint64 indexed burnBondGroupId, uint64 burnAmount ); event UpdateMaturity(uint64 indexed term, int16 newFeeBase, uint64 maturity); event AddLiquidity(address indexed user, uint256 tokenAmount); modifier isActive() { require(block.timestamp <= termInfo[currentTerm].maturity, "Not active"); _; } modifier endCoolTime() { require(block.timestamp > lastTrancheTime + COOLTIME, "Cool Time"); _; } modifier afterMaturity() { require(block.timestamp > termInfo[currentTerm].maturity, "Not Matured"); _; } modifier isRunning() { require(currentTerm != 0, "Not running"); _; } // When collateralPerToken becomes very small value, total supply of share token can overflow modifier isSafeSupply() { require(!isTotalSupplyDanger, "Unsafe supply"); _; } modifier onlyBonusProvider() { require(msg.sender == OWNER, "Only provider"); _; } constructor( LatestPriceOracleInterface _oracle, BondPricerWithAcceptableMaturity _pricer, SimpleStrategyInterface _strategy, ERC20 _rewardToken, BondRegistratorInterface _registrator, ExchangeInterface _exchangeAddress, uint64 _priceUnit, uint64 _firstRewardRate, bool _reverseOracle, VolatilityOracleInterface _volOracle ) UseVolatilityOracle(_volOracle) { BONDMAKER = _exchangeAddress.bondMakerAddress(); BOND_PRICER = _pricer; ORACLE = _oracle; BASE_PRICE_UNIT = _priceUnit; REVERSE_ORACLE = _reverseOracle; REWARD_TOKEN = _rewardToken; BOND_REGISTRATOR = _registrator; DOTC = _exchangeAddress; STRATEGY = _strategy; totalRewards.push(TotalReward(1, _firstRewardRate)); priceUnit = _priceUnit; OWNER = msg.sender; require( _firstRewardRate >= 10**decimals && _firstRewardRate <= 1000000 * 10**decimals, "Out of range" ); } /** * @notice Update maturity and strike price of SBT * Then, determine total amount of collateral asset and totalSupply of share token * Collateral asset to be withdrawn in `settleTokens()` is sent for reserve contract */ function renewMaturity() public override { uint256 totalUnsentTokens; uint256 collateralPerTokenE8; uint256 _currentTerm = currentTerm; uint256 currentUnremoved = totalUnremovedTokens[_currentTerm]; require(liquidationData[_currentTerm].isLiquidated || _currentTerm == 0, "Not expired yet"); uint256 totalShare = shareData[_currentTerm].totalShare; if (totalShare > 0) { uint256 collateralAmount = getCollateralAmount(); collateralPerTokenE8 = _applyDecimalGap( collateralAmount.mul(10**decimals).div(totalShare), true ); totalUnsentTokens = _applyDecimalGap( uint256(totalReceivedCollateral[_currentTerm]).mul(10**decimals) / collateralPerTokenE8, true ); } else if (totalReceivedCollateral[_currentTerm] > 0) { totalUnsentTokens = _applyDecimalGap(totalReceivedCollateral[_currentTerm], true); collateralPerTokenE8 = 10**decimals; } uint256 _totalSupply = totalShare + totalUnsentTokens; shareData[_currentTerm + 1].totalCollateralPerToken = collateralPerTokenE8.toUint128(); shareData[_currentTerm + 1].totalShare = uint256(totalShare) .add(totalUnsentTokens) .sub(currentUnremoved) .toUint128(); if ( shareData[_currentTerm + 1].totalShare > uint128(-1) / 10**uint128(MAX_SUPPLY_DENUMERATOR) ) { isTotalSupplyDanger = true; } if (_currentTerm != 0) { _updateFeeBase(); } if (_totalSupply > 0 && currentUnremoved > 0) { _reserveAsset(collateralPerTokenE8); } _updateBondGroupData(); emit UpdateMaturity(currentTerm.toUint64(), currentFeeBase, termInfo[currentTerm].maturity); } /** * @notice Update total reward token amount for one term * Only owner can call this function * @param rewardRate is restricted from 10**8 (1 LIEN) to 10**14 (total supply of Lien token) */ function updateTotalReward(uint64 rewardRate) public onlyBonusProvider isRunning { require(rewardRate >= 10**decimals && rewardRate <= 1000000 * 10**decimals, "Out of range"); totalRewards.push(TotalReward(currentTerm.toUint64() + 1, rewardRate)); } function _updateBondGroupData() internal { uint256 nextTimeStamp = STRATEGY.calcNextMaturity(); uint256 currentPriceE8 = ORACLE.latestPrice(); uint256 currentStrikePrice = STRATEGY.getCurrentStrikePrice( currentPriceE8, priceUnit, REVERSE_ORACLE ); _updatePriceUnit(currentPriceE8); // Register SBT for next term bytes32 SBTId = BOND_REGISTRATOR.registerSBT( BONDMAKER, currentStrikePrice.toUint64(), nextTimeStamp.toUint64() ); (address sbtAddress, , , ) = BONDMAKER.getBond(SBTId); IERC20(sbtAddress).approve(address(DOTC), INFINITY); currentTerm += 1; TermInfo memory newTermInfo = TermInfo( nextTimeStamp.toUint64(), currentStrikePrice.toUint64(), SBTId ); termInfo[currentTerm] = newTermInfo; BOND_PRICER.updateAcceptableMaturity(nextTimeStamp); } function _addLiquidity(uint256 amount) internal returns (bool success) { (, uint256 unsentToken, uint256 addLiquidityTerm) = _settleTokens(); _updateBalanceDataForLiquidityMove(msg.sender, unsentToken, 0, addLiquidityTerm); uint256 _currentTerm = currentTerm; if (receivedCollaterals[msg.sender].value == 0) { receivedCollaterals[msg.sender].term = uint128(_currentTerm); } receivedCollaterals[msg.sender].value += amount.toUint128(); totalReceivedCollateral[_currentTerm] += amount.toUint128(); emit SetAddLiquidity(msg.sender, _currentTerm, amount); return true; } /** * @notice Make a reservation for removing liquidity * Collateral asset can be withdrawn from next term * Share token to be removed is burned at this point * Before remove liquidity, run _settleTokens() */ function removeLiquidity(uint128 amount) external override returns (bool success) { (, uint256 unsentToken, uint256 addLiquidityTerm) = _settleTokens(); uint256 _currentTerm = currentTerm; if (unremovedTokens[msg.sender].value == 0) { unremovedTokens[msg.sender].term = uint128(_currentTerm); } unremovedTokens[msg.sender].value += amount; totalUnremovedTokens[_currentTerm] += amount; _updateBalanceDataForLiquidityMove(msg.sender, unsentToken, amount, addLiquidityTerm); emit SetRemoveLiquidity(msg.sender, _currentTerm, amount); return true; } function _settleTokens() internal returns ( uint256 unsentETH, uint256 unsentToken, uint256 addLiquidityTerm ) { uint256 _currentTerm = currentTerm; uint128 lastRemoveLiquidityTerm = unremovedTokens[msg.sender].term; uint128 lastRemoveLiquidityValue = unremovedTokens[msg.sender].value; uint128 lastAddLiquidityTerm = receivedCollaterals[msg.sender].term; uint128 lastAddLiquidityValue = receivedCollaterals[msg.sender].value; if (_currentTerm == 0) { return (0, 0, 0); } if (lastRemoveLiquidityValue != 0 && _currentTerm > lastRemoveLiquidityTerm) { unsentETH = _applyDecimalGap( uint256(lastRemoveLiquidityValue) .mul(shareData[uint256(lastRemoveLiquidityTerm + 1)].totalCollateralPerToken) .div(10**decimals), false ); if (unsentETH > 0) { _sendTokens(msg.sender, unsentETH); } delete unremovedTokens[msg.sender]; } if (lastAddLiquidityValue != 0 && _currentTerm > lastAddLiquidityTerm) { unsentToken = _applyDecimalGap( uint256(lastAddLiquidityValue).mul(10**decimals).div( uint256(shareData[lastAddLiquidityTerm + 1].totalCollateralPerToken) ), true ); addLiquidityTerm = lastAddLiquidityTerm; delete receivedCollaterals[msg.sender]; } emit SettleLiquidity(msg.sender, _currentTerm, unsentETH, unsentToken); } /** * @notice Increment share token for addLiquidity data * Transfer collateral asset for remove liquidity data */ function settleTokens() external override returns (uint256 unsentETH, uint256 unsentToken) { uint256 addLiquidityTerm; (unsentETH, unsentToken, addLiquidityTerm) = _settleTokens(); _updateBalanceDataForLiquidityMove(msg.sender, unsentToken, 0, addLiquidityTerm); } /** * @notice Update `startBondGroupId` to run `liquidateBonds()` more efficiently * All bond groups before `startBondGroupId` has expired before maturity of previous term */ function updateStartBondGroupId() external override isRunning { uint32 _startBondGroupId = startBondGroupId; uint64 previousMaturity = termInfo[currentTerm - 1].maturity; require(previousMaturity != 0, "Maturity shoudld exist"); while (true) { (, uint256 maturity) = BONDMAKER.getBondGroup(_startBondGroupId); if (maturity >= previousMaturity) { startBondGroupId = _startBondGroupId; return; } _startBondGroupId += 1; } } /** * @notice Liquidate and burn all bonds in this aggregator * Aggregator can search for 50 bondGroup and burn 10 bonds one time */ function liquidateBonds() public override afterMaturity { uint256 _currentTerm = currentTerm; require(!liquidationData[_currentTerm].isLiquidated, "Expired"); if (liquidationData[_currentTerm].endBondGroupId == 0) { liquidationData[_currentTerm].endBondGroupId = BONDMAKER.nextBondGroupID().toUint32(); } // ToDo: Register least bond group ID uint32 endIndex; uint32 startIndex; uint32 liquidateBondNumber; uint64 maturity = termInfo[_currentTerm].maturity; uint64 previousMaturity = termInfo[_currentTerm - 1].maturity; { uint256 ethAllowance = DOTC.ethAllowance(address(this)); if (ethAllowance > 0) { DOTC.withdrawEth(); } } if (liquidationData[_currentTerm].liquidatedBondGroupID == 0) { startIndex = startBondGroupId; } else { startIndex = liquidationData[_currentTerm].liquidatedBondGroupID; } if (liquidationData[_currentTerm].endBondGroupId - startIndex > 50) { endIndex = startIndex + 50; liquidationData[_currentTerm].liquidatedBondGroupID = endIndex; } else { endIndex = liquidationData[_currentTerm].endBondGroupId; } for (uint256 i = startIndex; i < endIndex; i++) { liquidateBondNumber = _liquidateBondGroup( i, liquidateBondNumber, maturity, previousMaturity ); if (liquidateBondNumber > 9) { if (i == endIndex - 1) { liquidationData[_currentTerm].isLiquidated = true; } else { liquidationData[_currentTerm].liquidatedBondGroupID = uint32(i + 1); } return; } } if (endIndex == liquidationData[_currentTerm].endBondGroupId) { liquidationData[_currentTerm].isLiquidated = true; } else { liquidationData[_currentTerm].liquidatedBondGroupID = endIndex; } } function addSuitableBondGroup() external override isActive returns (uint256 bondGroupID) { uint256 currentPriceE8 = ORACLE.latestPrice(); return _addSuitableBondGroup(currentPriceE8); } /** * @notice Can not tranche bonds for 3 days from last execution of this function */ function trancheBonds() external override isActive endCoolTime { uint256 currentPriceE8 = ORACLE.latestPrice(); uint256 bondGroupId = _getSuitableBondGroup(currentPriceE8); if (bondGroupId == 0) { bondGroupId = _addSuitableBondGroup(currentPriceE8); } (uint256 amount, uint256 ethAmount, uint256[2] memory reverseBonds) = STRATEGY .getTrancheBonds( BONDMAKER, address(this), bondGroupId, currentPriceE8, issuableBondGroupIds[currentTerm], priceUnit, REVERSE_ORACLE ); if (ethAmount > 0) { DOTC.depositEth{value: ethAmount}(); } if (amount > 0) { _issueBonds(bondGroupId, amount); } if (reverseBonds[1] > 0) { // Burn bond and get collateral asset require( BONDMAKER.reverseBondGroupToCollateral(reverseBonds[0], reverseBonds[1]), "Reverse" ); } lastTrancheTime = block.timestamp.toUint64(); emit TrancheBond( uint64(bondGroupId), uint64(amount), uint64(reverseBonds[0]), uint64(reverseBonds[1]) ); } function _burnBond( uint256 bondGroupId, address bondAddress, uint32 liquidateBondNumber, bool isLiquidated ) internal returns (uint32, bool) { BondTokenInterface bond = BondTokenInterface(bondAddress); if (bond.balanceOf(address(this)) > 0) { if (!isLiquidated) { // If this bond group is not liquidated in _liquidateBondGroup, try liquidate // BondMaker contract does not revert even if someone else calls 'BONDMAKER.liquidateBond()' BONDMAKER.liquidateBond(bondGroupId, 0); isLiquidated = true; } bond.burnAll(); liquidateBondNumber += 1; } return (liquidateBondNumber, isLiquidated); } function _liquidateBondGroup( uint256 bondGroupId, uint32 liquidateBondNumber, uint64 maturity, uint64 previousMaturity ) internal returns (uint32) { (bytes32[] memory bondIds, uint256 _maturity) = BONDMAKER.getBondGroup(bondGroupId); if (_maturity > maturity || (_maturity < previousMaturity && previousMaturity != 0)) { return liquidateBondNumber; } bool isLiquidated; for (uint256 i = 0; i < bondIds.length; i++) { (address bondAddress, , , ) = BONDMAKER.getBond(bondIds[i]); (liquidateBondNumber, isLiquidated) = _burnBond( bondGroupId, bondAddress, liquidateBondNumber, isLiquidated ); } return liquidateBondNumber; } function _getSuitableBondGroup(uint256 currentPriceE8) internal view returns (uint256) { uint256 roundedPrice = STRATEGY.calcRoundPrice(currentPriceE8, priceUnit, 1); mapping(uint256 => uint256) storage priceToGroupBondId = strikePriceToBondGroup[currentTerm]; if (priceToGroupBondId[roundedPrice] != 0) { return priceToGroupBondId[roundedPrice]; } // Suitable bond range is in between current price +- 2 * priceUnit for (uint256 i = 1; i <= 2; i++) { if (priceToGroupBondId[roundedPrice - priceUnit * i] != 0) { return priceToGroupBondId[roundedPrice - priceUnit * i]; } if (priceToGroupBondId[roundedPrice + priceUnit * i] != 0) { return priceToGroupBondId[roundedPrice + priceUnit * i]; } } } function _addSuitableBondGroup(uint256 currentPriceE8) internal returns (uint256 bondGroupID) { uint256 callStrikePrice = STRATEGY.calcCallStrikePrice( currentPriceE8, priceUnit, REVERSE_ORACLE ); uint256 _currentTerm = currentTerm; TermInfo memory info = termInfo[_currentTerm]; callStrikePrice = _adjustPrice(info.strikePrice, callStrikePrice); bondGroupID = BOND_REGISTRATOR.registerBondGroup( BONDMAKER, callStrikePrice, info.strikePrice, info.maturity, info.SBTId ); // If reverse oracle is set to aggregator, make Collateral/USD price if (REVERSE_ORACLE) { _addBondGroup( bondGroupID, STRATEGY.calcCallStrikePrice(currentPriceE8, priceUnit, false) ); } else { _addBondGroup(bondGroupID, callStrikePrice); } } function _addBondGroup(uint256 bondGroupId, uint256 callStrikePriceInEthUSD) internal { // Register bond group info issuableBondGroupIds[currentTerm].push(bondGroupId); strikePriceToBondGroup[currentTerm][callStrikePriceInEthUSD] = bondGroupId; (bytes32[] memory bondIDs, ) = BONDMAKER.getBondGroup(bondGroupId); (address bondType1Address, , , ) = BONDMAKER.getBond(bondIDs[1]); // Infinite approve if no approval if (IERC20(bondType1Address).allowance(address(this), address(DOTC)) == 0) { IERC20(bondType1Address).approve(address(DOTC), INFINITY); } (address bondType2Address, , , ) = BONDMAKER.getBond(bondIDs[2]); if (IERC20(bondType2Address).allowance(address(this), address(DOTC)) == 0) { IERC20(bondType2Address).approve(address(DOTC), INFINITY); } (address bondType3Address, , , ) = BONDMAKER.getBond(bondIDs[3]); if (IERC20(bondType3Address).allowance(address(this), address(DOTC)) == 0) { IERC20(bondType3Address).approve(address(DOTC), INFINITY); } } function _updatePriceUnit(uint256 currentPriceE8) internal { uint256 multiplyer = currentPriceE8.div(50 * BASE_PRICE_UNIT); if (multiplyer == 0) { priceUnit = BASE_PRICE_UNIT; } else { priceUnit = ((25 * multiplyer * BASE_PRICE_UNIT) / 10).toUint64(); } } function _updateFeeBase() internal { STRATEGY.registerCurrentFeeBase( currentFeeBase, shareData[currentTerm].totalCollateralPerToken, shareData[currentTerm + 1].totalCollateralPerToken, OWNER, address(ORACLE), REVERSE_ORACLE ); changeSpread(); } /** * @dev When sbtStrikePrice and callStrikePrice have different remainder of 2, * decrease callStrikePrice by 1 to avoid invalid line segment for register new bond */ function _adjustPrice(uint64 sbtStrikePrice, uint256 callStrikePrice) internal pure returns (uint256) { return callStrikePrice.sub(callStrikePrice.sub(sbtStrikePrice) % 2); } function changeSpread() public virtual override {} function _sendTokens(address user, uint256 amount) internal virtual {} function _reserveAsset(uint256 reserveAmountRatioE8) internal virtual {} function _issueBonds(uint256 bondgroupID, uint256 amount) internal virtual {} function getCollateralAddress() external view virtual override returns (address) {} function _applyDecimalGap(uint256 amount, bool isDiv) internal view virtual returns (uint256) {} function getCollateralDecimal() external view virtual override returns (int16) {} function getReserveAddress() external view virtual returns (address) {} function getCollateralAmount() public view virtual override returns (uint256) {} // Reward functions /** * @dev Update reward amount, then update balance */ function _updateBalanceData(address owner, int256 amount) internal { BalanceData memory balanceData = balance[owner]; balanceData.rewardAmount = _calcNextReward(balanceData, currentTerm); balanceData.term = uint64(currentTerm); if (amount < 0) { balanceData.balance = uint256(balanceData.balance) .sub(uint256(amount * -1)) .toUint128(); } else { balanceData.balance = uint256(balanceData.balance).add(uint256(amount)).toUint128(); } balance[owner] = balanceData; } function _updateBalanceDataForLiquidityMove( address owner, uint256 addAmount, uint256 removeAmount, uint256 term ) internal { BalanceData memory balanceData = balance[owner]; // Update reward amount before addliquidity if (addAmount != 0) { balanceData.rewardAmount = _calcNextReward(balanceData, term); balanceData.term = uint64(term); balanceData.balance = balanceData.balance = uint256(balanceData.balance) .add(uint256(addAmount)) .toUint128(); } // Update reward amount after addliquidity balanceData.rewardAmount = _calcNextReward(balanceData, currentTerm); balanceData.term = uint64(currentTerm); // Update balance if remove liquidity if (removeAmount != 0) { balanceData.balance = uint256(balanceData.balance).sub(removeAmount).toUint128(); } balance[owner] = balanceData; } /** * @dev This function is called before change balance of share token * @param term Reward amount is calculated from next term after this function is called to term `term` */ function _calcNextReward(BalanceData memory balanceData, uint256 term) internal view returns (uint64 rewardAmount) { rewardAmount = balanceData.rewardAmount; if (balanceData.balance > 0 && balanceData.term < term) { uint64 index = uint64(totalRewards.length - 1); uint64 referenceTerm = totalRewards[index].term; uint64 rewardTotal = totalRewards[index].value; for (uint256 i = term; i > balanceData.term; i--) { if (i < referenceTerm) { // If i is smaller than the term in which total reward amount is changed, update total reward amount index -= 1; rewardTotal = totalRewards[index].value; referenceTerm = totalRewards[index].term; } // Reward amount is calculated by `total reward amount * user balance / total share` rewardAmount = uint256(rewardAmount) .add( (uint256(rewardTotal).mul(balanceData.balance)).div(shareData[i].totalShare) ) .toUint64(); } } } /** * @notice update reward amount and transfer reward token, then change reward amount to 0 */ function claimReward() public override { BalanceData memory userData = balance[msg.sender]; userData.rewardAmount = _calcNextReward(userData, currentTerm); userData.term = uint64(currentTerm); require(userData.rewardAmount > 0, "No Reward"); uint256 rewardAmount = userData.rewardAmount; userData.rewardAmount = 0; balance[msg.sender] = userData; REWARD_TOKEN.safeTransfer(msg.sender, rewardAmount); } // ERC20 functions /** * @param amount If this value is uint256(-1) infinite approve */ function approve(address spender, uint256 amount) external override returns (bool) { if (amount == uint256(-1)) { amount = uint128(-1); } allowances[msg.sender][spender] = amount.toUint128(); emit Approval(msg.sender, spender, amount); return true; } function transfer(address recipient, uint256 amount) external override returns (bool) { return _transferToken(msg.sender, recipient, amount.toUint128()); } /** * @notice If allowance amount is uint128(-1), allowance amount is not updated */ function transferFrom( address sender, address recipient, uint256 amount ) external override returns (bool) { uint128 currentAllowance = allowances[sender][msg.sender]; if (currentAllowance < amount) { return false; } // Skip if infinity approve if (currentAllowance != uint128(-1)) { allowances[sender][msg.sender] = uint256(allowances[sender][msg.sender]) .sub(amount) .toUint128(); } _transferToken(sender, recipient, amount.toUint128()); return true; } /** * @dev Balance is changed by `_updateBalanceData` to reflect correct reward amount */ function _transferToken( address from, address to, uint128 amount ) internal returns (bool) { if (balance[from].balance < amount) { return false; } _updateBalanceData(from, -1 * int256(amount)); _updateBalanceData(to, int256(amount)); emit Transfer(from, to, uint256(amount)); return true; } function balanceOf(address user) public view override returns (uint256) { return balance[user].balance; } function totalSupply() public view override returns (uint256) { return uint256(shareData[currentTerm].totalShare).sub(totalUnremovedTokens[currentTerm]); } function getLiquidityReservationData(address user) public view returns ( uint128 receivedCollateralTerm, uint128 receivedCollateralAmount, uint128 removeTokenTerm, uint128 removeTokenAmount ) { return ( receivedCollaterals[user].term, receivedCollaterals[user].value, unremovedTokens[user].term, unremovedTokens[user].value ); } function getCurrentStatus() public view override returns ( uint256 term, int16 feeBase, uint32 uncheckbondGroupId, uint64 unit, uint64 trancheTime, bool isDanger ) { return ( currentTerm, currentFeeBase, startBondGroupId, priceUnit, lastTrancheTime, isTotalSupplyDanger ); } function getLiquidationData(uint256 term) public view override returns ( bool isLiquidated, uint32 liquidatedBondGroupID, uint32 endBondGroupId ) { if (term == 0) { term = currentTerm; } isLiquidated = liquidationData[term].isLiquidated; liquidatedBondGroupID = liquidationData[term].liquidatedBondGroupID; endBondGroupId = liquidationData[term].endBondGroupId; } function totalShareData(uint256 term) public view override returns (uint128 totalShare, uint128 totalCollateralPerToken) { if (term == 0) { term = currentTerm; } return (shareData[term].totalShare, shareData[term].totalCollateralPerToken); } function getBondGroupIDFromTermAndPrice(uint256 term, uint256 price) public view override returns (uint256 bondGroupID) { price = STRATEGY.calcRoundPrice(price, priceUnit, 1); if (term == 0) { term = currentTerm; } return strikePriceToBondGroup[term][price]; } function getInfo() public view override returns ( address bondMaker, address strategy, address dotc, address bondPricerAddress, address oracleAddress, address rewardTokenAddress, address registratorAddress, address owner, bool reverseOracle, uint64 basePriceUnit, uint128 maxSupply ) { return ( address(BONDMAKER), address(STRATEGY), address(DOTC), address(BOND_PRICER), address(ORACLE), address(REWARD_TOKEN), address(BOND_REGISTRATOR), OWNER, REVERSE_ORACLE, BASE_PRICE_UNIT, uint128(uint128(-1) / (10**uint256(MAX_SUPPLY_DENUMERATOR))) ); } function getTermInfo(uint256 term) public view override returns ( uint64 maturity, uint64 solidStrikePrice, bytes32 SBTID ) { if (term == 0) { term = currentTerm; } return (termInfo[term].maturity, termInfo[term].strikePrice, termInfo[term].SBTId); } /** * @notice return user's balance including unsettled share token */ function getExpectedBalance(address user, bool hasReservation) external view override returns (uint256 expectedBalance) { expectedBalance = balance[user].balance; if (receivedCollaterals[user].value != 0) { hasReservation = true; if (currentTerm > receivedCollaterals[msg.sender].term) { expectedBalance += _applyDecimalGap( uint256(receivedCollaterals[msg.sender].value).mul(10**decimals).div( uint256( shareData[receivedCollaterals[msg.sender].term + 1] .totalCollateralPerToken ) ), true ); } } } /** * @notice Return current phase of aggregator */ function getCurrentPhase() public view override returns (AggregatorPhase) { if (currentTerm == 0) { return AggregatorPhase.BEFORE_START; } else if (block.timestamp <= termInfo[currentTerm].maturity) { if (block.timestamp <= lastTrancheTime + COOLTIME) { return AggregatorPhase.COOL_TIME; } return AggregatorPhase.ACTIVE; } else if ( block.timestamp > termInfo[currentTerm].maturity && !liquidationData[currentTerm].isLiquidated ) { return AggregatorPhase.AFTER_MATURITY; } return AggregatorPhase.EXPIRED; } /** * @notice Calculate expected reward amount at this point */ function getRewardAmount(address user) public view override returns (uint64) { return _calcNextReward(balance[user], currentTerm); } function getTotalRewards() public view override returns (TotalReward[] memory) { return totalRewards; } function isTotalSupplySafe() public view override returns (bool) { return !isTotalSupplyDanger; } function getTotalUnmovedAssets() public view override returns (uint256, uint256) { return (totalReceivedCollateral[currentTerm], totalUnremovedTokens[currentTerm]); } function allowance(address owner, address spender) public view override returns (uint256) { return allowances[owner][spender]; } function getCollateralPerToken(uint256 term) public view override returns (uint256) { return shareData[term].totalCollateralPerToken; } function getBondGroupIdFromStrikePrice(uint256 term, uint256 strikePrice) public view override returns (uint256) { return strikePriceToBondGroup[term][strikePrice]; } function getBalanceData(address user) external view override returns ( uint128 amount, uint64 term, uint64 rewardAmount ) { return (balance[user].balance, balance[user].term, balance[user].rewardAmount); } /** * @notice Get suitable bond groups for current price */ function getIssuableBondGroups() public view override returns (uint256[] memory) { return issuableBondGroupIds[currentTerm]; } } // File: contracts/BondToken_and_GDOTC/bondMaker/BondMakerCollateralizedEthInterface.sol interface BondMakerCollateralizedEthInterface is BondMakerInterface { function issueNewBonds(uint256 bondGroupID) external payable returns (uint256 amount); } // File: contracts/BondToken_and_GDOTC/util/TransferETH.sol 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/contracts/SimpleAggregator/ReserveETH.sol contract ReserveEth is TransferETH { address owner; modifier onlyOwner() { require(msg.sender == owner, "Error: Only owner can execute this function"); _; } constructor() { owner = msg.sender; } /** * @notice Send ETH to user * Only aggregator can call this function */ function sendAsset(address payable user, uint256 amount) public onlyOwner { _transferETH(user, amount); } } // File: contracts/contracts/SimpleAggregator/SimpleAggregatorCollateralizedEth.sol contract SimpleAggregatorCollateralizedEth is SimpleAggregator, TransferETH { using SafeMath for uint256; ReserveEth internal immutable reserveEth; uint16 internal constant DECIMAL_GAP = 10; constructor( LatestPriceOracleInterface _ethOracle, BondPricerWithAcceptableMaturity _pricer, SimpleStrategyInterface strategy, ERC20 _rewardToken, BondRegistratorInterface _registrator, ExchangeInterface exchangeAddress, VolatilityOracleInterface _volOracle, uint64 _priceUnit, uint64 _firstRewardRate ) SimpleAggregator( _ethOracle, _pricer, strategy, _rewardToken, _registrator, exchangeAddress, _priceUnit, _firstRewardRate, false, _volOracle ) { BondMakerInterface _bondMaker = exchangeAddress.bondMakerAddress(); int16 feeBaseE4 = strategy.getCurrentSpread(msg.sender, address(_ethOracle), false); currentFeeBase = feeBaseE4; exchangeAddress.createVsBondPool(_bondMaker, _volOracle, _pricer, _pricer, feeBaseE4); exchangeAddress.createVsEthPool(_ethOracle, _pricer, feeBaseE4, true); exchangeAddress.createVsEthPool(_ethOracle, _pricer, feeBaseE4, false); reserveEth = new ReserveEth(); } function changeSpread() public override { int16 _currentFeeBase = STRATEGY.getCurrentSpread(OWNER, address(ORACLE), false); require(_currentFeeBase <= 1000 && _currentFeeBase >= 5, "Invalid feebase"); bytes32 poolIDETHSell = DOTC.generateVsEthPoolID(address(this), true); bytes32 poolIDETHBuy = DOTC.generateVsEthPoolID(address(this), false); bytes32 poolIDBond = DOTC.generateVsBondPoolID(address(this), address(BONDMAKER)); DOTC.updateVsEthPool(poolIDETHSell, ORACLE, BOND_PRICER, _currentFeeBase); DOTC.updateVsEthPool(poolIDETHBuy, ORACLE, BOND_PRICER, _currentFeeBase); DOTC.updateVsBondPool(poolIDBond, volOracle, BOND_PRICER, BOND_PRICER, _currentFeeBase); currentFeeBase = _currentFeeBase; } /** * @notice Receive ETH, then call _addLiquidity */ function addLiquidity() external payable isSafeSupply returns (bool success) { success = _addLiquidity(msg.value); } function _sendTokens(address user, uint256 amount) internal override { reserveEth.sendAsset(payable(user), amount); } function _reserveAsset(uint256 collateralPerTokenE8) internal override { uint256 amount = _applyDecimalGap( uint256(totalUnremovedTokens[currentTerm]).mul(collateralPerTokenE8).div(10**decimals), false ); _transferETH(address(reserveEth), amount); } function _issueBonds(uint256 bondgroupID, uint256 amount) internal override { BondMakerCollateralizedEthInterface bm = BondMakerCollateralizedEthInterface( address(BONDMAKER) ); bm.issueNewBonds{value: amount.mul(10**DECIMAL_GAP).mul(1002).div(1000)}(bondgroupID); } function getCollateralAddress() external pure override returns (address) { return address(0); } /** * @dev Decimal gap between ETH and share token is 10 */ function _applyDecimalGap(uint256 amount, bool isDiv) internal pure override returns (uint256) { if (isDiv) { return amount / 10**DECIMAL_GAP; } else { return amount * 10**DECIMAL_GAP; } } /** * @notice Get available collateral amount in this term */ function getCollateralAmount() public view override returns (uint256) { return address(this).balance.sub(totalReceivedCollateral[currentTerm]); } function getCollateralDecimal() external pure override returns (int16) { return 18; } function getReserveAddress() external view override returns (address) { return address(reserveEth); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract LatestPriceOracleInterface","name":"_ethOracle","type":"address"},{"internalType":"contract BondPricerWithAcceptableMaturity","name":"_pricer","type":"address"},{"internalType":"contract SimpleStrategyInterface","name":"strategy","type":"address"},{"internalType":"contract ERC20","name":"_rewardToken","type":"address"},{"internalType":"contract BondRegistratorInterface","name":"_registrator","type":"address"},{"internalType":"contract ExchangeInterface","name":"exchangeAddress","type":"address"},{"internalType":"contract VolatilityOracleInterface","name":"_volOracle","type":"address"},{"internalType":"uint64","name":"_priceUnit","type":"uint64"},{"internalType":"uint64","name":"_firstRewardRate","type":"uint64"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"AddLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","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":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"term","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"}],"name":"SetAddLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"term","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"SetRemoveLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"term","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"SettleLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"issueBondGroupId","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"issueAmount","type":"uint64"},{"indexed":true,"internalType":"uint64","name":"burnBondGroupId","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"burnAmount","type":"uint64"}],"name":"TrancheBond","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":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"term","type":"uint64"},{"indexed":false,"internalType":"int16","name":"newFeeBase","type":"int16"},{"indexed":false,"internalType":"uint64","name":"maturity","type":"uint64"}],"name":"UpdateMaturity","type":"event"},{"inputs":[],"name":"addLiquidity","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"addSuitableBondGroup","outputs":[{"internalType":"uint256","name":"bondGroupID","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"changeSpread","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getBalanceData","outputs":[{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint64","name":"term","type":"uint64"},{"internalType":"uint64","name":"rewardAmount","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"getBondGroupIDFromTermAndPrice","outputs":[{"internalType":"uint256","name":"bondGroupID","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"uint256","name":"strikePrice","type":"uint256"}],"name":"getBondGroupIdFromStrikePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCollateralAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getCollateralAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCollateralDecimal","outputs":[{"internalType":"int16","name":"","type":"int16"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"}],"name":"getCollateralPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentPhase","outputs":[{"internalType":"enum SimpleAggregatorInterface.AggregatorPhase","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentStatus","outputs":[{"internalType":"uint256","name":"term","type":"uint256"},{"internalType":"int16","name":"feeBase","type":"int16"},{"internalType":"uint32","name":"uncheckbondGroupId","type":"uint32"},{"internalType":"uint64","name":"unit","type":"uint64"},{"internalType":"uint64","name":"trancheTime","type":"uint64"},{"internalType":"bool","name":"isDanger","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bool","name":"hasReservation","type":"bool"}],"name":"getExpectedBalance","outputs":[{"internalType":"uint256","name":"expectedBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getInfo","outputs":[{"internalType":"address","name":"bondMaker","type":"address"},{"internalType":"address","name":"strategy","type":"address"},{"internalType":"address","name":"dotc","type":"address"},{"internalType":"address","name":"bondPricerAddress","type":"address"},{"internalType":"address","name":"oracleAddress","type":"address"},{"internalType":"address","name":"rewardTokenAddress","type":"address"},{"internalType":"address","name":"registratorAddress","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"reverseOracle","type":"bool"},{"internalType":"uint64","name":"basePriceUnit","type":"uint64"},{"internalType":"uint128","name":"maxSupply","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getIssuableBondGroups","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"}],"name":"getLiquidationData","outputs":[{"internalType":"bool","name":"isLiquidated","type":"bool"},{"internalType":"uint32","name":"liquidatedBondGroupID","type":"uint32"},{"internalType":"uint32","name":"endBondGroupId","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getLiquidityReservationData","outputs":[{"internalType":"uint128","name":"receivedCollateralTerm","type":"uint128"},{"internalType":"uint128","name":"receivedCollateralAmount","type":"uint128"},{"internalType":"uint128","name":"removeTokenTerm","type":"uint128"},{"internalType":"uint128","name":"removeTokenAmount","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserveAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getRewardAmount","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"}],"name":"getTermInfo","outputs":[{"internalType":"uint64","name":"maturity","type":"uint64"},{"internalType":"uint64","name":"solidStrikePrice","type":"uint64"},{"internalType":"bytes32","name":"SBTID","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalRewards","outputs":[{"components":[{"internalType":"uint64","name":"term","type":"uint64"},{"internalType":"uint64","name":"value","type":"uint64"}],"internalType":"struct SimpleAggregatorInterface.TotalReward[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalUnmovedAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isTotalSupplySafe","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidateBonds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"amount","type":"uint128"}],"name":"removeLiquidity","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renewMaturity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleTokens","outputs":[{"internalType":"uint256","name":"unsentETH","type":"uint256"},{"internalType":"uint256","name":"unsentToken","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"term","type":"uint256"}],"name":"totalShareData","outputs":[{"internalType":"uint128","name":"totalShare","type":"uint128"},{"internalType":"uint128","name":"totalCollateralPerToken","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trancheBonds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateStartBondGroupId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"rewardRate","type":"uint64"}],"name":"updateTotalReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6101e06040526008805463ffffffff60801b19167001000000000000000000000000000000001790553480156200003557600080fd5b506040516200693738038062006937833981016040819052620000589162000652565b888888888888878760008b80806000806101000a8154816001600160a01b0302191690836001600160a01b0316021790555050846001600160a01b0316630b1a35546040518163ffffffff1660e01b815260040160206040518083038186803b158015620000c557600080fd5b505afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062c565b6001600160601b0319606091821b8116610120528a821b811660e0528b821b8116610100526001600160c01b031960c087811b919091166101a05284151560f81b6101805289831b8216905287821b81166101405286821b811660a05289821b166080526040805180820190915260018082526001600160401b038681166020840181815260048054948501815560005293517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b9093018054945183166801000000000000000002600160401b600160801b03199484166001600160401b031996871617949094169390931790925560088054909316908816179091553390911b610160526305f5e10011801590620002285750655af3107a40006001600160401b03841611155b6200026a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200026190620007cb565b60405180910390fd5b505050505050505050506000846001600160a01b0316630b1a35546040518163ffffffff1660e01b815260040160206040518083038186803b158015620002b057600080fd5b505afa158015620002c5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002eb91906200062c565b90506000886001600160a01b031663601b45e2338d60006040518463ffffffff1660e01b8152600401620003229392919062000745565b60206040518083038186803b1580156200033b57600080fd5b505afa15801562000350573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000376919062000722565b6008805461ffff60a01b19167401000000000000000000000000000000000000000061ffff600185900b16021790556040517f78f286d90000000000000000000000000000000000000000000000000000000081529091506001600160a01b038716906378f286d990620003f790859089908f908190889060040162000769565b602060405180830381600087803b1580156200041257600080fd5b505af115801562000427573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200044d919062000613565b506040517f241d92290000000000000000000000000000000000000000000000000000000081526001600160a01b0387169063241d9229906200049c908e908e9086906001906004016200079f565b602060405180830381600087803b158015620004b757600080fd5b505af1158015620004cc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004f2919062000613565b506040517f241d92290000000000000000000000000000000000000000000000000000000081526001600160a01b0387169063241d92299062000541908e908e9086906000906004016200079f565b602060405180830381600087803b1580156200055c57600080fd5b505af115801562000571573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000597919062000613565b50604051620005a690620005e7565b604051809103906000f080158015620005c3573d6000803e3d6000fd5b5060601b6001600160601b0319166101c052506200081b9950505050505050505050565b61039380620065a483390190565b80516001600160401b03811681146200060d57600080fd5b92915050565b60006020828403121562000625578081fd5b5051919050565b6000602082840312156200063e578081fd5b81516200064b8162000802565b9392505050565b60008060008060008060008060006101208a8c03121562000671578485fd5b89516200067e8162000802565b60208b0151909950620006918162000802565b60408b0151909850620006a48162000802565b60608b0151909750620006b78162000802565b60808b0151909650620006ca8162000802565b60a08b0151909550620006dd8162000802565b60c08b0151909450620006f08162000802565b9250620007018b60e08c01620005f5565b9150620007138b6101008c01620005f5565b90509295985092959850929598565b60006020828403121562000734578081fd5b81518060010b81146200064b578182fd5b6001600160a01b039384168152919092166020820152901515604082015260600190565b6001600160a01b03958616815293851660208501529184166040840152909216606082015260019190910b608082015260a00190565b6001600160a01b03948516815292909316602083015260010b6040820152901515606082015260800190565b6020808252600c908201527f4f7574206f662072616e67650000000000000000000000000000000000000000604082015260600190565b6001600160a01b03811681146200081857600080fd5b50565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c6101205160601c6101405160601c6101605160601c6101805160f81c6101a05160c01c6101c05160601c615b9862000a0c6000398061198a5280612bd652806141f152508061164d528061410d528061414b528061418a52508061162b5280611c895280612b335280612d8052806136a05280613847525080610c5f5280611609528061271c5280612aef5250806115e75280612e07528061379a52508061083c5280610ead528061151b5280611c575280611db352806121445280612e365280612edd52806137c75280613ad65280613c225280613d1652806142d55280614365528061456352806147615280614a98525080610c815280610f82528061104652806115a352806118a65280611b425280612b115280612c94525080610fa452806110685280611111528061158152806130da5250806115c55280612004525080610d4c5280610dda5280610e7d5280610f53528061101552806110dc528061155f5280611d10528061224552806122d45280612fa1528061443f52806144df528061463d52806146dd528061483b52806148db525080610c32528061153d5280611c2a52806125a85280612a9d5280612bff5280612d455280613665528061388b528061395a5250615b986000f3fe60806040526004361061024a5760003560e01c806392da91ad11610139578063b88a802f116100b6578063dd62ed3e1161007a578063dd62ed3e146106f4578063e0e54dec14610714578063e627f2db14610734578063e8078d9414610756578063ef4498ff1461075e578063fde6fad91461077e5761028d565b8063b88a802f14610673578063c82e377814610688578063cc4df8ae146106aa578063d28f3330146106bf578063d3339533146106d45761028d565b80639a8fac74116100fd5780639a8fac74146105e0578063a3a40ea5146105f5578063a3dd261914610617578063a9059cbb1461063e578063ae1162561461065e5761028d565b806392da91ad1461055257806395d89b41146105725780639649a73714610587578063979c6fe61461059c5780639960d742146105cb5761028d565b80633beeae20116101c75780635a9b0b891161018b5780635a9b0b89146104855780636c13ba78146104b157806370a08231146104e15780638417cb13146105015780638c5301c0146105235761028d565b80633beeae20146103d257806344a040f5146103e75780634759898f146104145780634fac075b14610436578063506718ef146104655761028d565b806318160ddd1161020e57806318160ddd1461035157806323b872dd146103665780632e20da2714610386578063313ce5671461039b578063315deeaa146103bd5761028d565b806302ecdef21461029257806306fdde03146102a9578063095ea7b3146102d45780630dad4e4b1461030157806315e524871461032e5761028d565b3661028d57604051309033907fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9061028390349061532b565b60405180910390a3005b600080fd5b34801561029e57600080fd5b506102a76107ac565b005b3480156102b557600080fd5b506102be610914565b6040516102cb9190615503565b60405180910390f35b3480156102e057600080fd5b506102f46102ef366004614eb8565b610945565b6040516102cb9190615302565b34801561030d57600080fd5b5061032161031c366004614e8b565b6109e9565b6040516102cb919061532b565b34801561033a57600080fd5b50610343610abe565b6040516102cb9291906159e7565b34801561035d57600080fd5b50610321610aed565b34801561037257600080fd5b506102f4610381366004614e4b565b610b26565b34801561039257600080fd5b506102a7610c18565b3480156103a757600080fd5b506103b0611199565b6040516102cb9190615a9b565b3480156103c957600080fd5b5061032161119e565b3480156103de57600080fd5b506102a76111c5565b3480156103f357600080fd5b50610407610402366004614df7565b611447565b6040516102cb9190615a49565b34801561042057600080fd5b506104296114b3565b6040516102cb9190615493565b34801561044257600080fd5b50610456610451366004615051565b6114b8565b6040516102cb9392919061530d565b34801561047157600080fd5b50610321610480366004615051565b6114f7565b34801561049157600080fd5b5061049a611519565b6040516102cb9b9a999897969594939291906151be565b3480156104bd57600080fd5b506104d16104cc366004614df7565b61167e565b6040516102cb9493929190615953565b3480156104ed57600080fd5b506103216104fc366004614df7565b6116c5565b34801561050d57600080fd5b506105166116e9565b6040516102cb919061515c565b34801561052f57600080fd5b5061054361053e366004614df7565b6116ee565b6040516102cb9392919061597e565b34801561055e57600080fd5b506102f461056d36600461502a565b61172e565b34801561057e57600080fd5b506102be611848565b34801561059357600080fd5b50610321611868565b3480156105a857600080fd5b506105bc6105b7366004615051565b611948565b6040516102cb93929190615a77565b3480156105d757600080fd5b50610516611988565b3480156105ec57600080fd5b506102f46119ac565b34801561060157600080fd5b5061060a6119bd565b6040516102cb919061547f565b34801561062357600080fd5b5061062c611a77565b6040516102cb969594939291906159a8565b34801561064a57600080fd5b506102f4610659366004614eb8565b611abd565b34801561066a57600080fd5b506102a7611acd565b34801561067f57600080fd5b506102a7611ed9565b34801561069457600080fd5b5061069d61202b565b6040516102cb91906152be565b3480156106b657600080fd5b5061034361208e565b3480156106cb57600080fd5b506102a76120b4565b3480156106e057600080fd5b506103216106ef366004615069565b61253a565b34801561070057600080fd5b5061032161070f366004614e13565b612557565b34801561072057600080fd5b5061032161072f366004615069565b61258b565b34801561074057600080fd5b50610749612665565b6040516102cb9190615262565b6102f46126db565b34801561076a57600080fd5b506102a7610779366004615104565b612711565b34801561078a57600080fd5b5061079e610799366004615051565b612842565b6040516102cb929190615939565b6007546107d45760405162461bcd60e51b81526004016107cb90615870565b60405180910390fd5b60085460075460001901600090815260016020526040902054600160801b90910463ffffffff16906001600160401b0316806108225760405162461bcd60e51b81526004016107cb90615809565b6040516301e5ddfb60e71b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f2eefd8090610871908690600401615a38565b60006040518083038186803b15801561088957600080fd5b505afa15801561089d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108c59190810190614f2b565b915050816001600160401b031681106109035750506008805463ffffffff909216600160801b0263ffffffff60801b19909216919091179055610912565b60018301925050610822565b50505b565b604051806040016040528060158152602001744c49454e5f41474752454741544f525f534841524560581b81525081565b600060001982141561095c576001600160801b0391505b61096582612879565b336000818152600c602090815260408083206001600160a01b03891680855292529182902080546001600160801b0319166001600160801b039590951694909417909355517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906109d790869061532b565b60405180910390a35060015b92915050565b6001600160a01b0382166000908152600b60209081526040808320546009909252909120546001600160801b0391821691600160801b90910416156109e35733600090815260096020526040902054600754600193506001600160801b0390911610156109e357336000818152600960208181526040808420546001600160801b0380821660010181168652600684529185205495909452919052610ab792610ab092600160801b91829004831692610aaa92909104166305f5e1006128a2565b906128dc565b600161291e565b0192915050565b6007546000908152600d6020908152604080832054600e909252909120546001600160801b0391821691169091565b6007546000908152600e60209081526040808320546006909252822054610b20916001600160801b039182169116612942565b90505b90565b6001600160a01b0383166000908152600c602090815260408083203384529091528120546001600160801b031682811015610b65576000915050610c11565b6001600160801b0381811614610bf7576001600160a01b0385166000908152600c60209081526040808320338452909152902054610bb590610bb0906001600160801b031685612942565b612879565b6001600160a01b0386166000908152600c60209081526040808320338452909152902080546001600160801b0319166001600160801b03929092169190911790555b610c0a8585610c0586612879565b612984565b5060019150505b9392505050565b60405163300da2f160e11b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063601b45e290610cab907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000000090869060040161523e565b60206040518083038186803b158015610cc357600080fd5b505afa158015610cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfb9190615009565b90506103e88160010b13158015610d16575060058160010b12155b610d325760405162461bcd60e51b81526004016107cb9061571c565b6040516311ed607760e01b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906311ed607790610d8490309060019060040161518a565b60206040518083038186803b158015610d9c57600080fd5b505afa158015610db0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd49190614ff1565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166311ed60773060006040518363ffffffff1660e01b8152600401610e2792919061518a565b60206040518083038186803b158015610e3f57600080fd5b505afa158015610e53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e779190614ff1565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663488abbfc307f00000000000000000000000000000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401610ee9929190615170565b60206040518083038186803b158015610f0157600080fd5b505afa158015610f15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f399190614ff1565b604051631711ddb160e21b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635c4776c490610fce9086907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908a90600401615334565b600060405180830381600087803b158015610fe857600080fd5b505af1158015610ffc573d6000803e3d6000fd5b5050604051631711ddb160e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169250635c4776c491506110929085907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908a90600401615334565b600060405180830381600087803b1580156110ac57600080fd5b505af11580156110c0573d6000803e3d6000fd5b5050600054604051630ccb63b760e41b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116945063ccb63b70935061113d9286929116907f00000000000000000000000000000000000000000000000000000000000000009081908b9060040161535c565b600060405180830381600087803b15801561115757600080fd5b505af115801561116b573d6000803e3d6000fd5b50506008805460019790970b61ffff16600160a01b0261ffff60a01b19909716969096179095555050505050565b600881565b6007546000908152600d6020526040812054610b20903031906001600160801b0316612942565b6007546000818152600e602090815260408083205460059092528220549192839290916001600160801b031690600160401b900460ff1680611205575081155b6112215760405162461bcd60e51b81526004016107cb90615536565b6000828152600660205260409020546001600160801b031680156112a657600061124961119e565b9050611260610ab083610aaa846305f5e1006128a2565b6000858152600d602052604090205490955061129e90869061128f906001600160801b03166305f5e1006128a2565b8161129657fe5b04600161291e565b9550506112f0565b6000838152600d60205260409020546001600160801b0316156112f0576000838152600d60205260409020546112e6906001600160801b0316600161291e565b94506305f5e10093505b8085016112fc85612879565b60018501600090815260066020526040902080546001600160801b03928316600160801b029216919091179055611340610bb08461133a858a612a40565b90612942565b60018501600090815260066020526040902080546001600160801b0319166001600160801b0392831617908190556c2af31dc4611873bf3f70834acd91161115611398576008805460ff60b01b1916600160b01b1790555b83156113a6576113a6612a65565b6000811180156113b65750600083115b156113c4576113c485612b95565b6113cc612bfb565b6113d7600754613151565b6008546007546000908152600160208190526040918290205491516001600160401b03948516947fb6468ad5c9ad279cc97382791cf54035b2adbdc6126bee312967c4fdbb9a56da9461143794600160a01b90910490930b9216906154e7565b60405180910390a2505050505050565b6001600160a01b0381166000908152600b60209081526040808320815160608101835290546001600160801b03811682526001600160401b03600160801b8204811694830194909452600160c01b9004909216908201526007546114ab9190613176565b90505b919050565b601290565b60008080836114c75760075493505b50505060009081526005602052604090205460ff600160401b8204169163ffffffff600160201b83048116921690565b600090815260066020526040902054600160801b90046001600160801b031690565b7f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906c2af31dc4611873bf3f70834acd90565b6001600160a01b0316600090815260096020908152604080832054600a909252909120546001600160801b0380831693600160801b93849004821693828416930490911690565b6001600160a01b03166000908152600b60205260409020546001600160801b031690565b600090565b6001600160a01b03166000908152600b60205260409020546001600160801b038116916001600160401b03600160c01b8304811692600160801b90041690565b600080600061173b613309565b600754336000908152600a60205260409020549295509093509150600160801b90046001600160801b031661179357336000908152600a6020526040902080546001600160801b0319166001600160801b0383161790555b336000818152600a6020908152604080832080546001600160801b03600160801b80830482168d0182160291811691909117909155858452600e9092529091208054808316890183166001600160801b0319919091161790556117fb919085908816856134c1565b80336001600160a01b03167f3518f79326efc4570db0ebb1195252c857df4c2beb5932ab886faa94251a50e0876040516118359190615925565b60405180910390a3506001949350505050565b6040518060400160405280600481526020016309882a6960e31b81525081565b6007546000908152600160205260408120546001600160401b03164211156118a25760405162461bcd60e51b81526004016107cb90615600565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156118ff57600080fd5b505af1158015611913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119379190614ff1565b905061194281613646565b91505090565b60008080836119575760075493505b505050600090815260016020819052604090912080549101546001600160401b0380831693600160401b9093041691565b7f000000000000000000000000000000000000000000000000000000000000000090565b600854600160b01b900460ff161590565b6000600754600014156119d257506000610b23565b6007546000908152600160205260409020546001600160401b03164211611a22576008546001600160401b03600160401b909104166203f480014211611a1a57506002610b23565b506001610b23565b6007546000908152600160205260409020546001600160401b031642118015611a645750600754600090815260056020526040902054600160401b900460ff16155b15611a7157506003610b23565b50600490565b6007546008549091600160a01b820460010b91600160801b810463ffffffff16916001600160401b0380831692600160401b810490911691600160b01b90910460ff1690565b6000610c113384610c0585612879565b6007546000908152600160205260409020546001600160401b0316421115611b075760405162461bcd60e51b81526004016107cb90615600565b6008546001600160401b03600160401b909104166203f480014211611b3e5760405162461bcd60e51b81526004016107cb90615596565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611b9b57600080fd5b505af1158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd39190614ff1565b90506000611be08261393b565b905080611bf357611bf082613646565b90505b600080611bfe614db9565b6007546000908152600260205260409081902060085491516329069bdd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926329069bdd92611cb1927f00000000000000000000000000000000000000000000000000000000000000009230928b928d926001600160401b0316907f00000000000000000000000000000000000000000000000000000000000000009060040161538d565b60806040518083038186803b158015611cc957600080fd5b505afa158015611cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d01919061508a565b919450925090508115611d83577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663439370b1836040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d6957600080fd5b505af1158015611d7d573d6000803e3d6000fd5b50505050505b8215611d9357611d938484613ad4565b602081015115611e5c578051602082015160405163b9601d7760e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169263b9601d7792611dee926004016159e7565b602060405180830381600087803b158015611e0857600080fd5b505af1158015611e1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e409190614fd5565b611e5c5760405162461bcd60e51b81526004016107cb9061577c565b611e6542613151565b6008805467ffffffffffffffff60401b1916600160401b6001600160401b039384160217905581516020830151604051918316928716917f2eaafc32eed9e5ff41c1b57ddd1ef894ec4eb7499efb581d50edffa27f6af23291611eca91889190615a5d565b60405180910390a35050505050565b611ee1614dd7565b50336000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b900490911691810191909152600754611f42908290613176565b6001600160401b03908116602083018190526007549091166040830152611f7b5760405162461bcd60e51b81526004016107cb906156d2565b60208181018051600080835233808252600b909452604090819020855181549451928701516001600160801b03199095166001600160801b039091161767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b9483169490940293909317909255169061090f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169083613b9a565b60075460009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561208457602002820191906000526020600020905b815481526020019060010190808311612070575b5050505050905090565b600080600061209b613309565b919450925090506120af33836000846134c1565b509091565b6007546000908152600160205260409020546001600160401b031642116120ed5760405162461bcd60e51b81526004016107cb906158df565b600754600081815260056020526040902054600160401b900460ff16156121265760405162461bcd60e51b81526004016107cb90615904565b60008181526005602052604090205463ffffffff166121ff576121d87f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ac3fd8866040518163ffffffff1660e01b815260040160206040518083038186803b15801561219b57600080fd5b505afa1580156121af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d39190614ff1565b613bf5565b6000828152600560205260409020805463ffffffff191663ffffffff929092169190911790555b6000818152600160205260408082205460001984018352818320549151631c1b06f760e11b8152839283926001600160401b039081169291169083906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906338360dee9061227a90309060040161515c565b60206040518083038186803b15801561229257600080fd5b505afa1580156122a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ca9190614ff1565b90508015612346577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a0ef91df6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561232d57600080fd5b505af1158015612341573d6000803e3d6000fd5b505050505b50600086815260056020526040902054600160201b900463ffffffff1661237e57600854600160801b900463ffffffff16935061239d565b600086815260056020526040902054600160201b900463ffffffff1693505b600086815260056020526040902054603263ffffffff91821686900390911611156123ff576000868152600560205260409020805463ffffffff60328701908116600160201b0267ffffffff0000000019909216919091179091559450612417565b60008681526005602052604090205463ffffffff1694505b63ffffffff84165b8563ffffffff168110156124c25761243981858585613c1a565b935060098463ffffffff1611156124ba576001860363ffffffff1681141561247f576000878152600560205260409020805460ff60401b1916600160401b1790556124ae565b6000878152600560205260409020805467ffffffff000000001916600160201b6001840163ffffffff16021790555b50505050505050610912565b60010161241f565b5060008681526005602052604090205463ffffffff86811691161415612506576000868152600560205260409020805460ff60401b1916600160401b179055612532565b6000868152600560205260409020805467ffffffff000000001916600160201b63ffffffff8816021790555b505050505050565b600091825260036020908152604080842092845291905290205490565b6001600160a01b039182166000908152600c602090815260408083209390941682529190915220546001600160801b031690565b6008546040516351d19dc760e11b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a3a33b8e916125ea9186916001600160401b031690600190600401615a16565b60206040518083038186803b15801561260257600080fd5b505afa158015612616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263a9190614ff1565b9150826126475760075492505b50600091825260036020908152604080842092845291905290205490565b60606004805480602002602001604051908101604052809291908181526020016000905b828210156126d257600084815260209081902060408051808201909152908401546001600160401b038082168352600160401b9091041681830152825260019092019101612689565b50505050905090565b600854600090600160b01b900460ff16156127085760405162461bcd60e51b81526004016107cb906156f5565b610b2034613df2565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146127595760405162461bcd60e51b81526004016107cb906156ab565b6007546127785760405162461bcd60e51b81526004016107cb90615870565b6305f5e1006001600160401b038216108015906127a45750655af3107a40006001600160401b03821611155b6127c05760405162461bcd60e51b81526004016107cb9061579d565b600460405180604001604052806127d8600754613151565b60019081016001600160401b03908116835294851660209283015283549081018455600093845292819020825193018054929091015167ffffffffffffffff199092169284169290921767ffffffffffffffff60401b1916600160401b9190931602919091179055565b600080826128505760075492505b50506000908152600660205260409020546001600160801b0380821692600160801b9092041690565b6000600160801b821061289e5760405162461bcd60e51b81526004016107cb906155b9565b5090565b6000826128b1575060006109e3565b828202828482816128be57fe5b0414610c115760405162461bcd60e51b81526004016107cb90615624565b6000610c1183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613f0c565b6000811561293457506402540be40082046109e3565b506402540be40082026109e3565b6000610c1183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613f43565b6001600160a01b0383166000908152600b60205260408120546001600160801b03808416911610156129b857506000610c11565b6129cf84836001600160801b031660001902613f6f565b6129e283836001600160801b0316613f6f565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846001600160801b0316604051612a2e919061532b565b60405180910390a35060019392505050565b600082820183811015610c115760405162461bcd60e51b81526004016107cb9061555f565b6008546007546000818152600660205260408082205460019384018352918190205490516379b347db60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016946379b347db94612b5b94600160a01b909204900b926001600160801b03600160801b928390048116939290910416907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906004016154a1565b600060405180830381600087803b158015612b7557600080fd5b505af1158015612b89573d6000803e3d6000fd5b50505050610912610c18565b6007546000908152600e6020526040812054612bcf90612bc8906305f5e10090610aaa906001600160801b0316866128a2565b600061291e565b905061090f7f0000000000000000000000000000000000000000000000000000000000000000826140d8565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ca579d0a6040518163ffffffff1660e01b815260040160206040518083038186803b158015612c5657600080fd5b505afa158015612c6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c8e9190614ff1565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612ced57600080fd5b505af1158015612d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d259190614ff1565b600854604051637298096d60e11b81529192506000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163e53012da91612da89186916001600160401b03909116907f0000000000000000000000000000000000000000000000000000000000000000906004016159f5565b60206040518083038186803b158015612dc057600080fd5b505afa158015612dd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612df89190614ff1565b9050612e03826140fb565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a38593887f0000000000000000000000000000000000000000000000000000000000000000612e5e85613151565b612e6788613151565b6040518463ffffffff1660e01b8152600401612e8593929190615455565b602060405180830381600087803b158015612e9f57600080fd5b505af1158015612eb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed79190614ff1565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326d6c97b836040518263ffffffff1660e01b8152600401612f27919061532b565b60806040518083038186803b158015612f3f57600080fd5b505afa158015612f53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f779190614ee3565b505060405163095ea7b360e01b8152919250506001600160a01b0382169063095ea7b390612fcd907f000000000000000000000000000000000000000000000000000000000000000090600019906004016151a5565b602060405180830381600087803b158015612fe757600080fd5b505af1158015612ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061301f9190614fd5565b50600780546001019055613031614dd7565b604051806060016040528061304588613151565b6001600160401b0316815260200161305c86613151565b6001600160401b039081168252602091820186905260075460009081526001808452604091829020855181549587015167ffffffffffffffff199096169085161767ffffffffffffffff60401b1916600160401b959094169490940292909217835583810151929091019190915551631d3b07f760e21b81529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906374ec1fdc9061311790899060040161532b565b600060405180830381600087803b15801561313157600080fd5b505af1158015613145573d6000803e3d6000fd5b50505050505050505050565b6000600160401b821061289e5760405162461bcd60e51b81526004016107cb90615665565b602082015182516001600160801b0316158015906131a057508183604001516001600160401b0316105b156109e357600480546000198101916000916001600160401b0384169081106131c557fe5b6000918252602082200154600480546001600160401b039283169450909185169081106131ee57fe5b600091825260209091200154600160401b90046001600160401b03169050845b86604001516001600160401b03168111156132ff57826001600160401b03168110156132a1576001840393506004846001600160401b03168154811061325057fe5b9060005260206000200160000160089054906101000a90046001600160401b031691506004846001600160401b03168154811061328957fe5b6000918252602090912001546001600160401b031692505b60008181526006602052604090205487516132f4916132ef916132df916001600160801b0390811691610aaa916001600160401b03891691166128a2565b6001600160401b03881690612a40565b613151565b94506000190161320e565b5050505092915050565b600754336000908152600a602090815260408083205460099092528220549192839283926001600160801b0380821692600160801b92839004821692818316929104168461336657600080600097509750975050505050506134bc565b6001600160801b038316158015906133865750836001600160801b031685115b156133ef576001600160801b036001850181166000908152600660205260409020546133cc91612bc8916305f5e10091610aaa9188821691600160801b909104166128a2565b975087156133de576133de33896141da565b336000908152600a60205260408120555b6001600160801b0381161580159061340f5750816001600160801b031685115b15613472576001600160801b0360018301811660009081526006602052604090205461345391610ab091600160801b9004811690610aaa9085166305f5e1006128a2565b3360009081526009602052604081205596506001600160801b03821695505b84336001600160a01b03167fb11715e80d7e8d99a84fdd2112e0c3b821523d7416cb2082ec62d76c76f6f0168a8a6040516134ae9291906159e7565b60405180910390a350505050505b909192565b6134c9614dd7565b506001600160a01b0384166000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b9004909116918101919091528315613571576135358183613176565b6001600160401b03908116602083015282166040820152805161356590610bb0906001600160801b031686612a40565b6001600160801b031681525b61357d81600754613176565b6001600160401b03908116602083015260075416604082015282156135c15780516135b590610bb0906001600160801b031685612942565b6001600160801b031681525b6001600160a01b03949094166000908152600b6020908152604091829020865181549288015193909701516001600160801b03199092166001600160801b039097169690961767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b929091169190910217909355505050565b60085460405163a072a3e560e01b815260009182916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a072a3e5916136c89187916001600160401b03909116907f0000000000000000000000000000000000000000000000000000000000000000906004016159f5565b60206040518083038186803b1580156136e057600080fd5b505afa1580156136f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137189190614ff1565b600754909150613726614dd7565b50600081815260016020818152604092839020835160608101855281546001600160401b038082168352600160401b9091041692810183905292015492820192909252906137749084614256565b602082015182516040808501519051635b1caa5760e11b81529396506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169363b63954ae936137f1937f0000000000000000000000000000000000000000000000000000000000000000938a9360040161541e565b602060405180830381600087803b15801561380b57600080fd5b505af115801561381f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138439190614ff1565b93507f0000000000000000000000000000000000000000000000000000000000000000156139295760085460405163a072a3e560e01b81526139249186916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a072a3e5916138cf918b916001600160401b03909116906000906004016159f5565b60206040518083038186803b1580156138e757600080fd5b505afa1580156138fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061391f9190614ff1565b614280565b613933565b6139338484614280565b505050919050565b6008546040516351d19dc760e11b815260009182916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a3a33b8e9161399e9187916001600160401b0390911690600190600401615a16565b60206040518083038186803b1580156139b657600080fd5b505afa1580156139ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139ee9190614ff1565b600754600090815260036020908152604080832084845291829052909120549192509015613a2a576000918252602052604090205490506114ae565b60015b60028111613933576008546001600160401b03168102830360009081526020839052604090205415613a80576008546001600160401b0316029091036000908152602091909152604090205490506114ae565b6008546001600160401b03168102830160009081526020839052604090205415613acc576008546001600160401b031602919091016000908152602091909152604090205490506114ae565b600101613a2d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b038116638376c24d613b256103e8610aaa6103ea613b1f886402540be4006128a2565b906128a2565b856040518363ffffffff1660e01b8152600401613b42919061532b565b6020604051808303818588803b158015613b5b57600080fd5b505af1158015613b6f573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613b949190614ff1565b50505050565b613bf08363a9059cbb60e01b8484604051602401613bb99291906151a5565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614962565b505050565b6000600160201b821061289e5760405162461bcd60e51b81526004016107cb906157c3565b6000606060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f2eefd80886040518263ffffffff1660e01b8152600401613c6c919061532b565b60006040518083038186803b158015613c8457600080fd5b505afa158015613c98573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613cc09190810190614f2b565b91509150846001600160401b0316811180613cf65750836001600160401b031681108015613cf657506001600160401b03841615155b15613d05578592505050613dea565b6000805b8351811015613de25760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326d6c97b868481518110613d4f57fe5b60200260200101516040518263ffffffff1660e01b8152600401613d73919061532b565b60806040518083038186803b158015613d8b57600080fd5b505afa158015613d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613dc39190614ee3565b5050509050613dd48a828b866149f1565b909950925050600101613d09565b508693505050505b949350505050565b6000806000613dff613309565b9250925050613e1133836000846134c1565b60075433600090815260096020526040902054600160801b90046001600160801b0316613e615733600090815260096020526040902080546001600160801b0319166001600160801b0383161790555b613e6a85612879565b33600090815260096020526040902080546001600160801b03600160801b808304821690940181169093029216919091179055613ea685612879565b6000828152600d60205260409081902080546001600160801b031981166001600160801b0391821694909401169290921790915551819033907f4c86739b331ba35e12897451019b4a8cca47a228be900c18ab3a8ffa5dfe7e539061183590899061532b565b60008183613f2d5760405162461bcd60e51b81526004016107cb9190615503565b506000838581613f3957fe5b0495945050505050565b60008184841115613f675760405162461bcd60e51b81526004016107cb9190615503565b505050900390565b613f77614dd7565b506001600160a01b0382166000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b900490911691810191909152600754613fe1908290613176565b6001600160401b039081166020830152600754166040820152600082121561403057805161402090610bb0906001600160801b03166000859003612942565b6001600160801b03168152614055565b805161404990610bb0906001600160801b031684612a40565b6001600160801b031681525b6001600160a01b03929092166000908152600b6020908152604091829020845181549286015193909501516001600160801b03199092166001600160801b039095169490941767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b92909116919091021790915550565b61090f82826040518060600160405280602c8152602001615b37602c9139614bb0565b6000614133826001600160401b0360327f000000000000000000000000000000000000000000000000000000000000000002166128dc565b90508061417b576008805467ffffffffffffffff19167f00000000000000000000000000000000000000000000000000000000000000006001600160401b031617905561090f565b6141b5600a6001600160401b037f000000000000000000000000000000000000000000000000000000000000000016830260190204613151565b6008805467ffffffffffffffff19166001600160401b03929092169190911790555050565b60405163ed3de48760e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ed3de4879061422890859085906004016151a5565b600060405180830381600087803b15801561424257600080fd5b505af1158015612532573d6000803e3d6000fd5b6000610c116002614270846001600160401b038716612942565b8161427757fe5b84919006612942565b60078054600090815260026020908152604080832080546001810182559084528284200186905592548252600381528282208483529052819020839055516301e5ddfb60e71b81526060906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f2eefd809061430a90869060040161532b565b60006040518083038186803b15801561432257600080fd5b505afa158015614336573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261435e9190810190614f2b565b50905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326d6c97b8360018151811061439f57fe5b60200260200101516040518263ffffffff1660e01b81526004016143c3919061532b565b60806040518083038186803b1580156143db57600080fd5b505afa1580156143ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144139190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906144679030907f000000000000000000000000000000000000000000000000000000000000000090600401615170565b60206040518083038186803b15801561447f57600080fd5b505afa158015614493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144b79190614ff1565b61455f5760405163095ea7b360e01b81526001600160a01b0382169063095ea7b39061450b907f000000000000000000000000000000000000000000000000000000000000000090600019906004016151a5565b602060405180830381600087803b15801561452557600080fd5b505af1158015614539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061455d9190614fd5565b505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326d6c97b8460028151811061459d57fe5b60200260200101516040518263ffffffff1660e01b81526004016145c1919061532b565b60806040518083038186803b1580156145d957600080fd5b505afa1580156145ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146119190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906146659030907f000000000000000000000000000000000000000000000000000000000000000090600401615170565b60206040518083038186803b15801561467d57600080fd5b505afa158015614691573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146b59190614ff1565b61475d5760405163095ea7b360e01b81526001600160a01b0382169063095ea7b390614709907f000000000000000000000000000000000000000000000000000000000000000090600019906004016151a5565b602060405180830381600087803b15801561472357600080fd5b505af1158015614737573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061475b9190614fd5565b505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326d6c97b8560038151811061479b57fe5b60200260200101516040518263ffffffff1660e01b81526004016147bf919061532b565b60806040518083038186803b1580156147d757600080fd5b505afa1580156147eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061480f9190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906148639030907f000000000000000000000000000000000000000000000000000000000000000090600401615170565b60206040518083038186803b15801561487b57600080fd5b505afa15801561488f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148b39190614ff1565b6125325760405163095ea7b360e01b81526001600160a01b0382169063095ea7b390614907907f000000000000000000000000000000000000000000000000000000000000000090600019906004016151a5565b602060405180830381600087803b15801561492157600080fd5b505af1158015614935573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149599190614fd5565b50505050505050565b60606149b7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614ca69092919063ffffffff16565b805190915015613bf057808060200190518101906149d59190614fd5565b613bf05760405162461bcd60e51b81526004016107cb90615895565b6040516370a0823160e01b81526000908190859082906001600160a01b038316906370a0823190614a2690309060040161515c565b60206040518083038186803b158015614a3e57600080fd5b505afa158015614a52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a769190614ff1565b1115614ba35783614b28576040516301bc8ef560e61b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636f23bd4090614ad0908a906000906004016159e7565b602060405180830381600087803b158015614aea57600080fd5b505af1158015614afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b229190614ff1565b50600193505b806001600160a01b0316639975038c6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614b6357600080fd5b505af1158015614b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b9b9190614ff1565b506001850194505b5092959194509092505050565b614bb982614cb5565b8190614bd85760405162461bcd60e51b81526004016107cb9190615503565b506000836001600160a01b031683604051614bf290610b23565b60006040518083038185875af1925050503d8060008114614c2f576040519150601f19603f3d011682016040523d82523d6000602084013e614c34565b606091505b5050905080614c555760405162461bcd60e51b81526004016107cb90615745565b836001600160a01b0316306001600160a01b03167fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c85604051614c98919061532b565b60405180910390a350505050565b6060613dea8484600085614cbc565b3031101590565b6060614cc785614d80565b614ce35760405162461bcd60e51b81526004016107cb90615839565b60006060866001600160a01b03168587604051614d009190615140565b60006040518083038185875af1925050503d8060008114614d3d576040519150601f19603f3d011682016040523d82523d6000602084013e614d42565b606091505b50915091508115614d56579150613dea9050565b805115614d665780518082602001fd5b8360405162461bcd60e51b81526004016107cb9190615503565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590613dea575050151592915050565b60405180604001604052806002906020820280368337509192915050565b604080516060810182526000808252602082018190529181019190915290565b600060208284031215614e08578081fd5b8135610c1181615afb565b60008060408385031215614e25578081fd5b8235614e3081615afb565b91506020830135614e4081615afb565b809150509250929050565b600080600060608486031215614e5f578081fd5b8335614e6a81615afb565b92506020840135614e7a81615afb565b929592945050506040919091013590565b60008060408385031215614e9d578182fd5b8235614ea881615afb565b91506020830135614e4081615b13565b60008060408385031215614eca578182fd5b8235614ed581615afb565b946020939093013593505050565b60008060008060808587031215614ef8578081fd5b8451614f0381615afb565b602086015160408701519195509350614f1b81615b21565b6060959095015193969295505050565b60008060408385031215614f3d578182fd5b82516001600160401b0380821115614f53578384fd5b818501915085601f830112614f66578384fd5b815181811115614f74578485fd5b60209150818102614f86838201615aa9565b8281528381019085850183870186018b1015614fa0578889fd5b8896505b84871015614fc2578051835260019690960195918501918501614fa4565b5097909301519698969750505050505050565b600060208284031215614fe6578081fd5b8151610c1181615b13565b600060208284031215615002578081fd5b5051919050565b60006020828403121561501a578081fd5b81518060010b8114610c11578182fd5b60006020828403121561503b578081fd5b81356001600160801b0381168114610c11578182fd5b600060208284031215615062578081fd5b5035919050565b6000806040838503121561507b578182fd5b50508035926020909101359150565b60008060006080848603121561509e578081fd5b83519250602080850151925085605f8601126150b8578182fd5b6150c26040615aa9565b8060408701886080890111156150d6578485fd5b845b60028110156150f5578151845292840192908401906001016150d8565b50508093505050509250925092565b600060208284031215615115578081fd5b8135610c1181615b21565b15159052565b6001600160801b03169052565b6001600160401b03169052565b60008251615152818460208701615acf565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b038c811682528b811660208301528a811660408301528981166060830152888116608083015287811660a083015286811660c0830152851660e08201528315156101008201526001600160401b038316610120820152610160810161522e610140830184615126565b9c9b505050505050505050505050565b6001600160a01b039384168152919092166020820152901515604082015260600190565b602080825282518282018190526000919060409081850190868401855b828110156152b157815180516001600160401b039081168652908701511686850152928401929085019060010161527f565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156152f6578351835292840192918401916001016152da565b50909695505050505050565b901515815260200190565b921515835263ffffffff918216602084015216604082015260600190565b90815260200190565b9384526001600160a01b0392831660208501529116604083015260010b606082015260800190565b9485526001600160a01b0393841660208601529183166040850152909116606083015260010b608082015260a00190565b600060e0820160018060a01b03808b1684526020818b168186015289604086015288606086015260e060808601528291508754808452610100860192508885528185209350845b818110156153f0578454845260019485019493830193016153d4565b505050809250505061540560a0830185615133565b61541260c0830184615120565b98975050505050505050565b6001600160a01b0395909516855260208501939093526001600160401b039182166040850152166060830152608082015260a00190565b6001600160a01b039390931683526001600160401b03918216602084015216604082015260600190565b602081016005831061548d57fe5b91905290565b60019190910b815260200190565b60019690960b86526001600160801b0394851660208701529290931660408501526001600160a01b0390811660608501529091166080830152151560a082015260c00190565b60019290920b82526001600160401b0316602082015260400190565b6000602082528251806020840152615522816040850160208701615acf565b601f01601f19169190910160400192915050565b6020808252600f908201526e139bdd08195e1c1a5c9959081e595d608a1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b602080825260099082015268436f6f6c2054696d6560b81b604082015260600190565b60208082526027908201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316040820152663238206269747360c81b606082015260800190565b6020808252600a90820152694e6f742061637469766560b01b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526026908201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660408201526534206269747360d01b606082015260800190565b6020808252600d908201526c27b7363c90383937bb34b232b960991b604082015260600190565b602080825260099082015268139bc814995dd85c9960ba1b604082015260600190565b6020808252600d908201526c556e7361666520737570706c7960981b604082015260600190565b6020808252600f908201526e496e76616c6964206665656261736560881b604082015260600190565b60208082526019908201527f7472616e7366657272696e67204574686572206661696c656400000000000000604082015260600190565b6020808252600790820152665265766572736560c81b604082015260600190565b6020808252600c908201526b4f7574206f662072616e676560a01b604082015260600190565b60208082526026908201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360408201526532206269747360d01b606082015260800190565b60208082526016908201527513585d1d5c9a5d1e481cda1bdd591b1908195e1a5cdd60521b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a4e6f742072756e6e696e6760a81b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600b908201526a139bdd0813585d1d5c995960aa1b604082015260600190565b602080825260079082015266115e1c1a5c995960ca1b604082015260600190565b6001600160801b0391909116815260200190565b6001600160801b0392831681529116602082015260400190565b6001600160801b03948516815292841660208401529083166040830152909116606082015260800190565b6001600160801b039390931683526001600160401b03918216602084015216604082015260600190565b95865260019490940b602086015263ffffffff9290921660408501526001600160401b039081166060850152166080830152151560a082015260c00190565b918252602082015260400190565b9283526001600160401b039190911660208301521515604082015260600190565b9283526001600160401b0391909116602083015260ff16604082015260600190565b63ffffffff91909116815260200190565b6001600160401b0391909116815260200190565b6001600160401b0392831681529116602082015260400190565b6001600160401b039384168152919092166020820152604081019190915260600190565b60ff91909116815260200190565b6040518181016001600160401b0381118282101715615ac757600080fd5b604052919050565b60005b83811015615aea578181015183820152602001615ad2565b83811115613b945750506000910152565b6001600160a01b0381168114615b1057600080fd5b50565b8015158114615b1057600080fd5b6001600160401b0381168114615b1057600080fdfe5472616e736665724554483a207472616e7366657220616d6f756e7420657863656564732062616c616e6365a264697066735822122002e2720145b831229dc25d43b34aff7140055dd20fc8f575bd19116ae9ed92a464736f6c63430007010033608060405234801561001057600080fd5b50600080546001600160a01b03191633179055610361806100326000396000f3fe6080604052600436106100225760003560e01c8063ed3de4871461006a57610065565b3661006557604051309033907fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9061005b9034906102f6565b60405180910390a3005b600080fd5b34801561007657600080fd5b5061008a6100853660046101e8565b61008c565b005b6000546001600160a01b031633146100bf5760405162461bcd60e51b81526004016100b6906102ab565b60405180910390fd5b6100c982826100cd565b5050565b6100c982826040518060600160405280602c8152602001610300602c91396100f4826101e1565b81906101135760405162461bcd60e51b81526004016100b69190610221565b506000836001600160a01b03168360405161012d9061021e565b60006040518083038185875af1925050503d806000811461016a576040519150601f19603f3d011682016040523d82523d6000602084013e61016f565b606091505b50509050806101905760405162461bcd60e51b81526004016100b690610274565b836001600160a01b0316306001600160a01b03167fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c856040516101d391906102f6565b60405180910390a350505050565b3031101590565b600080604083850312156101fa578182fd5b82356001600160a01b0381168114610210578283fd5b946020939093013593505050565b90565b6000602080835283518082850152825b8181101561024d57858101830151858201604001528201610231565b8181111561025e5783604083870101525b50601f01601f1916929092016040019392505050565b60208082526019908201527f7472616e7366657272696e67204574686572206661696c656400000000000000604082015260600190565b6020808252602b908201527f4572726f723a204f6e6c79206f776e65722063616e206578656375746520746860408201526a34b990333ab731ba34b7b760a91b606082015260800190565b9081526020019056fe5472616e736665724554483a207472616e7366657220616d6f756e7420657863656564732062616c616e6365a26469706673582212204f0a0f8dfa8207815122cdcd7e302a058c41e7aa8d8ee8daf858e9b12287afea64736f6c634300070100330000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d00000000000000000000000095a08a245f5dc3eb0ac2b5b6592cdb9810bd09610000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b81700000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd7000000000000000000000000c8bbb8d57cebf834dc429ec4d65dd23ed0d65a87000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000174876e800
Deployed Bytecode
0x60806040526004361061024a5760003560e01c806392da91ad11610139578063b88a802f116100b6578063dd62ed3e1161007a578063dd62ed3e146106f4578063e0e54dec14610714578063e627f2db14610734578063e8078d9414610756578063ef4498ff1461075e578063fde6fad91461077e5761028d565b8063b88a802f14610673578063c82e377814610688578063cc4df8ae146106aa578063d28f3330146106bf578063d3339533146106d45761028d565b80639a8fac74116100fd5780639a8fac74146105e0578063a3a40ea5146105f5578063a3dd261914610617578063a9059cbb1461063e578063ae1162561461065e5761028d565b806392da91ad1461055257806395d89b41146105725780639649a73714610587578063979c6fe61461059c5780639960d742146105cb5761028d565b80633beeae20116101c75780635a9b0b891161018b5780635a9b0b89146104855780636c13ba78146104b157806370a08231146104e15780638417cb13146105015780638c5301c0146105235761028d565b80633beeae20146103d257806344a040f5146103e75780634759898f146104145780634fac075b14610436578063506718ef146104655761028d565b806318160ddd1161020e57806318160ddd1461035157806323b872dd146103665780632e20da2714610386578063313ce5671461039b578063315deeaa146103bd5761028d565b806302ecdef21461029257806306fdde03146102a9578063095ea7b3146102d45780630dad4e4b1461030157806315e524871461032e5761028d565b3661028d57604051309033907fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9061028390349061532b565b60405180910390a3005b600080fd5b34801561029e57600080fd5b506102a76107ac565b005b3480156102b557600080fd5b506102be610914565b6040516102cb9190615503565b60405180910390f35b3480156102e057600080fd5b506102f46102ef366004614eb8565b610945565b6040516102cb9190615302565b34801561030d57600080fd5b5061032161031c366004614e8b565b6109e9565b6040516102cb919061532b565b34801561033a57600080fd5b50610343610abe565b6040516102cb9291906159e7565b34801561035d57600080fd5b50610321610aed565b34801561037257600080fd5b506102f4610381366004614e4b565b610b26565b34801561039257600080fd5b506102a7610c18565b3480156103a757600080fd5b506103b0611199565b6040516102cb9190615a9b565b3480156103c957600080fd5b5061032161119e565b3480156103de57600080fd5b506102a76111c5565b3480156103f357600080fd5b50610407610402366004614df7565b611447565b6040516102cb9190615a49565b34801561042057600080fd5b506104296114b3565b6040516102cb9190615493565b34801561044257600080fd5b50610456610451366004615051565b6114b8565b6040516102cb9392919061530d565b34801561047157600080fd5b50610321610480366004615051565b6114f7565b34801561049157600080fd5b5061049a611519565b6040516102cb9b9a999897969594939291906151be565b3480156104bd57600080fd5b506104d16104cc366004614df7565b61167e565b6040516102cb9493929190615953565b3480156104ed57600080fd5b506103216104fc366004614df7565b6116c5565b34801561050d57600080fd5b506105166116e9565b6040516102cb919061515c565b34801561052f57600080fd5b5061054361053e366004614df7565b6116ee565b6040516102cb9392919061597e565b34801561055e57600080fd5b506102f461056d36600461502a565b61172e565b34801561057e57600080fd5b506102be611848565b34801561059357600080fd5b50610321611868565b3480156105a857600080fd5b506105bc6105b7366004615051565b611948565b6040516102cb93929190615a77565b3480156105d757600080fd5b50610516611988565b3480156105ec57600080fd5b506102f46119ac565b34801561060157600080fd5b5061060a6119bd565b6040516102cb919061547f565b34801561062357600080fd5b5061062c611a77565b6040516102cb969594939291906159a8565b34801561064a57600080fd5b506102f4610659366004614eb8565b611abd565b34801561066a57600080fd5b506102a7611acd565b34801561067f57600080fd5b506102a7611ed9565b34801561069457600080fd5b5061069d61202b565b6040516102cb91906152be565b3480156106b657600080fd5b5061034361208e565b3480156106cb57600080fd5b506102a76120b4565b3480156106e057600080fd5b506103216106ef366004615069565b61253a565b34801561070057600080fd5b5061032161070f366004614e13565b612557565b34801561072057600080fd5b5061032161072f366004615069565b61258b565b34801561074057600080fd5b50610749612665565b6040516102cb9190615262565b6102f46126db565b34801561076a57600080fd5b506102a7610779366004615104565b612711565b34801561078a57600080fd5b5061079e610799366004615051565b612842565b6040516102cb929190615939565b6007546107d45760405162461bcd60e51b81526004016107cb90615870565b60405180910390fd5b60085460075460001901600090815260016020526040902054600160801b90910463ffffffff16906001600160401b0316806108225760405162461bcd60e51b81526004016107cb90615809565b6040516301e5ddfb60e71b81526000906001600160a01b037f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0169063f2eefd8090610871908690600401615a38565b60006040518083038186803b15801561088957600080fd5b505afa15801561089d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108c59190810190614f2b565b915050816001600160401b031681106109035750506008805463ffffffff909216600160801b0263ffffffff60801b19909216919091179055610912565b60018301925050610822565b50505b565b604051806040016040528060158152602001744c49454e5f41474752454741544f525f534841524560581b81525081565b600060001982141561095c576001600160801b0391505b61096582612879565b336000818152600c602090815260408083206001600160a01b03891680855292529182902080546001600160801b0319166001600160801b039590951694909417909355517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906109d790869061532b565b60405180910390a35060015b92915050565b6001600160a01b0382166000908152600b60209081526040808320546009909252909120546001600160801b0391821691600160801b90910416156109e35733600090815260096020526040902054600754600193506001600160801b0390911610156109e357336000818152600960208181526040808420546001600160801b0380821660010181168652600684529185205495909452919052610ab792610ab092600160801b91829004831692610aaa92909104166305f5e1006128a2565b906128dc565b600161291e565b0192915050565b6007546000908152600d6020908152604080832054600e909252909120546001600160801b0391821691169091565b6007546000908152600e60209081526040808320546006909252822054610b20916001600160801b039182169116612942565b90505b90565b6001600160a01b0383166000908152600c602090815260408083203384529091528120546001600160801b031682811015610b65576000915050610c11565b6001600160801b0381811614610bf7576001600160a01b0385166000908152600c60209081526040808320338452909152902054610bb590610bb0906001600160801b031685612942565b612879565b6001600160a01b0386166000908152600c60209081526040808320338452909152902080546001600160801b0319166001600160801b03929092169190911790555b610c0a8585610c0586612879565b612984565b5060019150505b9392505050565b60405163300da2f160e11b81526000906001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169063601b45e290610cab907f000000000000000000000000a961684a3a654fb2cca8f8991226c0cefc514d80907f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d90869060040161523e565b60206040518083038186803b158015610cc357600080fd5b505afa158015610cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfb9190615009565b90506103e88160010b13158015610d16575060058160010b12155b610d325760405162461bcd60e51b81526004016107cb9061571c565b6040516311ed607760e01b81526000906001600160a01b037f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd716906311ed607790610d8490309060019060040161518a565b60206040518083038186803b158015610d9c57600080fd5b505afa158015610db0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd49190614ff1565b905060007f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd76001600160a01b03166311ed60773060006040518363ffffffff1660e01b8152600401610e2792919061518a565b60206040518083038186803b158015610e3f57600080fd5b505afa158015610e53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e779190614ff1565b905060007f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd76001600160a01b031663488abbfc307f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06040518363ffffffff1660e01b8152600401610ee9929190615170565b60206040518083038186803b158015610f0157600080fd5b505afa158015610f15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f399190614ff1565b604051631711ddb160e21b81529091506001600160a01b037f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd71690635c4776c490610fce9086907f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d907f00000000000000000000000095a08a245f5dc3eb0ac2b5b6592cdb9810bd0961908a90600401615334565b600060405180830381600087803b158015610fe857600080fd5b505af1158015610ffc573d6000803e3d6000fd5b5050604051631711ddb160e21b81526001600160a01b037f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd7169250635c4776c491506110929085907f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d907f00000000000000000000000095a08a245f5dc3eb0ac2b5b6592cdb9810bd0961908a90600401615334565b600060405180830381600087803b1580156110ac57600080fd5b505af11580156110c0573d6000803e3d6000fd5b5050600054604051630ccb63b760e41b81526001600160a01b037f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd78116945063ccb63b70935061113d9286929116907f00000000000000000000000095a08a245f5dc3eb0ac2b5b6592cdb9810bd09619081908b9060040161535c565b600060405180830381600087803b15801561115757600080fd5b505af115801561116b573d6000803e3d6000fd5b50506008805460019790970b61ffff16600160a01b0261ffff60a01b19909716969096179095555050505050565b600881565b6007546000908152600d6020526040812054610b20903031906001600160801b0316612942565b6007546000818152600e602090815260408083205460059092528220549192839290916001600160801b031690600160401b900460ff1680611205575081155b6112215760405162461bcd60e51b81526004016107cb90615536565b6000828152600660205260409020546001600160801b031680156112a657600061124961119e565b9050611260610ab083610aaa846305f5e1006128a2565b6000858152600d602052604090205490955061129e90869061128f906001600160801b03166305f5e1006128a2565b8161129657fe5b04600161291e565b9550506112f0565b6000838152600d60205260409020546001600160801b0316156112f0576000838152600d60205260409020546112e6906001600160801b0316600161291e565b94506305f5e10093505b8085016112fc85612879565b60018501600090815260066020526040902080546001600160801b03928316600160801b029216919091179055611340610bb08461133a858a612a40565b90612942565b60018501600090815260066020526040902080546001600160801b0319166001600160801b0392831617908190556c2af31dc4611873bf3f70834acd91161115611398576008805460ff60b01b1916600160b01b1790555b83156113a6576113a6612a65565b6000811180156113b65750600083115b156113c4576113c485612b95565b6113cc612bfb565b6113d7600754613151565b6008546007546000908152600160208190526040918290205491516001600160401b03948516947fb6468ad5c9ad279cc97382791cf54035b2adbdc6126bee312967c4fdbb9a56da9461143794600160a01b90910490930b9216906154e7565b60405180910390a2505050505050565b6001600160a01b0381166000908152600b60209081526040808320815160608101835290546001600160801b03811682526001600160401b03600160801b8204811694830194909452600160c01b9004909216908201526007546114ab9190613176565b90505b919050565b601290565b60008080836114c75760075493505b50505060009081526005602052604090205460ff600160401b8204169163ffffffff600160201b83048116921690565b600090815260066020526040902054600160801b90046001600160801b031690565b7f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0907f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd7907f00000000000000000000000095a08a245f5dc3eb0ac2b5b6592cdb9810bd0961907f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d907f000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e907f000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b817907f000000000000000000000000a961684a3a654fb2cca8f8991226c0cefc514d80907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000003b9aca00906c2af31dc4611873bf3f70834acd90565b6001600160a01b0316600090815260096020908152604080832054600a909252909120546001600160801b0380831693600160801b93849004821693828416930490911690565b6001600160a01b03166000908152600b60205260409020546001600160801b031690565b600090565b6001600160a01b03166000908152600b60205260409020546001600160801b038116916001600160401b03600160c01b8304811692600160801b90041690565b600080600061173b613309565b600754336000908152600a60205260409020549295509093509150600160801b90046001600160801b031661179357336000908152600a6020526040902080546001600160801b0319166001600160801b0383161790555b336000818152600a6020908152604080832080546001600160801b03600160801b80830482168d0182160291811691909117909155858452600e9092529091208054808316890183166001600160801b0319919091161790556117fb919085908816856134c1565b80336001600160a01b03167f3518f79326efc4570db0ebb1195252c857df4c2beb5932ab886faa94251a50e0876040516118359190615925565b60405180910390a3506001949350505050565b6040518060400160405280600481526020016309882a6960e31b81525081565b6007546000908152600160205260408120546001600160401b03164211156118a25760405162461bcd60e51b81526004016107cb90615600565b60007f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d6001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156118ff57600080fd5b505af1158015611913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119379190614ff1565b905061194281613646565b91505090565b60008080836119575760075493505b505050600090815260016020819052604090912080549101546001600160401b0380831693600160401b9093041691565b7f000000000000000000000000da605c4cab9dcdc51c4fe74d86f76ed80829b05790565b600854600160b01b900460ff161590565b6000600754600014156119d257506000610b23565b6007546000908152600160205260409020546001600160401b03164211611a22576008546001600160401b03600160401b909104166203f480014211611a1a57506002610b23565b506001610b23565b6007546000908152600160205260409020546001600160401b031642118015611a645750600754600090815260056020526040902054600160401b900460ff16155b15611a7157506003610b23565b50600490565b6007546008549091600160a01b820460010b91600160801b810463ffffffff16916001600160401b0380831692600160401b810490911691600160b01b90910460ff1690565b6000610c113384610c0585612879565b6007546000908152600160205260409020546001600160401b0316421115611b075760405162461bcd60e51b81526004016107cb90615600565b6008546001600160401b03600160401b909104166203f480014211611b3e5760405162461bcd60e51b81526004016107cb90615596565b60007f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d6001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611b9b57600080fd5b505af1158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd39190614ff1565b90506000611be08261393b565b905080611bf357611bf082613646565b90505b600080611bfe614db9565b6007546000908152600260205260409081902060085491516329069bdd60e01b81526001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd416926329069bdd92611cb1927f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef09230928b928d926001600160401b0316907f00000000000000000000000000000000000000000000000000000000000000009060040161538d565b60806040518083038186803b158015611cc957600080fd5b505afa158015611cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d01919061508a565b919450925090508115611d83577f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd76001600160a01b031663439370b1836040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d6957600080fd5b505af1158015611d7d573d6000803e3d6000fd5b50505050505b8215611d9357611d938484613ad4565b602081015115611e5c578051602082015160405163b9601d7760e01b81527f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03169263b9601d7792611dee926004016159e7565b602060405180830381600087803b158015611e0857600080fd5b505af1158015611e1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e409190614fd5565b611e5c5760405162461bcd60e51b81526004016107cb9061577c565b611e6542613151565b6008805467ffffffffffffffff60401b1916600160401b6001600160401b039384160217905581516020830151604051918316928716917f2eaafc32eed9e5ff41c1b57ddd1ef894ec4eb7499efb581d50edffa27f6af23291611eca91889190615a5d565b60405180910390a35050505050565b611ee1614dd7565b50336000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b900490911691810191909152600754611f42908290613176565b6001600160401b03908116602083018190526007549091166040830152611f7b5760405162461bcd60e51b81526004016107cb906156d2565b60208181018051600080835233808252600b909452604090819020855181549451928701516001600160801b03199095166001600160801b039091161767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b9483169490940293909317909255169061090f906001600160a01b037f000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e169083613b9a565b60075460009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561208457602002820191906000526020600020905b815481526020019060010190808311612070575b5050505050905090565b600080600061209b613309565b919450925090506120af33836000846134c1565b509091565b6007546000908152600160205260409020546001600160401b031642116120ed5760405162461bcd60e51b81526004016107cb906158df565b600754600081815260056020526040902054600160401b900460ff16156121265760405162461bcd60e51b81526004016107cb90615904565b60008181526005602052604090205463ffffffff166121ff576121d87f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b031663ac3fd8866040518163ffffffff1660e01b815260040160206040518083038186803b15801561219b57600080fd5b505afa1580156121af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d39190614ff1565b613bf5565b6000828152600560205260409020805463ffffffff191663ffffffff929092169190911790555b6000818152600160205260408082205460001984018352818320549151631c1b06f760e11b8152839283926001600160401b039081169291169083906001600160a01b037f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd716906338360dee9061227a90309060040161515c565b60206040518083038186803b15801561229257600080fd5b505afa1580156122a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ca9190614ff1565b90508015612346577f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd76001600160a01b031663a0ef91df6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561232d57600080fd5b505af1158015612341573d6000803e3d6000fd5b505050505b50600086815260056020526040902054600160201b900463ffffffff1661237e57600854600160801b900463ffffffff16935061239d565b600086815260056020526040902054600160201b900463ffffffff1693505b600086815260056020526040902054603263ffffffff91821686900390911611156123ff576000868152600560205260409020805463ffffffff60328701908116600160201b0267ffffffff0000000019909216919091179091559450612417565b60008681526005602052604090205463ffffffff1694505b63ffffffff84165b8563ffffffff168110156124c25761243981858585613c1a565b935060098463ffffffff1611156124ba576001860363ffffffff1681141561247f576000878152600560205260409020805460ff60401b1916600160401b1790556124ae565b6000878152600560205260409020805467ffffffff000000001916600160201b6001840163ffffffff16021790555b50505050505050610912565b60010161241f565b5060008681526005602052604090205463ffffffff86811691161415612506576000868152600560205260409020805460ff60401b1916600160401b179055612532565b6000868152600560205260409020805467ffffffff000000001916600160201b63ffffffff8816021790555b505050505050565b600091825260036020908152604080842092845291905290205490565b6001600160a01b039182166000908152600c602090815260408083209390941682529190915220546001600160801b031690565b6008546040516351d19dc760e11b81526000916001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169163a3a33b8e916125ea9186916001600160401b031690600190600401615a16565b60206040518083038186803b15801561260257600080fd5b505afa158015612616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263a9190614ff1565b9150826126475760075492505b50600091825260036020908152604080842092845291905290205490565b60606004805480602002602001604051908101604052809291908181526020016000905b828210156126d257600084815260209081902060408051808201909152908401546001600160401b038082168352600160401b9091041681830152825260019092019101612689565b50505050905090565b600854600090600160b01b900460ff16156127085760405162461bcd60e51b81526004016107cb906156f5565b610b2034613df2565b336001600160a01b037f000000000000000000000000a961684a3a654fb2cca8f8991226c0cefc514d8016146127595760405162461bcd60e51b81526004016107cb906156ab565b6007546127785760405162461bcd60e51b81526004016107cb90615870565b6305f5e1006001600160401b038216108015906127a45750655af3107a40006001600160401b03821611155b6127c05760405162461bcd60e51b81526004016107cb9061579d565b600460405180604001604052806127d8600754613151565b60019081016001600160401b03908116835294851660209283015283549081018455600093845292819020825193018054929091015167ffffffffffffffff199092169284169290921767ffffffffffffffff60401b1916600160401b9190931602919091179055565b600080826128505760075492505b50506000908152600660205260409020546001600160801b0380821692600160801b9092041690565b6000600160801b821061289e5760405162461bcd60e51b81526004016107cb906155b9565b5090565b6000826128b1575060006109e3565b828202828482816128be57fe5b0414610c115760405162461bcd60e51b81526004016107cb90615624565b6000610c1183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613f0c565b6000811561293457506402540be40082046109e3565b506402540be40082026109e3565b6000610c1183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613f43565b6001600160a01b0383166000908152600b60205260408120546001600160801b03808416911610156129b857506000610c11565b6129cf84836001600160801b031660001902613f6f565b6129e283836001600160801b0316613f6f565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846001600160801b0316604051612a2e919061532b565b60405180910390a35060019392505050565b600082820183811015610c115760405162461bcd60e51b81526004016107cb9061555f565b6008546007546000818152600660205260408082205460019384018352918190205490516379b347db60e01b81526001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd416946379b347db94612b5b94600160a01b909204900b926001600160801b03600160801b928390048116939290910416907f000000000000000000000000a961684a3a654fb2cca8f8991226c0cefc514d80907f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d907f0000000000000000000000000000000000000000000000000000000000000000906004016154a1565b600060405180830381600087803b158015612b7557600080fd5b505af1158015612b89573d6000803e3d6000fd5b50505050610912610c18565b6007546000908152600e6020526040812054612bcf90612bc8906305f5e10090610aaa906001600160801b0316866128a2565b600061291e565b905061090f7f000000000000000000000000da605c4cab9dcdc51c4fe74d86f76ed80829b057826140d8565b60007f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd46001600160a01b031663ca579d0a6040518163ffffffff1660e01b815260040160206040518083038186803b158015612c5657600080fd5b505afa158015612c6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c8e9190614ff1565b905060007f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d6001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612ced57600080fd5b505af1158015612d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d259190614ff1565b600854604051637298096d60e11b81529192506000916001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169163e53012da91612da89186916001600160401b03909116907f0000000000000000000000000000000000000000000000000000000000000000906004016159f5565b60206040518083038186803b158015612dc057600080fd5b505afa158015612dd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612df89190614ff1565b9050612e03826140fb565b60007f000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b8176001600160a01b031663a38593887f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0612e5e85613151565b612e6788613151565b6040518463ffffffff1660e01b8152600401612e8593929190615455565b602060405180830381600087803b158015612e9f57600080fd5b505af1158015612eb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed79190614ff1565b905060007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03166326d6c97b836040518263ffffffff1660e01b8152600401612f27919061532b565b60806040518083038186803b158015612f3f57600080fd5b505afa158015612f53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f779190614ee3565b505060405163095ea7b360e01b8152919250506001600160a01b0382169063095ea7b390612fcd907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600019906004016151a5565b602060405180830381600087803b158015612fe757600080fd5b505af1158015612ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061301f9190614fd5565b50600780546001019055613031614dd7565b604051806060016040528061304588613151565b6001600160401b0316815260200161305c86613151565b6001600160401b039081168252602091820186905260075460009081526001808452604091829020855181549587015167ffffffffffffffff199096169085161767ffffffffffffffff60401b1916600160401b959094169490940292909217835583810151929091019190915551631d3b07f760e21b81529091507f00000000000000000000000095a08a245f5dc3eb0ac2b5b6592cdb9810bd09616001600160a01b0316906374ec1fdc9061311790899060040161532b565b600060405180830381600087803b15801561313157600080fd5b505af1158015613145573d6000803e3d6000fd5b50505050505050505050565b6000600160401b821061289e5760405162461bcd60e51b81526004016107cb90615665565b602082015182516001600160801b0316158015906131a057508183604001516001600160401b0316105b156109e357600480546000198101916000916001600160401b0384169081106131c557fe5b6000918252602082200154600480546001600160401b039283169450909185169081106131ee57fe5b600091825260209091200154600160401b90046001600160401b03169050845b86604001516001600160401b03168111156132ff57826001600160401b03168110156132a1576001840393506004846001600160401b03168154811061325057fe5b9060005260206000200160000160089054906101000a90046001600160401b031691506004846001600160401b03168154811061328957fe5b6000918252602090912001546001600160401b031692505b60008181526006602052604090205487516132f4916132ef916132df916001600160801b0390811691610aaa916001600160401b03891691166128a2565b6001600160401b03881690612a40565b613151565b94506000190161320e565b5050505092915050565b600754336000908152600a602090815260408083205460099092528220549192839283926001600160801b0380821692600160801b92839004821692818316929104168461336657600080600097509750975050505050506134bc565b6001600160801b038316158015906133865750836001600160801b031685115b156133ef576001600160801b036001850181166000908152600660205260409020546133cc91612bc8916305f5e10091610aaa9188821691600160801b909104166128a2565b975087156133de576133de33896141da565b336000908152600a60205260408120555b6001600160801b0381161580159061340f5750816001600160801b031685115b15613472576001600160801b0360018301811660009081526006602052604090205461345391610ab091600160801b9004811690610aaa9085166305f5e1006128a2565b3360009081526009602052604081205596506001600160801b03821695505b84336001600160a01b03167fb11715e80d7e8d99a84fdd2112e0c3b821523d7416cb2082ec62d76c76f6f0168a8a6040516134ae9291906159e7565b60405180910390a350505050505b909192565b6134c9614dd7565b506001600160a01b0384166000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b9004909116918101919091528315613571576135358183613176565b6001600160401b03908116602083015282166040820152805161356590610bb0906001600160801b031686612a40565b6001600160801b031681525b61357d81600754613176565b6001600160401b03908116602083015260075416604082015282156135c15780516135b590610bb0906001600160801b031685612942565b6001600160801b031681525b6001600160a01b03949094166000908152600b6020908152604091829020865181549288015193909701516001600160801b03199092166001600160801b039097169690961767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b929091169190910217909355505050565b60085460405163a072a3e560e01b815260009182916001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169163a072a3e5916136c89187916001600160401b03909116907f0000000000000000000000000000000000000000000000000000000000000000906004016159f5565b60206040518083038186803b1580156136e057600080fd5b505afa1580156136f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137189190614ff1565b600754909150613726614dd7565b50600081815260016020818152604092839020835160608101855281546001600160401b038082168352600160401b9091041692810183905292015492820192909252906137749084614256565b602082015182516040808501519051635b1caa5760e11b81529396506001600160a01b037f000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b817169363b63954ae936137f1937f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0938a9360040161541e565b602060405180830381600087803b15801561380b57600080fd5b505af115801561381f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138439190614ff1565b93507f0000000000000000000000000000000000000000000000000000000000000000156139295760085460405163a072a3e560e01b81526139249186916001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169163a072a3e5916138cf918b916001600160401b03909116906000906004016159f5565b60206040518083038186803b1580156138e757600080fd5b505afa1580156138fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061391f9190614ff1565b614280565b613933565b6139338484614280565b505050919050565b6008546040516351d19dc760e11b815260009182916001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169163a3a33b8e9161399e9187916001600160401b0390911690600190600401615a16565b60206040518083038186803b1580156139b657600080fd5b505afa1580156139ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139ee9190614ff1565b600754600090815260036020908152604080832084845291829052909120549192509015613a2a576000918252602052604090205490506114ae565b60015b60028111613933576008546001600160401b03168102830360009081526020839052604090205415613a80576008546001600160401b0316029091036000908152602091909152604090205490506114ae565b6008546001600160401b03168102830160009081526020839052604090205415613acc576008546001600160401b031602919091016000908152602091909152604090205490506114ae565b600101613a2d565b7f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b038116638376c24d613b256103e8610aaa6103ea613b1f886402540be4006128a2565b906128a2565b856040518363ffffffff1660e01b8152600401613b42919061532b565b6020604051808303818588803b158015613b5b57600080fd5b505af1158015613b6f573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613b949190614ff1565b50505050565b613bf08363a9059cbb60e01b8484604051602401613bb99291906151a5565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614962565b505050565b6000600160201b821061289e5760405162461bcd60e51b81526004016107cb906157c3565b6000606060007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b031663f2eefd80886040518263ffffffff1660e01b8152600401613c6c919061532b565b60006040518083038186803b158015613c8457600080fd5b505afa158015613c98573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613cc09190810190614f2b565b91509150846001600160401b0316811180613cf65750836001600160401b031681108015613cf657506001600160401b03841615155b15613d05578592505050613dea565b6000805b8351811015613de25760007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03166326d6c97b868481518110613d4f57fe5b60200260200101516040518263ffffffff1660e01b8152600401613d73919061532b565b60806040518083038186803b158015613d8b57600080fd5b505afa158015613d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613dc39190614ee3565b5050509050613dd48a828b866149f1565b909950925050600101613d09565b508693505050505b949350505050565b6000806000613dff613309565b9250925050613e1133836000846134c1565b60075433600090815260096020526040902054600160801b90046001600160801b0316613e615733600090815260096020526040902080546001600160801b0319166001600160801b0383161790555b613e6a85612879565b33600090815260096020526040902080546001600160801b03600160801b808304821690940181169093029216919091179055613ea685612879565b6000828152600d60205260409081902080546001600160801b031981166001600160801b0391821694909401169290921790915551819033907f4c86739b331ba35e12897451019b4a8cca47a228be900c18ab3a8ffa5dfe7e539061183590899061532b565b60008183613f2d5760405162461bcd60e51b81526004016107cb9190615503565b506000838581613f3957fe5b0495945050505050565b60008184841115613f675760405162461bcd60e51b81526004016107cb9190615503565b505050900390565b613f77614dd7565b506001600160a01b0382166000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b900490911691810191909152600754613fe1908290613176565b6001600160401b039081166020830152600754166040820152600082121561403057805161402090610bb0906001600160801b03166000859003612942565b6001600160801b03168152614055565b805161404990610bb0906001600160801b031684612a40565b6001600160801b031681525b6001600160a01b03929092166000908152600b6020908152604091829020845181549286015193909501516001600160801b03199092166001600160801b039095169490941767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b92909116919091021790915550565b61090f82826040518060600160405280602c8152602001615b37602c9139614bb0565b6000614133826001600160401b0360327f000000000000000000000000000000000000000000000000000000003b9aca0002166128dc565b90508061417b576008805467ffffffffffffffff19167f000000000000000000000000000000000000000000000000000000003b9aca006001600160401b031617905561090f565b6141b5600a6001600160401b037f000000000000000000000000000000000000000000000000000000003b9aca0016830260190204613151565b6008805467ffffffffffffffff19166001600160401b03929092169190911790555050565b60405163ed3de48760e01b81526001600160a01b037f000000000000000000000000da605c4cab9dcdc51c4fe74d86f76ed80829b057169063ed3de4879061422890859085906004016151a5565b600060405180830381600087803b15801561424257600080fd5b505af1158015612532573d6000803e3d6000fd5b6000610c116002614270846001600160401b038716612942565b8161427757fe5b84919006612942565b60078054600090815260026020908152604080832080546001810182559084528284200186905592548252600381528282208483529052819020839055516301e5ddfb60e71b81526060906001600160a01b037f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0169063f2eefd809061430a90869060040161532b565b60006040518083038186803b15801561432257600080fd5b505afa158015614336573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261435e9190810190614f2b565b50905060007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03166326d6c97b8360018151811061439f57fe5b60200260200101516040518263ffffffff1660e01b81526004016143c3919061532b565b60806040518083038186803b1580156143db57600080fd5b505afa1580156143ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144139190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906144679030907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600401615170565b60206040518083038186803b15801561447f57600080fd5b505afa158015614493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144b79190614ff1565b61455f5760405163095ea7b360e01b81526001600160a01b0382169063095ea7b39061450b907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600019906004016151a5565b602060405180830381600087803b15801561452557600080fd5b505af1158015614539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061455d9190614fd5565b505b60007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03166326d6c97b8460028151811061459d57fe5b60200260200101516040518263ffffffff1660e01b81526004016145c1919061532b565b60806040518083038186803b1580156145d957600080fd5b505afa1580156145ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146119190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906146659030907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600401615170565b60206040518083038186803b15801561467d57600080fd5b505afa158015614691573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146b59190614ff1565b61475d5760405163095ea7b360e01b81526001600160a01b0382169063095ea7b390614709907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600019906004016151a5565b602060405180830381600087803b15801561472357600080fd5b505af1158015614737573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061475b9190614fd5565b505b60007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03166326d6c97b8560038151811061479b57fe5b60200260200101516040518263ffffffff1660e01b81526004016147bf919061532b565b60806040518083038186803b1580156147d757600080fd5b505afa1580156147eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061480f9190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906148639030907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600401615170565b60206040518083038186803b15801561487b57600080fd5b505afa15801561488f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148b39190614ff1565b6125325760405163095ea7b360e01b81526001600160a01b0382169063095ea7b390614907907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600019906004016151a5565b602060405180830381600087803b15801561492157600080fd5b505af1158015614935573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149599190614fd5565b50505050505050565b60606149b7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614ca69092919063ffffffff16565b805190915015613bf057808060200190518101906149d59190614fd5565b613bf05760405162461bcd60e51b81526004016107cb90615895565b6040516370a0823160e01b81526000908190859082906001600160a01b038316906370a0823190614a2690309060040161515c565b60206040518083038186803b158015614a3e57600080fd5b505afa158015614a52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a769190614ff1565b1115614ba35783614b28576040516301bc8ef560e61b81526001600160a01b037f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef01690636f23bd4090614ad0908a906000906004016159e7565b602060405180830381600087803b158015614aea57600080fd5b505af1158015614afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b229190614ff1565b50600193505b806001600160a01b0316639975038c6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614b6357600080fd5b505af1158015614b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b9b9190614ff1565b506001850194505b5092959194509092505050565b614bb982614cb5565b8190614bd85760405162461bcd60e51b81526004016107cb9190615503565b506000836001600160a01b031683604051614bf290610b23565b60006040518083038185875af1925050503d8060008114614c2f576040519150601f19603f3d011682016040523d82523d6000602084013e614c34565b606091505b5050905080614c555760405162461bcd60e51b81526004016107cb90615745565b836001600160a01b0316306001600160a01b03167fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c85604051614c98919061532b565b60405180910390a350505050565b6060613dea8484600085614cbc565b3031101590565b6060614cc785614d80565b614ce35760405162461bcd60e51b81526004016107cb90615839565b60006060866001600160a01b03168587604051614d009190615140565b60006040518083038185875af1925050503d8060008114614d3d576040519150601f19603f3d011682016040523d82523d6000602084013e614d42565b606091505b50915091508115614d56579150613dea9050565b805115614d665780518082602001fd5b8360405162461bcd60e51b81526004016107cb9190615503565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590613dea575050151592915050565b60405180604001604052806002906020820280368337509192915050565b604080516060810182526000808252602082018190529181019190915290565b600060208284031215614e08578081fd5b8135610c1181615afb565b60008060408385031215614e25578081fd5b8235614e3081615afb565b91506020830135614e4081615afb565b809150509250929050565b600080600060608486031215614e5f578081fd5b8335614e6a81615afb565b92506020840135614e7a81615afb565b929592945050506040919091013590565b60008060408385031215614e9d578182fd5b8235614ea881615afb565b91506020830135614e4081615b13565b60008060408385031215614eca578182fd5b8235614ed581615afb565b946020939093013593505050565b60008060008060808587031215614ef8578081fd5b8451614f0381615afb565b602086015160408701519195509350614f1b81615b21565b6060959095015193969295505050565b60008060408385031215614f3d578182fd5b82516001600160401b0380821115614f53578384fd5b818501915085601f830112614f66578384fd5b815181811115614f74578485fd5b60209150818102614f86838201615aa9565b8281528381019085850183870186018b1015614fa0578889fd5b8896505b84871015614fc2578051835260019690960195918501918501614fa4565b5097909301519698969750505050505050565b600060208284031215614fe6578081fd5b8151610c1181615b13565b600060208284031215615002578081fd5b5051919050565b60006020828403121561501a578081fd5b81518060010b8114610c11578182fd5b60006020828403121561503b578081fd5b81356001600160801b0381168114610c11578182fd5b600060208284031215615062578081fd5b5035919050565b6000806040838503121561507b578182fd5b50508035926020909101359150565b60008060006080848603121561509e578081fd5b83519250602080850151925085605f8601126150b8578182fd5b6150c26040615aa9565b8060408701886080890111156150d6578485fd5b845b60028110156150f5578151845292840192908401906001016150d8565b50508093505050509250925092565b600060208284031215615115578081fd5b8135610c1181615b21565b15159052565b6001600160801b03169052565b6001600160401b03169052565b60008251615152818460208701615acf565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b038c811682528b811660208301528a811660408301528981166060830152888116608083015287811660a083015286811660c0830152851660e08201528315156101008201526001600160401b038316610120820152610160810161522e610140830184615126565b9c9b505050505050505050505050565b6001600160a01b039384168152919092166020820152901515604082015260600190565b602080825282518282018190526000919060409081850190868401855b828110156152b157815180516001600160401b039081168652908701511686850152928401929085019060010161527f565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156152f6578351835292840192918401916001016152da565b50909695505050505050565b901515815260200190565b921515835263ffffffff918216602084015216604082015260600190565b90815260200190565b9384526001600160a01b0392831660208501529116604083015260010b606082015260800190565b9485526001600160a01b0393841660208601529183166040850152909116606083015260010b608082015260a00190565b600060e0820160018060a01b03808b1684526020818b168186015289604086015288606086015260e060808601528291508754808452610100860192508885528185209350845b818110156153f0578454845260019485019493830193016153d4565b505050809250505061540560a0830185615133565b61541260c0830184615120565b98975050505050505050565b6001600160a01b0395909516855260208501939093526001600160401b039182166040850152166060830152608082015260a00190565b6001600160a01b039390931683526001600160401b03918216602084015216604082015260600190565b602081016005831061548d57fe5b91905290565b60019190910b815260200190565b60019690960b86526001600160801b0394851660208701529290931660408501526001600160a01b0390811660608501529091166080830152151560a082015260c00190565b60019290920b82526001600160401b0316602082015260400190565b6000602082528251806020840152615522816040850160208701615acf565b601f01601f19169190910160400192915050565b6020808252600f908201526e139bdd08195e1c1a5c9959081e595d608a1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b602080825260099082015268436f6f6c2054696d6560b81b604082015260600190565b60208082526027908201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316040820152663238206269747360c81b606082015260800190565b6020808252600a90820152694e6f742061637469766560b01b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526026908201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660408201526534206269747360d01b606082015260800190565b6020808252600d908201526c27b7363c90383937bb34b232b960991b604082015260600190565b602080825260099082015268139bc814995dd85c9960ba1b604082015260600190565b6020808252600d908201526c556e7361666520737570706c7960981b604082015260600190565b6020808252600f908201526e496e76616c6964206665656261736560881b604082015260600190565b60208082526019908201527f7472616e7366657272696e67204574686572206661696c656400000000000000604082015260600190565b6020808252600790820152665265766572736560c81b604082015260600190565b6020808252600c908201526b4f7574206f662072616e676560a01b604082015260600190565b60208082526026908201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360408201526532206269747360d01b606082015260800190565b60208082526016908201527513585d1d5c9a5d1e481cda1bdd591b1908195e1a5cdd60521b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a4e6f742072756e6e696e6760a81b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600b908201526a139bdd0813585d1d5c995960aa1b604082015260600190565b602080825260079082015266115e1c1a5c995960ca1b604082015260600190565b6001600160801b0391909116815260200190565b6001600160801b0392831681529116602082015260400190565b6001600160801b03948516815292841660208401529083166040830152909116606082015260800190565b6001600160801b039390931683526001600160401b03918216602084015216604082015260600190565b95865260019490940b602086015263ffffffff9290921660408501526001600160401b039081166060850152166080830152151560a082015260c00190565b918252602082015260400190565b9283526001600160401b039190911660208301521515604082015260600190565b9283526001600160401b0391909116602083015260ff16604082015260600190565b63ffffffff91909116815260200190565b6001600160401b0391909116815260200190565b6001600160401b0392831681529116602082015260400190565b6001600160401b039384168152919092166020820152604081019190915260600190565b60ff91909116815260200190565b6040518181016001600160401b0381118282101715615ac757600080fd5b604052919050565b60005b83811015615aea578181015183820152602001615ad2565b83811115613b945750506000910152565b6001600160a01b0381168114615b1057600080fd5b50565b8015158114615b1057600080fd5b6001600160401b0381168114615b1057600080fdfe5472616e736665724554483a207472616e7366657220616d6f756e7420657863656564732062616c616e6365a264697066735822122002e2720145b831229dc25d43b34aff7140055dd20fc8f575bd19116ae9ed92a464736f6c63430007010033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d00000000000000000000000095a08a245f5dc3eb0ac2b5b6592cdb9810bd09610000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b81700000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd7000000000000000000000000c8bbb8d57cebf834dc429ec4d65dd23ed0d65a87000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000174876e800
-----Decoded View---------------
Arg [0] : _ethOracle (address): 0x6e33f11625b2c8B7270cf8e0319b8B9fFB8F086D
Arg [1] : _pricer (address): 0x95a08a245f5dC3Eb0aC2B5b6592CDb9810bD0961
Arg [2] : strategy (address): 0x5EE7B5b9845Cae2a8fD2E02e0Bf6cE6F83EbcFd4
Arg [3] : _rewardToken (address): 0xaB37e1358b639Fd877f015027Bb62d3ddAa7557E
Arg [4] : _registrator (address): 0xAAd52946E078Cd22D79050146d81a295bbC2b817
Arg [5] : exchangeAddress (address): 0x23f8477C9F19389069535720e3bA66A2b95d5DD7
Arg [6] : _volOracle (address): 0xc8BBb8d57CEbF834DC429ec4D65DD23eD0d65a87
Arg [7] : _priceUnit (uint64): 1000000000
Arg [8] : _firstRewardRate (uint64): 100000000000
-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d
Arg [1] : 00000000000000000000000095a08a245f5dc3eb0ac2b5b6592cdb9810bd0961
Arg [2] : 0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4
Arg [3] : 000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e
Arg [4] : 000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b817
Arg [5] : 00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd7
Arg [6] : 000000000000000000000000c8bbb8d57cebf834dc429ec4d65dd23ed0d65a87
Arg [7] : 000000000000000000000000000000000000000000000000000000003b9aca00
Arg [8] : 000000000000000000000000000000000000000000000000000000174876e800
Deployed Bytecode Sourcemap
121417:4128:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;119780:52;;119815:4;;119795:10;;119780:52;;;;119822:9;;119780:52;:::i;:::-;;;;;;;;121417:4128;;;;;95353:557;;;;;;;;;;;;;:::i;:::-;;84718:62;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110332:313;;;;;;;;;;-1:-1:-1;110332:313:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;116007:820::-;;;;;;;;;;-1:-1:-1;116007:820:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;118064:180::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;112202:169::-;;;;;;;;;;;;;:::i;110932:625::-;;;;;;;;;;-1:-1:-1;110932:625:0;;;;;:::i;:::-;;:::i;122841:795::-;;;;;;;;;;;;;:::i;84614:43::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;125153:159::-;;;;;;;;;;;;;:::i;87936:1968::-;;;;;;;;;;;;;:::i;117666:146::-;;;;;;;;;;-1:-1:-1;117666:146:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;125320:99::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;113394:515::-;;;;;;;;;;-1:-1:-1;113394:515:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;118402:149::-;;;;;;;;;;-1:-1:-1;118402:149:0;;;;;:::i;:::-;;:::i;114617:902::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;112379:496::-;;;;;;;;;;-1:-1:-1;112379:496:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;112075:119::-;;;;;;;;;;-1:-1:-1;112075:119:0;;;;;:::i;:::-;;:::i;124626:109::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;118788:308::-;;;;;;;;;;-1:-1:-1;118788:308:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;92355:645::-;;;;;;;;;;-1:-1:-1;92355:645:0;;;;;:::i;:::-;;:::i;84664:47::-;;;;;;;;;;;;;:::i;98261:208::-;;;;;;;;;;;;;:::i;115527:384::-;;;;;;;;;;-1:-1:-1;115527:384:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;125427:115::-;;;;;;;;;;;;;:::i;117945:111::-;;;;;;;;;;;;;:::i;116904:673::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;112883:503::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;110653:169::-;;;;;;;;;;-1:-1:-1;110653:169:0;;;;;:::i;:::-;;:::i;98581:1315::-;;;;;;;;;;;;;:::i;109734:478::-;;;;;;;;;;;;;:::i;119181:140::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;94851:296::-;;;;;;;;;;;;;:::i;96074:2179::-;;;;;;;;;;;;;:::i;118559:221::-;;;;;;;;;;-1:-1:-1;118559:221:0;;;;;:::i;:::-;;:::i;118252:142::-;;;;;;;;;;-1:-1:-1;118252:142:0;;;;;:::i;:::-;;:::i;114252:357::-;;;;;;;;;;-1:-1:-1;114252:357:0;;;;;:::i;:::-;;:::i;117820:117::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;123715:130::-;;;:::i;90133:272::-;;;;;;;;;;-1:-1:-1;90133:272:0;;;;;:::i;:::-;;:::i;113917:327::-;;;;;;;;;;-1:-1:-1;113917:327:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;95353:557::-;86213:11;;86205:40;;;;-1:-1:-1;;;86205:40:0;;;;;;;:::i;:::-;;;;;;;;;95453:16:::1;::::0;95515:11:::1;::::0;-1:-1:-1;;95515:15:0;95426:24:::1;95506:25:::0;;;:8:::1;:25;::::0;;;;:34;-1:-1:-1;;;95453:16:0;;::::1;;;::::0;-1:-1:-1;;;;;95506:34:0::1;::::0;95551:56:::1;;;;-1:-1:-1::0;;;95551:56:0::1;;;;;;;:::i;:::-;95669:41;::::0;-1:-1:-1;;;95669:41:0;;95649:16:::1;::::0;-1:-1:-1;;;;;95669:9:0::1;:22;::::0;::::1;::::0;:41:::1;::::0;95692:17;;95669:41:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;::::0;;::::1;-1:-1:-1::0;;95669:41:0::1;::::0;::::1;;::::0;::::1;::::0;;;::::1;::::0;::::1;:::i;:::-;95646:64;;;95741:16;-1:-1:-1::0;;;;;95729:28:0::1;:8;:28;95725:130;;-1:-1:-1::0;;95778:16:0::1;:36:::0;;::::1;::::0;;::::1;-1:-1:-1::0;;;95778:36:0::1;-1:-1:-1::0;;;;95778:36:0;;::::1;::::0;;;::::1;::::0;;95833:7:::1;;95725:130;95890:1;95869:22;;;;95618:285;;;;86256:1;;;95353:557::o:0;84718:62::-;;;;;;;;;;;;;;-1:-1:-1;;;84718:62:0;;;;:::o;110332:313::-;110409:4;-1:-1:-1;;110430:6:0;:21;110426:74;;;-1:-1:-1;;;;;110468:20:0;-1:-1:-1;110426:74:0;110544:18;:6;:16;:18::i;:::-;110521:10;110510:22;;;;:10;:22;;;;;;;;-1:-1:-1;;;;;110510:31:0;;;;;;;;;;;:52;;-1:-1:-1;;;;;;110510:52:0;-1:-1:-1;;;;;110510:52:0;;;;;;;;;;;110578:37;;;;;110608:6;;110578:37;:::i;:::-;;;;;;;;-1:-1:-1;110633:4:0;110332:313;;;;;:::o;116007:820::-;-1:-1:-1;;;;;116197:13:0;;116138:23;116197:13;;;:7;:13;;;;;;;;:21;116233:19;:25;;;;;;:31;-1:-1:-1;;;;;116197:21:0;;;;-1:-1:-1;;;116233:31:0;;;;:36;116229:591;;116360:10;116340:31;;;;:19;:31;;;;;:36;116326:11;;116303:4;;-1:-1:-1;;;;;;116340:36:0;;;-1:-1:-1;116322:487:0;;;116618:10;116588:51;116598:31;;;:19;:31;;;;;;;;:36;-1:-1:-1;;;;;116598:36:0;;;;:40;116588:51;;;;:9;:51;;;;;:109;116463:31;;;;;;;116416:377;;116455:292;;-1:-1:-1;;;116588:109:0;;;;;;;116455:64;;116463:37;;;;116506:12;116455:50;:64::i;:::-;:68;;:292::i;:::-;116770:4;116416:16;:377::i;:::-;116397:396;116007:820;;;;:::o;118064:180::-;118188:11;;118127:7;118164:36;;;:23;:36;;;;;;;;;118202:20;:33;;;;;;;-1:-1:-1;;;;;118164:36:0;;;;118202:33;118064:180;;:::o;112202:169::-;112350:11;;112255:7;112329:33;;;:20;:33;;;;;;;;;112290:9;:22;;;;;:33;112282:81;;-1:-1:-1;;;;;112290:33:0;;;;112329;112282:46;:81::i;:::-;112275:88;;112202:169;;:::o;110932:625::-;-1:-1:-1;;;;;111110:18:0;;111066:4;111110:18;;;:10;:18;;;;;;;;111129:10;111110:30;;;;;;;;-1:-1:-1;;;;;111110:30:0;111155:25;;;111151:70;;;111204:5;111197:12;;;;;111151:70;-1:-1:-1;;;;;111272:31:0;;;;111268:196;;-1:-1:-1;;;;;111361:18:0;;;;;;:10;:18;;;;;;;;111380:10;111361:30;;;;;;;;111353:99;;:69;;-1:-1:-1;;;;;111361:30:0;111415:6;111353:61;:69::i;:::-;:97;:99::i;:::-;-1:-1:-1;;;;;111320:18:0;;;;;;:10;:18;;;;;;;;111339:10;111320:30;;;;;;;:132;;-1:-1:-1;;;;;;111320:132:0;-1:-1:-1;;;;;111320:132:0;;;;;;;;;;111268:196;111474:53;111489:6;111497:9;111508:18;:6;:16;:18::i;:::-;111474:14;:53::i;:::-;;111545:4;111538:11;;;110932:625;;;;;;:::o;122841:795::-;122916:56;;-1:-1:-1;;;122916:56:0;;122892:21;;-1:-1:-1;;;;;122916:8:0;:25;;;;:56;;122942:5;;122957:6;;122892:21;;122916:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;122892:80;;123012:4;122993:15;:23;;;;:47;;;;;123039:1;123020:15;:20;;;;122993:47;122985:75;;;;-1:-1:-1;;;122985:75:0;;;;;;;:::i;:::-;123095:45;;-1:-1:-1;;;123095:45:0;;123071:21;;-1:-1:-1;;;;;123095:4:0;:24;;;;:45;;123128:4;;123135;;123095:45;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;123071:69;;123151:20;123174:4;-1:-1:-1;;;;;123174:24:0;;123207:4;123214:5;123174:46;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;123151:69;;123233:18;123254:4;-1:-1:-1;;;;;123254:25:0;;123288:4;123303:9;123254:60;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;123327:73;;-1:-1:-1;;;123327:73:0;;123233:81;;-1:-1:-1;;;;;;123327:4:0;:20;;;;:73;;123348:13;;123363:6;;123371:11;;123384:15;;123327:73;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;123413:72:0;;-1:-1:-1;;;123413:72:0;;-1:-1:-1;;;;;123413:4:0;:20;;-1:-1:-1;123413:20:0;;-1:-1:-1;123413:72:0;;123434:12;;123448:6;;123456:11;;123469:15;;123413:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;123532:9:0;;123498:87;;-1:-1:-1;;;123498:87:0;;-1:-1:-1;;;;;123498:4:0;:21;;;-1:-1:-1;123498:21:0;;-1:-1:-1;123498:87:0;;123520:10;;123532:9;;;123543:11;;;;123569:15;;123498:87;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;123596:14:0;:32;;;;;;;;;-1:-1:-1;;;123596:32:0;-1:-1:-1;;;;123596:32:0;;;;;;;;;;-1:-1:-1;;;;;122841:795:0:o;84614:43::-;84656:1;84614:43;:::o;125153:159::-;125291:11;;125214:7;125267:36;;;:23;:36;;;;;;125241:63;;125249:4;125241:21;;-1:-1:-1;;;;;125267:36:0;125241:25;:63::i;87936:1968::-;88086:11;;87988:25;88135:34;;;:20;:34;;;;;;;;;88188:15;:29;;;;;:42;87988:25;;;;88086:11;;-1:-1:-1;;;;;88135:34:0;;-1:-1:-1;;;88188:42:0;;;;;:63;;-1:-1:-1;88234:17:0;;88188:63;88180:91;;;;-1:-1:-1;;;88180:91:0;;;;;;;:::i;:::-;88282:18;88303:23;;;:9;:23;;;;;:34;-1:-1:-1;;;;;88303:34:0;88352:14;;88348:683;;88383:24;88410:21;:19;:21::i;:::-;88383:48;-1:-1:-1;88469:123:0;88504:50;88543:10;88504:34;88383:48;88525:12;88504:20;:34::i;88469:123::-;88670:37;;;;:23;:37;;;;;;88446:146;;-1:-1:-1;88627:181:0;;88446:146;;88662:64;;-1:-1:-1;;;;;88670:37:0;88713:12;88662:50;:64::i;:::-;:108;;;;;;88789:4;88627:16;:181::i;:::-;88607:201;;88348:683;;;;88870:1;88830:37;;;:23;:37;;;;;;-1:-1:-1;;;;;88830:37:0;:41;88826:205;;88925:37;;;;:23;:37;;;;;;88908:61;;-1:-1:-1;;;;;88925:37:0;;88908:16;:61::i;:::-;88888:81;-1:-1:-1;89007:12:0;;-1:-1:-1;88826:205:0;89066:30;;;89161:32;:20;:30;:32::i;:::-;89132:1;89117:16;;89107:27;;;;:9;:27;;;;;:86;;-1:-1:-1;;;;;89107:86:0;;;-1:-1:-1;;;89107:86:0;;;;;;;;;89245:118;:92;89320:16;89245:56;89253:10;89283:17;89245:37;:56::i;:::-;:74;;:92::i;:118::-;89229:1;89214:16;;89204:27;;;;:9;:27;;;;;:159;;-1:-1:-1;;;;;;89204:159:0;-1:-1:-1;;;;;89204:159:0;;;;;;;;89448:49;89394:38;;:103;89376:186;;;89524:19;:26;;-1:-1:-1;;;;89524:26:0;-1:-1:-1;;;89524:26:0;;;89376:186;89578:17;;89574:66;;89612:16;:14;:16::i;:::-;89671:1;89656:12;:16;:40;;;;;89695:1;89676:16;:20;89656:40;89652:108;;;89713:35;89727:20;89713:13;:35::i;:::-;89770:22;:20;:22::i;:::-;89825;:11;;:20;:22::i;:::-;89849:14;;89874:11;;89865:21;;;;89849:14;89865:21;;;;;;;;;:30;89810:86;;-1:-1:-1;;;;;89810:86:0;;;;;;;;-1:-1:-1;;;89849:14:0;;;;;;;89865:30;;89810:86;:::i;:::-;;;;;;;;87936:1968;;;;;;:::o;117666:146::-;-1:-1:-1;;;;;117777:13:0;;117735:6;117777:13;;;:7;:13;;;;;;;;117761:43;;;;;;;;;-1:-1:-1;;;;;117761:43:0;;;;-1:-1:-1;;;;;;;;117761:43:0;;;;;;;;;;;-1:-1:-1;;;117761:43:0;;;;;;;;;117792:11;;117761:43;;;:15;:43::i;:::-;117754:50;;117666:146;;;;:::o;125320:99::-;125409:2;125320:99;:::o;113394:515::-;113516:17;;;113644:9;113640:60;;113677:11;;113670:18;;113640:60;-1:-1:-1;;;113725:21:0;;;;:15;:21;;;;;:34;;-1:-1:-1;;;113725:34:0;;;;113794:43;-1:-1:-1;;;113794:43:0;;;;;113865:36;;113394:515::o;118402:149::-;118477:7;118504:15;;;:9;:15;;;;;:39;-1:-1:-1;;;118504:39:0;;-1:-1:-1;;;;;118504:39:0;;118402:149::o;114617:902::-;115135:9;;115168:8;;115200:4;;115228:11;;115263:6;;115293:12;;115329:16;;115361:5;;115381:14;;115410:15;;115448:51;;114617:902::o;112379:496::-;-1:-1:-1;;;;;112697:25:0;112492:30;112697:25;;;:19;:25;;;;;;;;:30;112788:15;:21;;;;;;:26;-1:-1:-1;;;;;112697:30:0;;;;-1:-1:-1;;;112742:31:0;;;;;;;112788:26;;;;112829:27;;;;;112379:496::o;112075:119::-;-1:-1:-1;;;;;112165:13:0;112138:7;112165:13;;;:7;:13;;;;;:21;-1:-1:-1;;;;;112165:21:0;;112075:119::o;124626:109::-;124690:7;124626:109;:::o;118788:308::-;-1:-1:-1;;;;;119018:13:0;118908:14;119018:13;;;:7;:13;;;;;:21;-1:-1:-1;;;;;119018:21:0;;;-1:-1:-1;;;;;;;;119041:18:0;;;;;-1:-1:-1;;;119061:26:0;;;;118788:308::o;92355:645::-;92423:12;92451:19;92472:24;92500:15;:13;:15::i;:::-;92549:11;;92591:10;92526:20;92575:27;;;:15;:27;;;;;:33;92448:67;;-1:-1:-1;92448:67:0;;-1:-1:-1;92549:11:0;-1:-1:-1;;;;92575:33:0;;-1:-1:-1;;;;;92575:33:0;92571:127;;92646:10;92630:27;;;;:15;:27;;;;;:56;;-1:-1:-1;;;;;;92630:56:0;-1:-1:-1;;;;;92630:56:0;;;;;92571:127;92724:10;92708:27;;;;:15;:27;;;;;;;;:43;;-1:-1:-1;;;;;;;;92708:43:0;;;;;;;;;;;;;;;;;;;;92762:34;;;:20;:34;;;;;;:44;;;;;;;;;-1:-1:-1;;;;;;92762:44:0;;;;;;;92817:85;;92724:10;92864:11;;92817:85;;92885:16;92817:34;:85::i;:::-;92949:12;92937:10;-1:-1:-1;;;;;92918:52:0;;92963:6;92918:52;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;92988:4:0;;92355:645;-1:-1:-1;;;;92355:645:0:o;84664:47::-;;;;;;;;;;;;;;-1:-1:-1;;;84664:47:0;;;;:::o;98261:208::-;85845:11;;98329:19;85836:21;;;:8;:21;;;;;:30;-1:-1:-1;;;;;85836:30:0;85817:15;:49;;85809:72;;;;-1:-1:-1;;;85809:72:0;;;;;;;:::i;:::-;98361:22:::1;98386:6;-1:-1:-1::0;;;;;98386:18:0::1;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98361:45;;98424:37;98446:14;98424:21;:37::i;:::-;98417:44;;;98261:208:::0;:::o;115527:384::-;115642:15;;;115755:9;115751:60;;115788:11;;115781:18;;115751:60;-1:-1:-1;;;115829:14:0;;;;:8;:14;;;;;;;;:23;;115882:20;;;-1:-1:-1;;;;;115829:23:0;;;;-1:-1:-1;;;115854:26:0;;;;;115527:384::o;125427:115::-;125523:10;125427:115;:::o;117945:111::-;118029:19;;-1:-1:-1;;;118029:19:0;;;;118028:20;;117945:111::o;116904:673::-;116961:15;116993:11;;117008:1;116993:16;116989:540;;;-1:-1:-1;117033:28:0;117026:35;;116989:540;117111:11;;117102:21;;;;:8;:21;;;;;:30;-1:-1:-1;;;;;117102:30:0;117083:15;:49;117079:450;;117172:15;;-1:-1:-1;;;;;;;;117172:15:0;;;;83107:13;117172:26;117153:15;:45;117149:118;;-1:-1:-1;117226:25:0;117219:32;;117149:118;-1:-1:-1;117288:22:0;117281:29;;117079:450;117373:11;;117364:21;;;;:8;:21;;;;;:30;-1:-1:-1;;;;;117364:30:0;117346:15;:48;:107;;;;-1:-1:-1;117428:11:0;;117412:28;;;;:15;:28;;;;;:41;-1:-1:-1;;;117412:41:0;;;;117411:42;117346:107;117328:201;;;-1:-1:-1;117487:30:0;117480:37;;117328:201;-1:-1:-1;117546:23:0;116904:673;:::o;112883:503::-;113208:11;;113234:14;;113208:11;;-1:-1:-1;;;113234:14:0;;;;;-1:-1:-1;;;113263:16:0;;;;;-1:-1:-1;;;;;113294:9:0;;;;-1:-1:-1;;;113318:15:0;;;;;;-1:-1:-1;;;113348:19:0;;;;;;112883:503::o;110653:169::-;110733:4;110757:57;110772:10;110784:9;110795:18;:6;:16;:18::i;98581:1315::-;85845:11;;85836:21;;;;:8;:21;;;;;:30;-1:-1:-1;;;;;85836:30:0;85817:15;:49;;85809:72;;;;-1:-1:-1;;;85809:72:0;;;;;;;:::i;:::-;85969:15:::1;::::0;-1:-1:-1;;;;;;;;85969:15:0;;::::1;;83107:13;85969:26;85951:15;:44;85943:66;;;;-1:-1:-1::0;;;85943:66:0::1;;;;;;;:::i;:::-;98655:22:::2;98680:6;-1:-1:-1::0;;;;;98680:18:0::2;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98655:45;;98711:19;98733:37;98755:14;98733:21;:37::i;:::-;98711:59:::0;-1:-1:-1;98785:16:0;98781:100:::2;;98832:37;98854:14;98832:21;:37::i;:::-;98818:51;;98781:100;98894:14;98910:17:::0;98929:30:::2;;:::i;:::-;99144:11;::::0;99123:33:::2;::::0;;;:20:::2;:33;::::0;;;;;;99171:9:::2;::::0;98963:257;;-1:-1:-1;;;98963:257:0;;-1:-1:-1;;;;;98963:8:0::2;:38;::::0;::::2;::::0;:257:::2;::::0;99016:9:::2;::::0;99048:4:::2;::::0;99068:11;;99094:14;;-1:-1:-1;;;;;99171:9:0::2;::::0;99195:14:::2;::::0;98963:257:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98893:327:::0;;-1:-1:-1;98893:327:0;-1:-1:-1;98893:327:0;-1:-1:-1;99237:13:0;;99233:81:::2;;99267:4;-1:-1:-1::0;;;;;99267:15:0::2;;99290:9;99267:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;99233:81;99330:10:::0;;99326:75:::2;;99357:32;99369:11;99382:6;99357:11;:32::i;:::-;99417:15;::::0;::::2;::::0;:19;99413:244:::2;;99569:15:::0;;::::2;99586::::0;::::2;::::0;99530:72:::2;::::0;-1:-1:-1;;;99530:72:0;;:9:::2;-1:-1:-1::0;;;;;99530:38:0::2;::::0;::::2;::::0;:72:::2;::::0;::::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99504:141;;;;-1:-1:-1::0;;;99504:141:0::2;;;;;;;:::i;:::-;99685:26;:15;:24;:26::i;:::-;99667:15;:44:::0;;-1:-1:-1;;;;99667:44:0::2;-1:-1:-1::0;;;;;;;;99667:44:0;;::::2;;;::::0;;99823:15;;::::2;99861::::0;::::2;::::0;99727:161:::2;::::0;;;::::2;::::0;;::::2;::::0;::::2;::::0;::::2;::::0;99794:6;;99861:15;99727:161:::2;:::i;:::-;;;;;;;;86020:1;;;;;98581:1315::o:0;109734:478::-;109784:27;;:::i;:::-;-1:-1:-1;109822:10:0;109814:19;;;;:7;:19;;;;;;;;;109784:49;;;;;;;;;-1:-1:-1;;;;;109784:49:0;;;;-1:-1:-1;;;;;;;;109784:49:0;;;;;;;;;;;-1:-1:-1;;;109784:49:0;;;;;;;;;;;;109894:11;;109868:38;;109784:49;;109868:15;:38::i;:::-;-1:-1:-1;;;;;109844:62:0;;;:21;;;:62;;;109940:11;;109917:35;;;:13;;;:35;109963:47;;;;-1:-1:-1;;;109963:47:0;;;;;;;:::i;:::-;110044:21;;;;;;110021:20;110076:25;;;110120:10;110112:19;;;:7;:19;;;;;;;;:30;;;;;;;;;;-1:-1:-1;;;;;;110112:30:0;;;-1:-1:-1;;;;;110112:30:0;;;;-1:-1:-1;;;;110112:30:0;-1:-1:-1;;;;;;;;110112:30:0;;;;;-1:-1:-1;;;;;110112:30:0;-1:-1:-1;;;110112:30:0;;;;;;;;;;;;;;110021:44;;110153:51;;-1:-1:-1;;;;;110153:12:0;:25;;110021:44;110153:25;:51::i;119181:140::-;119301:11;;119280:33;;;;:20;:33;;;;;;;;;119273:40;;;;;;;;;;;;;;;;;119244:16;;119273:40;;;119280:33;119273:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;119181:140;:::o;94851:296::-;94902:17;94921:19;94953:24;95033:15;:13;:15::i;:::-;94988:60;;-1:-1:-1;94988:60:0;-1:-1:-1;94988:60:0;-1:-1:-1;95059:80:0;95094:10;94988:60;95119:1;94988:60;95059:34;:80::i;:::-;94851:296;;;:::o;96074:2179::-;86108:11;;86099:21;;;;:8;:21;;;;;:30;-1:-1:-1;;;;;86099:30:0;86081:15;:48;86073:72;;;;-1:-1:-1;;;86073:72:0;;;;;;;:::i;:::-;96164:11:::1;::::0;96141:20:::1;96195:29:::0;;;:15:::1;:29;::::0;;;;:42;-1:-1:-1;;;96195:42:0;::::1;;;96194:43;96186:63;;;;-1:-1:-1::0;;;96186:63:0::1;;;;;;;:::i;:::-;96264:29;::::0;;;:15:::1;:29;::::0;;;;:44;::::1;;96260:167;;96377:38;:9;-1:-1:-1::0;;;;;96377:25:0::1;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:36;:38::i;:::-;96330:29;::::0;;;:15:::1;:29;::::0;;;;:85;;-1:-1:-1;;96330:85:0::1;;::::0;;;::::1;::::0;;;::::1;::::0;;96260:167:::1;96484:15;96593:22:::0;;;:8:::1;:22;::::0;;;;;:31;-1:-1:-1;;96670:16:0;;96661:26;;;;;:35;96745:32;;-1:-1:-1;;;96745:32:0;;96484:15;;;;-1:-1:-1;;;;;96593:31:0;;::::1;::::0;96661:35;::::1;::::0;96484:15;;-1:-1:-1;;;;;96745:4:0::1;:17;::::0;::::1;::::0;:32:::1;::::0;96771:4:::1;::::0;96745:32:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;96722:55:::0;-1:-1:-1;96796:16:0;;96792:75:::1;;96833:4;-1:-1:-1::0;;;;;96833:16:0::1;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;96792:75;-1:-1:-1::0;96894:29:0::1;::::0;;;:15:::1;:29;::::0;;;;:51;-1:-1:-1;;;96894:51:0;::::1;;;96890:215;;96980:16;::::0;-1:-1:-1;;;96980:16:0;::::1;;;::::0;-1:-1:-1;96890:215:0::1;;;97042:29;::::0;;;:15:::1;:29;::::0;;;;:51;-1:-1:-1;;;97042:51:0;::::1;;;::::0;-1:-1:-1;96890:215:0::1;97121:29;::::0;;;:15:::1;:29;::::0;;;;:44;97181:2:::1;97121:44;::::0;;::::1;:57:::0;;::::1;:62:::0;;::::1;;97117:286;;;97241:29;::::0;;;:15:::1;:29;::::0;;;;:62;;::::1;97224:2;97211:15:::0;::::1;97241:62:::0;;::::1;-1:-1:-1::0;;;97241:62:0::1;-1:-1:-1::0;;97241:62:0;;::::1;::::0;;;::::1;::::0;;;97211:15;-1:-1:-1;97117:286:0::1;;;97347:29;::::0;;;:15:::1;:29;::::0;;;;:44;::::1;;::::0;-1:-1:-1;97117:286:0::1;97420:22;::::0;::::1;97415:586;97448:8;97444:12;;:1;:12;97415:586;;;97500:154;97538:1;97558:19;97596:8;97623:16;97500:19;:154::i;:::-;97478:176;;97697:1;97675:19;:23;;;97671:319;;;97739:1;97728:8;:12;97723:17;;:1;:17;97719:231;;;97765:29;::::0;;;:15:::1;:29;::::0;;;;:49;;-1:-1:-1;;;;97765:49:0::1;-1:-1:-1::0;;;97765:49:0::1;::::0;;97719:231:::1;;;97863:29;::::0;;;:15:::1;:29;::::0;;;;:67;;-1:-1:-1;;97863:67:0::1;-1:-1:-1::0;;;97928:1:0::1;97924:5:::0;::::1;97863:67;;;;::::0;;97719:231:::1;97968:7;;;;;;;;;97671:319;97458:3;;97415:586;;;-1:-1:-1::0;98029:29:0::1;::::0;;;:15:::1;:29;::::0;;;;:44;::::1;98017:56:::0;;::::1;98029:44:::0;::::1;98017:56;98013:233;;;98090:29;::::0;;;:15:::1;:29;::::0;;;;:49;;-1:-1:-1;;;;98090:49:0::1;-1:-1:-1::0;;;98090:49:0::1;::::0;;98013:233:::1;;;98172:29;::::0;;;:15:::1;:29;::::0;;;;:62;;-1:-1:-1;;98172:62:0::1;-1:-1:-1::0;;;98172:62:0::1;::::0;::::1;;;::::0;;98013:233:::1;86156:1;;;;;;96074:2179::o:0;118559:221::-;118699:7;118731:28;;;:22;:28;;;;;;;;:41;;;;;;;;;;118559:221::o;118252:142::-;-1:-1:-1;;;;;118360:17:0;;;118333:7;118360:17;;;:10;:17;;;;;;;;:26;;;;;;;;;;;;-1:-1:-1;;;;;118360:26:0;;118252:142::o;114252:357::-;114463:9;;114432:44;;-1:-1:-1;;;114432:44:0;;114387:19;;-1:-1:-1;;;;;114432:8:0;:23;;;;:44;;114456:5;;-1:-1:-1;;;;;114463:9:0;;;;114432:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;114424:52;-1:-1:-1;114493:9:0;114489:60;;114526:11;;114519:18;;114489:60;-1:-1:-1;114566:28:0;;;;:22;:28;;;;;;;;:35;;;;;;;;;;114252:357::o;117820:117::-;117877:20;117917:12;117910:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;117910:19:0;;;;;-1:-1:-1;;;117910:19:0;;;;;;;;;;;;;;;;;;;;;;;;;117820:117;:::o;123715:130::-;86416:19;;123778:12;;-1:-1:-1;;;86416:19:0;;;;86415:20;86407:46;;;;-1:-1:-1;;;86407:46:0;;;;;;;:::i;:::-;123813:24:::1;123827:9;123813:13;:24::i;90133:272::-:0;86529:10;-1:-1:-1;;;;;86543:5:0;86529:19;;86521:45;;;;-1:-1:-1;;;86521:45:0;;;;;;;:::i;:::-;86213:11:::1;::::0;86205:40:::1;;;;-1:-1:-1::0;;;86205:40:0::1;;;;;;;:::i;:::-;90247:12:::0;-1:-1:-1;;;;;90233:26:0;::::2;;::::0;::::2;::::0;:66:::2;;-1:-1:-1::0;90277:22:0;-1:-1:-1;;;;;90263:36:0;::::2;;;90233:66;90225:91;;;;-1:-1:-1::0;;;90225:91:0::2;;;;;;;:::i;:::-;90327:12;90345:51;;;;;;;;90357:22;:11;;:20;:22::i;:::-;90382:1;90357:26:::0;;::::2;-1:-1:-1::0;;;;;90345:51:0;;::::2;::::0;;;;::::2;;::::0;;::::2;::::0;90327:70;;;;::::2;::::0;;-1:-1:-1;90327:70:0;;;;;;;;;;::::2;::::0;;;;;::::2;::::0;-1:-1:-1;;90327:70:0;;::::2;::::0;;::::2;::::0;;;::::2;-1:-1:-1::0;;;;90327:70:0::2;-1:-1:-1::0;;;90327:70:0;;;::::2;;::::0;;;::::2;::::0;;90133:272::o;113917:327::-;114021:18;;114094:9;114090:60;;114127:11;;114120:18;;114090:60;-1:-1:-1;;114168:15:0;;;;:9;:15;;;;;:26;-1:-1:-1;;;;;114168:26:0;;;;-1:-1:-1;;;114196:39:0;;;;;113917:327::o;45201:184::-;45258:7;-1:-1:-1;;;45286:5:0;:14;45278:67;;;;-1:-1:-1;;;45278:67:0;;;;;;;:::i;:::-;-1:-1:-1;45371:5:0;45201:184::o;18670:471::-;18728:7;18973:6;18969:47;;-1:-1:-1;19003:1:0;18996:8;;18969:47;19040:5;;;19044:1;19040;:5;:1;19064:5;;;;;:10;19056:56;;;;-1:-1:-1;;;19056:56:0;;;;;;;:::i;19617:132::-;19675:7;19702:39;19706:1;19709;19702:39;;;;;;;;;;;;;;;;;:3;:39::i;124820:246::-;124906:7;124930:5;124926:133;;;-1:-1:-1;124968:15:0;124959:24;;124952:31;;124926:133;-1:-1:-1;125032:15:0;125023:24;;125016:31;;17780:136;17838:7;17865:43;17869:1;17872;17865:43;;;;;;;;;;;;;;;;;:3;:43::i;111672:395::-;-1:-1:-1;;;;;111811:13:0;;111790:4;111811:13;;;:7;:13;;;;;:21;-1:-1:-1;;;;;111811:30:0;;;:21;;:30;111807:75;;;-1:-1:-1;111865:5:0;111858:12;;111807:75;111892:45;111911:4;111929:6;-1:-1:-1;;;;;111922:14:0;-1:-1:-1;;111917:19:0;111892:18;:45::i;:::-;111948:38;111967:2;111978:6;-1:-1:-1;;;;;111971:14:0;111948:18;:38::i;:::-;112017:2;-1:-1:-1;;;;;112002:35:0;112011:4;-1:-1:-1;;;;;112002:35:0;;112029:6;-1:-1:-1;;;;;112021:15:0;112002:35;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;112055:4:0;111672:395;;;;;:::o;17316:181::-;17374:7;17406:5;;;17430:6;;;;17422:46;;;;-1:-1:-1;;;17422:46:0;;;;;;;:::i;104932:355::-;105024:14;;105063:11;;105053:22;;;;:9;:22;;;;;;:46;105024:14;105124:15;;;105114:26;;;;;;:50;104978:276;;-1:-1:-1;;;104978:276:0;;-1:-1:-1;;;;;104978:8:0;:31;;;;:276;;-1:-1:-1;;;105024:14:0;;;;;;-1:-1:-1;;;;;;;;105053:46:0;;;;;;;105114:50;;;;;;105179:5;;105207:6;;105229:14;;104978:276;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105265:14;:12;:14::i;123992:307::-;124151:11;;124074:14;124130:33;;;:20;:33;;;;;;124091:148;;124122:86;;124195:12;;124122:68;;-1:-1:-1;;;;;124130:33:0;124169:20;124122:46;:68::i;:86::-;124223:5;124091:16;:148::i;:::-;124074:165;;124250:41;124271:10;124284:6;124250:12;:41::i;90413:1015::-;90465:21;90489:8;-1:-1:-1;;;;;90489:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90465:51;;90527:22;90552:6;-1:-1:-1;;;;;90552:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90686:9;;90612:123;;-1:-1:-1;;;90612:123:0;;90527:45;;-1:-1:-1;90583:26:0;;-1:-1:-1;;;;;90612:8:0;:30;;;;:123;;90527:45;;-1:-1:-1;;;;;90686:9:0;;;;90710:14;;90612:123;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90583:152;;90748:32;90765:14;90748:16;:32::i;:::-;90832:13;90848:16;-1:-1:-1;;;;;90848:28:0;;90891:9;90915:29;:18;:27;:29::i;:::-;90959:24;:13;:22;:24::i;:::-;90848:146;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;90832:162;;91006:18;91034:9;-1:-1:-1;;;;;91034:17:0;;91052:5;91034:24;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;91069:51:0;;-1:-1:-1;;;91069:51:0;;91005:53;;-1:-1:-1;;;;;;;91069:26:0;;;;;:51;;91104:4;;-1:-1:-1;;83069:2:0;91069:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;91133:11:0;:16;;91148:1;91133:16;;;91160:27;;:::i;:::-;91190:122;;;;;;;;91213:24;:13;:22;:24::i;:::-;-1:-1:-1;;;;;91190:122:0;;;;;91252:29;:18;:27;:29::i;:::-;-1:-1:-1;;;;;91190:122:0;;;;;;;;;;;;91332:11;;-1:-1:-1;91323:21:0;;;:8;:21;;;;;;;;:35;;;;;;;;-1:-1:-1;;91323:35:0;;;;;;;-1:-1:-1;;;;91323:35:0;-1:-1:-1;;;91323:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;91369:51;-1:-1:-1;;;91369:51:0;;91323:35;;-1:-1:-1;91369:11:0;-1:-1:-1;;;;;91369:36:0;;;;:51;;91406:13;;91369:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90413:1015;;;;;;:::o;45684:179::-;45740:6;-1:-1:-1;;;45767:5:0;:13;45759:65;;;;-1:-1:-1;;;45759:65:0;;;;;;;:::i;108389:1224::-;108562:24;;;;108601:19;;-1:-1:-1;;;;;108601:23:0;;;;;:50;;;108647:4;108628:11;:16;;;-1:-1:-1;;;;;108628:23:0;;108601:50;108597:1009;;;108690:12;:19;;-1:-1:-1;;108690:23:0;;;108668:12;;-1:-1:-1;;;;;108752:19:0;;;;;;;;;;;;;;;;;:24;108812:12;:19;;-1:-1:-1;;;;;108752:24:0;;;;-1:-1:-1;108812:12:0;;:19;;;;;;;;;;;;;;;;;;:25;-1:-1:-1;;;108812:25:0;;-1:-1:-1;;;;;108812:25:0;;-1:-1:-1;108871:4:0;108854:741;108881:11;:16;;;-1:-1:-1;;;;;108877:20:0;:1;:20;108854:741;;;108931:13;-1:-1:-1;;;;;108927:17:0;:1;:17;108923:323;;;109100:1;109091:10;;;;109138:12;109151:5;-1:-1:-1;;;;;109138:19:0;;;;;;;;;;;;;;;;:25;;;;;;;;;;-1:-1:-1;;;;;109138:25:0;109124:39;;109202:12;109215:5;-1:-1:-1;;;;;109202:19:0;;;;;;;;;;;;;;;;;;:24;-1:-1:-1;;;;;109202:24:0;;-1:-1:-1;108923:323:0;109503:12;;;;:9;:12;;;;;:23;109477:19;;109381:198;;:165;;109451:76;;-1:-1:-1;;;;;109503:23:0;;;;109452:45;;-1:-1:-1;;;;;109452:20:0;;;:45;:24;:45::i;109451:76::-;-1:-1:-1;;;;;109381:21:0;;;:47;:165::i;:::-;:196;:198::i;:::-;109366:213;-1:-1:-1;;;108899:3:0;108854:741;;;;108597:1009;;;108389:1224;;;;:::o;93008:1697::-;93224:11;;93296:10;93083:17;93280:27;;;:15;:27;;;;;;;;:32;93433:19;:31;;;;;:36;93083:17;;;;;;-1:-1:-1;;;;;93280:32:0;;;;-1:-1:-1;;;93358:33:0;;;;;;;93433:36;;;;93512:37;;;93564:17;93560:66;;93606:1;93609;93612;93598:16;;;;;;;;;;;;;93560:66;-1:-1:-1;;;;;93642:29:0;;;;;;:71;;;93690:23;-1:-1:-1;;;;;93675:38:0;:12;:38;93642:71;93638:513;;;-1:-1:-1;;;;;93881:1:0;93855:27;;93847:36;;93837:47;;;;:9;:47;;;;;:71;93742:246;;93777:172;;93936:12;;93777:132;;:33;;;;-1:-1:-1;;;93837:71:0;;;;93777:59;:132::i;93742:246::-;93730:258;-1:-1:-1;94007:13:0;;94003:88;;94041:34;94053:10;94065:9;94041:11;:34::i;:::-;94128:10;94112:27;;;;:15;:27;;;;;94105:34;93638:513;-1:-1:-1;;;;;94167:26:0;;;;;;:65;;;94212:20;-1:-1:-1;;;;;94197:35:0;:12;:35;94167:65;94163:454;;;-1:-1:-1;;;;;94414:1:0;94391:24;;94381:35;;;;;;:9;:35;;;;;:59;94263:235;;94298:162;;-1:-1:-1;;;94381:59:0;;;;;94298:48;;:30;;94333:12;94298:34;:48::i;94263:235::-;94594:10;94574:31;;;;:19;:31;;;;;94567:38;94249:249;-1:-1:-1;;;;;;94513:39:0;;;-1:-1:-1;94163:454:0;94660:12;94648:10;-1:-1:-1;;;;;94632:65:0;;94674:9;94685:11;94632:65;;;;;;;:::i;:::-;;;;;;;;93008:1697;;;;;;;;;:::o;107166:1014::-;107343:30;;:::i;:::-;-1:-1:-1;;;;;;107376:14:0;;;;;;:7;:14;;;;;;;;;107343:47;;;;;;;;;-1:-1:-1;;;;;107343:47:0;;;;-1:-1:-1;;;;;;;;107343:47:0;;;;;;;;;;;-1:-1:-1;;;107343:47:0;;;;;;;;;;;;107458:14;;107454:313;;107516:34;107532:11;107545:4;107516:15;:34::i;:::-;-1:-1:-1;;;;;107489:61:0;;;:24;;;:61;107565:31;;:16;;;:31;107663:19;;107655:100;;:70;;-1:-1:-1;;;;;107655:28:0;107714:9;107655:50;:70::i;:100::-;-1:-1:-1;;;;;107633:122:0;;;107454:313;107856:41;107872:11;107885;;107856:15;:41::i;:::-;-1:-1:-1;;;;;107829:68:0;;;:24;;;:68;107934:11;;107908:38;:16;;;:38;108008:17;;108004:130;;108072:19;;108064:58;;:46;;-1:-1:-1;;;;;108064:28:0;108097:12;108064:32;:46::i;:58::-;-1:-1:-1;;;;;108042:80:0;;;108004:130;-1:-1:-1;;;;;108144:14:0;;;;;;;;:7;:14;;;;;;;;;:28;;;;;;;;;;;;;-1:-1:-1;;;;;;108144:28:0;;;-1:-1:-1;;;;;108144:28:0;;;;;;;-1:-1:-1;;;;108144:28:0;-1:-1:-1;;;;;;;;108144:28:0;;;;;-1:-1:-1;;;;;108144:28:0;-1:-1:-1;;;108144:28:0;;;;;;;;;;;;-1:-1:-1;;;107166:1014:0:o;102452:995::-;102655:9;;102583:121;;-1:-1:-1;;;102583:121:0;;102525:19;;;;-1:-1:-1;;;;;102583:8:0;:28;;;;:121;;102626:14;;-1:-1:-1;;;;;102655:9:0;;;;102679:14;;102583:121;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102738:11;;102557:147;;-1:-1:-1;102760:20:0;;:::i;:::-;-1:-1:-1;102783:22:0;;;;:8;:22;;;;;;;;;102760:45;;;;;;;;;-1:-1:-1;;;;;102760:45:0;;;;;-1:-1:-1;;;102760:45:0;;;;;;;;;;;;;;;;;;;;;102834:47;;102865:15;102834:12;:47::i;:::-;103009:16;;;;103040:13;;103068:10;;;;;102906:183;;-1:-1:-1;;;102906:183:0;;102816:65;;-1:-1:-1;;;;;;102906:16:0;:34;;;;:183;;102955:9;;102816:65;;102906:183;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102892:197;;103182:14;103178:262;;;103320:9;;103275:62;;-1:-1:-1;;;103275:62:0;;103213:139;;103245:11;;-1:-1:-1;;;;;103275:8:0;:28;;;;:62;;103304:14;;-1:-1:-1;;;;;103320:9:0;;;;;;103275:62;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103213:13;:139::i;:::-;103178:262;;;103385:43;103399:11;103412:15;103385:13;:43::i;:::-;102452:995;;;;;;:::o;101562:882::-;101723:9;;101683:53;;-1:-1:-1;;;101683:53:0;;101640:7;;;;-1:-1:-1;;;;;101683:8:0;:23;;;;:53;;101707:14;;-1:-1:-1;;;;;101723:9:0;;;;;;101683:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101845:11;;101755:54;101822:35;;;:22;:35;;;;;;;;101872:32;;;;;;;;;;;101660:76;;-1:-1:-1;101822:35:0;101872:37;101868:109;;101933:32;;;;;;;;;;;-1:-1:-1;101926:39:0;;101868:109;102081:1;102064:373;102089:1;102084;:6;102064:373;;102150:9;;-1:-1:-1;;;;;102150:9:0;:13;;102135:28;;102116:48;;;;;;;;;;;;:53;102112:149;;102231:9;;-1:-1:-1;;;;;102231:9:0;:13;102216:28;;;102197:48;;;;;;;;;;;;;;-1:-1:-1;102190:55:0;;102112:149;102315:9;;-1:-1:-1;;;;;102315:9:0;:13;;102300:28;;102281:48;;;;;;;;;;;;:53;102277:149;;102396:9;;-1:-1:-1;;;;;102396:9:0;:13;102381:28;;;;102362:48;;;;;;;;;;;;;;-1:-1:-1;102355:55:0;;102277:149;102092:3;;102064:373;;124307:311;124493:9;-1:-1:-1;;;;;124525:16:0;;;124549:47;124591:4;124549:37;124581:4;124549:27;:6;124560:15;124549:10;:27::i;:::-;:31;;:37::i;:47::-;124598:11;124525:85;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;124307:311;;;:::o;79040:177::-;79123:86;79143:5;79173:23;;;79198:2;79202:5;79150:58;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;79150:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;79150:58:0;-1:-1:-1;;;;;;79150:58:0;;;;;;;;;;79123:19;:86::i;:::-;79040:177;;;:::o;46162:179::-;46218:6;-1:-1:-1;;;46245:5:0;:13;46237:65;;;;-1:-1:-1;;;46237:65:0;;;;;;;:::i;100703:851::-;100884:6;100904:24;100930:17;100951:9;-1:-1:-1;;;;;100951:22:0;;100974:11;100951:35;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;100951:35:0;;;;;;;;;;;;:::i;:::-;100903:83;;;;101013:8;-1:-1:-1;;;;;101001:20:0;:9;:20;:79;;;;101038:16;-1:-1:-1;;;;;101026:28:0;:9;:28;:53;;;;-1:-1:-1;;;;;;101058:21:0;;;;101026:53;100997:138;;;101104:19;101097:26;;;;;;100997:138;101145:17;;101173:337;101197:7;:14;101193:1;:18;101173:337;;;101234:19;101263:9;-1:-1:-1;;;;;101263:17:0;;101281:7;101289:1;101281:10;;;;;;;;;;;;;;101263:29;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101233:59;;;;;101345:153;101373:11;101403;101433:19;101471:12;101345:9;:153::i;:::-;101307:191;;-1:-1:-1;101307:191:0;-1:-1:-1;;101213:3:0;;101173:337;;;;101527:19;101520:26;;;;;100703:851;;;;;;;:::o;91436:665::-;91493:12;91521:19;91542:24;91570:15;:13;:15::i;:::-;91518:67;;;;;91596:80;91631:10;91643:11;91656:1;91659:16;91596:34;:80::i;:::-;91710:11;;91756:10;91687:20;91736:31;;;:19;:31;;;;;:37;-1:-1:-1;;;91736:37:0;;-1:-1:-1;;;;;91736:37:0;91732:135;;91815:10;91795:31;;;;:19;:31;;;;;:60;;-1:-1:-1;;;;;;91795:60:0;-1:-1:-1;;;;;91795:60:0;;;;;91732:135;91918:18;:6;:16;:18::i;:::-;91897:10;91877:31;;;;:19;:31;;;;;:59;;-1:-1:-1;;;;;;;;91877:59:0;;;;;;;;;;;;;;;;;;;;;91988:18;:6;:16;:18::i;:::-;91947:37;;;;:23;:37;;;;;;;:59;;-1:-1:-1;;;;;;91947:59:0;;-1:-1:-1;;;;;91947:59:0;;;;;;;;;;;;;;;92022:49;91947:37;;92038:10;;92022:49;;;;92064:6;;92022:49;:::i;20245:278::-;20331:7;20366:12;20359:5;20351:28;;;;-1:-1:-1;;;20351:28:0;;;;;;;;:::i;:::-;;20390:9;20406:1;20402;:5;;;;;;;20245:278;-1:-1:-1;;;;;20245:278:0:o;18219:192::-;18305:7;18341:12;18333:6;;;;18325:29;;;;-1:-1:-1;;;18325:29:0;;;;;;;;:::i;:::-;-1:-1:-1;;;18377:5:0;;;18219:192::o;106565:593::-;106643:30;;:::i;:::-;-1:-1:-1;;;;;;106676:14:0;;;;;;:7;:14;;;;;;;;;106643:47;;;;;;;;;-1:-1:-1;;;;;106643:47:0;;;;-1:-1:-1;;;;;;;;106643:47:0;;;;;;;;;;;-1:-1:-1;;;106643:47:0;;;;;;;;;;;;106757:11;;106728:41;;106643:47;;106728:15;:41::i;:::-;-1:-1:-1;;;;;106701:68:0;;;:24;;;:68;106806:11;;106780:38;:16;;;:38;-1:-1:-1;106833:10:0;;106829:283;;;106890:19;;106882:102;;:72;;-1:-1:-1;;;;;106882:28:0;106941:11;;;;106882:50;:72::i;:102::-;-1:-1:-1;;;;;106860:124:0;;;106829:283;;;107047:19;;107039:61;;:49;;-1:-1:-1;;;;;107039:28:0;107080:6;107039:32;:49::i;:61::-;-1:-1:-1;;;;;107017:83:0;;;106829:283;-1:-1:-1;;;;;107122:14:0;;;;;;;;:7;:14;;;;;;;;;:28;;;;;;;;;;;;;-1:-1:-1;;;;;;107122:28:0;;;-1:-1:-1;;;;;107122:28:0;;;;;;;-1:-1:-1;;;;107122:28:0;-1:-1:-1;;;;;;;;107122:28:0;;;;;-1:-1:-1;;;;;107122:28:0;-1:-1:-1;;;107122:28:0;;;;;;;;;;;;-1:-1:-1;106565:593:0:o;120583:172::-;120668:79;120681:9;120692:6;120668:79;;;;;;;;;;;;;;;;;:12;:79::i;104602:322::-;104672:18;104693:40;:14;-1:-1:-1;;;;;104712:2:0;104717:15;104712:20;104693:40;:18;:40::i;:::-;104672:61;-1:-1:-1;104748:15:0;104744:173;;104780:9;:27;;-1:-1:-1;;104780:27:0;104792:15;-1:-1:-1;;;;;104780:27:0;;;;104744:173;;;104852:53;104891:2;-1:-1:-1;;;;;104872:15:0;104854:33;;;:2;:33;104853:40;104852:51;:53::i;:::-;104840:9;:65;;-1:-1:-1;;104840:65:0;-1:-1:-1;;;;;104840:65:0;;;;;;;;;;-1:-1:-1;;104602:322:0:o;123853:131::-;123933:43;;-1:-1:-1;;;123933:43:0;;-1:-1:-1;;;;;123933:10:0;:20;;;;:43;;123962:4;;123969:6;;123933:43;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105487:220;105607:7;105639:60;105697:1;105659:35;:15;-1:-1:-1;;;;;105659:35:0;;:19;:35::i;:::-;:39;;;;;105639:15;;105659:39;;105639:19;:60::i;103455:1139::-;103610:11;;;103589:33;;;;:20;:33;;;;;;;;:51;;;;;;;;;;;;;;;;;103674:11;;103651:35;;:22;:35;;;;;:60;;;;;;;;:74;;;103769:35;-1:-1:-1;;;103769:35:0;;103739:24;;-1:-1:-1;;;;;103769:9:0;:22;;;;:35;;103628:11;;103769:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;103769:35:0;;;;;;;;;;;;:::i;:::-;103738:66;;;103816:24;103850:9;-1:-1:-1;;;;;103850:17:0;;103868:7;103876:1;103868:10;;;;;;;;;;;;;;103850:29;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;103940:64:0;;-1:-1:-1;;;103940:64:0;;103815;;-1:-1:-1;;;;;;;103940:34:0;;;;;:64;;103983:4;;103998;;103940:64;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103936:159;;104026:57;;-1:-1:-1;;;104026:57:0;;-1:-1:-1;;;;;104026:32:0;;;;;:57;;104067:4;;-1:-1:-1;;83069:2:0;104026:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;103936:159;104108:24;104142:9;-1:-1:-1;;;;;104142:17:0;;104160:7;104168:1;104160:10;;;;;;;;;;;;;;104142:29;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;104188:64:0;;-1:-1:-1;;;104188:64:0;;104107;;-1:-1:-1;;;;;;;104188:34:0;;;;;:64;;104231:4;;104246;;104188:64;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104184:159;;104274:57;;-1:-1:-1;;;104274:57:0;;-1:-1:-1;;;;;104274:32:0;;;;;:57;;104315:4;;-1:-1:-1;;83069:2:0;104274:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;104184:159;104354:24;104388:9;-1:-1:-1;;;;;104388:17:0;;104406:7;104414:1;104406:10;;;;;;;;;;;;;;104388:29;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;104432:64:0;;-1:-1:-1;;;104432:64:0;;104353;;-1:-1:-1;;;;;;;104432:34:0;;;;;:64;;104475:4;;104490;;104432:64;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104428:159;;104518:57;;-1:-1:-1;;;104518:57:0;;-1:-1:-1;;;;;104518:32:0;;;;;:57;;104559:4;;-1:-1:-1;;83069:2:0;104518:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;103455:1139;;;;;;:::o;81345:761::-;81769:23;81795:69;81823:4;81795:69;;;;;;;;;;;;;;;;;81803:5;-1:-1:-1;;;;;81795:27:0;;;:69;;;;;:::i;:::-;81879:17;;81769:95;;-1:-1:-1;81879:21:0;81875:224;;82021:10;82010:30;;;;;;;;;;;;:::i;:::-;82002:85;;;;-1:-1:-1;;;82002:85:0;;;;;;;:::i;99904:791::-;100170:29;;-1:-1:-1;;;100170:29:0;;100073:6;;;;100143:11;;100073:6;;-1:-1:-1;;;;;100170:14:0;;;;;:29;;100193:4;;100170:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:33;100166:469;;;100225:12;100220:336;;100463:39;;-1:-1:-1;;;100463:39:0;;-1:-1:-1;;;;;100463:9:0;:23;;;;:39;;100487:11;;100500:1;;100463:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;100536:4;100521:19;;100220:336;100570:4;-1:-1:-1;;;;;100570:12:0;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;100622:1;100599:24;;;;100166:469;-1:-1:-1;100653:19:0;;100674:12;;-1:-1:-1;99904:791:0;;-1:-1:-1;;;99904:791:0:o;120139:436::-;120294:29;120316:6;120294:21;:29::i;:::-;120325:12;120286:52;;;;;-1:-1:-1;;;120286:52:0;;;;;;;;:::i;:::-;;120350:12;120368:9;-1:-1:-1;;;;;120368:14:0;120390:6;120368:33;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;120349:52;;;120466:7;120458:45;;;;-1:-1:-1;;;120458:45:0;;;;;;;:::i;:::-;120549:9;-1:-1:-1;;;;;120519:48:0;120542:4;-1:-1:-1;;;;;120519:48:0;;120560:6;120519:48;;;;;;:::i;:::-;;;;;;;;120139:436;;;;:::o;25634:196::-;25737:12;25769:53;25792:6;25800:4;25806:1;25809:12;25769:22;:53::i;119848:182::-;119969:4;120002:20;-1:-1:-1;119992:30:0;;119848:182::o;27011:979::-;27141:12;27174:18;27185:6;27174:10;:18::i;:::-;27166:60;;;;-1:-1:-1;;;27166:60:0;;;;;;;:::i;:::-;27300:12;27314:23;27341:6;-1:-1:-1;;;;;27341:11:0;27361:8;27372:4;27341:36;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27299:78;;;;27392:7;27388:595;;;27423:10;-1:-1:-1;27416:17:0;;-1:-1:-1;27416:17:0;27388:595;27537:17;;:21;27533:439;;27800:10;27794:17;27861:15;27848:10;27844:2;27840:19;27833:44;27748:148;27943:12;27936:20;;-1:-1:-1;;;27936:20:0;;;;;;;;:::i;22519:619::-;22579:4;23047:20;;22890:66;23087:23;;;;;;:42;;-1:-1:-1;;23114:15:0;;;23079:51;-1:-1:-1;;22519:619:0:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;2929:241::-;;3033:2;3021:9;3012:7;3008:23;3004:32;3001:2;;;-1:-1;;3039:12;3001:2;85:6;72:20;97:33;124:5;97:33;:::i;3177:366::-;;;3298:2;3286:9;3277:7;3273:23;3269:32;3266:2;;;-1:-1;;3304:12;3266:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;3356:63;-1:-1;3456:2;3495:22;;72:20;97:33;72:20;97:33;:::i;:::-;3464:63;;;;3260:283;;;;;:::o;3550:491::-;;;;3688:2;3676:9;3667:7;3663:23;3659:32;3656:2;;;-1:-1;;3694:12;3656:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;3746:63;-1:-1;3846:2;3885:22;;72:20;97:33;72:20;97:33;:::i;:::-;3650:391;;3854:63;;-1:-1;;;3954:2;3993:22;;;;2444:20;;3650:391::o;4048:360::-;;;4166:2;4154:9;4145:7;4141:23;4137:32;4134:2;;;-1:-1;;4172:12;4134:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;4224:63;-1:-1;4324:2;4360:22;;1760:20;1785:30;1760:20;1785:30;:::i;4415:366::-;;;4536:2;4524:9;4515:7;4511:23;4507:32;4504:2;;;-1:-1;;4542:12;4504:2;85:6;72:20;97:33;124:5;97:33;:::i;:::-;4594:63;4694:2;4733:22;;;;2444:20;;-1:-1;;;4498:283::o;4788:670::-;;;;;4953:3;4941:9;4932:7;4928:23;4924:33;4921:2;;;-1:-1;;4960:12;4921:2;226:6;220:13;238:33;265:5;238:33;:::i;:::-;5123:2;5173:22;;2592:13;5242:2;5291:22;;2867:13;5012:74;;-1:-1;2592:13;-1:-1;2885:32;2867:13;2885:32;:::i;:::-;5360:2;5410:22;;;;2040:13;4915:543;;;;-1:-1;;;4915:543::o;5465:528::-;;;5622:2;5610:9;5601:7;5597:23;5593:32;5590:2;;;-1:-1;;5628:12;5590:2;5679:17;5673:24;-1:-1;;;;;5717:18;5709:6;5706:30;5703:2;;;-1:-1;;5739:12;5703:2;5841:6;5830:9;5826:22;;;429:3;422:4;414:6;410:17;406:27;396:2;;-1:-1;;437:12;396:2;477:6;471:13;5717:18;50377:6;50374:30;50371:2;;;-1:-1;;50407:12;50371:2;50452:4;;;;50444:6;50440:17;499:80;50452:4;50440:17;50505:15;499:80;:::i;:::-;607:21;;;664:14;;;;639:17;;;744:27;;;;;741:36;-1:-1;738:2;;;-1:-1;;780:12;738:2;-1:-1;806:10;;800:217;825:6;822:1;819:13;800:217;;;2040:13;;893:61;;847:1;840:9;;;;;968:14;;;;996;;800:217;;;-1:-1;5945:22;;;;2592:13;5759:99;;2592:13;;-1:-1;;;;;;;5584:409::o;6000:257::-;;6112:2;6100:9;6091:7;6087:23;6083:32;6080:2;;;-1:-1;;6118:12;6080:2;1908:6;1902:13;1920:30;1944:5;1920:30;:::i;6264:263::-;;6379:2;6367:9;6358:7;6354:23;6350:32;6347:2;;;-1:-1;;6385:12;6347:2;-1:-1;2040:13;;6341:186;-1:-1;6341:186::o;6534:259::-;;6647:2;6635:9;6626:7;6622:23;6618:32;6615:2;;;-1:-1;;6653:12;6615:2;2185:6;2179:13;58198:5;53819:1;53808:20;58175:5;58172:33;58162:2;;-1:-1;;58209:12;6800:241;;6904:2;6892:9;6883:7;6879:23;6875:32;6872:2;;;-1:-1;;6910:12;6872:2;2320:6;2307:20;-1:-1;;;;;58322:5;53902:46;58297:5;58294:35;58284:2;;-1:-1;;58333:12;7048:241;;7152:2;7140:9;7131:7;7127:23;7123:32;7120:2;;;-1:-1;;7158:12;7120:2;-1:-1;2444:20;;7114:175;-1:-1;7114:175::o;7566:366::-;;;7687:2;7675:9;7666:7;7662:23;7658:32;7655:2;;;-1:-1;;7693:12;7655:2;-1:-1;;2444:20;;;7845:2;7884:22;;;2444:20;;-1:-1;7649:283::o;7939:582::-;;;;8111:3;8099:9;8090:7;8086:23;8082:33;8079:2;;;-1:-1;;8118:12;8079:2;2598:6;2592:13;8170:74;;8281:2;;8335:9;8331:22;2592:13;8289:74;;1176:3;1157:17;8477:9;1157:17;1153:27;1143:2;;-1:-1;;1184:12;1143:2;1237:78;8400:2;1237:78;:::i;:::-;1321:16;8400:2;8477:9;8473:22;1438:3;8111;8477:9;1409:27;1406:36;1403:2;;;-1:-1;;1445:12;1403:2;-1:-1;1465:217;1218:4;1487:1;1484:13;1465:217;;;2592:13;;1558:61;;1633:14;;;;1661;;;;1512:1;1505:9;1465:217;;;1469:14;;8408:97;;;;;;8073:448;;;;;:::o;8528:239::-;;8631:2;8619:9;8610:7;8606:23;8602:32;8599:2;;;-1:-1;;8637:12;8599:2;2734:6;2721:20;2746:32;2772:5;2746:32;:::i;12167:104::-;53492:13;53485:21;12232:34;;12226:45::o;22465:113::-;-1:-1;;;;;53902:46;22536:37;;22530:48::o;23196:100::-;-1:-1;;;;;54323:30;23255:36;;23249:47::o;23534:271::-;;12558:5;51443:12;12669:52;12714:6;12709:3;12702:4;12695:5;12691:16;12669:52;:::i;:::-;12733:16;;;;;23668:137;-1:-1;;23668:137::o;24198:222::-;-1:-1;;;;;54022:54;;;;9486:45;;24325:2;24310:18;;24296:124::o;24427:349::-;-1:-1;;;;;54022:54;;;9329:58;;54022:54;;24762:2;24747:18;;9486:45;24590:2;24575:18;;24561:215::o;24783:337::-;-1:-1;;;;;54022:54;;;;9329:58;;53492:13;53485:21;25106:2;25091:18;;12232:34;24940:2;24925:18;;24911:209::o;25127:365::-;-1:-1;;;;;54022:54;;;;9486:45;;25478:2;25463:18;;12349:37;25298:2;25283:18;;25269:223::o;25839:1326::-;-1:-1;;;;;54022:54;;;9486:45;;54022:54;;;26404:2;26389:18;;9486:45;54022:54;;;26487:2;26472:18;;9486:45;54022:54;;;26570:2;26555:18;;9486:45;54022:54;;;26653:3;26638:19;;9486:45;54022:54;;;54033:42;26722:19;;9486:45;54022:54;;;26821:3;26806:19;;9486:45;54022:54;;26905:3;26890:19;;9486:45;53492:13;;53485:21;26983:3;26968:19;;12232:34;-1:-1;;;;;54323:30;;27065:3;27050:19;;23255:36;26239:3;26224:19;;27081:74;27150:3;27135:19;;27125:7;27081:74;:::i;:::-;26210:955;;;;;;;;;;;;;;:::o;27172:432::-;-1:-1;;;;;54022:54;;;9486:45;;54022:54;;;;27513:2;27498:18;;9486:45;53492:13;;53485:21;27590:2;27575:18;;12232:34;27349:2;27334:18;;27320:284::o;27951:482::-;28184:2;28198:47;;;51443:12;;28169:18;;;52550:19;;;27951:482;;28184:2;52590:14;;;;;;50931;;;27951:482;10316:344;10341:6;10338:1;10335:13;10316:344;;;10402:13;;22194:23;;-1:-1;;;;;54323:30;;;23255:36;;22353:16;;;22347:23;54323:30;22422:14;;;23255:36;9040:14;;;;52150;;;;10363:1;10356:9;10316:344;;;-1:-1;28251:172;;28155:278;-1:-1;;;;;;;28155:278::o;28440:370::-;28617:2;28631:47;;;51443:12;;28602:18;;;52550:19;;;28440:370;;28617:2;50931:14;;;;52590;;;;28440:370;11129:260;11154:6;11151:1;11148:13;11129:260;;;11215:13;;12349:37;;52150:14;;;;9222;;;;11176:1;11169:9;11129:260;;;-1:-1;28684:116;;28588:222;-1:-1;;;;;;28588:222::o;28817:210::-;53492:13;;53485:21;12232:34;;28938:2;28923:18;;28909:118::o;29034:424::-;53492:13;;53485:21;12232:34;;54239:10;54228:22;;;29363:2;29348:18;;23148:36;54228:22;29444:2;29429:18;;23148:36;29207:2;29192:18;;29178:280::o;29465:222::-;12349:37;;;29592:2;29577:18;;29563:124::o;29694:698::-;12349:37;;;-1:-1;;;;;54022:54;;;30175:2;30160:18;;12858:76;54022:54;;30299:2;30284:18;;12858:76;5717:18;53808:20;30378:2;30363:18;;13795:35;29976:3;29961:19;;29947:445::o;30399:890::-;12349:37;;;-1:-1;;;;;54022:54;;;30947:2;30932:18;;12858:76;54022:54;;;31071:2;31056:18;;12858:76;54022:54;;;31195:2;31180:18;;12858:76;5717:18;53808:20;31274:3;31259:19;;13795:35;30749:3;30734:19;;30720:569::o;31296:1070::-;;31656:3;31645:9;31641:19;5717:18;;54033:42;;;;53302:5;54022:54;12865:3;12858:76;31847:2;54033:42;53302:5;54022:54;31847:2;31836:9;31832:18;9486:45;12379:5;31930:2;31919:9;31915:18;12349:37;12379:5;32013:2;32002:9;31998:18;12349:37;31656:3;32050;32039:9;32035:19;32028:49;32091:105;;;11637:5;51734:12;52562:6;52557:3;52550:19;52590:14;31645:9;52590:14;11649:93;;51252:3;-1:-1;51242:14;31847:2;-1:-1;51271:18;11822:21;;-1:-1;11849:288;11874:6;11871:1;11868:13;11849:288;;;57393:11;;12349:37;;11896:1;52377:14;;;;9222;;;;11889:9;11849:288;;;11853:14;;;32083:113;;;;;32207:71;32273:3;32262:9;32258:19;32249:6;32207:71;:::i;:::-;32289:67;32351:3;32340:9;32336:19;32327:6;32289:67;:::i;:::-;31627:739;;;;;;;;;;:::o;32373:712::-;-1:-1;;;;;54022:54;;;;12858:76;;32825:2;32810:18;;12349:37;;;;-1:-1;;;;;54323:30;;;32906:2;32891:18;;23255:36;54323:30;32987:2;32972:18;;23255:36;33070:3;33055:19;;12349:37;32634:3;32619:19;;32605:480::o;33092:488::-;-1:-1;;;;;54022:54;;;;12858:76;;-1:-1;;;;;54323:30;;;33485:2;33470:18;;23255:36;54323:30;33566:2;33551:18;;23255:36;33297:2;33282:18;;33268:312::o;33587:256::-;33731:2;33716:18;;57720:1;57710:12;;57700:2;;57726:9;57700:2;13649:67;;;33702:141;:::o;33850:214::-;53819:1;53808:20;;;;13795:35;;33973:2;33958:18;;33944:120::o;34071:760::-;53819:1;53808:20;;;;13795:35;;-1:-1;;;;;53902:46;;;34489:2;34474:18;;22656:50;53902:46;;;;34572:2;34557:18;;22656:50;-1:-1;;;;;54022:54;;;34655:2;34640:18;;9486:45;54022:54;;;34738:3;34723:19;;9486:45;53492:13;53485:21;54033:42;34801:19;;12232:34;34328:3;34313:19;;34299:532::o;34838:321::-;53819:1;53808:20;;;;13795:35;;-1:-1;;;;;54323:30;35145:2;35130:18;;23255:36;34987:2;34972:18;;34958:201::o;35166:310::-;;35313:2;35334:17;35327:47;14281:5;51443:12;52562:6;35313:2;35302:9;35298:18;52550:19;14375:52;14420:6;52590:14;35302:9;52590:14;35313:2;14401:5;14397:16;14375:52;:::i;:::-;57501:7;57485:14;-1:-1;;57481:28;14439:39;;;;52590:14;14439:39;;35284:192;-1:-1;;35284:192::o;35483:416::-;35683:2;35697:47;;;14715:2;35668:18;;;52550:19;-1:-1;;;52590:14;;;14731:38;14788:12;;;35654:245::o;35906:416::-;36106:2;36120:47;;;15039:2;36091:18;;;52550:19;15075:29;52590:14;;;15055:50;15124:12;;;36077:245::o;36329:416::-;36529:2;36543:47;;;15375:1;36514:18;;;52550:19;-1:-1;;;52590:14;;;15390:32;15441:12;;;36500:245::o;36752:416::-;36952:2;36966:47;;;15692:2;36937:18;;;52550:19;15728:34;52590:14;;;15708:55;-1:-1;;;15783:12;;;15776:31;15826:12;;;36923:245::o;37175:416::-;37375:2;37389:47;;;16077:2;37360:18;;;52550:19;-1:-1;;;52590:14;;;16093:33;16145:12;;;37346:245::o;37598:416::-;37798:2;37812:47;;;16396:2;37783:18;;;52550:19;16432:34;52590:14;;;16412:55;-1:-1;;;16487:12;;;16480:25;16524:12;;;37769:245::o;38021:416::-;38221:2;38235:47;;;16775:2;38206:18;;;52550:19;16811:34;52590:14;;;16791:55;-1:-1;;;16866:12;;;16859:30;16908:12;;;38192:245::o;38444:416::-;38644:2;38658:47;;;17159:2;38629:18;;;52550:19;-1:-1;;;52590:14;;;17175:36;17230:12;;;38615:245::o;38867:416::-;39067:2;39081:47;;;17481:1;39052:18;;;52550:19;-1:-1;;;52590:14;;;17496:32;17547:12;;;39038:245::o;39290:416::-;39490:2;39504:47;;;17798:2;39475:18;;;52550:19;-1:-1;;;52590:14;;;17814:36;17869:12;;;39461:245::o;39713:416::-;39913:2;39927:47;;;18120:2;39898:18;;;52550:19;-1:-1;;;52590:14;;;18136:38;18193:12;;;39884:245::o;40136:416::-;40336:2;40350:47;;;18444:2;40321:18;;;52550:19;18480:27;52590:14;;;18460:48;18527:12;;;40307:245::o;40559:416::-;40759:2;40773:47;;;18778:1;40744:18;;;52550:19;-1:-1;;;52590:14;;;18793:30;18842:12;;;40730:245::o;40982:416::-;41182:2;41196:47;;;19398:2;41167:18;;;52550:19;-1:-1;;;52590:14;;;19414:35;19468:12;;;41153:245::o;41405:416::-;41605:2;41619:47;;;19719:2;41590:18;;;52550:19;19755:34;52590:14;;;19735:55;-1:-1;;;19810:12;;;19803:30;19852:12;;;41576:245::o;41828:416::-;42028:2;42042:47;;;20103:2;42013:18;;;52550:19;-1:-1;;;52590:14;;;20119:45;20183:12;;;41999:245::o;42251:416::-;42451:2;42465:47;;;20434:2;42436:18;;;52550:19;20470:31;52590:14;;;20450:52;20521:12;;;42422:245::o;42674:416::-;42874:2;42888:47;;;20772:2;42859:18;;;52550:19;-1:-1;;;52590:14;;;20788:34;20841:12;;;42845:245::o;43097:416::-;43297:2;43311:47;;;21092:2;43282:18;;;52550:19;21128:34;52590:14;;;21108:55;-1:-1;;;21183:12;;;21176:34;21229:12;;;43268:245::o;43520:416::-;43720:2;43734:47;;;21480:2;43705:18;;;52550:19;-1:-1;;;52590:14;;;21496:34;21549:12;;;43691:245::o;43943:416::-;44143:2;44157:47;;;21800:1;44128:18;;;52550:19;-1:-1;;;52590:14;;;21815:30;21864:12;;;44114:245::o;44366:222::-;-1:-1;;;;;53902:46;;;;22656:50;;44493:2;44478:18;;44464:124::o;44595:333::-;-1:-1;;;;;53902:46;;;22536:37;;53902:46;;44914:2;44899:18;;22536:37;44750:2;44735:18;;44721:207::o;44935:556::-;-1:-1;;;;;53902:46;;;22536:37;;53902:46;;;45311:2;45296:18;;22536:37;53902:46;;;45394:2;45379:18;;22536:37;53902:46;;;45477:2;45462:18;;22536:37;45146:3;45131:19;;45117:374::o;45498:436::-;-1:-1;;;;;53902:46;;;;22536:37;;-1:-1;;;;;54323:30;;;45839:2;45824:18;;23255:36;54323:30;45920:2;45905:18;;23255:36;45677:2;45662:18;;45648:286::o;46170:748::-;12349:37;;;53819:1;53808:20;;;;46582:2;46567:18;;13795:35;54239:10;54228:22;;;;46663:2;46648:18;;23148:36;-1:-1;;;;;54323:30;;;46744:2;46729:18;;23255:36;54323:30;46825:3;46810:19;;23255:36;53492:13;53485:21;46903:3;46888:19;;12232:34;46421:3;46406:19;;46392:526::o;46925:349::-;12349:37;;;47260:2;47245:18;;13921:58;47088:2;47073:18;;47059:215::o;47621:428::-;12349:37;;;-1:-1;;;;;54323:30;;;;47958:2;47943:18;;23255:36;53492:13;53485:21;48035:2;48020:18;;12232:34;47796:2;47781:18;;47767:282::o;48056:452::-;12349:37;;;-1:-1;;;;;54323:30;;;;48405:2;48390:18;;23255:36;54436:4;54425:16;48494:2;48479:18;;14068:56;48243:2;48228:18;;48214:294::o;48515:220::-;54239:10;54228:22;;;;23018:49;;48641:2;48626:18;;48612:123::o;48742:218::-;-1:-1;;;;;54323:30;;;;23255:36;;48867:2;48852:18;;48838:122::o;48967:325::-;-1:-1;;;;;54323:30;;;23255:36;;54323:30;;49278:2;49263:18;;23255:36;49118:2;49103:18;;49089:203::o;49299:436::-;-1:-1;;;;;54323:30;;;23255:36;;54323:30;;;;49638:2;49623:18;;23255:36;49721:2;49706:18;;12349:37;;;;49478:2;49463:18;;49449:286::o;49742:214::-;54436:4;54425:16;;;;23487:35;;49865:2;49850:18;;49836:120::o;49963:256::-;50025:2;50019:9;50051:17;;;-1:-1;;;;;50111:34;;50147:22;;;50108:62;50105:2;;;50183:1;;50173:12;50105:2;50025;50192:22;50003:216;;-1:-1;50003:216::o;56828:268::-;56893:1;56900:101;56914:6;56911:1;56908:13;56900:101;;;56981:11;;;56975:18;56962:11;;;56955:39;56936:2;56929:10;56900:101;;;57016:6;57013:1;57010:13;57007:2;;;-1:-1;;56893:1;57063:16;;57056:27;56877:219::o;57749:117::-;-1:-1;;;;;54022:54;;57808:35;;57798:2;;57857:1;;57847:12;57798:2;57792:74;:::o;57873:111::-;57954:5;53492:13;53485:21;57932:5;57929:32;57919:2;;57975:1;;57965:12;58483:115;-1:-1;;;;;58568:5;54323:30;58544:5;58541:34;58531:2;;58589:1;;58579:12
Swarm Source
ipfs://4f0a0f8dfa8207815122cdcd7e302a058c41e7aa8d8ee8daf858e9b12287afea
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.206469 | 1,000 | $206.47 |
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.