More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 42 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Liquidate Bonds | 12704192 | 1227 days ago | IN | 0 ETH | 0.02828985 | ||||
Settle Tokens | 12596076 | 1244 days ago | IN | 0 ETH | 0.00125199 | ||||
Renew Maturity | 12568999 | 1248 days ago | IN | 0 ETH | 0.04984668 | ||||
Liquidate Bonds | 12568992 | 1248 days ago | IN | 0 ETH | 0.01262324 | ||||
Claim Reward | 12498581 | 1259 days ago | IN | 0 ETH | 0.00364923 | ||||
Claim Reward | 12498516 | 1259 days ago | IN | 0 ETH | 0.00345717 | ||||
Remove Liquidity | 12490101 | 1260 days ago | IN | 0 ETH | 0.0101483 | ||||
Claim Reward | 12445355 | 1267 days ago | IN | 0 ETH | 0.0098918 | ||||
Settle Tokens | 12445342 | 1267 days ago | IN | 0 ETH | 0.00275437 | ||||
Settle Tokens | 12439318 | 1268 days ago | IN | 0 ETH | 0.00363077 | ||||
Settle Tokens | 12438540 | 1268 days ago | IN | 0 ETH | 0.00279611 | ||||
Claim Reward | 12436155 | 1269 days ago | IN | 0 ETH | 0.01175316 | ||||
Settle Tokens | 12436144 | 1269 days ago | IN | 0 ETH | 0.00542529 | ||||
Claim Reward | 12434414 | 1269 days ago | IN | 0 ETH | 0.01070585 | ||||
Settle Tokens | 12434157 | 1269 days ago | IN | 0 ETH | 0.00517489 | ||||
Settle Tokens | 12433560 | 1269 days ago | IN | 0 ETH | 0.00843006 | ||||
Renew Maturity | 12433522 | 1269 days ago | IN | 0 ETH | 0.31516011 | ||||
Liquidate Bonds | 12433506 | 1269 days ago | IN | 0 ETH | 0.21551657 | ||||
Claim Reward | 12433233 | 1269 days ago | IN | 0 ETH | 0.01532865 | ||||
Remove Liquidity | 12432889 | 1269 days ago | IN | 0 ETH | 0.01182591 | ||||
Remove Liquidity | 12432744 | 1269 days ago | IN | 0 ETH | 0.00881641 | ||||
Claim Reward | 12432619 | 1269 days ago | IN | 0 ETH | 0.00537633 | ||||
Update Total Rew... | 12426022 | 1270 days ago | IN | 0 ETH | 0.00772035 | ||||
Remove Liquidity | 12424264 | 1270 days ago | IN | 0 ETH | 0.00843202 | ||||
Claim Reward | 12422122 | 1271 days ago | IN | 0 ETH | 0.00680294 |
Latest 12 internal transactions
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
12568999 | 1248 days ago | 9.3648122 ETH | ||||
12433522 | 1269 days ago | 257.24381715 ETH | ||||
12433506 | 1269 days ago | 15.71364145 ETH | ||||
12433506 | 1269 days ago | 15.71364145 ETH | ||||
12433506 | 1269 days ago | 5.77658378 ETH | ||||
12433506 | 1269 days ago | 25.56979974 ETH | ||||
12381351 | 1277 days ago | 0.01674235 ETH | ||||
12302507 | 1289 days ago | 3.3598 ETH | ||||
12298476 | 1290 days ago | 1.28794853 ETH | ||||
12297550 | 1290 days ago | 57.05226216 ETH | ||||
12297550 | 1290 days ago | 28.46919269 ETH | ||||
12269341 | 1294 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-23 */ // 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 pragma solidity ^0.7.0; /** * @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 pragma solidity 0.7.1; 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 pragma solidity 0.7.1; /** * @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 pragma solidity 0.7.1; /** * @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 pragma solidity 0.7.1; 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 pragma solidity 0.7.1; 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; pragma solidity 0.7.1; 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 pragma solidity 0.7.1; interface VolatilityOracleInterface { function getVolatility(uint64 untilMaturity) external view returns (uint64 volatilityE8); } // File: contracts/BondToken_and_GDOTC/bondPricer/Enums.sol pragma solidity 0.7.1; /** 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 pragma solidity 0.7.1; 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 pragma solidity ^0.7.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ 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 pragma solidity ^0.7.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 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 pragma solidity ^0.7.0; /** * @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 pragma solidity ^0.7.0; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {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 pragma solidity 0.7.1; 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 pragma solidity ^0.7.0; /** * @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 pragma solidity ^0.7.0; /** * @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 pragma solidity 0.7.1; /** * @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 pragma solidity 0.7.1; 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 pragma solidity 0.7.1; /** * @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 pragma solidity 0.7.1; 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 pragma solidity ^0.7.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * 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 pragma solidity 0.7.1; 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 pragma solidity 0.7.1; 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 pragma solidity 0.7.1; 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 pragma solidity 0.7.1; 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 pragma solidity ^0.7.0; /** * @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 pragma solidity 0.7.1; 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 pragma solidity 0.7.1; interface BondMakerCollateralizedEthInterface is BondMakerInterface { function issueNewBonds(uint256 bondGroupID) external payable returns (uint256 amount); } // File: contracts/BondToken_and_GDOTC/util/TransferETH.sol pragma solidity 0.7.1; 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 pragma solidity 0.7.1; 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 pragma solidity 0.7.1; 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
6101e06040526008805463ffffffff60801b19167001000000000000000000000000000000001790553480156200003557600080fd5b506040516200693738038062006937833981016040819052620000589162000652565b888888888888878760008b80806000806101000a8154816001600160a01b0302191690836001600160a01b0316021790555050846001600160a01b0316630b1a35546040518163ffffffff1660e01b815260040160206040518083038186803b158015620000c557600080fd5b505afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062c565b6001600160601b0319606091821b8116610120528a821b811660e0528b821b8116610100526001600160c01b031960c087811b919091166101a05284151560f81b6101805289831b8216905287821b81166101405286821b811660a05289821b166080526040805180820190915260018082526001600160401b038681166020840181815260048054948501815560005293517f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b9093018054945183166801000000000000000002600160401b600160801b03199484166001600160401b031996871617949094169390931790925560088054909316908816179091553390911b610160526305f5e10011801590620002285750655af3107a40006001600160401b03841611155b6200026a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200026190620007cb565b60405180910390fd5b505050505050505050506000846001600160a01b0316630b1a35546040518163ffffffff1660e01b815260040160206040518083038186803b158015620002b057600080fd5b505afa158015620002c5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002eb91906200062c565b90506000886001600160a01b031663601b45e2338d60006040518463ffffffff1660e01b8152600401620003229392919062000745565b60206040518083038186803b1580156200033b57600080fd5b505afa15801562000350573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000376919062000722565b6008805461ffff60a01b19167401000000000000000000000000000000000000000061ffff600185900b16021790556040517f78f286d90000000000000000000000000000000000000000000000000000000081529091506001600160a01b038716906378f286d990620003f790859089908f908190889060040162000769565b602060405180830381600087803b1580156200041257600080fd5b505af115801562000427573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200044d919062000613565b506040517f241d92290000000000000000000000000000000000000000000000000000000081526001600160a01b0387169063241d9229906200049c908e908e9086906001906004016200079f565b602060405180830381600087803b158015620004b757600080fd5b505af1158015620004cc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004f2919062000613565b506040517f241d92290000000000000000000000000000000000000000000000000000000081526001600160a01b0387169063241d92299062000541908e908e9086906000906004016200079f565b602060405180830381600087803b1580156200055c57600080fd5b505af115801562000571573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000597919062000613565b50604051620005a690620005e7565b604051809103906000f080158015620005c3573d6000803e3d6000fd5b5060601b6001600160601b0319166101c052506200081b9950505050505050505050565b61039380620065a483390190565b80516001600160401b03811681146200060d57600080fd5b92915050565b60006020828403121562000625578081fd5b5051919050565b6000602082840312156200063e578081fd5b81516200064b8162000802565b9392505050565b60008060008060008060008060006101208a8c03121562000671578485fd5b89516200067e8162000802565b60208b0151909950620006918162000802565b60408b0151909850620006a48162000802565b60608b0151909750620006b78162000802565b60808b0151909650620006ca8162000802565b60a08b0151909550620006dd8162000802565b60c08b0151909450620006f08162000802565b9250620007018b60e08c01620005f5565b9150620007138b6101008c01620005f5565b90509295985092959850929598565b60006020828403121562000734578081fd5b81518060010b81146200064b578182fd5b6001600160a01b039384168152919092166020820152901515604082015260600190565b6001600160a01b03958616815293851660208501529184166040840152909216606082015260019190910b608082015260a00190565b6001600160a01b03948516815292909316602083015260010b6040820152901515606082015260800190565b6020808252600c908201527f4f7574206f662072616e67650000000000000000000000000000000000000000604082015260600190565b6001600160a01b03811681146200081857600080fd5b50565b60805160601c60a05160601c60c05160601c60e05160601c6101005160601c6101205160601c6101405160601c6101605160601c6101805160f81c6101a05160c01c6101c05160601c615b9862000a0c6000398061198a5280612bd652806141f152508061164d528061410d528061414b528061418a52508061162b5280611c895280612b335280612d8052806136a05280613847525080610c5f5280611609528061271c5280612aef5250806115e75280612e07528061379a52508061083c5280610ead528061151b5280611c575280611db352806121445280612e365280612edd52806137c75280613ad65280613c225280613d1652806142d55280614365528061456352806147615280614a98525080610c815280610f82528061104652806115a352806118a65280611b425280612b115280612c94525080610fa452806110685280611111528061158152806130da5250806115c55280612004525080610d4c5280610dda5280610e7d5280610f53528061101552806110dc528061155f5280611d10528061224552806122d45280612fa1528061443f52806144df528061463d52806146dd528061483b52806148db525080610c32528061153d5280611c2a52806125a85280612a9d5280612bff5280612d455280613665528061388b528061395a5250615b986000f3fe60806040526004361061024a5760003560e01c806392da91ad11610139578063b88a802f116100b6578063dd62ed3e1161007a578063dd62ed3e146106f4578063e0e54dec14610714578063e627f2db14610734578063e8078d9414610756578063ef4498ff1461075e578063fde6fad91461077e5761028d565b8063b88a802f14610673578063c82e377814610688578063cc4df8ae146106aa578063d28f3330146106bf578063d3339533146106d45761028d565b80639a8fac74116100fd5780639a8fac74146105e0578063a3a40ea5146105f5578063a3dd261914610617578063a9059cbb1461063e578063ae1162561461065e5761028d565b806392da91ad1461055257806395d89b41146105725780639649a73714610587578063979c6fe61461059c5780639960d742146105cb5761028d565b80633beeae20116101c75780635a9b0b891161018b5780635a9b0b89146104855780636c13ba78146104b157806370a08231146104e15780638417cb13146105015780638c5301c0146105235761028d565b80633beeae20146103d257806344a040f5146103e75780634759898f146104145780634fac075b14610436578063506718ef146104655761028d565b806318160ddd1161020e57806318160ddd1461035157806323b872dd146103665780632e20da2714610386578063313ce5671461039b578063315deeaa146103bd5761028d565b806302ecdef21461029257806306fdde03146102a9578063095ea7b3146102d45780630dad4e4b1461030157806315e524871461032e5761028d565b3661028d57604051309033907fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9061028390349061532b565b60405180910390a3005b600080fd5b34801561029e57600080fd5b506102a76107ac565b005b3480156102b557600080fd5b506102be610914565b6040516102cb9190615503565b60405180910390f35b3480156102e057600080fd5b506102f46102ef366004614eb8565b610945565b6040516102cb9190615302565b34801561030d57600080fd5b5061032161031c366004614e8b565b6109e9565b6040516102cb919061532b565b34801561033a57600080fd5b50610343610abe565b6040516102cb9291906159e7565b34801561035d57600080fd5b50610321610aed565b34801561037257600080fd5b506102f4610381366004614e4b565b610b26565b34801561039257600080fd5b506102a7610c18565b3480156103a757600080fd5b506103b0611199565b6040516102cb9190615a9b565b3480156103c957600080fd5b5061032161119e565b3480156103de57600080fd5b506102a76111c5565b3480156103f357600080fd5b50610407610402366004614df7565b611447565b6040516102cb9190615a49565b34801561042057600080fd5b506104296114b3565b6040516102cb9190615493565b34801561044257600080fd5b50610456610451366004615051565b6114b8565b6040516102cb9392919061530d565b34801561047157600080fd5b50610321610480366004615051565b6114f7565b34801561049157600080fd5b5061049a611519565b6040516102cb9b9a999897969594939291906151be565b3480156104bd57600080fd5b506104d16104cc366004614df7565b61167e565b6040516102cb9493929190615953565b3480156104ed57600080fd5b506103216104fc366004614df7565b6116c5565b34801561050d57600080fd5b506105166116e9565b6040516102cb919061515c565b34801561052f57600080fd5b5061054361053e366004614df7565b6116ee565b6040516102cb9392919061597e565b34801561055e57600080fd5b506102f461056d36600461502a565b61172e565b34801561057e57600080fd5b506102be611848565b34801561059357600080fd5b50610321611868565b3480156105a857600080fd5b506105bc6105b7366004615051565b611948565b6040516102cb93929190615a77565b3480156105d757600080fd5b50610516611988565b3480156105ec57600080fd5b506102f46119ac565b34801561060157600080fd5b5061060a6119bd565b6040516102cb919061547f565b34801561062357600080fd5b5061062c611a77565b6040516102cb969594939291906159a8565b34801561064a57600080fd5b506102f4610659366004614eb8565b611abd565b34801561066a57600080fd5b506102a7611acd565b34801561067f57600080fd5b506102a7611ed9565b34801561069457600080fd5b5061069d61202b565b6040516102cb91906152be565b3480156106b657600080fd5b5061034361208e565b3480156106cb57600080fd5b506102a76120b4565b3480156106e057600080fd5b506103216106ef366004615069565b61253a565b34801561070057600080fd5b5061032161070f366004614e13565b612557565b34801561072057600080fd5b5061032161072f366004615069565b61258b565b34801561074057600080fd5b50610749612665565b6040516102cb9190615262565b6102f46126db565b34801561076a57600080fd5b506102a7610779366004615104565b612711565b34801561078a57600080fd5b5061079e610799366004615051565b612842565b6040516102cb929190615939565b6007546107d45760405162461bcd60e51b81526004016107cb90615870565b60405180910390fd5b60085460075460001901600090815260016020526040902054600160801b90910463ffffffff16906001600160401b0316806108225760405162461bcd60e51b81526004016107cb90615809565b6040516301e5ddfb60e71b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f2eefd8090610871908690600401615a38565b60006040518083038186803b15801561088957600080fd5b505afa15801561089d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108c59190810190614f2b565b915050816001600160401b031681106109035750506008805463ffffffff909216600160801b0263ffffffff60801b19909216919091179055610912565b60018301925050610822565b50505b565b604051806040016040528060158152602001744c49454e5f41474752454741544f525f534841524560581b81525081565b600060001982141561095c576001600160801b0391505b61096582612879565b336000818152600c602090815260408083206001600160a01b03891680855292529182902080546001600160801b0319166001600160801b039590951694909417909355517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906109d790869061532b565b60405180910390a35060015b92915050565b6001600160a01b0382166000908152600b60209081526040808320546009909252909120546001600160801b0391821691600160801b90910416156109e35733600090815260096020526040902054600754600193506001600160801b0390911610156109e357336000818152600960208181526040808420546001600160801b0380821660010181168652600684529185205495909452919052610ab792610ab092600160801b91829004831692610aaa92909104166305f5e1006128a2565b906128dc565b600161291e565b0192915050565b6007546000908152600d6020908152604080832054600e909252909120546001600160801b0391821691169091565b6007546000908152600e60209081526040808320546006909252822054610b20916001600160801b039182169116612942565b90505b90565b6001600160a01b0383166000908152600c602090815260408083203384529091528120546001600160801b031682811015610b65576000915050610c11565b6001600160801b0381811614610bf7576001600160a01b0385166000908152600c60209081526040808320338452909152902054610bb590610bb0906001600160801b031685612942565b612879565b6001600160a01b0386166000908152600c60209081526040808320338452909152902080546001600160801b0319166001600160801b03929092169190911790555b610c0a8585610c0586612879565b612984565b5060019150505b9392505050565b60405163300da2f160e11b81526000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063601b45e290610cab907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000000090869060040161523e565b60206040518083038186803b158015610cc357600080fd5b505afa158015610cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfb9190615009565b90506103e88160010b13158015610d16575060058160010b12155b610d325760405162461bcd60e51b81526004016107cb9061571c565b6040516311ed607760e01b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906311ed607790610d8490309060019060040161518a565b60206040518083038186803b158015610d9c57600080fd5b505afa158015610db0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd49190614ff1565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166311ed60773060006040518363ffffffff1660e01b8152600401610e2792919061518a565b60206040518083038186803b158015610e3f57600080fd5b505afa158015610e53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e779190614ff1565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663488abbfc307f00000000000000000000000000000000000000000000000000000000000000006040518363ffffffff1660e01b8152600401610ee9929190615170565b60206040518083038186803b158015610f0157600080fd5b505afa158015610f15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f399190614ff1565b604051631711ddb160e21b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690635c4776c490610fce9086907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908a90600401615334565b600060405180830381600087803b158015610fe857600080fd5b505af1158015610ffc573d6000803e3d6000fd5b5050604051631711ddb160e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169250635c4776c491506110929085907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000908a90600401615334565b600060405180830381600087803b1580156110ac57600080fd5b505af11580156110c0573d6000803e3d6000fd5b5050600054604051630ccb63b760e41b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116945063ccb63b70935061113d9286929116907f00000000000000000000000000000000000000000000000000000000000000009081908b9060040161535c565b600060405180830381600087803b15801561115757600080fd5b505af115801561116b573d6000803e3d6000fd5b50506008805460019790970b61ffff16600160a01b0261ffff60a01b19909716969096179095555050505050565b600881565b6007546000908152600d6020526040812054610b20903031906001600160801b0316612942565b6007546000818152600e602090815260408083205460059092528220549192839290916001600160801b031690600160401b900460ff1680611205575081155b6112215760405162461bcd60e51b81526004016107cb90615536565b6000828152600660205260409020546001600160801b031680156112a657600061124961119e565b9050611260610ab083610aaa846305f5e1006128a2565b6000858152600d602052604090205490955061129e90869061128f906001600160801b03166305f5e1006128a2565b8161129657fe5b04600161291e565b9550506112f0565b6000838152600d60205260409020546001600160801b0316156112f0576000838152600d60205260409020546112e6906001600160801b0316600161291e565b94506305f5e10093505b8085016112fc85612879565b60018501600090815260066020526040902080546001600160801b03928316600160801b029216919091179055611340610bb08461133a858a612a40565b90612942565b60018501600090815260066020526040902080546001600160801b0319166001600160801b0392831617908190556c2af31dc4611873bf3f70834acd91161115611398576008805460ff60b01b1916600160b01b1790555b83156113a6576113a6612a65565b6000811180156113b65750600083115b156113c4576113c485612b95565b6113cc612bfb565b6113d7600754613151565b6008546007546000908152600160208190526040918290205491516001600160401b03948516947fb6468ad5c9ad279cc97382791cf54035b2adbdc6126bee312967c4fdbb9a56da9461143794600160a01b90910490930b9216906154e7565b60405180910390a2505050505050565b6001600160a01b0381166000908152600b60209081526040808320815160608101835290546001600160801b03811682526001600160401b03600160801b8204811694830194909452600160c01b9004909216908201526007546114ab9190613176565b90505b919050565b601290565b60008080836114c75760075493505b50505060009081526005602052604090205460ff600160401b8204169163ffffffff600160201b83048116921690565b600090815260066020526040902054600160801b90046001600160801b031690565b7f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906c2af31dc4611873bf3f70834acd90565b6001600160a01b0316600090815260096020908152604080832054600a909252909120546001600160801b0380831693600160801b93849004821693828416930490911690565b6001600160a01b03166000908152600b60205260409020546001600160801b031690565b600090565b6001600160a01b03166000908152600b60205260409020546001600160801b038116916001600160401b03600160c01b8304811692600160801b90041690565b600080600061173b613309565b600754336000908152600a60205260409020549295509093509150600160801b90046001600160801b031661179357336000908152600a6020526040902080546001600160801b0319166001600160801b0383161790555b336000818152600a6020908152604080832080546001600160801b03600160801b80830482168d0182160291811691909117909155858452600e9092529091208054808316890183166001600160801b0319919091161790556117fb919085908816856134c1565b80336001600160a01b03167f3518f79326efc4570db0ebb1195252c857df4c2beb5932ab886faa94251a50e0876040516118359190615925565b60405180910390a3506001949350505050565b6040518060400160405280600481526020016309882a6960e31b81525081565b6007546000908152600160205260408120546001600160401b03164211156118a25760405162461bcd60e51b81526004016107cb90615600565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156118ff57600080fd5b505af1158015611913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119379190614ff1565b905061194281613646565b91505090565b60008080836119575760075493505b505050600090815260016020819052604090912080549101546001600160401b0380831693600160401b9093041691565b7f000000000000000000000000000000000000000000000000000000000000000090565b600854600160b01b900460ff161590565b6000600754600014156119d257506000610b23565b6007546000908152600160205260409020546001600160401b03164211611a22576008546001600160401b03600160401b909104166203f480014211611a1a57506002610b23565b506001610b23565b6007546000908152600160205260409020546001600160401b031642118015611a645750600754600090815260056020526040902054600160401b900460ff16155b15611a7157506003610b23565b50600490565b6007546008549091600160a01b820460010b91600160801b810463ffffffff16916001600160401b0380831692600160401b810490911691600160b01b90910460ff1690565b6000610c113384610c0585612879565b6007546000908152600160205260409020546001600160401b0316421115611b075760405162461bcd60e51b81526004016107cb90615600565b6008546001600160401b03600160401b909104166203f480014211611b3e5760405162461bcd60e51b81526004016107cb90615596565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611b9b57600080fd5b505af1158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd39190614ff1565b90506000611be08261393b565b905080611bf357611bf082613646565b90505b600080611bfe614db9565b6007546000908152600260205260409081902060085491516329069bdd60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016926329069bdd92611cb1927f00000000000000000000000000000000000000000000000000000000000000009230928b928d926001600160401b0316907f00000000000000000000000000000000000000000000000000000000000000009060040161538d565b60806040518083038186803b158015611cc957600080fd5b505afa158015611cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d01919061508a565b919450925090508115611d83577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663439370b1836040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d6957600080fd5b505af1158015611d7d573d6000803e3d6000fd5b50505050505b8215611d9357611d938484613ad4565b602081015115611e5c578051602082015160405163b9601d7760e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169263b9601d7792611dee926004016159e7565b602060405180830381600087803b158015611e0857600080fd5b505af1158015611e1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e409190614fd5565b611e5c5760405162461bcd60e51b81526004016107cb9061577c565b611e6542613151565b6008805467ffffffffffffffff60401b1916600160401b6001600160401b039384160217905581516020830151604051918316928716917f2eaafc32eed9e5ff41c1b57ddd1ef894ec4eb7499efb581d50edffa27f6af23291611eca91889190615a5d565b60405180910390a35050505050565b611ee1614dd7565b50336000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b900490911691810191909152600754611f42908290613176565b6001600160401b03908116602083018190526007549091166040830152611f7b5760405162461bcd60e51b81526004016107cb906156d2565b60208181018051600080835233808252600b909452604090819020855181549451928701516001600160801b03199095166001600160801b039091161767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b9483169490940293909317909255169061090f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169083613b9a565b60075460009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561208457602002820191906000526020600020905b815481526020019060010190808311612070575b5050505050905090565b600080600061209b613309565b919450925090506120af33836000846134c1565b509091565b6007546000908152600160205260409020546001600160401b031642116120ed5760405162461bcd60e51b81526004016107cb906158df565b600754600081815260056020526040902054600160401b900460ff16156121265760405162461bcd60e51b81526004016107cb90615904565b60008181526005602052604090205463ffffffff166121ff576121d87f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ac3fd8866040518163ffffffff1660e01b815260040160206040518083038186803b15801561219b57600080fd5b505afa1580156121af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d39190614ff1565b613bf5565b6000828152600560205260409020805463ffffffff191663ffffffff929092169190911790555b6000818152600160205260408082205460001984018352818320549151631c1b06f760e11b8152839283926001600160401b039081169291169083906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906338360dee9061227a90309060040161515c565b60206040518083038186803b15801561229257600080fd5b505afa1580156122a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ca9190614ff1565b90508015612346577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a0ef91df6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561232d57600080fd5b505af1158015612341573d6000803e3d6000fd5b505050505b50600086815260056020526040902054600160201b900463ffffffff1661237e57600854600160801b900463ffffffff16935061239d565b600086815260056020526040902054600160201b900463ffffffff1693505b600086815260056020526040902054603263ffffffff91821686900390911611156123ff576000868152600560205260409020805463ffffffff60328701908116600160201b0267ffffffff0000000019909216919091179091559450612417565b60008681526005602052604090205463ffffffff1694505b63ffffffff84165b8563ffffffff168110156124c25761243981858585613c1a565b935060098463ffffffff1611156124ba576001860363ffffffff1681141561247f576000878152600560205260409020805460ff60401b1916600160401b1790556124ae565b6000878152600560205260409020805467ffffffff000000001916600160201b6001840163ffffffff16021790555b50505050505050610912565b60010161241f565b5060008681526005602052604090205463ffffffff86811691161415612506576000868152600560205260409020805460ff60401b1916600160401b179055612532565b6000868152600560205260409020805467ffffffff000000001916600160201b63ffffffff8816021790555b505050505050565b600091825260036020908152604080842092845291905290205490565b6001600160a01b039182166000908152600c602090815260408083209390941682529190915220546001600160801b031690565b6008546040516351d19dc760e11b81526000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a3a33b8e916125ea9186916001600160401b031690600190600401615a16565b60206040518083038186803b15801561260257600080fd5b505afa158015612616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263a9190614ff1565b9150826126475760075492505b50600091825260036020908152604080842092845291905290205490565b60606004805480602002602001604051908101604052809291908181526020016000905b828210156126d257600084815260209081902060408051808201909152908401546001600160401b038082168352600160401b9091041681830152825260019092019101612689565b50505050905090565b600854600090600160b01b900460ff16156127085760405162461bcd60e51b81526004016107cb906156f5565b610b2034613df2565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146127595760405162461bcd60e51b81526004016107cb906156ab565b6007546127785760405162461bcd60e51b81526004016107cb90615870565b6305f5e1006001600160401b038216108015906127a45750655af3107a40006001600160401b03821611155b6127c05760405162461bcd60e51b81526004016107cb9061579d565b600460405180604001604052806127d8600754613151565b60019081016001600160401b03908116835294851660209283015283549081018455600093845292819020825193018054929091015167ffffffffffffffff199092169284169290921767ffffffffffffffff60401b1916600160401b9190931602919091179055565b600080826128505760075492505b50506000908152600660205260409020546001600160801b0380821692600160801b9092041690565b6000600160801b821061289e5760405162461bcd60e51b81526004016107cb906155b9565b5090565b6000826128b1575060006109e3565b828202828482816128be57fe5b0414610c115760405162461bcd60e51b81526004016107cb90615624565b6000610c1183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613f0c565b6000811561293457506402540be40082046109e3565b506402540be40082026109e3565b6000610c1183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613f43565b6001600160a01b0383166000908152600b60205260408120546001600160801b03808416911610156129b857506000610c11565b6129cf84836001600160801b031660001902613f6f565b6129e283836001600160801b0316613f6f565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846001600160801b0316604051612a2e919061532b565b60405180910390a35060019392505050565b600082820183811015610c115760405162461bcd60e51b81526004016107cb9061555f565b6008546007546000818152600660205260408082205460019384018352918190205490516379b347db60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016946379b347db94612b5b94600160a01b909204900b926001600160801b03600160801b928390048116939290910416907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000907f0000000000000000000000000000000000000000000000000000000000000000906004016154a1565b600060405180830381600087803b158015612b7557600080fd5b505af1158015612b89573d6000803e3d6000fd5b50505050610912610c18565b6007546000908152600e6020526040812054612bcf90612bc8906305f5e10090610aaa906001600160801b0316866128a2565b600061291e565b905061090f7f0000000000000000000000000000000000000000000000000000000000000000826140d8565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663ca579d0a6040518163ffffffff1660e01b815260040160206040518083038186803b158015612c5657600080fd5b505afa158015612c6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c8e9190614ff1565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612ced57600080fd5b505af1158015612d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d259190614ff1565b600854604051637298096d60e11b81529192506000916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163e53012da91612da89186916001600160401b03909116907f0000000000000000000000000000000000000000000000000000000000000000906004016159f5565b60206040518083038186803b158015612dc057600080fd5b505afa158015612dd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612df89190614ff1565b9050612e03826140fb565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a38593887f0000000000000000000000000000000000000000000000000000000000000000612e5e85613151565b612e6788613151565b6040518463ffffffff1660e01b8152600401612e8593929190615455565b602060405180830381600087803b158015612e9f57600080fd5b505af1158015612eb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed79190614ff1565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326d6c97b836040518263ffffffff1660e01b8152600401612f27919061532b565b60806040518083038186803b158015612f3f57600080fd5b505afa158015612f53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f779190614ee3565b505060405163095ea7b360e01b8152919250506001600160a01b0382169063095ea7b390612fcd907f000000000000000000000000000000000000000000000000000000000000000090600019906004016151a5565b602060405180830381600087803b158015612fe757600080fd5b505af1158015612ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061301f9190614fd5565b50600780546001019055613031614dd7565b604051806060016040528061304588613151565b6001600160401b0316815260200161305c86613151565b6001600160401b039081168252602091820186905260075460009081526001808452604091829020855181549587015167ffffffffffffffff199096169085161767ffffffffffffffff60401b1916600160401b959094169490940292909217835583810151929091019190915551631d3b07f760e21b81529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906374ec1fdc9061311790899060040161532b565b600060405180830381600087803b15801561313157600080fd5b505af1158015613145573d6000803e3d6000fd5b50505050505050505050565b6000600160401b821061289e5760405162461bcd60e51b81526004016107cb90615665565b602082015182516001600160801b0316158015906131a057508183604001516001600160401b0316105b156109e357600480546000198101916000916001600160401b0384169081106131c557fe5b6000918252602082200154600480546001600160401b039283169450909185169081106131ee57fe5b600091825260209091200154600160401b90046001600160401b03169050845b86604001516001600160401b03168111156132ff57826001600160401b03168110156132a1576001840393506004846001600160401b03168154811061325057fe5b9060005260206000200160000160089054906101000a90046001600160401b031691506004846001600160401b03168154811061328957fe5b6000918252602090912001546001600160401b031692505b60008181526006602052604090205487516132f4916132ef916132df916001600160801b0390811691610aaa916001600160401b03891691166128a2565b6001600160401b03881690612a40565b613151565b94506000190161320e565b5050505092915050565b600754336000908152600a602090815260408083205460099092528220549192839283926001600160801b0380821692600160801b92839004821692818316929104168461336657600080600097509750975050505050506134bc565b6001600160801b038316158015906133865750836001600160801b031685115b156133ef576001600160801b036001850181166000908152600660205260409020546133cc91612bc8916305f5e10091610aaa9188821691600160801b909104166128a2565b975087156133de576133de33896141da565b336000908152600a60205260408120555b6001600160801b0381161580159061340f5750816001600160801b031685115b15613472576001600160801b0360018301811660009081526006602052604090205461345391610ab091600160801b9004811690610aaa9085166305f5e1006128a2565b3360009081526009602052604081205596506001600160801b03821695505b84336001600160a01b03167fb11715e80d7e8d99a84fdd2112e0c3b821523d7416cb2082ec62d76c76f6f0168a8a6040516134ae9291906159e7565b60405180910390a350505050505b909192565b6134c9614dd7565b506001600160a01b0384166000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b9004909116918101919091528315613571576135358183613176565b6001600160401b03908116602083015282166040820152805161356590610bb0906001600160801b031686612a40565b6001600160801b031681525b61357d81600754613176565b6001600160401b03908116602083015260075416604082015282156135c15780516135b590610bb0906001600160801b031685612942565b6001600160801b031681525b6001600160a01b03949094166000908152600b6020908152604091829020865181549288015193909701516001600160801b03199092166001600160801b039097169690961767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b929091169190910217909355505050565b60085460405163a072a3e560e01b815260009182916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a072a3e5916136c89187916001600160401b03909116907f0000000000000000000000000000000000000000000000000000000000000000906004016159f5565b60206040518083038186803b1580156136e057600080fd5b505afa1580156136f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137189190614ff1565b600754909150613726614dd7565b50600081815260016020818152604092839020835160608101855281546001600160401b038082168352600160401b9091041692810183905292015492820192909252906137749084614256565b602082015182516040808501519051635b1caa5760e11b81529396506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169363b63954ae936137f1937f0000000000000000000000000000000000000000000000000000000000000000938a9360040161541e565b602060405180830381600087803b15801561380b57600080fd5b505af115801561381f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138439190614ff1565b93507f0000000000000000000000000000000000000000000000000000000000000000156139295760085460405163a072a3e560e01b81526139249186916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a072a3e5916138cf918b916001600160401b03909116906000906004016159f5565b60206040518083038186803b1580156138e757600080fd5b505afa1580156138fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061391f9190614ff1565b614280565b613933565b6139338484614280565b505050919050565b6008546040516351d19dc760e11b815260009182916001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a3a33b8e9161399e9187916001600160401b0390911690600190600401615a16565b60206040518083038186803b1580156139b657600080fd5b505afa1580156139ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139ee9190614ff1565b600754600090815260036020908152604080832084845291829052909120549192509015613a2a576000918252602052604090205490506114ae565b60015b60028111613933576008546001600160401b03168102830360009081526020839052604090205415613a80576008546001600160401b0316029091036000908152602091909152604090205490506114ae565b6008546001600160401b03168102830160009081526020839052604090205415613acc576008546001600160401b031602919091016000908152602091909152604090205490506114ae565b600101613a2d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b038116638376c24d613b256103e8610aaa6103ea613b1f886402540be4006128a2565b906128a2565b856040518363ffffffff1660e01b8152600401613b42919061532b565b6020604051808303818588803b158015613b5b57600080fd5b505af1158015613b6f573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613b949190614ff1565b50505050565b613bf08363a9059cbb60e01b8484604051602401613bb99291906151a5565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614962565b505050565b6000600160201b821061289e5760405162461bcd60e51b81526004016107cb906157c3565b6000606060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f2eefd80886040518263ffffffff1660e01b8152600401613c6c919061532b565b60006040518083038186803b158015613c8457600080fd5b505afa158015613c98573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613cc09190810190614f2b565b91509150846001600160401b0316811180613cf65750836001600160401b031681108015613cf657506001600160401b03841615155b15613d05578592505050613dea565b6000805b8351811015613de25760007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326d6c97b868481518110613d4f57fe5b60200260200101516040518263ffffffff1660e01b8152600401613d73919061532b565b60806040518083038186803b158015613d8b57600080fd5b505afa158015613d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613dc39190614ee3565b5050509050613dd48a828b866149f1565b909950925050600101613d09565b508693505050505b949350505050565b6000806000613dff613309565b9250925050613e1133836000846134c1565b60075433600090815260096020526040902054600160801b90046001600160801b0316613e615733600090815260096020526040902080546001600160801b0319166001600160801b0383161790555b613e6a85612879565b33600090815260096020526040902080546001600160801b03600160801b808304821690940181169093029216919091179055613ea685612879565b6000828152600d60205260409081902080546001600160801b031981166001600160801b0391821694909401169290921790915551819033907f4c86739b331ba35e12897451019b4a8cca47a228be900c18ab3a8ffa5dfe7e539061183590899061532b565b60008183613f2d5760405162461bcd60e51b81526004016107cb9190615503565b506000838581613f3957fe5b0495945050505050565b60008184841115613f675760405162461bcd60e51b81526004016107cb9190615503565b505050900390565b613f77614dd7565b506001600160a01b0382166000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b900490911691810191909152600754613fe1908290613176565b6001600160401b039081166020830152600754166040820152600082121561403057805161402090610bb0906001600160801b03166000859003612942565b6001600160801b03168152614055565b805161404990610bb0906001600160801b031684612a40565b6001600160801b031681525b6001600160a01b03929092166000908152600b6020908152604091829020845181549286015193909501516001600160801b03199092166001600160801b039095169490941767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b92909116919091021790915550565b61090f82826040518060600160405280602c8152602001615b37602c9139614bb0565b6000614133826001600160401b0360327f000000000000000000000000000000000000000000000000000000000000000002166128dc565b90508061417b576008805467ffffffffffffffff19167f00000000000000000000000000000000000000000000000000000000000000006001600160401b031617905561090f565b6141b5600a6001600160401b037f000000000000000000000000000000000000000000000000000000000000000016830260190204613151565b6008805467ffffffffffffffff19166001600160401b03929092169190911790555050565b60405163ed3de48760e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ed3de4879061422890859085906004016151a5565b600060405180830381600087803b15801561424257600080fd5b505af1158015612532573d6000803e3d6000fd5b6000610c116002614270846001600160401b038716612942565b8161427757fe5b84919006612942565b60078054600090815260026020908152604080832080546001810182559084528284200186905592548252600381528282208483529052819020839055516301e5ddfb60e71b81526060906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f2eefd809061430a90869060040161532b565b60006040518083038186803b15801561432257600080fd5b505afa158015614336573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261435e9190810190614f2b565b50905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326d6c97b8360018151811061439f57fe5b60200260200101516040518263ffffffff1660e01b81526004016143c3919061532b565b60806040518083038186803b1580156143db57600080fd5b505afa1580156143ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144139190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906144679030907f000000000000000000000000000000000000000000000000000000000000000090600401615170565b60206040518083038186803b15801561447f57600080fd5b505afa158015614493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144b79190614ff1565b61455f5760405163095ea7b360e01b81526001600160a01b0382169063095ea7b39061450b907f000000000000000000000000000000000000000000000000000000000000000090600019906004016151a5565b602060405180830381600087803b15801561452557600080fd5b505af1158015614539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061455d9190614fd5565b505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326d6c97b8460028151811061459d57fe5b60200260200101516040518263ffffffff1660e01b81526004016145c1919061532b565b60806040518083038186803b1580156145d957600080fd5b505afa1580156145ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146119190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906146659030907f000000000000000000000000000000000000000000000000000000000000000090600401615170565b60206040518083038186803b15801561467d57600080fd5b505afa158015614691573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146b59190614ff1565b61475d5760405163095ea7b360e01b81526001600160a01b0382169063095ea7b390614709907f000000000000000000000000000000000000000000000000000000000000000090600019906004016151a5565b602060405180830381600087803b15801561472357600080fd5b505af1158015614737573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061475b9190614fd5565b505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166326d6c97b8560038151811061479b57fe5b60200260200101516040518263ffffffff1660e01b81526004016147bf919061532b565b60806040518083038186803b1580156147d757600080fd5b505afa1580156147eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061480f9190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906148639030907f000000000000000000000000000000000000000000000000000000000000000090600401615170565b60206040518083038186803b15801561487b57600080fd5b505afa15801561488f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148b39190614ff1565b6125325760405163095ea7b360e01b81526001600160a01b0382169063095ea7b390614907907f000000000000000000000000000000000000000000000000000000000000000090600019906004016151a5565b602060405180830381600087803b15801561492157600080fd5b505af1158015614935573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149599190614fd5565b50505050505050565b60606149b7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614ca69092919063ffffffff16565b805190915015613bf057808060200190518101906149d59190614fd5565b613bf05760405162461bcd60e51b81526004016107cb90615895565b6040516370a0823160e01b81526000908190859082906001600160a01b038316906370a0823190614a2690309060040161515c565b60206040518083038186803b158015614a3e57600080fd5b505afa158015614a52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a769190614ff1565b1115614ba35783614b28576040516301bc8ef560e61b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636f23bd4090614ad0908a906000906004016159e7565b602060405180830381600087803b158015614aea57600080fd5b505af1158015614afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b229190614ff1565b50600193505b806001600160a01b0316639975038c6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614b6357600080fd5b505af1158015614b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b9b9190614ff1565b506001850194505b5092959194509092505050565b614bb982614cb5565b8190614bd85760405162461bcd60e51b81526004016107cb9190615503565b506000836001600160a01b031683604051614bf290610b23565b60006040518083038185875af1925050503d8060008114614c2f576040519150601f19603f3d011682016040523d82523d6000602084013e614c34565b606091505b5050905080614c555760405162461bcd60e51b81526004016107cb90615745565b836001600160a01b0316306001600160a01b03167fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c85604051614c98919061532b565b60405180910390a350505050565b6060613dea8484600085614cbc565b3031101590565b6060614cc785614d80565b614ce35760405162461bcd60e51b81526004016107cb90615839565b60006060866001600160a01b03168587604051614d009190615140565b60006040518083038185875af1925050503d8060008114614d3d576040519150601f19603f3d011682016040523d82523d6000602084013e614d42565b606091505b50915091508115614d56579150613dea9050565b805115614d665780518082602001fd5b8360405162461bcd60e51b81526004016107cb9190615503565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590613dea575050151592915050565b60405180604001604052806002906020820280368337509192915050565b604080516060810182526000808252602082018190529181019190915290565b600060208284031215614e08578081fd5b8135610c1181615afb565b60008060408385031215614e25578081fd5b8235614e3081615afb565b91506020830135614e4081615afb565b809150509250929050565b600080600060608486031215614e5f578081fd5b8335614e6a81615afb565b92506020840135614e7a81615afb565b929592945050506040919091013590565b60008060408385031215614e9d578182fd5b8235614ea881615afb565b91506020830135614e4081615b13565b60008060408385031215614eca578182fd5b8235614ed581615afb565b946020939093013593505050565b60008060008060808587031215614ef8578081fd5b8451614f0381615afb565b602086015160408701519195509350614f1b81615b21565b6060959095015193969295505050565b60008060408385031215614f3d578182fd5b82516001600160401b0380821115614f53578384fd5b818501915085601f830112614f66578384fd5b815181811115614f74578485fd5b60209150818102614f86838201615aa9565b8281528381019085850183870186018b1015614fa0578889fd5b8896505b84871015614fc2578051835260019690960195918501918501614fa4565b5097909301519698969750505050505050565b600060208284031215614fe6578081fd5b8151610c1181615b13565b600060208284031215615002578081fd5b5051919050565b60006020828403121561501a578081fd5b81518060010b8114610c11578182fd5b60006020828403121561503b578081fd5b81356001600160801b0381168114610c11578182fd5b600060208284031215615062578081fd5b5035919050565b6000806040838503121561507b578182fd5b50508035926020909101359150565b60008060006080848603121561509e578081fd5b83519250602080850151925085605f8601126150b8578182fd5b6150c26040615aa9565b8060408701886080890111156150d6578485fd5b845b60028110156150f5578151845292840192908401906001016150d8565b50508093505050509250925092565b600060208284031215615115578081fd5b8135610c1181615b21565b15159052565b6001600160801b03169052565b6001600160401b03169052565b60008251615152818460208701615acf565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b038c811682528b811660208301528a811660408301528981166060830152888116608083015287811660a083015286811660c0830152851660e08201528315156101008201526001600160401b038316610120820152610160810161522e610140830184615126565b9c9b505050505050505050505050565b6001600160a01b039384168152919092166020820152901515604082015260600190565b602080825282518282018190526000919060409081850190868401855b828110156152b157815180516001600160401b039081168652908701511686850152928401929085019060010161527f565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156152f6578351835292840192918401916001016152da565b50909695505050505050565b901515815260200190565b921515835263ffffffff918216602084015216604082015260600190565b90815260200190565b9384526001600160a01b0392831660208501529116604083015260010b606082015260800190565b9485526001600160a01b0393841660208601529183166040850152909116606083015260010b608082015260a00190565b600060e0820160018060a01b03808b1684526020818b168186015289604086015288606086015260e060808601528291508754808452610100860192508885528185209350845b818110156153f0578454845260019485019493830193016153d4565b505050809250505061540560a0830185615133565b61541260c0830184615120565b98975050505050505050565b6001600160a01b0395909516855260208501939093526001600160401b039182166040850152166060830152608082015260a00190565b6001600160a01b039390931683526001600160401b03918216602084015216604082015260600190565b602081016005831061548d57fe5b91905290565b60019190910b815260200190565b60019690960b86526001600160801b0394851660208701529290931660408501526001600160a01b0390811660608501529091166080830152151560a082015260c00190565b60019290920b82526001600160401b0316602082015260400190565b6000602082528251806020840152615522816040850160208701615acf565b601f01601f19169190910160400192915050565b6020808252600f908201526e139bdd08195e1c1a5c9959081e595d608a1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b602080825260099082015268436f6f6c2054696d6560b81b604082015260600190565b60208082526027908201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316040820152663238206269747360c81b606082015260800190565b6020808252600a90820152694e6f742061637469766560b01b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526026908201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660408201526534206269747360d01b606082015260800190565b6020808252600d908201526c27b7363c90383937bb34b232b960991b604082015260600190565b602080825260099082015268139bc814995dd85c9960ba1b604082015260600190565b6020808252600d908201526c556e7361666520737570706c7960981b604082015260600190565b6020808252600f908201526e496e76616c6964206665656261736560881b604082015260600190565b60208082526019908201527f7472616e7366657272696e67204574686572206661696c656400000000000000604082015260600190565b6020808252600790820152665265766572736560c81b604082015260600190565b6020808252600c908201526b4f7574206f662072616e676560a01b604082015260600190565b60208082526026908201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360408201526532206269747360d01b606082015260800190565b60208082526016908201527513585d1d5c9a5d1e481cda1bdd591b1908195e1a5cdd60521b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a4e6f742072756e6e696e6760a81b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600b908201526a139bdd0813585d1d5c995960aa1b604082015260600190565b602080825260079082015266115e1c1a5c995960ca1b604082015260600190565b6001600160801b0391909116815260200190565b6001600160801b0392831681529116602082015260400190565b6001600160801b03948516815292841660208401529083166040830152909116606082015260800190565b6001600160801b039390931683526001600160401b03918216602084015216604082015260600190565b95865260019490940b602086015263ffffffff9290921660408501526001600160401b039081166060850152166080830152151560a082015260c00190565b918252602082015260400190565b9283526001600160401b039190911660208301521515604082015260600190565b9283526001600160401b0391909116602083015260ff16604082015260600190565b63ffffffff91909116815260200190565b6001600160401b0391909116815260200190565b6001600160401b0392831681529116602082015260400190565b6001600160401b039384168152919092166020820152604081019190915260600190565b60ff91909116815260200190565b6040518181016001600160401b0381118282101715615ac757600080fd5b604052919050565b60005b83811015615aea578181015183820152602001615ad2565b83811115613b945750506000910152565b6001600160a01b0381168114615b1057600080fd5b50565b8015158114615b1057600080fd5b6001600160401b0381168114615b1057600080fdfe5472616e736665724554483a207472616e7366657220616d6f756e7420657863656564732062616c616e6365a264697066735822122002e2720145b831229dc25d43b34aff7140055dd20fc8f575bd19116ae9ed92a464736f6c63430007010033608060405234801561001057600080fd5b50600080546001600160a01b03191633179055610361806100326000396000f3fe6080604052600436106100225760003560e01c8063ed3de4871461006a57610065565b3661006557604051309033907fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9061005b9034906102f6565b60405180910390a3005b600080fd5b34801561007657600080fd5b5061008a6100853660046101e8565b61008c565b005b6000546001600160a01b031633146100bf5760405162461bcd60e51b81526004016100b6906102ab565b60405180910390fd5b6100c982826100cd565b5050565b6100c982826040518060600160405280602c8152602001610300602c91396100f4826101e1565b81906101135760405162461bcd60e51b81526004016100b69190610221565b506000836001600160a01b03168360405161012d9061021e565b60006040518083038185875af1925050503d806000811461016a576040519150601f19603f3d011682016040523d82523d6000602084013e61016f565b606091505b50509050806101905760405162461bcd60e51b81526004016100b690610274565b836001600160a01b0316306001600160a01b03167fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c856040516101d391906102f6565b60405180910390a350505050565b3031101590565b600080604083850312156101fa578182fd5b82356001600160a01b0381168114610210578283fd5b946020939093013593505050565b90565b6000602080835283518082850152825b8181101561024d57858101830151858201604001528201610231565b8181111561025e5783604083870101525b50601f01601f1916929092016040019392505050565b60208082526019908201527f7472616e7366657272696e67204574686572206661696c656400000000000000604082015260600190565b6020808252602b908201527f4572726f723a204f6e6c79206f776e65722063616e206578656375746520746860408201526a34b990333ab731ba34b7b760a91b606082015260800190565b9081526020019056fe5472616e736665724554483a207472616e7366657220616d6f756e7420657863656564732062616c616e6365a26469706673582212204f0a0f8dfa8207815122cdcd7e302a058c41e7aa8d8ee8daf858e9b12287afea64736f6c634300070100330000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d00000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b81700000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd7000000000000000000000000c8bbb8d57cebf834dc429ec4d65dd23ed0d65a87000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000174876e800
Deployed Bytecode
0x60806040526004361061024a5760003560e01c806392da91ad11610139578063b88a802f116100b6578063dd62ed3e1161007a578063dd62ed3e146106f4578063e0e54dec14610714578063e627f2db14610734578063e8078d9414610756578063ef4498ff1461075e578063fde6fad91461077e5761028d565b8063b88a802f14610673578063c82e377814610688578063cc4df8ae146106aa578063d28f3330146106bf578063d3339533146106d45761028d565b80639a8fac74116100fd5780639a8fac74146105e0578063a3a40ea5146105f5578063a3dd261914610617578063a9059cbb1461063e578063ae1162561461065e5761028d565b806392da91ad1461055257806395d89b41146105725780639649a73714610587578063979c6fe61461059c5780639960d742146105cb5761028d565b80633beeae20116101c75780635a9b0b891161018b5780635a9b0b89146104855780636c13ba78146104b157806370a08231146104e15780638417cb13146105015780638c5301c0146105235761028d565b80633beeae20146103d257806344a040f5146103e75780634759898f146104145780634fac075b14610436578063506718ef146104655761028d565b806318160ddd1161020e57806318160ddd1461035157806323b872dd146103665780632e20da2714610386578063313ce5671461039b578063315deeaa146103bd5761028d565b806302ecdef21461029257806306fdde03146102a9578063095ea7b3146102d45780630dad4e4b1461030157806315e524871461032e5761028d565b3661028d57604051309033907fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9061028390349061532b565b60405180910390a3005b600080fd5b34801561029e57600080fd5b506102a76107ac565b005b3480156102b557600080fd5b506102be610914565b6040516102cb9190615503565b60405180910390f35b3480156102e057600080fd5b506102f46102ef366004614eb8565b610945565b6040516102cb9190615302565b34801561030d57600080fd5b5061032161031c366004614e8b565b6109e9565b6040516102cb919061532b565b34801561033a57600080fd5b50610343610abe565b6040516102cb9291906159e7565b34801561035d57600080fd5b50610321610aed565b34801561037257600080fd5b506102f4610381366004614e4b565b610b26565b34801561039257600080fd5b506102a7610c18565b3480156103a757600080fd5b506103b0611199565b6040516102cb9190615a9b565b3480156103c957600080fd5b5061032161119e565b3480156103de57600080fd5b506102a76111c5565b3480156103f357600080fd5b50610407610402366004614df7565b611447565b6040516102cb9190615a49565b34801561042057600080fd5b506104296114b3565b6040516102cb9190615493565b34801561044257600080fd5b50610456610451366004615051565b6114b8565b6040516102cb9392919061530d565b34801561047157600080fd5b50610321610480366004615051565b6114f7565b34801561049157600080fd5b5061049a611519565b6040516102cb9b9a999897969594939291906151be565b3480156104bd57600080fd5b506104d16104cc366004614df7565b61167e565b6040516102cb9493929190615953565b3480156104ed57600080fd5b506103216104fc366004614df7565b6116c5565b34801561050d57600080fd5b506105166116e9565b6040516102cb919061515c565b34801561052f57600080fd5b5061054361053e366004614df7565b6116ee565b6040516102cb9392919061597e565b34801561055e57600080fd5b506102f461056d36600461502a565b61172e565b34801561057e57600080fd5b506102be611848565b34801561059357600080fd5b50610321611868565b3480156105a857600080fd5b506105bc6105b7366004615051565b611948565b6040516102cb93929190615a77565b3480156105d757600080fd5b50610516611988565b3480156105ec57600080fd5b506102f46119ac565b34801561060157600080fd5b5061060a6119bd565b6040516102cb919061547f565b34801561062357600080fd5b5061062c611a77565b6040516102cb969594939291906159a8565b34801561064a57600080fd5b506102f4610659366004614eb8565b611abd565b34801561066a57600080fd5b506102a7611acd565b34801561067f57600080fd5b506102a7611ed9565b34801561069457600080fd5b5061069d61202b565b6040516102cb91906152be565b3480156106b657600080fd5b5061034361208e565b3480156106cb57600080fd5b506102a76120b4565b3480156106e057600080fd5b506103216106ef366004615069565b61253a565b34801561070057600080fd5b5061032161070f366004614e13565b612557565b34801561072057600080fd5b5061032161072f366004615069565b61258b565b34801561074057600080fd5b50610749612665565b6040516102cb9190615262565b6102f46126db565b34801561076a57600080fd5b506102a7610779366004615104565b612711565b34801561078a57600080fd5b5061079e610799366004615051565b612842565b6040516102cb929190615939565b6007546107d45760405162461bcd60e51b81526004016107cb90615870565b60405180910390fd5b60085460075460001901600090815260016020526040902054600160801b90910463ffffffff16906001600160401b0316806108225760405162461bcd60e51b81526004016107cb90615809565b6040516301e5ddfb60e71b81526000906001600160a01b037f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0169063f2eefd8090610871908690600401615a38565b60006040518083038186803b15801561088957600080fd5b505afa15801561089d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108c59190810190614f2b565b915050816001600160401b031681106109035750506008805463ffffffff909216600160801b0263ffffffff60801b19909216919091179055610912565b60018301925050610822565b50505b565b604051806040016040528060158152602001744c49454e5f41474752454741544f525f534841524560581b81525081565b600060001982141561095c576001600160801b0391505b61096582612879565b336000818152600c602090815260408083206001600160a01b03891680855292529182902080546001600160801b0319166001600160801b039590951694909417909355517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906109d790869061532b565b60405180910390a35060015b92915050565b6001600160a01b0382166000908152600b60209081526040808320546009909252909120546001600160801b0391821691600160801b90910416156109e35733600090815260096020526040902054600754600193506001600160801b0390911610156109e357336000818152600960208181526040808420546001600160801b0380821660010181168652600684529185205495909452919052610ab792610ab092600160801b91829004831692610aaa92909104166305f5e1006128a2565b906128dc565b600161291e565b0192915050565b6007546000908152600d6020908152604080832054600e909252909120546001600160801b0391821691169091565b6007546000908152600e60209081526040808320546006909252822054610b20916001600160801b039182169116612942565b90505b90565b6001600160a01b0383166000908152600c602090815260408083203384529091528120546001600160801b031682811015610b65576000915050610c11565b6001600160801b0381811614610bf7576001600160a01b0385166000908152600c60209081526040808320338452909152902054610bb590610bb0906001600160801b031685612942565b612879565b6001600160a01b0386166000908152600c60209081526040808320338452909152902080546001600160801b0319166001600160801b03929092169190911790555b610c0a8585610c0586612879565b612984565b5060019150505b9392505050565b60405163300da2f160e11b81526000906001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169063601b45e290610cab907f000000000000000000000000a961684a3a654fb2cca8f8991226c0cefc514d80907f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d90869060040161523e565b60206040518083038186803b158015610cc357600080fd5b505afa158015610cd7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cfb9190615009565b90506103e88160010b13158015610d16575060058160010b12155b610d325760405162461bcd60e51b81526004016107cb9061571c565b6040516311ed607760e01b81526000906001600160a01b037f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd716906311ed607790610d8490309060019060040161518a565b60206040518083038186803b158015610d9c57600080fd5b505afa158015610db0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dd49190614ff1565b905060007f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd76001600160a01b03166311ed60773060006040518363ffffffff1660e01b8152600401610e2792919061518a565b60206040518083038186803b158015610e3f57600080fd5b505afa158015610e53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e779190614ff1565b905060007f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd76001600160a01b031663488abbfc307f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06040518363ffffffff1660e01b8152600401610ee9929190615170565b60206040518083038186803b158015610f0157600080fd5b505afa158015610f15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f399190614ff1565b604051631711ddb160e21b81529091506001600160a01b037f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd71690635c4776c490610fce9086907f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d907f000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d0908a90600401615334565b600060405180830381600087803b158015610fe857600080fd5b505af1158015610ffc573d6000803e3d6000fd5b5050604051631711ddb160e21b81526001600160a01b037f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd7169250635c4776c491506110929085907f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d907f000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d0908a90600401615334565b600060405180830381600087803b1580156110ac57600080fd5b505af11580156110c0573d6000803e3d6000fd5b5050600054604051630ccb63b760e41b81526001600160a01b037f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd78116945063ccb63b70935061113d9286929116907f000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d09081908b9060040161535c565b600060405180830381600087803b15801561115757600080fd5b505af115801561116b573d6000803e3d6000fd5b50506008805460019790970b61ffff16600160a01b0261ffff60a01b19909716969096179095555050505050565b600881565b6007546000908152600d6020526040812054610b20903031906001600160801b0316612942565b6007546000818152600e602090815260408083205460059092528220549192839290916001600160801b031690600160401b900460ff1680611205575081155b6112215760405162461bcd60e51b81526004016107cb90615536565b6000828152600660205260409020546001600160801b031680156112a657600061124961119e565b9050611260610ab083610aaa846305f5e1006128a2565b6000858152600d602052604090205490955061129e90869061128f906001600160801b03166305f5e1006128a2565b8161129657fe5b04600161291e565b9550506112f0565b6000838152600d60205260409020546001600160801b0316156112f0576000838152600d60205260409020546112e6906001600160801b0316600161291e565b94506305f5e10093505b8085016112fc85612879565b60018501600090815260066020526040902080546001600160801b03928316600160801b029216919091179055611340610bb08461133a858a612a40565b90612942565b60018501600090815260066020526040902080546001600160801b0319166001600160801b0392831617908190556c2af31dc4611873bf3f70834acd91161115611398576008805460ff60b01b1916600160b01b1790555b83156113a6576113a6612a65565b6000811180156113b65750600083115b156113c4576113c485612b95565b6113cc612bfb565b6113d7600754613151565b6008546007546000908152600160208190526040918290205491516001600160401b03948516947fb6468ad5c9ad279cc97382791cf54035b2adbdc6126bee312967c4fdbb9a56da9461143794600160a01b90910490930b9216906154e7565b60405180910390a2505050505050565b6001600160a01b0381166000908152600b60209081526040808320815160608101835290546001600160801b03811682526001600160401b03600160801b8204811694830194909452600160c01b9004909216908201526007546114ab9190613176565b90505b919050565b601290565b60008080836114c75760075493505b50505060009081526005602052604090205460ff600160401b8204169163ffffffff600160201b83048116921690565b600090815260066020526040902054600160801b90046001600160801b031690565b7f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0907f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd7907f000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d0907f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d907f000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e907f000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b817907f000000000000000000000000a961684a3a654fb2cca8f8991226c0cefc514d80907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000003b9aca00906c2af31dc4611873bf3f70834acd90565b6001600160a01b0316600090815260096020908152604080832054600a909252909120546001600160801b0380831693600160801b93849004821693828416930490911690565b6001600160a01b03166000908152600b60205260409020546001600160801b031690565b600090565b6001600160a01b03166000908152600b60205260409020546001600160801b038116916001600160401b03600160c01b8304811692600160801b90041690565b600080600061173b613309565b600754336000908152600a60205260409020549295509093509150600160801b90046001600160801b031661179357336000908152600a6020526040902080546001600160801b0319166001600160801b0383161790555b336000818152600a6020908152604080832080546001600160801b03600160801b80830482168d0182160291811691909117909155858452600e9092529091208054808316890183166001600160801b0319919091161790556117fb919085908816856134c1565b80336001600160a01b03167f3518f79326efc4570db0ebb1195252c857df4c2beb5932ab886faa94251a50e0876040516118359190615925565b60405180910390a3506001949350505050565b6040518060400160405280600481526020016309882a6960e31b81525081565b6007546000908152600160205260408120546001600160401b03164211156118a25760405162461bcd60e51b81526004016107cb90615600565b60007f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d6001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156118ff57600080fd5b505af1158015611913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119379190614ff1565b905061194281613646565b91505090565b60008080836119575760075493505b505050600090815260016020819052604090912080549101546001600160401b0380831693600160401b9093041691565b7f00000000000000000000000026541e091025d4601aed5ca7d8c7e0755fdf738b90565b600854600160b01b900460ff161590565b6000600754600014156119d257506000610b23565b6007546000908152600160205260409020546001600160401b03164211611a22576008546001600160401b03600160401b909104166203f480014211611a1a57506002610b23565b506001610b23565b6007546000908152600160205260409020546001600160401b031642118015611a645750600754600090815260056020526040902054600160401b900460ff16155b15611a7157506003610b23565b50600490565b6007546008549091600160a01b820460010b91600160801b810463ffffffff16916001600160401b0380831692600160401b810490911691600160b01b90910460ff1690565b6000610c113384610c0585612879565b6007546000908152600160205260409020546001600160401b0316421115611b075760405162461bcd60e51b81526004016107cb90615600565b6008546001600160401b03600160401b909104166203f480014211611b3e5760405162461bcd60e51b81526004016107cb90615596565b60007f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d6001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611b9b57600080fd5b505af1158015611baf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd39190614ff1565b90506000611be08261393b565b905080611bf357611bf082613646565b90505b600080611bfe614db9565b6007546000908152600260205260409081902060085491516329069bdd60e01b81526001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd416926329069bdd92611cb1927f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef09230928b928d926001600160401b0316907f00000000000000000000000000000000000000000000000000000000000000009060040161538d565b60806040518083038186803b158015611cc957600080fd5b505afa158015611cdd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d01919061508a565b919450925090508115611d83577f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd76001600160a01b031663439370b1836040518263ffffffff1660e01b81526004016000604051808303818588803b158015611d6957600080fd5b505af1158015611d7d573d6000803e3d6000fd5b50505050505b8215611d9357611d938484613ad4565b602081015115611e5c578051602082015160405163b9601d7760e01b81527f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03169263b9601d7792611dee926004016159e7565b602060405180830381600087803b158015611e0857600080fd5b505af1158015611e1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e409190614fd5565b611e5c5760405162461bcd60e51b81526004016107cb9061577c565b611e6542613151565b6008805467ffffffffffffffff60401b1916600160401b6001600160401b039384160217905581516020830151604051918316928716917f2eaafc32eed9e5ff41c1b57ddd1ef894ec4eb7499efb581d50edffa27f6af23291611eca91889190615a5d565b60405180910390a35050505050565b611ee1614dd7565b50336000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b900490911691810191909152600754611f42908290613176565b6001600160401b03908116602083018190526007549091166040830152611f7b5760405162461bcd60e51b81526004016107cb906156d2565b60208181018051600080835233808252600b909452604090819020855181549451928701516001600160801b03199095166001600160801b039091161767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b9483169490940293909317909255169061090f906001600160a01b037f000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e169083613b9a565b60075460009081526002602090815260409182902080548351818402810184019094528084526060939283018282801561208457602002820191906000526020600020905b815481526020019060010190808311612070575b5050505050905090565b600080600061209b613309565b919450925090506120af33836000846134c1565b509091565b6007546000908152600160205260409020546001600160401b031642116120ed5760405162461bcd60e51b81526004016107cb906158df565b600754600081815260056020526040902054600160401b900460ff16156121265760405162461bcd60e51b81526004016107cb90615904565b60008181526005602052604090205463ffffffff166121ff576121d87f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b031663ac3fd8866040518163ffffffff1660e01b815260040160206040518083038186803b15801561219b57600080fd5b505afa1580156121af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d39190614ff1565b613bf5565b6000828152600560205260409020805463ffffffff191663ffffffff929092169190911790555b6000818152600160205260408082205460001984018352818320549151631c1b06f760e11b8152839283926001600160401b039081169291169083906001600160a01b037f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd716906338360dee9061227a90309060040161515c565b60206040518083038186803b15801561229257600080fd5b505afa1580156122a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ca9190614ff1565b90508015612346577f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd76001600160a01b031663a0ef91df6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561232d57600080fd5b505af1158015612341573d6000803e3d6000fd5b505050505b50600086815260056020526040902054600160201b900463ffffffff1661237e57600854600160801b900463ffffffff16935061239d565b600086815260056020526040902054600160201b900463ffffffff1693505b600086815260056020526040902054603263ffffffff91821686900390911611156123ff576000868152600560205260409020805463ffffffff60328701908116600160201b0267ffffffff0000000019909216919091179091559450612417565b60008681526005602052604090205463ffffffff1694505b63ffffffff84165b8563ffffffff168110156124c25761243981858585613c1a565b935060098463ffffffff1611156124ba576001860363ffffffff1681141561247f576000878152600560205260409020805460ff60401b1916600160401b1790556124ae565b6000878152600560205260409020805467ffffffff000000001916600160201b6001840163ffffffff16021790555b50505050505050610912565b60010161241f565b5060008681526005602052604090205463ffffffff86811691161415612506576000868152600560205260409020805460ff60401b1916600160401b179055612532565b6000868152600560205260409020805467ffffffff000000001916600160201b63ffffffff8816021790555b505050505050565b600091825260036020908152604080842092845291905290205490565b6001600160a01b039182166000908152600c602090815260408083209390941682529190915220546001600160801b031690565b6008546040516351d19dc760e11b81526000916001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169163a3a33b8e916125ea9186916001600160401b031690600190600401615a16565b60206040518083038186803b15801561260257600080fd5b505afa158015612616573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263a9190614ff1565b9150826126475760075492505b50600091825260036020908152604080842092845291905290205490565b60606004805480602002602001604051908101604052809291908181526020016000905b828210156126d257600084815260209081902060408051808201909152908401546001600160401b038082168352600160401b9091041681830152825260019092019101612689565b50505050905090565b600854600090600160b01b900460ff16156127085760405162461bcd60e51b81526004016107cb906156f5565b610b2034613df2565b336001600160a01b037f000000000000000000000000a961684a3a654fb2cca8f8991226c0cefc514d8016146127595760405162461bcd60e51b81526004016107cb906156ab565b6007546127785760405162461bcd60e51b81526004016107cb90615870565b6305f5e1006001600160401b038216108015906127a45750655af3107a40006001600160401b03821611155b6127c05760405162461bcd60e51b81526004016107cb9061579d565b600460405180604001604052806127d8600754613151565b60019081016001600160401b03908116835294851660209283015283549081018455600093845292819020825193018054929091015167ffffffffffffffff199092169284169290921767ffffffffffffffff60401b1916600160401b9190931602919091179055565b600080826128505760075492505b50506000908152600660205260409020546001600160801b0380821692600160801b9092041690565b6000600160801b821061289e5760405162461bcd60e51b81526004016107cb906155b9565b5090565b6000826128b1575060006109e3565b828202828482816128be57fe5b0414610c115760405162461bcd60e51b81526004016107cb90615624565b6000610c1183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613f0c565b6000811561293457506402540be40082046109e3565b506402540be40082026109e3565b6000610c1183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613f43565b6001600160a01b0383166000908152600b60205260408120546001600160801b03808416911610156129b857506000610c11565b6129cf84836001600160801b031660001902613f6f565b6129e283836001600160801b0316613f6f565b826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846001600160801b0316604051612a2e919061532b565b60405180910390a35060019392505050565b600082820183811015610c115760405162461bcd60e51b81526004016107cb9061555f565b6008546007546000818152600660205260408082205460019384018352918190205490516379b347db60e01b81526001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd416946379b347db94612b5b94600160a01b909204900b926001600160801b03600160801b928390048116939290910416907f000000000000000000000000a961684a3a654fb2cca8f8991226c0cefc514d80907f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d907f0000000000000000000000000000000000000000000000000000000000000000906004016154a1565b600060405180830381600087803b158015612b7557600080fd5b505af1158015612b89573d6000803e3d6000fd5b50505050610912610c18565b6007546000908152600e6020526040812054612bcf90612bc8906305f5e10090610aaa906001600160801b0316866128a2565b600061291e565b905061090f7f00000000000000000000000026541e091025d4601aed5ca7d8c7e0755fdf738b826140d8565b60007f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd46001600160a01b031663ca579d0a6040518163ffffffff1660e01b815260040160206040518083038186803b158015612c5657600080fd5b505afa158015612c6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c8e9190614ff1565b905060007f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d6001600160a01b031663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015612ced57600080fd5b505af1158015612d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d259190614ff1565b600854604051637298096d60e11b81529192506000916001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169163e53012da91612da89186916001600160401b03909116907f0000000000000000000000000000000000000000000000000000000000000000906004016159f5565b60206040518083038186803b158015612dc057600080fd5b505afa158015612dd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612df89190614ff1565b9050612e03826140fb565b60007f000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b8176001600160a01b031663a38593887f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0612e5e85613151565b612e6788613151565b6040518463ffffffff1660e01b8152600401612e8593929190615455565b602060405180830381600087803b158015612e9f57600080fd5b505af1158015612eb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed79190614ff1565b905060007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03166326d6c97b836040518263ffffffff1660e01b8152600401612f27919061532b565b60806040518083038186803b158015612f3f57600080fd5b505afa158015612f53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f779190614ee3565b505060405163095ea7b360e01b8152919250506001600160a01b0382169063095ea7b390612fcd907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600019906004016151a5565b602060405180830381600087803b158015612fe757600080fd5b505af1158015612ffb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061301f9190614fd5565b50600780546001019055613031614dd7565b604051806060016040528061304588613151565b6001600160401b0316815260200161305c86613151565b6001600160401b039081168252602091820186905260075460009081526001808452604091829020855181549587015167ffffffffffffffff199096169085161767ffffffffffffffff60401b1916600160401b959094169490940292909217835583810151929091019190915551631d3b07f760e21b81529091507f000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d06001600160a01b0316906374ec1fdc9061311790899060040161532b565b600060405180830381600087803b15801561313157600080fd5b505af1158015613145573d6000803e3d6000fd5b50505050505050505050565b6000600160401b821061289e5760405162461bcd60e51b81526004016107cb90615665565b602082015182516001600160801b0316158015906131a057508183604001516001600160401b0316105b156109e357600480546000198101916000916001600160401b0384169081106131c557fe5b6000918252602082200154600480546001600160401b039283169450909185169081106131ee57fe5b600091825260209091200154600160401b90046001600160401b03169050845b86604001516001600160401b03168111156132ff57826001600160401b03168110156132a1576001840393506004846001600160401b03168154811061325057fe5b9060005260206000200160000160089054906101000a90046001600160401b031691506004846001600160401b03168154811061328957fe5b6000918252602090912001546001600160401b031692505b60008181526006602052604090205487516132f4916132ef916132df916001600160801b0390811691610aaa916001600160401b03891691166128a2565b6001600160401b03881690612a40565b613151565b94506000190161320e565b5050505092915050565b600754336000908152600a602090815260408083205460099092528220549192839283926001600160801b0380821692600160801b92839004821692818316929104168461336657600080600097509750975050505050506134bc565b6001600160801b038316158015906133865750836001600160801b031685115b156133ef576001600160801b036001850181166000908152600660205260409020546133cc91612bc8916305f5e10091610aaa9188821691600160801b909104166128a2565b975087156133de576133de33896141da565b336000908152600a60205260408120555b6001600160801b0381161580159061340f5750816001600160801b031685115b15613472576001600160801b0360018301811660009081526006602052604090205461345391610ab091600160801b9004811690610aaa9085166305f5e1006128a2565b3360009081526009602052604081205596506001600160801b03821695505b84336001600160a01b03167fb11715e80d7e8d99a84fdd2112e0c3b821523d7416cb2082ec62d76c76f6f0168a8a6040516134ae9291906159e7565b60405180910390a350505050505b909192565b6134c9614dd7565b506001600160a01b0384166000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b9004909116918101919091528315613571576135358183613176565b6001600160401b03908116602083015282166040820152805161356590610bb0906001600160801b031686612a40565b6001600160801b031681525b61357d81600754613176565b6001600160401b03908116602083015260075416604082015282156135c15780516135b590610bb0906001600160801b031685612942565b6001600160801b031681525b6001600160a01b03949094166000908152600b6020908152604091829020865181549288015193909701516001600160801b03199092166001600160801b039097169690961767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b929091169190910217909355505050565b60085460405163a072a3e560e01b815260009182916001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169163a072a3e5916136c89187916001600160401b03909116907f0000000000000000000000000000000000000000000000000000000000000000906004016159f5565b60206040518083038186803b1580156136e057600080fd5b505afa1580156136f4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137189190614ff1565b600754909150613726614dd7565b50600081815260016020818152604092839020835160608101855281546001600160401b038082168352600160401b9091041692810183905292015492820192909252906137749084614256565b602082015182516040808501519051635b1caa5760e11b81529396506001600160a01b037f000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b817169363b63954ae936137f1937f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0938a9360040161541e565b602060405180830381600087803b15801561380b57600080fd5b505af115801561381f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138439190614ff1565b93507f0000000000000000000000000000000000000000000000000000000000000000156139295760085460405163a072a3e560e01b81526139249186916001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169163a072a3e5916138cf918b916001600160401b03909116906000906004016159f5565b60206040518083038186803b1580156138e757600080fd5b505afa1580156138fb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061391f9190614ff1565b614280565b613933565b6139338484614280565b505050919050565b6008546040516351d19dc760e11b815260009182916001600160a01b037f0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4169163a3a33b8e9161399e9187916001600160401b0390911690600190600401615a16565b60206040518083038186803b1580156139b657600080fd5b505afa1580156139ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139ee9190614ff1565b600754600090815260036020908152604080832084845291829052909120549192509015613a2a576000918252602052604090205490506114ae565b60015b60028111613933576008546001600160401b03168102830360009081526020839052604090205415613a80576008546001600160401b0316029091036000908152602091909152604090205490506114ae565b6008546001600160401b03168102830160009081526020839052604090205415613acc576008546001600160401b031602919091016000908152602091909152604090205490506114ae565b600101613a2d565b7f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b038116638376c24d613b256103e8610aaa6103ea613b1f886402540be4006128a2565b906128a2565b856040518363ffffffff1660e01b8152600401613b42919061532b565b6020604051808303818588803b158015613b5b57600080fd5b505af1158015613b6f573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613b949190614ff1565b50505050565b613bf08363a9059cbb60e01b8484604051602401613bb99291906151a5565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614962565b505050565b6000600160201b821061289e5760405162461bcd60e51b81526004016107cb906157c3565b6000606060007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b031663f2eefd80886040518263ffffffff1660e01b8152600401613c6c919061532b565b60006040518083038186803b158015613c8457600080fd5b505afa158015613c98573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613cc09190810190614f2b565b91509150846001600160401b0316811180613cf65750836001600160401b031681108015613cf657506001600160401b03841615155b15613d05578592505050613dea565b6000805b8351811015613de25760007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03166326d6c97b868481518110613d4f57fe5b60200260200101516040518263ffffffff1660e01b8152600401613d73919061532b565b60806040518083038186803b158015613d8b57600080fd5b505afa158015613d9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613dc39190614ee3565b5050509050613dd48a828b866149f1565b909950925050600101613d09565b508693505050505b949350505050565b6000806000613dff613309565b9250925050613e1133836000846134c1565b60075433600090815260096020526040902054600160801b90046001600160801b0316613e615733600090815260096020526040902080546001600160801b0319166001600160801b0383161790555b613e6a85612879565b33600090815260096020526040902080546001600160801b03600160801b808304821690940181169093029216919091179055613ea685612879565b6000828152600d60205260409081902080546001600160801b031981166001600160801b0391821694909401169290921790915551819033907f4c86739b331ba35e12897451019b4a8cca47a228be900c18ab3a8ffa5dfe7e539061183590899061532b565b60008183613f2d5760405162461bcd60e51b81526004016107cb9190615503565b506000838581613f3957fe5b0495945050505050565b60008184841115613f675760405162461bcd60e51b81526004016107cb9190615503565b505050900390565b613f77614dd7565b506001600160a01b0382166000908152600b6020908152604091829020825160608101845290546001600160801b03811682526001600160401b03600160801b8204811693830193909352600160c01b900490911691810191909152600754613fe1908290613176565b6001600160401b039081166020830152600754166040820152600082121561403057805161402090610bb0906001600160801b03166000859003612942565b6001600160801b03168152614055565b805161404990610bb0906001600160801b031684612a40565b6001600160801b031681525b6001600160a01b03929092166000908152600b6020908152604091829020845181549286015193909501516001600160801b03199092166001600160801b039095169490941767ffffffffffffffff60801b1916600160801b6001600160401b0393841602176001600160c01b0316600160c01b92909116919091021790915550565b61090f82826040518060600160405280602c8152602001615b37602c9139614bb0565b6000614133826001600160401b0360327f000000000000000000000000000000000000000000000000000000003b9aca0002166128dc565b90508061417b576008805467ffffffffffffffff19167f000000000000000000000000000000000000000000000000000000003b9aca006001600160401b031617905561090f565b6141b5600a6001600160401b037f000000000000000000000000000000000000000000000000000000003b9aca0016830260190204613151565b6008805467ffffffffffffffff19166001600160401b03929092169190911790555050565b60405163ed3de48760e01b81526001600160a01b037f00000000000000000000000026541e091025d4601aed5ca7d8c7e0755fdf738b169063ed3de4879061422890859085906004016151a5565b600060405180830381600087803b15801561424257600080fd5b505af1158015612532573d6000803e3d6000fd5b6000610c116002614270846001600160401b038716612942565b8161427757fe5b84919006612942565b60078054600090815260026020908152604080832080546001810182559084528284200186905592548252600381528282208483529052819020839055516301e5ddfb60e71b81526060906001600160a01b037f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef0169063f2eefd809061430a90869060040161532b565b60006040518083038186803b15801561432257600080fd5b505afa158015614336573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261435e9190810190614f2b565b50905060007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03166326d6c97b8360018151811061439f57fe5b60200260200101516040518263ffffffff1660e01b81526004016143c3919061532b565b60806040518083038186803b1580156143db57600080fd5b505afa1580156143ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144139190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906144679030907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600401615170565b60206040518083038186803b15801561447f57600080fd5b505afa158015614493573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144b79190614ff1565b61455f5760405163095ea7b360e01b81526001600160a01b0382169063095ea7b39061450b907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600019906004016151a5565b602060405180830381600087803b15801561452557600080fd5b505af1158015614539573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061455d9190614fd5565b505b60007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03166326d6c97b8460028151811061459d57fe5b60200260200101516040518263ffffffff1660e01b81526004016145c1919061532b565b60806040518083038186803b1580156145d957600080fd5b505afa1580156145ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146119190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906146659030907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600401615170565b60206040518083038186803b15801561467d57600080fd5b505afa158015614691573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146b59190614ff1565b61475d5760405163095ea7b360e01b81526001600160a01b0382169063095ea7b390614709907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600019906004016151a5565b602060405180830381600087803b15801561472357600080fd5b505af1158015614737573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061475b9190614fd5565b505b60007f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef06001600160a01b03166326d6c97b8560038151811061479b57fe5b60200260200101516040518263ffffffff1660e01b81526004016147bf919061532b565b60806040518083038186803b1580156147d757600080fd5b505afa1580156147eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061480f9190614ee3565b5050604051636eb1769f60e11b8152919250506001600160a01b0382169063dd62ed3e906148639030907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600401615170565b60206040518083038186803b15801561487b57600080fd5b505afa15801561488f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148b39190614ff1565b6125325760405163095ea7b360e01b81526001600160a01b0382169063095ea7b390614907907f00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd790600019906004016151a5565b602060405180830381600087803b15801561492157600080fd5b505af1158015614935573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149599190614fd5565b50505050505050565b60606149b7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614ca69092919063ffffffff16565b805190915015613bf057808060200190518101906149d59190614fd5565b613bf05760405162461bcd60e51b81526004016107cb90615895565b6040516370a0823160e01b81526000908190859082906001600160a01b038316906370a0823190614a2690309060040161515c565b60206040518083038186803b158015614a3e57600080fd5b505afa158015614a52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a769190614ff1565b1115614ba35783614b28576040516301bc8ef560e61b81526001600160a01b037f000000000000000000000000da6fc5625e617bb92f5359921d43321cebc6bef01690636f23bd4090614ad0908a906000906004016159e7565b602060405180830381600087803b158015614aea57600080fd5b505af1158015614afe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b229190614ff1565b50600193505b806001600160a01b0316639975038c6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015614b6357600080fd5b505af1158015614b77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614b9b9190614ff1565b506001850194505b5092959194509092505050565b614bb982614cb5565b8190614bd85760405162461bcd60e51b81526004016107cb9190615503565b506000836001600160a01b031683604051614bf290610b23565b60006040518083038185875af1925050503d8060008114614c2f576040519150601f19603f3d011682016040523d82523d6000602084013e614c34565b606091505b5050905080614c555760405162461bcd60e51b81526004016107cb90615745565b836001600160a01b0316306001600160a01b03167fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c85604051614c98919061532b565b60405180910390a350505050565b6060613dea8484600085614cbc565b3031101590565b6060614cc785614d80565b614ce35760405162461bcd60e51b81526004016107cb90615839565b60006060866001600160a01b03168587604051614d009190615140565b60006040518083038185875af1925050503d8060008114614d3d576040519150601f19603f3d011682016040523d82523d6000602084013e614d42565b606091505b50915091508115614d56579150613dea9050565b805115614d665780518082602001fd5b8360405162461bcd60e51b81526004016107cb9190615503565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590613dea575050151592915050565b60405180604001604052806002906020820280368337509192915050565b604080516060810182526000808252602082018190529181019190915290565b600060208284031215614e08578081fd5b8135610c1181615afb565b60008060408385031215614e25578081fd5b8235614e3081615afb565b91506020830135614e4081615afb565b809150509250929050565b600080600060608486031215614e5f578081fd5b8335614e6a81615afb565b92506020840135614e7a81615afb565b929592945050506040919091013590565b60008060408385031215614e9d578182fd5b8235614ea881615afb565b91506020830135614e4081615b13565b60008060408385031215614eca578182fd5b8235614ed581615afb565b946020939093013593505050565b60008060008060808587031215614ef8578081fd5b8451614f0381615afb565b602086015160408701519195509350614f1b81615b21565b6060959095015193969295505050565b60008060408385031215614f3d578182fd5b82516001600160401b0380821115614f53578384fd5b818501915085601f830112614f66578384fd5b815181811115614f74578485fd5b60209150818102614f86838201615aa9565b8281528381019085850183870186018b1015614fa0578889fd5b8896505b84871015614fc2578051835260019690960195918501918501614fa4565b5097909301519698969750505050505050565b600060208284031215614fe6578081fd5b8151610c1181615b13565b600060208284031215615002578081fd5b5051919050565b60006020828403121561501a578081fd5b81518060010b8114610c11578182fd5b60006020828403121561503b578081fd5b81356001600160801b0381168114610c11578182fd5b600060208284031215615062578081fd5b5035919050565b6000806040838503121561507b578182fd5b50508035926020909101359150565b60008060006080848603121561509e578081fd5b83519250602080850151925085605f8601126150b8578182fd5b6150c26040615aa9565b8060408701886080890111156150d6578485fd5b845b60028110156150f5578151845292840192908401906001016150d8565b50508093505050509250925092565b600060208284031215615115578081fd5b8135610c1181615b21565b15159052565b6001600160801b03169052565b6001600160401b03169052565b60008251615152818460208701615acf565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b038c811682528b811660208301528a811660408301528981166060830152888116608083015287811660a083015286811660c0830152851660e08201528315156101008201526001600160401b038316610120820152610160810161522e610140830184615126565b9c9b505050505050505050505050565b6001600160a01b039384168152919092166020820152901515604082015260600190565b602080825282518282018190526000919060409081850190868401855b828110156152b157815180516001600160401b039081168652908701511686850152928401929085019060010161527f565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b818110156152f6578351835292840192918401916001016152da565b50909695505050505050565b901515815260200190565b921515835263ffffffff918216602084015216604082015260600190565b90815260200190565b9384526001600160a01b0392831660208501529116604083015260010b606082015260800190565b9485526001600160a01b0393841660208601529183166040850152909116606083015260010b608082015260a00190565b600060e0820160018060a01b03808b1684526020818b168186015289604086015288606086015260e060808601528291508754808452610100860192508885528185209350845b818110156153f0578454845260019485019493830193016153d4565b505050809250505061540560a0830185615133565b61541260c0830184615120565b98975050505050505050565b6001600160a01b0395909516855260208501939093526001600160401b039182166040850152166060830152608082015260a00190565b6001600160a01b039390931683526001600160401b03918216602084015216604082015260600190565b602081016005831061548d57fe5b91905290565b60019190910b815260200190565b60019690960b86526001600160801b0394851660208701529290931660408501526001600160a01b0390811660608501529091166080830152151560a082015260c00190565b60019290920b82526001600160401b0316602082015260400190565b6000602082528251806020840152615522816040850160208701615acf565b601f01601f19169190910160400192915050565b6020808252600f908201526e139bdd08195e1c1a5c9959081e595d608a1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b602080825260099082015268436f6f6c2054696d6560b81b604082015260600190565b60208082526027908201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316040820152663238206269747360c81b606082015260800190565b6020808252600a90820152694e6f742061637469766560b01b604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526026908201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660408201526534206269747360d01b606082015260800190565b6020808252600d908201526c27b7363c90383937bb34b232b960991b604082015260600190565b602080825260099082015268139bc814995dd85c9960ba1b604082015260600190565b6020808252600d908201526c556e7361666520737570706c7960981b604082015260600190565b6020808252600f908201526e496e76616c6964206665656261736560881b604082015260600190565b60208082526019908201527f7472616e7366657272696e67204574686572206661696c656400000000000000604082015260600190565b6020808252600790820152665265766572736560c81b604082015260600190565b6020808252600c908201526b4f7574206f662072616e676560a01b604082015260600190565b60208082526026908201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360408201526532206269747360d01b606082015260800190565b60208082526016908201527513585d1d5c9a5d1e481cda1bdd591b1908195e1a5cdd60521b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a4e6f742072756e6e696e6760a81b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600b908201526a139bdd0813585d1d5c995960aa1b604082015260600190565b602080825260079082015266115e1c1a5c995960ca1b604082015260600190565b6001600160801b0391909116815260200190565b6001600160801b0392831681529116602082015260400190565b6001600160801b03948516815292841660208401529083166040830152909116606082015260800190565b6001600160801b039390931683526001600160401b03918216602084015216604082015260600190565b95865260019490940b602086015263ffffffff9290921660408501526001600160401b039081166060850152166080830152151560a082015260c00190565b918252602082015260400190565b9283526001600160401b039190911660208301521515604082015260600190565b9283526001600160401b0391909116602083015260ff16604082015260600190565b63ffffffff91909116815260200190565b6001600160401b0391909116815260200190565b6001600160401b0392831681529116602082015260400190565b6001600160401b039384168152919092166020820152604081019190915260600190565b60ff91909116815260200190565b6040518181016001600160401b0381118282101715615ac757600080fd5b604052919050565b60005b83811015615aea578181015183820152602001615ad2565b83811115613b945750506000910152565b6001600160a01b0381168114615b1057600080fd5b50565b8015158114615b1057600080fd5b6001600160401b0381168114615b1057600080fdfe5472616e736665724554483a207472616e7366657220616d6f756e7420657863656564732062616c616e6365a264697066735822122002e2720145b831229dc25d43b34aff7140055dd20fc8f575bd19116ae9ed92a464736f6c63430007010033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d00000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b81700000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd7000000000000000000000000c8bbb8d57cebf834dc429ec4d65dd23ed0d65a87000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000000000000000000000000000000000174876e800
-----Decoded View---------------
Arg [0] : _ethOracle (address): 0x6e33f11625b2c8B7270cf8e0319b8B9fFB8F086D
Arg [1] : _pricer (address): 0x965666E465c48DaCc15e001aa7327B707EA2B7D0
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] : 000000000000000000000000965666e465c48dacc15e001aa7327b707ea2b7d0
Arg [2] : 0000000000000000000000005ee7b5b9845cae2a8fd2e02e0bf6ce6f83ebcfd4
Arg [3] : 000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e
Arg [4] : 000000000000000000000000aad52946e078cd22d79050146d81a295bbc2b817
Arg [5] : 00000000000000000000000023f8477c9f19389069535720e3ba66a2b95d5dd7
Arg [6] : 000000000000000000000000c8bbb8d57cebf834dc429ec4d65dd23ed0d65a87
Arg [7] : 000000000000000000000000000000000000000000000000000000003b9aca00
Arg [8] : 000000000000000000000000000000000000000000000000000000174876e800
Deployed Bytecode Sourcemap
122130:4128:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;120449:52;;120484:4;;120464:10;;120449:52;;;;120491:9;;120449:52;:::i;:::-;;;;;;;;122130:4128;;;;;95978:557;;;;;;;;;;;;;:::i;:::-;;85343:62;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;110957:313;;;;;;;;;;-1:-1:-1;110957:313:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;116632:820::-;;;;;;;;;;-1:-1:-1;116632:820:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;118689:180::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;112827:169::-;;;;;;;;;;;;;:::i;111557:625::-;;;;;;;;;;-1:-1:-1;111557:625:0;;;;;:::i;:::-;;:::i;123554:795::-;;;;;;;;;;;;;:::i;85239:43::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;125866:159::-;;;;;;;;;;;;;:::i;88561:1968::-;;;;;;;;;;;;;:::i;118291:146::-;;;;;;;;;;-1:-1:-1;118291:146:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;126033:99::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;114019:515::-;;;;;;;;;;-1:-1:-1;114019:515:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;119027:149::-;;;;;;;;;;-1:-1:-1;119027:149:0;;;;;:::i;:::-;;:::i;115242:902::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;113004:496::-;;;;;;;;;;-1:-1:-1;113004:496:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;:::i;112700:119::-;;;;;;;;;;-1:-1:-1;112700:119:0;;;;;:::i;:::-;;:::i;125339:109::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;119413:308::-;;;;;;;;;;-1:-1:-1;119413:308:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;92980:645::-;;;;;;;;;;-1:-1:-1;92980:645:0;;;;;:::i;:::-;;:::i;85289:47::-;;;;;;;;;;;;;:::i;98886:208::-;;;;;;;;;;;;;:::i;116152:384::-;;;;;;;;;;-1:-1:-1;116152:384:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;126140:115::-;;;;;;;;;;;;;:::i;118570:111::-;;;;;;;;;;;;;:::i;117529:673::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;113508:503::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;111278:169::-;;;;;;;;;;-1:-1:-1;111278:169:0;;;;;:::i;:::-;;:::i;99206:1315::-;;;;;;;;;;;;;:::i;110359:478::-;;;;;;;;;;;;;:::i;119806:140::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;95476:296::-;;;;;;;;;;;;;:::i;96699:2179::-;;;;;;;;;;;;;:::i;119184:221::-;;;;;;;;;;-1:-1:-1;119184:221:0;;;;;:::i;:::-;;:::i;118877:142::-;;;;;;;;;;-1:-1:-1;118877:142:0;;;;;:::i;:::-;;:::i;114877:357::-;;;;;;;;;;-1:-1:-1;114877:357:0;;;;;:::i;:::-;;:::i;118445:117::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;124428:130::-;;;:::i;90758:272::-;;;;;;;;;;-1:-1:-1;90758:272:0;;;;;:::i;:::-;;:::i;114542:327::-;;;;;;;;;;-1:-1:-1;114542:327:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;95978:557::-;86838:11;;86830:40;;;;-1:-1:-1;;;86830:40:0;;;;;;;:::i;:::-;;;;;;;;;96078:16:::1;::::0;96140:11:::1;::::0;-1:-1:-1;;96140:15:0;96051:24:::1;96131:25:::0;;;:8:::1;:25;::::0;;;;:34;-1:-1:-1;;;96078:16:0;;::::1;;;::::0;-1:-1:-1;;;;;96131:34:0::1;::::0;96176:56:::1;;;;-1:-1:-1::0;;;96176:56:0::1;;;;;;;:::i;:::-;96294:41;::::0;-1:-1:-1;;;96294:41:0;;96274:16:::1;::::0;-1:-1:-1;;;;;96294:9:0::1;:22;::::0;::::1;::::0;:41:::1;::::0;96317:17;;96294:41:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;::::0;;::::1;-1:-1:-1::0;;96294:41:0::1;::::0;::::1;;::::0;::::1;::::0;;;::::1;::::0;::::1;:::i;:::-;96271:64;;;96366:16;-1:-1:-1::0;;;;;96354:28:0::1;:8;:28;96350:130;;-1:-1:-1::0;;96403:16:0::1;:36:::0;;::::1;::::0;;::::1;-1:-1:-1::0;;;96403:36:0::1;-1:-1:-1::0;;;;96403:36:0;;::::1;::::0;;;::::1;::::0;;96458:7:::1;;96350:130;96515:1;96494:22;;;;96243:285;;;;86881:1;;;95978:557::o:0;85343:62::-;;;;;;;;;;;;;;-1:-1:-1;;;85343:62:0;;;;:::o;110957:313::-;111034:4;-1:-1:-1;;111055:6:0;:21;111051:74;;;-1:-1:-1;;;;;111093:20:0;-1:-1:-1;111051:74:0;111169:18;:6;:16;:18::i;:::-;111146:10;111135:22;;;;:10;:22;;;;;;;;-1:-1:-1;;;;;111135:31:0;;;;;;;;;;;:52;;-1:-1:-1;;;;;;111135:52:0;-1:-1:-1;;;;;111135:52:0;;;;;;;;;;;111203:37;;;;;111233:6;;111203:37;:::i;:::-;;;;;;;;-1:-1:-1;111258:4:0;110957:313;;;;;:::o;116632:820::-;-1:-1:-1;;;;;116822:13:0;;116763:23;116822:13;;;:7;:13;;;;;;;;:21;116858:19;:25;;;;;;:31;-1:-1:-1;;;;;116822:21:0;;;;-1:-1:-1;;;116858:31:0;;;;:36;116854:591;;116985:10;116965:31;;;;:19;:31;;;;;:36;116951:11;;116928:4;;-1:-1:-1;;;;;;116965:36:0;;;-1:-1:-1;116947:487:0;;;117243:10;117213:51;117223:31;;;:19;:31;;;;;;;;:36;-1:-1:-1;;;;;117223:36:0;;;;:40;117213:51;;;;:9;:51;;;;;:109;117088:31;;;;;;;117041:377;;117080:292;;-1:-1:-1;;;117213:109:0;;;;;;;117080:64;;117088:37;;;;117131:12;117080:50;:64::i;:::-;:68;;:292::i;:::-;117395:4;117041:16;:377::i;:::-;117022:396;116632:820;;;;:::o;118689:180::-;118813:11;;118752:7;118789:36;;;:23;:36;;;;;;;;;118827:20;:33;;;;;;;-1:-1:-1;;;;;118789:36:0;;;;118827:33;118689:180;;:::o;112827:169::-;112975:11;;112880:7;112954:33;;;:20;:33;;;;;;;;;112915:9;:22;;;;;:33;112907:81;;-1:-1:-1;;;;;112915:33:0;;;;112954;112907:46;:81::i;:::-;112900:88;;112827:169;;:::o;111557:625::-;-1:-1:-1;;;;;111735:18:0;;111691:4;111735:18;;;:10;:18;;;;;;;;111754:10;111735:30;;;;;;;;-1:-1:-1;;;;;111735:30:0;111780:25;;;111776:70;;;111829:5;111822:12;;;;;111776:70;-1:-1:-1;;;;;111897:31:0;;;;111893:196;;-1:-1:-1;;;;;111986:18:0;;;;;;:10;:18;;;;;;;;112005:10;111986:30;;;;;;;;111978:99;;:69;;-1:-1:-1;;;;;111986:30:0;112040:6;111978:61;:69::i;:::-;:97;:99::i;:::-;-1:-1:-1;;;;;111945:18:0;;;;;;:10;:18;;;;;;;;111964:10;111945:30;;;;;;;:132;;-1:-1:-1;;;;;;111945:132:0;-1:-1:-1;;;;;111945:132:0;;;;;;;;;;111893:196;112099:53;112114:6;112122:9;112133:18;:6;:16;:18::i;:::-;112099:14;:53::i;:::-;;112170:4;112163:11;;;111557:625;;;;;;:::o;123554:795::-;123629:56;;-1:-1:-1;;;123629:56:0;;123605:21;;-1:-1:-1;;;;;123629:8:0;:25;;;;:56;;123655:5;;123670:6;;123605:21;;123629:56;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;123605:80;;123725:4;123706:15;:23;;;;:47;;;;;123752:1;123733:15;:20;;;;123706:47;123698:75;;;;-1:-1:-1;;;123698:75:0;;;;;;;:::i;:::-;123808:45;;-1:-1:-1;;;123808:45:0;;123784:21;;-1:-1:-1;;;;;123808:4:0;:24;;;;:45;;123841:4;;123848;;123808:45;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;123784:69;;123864:20;123887:4;-1:-1:-1;;;;;123887:24:0;;123920:4;123927:5;123887:46;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;123864:69;;123946:18;123967:4;-1:-1:-1;;;;;123967:25:0;;124001:4;124016:9;123967:60;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;124040:73;;-1:-1:-1;;;124040:73:0;;123946:81;;-1:-1:-1;;;;;;124040:4:0;:20;;;;:73;;124061:13;;124076:6;;124084:11;;124097:15;;124040:73;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;124126:72:0;;-1:-1:-1;;;124126:72:0;;-1:-1:-1;;;;;124126:4:0;:20;;-1:-1:-1;124126:20:0;;-1:-1:-1;124126:72:0;;124147:12;;124161:6;;124169:11;;124182:15;;124126:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;124245:9:0;;124211:87;;-1:-1:-1;;;124211:87:0;;-1:-1:-1;;;;;124211:4:0;:21;;;-1:-1:-1;124211:21:0;;-1:-1:-1;124211:87:0;;124233:10;;124245:9;;;124256:11;;;;124282:15;;124211:87;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;124309:14:0;:32;;;;;;;;;-1:-1:-1;;;124309:32:0;-1:-1:-1;;;;124309:32:0;;;;;;;;;;-1:-1:-1;;;;;123554:795:0:o;85239:43::-;85281:1;85239:43;:::o;125866:159::-;126004:11;;125927:7;125980:36;;;:23;:36;;;;;;125954:63;;125962:4;125954:21;;-1:-1:-1;;;;;125980:36:0;125954:25;:63::i;88561:1968::-;88711:11;;88613:25;88760:34;;;:20;:34;;;;;;;;;88813:15;:29;;;;;:42;88613:25;;;;88711:11;;-1:-1:-1;;;;;88760:34:0;;-1:-1:-1;;;88813:42:0;;;;;:63;;-1:-1:-1;88859:17:0;;88813:63;88805:91;;;;-1:-1:-1;;;88805:91:0;;;;;;;:::i;:::-;88907:18;88928:23;;;:9;:23;;;;;:34;-1:-1:-1;;;;;88928:34:0;88977:14;;88973:683;;89008:24;89035:21;:19;:21::i;:::-;89008:48;-1:-1:-1;89094:123:0;89129:50;89168:10;89129:34;89008:48;89150:12;89129:20;:34::i;89094:123::-;89295:37;;;;:23;:37;;;;;;89071:146;;-1:-1:-1;89252:181:0;;89071:146;;89287:64;;-1:-1:-1;;;;;89295:37:0;89338:12;89287:50;:64::i;:::-;:108;;;;;;89414:4;89252:16;:181::i;:::-;89232:201;;88973:683;;;;89495:1;89455:37;;;:23;:37;;;;;;-1:-1:-1;;;;;89455:37:0;:41;89451:205;;89550:37;;;;:23;:37;;;;;;89533:61;;-1:-1:-1;;;;;89550:37:0;;89533:16;:61::i;:::-;89513:81;-1:-1:-1;89632:12:0;;-1:-1:-1;89451:205:0;89691:30;;;89786:32;:20;:30;:32::i;:::-;89757:1;89742:16;;89732:27;;;;:9;:27;;;;;:86;;-1:-1:-1;;;;;89732:86:0;;;-1:-1:-1;;;89732:86:0;;;;;;;;;89870:118;:92;89945:16;89870:56;89878:10;89908:17;89870:37;:56::i;:::-;:74;;:92::i;:118::-;89854:1;89839:16;;89829:27;;;;:9;:27;;;;;:159;;-1:-1:-1;;;;;;89829:159:0;-1:-1:-1;;;;;89829:159:0;;;;;;;;90073:49;90019:38;;:103;90001:186;;;90149:19;:26;;-1:-1:-1;;;;90149:26:0;-1:-1:-1;;;90149:26:0;;;90001:186;90203:17;;90199:66;;90237:16;:14;:16::i;:::-;90296:1;90281:12;:16;:40;;;;;90320:1;90301:16;:20;90281:40;90277:108;;;90338:35;90352:20;90338:13;:35::i;:::-;90395:22;:20;:22::i;:::-;90450;:11;;:20;:22::i;:::-;90474:14;;90499:11;;90490:21;;;;90474:14;90490:21;;;;;;;;;:30;90435:86;;-1:-1:-1;;;;;90435:86:0;;;;;;;;-1:-1:-1;;;90474:14:0;;;;;;;90490:30;;90435:86;:::i;:::-;;;;;;;;88561:1968;;;;;;:::o;118291:146::-;-1:-1:-1;;;;;118402:13:0;;118360:6;118402:13;;;:7;:13;;;;;;;;118386:43;;;;;;;;;-1:-1:-1;;;;;118386:43:0;;;;-1:-1:-1;;;;;;;;118386:43:0;;;;;;;;;;;-1:-1:-1;;;118386:43:0;;;;;;;;;118417:11;;118386:43;;;:15;:43::i;:::-;118379:50;;118291:146;;;;:::o;126033:99::-;126122:2;126033:99;:::o;114019:515::-;114141:17;;;114269:9;114265:60;;114302:11;;114295:18;;114265:60;-1:-1:-1;;;114350:21:0;;;;:15;:21;;;;;:34;;-1:-1:-1;;;114350:34:0;;;;114419:43;-1:-1:-1;;;114419:43:0;;;;;114490:36;;114019:515::o;119027:149::-;119102:7;119129:15;;;:9;:15;;;;;:39;-1:-1:-1;;;119129:39:0;;-1:-1:-1;;;;;119129:39:0;;119027:149::o;115242:902::-;115760:9;;115793:8;;115825:4;;115853:11;;115888:6;;115918:12;;115954:16;;115986:5;;116006:14;;116035:15;;116073:51;;115242:902::o;113004:496::-;-1:-1:-1;;;;;113322:25:0;113117:30;113322:25;;;:19;:25;;;;;;;;:30;113413:15;:21;;;;;;:26;-1:-1:-1;;;;;113322:30:0;;;;-1:-1:-1;;;113367:31:0;;;;;;;113413:26;;;;113454:27;;;;;113004:496::o;112700:119::-;-1:-1:-1;;;;;112790:13:0;112763:7;112790:13;;;:7;:13;;;;;:21;-1:-1:-1;;;;;112790:21:0;;112700:119::o;125339:109::-;125403:7;125339:109;:::o;119413:308::-;-1:-1:-1;;;;;119643:13:0;119533:14;119643:13;;;:7;:13;;;;;:21;-1:-1:-1;;;;;119643:21:0;;;-1:-1:-1;;;;;;;;119666:18:0;;;;;-1:-1:-1;;;119686:26:0;;;;119413:308::o;92980:645::-;93048:12;93076:19;93097:24;93125:15;:13;:15::i;:::-;93174:11;;93216:10;93151:20;93200:27;;;:15;:27;;;;;:33;93073:67;;-1:-1:-1;93073:67:0;;-1:-1:-1;93174:11:0;-1:-1:-1;;;;93200:33:0;;-1:-1:-1;;;;;93200:33:0;93196:127;;93271:10;93255:27;;;;:15;:27;;;;;:56;;-1:-1:-1;;;;;;93255:56:0;-1:-1:-1;;;;;93255:56:0;;;;;93196:127;93349:10;93333:27;;;;:15;:27;;;;;;;;:43;;-1:-1:-1;;;;;;;;93333:43:0;;;;;;;;;;;;;;;;;;;;93387:34;;;:20;:34;;;;;;:44;;;;;;;;;-1:-1:-1;;;;;;93387:44:0;;;;;;;93442:85;;93349:10;93489:11;;93442:85;;93510:16;93442:34;:85::i;:::-;93574:12;93562:10;-1:-1:-1;;;;;93543:52:0;;93588:6;93543:52;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;93613:4:0;;92980:645;-1:-1:-1;;;;92980:645:0:o;85289:47::-;;;;;;;;;;;;;;-1:-1:-1;;;85289:47:0;;;;:::o;98886:208::-;86470:11;;98954:19;86461:21;;;:8;:21;;;;;:30;-1:-1:-1;;;;;86461:30:0;86442:15;:49;;86434:72;;;;-1:-1:-1;;;86434:72:0;;;;;;;:::i;:::-;98986:22:::1;99011:6;-1:-1:-1::0;;;;;99011:18:0::1;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;98986:45;;99049:37;99071:14;99049:21;:37::i;:::-;99042:44;;;98886:208:::0;:::o;116152:384::-;116267:15;;;116380:9;116376:60;;116413:11;;116406:18;;116376:60;-1:-1:-1;;;116454:14:0;;;;:8;:14;;;;;;;;:23;;116507:20;;;-1:-1:-1;;;;;116454:23:0;;;;-1:-1:-1;;;116479:26:0;;;;;116152:384::o;126140:115::-;126236:10;126140:115;:::o;118570:111::-;118654:19;;-1:-1:-1;;;118654:19:0;;;;118653:20;;118570:111::o;117529:673::-;117586:15;117618:11;;117633:1;117618:16;117614:540;;;-1:-1:-1;117658:28:0;117651:35;;117614:540;117736:11;;117727:21;;;;:8;:21;;;;;:30;-1:-1:-1;;;;;117727:30:0;117708:15;:49;117704:450;;117797:15;;-1:-1:-1;;;;;;;;117797:15:0;;;;83732:13;117797:26;117778:15;:45;117774:118;;-1:-1:-1;117851:25:0;117844:32;;117774:118;-1:-1:-1;117913:22:0;117906:29;;117704:450;117998:11;;117989:21;;;;:8;:21;;;;;:30;-1:-1:-1;;;;;117989:30:0;117971:15;:48;:107;;;;-1:-1:-1;118053:11:0;;118037:28;;;;:15;:28;;;;;:41;-1:-1:-1;;;118037:41:0;;;;118036:42;117971:107;117953:201;;;-1:-1:-1;118112:30:0;118105:37;;117953:201;-1:-1:-1;118171:23:0;117529:673;:::o;113508:503::-;113833:11;;113859:14;;113833:11;;-1:-1:-1;;;113859:14:0;;;;;-1:-1:-1;;;113888:16:0;;;;;-1:-1:-1;;;;;113919:9:0;;;;-1:-1:-1;;;113943:15:0;;;;;;-1:-1:-1;;;113973:19:0;;;;;;113508:503::o;111278:169::-;111358:4;111382:57;111397:10;111409:9;111420:18;:6;:16;:18::i;99206:1315::-;86470:11;;86461:21;;;;:8;:21;;;;;:30;-1:-1:-1;;;;;86461:30:0;86442:15;:49;;86434:72;;;;-1:-1:-1;;;86434:72:0;;;;;;;:::i;:::-;86594:15:::1;::::0;-1:-1:-1;;;;;;;;86594:15:0;;::::1;;83732:13;86594:26;86576:15;:44;86568:66;;;;-1:-1:-1::0;;;86568:66:0::1;;;;;;;:::i;:::-;99280:22:::2;99305:6;-1:-1:-1::0;;;;;99305:18:0::2;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99280:45;;99336:19;99358:37;99380:14;99358:21;:37::i;:::-;99336:59:::0;-1:-1:-1;99410:16:0;99406:100:::2;;99457:37;99479:14;99457:21;:37::i;:::-;99443:51;;99406:100;99519:14;99535:17:::0;99554:30:::2;;:::i;:::-;99769:11;::::0;99748:33:::2;::::0;;;:20:::2;:33;::::0;;;;;;99796:9:::2;::::0;99588:257;;-1:-1:-1;;;99588:257:0;;-1:-1:-1;;;;;99588:8:0::2;:38;::::0;::::2;::::0;:257:::2;::::0;99641:9:::2;::::0;99673:4:::2;::::0;99693:11;;99719:14;;-1:-1:-1;;;;;99796:9:0::2;::::0;99820:14:::2;::::0;99588:257:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;99518:327:::0;;-1:-1:-1;99518:327:0;-1:-1:-1;99518:327:0;-1:-1:-1;99862:13:0;;99858:81:::2;;99892:4;-1:-1:-1::0;;;;;99892:15:0::2;;99915:9;99892:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;99858:81;99955:10:::0;;99951:75:::2;;99982:32;99994:11;100007:6;99982:11;:32::i;:::-;100042:15;::::0;::::2;::::0;:19;100038:244:::2;;100194:15:::0;;::::2;100211::::0;::::2;::::0;100155:72:::2;::::0;-1:-1:-1;;;100155:72:0;;:9:::2;-1:-1:-1::0;;;;;100155:38:0::2;::::0;::::2;::::0;:72:::2;::::0;::::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;100129:141;;;;-1:-1:-1::0;;;100129:141:0::2;;;;;;;:::i;:::-;100310:26;:15;:24;:26::i;:::-;100292:15;:44:::0;;-1:-1:-1;;;;100292:44:0::2;-1:-1:-1::0;;;;;;;;100292:44:0;;::::2;;;::::0;;100448:15;;::::2;100486::::0;::::2;::::0;100352:161:::2;::::0;;;::::2;::::0;;::::2;::::0;::::2;::::0;::::2;::::0;100419:6;;100486:15;100352:161:::2;:::i;:::-;;;;;;;;86645:1;;;;;99206:1315::o:0;110359:478::-;110409:27;;:::i;:::-;-1:-1:-1;110447:10:0;110439:19;;;;:7;:19;;;;;;;;;110409:49;;;;;;;;;-1:-1:-1;;;;;110409:49:0;;;;-1:-1:-1;;;;;;;;110409:49:0;;;;;;;;;;;-1:-1:-1;;;110409:49:0;;;;;;;;;;;;110519:11;;110493:38;;110409:49;;110493:15;:38::i;:::-;-1:-1:-1;;;;;110469:62:0;;;:21;;;:62;;;110565:11;;110542:35;;;:13;;;:35;110588:47;;;;-1:-1:-1;;;110588:47:0;;;;;;;:::i;:::-;110669:21;;;;;;110646:20;110701:25;;;110745:10;110737:19;;;:7;:19;;;;;;;;:30;;;;;;;;;;-1:-1:-1;;;;;;110737:30:0;;;-1:-1:-1;;;;;110737:30:0;;;;-1:-1:-1;;;;110737:30:0;-1:-1:-1;;;;;;;;110737:30:0;;;;;-1:-1:-1;;;;;110737:30:0;-1:-1:-1;;;110737:30:0;;;;;;;;;;;;;;110646:44;;110778:51;;-1:-1:-1;;;;;110778:12:0;:25;;110646:44;110778:25;:51::i;119806:140::-;119926:11;;119905:33;;;;:20;:33;;;;;;;;;119898:40;;;;;;;;;;;;;;;;;119869:16;;119898:40;;;119905:33;119898:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;119806:140;:::o;95476:296::-;95527:17;95546:19;95578:24;95658:15;:13;:15::i;:::-;95613:60;;-1:-1:-1;95613:60:0;-1:-1:-1;95613:60:0;-1:-1:-1;95684:80:0;95719:10;95613:60;95744:1;95613:60;95684:34;:80::i;:::-;95476:296;;;:::o;96699:2179::-;86733:11;;86724:21;;;;:8;:21;;;;;:30;-1:-1:-1;;;;;86724:30:0;86706:15;:48;86698:72;;;;-1:-1:-1;;;86698:72:0;;;;;;;:::i;:::-;96789:11:::1;::::0;96766:20:::1;96820:29:::0;;;:15:::1;:29;::::0;;;;:42;-1:-1:-1;;;96820:42:0;::::1;;;96819:43;96811:63;;;;-1:-1:-1::0;;;96811:63:0::1;;;;;;;:::i;:::-;96889:29;::::0;;;:15:::1;:29;::::0;;;;:44;::::1;;96885:167;;97002:38;:9;-1:-1:-1::0;;;;;97002:25:0::1;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:36;:38::i;:::-;96955:29;::::0;;;:15:::1;:29;::::0;;;;:85;;-1:-1:-1;;96955:85:0::1;;::::0;;;::::1;::::0;;;::::1;::::0;;96885:167:::1;97109:15;97218:22:::0;;;:8:::1;:22;::::0;;;;;:31;-1:-1:-1;;97295:16:0;;97286:26;;;;;:35;97370:32;;-1:-1:-1;;;97370:32:0;;97109:15;;;;-1:-1:-1;;;;;97218:31:0;;::::1;::::0;97286:35;::::1;::::0;97109:15;;-1:-1:-1;;;;;97370:4:0::1;:17;::::0;::::1;::::0;:32:::1;::::0;97396:4:::1;::::0;97370:32:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;97347:55:::0;-1:-1:-1;97421:16:0;;97417:75:::1;;97458:4;-1:-1:-1::0;;;;;97458:16:0::1;;:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;97417:75;-1:-1:-1::0;97519:29:0::1;::::0;;;:15:::1;:29;::::0;;;;:51;-1:-1:-1;;;97519:51:0;::::1;;;97515:215;;97605:16;::::0;-1:-1:-1;;;97605:16:0;::::1;;;::::0;-1:-1:-1;97515:215:0::1;;;97667:29;::::0;;;:15:::1;:29;::::0;;;;:51;-1:-1:-1;;;97667:51:0;::::1;;;::::0;-1:-1:-1;97515:215:0::1;97746:29;::::0;;;:15:::1;:29;::::0;;;;:44;97806:2:::1;97746:44;::::0;;::::1;:57:::0;;::::1;:62:::0;;::::1;;97742:286;;;97866:29;::::0;;;:15:::1;:29;::::0;;;;:62;;::::1;97849:2;97836:15:::0;::::1;97866:62:::0;;::::1;-1:-1:-1::0;;;97866:62:0::1;-1:-1:-1::0;;97866:62:0;;::::1;::::0;;;::::1;::::0;;;97836:15;-1:-1:-1;97742:286:0::1;;;97972:29;::::0;;;:15:::1;:29;::::0;;;;:44;::::1;;::::0;-1:-1:-1;97742:286:0::1;98045:22;::::0;::::1;98040:586;98073:8;98069:12;;:1;:12;98040:586;;;98125:154;98163:1;98183:19;98221:8;98248:16;98125:19;:154::i;:::-;98103:176;;98322:1;98300:19;:23;;;98296:319;;;98364:1;98353:8;:12;98348:17;;:1;:17;98344:231;;;98390:29;::::0;;;:15:::1;:29;::::0;;;;:49;;-1:-1:-1;;;;98390:49:0::1;-1:-1:-1::0;;;98390:49:0::1;::::0;;98344:231:::1;;;98488:29;::::0;;;:15:::1;:29;::::0;;;;:67;;-1:-1:-1;;98488:67:0::1;-1:-1:-1::0;;;98553:1:0::1;98549:5:::0;::::1;98488:67;;;;::::0;;98344:231:::1;98593:7;;;;;;;;;98296:319;98083:3;;98040:586;;;-1:-1:-1::0;98654:29:0::1;::::0;;;:15:::1;:29;::::0;;;;:44;::::1;98642:56:::0;;::::1;98654:44:::0;::::1;98642:56;98638:233;;;98715:29;::::0;;;:15:::1;:29;::::0;;;;:49;;-1:-1:-1;;;;98715:49:0::1;-1:-1:-1::0;;;98715:49:0::1;::::0;;98638:233:::1;;;98797:29;::::0;;;:15:::1;:29;::::0;;;;:62;;-1:-1:-1;;98797:62:0::1;-1:-1:-1::0;;;98797:62:0::1;::::0;::::1;;;::::0;;98638:233:::1;86781:1;;;;;;96699:2179::o:0;119184:221::-;119324:7;119356:28;;;:22;:28;;;;;;;;:41;;;;;;;;;;119184:221::o;118877:142::-;-1:-1:-1;;;;;118985:17:0;;;118958:7;118985:17;;;:10;:17;;;;;;;;:26;;;;;;;;;;;;-1:-1:-1;;;;;118985:26:0;;118877:142::o;114877:357::-;115088:9;;115057:44;;-1:-1:-1;;;115057:44:0;;115012:19;;-1:-1:-1;;;;;115057:8:0;:23;;;;:44;;115081:5;;-1:-1:-1;;;;;115088:9:0;;;;115057:44;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;115049:52;-1:-1:-1;115118:9:0;115114:60;;115151:11;;115144:18;;115114:60;-1:-1:-1;115191:28:0;;;;:22;:28;;;;;;;;:35;;;;;;;;;;114877:357::o;118445:117::-;118502:20;118542:12;118535:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;118535:19:0;;;;;-1:-1:-1;;;118535:19:0;;;;;;;;;;;;;;;;;;;;;;;;;118445:117;:::o;124428:130::-;87041:19;;124491:12;;-1:-1:-1;;;87041:19:0;;;;87040:20;87032:46;;;;-1:-1:-1;;;87032:46:0;;;;;;;:::i;:::-;124526:24:::1;124540:9;124526:13;:24::i;90758:272::-:0;87154:10;-1:-1:-1;;;;;87168:5:0;87154:19;;87146:45;;;;-1:-1:-1;;;87146:45:0;;;;;;;:::i;:::-;86838:11:::1;::::0;86830:40:::1;;;;-1:-1:-1::0;;;86830:40:0::1;;;;;;;:::i;:::-;90872:12:::0;-1:-1:-1;;;;;90858:26:0;::::2;;::::0;::::2;::::0;:66:::2;;-1:-1:-1::0;90902:22:0;-1:-1:-1;;;;;90888:36:0;::::2;;;90858:66;90850:91;;;;-1:-1:-1::0;;;90850:91:0::2;;;;;;;:::i;:::-;90952:12;90970:51;;;;;;;;90982:22;:11;;:20;:22::i;:::-;91007:1;90982:26:::0;;::::2;-1:-1:-1::0;;;;;90970:51:0;;::::2;::::0;;;;::::2;;::::0;;::::2;::::0;90952:70;;;;::::2;::::0;;-1:-1:-1;90952:70:0;;;;;;;;;;::::2;::::0;;;;;::::2;::::0;-1:-1:-1;;90952:70:0;;::::2;::::0;;::::2;::::0;;;::::2;-1:-1:-1::0;;;;90952:70:0::2;-1:-1:-1::0;;;90952:70:0;;;::::2;;::::0;;;::::2;::::0;;90758:272::o;114542:327::-;114646:18;;114719:9;114715:60;;114752:11;;114745:18;;114715:60;-1:-1:-1;;114793:15:0;;;;:9;:15;;;;;:26;-1:-1:-1;;;;;114793:26:0;;;;-1:-1:-1;;;114821:39:0;;;;;114542:327::o;45582:184::-;45639:7;-1:-1:-1;;;45667:5:0;:14;45659:67;;;;-1:-1:-1;;;45659:67:0;;;;;;;:::i;:::-;-1:-1:-1;45752:5:0;45582:184::o;18937:471::-;18995:7;19240:6;19236:47;;-1:-1:-1;19270:1:0;19263:8;;19236:47;19307:5;;;19311:1;19307;:5;:1;19331:5;;;;;:10;19323:56;;;;-1:-1:-1;;;19323:56:0;;;;;;;:::i;19884:132::-;19942:7;19969:39;19973:1;19976;19969:39;;;;;;;;;;;;;;;;;:3;:39::i;125533:246::-;125619:7;125643:5;125639:133;;;-1:-1:-1;125681:15:0;125672:24;;125665:31;;125639:133;-1:-1:-1;125745:15:0;125736:24;;125729:31;;18047:136;18105:7;18132:43;18136:1;18139;18132:43;;;;;;;;;;;;;;;;;:3;:43::i;112297:395::-;-1:-1:-1;;;;;112436:13:0;;112415:4;112436:13;;;:7;:13;;;;;:21;-1:-1:-1;;;;;112436:30:0;;;:21;;:30;112432:75;;;-1:-1:-1;112490:5:0;112483:12;;112432:75;112517:45;112536:4;112554:6;-1:-1:-1;;;;;112547:14:0;-1:-1:-1;;112542:19:0;112517:18;:45::i;:::-;112573:38;112592:2;112603:6;-1:-1:-1;;;;;112596:14:0;112573:18;:38::i;:::-;112642:2;-1:-1:-1;;;;;112627:35:0;112636:4;-1:-1:-1;;;;;112627:35:0;;112654:6;-1:-1:-1;;;;;112646:15:0;112627:35;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;112680:4:0;112297:395;;;;;:::o;17583:181::-;17641:7;17673:5;;;17697:6;;;;17689:46;;;;-1:-1:-1;;;17689:46:0;;;;;;;:::i;105557:355::-;105649:14;;105688:11;;105678:22;;;;:9;:22;;;;;;:46;105649:14;105749:15;;;105739:26;;;;;;:50;105603:276;;-1:-1:-1;;;105603:276:0;;-1:-1:-1;;;;;105603:8:0;:31;;;;:276;;-1:-1:-1;;;105649:14:0;;;;;;-1:-1:-1;;;;;;;;105678:46:0;;;;;;;105739:50;;;;;;105804:5;;105832:6;;105854:14;;105603:276;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105890:14;:12;:14::i;124705:307::-;124864:11;;124787:14;124843:33;;;:20;:33;;;;;;124804:148;;124835:86;;124908:12;;124835:68;;-1:-1:-1;;;;;124843:33:0;124882:20;124835:46;:68::i;:86::-;124936:5;124804:16;:148::i;:::-;124787:165;;124963:41;124984:10;124997:6;124963:12;:41::i;91038:1015::-;91090:21;91114:8;-1:-1:-1;;;;;91114:25:0;;:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91090:51;;91152:22;91177:6;-1:-1:-1;;;;;91177:18:0;;:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91311:9;;91237:123;;-1:-1:-1;;;91237:123:0;;91152:45;;-1:-1:-1;91208:26:0;;-1:-1:-1;;;;;91237:8:0;:30;;;;:123;;91152:45;;-1:-1:-1;;;;;91311:9:0;;;;91335:14;;91237:123;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91208:152;;91373:32;91390:14;91373:16;:32::i;:::-;91457:13;91473:16;-1:-1:-1;;;;;91473:28:0;;91516:9;91540:29;:18;:27;:29::i;:::-;91584:24;:13;:22;:24::i;:::-;91473:146;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;91457:162;;91631:18;91659:9;-1:-1:-1;;;;;91659:17:0;;91677:5;91659:24;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;91694:51:0;;-1:-1:-1;;;91694:51:0;;91630:53;;-1:-1:-1;;;;;;;91694:26:0;;;;;:51;;91729:4;;-1:-1:-1;;83694:2:0;91694:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;91758:11:0;:16;;91773:1;91758:16;;;91785:27;;:::i;:::-;91815:122;;;;;;;;91838:24;:13;:22;:24::i;:::-;-1:-1:-1;;;;;91815:122:0;;;;;91877:29;:18;:27;:29::i;:::-;-1:-1:-1;;;;;91815:122:0;;;;;;;;;;;;91957:11;;-1:-1:-1;91948:21:0;;;:8;:21;;;;;;;;:35;;;;;;;;-1:-1:-1;;91948:35:0;;;;;;;-1:-1:-1;;;;91948:35:0;-1:-1:-1;;;91948:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;91994:51;-1:-1:-1;;;91994:51:0;;91948:35;;-1:-1:-1;91994:11:0;-1:-1:-1;;;;;91994:36:0;;;;:51;;92031:13;;91994:51;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91038:1015;;;;;;:::o;46065:179::-;46121:6;-1:-1:-1;;;46148:5:0;:13;46140:65;;;;-1:-1:-1;;;46140:65:0;;;;;;;:::i;109014:1224::-;109187:24;;;;109226:19;;-1:-1:-1;;;;;109226:23:0;;;;;:50;;;109272:4;109253:11;:16;;;-1:-1:-1;;;;;109253:23:0;;109226:50;109222:1009;;;109315:12;:19;;-1:-1:-1;;109315:23:0;;;109293:12;;-1:-1:-1;;;;;109377:19:0;;;;;;;;;;;;;;;;;:24;109437:12;:19;;-1:-1:-1;;;;;109377:24:0;;;;-1:-1:-1;109437:12:0;;:19;;;;;;;;;;;;;;;;;;:25;-1:-1:-1;;;109437:25:0;;-1:-1:-1;;;;;109437:25:0;;-1:-1:-1;109496:4:0;109479:741;109506:11;:16;;;-1:-1:-1;;;;;109502:20:0;:1;:20;109479:741;;;109556:13;-1:-1:-1;;;;;109552:17:0;:1;:17;109548:323;;;109725:1;109716:10;;;;109763:12;109776:5;-1:-1:-1;;;;;109763:19:0;;;;;;;;;;;;;;;;:25;;;;;;;;;;-1:-1:-1;;;;;109763:25:0;109749:39;;109827:12;109840:5;-1:-1:-1;;;;;109827:19:0;;;;;;;;;;;;;;;;;;:24;-1:-1:-1;;;;;109827:24:0;;-1:-1:-1;109548:323:0;110128:12;;;;:9;:12;;;;;:23;110102:19;;110006:198;;:165;;110076:76;;-1:-1:-1;;;;;110128:23:0;;;;110077:45;;-1:-1:-1;;;;;110077:20:0;;;:45;:24;:45::i;110076:76::-;-1:-1:-1;;;;;110006:21:0;;;:47;:165::i;:::-;:196;:198::i;:::-;109991:213;-1:-1:-1;;;109524:3:0;109479:741;;;;109222:1009;;;109014:1224;;;;:::o;93633:1697::-;93849:11;;93921:10;93708:17;93905:27;;;:15;:27;;;;;;;;:32;94058:19;:31;;;;;:36;93708:17;;;;;;-1:-1:-1;;;;;93905:32:0;;;;-1:-1:-1;;;93983:33:0;;;;;;;94058:36;;;;94137:37;;;94189:17;94185:66;;94231:1;94234;94237;94223:16;;;;;;;;;;;;;94185:66;-1:-1:-1;;;;;94267:29:0;;;;;;:71;;;94315:23;-1:-1:-1;;;;;94300:38:0;:12;:38;94267:71;94263:513;;;-1:-1:-1;;;;;94506:1:0;94480:27;;94472:36;;94462:47;;;;:9;:47;;;;;:71;94367:246;;94402:172;;94561:12;;94402:132;;:33;;;;-1:-1:-1;;;94462:71:0;;;;94402:59;:132::i;94367:246::-;94355:258;-1:-1:-1;94632:13:0;;94628:88;;94666:34;94678:10;94690:9;94666:11;:34::i;:::-;94753:10;94737:27;;;;:15;:27;;;;;94730:34;94263:513;-1:-1:-1;;;;;94792:26:0;;;;;;:65;;;94837:20;-1:-1:-1;;;;;94822:35:0;:12;:35;94792:65;94788:454;;;-1:-1:-1;;;;;95039:1:0;95016:24;;95006:35;;;;;;:9;:35;;;;;:59;94888:235;;94923:162;;-1:-1:-1;;;95006:59:0;;;;;94923:48;;:30;;94958:12;94923:34;:48::i;94888:235::-;95219:10;95199:31;;;;:19;:31;;;;;95192:38;94874:249;-1:-1:-1;;;;;;95138:39:0;;;-1:-1:-1;94788:454:0;95285:12;95273:10;-1:-1:-1;;;;;95257:65:0;;95299:9;95310:11;95257:65;;;;;;;:::i;:::-;;;;;;;;93633:1697;;;;;;;;;:::o;107791:1014::-;107968:30;;:::i;:::-;-1:-1:-1;;;;;;108001:14:0;;;;;;:7;:14;;;;;;;;;107968:47;;;;;;;;;-1:-1:-1;;;;;107968:47:0;;;;-1:-1:-1;;;;;;;;107968:47:0;;;;;;;;;;;-1:-1:-1;;;107968:47:0;;;;;;;;;;;;108083:14;;108079:313;;108141:34;108157:11;108170:4;108141:15;:34::i;:::-;-1:-1:-1;;;;;108114:61:0;;;:24;;;:61;108190:31;;:16;;;:31;108288:19;;108280:100;;:70;;-1:-1:-1;;;;;108280:28:0;108339:9;108280:50;:70::i;:100::-;-1:-1:-1;;;;;108258:122:0;;;108079:313;108481:41;108497:11;108510;;108481:15;:41::i;:::-;-1:-1:-1;;;;;108454:68:0;;;:24;;;:68;108559:11;;108533:38;:16;;;:38;108633:17;;108629:130;;108697:19;;108689:58;;:46;;-1:-1:-1;;;;;108689:28:0;108722:12;108689:32;:46::i;:58::-;-1:-1:-1;;;;;108667:80:0;;;108629:130;-1:-1:-1;;;;;108769:14:0;;;;;;;;:7;:14;;;;;;;;;:28;;;;;;;;;;;;;-1:-1:-1;;;;;;108769:28:0;;;-1:-1:-1;;;;;108769:28:0;;;;;;;-1:-1:-1;;;;108769:28:0;-1:-1:-1;;;;;;;;108769:28:0;;;;;-1:-1:-1;;;;;108769:28:0;-1:-1:-1;;;108769:28:0;;;;;;;;;;;;-1:-1:-1;;;107791:1014:0:o;103077:995::-;103280:9;;103208:121;;-1:-1:-1;;;103208:121:0;;103150:19;;;;-1:-1:-1;;;;;103208:8:0;:28;;;;:121;;103251:14;;-1:-1:-1;;;;;103280:9:0;;;;103304:14;;103208:121;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103363:11;;103182:147;;-1:-1:-1;103385:20:0;;:::i;:::-;-1:-1:-1;103408:22:0;;;;:8;:22;;;;;;;;;103385:45;;;;;;;;;-1:-1:-1;;;;;103385:45:0;;;;;-1:-1:-1;;;103385:45:0;;;;;;;;;;;;;;;;;;;;;103459:47;;103490:15;103459:12;:47::i;:::-;103634:16;;;;103665:13;;103693:10;;;;;103531:183;;-1:-1:-1;;;103531:183:0;;103441:65;;-1:-1:-1;;;;;;103531:16:0;:34;;;;:183;;103580:9;;103441:65;;103531:183;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103517:197;;103807:14;103803:262;;;103945:9;;103900:62;;-1:-1:-1;;;103900:62:0;;103838:139;;103870:11;;-1:-1:-1;;;;;103900:8:0;:28;;;;:62;;103929:14;;-1:-1:-1;;;;;103945:9:0;;;;;;103900:62;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;103838:13;:139::i;:::-;103803:262;;;104010:43;104024:11;104037:15;104010:13;:43::i;:::-;103077:995;;;;;;:::o;102187:882::-;102348:9;;102308:53;;-1:-1:-1;;;102308:53:0;;102265:7;;;;-1:-1:-1;;;;;102308:8:0;:23;;;;:53;;102332:14;;-1:-1:-1;;;;;102348:9:0;;;;;;102308:53;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102470:11;;102380:54;102447:35;;;:22;:35;;;;;;;;102497:32;;;;;;;;;;;102285:76;;-1:-1:-1;102447:35:0;102497:37;102493:109;;102558:32;;;;;;;;;;;-1:-1:-1;102551:39:0;;102493:109;102706:1;102689:373;102714:1;102709;:6;102689:373;;102775:9;;-1:-1:-1;;;;;102775:9:0;:13;;102760:28;;102741:48;;;;;;;;;;;;:53;102737:149;;102856:9;;-1:-1:-1;;;;;102856:9:0;:13;102841:28;;;102822:48;;;;;;;;;;;;;;-1:-1:-1;102815:55:0;;102737:149;102940:9;;-1:-1:-1;;;;;102940:9:0;:13;;102925:28;;102906:48;;;;;;;;;;;;:53;102902:149;;103021:9;;-1:-1:-1;;;;;103021:9:0;:13;103006:28;;;;102987:48;;;;;;;;;;;;;;-1:-1:-1;102980:55:0;;102902:149;102717:3;;102689:373;;125020:311;125206:9;-1:-1:-1;;;;;125238:16:0;;;125262:47;125304:4;125262:37;125294:4;125262:27;:6;125273:15;125262:10;:27::i;:::-;:31;;:37::i;:47::-;125311:11;125238:85;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;125020:311;;;:::o;79643:177::-;79726:86;79746:5;79776:23;;;79801:2;79805:5;79753:58;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;79753:58:0;;;;;;;;;;;;;;-1:-1:-1;;;;;79753:58:0;-1:-1:-1;;;;;;79753:58:0;;;;;;;;;;79726:19;:86::i;:::-;79643:177;;;:::o;46543:179::-;46599:6;-1:-1:-1;;;46626:5:0;:13;46618:65;;;;-1:-1:-1;;;46618:65:0;;;;;;;:::i;101328:851::-;101509:6;101529:24;101555:17;101576:9;-1:-1:-1;;;;;101576:22:0;;101599:11;101576:35;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;101576:35:0;;;;;;;;;;;;:::i;:::-;101528:83;;;;101638:8;-1:-1:-1;;;;;101626:20:0;:9;:20;:79;;;;101663:16;-1:-1:-1;;;;;101651:28:0;:9;:28;:53;;;;-1:-1:-1;;;;;;101683:21:0;;;;101651:53;101622:138;;;101729:19;101722:26;;;;;;101622:138;101770:17;;101798:337;101822:7;:14;101818:1;:18;101798:337;;;101859:19;101888:9;-1:-1:-1;;;;;101888:17:0;;101906:7;101914:1;101906:10;;;;;;;;;;;;;;101888:29;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;101858:59;;;;;101970:153;101998:11;102028;102058:19;102096:12;101970:9;:153::i;:::-;101932:191;;-1:-1:-1;101932:191:0;-1:-1:-1;;101838:3:0;;101798:337;;;;102152:19;102145:26;;;;;101328:851;;;;;;;:::o;92061:665::-;92118:12;92146:19;92167:24;92195:15;:13;:15::i;:::-;92143:67;;;;;92221:80;92256:10;92268:11;92281:1;92284:16;92221:34;:80::i;:::-;92335:11;;92381:10;92312:20;92361:31;;;:19;:31;;;;;:37;-1:-1:-1;;;92361:37:0;;-1:-1:-1;;;;;92361:37:0;92357:135;;92440:10;92420:31;;;;:19;:31;;;;;:60;;-1:-1:-1;;;;;;92420:60:0;-1:-1:-1;;;;;92420:60:0;;;;;92357:135;92543:18;:6;:16;:18::i;:::-;92522:10;92502:31;;;;:19;:31;;;;;:59;;-1:-1:-1;;;;;;;;92502:59:0;;;;;;;;;;;;;;;;;;;;;92613:18;:6;:16;:18::i;:::-;92572:37;;;;:23;:37;;;;;;;:59;;-1:-1:-1;;;;;;92572:59:0;;-1:-1:-1;;;;;92572:59:0;;;;;;;;;;;;;;;92647:49;92572:37;;92663:10;;92647:49;;;;92689:6;;92647:49;:::i;20512:278::-;20598:7;20633:12;20626:5;20618:28;;;;-1:-1:-1;;;20618:28:0;;;;;;;;:::i;:::-;;20657:9;20673:1;20669;:5;;;;;;;20512:278;-1:-1:-1;;;;;20512:278:0:o;18486:192::-;18572:7;18608:12;18600:6;;;;18592:29;;;;-1:-1:-1;;;18592:29:0;;;;;;;;:::i;:::-;-1:-1:-1;;;18644:5:0;;;18486:192::o;107190:593::-;107268:30;;:::i;:::-;-1:-1:-1;;;;;;107301:14:0;;;;;;:7;:14;;;;;;;;;107268:47;;;;;;;;;-1:-1:-1;;;;;107268:47:0;;;;-1:-1:-1;;;;;;;;107268:47:0;;;;;;;;;;;-1:-1:-1;;;107268:47:0;;;;;;;;;;;;107382:11;;107353:41;;107268:47;;107353:15;:41::i;:::-;-1:-1:-1;;;;;107326:68:0;;;:24;;;:68;107431:11;;107405:38;:16;;;:38;-1:-1:-1;107458:10:0;;107454:283;;;107515:19;;107507:102;;:72;;-1:-1:-1;;;;;107507:28:0;107566:11;;;;107507:50;:72::i;:102::-;-1:-1:-1;;;;;107485:124:0;;;107454:283;;;107672:19;;107664:61;;:49;;-1:-1:-1;;;;;107664:28:0;107705:6;107664:32;:49::i;:61::-;-1:-1:-1;;;;;107642:83:0;;;107454:283;-1:-1:-1;;;;;107747:14:0;;;;;;;;:7;:14;;;;;;;;;:28;;;;;;;;;;;;;-1:-1:-1;;;;;;107747:28:0;;;-1:-1:-1;;;;;107747:28:0;;;;;;;-1:-1:-1;;;;107747:28:0;-1:-1:-1;;;;;;;;107747:28:0;;;;;-1:-1:-1;;;;;107747:28:0;-1:-1:-1;;;107747:28:0;;;;;;;;;;;;-1:-1:-1;107190:593:0:o;121252:172::-;121337:79;121350:9;121361:6;121337:79;;;;;;;;;;;;;;;;;:12;:79::i;105227:322::-;105297:18;105318:40;:14;-1:-1:-1;;;;;105337:2:0;105342:15;105337:20;105318:40;:18;:40::i;:::-;105297:61;-1:-1:-1;105373:15:0;105369:173;;105405:9;:27;;-1:-1:-1;;105405:27:0;105417:15;-1:-1:-1;;;;;105405:27:0;;;;105369:173;;;105477:53;105516:2;-1:-1:-1;;;;;105497:15:0;105479:33;;;:2;:33;105478:40;105477:51;:53::i;:::-;105465:9;:65;;-1:-1:-1;;105465:65:0;-1:-1:-1;;;;;105465:65:0;;;;;;;;;;-1:-1:-1;;105227:322:0:o;124566:131::-;124646:43;;-1:-1:-1;;;124646:43:0;;-1:-1:-1;;;;;124646:10:0;:20;;;;:43;;124675:4;;124682:6;;124646:43;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106112:220;106232:7;106264:60;106322:1;106284:35;:15;-1:-1:-1;;;;;106284:35:0;;:19;:35::i;:::-;:39;;;;;106264:15;;106284:39;;106264:19;:60::i;104080:1139::-;104235:11;;;104214:33;;;;:20;:33;;;;;;;;:51;;;;;;;;;;;;;;;;;104299:11;;104276:35;;:22;:35;;;;;:60;;;;;;;;:74;;;104394:35;-1:-1:-1;;;104394:35:0;;104364:24;;-1:-1:-1;;;;;104394:9:0;:22;;;;:35;;104253:11;;104394:35;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;104394:35:0;;;;;;;;;;;;:::i;:::-;104363:66;;;104441:24;104475:9;-1:-1:-1;;;;;104475:17:0;;104493:7;104501:1;104493:10;;;;;;;;;;;;;;104475:29;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;104565:64:0;;-1:-1:-1;;;104565:64:0;;104440;;-1:-1:-1;;;;;;;104565:34:0;;;;;:64;;104608:4;;104623;;104565:64;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104561:159;;104651:57;;-1:-1:-1;;;104651:57:0;;-1:-1:-1;;;;;104651:32:0;;;;;:57;;104692:4;;-1:-1:-1;;83694:2:0;104651:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;104561:159;104733:24;104767:9;-1:-1:-1;;;;;104767:17:0;;104785:7;104793:1;104785:10;;;;;;;;;;;;;;104767:29;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;104813:64:0;;-1:-1:-1;;;104813:64:0;;104732;;-1:-1:-1;;;;;;;104813:34:0;;;;;:64;;104856:4;;104871;;104813:64;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;104809:159;;104899:57;;-1:-1:-1;;;104899:57:0;;-1:-1:-1;;;;;104899:32:0;;;;;:57;;104940:4;;-1:-1:-1;;83694:2:0;104899:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;104809:159;104979:24;105013:9;-1:-1:-1;;;;;105013:17:0;;105031:7;105039:1;105031:10;;;;;;;;;;;;;;105013:29;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;105057:64:0;;-1:-1:-1;;;105057:64:0;;104978;;-1:-1:-1;;;;;;;105057:34:0;;;;;:64;;105100:4;;105115;;105057:64;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;105053:159;;105143:57;;-1:-1:-1;;;105143:57:0;;-1:-1:-1;;;;;105143:32:0;;;;;:57;;105184:4;;-1:-1:-1;;83694:2:0;105143:57;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;104080:1139;;;;;;:::o;81948:761::-;82372:23;82398:69;82426:4;82398:69;;;;;;;;;;;;;;;;;82406:5;-1:-1:-1;;;;;82398:27:0;;;:69;;;;;:::i;:::-;82482:17;;82372:95;;-1:-1:-1;82482:21:0;82478:224;;82624:10;82613:30;;;;;;;;;;;;:::i;:::-;82605:85;;;;-1:-1:-1;;;82605:85:0;;;;;;;:::i;100529:791::-;100795:29;;-1:-1:-1;;;100795:29:0;;100698:6;;;;100768:11;;100698:6;;-1:-1:-1;;;;;100795:14:0;;;;;:29;;100818:4;;100795:29;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:33;100791:469;;;100850:12;100845:336;;101088:39;;-1:-1:-1;;;101088:39:0;;-1:-1:-1;;;;;101088:9:0;:23;;;;:39;;101112:11;;101125:1;;101088:39;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;101161:4;101146:19;;100845:336;101195:4;-1:-1:-1;;;;;101195:12:0;;:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;101247:1;101224:24;;;;100791:469;-1:-1:-1;101278:19:0;;101299:12;;-1:-1:-1;100529:791:0;;-1:-1:-1;;;100529:791:0:o;120808:436::-;120963:29;120985:6;120963:21;:29::i;:::-;120994:12;120955:52;;;;;-1:-1:-1;;;120955:52:0;;;;;;;;:::i;:::-;;121019:12;121037:9;-1:-1:-1;;;;;121037:14:0;121059:6;121037:33;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;121018:52;;;121135:7;121127:45;;;;-1:-1:-1;;;121127:45:0;;;;;;;:::i;:::-;121218:9;-1:-1:-1;;;;;121188:48:0;121211:4;-1:-1:-1;;;;;121188:48:0;;121229:6;121188:48;;;;;;:::i;:::-;;;;;;;;120808:436;;;;:::o;25924:196::-;26027:12;26059:53;26082:6;26090:4;26096:1;26099:12;26059:22;:53::i;120517:182::-;120638:4;120671:20;-1:-1:-1;120661:30:0;;120517:182::o;27301:979::-;27431:12;27464:18;27475:6;27464:10;:18::i;:::-;27456:60;;;;-1:-1:-1;;;27456:60:0;;;;;;;:::i;:::-;27590:12;27604:23;27631:6;-1:-1:-1;;;;;27631:11:0;27651:8;27662:4;27631:36;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27589:78;;;;27682:7;27678:595;;;27713:10;-1:-1:-1;27706:17:0;;-1:-1:-1;27706:17:0;27678:595;27827:17;;:21;27823:439;;28090:10;28084:17;28151:15;28138:10;28134:2;28130:19;28123:44;28038:148;28233:12;28226:20;;-1:-1:-1;;;28226:20:0;;;;;;;;:::i;22809:619::-;22869:4;23337:20;;23180:66;23377:23;;;;;;:42;;-1:-1:-1;;23404:15:0;;;23369:51;-1:-1:-1;;22809: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
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.