ETH Price: $3,321.56 (-4.05%)

Token

ESP (ESP)
 

Overview

Max Total Supply

26,151,832.78795845 ESP

Holders

6

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 8 Decimals)

Balance
0.63636363 ESP

Value
$0.00
0x16B00dB74167b7469dDa63b674Ca9A3B1b70C439
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
ESP

Compiler Version
v0.5.10+commit.5a6ea5b1

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-11-28
*/

pragma solidity 0.5.10;


contract Context {
    // Empty internal constructor, to prevent people from mistakenly deploying
    // an instance of this contract, which should be used via inheritance.
    constructor () internal { }
    // solhint-disable-previous-line no-empty-blocks

    function _msgSender() internal view returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see {ERC20Detailed}.
 */
interface TRC20 {
    /**
     * @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);
}

/**
 * @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.
     *
     * _Available since v2.4.0._
     */
    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.
     *
     * _Available since v2.4.0._
     */
    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.
     *
     * _Available since v2.4.0._
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

/**
 * @dev Implementation of the {TRC20} 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 {ERC20Mintable}.
 *
 * 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 {TRC20-approve}.
 */
contract ERC20 is Context, TRC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    // allocating 30 million tokens for promotion, airdrop, liquidity and dev share
    // modified original contract from 25000000
    uint256 private _totalSupply = 30000000 * (10 ** 8);

    constructor() public {
        _balances[msg.sender] = _totalSupply;
    }

    /**
     * @dev See {TRC20-totalSupply}.
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {TRC20-balanceOf}.
     */
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {TRC20-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 returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {TRC20-allowance}.
     */
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {TRC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {TRC20-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 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 {TRC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public 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 {TRC20-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 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 {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _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 {
        require(account != address(0), "ERC20: mint to the zero address");

        _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 {
        require(account != address(0), "ERC20: burn from the zero address");

        _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 {
        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 Destroys `amount` tokens from `account`.`amount` is then deducted
     * from the caller's allowance.
     *
     * See {_burn} and {_approve}.
     */
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(account, _msgSender(), _allowances[account][_msgSender()].sub(amount, "ERC20: burn amount exceeds allowance"));
    }
}

contract GlobalsAndUtility is ERC20 {
    /*  XfLobbyEnter
    */
    event XfLobbyEnter(
        uint256 timestamp,
        uint256 enterDay,
        uint256 indexed entryIndex,
        uint256 indexed rawAmount
    );

    /*  XfLobbyExit 
    */
    event XfLobbyExit(
        uint256 timestamp,
        uint256 enterDay,
        uint256 indexed entryIndex,
        uint256 indexed xfAmount,
        address indexed referrerAddr
    );

    /*  DailyDataUpdate
    */
    event DailyDataUpdate(
        address indexed updaterAddr,
        uint256 timestamp,
        uint256 beginDay,
        uint256 endDay
    );

    /*  StakeStart
    */
    event StakeStart(
        uint40 indexed stakeId,
        address indexed stakerAddr,
        uint256 stakedSuns,
        uint256 stakeShares,
        uint256 stakedDays
    );
    
    /*  StakeGoodAccounting
    */
    event StakeGoodAccounting(
        uint40 indexed stakeId,
        address indexed stakerAddr,
        address indexed senderAddr,
        uint256 stakedSuns,
        uint256 stakeShares,
        uint256 payout,
        uint256 penalty
    );

    /*  StakeEnd 
    */
    event StakeEnd(
        uint40 indexed stakeId,
        uint40 prevUnlocked,
        address indexed stakerAddr,
        uint256 lockedDay,
        uint256 servedDays,
        uint256 stakedSuns,
        uint256 stakeShares,
        uint256 dividends,
        uint256 payout,
        uint256 penalty,
        uint256 stakeReturn
    );

    /*  ShareRateChange 
    */
    event ShareRateChange(
        uint40 indexed stakeId,
        uint256 timestamp,
        uint256 newShareRate
    );
	
	 address payable internal constant FLUSH_ADDR = 0x2d170A681467aF00680EA9AF137C96fA1a4120b5;


    /* ERC20 constants */
    string public constant name = "ESP";
    string public constant symbol = "ESP";
    uint8 public constant decimals = 8;

    /* Suns per Satoshi = 10,000 * 1e8 / 1e8 = 1e4 */
    uint256 private constant SUNS_PER_DIV = 10 ** uint256(decimals); // 1e8

    /* Time of contract launch (11/27 00:00 UTC)
	*  First auction opens to the public: (11/28 00:00 UTC)
	*/
    uint256 internal constant LAUNCH_TIME = 1606521600;

    /* Start of claim phase */
    uint256 internal constant PRE_CLAIM_DAYS = 1;
    /* reduce amount of tokens to 1000000 */
    uint256 internal constant CLAIM_STARTING_AMOUNT = 1000000 * (10 ** 8);
    /* reduce amount of tokens to 100000 */
    uint256 internal constant CLAIM_LOWEST_AMOUNT = 100000 * (10 ** 8);
    uint256 internal constant CLAIM_PHASE_START_DAY = PRE_CLAIM_DAYS;

    /* Number of words to hold 1 bit for each transform lobby day */
    uint256 internal constant XF_LOBBY_DAY_WORDS = ((1 + (50 * 7)) + 255) >> 8;

    /* Stake timing parameters */
    uint256 internal constant MIN_STAKE_DAYS = 1;

    uint256 internal constant MAX_STAKE_DAYS = 30; // ~one month

    uint256 internal constant EARLY_PENALTY_MIN_DAYS = 15;

    uint256 private constant LATE_PENALTY_GRACE_WEEKS = 2;
    uint256 internal constant LATE_PENALTY_GRACE_DAYS = LATE_PENALTY_GRACE_WEEKS * 7;

    uint256 private constant LATE_PENALTY_SCALE_WEEKS = 100;
    uint256 internal constant LATE_PENALTY_SCALE_DAYS = LATE_PENALTY_SCALE_WEEKS * 7;

    /* Stake shares Longer Pays Better bonus constants used by _stakeStartBonusSuns() */
    uint256 private constant LPB_BONUS_PERCENT = 20;
    uint256 private constant LPB_BONUS_MAX_PERCENT = 200;
    uint256 internal constant LPB = 364 * 100 / LPB_BONUS_PERCENT;
    uint256 internal constant LPB_MAX_DAYS = LPB * LPB_BONUS_MAX_PERCENT / 100;

    /* Stake shares Bigger Pays Better bonus constants used by _stakeStartBonusSuns() */
    uint256 private constant BPB_BONUS_PERCENT = 10;
    uint256 private constant BPB_MAX_DIV = 7 * 1e6;
    uint256 internal constant BPB_MAX_SUNS = BPB_MAX_DIV * SUNS_PER_DIV;
    uint256 internal constant BPB = BPB_MAX_SUNS * 100 / BPB_BONUS_PERCENT;

    /* Share rate is scaled to increase precision */
    uint256 internal constant SHARE_RATE_SCALE = 1e5;

    /* Share rate max (after scaling) */
    uint256 internal constant SHARE_RATE_UINT_SIZE = 40;
    uint256 internal constant SHARE_RATE_MAX = (1 << SHARE_RATE_UINT_SIZE) - 1;

    /* weekly staking bonus */
    uint8 internal constant BONUS_DAY_SCALE = 2;

    /* Globals expanded for memory (except _latestStakeId) and compact for storage */
    struct GlobalsCache {
        uint256 _lockedSunsTotal;
        uint256 _nextStakeSharesTotal;
        uint256 _shareRate;
        uint256 _stakePenaltyTotal;
        uint256 _dailyDataCount;
        uint256 _stakeSharesTotal;
        uint40 _latestStakeId;
        uint256 _currentDay;
    }

    struct GlobalsStore {
        uint72 lockedSunsTotal;
        uint72 nextStakeSharesTotal;
        uint40 shareRate;
        uint72 stakePenaltyTotal;
        uint16 dailyDataCount;
        uint72 stakeSharesTotal;
        uint40 latestStakeId;
    }

    GlobalsStore public globals;

    /* Daily data */
    struct DailyDataStore {
        uint72 dayPayoutTotal;
        uint256 dayDividends;
        uint72 dayStakeSharesTotal;
    }

    mapping(uint256 => DailyDataStore) public dailyData;

    /* Stake expanded for memory (except _stakeId) and compact for storage */
    struct StakeCache {
        uint40 _stakeId;
        uint256 _stakedSuns;
        uint256 _stakeShares;
        uint256 _lockedDay;
        uint256 _stakedDays;
        uint256 _unlockedDay;
    }

    struct StakeStore {
        uint40 stakeId;
        uint72 stakedSuns;
        uint72 stakeShares;
        uint16 lockedDay;
        uint16 stakedDays;
        uint16 unlockedDay;
    }

    mapping(address => StakeStore[]) public stakeLists;

    /* Temporary state for calculating daily rounds */
    struct DailyRoundState {
        uint256 _allocSupplyCached;
        uint256 _payoutTotal;
    }

    struct XfLobbyEntryStore {
        uint96 rawAmount;
        address referrerAddr;
    }

    struct XfLobbyQueueStore {
        uint40 headIndex;
        uint40 tailIndex;
        mapping(uint256 => XfLobbyEntryStore) entries;
    }

    mapping(uint256 => uint256) public xfLobby;
    mapping(uint256 => mapping(address => XfLobbyQueueStore)) public xfLobbyMembers;

    /**
     * @dev PUBLIC FACING: Optionally update daily data for a smaller
     * range to reduce gas cost for a subsequent operation
     * @param beforeDay Only update days before this day number (optional; 0 for current day)
     */
    function dailyDataUpdate(uint256 beforeDay)
        external
    {
        GlobalsCache memory g;
        GlobalsCache memory gSnapshot;
        _globalsLoad(g, gSnapshot);

        /* Skip pre-claim period */
        require(g._currentDay > CLAIM_PHASE_START_DAY, "ESP: Too early");

        if (beforeDay != 0) {
            require(beforeDay <= g._currentDay, "ESP: beforeDay cannot be in the future");

            _dailyDataUpdate(g, beforeDay, false);
        } else {
            /* Default to updating before current day */
            _dailyDataUpdate(g, g._currentDay, false);
        }

        _globalsSync(g, gSnapshot);
    }

    /**
     * @dev PUBLIC FACING: External helper to return multiple values of daily data with
     * a single call.
     * @param beginDay First day of data range
     * @param endDay Last day (non-inclusive) of data range
     * @return array of day stake shares total
     * @return array of day payout total
     */
    function dailyDataRange(uint256 beginDay, uint256 endDay)
        external
        view
        returns (uint256[] memory _dayStakeSharesTotal, uint256[] memory _dayPayoutTotal, uint256[] memory _dayDividends)
    {
        require(beginDay < endDay && endDay <= globals.dailyDataCount, "ESP: range invalid");

        _dayStakeSharesTotal = new uint256[](endDay - beginDay);
        _dayPayoutTotal = new uint256[](endDay - beginDay);
        _dayDividends = new uint256[](endDay - beginDay);

        uint256 src = beginDay;
        uint256 dst = 0;
        do {
            _dayStakeSharesTotal[dst] = uint256(dailyData[src].dayStakeSharesTotal);
            _dayPayoutTotal[dst++] = uint256(dailyData[src].dayPayoutTotal);
            _dayDividends[dst++] = dailyData[src].dayDividends;
        } while (++src < endDay);

        return (_dayStakeSharesTotal, _dayPayoutTotal, _dayDividends);
    }


    /**
     * @dev PUBLIC FACING: External helper to return most global info with a single call.
     * Ugly implementation due to limitations of the standard ABI encoder.
     * @return Fixed array of values
     */
    function globalInfo()
        external
        view
        returns (uint256[10] memory)
    {

        return [
            globals.lockedSunsTotal,
            globals.nextStakeSharesTotal,
            globals.shareRate,
            globals.stakePenaltyTotal,
            globals.dailyDataCount,
            globals.stakeSharesTotal,
            globals.latestStakeId,
            block.timestamp,
            totalSupply(),
            xfLobby[_currentDay()]
        ];
    }

    /**
     * @dev PUBLIC FACING: ERC20 totalSupply() is the circulating supply and does not include any
     * staked Suns. allocatedSupply() includes both.
     * @return Allocated Supply in Suns
     */
    function allocatedSupply()
        external
        view
        returns (uint256)
    {
        return totalSupply() + globals.lockedSunsTotal;
    }

    /**
     * @dev PUBLIC FACING: External helper for the current day number since launch time
     * @return Current day number (zero-based)
     */
    function currentDay()
        external
        view
        returns (uint256)
    {
        return _currentDay();
    }

    function _currentDay()
        internal
        view
        returns (uint256)
    {
        if (block.timestamp < LAUNCH_TIME){
             return 0;
        }else{
             return (block.timestamp - LAUNCH_TIME) / 1 days;
        }
    }

    function _dailyDataUpdateAuto(GlobalsCache memory g)
        internal
    {
        _dailyDataUpdate(g, g._currentDay, true);
    }

    function _globalsLoad(GlobalsCache memory g, GlobalsCache memory gSnapshot)
        internal
        view
    {
        g._lockedSunsTotal = globals.lockedSunsTotal;
        g._nextStakeSharesTotal = globals.nextStakeSharesTotal;
        g._shareRate = globals.shareRate;
        g._stakePenaltyTotal = globals.stakePenaltyTotal;
        g._dailyDataCount = globals.dailyDataCount;
        g._stakeSharesTotal = globals.stakeSharesTotal;
        g._latestStakeId = globals.latestStakeId;
        g._currentDay = _currentDay();

        _globalsCacheSnapshot(g, gSnapshot);
    }

    function _globalsCacheSnapshot(GlobalsCache memory g, GlobalsCache memory gSnapshot)
        internal
        pure
    {
        gSnapshot._lockedSunsTotal = g._lockedSunsTotal;
        gSnapshot._nextStakeSharesTotal = g._nextStakeSharesTotal;
        gSnapshot._shareRate = g._shareRate;
        gSnapshot._stakePenaltyTotal = g._stakePenaltyTotal;
        gSnapshot._dailyDataCount = g._dailyDataCount;
        gSnapshot._stakeSharesTotal = g._stakeSharesTotal;
        gSnapshot._latestStakeId = g._latestStakeId;
    }

    function _globalsSync(GlobalsCache memory g, GlobalsCache memory gSnapshot)
        internal
    {
        if (g._lockedSunsTotal != gSnapshot._lockedSunsTotal
            || g._nextStakeSharesTotal != gSnapshot._nextStakeSharesTotal
            || g._shareRate != gSnapshot._shareRate
            || g._stakePenaltyTotal != gSnapshot._stakePenaltyTotal) {
            globals.lockedSunsTotal = uint72(g._lockedSunsTotal);
            globals.nextStakeSharesTotal = uint72(g._nextStakeSharesTotal);
            globals.shareRate = uint40(g._shareRate);
            globals.stakePenaltyTotal = uint72(g._stakePenaltyTotal);
        }
        if (g._dailyDataCount != gSnapshot._dailyDataCount
            || g._stakeSharesTotal != gSnapshot._stakeSharesTotal
            || g._latestStakeId != gSnapshot._latestStakeId) {
            globals.dailyDataCount = uint16(g._dailyDataCount);
            globals.stakeSharesTotal = uint72(g._stakeSharesTotal);
            globals.latestStakeId = g._latestStakeId;
        }
    }

    function _stakeLoad(StakeStore storage stRef, uint40 stakeIdParam, StakeCache memory st)
        internal
        view
    {
        /* Ensure caller's stakeIndex is still current */
        require(stakeIdParam == stRef.stakeId, "ESP: stakeIdParam not in stake");

        st._stakeId = stRef.stakeId;
        st._stakedSuns = stRef.stakedSuns;
        st._stakeShares = stRef.stakeShares;
        st._lockedDay = stRef.lockedDay;
        st._stakedDays = stRef.stakedDays;
        st._unlockedDay = stRef.unlockedDay;
    }

    function _stakeUpdate(StakeStore storage stRef, StakeCache memory st)
        internal
    {
        stRef.stakeId = st._stakeId;
        stRef.stakedSuns = uint72(st._stakedSuns);
        stRef.stakeShares = uint72(st._stakeShares);
        stRef.lockedDay = uint16(st._lockedDay);
        stRef.stakedDays = uint16(st._stakedDays);
        stRef.unlockedDay = uint16(st._unlockedDay);
    }

    function _stakeAdd(
        StakeStore[] storage stakeListRef,
        uint40 newStakeId,
        uint256 newStakedSuns,
        uint256 newStakeShares,
        uint256 newLockedDay,
        uint256 newStakedDays
    )
        internal
    {
        stakeListRef.push(
            StakeStore(
                newStakeId,
                uint72(newStakedSuns),
                uint72(newStakeShares),
                uint16(newLockedDay),
                uint16(newStakedDays),
                uint16(0) // unlockedDay
            )
        );
    }

    /**
     * @dev Efficiently delete from an unordered array by moving the last element
     * to the "hole" and reducing the array length. Can change the order of the list
     * and invalidate previously held indexes.
     * @notice stakeListRef length and stakeIndex are already ensured valid in stakeEnd()
     * @param stakeListRef Reference to stakeLists[stakerAddr] array in storage
     * @param stakeIndex Index of the element to delete
     */
    function _stakeRemove(StakeStore[] storage stakeListRef, uint256 stakeIndex)
        internal
    {
        uint256 lastIndex = stakeListRef.length - 1;

        /* Skip the copy if element to be removed is already the last element */
        if (stakeIndex != lastIndex) {
            /* Copy last element to the requested element's "hole" */
            stakeListRef[stakeIndex] = stakeListRef[lastIndex];
        }

        /*
            Reduce the array length now that the array is contiguous.
            Surprisingly, 'pop()' uses less gas than 'stakeListRef.length = lastIndex'
        */
        stakeListRef.pop();
    }

    /**
     * @dev Estimate the stake payout for an incomplete day
     * @param g Cache of stored globals
     * @param stakeSharesParam Param from stake to calculate bonuses for
     * @param day Day to calculate bonuses for
     * @return Payout in Suns
     */
    function _estimatePayoutRewardsDay(GlobalsCache memory g, uint256 stakeSharesParam, uint256 day)
        internal
        view
        returns (uint256 payout)
    {
        /* Prevent updating state for this estimation */
        GlobalsCache memory gTmp;
        _globalsCacheSnapshot(g, gTmp);

        DailyRoundState memory rs;
        rs._allocSupplyCached = totalSupply() + g._lockedSunsTotal;

        _dailyRoundCalc(gTmp, rs, day);

        /* Stake is no longer locked so it must be added to total as if it were */
        gTmp._stakeSharesTotal += stakeSharesParam;

        payout = rs._payoutTotal * stakeSharesParam / gTmp._stakeSharesTotal;

        return payout;
    }

    function _dailyRoundCalc(GlobalsCache memory g, DailyRoundState memory rs, uint256 day)
        private
        view
    {
        /*
            Calculate payout round

            Inflation of 5.42% inflation per 364 days             (approx 1 year)
            dailyInterestRate   = exp(log(1 + 5.42%)  / 364) - 1
                                = exp(log(1 + 0.0542) / 364) - 1
                                = exp(log(1.0542) / 364) - 1
                                = 0.0.00014523452066           (approx)

            payout  = allocSupply * dailyInterestRate
                    = allocSupply / (1 / dailyInterestRate)
                    = allocSupply / (1 / 0.00014523452066)
                    = allocSupply / 6885.4153644438375            (approx)
                    = allocSupply * 50000 / 68854153             (* 50000/50000 for int precision)
        */
        
        rs._payoutTotal = (rs._allocSupplyCached * 50000 / 68854153);

        if (g._stakePenaltyTotal != 0) {
            rs._payoutTotal += g._stakePenaltyTotal;
            g._stakePenaltyTotal = 0;
        }
    }

    function _dailyRoundCalcAndStore(GlobalsCache memory g, DailyRoundState memory rs, uint256 day)
        private
    {
        _dailyRoundCalc(g, rs, day);

        dailyData[day].dayPayoutTotal = uint72(rs._payoutTotal);
        dailyData[day].dayDividends = xfLobby[day];
        dailyData[day].dayStakeSharesTotal = uint72(g._stakeSharesTotal);
    }

    function _dailyDataUpdate(GlobalsCache memory g, uint256 beforeDay, bool isAutoUpdate)
        private
    {
        if (g._dailyDataCount >= beforeDay) {
            /* Already up-to-date */
            return;
        }

        DailyRoundState memory rs;
        rs._allocSupplyCached = totalSupply() + g._lockedSunsTotal;

        uint256 day = g._dailyDataCount;

        _dailyRoundCalcAndStore(g, rs, day);

        /* Stakes started during this day are added to the total the next day */
        if (g._nextStakeSharesTotal != 0) {
            g._stakeSharesTotal += g._nextStakeSharesTotal;
            g._nextStakeSharesTotal = 0;
        }

        while (++day < beforeDay) {
            _dailyRoundCalcAndStore(g, rs, day);
        }

        emit DailyDataUpdate(
            msg.sender,
            block.timestamp,
            g._dailyDataCount, 
            day
        );
        
        g._dailyDataCount = day;
    }
}

contract StakeableToken is GlobalsAndUtility {
    /**
     * @dev PUBLIC FACING: Open a stake.
     * @param newStakedSuns Number of Suns to stake
     * @param newStakedDays Number of days to stake
     */
    function stakeStart(uint256 newStakedSuns, uint256 newStakedDays)
        external
    {
        GlobalsCache memory g;
        GlobalsCache memory gSnapshot;
        _globalsLoad(g, gSnapshot);

        /* Enforce the minimum stake time */
        require(newStakedDays >= MIN_STAKE_DAYS, "ESP: newStakedDays lower than minimum");

        /* Check if log data needs to be updated */
        _dailyDataUpdateAuto(g);

        _stakeStart(g, newStakedSuns, newStakedDays);

        /* Remove staked Suns from balance of staker */
        _burn(msg.sender, newStakedSuns);

        _globalsSync(g, gSnapshot);
    }

    /**
     * @dev PUBLIC FACING: Unlocks a completed stake, distributing the proceeds of any penalty
     * immediately. The staker must still call stakeEnd() to retrieve their stake return (if any).
     * @param stakerAddr Address of staker
     * @param stakeIndex Index of stake within stake list
     * @param stakeIdParam The stake's id
     */
    function stakeGoodAccounting(address stakerAddr, uint256 stakeIndex, uint40 stakeIdParam)
        external
    {
        GlobalsCache memory g;
        GlobalsCache memory gSnapshot;
        _globalsLoad(g, gSnapshot);

        /* require() is more informative than the default assert() */
        require(stakeLists[stakerAddr].length != 0, "ESP: Empty stake list");
        require(stakeIndex < stakeLists[stakerAddr].length, "ESP: stakeIndex invalid");

        StakeStore storage stRef = stakeLists[stakerAddr][stakeIndex];

        /* Get stake copy */
        StakeCache memory st;
        _stakeLoad(stRef, stakeIdParam, st);

        /* Stake must have served full term */
        require(g._currentDay >= st._lockedDay + st._stakedDays, "ESP: Stake not fully served");

        /* Stake must still be locked */
        require(st._unlockedDay == 0, "ESP: Stake already unlocked");

        /* Check if log data needs to be updated */
        _dailyDataUpdateAuto(g);

        /* Unlock the completed stake */
        _stakeUnlock(g, st);

        /* stakeReturn & dividends values are unused here */
        (, uint256 payout, uint256 dividends, uint256 penalty, uint256 cappedPenalty) = _stakePerformance(
            g,
            st,
            st._stakedDays
        );

        emit StakeGoodAccounting(
            stakeIdParam,
            stakerAddr,
            msg.sender,
            st._stakedSuns,
            st._stakeShares,
            payout,
            penalty
        );

        if (cappedPenalty != 0) {
            g._stakePenaltyTotal += cappedPenalty;
        }

        /* st._unlockedDay has changed */
        _stakeUpdate(stRef, st);

        _globalsSync(g, gSnapshot);
    }

    /**
     * @dev PUBLIC FACING: Closes a stake. The order of the stake list can change so
     * a stake id is used to reject stale indexes.
     * @param stakeIndex Index of stake within stake list
     * @param stakeIdParam The stake's id
     */
    function stakeEnd(uint256 stakeIndex, uint40 stakeIdParam)
        external
    {
        GlobalsCache memory g;
        GlobalsCache memory gSnapshot;
        _globalsLoad(g, gSnapshot);

        StakeStore[] storage stakeListRef = stakeLists[msg.sender];

        /* require() is more informative than the default assert() */
        require(stakeListRef.length != 0, "ESP: Empty stake list");
        require(stakeIndex < stakeListRef.length, "ESP: stakeIndex invalid");

        /* Get stake copy */
        StakeCache memory st;
        _stakeLoad(stakeListRef[stakeIndex], stakeIdParam, st);

        /* Check if log data needs to be updated */
        _dailyDataUpdateAuto(g);

        uint256 servedDays = 0;

        bool prevUnlocked = (st._unlockedDay != 0);
        uint256 stakeReturn;
        uint256 payout = 0;
        uint256 dividends = 0;
        uint256 penalty = 0;
        uint256 cappedPenalty = 0;

        if (g._currentDay >= st._lockedDay) {
            if (prevUnlocked) {
                /* Previously unlocked in stakeGoodAccounting(), so must have served full term */
                servedDays = st._stakedDays;
            } else {
                _stakeUnlock(g, st);

                servedDays = g._currentDay - st._lockedDay;
                if (servedDays > st._stakedDays) {
                    servedDays = st._stakedDays;
                }
            }

            (stakeReturn, payout, dividends, penalty, cappedPenalty) = _stakePerformance(g, st, servedDays);

            msg.sender.transfer(dividends);
        } else {
            /* Stake hasn't been added to the total yet, so no penalties or rewards apply */
            g._nextStakeSharesTotal -= st._stakeShares;

            stakeReturn = st._stakedSuns;
        }

        emit StakeEnd(
            stakeIdParam, 
            prevUnlocked ? 1 : 0,
            msg.sender,
            st._lockedDay,
            servedDays, 
            st._stakedSuns, 
            st._stakeShares, 
            dividends,
            payout, 
            penalty,
            stakeReturn
        );

        if (cappedPenalty != 0 && !prevUnlocked) {
            /* Split penalty proceeds only if not previously unlocked by stakeGoodAccounting() */
            g._stakePenaltyTotal += cappedPenalty;
        }

        /* Pay the stake return, if any, to the staker */
        if (stakeReturn != 0) {
            _mint(msg.sender, stakeReturn);

            /* Update the share rate if necessary */
            _shareRateUpdate(g, st, stakeReturn);
        }
        g._lockedSunsTotal -= st._stakedSuns;

        _stakeRemove(stakeListRef, stakeIndex);

        _globalsSync(g, gSnapshot);
    }

    /**
     * @dev PUBLIC FACING: Return the current stake count for a staker address
     * @param stakerAddr Address of staker
     */
    function stakeCount(address stakerAddr)
        external
        view
        returns (uint256)
    {
        return stakeLists[stakerAddr].length;
    }

    /**
     * @dev Open a stake.
     * @param g Cache of stored globals
     * @param newStakedSuns Number of Suns to stake
     * @param newStakedDays Number of days to stake
     */
    function _stakeStart(
        GlobalsCache memory g,
        uint256 newStakedSuns,
        uint256 newStakedDays
    )
        internal
    {
        /* Enforce the maximum stake time */
        require(newStakedDays <= MAX_STAKE_DAYS, "ESP: newStakedDays higher than maximum");

        uint256 bonusSuns = _stakeStartBonusSuns(newStakedSuns, newStakedDays);
        uint256 newStakeShares = (newStakedSuns + bonusSuns) * SHARE_RATE_SCALE / g._shareRate;

        /* Ensure newStakedSuns is enough for at least one stake share */
        require(newStakeShares != 0, "ESP: newStakedSuns must be at least minimum shareRate");

        /*
            The stakeStart timestamp will always be part-way through the current
            day, so it needs to be rounded-up to the next day to ensure all
            stakes align with the same fixed calendar days. The current day is
            already rounded-down, so rounded-up is current day + 1.
        */
        uint256 newLockedDay = g._currentDay + 1;

        /* Create Stake */
        uint40 newStakeId = ++g._latestStakeId;
        _stakeAdd(
            stakeLists[msg.sender],
            newStakeId,
            newStakedSuns,
            newStakeShares,
            newLockedDay,
            newStakedDays
        );

        emit StakeStart(
            newStakeId, 
            msg.sender,
            newStakedSuns, 
            newStakeShares, 
            newStakedDays
        );

        /* Stake is added to total in the next round, not the current round */
        g._nextStakeSharesTotal += newStakeShares;

        /* Track total staked Suns for inflation calculations */
        g._lockedSunsTotal += newStakedSuns;
    }

    /**
     * @dev Calculates total stake payout including rewards for a multi-day range
     * @param g Cache of stored globals
     * @param stakeSharesParam Param from stake to calculate bonuses for
     * @param beginDay First day to calculate bonuses for
     * @param endDay Last day (non-inclusive) of range to calculate bonuses for
     * @return Payout in Suns
     */
    function _calcPayoutRewards(
        GlobalsCache memory g,
        uint256 stakeSharesParam,
        uint256 beginDay,
        uint256 endDay
    )
        private
        view
        returns (uint256 payout)
    {
        uint256 counter;

        for (uint256 day = beginDay; day < endDay; day++) {
            uint256 dayPayout;

            dayPayout = dailyData[day].dayPayoutTotal * stakeSharesParam
                / dailyData[day].dayStakeSharesTotal;

            if (counter < 4) {
                counter++;
            } 
            /* Eligible to receive bonus */
            else {
                dayPayout = (dailyData[day].dayPayoutTotal * stakeSharesParam
                / dailyData[day].dayStakeSharesTotal) * BONUS_DAY_SCALE;
                counter = 0;
            }

            payout += dayPayout;
        }

        return payout;
    }

    /**
     * @dev Calculates user dividends
     * @param g Cache of stored globals
     * @param stakeSharesParam Param from stake to calculate bonuses for
     * @param beginDay First day to calculate bonuses for
     * @param endDay Last day (non-inclusive) of range to calculate bonuses for
     * @return Payout in Suns
     */
    function _calcPayoutDividendsReward(
        GlobalsCache memory g,
        uint256 stakeSharesParam,
        uint256 beginDay,
        uint256 endDay
    )
        private
        view
        returns (uint256 payout)
    {

        for (uint256 day = beginDay; day < endDay; day++) {
            uint256 dayPayout;

            /* user's share of 100% of the day's dividends */
            dayPayout += dailyData[day].dayDividends * stakeSharesParam
            / dailyData[day].dayStakeSharesTotal;

            payout += dayPayout;
        }

        return payout;
    }

    /**
     * @dev Calculate bonus Suns for a new stake, if any
     * @param newStakedSuns Number of Suns to stake
     * @param newStakedDays Number of days to stake
     */
    function _stakeStartBonusSuns(uint256 newStakedSuns, uint256 newStakedDays)
        private
        pure
        returns (uint256 bonusSuns)
    {
        /*
            LONGER PAYS BETTER:

            If longer than 1 day stake is committed to, each extra day
            gives bonus shares of approximately 0.0548%, which is approximately 20%
            extra per year of increased stake length committed to, but capped to a
            maximum of 200% extra.

            extraDays       =  stakedDays - 1

            longerBonus%    = (extraDays / 364) * 20%
                            = (extraDays / 364) / 5
                            =  extraDays / 1820
                            =  extraDays / LPB

            extraDays       =  longerBonus% * 1820
            extraDaysMax    =  longerBonusMax% * 1820
                            =  200% * 1820
                            =  3640
                            =  LPB_MAX_DAYS

            BIGGER PAYS BETTER:

            Bonus percentage scaled 0% to 10% for the first 7M ESP of stake.

            biggerBonus%    = (cappedSuns /  BPB_MAX_SUNS) * 10%
                            = (cappedSuns /  BPB_MAX_SUNS) / 10
                            =  cappedSuns / (BPB_MAX_SUNS * 10)
                            =  cappedSuns /  BPB

            COMBINED:

            combinedBonus%  =            longerBonus%  +  biggerBonus%

                                      cappedExtraDays     cappedSuns
                            =         ---------------  +  ------------
                                            LPB               BPB

                                cappedExtraDays * BPB     cappedSuns * LPB
                            =   ---------------------  +  ------------------
                                      LPB * BPB               LPB * BPB

                                cappedExtraDays * BPB  +  cappedSuns * LPB
                            =   --------------------------------------------
                                                  LPB  *  BPB

            bonusSuns     = suns * combinedBonus%
                            = suns * (cappedExtraDays * BPB  +  cappedSuns * LPB) / (LPB * BPB)
        */
        uint256 cappedExtraDays = 0;

        /* Must be more than 1 day for Longer-Pays-Better */
        if (newStakedDays > 1) {
            cappedExtraDays = newStakedDays <= LPB_MAX_DAYS ? newStakedDays - 1 : LPB_MAX_DAYS;
        }

        uint256 cappedStakedSuns = newStakedSuns <= BPB_MAX_SUNS
            ? newStakedSuns
            : BPB_MAX_SUNS;

        bonusSuns = cappedExtraDays * BPB + cappedStakedSuns * LPB;
        bonusSuns = newStakedSuns * bonusSuns / (LPB * BPB);

        return bonusSuns;
    }

    function _stakeUnlock(GlobalsCache memory g, StakeCache memory st)
        private
        pure
    {
        g._stakeSharesTotal -= st._stakeShares;
        st._unlockedDay = g._currentDay;
    }

    function _stakePerformance(GlobalsCache memory g, StakeCache memory st, uint256 servedDays)
        private
        view
        returns (uint256 stakeReturn, uint256 payout, uint256 dividends, uint256 penalty, uint256 cappedPenalty)
    {
        if (servedDays < st._stakedDays) {
            (payout, penalty) = _calcPayoutAndEarlyPenalty(
                g,
                st._lockedDay,
                st._stakedDays,
                servedDays,
                st._stakeShares
            );
            stakeReturn = st._stakedSuns + payout;

            dividends = _calcPayoutDividendsReward(
                g,
                st._stakeShares,
                st._lockedDay,
                st._lockedDay + servedDays
            );
        } else {
            // servedDays must == stakedDays here
            payout = _calcPayoutRewards(
                g,
                st._stakeShares,
                st._lockedDay,
                st._lockedDay + servedDays
            );

            dividends = _calcPayoutDividendsReward(
                g,
                st._stakeShares,
                st._lockedDay,
                st._lockedDay + servedDays
            );

            stakeReturn = st._stakedSuns + payout;

            penalty = _calcLatePenalty(st._lockedDay, st._stakedDays, st._unlockedDay, stakeReturn);
        }
        if (penalty != 0) {
            if (penalty > stakeReturn) {
                /* Cannot have a negative stake return */
                cappedPenalty = stakeReturn;
                stakeReturn = 0;
            } else {
                /* Remove penalty from the stake return */
                cappedPenalty = penalty;
                stakeReturn -= cappedPenalty;
            }
        }
        return (stakeReturn, payout, dividends, penalty, cappedPenalty);
    }

    function _calcPayoutAndEarlyPenalty(
        GlobalsCache memory g,
        uint256 lockedDayParam,
        uint256 stakedDaysParam,
        uint256 servedDays,
        uint256 stakeSharesParam
    )
        private
        view
        returns (uint256 payout, uint256 penalty)
    {
        uint256 servedEndDay = lockedDayParam + servedDays;

        /* 50% of stakedDays (rounded up) with a minimum applied */
        uint256 penaltyDays = (stakedDaysParam + 1) / 2;
        if (penaltyDays < EARLY_PENALTY_MIN_DAYS) {
            penaltyDays = EARLY_PENALTY_MIN_DAYS;
        }

        if (servedDays == 0) {
            /* Fill penalty days with the estimated average payout */
            uint256 expected = _estimatePayoutRewardsDay(g, stakeSharesParam, lockedDayParam);
            penalty = expected * penaltyDays;
            return (payout, penalty); // Actual payout was 0
        }

        if (penaltyDays < servedDays) {
            /*
                Simplified explanation of intervals where end-day is non-inclusive:

                penalty:    [lockedDay  ...  penaltyEndDay)
                delta:                      [penaltyEndDay  ...  servedEndDay)
                payout:     [lockedDay  .......................  servedEndDay)
            */
            uint256 penaltyEndDay = lockedDayParam + penaltyDays;
            penalty = _calcPayoutRewards(g, stakeSharesParam, lockedDayParam, penaltyEndDay);

            uint256 delta = _calcPayoutRewards(g, stakeSharesParam, penaltyEndDay, servedEndDay);
            payout = penalty + delta;
            return (payout, penalty);
        }

        /* penaltyDays >= servedDays  */
        payout = _calcPayoutRewards(g, stakeSharesParam, lockedDayParam, servedEndDay);

        if (penaltyDays == servedDays) {
            penalty = payout;
        } else {
            /*
                (penaltyDays > servedDays) means not enough days served, so fill the
                penalty days with the average payout from only the days that were served.
            */
            penalty = payout * penaltyDays / servedDays;
        }
        return (payout, penalty);
    }

    function _calcLatePenalty(
        uint256 lockedDayParam,
        uint256 stakedDaysParam,
        uint256 unlockedDayParam,
        uint256 rawStakeReturn
    )
        private
        pure
        returns (uint256)
    {
        /* Allow grace time before penalties accrue */
        uint256 maxUnlockedDay = lockedDayParam + stakedDaysParam + LATE_PENALTY_GRACE_DAYS;
        if (unlockedDayParam <= maxUnlockedDay) {
            return 0;
        }

        /* Calculate penalty as a percentage of stake return based on time */
        return rawStakeReturn * (unlockedDayParam - maxUnlockedDay) / LATE_PENALTY_SCALE_DAYS;
    }

    function _shareRateUpdate(GlobalsCache memory g, StakeCache memory st, uint256 stakeReturn)
        private
    {
        if (stakeReturn > st._stakedSuns) {
            /*
                Calculate the new shareRate that would yield the same number of shares if
                the user re-staked this stakeReturn, factoring in any bonuses they would
                receive in stakeStart().
            */
            uint256 bonusSuns = _stakeStartBonusSuns(stakeReturn, st._stakedDays);
            uint256 newShareRate = (stakeReturn + bonusSuns) * SHARE_RATE_SCALE / st._stakeShares;

            if (newShareRate > SHARE_RATE_MAX) {
                /*
                    Realistically this can't happen, but there are contrived theoretical
                    scenarios that can lead to extreme values of newShareRate, so it is
                    capped to prevent them anyway.
                */
                newShareRate = SHARE_RATE_MAX;
            }

            if (newShareRate > g._shareRate) {
                g._shareRate = newShareRate;

                emit ShareRateChange(
                    st._stakeId,
                    block.timestamp,
                    newShareRate
                );
            }
        }
    }
}

contract TransformableToken is StakeableToken {
    /**
     * @dev PUBLIC FACING: Enter the auction lobby for the current round
     * @param referrerAddr TRX address of referring user (optional; 0x0 for no referrer)
     */
    function xfLobbyEnter(address referrerAddr)
        external
        payable
    {
	require(_currentDay() > 0, "ESP: Auction has not begun yet");

        uint256 enterDay = _currentDay();

        uint256 rawAmount = msg.value;
        require(rawAmount != 0, "ESP: Amount required");

        XfLobbyQueueStore storage qRef = xfLobbyMembers[enterDay][msg.sender];

        uint256 entryIndex = qRef.tailIndex++;

        qRef.entries[entryIndex] = XfLobbyEntryStore(uint96(rawAmount), referrerAddr);

        xfLobby[enterDay] += rawAmount;

        emit XfLobbyEnter(
            block.timestamp, 
            enterDay, 
            entryIndex, 
            rawAmount
        );
    }

    /**
     * @dev PUBLIC FACING: Leave the transform lobby after the round is complete
     * @param enterDay Day number when the member entered
     * @param count Number of queued-enters to exit (optional; 0 for all)
     */
    function xfLobbyExit(uint256 enterDay, uint256 count)
        external
    {
        require(enterDay < _currentDay(), "ESP: Round is not complete");

        XfLobbyQueueStore storage qRef = xfLobbyMembers[enterDay][msg.sender];

        uint256 headIndex = qRef.headIndex;
        uint256 endIndex;

        if (count != 0) {
            require(count <= qRef.tailIndex - headIndex, "ESP: count invalid");
            endIndex = headIndex + count;
        } else {
            endIndex = qRef.tailIndex;
            require(headIndex < endIndex, "ESP: count invalid");
        }

        uint256 waasLobby = _waasLobby(enterDay);
        uint256 _xfLobby = xfLobby[enterDay];
        uint256 totalXfAmount = 0;

        do {
            uint256 rawAmount = qRef.entries[headIndex].rawAmount;
            address referrerAddr = qRef.entries[headIndex].referrerAddr;

            delete qRef.entries[headIndex];

            uint256 xfAmount = waasLobby * rawAmount / _xfLobby;

            if (referrerAddr == address(0) || referrerAddr == msg.sender) {
                /* No referrer or Self-referred */
                _emitXfLobbyExit(enterDay, headIndex, xfAmount, referrerAddr);
            } else {
                /* Referral bonus of 5% of xfAmount to member */
                uint256 referralBonusSuns = xfAmount / 20;

                xfAmount += referralBonusSuns;

                /* Then a cumulative referrer bonus of 20% to referrer */
                uint256 referrerBonusSuns = xfAmount / 10;

                _emitXfLobbyExit(enterDay, headIndex, xfAmount, referrerAddr);
                _mint(referrerAddr, referrerBonusSuns);
            }

            totalXfAmount += xfAmount;
        } while (++headIndex < endIndex);

        qRef.headIndex = uint40(headIndex);

        if (totalXfAmount != 0) {
            _mint(msg.sender, totalXfAmount);
        }
    }

    /**
     * @dev PUBLIC FACING: External helper to return multiple values of xfLobby[] with
     * a single call
     * @param beginDay First day of data range
     * @param endDay Last day (non-inclusive) of data range
     * @return Fixed array of values
     */
    function xfLobbyRange(uint256 beginDay, uint256 endDay)
        external
        view
        returns (uint256[] memory list)
    {
        require(
            beginDay < endDay && endDay <= _currentDay(),
            "ESP: invalid range"
        );

        list = new uint256[](endDay - beginDay);

        uint256 src = beginDay;
        uint256 dst = 0;
        do {
            list[dst++] = uint256(xfLobby[src++]);
        } while (src < endDay);

        return list;
    }

    /**
     * @dev PUBLIC FACING: Return a current lobby member queue entry.
     * Only needed due to limitations of the standard ABI encoder.
     * @param memberAddr TRX address of the lobby member
     * @param enterDay 
     * @param entryIndex 
     * @return 1: Raw amount that was entered with; 2: Referring TRX addr (optional; 0x0 for no referrer)
     */
    function xfLobbyEntry(address memberAddr, uint256 enterDay, uint256 entryIndex)
        external
        view
        returns (uint256 rawAmount, address referrerAddr)
    {
        XfLobbyEntryStore storage entry = xfLobbyMembers[enterDay][memberAddr].entries[entryIndex];

        require(entry.rawAmount != 0, "ESP: Param invalid");

        return (entry.rawAmount, entry.referrerAddr);
    }

    /**
     * @dev PUBLIC FACING: Return the lobby days that a user is in with a single call
     * @param memberAddr TRX address of the user
     * @return Bit vector of lobby day numbers
     */
    function xfLobbyPendingDays(address memberAddr)
        external
        view
        returns (uint256[XF_LOBBY_DAY_WORDS] memory words)
    {
        uint256 day = _currentDay() + 1;

        while (day-- != 0) {
            if (xfLobbyMembers[day][memberAddr].tailIndex > xfLobbyMembers[day][memberAddr].headIndex) {
                words[day >> 8] |= 1 << (day & 255);
            }
        }

        return words;
    }
    
    function _waasLobby(uint256 enterDay)
        private
        returns (uint256 waasLobby)
    {
        /*   1 mil start, down 10,000 per day, 100,000 minimum per day.*/
        if (enterDay > 0 && enterDay <= 90) {                                     
            waasLobby = CLAIM_STARTING_AMOUNT - ((enterDay - 1) * 1000000000000);
        } else {
            waasLobby = CLAIM_LOWEST_AMOUNT;
        }

        return waasLobby;
    }

    function _emitXfLobbyExit(
        uint256 enterDay,
        uint256 entryIndex,
        uint256 xfAmount,
        address referrerAddr
    )
        private
    {
        emit XfLobbyExit(
            block.timestamp, 
            enterDay,
            entryIndex,
            xfAmount,
            referrerAddr
        );
    }
}

contract ESP is TransformableToken {
    constructor()
        public
    {
        /* Initialize global shareRate to 1 */
        globals.shareRate = uint40(1 * SHARE_RATE_SCALE);
    }

    function() external payable {}
}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"amount","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"sender","type":"address"},{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint256"}],"name":"stakeLists","outputs":[{"name":"stakeId","type":"uint40"},{"name":"stakedSuns","type":"uint72"},{"name":"stakeShares","type":"uint72"},{"name":"lockedDay","type":"uint16"},{"name":"stakedDays","type":"uint16"},{"name":"unlockedDay","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"memberAddr","type":"address"},{"name":"enterDay","type":"uint256"},{"name":"entryIndex","type":"uint256"}],"name":"xfLobbyEntry","outputs":[{"name":"rawAmount","type":"uint256"},{"name":"referrerAddr","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"stakerAddr","type":"address"}],"name":"stakeCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"stakeIndex","type":"uint256"},{"name":"stakeIdParam","type":"uint40"}],"name":"stakeEnd","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"allocatedSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"},{"name":"","type":"address"}],"name":"xfLobbyMembers","outputs":[{"name":"headIndex","type":"uint40"},{"name":"tailIndex","type":"uint40"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"memberAddr","type":"address"}],"name":"xfLobbyPendingDays","outputs":[{"name":"words","type":"uint256[2]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newStakedSuns","type":"uint256"},{"name":"newStakedDays","type":"uint256"}],"name":"stakeStart","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"currentDay","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"stakerAddr","type":"address"},{"name":"stakeIndex","type":"uint256"},{"name":"stakeIdParam","type":"uint40"}],"name":"stakeGoodAccounting","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"beginDay","type":"uint256"},{"name":"endDay","type":"uint256"}],"name":"dailyDataRange","outputs":[{"name":"_dayStakeSharesTotal","type":"uint256[]"},{"name":"_dayPayoutTotal","type":"uint256[]"},{"name":"_dayDividends","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"xfLobby","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"beforeDay","type":"uint256"}],"name":"dailyDataUpdate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"dailyData","outputs":[{"name":"dayPayoutTotal","type":"uint72"},{"name":"dayDividends","type":"uint256"},{"name":"dayStakeSharesTotal","type":"uint72"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"recipient","type":"address"},{"name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"globals","outputs":[{"name":"lockedSunsTotal","type":"uint72"},{"name":"nextStakeSharesTotal","type":"uint72"},{"name":"shareRate","type":"uint40"},{"name":"stakePenaltyTotal","type":"uint72"},{"name":"dailyDataCount","type":"uint16"},{"name":"stakeSharesTotal","type":"uint72"},{"name":"latestStakeId","type":"uint40"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"enterDay","type":"uint256"},{"name":"count","type":"uint256"}],"name":"xfLobbyExit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"referrerAddr","type":"address"}],"name":"xfLobbyEnter","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"globalInfo","outputs":[{"name":"","type":"uint256[10]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"beginDay","type":"uint256"},{"name":"endDay","type":"uint256"}],"name":"xfLobbyRange","outputs":[{"name":"list","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"timestamp","type":"uint256"},{"indexed":false,"name":"enterDay","type":"uint256"},{"indexed":true,"name":"entryIndex","type":"uint256"},{"indexed":true,"name":"rawAmount","type":"uint256"}],"name":"XfLobbyEnter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"timestamp","type":"uint256"},{"indexed":false,"name":"enterDay","type":"uint256"},{"indexed":true,"name":"entryIndex","type":"uint256"},{"indexed":true,"name":"xfAmount","type":"uint256"},{"indexed":true,"name":"referrerAddr","type":"address"}],"name":"XfLobbyExit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"updaterAddr","type":"address"},{"indexed":false,"name":"timestamp","type":"uint256"},{"indexed":false,"name":"beginDay","type":"uint256"},{"indexed":false,"name":"endDay","type":"uint256"}],"name":"DailyDataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"stakeId","type":"uint40"},{"indexed":true,"name":"stakerAddr","type":"address"},{"indexed":false,"name":"stakedSuns","type":"uint256"},{"indexed":false,"name":"stakeShares","type":"uint256"},{"indexed":false,"name":"stakedDays","type":"uint256"}],"name":"StakeStart","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"stakeId","type":"uint40"},{"indexed":true,"name":"stakerAddr","type":"address"},{"indexed":true,"name":"senderAddr","type":"address"},{"indexed":false,"name":"stakedSuns","type":"uint256"},{"indexed":false,"name":"stakeShares","type":"uint256"},{"indexed":false,"name":"payout","type":"uint256"},{"indexed":false,"name":"penalty","type":"uint256"}],"name":"StakeGoodAccounting","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"stakeId","type":"uint40"},{"indexed":false,"name":"prevUnlocked","type":"uint40"},{"indexed":true,"name":"stakerAddr","type":"address"},{"indexed":false,"name":"lockedDay","type":"uint256"},{"indexed":false,"name":"servedDays","type":"uint256"},{"indexed":false,"name":"stakedSuns","type":"uint256"},{"indexed":false,"name":"stakeShares","type":"uint256"},{"indexed":false,"name":"dividends","type":"uint256"},{"indexed":false,"name":"payout","type":"uint256"},{"indexed":false,"name":"penalty","type":"uint256"},{"indexed":false,"name":"stakeReturn","type":"uint256"}],"name":"StakeEnd","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"stakeId","type":"uint40"},{"indexed":false,"name":"timestamp","type":"uint256"},{"indexed":false,"name":"newShareRate","type":"uint256"}],"name":"ShareRateChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}]

6080604052660aa87bee53800060025534801561001b57600080fd5b506002543360009081526020819052604090205560038054740186a000000000000000000000000000000000000064ffffffffff60901b199091161790556132f9806100686000396000f3fe6080604052600436106101cd5760003560e01c806365cf71b2116100f7578063a457c2d711610095578063ce7d1f7711610064578063ce7d1f7714610924578063dd62ed3e1461094a578063f04b5fa014610985578063f57a1b3c146109b0576101cd565b8063a457c2d714610819578063a9059cbb14610852578063c31245251461088b578063cbb151d3146108f4576101cd565b806387a0f31c116100d157806387a0f31c146107705780638f1c65c01461079a57806390de6871146107c457806395d89b41146101cf576101cd565b806365cf71b2146105e95780636a210a0e1461062f57806370a082311461073d576101cd565b806333060d901161016f57806344203faf1161013e57806344203faf146104d957806344f0de751461053657806352a438b8146105a45780635c9302c9146105d4576101cd565b806333060d9014610421578063343009a214610454578063395093511461048b5780633a70a5ca146104c4576101cd565b806323b872dd116101ab57806323b872dd146102cd5780632607443b146103105780632e60d1c414610396578063313ce567146103f6576101cd565b806306fdde03146101cf578063095ea7b31461025957806318160ddd146102a6575b005b3480156101db57600080fd5b506101e4610a30565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561021e578181015183820152602001610206565b50505050905090810190601f16801561024b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561026557600080fd5b506102926004803603604081101561027c57600080fd5b506001600160a01b038135169060200135610a4f565b604080519115158252519081900360200190f35b3480156102b257600080fd5b506102bb610a6c565b60408051918252519081900360200190f35b3480156102d957600080fd5b50610292600480360360608110156102f057600080fd5b506001600160a01b03813581169160208101359091169060400135610a73565b34801561031c57600080fd5b506103496004803603604081101561033357600080fd5b506001600160a01b038135169060200135610b00565b6040805164ffffffffff90971687526001600160481b039586166020880152939094168584015261ffff9182166060860152811660808501529190911660a0830152519081900360c00190f35b3480156103a257600080fd5b506103d5600480360360608110156103b957600080fd5b506001600160a01b038135169060208101359060400135610b6e565b604080519283526001600160a01b0390911660208301528051918290030190f35b34801561040257600080fd5b5061040b610c15565b6040805160ff9092168252519081900360200190f35b34801561042d57600080fd5b506102bb6004803603602081101561044457600080fd5b50356001600160a01b0316610c1a565b34801561046057600080fd5b506101cd6004803603604081101561047757600080fd5b508035906020013564ffffffffff16610c35565b34801561049757600080fd5b50610292600480360360408110156104ae57600080fd5b506001600160a01b038135169060200135610ef7565b3480156104d057600080fd5b506102bb610f4b565b3480156104e557600080fd5b50610512600480360360408110156104fc57600080fd5b50803590602001356001600160a01b0316610f68565b6040805164ffffffffff938416815291909216602082015281519081900390910190f35b34801561054257600080fd5b506105696004803603602081101561055957600080fd5b50356001600160a01b0316610f97565b6040518082600260200280838360005b83811015610591578181015183820152602001610579565b5050505090500191505060405180910390f35b3480156105b057600080fd5b506101cd600480360360408110156105c757600080fd5b5080359060200135611023565b3480156105e057600080fd5b506102bb6110ab565b3480156105f557600080fd5b506101cd6004803603606081101561060c57600080fd5b5080356001600160a01b0316906020810135906040013564ffffffffff166110ba565b34801561063b57600080fd5b5061065f6004803603604081101561065257600080fd5b508035906020013561136f565b60405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b838110156106a757818101518382015260200161068f565b50505050905001848103835286818151815260200191508051906020019060200280838360005b838110156106e65781810151838201526020016106ce565b50505050905001848103825285818151815260200191508051906020019060200280838360005b8381101561072557818101518382015260200161070d565b50505050905001965050505050505060405180910390f35b34801561074957600080fd5b506102bb6004803603602081101561076057600080fd5b50356001600160a01b031661151e565b34801561077c57600080fd5b506102bb6004803603602081101561079357600080fd5b5035611539565b3480156107a657600080fd5b506101cd600480360360208110156107bd57600080fd5b503561154b565b3480156107d057600080fd5b506107ee600480360360208110156107e757600080fd5b5035611628565b604080516001600160481b039485168152602081019390935292168183015290519081900360600190f35b34801561082557600080fd5b506102926004803603604081101561083c57600080fd5b506001600160a01b038135169060200135611654565b34801561085e57600080fd5b506102926004803603604081101561087557600080fd5b506001600160a01b0381351690602001356116c2565b34801561089757600080fd5b506108a06116d6565b604080516001600160481b039889168152968816602088015264ffffffffff95861687820152938716606087015261ffff909216608086015290941660a0840152921660c082015290519081900360e00190f35b34801561090057600080fd5b506101cd6004803603604081101561091757600080fd5b5080359060200135611729565b6101cd6004803603602081101561093a57600080fd5b50356001600160a01b031661196b565b34801561095657600080fd5b506102bb6004803603604081101561096d57600080fd5b506001600160a01b0381358116916020013516611b1a565b34801561099157600080fd5b5061099a611b45565b6040518151815280826101408083836020610579565b3480156109bc57600080fd5b506109e0600480360360408110156109d357600080fd5b5080359060200135611c00565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610a1c578181015183820152602001610a04565b505050509050019250505060405180910390f35b6040518060400160405280600381526020016204553560ec1b81525081565b6000610a63610a5c611cd0565b8484611cd4565b50600192915050565b6002545b90565b6000610a80848484611dc0565b610af684610a8c611cd0565b610af1856040518060600160405280602881526020016131b3602891396001600160a01b038a16600090815260016020526040812090610aca611cd0565b6001600160a01b03168152602081019190915260400160002054919063ffffffff611f1c16565b611cd4565b5060019392505050565b60066020528160005260406000208181548110610b1957fe5b60009182526020909120015464ffffffffff811692506001600160481b03600160281b820481169250600160701b8204169061ffff600160b81b8204811691600160c81b8104821691600160d81b9091041686565b60008281526008602090815260408083206001600160a01b03871684528252808320848452600101909152812080548291906001600160601b0316610bef576040805162461bcd60e51b81526020600482015260126024820152711154d40e8814185c985b481a5b9d985b1a5960721b604482015290519081900360640190fd5b546001600160601b03811696600160601b9091046001600160a01b031695509350505050565b600881565b6001600160a01b031660009081526006602052604090205490565b610c3d612ffa565b610c45612ffa565b610c4f8282611fb3565b3360009081526006602052604090208054610ca9576040805162461bcd60e51b81526020600482015260156024820152741154d40e88115b5c1d1e481cdd185ad9481b1a5cdd605a1b604482015290519081900360640190fd5b80548510610cf8576040805162461bcd60e51b81526020600482015260176024820152761154d40e881cdd185ad9525b99195e081a5b9d985b1a59604a1b604482015290519081900360640190fd5b610d00613046565b610d20828781548110610d0f57fe5b906000526020600020018683612037565b610d29846120f9565b60a0810151606082015160e08601516000921515918391829182918291829110610dd5578515610d5f5787608001519650610d8a565b610d698b8961210c565b87606001518b60e001510396508760800151871115610d8a57876080015196505b610d958b898961212a565b60405194995092975090955093509150339084156108fc029085906000818181858888f19350505050158015610dcf573d6000803e3d6000fd5b50610dee565b60408801516020808d0180519290920390915288015194505b3364ffffffffff8d167f80bb257dd672adb291601517b3f5d31642fccf6d3db7a40983552a9baacbbabd88610e24576000610e27565b60015b8b606001518b8d602001518e604001518a8c8b8f604051808a60ff1664ffffffffff168152602001898152602001888152602001878152602001868152602001858152602001848152602001838152602001828152602001995050505050505050505060405180910390a38015801590610e9f575085155b15610eaf5760608b018051820190525b8415610eca57610ebf338661220a565b610eca8b89876122fa565b60208801518b51038b52610ede898e6123a5565b610ee88b8b6124e5565b50505050505050505050505050565b6000610a63610f04611cd0565b84610af18560016000610f15611cd0565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff61266816565b6003546000906001600160481b0316610f62610a6c565b01905090565b600860209081526000928352604080842090915290825290205464ffffffffff80821691600160281b90041682565b610f9f613083565b6000610fa96126c9565b60010190505b6000198101901561101d5760008181526008602090815260408083206001600160a01b038716845290915290205464ffffffffff808216600160281b90920416111561101857600160ff82161b82600883901c6002811061100c57fe5b60200201805190911790525b610faf565b50919050565b61102b612ffa565b611033612ffa565b61103d8282611fb3565b600183101561107d5760405162461bcd60e51b815260040180806020018281038252602581526020018061318e6025913960400191505060405180910390fd5b611086826120f9565b6110918285856126f2565b61109b3385612831565b6110a582826124e5565b50505050565b60006110b56126c9565b905090565b6110c2612ffa565b6110ca612ffa565b6110d48282611fb3565b6001600160a01b038516600090815260066020526040902054611136576040805162461bcd60e51b81526020600482015260156024820152741154d40e88115b5c1d1e481cdd185ad9481b1a5cdd605a1b604482015290519081900360640190fd5b6001600160a01b038516600090815260066020526040902054841061119c576040805162461bcd60e51b81526020600482015260176024820152761154d40e881cdd185ad9525b99195e081a5b9d985b1a59604a1b604482015290519081900360640190fd5b6001600160a01b03851660009081526006602052604081208054869081106111c057fe5b9060005260206000200190506111d4613046565b6111df828683612037565b80608001518160600151018460e001511015611242576040805162461bcd60e51b815260206004820152601b60248201527f4553503a205374616b65206e6f742066756c6c79207365727665640000000000604482015290519081900360640190fd5b60a081015115611299576040805162461bcd60e51b815260206004820152601b60248201527f4553503a205374616b6520616c726561647920756e6c6f636b65640000000000604482015290519081900360640190fd5b6112a2846120f9565b6112ac848261210c565b6000806000806112c18886876080015161212a565b945094509450945050336001600160a01b03168b6001600160a01b03168a64ffffffffff167f0bff00790f1231cf0c26911db2d0c4e670b204ebb02d6a73d3fb5c995910705e8860200151896040015189886040518085815260200184815260200183815260200182815260200194505050505060405180910390a4801561134e57606088018051820190525b611358868661292d565b61136288886124e5565b5050505050505050505050565b60608060608385108015611389575060045461ffff168411155b6113cf576040805162461bcd60e51b81526020600482015260126024820152711154d40e881c985b99d9481a5b9d985b1a5960721b604482015290519081900360640190fd5b8484036040519080825280602002602001820160405280156113fb578160200160208202803883390190505b50925084840360405190808252806020026020018201604052801561142a578160200160208202803883390190505b509150848403604051908082528060200260200182016040528015611459578160200160208202803883390190505b5090508460005b60008281526005602052604090206002015485516001600160481b039091169086908390811061148c57fe5b602090810291909101810191909152600083815260059091526040902054845160018301926001600160481b0390921691869181106114c757fe5b60200260200101818152505060056000838152602001908152602001600020600101548382806001019350815181106114fc57fe5b6020026020010181815250508582600101925082106114605750509250925092565b6001600160a01b031660009081526020819052604090205490565b60076020526000908152604090205481565b611553612ffa565b61155b612ffa565b6115658282611fb3565b60018260e00151116115af576040805162461bcd60e51b815260206004820152600e60248201526d4553503a20546f6f206561726c7960901b604482015290519081900360640190fd5b8215611609578160e001518311156115f85760405162461bcd60e51b81526004018080602001828103825260268152602001806130fe6026913960400191505060405180910390fd5b611604828460006129e6565b611619565b611619828360e0015160006129e6565b61162382826124e5565b505050565b6005602052600090815260409020805460018201546002909201546001600160481b0391821692911683565b6000610a63611661611cd0565b84610af1856040518060600160405280602581526020016132a0602591396001600061168b611cd0565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff611f1c16565b6000610a636116cf611cd0565b8484611dc0565b6003546004546001600160481b0380831692600160481b810482169264ffffffffff600160901b8304811693600160b81b90930483169261ffff83169262010000810490911691600160581b9091041687565b6117316126c9565b8210611784576040805162461bcd60e51b815260206004820152601a60248201527f4553503a20526f756e64206973206e6f7420636f6d706c657465000000000000604482015290519081900360640190fd5b600082815260086020908152604080832033845290915281208054909164ffffffffff909116908315611816578254600160281b900464ffffffffff1682900384111561180d576040805162461bcd60e51b81526020600482015260126024820152711154d40e8818dbdd5b9d081a5b9d985b1a5960721b604482015290519081900360640190fd5b50808301611870565b508154600160281b900464ffffffffff16808210611870576040805162461bcd60e51b81526020600482015260126024820152711154d40e8818dbdd5b9d081a5b9d985b1a5960721b604482015290519081900360640190fd5b600061187b86612aa9565b6000878152600760205260408120549192505b600085815260018701602052604081208054908290556001600160601b03811691600160601b9091046001600160a01b03169084868402816118cc57fe5b0490506001600160a01b03821615806118ed57506001600160a01b03821633145b15611903576118fe8b898385612ae8565b611928565b6014810490810190600a820461191b8d8b8587612ae8565b611925848261220a565b50505b6001909701969290920191505083851061188e57855464ffffffffff191664ffffffffff8616178655801561196157611961338261220a565b5050505050505050565b60006119756126c9565b116119c7576040805162461bcd60e51b815260206004820152601e60248201527f4553503a2041756374696f6e20686173206e6f7420626567756e207965740000604482015290519081900360640190fd5b60006119d16126c9565b90503480611a1d576040805162461bcd60e51b81526020600482015260146024820152731154d40e88105b5bdd5b9d081c995c5d5a5c995960621b604482015290519081900360640190fd5b600082815260086020908152604080832033845282528083208054600164ffffffffff600160281b80840482168381019092160269ffffffffff000000000019909316929092178355835180850185526001600160601b0380891682526001600160a01b038b8116838901908152858a529386018852868920925183549451909116600160601b029082166bffffffffffffffffffffffff199094169390931716919091179055868552600784529382902080548601905581514281529283018690528151909392859284927f683f950243ca541a09abd8157385ce15a23ac43a47b8d0306de2bdc20d0b9e099281900390910190a35050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b611b4d6130a1565b60408051610140810182526003546001600160481b038082168352600160481b82048116602084015264ffffffffff600160901b8304811694840194909452600160b81b9091048116606083015260045461ffff8116608084015262010000810490911660a0830152600160581b900490911660c08201524260e08201526101008101611bd8610a6c565b815260200160076000611be96126c9565b815260200190815260200160002054815250905090565b60608183108015611c185750611c146126c9565b8211155b611c5e576040805162461bcd60e51b81526020600482015260126024820152714553503a20696e76616c69642072616e676560701b604482015290519081900360640190fd5b828203604051908082528060200260200182016040528015611c8a578160200160208202803883390190505b5090508260005b600082815260076020526040902054835160019384019383019285918110611cb557fe5b602002602001018181525050838210611c9157505092915050565b3390565b6001600160a01b038316611d195760405162461bcd60e51b81526004018080602001828103825260248152602001806132476024913960400191505060405180910390fd5b6001600160a01b038216611d5e5760405162461bcd60e51b81526004018080602001828103825260228152602001806131466022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316611e055760405162461bcd60e51b81526004018080602001828103825260258152602001806132226025913960400191505060405180910390fd5b6001600160a01b038216611e4a5760405162461bcd60e51b81526004018080602001828103825260238152602001806130db6023913960400191505060405180910390fd5b611e8d81604051806060016040528060268152602001613168602691396001600160a01b038616600090815260208190526040902054919063ffffffff611f1c16565b6001600160a01b038085166000908152602081905260408082209390935590841681522054611ec2908263ffffffff61266816565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115611fab5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611f70578181015183820152602001611f58565b50505050905090810190601f168015611f9d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6003546001600160481b038082168452600160481b82048116602085015264ffffffffff600160901b830481166040860152600160b81b9092048116606085015260045461ffff8116608086015262010000810490911660a0850152600160581b90041660c08301526120246126c9565b60e08301526120338282612b39565b5050565b825464ffffffffff838116911614612096576040805162461bcd60e51b815260206004820152601e60248201527f4553503a207374616b654964506172616d206e6f7420696e207374616b650000604482015290519081900360640190fd5b915464ffffffffff811683526001600160481b03600160281b820481166020850152600160701b820416604084015261ffff600160b81b820481166060850152600160c81b820481166080850152600160d81b9091041660a09092019190915250565b612109818260e0015160016129e6565b50565b604081015160a080840180519290920390915260e090920151910152565b60008060008060008660800151861015612186576121578888606001518960800151898b60400151612b81565b602089015160408a015160608b0151918401985092965090935061217f918a91898101612c2a565b92506121e0565b6040870151606088015161219e918a91898101612c7d565b93506121ba8888604001518960600151898b6060015101612c2a565b92508387602001510194506121dd876060015188608001518960a0015188612d1a565b91505b81156121ff57848211156121f757506000936121ff565b509283900392805b939792965093509350565b6001600160a01b038216612265576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b600254612278908263ffffffff61266816565b6002556001600160a01b0382166000908152602081905260409020546122a4908263ffffffff61266816565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b8160200151811115611623576000612316828460800151612d46565b905060008360400151620186a0838501028161232e57fe5b04905064ffffffffff811115612346575064ffffffffff5b846040015181111561239e5760408086018290528451815142815260208101849052825164ffffffffff909216927faf62aa7dadbf7e5e54b91236b109372266fcf681cc74f199a41e14c242a3db3f92918290030190a25b5050505050565b8154600019018181146124b4578281815481106123be57fe5b906000526020600020018383815481106123d457fe5b6000918252602090912082549101805464ffffffffff191664ffffffffff9092169190911780825582546001600160481b03600160281b9182900481169091026dffffffffffffffffff000000000019909216919091178083558354600160701b9081900490921690910268ffffffffffffffffff60701b1990911617808255825461ffff600160b81b91829004811690910261ffff60b81b19909216919091178083558354600160c81b9081900483160261ffff60c81b19909116178083559254600160d81b908190049091160261ffff60d81b199092169190911790555b828054806124be57fe5b600082815260209020810160001990810180546001600160e81b0319169055019055505050565b805182511415806124fe57508060200151826020015114155b8061251157508060400151826040015114155b8061252457508060600151826060015114155b156125b85781516003805460208501516040860151606087015168ffffffffffffffffff199093166001600160481b039586161771ffffffffffffffffff0000000000000000001916600160481b928616929092029190911764ffffffffff60901b1916600160901b64ffffffffff90921691909102176001600160b81b0316600160b81b93909116929092029190911790555b806080015182608001511415806125d757508060a001518260a0015114155b806125f857508060c0015164ffffffffff168260c0015164ffffffffff1614155b156120335760808201516004805460a085015160c086015164ffffffffff16600160581b0264ffffffffff60581b196001600160481b0390921662010000026affffffffffffffffff00001961ffff90961661ffff19909416939093179490941691909117169190911790555050565b6000828201838110156126c2576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000635fc193004210156126df57506000610a70565b506201518042635fc192ff190104610a70565b601e8111156127325760405162461bcd60e51b81526004018080602001828103825260268152602001806131fc6026913960400191505060405180910390fd5b600061273e8383612d46565b905060008460400151620186a0838601028161275657fe5b049050806127955760405162461bcd60e51b815260040180806020018281038252603581526020018061326b6035913960400191505060405180910390fd5b60e085015160c08601805164ffffffffff600191820116918290523360009081526006602052604090209201916127d090828886868a612db6565b60408051878152602081018590528082018790529051339164ffffffffff8416917fa75ea2f0baef0a6cfa36f61bc0cdc9b3a55ce8876892cf96f640208f65c799e99181900360600190a35050602085018051909101905250508151019052565b6001600160a01b0382166128765760405162461bcd60e51b81526004018080602001828103825260218152602001806131db6021913960400191505060405180910390fd5b6128b981604051806060016040528060228152602001613124602291396001600160a01b038516600090815260208190526040902054919063ffffffff611f1c16565b6001600160a01b0383166000908152602081905260409020556002546128e5908263ffffffff612ec116565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b80518254602083015160408401516060850151608086015160a09096015164ffffffffff1990941664ffffffffff909516949094176dffffffffffffffffff00000000001916600160281b6001600160481b03938416021768ffffffffffffffffff60701b1916600160701b92909116919091021761ffff60b81b1916600160b81b61ffff938416021761ffff60c81b1916600160c81b938316939093029290921761ffff60d81b1916600160d81b9190921602179055565b818360800151106129f657611623565b6129fe6130c0565b8351612a08610a6c565b0181526080840151612a1b858383612f03565b602085015115612a3b5760208501805160a0870180519091019052600090525b60010183811015612a5657612a51858383612f03565b612a3b565b60808501516040805142815260208101929092528181018390525133917fe00f6f1c2b3ba17574be0a8136275368d74f37631cf36525a360b272fe21195b919081900360600190a2608085015250505050565b60008082118015612abb5750605a8211155b15612ada575064e8d4a51000600019820102655af3107a400003612ae3565b506509184e72a0005b919050565b806001600160a01b031682847ff8fa88708321411fd98e823a1eb882047c8dc276ba17a8b81722ed282c4560f74288604051808381526020018281526020019250505060405180910390a450505050565b815181526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0808301519082015260c09182015164ffffffffff16910152565b60008083860160026001870104600f811015612b9b5750600f5b85612bbb576000612bad8a878b612f6b565b919091029250612c20915050565b85811015612bf057878101612bd28a878b84612c7d565b93506000612be28b888487612c7d565b85019550612c209350505050565b612bfc89868a85612c7d565b935085811415612c0e57839250612c1d565b8581850281612c1957fe5b0492505b50505b9550959350505050565b6000825b82811015612c7357600081815260056020526040812060028101546001909101546001600160481b0390911690870281612c6457fe5b04019190910190600101612c2e565b505b949350505050565b600080835b83811015612d10576000818152600560205260408120600281015490546001600160481b039182169116880281612cb557fe5b0490506004831015612ccc57600190920191612d03565b6000828152600560205260409020600281810154915490916001600160481b039081169116890281612cfa57fe5b04029050600092505b9290920191600101612c82565b5050949350505050565b6000848401600e01808411612d33576000915050612c75565b6102bc8185038402049695505050505050565b6000806001831115612d6c57610e38831115612d6457610e38612d69565b600183035b90505b600066027ca57357c000851115612d8a5766027ca57357c000612d8c565b845b6618de76816d8000830261071c8202019350905067b0cd9280267a00008584020495945050505050565b6040805160c08101825264ffffffffff96871681526001600160481b03958616602080830191825295871692820192835261ffff9485166060830190815293851660808301908152600060a084018181528b54600181018d559b825297902092519290990180549151935194519951965164ffffffffff1990921692909816919091176dffffffffffffffffff00000000001916600160281b928716929092029190911768ffffffffffffffffff60701b1916600160701b92909516919091029390931761ffff60b81b1916600160b81b958216959095029490941761ffff60c81b1916600160c81b918516919091021761ffff60d81b1916600160d81b9190931602919091179055565b60006126c283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611f1c565b612f0e838383612fc4565b60209182015160009182526005808452604080842080546001600160481b0394851668ffffffffffffffffff1991821617825560078752919094205491909452600183015560a09093015160029091018054919093169116179055565b6000612f75612ffa565b612f7f8582612b39565b612f876130c0565b8551612f91610a6c565b018152612f9f828286612fc4565b60a0820180518601908190526020820151860281612fb957fe5b049695505050505050565b815163041aa1899061c3500204602083015260608301511561162357606083018051602084018051909101905260009052505050565b604051806101000160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600064ffffffffff168152602001600081525090565b6040518060c00160405280600064ffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180604001604052806002906020820280388339509192915050565b604051806101400160405280600a906020820280388339509192915050565b60405180604001604052806000815260200160008152509056fe45524332303a207472616e7366657220746f20746865207a65726f20616464726573734553503a206265666f72654461792063616e6e6f7420626520696e207468652066757475726545524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63654553503a206e65775374616b656444617973206c6f776572207468616e206d696e696d756d45524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f20616464726573734553503a206e65775374616b65644461797320686967686572207468616e206d6178696d756d45524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573734553503a206e65775374616b656453756e73206d757374206265206174206c65617374206d696e696d756d2073686172655261746545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a7230582006af273706377a68b09951e6be9e7a5a10efc9c8510be59fcbdb32292e4b977864736f6c634300050a0032

Deployed Bytecode

0x6080604052600436106101cd5760003560e01c806365cf71b2116100f7578063a457c2d711610095578063ce7d1f7711610064578063ce7d1f7714610924578063dd62ed3e1461094a578063f04b5fa014610985578063f57a1b3c146109b0576101cd565b8063a457c2d714610819578063a9059cbb14610852578063c31245251461088b578063cbb151d3146108f4576101cd565b806387a0f31c116100d157806387a0f31c146107705780638f1c65c01461079a57806390de6871146107c457806395d89b41146101cf576101cd565b806365cf71b2146105e95780636a210a0e1461062f57806370a082311461073d576101cd565b806333060d901161016f57806344203faf1161013e57806344203faf146104d957806344f0de751461053657806352a438b8146105a45780635c9302c9146105d4576101cd565b806333060d9014610421578063343009a214610454578063395093511461048b5780633a70a5ca146104c4576101cd565b806323b872dd116101ab57806323b872dd146102cd5780632607443b146103105780632e60d1c414610396578063313ce567146103f6576101cd565b806306fdde03146101cf578063095ea7b31461025957806318160ddd146102a6575b005b3480156101db57600080fd5b506101e4610a30565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561021e578181015183820152602001610206565b50505050905090810190601f16801561024b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561026557600080fd5b506102926004803603604081101561027c57600080fd5b506001600160a01b038135169060200135610a4f565b604080519115158252519081900360200190f35b3480156102b257600080fd5b506102bb610a6c565b60408051918252519081900360200190f35b3480156102d957600080fd5b50610292600480360360608110156102f057600080fd5b506001600160a01b03813581169160208101359091169060400135610a73565b34801561031c57600080fd5b506103496004803603604081101561033357600080fd5b506001600160a01b038135169060200135610b00565b6040805164ffffffffff90971687526001600160481b039586166020880152939094168584015261ffff9182166060860152811660808501529190911660a0830152519081900360c00190f35b3480156103a257600080fd5b506103d5600480360360608110156103b957600080fd5b506001600160a01b038135169060208101359060400135610b6e565b604080519283526001600160a01b0390911660208301528051918290030190f35b34801561040257600080fd5b5061040b610c15565b6040805160ff9092168252519081900360200190f35b34801561042d57600080fd5b506102bb6004803603602081101561044457600080fd5b50356001600160a01b0316610c1a565b34801561046057600080fd5b506101cd6004803603604081101561047757600080fd5b508035906020013564ffffffffff16610c35565b34801561049757600080fd5b50610292600480360360408110156104ae57600080fd5b506001600160a01b038135169060200135610ef7565b3480156104d057600080fd5b506102bb610f4b565b3480156104e557600080fd5b50610512600480360360408110156104fc57600080fd5b50803590602001356001600160a01b0316610f68565b6040805164ffffffffff938416815291909216602082015281519081900390910190f35b34801561054257600080fd5b506105696004803603602081101561055957600080fd5b50356001600160a01b0316610f97565b6040518082600260200280838360005b83811015610591578181015183820152602001610579565b5050505090500191505060405180910390f35b3480156105b057600080fd5b506101cd600480360360408110156105c757600080fd5b5080359060200135611023565b3480156105e057600080fd5b506102bb6110ab565b3480156105f557600080fd5b506101cd6004803603606081101561060c57600080fd5b5080356001600160a01b0316906020810135906040013564ffffffffff166110ba565b34801561063b57600080fd5b5061065f6004803603604081101561065257600080fd5b508035906020013561136f565b60405180806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b838110156106a757818101518382015260200161068f565b50505050905001848103835286818151815260200191508051906020019060200280838360005b838110156106e65781810151838201526020016106ce565b50505050905001848103825285818151815260200191508051906020019060200280838360005b8381101561072557818101518382015260200161070d565b50505050905001965050505050505060405180910390f35b34801561074957600080fd5b506102bb6004803603602081101561076057600080fd5b50356001600160a01b031661151e565b34801561077c57600080fd5b506102bb6004803603602081101561079357600080fd5b5035611539565b3480156107a657600080fd5b506101cd600480360360208110156107bd57600080fd5b503561154b565b3480156107d057600080fd5b506107ee600480360360208110156107e757600080fd5b5035611628565b604080516001600160481b039485168152602081019390935292168183015290519081900360600190f35b34801561082557600080fd5b506102926004803603604081101561083c57600080fd5b506001600160a01b038135169060200135611654565b34801561085e57600080fd5b506102926004803603604081101561087557600080fd5b506001600160a01b0381351690602001356116c2565b34801561089757600080fd5b506108a06116d6565b604080516001600160481b039889168152968816602088015264ffffffffff95861687820152938716606087015261ffff909216608086015290941660a0840152921660c082015290519081900360e00190f35b34801561090057600080fd5b506101cd6004803603604081101561091757600080fd5b5080359060200135611729565b6101cd6004803603602081101561093a57600080fd5b50356001600160a01b031661196b565b34801561095657600080fd5b506102bb6004803603604081101561096d57600080fd5b506001600160a01b0381358116916020013516611b1a565b34801561099157600080fd5b5061099a611b45565b6040518151815280826101408083836020610579565b3480156109bc57600080fd5b506109e0600480360360408110156109d357600080fd5b5080359060200135611c00565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610a1c578181015183820152602001610a04565b505050509050019250505060405180910390f35b6040518060400160405280600381526020016204553560ec1b81525081565b6000610a63610a5c611cd0565b8484611cd4565b50600192915050565b6002545b90565b6000610a80848484611dc0565b610af684610a8c611cd0565b610af1856040518060600160405280602881526020016131b3602891396001600160a01b038a16600090815260016020526040812090610aca611cd0565b6001600160a01b03168152602081019190915260400160002054919063ffffffff611f1c16565b611cd4565b5060019392505050565b60066020528160005260406000208181548110610b1957fe5b60009182526020909120015464ffffffffff811692506001600160481b03600160281b820481169250600160701b8204169061ffff600160b81b8204811691600160c81b8104821691600160d81b9091041686565b60008281526008602090815260408083206001600160a01b03871684528252808320848452600101909152812080548291906001600160601b0316610bef576040805162461bcd60e51b81526020600482015260126024820152711154d40e8814185c985b481a5b9d985b1a5960721b604482015290519081900360640190fd5b546001600160601b03811696600160601b9091046001600160a01b031695509350505050565b600881565b6001600160a01b031660009081526006602052604090205490565b610c3d612ffa565b610c45612ffa565b610c4f8282611fb3565b3360009081526006602052604090208054610ca9576040805162461bcd60e51b81526020600482015260156024820152741154d40e88115b5c1d1e481cdd185ad9481b1a5cdd605a1b604482015290519081900360640190fd5b80548510610cf8576040805162461bcd60e51b81526020600482015260176024820152761154d40e881cdd185ad9525b99195e081a5b9d985b1a59604a1b604482015290519081900360640190fd5b610d00613046565b610d20828781548110610d0f57fe5b906000526020600020018683612037565b610d29846120f9565b60a0810151606082015160e08601516000921515918391829182918291829110610dd5578515610d5f5787608001519650610d8a565b610d698b8961210c565b87606001518b60e001510396508760800151871115610d8a57876080015196505b610d958b898961212a565b60405194995092975090955093509150339084156108fc029085906000818181858888f19350505050158015610dcf573d6000803e3d6000fd5b50610dee565b60408801516020808d0180519290920390915288015194505b3364ffffffffff8d167f80bb257dd672adb291601517b3f5d31642fccf6d3db7a40983552a9baacbbabd88610e24576000610e27565b60015b8b606001518b8d602001518e604001518a8c8b8f604051808a60ff1664ffffffffff168152602001898152602001888152602001878152602001868152602001858152602001848152602001838152602001828152602001995050505050505050505060405180910390a38015801590610e9f575085155b15610eaf5760608b018051820190525b8415610eca57610ebf338661220a565b610eca8b89876122fa565b60208801518b51038b52610ede898e6123a5565b610ee88b8b6124e5565b50505050505050505050505050565b6000610a63610f04611cd0565b84610af18560016000610f15611cd0565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff61266816565b6003546000906001600160481b0316610f62610a6c565b01905090565b600860209081526000928352604080842090915290825290205464ffffffffff80821691600160281b90041682565b610f9f613083565b6000610fa96126c9565b60010190505b6000198101901561101d5760008181526008602090815260408083206001600160a01b038716845290915290205464ffffffffff808216600160281b90920416111561101857600160ff82161b82600883901c6002811061100c57fe5b60200201805190911790525b610faf565b50919050565b61102b612ffa565b611033612ffa565b61103d8282611fb3565b600183101561107d5760405162461bcd60e51b815260040180806020018281038252602581526020018061318e6025913960400191505060405180910390fd5b611086826120f9565b6110918285856126f2565b61109b3385612831565b6110a582826124e5565b50505050565b60006110b56126c9565b905090565b6110c2612ffa565b6110ca612ffa565b6110d48282611fb3565b6001600160a01b038516600090815260066020526040902054611136576040805162461bcd60e51b81526020600482015260156024820152741154d40e88115b5c1d1e481cdd185ad9481b1a5cdd605a1b604482015290519081900360640190fd5b6001600160a01b038516600090815260066020526040902054841061119c576040805162461bcd60e51b81526020600482015260176024820152761154d40e881cdd185ad9525b99195e081a5b9d985b1a59604a1b604482015290519081900360640190fd5b6001600160a01b03851660009081526006602052604081208054869081106111c057fe5b9060005260206000200190506111d4613046565b6111df828683612037565b80608001518160600151018460e001511015611242576040805162461bcd60e51b815260206004820152601b60248201527f4553503a205374616b65206e6f742066756c6c79207365727665640000000000604482015290519081900360640190fd5b60a081015115611299576040805162461bcd60e51b815260206004820152601b60248201527f4553503a205374616b6520616c726561647920756e6c6f636b65640000000000604482015290519081900360640190fd5b6112a2846120f9565b6112ac848261210c565b6000806000806112c18886876080015161212a565b945094509450945050336001600160a01b03168b6001600160a01b03168a64ffffffffff167f0bff00790f1231cf0c26911db2d0c4e670b204ebb02d6a73d3fb5c995910705e8860200151896040015189886040518085815260200184815260200183815260200182815260200194505050505060405180910390a4801561134e57606088018051820190525b611358868661292d565b61136288886124e5565b5050505050505050505050565b60608060608385108015611389575060045461ffff168411155b6113cf576040805162461bcd60e51b81526020600482015260126024820152711154d40e881c985b99d9481a5b9d985b1a5960721b604482015290519081900360640190fd5b8484036040519080825280602002602001820160405280156113fb578160200160208202803883390190505b50925084840360405190808252806020026020018201604052801561142a578160200160208202803883390190505b509150848403604051908082528060200260200182016040528015611459578160200160208202803883390190505b5090508460005b60008281526005602052604090206002015485516001600160481b039091169086908390811061148c57fe5b602090810291909101810191909152600083815260059091526040902054845160018301926001600160481b0390921691869181106114c757fe5b60200260200101818152505060056000838152602001908152602001600020600101548382806001019350815181106114fc57fe5b6020026020010181815250508582600101925082106114605750509250925092565b6001600160a01b031660009081526020819052604090205490565b60076020526000908152604090205481565b611553612ffa565b61155b612ffa565b6115658282611fb3565b60018260e00151116115af576040805162461bcd60e51b815260206004820152600e60248201526d4553503a20546f6f206561726c7960901b604482015290519081900360640190fd5b8215611609578160e001518311156115f85760405162461bcd60e51b81526004018080602001828103825260268152602001806130fe6026913960400191505060405180910390fd5b611604828460006129e6565b611619565b611619828360e0015160006129e6565b61162382826124e5565b505050565b6005602052600090815260409020805460018201546002909201546001600160481b0391821692911683565b6000610a63611661611cd0565b84610af1856040518060600160405280602581526020016132a0602591396001600061168b611cd0565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff611f1c16565b6000610a636116cf611cd0565b8484611dc0565b6003546004546001600160481b0380831692600160481b810482169264ffffffffff600160901b8304811693600160b81b90930483169261ffff83169262010000810490911691600160581b9091041687565b6117316126c9565b8210611784576040805162461bcd60e51b815260206004820152601a60248201527f4553503a20526f756e64206973206e6f7420636f6d706c657465000000000000604482015290519081900360640190fd5b600082815260086020908152604080832033845290915281208054909164ffffffffff909116908315611816578254600160281b900464ffffffffff1682900384111561180d576040805162461bcd60e51b81526020600482015260126024820152711154d40e8818dbdd5b9d081a5b9d985b1a5960721b604482015290519081900360640190fd5b50808301611870565b508154600160281b900464ffffffffff16808210611870576040805162461bcd60e51b81526020600482015260126024820152711154d40e8818dbdd5b9d081a5b9d985b1a5960721b604482015290519081900360640190fd5b600061187b86612aa9565b6000878152600760205260408120549192505b600085815260018701602052604081208054908290556001600160601b03811691600160601b9091046001600160a01b03169084868402816118cc57fe5b0490506001600160a01b03821615806118ed57506001600160a01b03821633145b15611903576118fe8b898385612ae8565b611928565b6014810490810190600a820461191b8d8b8587612ae8565b611925848261220a565b50505b6001909701969290920191505083851061188e57855464ffffffffff191664ffffffffff8616178655801561196157611961338261220a565b5050505050505050565b60006119756126c9565b116119c7576040805162461bcd60e51b815260206004820152601e60248201527f4553503a2041756374696f6e20686173206e6f7420626567756e207965740000604482015290519081900360640190fd5b60006119d16126c9565b90503480611a1d576040805162461bcd60e51b81526020600482015260146024820152731154d40e88105b5bdd5b9d081c995c5d5a5c995960621b604482015290519081900360640190fd5b600082815260086020908152604080832033845282528083208054600164ffffffffff600160281b80840482168381019092160269ffffffffff000000000019909316929092178355835180850185526001600160601b0380891682526001600160a01b038b8116838901908152858a529386018852868920925183549451909116600160601b029082166bffffffffffffffffffffffff199094169390931716919091179055868552600784529382902080548601905581514281529283018690528151909392859284927f683f950243ca541a09abd8157385ce15a23ac43a47b8d0306de2bdc20d0b9e099281900390910190a35050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b611b4d6130a1565b60408051610140810182526003546001600160481b038082168352600160481b82048116602084015264ffffffffff600160901b8304811694840194909452600160b81b9091048116606083015260045461ffff8116608084015262010000810490911660a0830152600160581b900490911660c08201524260e08201526101008101611bd8610a6c565b815260200160076000611be96126c9565b815260200190815260200160002054815250905090565b60608183108015611c185750611c146126c9565b8211155b611c5e576040805162461bcd60e51b81526020600482015260126024820152714553503a20696e76616c69642072616e676560701b604482015290519081900360640190fd5b828203604051908082528060200260200182016040528015611c8a578160200160208202803883390190505b5090508260005b600082815260076020526040902054835160019384019383019285918110611cb557fe5b602002602001018181525050838210611c9157505092915050565b3390565b6001600160a01b038316611d195760405162461bcd60e51b81526004018080602001828103825260248152602001806132476024913960400191505060405180910390fd5b6001600160a01b038216611d5e5760405162461bcd60e51b81526004018080602001828103825260228152602001806131466022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b038316611e055760405162461bcd60e51b81526004018080602001828103825260258152602001806132226025913960400191505060405180910390fd5b6001600160a01b038216611e4a5760405162461bcd60e51b81526004018080602001828103825260238152602001806130db6023913960400191505060405180910390fd5b611e8d81604051806060016040528060268152602001613168602691396001600160a01b038616600090815260208190526040902054919063ffffffff611f1c16565b6001600160a01b038085166000908152602081905260408082209390935590841681522054611ec2908263ffffffff61266816565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115611fab5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611f70578181015183820152602001611f58565b50505050905090810190601f168015611f9d5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6003546001600160481b038082168452600160481b82048116602085015264ffffffffff600160901b830481166040860152600160b81b9092048116606085015260045461ffff8116608086015262010000810490911660a0850152600160581b90041660c08301526120246126c9565b60e08301526120338282612b39565b5050565b825464ffffffffff838116911614612096576040805162461bcd60e51b815260206004820152601e60248201527f4553503a207374616b654964506172616d206e6f7420696e207374616b650000604482015290519081900360640190fd5b915464ffffffffff811683526001600160481b03600160281b820481166020850152600160701b820416604084015261ffff600160b81b820481166060850152600160c81b820481166080850152600160d81b9091041660a09092019190915250565b612109818260e0015160016129e6565b50565b604081015160a080840180519290920390915260e090920151910152565b60008060008060008660800151861015612186576121578888606001518960800151898b60400151612b81565b602089015160408a015160608b0151918401985092965090935061217f918a91898101612c2a565b92506121e0565b6040870151606088015161219e918a91898101612c7d565b93506121ba8888604001518960600151898b6060015101612c2a565b92508387602001510194506121dd876060015188608001518960a0015188612d1a565b91505b81156121ff57848211156121f757506000936121ff565b509283900392805b939792965093509350565b6001600160a01b038216612265576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b600254612278908263ffffffff61266816565b6002556001600160a01b0382166000908152602081905260409020546122a4908263ffffffff61266816565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b8160200151811115611623576000612316828460800151612d46565b905060008360400151620186a0838501028161232e57fe5b04905064ffffffffff811115612346575064ffffffffff5b846040015181111561239e5760408086018290528451815142815260208101849052825164ffffffffff909216927faf62aa7dadbf7e5e54b91236b109372266fcf681cc74f199a41e14c242a3db3f92918290030190a25b5050505050565b8154600019018181146124b4578281815481106123be57fe5b906000526020600020018383815481106123d457fe5b6000918252602090912082549101805464ffffffffff191664ffffffffff9092169190911780825582546001600160481b03600160281b9182900481169091026dffffffffffffffffff000000000019909216919091178083558354600160701b9081900490921690910268ffffffffffffffffff60701b1990911617808255825461ffff600160b81b91829004811690910261ffff60b81b19909216919091178083558354600160c81b9081900483160261ffff60c81b19909116178083559254600160d81b908190049091160261ffff60d81b199092169190911790555b828054806124be57fe5b600082815260209020810160001990810180546001600160e81b0319169055019055505050565b805182511415806124fe57508060200151826020015114155b8061251157508060400151826040015114155b8061252457508060600151826060015114155b156125b85781516003805460208501516040860151606087015168ffffffffffffffffff199093166001600160481b039586161771ffffffffffffffffff0000000000000000001916600160481b928616929092029190911764ffffffffff60901b1916600160901b64ffffffffff90921691909102176001600160b81b0316600160b81b93909116929092029190911790555b806080015182608001511415806125d757508060a001518260a0015114155b806125f857508060c0015164ffffffffff168260c0015164ffffffffff1614155b156120335760808201516004805460a085015160c086015164ffffffffff16600160581b0264ffffffffff60581b196001600160481b0390921662010000026affffffffffffffffff00001961ffff90961661ffff19909416939093179490941691909117169190911790555050565b6000828201838110156126c2576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6000635fc193004210156126df57506000610a70565b506201518042635fc192ff190104610a70565b601e8111156127325760405162461bcd60e51b81526004018080602001828103825260268152602001806131fc6026913960400191505060405180910390fd5b600061273e8383612d46565b905060008460400151620186a0838601028161275657fe5b049050806127955760405162461bcd60e51b815260040180806020018281038252603581526020018061326b6035913960400191505060405180910390fd5b60e085015160c08601805164ffffffffff600191820116918290523360009081526006602052604090209201916127d090828886868a612db6565b60408051878152602081018590528082018790529051339164ffffffffff8416917fa75ea2f0baef0a6cfa36f61bc0cdc9b3a55ce8876892cf96f640208f65c799e99181900360600190a35050602085018051909101905250508151019052565b6001600160a01b0382166128765760405162461bcd60e51b81526004018080602001828103825260218152602001806131db6021913960400191505060405180910390fd5b6128b981604051806060016040528060228152602001613124602291396001600160a01b038516600090815260208190526040902054919063ffffffff611f1c16565b6001600160a01b0383166000908152602081905260409020556002546128e5908263ffffffff612ec116565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b80518254602083015160408401516060850151608086015160a09096015164ffffffffff1990941664ffffffffff909516949094176dffffffffffffffffff00000000001916600160281b6001600160481b03938416021768ffffffffffffffffff60701b1916600160701b92909116919091021761ffff60b81b1916600160b81b61ffff938416021761ffff60c81b1916600160c81b938316939093029290921761ffff60d81b1916600160d81b9190921602179055565b818360800151106129f657611623565b6129fe6130c0565b8351612a08610a6c565b0181526080840151612a1b858383612f03565b602085015115612a3b5760208501805160a0870180519091019052600090525b60010183811015612a5657612a51858383612f03565b612a3b565b60808501516040805142815260208101929092528181018390525133917fe00f6f1c2b3ba17574be0a8136275368d74f37631cf36525a360b272fe21195b919081900360600190a2608085015250505050565b60008082118015612abb5750605a8211155b15612ada575064e8d4a51000600019820102655af3107a400003612ae3565b506509184e72a0005b919050565b806001600160a01b031682847ff8fa88708321411fd98e823a1eb882047c8dc276ba17a8b81722ed282c4560f74288604051808381526020018281526020019250505060405180910390a450505050565b815181526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0808301519082015260c09182015164ffffffffff16910152565b60008083860160026001870104600f811015612b9b5750600f5b85612bbb576000612bad8a878b612f6b565b919091029250612c20915050565b85811015612bf057878101612bd28a878b84612c7d565b93506000612be28b888487612c7d565b85019550612c209350505050565b612bfc89868a85612c7d565b935085811415612c0e57839250612c1d565b8581850281612c1957fe5b0492505b50505b9550959350505050565b6000825b82811015612c7357600081815260056020526040812060028101546001909101546001600160481b0390911690870281612c6457fe5b04019190910190600101612c2e565b505b949350505050565b600080835b83811015612d10576000818152600560205260408120600281015490546001600160481b039182169116880281612cb557fe5b0490506004831015612ccc57600190920191612d03565b6000828152600560205260409020600281810154915490916001600160481b039081169116890281612cfa57fe5b04029050600092505b9290920191600101612c82565b5050949350505050565b6000848401600e01808411612d33576000915050612c75565b6102bc8185038402049695505050505050565b6000806001831115612d6c57610e38831115612d6457610e38612d69565b600183035b90505b600066027ca57357c000851115612d8a5766027ca57357c000612d8c565b845b6618de76816d8000830261071c8202019350905067b0cd9280267a00008584020495945050505050565b6040805160c08101825264ffffffffff96871681526001600160481b03958616602080830191825295871692820192835261ffff9485166060830190815293851660808301908152600060a084018181528b54600181018d559b825297902092519290990180549151935194519951965164ffffffffff1990921692909816919091176dffffffffffffffffff00000000001916600160281b928716929092029190911768ffffffffffffffffff60701b1916600160701b92909516919091029390931761ffff60b81b1916600160b81b958216959095029490941761ffff60c81b1916600160c81b918516919091021761ffff60d81b1916600160d81b9190931602919091179055565b60006126c283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611f1c565b612f0e838383612fc4565b60209182015160009182526005808452604080842080546001600160481b0394851668ffffffffffffffffff1991821617825560078752919094205491909452600183015560a09093015160029091018054919093169116179055565b6000612f75612ffa565b612f7f8582612b39565b612f876130c0565b8551612f91610a6c565b018152612f9f828286612fc4565b60a0820180518601908190526020820151860281612fb957fe5b049695505050505050565b815163041aa1899061c3500204602083015260608301511561162357606083018051602084018051909101905260009052505050565b604051806101000160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600064ffffffffff168152602001600081525090565b6040518060c00160405280600064ffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081525090565b60405180604001604052806002906020820280388339509192915050565b604051806101400160405280600a906020820280388339509192915050565b60405180604001604052806000815260200160008152509056fe45524332303a207472616e7366657220746f20746865207a65726f20616464726573734553503a206265666f72654461792063616e6e6f7420626520696e207468652066757475726545524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63654553503a206e65775374616b656444617973206c6f776572207468616e206d696e696d756d45524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a206275726e2066726f6d20746865207a65726f20616464726573734553503a206e65775374616b65644461797320686967686572207468616e206d6178696d756d45524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573734553503a206e65775374616b656453756e73206d757374206265206174206c65617374206d696e696d756d2073686172655261746545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a7230582006af273706377a68b09951e6be9e7a5a10efc9c8510be59fcbdb32292e4b977864736f6c634300050a0032

Deployed Bytecode Sourcemap

61933:233:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19132:35;;8:9:-1;5:2;;;30:1;27;20:12;5:2;19132:35:0;;;:::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;19132:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11550:152;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11550:152:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;11550:152:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;10575:91;;8:9:-1;5:2;;;30:1;27;20:12;5:2;10575:91:0;;;:::i;:::-;;;;;;;;;;;;;;;;12173:304;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12173:304:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;12173:304:0;;;;;;;;;;;;;;;;;:::i;23124:50::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;23124:50:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;23124:50:0;;;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;;;23124:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60056:406;;8:9:-1;5:2;;;30:1;27;20:12;5:2;60056:406:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;60056:406:0;;;;;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;60056:406:0;;;;;;;;;;;;;;;;19218:34;;8:9:-1;5:2;;;30:1;27;20:12;5:2;19218:34:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;42183:159;;8:9:-1;5:2;;;30:1;27;20:12;5:2;42183:159:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;42183:159:0;-1:-1:-1;;;;;42183:159:0;;:::i;39264:2769::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;39264:2769:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;39264:2769:0;;;;;;;;;:::i;12885:210::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12885:210:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;12885:210:0;;;;;;;;:::i;26844:156::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;26844:156:0;;;:::i;23645:79::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;23645:79:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;23645:79:0;;;;;;-1:-1:-1;;;;;23645:79:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;60673:438;;8:9:-1;5:2;;;30:1;27;20:12;5:2;60673:438:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;60673:438:0;-1:-1:-1;;;;;60673:438:0;;:::i;:::-;;;;;;;;;;;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;60673:438:0;;;;;;;;;;;;;;;;36227:633;;8:9:-1;5:2;;;30:1;27;20:12;5:2;36227:633:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;36227:633:0;;;;;;;:::i;27163:125::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;27163:125:0;;;:::i;37228:1770::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;37228:1770:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37228:1770:0;;-1:-1:-1;;;;;37228:1770:0;;;;;;;;;;;;;:::i;24973:922::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;24973:922:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;24973:922:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;24973:922: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;24973:922: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;24973:922:0;;;;;;;;;;;;;;;;;;;;;10728:110;;8:9:-1;5:2;;;30:1;27;20:12;5:2;10728:110:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;10728:110:0;-1:-1:-1;;;;;10728:110:0;;:::i;23596:42::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;23596:42:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;23596:42:0;;:::i;23977:659::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;23977:659:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;23977:659:0;;:::i;22574:51::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;22574:51:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;22574:51:0;;:::i;:::-;;;;-1:-1:-1;;;;;22574:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;13597:261;;8:9:-1;5:2;;;30:1;27;20:12;5:2;13597:261:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;13597:261:0;;;;;;;;:::i;11050:158::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11050:158:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;11050:158:0;;;;;;;;:::i;22378:27::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;22378:27:0;;;:::i;:::-;;;;-1:-1:-1;;;;;22378:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56951:1939;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56951:1939:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;56951:1939:0;;;;;;;:::i;55997:712::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;55997:712:0;-1:-1:-1;;;;;55997:712:0;;:::i;11270:134::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11270:134:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;11270:134:0;;;;;;;;;;:::i;26128:496::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;26128:496:0;;;:::i;:::-;;;84:18:-1;;64:39;;26128:496:0;;;;;;52:2:-1;8:100;;59173:501:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59173:501:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;59173:501:0;;;;;;;:::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;59173:501:0;;;;;;;;;;;;;;;;;19132:35;;;;;;;;;;;;;;-1:-1:-1;;;19132:35:0;;;;:::o;11550:152::-;11616:4;11633:39;11642:12;:10;:12::i;:::-;11656:7;11665:6;11633:8;:39::i;:::-;-1:-1:-1;11690:4:0;11550:152;;;;:::o;10575:91::-;10646:12;;10575:91;;:::o;12173:304::-;12262:4;12279:36;12289:6;12297:9;12308:6;12279:9;:36::i;:::-;12326:121;12335:6;12343:12;:10;:12::i;:::-;12357:89;12395:6;12357:89;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;12357:19:0;;;;;;:11;:19;;;;;;12377:12;:10;:12::i;:::-;-1:-1:-1;;;;;12357:33:0;;;;;;;;;;;;-1:-1:-1;12357:33:0;;;:89;;:37;:89;:::i;:::-;12326:8;:121::i;:::-;-1:-1:-1;12465:4:0;12173:304;;;;;:::o;23124:50::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;23124:50:0;;;;;-1:-1:-1;;;;23124:50:0;;;;;-1:-1:-1;;;23124:50:0;;;;;-1:-1:-1;;;23124:50:0;;;;;-1:-1:-1;;;23124:50:0;;;;;:::o;60056:406::-;60186:17;60277:24;;;:14;:24;;;;;;;;-1:-1:-1;;;;;60277:36:0;;;;;;;;;:56;;;:44;;:56;;;;;60354:15;;60186:17;;60277:56;-1:-1:-1;;;;;60354:15:0;60346:51;;;;;-1:-1:-1;;;60346:51:0;;;;;;;;;;;;-1:-1:-1;;;60346:51:0;;;;;;;;;;;;;;;60418:15;-1:-1:-1;;;;;60418:15:0;;;-1:-1:-1;;;60435:18:0;;;-1:-1:-1;;;;;60435:18:0;;-1:-1:-1;60056:406:0;-1:-1:-1;;;;60056:406:0:o;19218:34::-;19251:1;19218:34;:::o;42183:159::-;-1:-1:-1;;;;;42305:22:0;42273:7;42305:22;;;:10;:22;;;;;:29;;42183:159::o;39264:2769::-;39357:21;;:::i;:::-;39389:29;;:::i;:::-;39429:26;39442:1;39445:9;39429:12;:26::i;:::-;39515:10;39468:33;39504:22;;;:10;:22;;;;;39618:19;;39610:58;;;;;-1:-1:-1;;;39610:58:0;;;;;;;;;;;;-1:-1:-1;;;39610:58:0;;;;;;;;;;;;;;;39700:19;;39687:32;;39679:68;;;;;-1:-1:-1;;;39679:68:0;;;;;;;;;;;;-1:-1:-1;;;39679:68:0;;;;;;;;;;;;;;;39790:20;;:::i;:::-;39821:54;39832:12;39845:10;39832:24;;;;;;;;;;;;;;;39858:12;39872:2;39821:10;:54::i;:::-;39941:23;39962:1;39941:20;:23::i;:::-;40033:15;;;;40245:13;;;;40228;;;;39977:18;;40033:20;;;39977:18;;;;;;;;;;40228:30;40224:858;;40279:12;40275:423;;;40424:2;:14;;;40411:27;;40275:423;;;40479:19;40492:1;40495:2;40479:12;:19::i;:::-;40548:2;:13;;;40532:1;:13;;;:29;40519:42;;40597:2;:14;;;40584:10;:27;40580:103;;;40649:2;:14;;;40636:27;;40580:103;40773:36;40791:1;40794:2;40798:10;40773:17;:36::i;:::-;40826:30;;40714:95;;-1:-1:-1;40714:95:0;;-1:-1:-1;40714:95:0;;-1:-1:-1;40714:95:0;-1:-1:-1;40714:95:0;-1:-1:-1;40826:10:0;;:30;;;;;40714:95;;40826:30;;;;40714:95;40826:10;:30;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;40826:30:0;40224:858;;;41010:15;;;;40983:23;;;;:42;;;;;;;;;41056:14;;;;-1:-1:-1;40224:858:0;41185:10;41099:316;;;;41150:12;:20;;41169:1;41150:20;;;41165:1;41150:20;41210:2;:13;;;41238:10;41264:2;:14;;;41294:2;:15;;;41325:9;41349:6;41371:7;41393:11;41099:316;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41432:18;;;;;:35;;;41455:12;41454:13;41432:35;41428:204;;;41583:20;;;:37;;;;;;41428:204;41707:16;;41703:186;;41740:30;41746:10;41758:11;41740:5;:30::i;:::-;41841:36;41858:1;41861:2;41865:11;41841:16;:36::i;:::-;41921:14;;;;41899:36;;;;;41948:38;41961:12;41975:10;41948:12;:38::i;:::-;41999:26;42012:1;42015:9;41999:12;:26::i;:::-;39264:2769;;;;;;;;;;;;;:::o;12885:210::-;12965:4;12982:83;12991:12;:10;:12::i;:::-;13005:7;13014:50;13053:10;13014:11;:25;13026:12;:10;:12::i;:::-;-1:-1:-1;;;;;13014:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;13014:25:0;;;:34;;;;;;;;;;;:50;:38;:50;:::i;26844:156::-;26969:7;:23;26921:7;;-1:-1:-1;;;;;26969:23:0;26953:13;:11;:13::i;:::-;:39;26946:46;;26844:156;:::o;23645:79::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;23645:79:0;;;;:::o;60673:438::-;60771:40;;:::i;:::-;60829:11;60843:13;:11;:13::i;:::-;60859:1;60843:17;60829:31;;60873:206;-1:-1:-1;;60880:5:0;;;:10;60873:206;;60955:19;;;;:14;:19;;;;;;;;-1:-1:-1;;;;;60955:31:0;;;;;;;;;:41;;;;;-1:-1:-1;;;60911:41:0;;;;:85;60907:161;;;61036:1;61048:3;61042:9;;61036:16;61017:5;61030:1;61023:8;;;61017:15;;;;;;;;;;:35;;;;;;;60907:161;60873:206;;;-1:-1:-1;60673:438:0;;;:::o;36227:633::-;36327:21;;:::i;:::-;36359:29;;:::i;:::-;36399:26;36412:1;36415:9;36399:12;:26::i;:::-;20194:1;36492:13;:31;;36484:81;;;;-1:-1:-1;;;36484:81:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36631:23;36652:1;36631:20;:23::i;:::-;36667:44;36679:1;36682:13;36697;36667:11;:44::i;:::-;36781:32;36787:10;36799:13;36781:5;:32::i;:::-;36826:26;36839:1;36842:9;36826:12;:26::i;:::-;36227:633;;;;:::o;27163:125::-;27235:7;27267:13;:11;:13::i;:::-;27260:20;;27163:125;:::o;37228:1770::-;37352:21;;:::i;:::-;37384:29;;:::i;:::-;37424:26;37437:1;37440:9;37424:12;:26::i;:::-;-1:-1:-1;;;;;37542:22:0;;;;;;:10;:22;;;;;:29;37534:68;;;;;-1:-1:-1;;;37534:68:0;;;;;;;;;;;;-1:-1:-1;;;37534:68:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;37634:22:0;;;;;;:10;:22;;;;;:29;37621:42;;37613:78;;;;;-1:-1:-1;;;37613:78:0;;;;;;;;;;;;-1:-1:-1;;;37613:78:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;37731:22:0;;37704:24;37731:22;;;:10;:22;;;;;:34;;37754:10;;37731:34;;;;;;;;;;;;;37704:61;;37808:20;;:::i;:::-;37839:35;37850:5;37857:12;37871:2;37839:10;:35::i;:::-;37976:2;:14;;;37960:2;:13;;;:30;37943:1;:13;;;:47;;37935:87;;;;;-1:-1:-1;;;37935:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;38085:15;;;;:20;38077:60;;;;;-1:-1:-1;;;38077:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;38203:23;38224:1;38203:20;:23::i;:::-;38281:19;38294:1;38297:2;38281:12;:19::i;:::-;38378:14;38394:17;38413:15;38430:21;38455:90;38487:1;38503:2;38520;:14;;;38455:17;:90::i;:::-;38375:170;;;;;;;;;38649:10;-1:-1:-1;;;;;38563:209:0;38624:10;-1:-1:-1;;;;;38563:209:0;38597:12;38563:209;;;38674:2;:14;;;38703:2;:15;;;38733:6;38754:7;38563:209;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;38789:18;;38785:88;;38824:20;;;:37;;;;;;38785:88;38928:23;38941:5;38948:2;38928:12;:23::i;:::-;38964:26;38977:1;38980:9;38964:12;:26::i;:::-;37228:1770;;;;;;;;;;;:::o;24973:922::-;25081:37;25120:32;25154:30;25221:6;25210:8;:17;:53;;;;-1:-1:-1;25241:22:0;;;;25231:32;;;25210:53;25202:84;;;;;-1:-1:-1;;;25202:84:0;;;;;;;;;;;;-1:-1:-1;;;25202:84:0;;;;;;;;;;;;;;;25345:8;25336:6;:17;25322:32;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;25322:32:0;;25299:55;;25406:8;25397:6;:17;25383:32;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;25383:32:0;;25365:50;;25465:8;25456:6;:17;25442:32;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;25442:32:0;-1:-1:-1;25426:48:0;-1:-1:-1;25501:8:0;25487:11;25546:268;25600:14;;;;:9;:14;;;;;:34;;;25564:25;;-1:-1:-1;;;;;25600:34:0;;;;25564:20;;25585:3;;25564:25;;;;;;;;;;;;;;;;:71;;;;25683:14;;;;:9;:14;;;;;;:29;25650:22;;25683:29;25666:5;;;-1:-1:-1;;;;;25683:29:0;;;;25650:15;;:22;;;;;;;;;;;:63;;;;;25751:9;:14;25761:3;25751:14;;;;;;;;;;;:27;;;25728:13;25742:5;;;;;;25728:20;;;;;;;;;;;;;:50;;;;;25806:6;25798:5;;;;;;:14;25546:268;;-1:-1:-1;;24973:922:0;;;;;:::o;10728:110::-;-1:-1:-1;;;;;10812:18:0;10785:7;10812:18;;;;;;;;;;;;10728:110::o;23596:42::-;;;;;;;;;;;;;:::o;23977:659::-;24055:21;;:::i;:::-;24087:29;;:::i;:::-;24127:26;24140:1;24143:9;24127:12;:26::i;:::-;19642:1;24211;:13;;;:37;24203:64;;;;;-1:-1:-1;;;24203:64:0;;;;;;;;;;;;-1:-1:-1;;;24203:64:0;;;;;;;;;;;;;;;24284:14;;24280:310;;24336:1;:13;;;24323:9;:26;;24315:77;;;;-1:-1:-1;;;24315:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24409:37;24426:1;24429:9;24440:5;24409:16;:37::i;:::-;24280:310;;;24537:41;24554:1;24557;:13;;;24572:5;24537:16;:41::i;:::-;24602:26;24615:1;24618:9;24602:12;:26::i;:::-;23977:659;;;:::o;22574:51::-;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;22574:51:0;;;;;;;:::o;13597:261::-;13682:4;13699:129;13708:12;:10;:12::i;:::-;13722:7;13731:96;13770:15;13731:96;;;;;;;;;;;;;;;;;:11;:25;13743:12;:10;:12::i;:::-;-1:-1:-1;;;;;13731:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;13731:25:0;;;:34;;;;;;;;;;;:96;;:38;:96;:::i;11050:158::-;11119:4;11136:42;11146:12;:10;:12::i;:::-;11160:9;11171:6;11136:9;:42::i;22378:27::-;;;;;-1:-1:-1;;;;;22378:27:0;;;;-1:-1:-1;;;22378:27:0;;;;;;-1:-1:-1;;;22378:27:0;;;;;-1:-1:-1;;;22378:27:0;;;;;;;;;;;;;;;;;-1:-1:-1;;;22378:27:0;;;;;:::o;56951:1939::-;57058:13;:11;:13::i;:::-;57047:8;:24;57039:63;;;;;-1:-1:-1;;;57039:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;57115:30;57148:24;;;:14;:24;;;;;;;;57173:10;57148:36;;;;;;;57217:14;;57148:36;;57217:14;;;;;57275:10;;57271:276;;57319:14;;-1:-1:-1;;;57319:14:0;;;;:26;;;57310:35;;;57302:66;;;;;-1:-1:-1;;;57302:66:0;;;;;;;;;;;;-1:-1:-1;;;57302:66:0;;;;;;;;;;;;;;;-1:-1:-1;57394:17:0;;;57271:276;;;-1:-1:-1;57455:14:0;;-1:-1:-1;;;57455:14:0;;;;57492:20;;;57484:51;;;;;-1:-1:-1;;;57484:51:0;;;;;;;;;;;;-1:-1:-1;;;57484:51:0;;;;;;;;;;;;;;;57559:17;57579:20;57590:8;57579:10;:20::i;:::-;57610:16;57629:17;;;:7;:17;;;;;;57559:40;;-1:-1:-1;57695:1046:0;57713:17;57733:23;;;:12;;;:23;;;;;:33;;57857:30;;;;-1:-1:-1;;;;;57733:33:0;;;-1:-1:-1;;;57804:36:0;;;-1:-1:-1;;;;;57804:36:0;;57947:8;57923:21;;;57947:8;57923:32;;;;;;-1:-1:-1;;;;;;57976:26:0;;;;:56;;-1:-1:-1;;;;;;58006:26:0;;58022:10;58006:26;57976:56;57972:684;;;58105:61;58122:8;58132:9;58143:8;58153:12;58105:16;:61::i;:::-;57972:684;;;58312:2;58301:13;;58335:29;;;;58499:2;58488:13;;58522:61;58539:8;58549:9;58335:29;58570:12;58522:16;:61::i;:::-;58602:38;58608:12;58622:17;58602:5;:38::i;:::-;57972:684;;;58717:11;;;;;58672:25;;;;;-1:-1:-1;;58717:22:0;;;57695:1046;;58753:34;;-1:-1:-1;;58753:34:0;;;;;;;58804:18;;58800:83;;58839:32;58845:10;58857:13;58839:5;:32::i;:::-;56951:1939;;;;;;;;:::o;55997:712::-;56109:1;56093:13;:11;:13::i;:::-;:17;56085:60;;;;;-1:-1:-1;;;56085:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;56158:16;56177:13;:11;:13::i;:::-;56158:32;-1:-1:-1;56223:9:0;56251:14;56243:47;;;;;-1:-1:-1;;;56243:47:0;;;;;;;;;;;;-1:-1:-1;;;56243:47:0;;;;;;;;;;;;;;;56303:30;56336:24;;;:14;:24;;;;;;;;56361:10;56336:36;;;;;;;56406:16;;;;-1:-1:-1;;;56406:16:0;;;;;;;;;;;;-1:-1:-1;;56406:16:0;;;;;;;;;56462:50;;;;;;;-1:-1:-1;;;;;56462:50:0;;;;;-1:-1:-1;;;;;56462:50:0;;;;;;;;;56435:24;;;:12;;;:24;;;;;:77;;;;;;;;;-1:-1:-1;;;56435:77:0;;;;-1:-1:-1;;56435:77:0;;;;;;;;;;;;;;56525:17;;;:7;:17;;;;;;:30;;;;;;56573:128;;56600:15;56573:128;;;;;;;;;;56336:36;;56406:16;56487:9;;56406:16;;56573:128;;;;;;;;;;55997:712;;;;;:::o;11270:134::-;-1:-1:-1;;;;;11369:18:0;;;11342:7;11369:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;11270:134::o;26128:496::-;26200:18;;:::i;:::-;26238:378;;;;;;;;26260:7;:23;-1:-1:-1;;;;;26260:23:0;;;26238:378;;-1:-1:-1;;;26298:28:0;;;;26238:378;;;;26341:17;-1:-1:-1;;;26341:17:0;;;;26238:378;;;;;;;-1:-1:-1;;;26373:25:0;;;;;26238:378;;;;26413:22;;;;;26238:378;;;;26450:24;;;;;;26238:378;;;;-1:-1:-1;;;26489:21:0;;;;;26238:378;;;;26525:15;26238:378;;;;26260:23;26238:378;;26555:13;:11;:13::i;:::-;26238:378;;;;26583:7;:22;26591:13;:11;:13::i;:::-;26583:22;;;;;;;;;;;;26238:378;;;;;26128:496;:::o;59173:501::-;59279:21;59351:6;59340:8;:17;:44;;;;;59371:13;:11;:13::i;:::-;59361:6;:23;;59340:44;59318:112;;;;;-1:-1:-1;;;59318:112:0;;;;;;;;;;;;-1:-1:-1;;;59318:112:0;;;;;;;;;;;;;;;59473:8;59464:6;:17;59450:32;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;59450:32:0;-1:-1:-1;59443:39:0;-1:-1:-1;59509:8:0;59495:11;59554:89;59594:14;;;;:7;:14;;;;;;59572:11;;59602:5;;;;;59577;;;59572:4;;:11;;;;;;;;;;;:37;;;;;59635:6;59629:3;:12;59554:89;;-1:-1:-1;;59173:501:0;;;;:::o;298:98::-;378:10;298:98;:::o;16529:338::-;-1:-1:-1;;;;;16623:19:0;;16615:68;;;;-1:-1:-1;;;16615:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;16702:21:0;;16694:68;;;;-1:-1:-1;;;16694:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;16775:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;16827:32;;;;;;;;;;;;;;;;;16529:338;;;:::o;14348:471::-;-1:-1:-1;;;;;14446:20:0;;14438:70;;;;-1:-1:-1;;;14438:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;14527:23:0;;14519:71;;;;-1:-1:-1;;;14519:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14623;14645:6;14623:71;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;14623:17:0;;:9;:17;;;;;;;;;;;;:71;;:21;:71;:::i;:::-;-1:-1:-1;;;;;14603:17:0;;;:9;:17;;;;;;;;;;;:91;;;;14728:20;;;;;;;:32;;14753:6;14728:32;:24;:32;:::i;:::-;-1:-1:-1;;;;;14705:20:0;;;:9;:20;;;;;;;;;;;;:55;;;;14776:35;;;;;;;14705:20;;14776:35;;;;;;;;;;;;;14348:471;;;:::o;5190:192::-;5276:7;5312:12;5304:6;;;;5296:29;;;;-1:-1:-1;;;5296: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;5296:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5348:5:0;;;5190:192::o;27701:592::-;27846:7;:23;-1:-1:-1;;;;;27846:23:0;;;27825:44;;-1:-1:-1;;;27906:28:0;;;;27880:23;;;:54;27960:17;-1:-1:-1;;;27960:17:0;;;;27945:12;;;:32;-1:-1:-1;;;28011:25:0;;;;;27988:20;;;:48;28067:22;;;;;28047:17;;;:42;28122:24;;;;;;28100:19;;;:46;-1:-1:-1;;;28176:21:0;;;28157:16;;;:40;28224:13;:11;:13::i;:::-;28208;;;:29;28250:35;28208:1;28275:9;28250:21;:35::i;:::-;27701:592;;:::o;29892:538::-;30112:13;;;30096:29;;;30112:13;;30096:29;30088:72;;;;;-1:-1:-1;;;30088:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;30187:13;;;;;30173:27;;-1:-1:-1;;;;;;;;30228:16:0;;;;30211:14;;;:33;-1:-1:-1;;;30273:17:0;;;30255:15;;;:35;30317:15;-1:-1:-1;;;30317:15:0;;;;30301:13;;;:31;-1:-1:-1;;;30360:16:0;;;;30343:14;;;:33;-1:-1:-1;;;30405:17:0;;;;30387:15;;;;:35;;;;-1:-1:-1;29892:538:0:o;27558:135::-;27645:40;27662:1;27665;:13;;;27680:4;27645:16;:40::i;:::-;27558:135;:::o;49509:202::-;49646:15;;;;49623:19;;;;:38;;;;;;;;;49690:13;;;;;49672:15;;:31;49509:202::o;49719:1879::-;49860:19;49881:14;49897:17;49916:15;49933:21;49989:2;:14;;;49976:10;:27;49972:1138;;;50040:189;50085:1;50105:2;:13;;;50137:2;:14;;;50170:10;50199:2;:15;;;50040:26;:189::i;:::-;50258:14;;;;50375:15;;;;50409:13;;;;50258:23;;;;-1:-1:-1;50020:209:0;;-1:-1:-1;50020:209:0;;-1:-1:-1;50310:172:0;;50355:1;;50441:26;;;50310;:172::i;:::-;50298:184;;49972:1138;;;50632:15;;;;50666:13;;;;50575:164;;50612:1;;50698:26;;;50575:18;:164::i;:::-;50566:173;;50768:172;50813:1;50833:2;:15;;;50867:2;:13;;;50915:10;50899:2;:13;;;:26;50768;:172::i;:::-;50756:184;;50988:6;50971:2;:14;;;:23;50957:37;;51021:77;51038:2;:13;;;51053:2;:14;;;51069:2;:15;;;51086:11;51021:16;:77::i;:::-;51011:87;;49972:1138;51124:12;;51120:397;;51167:11;51157:7;:21;51153:353;;;-1:-1:-1;51318:1:0;;51153:353;;;-1:-1:-1;51462:28:0;;;;;51436:7;51153:353;49719:1879;;;;;;;;;:::o;15100:308::-;-1:-1:-1;;;;;15176:21:0;;15168:65;;;;;-1:-1:-1;;;15168:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;15261:12;;:24;;15278:6;15261:24;:16;:24;:::i;:::-;15246:12;:39;-1:-1:-1;;;;;15317:18:0;;:9;:18;;;;;;;;;;;:30;;15340:6;15317:30;:22;:30;:::i;:::-;-1:-1:-1;;;;;15296:18:0;;:9;:18;;;;;;;;;;;:51;;;;15363:37;;;;;;;15296:18;;:9;;15363:37;;;;;;;;;;15100:308;;:::o;54474:1281::-;54617:2;:14;;;54603:11;:28;54599:1149;;;54903:17;54923:49;54944:11;54957:2;:14;;;54923:20;:49::i;:::-;54903:69;;54987:20;55057:2;:15;;;21437:3;55025:9;55011:11;:23;55010:44;:62;;;;;;;-1:-1:-1;21592:31:0;55093:29;;55089:370;;;-1:-1:-1;21592:31:0;55089:370;55494:1;:12;;;55479;:27;55475:262;;;55527:12;;;;:27;;;55618:11;;55580:141;;55652:15;55580:141;;;;;;;;;;;;;;;;;;;;;;;;55475:262;54599:1149;;54474:1281;;;:::o;31887:647::-;32018:19;;-1:-1:-1;;32018:23:0;32140;;;32136:177;;32278:12;32291:9;32278:23;;;;;;;;;;;;;;;32251:12;32264:10;32251:24;;;;;;;;;;;;;;;;:50;;:24;;:50;;-1:-1:-1;;32251:50:0;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;32251:50:0;;;;;;;;;-1:-1:-1;;32251:50:0;;;;;;;;;;;;-1:-1:-1;;;32251:50:0;;;;;;;;;;-1:-1:-1;;;;32251:50:0;;;;;;;;;;-1:-1:-1;;;32251:50:0;;;;;;;;;-1:-1:-1;;;;32251:50:0;;;;;;;;;;;;-1:-1:-1;;;32251:50:0;;;;;;;-1:-1:-1;;;;32251:50:0;;;;;;;;;-1:-1:-1;;;32251:50:0;;;;;;;;-1:-1:-1;;;;32251:50:0;;;;;;;;;32136:177;32508:12;:18;;;;;;;;;;;;;;;;-1:-1:-1;;32508:18:0;;;;;-1:-1:-1;;;;;;32508:18:0;;;;;;-1:-1:-1;;;31887:647:0:o;28843:1041::-;28979:26;;28957:18;;:48;;;:123;;;29049:9;:31;;;29022:1;:23;;;:58;;28957:123;:176;;;;29113:9;:20;;;29097:1;:12;;;:36;;28957:176;:245;;;;29174:9;:28;;;29150:1;:20;;;:52;;28957:245;28953:533;;;29252:18;;29219:7;:52;;29324:23;;;;29390:12;;;;29453:20;;;;-1:-1:-1;;29219:52:0;;;-1:-1:-1;;;;;29219:52:0;;;;-1:-1:-1;;29286:62:0;-1:-1:-1;;;29286:62:0;;;;;;;;;;;-1:-1:-1;;;;29363:40:0;-1:-1:-1;;;29363:40:0;;;;;;;;;-1:-1:-1;;;;;29418:56:0;-1:-1:-1;;;29418:56:0;;;;;;;;;;;;;;28953:533;29521:9;:25;;;29500:1;:17;;;:46;;:113;;;;29586:9;:27;;;29563:1;:19;;;:50;;29500:113;:174;;;;29650:9;:24;;;29630:44;;:1;:16;;;:44;;;;29500:174;29496:381;;;29723:17;;;;29691:22;:50;;29790:19;;;;29849:16;;;;29825:40;;-1:-1:-1;;;29825:40:0;-1:-1:-1;;;;;;;;;29756:54:0;;;;;-1:-1:-1;;29691:50:0;;;;-1:-1:-1;;29691:50:0;;;;;;;29756:54;;;;;;;;29825:40;;;;;;;28843:1041;;:::o;4261:181::-;4319:7;4351:5;;;4375:6;;;;4367:46;;;;;-1:-1:-1;;;4367:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;4433:1;4261:181;-1:-1:-1;;;4261:181:0:o;27296:254::-;27369:7;19548:10;27398:15;:29;27394:149;;;-1:-1:-1;27451:1:0;27444:8;;27394:149;-1:-1:-1;27525:6:0;27492:15;-1:-1:-1;;27492:29:0;27491:40;27484:47;;42542:1741;20247:2;42754:13;:31;;42746:82;;;;-1:-1:-1;;;42746:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42841:17;42861:50;42882:13;42897;42861:20;:50::i;:::-;42841:70;;42922:22;42996:1;:12;;;21437:3;42964:9;42948:13;:25;42947:46;:61;;;;;;;-1:-1:-1;43104:19:0;43096:85;;;;-1:-1:-1;;;43096:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;43549:13;;;;43629:16;;;43627:18;;;43565:1;43627:18;;;;;;;;43691:10;43526:20;43680:22;;;:10;-1:-1:-1;43680:22:0;;;;43549:17;;;43656:194;;43627:18;43742:13;43770:14;43549:17;43826:13;43656:9;:194::i;:::-;43868:159;;;;;;;;;;;;;;;;;;;;43919:10;;43868:159;;;;;;;;;;;;;-1:-1:-1;;44120:23:0;;;:41;;;;;;;-1:-1:-1;;44240:35:0;;;;;42542:1741::o;15741:348::-;-1:-1:-1;;;;;15817:21:0;;15809:67;;;;-1:-1:-1;;;15809:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15910:68;15933:6;15910:68;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;15910:18:0;;:9;:18;;;;;;;;;;;;:68;;:22;:68;:::i;:::-;-1:-1:-1;;;;;15889:18:0;;:9;:18;;;;;;;;;;:89;16004:12;;:24;;16021:6;16004:24;:16;:24;:::i;:::-;15989:12;:39;16044:37;;;;;;;;16070:1;;-1:-1:-1;;;;;16044:37:0;;;;;;;;;;;;15741:348;;:::o;30438:401::-;30558:11;;30542:27;;30606:14;;;;30659:15;;;;30711:13;;;;30762:14;;;;30815:15;;;;;-1:-1:-1;;30542:27:0;;;;;;;;;;;-1:-1:-1;;30580:41:0;-1:-1:-1;;;;;;;;30580:41:0;;;;;-1:-1:-1;;;;30632:43:0;-1:-1:-1;;;30632:43:0;;;;;;;;;-1:-1:-1;;;;30686:39:0;-1:-1:-1;;;30686:39:0;;;;;;-1:-1:-1;;;;30736:41:0;-1:-1:-1;;;30736:41:0;;;;;;;;;;;-1:-1:-1;;;;30788:43:0;-1:-1:-1;;;30788:43:0;;;;;;;;30438:401::o;35032:970::-;35177:9;35156:1;:17;;;:30;35152:107;;35241:7;;35152:107;35271:25;;:::i;:::-;35347:18;;35331:13;:11;:13::i;:::-;:34;35307:58;;35392:17;;;;35422:35;35392:1;35307:2;35392:17;35422:23;:35::i;:::-;35556:23;;;;:28;35552:149;;35624:23;;;;;35601:19;;;:46;;;;;;;-1:-1:-1;35662:27:0;;35552:149;35720:5;;:17;;;35713:88;;;35754:35;35778:1;35781:2;35785:3;35754:23;:35::i;:::-;35713:88;;;35903:17;;;;35818:132;;;35873:15;35818:132;;;;;;;;;;;;;;;;35848:10;;35818:132;;;;;;;;;;35971:17;;;:23;-1:-1:-1;35032:970:0;;;:::o;61123:451::-;61196:17;61321:1;61310:8;:12;:30;;;;;61338:2;61326:8;:14;;61310:30;61306:232;;;-1:-1:-1;61448:13:0;-1:-1:-1;;61432:12:0;;61431:30;19746:19;61406:56;61306:232;;;-1:-1:-1;19865:18:0;61306:232;61123:451;;;:::o;61582:344::-;61895:12;-1:-1:-1;;;;;61767:151:0;61872:8;61847:10;61767:151;61793:15;61824:8;61767:151;;;;;;;;;;;;;;;;;;;;;;;;61582:344;;;;:::o;28301:534::-;28463:18;;28434:47;;28526:23;;;;;28492:31;;;:57;28583:12;;;;;28560:20;;;:35;28637:20;;;;;28606:28;;;:51;28696:17;;;;;28668:25;;;:45;28754:19;;;;;28724:27;;;:49;28811:16;;;;;28784:43;;:24;;:43;28301:534::o;51606:2201::-;51861:14;;51933:27;;;52088:1;52083;52065:19;;52064:25;20323:2;52104:36;;52100:105;;;-1:-1:-1;20323:2:0;52100:105;52221:15;52217:309;;52324:16;52343:62;52369:1;52372:16;52390:14;52343:25;:62::i;:::-;52430:22;;;;;-1:-1:-1;52467:24:0;;-1:-1:-1;;52467:24:0;52217:309;52556:10;52542:11;:24;52538:723;;;52947:28;;;53000:70;53019:1;53022:16;52947:14;:28;53000:18;:70::i;:::-;52990:80;;53087:13;53103:68;53122:1;53125:16;53143:13;53158:12;53103:18;:68::i;:::-;53195:15;;;-1:-1:-1;53225:24:0;;-1:-1:-1;;;;53225:24:0;52538:723;53324:69;53343:1;53346:16;53364:14;53380:12;53324:18;:69::i;:::-;53315:78;;53425:10;53410:11;:25;53406:359;;;53462:6;53452:16;;53406:359;;;53743:10;53729:11;53720:6;:20;:33;;;;;;53710:43;;53406:359;-1:-1:-1;;51606:2201:0;;;;;;;;;:::o;45927:597::-;46138:14;46191:8;46172:319;46207:6;46201:3;:12;46172:319;;;46237:17;46409:14;;;:9;:14;;;;;:34;;;;;46347:27;;;;-1:-1:-1;;;;;46409:34:0;;;;46347:46;;46409:34;46347:96;;;;;46334:109;46460:19;;;;;46215:5;;46172:319;;;-1:-1:-1;45927:597:0;;;;;;;:::o;44678:898::-;44881:14;;44960:8;44941:602;44976:6;44970:3;:12;44941:602;;;45006:17;45120:14;;;:9;:14;;;;;:34;;;;45052:29;;-1:-1:-1;;;;;45120:34:0;;;;45052:29;:48;;45120:34;45052:102;;;;;45040:114;;45185:1;45175:7;:11;45171:325;;;45207:9;;;;;45171:325;;;45397:14;;;;:9;:14;;;;;21706:1;45397:34;;;;45329:29;;21706:1;;-1:-1:-1;;;;;45397:34:0;;;;45329:29;:48;;45397:34;45329:102;;;;;45328:122;45316:134;;45479:1;45469:11;;45171:325;45512:19;;;;;44984:5;;44941:602;;;-1:-1:-1;;44678:898:0;;;;;;:::o;53815:651::-;54032:7;54138:32;;;20446:28;54138:58;54211:34;;;54207:75;;54269:1;54262:8;;;;;54207:75;20597:28;54398:33;;;54380:52;;:78;;53815:651;-1:-1:-1;;;;;;53815:651:0:o;46714:2787::-;46839:17;;49094:1;49078:17;;49074:132;;;20946:33;49130:29;;;:64;;20946:33;49130:64;;;49178:1;49162:13;:17;49130:64;49112:82;;49074:132;49218:24;21226:26;49245:29;;;:86;;21226:26;49245:86;;;49290:13;49245:86;21291:38;49356:21;;20869:29;49380:22;;49356:46;;-1:-1:-1;49218:113:0;-1:-1:-1;49454:9:0;49425:25;;;:39;;46714:2787;-1:-1:-1;;;;;46714:2787:0:o;30847:568::-;31139:257;;;;;;;;;;;;;;-1:-1:-1;;;;;31139:257:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;31139:257:0;;;;;;27:10:-1;;39:1;23:18;;45:23;;31107:300:0;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;31107:300:0;;;;;;;;;;;-1:-1:-1;;31107:300:0;-1:-1:-1;;;31107:300:0;;;;;;;;;;;-1:-1:-1;;;;31107:300:0;-1:-1:-1;;;31107:300:0;;;;;;;;;;;;-1:-1:-1;;;;31107:300:0;-1:-1:-1;;;31107:300:0;;;;;;;;;;;-1:-1:-1;;;;31107:300:0;-1:-1:-1;;;31107:300:0;;;;;;;;-1:-1:-1;;;;31107:300:0;-1:-1:-1;;;31107:300:0;;;;;;;;;;;30847:568::o;4717:136::-;4775:7;4802:43;4806:1;4809;4802:43;;;;;;;;;;;;;;;;;:3;:43::i;34664:360::-;34793:27;34809:1;34812:2;34816:3;34793:15;:27::i;:::-;34872:15;;;;;34833:14;;;;:9;:14;;;;;;;:55;;-1:-1:-1;;;;;34833:55:0;;;-1:-1:-1;;34833:55:0;;;;;;34929:7;:12;;;;;;;34899:14;;;;34833:55;34899:27;;:42;34996:19;;;;;34952:34;;;;:64;;;;;;;;;;;34664:360::o;32815:706::-;32962:14;33052:24;;:::i;:::-;33087:30;33109:1;33112:4;33087:21;:30::i;:::-;33130:25;;:::i;:::-;33206:18;;33190:13;:11;:13::i;:::-;:34;33166:58;;33237:30;33253:4;33166:2;33263:3;33237:15;:30::i;:::-;33364:22;;;:42;;;;;;;;33428:15;;;;:34;;33364:42;33428:59;;;;;;32815:706;-1:-1:-1;;;;;;32815:706:0:o;33529:1127::-;34459:21;;34491:8;;34483:5;34459:29;:40;34440:15;;;:60;34517:20;;;;:25;34513:136;;34578:20;;;;;34559:15;;;:39;;;;;;;-1:-1:-1;34613:24:0;;33529:1127;;;:::o;61933:233::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;61933:233:0;;;-1:-1:-1;;61933:233:0:o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;61933:233:0;;;-1:-1:-1;;61933:233:0:o;:::-;;;;;;;;;;;;;;;;;;;:::o

Swarm Source

bzzr://06af273706377a68b09951e6be9e7a5a10efc9c8510be59fcbdb32292e4b9778
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.