Overview
ETH Balance
3 wei
Eth Value
Less Than $0.01 (@ $2,310.27/ETH)More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x61016060 | 12003479 | 1287 days ago | IN | 0 ETH | 0.5029641 |
Loading...
Loading
Contract Name:
BondMakerCollateralizedEth
Compiler Version
v0.7.1+commit.f4a555be
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2021-03-10 */ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.7.1; // File: contracts/BondToken_and_GDOTC/util/TransferETHInterface.sol interface TransferETHInterface { receive() external payable; event LogTransferETH(address indexed from, address indexed to, uint256 value); } // File: contracts/BondToken_and_GDOTC/util/TransferETH.sol abstract contract TransferETH is TransferETHInterface { receive() external payable override { emit LogTransferETH(msg.sender, address(this), msg.value); } function _hasSufficientBalance(uint256 amount) internal view returns (bool ok) { address thisContract = address(this); return amount <= thisContract.balance; } /** * @notice transfer `amount` ETH to the `recipient` account with emitting log */ function _transferETH( address payable recipient, uint256 amount, string memory errorMessage ) internal { require(_hasSufficientBalance(amount), errorMessage); (bool success, ) = recipient.call{value: amount}(""); // solhint-disable-line avoid-low-level-calls require(success, "transferring Ether failed"); emit LogTransferETH(address(this), recipient, amount); } function _transferETH(address payable recipient, uint256 amount) internal { _transferETH(recipient, amount, "TransferETH: transfer amount exceeds balance"); } } // File: @openzeppelin/contracts/math/SafeMath.sol /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: @openzeppelin/contracts/math/SignedSafeMath.sol /** * @title SignedSafeMath * @dev Signed math operations with safety checks that revert on error. */ library SignedSafeMath { int256 constant private _INT256_MIN = -2**255; /** * @dev Returns the multiplication of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(int256 a, int256 b) internal pure returns (int256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow"); int256 c = a * b; require(c / a == b, "SignedSafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two signed integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(int256 a, int256 b) internal pure returns (int256) { require(b != 0, "SignedSafeMath: division by zero"); require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow"); int256 c = a / b; return c; } /** * @dev Returns the subtraction of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(int256 a, int256 b) internal pure returns (int256) { int256 c = a - b; require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow"); return c; } /** * @dev Returns the addition of two signed integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(int256 a, int256 b) internal pure returns (int256) { int256 c = a + b; require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow"); return c; } } // File: @openzeppelin/contracts/utils/SafeCast.sol /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing * all math on `uint256` and `int256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits. */ function toUint8(uint256 value) internal pure returns (uint8) { require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits * * _Available since v3.1._ */ function toInt128(int256 value) internal pure returns (int128) { require(value >= -2**127 && value < 2**127, "SafeCast: value doesn\'t fit in 128 bits"); return int128(value); } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits * * _Available since v3.1._ */ function toInt64(int256 value) internal pure returns (int64) { require(value >= -2**63 && value < 2**63, "SafeCast: value doesn\'t fit in 64 bits"); return int64(value); } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits * * _Available since v3.1._ */ function toInt32(int256 value) internal pure returns (int32) { require(value >= -2**31 && value < 2**31, "SafeCast: value doesn\'t fit in 32 bits"); return int32(value); } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits * * _Available since v3.1._ */ function toInt16(int256 value) internal pure returns (int16) { require(value >= -2**15 && value < 2**15, "SafeCast: value doesn\'t fit in 16 bits"); return int16(value); } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits. * * _Available since v3.1._ */ function toInt8(int256 value) internal pure returns (int8) { require(value >= -2**7 && value < 2**7, "SafeCast: value doesn\'t fit in 8 bits"); return int8(value); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { require(value < 2**255, "SafeCast: value doesn't fit in an int256"); return int256(value); } } // File: contracts/BondToken_and_GDOTC/math/UseSafeMath.sol /** * @notice ((a - 1) / b) + 1 = (a + b -1) / b * for example a.add(10**18 -1).div(10**18) = a.sub(1).div(10**18) + 1 */ library SafeMathDivRoundUp { using SafeMath for uint256; function divRoundUp( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { if (a == 0) { return 0; } require(b > 0, errorMessage); return ((a - 1) / b) + 1; } function divRoundUp(uint256 a, uint256 b) internal pure returns (uint256) { return divRoundUp(a, b, "SafeMathDivRoundUp: modulo by zero"); } } /** * @title UseSafeMath * @dev One can use SafeMath for not only uint256 but also uin64 or uint16, * and also can use SafeCast for uint256. * For example: * uint64 a = 1; * uint64 b = 2; * a = a.add(b).toUint64() // `a` become 3 as uint64 * In addition, one can use SignedSafeMath and SafeCast.toUint256(int256) for int256. * In the case of the operation to the uint64 value, one needs to cast the value into int256 in * advance to use `sub` as SignedSafeMath.sub not SafeMath.sub. * For example: * int256 a = 1; * uint64 b = 2; * int256 c = 3; * a = a.add(int256(b).sub(c)); // `a` becomes 0 as int256 * b = a.toUint256().toUint64(); // `b` becomes 0 as uint64 */ abstract contract UseSafeMath { using SafeMath for uint256; using SafeMathDivRoundUp for uint256; using SafeMath for uint64; using SafeMathDivRoundUp for uint64; using SafeMath for uint16; using SignedSafeMath for int256; using SafeCast for uint256; using SafeCast for int256; } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File: contracts/BondToken_and_GDOTC/bondToken/BondTokenInterface.sol interface BondTokenInterface is IERC20 { event LogExpire(uint128 rateNumerator, uint128 rateDenominator, bool firstTime); function mint(address account, uint256 amount) external returns (bool success); function expire(uint128 rateNumerator, uint128 rateDenominator) external returns (bool firstTime); function simpleBurn(address account, uint256 amount) external returns (bool success); function burn(uint256 amount) external returns (bool success); function burnAll() external returns (uint256 amount); function getRate() external view returns (uint128 rateNumerator, uint128 rateDenominator); } // File: contracts/BondToken_and_GDOTC/oracle/LatestPriceOracleInterface.sol /** * @dev Interface of the price oracle. */ interface LatestPriceOracleInterface { /** * @dev Returns `true`if oracle is working. */ function isWorking() external returns (bool); /** * @dev Returns the last updated price. Decimals is 8. **/ function latestPrice() external returns (uint256); /** * @dev Returns the timestamp of the last updated price. */ function latestTimestamp() external returns (uint256); } // File: contracts/BondToken_and_GDOTC/oracle/PriceOracleInterface.sol /** * @dev Interface of the price oracle. */ interface PriceOracleInterface is LatestPriceOracleInterface { /** * @dev Returns the latest id. The id start from 1 and increments by 1. */ function latestId() external returns (uint256); /** * @dev Returns the historical price specified by `id`. Decimals is 8. */ function getPrice(uint256 id) external returns (uint256); /** * @dev Returns the timestamp of historical price specified by `id`. */ function getTimestamp(uint256 id) external returns (uint256); } // File: contracts/BondToken_and_GDOTC/bondMaker/BondMakerInterface.sol interface BondMakerInterface { event LogNewBond( bytes32 indexed bondID, address indexed bondTokenAddress, uint256 indexed maturity, bytes32 fnMapID ); event LogNewBondGroup( uint256 indexed bondGroupID, uint256 indexed maturity, uint64 indexed sbtStrikePrice, bytes32[] bondIDs ); event LogIssueNewBonds(uint256 indexed bondGroupID, address indexed issuer, uint256 amount); event LogReverseBondGroupToCollateral( uint256 indexed bondGroupID, address indexed owner, uint256 amount ); event LogExchangeEquivalentBonds( address indexed owner, uint256 indexed inputBondGroupID, uint256 indexed outputBondGroupID, uint256 amount ); event LogLiquidateBond(bytes32 indexed bondID, uint128 rateNumerator, uint128 rateDenominator); function registerNewBond(uint256 maturity, bytes calldata fnMap) external returns ( bytes32 bondID, address bondTokenAddress, bytes32 fnMapID ); function registerNewBondGroup(bytes32[] calldata bondIDList, uint256 maturity) external returns (uint256 bondGroupID); function reverseBondGroupToCollateral(uint256 bondGroupID, uint256 amount) external returns (bool success); function exchangeEquivalentBonds( uint256 inputBondGroupID, uint256 outputBondGroupID, uint256 amount, bytes32[] calldata exceptionBonds ) external returns (bool); function liquidateBond(uint256 bondGroupID, uint256 oracleHintID) external returns (uint256 totalPayment); function collateralAddress() external view returns (address); function oracleAddress() external view returns (PriceOracleInterface); function feeTaker() external view returns (address); function decimalsOfBond() external view returns (uint8); function decimalsOfOraclePrice() external view returns (uint8); function maturityScale() external view returns (uint256); function nextBondGroupID() external view returns (uint256); function getBond(bytes32 bondID) external view returns ( address bondAddress, uint256 maturity, uint64 solidStrikePrice, bytes32 fnMapID ); function getFnMap(bytes32 fnMapID) external view returns (bytes memory fnMap); function getBondGroup(uint256 bondGroupID) external view returns (bytes32[] memory bondIDs, uint256 maturity); function generateFnMapID(bytes calldata fnMap) external view returns (bytes32 fnMapID); function generateBondID(uint256 maturity, bytes calldata fnMap) external view returns (bytes32 bondID); } // File: contracts/BondToken_and_GDOTC/bondMaker/BondMakerCollateralizedErc20Interface.sol interface BondMakerCollateralizedErc20Interface is BondMakerInterface { function issueNewBonds(uint256 bondGroupID, uint256 amount) external returns (uint256 bondAmount); } // File: contracts/BondToken_and_GDOTC/util/Time.sol abstract contract Time { function _getBlockTimestampSec() internal view returns (uint256 unixtimesec) { unixtimesec = block.timestamp; // solhint-disable-line not-rely-on-time } } // File: @openzeppelin/contracts/GSN/Context.sol /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File: @openzeppelin/contracts/utils/Address.sol /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return _functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); return _functionCallWithValue(target, data, value, errorMessage); } function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File: @openzeppelin/contracts/token/ERC20/ERC20.sol /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; using Address for address; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for {name} and {symbol}, initializes {decimals} with * a default value of 18. * * To select a different value for {decimals}, use {_setupDecimals}. * * All three of these values are immutable: they can only be set once during * construction. */ constructor (string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; _decimals = 18; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Sets {decimals} to a value other than the default one of 18. * * WARNING: This function should only be called from the constructor. Most * applications that interact with token contracts will not expect * {decimals} to ever change, and may work incorrectly if it does. */ function _setupDecimals(uint8 decimals_) internal { _decimals = decimals_; } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } } // File: @openzeppelin/contracts/access/Ownable.sol /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(_owner == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File: contracts/BondToken_and_GDOTC/bondToken/BondToken.sol abstract contract BondToken is Ownable, BondTokenInterface, ERC20 { using SafeMath for uint256; struct Frac128x128 { uint128 numerator; uint128 denominator; } Frac128x128 internal _rate; constructor( string memory name, string memory symbol, uint8 decimals ) ERC20(name, symbol) { _setupDecimals(decimals); } function mint(address account, uint256 amount) public virtual override onlyOwner returns (bool success) { require(!_isExpired(), "this token contract has expired"); _mint(account, amount); return true; } function transfer(address recipient, uint256 amount) public override(ERC20, IERC20) returns (bool success) { _transfer(msg.sender, recipient, amount); return true; } function transferFrom( address sender, address recipient, uint256 amount ) public override(ERC20, IERC20) returns (bool success) { _transfer(sender, recipient, amount); _approve( sender, msg.sender, allowance(sender, msg.sender).sub(amount, "ERC20: transfer amount exceeds allowance") ); return true; } /** * @dev Record the settlement price at maturity in the form of a fraction and let the bond * token expire. */ function expire(uint128 rateNumerator, uint128 rateDenominator) public override onlyOwner returns (bool isFirstTime) { isFirstTime = !_isExpired(); if (isFirstTime) { _setRate(Frac128x128(rateNumerator, rateDenominator)); } emit LogExpire(rateNumerator, rateDenominator, isFirstTime); } function simpleBurn(address from, uint256 amount) public override onlyOwner returns (bool) { if (amount > balanceOf(from)) { return false; } _burn(from, amount); return true; } function burn(uint256 amount) public override returns (bool success) { if (!_isExpired()) { return false; } _burn(msg.sender, amount); if (_rate.numerator != 0) { uint8 decimalsOfCollateral = _getCollateralDecimals(); uint256 withdrawAmount = _applyDecimalGap(amount, decimals(), decimalsOfCollateral) .mul(_rate.numerator) .div(_rate.denominator); _sendCollateralTo(msg.sender, withdrawAmount); } return true; } function burnAll() public override returns (uint256 amount) { amount = balanceOf(msg.sender); bool success = burn(amount); if (!success) { amount = 0; } } /** * @dev rateDenominator never be zero due to div() function, thus initial _rateDenominator is 0 * can be used for flag of non-expired; */ function _isExpired() internal view returns (bool) { return _rate.denominator != 0; } function getRate() public view override returns (uint128 rateNumerator, uint128 rateDenominator) { rateNumerator = _rate.numerator; rateDenominator = _rate.denominator; } function _setRate(Frac128x128 memory rate) internal { require( rate.denominator != 0, "system error: the exchange rate must be non-negative number" ); _rate = rate; } /** * @dev removes a decimal gap from rate. */ function _applyDecimalGap( uint256 baseAmount, uint8 decimalsOfBase, uint8 decimalsOfQuote ) internal pure returns (uint256 quoteAmount) { uint256 n; uint256 d; if (decimalsOfBase > decimalsOfQuote) { d = decimalsOfBase - decimalsOfQuote; } else if (decimalsOfBase < decimalsOfQuote) { n = decimalsOfQuote - decimalsOfBase; } // The consequent multiplication would overflow under extreme and non-blocking circumstances. require(n < 19 && d < 19, "decimal gap needs to be lower than 19"); quoteAmount = baseAmount.mul(10**n).div(10**d); } function _getCollateralDecimals() internal view virtual returns (uint8); function _sendCollateralTo(address receiver, uint256 amount) internal virtual; } // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: contracts/BondToken_and_GDOTC/bondToken/BondTokenCollateralizedErc20.sol contract BondTokenCollateralizedErc20 is BondToken { using SafeERC20 for ERC20; ERC20 internal immutable COLLATERALIZED_TOKEN; constructor( ERC20 collateralizedTokenAddress, string memory name, string memory symbol, uint8 decimals ) BondToken(name, symbol, decimals) { COLLATERALIZED_TOKEN = collateralizedTokenAddress; } function _getCollateralDecimals() internal view override returns (uint8) { return COLLATERALIZED_TOKEN.decimals(); } function _sendCollateralTo(address receiver, uint256 amount) internal override { COLLATERALIZED_TOKEN.safeTransfer(receiver, amount); } } // File: contracts/BondToken_and_GDOTC/bondToken/BondTokenCollateralizedEth.sol contract BondTokenCollateralizedEth is BondToken, TransferETH { constructor( string memory name, string memory symbol, uint8 decimals ) BondToken(name, symbol, decimals) {} function _getCollateralDecimals() internal pure override returns (uint8) { return 18; } function _sendCollateralTo(address receiver, uint256 amount) internal override { _transferETH(payable(receiver), amount); } } // File: contracts/BondToken_and_GDOTC/bondToken/BondTokenFactory.sol contract BondTokenFactory { address private constant ETH = address(0); function createBondToken( address collateralizedTokenAddress, string calldata name, string calldata symbol, uint8 decimals ) external returns (address createdBondAddress) { if (collateralizedTokenAddress == ETH) { BondTokenCollateralizedEth bond = new BondTokenCollateralizedEth( name, symbol, decimals ); bond.transferOwnership(msg.sender); return address(bond); } else { BondTokenCollateralizedErc20 bond = new BondTokenCollateralizedErc20( ERC20(collateralizedTokenAddress), name, symbol, decimals ); bond.transferOwnership(msg.sender); return address(bond); } } } // File: contracts/BondToken_and_GDOTC/util/Polyline.sol contract Polyline { struct Point { uint64 x; // Value of the x-axis of the x-y plane uint64 y; // Value of the y-axis of the x-y plane } struct LineSegment { Point left; // The left end of the line definition range Point right; // The right end of the line definition range } /** * @notice Return the value of y corresponding to x on the given line. line in the form of * a rational number (numerator / denominator). * If you treat a line as a line segment instead of a line, you should run * includesDomain(line, x) to check whether x is included in the line's domain or not. * @dev To guarantee accuracy, the bit length of the denominator must be greater than or equal * to the bit length of x, and the bit length of the numerator must be greater than or equal * to the sum of the bit lengths of x and y. */ function _mapXtoY(LineSegment memory line, uint64 x) internal pure returns (uint128 numerator, uint64 denominator) { int256 x1 = int256(line.left.x); int256 y1 = int256(line.left.y); int256 x2 = int256(line.right.x); int256 y2 = int256(line.right.y); require(x2 > x1, "must be left.x < right.x"); denominator = uint64(x2 - x1); // Calculate y = ((x2 - x) * y1 + (x - x1) * y2) / (x2 - x1) // in the form of a fraction (numerator / denominator). int256 n = (x - x1) * y2 + (x2 - x) * y1; require(n >= 0, "underflow n"); require(n < 2**128, "system error: overflow n"); numerator = uint128(n); } /** * @notice Checking that a line segment is a valid format. */ function assertLineSegment(LineSegment memory segment) internal pure { uint64 x1 = segment.left.x; uint64 x2 = segment.right.x; require(x1 < x2, "must be left.x < right.x"); } /** * @notice Checking that a polyline is a valid format. */ function assertPolyline(LineSegment[] memory polyline) internal pure { uint256 numOfSegment = polyline.length; require(numOfSegment != 0, "polyline must not be empty array"); LineSegment memory leftSegment = polyline[0]; // mutable int256 gradientNumerator = int256(leftSegment.right.y) - int256(leftSegment.left.y); // mutable int256 gradientDenominator = int256(leftSegment.right.x) - int256(leftSegment.left.x); // mutable // The beginning of the first line segment's domain is 0. require( leftSegment.left.x == uint64(0), "the x coordinate of left end of the first segment must be 0" ); // The value of y when x is 0 is 0. require( leftSegment.left.y == uint64(0), "the y coordinate of left end of the first segment must be 0" ); // Making sure that the first line segment is a correct format. assertLineSegment(leftSegment); // The end of the domain of a segment and the beginning of the domain of the adjacent // segment must coincide. LineSegment memory rightSegment; // mutable for (uint256 i = 1; i < numOfSegment; i++) { rightSegment = polyline[i]; // Make sure that the i-th line segment is a correct format. assertLineSegment(rightSegment); // Checking that the x-coordinates are same. require( leftSegment.right.x == rightSegment.left.x, "given polyline has an undefined domain." ); // Checking that the y-coordinates are same. require( leftSegment.right.y == rightSegment.left.y, "given polyline is not a continuous function" ); int256 nextGradientNumerator = int256(rightSegment.right.y) - int256(rightSegment.left.y); int256 nextGradientDenominator = int256(rightSegment.right.x) - int256(rightSegment.left.x); require( nextGradientNumerator * gradientDenominator != nextGradientDenominator * gradientNumerator, "the sequential segments must not have the same gradient" ); leftSegment = rightSegment; gradientNumerator = nextGradientNumerator; gradientDenominator = nextGradientDenominator; } // rightSegment is lastSegment // About the last line segment. require( gradientNumerator >= 0 && gradientNumerator <= gradientDenominator, "the gradient of last line segment must be non-negative, and equal to or less than 1" ); } /** * @notice zip a LineSegment structure to uint256 * @return zip uint256( 0 ... 0 | x1 | y1 | x2 | y2 ) */ function zipLineSegment(LineSegment memory segment) internal pure returns (uint256 zip) { uint256 x1U256 = uint256(segment.left.x) << (64 + 64 + 64); // uint64 uint256 y1U256 = uint256(segment.left.y) << (64 + 64); // uint64 uint256 x2U256 = uint256(segment.right.x) << 64; // uint64 uint256 y2U256 = uint256(segment.right.y); // uint64 zip = x1U256 | y1U256 | x2U256 | y2U256; } /** * @notice unzip uint256 to a LineSegment structure */ function unzipLineSegment(uint256 zip) internal pure returns (LineSegment memory) { uint64 x1 = uint64(zip >> (64 + 64 + 64)); uint64 y1 = uint64(zip >> (64 + 64)); uint64 x2 = uint64(zip >> 64); uint64 y2 = uint64(zip); return LineSegment({left: Point({x: x1, y: y1}), right: Point({x: x2, y: y2})}); } /** * @notice unzip the fnMap to uint256[]. */ function decodePolyline(bytes memory fnMap) internal pure returns (uint256[] memory) { return abi.decode(fnMap, (uint256[])); } } // File: contracts/BondToken_and_GDOTC/bondMaker/BondMaker.sol abstract contract BondMaker is UseSafeMath, BondMakerInterface, Time, Polyline { using SafeMath for uint256; using SafeMathDivRoundUp for uint256; using SafeMath for uint64; uint8 internal immutable DECIMALS_OF_BOND; uint8 internal immutable DECIMALS_OF_ORACLE_PRICE; address internal immutable FEE_TAKER; uint256 internal immutable MATURITY_SCALE; PriceOracleInterface internal immutable _oracleContract; uint256 internal _nextBondGroupID = 1; /** * @dev The contents in this internal storage variable can be seen by getBond function. */ struct BondInfo { uint256 maturity; BondTokenInterface contractInstance; uint64 strikePrice; bytes32 fnMapID; } mapping(bytes32 => BondInfo) internal _bonds; /** * @dev The contents in this internal storage variable can be seen by getFnMap function. */ mapping(bytes32 => LineSegment[]) internal _registeredFnMap; /** * @dev The contents in this internal storage variable can be seen by getBondGroup function. */ struct BondGroup { bytes32[] bondIDs; uint256 maturity; } mapping(uint256 => BondGroup) internal _bondGroupList; constructor( PriceOracleInterface oracleAddress, address feeTaker, uint256 maturityScale, uint8 decimalsOfBond, uint8 decimalsOfOraclePrice ) { require(address(oracleAddress) != address(0), "oracleAddress should be non-zero address"); _oracleContract = oracleAddress; require(decimalsOfBond < 19, "the decimals of bond must be less than 19"); DECIMALS_OF_BOND = decimalsOfBond; require(decimalsOfOraclePrice < 19, "the decimals of oracle price must be less than 19"); DECIMALS_OF_ORACLE_PRICE = decimalsOfOraclePrice; require(feeTaker != address(0), "the fee taker must be non-zero address"); FEE_TAKER = feeTaker; require(maturityScale != 0, "MATURITY_SCALE must be positive"); MATURITY_SCALE = maturityScale; } /** * @notice Create bond token contract. * The name of this bond token is its bond ID. * @dev To convert bytes32 to string, encode its bond ID at first, then convert to string. * The symbol of any bond token with bond ID is either SBT or LBT; * As SBT is a special case of bond token, any bond token which does not match to the form of * SBT is defined as LBT. */ function registerNewBond(uint256 maturity, bytes calldata fnMap) external virtual override returns ( bytes32, address, bytes32 ) { _assertBeforeMaturity(maturity); require(maturity < _getBlockTimestampSec() + 365 days, "the maturity is too far"); require( maturity % MATURITY_SCALE == 0, "the maturity must be the multiple of MATURITY_SCALE" ); bytes32 bondID = generateBondID(maturity, fnMap); // Check if the same form of bond is already registered. // Cannot detect if the bond is described in a different polyline while two are // mathematically equivalent. require( address(_bonds[bondID].contractInstance) == address(0), "the bond type has been already registered" ); // Register function mapping if necessary. bytes32 fnMapID = generateFnMapID(fnMap); uint64 sbtStrikePrice; if (_registeredFnMap[fnMapID].length == 0) { uint256[] memory polyline = decodePolyline(fnMap); for (uint256 i = 0; i < polyline.length; i++) { _registeredFnMap[fnMapID].push(unzipLineSegment(polyline[i])); } LineSegment[] memory segments = _registeredFnMap[fnMapID]; assertPolyline(segments); require(!_isBondWorthless(segments), "the bond is 0-value at any price"); sbtStrikePrice = _getSbtStrikePrice(segments); } else { LineSegment[] memory segments = _registeredFnMap[fnMapID]; sbtStrikePrice = _getSbtStrikePrice(segments); } BondTokenInterface bondTokenContract = _createNewBondToken(maturity, fnMap); // Set bond info to storage. _bonds[bondID] = BondInfo({ maturity: maturity, contractInstance: bondTokenContract, strikePrice: sbtStrikePrice, fnMapID: fnMapID }); emit LogNewBond(bondID, address(bondTokenContract), maturity, fnMapID); return (bondID, address(bondTokenContract), fnMapID); } /** * @dev Count the number of the end points on x axis. In the case of a simple SBT/LBT split, * 3 for SBT plus 3 for LBT equals to 6. * In the case of SBT with the strike price 100, (x,y) = (0,0), (100,100), (200,100) defines * the form of SBT on the field. * In the case of LBT with the strike price 100, (x,y) = (0,0), (100,0), (200,100) defines * the form of LBT on the field. * Right hand side area of the last grid point is expanded on the last line to the infinity. * nextBreakPointIndex returns the number of unique points on x axis. * In the case of SBT and LBT with the strike price 100, x = 0,100,200 are the unique points * and the number is 3. */ function _assertBondGroup(bytes32[] memory bondIDs, uint256 maturity) internal view { require(bondIDs.length >= 2, "the bond group should consist of 2 or more bonds"); uint256 numOfBreakPoints = 0; for (uint256 i = 0; i < bondIDs.length; i++) { BondInfo storage bond = _bonds[bondIDs[i]]; require(bond.maturity == maturity, "the maturity of the bonds must be same"); LineSegment[] storage polyline = _registeredFnMap[bond.fnMapID]; numOfBreakPoints = numOfBreakPoints.add(polyline.length); } uint256 nextBreakPointIndex = 0; uint64[] memory rateBreakPoints = new uint64[](numOfBreakPoints); for (uint256 i = 0; i < bondIDs.length; i++) { BondInfo storage bond = _bonds[bondIDs[i]]; LineSegment[] storage segments = _registeredFnMap[bond.fnMapID]; for (uint256 j = 0; j < segments.length; j++) { uint64 breakPoint = segments[j].right.x; bool ok = false; for (uint256 k = 0; k < nextBreakPointIndex; k++) { if (rateBreakPoints[k] == breakPoint) { ok = true; break; } } if (ok) { continue; } rateBreakPoints[nextBreakPointIndex] = breakPoint; nextBreakPointIndex++; } } for (uint256 k = 0; k < rateBreakPoints.length; k++) { uint64 rate = rateBreakPoints[k]; uint256 totalBondPriceN = 0; uint256 totalBondPriceD = 1; for (uint256 i = 0; i < bondIDs.length; i++) { BondInfo storage bond = _bonds[bondIDs[i]]; LineSegment[] storage segments = _registeredFnMap[bond.fnMapID]; (uint256 segmentIndex, bool ok) = _correspondSegment(segments, rate); require(ok, "invalid domain expression"); (uint128 n, uint64 d) = _mapXtoY(segments[segmentIndex], rate); if (n != 0) { // a/b + c/d = (ad+bc)/bd // totalBondPrice += (n / d); // N = D*n + N*d, D = D*d totalBondPriceN = totalBondPriceD.mul(n).add(totalBondPriceN.mul(d)); totalBondPriceD = totalBondPriceD.mul(d); } } /** * @dev Ensure that totalBondPrice (= totalBondPriceN / totalBondPriceD) is the same * with rate. Because we need 1 Ether to mint a unit of each bond token respectively, * the sum of cashflow (USD) per a unit of bond token is the same as USD/ETH * rate at maturity. */ require( totalBondPriceN == totalBondPriceD.mul(rate), "the total price at any rateBreakPoints should be the same value as the rate" ); } } /** * @notice Collect bondIDs that regenerate the collateral, and group them as a bond group. * Any bond is described as a set of linear functions(i.e. polyline), * so we can easily check if the set of bondIDs are well-formed by looking at all the end * points of the lines. */ function registerNewBondGroup(bytes32[] calldata bondIDs, uint256 maturity) external virtual override returns (uint256 bondGroupID) { _assertBondGroup(bondIDs, maturity); (, , uint64 sbtStrikePrice, ) = getBond(bondIDs[0]); for (uint256 i = 1; i < bondIDs.length; i++) { (, , uint64 strikePrice, ) = getBond(bondIDs[i]); require(strikePrice == 0, "except the first bond must not be pure SBT"); } // Get and increment next bond group ID bondGroupID = _nextBondGroupID; _nextBondGroupID = _nextBondGroupID.add(1); _bondGroupList[bondGroupID] = BondGroup(bondIDs, maturity); emit LogNewBondGroup(bondGroupID, maturity, sbtStrikePrice, bondIDs); return bondGroupID; } /** * @dev A user needs to issue a bond via BondGroup in order to guarantee that the total value * of bonds in the bond group equals to the token allowance except for about 0.2% fee (accurately 2/1002). * The fee send to Lien token contract when liquidateBond() or reverseBondGroupToCollateral(). */ function _issueNewBonds(uint256 bondGroupID, uint256 collateralAmountWithFee) internal returns (uint256 bondAmount) { (bytes32[] memory bondIDs, uint256 maturity) = getBondGroup(bondGroupID); _assertNonEmptyBondGroup(bondIDs); _assertBeforeMaturity(maturity); uint256 fee = collateralAmountWithFee.mul(2).divRoundUp(1002); uint8 decimalsOfCollateral = _getCollateralDecimals(); bondAmount = _applyDecimalGap( collateralAmountWithFee.sub(fee), decimalsOfCollateral, DECIMALS_OF_BOND ); require(bondAmount != 0, "the minting amount must be non-zero"); for (uint256 i = 0; i < bondIDs.length; i++) { _mintBond(bondIDs[i], msg.sender, bondAmount); } emit LogIssueNewBonds(bondGroupID, msg.sender, bondAmount); } /** * @notice redeems collateral from the total set of bonds in the bondGroupID before maturity date. * @param bondGroupID is the bond group ID. * @param bondAmount is the redeemed bond amount (decimal: 8). */ function reverseBondGroupToCollateral(uint256 bondGroupID, uint256 bondAmount) external virtual override returns (bool) { require(bondAmount != 0, "the bond amount must be non-zero"); (bytes32[] memory bondIDs, uint256 maturity) = getBondGroup(bondGroupID); _assertNonEmptyBondGroup(bondIDs); _assertBeforeMaturity(maturity); for (uint256 i = 0; i < bondIDs.length; i++) { _burnBond(bondIDs[i], msg.sender, bondAmount); } uint8 decimalsOfCollateral = _getCollateralDecimals(); uint256 collateralAmount = _applyDecimalGap( bondAmount, DECIMALS_OF_BOND, decimalsOfCollateral ); uint256 fee = collateralAmount.mul(2).div(1000); // collateral:fee = 1000:2 _sendCollateralTo(payable(FEE_TAKER), fee); _sendCollateralTo(msg.sender, collateralAmount); emit LogReverseBondGroupToCollateral(bondGroupID, msg.sender, collateralAmount); return true; } /** * @notice Burns set of LBTs and mints equivalent set of LBTs that are not in the exception list. * @param inputBondGroupID is the BondGroupID of bonds which you want to burn. * @param outputBondGroupID is the BondGroupID of bonds which you want to mint. * @param exceptionBonds is the list of bondIDs that should be excluded in burn/mint process. */ function exchangeEquivalentBonds( uint256 inputBondGroupID, uint256 outputBondGroupID, uint256 amount, bytes32[] calldata exceptionBonds ) external virtual override returns (bool) { (bytes32[] memory inputIDs, uint256 inputMaturity) = getBondGroup(inputBondGroupID); _assertNonEmptyBondGroup(inputIDs); (bytes32[] memory outputIDs, uint256 outputMaturity) = getBondGroup(outputBondGroupID); _assertNonEmptyBondGroup(outputIDs); require(inputMaturity == outputMaturity, "cannot exchange bonds with different maturities"); _assertBeforeMaturity(inputMaturity); bool flag; uint256 exceptionCount; for (uint256 i = 0; i < inputIDs.length; i++) { // this flag control checks whether the bond is in the scope of burn/mint flag = true; for (uint256 j = 0; j < exceptionBonds.length; j++) { if (exceptionBonds[j] == inputIDs[i]) { flag = false; // this count checks if all the bondIDs in exceptionBonds are included both in inputBondGroupID and outputBondGroupID exceptionCount = exceptionCount.add(1); } } if (flag) { _burnBond(inputIDs[i], msg.sender, amount); } } require( exceptionBonds.length == exceptionCount, "All the exceptionBonds need to be included in input" ); for (uint256 i = 0; i < outputIDs.length; i++) { flag = true; for (uint256 j = 0; j < exceptionBonds.length; j++) { if (exceptionBonds[j] == outputIDs[i]) { flag = false; exceptionCount = exceptionCount.sub(1); } } if (flag) { _mintBond(outputIDs[i], msg.sender, amount); } } require( exceptionCount == 0, "All the exceptionBonds need to be included both in input and output" ); emit LogExchangeEquivalentBonds(msg.sender, inputBondGroupID, outputBondGroupID, amount); return true; } /** * @notice This function distributes the collateral to the bond token holders * after maturity date based on the oracle price. * @param bondGroupID is the target bond group ID. * @param oracleHintID is manually set to be smaller number than the oracle latestId * when the caller wants to save gas. */ function liquidateBond(uint256 bondGroupID, uint256 oracleHintID) external virtual override returns (uint256 totalPayment) { (bytes32[] memory bondIDs, uint256 maturity) = getBondGroup(bondGroupID); _assertNonEmptyBondGroup(bondIDs); require(_getBlockTimestampSec() >= maturity, "the bond has not expired yet"); uint256 latestID = _oracleContract.latestId(); require(latestID != 0, "system error: the ID of oracle data should not be zero"); uint256 price = _getPriceOn( maturity, (oracleHintID != 0 && oracleHintID <= latestID) ? oracleHintID : latestID ); require(price != 0, "price should be non-zero value"); require(price < 2**64, "price should be less than 2^64"); for (uint256 i = 0; i < bondIDs.length; i++) { bytes32 bondID = bondIDs[i]; uint256 payment = _sendCollateralToBondTokenContract(bondID, uint64(price)); totalPayment = totalPayment.add(payment); } if (totalPayment != 0) { uint256 fee = totalPayment.mul(2).div(1000); // collateral:fee = 1000:2 _sendCollateralTo(payable(FEE_TAKER), fee); } } function collateralAddress() external view override returns (address) { return _collateralAddress(); } function oracleAddress() external view override returns (PriceOracleInterface) { return _oracleContract; } function feeTaker() external view override returns (address) { return FEE_TAKER; } function decimalsOfBond() external view override returns (uint8) { return DECIMALS_OF_BOND; } function decimalsOfOraclePrice() external view override returns (uint8) { return DECIMALS_OF_ORACLE_PRICE; } function maturityScale() external view override returns (uint256) { return MATURITY_SCALE; } function nextBondGroupID() external view override returns (uint256) { return _nextBondGroupID; } /** * @notice Returns multiple information for the bondID. * @dev The decimals of strike price is the same as that of oracle price. */ function getBond(bytes32 bondID) public view override returns ( address bondTokenAddress, uint256 maturity, uint64 solidStrikePrice, bytes32 fnMapID ) { BondInfo memory bondInfo = _bonds[bondID]; bondTokenAddress = address(bondInfo.contractInstance); maturity = bondInfo.maturity; solidStrikePrice = bondInfo.strikePrice; fnMapID = bondInfo.fnMapID; } /** * @dev Returns polyline for the fnMapID. */ function getFnMap(bytes32 fnMapID) public view override returns (bytes memory fnMap) { LineSegment[] storage segments = _registeredFnMap[fnMapID]; uint256[] memory polyline = new uint256[](segments.length); for (uint256 i = 0; i < segments.length; i++) { polyline[i] = zipLineSegment(segments[i]); } return abi.encode(polyline); } /** * @dev Returns all the bondIDs and their maturity for the bondGroupID. */ function getBondGroup(uint256 bondGroupID) public view override returns (bytes32[] memory bondIDs, uint256 maturity) { require(bondGroupID < _nextBondGroupID, "the bond group does not exist"); BondGroup memory bondGroup = _bondGroupList[bondGroupID]; bondIDs = bondGroup.bondIDs; maturity = bondGroup.maturity; } /** * @dev Returns keccak256 for the fnMap. */ function generateFnMapID(bytes memory fnMap) public pure override returns (bytes32 fnMapID) { return keccak256(fnMap); } /** * @dev Returns a bond ID determined by this contract address, maturity and fnMap. */ function generateBondID(uint256 maturity, bytes memory fnMap) public view override returns (bytes32 bondID) { return keccak256(abi.encodePacked(address(this), maturity, fnMap)); } function _mintBond( bytes32 bondID, address account, uint256 amount ) internal { BondTokenInterface bondTokenContract = _bonds[bondID].contractInstance; _assertRegisteredBond(bondTokenContract); require(bondTokenContract.mint(account, amount), "failed to mint bond token"); } function _burnBond( bytes32 bondID, address account, uint256 amount ) internal { BondTokenInterface bondTokenContract = _bonds[bondID].contractInstance; _assertRegisteredBond(bondTokenContract); require(bondTokenContract.simpleBurn(account, amount), "failed to burn bond token"); } function _sendCollateralToBondTokenContract(bytes32 bondID, uint64 price) internal returns (uint256 collateralAmount) { BondTokenInterface bondTokenContract = _bonds[bondID].contractInstance; _assertRegisteredBond(bondTokenContract); LineSegment[] storage segments = _registeredFnMap[_bonds[bondID].fnMapID]; (uint256 segmentIndex, bool ok) = _correspondSegment(segments, price); assert(ok); // not found a segment whose price range include current price (uint128 n, uint64 _d) = _mapXtoY(segments[segmentIndex], price); // x = price, y = n / _d // uint64(-1) * uint64(-1) < uint128(-1) uint128 d = uint128(_d) * uint128(price); uint256 totalSupply = bondTokenContract.totalSupply(); bool expiredFlag = bondTokenContract.expire(n, d); // rateE0 = n / d = f(price) / price if (expiredFlag) { uint8 decimalsOfCollateral = _getCollateralDecimals(); collateralAmount = _applyDecimalGap(totalSupply, DECIMALS_OF_BOND, decimalsOfCollateral) .mul(n) .div(d); _sendCollateralTo(address(bondTokenContract), collateralAmount); emit LogLiquidateBond(bondID, n, d); } } /** * @dev Get the price of the oracle data with a minimum timestamp that does more than input value * when you know the ID you are looking for. * @param timestamp is the timestamp that you want to get price. * @param hintID is the ID of the oracle data you are looking for. * @return priceE8 (10^-8 USD) */ function _getPriceOn(uint256 timestamp, uint256 hintID) internal returns (uint256 priceE8) { require( _oracleContract.getTimestamp(hintID) > timestamp, "there is no price data after maturity" ); uint256 id = hintID - 1; while (id != 0) { if (_oracleContract.getTimestamp(id) <= timestamp) { break; } id--; } return _oracleContract.getPrice(id + 1); } /** * @dev removes a decimal gap from rate. */ function _applyDecimalGap( uint256 baseAmount, uint8 decimalsOfBase, uint8 decimalsOfQuote ) internal pure returns (uint256 quoteAmount) { uint256 n; uint256 d; if (decimalsOfBase > decimalsOfQuote) { d = decimalsOfBase - decimalsOfQuote; } else if (decimalsOfBase < decimalsOfQuote) { n = decimalsOfQuote - decimalsOfBase; } // The consequent multiplication would overflow under extreme and non-blocking circumstances. require(n < 19 && d < 19, "decimal gap needs to be lower than 19"); quoteAmount = baseAmount.mul(10**n).div(10**d); } function _assertRegisteredBond(BondTokenInterface bondTokenContract) internal pure { require(address(bondTokenContract) != address(0), "the bond is not registered"); } function _assertNonEmptyBondGroup(bytes32[] memory bondIDs) internal pure { require(bondIDs.length != 0, "the list of bond ID must be non-empty"); } function _assertBeforeMaturity(uint256 maturity) internal view { require(_getBlockTimestampSec() < maturity, "the maturity has already expired"); } function _isBondWorthless(LineSegment[] memory polyline) internal pure returns (bool) { for (uint256 i = 0; i < polyline.length; i++) { LineSegment memory segment = polyline[i]; if (segment.right.y != 0) { return false; } } return true; } /** * @dev Return the strike price only when the form of polyline matches to the definition of SBT. * Check if the form is SBT even when the polyline is in a verbose style. */ function _getSbtStrikePrice(LineSegment[] memory polyline) internal pure returns (uint64) { if (polyline.length != 2) { return 0; } uint64 strikePrice = polyline[0].right.x; if (strikePrice == 0) { return 0; } for (uint256 i = 0; i < polyline.length; i++) { LineSegment memory segment = polyline[i]; if (segment.right.y != strikePrice) { return 0; } } return uint64(strikePrice); } /** * @dev Only when the form of polyline matches to the definition of LBT, this function returns * the minimum collateral price (USD) that LBT is not worthless. * Check if the form is LBT even when the polyline is in a verbose style. */ function _getLbtStrikePrice(LineSegment[] memory polyline) internal pure returns (uint64) { if (polyline.length != 2) { return 0; } uint64 strikePrice = polyline[0].right.x; if (strikePrice == 0) { return 0; } for (uint256 i = 0; i < polyline.length; i++) { LineSegment memory segment = polyline[i]; if (segment.right.y.add(strikePrice) != segment.right.x) { return 0; } } return uint64(strikePrice); } /** * @dev In order to calculate y axis value for the corresponding x axis value, we need to find * the place of domain of x value on the polyline. * As the polyline is already checked to be correctly formed, we can simply look from the right * hand side of the polyline. */ function _correspondSegment(LineSegment[] memory segments, uint64 x) internal pure returns (uint256 i, bool ok) { i = segments.length; while (i > 0) { i--; if (segments[i].left.x <= x) { ok = true; break; } } } // function issueNewBonds(uint256 bondGroupID, uint256 amount) external returns (uint256 bondAmount); function _createNewBondToken(uint256 maturity, bytes memory fnMap) internal virtual returns (BondTokenInterface); function _collateralAddress() internal view virtual returns (address); function _getCollateralDecimals() internal view virtual returns (uint8); function _sendCollateralTo(address receiver, uint256 amount) internal virtual; } // File: contracts/BondToken_and_GDOTC/bondTokenName/BondTokenNameInterface.sol /** * @title bond token name contract interface */ interface BondTokenNameInterface { function genBondTokenName( string calldata shortNamePrefix, string calldata longNamePrefix, uint256 maturity, uint256 solidStrikePriceE4 ) external pure returns (string memory shortName, string memory longName); function getBondTokenName( uint256 maturity, uint256 solidStrikePriceE4, uint256 rateLBTWorthlessE4 ) external pure returns (string memory shortName, string memory longName); } // File: contracts/BondToken_and_GDOTC/bondMaker/BondMakerCollateralizedEth.sol contract BondMakerCollateralizedEth is BondMaker, TransferETH { address private constant ETH = address(0); BondTokenNameInterface internal immutable BOND_TOKEN_NAMER; BondTokenFactory internal immutable BOND_TOKEN_FACTORY; constructor( PriceOracleInterface oracleAddress, address feeTaker, BondTokenNameInterface bondTokenNamerAddress, BondTokenFactory bondTokenFactoryAddress, uint256 maturityScale ) BondMaker(oracleAddress, feeTaker, maturityScale, 8, 8) { require( address(bondTokenNamerAddress) != address(0), "bondTokenNamerAddress should be non-zero address" ); BOND_TOKEN_NAMER = bondTokenNamerAddress; require( address(bondTokenFactoryAddress) != address(0), "bondTokenFactoryAddress should be non-zero address" ); BOND_TOKEN_FACTORY = bondTokenFactoryAddress; } function issueNewBonds(uint256 bondGroupID) public payable returns (uint256 bondAmount) { return _issueNewBonds(bondGroupID, msg.value); } function _createNewBondToken(uint256 maturity, bytes memory fnMap) internal override returns (BondTokenInterface) { (string memory symbol, string memory name) = _getBondTokenName(maturity, fnMap); address bondAddress = BOND_TOKEN_FACTORY.createBondToken( ETH, name, symbol, DECIMALS_OF_BOND ); return BondTokenInterface(bondAddress); } function _getBondTokenName(uint256 maturity, bytes memory fnMap) internal view virtual returns (string memory symbol, string memory name) { bytes32 fnMapID = generateFnMapID(fnMap); LineSegment[] memory segments = _registeredFnMap[fnMapID]; uint64 sbtStrikePrice = _getSbtStrikePrice(segments); uint64 lbtStrikePrice = _getLbtStrikePrice(segments); uint64 sbtStrikePriceE0 = sbtStrikePrice / (uint64(10)**DECIMALS_OF_ORACLE_PRICE); uint64 lbtStrikePriceE0 = lbtStrikePrice / (uint64(10)**DECIMALS_OF_ORACLE_PRICE); if (sbtStrikePrice != 0) { return BOND_TOKEN_NAMER.genBondTokenName("SBT", "SBT", maturity, sbtStrikePriceE0); } else if (lbtStrikePrice != 0) { return BOND_TOKEN_NAMER.genBondTokenName("LBT", "LBT", maturity, lbtStrikePriceE0); } else { return BOND_TOKEN_NAMER.genBondTokenName("IMT", "Immortal Option", maturity, 0); } } function _collateralAddress() internal pure override returns (address) { return address(0); } function _getCollateralDecimals() internal pure override returns (uint8) { return 18; } function _sendCollateralTo(address receiver, uint256 amount) internal override { _transferETH(payable(receiver), amount); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract PriceOracleInterface","name":"oracleAddress","type":"address"},{"internalType":"address","name":"feeTaker","type":"address"},{"internalType":"contract BondTokenNameInterface","name":"bondTokenNamerAddress","type":"address"},{"internalType":"contract BondTokenFactory","name":"bondTokenFactoryAddress","type":"address"},{"internalType":"uint256","name":"maturityScale","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"inputBondGroupID","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"outputBondGroupID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LogExchangeEquivalentBonds","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"bondGroupID","type":"uint256"},{"indexed":true,"internalType":"address","name":"issuer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LogIssueNewBonds","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"bondID","type":"bytes32"},{"indexed":false,"internalType":"uint128","name":"rateNumerator","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"rateDenominator","type":"uint128"}],"name":"LogLiquidateBond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"bondID","type":"bytes32"},{"indexed":true,"internalType":"address","name":"bondTokenAddress","type":"address"},{"indexed":true,"internalType":"uint256","name":"maturity","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"fnMapID","type":"bytes32"}],"name":"LogNewBond","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"bondGroupID","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"maturity","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"sbtStrikePrice","type":"uint64"},{"indexed":false,"internalType":"bytes32[]","name":"bondIDs","type":"bytes32[]"}],"name":"LogNewBondGroup","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"bondGroupID","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LogReverseBondGroupToCollateral","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"},{"inputs":[],"name":"collateralAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimalsOfBond","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimalsOfOraclePrice","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"inputBondGroupID","type":"uint256"},{"internalType":"uint256","name":"outputBondGroupID","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"exceptionBonds","type":"bytes32[]"}],"name":"exchangeEquivalentBonds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeTaker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"bytes","name":"fnMap","type":"bytes"}],"name":"generateBondID","outputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"fnMap","type":"bytes"}],"name":"generateFnMapID","outputs":[{"internalType":"bytes32","name":"fnMapID","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"}],"name":"getBond","outputs":[{"internalType":"address","name":"bondTokenAddress","type":"address"},{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"uint64","name":"solidStrikePrice","type":"uint64"},{"internalType":"bytes32","name":"fnMapID","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bondGroupID","type":"uint256"}],"name":"getBondGroup","outputs":[{"internalType":"bytes32[]","name":"bondIDs","type":"bytes32[]"},{"internalType":"uint256","name":"maturity","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"fnMapID","type":"bytes32"}],"name":"getFnMap","outputs":[{"internalType":"bytes","name":"fnMap","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bondGroupID","type":"uint256"}],"name":"issueNewBonds","outputs":[{"internalType":"uint256","name":"bondAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bondGroupID","type":"uint256"},{"internalType":"uint256","name":"oracleHintID","type":"uint256"}],"name":"liquidateBond","outputs":[{"internalType":"uint256","name":"totalPayment","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maturityScale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextBondGroupID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracleAddress","outputs":[{"internalType":"contract PriceOracleInterface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"maturity","type":"uint256"},{"internalType":"bytes","name":"fnMap","type":"bytes"}],"name":"registerNewBond","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"bondIDs","type":"bytes32[]"},{"internalType":"uint256","name":"maturity","type":"uint256"}],"name":"registerNewBondGroup","outputs":[{"internalType":"uint256","name":"bondGroupID","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bondGroupID","type":"uint256"},{"internalType":"uint256","name":"bondAmount","type":"uint256"}],"name":"reverseBondGroupToCollateral","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
61016060405260016000553480156200001757600080fd5b506040516200474d3803806200474d833981810160405260a08110156200003d57600080fd5b508051602082015160408301516060840151608090940151929391929091908484826008806001600160a01b038516620000c3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526028815260200180620046696028913960400191505060405180910390fd5b6001600160601b0319606086901b1661010052601360ff83161062000134576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180620046c16029913960400191505060405180910390fd5b7fff0000000000000000000000000000000000000000000000000000000000000060f883901b16608052601360ff821610620001bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260318152602001806200471c6031913960400191505060405180910390fd5b7fff0000000000000000000000000000000000000000000000000000000000000060f882901b1660a0526001600160a01b03841662000247576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180620046436026913960400191505060405180910390fd5b6001600160601b0319606085901b1660c05282620002c657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4d415455524954595f5343414c45206d75737420626520706f73697469766500604482015290519081900360640190fd5b505060e05250506001600160a01b0383166200032e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180620046916030913960400191505060405180910390fd5b6001600160601b0319606084901b16610120526001600160a01b038216620003a2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180620046ea6032913960400191505060405180910390fd5b506001600160601b031960609190911b166101405250505060805160f81c60a05160f81c60c05160601c60e0516101005160601c6101205160601c6101405160601c6141d86200046b6000398061287552508061366852806138c45280613975525080610cbd52806115225280611d595280611e345280611ed9525080610f6352806114f2525080610ec152806114ce52806116495250806116bf528061355d52806135ac52508061160852806118b3528061222452806128a85280612a7152506141d86000f3fe60806040526004361061010d5760003560e01c806379265a8511610095578063b9601d7711610064578063b9601d77146105e8578063d0d6153a14610618578063e59455e014610643578063f08e2a33146106be578063f2eefd80146106d35761014b565b806379265a851461058c5780638376c24d146105a1578063a89ae4ba146105be578063ac3fd886146105d35761014b565b806356481cb4116100dc57806356481cb41461034f5780636d17f168146103ee5780636f23bd401461049f5780637369bcaa146104cf578063749f1044146105775761014b565b806326d6c97b146101505780632770aa64146101b257806348d399e71461027c578063529aa16b146102ad5761014b565b3661014b57604080513481529051309133917fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9181900360200190a3005b600080fd5b34801561015c57600080fd5b5061017a6004803603602081101561017357600080fd5b5035610758565b604080516001600160a01b03909516855260208501939093526001600160401b03909116838301526060830152519081900360800190f35b3480156101be57600080fd5b5061026a600480360360408110156101d557600080fd5b81359190810190604081016020820135600160201b8111156101f657600080fd5b82018360208201111561020857600080fd5b803590602001918460018302840111600160201b8311171561022957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506107c9945050505050565b60408051918252519081900360200190f35b34801561028857600080fd5b5061029161085e565b604080516001600160a01b039092168252519081900360200190f35b3480156102b957600080fd5b5061033b600480360360808110156102d057600080fd5b81359160208101359160408201359190810190608081016060820135600160201b8111156102fd57600080fd5b82018360208201111561030f57600080fd5b803590602001918460208302840111600160201b8311171561033057600080fd5b50909250905061086d565b604080519115158252519081900360200190f35b34801561035b57600080fd5b506103796004803603602081101561037257600080fd5b5035610ad4565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103b357818101518382015260200161039b565b50505050905090810190601f1680156103e05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103fa57600080fd5b5061026a6004803603602081101561041157600080fd5b810190602081018135600160201b81111561042b57600080fd5b82018360208201111561043d57600080fd5b803590602001918460018302840111600160201b8311171561045e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610c36945050505050565b3480156104ab57600080fd5b5061026a600480360360408110156104c257600080fd5b5080359060200135610c41565b3480156104db57600080fd5b50610551600480360360408110156104f257600080fd5b81359190810190604081016020820135600160201b81111561051357600080fd5b82018360208201111561052557600080fd5b803590602001918460018302840111600160201b8311171561054657600080fd5b509092509050610ef2565b604080519384526001600160a01b03909216602084015282820152519081900360600190f35b34801561058357600080fd5b506102916114cc565b34801561059857600080fd5b5061026a6114f0565b61026a600480360360208110156105b757600080fd5b5035611514565b3480156105ca57600080fd5b50610291611520565b3480156105df57600080fd5b5061026a611544565b3480156105f457600080fd5b5061033b6004803603604081101561060b57600080fd5b508035906020013561154a565b34801561062457600080fd5b5061062d6116bd565b6040805160ff9092168252519081900360200190f35b34801561064f57600080fd5b5061026a6004803603604081101561066657600080fd5b810190602081018135600160201b81111561068057600080fd5b82018360208201111561069257600080fd5b803590602001918460208302840111600160201b831117156106b357600080fd5b9193509150356116e1565b3480156106ca57600080fd5b5061062d6118b1565b3480156106df57600080fd5b506106fd600480360360208110156106f657600080fd5b50356118d5565b6040518080602001838152602001828103825284818151815260200191508051906020019060200280838360005b8381101561074357818101518382015260200161072b565b50505050905001935050505060405180910390f35b600080600080610766613c70565b505050600092835250506001602081815260409283902083516080810185528154808252938201546001600160a01b038116938201849052600160a01b90046001600160401b031694810185905260029091015460609091018190529093919291565b600030838360405160200180846001600160a01b031660601b815260140183815260200182805190602001908083835b602083106108185780518252601f1990920191602091820191016107f9565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040528051906020012090505b92915050565b60006108686119b9565b905090565b60006060600061087c886118d5565b91509150610889826119be565b60606000610896896118d5565b915091506108a3826119be565b8083146108e15760405162461bcd60e51b815260040180806020018281038252602f815260200180613e7c602f913960400191505060405180910390fd5b6108ea836119fe565b60008060005b865181101561097c576001925060005b8981101561094f5787828151811061091457fe5b60200260200101518b8b8381811061092857fe5b9050602002013514156109475760009350610944836001611a59565b92505b600101610900565b5082156109745761097487828151811061096557fe5b6020026020010151338d611ab3565b6001016108f0565b508781146109bb5760405162461bcd60e51b81526004018080602001828103825260338152602001806140156033913960400191505060405180910390fd5b60005b8451811015610a4a576001925060005b89811015610a1d578582815181106109e257fe5b60200260200101518b8b838181106109f657fe5b905060200201351415610a155760009350610a12836001611bb2565b92505b6001016109ce565b508215610a4257610a42858281518110610a3357fe5b6020026020010151338d611bf4565b6001016109be565b508015610a885760405162461bcd60e51b81526004018080602001828103825260438152602001806140716043913960600191505060405180910390fd5b604080518b815290518c918e9133917fd7cc25b50fd05b627f35998c0c134fd1f025ced4e16b99ca2feaeb8361664d44919081900360200190a45060019b9a5050505050505050505050565b600081815260026020526040902080546060919082906001600160401b0381118015610aff57600080fd5b50604051908082528060200260200182016040528015610b29578160200160208202803683370190505b50905060005b8254811015610bcd57610bae838281548110610b4757fe5b600091825260209182902060408051608081018252600290930290910180546001600160401b03808216858501908152600160401b928390048216606087015285528351808501909452600190920154808316845204168184015291810191909152611ced565b828281518110610bba57fe5b6020908102919091010152600101610b2f565b50806040516020018080602001828103825283818151815260200191508051906020019060200280838360005b83811015610c12578181015183820152602001610bfa565b5050505090500192505050604051602081830303815290604052925050505b919050565b805160209091012090565b600060606000610c50856118d5565b91509150610c5d826119be565b80610c66611d50565b1015610cb9576040805162461bcd60e51b815260206004820152601c60248201527f74686520626f6e6420686173206e6f7420657870697265642079657400000000604482015290519081900360640190fd5b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634bfbbe0b6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610d1657600080fd5b505af1158015610d2a573d6000803e3d6000fd5b505050506040513d6020811015610d4057600080fd5b5051905080610d805760405162461bcd60e51b8152600401808060200182810382526036815260200180613dc66036913960400191505060405180910390fd5b6000610da6838715801590610d955750838811155b610d9f5783610da1565b875b611d54565b905080610dfa576040805162461bcd60e51b815260206004820152601e60248201527f70726963652073686f756c64206265206e6f6e2d7a65726f2076616c75650000604482015290519081900360640190fd5b600160401b8110610e52576040805162461bcd60e51b815260206004820152601e60248201527f70726963652073686f756c64206265206c657373207468616e20325e36340000604482015290519081900360640190fd5b60005b8451811015610e9a576000858281518110610e6c57fe5b602002602001015190506000610e828285611f74565b9050610e8e8882611a59565b97505050600101610e55565b508415610ee8576000610eba6103e8610eb48860026122b0565b90612309565b9050610ee67f00000000000000000000000000000000000000000000000000000000000000008261234b565b505b5050505092915050565b6000806000610f00866119fe565b610f08611d50565b6301e13380018610610f61576040805162461bcd60e51b815260206004820152601760248201527f746865206d6174757269747920697320746f6f20666172000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000008681610f8a57fe5b0615610fc75760405162461bcd60e51b815260040180806020018281038252603381526020018061414b6033913960400191505060405180910390fd5b60006110098787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506107c992505050565b600081815260016020819052604090912001549091506001600160a01b0316156110645760405162461bcd60e51b81526004018080602001828103825260298152602001806140486029913960400191505060405180910390fd5b60006110a587878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610c3692505050565b600081815260026020526040812054919250906112ef5760606110fd89898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061235992505050565b905060005b81518110156111c457600084815260026020526040902082516111389084908490811061112b57fe5b6020026020010151612401565b815460018082018455600093845260209384902083518051600290940290910180549186015167ffffffffffffffff199283166001600160401b03958616176fffffffffffffffff000000000000000019908116600160401b92871683021783559587015180519285018054919098015193169185169190911790941692169092021790915501611102565b50606060026000858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015611273576000848152602090819020604080516080810182526002860290920180546001600160401b03808216858501908152600160401b92839004821660608701528552835180850190945260019283015480821685529190910416828501528284019190915290835290920191016111fa565b50505050905061128281612456565b61128b81612746565b156112dd576040805162461bcd60e51b815260206004820181905260248201527f74686520626f6e6420697320302d76616c756520617420616e79207072696365604482015290519081900360640190fd5b6112e6816127a7565b925050506113b0565b606060026000848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561139d576000848152602090819020604080516080810182526002860290920180546001600160401b03808216858501908152600160401b9283900482166060870152855283518085019094526001928301548082168552919091041682850152828401919091529083529092019101611324565b5050505090506113ac816127a7565b9150505b60006113f28a8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061285e92505050565b604080516080810182528c81526001600160a01b0383811660208084018281526001600160401b03898116868801908152606087018c815260008e81526001808752908a9020985189559351938801805492516001600160a01b0319909316949097169390931767ffffffffffffffff60a01b1916600160a01b9190921602179093559151600290930192909255825187815292519394508d93919288927f3ebc23c737571cd7ddd871023e6c7d173a086959da035cc9707ef4e80c4b6e0a929181900390910190a4929992985090965090945050505050565b7f000000000000000000000000000000000000000000000000000000000000000090565b7f000000000000000000000000000000000000000000000000000000000000000090565b60006108588234612a15565b7f000000000000000000000000000000000000000000000000000000000000000090565b60005490565b60008161159e576040805162461bcd60e51b815260206004820181905260248201527f74686520626f6e6420616d6f756e74206d757374206265206e6f6e2d7a65726f604482015290519081900360640190fd5b606060006115ab856118d5565b915091506115b8826119be565b6115c1816119fe565b60005b82518110156115f3576115eb8382815181106115dc57fe5b60200260200101513387611ab3565b6001016115c4565b5060006115fe612b47565b9050600061162d867f000000000000000000000000000000000000000000000000000000000000000084612b4c565b905060006116426103e8610eb48460026122b0565b905061166e7f00000000000000000000000000000000000000000000000000000000000000008261234b565b611678338361234b565b60408051838152905133918a917fd696d42b904abc4f87f6ff63556b7cb4114b23ca9a5c5c312c6b352cadc47a399181900360200190a3506001979650505050505050565b7f000000000000000000000000000000000000000000000000000000000000000090565b6000611721848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250869250612bf4915050565b600061173f8585600081811061173357fe5b90506020020135610758565b50925060019150505b848110156117b557600061176187878481811061173357fe5b50925050506001600160401b038116156117ac5760405162461bcd60e51b815260040180806020018281038252602a815260200180613f44602a913960400191505060405180910390fd5b50600101611748565b5060005491506117c6826001611a59565b600055604080516060602087028083018201845292820187815291928392918991899182919086019084908082843760009201829052509385525050506020918201869052848152600382526040902082518051919261182b92849290910190613c97565b5060208201518160010155905050806001600160401b031683837f908f2c9b76fe27e36f828f88b8d9d0ebb7b536f27569521b54a6ba4c79a46901888860405180806020018281038252848482818152602001925060200280828437600083820152604051601f909101601f19169092018290039550909350505050a4505b9392505050565b7f000000000000000000000000000000000000000000000000000000000000000090565b606060008054831061192e576040805162461bcd60e51b815260206004820152601d60248201527f74686520626f6e642067726f757020646f6573206e6f74206578697374000000604482015290519081900360640190fd5b611936613ce2565b600084815260036020908152604091829020825181546060938102820184018552938101848152909391928492849184018282801561199457602002820191906000526020600020905b815481526020019060010190808311611980575b5050509183525050600191909101546020918201528151910151909590945092505050565b600090565b80516119fb5760405162461bcd60e51b815260040180806020018281038252602581526020018061417e6025913960400191505060405180910390fd5b50565b80611a07611d50565b106119fb576040805162461bcd60e51b815260206004820181905260248201527f746865206d617475726974792068617320616c72656164792065787069726564604482015290519081900360640190fd5b6000828201838110156118aa576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600083815260016020819052604090912001546001600160a01b0316611ad881613105565b806001600160a01b031663f05fcdf284846040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015611b2f57600080fd5b505af1158015611b43573d6000803e3d6000fd5b505050506040513d6020811015611b5957600080fd5b5051611bac576040805162461bcd60e51b815260206004820152601960248201527f6661696c656420746f206275726e20626f6e6420746f6b656e00000000000000604482015290519081900360640190fd5b50505050565b60006118aa83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613160565b600083815260016020819052604090912001546001600160a01b0316611c1981613105565b806001600160a01b03166340c10f1984846040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015611c7057600080fd5b505af1158015611c84573d6000803e3d6000fd5b505050506040513d6020811015611c9a57600080fd5b5051611bac576040805162461bcd60e51b815260206004820152601960248201527f6661696c656420746f206d696e7420626f6e6420746f6b656e00000000000000604482015290519081900360640190fd5b805180516020918201519282015180519201516001600160401b031660409290921b6fffffffffffffffff00000000000000001660c09190911b6001600160c01b03191660809390931b67ffffffffffffffff60801b1692909217919091171790565b4290565b6000827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b633620c846040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015611dbd57600080fd5b505af1158015611dd1573d6000803e3d6000fd5b505050506040513d6020811015611de757600080fd5b505111611e255760405162461bcd60e51b8152600401808060200182810382526025815260200180613efc6025913960400191505060405180910390fd5b60001982015b8015611ed757837f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b633620c836040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015611e9857600080fd5b505af1158015611eac573d6000803e3d6000fd5b505050506040513d6020811015611ec257600080fd5b505111611ece57611ed7565b60001901611e2b565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e7572230826001016040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015611f4057600080fd5b505af1158015611f54573d6000803e3d6000fd5b505050506040513d6020811015611f6a57600080fd5b5051949350505050565b6000828152600160208190526040822001546001600160a01b0316611f9881613105565b6000848152600160209081526040808320600290810154845282528083208054825181850281018501909352808352909392839261205d929091869190859084015b82821015612053576000848152602090819020604080516080810182526002860290920180546001600160401b03808216858501908152600160401b9283900482166060870152855283518085019094526001928301548082168552919091041682850152828401919091529083529092019101611fda565b50505050876131f7565b915091508061206857fe5b6000806120e285858154811061207a57fe5b600091825260209182902060408051608081018252600290930290910180546001600160401b03808216858501908152600160401b92839004821660608701528552835180850190945260019092015480831684520416818401529181019190915289613253565b915091506000886001600160401b0316826001600160401b03160290506000876001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561213a57600080fd5b505afa15801561214e573d6000803e3d6000fd5b505050506040513d602081101561216457600080fd5b50516040805163903d8e7760e01b81526001600160801b0380881660048301528516602482015290519192506000916001600160a01b038b169163903d8e7791604480830192602092919082900301818787803b1580156121c457600080fd5b505af11580156121d8573d6000803e3d6000fd5b505050506040513d60208110156121ee57600080fd5b5051905080156122a1576000612202612b47565b905061224f846001600160801b0316610eb4886001600160801b0316612249877f000000000000000000000000000000000000000000000000000000000000000087612b4c565b906122b0565b9a5061225b8a8c61234b565b604080516001600160801b0380891682528616602082015281518f927fc35eb5b2a98868fe11fdaa24c3ab70ddcbf1ab90e0bee977e05a6945bad21ff1928290030190a2505b50505050505050505092915050565b6000826122bf57506000610858565b828202828482816122cc57fe5b04146118aa5760405162461bcd60e51b8152600401808060200182810382526021815260200180613ff46021913960400191505060405180910390fd5b60006118aa83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613392565b61235582826133f7565b5050565b606081806020019051602081101561237057600080fd5b8101908080516040519392919084600160201b82111561238f57600080fd5b9083019060208201858111156123a457600080fd5b82518660208202830111600160201b821117156123c057600080fd5b82525081516020918201928201910280838360005b838110156123ed5781810151838201526020016123d5565b505050509050016040525050509050919050565b612409613cfc565b50604080516080808201835260c084901c8284019081526001600160401b039185901c821660608401528252825180840184529284901c8116835290921660208083019190915282015290565b8051806124aa576040805162461bcd60e51b815260206004820181905260248201527f706f6c796c696e65206d757374206e6f7420626520656d707479206172726179604482015290519081900360640190fd5b6124b2613cfc565b826000815181106124bf57fe5b6020908102919091018101518051808301518284015193840151915193519294506001600160401b0390811691811691909103928116911681900390156125375760405162461bcd60e51b815260040180806020018281038252603b8152602001806140e4603b913960400191505060405180910390fd5b8251602001516001600160401b0316156125825760405162461bcd60e51b815260040180806020018281038252603b815260200180613fb9603b913960400191505060405180910390fd5b61258b8361341a565b612593613cfc565b60015b858110156126f1578681815181106125aa57fe5b602002602001015191506125bd8261341a565b8151516020860151516001600160401b0390811691161461260f5760405162461bcd60e51b8152600401808060200182810382526027815260200180613e1e6027913960400191505060405180910390fd5b8160000151602001516001600160401b03168560200151602001516001600160401b03161461266f5760405162461bcd60e51b815260040180806020018281038252602b815260200180613eab602b913960400191505060405180910390fd5b81516020808201518185015191820151925191516001600160401b03918216938216939093039291811691160384820286820214156126df5760405162461bcd60e51b8152600401808060200182810382526037815260200180613e456037913960400191505060405180910390fd5b92955093509091508390600101612596565b50600083121580156127035750818313155b61273e5760405162461bcd60e51b8152600401808060200182810382526053815260200180613d4e6053913960600191505060405180910390fd5b505050505050565b6000805b825181101561279e5761275b613cfc565b83828151811061276757fe5b602002602001015190508060200151602001516001600160401b031660001461279557600092505050610c31565b5060010161274a565b50600192915050565b600081516002146127ba57506000610c31565b6000826000815181106127c957fe5b602002602001015160200151600001519050806001600160401b0316600014156127f7576000915050610c31565b60005b83518110156128575761280b613cfc565b84828151811061281757fe5b60200260200101519050826001600160401b03168160200151602001516001600160401b03161461284e5760009350505050610c31565b506001016127fa565b5092915050565b600060608061286d8585613483565b9150915060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0904d9b600084867f00000000000000000000000000000000000000000000000000000000000000006040518563ffffffff1660e01b815260040180856001600160a01b0316815260200180602001806020018460ff168152602001838103835286818151815260200191508051906020019080838360005b8381101561292f578181015183820152602001612917565b50505050905090810190601f16801561295c5780820380516001836020036101000a031916815260200191505b50838103825285518152855160209182019187019080838360005b8381101561298f578181015183820152602001612977565b50505050905090810190601f1680156129bc5780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b1580156129df57600080fd5b505af11580156129f3573d6000803e3d6000fd5b505050506040513d6020811015612a0957600080fd5b50519695505050505050565b600060606000612a24856118d5565b91509150612a31826119be565b612a3a816119fe565b6000612a536103ea612a4d8760026122b0565b906139b8565b90506000612a5f612b47565b9050612a95612a6e8784611bb2565b827f0000000000000000000000000000000000000000000000000000000000000000612b4c565b945084612ad35760405162461bcd60e51b8152600401808060200182810382526023815260200180613f216023913960400191505060405180910390fd5b60005b8451811015612b0557612afd858281518110612aee57fe5b60200260200101513388611bf4565b600101612ad6565b50604080518681529051339189917f58119118163827fe45f023219bbd8afd3de022473ee123ab28257e6e7cb1a5969181900360200190a35050505092915050565b601290565b60008060008360ff168560ff161115612b6b575060ff83850316612b82565b8360ff168560ff161015612b825784840360ff1691505b601382108015612b925750601381105b612bcd5760405162461bcd60e51b8152600401808060200182810382526025815260200180613da16025913960400191505060405180910390fd5b612bea81600a0a610eb484600a0a896122b090919063ffffffff16565b9695505050505050565b600282511015612c355760405162461bcd60e51b81526004018080602001828103825260308152602001806140b46030913960400191505060405180910390fd5b6000805b8351811015612cdc57600060016000868481518110612c5457fe5b60200260200101518152602001908152602001600020905083816000015414612cae5760405162461bcd60e51b8152600401808060200182810382526026815260200180613ed66026913960400191505060405180910390fd5b6002818101546000908152602091909152604090208054612cd0908590611a59565b93505050600101612c39565b5060006060826001600160401b0381118015612cf757600080fd5b50604051908082528060200260200182016040528015612d21578160200160208202803683370190505b50905060005b8551811015612e4457600060016000888481518110612d4257fe5b60200260200101518152602001908152602001600020905060006002600083600201548152602001908152602001600020905060005b8154811015612e39576000828281548110612d8f57fe5b600091825260208220600160029092020101546001600160401b03169150805b88811015612df557826001600160401b0316888281518110612dcd57fe5b60200260200101516001600160401b03161415612ded5760019150612df5565b600101612daf565b508015612e03575050612e31565b81878981518110612e1057fe5b6001600160401b039092166020928302919091019091015250506001909501945b600101612d78565b505050600101612d27565b5060005b815181101561273e576000828281518110612e5f57fe5b602002602001015190506000806001905060005b89518110156130a9576000600160008c8481518110612e8e57fe5b602002602001015181526020019081526020016000209050600060026000836002015481526020019081526020016000209050600080612f6b83805480602002602001604051908101604052809291908181526020016000905b82821015612f61576000848152602090819020604080516080810182526002860290920180546001600160401b03808216858501908152600160401b9283900482166060870152855283518085019094526001928301548082168552919091041682850152828401919091529083529092019101612ee8565b50505050896131f7565b9150915080612fc1576040805162461bcd60e51b815260206004820152601960248201527f696e76616c696420646f6d61696e2065787072657373696f6e00000000000000604482015290519081900360640190fd5b60008061303b858581548110612fd357fe5b600091825260209182902060408051608081018252600290930290910180546001600160401b03808216858501908152600160401b9283900482166060870152855283518085019094526001909201548083168452041681840152918101919091528b613253565b91509150816001600160801b03166000146130975761307f6130668a6001600160401b0384166122b0565b6130798a6001600160801b0386166122b0565b90611a59565b9850613094886001600160401b0383166122b0565b97505b505060019094019350612e7392505050565b506130bd816001600160401b0385166122b0565b82146130fa5760405162461bcd60e51b815260040180806020018281038252604b815260200180613f6e604b913960600191505060405180910390fd5b505050600101612e48565b6001600160a01b0381166119fb576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b600081848411156131ef5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156131b457818101518382015260200161319c565b50505050905090810190601f1680156131e15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b815160005b811561324c57818060019003925050826001600160401b031684838151811061322157fe5b602002602001015160000151600001516001600160401b0316116132475750600161324c565b6131fc565b9250929050565b8151805160209182015182850151805193015160009384936001600160401b039081169381169291811691168382136132ce576040805162461bcd60e51b81526020600482015260186024820152770daeae6e840c4ca40d8cacce85cf0407840e4d2ced0e85cf60431b604482015290519081900360640190fd5b83820394506001600160401b0387168481038202908303840201600081121561332c576040805162461bcd60e51b815260206004820152600b60248201526a3ab73232b9333637bb903760a91b604482015290519081900360640190fd5b600160801b8112613384576040805162461bcd60e51b815260206004820152601860248201527f73797374656d206572726f723a206f766572666c6f77206e0000000000000000604482015290519081900360640190fd5b989497509395505050505050565b600081836133e15760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156131b457818101518382015260200161319c565b5060008385816133ed57fe5b0495945050505050565b61235582826040518060600160405280602c815260200161411f602c91396139dd565b8051516020820151516001600160401b038082169083161061347e576040805162461bcd60e51b81526020600482015260186024820152770daeae6e840c4ca40d8cacce85cf0407840e4d2ced0e85cf60431b604482015290519081900360640190fd5b505050565b606080600061349184610c36565b600081815260026020908152604080832080548251818502810185019093528083529495506060949193909284015b82821015613539576000848152602090819020604080516080810182526002860290920180546001600160401b03808216858501908152600160401b92839004821660608701528552835180850190945260019283015480821685529190910416828501528284019190915290835290920191016134c0565b505050509050600061354a826127a7565b9050600061355783613b20565b905060007f000000000000000000000000000000000000000000000000000000000000000060ff16600a6001600160401b03160a6001600160401b0316836001600160401b0316816135a557fe5b04905060007f000000000000000000000000000000000000000000000000000000000000000060ff16600a6001600160401b03160a6001600160401b0316836001600160401b0316816135f457fe5b0490506001600160401b0384161561385357604080516313ba1d9360e31b8152604481018c90526001600160401b0384166064820152608060048201526003608482018190526214d09560ea1b60a4830181905260c0602484015260c483019190915260e482015290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691639dd0ec9891610104808301926000929190829003018186803b1580156136af57600080fd5b505afa1580156136c3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160409081528110156136ec57600080fd5b8101908080516040519392919084600160201b82111561370b57600080fd5b90830190602082018581111561372057600080fd5b8251600160201b81118282018810171561373957600080fd5b82525081516020918201929091019080838360005b8381101561376657818101518382015260200161374e565b50505050905090810190601f1680156137935780820380516001836020036101000a031916815260200191505b5060405260200180516040519392919084600160201b8211156137b557600080fd5b9083019060208201858111156137ca57600080fd5b8251600160201b8111828201881017156137e357600080fd5b82525081516020918201929091019080838360005b838110156138105781810151838201526020016137f8565b50505050905090810190601f16801561383d5780820380516001836020036101000a031916815260200191505b506040525050509750975050505050505061324c565b6001600160401b0383161561390b57604080516313ba1d9360e31b8152604481018c90526001600160401b0383166064820152608060048201526003608482018190526213109560ea1b60a4830181905260c0602484015260c483019190915260e482015290516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691639dd0ec9891610104808301926000929190829003018186803b1580156136af57600080fd5b604080516313ba1d9360e31b8152604481018c905260006064820181905260806004830152600360848301526212535560ea1b60a483015260c06024830152600f60c48301526e24b6b6b7b93a30b61027b83a34b7b760891b60e483015291516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692639dd0ec98926101048082019391829003018186803b1580156136af57600080fd5b60006118aa8383604051806060016040528060228152602001613dfc60229139613bf3565b6139e682613c69565b8190613a335760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156131b457818101518382015260200161319c565b506040516000906001600160a01b0385169084908381818185875af1925050503d8060008114613a7f576040519150601f19603f3d011682016040523d82523d6000602084013e613a84565b606091505b5050905080613ada576040805162461bcd60e51b815260206004820152601960248201527f7472616e7366657272696e67204574686572206661696c656400000000000000604482015290519081900360640190fd5b6040805184815290516001600160a01b0386169130917fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9181900360200190a350505050565b60008151600214613b3357506000610c31565b600082600081518110613b4257fe5b602002602001015160200151600001519050806001600160401b031660001415613b70576000915050610c31565b60005b835181101561285757613b84613cfc565b848281518110613b9057fe5b602002602001015190508060200151600001516001600160401b0316613bd9846001600160401b03168360200151602001516001600160401b0316611a5990919063ffffffff16565b14613bea5760009350505050610c31565b50600101613b73565b600083613c02575060006118aa565b8183613c4f5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156131b457818101518382015260200161319c565b50826001850381613c5c57fe5b0460010190509392505050565b3031101590565b60408051608081018252600080825260208201819052918101829052606081019190915290565b828054828255906000526020600020908101928215613cd2579160200282015b82811115613cd2578251825591602001919060010190613cb7565b50613cde929150613d21565b5090565b604051806040016040528060608152602001600081525090565b6040518060400160405280613d0f613d36565b8152602001613d1c613d36565b905290565b5b80821115613cde5760008155600101613d22565b60408051808201909152600080825260208201529056fe746865206772616469656e74206f66206c617374206c696e65207365676d656e74206d757374206265206e6f6e2d6e656761746976652c20616e6420657175616c20746f206f72206c657373207468616e2031646563696d616c20676170206e6565647320746f206265206c6f776572207468616e20313973797374656d206572726f723a20746865204944206f66206f7261636c6520646174612073686f756c64206e6f74206265207a65726f536166654d617468446976526f756e6455703a206d6f64756c6f206279207a65726f676976656e20706f6c796c696e652068617320616e20756e646566696e656420646f6d61696e2e7468652073657175656e7469616c207365676d656e7473206d757374206e6f742068617665207468652073616d65206772616469656e7463616e6e6f742065786368616e676520626f6e6473207769746820646966666572656e74206d617475726974696573676976656e20706f6c796c696e65206973206e6f74206120636f6e74696e756f75732066756e6374696f6e746865206d61747572697479206f662074686520626f6e6473206d7573742062652073616d657468657265206973206e6f2070726963652064617461206166746572206d61747572697479746865206d696e74696e6720616d6f756e74206d757374206265206e6f6e2d7a65726f6578636570742074686520666972737420626f6e64206d757374206e6f7420626520707572652053425474686520746f74616c20707269636520617420616e792072617465427265616b506f696e74732073686f756c64206265207468652073616d652076616c7565206173207468652072617465746865207920636f6f7264696e617465206f66206c65667420656e64206f6620746865206669727374207365676d656e74206d7573742062652030536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77416c6c2074686520657863657074696f6e426f6e6473206e65656420746f20626520696e636c7564656420696e20696e70757474686520626f6e64207479706520686173206265656e20616c72656164792072656769737465726564416c6c2074686520657863657074696f6e426f6e6473206e65656420746f20626520696e636c7564656420626f746820696e20696e70757420616e64206f757470757474686520626f6e642067726f75702073686f756c6420636f6e73697374206f662032206f72206d6f726520626f6e6473746865207820636f6f7264696e617465206f66206c65667420656e64206f6620746865206669727374207365676d656e74206d75737420626520305472616e736665724554483a207472616e7366657220616d6f756e7420657863656564732062616c616e6365746865206d61747572697479206d75737420626520746865206d756c7469706c65206f66204d415455524954595f5343414c45746865206c697374206f6620626f6e64204944206d757374206265206e6f6e2d656d707479a264697066735822122063a81399959e72b2960a3c4dddad64fe97d7afeac10d641129892298092ffbef64736f6c63430007010033746865206665652074616b6572206d757374206265206e6f6e2d7a65726f20616464726573736f7261636c65416464726573732073686f756c64206265206e6f6e2d7a65726f2061646472657373626f6e64546f6b656e4e616d6572416464726573732073686f756c64206265206e6f6e2d7a65726f206164647265737374686520646563696d616c73206f6620626f6e64206d757374206265206c657373207468616e203139626f6e64546f6b656e466163746f7279416464726573732073686f756c64206265206e6f6e2d7a65726f206164647265737374686520646563696d616c73206f66206f7261636c65207072696365206d757374206265206c657373207468616e2031390000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e00000000000000000000000096f1a323097806c485c87b012b0b9e8549f629f10000000000000000000000008b8843c0183422e00433145493dec7d3a195d51b0000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode
0x60806040526004361061010d5760003560e01c806379265a8511610095578063b9601d7711610064578063b9601d77146105e8578063d0d6153a14610618578063e59455e014610643578063f08e2a33146106be578063f2eefd80146106d35761014b565b806379265a851461058c5780638376c24d146105a1578063a89ae4ba146105be578063ac3fd886146105d35761014b565b806356481cb4116100dc57806356481cb41461034f5780636d17f168146103ee5780636f23bd401461049f5780637369bcaa146104cf578063749f1044146105775761014b565b806326d6c97b146101505780632770aa64146101b257806348d399e71461027c578063529aa16b146102ad5761014b565b3661014b57604080513481529051309133917fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9181900360200190a3005b600080fd5b34801561015c57600080fd5b5061017a6004803603602081101561017357600080fd5b5035610758565b604080516001600160a01b03909516855260208501939093526001600160401b03909116838301526060830152519081900360800190f35b3480156101be57600080fd5b5061026a600480360360408110156101d557600080fd5b81359190810190604081016020820135600160201b8111156101f657600080fd5b82018360208201111561020857600080fd5b803590602001918460018302840111600160201b8311171561022957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506107c9945050505050565b60408051918252519081900360200190f35b34801561028857600080fd5b5061029161085e565b604080516001600160a01b039092168252519081900360200190f35b3480156102b957600080fd5b5061033b600480360360808110156102d057600080fd5b81359160208101359160408201359190810190608081016060820135600160201b8111156102fd57600080fd5b82018360208201111561030f57600080fd5b803590602001918460208302840111600160201b8311171561033057600080fd5b50909250905061086d565b604080519115158252519081900360200190f35b34801561035b57600080fd5b506103796004803603602081101561037257600080fd5b5035610ad4565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103b357818101518382015260200161039b565b50505050905090810190601f1680156103e05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156103fa57600080fd5b5061026a6004803603602081101561041157600080fd5b810190602081018135600160201b81111561042b57600080fd5b82018360208201111561043d57600080fd5b803590602001918460018302840111600160201b8311171561045e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610c36945050505050565b3480156104ab57600080fd5b5061026a600480360360408110156104c257600080fd5b5080359060200135610c41565b3480156104db57600080fd5b50610551600480360360408110156104f257600080fd5b81359190810190604081016020820135600160201b81111561051357600080fd5b82018360208201111561052557600080fd5b803590602001918460018302840111600160201b8311171561054657600080fd5b509092509050610ef2565b604080519384526001600160a01b03909216602084015282820152519081900360600190f35b34801561058357600080fd5b506102916114cc565b34801561059857600080fd5b5061026a6114f0565b61026a600480360360208110156105b757600080fd5b5035611514565b3480156105ca57600080fd5b50610291611520565b3480156105df57600080fd5b5061026a611544565b3480156105f457600080fd5b5061033b6004803603604081101561060b57600080fd5b508035906020013561154a565b34801561062457600080fd5b5061062d6116bd565b6040805160ff9092168252519081900360200190f35b34801561064f57600080fd5b5061026a6004803603604081101561066657600080fd5b810190602081018135600160201b81111561068057600080fd5b82018360208201111561069257600080fd5b803590602001918460208302840111600160201b831117156106b357600080fd5b9193509150356116e1565b3480156106ca57600080fd5b5061062d6118b1565b3480156106df57600080fd5b506106fd600480360360208110156106f657600080fd5b50356118d5565b6040518080602001838152602001828103825284818151815260200191508051906020019060200280838360005b8381101561074357818101518382015260200161072b565b50505050905001935050505060405180910390f35b600080600080610766613c70565b505050600092835250506001602081815260409283902083516080810185528154808252938201546001600160a01b038116938201849052600160a01b90046001600160401b031694810185905260029091015460609091018190529093919291565b600030838360405160200180846001600160a01b031660601b815260140183815260200182805190602001908083835b602083106108185780518252601f1990920191602091820191016107f9565b6001836020036101000a03801982511681845116808217855250505050505090500193505050506040516020818303038152906040528051906020012090505b92915050565b60006108686119b9565b905090565b60006060600061087c886118d5565b91509150610889826119be565b60606000610896896118d5565b915091506108a3826119be565b8083146108e15760405162461bcd60e51b815260040180806020018281038252602f815260200180613e7c602f913960400191505060405180910390fd5b6108ea836119fe565b60008060005b865181101561097c576001925060005b8981101561094f5787828151811061091457fe5b60200260200101518b8b8381811061092857fe5b9050602002013514156109475760009350610944836001611a59565b92505b600101610900565b5082156109745761097487828151811061096557fe5b6020026020010151338d611ab3565b6001016108f0565b508781146109bb5760405162461bcd60e51b81526004018080602001828103825260338152602001806140156033913960400191505060405180910390fd5b60005b8451811015610a4a576001925060005b89811015610a1d578582815181106109e257fe5b60200260200101518b8b838181106109f657fe5b905060200201351415610a155760009350610a12836001611bb2565b92505b6001016109ce565b508215610a4257610a42858281518110610a3357fe5b6020026020010151338d611bf4565b6001016109be565b508015610a885760405162461bcd60e51b81526004018080602001828103825260438152602001806140716043913960600191505060405180910390fd5b604080518b815290518c918e9133917fd7cc25b50fd05b627f35998c0c134fd1f025ced4e16b99ca2feaeb8361664d44919081900360200190a45060019b9a5050505050505050505050565b600081815260026020526040902080546060919082906001600160401b0381118015610aff57600080fd5b50604051908082528060200260200182016040528015610b29578160200160208202803683370190505b50905060005b8254811015610bcd57610bae838281548110610b4757fe5b600091825260209182902060408051608081018252600290930290910180546001600160401b03808216858501908152600160401b928390048216606087015285528351808501909452600190920154808316845204168184015291810191909152611ced565b828281518110610bba57fe5b6020908102919091010152600101610b2f565b50806040516020018080602001828103825283818151815260200191508051906020019060200280838360005b83811015610c12578181015183820152602001610bfa565b5050505090500192505050604051602081830303815290604052925050505b919050565b805160209091012090565b600060606000610c50856118d5565b91509150610c5d826119be565b80610c66611d50565b1015610cb9576040805162461bcd60e51b815260206004820152601c60248201527f74686520626f6e6420686173206e6f7420657870697265642079657400000000604482015290519081900360640190fd5b60007f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d6001600160a01b0316634bfbbe0b6040518163ffffffff1660e01b8152600401602060405180830381600087803b158015610d1657600080fd5b505af1158015610d2a573d6000803e3d6000fd5b505050506040513d6020811015610d4057600080fd5b5051905080610d805760405162461bcd60e51b8152600401808060200182810382526036815260200180613dc66036913960400191505060405180910390fd5b6000610da6838715801590610d955750838811155b610d9f5783610da1565b875b611d54565b905080610dfa576040805162461bcd60e51b815260206004820152601e60248201527f70726963652073686f756c64206265206e6f6e2d7a65726f2076616c75650000604482015290519081900360640190fd5b600160401b8110610e52576040805162461bcd60e51b815260206004820152601e60248201527f70726963652073686f756c64206265206c657373207468616e20325e36340000604482015290519081900360640190fd5b60005b8451811015610e9a576000858281518110610e6c57fe5b602002602001015190506000610e828285611f74565b9050610e8e8882611a59565b97505050600101610e55565b508415610ee8576000610eba6103e8610eb48860026122b0565b90612309565b9050610ee67f000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e8261234b565b505b5050505092915050565b6000806000610f00866119fe565b610f08611d50565b6301e13380018610610f61576040805162461bcd60e51b815260206004820152601760248201527f746865206d6174757269747920697320746f6f20666172000000000000000000604482015290519081900360640190fd5b7f00000000000000000000000000000000000000000000000000000000000000018681610f8a57fe5b0615610fc75760405162461bcd60e51b815260040180806020018281038252603381526020018061414b6033913960400191505060405180910390fd5b60006110098787878080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506107c992505050565b600081815260016020819052604090912001549091506001600160a01b0316156110645760405162461bcd60e51b81526004018080602001828103825260298152602001806140486029913960400191505060405180910390fd5b60006110a587878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610c3692505050565b600081815260026020526040812054919250906112ef5760606110fd89898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061235992505050565b905060005b81518110156111c457600084815260026020526040902082516111389084908490811061112b57fe5b6020026020010151612401565b815460018082018455600093845260209384902083518051600290940290910180549186015167ffffffffffffffff199283166001600160401b03958616176fffffffffffffffff000000000000000019908116600160401b92871683021783559587015180519285018054919098015193169185169190911790941692169092021790915501611102565b50606060026000858152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b82821015611273576000848152602090819020604080516080810182526002860290920180546001600160401b03808216858501908152600160401b92839004821660608701528552835180850190945260019283015480821685529190910416828501528284019190915290835290920191016111fa565b50505050905061128281612456565b61128b81612746565b156112dd576040805162461bcd60e51b815260206004820181905260248201527f74686520626f6e6420697320302d76616c756520617420616e79207072696365604482015290519081900360640190fd5b6112e6816127a7565b925050506113b0565b606060026000848152602001908152602001600020805480602002602001604051908101604052809291908181526020016000905b8282101561139d576000848152602090819020604080516080810182526002860290920180546001600160401b03808216858501908152600160401b9283900482166060870152855283518085019094526001928301548082168552919091041682850152828401919091529083529092019101611324565b5050505090506113ac816127a7565b9150505b60006113f28a8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061285e92505050565b604080516080810182528c81526001600160a01b0383811660208084018281526001600160401b03898116868801908152606087018c815260008e81526001808752908a9020985189559351938801805492516001600160a01b0319909316949097169390931767ffffffffffffffff60a01b1916600160a01b9190921602179093559151600290930192909255825187815292519394508d93919288927f3ebc23c737571cd7ddd871023e6c7d173a086959da035cc9707ef4e80c4b6e0a929181900390910190a4929992985090965090945050505050565b7f000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e90565b7f000000000000000000000000000000000000000000000000000000000000000190565b60006108588234612a15565b7f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d90565b60005490565b60008161159e576040805162461bcd60e51b815260206004820181905260248201527f74686520626f6e6420616d6f756e74206d757374206265206e6f6e2d7a65726f604482015290519081900360640190fd5b606060006115ab856118d5565b915091506115b8826119be565b6115c1816119fe565b60005b82518110156115f3576115eb8382815181106115dc57fe5b60200260200101513387611ab3565b6001016115c4565b5060006115fe612b47565b9050600061162d867f000000000000000000000000000000000000000000000000000000000000000884612b4c565b905060006116426103e8610eb48460026122b0565b905061166e7f000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e8261234b565b611678338361234b565b60408051838152905133918a917fd696d42b904abc4f87f6ff63556b7cb4114b23ca9a5c5c312c6b352cadc47a399181900360200190a3506001979650505050505050565b7f000000000000000000000000000000000000000000000000000000000000000890565b6000611721848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250869250612bf4915050565b600061173f8585600081811061173357fe5b90506020020135610758565b50925060019150505b848110156117b557600061176187878481811061173357fe5b50925050506001600160401b038116156117ac5760405162461bcd60e51b815260040180806020018281038252602a815260200180613f44602a913960400191505060405180910390fd5b50600101611748565b5060005491506117c6826001611a59565b600055604080516060602087028083018201845292820187815291928392918991899182919086019084908082843760009201829052509385525050506020918201869052848152600382526040902082518051919261182b92849290910190613c97565b5060208201518160010155905050806001600160401b031683837f908f2c9b76fe27e36f828f88b8d9d0ebb7b536f27569521b54a6ba4c79a46901888860405180806020018281038252848482818152602001925060200280828437600083820152604051601f909101601f19169092018290039550909350505050a4505b9392505050565b7f000000000000000000000000000000000000000000000000000000000000000890565b606060008054831061192e576040805162461bcd60e51b815260206004820152601d60248201527f74686520626f6e642067726f757020646f6573206e6f74206578697374000000604482015290519081900360640190fd5b611936613ce2565b600084815260036020908152604091829020825181546060938102820184018552938101848152909391928492849184018282801561199457602002820191906000526020600020905b815481526020019060010190808311611980575b5050509183525050600191909101546020918201528151910151909590945092505050565b600090565b80516119fb5760405162461bcd60e51b815260040180806020018281038252602581526020018061417e6025913960400191505060405180910390fd5b50565b80611a07611d50565b106119fb576040805162461bcd60e51b815260206004820181905260248201527f746865206d617475726974792068617320616c72656164792065787069726564604482015290519081900360640190fd5b6000828201838110156118aa576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600083815260016020819052604090912001546001600160a01b0316611ad881613105565b806001600160a01b031663f05fcdf284846040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015611b2f57600080fd5b505af1158015611b43573d6000803e3d6000fd5b505050506040513d6020811015611b5957600080fd5b5051611bac576040805162461bcd60e51b815260206004820152601960248201527f6661696c656420746f206275726e20626f6e6420746f6b656e00000000000000604482015290519081900360640190fd5b50505050565b60006118aa83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613160565b600083815260016020819052604090912001546001600160a01b0316611c1981613105565b806001600160a01b03166340c10f1984846040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015611c7057600080fd5b505af1158015611c84573d6000803e3d6000fd5b505050506040513d6020811015611c9a57600080fd5b5051611bac576040805162461bcd60e51b815260206004820152601960248201527f6661696c656420746f206d696e7420626f6e6420746f6b656e00000000000000604482015290519081900360640190fd5b805180516020918201519282015180519201516001600160401b031660409290921b6fffffffffffffffff00000000000000001660c09190911b6001600160c01b03191660809390931b67ffffffffffffffff60801b1692909217919091171790565b4290565b6000827f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d6001600160a01b031663b633620c846040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015611dbd57600080fd5b505af1158015611dd1573d6000803e3d6000fd5b505050506040513d6020811015611de757600080fd5b505111611e255760405162461bcd60e51b8152600401808060200182810382526025815260200180613efc6025913960400191505060405180910390fd5b60001982015b8015611ed757837f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d6001600160a01b031663b633620c836040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015611e9857600080fd5b505af1158015611eac573d6000803e3d6000fd5b505050506040513d6020811015611ec257600080fd5b505111611ece57611ed7565b60001901611e2b565b7f0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d6001600160a01b031663e7572230826001016040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015611f4057600080fd5b505af1158015611f54573d6000803e3d6000fd5b505050506040513d6020811015611f6a57600080fd5b5051949350505050565b6000828152600160208190526040822001546001600160a01b0316611f9881613105565b6000848152600160209081526040808320600290810154845282528083208054825181850281018501909352808352909392839261205d929091869190859084015b82821015612053576000848152602090819020604080516080810182526002860290920180546001600160401b03808216858501908152600160401b9283900482166060870152855283518085019094526001928301548082168552919091041682850152828401919091529083529092019101611fda565b50505050876131f7565b915091508061206857fe5b6000806120e285858154811061207a57fe5b600091825260209182902060408051608081018252600290930290910180546001600160401b03808216858501908152600160401b92839004821660608701528552835180850190945260019092015480831684520416818401529181019190915289613253565b915091506000886001600160401b0316826001600160401b03160290506000876001600160a01b03166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561213a57600080fd5b505afa15801561214e573d6000803e3d6000fd5b505050506040513d602081101561216457600080fd5b50516040805163903d8e7760e01b81526001600160801b0380881660048301528516602482015290519192506000916001600160a01b038b169163903d8e7791604480830192602092919082900301818787803b1580156121c457600080fd5b505af11580156121d8573d6000803e3d6000fd5b505050506040513d60208110156121ee57600080fd5b5051905080156122a1576000612202612b47565b905061224f846001600160801b0316610eb4886001600160801b0316612249877f000000000000000000000000000000000000000000000000000000000000000887612b4c565b906122b0565b9a5061225b8a8c61234b565b604080516001600160801b0380891682528616602082015281518f927fc35eb5b2a98868fe11fdaa24c3ab70ddcbf1ab90e0bee977e05a6945bad21ff1928290030190a2505b50505050505050505092915050565b6000826122bf57506000610858565b828202828482816122cc57fe5b04146118aa5760405162461bcd60e51b8152600401808060200182810382526021815260200180613ff46021913960400191505060405180910390fd5b60006118aa83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250613392565b61235582826133f7565b5050565b606081806020019051602081101561237057600080fd5b8101908080516040519392919084600160201b82111561238f57600080fd5b9083019060208201858111156123a457600080fd5b82518660208202830111600160201b821117156123c057600080fd5b82525081516020918201928201910280838360005b838110156123ed5781810151838201526020016123d5565b505050509050016040525050509050919050565b612409613cfc565b50604080516080808201835260c084901c8284019081526001600160401b039185901c821660608401528252825180840184529284901c8116835290921660208083019190915282015290565b8051806124aa576040805162461bcd60e51b815260206004820181905260248201527f706f6c796c696e65206d757374206e6f7420626520656d707479206172726179604482015290519081900360640190fd5b6124b2613cfc565b826000815181106124bf57fe5b6020908102919091018101518051808301518284015193840151915193519294506001600160401b0390811691811691909103928116911681900390156125375760405162461bcd60e51b815260040180806020018281038252603b8152602001806140e4603b913960400191505060405180910390fd5b8251602001516001600160401b0316156125825760405162461bcd60e51b815260040180806020018281038252603b815260200180613fb9603b913960400191505060405180910390fd5b61258b8361341a565b612593613cfc565b60015b858110156126f1578681815181106125aa57fe5b602002602001015191506125bd8261341a565b8151516020860151516001600160401b0390811691161461260f5760405162461bcd60e51b8152600401808060200182810382526027815260200180613e1e6027913960400191505060405180910390fd5b8160000151602001516001600160401b03168560200151602001516001600160401b03161461266f5760405162461bcd60e51b815260040180806020018281038252602b815260200180613eab602b913960400191505060405180910390fd5b81516020808201518185015191820151925191516001600160401b03918216938216939093039291811691160384820286820214156126df5760405162461bcd60e51b8152600401808060200182810382526037815260200180613e456037913960400191505060405180910390fd5b92955093509091508390600101612596565b50600083121580156127035750818313155b61273e5760405162461bcd60e51b8152600401808060200182810382526053815260200180613d4e6053913960600191505060405180910390fd5b505050505050565b6000805b825181101561279e5761275b613cfc565b83828151811061276757fe5b602002602001015190508060200151602001516001600160401b031660001461279557600092505050610c31565b5060010161274a565b50600192915050565b600081516002146127ba57506000610c31565b6000826000815181106127c957fe5b602002602001015160200151600001519050806001600160401b0316600014156127f7576000915050610c31565b60005b83518110156128575761280b613cfc565b84828151811061281757fe5b60200260200101519050826001600160401b03168160200151602001516001600160401b03161461284e5760009350505050610c31565b506001016127fa565b5092915050565b600060608061286d8585613483565b9150915060007f0000000000000000000000008b8843c0183422e00433145493dec7d3a195d51b6001600160a01b031663b0904d9b600084867f00000000000000000000000000000000000000000000000000000000000000086040518563ffffffff1660e01b815260040180856001600160a01b0316815260200180602001806020018460ff168152602001838103835286818151815260200191508051906020019080838360005b8381101561292f578181015183820152602001612917565b50505050905090810190601f16801561295c5780820380516001836020036101000a031916815260200191505b50838103825285518152855160209182019187019080838360005b8381101561298f578181015183820152602001612977565b50505050905090810190601f1680156129bc5780820380516001836020036101000a031916815260200191505b509650505050505050602060405180830381600087803b1580156129df57600080fd5b505af11580156129f3573d6000803e3d6000fd5b505050506040513d6020811015612a0957600080fd5b50519695505050505050565b600060606000612a24856118d5565b91509150612a31826119be565b612a3a816119fe565b6000612a536103ea612a4d8760026122b0565b906139b8565b90506000612a5f612b47565b9050612a95612a6e8784611bb2565b827f0000000000000000000000000000000000000000000000000000000000000008612b4c565b945084612ad35760405162461bcd60e51b8152600401808060200182810382526023815260200180613f216023913960400191505060405180910390fd5b60005b8451811015612b0557612afd858281518110612aee57fe5b60200260200101513388611bf4565b600101612ad6565b50604080518681529051339189917f58119118163827fe45f023219bbd8afd3de022473ee123ab28257e6e7cb1a5969181900360200190a35050505092915050565b601290565b60008060008360ff168560ff161115612b6b575060ff83850316612b82565b8360ff168560ff161015612b825784840360ff1691505b601382108015612b925750601381105b612bcd5760405162461bcd60e51b8152600401808060200182810382526025815260200180613da16025913960400191505060405180910390fd5b612bea81600a0a610eb484600a0a896122b090919063ffffffff16565b9695505050505050565b600282511015612c355760405162461bcd60e51b81526004018080602001828103825260308152602001806140b46030913960400191505060405180910390fd5b6000805b8351811015612cdc57600060016000868481518110612c5457fe5b60200260200101518152602001908152602001600020905083816000015414612cae5760405162461bcd60e51b8152600401808060200182810382526026815260200180613ed66026913960400191505060405180910390fd5b6002818101546000908152602091909152604090208054612cd0908590611a59565b93505050600101612c39565b5060006060826001600160401b0381118015612cf757600080fd5b50604051908082528060200260200182016040528015612d21578160200160208202803683370190505b50905060005b8551811015612e4457600060016000888481518110612d4257fe5b60200260200101518152602001908152602001600020905060006002600083600201548152602001908152602001600020905060005b8154811015612e39576000828281548110612d8f57fe5b600091825260208220600160029092020101546001600160401b03169150805b88811015612df557826001600160401b0316888281518110612dcd57fe5b60200260200101516001600160401b03161415612ded5760019150612df5565b600101612daf565b508015612e03575050612e31565b81878981518110612e1057fe5b6001600160401b039092166020928302919091019091015250506001909501945b600101612d78565b505050600101612d27565b5060005b815181101561273e576000828281518110612e5f57fe5b602002602001015190506000806001905060005b89518110156130a9576000600160008c8481518110612e8e57fe5b602002602001015181526020019081526020016000209050600060026000836002015481526020019081526020016000209050600080612f6b83805480602002602001604051908101604052809291908181526020016000905b82821015612f61576000848152602090819020604080516080810182526002860290920180546001600160401b03808216858501908152600160401b9283900482166060870152855283518085019094526001928301548082168552919091041682850152828401919091529083529092019101612ee8565b50505050896131f7565b9150915080612fc1576040805162461bcd60e51b815260206004820152601960248201527f696e76616c696420646f6d61696e2065787072657373696f6e00000000000000604482015290519081900360640190fd5b60008061303b858581548110612fd357fe5b600091825260209182902060408051608081018252600290930290910180546001600160401b03808216858501908152600160401b9283900482166060870152855283518085019094526001909201548083168452041681840152918101919091528b613253565b91509150816001600160801b03166000146130975761307f6130668a6001600160401b0384166122b0565b6130798a6001600160801b0386166122b0565b90611a59565b9850613094886001600160401b0383166122b0565b97505b505060019094019350612e7392505050565b506130bd816001600160401b0385166122b0565b82146130fa5760405162461bcd60e51b815260040180806020018281038252604b815260200180613f6e604b913960600191505060405180910390fd5b505050600101612e48565b6001600160a01b0381166119fb576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b600081848411156131ef5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156131b457818101518382015260200161319c565b50505050905090810190601f1680156131e15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b815160005b811561324c57818060019003925050826001600160401b031684838151811061322157fe5b602002602001015160000151600001516001600160401b0316116132475750600161324c565b6131fc565b9250929050565b8151805160209182015182850151805193015160009384936001600160401b039081169381169291811691168382136132ce576040805162461bcd60e51b81526020600482015260186024820152770daeae6e840c4ca40d8cacce85cf0407840e4d2ced0e85cf60431b604482015290519081900360640190fd5b83820394506001600160401b0387168481038202908303840201600081121561332c576040805162461bcd60e51b815260206004820152600b60248201526a3ab73232b9333637bb903760a91b604482015290519081900360640190fd5b600160801b8112613384576040805162461bcd60e51b815260206004820152601860248201527f73797374656d206572726f723a206f766572666c6f77206e0000000000000000604482015290519081900360640190fd5b989497509395505050505050565b600081836133e15760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156131b457818101518382015260200161319c565b5060008385816133ed57fe5b0495945050505050565b61235582826040518060600160405280602c815260200161411f602c91396139dd565b8051516020820151516001600160401b038082169083161061347e576040805162461bcd60e51b81526020600482015260186024820152770daeae6e840c4ca40d8cacce85cf0407840e4d2ced0e85cf60431b604482015290519081900360640190fd5b505050565b606080600061349184610c36565b600081815260026020908152604080832080548251818502810185019093528083529495506060949193909284015b82821015613539576000848152602090819020604080516080810182526002860290920180546001600160401b03808216858501908152600160401b92839004821660608701528552835180850190945260019283015480821685529190910416828501528284019190915290835290920191016134c0565b505050509050600061354a826127a7565b9050600061355783613b20565b905060007f000000000000000000000000000000000000000000000000000000000000000860ff16600a6001600160401b03160a6001600160401b0316836001600160401b0316816135a557fe5b04905060007f000000000000000000000000000000000000000000000000000000000000000860ff16600a6001600160401b03160a6001600160401b0316836001600160401b0316816135f457fe5b0490506001600160401b0384161561385357604080516313ba1d9360e31b8152604481018c90526001600160401b0384166064820152608060048201526003608482018190526214d09560ea1b60a4830181905260c0602484015260c483019190915260e482015290516001600160a01b037f00000000000000000000000096f1a323097806c485c87b012b0b9e8549f629f11691639dd0ec9891610104808301926000929190829003018186803b1580156136af57600080fd5b505afa1580156136c3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160409081528110156136ec57600080fd5b8101908080516040519392919084600160201b82111561370b57600080fd5b90830190602082018581111561372057600080fd5b8251600160201b81118282018810171561373957600080fd5b82525081516020918201929091019080838360005b8381101561376657818101518382015260200161374e565b50505050905090810190601f1680156137935780820380516001836020036101000a031916815260200191505b5060405260200180516040519392919084600160201b8211156137b557600080fd5b9083019060208201858111156137ca57600080fd5b8251600160201b8111828201881017156137e357600080fd5b82525081516020918201929091019080838360005b838110156138105781810151838201526020016137f8565b50505050905090810190601f16801561383d5780820380516001836020036101000a031916815260200191505b506040525050509750975050505050505061324c565b6001600160401b0383161561390b57604080516313ba1d9360e31b8152604481018c90526001600160401b0383166064820152608060048201526003608482018190526213109560ea1b60a4830181905260c0602484015260c483019190915260e482015290516001600160a01b037f00000000000000000000000096f1a323097806c485c87b012b0b9e8549f629f11691639dd0ec9891610104808301926000929190829003018186803b1580156136af57600080fd5b604080516313ba1d9360e31b8152604481018c905260006064820181905260806004830152600360848301526212535560ea1b60a483015260c06024830152600f60c48301526e24b6b6b7b93a30b61027b83a34b7b760891b60e483015291516001600160a01b037f00000000000000000000000096f1a323097806c485c87b012b0b9e8549f629f11692639dd0ec98926101048082019391829003018186803b1580156136af57600080fd5b60006118aa8383604051806060016040528060228152602001613dfc60229139613bf3565b6139e682613c69565b8190613a335760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156131b457818101518382015260200161319c565b506040516000906001600160a01b0385169084908381818185875af1925050503d8060008114613a7f576040519150601f19603f3d011682016040523d82523d6000602084013e613a84565b606091505b5050905080613ada576040805162461bcd60e51b815260206004820152601960248201527f7472616e7366657272696e67204574686572206661696c656400000000000000604482015290519081900360640190fd5b6040805184815290516001600160a01b0386169130917fdd4e7375a5084e0c4cc4e1bfc7ba67beb26a368120ea78d2e0948123910bbf7c9181900360200190a350505050565b60008151600214613b3357506000610c31565b600082600081518110613b4257fe5b602002602001015160200151600001519050806001600160401b031660001415613b70576000915050610c31565b60005b835181101561285757613b84613cfc565b848281518110613b9057fe5b602002602001015190508060200151600001516001600160401b0316613bd9846001600160401b03168360200151602001516001600160401b0316611a5990919063ffffffff16565b14613bea5760009350505050610c31565b50600101613b73565b600083613c02575060006118aa565b8183613c4f5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156131b457818101518382015260200161319c565b50826001850381613c5c57fe5b0460010190509392505050565b3031101590565b60408051608081018252600080825260208201819052918101829052606081019190915290565b828054828255906000526020600020908101928215613cd2579160200282015b82811115613cd2578251825591602001919060010190613cb7565b50613cde929150613d21565b5090565b604051806040016040528060608152602001600081525090565b6040518060400160405280613d0f613d36565b8152602001613d1c613d36565b905290565b5b80821115613cde5760008155600101613d22565b60408051808201909152600080825260208201529056fe746865206772616469656e74206f66206c617374206c696e65207365676d656e74206d757374206265206e6f6e2d6e656761746976652c20616e6420657175616c20746f206f72206c657373207468616e2031646563696d616c20676170206e6565647320746f206265206c6f776572207468616e20313973797374656d206572726f723a20746865204944206f66206f7261636c6520646174612073686f756c64206e6f74206265207a65726f536166654d617468446976526f756e6455703a206d6f64756c6f206279207a65726f676976656e20706f6c796c696e652068617320616e20756e646566696e656420646f6d61696e2e7468652073657175656e7469616c207365676d656e7473206d757374206e6f742068617665207468652073616d65206772616469656e7463616e6e6f742065786368616e676520626f6e6473207769746820646966666572656e74206d617475726974696573676976656e20706f6c796c696e65206973206e6f74206120636f6e74696e756f75732066756e6374696f6e746865206d61747572697479206f662074686520626f6e6473206d7573742062652073616d657468657265206973206e6f2070726963652064617461206166746572206d61747572697479746865206d696e74696e6720616d6f756e74206d757374206265206e6f6e2d7a65726f6578636570742074686520666972737420626f6e64206d757374206e6f7420626520707572652053425474686520746f74616c20707269636520617420616e792072617465427265616b506f696e74732073686f756c64206265207468652073616d652076616c7565206173207468652072617465746865207920636f6f7264696e617465206f66206c65667420656e64206f6620746865206669727374207365676d656e74206d7573742062652030536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77416c6c2074686520657863657074696f6e426f6e6473206e65656420746f20626520696e636c7564656420696e20696e70757474686520626f6e64207479706520686173206265656e20616c72656164792072656769737465726564416c6c2074686520657863657074696f6e426f6e6473206e65656420746f20626520696e636c7564656420626f746820696e20696e70757420616e64206f757470757474686520626f6e642067726f75702073686f756c6420636f6e73697374206f662032206f72206d6f726520626f6e6473746865207820636f6f7264696e617465206f66206c65667420656e64206f6620746865206669727374207365676d656e74206d75737420626520305472616e736665724554483a207472616e7366657220616d6f756e7420657863656564732062616c616e6365746865206d61747572697479206d75737420626520746865206d756c7469706c65206f66204d415455524954595f5343414c45746865206c697374206f6620626f6e64204944206d757374206265206e6f6e2d656d707479a264697066735822122063a81399959e72b2960a3c4dddad64fe97d7afeac10d641129892298092ffbef64736f6c63430007010033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e00000000000000000000000096f1a323097806c485c87b012b0b9e8549f629f10000000000000000000000008b8843c0183422e00433145493dec7d3a195d51b0000000000000000000000000000000000000000000000000000000000000001
-----Decoded View---------------
Arg [0] : oracleAddress (address): 0x6e33f11625b2c8B7270cf8e0319b8B9fFB8F086D
Arg [1] : feeTaker (address): 0xaB37e1358b639Fd877f015027Bb62d3ddAa7557E
Arg [2] : bondTokenNamerAddress (address): 0x96f1A323097806c485C87b012B0B9E8549f629F1
Arg [3] : bondTokenFactoryAddress (address): 0x8b8843C0183422E00433145493deC7d3A195d51b
Arg [4] : maturityScale (uint256): 1
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000006e33f11625b2c8b7270cf8e0319b8b9ffb8f086d
Arg [1] : 000000000000000000000000ab37e1358b639fd877f015027bb62d3ddaa7557e
Arg [2] : 00000000000000000000000096f1a323097806c485c87b012b0b9e8549f629f1
Arg [3] : 0000000000000000000000008b8843c0183422e00433145493dec7d3a195d51b
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000001
Deployed Bytecode Sourcemap
91463:2978:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;488:52;;;530:9;488:52;;;;523:4;;503:10;;488:52;;;;;;;;;91463:2978;;;;;81452:503;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;81452:503:0;;:::i;:::-;;;;-1:-1:-1;;;;;81452:503:0;;;;;;;;;;;;-1:-1:-1;;;;;81452:503:0;;;;;;;;;;;;;;;;;;;;83238:234;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;83238:234:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;83238:234:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;83238:234:0;;-1:-1:-1;83238:234:0;;-1:-1:-1;;;;;83238:234:0:i;:::-;;;;;;;;;;;;;;;;80461:116;;;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;80461:116:0;;;;;;;;;;;;;;76556:2271;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;76556:2271:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;76556:2271:0;;;;;;;;;;-1:-1:-1;76556:2271:0;;-1:-1:-1;76556:2271:0;-1:-1:-1;76556:2271:0;:::i;:::-;;;;;;;;;;;;;;;;;;82028:393;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;82028:393:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82990:134;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;82990:134:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;82990:134:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;82990:134:0;;-1:-1:-1;82990:134:0;;-1:-1:-1;;;;;82990:134:0:i;79180:1273::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;79180:1273:0;;;;;;;:::i;66416:2228::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;66416:2228:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;66416:2228:0;;;;;;;;;;-1:-1:-1;66416:2228:0;;-1:-1:-1;66416:2228:0;-1:-1:-1;66416:2228:0;:::i;:::-;;;;;;;-1:-1:-1;;;;;66416:2228:0;;;;;;;;;;;;;;;;;;;;80713:96;;;;;;;;;;;;;:::i;81062:106::-;;;;;;;;;;;;;:::i;92427:152::-;;;;;;;;;;;;;;;;-1:-1:-1;92427:152:0;;:::i;80585:120::-;;;;;;;;;;;;;:::i;81176:110::-;;;;;;;;;;;;;:::i;75085:1074::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;75085:1074:0;;;;;;;:::i;80932:122::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;72772:835;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;72772:835:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;72772:835:0;;;;;;;;;;;;-1:-1:-1;72772:835:0;-1:-1:-1;72772:835:0;;:::i;80817:107::-;;;;;;;;;;;;;:::i;82524:394::-;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;82524:394:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;81452:503;81565:24;81604:16;81635:23;81673:15;81716:24;;:::i;:::-;-1:-1:-1;;;81743:14:0;;;;-1:-1:-1;;81743:6:0;:14;;;;;;;;;81716:41;;;;;;;;;;;;;;;;-1:-1:-1;;;;;81716:41:0;;;;;;;;-1:-1:-1;;;81716:41:0;;-1:-1:-1;;;;;81716:41:0;;;;;;;;;;;;;;;;;;;;;;;;81452:503::o;83238:234::-;83366:14;83440:4;83447:8;83457:5;83415:48;;;;;;-1:-1:-1;;;;;83415:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;83415:48:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83405:59;;;;;;83398:66;;83238:234;;;;;:::o;80461:116::-;80522:7;80549:20;:18;:20::i;:::-;80542:27;;80461:116;:::o;76556:2271::-;76771:4;76789:25;76816:21;76841:30;76854:16;76841:12;:30::i;:::-;76788:83;;;;76882:34;76907:8;76882:24;:34::i;:::-;76928:26;76956:22;76982:31;76995:17;76982:12;:31::i;:::-;76927:86;;;;77024:35;77049:9;77024:24;:35::i;:::-;77095:14;77078:13;:31;77070:91;;;;-1:-1:-1;;;77070:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77172:36;77194:13;77172:21;:36::i;:::-;77221:9;77241:22;77279:9;77274:665;77298:8;:15;77294:1;:19;77274:665;;;77429:4;77422:11;;77453:9;77448:379;77468:25;;;77448:379;;;77544:8;77553:1;77544:11;;;;;;;;;;;;;;77523:14;;77538:1;77523:17;;;;;;;;;;;;;:32;77519:293;;;77587:5;;-1:-1:-1;77771:21:0;:14;77790:1;77771:18;:21::i;:::-;77754:38;;77519:293;77495:3;;77448:379;;;;77845:4;77841:87;;;77870:42;77880:8;77889:1;77880:11;;;;;;;;;;;;;;77893:10;77905:6;77870:9;:42::i;:::-;77315:3;;77274:665;;;-1:-1:-1;77973:39:0;;;77951:140;;;;-1:-1:-1;;;77951:140:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78109:9;78104:442;78128:9;:16;78124:1;:20;78104:442;;;78173:4;78166:11;;78197:9;78192:241;78212:25;;;78192:241;;;78288:9;78298:1;78288:12;;;;;;;;;;;;;;78267:14;;78282:1;78267:17;;;;;;;;;;;;;:33;78263:155;;;78332:5;;-1:-1:-1;78377:21:0;:14;78396:1;78377:18;:21::i;:::-;78360:38;;78263:155;78239:3;;78192:241;;;;78451:4;78447:88;;;78476:43;78486:9;78496:1;78486:12;;;;;;;;;;;;;;78500:10;78512:6;78476:9;:43::i;:::-;78146:3;;78104:442;;;-1:-1:-1;78580:19:0;;78558:136;;;;-1:-1:-1;;;78558:136:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;78712:83;;;;;;;;78769:17;;78751:16;;78739:10;;78712:83;;;;;;;;;;-1:-1:-1;78815:4:0;;76556:2271;-1:-1:-1;;;;;;;;;;;76556:2271:0:o;82028:393::-;82124:30;82157:25;;;:16;:25;;;;;82235:15;;82093:18;;82157:25;82093:18;;-1:-1:-1;;;;;82221:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;82221:30:0;;82193:58;;82267:9;82262:114;82286:15;;82282:19;;82262:114;;;82337:27;82352:8;82361:1;82352:11;;;;;;;;;;;;;;;;;82337:27;;;;;;;;82352:11;;;;;;;82337:27;;-1:-1:-1;;;;;82337:27:0;;;;;;;;;-1:-1:-1;;;82337:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:14;:27::i;:::-;82323:8;82332:1;82323:11;;;;;;;;;;;;;;;;;:41;82303:3;;82262:114;;;;82404:8;82393:20;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82386:27;;;;82028:393;;;;:::o;82990:134::-;83100:16;;;;;;;;82990:134::o;79180:1273::-;79317:20;79356:24;79382:16;79402:25;79415:11;79402:12;:25::i;:::-;79355:72;;;;79438:33;79463:7;79438:24;:33::i;:::-;79517:8;79490:23;:21;:23::i;:::-;:35;;79482:76;;;;;-1:-1:-1;;;79482:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;79571:16;79590:15;-1:-1:-1;;;;;79590:24:0;;:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;79590:26:0;;-1:-1:-1;79635:13:0;79627:80;;;;-1:-1:-1;;;79627:80:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79720:13;79736:133;79762:8;79786:17;;;;;:45;;;79823:8;79807:12;:24;;79786:45;79785:73;;79850:8;79785:73;;;79835:12;79785:73;79736:11;:133::i;:::-;79720:149;-1:-1:-1;79888:10:0;79880:53;;;;;-1:-1:-1;;;79880:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;79952:5:0;:13;79944:56;;;;;-1:-1:-1;;;79944:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;80018:9;80013:244;80037:7;:14;80033:1;:18;80013:244;;;80073:14;80090:7;80098:1;80090:10;;;;;;;;;;;;;;80073:27;;80115:15;80133:57;80168:6;80183:5;80133:34;:57::i;:::-;80115:75;-1:-1:-1;80220:25:0;:12;80115:75;80220:16;:25::i;:::-;80205:40;-1:-1:-1;;;80053:3:0;;80013:244;;;-1:-1:-1;80273:17:0;;80269:177;;80307:11;80321:29;80345:4;80321:19;:12;80338:1;80321:16;:19::i;:::-;:23;;:29::i;:::-;80307:43;;80392:42;80418:9;80430:3;80392:17;:42::i;:::-;80269:177;;79180:1273;;;;;;;;:::o;66416:2228::-;66566:7;66588;66610;66645:31;66667:8;66645:21;:31::i;:::-;66706:23;:21;:23::i;:::-;66732:8;66706:34;66695:8;:45;66687:81;;;;;-1:-1:-1;;;66687:81:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;66812:14;66801:8;:25;;;;;;:30;66779:131;;;;-1:-1:-1;;;66779:131:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66923:14;66940:31;66955:8;66965:5;;66940:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;66940:14:0;;-1:-1:-1;;;66940:31:0:i;:::-;67252:1;67208:14;;;:6;:14;;;;;;;;:31;;66923:48;;-1:-1:-1;;;;;;67208:31:0;67200:54;67178:145;;;;-1:-1:-1;;;67178:145:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67388:15;67406:22;67422:5;;67406:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;67406:15:0;;-1:-1:-1;;;67406:22:0:i;:::-;67439:21;67475:25;;;:16;:25;;;;;:32;67388:40;;-1:-1:-1;67439:21:0;67471:685;;67529:25;67557:21;67572:5;;67557:21;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;67557:14:0;;-1:-1:-1;;;67557:21:0:i;:::-;67529:49;;67598:9;67593:142;67617:8;:15;67613:1;:19;67593:142;;;67658:25;;;;:16;:25;;;;;67706:11;;67689:29;;67706:8;;67715:1;;67706:11;;;;;;;;;;;;67689:16;:29::i;:::-;67658:61;;;;;;;;-1:-1:-1;67658:61:0;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;67658:61:0;;;-1:-1:-1;;;;;67658:61:0;;;;-1:-1:-1;;67658:61:0;;;-1:-1:-1;;;67658:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67634:3;67593:142;;;;67751:29;67783:16;:25;67800:7;67783:25;;;;;;;;;;;67751:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;67751:57:0;;;;;;;;;-1:-1:-1;;;67751:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67823:24;67838:8;67823:14;:24::i;:::-;67871:26;67888:8;67871:16;:26::i;:::-;67870:27;67862:72;;;;;-1:-1:-1;;;67862:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;67966:28;67985:8;67966:18;:28::i;:::-;67949:45;;67471:685;;;;;68027:29;68059:16;:25;68076:7;68059:25;;;;;;;;;;;68027:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;68027:57:0;;;;;;;;;-1:-1:-1;;;68027:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;68116:28;68135:8;68116:18;:28::i;:::-;68099:45;;67471:685;;68168:36;68207;68227:8;68237:5;;68207:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;68207:19:0;;-1:-1:-1;;;68207:36:0:i;:::-;68311:177;;;;;;;;;;;-1:-1:-1;;;;;68311:177:0;;;;;;;;;;-1:-1:-1;;;;;68311:177:0;;;;;;;;;;;;;;;-1:-1:-1;68294:14:0;;;:6;:14;;;;;;;:194;;;;;;;;;;;;;-1:-1:-1;;;;;;68294:194:0;;;;;;;;;;;-1:-1:-1;;;;68294:194:0;-1:-1:-1;;;68294:194:0;;;;;;;;;;;;;;;;;;;68506:65;;;;;;;68311:177;;-1:-1:-1;68311:177:0;;;;68294:14;;68506:65;;;;;;;;;;;68592:6;;;;-1:-1:-1;68628:7:0;;-1:-1:-1;66416:2228:0;;-1:-1:-1;;;;;66416:2228:0:o;80713:96::-;80792:9;80713:96;:::o;81062:106::-;81146:14;81062:106;:::o;92427:152::-;92495:18;92533:38;92548:11;92561:9;92533:14;:38::i;80585:120::-;80682:15;80585:120;:::o;81176:110::-;81235:7;81262:16;81176:110;:::o;75085:1074::-;75235:4;75265:15;75257:60;;;;;-1:-1:-1;;;75257:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75331:24;75357:16;75377:25;75390:11;75377:12;:25::i;:::-;75330:72;;;;75413:33;75438:7;75413:24;:33::i;:::-;75457:31;75479:8;75457:21;:31::i;:::-;75504:9;75499:117;75523:7;:14;75519:1;:18;75499:117;;;75559:45;75569:7;75577:1;75569:10;;;;;;;;;;;;;;75581;75593;75559:9;:45::i;:::-;75539:3;;75499:117;;;;75628:26;75657:24;:22;:24::i;:::-;75628:53;;75692:24;75719:118;75750:10;75775:16;75806:20;75719:16;:118::i;:::-;75692:145;-1:-1:-1;75850:11:0;75864:33;75892:4;75864:23;75692:145;75885:1;75864:20;:23::i;:33::-;75850:47;;75935:42;75961:9;75973:3;75935:17;:42::i;:::-;75988:47;76006:10;76018:16;75988:17;:47::i;:::-;76053:74;;;;;;;;76098:10;;76085:11;;76053:74;;;;;;;;;-1:-1:-1;76147:4:0;;75085:1074;-1:-1:-1;;;;;;;75085:1074:0:o;80932:122::-;81022:24;80932:122;:::o;72772:835::-;72919:19;72956:35;72973:7;;72956:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;72982:8:0;;-1:-1:-1;72956:16:0;;-1:-1:-1;;72956:35:0:i;:::-;73009:21;73036:19;73044:7;;73052:1;73044:10;;;;;;;;;;;;;73036:7;:19::i;:::-;-1:-1:-1;73004:51:0;-1:-1:-1;73083:1:0;;-1:-1:-1;;73066:206:0;73086:18;;;73066:206;;;73131:18;73155:19;73163:7;;73171:1;73163:10;;;;;;73155:19;-1:-1:-1;73126:48:0;-1:-1:-1;;;;;;;;73197:16:0;;;73189:71;;;;-1:-1:-1;;;73189:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;73106:3:0;;73066:206;;;-1:-1:-1;73347:16:0;;;-1:-1:-1;73393:23:0;73347:16;73414:1;73393:20;:23::i;:::-;73374:16;:42;73459:28;;;;;;;;;;;;;;;;;;;;;;;;;73469:7;;;;;;73459:28;;;;73469:7;;73459:28;73469:7;73459:28;;;;;;;;-1:-1:-1;73459:28:0;;;-1:-1:-1;;;73459:28:0;;;;;;;73429:27;;;:14;:27;;;;;:58;;;;:27;;:58;;:27;;:58;;;;;:::i;:::-;;;;;;;;;;;;;73544:14;-1:-1:-1;;;;;73505:63:0;73534:8;73521:11;73505:63;73560:7;;73505:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;73505:63:0;;;;;;;;-1:-1:-1;73505:63:0;;-1:-1:-1;;;;73505:63:0;73581:18;72772:835;;;;;;:::o;80817:107::-;80900:16;80817:107;:::o;82524:394::-;82633:24;82659:16;82715;;82701:11;:30;82693:72;;;;;-1:-1:-1;;;82693:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;82776:26;;:::i;:::-;82805:27;;;;:14;:27;;;;;;;;;82776:56;;;;;;;;;;;;;;;;;;;;;;82805:27;;82776:56;;82805:27;;82776:56;;82805:27;82776:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;82776:56:0;;;-1:-1:-1;;82776:56:0;;;;;;;;;;;82853:17;;82892:18;;;82853:17;;82892:18;;-1:-1:-1;82524:394:0;-1:-1:-1;;;82524:394:0:o;94077:107::-;94139:7;94077:107;:::o;87271:162::-;87364:14;;87356:69;;;;-1:-1:-1;;;87356:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87271:162;:::o;87441:161::-;87549:8;87523:23;:21;:23::i;:::-;:34;87515:79;;;;;-1:-1:-1;;;87515:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;2372:181;2430:7;2462:5;;;2486:6;;;;2478:46;;;;;-1:-1:-1;;;2478:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;83827:345;83949:36;83988:14;;;:6;:14;;;;;;;;:31;;-1:-1:-1;;;;;83988:31:0;84030:40;83988:31;84030:21;:40::i;:::-;84089:17;-1:-1:-1;;;;;84089:28:0;;84118:7;84127:6;84089:45;;;;;;;;;;;;;-1:-1:-1;;;;;84089:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;84089:45:0;84081:83;;;;;-1:-1:-1;;;84081:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;83827:345;;;;:::o;2836:136::-;2894:7;2921:43;2925:1;2928;2921:43;;;;;;;;;;;;;;;;;:3;:43::i;83480:339::-;83602:36;83641:14;;;:6;:14;;;;;;;;:31;;-1:-1:-1;;;;;83641:31:0;83683:40;83641:31;83683:21;:40::i;:::-;83742:17;-1:-1:-1;;;;;83742:22:0;;83765:7;83774:6;83742:39;;;;;;;;;;;;;-1:-1:-1;;;;;83742:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;83742:39:0;83734:77;;;;;-1:-1:-1;;;83734:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;;62705:429;62829:12;;:14;;62908;;;;;62982:13;;;;:15;;63050;;;-1:-1:-1;;;;;63042:24:0;63002:2;62974:30;;;;;;62849:12;62821:41;;;;-1:-1:-1;;;;;;62821:41:0;62928:7;62900:36;;;;-1:-1:-1;;;62900:36:0;63093:15;;;;:24;;;;:33;;62705:429::o;26293:166::-;26395:15;;26293:166::o;85831:495::-;85905:15;85994:9;85955:15;-1:-1:-1;;;;;85955:28:0;;85984:6;85955:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85955:36:0;:48;85933:135;;;;-1:-1:-1;;;85933:135:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;86094:10:0;;86115:152;86122:7;;86115:152;;86186:9;86150:15;-1:-1:-1;;;;;86150:28:0;;86179:2;86150:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;86150:32:0;:45;86146:91;;86216:5;;86146:91;-1:-1:-1;;86251:4:0;86115:152;;;86286:15;-1:-1:-1;;;;;86286:24:0;;86311:2;86316:1;86311:6;86286:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;86286:32:0;;85831:495;-1:-1:-1;;;;85831:495:0:o;84180:1294::-;84290:24;84371:14;;;:6;:14;;;;;;;:31;;-1:-1:-1;;;;;84371:31:0;84413:40;84371:31;84413:21;:40::i;:::-;84466:30;84516:14;;;:6;:14;;;;;;;;84499:16;84516:22;;;;84499:40;;;;;;;84586:35;;;;;;;;;;;;;;;;;84499:40;;84466:30;;;84586:35;;;;84499:40;;84586:35;84466:30;;84586:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;84586:35:0;;;;;;;;;-1:-1:-1;;;84586:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84615:5;84586:18;:35::i;:::-;84552:69;;;;84639:2;84632:10;;;;84719:9;84730;84743:39;84752:8;84761:12;84752:22;;;;;;;;;;;;;;;;;84743:39;;;;;;;;84752:22;;;;;;;84743:39;;-1:-1:-1;;;;;84743:39:0;;;;;;;;;-1:-1:-1;;;84743:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84776:5;84743:8;:39::i;:::-;84718:64;;;;84871:9;84905:5;-1:-1:-1;;;;;84897:14:0;84891:2;-1:-1:-1;;;;;84883:11:0;:28;84871:40;;84924:19;84946:17;-1:-1:-1;;;;;84946:29:0;;:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;84946:31:0;85007:30;;;-1:-1:-1;;;85007:30:0;;-1:-1:-1;;;;;85007:30:0;;;;;;;;;;;;;;;84946:31;;-1:-1:-1;84988:16:0;;-1:-1:-1;;;;;85007:24:0;;;;;:30;;;;;84946:31;;85007:30;;;;;;;84988:16;85007:24;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;85007:30:0;;-1:-1:-1;85087:380:0;;;;85119:26;85148:24;:22;:24::i;:::-;85119:53;;85206:119;85323:1;-1:-1:-1;;;;;85206:119:0;:94;85298:1;-1:-1:-1;;;;;85206:94:0;:69;85223:11;85236:16;85254:20;85206:16;:69::i;:::-;:91;;:94::i;:119::-;85187:138;;85340:63;85366:17;85386:16;85340:17;:63::i;:::-;85425:30;;;-1:-1:-1;;;;;85425:30:0;;;;;;;;;;;;;85442:6;;85425:30;;;;;;;;85087:380;;84180:1294;;;;;;;;;;;;;:::o;3726:471::-;3784:7;4029:6;4025:47;;-1:-1:-1;4059:1:0;4052:8;;4025:47;4096:5;;;4100:1;4096;:5;:1;4120:5;;;;;:10;4112:56;;;;-1:-1:-1;;;4112:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4673:132;4731:7;4758:39;4762:1;4765;4758:39;;;;;;;;;;;;;;;;;:3;:39::i;94301:137::-;94391:39;94412:8;94423:6;94391:12;:39::i;:::-;94301:137;;:::o;63642:141::-;63709:16;63756:5;63745:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;63745:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;63745:30:0;;;;;;;;;;;;-1:-1:-1;63745:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63738:37;;63642:141;;;:::o;63217:353::-;63279:18;;:::i;:::-;-1:-1:-1;63435:2:0;63490:72;;63389:7;63509:21;;;;;63337:12;63329:21;;;63490:72;;;63509:21;;;-1:-1:-1;;;;;63381:16:0;;;;63509:21;;;;;;63490:72;;63539:21;;;;;;;63428:9;;;;63539:21;;;;;;;-1:-1:-1;63539:21:0;;;;;;;-1:-1:-1;;63490:72:0;;63217:353::o;59758:2807::-;59861:15;;59895:17;59887:62;;;;;-1:-1:-1;;;59887:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59962:30;;:::i;:::-;59995:8;60004:1;59995:11;;;;;;;;;;;;;;;;;;;60092:16;;:18;;;;60062:17;;;;:19;;;;60199:18;;60169:19;;59995:11;;-1:-1:-1;;;;;;60085:26:0;;;60055:27;;;:56;;;;;60192:26;;60162:27;;:56;;;;60331:31;60309:140;;;;-1:-1:-1;;;60309:140:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60527:16;;:18;;;-1:-1:-1;;;;;60527:31:0;;60505:140;;;;-1:-1:-1;;;60505:140:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60731:30;60749:11;60731:17;:30::i;:::-;60904:31;;:::i;:::-;60974:1;60957:1306;60981:12;60977:1;:16;60957:1306;;;61030:8;61039:1;61030:11;;;;;;;;;;;;;;61015:26;;61132:31;61150:12;61132:17;:31::i;:::-;61287:17;;:19;61264:17;;;;:19;-1:-1:-1;;;;;61264:42:0;;;;;;61238:143;;;;-1:-1:-1;;;61238:143:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61505:12;:17;;;:19;;;-1:-1:-1;;;;;61482:42:0;:11;:17;;;:19;;;-1:-1:-1;;;;;61482:42:0;;61456:147;;;;-1:-1:-1;;;61456:147:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61706:17;;:19;;;;;61658:18;;;;:20;;;;61829:19;;61781:20;;-1:-1:-1;;;;;61699:27:0;;;61651:28;;;:75;;;;;61822:27;;;61774:28;;:75;61890:43;;;61958;;;61890:111;;61864:228;;;;-1:-1:-1;;;61864:228:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62123:12;;-1:-1:-1;62170:21:0;-1:-1:-1;62228:23:0;;-1:-1:-1;62123:12:0;;60995:3;;60957:1306;;;;62401:1;62380:17;:22;;:66;;;;;62427:19;62406:17;:40;;62380:66;62358:199;;;;-1:-1:-1;;;62358:199:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59758:2807;;;;;;:::o;87610:328::-;87690:4;;87707:200;87731:8;:15;87727:1;:19;87707:200;;;87768:26;;:::i;:::-;87797:8;87806:1;87797:11;;;;;;;;;;;;;;87768:40;;87827:7;:13;;;:15;;;-1:-1:-1;;;;;87827:20:0;87846:1;87827:20;87823:73;;87875:5;87868:12;;;;;;87823:73;-1:-1:-1;87748:3:0;;87707:200;;;-1:-1:-1;87926:4:0;;87610:328;-1:-1:-1;;87610:328:0:o;88145:548::-;88227:6;88250:8;:15;88269:1;88250:20;88246:61;;-1:-1:-1;88294:1:0;88287:8;;88246:61;88319:18;88340:8;88349:1;88340:11;;;;;;;;;;;;;;:17;;;:19;;;88319:40;;88376:11;-1:-1:-1;;;;;88376:16:0;88391:1;88376:16;88372:57;;;88416:1;88409:8;;;;;88372:57;88446:9;88441:206;88465:8;:15;88461:1;:19;88441:206;;;88502:26;;:::i;:::-;88531:8;88540:1;88531:11;;;;;;;;;;;;;;88502:40;;88580:11;-1:-1:-1;;;;;88561:30:0;:7;:13;;;:15;;;-1:-1:-1;;;;;88561:30:0;;88557:79;;88619:1;88612:8;;;;;;;88557:79;-1:-1:-1;88482:3:0;;88441:206;;;-1:-1:-1;88673:11:0;88145:548;-1:-1:-1;;88145:548:0:o;92587:460::-;92708:18;92745:20;92767:18;92789:34;92807:8;92817:5;92789:17;:34::i;:::-;92744:79;;;;92834:19;92856:18;-1:-1:-1;;;;;92856:34:0;;91571:1;92923:4;92942:6;92963:16;92856:134;;;;;;;;;;;;;-1:-1:-1;;;;;92856:134:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;92856:134:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;92856:134:0;;92587:460;-1:-1:-1;;;;;;92587:460:0:o;73944:894::-;74058:18;74095:24;74121:16;74141:25;74154:11;74141:12;:25::i;:::-;74094:72;;;;74177:33;74202:7;74177:24;:33::i;:::-;74221:31;74243:8;74221:21;:31::i;:::-;74265:11;74279:47;74321:4;74279:30;:23;74307:1;74279:27;:30::i;:::-;:41;;:47::i;:::-;74265:61;;74339:26;74368:24;:22;:24::i;:::-;74339:53;-1:-1:-1;74416:140:0;74447:32;:23;74475:3;74447:27;:32::i;:::-;74494:20;74529:16;74416;:140::i;:::-;74403:153;-1:-1:-1;74575:15:0;74567:63;;;;-1:-1:-1;;;74567:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74648:9;74643:117;74667:7;:14;74663:1;:18;74643:117;;;74703:45;74713:7;74721:1;74713:10;;;;;;;;;;;;;;74725;74737;74703:9;:45::i;:::-;74683:3;;74643:117;;;-1:-1:-1;74777:53:0;;;;;;;;74807:10;;74794:11;;74777:53;;;;;;;;;73944:894;;;;;;;;:::o;94192:101::-;94283:2;94192:101;:::o;86398:676::-;86546:19;86578:9;86598;86641:15;86624:32;;:14;:32;;;86620:208;;;-1:-1:-1;86673:36:0;86677:32;;;86673:36;86620:208;;;86748:15;86731:32;;:14;:32;;;86727:101;;;86802:14;86784:15;:32;86780:36;;;;86727:101;86955:2;86951:1;:6;:16;;;;;86965:2;86961:1;:6;86951:16;86943:66;;;;-1:-1:-1;;;86943:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87034:32;87064:1;87060:2;:5;87034:21;87053:1;87049:2;:5;87034:10;:14;;:21;;;;:::i;:32::-;87020:46;86398:676;-1:-1:-1;;;;;;86398:676:0:o;69384:3067::-;69505:1;69487:7;:14;:19;;69479:80;;;;-1:-1:-1;;;69479:80:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69572:24;69616:9;69611:354;69635:7;:14;69631:1;:18;69611:354;;;69671:21;69695:6;:18;69702:7;69710:1;69702:10;;;;;;;;;;;;;;69695:18;;;;;;;;;;;69671:42;;69753:8;69736:4;:13;;;:25;69728:76;;;;-1:-1:-1;;;69728:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69852:16;69869:12;;;;69819:30;69852;;;;;;;;;;;69937:15;;69916:37;;:16;;:20;:37::i;:::-;69897:56;-1:-1:-1;;;69651:3:0;;69611:354;;;;69977:27;70019:31;70066:16;-1:-1:-1;;;;;70053:30:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;70053:30:0;;70019:64;;70099:9;70094:791;70118:7;:14;70114:1;:18;70094:791;;;70154:21;70178:6;:18;70185:7;70193:1;70185:10;;;;;;;;;;;;;;70178:18;;;;;;;;;;;70154:42;;70211:30;70244:16;:30;70261:4;:12;;;70244:30;;;;;;;;;;;70211:63;;70294:9;70289:585;70313:15;;70309:19;;70289:585;;;70354:17;70374:8;70383:1;70374:11;;;;;;;;;;;;;;;:17;:11;;;;;:17;:19;-1:-1:-1;;;;;70374:19:0;;-1:-1:-1;70374:11:0;70448:222;70472:19;70468:1;:23;70448:222;;;70547:10;-1:-1:-1;;;;;70525:32:0;:15;70541:1;70525:18;;;;;;;;;;;;;;-1:-1:-1;;;;;70525:32:0;;70521:130;;;70591:4;70586:9;;70622:5;;70521:130;70493:3;;70448:222;;;;70694:2;70690:59;;;70721:8;;;;70690:59;70808:10;70769:15;70785:19;70769:36;;;;;;;;-1:-1:-1;;;;;70769:49:0;;;:36;;;;;;;;;;;:49;-1:-1:-1;;70837:21:0;;;;;70289:585;70330:3;;70289:585;;;-1:-1:-1;;;70134:3:0;;70094:791;;;;70902:9;70897:1547;70921:15;:22;70917:1;:26;70897:1547;;;70965:11;70979:15;70995:1;70979:18;;;;;;;;;;;;;;70965:32;;71012:23;71054;71080:1;71054:27;;71101:9;71096:786;71120:7;:14;71116:1;:18;71096:786;;;71160:21;71184:6;:18;71191:7;71199:1;71191:10;;;;;;;;;;;;;;71184:18;;;;;;;;;;;71160:42;;71221:30;71254:16;:30;71271:4;:12;;;71254:30;;;;;;;;;;;71221:63;;71304:20;71326:7;71337:34;71356:8;71337:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;71337:34:0;;;;;;;;;-1:-1:-1;;;71337:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71366:4;71337:18;:34::i;:::-;71303:68;;;;71400:2;71392:40;;;;;-1:-1:-1;;;71392:40:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;71454:9;71465:8;71477:38;71486:8;71495:12;71486:22;;;;;;;;;;;;;;;;;71477:38;;;;;;;;71486:22;;;;;;;71477:38;;-1:-1:-1;;;;;71477:38:0;;;;;;;;;-1:-1:-1;;;71477:38:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71510:4;71477:8;:38::i;:::-;71453:62;;;;71540:1;-1:-1:-1;;;;;71540:6:0;71545:1;71540:6;71536:331;;71734:50;71761:22;:15;-1:-1:-1;;;;;71761:22:0;;:19;:22::i;:::-;71734;:15;-1:-1:-1;;;;;71734:22:0;;:19;:22::i;:::-;:26;;:50::i;:::-;71716:68;-1:-1:-1;71825:22:0;:15;-1:-1:-1;;;;;71825:22:0;;:19;:22::i;:::-;71807:40;;71536:331;-1:-1:-1;;71136:3:0;;;;;-1:-1:-1;71096:786:0;;-1:-1:-1;;;71096:786:0;;-1:-1:-1;72296:25:0;:15;-1:-1:-1;;;;;72296:25:0;;:19;:25::i;:::-;72277:15;:44;72251:181;;;;-1:-1:-1;;;72251:181:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;70945:3:0;;70897:1547;;87082:181;-1:-1:-1;;;;;87184:40:0;;87176:79;;;;;-1:-1:-1;;;87176:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;;3275:192;3361:7;3397:12;3389:6;;;;3381:29;;;;-1:-1:-1;;;3381:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;3433:5:0;;;3275:192::o;89855:347::-;90014:15;;89974:9;90040:155;90047:5;;90040:155;;90069:3;;;;;;;;90113:1;-1:-1:-1;;;;;90091:23:0;:8;90100:1;90091:11;;;;;;;;;;;;;;:16;;;:18;;;-1:-1:-1;;;;;90091:23:0;;90087:97;;-1:-1:-1;90140:4:0;90163:5;;90087:97;90040:155;;;89855:347;;;;;:::o;58629:746::-;58806:9;;:11;;58848;;;;;58890:10;;;;:12;;58933;;;58732:17;;;;-1:-1:-1;;;;;58799:19:0;;;;58841;;;58883:20;;;;58926;58967:7;;;58959:44;;;;;-1:-1:-1;;;58959:44:0;;;;;;;;;;;;-1:-1:-1;;;58959:44:0;;;;;;;;;;;;;;;59037:7;;;;-1:-1:-1;;;;;;59221:6:0;;59205;;;59204:13;;59221:6;;;59220:13;;59204:29;59193:8;59254:6;;;59246:30;;;;;-1:-1:-1;;;59246:30:0;;;;;;;;;;;;-1:-1:-1;;;59246:30:0;;;;;;;;;;;;;;;-1:-1:-1;;;59295:1:0;:10;59287:47;;;;;-1:-1:-1;;;59287:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;59365:1;58629:746;;-1:-1:-1;58629:746:0;;-1:-1:-1;;;;;;58629:746:0:o;5301:278::-;5387:7;5422:12;5415:5;5407:28;;;;-1:-1:-1;;;5407:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5446:9;5462:1;5458;:5;;;;;;;5301:278;-1:-1:-1;;;;;5301:278:0:o;1291:172::-;1376:79;1389:9;1400:6;1376:79;;;;;;;;;;;;;;;;;:12;:79::i;59465:207::-;59557:12;;:14;59594:13;;;;:15;-1:-1:-1;;;;;59628:7:0;;;;;;;59620:44;;;;;-1:-1:-1;;;59620:44:0;;;;;;;;;;;;-1:-1:-1;;;59620:44:0;;;;;;;;;;;;;;;59465:207;;;:::o;93055:1014::-;93187:20;93209:18;93245:15;93263:22;93279:5;93263:15;:22::i;:::-;93328:25;;;;:16;:25;;;;;;;;93296:57;;;;;;;;;;;;;;;;;93245:40;;-1:-1:-1;93296:29:0;;:57;;93328:25;;93296:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;93296:57:0;;;;;;;;;-1:-1:-1;;;93296:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93364:21;93388:28;93407:8;93388:18;:28::i;:::-;93364:52;;93427:21;93451:28;93470:8;93451:18;:28::i;:::-;93427:52;;93490:23;93546:24;93534:36;;93541:2;-1:-1:-1;;;;;93534:36:0;;-1:-1:-1;;;;;93516:55:0;:14;-1:-1:-1;;;;;93516:55:0;;;;;;;93490:81;;93582:23;93638:24;93626:36;;93633:2;-1:-1:-1;;;;;93626:36:0;;-1:-1:-1;;;;;93608:55:0;:14;-1:-1:-1;;;;;93608:55:0;;;;;;;;-1:-1:-1;;;;;;93680:19:0;;;93676:386;;93723:75;;;-1:-1:-1;;;93723:75:0;;;;;;;;-1:-1:-1;;;;;93723:75:0;;;;;;;;;;;;;;;;;;-1:-1:-1;;;93723:75:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;93723:16:0;:33;;;;:75;;;;;-1:-1:-1;;93723:75:0;;;;;;;:33;:75;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;93723:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;93723:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;93723:75:0;;;;;;-1:-1:-1;93723:75:0;;;;;;;;;;-1:-1:-1;93723:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;93723:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;93723:75:0;;;;;;-1:-1:-1;93723:75:0;;;;;;;;;;-1:-1:-1;93723:75:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93716:82;;;;;;;;;;;;93676:386;-1:-1:-1;;;;;93820:19:0;;;93816:246;;93863:75;;;-1:-1:-1;;;93863:75:0;;;;;;;;-1:-1:-1;;;;;93863:75:0;;;;;;;;;;;;;;;;;;-1:-1:-1;;;93863:75:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;93863:16:0;:33;;;;:75;;;;;-1:-1:-1;;93863:75:0;;;;;;;:33;:75;;;;;;;;;;93816:246;93978:72;;;-1:-1:-1;;;93978:72:0;;;;;;;;94048:1;93978:72;;;;;;;;;;;;;;;;-1:-1:-1;;;93978:72:0;;;;;;;;;;;;;;-1:-1:-1;;;93978:72:0;;;;;;-1:-1:-1;;;;;93978:16:0;:33;;;;:72;;;;;;;;;;;:33;:72;;;;;;;;;;16898:154;16963:7;16990:54;17001:1;17004;16990:54;;;;;;;;;;;;;;;;;:10;:54::i;847:436::-;1002:29;1024:6;1002:21;:29::i;:::-;1033:12;994:52;;;;;-1:-1:-1;;;994:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1076:33:0;;1058:12;;-1:-1:-1;;;;;1076:14:0;;;1098:6;;1058:12;1076:33;1058:12;1076:33;1098:6;1076:14;:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1057:52;;;1174:7;1166:45;;;;;-1:-1:-1;;;1166:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;1227:48;;;;;;;;-1:-1:-1;;;;;1227:48:0;;;1250:4;;1227:48;;;;;;;;;847:436;;;;:::o;88968:569::-;89050:6;89073:8;:15;89092:1;89073:20;89069:61;;-1:-1:-1;89117:1:0;89110:8;;89069:61;89142:18;89163:8;89172:1;89163:11;;;;;;;;;;;;;;:17;;;:19;;;89142:40;;89199:11;-1:-1:-1;;;;;89199:16:0;89214:1;89199:16;89195:57;;;89239:1;89232:8;;;;;89195:57;89269:9;89264:227;89288:8;:15;89284:1;:19;89264:227;;;89325:26;;:::i;:::-;89354:8;89363:1;89354:11;;;;;;;;;;;;;;89325:40;;89420:7;:13;;;:15;;;-1:-1:-1;;;;;89384:51:0;:32;89404:11;-1:-1:-1;;;;;89384:32:0;:7;:13;;;:15;;;-1:-1:-1;;;;;89384:19:0;;;:32;;;;:::i;:::-;:51;89380:100;;89463:1;89456:8;;;;;;;89380:100;-1:-1:-1;89305:3:0;;89264:227;;16615:275;16742:7;16766:6;16762:47;;-1:-1:-1;16796:1:0;16789:8;;16762:47;16834:12;16827:5;16819:28;;;;-1:-1:-1;;;16819:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16876:1;16871;16867;:5;16866:11;;;;;;16881:1;16865:17;16858:24;;16615:275;;;;;:::o;556:182::-;677:4;710:20;-1:-1:-1;700:30:0;;556:182::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o
Swarm Source
ipfs://63a81399959e72b2960a3c4dddad64fe97d7afeac10d641129892298092ffbef
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 27 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | Ether (ETH) | 100.00% | $2,309.73 | 0.000000000000000003 | <$0.000001 |
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.