Feature Tip: Add private address tag to any address under My Name Tag !
ERC-20
Overview
Max Total Supply
314,914,121.87679886 iDOL
Holders
342
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 8 Decimals)
Balance
7.70971494 iDOLValue
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
StableCoin
Compiler Version
v0.6.6+commit.6c089d02
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-08-31 */ pragma solidity 0.6.6; // File: @openzeppelin/contracts/math/SafeMath.sol /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: @openzeppelin/contracts/math/SignedSafeMath.sol /** * @title SignedSafeMath * @dev Signed math operations with safety checks that revert on error. */ library SignedSafeMath { int256 constant private _INT256_MIN = -2**255; /** * @dev Multiplies two signed integers, reverts on overflow. */ function mul(int256 a, int256 b) internal pure returns (int256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow"); int256 c = a * b; require(c / a == b, "SignedSafeMath: multiplication overflow"); return c; } /** * @dev Integer division of two signed integers truncating the quotient, reverts on division by zero. */ function div(int256 a, int256 b) internal pure returns (int256) { require(b != 0, "SignedSafeMath: division by zero"); require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow"); int256 c = a / b; return c; } /** * @dev Subtracts two signed integers, reverts on overflow. */ function sub(int256 a, int256 b) internal pure returns (int256) { int256 c = a - b; require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow"); return c; } /** * @dev Adds two signed integers, reverts on overflow. */ function add(int256 a, int256 b) internal pure returns (int256) { int256 c = a + b; require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow"); return c; } } // File: @openzeppelin/contracts/utils/SafeCast.sol /** * @dev Wrappers over Solidity's uintXX casting operators with added overflow * checks. * * Downcasting from uint256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. * * Can be combined with {SafeMath} to extend it to smaller types, by performing * all math on `uint256` and then downcasting. */ library SafeCast { /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits"); return uint128(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits"); return uint64(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits"); return uint32(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits"); return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits. */ function toUint8(uint256 value) internal pure returns (uint8) { require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits"); return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, "SafeCast: value must be positive"); return uint256(value); } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { require(value < 2**255, "SafeCast: value doesn't fit in an int256"); return int256(value); } } // File: contracts/math/UseSafeMath.sol /** * @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 additionally, one can use SignedSafeMath and SafeCast.toUint256(int256) for int256. * In the case of the operation to the uint64 value, one need 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` become 0 as int256 * b = a.toUint256().toUint64(); // `b` become 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/StableCoinInterface.sol interface StableCoinInterface is IERC20 { event LogIsAcceptableSBT(bytes32 indexed bondID, bool isAcceptable); event LogMintIDOL( bytes32 indexed bondID, address indexed owner, bytes32 poolID, uint256 obtainIDOLAmount, uint256 poolIDOLAmount ); event LogBurnIDOL( bytes32 indexed bondID, // poolID? address indexed owner, uint256 burnIDOLAmount, uint256 unlockSBTAmount ); event LogReturnLockedPool( bytes32 indexed poolID, address indexed owner, uint64 backIDOLAmount ); event LogLambda( bytes32 indexed poolID, uint64 settledAverageAuctionPrice, uint256 totalSupply, uint256 lockedSBTValue ); function getPoolInfo(bytes32 poolID) external view returns ( uint64 lockedSBTTotal, uint64 unlockedSBTTotal, uint64 lockedPoolIDOLTotal, uint64 burnedIDOLTotal, uint64 soldSBTTotalInAuction, uint64 paidIDOLTotalInAuction, uint64 settledAverageAuctionPrice, bool isAllAmountSoldInAuction ); function solidValueTotal() external view returns (uint256 solidValue); function isAcceptableSBT(bytes32 bondID) external returns (bool ok); function mint( bytes32 bondID, address recipient, uint64 lockAmount ) external returns ( bytes32 poolID, uint64 obtainIDOLAmount, uint64 poolIDOLAmount ); function burnFrom(address account, uint256 amount) external; function unlockSBT(bytes32 bondID, uint64 burnAmount) external returns (uint64 rewardSBT); function startAuctionOnMaturity(bytes32 bondID) external; function startAuctionByMarket(bytes32 bondID) external; function setSettledAverageAuctionPrice( bytes32 bondID, uint64 totalPaidIDOL, uint64 SBTAmount, bool isLast ) external; function calcSBT2IDOL(uint256 solidBondAmount) external view returns (uint256 IDOLAmount); function returnLockedPool(bytes32[] calldata poolIDs) external returns (uint64 IDOLAmount); function returnLockedPoolTo(bytes32[] calldata poolIDs, address account) external returns (uint64 IDOLAmount); function generatePoolID(bytes32 bondID, uint64 count) external pure returns (bytes32 poolID); function getCurrentPoolID(bytes32 bondID) external view returns (bytes32 poolID); function getLockedPool(address user, bytes32 poolID) external view returns (uint64, uint64); } // File: contracts/util/Time.sol abstract contract Time { function _getBlockTimestampSec() internal view returns (uint256 unixtimesec) { unixtimesec = now; // solium-disable-line security/no-block-members } } // File: @openzeppelin/contracts/GSN/Context.sol /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } function _msgSender() internal view virtual returns (address payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File: @openzeppelin/contracts/utils/Address.sol /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } } // File: @openzeppelin/contracts/token/ERC20/ERC20.sol /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20MinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; using Address for address; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for {name} and {symbol}, initializes {decimals} with * a default value of 18. * * To select a different value for {decimals}, use {_setupDecimals}. * * All three of these values are immutable: they can only be set once during * construction. */ constructor (string memory name, string memory symbol) public { _name = name; _symbol = symbol; _decimals = 18; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Sets {decimals} to a value other than the default one of 18. * * WARNING: This function should only be called from the constructor. Most * applications that interact with token contracts will not expect * {decimals} to ever change, and may work incorrectly if it does. */ function _setupDecimals(uint8 decimals_) internal { _decimals = decimals_; } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } } // File: @openzeppelin/contracts/math/Math.sol /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } } // File: contracts/solidBondSafety/SolidBondSafety.sol // This contract is used for calculating minimum threshold acceptable strike price (relative to the current oracle price) // for the SBT with the time to maturity and the volatility from oracle. // It is derived from the risk appetite of this protocol. // For volatile SBT due to the long time to maturity or the underlying ETH volatility, // the minimum threshold acceptable strike price needs to increase in order to mitigate the risk of emergency auction. // The policy in this protocol is to equalize the risk of acceptable SBT over the different time to maturity or the underlying ETH volatility. // The threshold is thus derived from solving the black-scholes formula with a linear approximation technique. // Even in the approximation of the formula, there remains square root of time, which is tricky to handle in solidity. // Hence, we deal with the value in the squared form of the value. // In the following notations, for example, vvtE16 represents v^2 * t * 10^16. abstract contract SolidBondSafety is UseSafeMath, Time { /// @notice The return values of getEmergencyBorderInfo are intermediate values /// used for checking if the SBT is acceptable to the IDOL contract. /// Let f(x) = a*x + b be the function defined below: /// f(x) = 1.1 for 0 <= x <= 0.3576 /// f(x) = 1.52 x + 0.5564 for 0.3576 < x <= 0.7751 /// f(x) = 6.4 x - 3.226 for 0.7751 < x <= 1.1562 /// f(x) = 14.27 x - 12.3256 for 1.1562 < x <= 1.416 /// f(x) = 29.13 x - 33.3676 for 1.416 < x <= 1.6257 /// f(x) = 53.15 x - 72.4165 for 1.6257 < x <= 1.8 /// Then, we define getEmergencyBorderInfo(x^2 * 10^8) = (a^2 * 10^4, b * 10^4). /// @param xxE8 is multiply 10^8 with the square of x /// @return aaE4 is multiply 10000 with the square of a /// @return bE4 is multiply 10000 with b function getEmergencyBorderInfo(uint256 xxE8) public pure returns (int256 aaE4, int256 bE4) { if (xxE8 <= 3576 * 3576) { return (0, 11000); } else if (xxE8 <= 7751 * 7751) { return (152 * 152, 5564); } else if (xxE8 <= 11562 * 11562) { return (640 * 640, -32260); } else if (xxE8 <= 14160 * 14160) { return (1427 * 1427, -123256); } else if (xxE8 <= 16257 * 16257) { return (2913 * 2913, -333676); } else if (xxE8 <= 18000 * 18000) { return (5315 * 5315, -724165); } else { revert("not acceptable"); } } /// @param rateETH2USD S * 10^8 (USD/ETH) /// @param solidBondStrikePrice K * 10^4 (USD/SBT) /// @param volatility v * 10^8 /// @param untilMaturity t (= T * 365 * 86400) // isInEmergency checks if the SBT should be put into emergency auction. // The condition is verified by utilizing approximate form of black-scholes formula. function isInEmergency( uint256 rateETH2USD, uint256 solidBondStrikePrice, uint256 volatility, uint256 untilMaturity ) public pure returns (bool) { uint256 vE8 = volatility; if (vE8 > 2 * 10**8) { vE8 = 2 * 10**8; // The volatility is too high. } if (untilMaturity >= 12 weeks) { return true; // The period until maturity is too long. } uint256 vvtE16 = vE8.mul(vE8).mul(untilMaturity); uint256 xxE8 = vvtE16 / (64 * 10**6 * 86400 * 365); // 1.25^2 / 10^8 = 1 / (64 * 10^6) (int256 aaE4, int256 bE4) = getEmergencyBorderInfo(xxE8); int256 sE8 = rateETH2USD.toInt256(); int256 kE4 = solidBondStrikePrice.toInt256(); int256 cE8 = sE8.sub(bE4.mul(kE4)); // int256 lE28 = cE8.mul(cE8).mul(20183040 * 10**12); int256 rE28 = int256(vvtE16).mul(aaE4).mul(kE4).mul(kE4); bool isDanger = cE8 <= 0 || cE8.mul(cE8).mul(20183040 * 10**12) <= rE28; return isDanger; } /// @param rateETH2USD S * 10^8 (USD/ETH) /// @param solidBondStrikePrice K * 10^4 (USD/SBT) /// @param volatility v * 10^8 /// @param untilMaturity t (= T * 365 * 86400) // isDangerSolidBond checks if the SBT is acceptable to be a part of IDOL. // The condition is verified by utilizing approximate form of black-scholes formula. // This condition is more strict than the condition for triggering emergency auction described in isInEmergency function above. function isDangerSolidBond( uint256 rateETH2USD, uint256 solidBondStrikePrice, uint256 volatility, uint256 untilMaturity ) public pure returns (bool) { if ( solidBondStrikePrice * 5 * 10**4 < rateETH2USD * 2 && untilMaturity < 2 weeks ) { return false; } else if (volatility > 2 * 10**8) { return true; // The volatility is too high. } if (untilMaturity >= 12 weeks) { return true; // The period until maturity is too long. } uint256 vvtE16 = volatility.mul(volatility).mul(untilMaturity); uint256 xxE8 = vvtE16 / (64 * 10**6 * 86400 * 365); // 1.25^2 / 10^8 = 1 / (64 * 10^6) (int256 aaE4, int256 bE4) = getEmergencyBorderInfo(xxE8); // S/K <= 1.5f(1.25*v*sqrt(T)) // <=> S/K <= 1.5(1.25a*v*sqrt(T) + b) // <=> (2S - 3bK) <= (3.75aKv) * sqrt(T) // if 2S > 3bK, // (2S - 3bK)^2 <= (3.75aKv)^2 * t / 365 / 86400 // <=> 20183040(2S - 3bK)^2 <= 9t(aKv)^2 // <=> 20183040 * 10^12(10^8 * 2S - 10^8 * 3bK)^2 <= 9 * 10000a^2 * (10000K)^2 * t(10^8 * v)^2 int256 sE8 = rateETH2USD.toInt256(); int256 kE4 = solidBondStrikePrice.toInt256(); int256 cE8 = sE8.mul(2).sub(bE4.mul(kE4).mul(3)); // int256 lE28 = cE8.mul(cE8).mul(20183040 * 10**12); int256 rE28 = int256(vvtE16).mul(aaE4).mul(kE4).mul(kE4).mul(9); bool isDanger = cE8 <= 0 || cE8.mul(cE8).mul(20183040 * 10**12) <= rE28; return isDanger; } } // File: contracts/AuctionTimeControlInterface.sol interface AuctionTimeControlInterface { enum TimeControlFlag { BEFORE_AUCTION_FLAG, ACCEPTING_BIDS_PERIOD_FLAG, REVEALING_BIDS_PERIOD_FLAG, RECEIVING_SBT_PERIOD_FLAG, AFTER_AUCTION_FLAG } function listAuction(uint256 timestamp) external view returns (bytes32[] memory); function getTimeControlFlag(bytes32 auctionID) external view returns (TimeControlFlag); function isInPeriod(bytes32 auctionID, TimeControlFlag flag) external view returns (bool); function isAfterPeriod(bytes32 auctionID, TimeControlFlag flag) external view returns (bool); } // File: contracts/AuctionInterface.sol interface AuctionInterface is AuctionTimeControlInterface { event LogStartAuction( bytes32 indexed auctionID, bytes32 bondID, uint256 auctionedAmount ); event LogCancelBid( bytes32 indexed auctionID, address indexed bidder, bytes32 secret, uint256 returnedIDOLAmount ); event LogAuctionResult( bytes32 indexed auctionID, address indexed bidder, uint256 SBTAmountOfReward, uint256 IDOLAmountOfPayment, uint256 IDOLAmountOfChange ); event LogCloseAuction( bytes32 indexed auctionID, bool isLast, bytes32 nextAuctionID ); function ongoingAuctionSBTTotal(bytes32 auctionID) external view returns (uint64 ongoingSBTAmountE8); function startAuction( bytes32 bondID, uint64 auctionAmount, bool isEmergency ) external returns (bytes32 auctonID); function cancelBid(bytes32 auctionID, bytes32 secret) external returns (uint64 returnedIDOLAmount); function makeAuctionResult( bytes32 auctionID, uint64 myLowestPrice, uint64[] calldata winnerBids, uint64[] calldata loserBids ) external returns ( uint64 winnerAmount, uint64 toPay, uint64 IDOLAmountOfChange ); function closeAuction(bytes32 auctionID) external returns (bool isLast, bytes32 nextAuctionID); function receiveUnrevealedBidDistribution(bytes32 auctionID, bytes32 secret) external returns (bool success); function getCurrentAuctionID(bytes32 bondID) external view returns (bytes32 auctionID); function generateAuctionID(bytes32 bondID, uint256 auctionCount) external pure returns (bytes32 auctionID); function listBondIDFromAuctionID(bytes32[] calldata auctionIDs) external view returns (bytes32[] memory bondIDs); function getAuctionStatus(bytes32 auctionID) external view returns ( uint256 closingTime, uint64 auctionAmount, uint64 rewardedAmount, uint64 totalSBTAmountBid, bool isEmergency, bool doneFinalizeWinnerAmount, bool doneSortPrice, uint64 lowestBidPriceDeadLine, uint64 highestBidPriceDeadLine, uint64 totalSBTAmountPaidForUnrevealed ); function getWeeklyAuctionStatus(uint256 weekNumber) external view returns (uint256[] memory weeklyAuctionStatus); function calcWinnerAmount( bytes32 auctionID, address sender, uint64[] calldata winnerBids ) external view returns (uint64 winnerAmount); function calcBillAndCheckLoserBids( bytes32 auctionID, address sender, uint64 winnerAmountInput, uint64 myLowestPrice, uint64[] calldata myLoseBids ) external view returns (uint64 paymentAmount); function getAuctionCount(bytes32 bondID) external view returns (uint256 auctionCount); } // File: contracts/AuctionTimeControl.sol contract AuctionTimeControl is Time, AuctionTimeControlInterface { uint256 internal immutable MIN_NORMAL_AUCTION_PERIOD; uint256 internal immutable MIN_EMERGENCY_AUCTION_PERIOD; uint256 internal immutable NORMAL_AUCTION_REVEAL_SPAN; uint256 internal immutable EMERGENCY_AUCTION_REVEAL_SPAN; uint256 internal immutable AUCTION_WITHDRAW_SPAN; uint256 internal immutable EMERGENCY_AUCTION_WITHDRAW_SPAN; TimeControlFlag internal constant BEFORE_AUCTION_FLAG = TimeControlFlag .BEFORE_AUCTION_FLAG; TimeControlFlag internal constant ACCEPTING_BIDS_PERIOD_FLAG = TimeControlFlag .ACCEPTING_BIDS_PERIOD_FLAG; TimeControlFlag internal constant REVEALING_BIDS_PERIOD_FLAG = TimeControlFlag .REVEALING_BIDS_PERIOD_FLAG; TimeControlFlag internal constant RECEIVING_SBT_PERIOD_FLAG = TimeControlFlag .RECEIVING_SBT_PERIOD_FLAG; TimeControlFlag internal constant AFTER_AUCTION_FLAG = TimeControlFlag .AFTER_AUCTION_FLAG; /** * @dev Get whether the auction is in emergency or not. */ mapping(bytes32 => bool) public isAuctionEmergency; /** * @dev The end time that the auction accepts bids. * The zero value indicates the auction is not held. */ mapping(bytes32 => uint256) public auctionClosingTime; /** * @dev The contents in this internal storage variable can be seen by listAuction function. */ mapping(uint256 => bytes32[]) internal _weeklyAuctionList; constructor( uint256 minNormalAuctionPeriod, uint256 minEmergencyAuctionPeriod, uint256 normalAuctionRevealSpan, uint256 emergencyAuctionRevealSpan, uint256 auctionWithdrawSpan, uint256 emergencyAuctionWithdrawSpan ) public { MIN_NORMAL_AUCTION_PERIOD = minNormalAuctionPeriod; MIN_EMERGENCY_AUCTION_PERIOD = minEmergencyAuctionPeriod; NORMAL_AUCTION_REVEAL_SPAN = normalAuctionRevealSpan; EMERGENCY_AUCTION_REVEAL_SPAN = emergencyAuctionRevealSpan; AUCTION_WITHDRAW_SPAN = auctionWithdrawSpan; EMERGENCY_AUCTION_WITHDRAW_SPAN = emergencyAuctionWithdrawSpan; } /** * @dev Get auctions which will close within the week. */ function listAuction(uint256 weekNumber) public override view returns (bytes32[] memory) { return _weeklyAuctionList[weekNumber]; } /** * @notice Gets the period the auction is currently in. * This function returns 0-4 corresponding to its period. */ function getTimeControlFlag(bytes32 auctionID) public override view returns (TimeControlFlag) { uint256 closingTime = auctionClosingTime[auctionID]; // Note that the auction span differs based on whether the auction is in emergency or not. bool isEmergency = isAuctionEmergency[auctionID]; uint256 revealSpan = NORMAL_AUCTION_REVEAL_SPAN; uint256 withdrawSpan = AUCTION_WITHDRAW_SPAN; if (isEmergency) { revealSpan = EMERGENCY_AUCTION_REVEAL_SPAN; withdrawSpan = EMERGENCY_AUCTION_WITHDRAW_SPAN; } uint256 nowTime = _getBlockTimestampSec(); if (closingTime == 0) { return BEFORE_AUCTION_FLAG; } else if (nowTime <= closingTime) { return ACCEPTING_BIDS_PERIOD_FLAG; } else if (nowTime < closingTime + revealSpan) { return REVEALING_BIDS_PERIOD_FLAG; } else if (nowTime < closingTime + revealSpan + withdrawSpan) { return RECEIVING_SBT_PERIOD_FLAG; } else { return AFTER_AUCTION_FLAG; } } /** * @notice This function returns whether or not the auction is in the period indicated * by the flag. */ function isInPeriod(bytes32 auctionID, TimeControlFlag flag) public override view returns (bool) { return getTimeControlFlag(auctionID) == flag; } /** * @notice Returns whether or not the auction is in or after the period indicated * by the flag. */ function isAfterPeriod(bytes32 auctionID, TimeControlFlag flag) public override view returns (bool) { return getTimeControlFlag(auctionID) >= flag; } /** * @dev Calculates and registers the end time of the period in which the auction accepts bids * (= closingTime). The period in which bids are revealed follows after this time. */ function _setAuctionClosingTime(bytes32 auctionID, bool isEmergency) internal { uint256 closingTime; if (isEmergency) { closingTime = ((_getBlockTimestampSec() + MIN_EMERGENCY_AUCTION_PERIOD + 5 minutes - 1) / 5 minutes) * (5 minutes); } else { closingTime = ((_getBlockTimestampSec() + MIN_NORMAL_AUCTION_PERIOD + 1 hours - 1) / 1 hours) * (1 hours); } _setAuctionClosingTime(auctionID, isEmergency, closingTime); } /** * @dev Registers the end time of the period in which the auction accepts bids (= closingTime). * The period in which bids are revealed follows after this time. */ function _setAuctionClosingTime( bytes32 auctionID, bool isEmergency, uint256 closingTime ) internal { isAuctionEmergency[auctionID] = isEmergency; auctionClosingTime[auctionID] = closingTime; uint256 weekNumber = closingTime / (1 weeks); _weeklyAuctionList[weekNumber].push(auctionID); } } // File: contracts/BondMakerInterface.sol interface BondMakerInterface { event LogNewBond( bytes32 indexed bondID, address bondTokenAddress, uint64 stableStrikePrice, bytes32 fnMapID ); event LogNewBondGroup(uint256 indexed bondGroupID); event LogIssueNewBonds( uint256 indexed bondGroupID, address indexed issuer, uint256 amount ); event LogReverseBondToETH( uint256 indexed bondGroupID, address indexed owner, uint256 amount ); event LogExchangeEquivalentBonds( address indexed owner, uint256 indexed inputBondGroupID, uint256 indexed outputBondGroupID, uint256 amount ); event LogTransferETH( address indexed from, address indexed to, uint256 value ); function registerNewBond(uint256 maturity, bytes calldata fnMap) external returns ( bytes32 bondID, address bondTokenAddress, uint64 solidStrikePrice, bytes32 fnMapID ); function registerNewBondGroup( bytes32[] calldata bondIDList, uint256 maturity ) external returns (uint256 bondGroupID); function issueNewBonds(uint256 bondGroupID) external payable returns (uint256 amount); function reverseBondToETH(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; 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 generateBondID(uint256 maturity, bytes calldata functionHash) external pure returns (bytes32 bondID); } // File: contracts/UseBondMaker.sol abstract contract UseBondMaker { BondMakerInterface internal immutable _bondMakerContract; constructor(address contractAddress) public { require( contractAddress != address(0), "contract should be non-zero address" ); _bondMakerContract = BondMakerInterface(payable(contractAddress)); } } // File: contracts/UseStableCoin.sol abstract contract UseStableCoin { StableCoinInterface internal immutable _IDOLContract; constructor(address contractAddress) public { require( contractAddress != address(0), "contract should be non-zero address" ); _IDOLContract = StableCoinInterface(contractAddress); } function _transferIDOLFrom( address from, address to, uint256 amount ) internal { _IDOLContract.transferFrom(from, to, amount); } function _transferIDOL(address to, uint256 amount) internal { _IDOLContract.transfer(to, amount); } function _transferIDOL( address to, uint256 amount, string memory errorMessage ) internal { require(_IDOLContract.balanceOf(address(this)) >= amount, errorMessage); _IDOLContract.transfer(to, amount); } } // File: contracts/auction/AuctionSecret.sol interface AuctionSecretInterface { function auctionSecret( bytes32 auctionID, bytes32 secret ) external view returns ( address sender, uint64 amount, uint64 IDOLamount ); } abstract contract AuctionSecret is AuctionSecretInterface { /** * @param sender is the account who set this secret bid. * @param amount is target SBT amount. * @param IDOLamount is deposited iDOL amount attached to this secret bid. */ struct Secret { address sender; uint64 amount; uint64 IDOLamount; } mapping(bytes32 => mapping(bytes32 => Secret)) public override auctionSecret; function _setSecret( bytes32 auctionID, bytes32 secret, address sender, uint64 amount, uint64 IDOLamount ) internal returns (bool) { require( auctionSecret[auctionID][secret].sender == address(0), "Secret already exists" ); require(sender != address(0), "the zero address cannot set secret"); auctionSecret[auctionID][secret] = Secret({ sender: sender, amount: amount, IDOLamount: IDOLamount }); return true; } function _removeSecret(bytes32 auctionID, bytes32 secret) internal returns (bool) { delete auctionSecret[auctionID][secret]; return true; } } // File: contracts/AuctionBoardInterface.sol interface AuctionBoardInterface is AuctionSecretInterface { event LogBidMemo( bytes32 indexed auctionID, address indexed bidder, bytes memo ); event LogInsertBoard( bytes32 indexed auctionID, address indexed bidder, uint64 bidPrice, uint64 boardIndex, uint64 targetSBTAmount ); event LogAuctionInfoDiff( bytes32 indexed auctionID, uint64 settledAmount, uint64 paidIDOL, uint64 rewardedSBT ); function bidWithMemo( bytes32 auctionID, bytes32 secret, uint64 totalSBTAmountBid, bytes calldata memo ) external returns (uint256 depositedIDOLAmount); function revealBids( bytes32 auctionID, uint64[] calldata bids, uint64 random ) external; function sortBidPrice(bytes32 auctionID, uint64[] calldata sortedPrice) external; function makeEndInfo(bytes32 auctionID) external; function calcBill( bytes32 auctionID, uint64 winnerAmount, uint64 myLowestPrice ) external view returns (uint64 paymentAmount); function getUnsortedBidPrice(bytes32 auctionID) external view returns (uint64[] memory bidPriceList); function getSortedBidPrice(bytes32 auctionID) external view returns (uint64[] memory bidPriceList); function getEndInfo(bytes32 auctionID) external view returns ( uint64 price, uint64 boardIndex, uint64 loseSBTAmount, uint64 auctionEndPriceWinnerSBTAmount ); function getBidderStatus(bytes32 auctionID, address bidder) external view returns (uint64 toBack, bool isIDOLReturned); function getBoard( bytes32 auctionID, uint64 price, uint64 boardIndex ) external view returns (address bidder, uint64 amount); function getBoardStatus(bytes32 auctionID) external view returns (uint64[] memory boardStatus); function generateMultiSecret( bytes32 auctionID, uint64[] calldata bids, uint64 random ) external pure returns (bytes32 secret); function discretizeBidPrice(uint64 price) external pure returns (uint64 discretizedPrice); function auctionDisposalInfo(bytes32 auctionID) external view returns ( uint64 solidStrikePriceIDOLForUnrevealedE8, uint64 solidStrikePriceIDOLForRestWinnersE8, bool isEndInfoCreated, bool isForceToFinalizeWinnerAmountTriggered, bool isPriceSorted ); function removeSecret( bytes32 auctionID, bytes32 secret, uint64 subtractAmount ) external; function auctionRevealInfo(bytes32 auctionID) external view returns ( uint64 totalSBTAmountBid, uint64 totalIDOLSecret, uint64 totalIDOLRevealed, uint16 auctionPriceCount ); function auctionBoard( bytes32 auctionID, uint64 bidPrice, uint256 boardIndex ) external view returns ( uint64 bidAmount, address bidder ); function auctionParticipantInfo( bytes32 auctionID, address participant ) external view returns ( uint64 auctionLockedIDOLAmountE8, uint16 bidCount ); function auctionInfo( bytes32 auctionID ) external view returns ( uint64 auctionSettledTotalE8, uint64 auctionRewardedTotalE8, uint64 auctionPaidTotalE8 ); function updateAuctionInfo( bytes32 auctionID, uint64 settledAmountE8, uint64 paidIDOLE8, uint64 rewardedSBTE8 ) external; function deleteParticipantInfo( bytes32 auctionID, address participant ) external; } // File: contracts/UseAuctionBoard.sol abstract contract UseAuctionBoard { AuctionBoardInterface internal immutable _auctionBoardContract; constructor(address contractAddress) public { require( contractAddress != address(0), "contract should be non-zero address" ); _auctionBoardContract = AuctionBoardInterface(contractAddress); } } // File: contracts/oracle/OracleInterface.sol // Oracle referenced by OracleProxy must implement this interface. interface OracleInterface { // Returns if oracle is running. function alive() external view returns (bool); // Returns latest id. // The first id is 1 and 0 value is invalid as id. // Each price values and theirs timestamps are identified by id. // Ids are assigned incrementally to values. function latestId() external returns (uint256); // Returns latest price value. // decimal 8 function latestPrice() external returns (uint256); // Returns timestamp of latest price. function latestTimestamp() external returns (uint256); // Returns price of id. function getPrice(uint256 id) external returns (uint256); // Returns timestamp of id. function getTimestamp(uint256 id) external returns (uint256); function getVolatility() external returns (uint256); } // File: contracts/oracle/UseOracle.sol abstract contract UseOracle { OracleInterface internal _oracleContract; constructor(address contractAddress) public { require( contractAddress != address(0), "contract should be non-zero address" ); _oracleContract = OracleInterface(contractAddress); } /// @notice Get the latest USD/ETH price and historical volatility using oracle. /// @return rateETH2USDE8 (10^-8 USD/ETH) /// @return volatilityE8 (10^-8) function _getOracleData() internal returns (uint256 rateETH2USDE8, uint256 volatilityE8) { rateETH2USDE8 = _oracleContract.latestPrice(); volatilityE8 = _oracleContract.getVolatility(); return (rateETH2USDE8, volatilityE8); } /// @notice 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 rateETH2USDE8 (10^-8 USD/ETH) function _getPriceOn(uint256 timestamp, uint256 hintID) internal returns (uint256 rateETH2USDE8) { uint256 latestID = _oracleContract.latestId(); require( latestID != 0, "system error: the ID of oracle data should not be zero" ); require(hintID != 0, "the hint ID must not be zero"); uint256 id = hintID; if (hintID > latestID) { id = latestID; } require( _oracleContract.getTimestamp(id) > timestamp, "there is no price data after maturity" ); id--; while (id != 0) { if (_oracleContract.getTimestamp(id) <= timestamp) { break; } id--; } return _oracleContract.getPrice(id + 1); } } // File: contracts/util/TransferETHInterface.sol interface TransferETHInterface { receive() external payable; event LogTransferETH( address indexed from, address indexed to, uint256 value ); } // File: contracts/bondToken/BondTokenInterface.sol interface BondTokenInterface is TransferETHInterface, 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 burn(uint256 amount) external returns (bool success); function burnAll() external returns (uint256 amount); function isMinter(address account) external view returns (bool minter); function getRate() external view returns (uint128 rateNumerator, uint128 rateDenominator); } // File: contracts/Auction.sol contract Auction is UseSafeMath, AuctionInterface, AuctionTimeControl, UseStableCoin, UseBondMaker, UseAuctionBoard { using Math for uint256; uint64 internal constant NO_SKIP_BID = uint64(-1); uint64 internal constant SKIP_RECEIVING_WIN_BIDS = uint64(-2); uint256 internal constant POOL_AUCTION_COUNT_PADDING = 10**8; /** * @notice The times of auctions held for the auction ID. * @dev The contents in this internal storage variable can be seen by getAuctionCount function. */ mapping(bytes32 => uint256) internal _bondIDAuctionCount; /** * @notice Get the bond ID from the auction ID. */ mapping(bytes32 => bytes32) public auctionID2BondID; /** * @dev The contents in this internal storage variable can be seen by getAuctionStatus function. * @param ongoingAuctionSBTTotalE8 is the SBT amount put up in the auction. * @param lowestBidPriceDeadLineE8 is the minimum bid price in the auction. * @param highestBidPriceDeadLineE8 is the maximum bid price in the auction. * @param totalSBTAmountPaidForUnrevealedE8 is the SBT Amount allocated for those who had not revealed their own bid. */ struct AuctionConfig { uint64 ongoingAuctionSBTTotalE8; uint64 lowestBidPriceDeadLineE8; uint64 highestBidPriceDeadLineE8; uint64 totalSBTAmountPaidForUnrevealedE8; } mapping(bytes32 => AuctionConfig) internal _auctionConfigList; constructor( address bondMakerAddress, address IDOLAddress, address auctionBoardAddress, uint256 minNormalAuctionPeriod, uint256 minEmergencyAuctionPeriod, uint256 normalAuctionRevealSpan, uint256 emergencyAuctionRevealSpan, uint256 auctionWithdrawSpan, uint256 emergencyAuctionWithdrawSpan ) public AuctionTimeControl( minNormalAuctionPeriod, minEmergencyAuctionPeriod, normalAuctionRevealSpan, emergencyAuctionRevealSpan, auctionWithdrawSpan, emergencyAuctionWithdrawSpan ) UseBondMaker(bondMakerAddress) UseStableCoin(IDOLAddress) UseAuctionBoard(auctionBoardAddress) {} /** * @dev This function starts the auction for the auctionID. Can be called only by the IDOL contract. */ function startAuction( bytes32 bondID, uint64 auctionAmount, bool isEmergency ) external override returns (bytes32) { require( msg.sender == address(_IDOLContract), "caller must be IDOL contract" ); return _startAuction(bondID, auctionAmount, isEmergency); } /** * @notice This function is called when the auction (re)starts. * @param bondID is SBT ID whose auction will be held. * @param auctionAmount is SBT amount put up in the auction. * @param isEmergency is the flag that indicates the auction schedule is for emergency mode. */ function _startAuction( bytes32 bondID, uint64 auctionAmount, bool isEmergency ) internal returns (bytes32) { (, , uint256 solidStrikePriceE4, ) = _bondMakerContract.getBond(bondID); uint256 strikePriceIDOL = _IDOLContract.calcSBT2IDOL( solidStrikePriceE4.mul(10**8) ); uint256 auctionCount = _bondIDAuctionCount[bondID].add(1); _bondIDAuctionCount[bondID] = auctionCount; bytes32 auctionID = getCurrentAuctionID(bondID); require( isInPeriod(auctionID, BEFORE_AUCTION_FLAG), "the auction has been held" ); uint256 betaCount = auctionCount.mod(POOL_AUCTION_COUNT_PADDING).min(9); auctionID2BondID[auctionID] = bondID; _setAuctionClosingTime(auctionID, isEmergency); { AuctionConfig memory auctionConfig = _auctionConfigList[auctionID]; auctionConfig.ongoingAuctionSBTTotalE8 = auctionAmount; auctionConfig.lowestBidPriceDeadLineE8 = _auctionBoardContract .discretizeBidPrice( strikePriceIDOL .mul(10 - betaCount) .divRoundUp(10**(1 + 8)) .mul(10**8) .toUint64() ); auctionConfig.highestBidPriceDeadLineE8 = _auctionBoardContract .discretizeBidPrice( strikePriceIDOL.divRoundUp(10**8).mul(10**8).toUint64() ); _auctionConfigList[auctionID] = auctionConfig; } emit LogStartAuction(auctionID, bondID, auctionAmount); return auctionID; } /** * @notice submit only your own winning bids and get SBT amount which you'll aquire. */ function calcWinnerAmount( bytes32 auctionID, address sender, uint64[] memory winnerBids ) public override view returns (uint64) { uint256 totalBidAmount; ( uint64 endPrice, uint64 endBoardIndex, uint64 loseSBTAmount, ) = _auctionBoardContract.getEndInfo(auctionID); uint64 bidPrice; uint64 boardIndex; // can calculate winner amount after making the end info. { (, , bool isEndInfoCreated, , ) = _auctionBoardContract .auctionDisposalInfo(auctionID); require(isEndInfoCreated, "the end info has not been made yet"); } for (uint256 i = 0; i < winnerBids.length; i += 2) { if (i != 0) { require( bidPrice > winnerBids[i] || (bidPrice == winnerBids[i] && boardIndex < winnerBids[i + 1]), "winner bids are not sorted" ); } bidPrice = winnerBids[i]; boardIndex = winnerBids[i + 1]; (uint64 bidAmount, address bidder) = _auctionBoardContract .auctionBoard(auctionID, bidPrice, boardIndex); require(bidder == sender, "this bid is not yours"); totalBidAmount = totalBidAmount.add(bidAmount); if (endPrice == bidPrice) { if (boardIndex == endBoardIndex) { // Guarantee loseSBTAmount <= bidAmount in this case. totalBidAmount = totalBidAmount.sub(loseSBTAmount); } else { require( boardIndex < endBoardIndex, "this bid does not win" ); } } else { require(endPrice < bidPrice, "this bid does not win"); } } return totalBidAmount.toUint64(); } /** * @notice all loser bids must be reported to this function. These are checked and counted for calculations of bill. * @param auctionID aunctionID * @param sender owner of the bids * @param winnerAmountInput SBT amount to aquire. this is needed because this effect the price of SBT in Vickly Auction's protocol. * @param myLowestPrice myLowestPrice is the lowest price of skip bids. * @param myLoseBids is the all bids which is after the endInfo */ function calcBillAndCheckLoserBids( bytes32 auctionID, address sender, uint64 winnerAmountInput, uint64 myLowestPrice, uint64[] memory myLoseBids ) public override view returns (uint64) { uint256 winnerAmount = winnerAmountInput; uint256 toPaySkip = 0; if ( myLowestPrice != NO_SKIP_BID && myLowestPrice != SKIP_RECEIVING_WIN_BIDS ) { bool myLowestVerify = false; for (uint256 i = 0; i < myLoseBids.length; i += 2) { uint64 price = myLoseBids[i]; if (price == myLowestPrice) { myLowestVerify = true; break; } } require( myLowestVerify, "myLowestPrice must be included in myLoseBids" ); } // The amount of sender's lose bids will be skipped. In order to optimize the calculation, // components in myLoseBids with a higher price than myLowestPrice are added to winnerAmount and // to be subtracted at the end of this function. for (uint256 i = 0; i < myLoseBids.length; i += 2) { uint64 price = myLoseBids[i]; uint64 boardIndex = myLoseBids[i + 1]; if (i != 0) { require( price < myLoseBids[i - 2] || (price == myLoseBids[i - 2] && boardIndex > myLoseBids[i - 1]), "myLoseBids is not sorted" ); } { ( uint64 endPrice, uint64 endBoardIndex, uint64 loseSBTAmount, ) = _auctionBoardContract.getEndInfo(auctionID); if (price == endPrice) { if (boardIndex == endBoardIndex) { require( loseSBTAmount != 0, "myLoseBids includes the bid which is same as endInfo with no lose SBT amount" ); // This function does not guarantee to return the correct result if an invalid input is given, // because this function can be used just for getting information. // This function is used in the procecss of makeAuctionResult(), and in such a case, // all the verification for bidder==sender and some necessary conditions are processed // in different functions. if (myLowestPrice <= price) { winnerAmount = winnerAmount.add(loseSBTAmount); toPaySkip = toPaySkip.add( price.mul(loseSBTAmount).div(10**8) ); continue; } } else { require( boardIndex > endBoardIndex, "myLoseBids includes the bid whose bid index is less than that of endInfo" ); } } else { require( price < endPrice, "myLoseBids includes the bid whose price is more than that of endInfo" ); } } (uint64 bidAmount, address bidder) = _auctionBoardContract .auctionBoard(auctionID, price, boardIndex); require( bidder == sender, "myLoseBids includes the bid whose owner is not the sender" ); if (myLowestPrice <= price) { winnerAmount = winnerAmount.add(bidAmount); toPaySkip = toPaySkip.add(price.mul(bidAmount).div(10**8)); } } if (myLowestPrice == SKIP_RECEIVING_WIN_BIDS) { // Reduce calculation costs instead by receiving obtained SBT at the highest losing price. (uint64 endPrice, , , ) = _auctionBoardContract.getEndInfo( auctionID ); //while toPaySkip is expected to be zero in the loop above, //only the exception is when the the price acctually hit uint64(-1) at an extremely unexpected case. return endPrice .mul(winnerAmount) .divRoundUp(10**8) .sub(toPaySkip) .toUint64(); } return _auctionBoardContract .calcBill(auctionID, winnerAmount.toUint64(), myLowestPrice) .sub(toPaySkip) .toUint64(); } /** * @notice Submit all my win and lose bids, verify them, and transfer the auction reward. * @param winnerBids is an array of alternating price and board index. * For example, if the end info is { price: 96, boardIndex: 0, loseSBTAmount: 100000000 } and you have 3 bids: * { price: 99, boardIndex: 0 }, { price: 97, boardIndex: 2 }, and { price: 96, boardIndex: 1 }, * you should submit [9900000000, 0, 9700000000, 2] as winnerBids and [9600000000, 1] as loserBids. * If the end info is { price: 96, boardIndex: 0, loseSBTAmount: 100000000 } and you have 1 bid: * { price: 96, boardIndex: 0 }, you should submit [9600000000, 0] as winnerBids and [9600000000, 0] * as loserBids. */ function makeAuctionResult( bytes32 auctionID, uint64 myLowestPrice, uint64[] memory winnerBids, uint64[] memory loserBids ) public override returns ( uint64, uint64, uint64 ) { ( uint64 auctionLockedIDOLAmountE8, uint16 bidCount ) = _auctionBoardContract.auctionParticipantInfo(auctionID, msg.sender); require(auctionLockedIDOLAmountE8 != 0, "This process is already done"); { ( uint64 endPrice, uint64 endBoardIndex, uint64 loseSBTAmount, uint64 auctionEndPriceWinnerSBTAmount ) = _auctionBoardContract.getEndInfo(auctionID); (address endBidder, ) = _auctionBoardContract.getBoard( auctionID, endPrice, endBoardIndex ); // If dupicated bid count is included (loseSBTAmount != 0), bidCount is increased by 1. // When both auctionEndPriceWinnerSBTAmount and loseSBTAmount are no-zero value, // the end info bid has two components(a winner bid side & a loser bid side). // If endInfo bid is frauded in calcBillAndCheckLoserBids L269, revert here. So there needs not check sender==bidder. require( winnerBids.length.div(2) + loserBids.length.div(2) == bidCount + ( (msg.sender == endBidder && loseSBTAmount != 0 && auctionEndPriceWinnerSBTAmount != 0) ? 1 : 0 ), "must submit all of your bids" ); } uint64 winnerAmount = calcWinnerAmount( auctionID, msg.sender, winnerBids ); uint64 toPay; TimeControlFlag timeFlag = getTimeControlFlag(auctionID); if (timeFlag == RECEIVING_SBT_PERIOD_FLAG) { toPay = calcBillAndCheckLoserBids( auctionID, msg.sender, winnerAmount, myLowestPrice, loserBids ); } else { require( timeFlag > RECEIVING_SBT_PERIOD_FLAG, "has not been the receiving period yet" ); toPay = calcBillAndCheckLoserBids( auctionID, msg.sender, winnerAmount, SKIP_RECEIVING_WIN_BIDS, loserBids ); } // IDOLAmountOfChange = max(auctionLockedIDOLAmountE8 - toPay, 0) if (toPay > auctionLockedIDOLAmountE8) { // assertion to prevent from the worst case that accumulate to certain amount by rounding up of toPay. require( toPay.sub(auctionLockedIDOLAmountE8) < 10**8, "system error: does not ignore too big error for spam protection" ); toPay = auctionLockedIDOLAmountE8; } uint64 IDOLAmountOfChange = auctionLockedIDOLAmountE8 - toPay; _auctionBoardContract.deleteParticipantInfo(auctionID, msg.sender); _transferIDOL(msg.sender, IDOLAmountOfChange); _auctionBoardContract.updateAuctionInfo( auctionID, 0, toPay, winnerAmount ); _distributeToWinners(auctionID, winnerAmount); emit LogAuctionResult( auctionID, msg.sender, winnerAmount, toPay, IDOLAmountOfChange ); return (winnerAmount, toPay, IDOLAmountOfChange); } /** * @notice Close the auction when it is done. If some part of SBTs remain unsold, the auction is held again. */ function closeAuction(bytes32 auctionID) public override returns (bool, bytes32) { (uint64 auctionSettledTotalE8, , ) = _auctionBoardContract.auctionInfo( auctionID ); require( isInPeriod(auctionID, AFTER_AUCTION_FLAG), "This function is not allowed to execute in this period" ); uint64 ongoingAuctionSBTTotal = _auctionConfigList[auctionID] .ongoingAuctionSBTTotalE8; require(ongoingAuctionSBTTotal != 0, "already closed"); bytes32 bondID = auctionID2BondID[auctionID]; { (, , bool isEndInfoCreated, , ) = _auctionBoardContract .auctionDisposalInfo(auctionID); require(isEndInfoCreated, "has not set end info"); } _forceToFinalizeWinnerAmount(auctionID); uint256 nextAuctionAmount = ongoingAuctionSBTTotal.sub( auctionSettledTotalE8, "allocated SBT amount for auction never becomes lower than reward total" ); bool isLast = nextAuctionAmount == 0; _publishSettledAverageAuctionPrice(auctionID, isLast); bytes32 nextAuctionID = bytes32(0); if (isLast) { // closeAuction adds 10**8 to _bondIDAuctionCount[bondID] and resets beta count // when all SBT of the auction is sold out. _bondIDAuctionCount[bondID] = _bondIDAuctionCount[bondID] .div(POOL_AUCTION_COUNT_PADDING) .add(1) .mul(POOL_AUCTION_COUNT_PADDING); } else { // When the SBT is not sold out in the auction, restart a new one until all the SBT is successfully sold. nextAuctionID = _startAuction( bondID, nextAuctionAmount.toUint64(), true ); } delete _auctionConfigList[auctionID].ongoingAuctionSBTTotalE8; emit LogCloseAuction(auctionID, isLast, nextAuctionID); return (isLast, nextAuctionID); } /** * @notice This function returns SBT amount and iDOL amount (as its change) settled for those who didn't reveal bids. */ function _calcUnrevealedBidDistribution( uint64 ongoingAmount, uint64 totalIDOLAmountUnrevealed, uint64 totalSBTAmountPaidForUnrevealed, uint64 solidStrikePriceIDOL, uint64 IDOLAmountDeposited ) internal pure returns (uint64 receivingSBTAmount, uint64 returnedIDOLAmount) { // (total target) - (total revealed) = (total unrevealed) uint64 totalSBTAmountUnrevealed = totalIDOLAmountUnrevealed .mul(10**8) .div(solidStrikePriceIDOL, "system error: Oracle has a problem") .toUint64(); // min((total unrevealed), ongoing) - (total paid already) = (total deposit for punishment) uint64 totalLeftSBTAmountForUnrevealed = uint256( totalSBTAmountUnrevealed ) .min(ongoingAmount) .sub(totalSBTAmountPaidForUnrevealed) .toUint64(); // (receiving SBT amount) = min((bid amount), (total deposited)) uint256 expectedReceivingSBTAmount = IDOLAmountDeposited.mul(10**8).div( solidStrikePriceIDOL, "system error: Oracle has a problem" ); // (returned iDOL amount) = (deposit amount) - (iDOL value of receiving SBT amount) if (expectedReceivingSBTAmount <= totalLeftSBTAmountForUnrevealed) { receivingSBTAmount = expectedReceivingSBTAmount.toUint64(); returnedIDOLAmount = 0; } else if (totalLeftSBTAmountForUnrevealed == 0) { receivingSBTAmount = 0; returnedIDOLAmount = IDOLAmountDeposited; } else { receivingSBTAmount = totalLeftSBTAmountForUnrevealed; returnedIDOLAmount = IDOLAmountDeposited .sub( totalLeftSBTAmountForUnrevealed .mul(solidStrikePriceIDOL) .divRoundUp(10**8) ) .toUint64(); } return (receivingSBTAmount, returnedIDOLAmount); } /** * @notice Transfer SBT for those who forget to reveal. */ function receiveUnrevealedBidDistribution(bytes32 auctionID, bytes32 secret) public override returns (bool) { ( uint64 solidStrikePriceIDOL, , bool isEndInfoCreated, , ) = _auctionBoardContract.auctionDisposalInfo(auctionID); require( isEndInfoCreated, "EndInfo hasn't been made. This Function has not been allowed yet." ); (address secOwner, , uint64 IDOLAmountDeposited) = _auctionBoardContract .auctionSecret(auctionID, secret); require(secOwner == msg.sender, "ownership of the bid is required"); ( , uint64 totalIDOLSecret, uint64 totalIDOLAmountRevealed, ) = _auctionBoardContract.auctionRevealInfo(auctionID); uint64 totalIDOLAmountUnrevealed = totalIDOLSecret .sub(totalIDOLAmountRevealed) .toUint64(); uint64 receivingSBTAmount; uint64 returnedIDOLAmount; uint64 totalSBTAmountPaidForUnrevealed; { AuctionConfig memory auctionConfig = _auctionConfigList[auctionID]; totalSBTAmountPaidForUnrevealed = auctionConfig .totalSBTAmountPaidForUnrevealedE8; ( receivingSBTAmount, returnedIDOLAmount ) = _calcUnrevealedBidDistribution( auctionConfig.ongoingAuctionSBTTotalE8, totalIDOLAmountUnrevealed, totalSBTAmountPaidForUnrevealed, solidStrikePriceIDOL, IDOLAmountDeposited ); } _auctionConfigList[auctionID] .totalSBTAmountPaidForUnrevealedE8 = totalSBTAmountPaidForUnrevealed .add(receivingSBTAmount) .toUint64(); _auctionBoardContract.removeSecret(auctionID, secret, 0); // Transfer the winning SBT and (if necessary) return the rest of deposited iDOL. _distributeToWinners(auctionID, receivingSBTAmount); _IDOLContract.transfer(secOwner, returnedIDOLAmount); return true; } /** * @notice Cancel the bid of your own within the bid acceptance period. */ function cancelBid(bytes32 auctionID, bytes32 secret) public override returns (uint64) { require( isInPeriod(auctionID, ACCEPTING_BIDS_PERIOD_FLAG), "it is not the time to accept bids" ); (address owner, , uint64 IDOLamount) = _auctionBoardContract .auctionSecret(auctionID, secret); require(owner == msg.sender, "you are not the bidder for the secret"); _auctionBoardContract.removeSecret(auctionID, secret, IDOLamount); _transferIDOL( owner, IDOLamount, "system error: try to cancel bid, but cannot return iDOL" ); emit LogCancelBid(auctionID, owner, secret, IDOLamount); return IDOLamount; } /** * @notice Returns the current auction ID. */ function getCurrentAuctionID(bytes32 bondID) public override view returns (bytes32) { uint256 count = _bondIDAuctionCount[bondID]; return generateAuctionID(bondID, count); } /** * @notice Generates auction ID from bond ID and the count of auctions for the bond. */ function generateAuctionID(bytes32 bondID, uint256 count) public override pure returns (bytes32) { return keccak256(abi.encode(bondID, count)); } /** * @dev The bidder succeeds in winning the SBT for the auctionID with receivingBondAmount, and pays IDOL with billingIDOLAmount. */ function _distributeToWinners(bytes32 auctionID, uint64 receivingBondAmount) internal returns (uint64) { // Get the address of SBT contract. (address solidBondAddress, , , ) = _getBondFromAuctionID(auctionID); require(solidBondAddress != address(0), "the bond is not registered"); // Transfer the winning SBT. BondTokenInterface solidBondContract = BondTokenInterface( payable(solidBondAddress) ); solidBondContract.transfer(msg.sender, receivingBondAmount); } /** * @dev When isLast is true, the SBTs put up in the auction are sold entirely. * The average auction price is used for deciding the amount of IDOL to return from the lock pool. */ function _publishSettledAverageAuctionPrice(bytes32 auctionID, bool isLast) internal { bytes32 bondID = auctionID2BondID[auctionID]; ( , uint64 auctionRewardedTotalE8, uint64 auctionPaidTotalE8 ) = _auctionBoardContract.auctionInfo(auctionID); // The auction contract actually do not burn iDOL. Paid iDOL will be transferred and burned in the stable coin contract. _transferIDOL( address(_IDOLContract), auctionPaidTotalE8, "system error: cannot transfer iDOL from auction contract to iDOL contract" ); _IDOLContract.setSettledAverageAuctionPrice( bondID, auctionPaidTotalE8, auctionRewardedTotalE8, isLast ); } /** * @dev How much IDOL to burn is decided by the settlement price. * Hence, this contract needs to decide the price within some specified period. */ function _forceToFinalizeWinnerAmount(bytes32 auctionID) internal { ( uint64 auctionSettledTotalE8, uint64 auctionRewardedTotalE8, ) = _auctionBoardContract.auctionInfo(auctionID); if (_auctionBoardContract.getSortedBidPrice(auctionID).length == 0) { return; } (uint256 burnIDOLRate, , , ) = _auctionBoardContract.getEndInfo( auctionID ); uint256 _totalSBTForRestWinners = auctionSettledTotalE8.sub( auctionRewardedTotalE8, "system error: allocated SBT amount for auction never becomes lower than reward total at any point" ); uint256 burnIDOL = _totalSBTForRestWinners.mul(burnIDOLRate).div(10**8); _auctionBoardContract.updateAuctionInfo( auctionID, _totalSBTForRestWinners.toUint64(), burnIDOL.toUint64(), _totalSBTForRestWinners.toUint64() ); } /** * @notice Returns the bond information corresponding to the auction ID. */ function _getBondFromAuctionID(bytes32 auctionID) internal view returns ( address erc20Address, uint256 maturity, uint64 solidStrikePrice, bytes32 fnMapID ) { bytes32 bondID = auctionID2BondID[auctionID]; return _bondMakerContract.getBond(bondID); } /** * @notice Returns the bond IDs corresponding to the auction IDs respectively. */ function listBondIDFromAuctionID(bytes32[] memory auctionIDs) public override view returns (bytes32[] memory bondIDs) { bondIDs = new bytes32[](auctionIDs.length); for (uint256 i = 0; i < auctionIDs.length; i++) { bondIDs[i] = auctionID2BondID[auctionIDs[i]]; } } /** * @notice Returns the auction status. * @param auctionID is a auction ID. * @return closingTime is . * @return auctionAmount is the SBT amount put up in the auction. * @return rewardedAmount is . * @return totalSBTAmountBid is . * @return isEmergency is . * @return doneFinalizeWinnerAmount is . * @return doneSortPrice is . * @return lowestBidPriceDeadLine is the minimum bid price in the auction. * @return highestBidPriceDeadLine is the maximum bid price in the auction. * @return totalSBTAmountPaidForUnrevealed is the SBT Amount allocated for those who had not revealed their own bid. */ function getAuctionStatus(bytes32 auctionID) public override view returns ( uint256 closingTime, uint64 auctionAmount, uint64 rewardedAmount, uint64 totalSBTAmountBid, bool isEmergency, bool doneFinalizeWinnerAmount, bool doneSortPrice, uint64 lowestBidPriceDeadLine, uint64 highestBidPriceDeadLine, uint64 totalSBTAmountPaidForUnrevealed ) { closingTime = auctionClosingTime[auctionID].toUint64(); AuctionConfig memory auctionConfig = _auctionConfigList[auctionID]; auctionAmount = auctionConfig.ongoingAuctionSBTTotalE8; lowestBidPriceDeadLine = auctionConfig.lowestBidPriceDeadLineE8; highestBidPriceDeadLine = auctionConfig.highestBidPriceDeadLineE8; totalSBTAmountPaidForUnrevealed = auctionConfig .totalSBTAmountPaidForUnrevealedE8; (, rewardedAmount, ) = _auctionBoardContract.auctionInfo(auctionID); (totalSBTAmountBid, , , ) = _auctionBoardContract.auctionRevealInfo( auctionID ); isEmergency = isAuctionEmergency[auctionID]; (, , , doneFinalizeWinnerAmount, doneSortPrice) = _auctionBoardContract .auctionDisposalInfo(auctionID); } /** * @notice Returns the status of auctions which is held in the week. * @param weekNumber is the quotient obtained by dividing the timestamp by 7 * 24 * 60 * 60 (= 7 days). */ function getWeeklyAuctionStatus(uint256 weekNumber) external override view returns (uint256[] memory weeklyAuctionStatus) { bytes32[] memory auctions = listAuction(weekNumber); weeklyAuctionStatus = new uint256[](auctions.length.mul(6)); for (uint256 i = 0; i < auctions.length; i++) { ( uint256 closingTime, uint64 auctionAmount, uint64 rewardedAmount, uint64 totalSBTAmountBid, bool isEmergency, bool doneFinalizeWinnerAmount, bool doneSortPrice, , , ) = getAuctionStatus(auctions[i]); uint8 auctionStatusCode = (isEmergency ? 1 : 0) << 2; auctionStatusCode += (doneFinalizeWinnerAmount ? 1 : 0) << 1; auctionStatusCode += doneSortPrice ? 1 : 0; weeklyAuctionStatus[i * 6] = closingTime; weeklyAuctionStatus[i * 6 + 1] = auctionAmount; weeklyAuctionStatus[i * 6 + 2] = rewardedAmount; weeklyAuctionStatus[i * 6 + 3] = totalSBTAmountBid; weeklyAuctionStatus[i * 6 + 4] = auctionStatusCode; weeklyAuctionStatus[i * 6 + 5] = uint256(auctions[i]); } } /** * @notice Returns total SBT amount put up in the auction. */ function ongoingAuctionSBTTotal(bytes32 auctionID) external override view returns (uint64 ongoingSBTAmountE8) { AuctionConfig memory auctionConfig = _auctionConfigList[auctionID]; return auctionConfig.ongoingAuctionSBTTotalE8; } function getAuctionCount(bytes32 bondID) external override view returns (uint256 auctionCount) { return _bondIDAuctionCount[bondID]; } } // File: contracts/util/DeployerRole.sol abstract contract DeployerRole { address internal immutable _deployer; modifier onlyDeployer() { require( _isDeployer(msg.sender), "only deployer is allowed to call this function" ); _; } constructor() public { _deployer = msg.sender; } function _isDeployer(address account) internal view returns (bool) { return account == _deployer; } } // File: contracts/UseAuctionLater.sol abstract contract UseAuctionLater is DeployerRole { Auction internal _auctionContract; modifier isNotEmptyAuctionInstance() { require( address(_auctionContract) != address(0), "the auction contract is not set" ); _; } /** * @dev This function is called only once when the code is initially deployed. */ function setAuctionContract(address contractAddress) public onlyDeployer { require( address(_auctionContract) == address(0), "the auction contract is already registered" ); require( contractAddress != address(0), "contract should be non-zero address" ); _setAuctionContract(contractAddress); } function _setAuctionContract(address contractAddress) internal { _auctionContract = Auction(payable(contractAddress)); } } // File: contracts/StableCoin.sol contract StableCoin is UseSafeMath, StableCoinInterface, Time, ERC20("iDOL", "iDOL"), SolidBondSafety, UseOracle, UseBondMaker, UseAuctionLater { using Math for uint256; /** * @dev pool:mint = 1:9 */ uint256 internal constant LOCK_POOL_BORDER = 1; uint256 internal constant MINT_IDOL_BORDER = 10 - LOCK_POOL_BORDER; uint256 internal immutable AUCTION_SPAN; uint256 internal immutable EMERGENCY_AUCTION_SPAN; uint256 internal immutable MINT_IDOL_AMOUNT_BORDER; /** * @dev The contents of this internal storage variable can be seen by solidValueTotal function. */ uint256 internal _solidValueTotalE12; mapping(bytes32 => uint64) public auctionTriggerCount; /** * @dev Record the pooled IDOL for each person(= beta * minted amount). * The pooled IDOL is going to be refunded partially to the person when the deposited SBT is * sold in the auction. */ struct LockedPool { uint64 IDOLAmount; uint64 baseSBTAmount; } mapping(address => mapping(bytes32 => LockedPool)) public lockedPoolE8; /** * @dev The contents in this internal storage variable can be seen by getPoolInfo function. * @param lockedSolidBondTotalE8 is the current locked SBT amount. * @param unlockedSolidBondTotalE8 is the SBT amount unlocked by unlockSBT(). * @param lockedPoolIDOLTotalE8 is the iDOL amount locked to the pool for the SBT. * @param SBT2BurnedIDOLTotalE8 is the iDOL amount burned by unlockSBT() or setSettledAverageAuctionPrice(). */ struct AccountingTotalInfo { uint64 lockedSolidBondTotalE8; uint64 unlockedSolidBondTotalE8; uint64 lockedPoolIDOLTotalE8; uint64 SBT2BurnedIDOLTotalE8; } mapping(bytes32 => AccountingTotalInfo) internal _accountingTotalInfo; /** * @notice Record the average settlement price for each SBT bondID. * @dev The average settlement price is used for calculating the amount to return partially from * the pooled IDOL. * The contents in this internal storage variable can be seen by getPoolInfo function. * @param auctionSoldSolidBondTotal is the SBT total amount already sold in the auction. * @param auctionPaidIDOLTotalE8 is the iDOL amount already paid for the SBT in the auction. * @param settledAverageAuctionPrice is the average price for the SBT in the auction and unlockSBT(). * @param isAllAmountSoldInAuction indicates whether auctionSoldSolidBondTotal equals to the auction amount or not. */ struct AuctionAmountInfo { uint64 auctionSoldSolidBondTotal; uint64 auctionPaidIDOLTotalE8; uint64 settledAverageAuctionPrice; bool isAllAmountSoldInAuction; } mapping(bytes32 => AuctionAmountInfo) internal _auctionAmountInfo; constructor( address oracleAddress, address bondMakerAddress, uint256 auctionSpan, uint256 emergencyAuctionSpan, uint256 mintIDOLAmountBorder ) public UseOracle(oracleAddress) UseBondMaker(bondMakerAddress) { _setupDecimals(8); AUCTION_SPAN = auctionSpan; EMERGENCY_AUCTION_SPAN = emergencyAuctionSpan; MINT_IDOL_AMOUNT_BORDER = mintIDOLAmountBorder; } function _reduceSBTValue(uint256 SBTValueE12) internal { _solidValueTotalE12 = _solidValueTotalE12.sub(SBTValueE12); } /** * @notice In order to calculate the amount to burn from the pooled IDOL, need to aggregate * IDOLs both in the auction and in the unlockSBT function. Calculate settled-average-auction- * price (every time an auction ends, the auction contract trigger this) * @param bondID ID for auctioned SBT * @param auctionPaidIDOL IDOL amount burned in this auction * @param auctionSoldAmount SBT amount sold in this auction * @param isLastTime True when the auction successfully sold all the SBT */ function _setSettledAverageAuctionPrice( bytes32 bondID, uint64 auctionPaidIDOL, uint64 auctionSoldAmount, bool isLastTime ) internal { bytes32 poolID = getCurrentPoolID(bondID); AuctionAmountInfo memory auctionInfo = _auctionAmountInfo[poolID]; auctionInfo.auctionSoldSolidBondTotal = auctionInfo .auctionSoldSolidBondTotal .add(auctionSoldAmount) .toUint64(); auctionInfo.auctionPaidIDOLTotalE8 = auctionInfo .auctionPaidIDOLTotalE8 .add(auctionPaidIDOL) .toUint64(); if (isLastTime) { // Calculate the amount of IDOL to burn AccountingTotalInfo memory accountingInfo = _accountingTotalInfo[poolID]; uint256 burnIDOLAmount = 0; /** * @dev In the case of beta=0.1, total distributed IDOL for the bondID * can be calculated by the pooled IDOL amount for the bondID multiplied by 9 * (= MINT_IDOL_BORDER). * In the case that someone has withdrawn SBT by unlockSBT(), the pooled IDOL is also * circulated. * When 3 SBT (strike = $100) are withdrawn by unlockSBT() and 8 SBT are sold in the * auction, circulated = (3+8)*100*0.9 and everminted = (3+8)*100. * Those 3 and 8 can be captured by looking at the amount of IDOL in the pool. */ { // (circulated amount) = (locked pool iDOL total) * MINT_IDOL_BORDER / LOCK_POOL_BORDER // = (locked pool iDOL total) * MINT_IDOL_BORDER uint256 circulated = accountingInfo.lockedPoolIDOLTotalE8.mul( MINT_IDOL_BORDER ); uint256 everMinted = accountingInfo.lockedPoolIDOLTotalE8.add( circulated ); uint256 allBurn = accountingInfo.SBT2BurnedIDOLTotalE8.add( auctionInfo.auctionPaidIDOLTotalE8 ); if (allBurn > circulated) { if (everMinted >= allBurn) { // burn all the IDOL issued for the SBT put up in the auction //SAME MEANING of: burnIDOLAmount = everMinted.sub(allBurn).add(auctionPaidIDOLTotalE8[bondID]); burnIDOLAmount = everMinted.sub( accountingInfo.SBT2BurnedIDOLTotalE8 ); } else { // burn all the IDOL issued for the SBT put up in the auction, and excess amount. //SAME MEANING of: burnIDOLAmount = allBurn.sub(allBurn).add(auctionPaidIDOLTotalE8[bondID]); burnIDOLAmount = allBurn.sub( accountingInfo.SBT2BurnedIDOLTotalE8 ); } } else { // burn as much as we can. //In this case, burn rate(price) is lower than 1-beta burnIDOLAmount = accountingInfo.lockedPoolIDOLTotalE8.add( auctionInfo.auctionPaidIDOLTotalE8 ); } } (, , uint64 solidBondStrikePriceUSD, ) = _bondMakerContract.getBond( bondID ); _burn(address(this), burnIDOLAmount); accountingInfo.SBT2BurnedIDOLTotalE8 = accountingInfo .SBT2BurnedIDOLTotalE8 .add(auctionInfo.auctionPaidIDOLTotalE8) .toUint64(); _reduceSBTValue( auctionInfo.auctionSoldSolidBondTotal.mul( solidBondStrikePriceUSD ) ); accountingInfo.unlockedSolidBondTotalE8 = accountingInfo .unlockedSolidBondTotalE8 .add(auctionInfo.auctionSoldSolidBondTotal) .toUint64(); auctionInfo.settledAverageAuctionPrice = accountingInfo .SBT2BurnedIDOLTotalE8 .mul(10**8) .div( accountingInfo .unlockedSolidBondTotalE8, "system: the total unlock amount should be non-zero value" ) .toUint64(); auctionInfo.isAllAmountSoldInAuction = true; auctionTriggerCount[bondID] = auctionTriggerCount[bondID] .add(1) .toUint64(); _accountingTotalInfo[poolID] = accountingInfo; uint256 totalIDOLSupply = totalSupply(); emit LogLambda( poolID, auctionInfo.settledAverageAuctionPrice, totalIDOLSupply, _solidValueTotalE12 ); } _auctionAmountInfo[poolID] = auctionInfo; } /** * @param poolID is a pool ID. * @return lockedSBTTotal is the current locked SBT amount. (e8) * @return unlockedSBTTotal is the SBT amount unlocked with unlockSBT(). (e8) * @return lockedPoolIDOLTotal is the iDOL amount locked to the pool when this was minted. (e8) * @return burnedIDOLTotal is the iDOL amount burned with unlockSBT() and setSettledAverageAuctionPrice(). (e8) * @return soldSBTTotalInAuction is the SBT total amount already sold in the auction. (e8) * @return paidIDOLTotalInAuction is the iDOL amount already paid for SBT in the auction. (e8) * @return settledAverageAuctionPrice is the average price with iDOL of the SBT in the auction and unlockSBT(). (e8) * @return isAllAmountSoldInAuction is whether auctionSoldSolidBondTotal is equal to the auction amount or not. */ function getPoolInfo(bytes32 poolID) external override view returns ( uint64 lockedSBTTotal, uint64 unlockedSBTTotal, uint64 lockedPoolIDOLTotal, uint64 burnedIDOLTotal, uint64 soldSBTTotalInAuction, uint64 paidIDOLTotalInAuction, uint64 settledAverageAuctionPrice, bool isAllAmountSoldInAuction ) { AccountingTotalInfo memory accountingInfo = _accountingTotalInfo[poolID]; lockedSBTTotal = accountingInfo.lockedSolidBondTotalE8; unlockedSBTTotal = accountingInfo.unlockedSolidBondTotalE8; lockedPoolIDOLTotal = accountingInfo.lockedPoolIDOLTotalE8; burnedIDOLTotal = accountingInfo.SBT2BurnedIDOLTotalE8; AuctionAmountInfo memory auctionSettlementInfo = _auctionAmountInfo[poolID]; soldSBTTotalInAuction = auctionSettlementInfo.auctionSoldSolidBondTotal; paidIDOLTotalInAuction = auctionSettlementInfo.auctionPaidIDOLTotalE8; settledAverageAuctionPrice = auctionSettlementInfo .settledAverageAuctionPrice; isAllAmountSoldInAuction = auctionSettlementInfo .isAllAmountSoldInAuction; } function solidValueTotal() external override view returns (uint256) { return _solidValueTotalE12; } function generatePoolID(bytes32 bondID, uint64 count) public override pure returns (bytes32) { return keccak256(abi.encodePacked(bondID, count, "lien")); } function getCurrentPoolID(bytes32 bondID) public override view returns (bytes32) { uint64 currentTriggeredCount = auctionTriggerCount[bondID]; return generatePoolID(bondID, currentTriggeredCount); } function getLockedPool(address user, bytes32 poolID) public override view returns (uint64, uint64) { return ( lockedPoolE8[user][poolID].IDOLAmount, lockedPoolE8[user][poolID].baseSBTAmount ); } /** * @dev poolID is counted up and used when the SBT once released from IDOL in the emergency * auction becomes qualified again before its maturity. */ /** * @dev Check if the SBT is qualified in terms of the length of the time until maturity, * the volatility, and the distance between the current price and the strike price. */ function isAcceptableSBT(bytes32 bondID) public virtual override isNotEmptyAuctionInstance returns (bool) { ( address bondTokenAddress, uint256 maturity, uint64 solidStrikePriceE4, ) = _bondMakerContract.getBond(bondID); require(bondTokenAddress != address(0), "the bond is not registered"); require( solidStrikePriceE4 != 0, "the bond does not match to the form of SBT" ); require( maturity > _getBlockTimestampSec() + AUCTION_SPAN, "a request to hold an auction of the bond has already expired" ); require( solidStrikePriceE4 % (10**5) == 0, "the strike price need to be $ 10*X" ); bytes32 auctionID = _auctionContract.getCurrentAuctionID(bondID); require( _auctionContract.ongoingAuctionSBTTotal(auctionID) == 0, "this SBT is on a auciton" ); (uint256 rateETH2USDE8, uint256 volatilityE8) = _getOracleData(); bool isDanger = isDangerSolidBond( rateETH2USDE8, solidStrikePriceE4, volatilityE8, maturity - _getBlockTimestampSec() ); emit LogIsAcceptableSBT(bondID, !isDanger); return !isDanger; } /** * @notice Lock SBT and mint IDOL * @param bondID the ID for the SBT locked for minting IDOL * @param lockAmountE8 the amount of locked SBT */ function mint( bytes32 bondID, address recipient, uint64 lockAmountE8 ) public override returns ( bytes32 poolID, uint64 obtainIDOLAmountE8, uint64 poolIDOLAmountE8 ) { poolID = getCurrentPoolID(bondID); // Check if the maturity is sufficiently distant from the current time. ( address bondTokenAddress, , uint256 solidStrikePriceE4, ) = _bondMakerContract.getBond(bondID); require( isAcceptableSBT(bondID), "SBT with the bondID is not currently acceptable" ); AccountingTotalInfo memory accountingInfo = _accountingTotalInfo[poolID]; // Calculate the mint amount based on the dilution ratio. uint256 solidBondValueE12 = lockAmountE8.mul(solidStrikePriceE4); uint256 mintAmountE8 = calcSBT2IDOL(solidBondValueE12); require( accountingInfo.lockedPoolIDOLTotalE8 != 0 || mintAmountE8 >= MINT_IDOL_AMOUNT_BORDER, "mint amount need to be greater than 500 idol for this bond" ); ERC20 bondTokenContract = ERC20(bondTokenAddress); bondTokenContract.transferFrom(msg.sender, address(this), lockAmountE8); // (pooling amount) = mintAmountE8 * LOCK_POOL_BORDER / 10 = mintAmountE8 / 10 uint256 poolAmount = mintAmountE8.div(10); LockedPool storage lockedPoolInfo = lockedPoolE8[recipient][poolID]; lockedPoolInfo.IDOLAmount = lockedPoolInfo .IDOLAmount .add(poolAmount) .toUint64(); lockedPoolInfo.baseSBTAmount = lockedPoolInfo .baseSBTAmount .add(lockAmountE8) .toUint64(); _mint(recipient, mintAmountE8.sub(poolAmount)); _mint(address(this), poolAmount); _solidValueTotalE12 = _solidValueTotalE12.add(solidBondValueE12); accountingInfo.lockedSolidBondTotalE8 = accountingInfo .lockedSolidBondTotalE8 .add(lockAmountE8) .toUint64(); accountingInfo.lockedPoolIDOLTotalE8 = accountingInfo .lockedPoolIDOLTotalE8 .add(poolAmount) .toUint64(); _accountingTotalInfo[poolID] = accountingInfo; uint256 obtainAmount = mintAmountE8.sub(poolAmount); emit LogMintIDOL(bondID, recipient, poolID, obtainAmount, poolAmount); return (poolID, obtainAmount.toUint64(), poolAmount.toUint64()); } /** * @dev Only the auction contract address can burn some specified amount of the IDOL held by * an account. */ function burnFrom(address account, uint256 amount) public override isNotEmptyAuctionInstance { require( msg.sender == address(_auctionContract), "msg.sender must be auction contract" ); _burn(account, amount); } /** * @notice This function provides the opportunity to redeem any type of SBT with a correct * amount by burning iDOL. iDOL is pegged to totalLockedValue/totalSupply dollar * (initially 1 dollar), so we can always allow anyone to redeem at most 1 dollar worth SBT * by burning 1 dollar worth iDOL. * This is based on the mathematical fact that the theoretical value of 1 unit SBT with * strike price 100 dollar is always strictly less than 100 dollar (e.g. 99.99 dollar). * @dev IDOL contract needs to know the value of iDOL per unit by calculating * totalLockedValue/totalSupply the value of iDOL per unit may change when the auction * settlement price is not within the certain price range. * rewardSBT = burnAmountE8/solidStrikePriceE4 * totalSupply/totalLockedValue * @param bondID is the bond to unlock * @param burnAmountE8 is the iDOL amount to burn */ function unlockSBT(bytes32 bondID, uint64 burnAmountE8) public override returns (uint64) { bytes32 poolID = getCurrentPoolID(bondID); ( address bondTokenAddress, , uint256 solidStrikePriceE4, ) = _bondMakerContract.getBond(bondID); require(bondTokenAddress != address(0), "the bond is not registered"); require(solidStrikePriceE4 != 0, "the bond is not the form of SBT"); AccountingTotalInfo memory accountingInfo = _accountingTotalInfo[poolID]; uint64 rewardSBTE8 = burnAmountE8 .mul(_solidValueTotalE12) .div(totalSupply(), "system error: totalSupply never becomes zero") .div( solidStrikePriceE4, "system error: solidStrikePrice never becomes zero [unlockSBT]" ) .toUint64(); // Burn iDOL. accountingInfo.SBT2BurnedIDOLTotalE8 = accountingInfo .SBT2BurnedIDOLTotalE8 .add(burnAmountE8) .toUint64(); _burn(msg.sender, burnAmountE8); // Return SBT. BondTokenInterface bondTokenContract = BondTokenInterface( payable(bondTokenAddress) ); bondTokenContract.transfer(msg.sender, rewardSBTE8); emit LogBurnIDOL(bondID, msg.sender, burnAmountE8, rewardSBTE8); // Update solidValueTotal, lockedSolidBondTotalE18 and unlockedSolidBondTotal. _solidValueTotalE12 = _solidValueTotalE12.sub( rewardSBTE8.mul(solidStrikePriceE4) ); accountingInfo.lockedSolidBondTotalE8 = accountingInfo .lockedSolidBondTotalE8 .sub(rewardSBTE8) .toUint64(); accountingInfo.unlockedSolidBondTotalE8 = accountingInfo .unlockedSolidBondTotalE8 .add(rewardSBTE8) .toUint64(); _accountingTotalInfo[poolID] = accountingInfo; return rewardSBTE8; } /** * @notice Starts regular auction for SBT with short maturity. */ function startAuctionOnMaturity(bytes32 bondID) public override isNotEmptyAuctionInstance { bytes32 poolID = getCurrentPoolID(bondID); ( address bondTokenAddress, uint256 maturity, uint64 solidBondStrikePriceUSD, ) = _bondMakerContract.getBond(bondID); require(bondTokenAddress != address(0), "the bond is not registered"); require( solidBondStrikePriceUSD != 0, "the bond is not the form of SBT" ); require( maturity <= _getBlockTimestampSec() + AUCTION_SPAN, "maturity is later than the regular auctionSpan" ); uint64 lockedSolidBondTotalE8; { AccountingTotalInfo memory accountingInfo = _accountingTotalInfo[poolID]; lockedSolidBondTotalE8 = accountingInfo.lockedSolidBondTotalE8; if (lockedSolidBondTotalE8 == 0) { if (accountingInfo.lockedPoolIDOLTotalE8 != 0) { _setSettledAverageAuctionPrice(bondID, 0, 0, true); } return; } delete _accountingTotalInfo[poolID].lockedSolidBondTotalE8; } if (maturity <= _getBlockTimestampSec() + EMERGENCY_AUCTION_SPAN) { _auctionContract.startAuction(bondID, lockedSolidBondTotalE8, true); } else { _auctionContract.startAuction( bondID, lockedSolidBondTotalE8, false ); } // Send SBT to the auction contract. BondTokenInterface bondTokenContract = BondTokenInterface( payable(bondTokenAddress) ); bondTokenContract.transfer( address(_auctionContract), lockedSolidBondTotalE8 ); } /** * @notice Starts emergency auction * @dev Check if the SBT needs to trigger the emergency auction based on the length of the * time until maturity, the volatility, and the distance between the current price and the * strike price. */ function startAuctionByMarket(bytes32 bondID) public override isNotEmptyAuctionInstance { bytes32 poolID = getCurrentPoolID(bondID); ( address bondTokenAddress, uint256 maturity, uint64 solidBondStrikePriceUSD, ) = _bondMakerContract.getBond(bondID); require(bondTokenAddress != address(0), "the bond is not registered"); require( solidBondStrikePriceUSD != 0, "the bond is not the form of SBT" ); (uint256 rateETH2USD, uint256 volatility) = _getOracleData(); bool isDanger = isInEmergency( rateETH2USD, solidBondStrikePriceUSD, volatility, maturity - _getBlockTimestampSec() ); require(isDanger, "the SBT is not in emergency"); uint64 lockedSolidBondTotalE8; { AccountingTotalInfo memory accountingInfo = _accountingTotalInfo[poolID]; lockedSolidBondTotalE8 = accountingInfo.lockedSolidBondTotalE8; if (lockedSolidBondTotalE8 == 0) { if (accountingInfo.lockedPoolIDOLTotalE8 != 0) { _setSettledAverageAuctionPrice(bondID, 0, 0, true); } return; } delete _accountingTotalInfo[poolID].lockedSolidBondTotalE8; } _auctionContract.startAuction(bondID, lockedSolidBondTotalE8, true); // Send SBT to the auction contract. BondTokenInterface bondTokenContract = BondTokenInterface( payable(bondTokenAddress) ); bondTokenContract.transfer( address(_auctionContract), lockedSolidBondTotalE8 ); } /** * @notice Sets SettledAverageAuctionPrice and burns a portion of pooled IDOL. * @dev Only callable from the auction contract. */ function setSettledAverageAuctionPrice( bytes32 bondID, uint64 totalPaidIDOL, uint64 SBTAmount, bool isLast ) public override isNotEmptyAuctionInstance { require( msg.sender == address(_auctionContract), "msg.sender must be auction contract" ); (, , uint256 solidStrikePrice, ) = _bondMakerContract.getBond(bondID); require(solidStrikePrice != 0, "the bond is not the form of SBT"); _setSettledAverageAuctionPrice( bondID, totalPaidIDOL, SBTAmount, isLast ); } /** * @dev Returns the IDOL amount equivalent to the strike price value of SBT. * @param solidBondValueE12 solidBondValueE12(USD) = SBT(SBT) * strikePrice(USD/SBT) */ function calcSBT2IDOL(uint256 solidBondValueE12) public override view returns (uint256 IDOLAmountE8) { if (_solidValueTotalE12 == 0) { return solidBondValueE12.div(10**4); } return solidBondValueE12.mul(totalSupply()).div(_solidValueTotalE12); } function _calcUnlockablePoolAmount(bytes32 poolID, address account) internal returns (uint64) { AuctionAmountInfo memory auctionInfo = _auctionAmountInfo[poolID]; if (!auctionInfo.isAllAmountSoldInAuction) { return 0; } uint256 pool = lockedPoolE8[account][poolID].IDOLAmount; uint256 amountE8 = lockedPoolE8[account][poolID].baseSBTAmount; delete lockedPoolE8[account][poolID]; uint256 auctionIDOLPriceE8 = auctionInfo.settledAverageAuctionPrice; uint256 toBack = 0; // The return value can be calculated by // (average sold price) * (total sold amount) - (total distributed amount) for the bondID. // Here, (total distributed amount) = pool * MINT_IDOL_BORDER / LOCK_POOL_BORDER = pool * MINT_IDOL_BORDER if ( auctionIDOLPriceE8.mul(amountE8).div(10**8) > pool.mul(MINT_IDOL_BORDER) ) { toBack = auctionIDOLPriceE8.mul(amountE8).div(10**8) - pool.mul(MINT_IDOL_BORDER); } return toBack.min(pool).toUint64(); } /** * @notice Receives all the redeemable IDOL in one action. * @dev Receive corresponding pooled IDOL based on the SettledAverageAuctionPrice. */ function returnLockedPoolTo(bytes32[] memory poolIDs, address account) public override returns (uint64) { uint256 totalBackIDOLAmount = 0; for (uint256 i = 0; i < poolIDs.length; i++) { // For each bondID, the return amount should not exceed the pooled amount. uint64 backIDOLAmount = _calcUnlockablePoolAmount( poolIDs[i], account ); totalBackIDOLAmount = totalBackIDOLAmount.add(backIDOLAmount); if (backIDOLAmount != 0) { emit LogReturnLockedPool(poolIDs[i], account, backIDOLAmount); } } this.transfer(account, totalBackIDOLAmount); return totalBackIDOLAmount.toUint64(); } function returnLockedPool(bytes32[] memory poolIDs) public override returns (uint64) { return returnLockedPoolTo(poolIDs, msg.sender); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"oracleAddress","type":"address"},{"internalType":"address","name":"bondMakerAddress","type":"address"},{"internalType":"uint256","name":"auctionSpan","type":"uint256"},{"internalType":"uint256","name":"emergencyAuctionSpan","type":"uint256"},{"internalType":"uint256","name":"mintIDOLAmountBorder","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"bondID","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"burnIDOLAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unlockSBTAmount","type":"uint256"}],"name":"LogBurnIDOL","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"bondID","type":"bytes32"},{"indexed":false,"internalType":"bool","name":"isAcceptable","type":"bool"}],"name":"LogIsAcceptableSBT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"settledAverageAuctionPrice","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"totalSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockedSBTValue","type":"uint256"}],"name":"LogLambda","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"bondID","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"obtainIDOLAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"poolIDOLAmount","type":"uint256"}],"name":"LogMintIDOL","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolID","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint64","name":"backIDOLAmount","type":"uint64"}],"name":"LogReturnLockedPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"auctionTriggerCount","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"solidBondValueE12","type":"uint256"}],"name":"calcSBT2IDOL","outputs":[{"internalType":"uint256","name":"IDOLAmountE8","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"},{"internalType":"uint64","name":"count","type":"uint64"}],"name":"generatePoolID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"}],"name":"getCurrentPoolID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"xxE8","type":"uint256"}],"name":"getEmergencyBorderInfo","outputs":[{"internalType":"int256","name":"aaE4","type":"int256"},{"internalType":"int256","name":"bE4","type":"int256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"name":"getLockedPool","outputs":[{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"}],"name":"getPoolInfo","outputs":[{"internalType":"uint64","name":"lockedSBTTotal","type":"uint64"},{"internalType":"uint64","name":"unlockedSBTTotal","type":"uint64"},{"internalType":"uint64","name":"lockedPoolIDOLTotal","type":"uint64"},{"internalType":"uint64","name":"burnedIDOLTotal","type":"uint64"},{"internalType":"uint64","name":"soldSBTTotalInAuction","type":"uint64"},{"internalType":"uint64","name":"paidIDOLTotalInAuction","type":"uint64"},{"internalType":"uint64","name":"settledAverageAuctionPrice","type":"uint64"},{"internalType":"bool","name":"isAllAmountSoldInAuction","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"}],"name":"isAcceptableSBT","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"rateETH2USD","type":"uint256"},{"internalType":"uint256","name":"solidBondStrikePrice","type":"uint256"},{"internalType":"uint256","name":"volatility","type":"uint256"},{"internalType":"uint256","name":"untilMaturity","type":"uint256"}],"name":"isDangerSolidBond","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"rateETH2USD","type":"uint256"},{"internalType":"uint256","name":"solidBondStrikePrice","type":"uint256"},{"internalType":"uint256","name":"volatility","type":"uint256"},{"internalType":"uint256","name":"untilMaturity","type":"uint256"}],"name":"isInEmergency","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"lockedPoolE8","outputs":[{"internalType":"uint64","name":"IDOLAmount","type":"uint64"},{"internalType":"uint64","name":"baseSBTAmount","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint64","name":"lockAmountE8","type":"uint64"}],"name":"mint","outputs":[{"internalType":"bytes32","name":"poolID","type":"bytes32"},{"internalType":"uint64","name":"obtainIDOLAmountE8","type":"uint64"},{"internalType":"uint64","name":"poolIDOLAmountE8","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"poolIDs","type":"bytes32[]"}],"name":"returnLockedPool","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"poolIDs","type":"bytes32[]"},{"internalType":"address","name":"account","type":"address"}],"name":"returnLockedPoolTo","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"setAuctionContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"},{"internalType":"uint64","name":"totalPaidIDOL","type":"uint64"},{"internalType":"uint64","name":"SBTAmount","type":"uint64"},{"internalType":"bool","name":"isLast","type":"bool"}],"name":"setSettledAverageAuctionPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"solidValueTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"}],"name":"startAuctionByMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"}],"name":"startAuctionOnMaturity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"bondID","type":"bytes32"},{"internalType":"uint64","name":"burnAmountE8","type":"uint64"}],"name":"unlockSBT","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101206040523480156200001257600080fd5b5060405162004eff38038062004eff833981810160405260a08110156200003857600080fd5b50805160208083015160408085015160608601516080909601518251808401845260048082527f69444f4c000000000000000000000000000000000000000000000000000000008288018181528651808801909752918652968501969096528051969794969295919387938993620000b491600391906200020e565b508051620000ca9060049060208401906200020e565b50506005805460ff19166012179055506001600160a01b0381166200013b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602381526020018062004edc6023913960400191505060405180910390fd5b60058054610100600160a81b0319166101006001600160a01b03938416021790558116620001b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602381526020018062004edc6023913960400191505060405180910390fd5b6001600160601b0319606091821b1660805233901b60a052620001e260086001600160e01b03620001f816565b60c09290925260e0526101005250620002b39050565b6005805460ff191660ff92909216919091179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200025157805160ff191683800117855562000281565b8280016001018555821562000281579182015b828111156200028157825182559160200191906001019062000264565b506200028f92915062000293565b5090565b620002b091905b808211156200028f57600081556001016200029a565b90565b60805160601c60a05160601c60c05160e05161010051614bc06200031c60003980610f5b5250806130ed52508061224e5280612f9052508061334f525080610da052806116185280611b3e52806120ef528061252f5280612e1b5280613f225250614bc06000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c806379cc67901161010f578063b67f0935116100a2578063dbb2348311610071578063dbb23483146108dd578063dd62ed3e14610916578063dfef99f614610951578063e2fbacdd14610987576101f0565b8063b67f0935146107c1578063bc27f2ec146107ee578063c4fb3c3e1461080b578063d528d8aa146108ae576101f0565b80639ed7ac70116100de5780639ed7ac7014610705578063a457c2d714610732578063a9059cbb1461076b578063b515f740146107a4576101f0565b806379cc67901461068d5780637b7e31b1146106c657806393bb8a01146106ce57806395d89b41146106fd576101f0565b8063313ce56711610187578063616d272f11610156578063616d272f1461059e57806367fd88d0146105dd5780636881df131461063d57806370a082311461065a576101f0565b8063313ce5671461045257806339509351146104705780634e167ed9146104a957806350fef38c14610581576101f0565b8063134b0fca116101c3578063134b0fca1461036657806318160ddd1461039557806323b872dd1461039d5780632fe82fe6146103e0576101f0565b8063023924c7146101f557806306fdde031461022a578063095ea7b3146102a757806309f2c019146102f4575b600080fd5b6102286004803603602081101561020b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166109a4565b005b610232610a9b565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561026c578181015183820152602001610254565b50505050905090810190601f1680156102995780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102e0600480360360408110156102bd57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610b4f565b604080519115158252519081900360200190f35b6103116004803603602081101561030a57600080fd5b5035610b6d565b6040805167ffffffffffffffff998a16815297891660208901529588168787015293871660608701529186166080860152851660a085015290931660c083015291151560e08201529051908190036101000190f35b6103836004803603602081101561037c57600080fd5b5035610cb2565b60408051918252519081900360200190f35b610383610cde565b6102e0600480360360608110156103b357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610ce4565b610429600480360360608110156103f657600080fd5b50803590602081013573ffffffffffffffffffffffffffffffffffffffff16906040013567ffffffffffffffff16610d8b565b6040805193845267ffffffffffffffff9283166020850152911682820152519081900360600190f35b61045a6113a1565b6040805160ff9092168252519081900360200190f35b6102e06004803603604081101561048657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356113aa565b610564600480360360408110156104bf57600080fd5b8101906020810181356401000000008111156104da57600080fd5b8201836020820111156104ec57600080fd5b8035906020019184602083028401116401000000008311171561050e57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505050903573ffffffffffffffffffffffffffffffffffffffff16915061140b9050565b6040805167ffffffffffffffff9092168252519081900360200190f35b6102286004803603602081101561059757600080fd5b503561159a565b610228600480360360808110156105b457600080fd5b5080359067ffffffffffffffff6020820135811691604081013590911690606001351515611a7a565b610616600480360360408110156105f357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611c4d565b6040805167ffffffffffffffff938416815291909216602082015281519081900390910190f35b6103836004803603602081101561065357600080fd5b5035611c9d565b6103836004803603602081101561067057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611ced565b610228600480360360408110156106a357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611d15565b610383611de3565b6102e0600480360360808110156106e457600080fd5b5080359060208101359060408101359060600135611de9565b610232611ef5565b6103836004803603604081101561071b57600080fd5b508035906020013567ffffffffffffffff16611f74565b6102e06004803603604081101561074857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611fec565b6102e06004803603604081101561078157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612067565b6102e0600480360360208110156107ba57600080fd5b503561207b565b610564600480360360408110156107d757600080fd5b508035906020013567ffffffffffffffff1661251c565b6105646004803603602081101561080457600080fd5b5035612a72565b6105646004803603602081101561082157600080fd5b81019060208101813564010000000081111561083c57600080fd5b82018360208201111561084e57600080fd5b8035906020019184602083028401116401000000008311171561087057600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612a8e945050505050565b6102e0600480360360808110156108c457600080fd5b5080359060208101359060408101359060600135612a9a565b610616600480360360408110156108f357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612bc8565b6103836004803603604081101561092c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612bff565b61096e6004803603602081101561096757600080fd5b5035612c37565b6040805192835260208301919091528051918290030190f35b6102286004803603602081101561099d57600080fd5b5035612d9d565b6109ad3361334d565b6109e85760405162461bcd60e51b815260040180806020018281038252602e8152602001806148dd602e913960400191505060405180910390fd5b60065473ffffffffffffffffffffffffffffffffffffffff1615610a3d5760405162461bcd60e51b815260040180806020018281038252602a815260200180614af6602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116610a8f5760405162461bcd60e51b81526004018080602001828103825260238152602001806149a16023913960400191505060405180910390fd5b610a988161338c565b50565b60038054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610b455780601f10610b1a57610100808354040283529160200191610b45565b820191906000526020600020905b815481529060010190602001808311610b2857829003601f168201915b5050505050905090565b6000610b63610b5c6133d3565b84846133d7565b5060015b92915050565b600080600080600080600080610b81614707565b506000898152600a60209081526040918290208251608081018452905467ffffffffffffffff80821680845268010000000000000000830482169484018590527001000000000000000000000000000000008304821695840186905278010000000000000000000000000000000000000000000000009092041660608301819052909b509199509197509550610c15614707565b50505060009788525050600b60209081526040968790208751608081018952905467ffffffffffffffff808216808452680100000000000000008304821694840185905270010000000000000000000000000000000083049091169983018a9052780100000000000000000000000000000000000000000000000090910460ff161515606090920182905296989597949693959394919391925090565b60008181526008602052604081205467ffffffffffffffff16610cd58382611f74565b9150505b919050565b60025490565b6000610cf18484846134ea565b610d8184610cfd6133d3565b610d7c856040518060600160405280602881526020016149526028913973ffffffffffffffffffffffffffffffffffffffff8a16600090815260016020526040812090610d486133d3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054919063ffffffff61369216565b6133d7565b5060019392505050565b6000806000610d9986610cb2565b92506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166326d6c97b896040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b158015610e0f57600080fd5b505afa158015610e23573d6000803e3d6000fd5b505050506040513d6080811015610e3957600080fd5b50805160409091015190925067ffffffffffffffff169050610e5a8861207b565b610e955760405162461bcd60e51b815260040180806020018281038252602f81526020018061484e602f913960400191505060405180910390fd5b610e9d614707565b506000858152600a602090815260408083208151608081018352905467ffffffffffffffff808216835268010000000000000000820481169483019490945270010000000000000000000000000000000081048416928201929092527801000000000000000000000000000000000000000000000000909104821660608201529190610f319089168463ffffffff61372916565b90506000610f3e82611c9d565b9050826040015167ffffffffffffffff166000141580610f7e57507f00000000000000000000000000000000000000000000000000000000000000008110155b610fb95760405162461bcd60e51b815260040180806020018281038252603a815260200180614a1d603a913960400191505060405180910390fd5b604080517f23b872dd00000000000000000000000000000000000000000000000000000000815233600482015230602482015267ffffffffffffffff8b1660448201529051869173ffffffffffffffffffffffffffffffffffffffff8316916323b872dd916064808201926020929091908290030181600087803b15801561104057600080fd5b505af1158015611054573d6000803e3d6000fd5b505050506040513d602081101561106a57600080fd5b506000905061108083600a63ffffffff61378916565b73ffffffffffffffffffffffffffffffffffffffff8d1660009081526009602090815260408083208e845290915290208054919250906110d9906110d49067ffffffffffffffff168463ffffffff6137cb16565b613825565b81547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff9182161780835561112b916110d4916801000000000000000090048116908f166137cb565b815467ffffffffffffffff9190911668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161781556111858d611180868563ffffffff61387216565b6138b4565b61118f30836138b4565b6007546111a2908663ffffffff6137cb16565b60075585516111c9906110d49067ffffffffffffffff908116908f1663ffffffff6137cb16565b67ffffffffffffffff908116875260408701516111f1916110d491168463ffffffff6137cb16565b67ffffffffffffffff908116604080890191825260008e8152600a60209081529181208a518154938c0151945160608d0151871678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff918816700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff97891668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff949099167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909716969096179290921696909617949094169290921793909316919091179055611315858463ffffffff61387216565b90508d73ffffffffffffffffffffffffffffffffffffffff168f7f5a0def86b68ea53595ef32019b93a42eedf7c609407f51834703faa48bd592d08e848760405180848152602001838152602001828152602001935050505060405180910390a38b61138082613825565b61138985613825565b9b509b509b5050505050505050505093509350939050565b60055460ff1690565b6000610b636113b76133d3565b84610d7c85600160006113c86133d3565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff6137cb16565b600080805b84518110156114e657600061143886838151811061142a57fe5b6020026020010151866139d7565b90506114548367ffffffffffffffff831663ffffffff6137cb16565b925067ffffffffffffffff8116156114dd578473ffffffffffffffffffffffffffffffffffffffff1686838151811061148957fe5b60200260200101517fb931a8416f2f16d5400a0cce933872df77c3cfcadae032ff6b1646e8cdc12a3c83604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390a35b50600101611410565b50604080517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602481018390529051309163a9059cbb9160448083019260209291908290030181600087803b15801561155c57600080fd5b505af1158015611570573d6000803e3d6000fd5b505050506040513d602081101561158657600080fd5b50611592905081613825565b949350505050565b60065473ffffffffffffffffffffffffffffffffffffffff16611604576040805162461bcd60e51b815260206004820152601f60248201527f7468652061756374696f6e20636f6e7472616374206973206e6f742073657400604482015290519081900360640190fd5b600061160f82610cb2565b905060008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166326d6c97b866040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b15801561168757600080fd5b505afa15801561169b573d6000803e3d6000fd5b505050506040513d60808110156116b157600080fd5b5080516020820151604090920151909450909250905073ffffffffffffffffffffffffffffffffffffffff831661172f576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b67ffffffffffffffff811661178b576040805162461bcd60e51b815260206004820152601f60248201527f74686520626f6e64206973206e6f742074686520666f726d206f662053425400604482015290519081900360640190fd5b600080611796613b68565b9150915060006117bb838567ffffffffffffffff16846117b4613ca7565b8903611de9565b90508061180f576040805162461bcd60e51b815260206004820152601b60248201527f74686520534254206973206e6f7420696e20656d657267656e63790000000000604482015290519081900360640190fd5b6000611819614707565b50506000878152600a60209081526040918290208251608081018452905467ffffffffffffffff808216808452680100000000000000008304821694840194909452700100000000000000000000000000000000820481169483019490945278010000000000000000000000000000000000000000000000009004909216606083015290816118d257604081015167ffffffffffffffff16156118c4576118c48a6000806001613cab565b505050505050505050610a98565b506000888152600a6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560065481517f9da326ef000000000000000000000000000000000000000000000000000000008152600481018e905267ffffffffffffffff8616602482015260016044820152915173ffffffffffffffffffffffffffffffffffffffff90911693639da326ef93606480850194919392918390030190829087803b15801561199157600080fd5b505af11580156119a5573d6000803e3d6000fd5b505050506040513d60208110156119bb57600080fd5b5050600654604080517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff928316600482015267ffffffffffffffff841660248201529051899283169163a9059cbb9160448083019260209291908290030181600087803b158015611a4257600080fd5b505af1158015611a56573d6000803e3d6000fd5b505050506040513d6020811015611a6c57600080fd5b505050505050505050505050565b60065473ffffffffffffffffffffffffffffffffffffffff16611ae4576040805162461bcd60e51b815260206004820152601f60248201527f7468652061756374696f6e20636f6e7472616374206973206e6f742073657400604482015290519081900360640190fd5b60065473ffffffffffffffffffffffffffffffffffffffff163314611b3a5760405162461bcd60e51b81526004018080602001828103825260238152602001806148ba6023913960400191505060405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166326d6c97b866040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b158015611bad57600080fd5b505afa158015611bc1573d6000803e3d6000fd5b505050506040513d6080811015611bd757600080fd5b506040015167ffffffffffffffff16905080611c3a576040805162461bcd60e51b815260206004820152601f60248201527f74686520626f6e64206973206e6f742074686520666f726d206f662053425400604482015290519081900360640190fd5b611c4685858585613cab565b5050505050565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152600960209081526040808320938352929052205467ffffffffffffffff80821692680100000000000000009092041690565b600060075460001415611cc357611cbc8261271063ffffffff61378916565b9050610cd9565b610b67600754611ce1611cd4610cde565b859063ffffffff61372916565b9063ffffffff61378916565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b60065473ffffffffffffffffffffffffffffffffffffffff16611d7f576040805162461bcd60e51b815260206004820152601f60248201527f7468652061756374696f6e20636f6e7472616374206973206e6f742073657400604482015290519081900360640190fd5b60065473ffffffffffffffffffffffffffffffffffffffff163314611dd55760405162461bcd60e51b81526004018080602001828103825260238152602001806148ba6023913960400191505060405180910390fd5b611ddf828261438a565b5050565b60075490565b600082630bebc200811115611dff5750630bebc2005b626ebe008310611e13576001915050611592565b6000611e3584611e29848063ffffffff61372916565b9063ffffffff61372916565b905066072ba304f800008104600080611e4d83612c37565b915091506000611e5c8b6144c6565b90506000611e698b6144c6565b90506000611e8d611e80858463ffffffff61452616565b849063ffffffff61460916565b90506000611eb383611ea781818c8b63ffffffff61452616565b9063ffffffff61452616565b905060008083131580611ee2575081611edf680118188ff217800000611ea7868063ffffffff61452616565b13155b9f9e505050505050505050505050505050565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610b455780601f10610b1a57610100808354040283529160200191610b45565b6040805160208082019490945260c09290921b7fffffffffffffffff00000000000000000000000000000000000000000000000016828201527f6c69656e0000000000000000000000000000000000000000000000000000000060488301528051808303602c018152604c9092019052805191012090565b6000610b63611ff96133d3565b84610d7c85604051806060016040528060258152602001614b6660259139600160006120236133d3565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff61369216565b6000610b636120746133d3565b84846134ea565b60065460009073ffffffffffffffffffffffffffffffffffffffff166120e8576040805162461bcd60e51b815260206004820152601f60248201527f7468652061756374696f6e20636f6e7472616374206973206e6f742073657400604482015290519081900360640190fd5b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166326d6c97b866040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b15801561215e57600080fd5b505afa158015612172573d6000803e3d6000fd5b505050506040513d608081101561218857600080fd5b5080516020820151604090920151909450909250905073ffffffffffffffffffffffffffffffffffffffff8316612206576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b67ffffffffffffffff811661224c5760405162461bcd60e51b815260040180806020018281038252602a815260200180614752602a913960400191505060405180910390fd5b7f0000000000000000000000000000000000000000000000000000000000000000612275613ca7565b0182116122b35760405162461bcd60e51b815260040180806020018281038252603c81526020018061479e603c913960400191505060405180910390fd5b620186a067ffffffffffffffff82160667ffffffffffffffff1660001461230b5760405162461bcd60e51b8152600401808060200182810382526022815260200180614b446022913960400191505060405180910390fd5b600654604080517fecfb314d00000000000000000000000000000000000000000000000000000000815260048101889052905160009273ffffffffffffffffffffffffffffffffffffffff169163ecfb314d916024808301926020929190829003018186803b15801561237d57600080fd5b505afa158015612391573d6000803e3d6000fd5b505050506040513d60208110156123a757600080fd5b5051600654604080517f9737d6fd00000000000000000000000000000000000000000000000000000000815260048101849052905192935073ffffffffffffffffffffffffffffffffffffffff90911691639737d6fd91602480820192602092909190829003018186803b15801561241e57600080fd5b505afa158015612432573d6000803e3d6000fd5b505050506040513d602081101561244857600080fd5b505167ffffffffffffffff16156124a6576040805162461bcd60e51b815260206004820152601860248201527f7468697320534254206973206f6e20612061756369746f6e0000000000000000604482015290519081900360640190fd5b6000806124b1613b68565b9150915060006124d6838667ffffffffffffffff16846124cf613ca7565b8a03612a9a565b604080518215815290519192508a917fea0241146eaea8e64956684a8df42cc134671b71fcc2b474bcbd63f30b32984f9181900360200190a21598975050505050505050565b60008061252884610cb2565b90506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166326d6c97b876040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b15801561259e57600080fd5b505afa1580156125b2573d6000803e3d6000fd5b505050506040513d60808110156125c857600080fd5b50805160409091015190925067ffffffffffffffff16905073ffffffffffffffffffffffffffffffffffffffff8216612648576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b8061269a576040805162461bcd60e51b815260206004820152601f60248201527f74686520626f6e64206973206e6f742074686520666f726d206f662053425400604482015290519081900360640190fd5b6126a2614707565b506000838152600a602090815260408083208151608081018352905467ffffffffffffffff808216835268010000000000000000820481168386015270010000000000000000000000000000000082048116838501527801000000000000000000000000000000000000000000000000909104166060808301919091528251908101909252603d808352909392612790926110d492879261487d9083013961278361274b610cde565b6040518060600160405280602c8152602001614822602c91396127836007548f67ffffffffffffffff1661372990919063ffffffff16565b919063ffffffff61466e16565b90506127c06110d48867ffffffffffffffff16846060015167ffffffffffffffff166137cb90919063ffffffff16565b67ffffffffffffffff90811660608401526127de903390891661438a565b604080517fa9059cbb00000000000000000000000000000000000000000000000000000000815233600482015267ffffffffffffffff831660248201529051859173ffffffffffffffffffffffffffffffffffffffff83169163a9059cbb916044808201926020929091908290030181600087803b15801561285f57600080fd5b505af1158015612873573d6000803e3d6000fd5b505050506040513d602081101561288957600080fd5b50506040805167ffffffffffffffff808b16825284166020820152815133928c927f87efbe374e86e4f26b4593306372ef7f3c1fa4ed256c9d4f7400d00b3f729114929081900390910190a36129016128f267ffffffffffffffff84168663ffffffff61372916565b6007549063ffffffff61387216565b6007558251612928906110d49067ffffffffffffffff90811690851663ffffffff61387216565b67ffffffffffffffff90811684526020840151612953916110d491811690851663ffffffff6137cb16565b67ffffffffffffffff90811660208086019182526000988952600a905260409788902085518154925199870151606090970151841678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff978516700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff9b861668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff939096167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009095169490941791909116939093179890981617939093169290921790945550919250505092915050565b60086020526000908152604090205467ffffffffffffffff1681565b6000610b67823361140b565b60006002850261c3508502108015612ab457506212750082105b15612ac157506000611592565b630bebc200831115612ad557506001611592565b626ebe008210612ae757506001611592565b6000612afd83611e29868063ffffffff61372916565b905066072ba304f800008104600080612b1583612c37565b915091506000612b248a6144c6565b90506000612b318a6144c6565b90506000612b6a612b4d6003611ea7878663ffffffff61452616565b612b5e85600263ffffffff61452616565b9063ffffffff61460916565b90506000612b876009611ea7858181818e8d63ffffffff61452616565b905060008083131580612bb6575081612bb3680118188ff217800000611ea7868063ffffffff61452616565b13155b9e9d5050505050505050505050505050565b600960209081526000928352604080842090915290825290205467ffffffffffffffff808216916801000000000000000090041682565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60008062c320408311612c51575060009050612af8612d98565b630394b7b18311612c6a5750615a4090506115bc612d98565b6307f7cae48311612ca257506206400090507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81fc612d98565b630bf379008311612cda5750621f126990507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1e88612d98565b630fc0bf018311612d12575062817ac190507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffae894612d98565b63134fd9008311612d4b57506301af0c8990507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f33b612d98565b6040805162461bcd60e51b815260206004820152600e60248201527f6e6f742061636365707461626c65000000000000000000000000000000000000604482015290519081900360640190fd5b915091565b60065473ffffffffffffffffffffffffffffffffffffffff16612e07576040805162461bcd60e51b815260206004820152601f60248201527f7468652061756374696f6e20636f6e7472616374206973206e6f742073657400604482015290519081900360640190fd5b6000612e1282610cb2565b905060008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166326d6c97b866040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b158015612e8a57600080fd5b505afa158015612e9e573d6000803e3d6000fd5b505050506040513d6080811015612eb457600080fd5b5080516020820151604090920151909450909250905073ffffffffffffffffffffffffffffffffffffffff8316612f32576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b67ffffffffffffffff8116612f8e576040805162461bcd60e51b815260206004820152601f60248201527f74686520626f6e64206973206e6f742074686520666f726d206f662053425400604482015290519081900360640190fd5b7f0000000000000000000000000000000000000000000000000000000000000000612fb7613ca7565b01821115612ff65760405162461bcd60e51b815260040180806020018281038252602e815260200180614ac8602e913960400191505060405180910390fd5b6000613000614707565b50506000848152600a60209081526040918290208251608081018452905467ffffffffffffffff808216808452680100000000000000008304821694840194909452700100000000000000000000000000000000820481169483019490945278010000000000000000000000000000000000000000000000009004909216606083015290816130b657604081015167ffffffffffffffff16156130ab576130ab876000806001613cab565b505050505050610a98565b506000858152600a6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001690557f0000000000000000000000000000000000000000000000000000000000000000613114613ca7565b0183116131d857600654604080517f9da326ef0000000000000000000000000000000000000000000000000000000081526004810189905267ffffffffffffffff8416602482015260016044820152905173ffffffffffffffffffffffffffffffffffffffff90921691639da326ef916064808201926020929091908290030181600087803b1580156131a657600080fd5b505af11580156131ba573d6000803e3d6000fd5b505050506040513d60208110156131d057600080fd5b506132939050565b600654604080517f9da326ef0000000000000000000000000000000000000000000000000000000081526004810189905267ffffffffffffffff84166024820152600060448201819052915173ffffffffffffffffffffffffffffffffffffffff90931692639da326ef92606480840193602093929083900390910190829087803b15801561326657600080fd5b505af115801561327a573d6000803e3d6000fd5b505050506040513d602081101561329057600080fd5b50505b600654604080517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff928316600482015267ffffffffffffffff841660248201529051869283169163a9059cbb9160448083019260209291908290030181600087803b15801561331857600080fd5b505af115801561332c573d6000803e3d6000fd5b505050506040513d602081101561334257600080fd5b505050505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff90811691161490565b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3390565b73ffffffffffffffffffffffffffffffffffffffff83166134295760405162461bcd60e51b8152600401808060200182810382526024815260200180614a7c6024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821661347b5760405162461bcd60e51b81526004018080602001828103825260228152602001806147da6022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b73ffffffffffffffffffffffffffffffffffffffff831661353c5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a576025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821661358e5760405162461bcd60e51b815260040180806020018281038252602381526020018061472f6023913960400191505060405180910390fd5b6135998383836146d3565b6135e9816040518060600160405280602681526020016147fc6026913973ffffffffffffffffffffffffffffffffffffffff8616600090815260208190526040902054919063ffffffff61369216565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220939093559084168152205461362b908263ffffffff6137cb16565b73ffffffffffffffffffffffffffffffffffffffff8084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156137215760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156136e65781810151838201526020016136ce565b50505050905090810190601f1680156137135780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008261373857506000610b67565b8282028284828161374557fe5b04146137825760405162461bcd60e51b815260040180806020018281038252602181526020018061490b6021913960400191505060405180910390fd5b9392505050565b600061378283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061466e565b600082820183811015613782576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600068010000000000000000821061386e5760405162461bcd60e51b815260040180806020018281038252602681526020018061492c6026913960400191505060405180910390fd5b5090565b600061378283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613692565b73ffffffffffffffffffffffffffffffffffffffff821661391c576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b613928600083836146d3565b60025461393b908263ffffffff6137cb16565b60025573ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054613974908263ffffffff6137cb16565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b60006139e1614707565b506000838152600b60209081526040918290208251608081018452905467ffffffffffffffff80821683526801000000000000000082048116938301939093527001000000000000000000000000000000008104909216928101929092527801000000000000000000000000000000000000000000000000900460ff16151560608201819052613a75576000915050610b67565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260096020818152604080842088855290915280832080547fffffffffffffffffffffffffffffffff0000000000000000000000000000000081169091559084015167ffffffffffffffff808316946801000000000000000090930481169391169190613afe908590613729565b613b166305f5e100611ce1858763ffffffff61372916565b1115613b4957613b2d84600963ffffffff61372916565b613b456305f5e100611ce1858763ffffffff61372916565b0390505b613b5c6110d4828663ffffffff6146d816565b98975050505050505050565b600080600560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015613bd557600080fd5b505af1158015613be9573d6000803e3d6000fd5b505050506040513d6020811015613bff57600080fd5b5051600554604080517f3af2888b000000000000000000000000000000000000000000000000000000008152905192945061010090910473ffffffffffffffffffffffffffffffffffffffff1691633af2888b916004808201926020929091908290030181600087803b158015613c7557600080fd5b505af1158015613c89573d6000803e3d6000fd5b505050506040513d6020811015613c9f57600080fd5b505190509091565b4290565b6000613cb685610cb2565b9050613cc0614707565b506000818152600b60209081526040918290208251608081018452905467ffffffffffffffff80821680845268010000000000000000830482169484019490945270010000000000000000000000000000000082048116948301949094527801000000000000000000000000000000000000000000000000900460ff161515606082015291613d54916110d49187166137cb565b67ffffffffffffffff90811682526020820151613d7f916110d491811690881663ffffffff6137cb16565b67ffffffffffffffff166020820152821561427257613d9c614707565b506000828152600a602090815260408083208151608081018352905467ffffffffffffffff8082168352680100000000000000008204811694830194909452700100000000000000000000000000000000810484169282018390527801000000000000000000000000000000000000000000000000900490921660608301529091908190613e3190600963ffffffff61372916565b90506000613e5682856040015167ffffffffffffffff166137cb90919063ffffffff16565b90506000613e89866020015167ffffffffffffffff16866060015167ffffffffffffffff166137cb90919063ffffffff16565b905082811115613ee957808210613ec1576060850151613eba90839067ffffffffffffffff1663ffffffff61387216565b9350613ee4565b6060850151613ee190829067ffffffffffffffff1663ffffffff61387216565b93505b613f1b565b613f18866020015167ffffffffffffffff16866040015167ffffffffffffffff166137cb90919063ffffffff16565b93505b50505060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166326d6c97b8a6040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b158015613f9157600080fd5b505afa158015613fa5573d6000803e3d6000fd5b505050506040513d6080811015613fbb57600080fd5b50604001519050613fcc308361438a565b613ffe6110d4856020015167ffffffffffffffff16856060015167ffffffffffffffff166137cb90919063ffffffff16565b67ffffffffffffffff9081166060850152845161402e9161402991811690841663ffffffff61372916565b6146ee565b83516020840151614056916110d49167ffffffffffffffff908116911663ffffffff6137cb16565b67ffffffffffffffff166020808501829052604080516060810190915260388082526140ae936110d493909291906149c49083013960608701516127839067ffffffffffffffff166305f5e10063ffffffff61372916565b67ffffffffffffffff90811660408087019190915260016060870181905260008c8152600860205291909120546140f1926110d49291169063ffffffff6137cb16565b60008a8152600860209081526040808320805467ffffffffffffffff9586167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000091821617909155898452600a835281842088518154948a0151938a015160608b0151881678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff918916700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff968a1668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff94909a169790951696909617919091169690961792909216179390931617909155614218610cde565b604080870151600754825167ffffffffffffffff90921682526020820184905281830152905191925087917fc96942e0138bef71dbf15b3512ad2970a8a07aeea02f0c50a94d373906dbf4cb9181900360600190a2505050505b6000918252600b60209081526040928390208251815492840151948401516060909401517fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090931667ffffffffffffffff918216177fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000095821695909502949094177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000009490931693909302919091177fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff1678010000000000000000000000000000000000000000000000009115159190910217905550505050565b73ffffffffffffffffffffffffffffffffffffffff82166143dc5760405162461bcd60e51b81526004018080602001828103825260218152602001806149fc6021913960400191505060405180910390fd5b6143e8826000836146d3565b6144388160405180606001604052806022815260200161477c6022913973ffffffffffffffffffffffffffffffffffffffff8516600090815260208190526040902054919063ffffffff61369216565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040902055600254614471908263ffffffff61387216565b60025560408051828152905160009173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b60007f8000000000000000000000000000000000000000000000000000000000000000821061386e5760405162461bcd60e51b8152600401808060200182810382526028815260200180614aa06028913960400191505060405180910390fd5b60008261453557506000610b67565b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14801561458357507f800000000000000000000000000000000000000000000000000000000000000082145b156145bf5760405162461bcd60e51b815260040180806020018281038252602781526020018061497a6027913960400191505060405180910390fd5b828202828482816145cc57fe5b05146137825760405162461bcd60e51b815260040180806020018281038252602781526020018061497a6027913960400191505060405180910390fd5b600081830381831280159061461e5750838113155b80614633575060008312801561463357508381135b6137825760405162461bcd60e51b8152600401808060200182810382526024815260200180614b206024913960400191505060405180910390fd5b600081836146bd5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156136e65781810151838201526020016136ce565b5060008385816146c957fe5b0495945050505050565b505050565b60008183106146e75781613782565b5090919050565b600754614701908263ffffffff61387216565b60075550565b6040805160808101825260008082526020820181905291810182905260608101919091529056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737374686520626f6e6420646f6573206e6f74206d6174636820746f2074686520666f726d206f662053425445524332303a206275726e20616d6f756e7420657863656564732062616c616e636561207265717565737420746f20686f6c6420616e2061756374696f6e206f662074686520626f6e642068617320616c7265616479206578706972656445524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636573797374656d206572726f723a20746f74616c537570706c79206e65766572206265636f6d6573207a65726f53425420776974682074686520626f6e644944206973206e6f742063757272656e746c792061636365707461626c6573797374656d206572726f723a20736f6c6964537472696b655072696365206e65766572206265636f6d6573207a65726f205b756e6c6f636b5342545d6d73672e73656e646572206d7573742062652061756374696f6e20636f6e74726163746f6e6c79206465706c6f79657220697320616c6c6f77656420746f2063616c6c20746869732066756e6374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7753616665436173743a2076616c756520646f65736e27742066697420696e203634206269747345524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63655369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77636f6e74726163742073686f756c64206265206e6f6e2d7a65726f206164647265737373797374656d3a2074686520746f74616c20756e6c6f636b20616d6f756e742073686f756c64206265206e6f6e2d7a65726f2076616c756545524332303a206275726e2066726f6d20746865207a65726f20616464726573736d696e7420616d6f756e74206e65656420746f2062652067726561746572207468616e203530302069646f6c20666f72207468697320626f6e6445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737353616665436173743a2076616c756520646f65736e27742066697420696e20616e20696e743235366d61747572697479206973206c61746572207468616e2074686520726567756c61722061756374696f6e5370616e7468652061756374696f6e20636f6e747261637420697320616c726561647920726567697374657265645369676e6564536166654d6174683a207375627472616374696f6e206f766572666c6f7774686520737472696b65207072696365206e65656420746f20626520242031302a5845524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220d085672f8467497f59973194f9b1d4d97c7592939b63afb78bc9add4e0e727e664736f6c63430006060033636f6e74726163742073686f756c64206265206e6f6e2d7a65726f2061646472657373000000000000000000000000120a078fdc516a1a98bbecb9e961f8741ac7ac820000000000000000000000008b24f5c764ab741bc8a2426505bda458c30df010000000000000000000000000000000000000000000000000000000000003f4800000000000000000000000000000000000000000000000000000000000015f900000000000000000000000000000000000000000000000000000000ba43b7400
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101f05760003560e01c806379cc67901161010f578063b67f0935116100a2578063dbb2348311610071578063dbb23483146108dd578063dd62ed3e14610916578063dfef99f614610951578063e2fbacdd14610987576101f0565b8063b67f0935146107c1578063bc27f2ec146107ee578063c4fb3c3e1461080b578063d528d8aa146108ae576101f0565b80639ed7ac70116100de5780639ed7ac7014610705578063a457c2d714610732578063a9059cbb1461076b578063b515f740146107a4576101f0565b806379cc67901461068d5780637b7e31b1146106c657806393bb8a01146106ce57806395d89b41146106fd576101f0565b8063313ce56711610187578063616d272f11610156578063616d272f1461059e57806367fd88d0146105dd5780636881df131461063d57806370a082311461065a576101f0565b8063313ce5671461045257806339509351146104705780634e167ed9146104a957806350fef38c14610581576101f0565b8063134b0fca116101c3578063134b0fca1461036657806318160ddd1461039557806323b872dd1461039d5780632fe82fe6146103e0576101f0565b8063023924c7146101f557806306fdde031461022a578063095ea7b3146102a757806309f2c019146102f4575b600080fd5b6102286004803603602081101561020b57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166109a4565b005b610232610a9b565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561026c578181015183820152602001610254565b50505050905090810190601f1680156102995780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102e0600480360360408110156102bd57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610b4f565b604080519115158252519081900360200190f35b6103116004803603602081101561030a57600080fd5b5035610b6d565b6040805167ffffffffffffffff998a16815297891660208901529588168787015293871660608701529186166080860152851660a085015290931660c083015291151560e08201529051908190036101000190f35b6103836004803603602081101561037c57600080fd5b5035610cb2565b60408051918252519081900360200190f35b610383610cde565b6102e0600480360360608110156103b357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610ce4565b610429600480360360608110156103f657600080fd5b50803590602081013573ffffffffffffffffffffffffffffffffffffffff16906040013567ffffffffffffffff16610d8b565b6040805193845267ffffffffffffffff9283166020850152911682820152519081900360600190f35b61045a6113a1565b6040805160ff9092168252519081900360200190f35b6102e06004803603604081101561048657600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356113aa565b610564600480360360408110156104bf57600080fd5b8101906020810181356401000000008111156104da57600080fd5b8201836020820111156104ec57600080fd5b8035906020019184602083028401116401000000008311171561050e57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295505050903573ffffffffffffffffffffffffffffffffffffffff16915061140b9050565b6040805167ffffffffffffffff9092168252519081900360200190f35b6102286004803603602081101561059757600080fd5b503561159a565b610228600480360360808110156105b457600080fd5b5080359067ffffffffffffffff6020820135811691604081013590911690606001351515611a7a565b610616600480360360408110156105f357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611c4d565b6040805167ffffffffffffffff938416815291909216602082015281519081900390910190f35b6103836004803603602081101561065357600080fd5b5035611c9d565b6103836004803603602081101561067057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16611ced565b610228600480360360408110156106a357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611d15565b610383611de3565b6102e0600480360360808110156106e457600080fd5b5080359060208101359060408101359060600135611de9565b610232611ef5565b6103836004803603604081101561071b57600080fd5b508035906020013567ffffffffffffffff16611f74565b6102e06004803603604081101561074857600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135611fec565b6102e06004803603604081101561078157600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612067565b6102e0600480360360208110156107ba57600080fd5b503561207b565b610564600480360360408110156107d757600080fd5b508035906020013567ffffffffffffffff1661251c565b6105646004803603602081101561080457600080fd5b5035612a72565b6105646004803603602081101561082157600080fd5b81019060208101813564010000000081111561083c57600080fd5b82018360208201111561084e57600080fd5b8035906020019184602083028401116401000000008311171561087057600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550612a8e945050505050565b6102e0600480360360808110156108c457600080fd5b5080359060208101359060408101359060600135612a9a565b610616600480360360408110156108f357600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612bc8565b6103836004803603604081101561092c57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612bff565b61096e6004803603602081101561096757600080fd5b5035612c37565b6040805192835260208301919091528051918290030190f35b6102286004803603602081101561099d57600080fd5b5035612d9d565b6109ad3361334d565b6109e85760405162461bcd60e51b815260040180806020018281038252602e8152602001806148dd602e913960400191505060405180910390fd5b60065473ffffffffffffffffffffffffffffffffffffffff1615610a3d5760405162461bcd60e51b815260040180806020018281038252602a815260200180614af6602a913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116610a8f5760405162461bcd60e51b81526004018080602001828103825260238152602001806149a16023913960400191505060405180910390fd5b610a988161338c565b50565b60038054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610b455780601f10610b1a57610100808354040283529160200191610b45565b820191906000526020600020905b815481529060010190602001808311610b2857829003601f168201915b5050505050905090565b6000610b63610b5c6133d3565b84846133d7565b5060015b92915050565b600080600080600080600080610b81614707565b506000898152600a60209081526040918290208251608081018452905467ffffffffffffffff80821680845268010000000000000000830482169484018590527001000000000000000000000000000000008304821695840186905278010000000000000000000000000000000000000000000000009092041660608301819052909b509199509197509550610c15614707565b50505060009788525050600b60209081526040968790208751608081018952905467ffffffffffffffff808216808452680100000000000000008304821694840185905270010000000000000000000000000000000083049091169983018a9052780100000000000000000000000000000000000000000000000090910460ff161515606090920182905296989597949693959394919391925090565b60008181526008602052604081205467ffffffffffffffff16610cd58382611f74565b9150505b919050565b60025490565b6000610cf18484846134ea565b610d8184610cfd6133d3565b610d7c856040518060600160405280602881526020016149526028913973ffffffffffffffffffffffffffffffffffffffff8a16600090815260016020526040812090610d486133d3565b73ffffffffffffffffffffffffffffffffffffffff168152602081019190915260400160002054919063ffffffff61369216565b6133d7565b5060019392505050565b6000806000610d9986610cb2565b92506000807f0000000000000000000000008b24f5c764ab741bc8a2426505bda458c30df01073ffffffffffffffffffffffffffffffffffffffff166326d6c97b896040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b158015610e0f57600080fd5b505afa158015610e23573d6000803e3d6000fd5b505050506040513d6080811015610e3957600080fd5b50805160409091015190925067ffffffffffffffff169050610e5a8861207b565b610e955760405162461bcd60e51b815260040180806020018281038252602f81526020018061484e602f913960400191505060405180910390fd5b610e9d614707565b506000858152600a602090815260408083208151608081018352905467ffffffffffffffff808216835268010000000000000000820481169483019490945270010000000000000000000000000000000081048416928201929092527801000000000000000000000000000000000000000000000000909104821660608201529190610f319089168463ffffffff61372916565b90506000610f3e82611c9d565b9050826040015167ffffffffffffffff166000141580610f7e57507f0000000000000000000000000000000000000000000000000000000ba43b74008110155b610fb95760405162461bcd60e51b815260040180806020018281038252603a815260200180614a1d603a913960400191505060405180910390fd5b604080517f23b872dd00000000000000000000000000000000000000000000000000000000815233600482015230602482015267ffffffffffffffff8b1660448201529051869173ffffffffffffffffffffffffffffffffffffffff8316916323b872dd916064808201926020929091908290030181600087803b15801561104057600080fd5b505af1158015611054573d6000803e3d6000fd5b505050506040513d602081101561106a57600080fd5b506000905061108083600a63ffffffff61378916565b73ffffffffffffffffffffffffffffffffffffffff8d1660009081526009602090815260408083208e845290915290208054919250906110d9906110d49067ffffffffffffffff168463ffffffff6137cb16565b613825565b81547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001667ffffffffffffffff9182161780835561112b916110d4916801000000000000000090048116908f166137cb565b815467ffffffffffffffff9190911668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff9091161781556111858d611180868563ffffffff61387216565b6138b4565b61118f30836138b4565b6007546111a2908663ffffffff6137cb16565b60075585516111c9906110d49067ffffffffffffffff908116908f1663ffffffff6137cb16565b67ffffffffffffffff908116875260408701516111f1916110d491168463ffffffff6137cb16565b67ffffffffffffffff908116604080890191825260008e8152600a60209081529181208a518154938c0151945160608d0151871678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff918816700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff97891668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff949099167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909716969096179290921696909617949094169290921793909316919091179055611315858463ffffffff61387216565b90508d73ffffffffffffffffffffffffffffffffffffffff168f7f5a0def86b68ea53595ef32019b93a42eedf7c609407f51834703faa48bd592d08e848760405180848152602001838152602001828152602001935050505060405180910390a38b61138082613825565b61138985613825565b9b509b509b5050505050505050505093509350939050565b60055460ff1690565b6000610b636113b76133d3565b84610d7c85600160006113c86133d3565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff6137cb16565b600080805b84518110156114e657600061143886838151811061142a57fe5b6020026020010151866139d7565b90506114548367ffffffffffffffff831663ffffffff6137cb16565b925067ffffffffffffffff8116156114dd578473ffffffffffffffffffffffffffffffffffffffff1686838151811061148957fe5b60200260200101517fb931a8416f2f16d5400a0cce933872df77c3cfcadae032ff6b1646e8cdc12a3c83604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390a35b50600101611410565b50604080517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602481018390529051309163a9059cbb9160448083019260209291908290030181600087803b15801561155c57600080fd5b505af1158015611570573d6000803e3d6000fd5b505050506040513d602081101561158657600080fd5b50611592905081613825565b949350505050565b60065473ffffffffffffffffffffffffffffffffffffffff16611604576040805162461bcd60e51b815260206004820152601f60248201527f7468652061756374696f6e20636f6e7472616374206973206e6f742073657400604482015290519081900360640190fd5b600061160f82610cb2565b905060008060007f0000000000000000000000008b24f5c764ab741bc8a2426505bda458c30df01073ffffffffffffffffffffffffffffffffffffffff166326d6c97b866040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b15801561168757600080fd5b505afa15801561169b573d6000803e3d6000fd5b505050506040513d60808110156116b157600080fd5b5080516020820151604090920151909450909250905073ffffffffffffffffffffffffffffffffffffffff831661172f576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b67ffffffffffffffff811661178b576040805162461bcd60e51b815260206004820152601f60248201527f74686520626f6e64206973206e6f742074686520666f726d206f662053425400604482015290519081900360640190fd5b600080611796613b68565b9150915060006117bb838567ffffffffffffffff16846117b4613ca7565b8903611de9565b90508061180f576040805162461bcd60e51b815260206004820152601b60248201527f74686520534254206973206e6f7420696e20656d657267656e63790000000000604482015290519081900360640190fd5b6000611819614707565b50506000878152600a60209081526040918290208251608081018452905467ffffffffffffffff808216808452680100000000000000008304821694840194909452700100000000000000000000000000000000820481169483019490945278010000000000000000000000000000000000000000000000009004909216606083015290816118d257604081015167ffffffffffffffff16156118c4576118c48a6000806001613cab565b505050505050505050610a98565b506000888152600a6020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016905560065481517f9da326ef000000000000000000000000000000000000000000000000000000008152600481018e905267ffffffffffffffff8616602482015260016044820152915173ffffffffffffffffffffffffffffffffffffffff90911693639da326ef93606480850194919392918390030190829087803b15801561199157600080fd5b505af11580156119a5573d6000803e3d6000fd5b505050506040513d60208110156119bb57600080fd5b5050600654604080517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff928316600482015267ffffffffffffffff841660248201529051899283169163a9059cbb9160448083019260209291908290030181600087803b158015611a4257600080fd5b505af1158015611a56573d6000803e3d6000fd5b505050506040513d6020811015611a6c57600080fd5b505050505050505050505050565b60065473ffffffffffffffffffffffffffffffffffffffff16611ae4576040805162461bcd60e51b815260206004820152601f60248201527f7468652061756374696f6e20636f6e7472616374206973206e6f742073657400604482015290519081900360640190fd5b60065473ffffffffffffffffffffffffffffffffffffffff163314611b3a5760405162461bcd60e51b81526004018080602001828103825260238152602001806148ba6023913960400191505060405180910390fd5b60007f0000000000000000000000008b24f5c764ab741bc8a2426505bda458c30df01073ffffffffffffffffffffffffffffffffffffffff166326d6c97b866040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b158015611bad57600080fd5b505afa158015611bc1573d6000803e3d6000fd5b505050506040513d6080811015611bd757600080fd5b506040015167ffffffffffffffff16905080611c3a576040805162461bcd60e51b815260206004820152601f60248201527f74686520626f6e64206973206e6f742074686520666f726d206f662053425400604482015290519081900360640190fd5b611c4685858585613cab565b5050505050565b73ffffffffffffffffffffffffffffffffffffffff919091166000908152600960209081526040808320938352929052205467ffffffffffffffff80821692680100000000000000009092041690565b600060075460001415611cc357611cbc8261271063ffffffff61378916565b9050610cd9565b610b67600754611ce1611cd4610cde565b859063ffffffff61372916565b9063ffffffff61378916565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b60065473ffffffffffffffffffffffffffffffffffffffff16611d7f576040805162461bcd60e51b815260206004820152601f60248201527f7468652061756374696f6e20636f6e7472616374206973206e6f742073657400604482015290519081900360640190fd5b60065473ffffffffffffffffffffffffffffffffffffffff163314611dd55760405162461bcd60e51b81526004018080602001828103825260238152602001806148ba6023913960400191505060405180910390fd5b611ddf828261438a565b5050565b60075490565b600082630bebc200811115611dff5750630bebc2005b626ebe008310611e13576001915050611592565b6000611e3584611e29848063ffffffff61372916565b9063ffffffff61372916565b905066072ba304f800008104600080611e4d83612c37565b915091506000611e5c8b6144c6565b90506000611e698b6144c6565b90506000611e8d611e80858463ffffffff61452616565b849063ffffffff61460916565b90506000611eb383611ea781818c8b63ffffffff61452616565b9063ffffffff61452616565b905060008083131580611ee2575081611edf680118188ff217800000611ea7868063ffffffff61452616565b13155b9f9e505050505050505050505050505050565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610b455780601f10610b1a57610100808354040283529160200191610b45565b6040805160208082019490945260c09290921b7fffffffffffffffff00000000000000000000000000000000000000000000000016828201527f6c69656e0000000000000000000000000000000000000000000000000000000060488301528051808303602c018152604c9092019052805191012090565b6000610b63611ff96133d3565b84610d7c85604051806060016040528060258152602001614b6660259139600160006120236133d3565b73ffffffffffffffffffffffffffffffffffffffff908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff61369216565b6000610b636120746133d3565b84846134ea565b60065460009073ffffffffffffffffffffffffffffffffffffffff166120e8576040805162461bcd60e51b815260206004820152601f60248201527f7468652061756374696f6e20636f6e7472616374206973206e6f742073657400604482015290519081900360640190fd5b60008060007f0000000000000000000000008b24f5c764ab741bc8a2426505bda458c30df01073ffffffffffffffffffffffffffffffffffffffff166326d6c97b866040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b15801561215e57600080fd5b505afa158015612172573d6000803e3d6000fd5b505050506040513d608081101561218857600080fd5b5080516020820151604090920151909450909250905073ffffffffffffffffffffffffffffffffffffffff8316612206576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b67ffffffffffffffff811661224c5760405162461bcd60e51b815260040180806020018281038252602a815260200180614752602a913960400191505060405180910390fd5b7f000000000000000000000000000000000000000000000000000000000003f480612275613ca7565b0182116122b35760405162461bcd60e51b815260040180806020018281038252603c81526020018061479e603c913960400191505060405180910390fd5b620186a067ffffffffffffffff82160667ffffffffffffffff1660001461230b5760405162461bcd60e51b8152600401808060200182810382526022815260200180614b446022913960400191505060405180910390fd5b600654604080517fecfb314d00000000000000000000000000000000000000000000000000000000815260048101889052905160009273ffffffffffffffffffffffffffffffffffffffff169163ecfb314d916024808301926020929190829003018186803b15801561237d57600080fd5b505afa158015612391573d6000803e3d6000fd5b505050506040513d60208110156123a757600080fd5b5051600654604080517f9737d6fd00000000000000000000000000000000000000000000000000000000815260048101849052905192935073ffffffffffffffffffffffffffffffffffffffff90911691639737d6fd91602480820192602092909190829003018186803b15801561241e57600080fd5b505afa158015612432573d6000803e3d6000fd5b505050506040513d602081101561244857600080fd5b505167ffffffffffffffff16156124a6576040805162461bcd60e51b815260206004820152601860248201527f7468697320534254206973206f6e20612061756369746f6e0000000000000000604482015290519081900360640190fd5b6000806124b1613b68565b9150915060006124d6838667ffffffffffffffff16846124cf613ca7565b8a03612a9a565b604080518215815290519192508a917fea0241146eaea8e64956684a8df42cc134671b71fcc2b474bcbd63f30b32984f9181900360200190a21598975050505050505050565b60008061252884610cb2565b90506000807f0000000000000000000000008b24f5c764ab741bc8a2426505bda458c30df01073ffffffffffffffffffffffffffffffffffffffff166326d6c97b876040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b15801561259e57600080fd5b505afa1580156125b2573d6000803e3d6000fd5b505050506040513d60808110156125c857600080fd5b50805160409091015190925067ffffffffffffffff16905073ffffffffffffffffffffffffffffffffffffffff8216612648576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b8061269a576040805162461bcd60e51b815260206004820152601f60248201527f74686520626f6e64206973206e6f742074686520666f726d206f662053425400604482015290519081900360640190fd5b6126a2614707565b506000838152600a602090815260408083208151608081018352905467ffffffffffffffff808216835268010000000000000000820481168386015270010000000000000000000000000000000082048116838501527801000000000000000000000000000000000000000000000000909104166060808301919091528251908101909252603d808352909392612790926110d492879261487d9083013961278361274b610cde565b6040518060600160405280602c8152602001614822602c91396127836007548f67ffffffffffffffff1661372990919063ffffffff16565b919063ffffffff61466e16565b90506127c06110d48867ffffffffffffffff16846060015167ffffffffffffffff166137cb90919063ffffffff16565b67ffffffffffffffff90811660608401526127de903390891661438a565b604080517fa9059cbb00000000000000000000000000000000000000000000000000000000815233600482015267ffffffffffffffff831660248201529051859173ffffffffffffffffffffffffffffffffffffffff83169163a9059cbb916044808201926020929091908290030181600087803b15801561285f57600080fd5b505af1158015612873573d6000803e3d6000fd5b505050506040513d602081101561288957600080fd5b50506040805167ffffffffffffffff808b16825284166020820152815133928c927f87efbe374e86e4f26b4593306372ef7f3c1fa4ed256c9d4f7400d00b3f729114929081900390910190a36129016128f267ffffffffffffffff84168663ffffffff61372916565b6007549063ffffffff61387216565b6007558251612928906110d49067ffffffffffffffff90811690851663ffffffff61387216565b67ffffffffffffffff90811684526020840151612953916110d491811690851663ffffffff6137cb16565b67ffffffffffffffff90811660208086019182526000988952600a905260409788902085518154925199870151606090970151841678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff978516700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff9b861668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff939096167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009095169490941791909116939093179890981617939093169290921790945550919250505092915050565b60086020526000908152604090205467ffffffffffffffff1681565b6000610b67823361140b565b60006002850261c3508502108015612ab457506212750082105b15612ac157506000611592565b630bebc200831115612ad557506001611592565b626ebe008210612ae757506001611592565b6000612afd83611e29868063ffffffff61372916565b905066072ba304f800008104600080612b1583612c37565b915091506000612b248a6144c6565b90506000612b318a6144c6565b90506000612b6a612b4d6003611ea7878663ffffffff61452616565b612b5e85600263ffffffff61452616565b9063ffffffff61460916565b90506000612b876009611ea7858181818e8d63ffffffff61452616565b905060008083131580612bb6575081612bb3680118188ff217800000611ea7868063ffffffff61452616565b13155b9e9d5050505050505050505050505050565b600960209081526000928352604080842090915290825290205467ffffffffffffffff808216916801000000000000000090041682565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b60008062c320408311612c51575060009050612af8612d98565b630394b7b18311612c6a5750615a4090506115bc612d98565b6307f7cae48311612ca257506206400090507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81fc612d98565b630bf379008311612cda5750621f126990507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1e88612d98565b630fc0bf018311612d12575062817ac190507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffae894612d98565b63134fd9008311612d4b57506301af0c8990507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4f33b612d98565b6040805162461bcd60e51b815260206004820152600e60248201527f6e6f742061636365707461626c65000000000000000000000000000000000000604482015290519081900360640190fd5b915091565b60065473ffffffffffffffffffffffffffffffffffffffff16612e07576040805162461bcd60e51b815260206004820152601f60248201527f7468652061756374696f6e20636f6e7472616374206973206e6f742073657400604482015290519081900360640190fd5b6000612e1282610cb2565b905060008060007f0000000000000000000000008b24f5c764ab741bc8a2426505bda458c30df01073ffffffffffffffffffffffffffffffffffffffff166326d6c97b866040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b158015612e8a57600080fd5b505afa158015612e9e573d6000803e3d6000fd5b505050506040513d6080811015612eb457600080fd5b5080516020820151604090920151909450909250905073ffffffffffffffffffffffffffffffffffffffff8316612f32576040805162461bcd60e51b815260206004820152601a60248201527f74686520626f6e64206973206e6f742072656769737465726564000000000000604482015290519081900360640190fd5b67ffffffffffffffff8116612f8e576040805162461bcd60e51b815260206004820152601f60248201527f74686520626f6e64206973206e6f742074686520666f726d206f662053425400604482015290519081900360640190fd5b7f000000000000000000000000000000000000000000000000000000000003f480612fb7613ca7565b01821115612ff65760405162461bcd60e51b815260040180806020018281038252602e815260200180614ac8602e913960400191505060405180910390fd5b6000613000614707565b50506000848152600a60209081526040918290208251608081018452905467ffffffffffffffff808216808452680100000000000000008304821694840194909452700100000000000000000000000000000000820481169483019490945278010000000000000000000000000000000000000000000000009004909216606083015290816130b657604081015167ffffffffffffffff16156130ab576130ab876000806001613cab565b505050505050610a98565b506000858152600a6020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001690557f0000000000000000000000000000000000000000000000000000000000015f90613114613ca7565b0183116131d857600654604080517f9da326ef0000000000000000000000000000000000000000000000000000000081526004810189905267ffffffffffffffff8416602482015260016044820152905173ffffffffffffffffffffffffffffffffffffffff90921691639da326ef916064808201926020929091908290030181600087803b1580156131a657600080fd5b505af11580156131ba573d6000803e3d6000fd5b505050506040513d60208110156131d057600080fd5b506132939050565b600654604080517f9da326ef0000000000000000000000000000000000000000000000000000000081526004810189905267ffffffffffffffff84166024820152600060448201819052915173ffffffffffffffffffffffffffffffffffffffff90931692639da326ef92606480840193602093929083900390910190829087803b15801561326657600080fd5b505af115801561327a573d6000803e3d6000fd5b505050506040513d602081101561329057600080fd5b50505b600654604080517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff928316600482015267ffffffffffffffff841660248201529051869283169163a9059cbb9160448083019260209291908290030181600087803b15801561331857600080fd5b505af115801561332c573d6000803e3d6000fd5b505050506040513d602081101561334257600080fd5b505050505050505050565b7f00000000000000000000000039a5bbc3f5536d7a9f40acfcb34738ff29540f4973ffffffffffffffffffffffffffffffffffffffff90811691161490565b600680547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b3390565b73ffffffffffffffffffffffffffffffffffffffff83166134295760405162461bcd60e51b8152600401808060200182810382526024815260200180614a7c6024913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821661347b5760405162461bcd60e51b81526004018080602001828103825260228152602001806147da6022913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b73ffffffffffffffffffffffffffffffffffffffff831661353c5760405162461bcd60e51b8152600401808060200182810382526025815260200180614a576025913960400191505060405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821661358e5760405162461bcd60e51b815260040180806020018281038252602381526020018061472f6023913960400191505060405180910390fd5b6135998383836146d3565b6135e9816040518060600160405280602681526020016147fc6026913973ffffffffffffffffffffffffffffffffffffffff8616600090815260208190526040902054919063ffffffff61369216565b73ffffffffffffffffffffffffffffffffffffffff808516600090815260208190526040808220939093559084168152205461362b908263ffffffff6137cb16565b73ffffffffffffffffffffffffffffffffffffffff8084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600081848411156137215760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156136e65781810151838201526020016136ce565b50505050905090810190601f1680156137135780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008261373857506000610b67565b8282028284828161374557fe5b04146137825760405162461bcd60e51b815260040180806020018281038252602181526020018061490b6021913960400191505060405180910390fd5b9392505050565b600061378283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061466e565b600082820183811015613782576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600068010000000000000000821061386e5760405162461bcd60e51b815260040180806020018281038252602681526020018061492c6026913960400191505060405180910390fd5b5090565b600061378283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613692565b73ffffffffffffffffffffffffffffffffffffffff821661391c576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b613928600083836146d3565b60025461393b908263ffffffff6137cb16565b60025573ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054613974908263ffffffff6137cb16565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b60006139e1614707565b506000838152600b60209081526040918290208251608081018452905467ffffffffffffffff80821683526801000000000000000082048116938301939093527001000000000000000000000000000000008104909216928101929092527801000000000000000000000000000000000000000000000000900460ff16151560608201819052613a75576000915050610b67565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260096020818152604080842088855290915280832080547fffffffffffffffffffffffffffffffff0000000000000000000000000000000081169091559084015167ffffffffffffffff808316946801000000000000000090930481169391169190613afe908590613729565b613b166305f5e100611ce1858763ffffffff61372916565b1115613b4957613b2d84600963ffffffff61372916565b613b456305f5e100611ce1858763ffffffff61372916565b0390505b613b5c6110d4828663ffffffff6146d816565b98975050505050505050565b600080600560019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a3e6ba946040518163ffffffff1660e01b8152600401602060405180830381600087803b158015613bd557600080fd5b505af1158015613be9573d6000803e3d6000fd5b505050506040513d6020811015613bff57600080fd5b5051600554604080517f3af2888b000000000000000000000000000000000000000000000000000000008152905192945061010090910473ffffffffffffffffffffffffffffffffffffffff1691633af2888b916004808201926020929091908290030181600087803b158015613c7557600080fd5b505af1158015613c89573d6000803e3d6000fd5b505050506040513d6020811015613c9f57600080fd5b505190509091565b4290565b6000613cb685610cb2565b9050613cc0614707565b506000818152600b60209081526040918290208251608081018452905467ffffffffffffffff80821680845268010000000000000000830482169484019490945270010000000000000000000000000000000082048116948301949094527801000000000000000000000000000000000000000000000000900460ff161515606082015291613d54916110d49187166137cb565b67ffffffffffffffff90811682526020820151613d7f916110d491811690881663ffffffff6137cb16565b67ffffffffffffffff166020820152821561427257613d9c614707565b506000828152600a602090815260408083208151608081018352905467ffffffffffffffff8082168352680100000000000000008204811694830194909452700100000000000000000000000000000000810484169282018390527801000000000000000000000000000000000000000000000000900490921660608301529091908190613e3190600963ffffffff61372916565b90506000613e5682856040015167ffffffffffffffff166137cb90919063ffffffff16565b90506000613e89866020015167ffffffffffffffff16866060015167ffffffffffffffff166137cb90919063ffffffff16565b905082811115613ee957808210613ec1576060850151613eba90839067ffffffffffffffff1663ffffffff61387216565b9350613ee4565b6060850151613ee190829067ffffffffffffffff1663ffffffff61387216565b93505b613f1b565b613f18866020015167ffffffffffffffff16866040015167ffffffffffffffff166137cb90919063ffffffff16565b93505b50505060007f0000000000000000000000008b24f5c764ab741bc8a2426505bda458c30df01073ffffffffffffffffffffffffffffffffffffffff166326d6c97b8a6040518263ffffffff1660e01b81526004018082815260200191505060806040518083038186803b158015613f9157600080fd5b505afa158015613fa5573d6000803e3d6000fd5b505050506040513d6080811015613fbb57600080fd5b50604001519050613fcc308361438a565b613ffe6110d4856020015167ffffffffffffffff16856060015167ffffffffffffffff166137cb90919063ffffffff16565b67ffffffffffffffff9081166060850152845161402e9161402991811690841663ffffffff61372916565b6146ee565b83516020840151614056916110d49167ffffffffffffffff908116911663ffffffff6137cb16565b67ffffffffffffffff166020808501829052604080516060810190915260388082526140ae936110d493909291906149c49083013960608701516127839067ffffffffffffffff166305f5e10063ffffffff61372916565b67ffffffffffffffff90811660408087019190915260016060870181905260008c8152600860205291909120546140f1926110d49291169063ffffffff6137cb16565b60008a8152600860209081526040808320805467ffffffffffffffff9586167fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000091821617909155898452600a835281842088518154948a0151938a015160608b0151881678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff918916700100000000000000000000000000000000027fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff968a1668010000000000000000027fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff94909a169790951696909617919091169690961792909216179390931617909155614218610cde565b604080870151600754825167ffffffffffffffff90921682526020820184905281830152905191925087917fc96942e0138bef71dbf15b3512ad2970a8a07aeea02f0c50a94d373906dbf4cb9181900360600190a2505050505b6000918252600b60209081526040928390208251815492840151948401516060909401517fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000090931667ffffffffffffffff918216177fffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff166801000000000000000095821695909502949094177fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000009490931693909302919091177fffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffff1678010000000000000000000000000000000000000000000000009115159190910217905550505050565b73ffffffffffffffffffffffffffffffffffffffff82166143dc5760405162461bcd60e51b81526004018080602001828103825260218152602001806149fc6021913960400191505060405180910390fd5b6143e8826000836146d3565b6144388160405180606001604052806022815260200161477c6022913973ffffffffffffffffffffffffffffffffffffffff8516600090815260208190526040902054919063ffffffff61369216565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040902055600254614471908263ffffffff61387216565b60025560408051828152905160009173ffffffffffffffffffffffffffffffffffffffff8516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b60007f8000000000000000000000000000000000000000000000000000000000000000821061386e5760405162461bcd60e51b8152600401808060200182810382526028815260200180614aa06028913960400191505060405180910390fd5b60008261453557506000610b67565b827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14801561458357507f800000000000000000000000000000000000000000000000000000000000000082145b156145bf5760405162461bcd60e51b815260040180806020018281038252602781526020018061497a6027913960400191505060405180910390fd5b828202828482816145cc57fe5b05146137825760405162461bcd60e51b815260040180806020018281038252602781526020018061497a6027913960400191505060405180910390fd5b600081830381831280159061461e5750838113155b80614633575060008312801561463357508381135b6137825760405162461bcd60e51b8152600401808060200182810382526024815260200180614b206024913960400191505060405180910390fd5b600081836146bd5760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156136e65781810151838201526020016136ce565b5060008385816146c957fe5b0495945050505050565b505050565b60008183106146e75781613782565b5090919050565b600754614701908263ffffffff61387216565b60075550565b6040805160808101825260008082526020820181905291810182905260608101919091529056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737374686520626f6e6420646f6573206e6f74206d6174636820746f2074686520666f726d206f662053425445524332303a206275726e20616d6f756e7420657863656564732062616c616e636561207265717565737420746f20686f6c6420616e2061756374696f6e206f662074686520626f6e642068617320616c7265616479206578706972656445524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636573797374656d206572726f723a20746f74616c537570706c79206e65766572206265636f6d6573207a65726f53425420776974682074686520626f6e644944206973206e6f742063757272656e746c792061636365707461626c6573797374656d206572726f723a20736f6c6964537472696b655072696365206e65766572206265636f6d6573207a65726f205b756e6c6f636b5342545d6d73672e73656e646572206d7573742062652061756374696f6e20636f6e74726163746f6e6c79206465706c6f79657220697320616c6c6f77656420746f2063616c6c20746869732066756e6374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7753616665436173743a2076616c756520646f65736e27742066697420696e203634206269747345524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63655369676e6564536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77636f6e74726163742073686f756c64206265206e6f6e2d7a65726f206164647265737373797374656d3a2074686520746f74616c20756e6c6f636b20616d6f756e742073686f756c64206265206e6f6e2d7a65726f2076616c756545524332303a206275726e2066726f6d20746865207a65726f20616464726573736d696e7420616d6f756e74206e65656420746f2062652067726561746572207468616e203530302069646f6c20666f72207468697320626f6e6445524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737353616665436173743a2076616c756520646f65736e27742066697420696e20616e20696e743235366d61747572697479206973206c61746572207468616e2074686520726567756c61722061756374696f6e5370616e7468652061756374696f6e20636f6e747261637420697320616c726561647920726567697374657265645369676e6564536166654d6174683a207375627472616374696f6e206f766572666c6f7774686520737472696b65207072696365206e65656420746f20626520242031302a5845524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220d085672f8467497f59973194f9b1d4d97c7592939b63afb78bc9add4e0e727e664736f6c63430006060033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000120a078fdc516a1a98bbecb9e961f8741ac7ac820000000000000000000000008b24f5c764ab741bc8a2426505bda458c30df010000000000000000000000000000000000000000000000000000000000003f4800000000000000000000000000000000000000000000000000000000000015f900000000000000000000000000000000000000000000000000000000ba43b7400
-----Decoded View---------------
Arg [0] : oracleAddress (address): 0x120a078FdC516A1A98bbecb9e961F8741AC7ac82
Arg [1] : bondMakerAddress (address): 0x8B24F5C764AB741Bc8a2426505BDa458C30dF010
Arg [2] : auctionSpan (uint256): 259200
Arg [3] : emergencyAuctionSpan (uint256): 90000
Arg [4] : mintIDOLAmountBorder (uint256): 50000000000
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000120a078fdc516a1a98bbecb9e961f8741ac7ac82
Arg [1] : 0000000000000000000000008b24f5c764ab741bc8a2426505bda458c30df010
Arg [2] : 000000000000000000000000000000000000000000000000000000000003f480
Arg [3] : 0000000000000000000000000000000000000000000000000000000000015f90
Arg [4] : 0000000000000000000000000000000000000000000000000000000ba43b7400
Deployed Bytecode Sourcemap
100095:28022:0:-:0;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;100095:28022:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;99488:395:0;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;99488:395:0;;;;:::i;:::-;;24899:83;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;24899:83:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27005:169;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;27005:169:0;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;110080:1293;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;110080:1293:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;111720:262;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;111720:262:0;;:::i;:::-;;;;;;;;;;;;;;;;25974:100;;;:::i;27648:321::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;27648:321:0;;;;;;;;;;;;;;;;;;:::i;114254:2635::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;114254:2635:0;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25826:83;;;:::i;:::-;;;;;;;;;;;;;;;;;;;28378:218;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;28378:218:0;;;;;;;;;:::i;127132:792::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;127132:792:0;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;127132:792:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;127132:792:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;127132:792:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;127132:792:0;;-1:-1:-1;;;127132:792:0;;;;;-1:-1:-1;127132:792:0;;-1:-1:-1;127132:792:0:i;:::-;;;;;;;;;;;;;;;;;;;122626:1817;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;122626:1817:0;;:::i;124607:640::-;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;124607:640:0;;;;;;;;;;;;;;;;;;;;;;;;;:::i;111990:284::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;111990:284:0;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;125445:333;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;125445:333:0;;:::i;26137:119::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;26137:119:0;;;;:::i;117033:301::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;117033:301:0;;;;;;;;;:::i;111381:113::-;;;:::i;37553:1063::-;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;37553:1063:0;;;;;;;;;;;;;;;;;:::i;25101:87::-;;;:::i;111502:210::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;111502:210:0;;;;;;;;;:::i;29099:269::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;29099:269:0;;;;;;;;;:::i;26469:175::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;26469:175:0;;;;;;;;;:::i;112661:1410::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;112661:1410:0;;:::i;118286:2051::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;118286:2051:0;;;;;;;;;:::i;100816:53::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;100816:53:0;;:::i;127932:182::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;127932:182:0;;;;;;;;27:11:-1;11:28;;8:2;;;52:1;49;42:12;8:2;127932:182:0;;41:9:-1;34:4;18:14;14:25;11:40;8:2;;;64:1;61;54:12;8:2;127932:182:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;39:11;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;127932:182:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;127932:182:0;;-1:-1:-1;127932:182:0;;-1:-1:-1;;;;;127932:182:0:i;39119:1780::-;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;39119:1780:0;;;;;;;;;;;;;;;;;:::i;101191:70::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;101191:70:0;;;;;;;;;:::i;26707:151::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;26707:151:0;;;;;;;;;;;:::i;36483:703::-;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;36483:703:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;120431:1914;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;120431:1914:0;;:::i;99488:395::-;98724:23;98736:10;98724:11;:23::i;:::-;98702:119;;;;-1:-1:-1;;;98702:119:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;99602:16:::1;::::0;99594:39:::1;99602:16;99594:39:::0;99572:131:::1;;;;-1:-1:-1::0;;;99572:131:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;99736:29;::::0;::::1;99714:114;;;;-1:-1:-1::0;;;99714:114:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;99839:36;99859:15;99839:19;:36::i;:::-;99488:395:::0;:::o;24899:83::-;24969:5;24962:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24936:13;;24962:12;;24969:5;;24962:12;;24969:5;24962:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24899:83;:::o;27005:169::-;27088:4;27105:39;27114:12;:10;:12::i;:::-;27128:7;27137:6;27105:8;:39::i;:::-;-1:-1:-1;27162:4:0;27005:169;;;;;:::o;110080:1293::-;110199:21;110235:23;110273:26;110314:22;110351:28;110394:29;110438:33;110486:29;110549:41;;:::i;:::-;-1:-1:-1;110603:28:0;;;;:20;:28;;;;;;;;;110549:82;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;110549:82:0;;-1:-1:-1;110549:82:0;;-1:-1:-1;110549:82:0;-1:-1:-1;110918:46:0;;:::i;:::-;-1:-1:-1;;;110977:26:0;;;;-1:-1:-1;;110977:18:0;:26;;;;;;;;;110918:85;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;110080:1293;;;;;;;;110918:85;;;;;;-1:-1:-1;110918:85:0;110080:1293::o;111720:262::-;111828:7;111884:27;;;:19;:27;;;;;;;;111929:45;111904:6;111884:27;111929:14;:45::i;:::-;111922:52;;;111720:262;;;;:::o;25974:100::-;26054:12;;25974:100;:::o;27648:321::-;27754:4;27771:36;27781:6;27789:9;27800:6;27771:9;:36::i;:::-;27818:121;27827:6;27835:12;:10;:12::i;:::-;27849:89;27887:6;27849:89;;;;;;;;;;;;;;;;;:19;;;;;;;:11;:19;;;;;;27869:12;:10;:12::i;:::-;27849:33;;;;;;;;;;;;;-1:-1:-1;27849:33:0;;;:89;;:37;:89;:::i;:::-;27818:8;:121::i;:::-;-1:-1:-1;27957:4:0;27648:321;;;;;:::o;114254:2635::-;114424:14;114453:25;114493:23;114553:24;114570:6;114553:16;:24::i;:::-;114544:33;;114686:24;114740:26;114783:18;:26;;;114810:6;114783:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;114783:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;114783:34:0;;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;114783:34:0;;;;;;;;;-1:-1:-1;114671:146:0;;;-1:-1:-1;114850:23:0;114866:6;114850:15;:23::i;:::-;114828:120;;;;-1:-1:-1;;;114828:120:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;114967:41;;:::i;:::-;-1:-1:-1;115021:28:0;;;;:20;:28;;;;;;;;114967:82;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;115021:28;115157:36;;:16;;115174:18;115157:36;:16;:36;:::i;:::-;115129:64;;115204:20;115227:31;115240:17;115227:12;:31::i;:::-;115204:54;;115291:14;:36;;;:41;;115331:1;115291:41;;:101;;;;115369:23;115353:12;:39;;115291:101;115269:209;;;;-1:-1:-1;;;115269:209:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;115551:71;;;;;;115582:10;115551:71;;;;115602:4;115551:71;;;;;;;;;;;;;115523:16;;115551:30;;;;;;:71;;;;;;;;;;;;;;;115491:23;115551:30;:71;;;2:2:-1;;;;27:1;24;17:12;2:2;115551:71:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;115551:71:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;115723:18:0;;-1:-1:-1;115744:20:0;:12;115761:2;115744:20;:16;:20;:::i;:::-;115811:23;;;115775:33;115811:23;;;:12;:23;;;;;;;;:31;;;;;;;;115881:39;;115723:41;;-1:-1:-1;115811:31:0;115881:94;;:69;;:39;;115723:41;115881:69;:57;:69;:::i;:::-;:92;:94::i;:::-;115853:122;;;;;;;;;;;;116017:99;;:74;;:42;;;;;;:74;;:60;:74::i;:99::-;115986:130;;;;;;;;;;;;;;;;116129:46;116135:9;116146:28;:12;116163:10;116146:28;:16;:28;:::i;:::-;116129:5;:46::i;:::-;116186:32;116200:4;116207:10;116186:5;:32::i;:::-;116251:19;;:42;;116275:17;116251:42;:23;:42;:::i;:::-;116229:19;:64;116344:51;;:108;;:83;;;:69;;;;:83;;;:69;:83;:::i;:108::-;116304:148;;;;;;116502:50;;;;:105;;:80;;:68;116571:10;116502:80;:68;:80;:::i;:105::-;116463:144;;;;:36;;;;:144;;;116618:28;;;;:20;:28;;;;;;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;116699:28;:12;116716:10;116699:28;:16;:28;:::i;:::-;116676:51;;116763:9;116743:64;;116755:6;116743:64;116774:6;116782:12;116796:10;116743:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;116826:6;116834:23;:12;:21;:23::i;:::-;116859:21;:10;:19;:21::i;:::-;116818:63;;;;;;;;;;;;;;;114254:2635;;;;;;;:::o;25826:83::-;25892:9;;;;25826:83;:::o;28378:218::-;28466:4;28483:83;28492:12;:10;:12::i;:::-;28506:7;28515:50;28554:10;28515:11;:25;28527:12;:10;:12::i;:::-;28515:25;;;;;;;;;;;;;;;;;;-1:-1:-1;28515:25:0;;;:34;;;;;;;;;;;:50;:38;:50;:::i;127132:792::-;127255:6;;;127321:490;127345:7;:14;127341:1;:18;127321:490;;;127469:21;127493:95;127537:7;127545:1;127537:10;;;;;;;;;;;;;;127566:7;127493:25;:95::i;:::-;127469:119;-1:-1:-1;127625:39:0;:19;:39;;;;:23;:39;:::i;:::-;127603:61;-1:-1:-1;127683:19:0;;;;127679:121;;127760:7;127728:56;;127748:7;127756:1;127748:10;;;;;;;;;;;;;;127728:56;127769:14;127728:56;;;;;;;;;;;;;;;;;;;;;;127679:121;-1:-1:-1;127361:3:0;;127321:490;;;-1:-1:-1;127823:43:0;;;;;;:13;:43;;;;;;;;;;;;;;:4;;:13;;:43;;;;;;;;;;;;;;-1:-1:-1;127823:4:0;:43;;;2:2:-1;;;;27:1;24;17:12;2:2;127823:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;127823:43:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;127886:30:0;;-1:-1:-1;127886:19:0;:28;:30::i;:::-;127879:37;127132:792;-1:-1:-1;;;;127132:792:0:o;122626:1817::-;99268:16;;99260:39;99268:16;99238:120;;;;;-1:-1:-1;;;99238:120:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;122757:14:::1;122774:24;122791:6;122774:16;:24::i;:::-;122757:41;;122824:24;122863:16:::0;122894:30:::1;122941:18;:26;;;122968:6;122941:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;122941:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;122941:34:0;;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29::::0;22:12:::1;4:2;-1:-1:::0;122941:34:0;;::::1;::::0;::::1;::::0;;;;;;;;-1:-1:-1;122941:34:0;;-1:-1:-1;122941:34:0;-1:-1:-1;122994:30:0::1;::::0;::::1;122986:69;;;::::0;;-1:-1:-1;;;122986:69:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;123088:28;::::0;::::1;123066:109;;;::::0;;-1:-1:-1;;;123066:109:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;123189:19;123210:18:::0;123232:16:::1;:14;:16::i;:::-;123188:60;;;;123259:13;123275:162;123303:11;123329:23;123275:162;;123367:10;123403:23;:21;:23::i;:::-;123392:8;:34;123275:13;:162::i;:::-;123259:178;;123456:8;123448:48;;;::::0;;-1:-1:-1;;;123448:48:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;123509:29;123570:41;;:::i;:::-;-1:-1:-1::0;;123628:28:0::1;::::0;;;:20:::1;:28;::::0;;;;;;;;123570:86;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;;;;;;;::::1;::::0;;::::1;::::0;;;;;123752:27;123748:232:::1;;123804:36;::::0;::::1;::::0;:41:::1;;::::0;123800:140:::1;;123870:50;123901:6;123909:1;123912::::0;123915:4:::1;123870:30;:50::i;:::-;123958:7;;;;;;;;;;;123748:232;-1:-1:-1::0;124001:28:0::1;::::0;;;:20:::1;:28;::::0;;;;;;;123994:58;;;::::1;::::0;;124076:16:::1;::::0;:67;;;;;::::1;::::0;::::1;::::0;;;123994:58:::1;124076:67:::0;::::1;::::0;;;;123994:58;124076:67;;;;;;:16:::1;::::0;;::::1;::::0;:29:::1;::::0;:67;;;;;124001:28;;124076:67;;;;;;;;;:16;:67;::::1;;2:2:-1::0;::::1;;;27:1;24::::0;17:12:::1;2:2;124076:67:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;124076:67:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::1;4:2;-1:-1:::0;;124370:16:0::1;::::0;124321:114:::1;::::0;;;;;:26:::1;124370:16:::0;;::::1;124321:114;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;;;;124282:16;;124321:26;::::1;::::0;::::1;::::0;:114;;;;;124076:67:::1;::::0;124321:114;;;;;;;124202:36:::1;124321:26:::0;:114;::::1;;2:2:-1::0;::::1;;;27:1;24::::0;17:12:::1;2:2;124321:114:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;124321:114:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::1;4:2;-1:-1:::0;;;;;;;;;;;122626:1817:0;:::o;124607:640::-;99268:16;;99260:39;99268:16;99238:120;;;;;-1:-1:-1;;;99238:120:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;124855:16:::1;::::0;::::1;;124833:10;:39;124811:124;;;;-1:-1:-1::0;;;124811:124:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;124953:24;124983:18;:26;;;125010:6;124983:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;124983:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;124983:34:0;;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29::::0;22:12:::1;4:2;-1:-1:::0;124983:34:0;;;124948:69:::1;;::::0;-1:-1:-1;125036:21:0;125028:65:::1;;;::::0;;-1:-1:-1;;;125028:65:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;125104:135;125149:6;125170:13;125198:9;125222:6;125104:30;:135::i;:::-;99369:1;124607:640:::0;;;;:::o;111990:284::-;112163:18;;;;;112109:6;112163:18;;;:12;:18;;;;;;;;:26;;;;;;;:37;;;;;;112215:40;;;;;;111990:284::o;125445:333::-;125560:20;125602:19;;125625:1;125602:24;125598:92;;;125650:28;:17;125672:5;125650:28;:21;:28;:::i;:::-;125643:35;;;;125598:92;125709:61;125750:19;;125709:36;125731:13;:11;:13::i;:::-;125709:17;;:36;:21;:36;:::i;:::-;:40;:61;:40;:61;:::i;26137:119::-;26230:18;;26203:7;26230:18;;;;;;;;;;;;26137:119::o;117033:301::-;99268:16;;99260:39;99268:16;99238:120;;;;;-1:-1:-1;;;99238:120:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;117213:16:::1;::::0;::::1;;117191:10;:39;117169:124;;;;-1:-1:-1::0;;;117169:124:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;117304:22;117310:7;117319:6;117304:5;:22::i;:::-;117033:301:::0;;:::o;111381:113::-;111467:19;;111381:113;:::o;37553:1063::-;37734:4;37765:10;37796:9;37790:15;;37786:94;;;-1:-1:-1;37828:9:0;37786:94;37911:8;37894:13;:25;37890:111;;37943:4;37936:11;;;;;37890:111;38011:14;38028:31;38045:13;38028:12;38036:3;;38028:12;:7;:12;:::i;:::-;:16;:31;:16;:31;:::i;:::-;38011:48;-1:-1:-1;38097:24:0;38087:35;;38072:12;;38196:28;38087:35;38196:22;:28::i;:::-;38168:56;;;;38235:10;38248:22;:11;:20;:22::i;:::-;38235:35;;38281:10;38294:31;:20;:29;:31::i;:::-;38281:44;-1:-1:-1;38336:10:0;38349:21;38357:12;:3;38281:44;38357:12;:7;:12;:::i;:::-;38349:3;;:21;:7;:21;:::i;:::-;38336:34;-1:-1:-1;38444:11:0;38458:42;38496:3;38458:33;38496:3;38458:33;38465:6;38477:4;38458:24;:18;:24;:::i;:::-;:28;:33;:28;:33;:::i;:42::-;38444:56;;38511:13;38534:1;38527:3;:8;;:55;;;-1:-1:-1;38578:4:0;38539:35;38556:17;38539:12;38547:3;;38539:12;:7;:12;:::i;:35::-;:43;;38527:55;38511:71;37553:1063;-1:-1:-1;;;;;;;;;;;;;;;37553:1063:0:o;25101:87::-;25173:7;25166:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25140:13;;25166:14;;25173:7;;25166:14;;25173:7;25166:14;;;;;;;;;;;;;;;;;;;;;;;;111502:210;111664:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;111664:39:0;;;;;;111654:50;;;;;;111502:210::o;29099:269::-;29192:4;29209:129;29218:12;:10;:12::i;:::-;29232:7;29241:96;29280:15;29241:96;;;;;;;;;;;;;;;;;:11;:25;29253:12;:10;:12::i;:::-;29241:25;;;;;;;;;;;;;;;;;;-1:-1:-1;29241:25:0;;;:34;;;;;;;;;;;:96;;:38;:96;:::i;26469:175::-;26555:4;26572:42;26582:12;:10;:12::i;:::-;26596:9;26607:6;26572:9;:42::i;112661:1410::-;99268:16;;112806:4;;99260:39;99268:16;99238:120;;;;;-1:-1:-1;;;99238:120:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;112843:24:::1;112882:16:::0;112913:25:::1;112955:18;:26;;;112982:6;112955:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;112955:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;112955:34:0;;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29::::0;22:12:::1;4:2;-1:-1:::0;112955:34:0;;::::1;::::0;::::1;::::0;;;;;;;;-1:-1:-1;112955:34:0;;-1:-1:-1;112955:34:0;-1:-1:-1;113008:30:0::1;::::0;::::1;113000:69;;;::::0;;-1:-1:-1;;;113000:69:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;113102:23;::::0;::::1;113080:115;;;;-1:-1:-1::0;;;113080:115:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;113265:12;113239:23;:21;:23::i;:::-;:38;113228:8;:49;113206:159;;;;-1:-1:-1::0;;;113206:159:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;113420:5;113398:28;::::0;::::1;;:33;;113430:1;113398:33;113376:117;;;;-1:-1:-1::0;;;113376:117:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;113526:16;::::0;:44:::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;113506:17:::1;::::0;113526:16:::1;;::::0;:36:::1;::::0;:44;;;;;::::1;::::0;;;;;;;;:16;:44;::::1;;2:2:-1::0;::::1;;;27:1;24::::0;17:12:::1;2:2;113526:44:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;113526:44:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::1;4:2;-1:-1:::0;113526:44:0;113603:16:::1;::::0;:50:::1;::::0;;;;;::::1;::::0;::::1;::::0;;;;;113526:44;;-1:-1:-1;113603:16:0::1;::::0;;::::1;::::0;:39:::1;::::0;:50;;;;;113526:44:::1;::::0;113603:50;;;;;;;;:16;:50;::::1;;2:2:-1::0;::::1;;;27:1;24::::0;17:12:::1;2:2;113603:50:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;113603:50:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::1;4:2;-1:-1:::0;113603:50:0;:55:::1;;::::0;113581:129:::1;;;::::0;;-1:-1:-1;;;113581:129:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;113724:21;113747:20:::0;113771:16:::1;:14;:16::i;:::-;113723:64;;;;113798:13;113814:165;113846:13;113874:18;113814:165;;113907:12;113945:23;:21;:23::i;:::-;113934:8;:34;113814:17;:165::i;:::-;113997:37;::::0;;114024:9;::::1;113997:37:::0;;;;113798:181;;-1:-1:-1;114016:6:0;;113997:37:::1;::::0;;;;::::1;::::0;;::::1;114054:9;::::0;112661:1410;-1:-1:-1;;;;;;;;112661:1410:0:o;118286:2051::-;118394:6;118418:14;118435:24;118452:6;118435:16;:24::i;:::-;118418:41;;118485:24;118539:26;118582:18;:26;;;118609:6;118582:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;118582:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;118582:34:0;;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;118582:34:0;;;;;;;;;-1:-1:-1;118470:146:0;;;-1:-1:-1;118635:30:0;;;118627:69;;;;;-1:-1:-1;;;118627:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;118715:23;118707:67;;;;;-1:-1:-1;;;118707:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;118791:41;;:::i;:::-;-1:-1:-1;118845:28:0;;;;:20;:28;;;;;;;;118791:82;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;118907:272;;;;;;;;;;;;118791:82;;118845:28;118907:297;;:272;;119072:18;;118907:272;;;;;:132;118977:13;:11;:13::i;:::-;118907:132;;;;;;;;;;;;;;;;;:51;118938:19;;118907:12;:30;;;;:51;;;;:::i;:::-;:69;:132;;:69;:132;:::i;:297::-;118886:318;;119279:107;:82;119348:12;119279:82;;:14;:50;;;:68;;;;:82;;;;:::i;:107::-;119240:146;;;;:36;;;:146;119399:31;;119405:10;;119399:31;;:5;:31::i;:::-;119586:51;;;;;;119613:10;119586:51;;;;;;;;;;;;;119547:16;;119586:26;;;;;;:51;;;;;;;;;;;;;;;119467:36;119586:26;:51;;;2:2:-1;;;;27:1;24;17:12;2:2;119586:51:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;119586:51:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;;119655:58:0;;;;;;;;;;;119586:51;119655:58;;;;;119675:10;;119667:6;;119655:58;;;;;;;;;;;119836:84;119874:35;:15;;;119890:18;119874:35;:15;:35;:::i;:::-;119836:19;;;:84;:23;:84;:::i;:::-;119814:19;:106;119971:51;;:107;;:82;;;:69;;;;:82;;;:69;:82;:::i;:107::-;119931:147;;;;;;120131:53;;;;:109;;:84;;:71;;;:84;;;:71;:84;:::i;:109::-;120089:151;;;;:39;;;;:151;;;120253:28;;;;:20;:28;;;;;;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;120318:11:0;;-1:-1:-1;;;118286:2051:0;;;;:::o;100816:53::-;;;;;;;;;;;;;;;:::o;127932:182::-;128036:6;128067:39;128086:7;128095:10;128067:18;:39::i;39119:1780::-;39304:4;39388:1;39374:15;;39339:32;;;:50;:90;;;;;39422:7;39406:13;:23;39339:90;39321:262;;;-1:-1:-1;39463:5:0;39456:12;;39321:262;39503:9;39490:10;:22;39486:97;;;-1:-1:-1;39536:4:0;39529:11;;39486:97;39614:8;39597:13;:25;39593:111;;-1:-1:-1;39646:4:0;39639:11;;39593:111;39714:14;39731:45;39762:13;39731:26;39746:10;;39731:26;:14;:26;:::i;:45::-;39714:62;-1:-1:-1;39814:24:0;39804:35;;39789:12;;39913:28;39804:35;39913:22;:28::i;:::-;39885:56;;;;40497:10;40510:22;:11;:20;:22::i;:::-;40497:35;;40543:10;40556:31;:20;:29;:31::i;:::-;40543:44;-1:-1:-1;40598:10:0;40611:35;40626:19;40643:1;40626:12;:3;40543:44;40626:12;:7;:12;:::i;:19::-;40611:10;:3;40619:1;40611:10;:7;:10;:::i;:::-;:14;:35;:14;:35;:::i;:::-;40598:48;-1:-1:-1;40720:11:0;40734:49;40781:1;40734:42;40772:3;40734:42;40772:3;40734:42;40741:6;40753:4;40734:24;:18;:24;:::i;:49::-;40720:63;;40794:13;40817:1;40810:3;:8;;:55;;;-1:-1:-1;40861:4:0;40822:35;40839:17;40822:12;40830:3;;40822:12;:7;:12;:::i;:35::-;:43;;40810:55;40794:71;39119:1780;-1:-1:-1;;;;;;;;;;;;;;39119:1780:0:o;101191:70::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;26707:151::-;26823:18;;;;26796:7;26823:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;26707:151::o;36483:703::-;36577:11;36590:10;36630:11;36622:4;:19;36618:561;;-1:-1:-1;36666:1:0;;-1:-1:-1;36669:5:0;36658:17;;36618:561;36705:11;36697:4;:19;36693:486;;-1:-1:-1;36741:9:0;;-1:-1:-1;36752:4:0;36733:24;;36693:486;36787:13;36779:4;:21;36775:404;;-1:-1:-1;36825:9:0;;-1:-1:-1;36836:6:0;36817:26;;36775:404;36873:13;36865:4;:21;36861:318;;-1:-1:-1;36911:11:0;;-1:-1:-1;36924:7:0;36903:29;;36861:318;36962:13;36954:4;:21;36950:229;;-1:-1:-1;37000:11:0;;-1:-1:-1;37013:7:0;36992:29;;36950:229;37051:13;37043:4;:21;37039:140;;-1:-1:-1;37089:11:0;;-1:-1:-1;37102:7:0;37081:29;;37039:140;37143:24;;;-1:-1:-1;;;37143:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;37039:140;36483:703;;;:::o;120431:1914::-;99268:16;;99260:39;99268:16;99238:120;;;;;-1:-1:-1;;;99238:120:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;120564:14:::1;120581:24;120598:6;120581:16;:24::i;:::-;120564:41;;120631:24;120670:16:::0;120701:30:::1;120748:18;:26;;;120775:6;120748:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;120748:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;120748:34:0;;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29::::0;22:12:::1;4:2;-1:-1:::0;120748:34:0;;::::1;::::0;::::1;::::0;;;;;;;;-1:-1:-1;120748:34:0;;-1:-1:-1;120748:34:0;-1:-1:-1;120801:30:0::1;::::0;::::1;120793:69;;;::::0;;-1:-1:-1;;;120793:69:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;120895:28;::::0;::::1;120873:109;;;::::0;;-1:-1:-1;;;120873:109:0;;::::1;;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;;;;;;;;;::::1;;121053:12;121027:23;:21;:23::i;:::-;:38;121015:8;:50;;120993:146;;;;-1:-1:-1::0;;;120993:146:0::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;121152:29;121213:41;;:::i;:::-;-1:-1:-1::0;;121271:28:0::1;::::0;;;:20:::1;:28;::::0;;;;;;;;121213:86;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;;;;;;;::::1;::::0;;::::1;::::0;;;;;121395:27;121391:232:::1;;121447:36;::::0;::::1;::::0;:41:::1;;::::0;121443:140:::1;;121513:50;121544:6;121552:1;121555::::0;121558:4:::1;121513:30;:50::i;:::-;121601:7;;;;;;;;121391:232;-1:-1:-1::0;121644:28:0::1;::::0;;;:20:::1;:28;::::0;;;;121637:58;;;::::1;::::0;;121761:22:::1;121735:23;:21;:23::i;:::-;:48;121723:8;:60;121719:327;;121800:16;::::0;:67:::1;::::0;;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;;:16;:67;;;;;;:16:::1;::::0;;::::1;::::0;:29:::1;::::0;:67;;;;;::::1;::::0;;;;;;;;;:16:::1;::::0;:67;::::1;;2:2:-1::0;::::1;;;27:1;24::::0;17:12:::1;2:2;121800:67:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;121800:67:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::1;4:2;-1:-1:::0;121719:327:0::1;::::0;-1:-1:-1;121719:327:0::1;;121900:16;::::0;:134:::1;::::0;;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;::::1;::::0;;;;:16:::1;:134:::0;;;;;;;;:16:::1;::::0;;::::1;::::0;:29:::1;::::0;:134;;;;;::::1;::::0;;;;;;;;;;;;:16;:134;::::1;;2:2:-1::0;::::1;;;27:1;24::::0;17:12:::1;2:2;121900:134:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;121900:134:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::1;4:2;-1:-1:::0;;121719:327:0::1;122272:16;::::0;122223:114:::1;::::0;;;;;:26:::1;122272:16:::0;;::::1;122223:114;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;;;;122184:16;;122223:26;::::1;::::0;::::1;::::0;:114;;;;;::::1;::::0;;;;;;;;122104:36:::1;122223:26:::0;:114;::::1;;2:2:-1::0;::::1;;;27:1;24::::0;17:12:::1;2:2;122223:114:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;122223:114:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28::::0;21:12:::1;4:2;-1:-1:::0;;;;;;;;120431:1914:0;:::o;98919:113::-;99015:9;99004:20;;;;;;;;98919:113::o;99891:134::-;99965:16;:52;;;;;;;;;;;;;;;99891:134::o;19691:106::-;19779:10;19691:106;:::o;32246:346::-;32348:19;;;32340:68;;;;-1:-1:-1;;;32340:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32427:21;;;32419:68;;;;-1:-1:-1;;;32419:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32500:18;;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;32552:32;;;;;;;;;;;;;;;;;32246:346;;;:::o;29858:539::-;29964:20;;;29956:70;;;;-1:-1:-1;;;29956:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30045:23;;;30037:71;;;;-1:-1:-1;;;30037:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30121:47;30142:6;30150:9;30161:6;30121:20;:47::i;:::-;30201:71;30223:6;30201:71;;;;;;;;;;;;;;;;;:17;;;:9;:17;;;;;;;;;;;;:71;;:21;:71;:::i;:::-;30181:17;;;;:9;:17;;;;;;;;;;;:91;;;;30306:20;;;;;;;:32;;30331:6;30306:32;:24;:32;:::i;:::-;30283:20;;;;:9;:20;;;;;;;;;;;;:55;;;;30354:35;;;;;;;30283:20;;30354:35;;;;;;;;;;;;;29858:539;;;:::o;1801:192::-;1887:7;1923:12;1915:6;;;;1907:29;;;;-1:-1:-1;;;1907:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;1907:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1959:5:0;;;1801:192::o;2244:471::-;2302:7;2547:6;2543:47;;-1:-1:-1;2577:1:0;2570:8;;2543:47;2614:5;;;2618:1;2614;:5;:1;2638:5;;;;;:10;2630:56;;;;-1:-1:-1;;;2630:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2706:1;2244:471;-1:-1:-1;;;2244:471:0:o;3183:132::-;3241:7;3268:39;3272:1;3275;3268:39;;;;;;;;;;;;;;;;;:3;:39::i;914:181::-;972:7;1004:5;;;1028:6;;;;1020:46;;;;;-1:-1:-1;;;1020:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;8858:179;8914:6;8949:5;8941;:13;8933:65;;;;-1:-1:-1;;;8933:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9023:5:0;8858:179::o;1370:136::-;1428:7;1455:43;1459:1;1462;1455:43;;;;;;;;;;;;;;;;;:3;:43::i;30678:378::-;30762:21;;;30754:65;;;;;-1:-1:-1;;;30754:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;30832:49;30861:1;30865:7;30874:6;30832:20;:49::i;:::-;30909:12;;:24;;30926:6;30909:24;:16;:24;:::i;:::-;30894:12;:39;30965:18;;;:9;:18;;;;;;;;;;;:30;;30988:6;30965:30;:22;:30;:::i;:::-;30944:18;;;:9;:18;;;;;;;;;;;:51;;;;31011:37;;;;;;;30944:18;;:9;;31011:37;;;;;;;;;;30678:378;;:::o;125786:1168::-;125890:6;125914:36;;:::i;:::-;-1:-1:-1;125953:26:0;;;;:18;:26;;;;;;;;;125914:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;125990:78;;126055:1;126048:8;;;;;125990:78;126095:21;;;126080:12;126095:21;;;:12;:21;;;;;;;;:29;;;;;;;;;:40;;126219:36;;;;;;126297:38;;;;126095:40;;;;;126165:43;;;;;;;126268:67;;;126080:12;126720:26;;126095:40;;126720:8;:26::i;:::-;126661:43;126698:5;126661:32;:18;126684:8;126661:32;:22;:32;:::i;:43::-;:85;126643:257;;;126862:26;:4;100463:21;126862:26;:8;:26;:::i;:::-;126799:43;126836:5;126799:32;:18;126822:8;126799:32;:22;:32;:::i;:43::-;:89;126773:115;;126643:257;126919:27;:16;:6;126930:4;126919:16;:10;:16;:::i;:27::-;126912:34;125786:1168;-1:-1:-1;;;;;;;;125786:1168:0:o;62486:282::-;62548:21;62571:20;62625:15;;;;;;;;;;;:27;;;:29;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;62625:29:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;62625:29:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;62625:29:0;62680:15;;:31;;;;;;;;62625:29;;-1:-1:-1;62680:15:0;;;;;;;:29;;:31;;;;;62625:29;;62680:31;;;;;;;;;:15;:31;;;2:2:-1;;;;27:1;24;17:12;2:2;62680:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;62680:31:0;;;;;;;15:2:-1;10:3;7:11;4:2;;;31:1;28;21:12;4:2;-1:-1;62680:31:0;;-1:-1:-1;62486:282:0;;:::o;18709:194::-;18843:3;;18709:194::o;104167:5045::-;104353:14;104370:24;104387:6;104370:16;:24::i;:::-;104353:41;;104405:36;;:::i;:::-;-1:-1:-1;104444:26:0;;;;:18;:26;;;;;;;;;104405:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;104523:113;;:88;;;;:69;:88::i;:113::-;104483:153;;;;;;104684:48;;;;:108;;:83;;:66;;;:83;;;:66;:83;:::i;:108::-;104647:145;;:34;;;:145;104805:4349;;;;104895:41;;:::i;:::-;-1:-1:-1;104953:28:0;;;;:20;:28;;;;;;;;104895:86;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;104953:28;;;105914:98;;100463:21;105914:98;:40;:98;:::i;:::-;105893:119;;106031:18;106052:92;106115:10;106052:14;:36;;;:40;;;;:92;;;;:::i;:::-;106031:113;;106163:15;106181:116;106244:11;:34;;;106181:116;;:14;:36;;;:40;;;;:116;;;;:::i;:::-;106163:134;;106330:10;106320:7;:20;106316:1198;;;106383:7;106369:10;:21;106365:817;;106690:36;;;;106645:108;;:10;;:108;;;:14;:108;:::i;:::-;106628:125;;106365:817;;;107095:36;;;;107053:105;;:7;;:105;;;:11;:105;:::i;:::-;107036:122;;106365:817;106316:1198;;;107370:124;107437:11;:34;;;107370:124;;:14;:36;;;:40;;;;:124;;;;:::i;:::-;107353:141;;106316:1198;104805:4349;;;107550:30;107586:18;:26;;;107631:6;107586:66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;107586:66:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;107586:66:0;;;;;;;15:3:-1;10;7:12;4:2;;;32:1;29;22:12;4:2;-1:-1;107586:66:0;;;;-1:-1:-1;107669:36:0;107683:4;107690:14;107669:5;:36::i;:::-;107759:141;:112;107836:11;:34;;;107759:112;;:14;:54;;;:76;;;;:112;;;;:::i;:141::-;107720:180;;;;:36;;;:180;107951:37;;107917:155;;107951:106;;:41;;;:106;;;:41;:106;:::i;:::-;107917:15;:155::i;:::-;108209:37;;108129:57;;;;:147;;:118;;;:79;;;;:118;;:79;:118;:::i;:147::-;108087:189;;:39;;;;:189;;;108334:277;;;;;;;;;;;;;:306;;:277;;108087:189;;108334:277;;;;;;;:54;;;;:83;;:76;;108411:5;108334:83;:76;:83;:::i;:306::-;108293:347;;;;:38;;;;:347;;;;108696:4;108657:36;;;:43;;;;108745:27;;;:19;:27;;;;;;;:81;;:52;;:27;;;:52;:49;:52;:::i;:81::-;108715:27;;;;:19;:27;;;;;;;;:111;;;;;;;;;;;;;;108843:28;;;:20;:28;;;;;:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;108931:13;:11;:13::i;:::-;109017:38;;;;;109108:19;;108964:178;;;;;;;;;;;;;;;;;;;;108905:39;;-1:-1:-1;108992:6:0;;108964:178;;;;;;;;;104805:4349;;;;;109164:26;;;;:18;:26;;;;;;;;;:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;104167:5045:0:o;31388:418::-;31472:21;;;31464:67;;;;-1:-1:-1;;;31464:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31544:49;31565:7;31582:1;31586:6;31544:20;:49::i;:::-;31627:68;31650:6;31627:68;;;;;;;;;;;;;;;;;:18;;;:9;:18;;;;;;;;;;;;:68;;:22;:68;:::i;:::-;31606:18;;;:9;:18;;;;;;;;;;:89;31721:12;;:24;;31738:6;31721:24;:16;:24;:::i;:::-;31706:12;:39;31761:37;;;;;;;;31787:1;;31761:37;;;;;;;;;;;;;31388:418;;:::o;10999:181::-;11055:6;11090;11082:5;:14;11074:67;;;;-1:-1:-1;;;11074:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5726:568;5782:6;6026;6022:47;;-1:-1:-1;6056:1:0;6049:8;;6022:47;6091:1;6096:2;6091:7;:27;;;;;5626:7;6102:1;:16;6091:27;6089:30;6081:82;;;;-1:-1:-1;;;6081:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6187:5;;;6191:1;6187;:5;:1;6211:5;;;;;:10;6203:62;;;;-1:-1:-1;;;6203:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6789:218;6845:6;6875:5;;;6900:6;;;;;;:16;;;6915:1;6910;:6;;6900:16;6899:38;;;;6926:1;6922;:5;:14;;;;;6935:1;6931;:5;6922:14;6891:87;;;;-1:-1:-1;;;6891:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3803:345;3889:7;3991:12;3984:5;3976:28;;;;-1:-1:-1;;;3976:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27:10:-1;;8:100;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;3976:28:0;;4015:9;4031:1;4027;:5;;;;;;;3803:345;-1:-1:-1;;;;;3803:345:0:o;33617:92::-;;;;:::o;34117:106::-;34175:7;34206:1;34202;:5;:13;;34214:1;34202:13;;;-1:-1:-1;34210:1:0;;34117:106;-1:-1:-1;34117:106:0:o;103482:132::-;103570:19;;:36;;103594:11;103570:36;:23;:36;:::i;:::-;103548:19;:58;-1:-1:-1;103482:132:0:o;100095:28022::-;;;;;;;;;-1:-1:-1;100095:28022:0;;;;;;;;;;;;;;;;;;;;;;;:::o
Swarm Source
ipfs://d085672f8467497f59973194f9b1d4d97c7592939b63afb78bc9add4e0e727e6
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.