ETH Price: $3,396.10 (-6.04%)
Gas: 26 Gwei

Token

HEX (HEX)
 

Overview

Max Total Supply

594,317,021,646.4268604 HEX

Holders

332,847 ( -0.002%)

Total Transfers

-

Market

Price

$0.00 @ 0.000001 ETH (-14.39%)

Onchain Market Cap

$1,478,690,590.92

Circulating Supply Market Cap

$431,455,460.23

Other Info

Token Contract (WITH 8 Decimals)

Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

HEX.com averages 25% APY interest recently. HEX virtually lends value from stakers to non-stakers as staking reduces supply. The launch ends Nov. 19th, 2020 when HEX stakers get credited ~200B HEX. HEX's total supply is now ~350B. Audited 3 times, 2 security, and 1 economics.

Market

Volume (24H):$1,198,573.64
Market Capitalization:$431,455,460.23
Circulating Supply:173,411,074,413.00 HEX
Market Data Source: Coinmarketcap

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
HEX

Compiler Version
v0.5.13+commit.5b0b510c

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license, Audited

Contract Source Code (Solidity)Audit Report

/**
 *Submitted for verification at Etherscan.io on 2019-12-03
*/

pragma solidity 0.5.13;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
contract Context {
    // Empty internal constructor, to prevent people from mistakenly deploying
    // an instance of this contract, which should be used via inheritance.
    constructor () internal { }
    // 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 IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

/**
 * @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 {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {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 {IERC20-approve}.
 */
contract ERC20 is Context, IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

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

    uint256 private _totalSupply;

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

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

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

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

    /**
     * @dev See {IERC20-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 {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20};
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for `sender`'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public 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      (auto-generated event)

        uint40            timestamp       -->  data0 [ 39:  0]
        address  indexed  memberAddr
        uint256  indexed  entryId
        uint96            rawAmount       -->  data0 [135: 40]
        address  indexed  referrerAddr
    */
    event XfLobbyEnter(
        uint256 data0,
        address indexed memberAddr,
        uint256 indexed entryId,
        address indexed referrerAddr
    );

    /*  XfLobbyExit       (auto-generated event)

        uint40            timestamp       -->  data0 [ 39:  0]
        address  indexed  memberAddr
        uint256  indexed  entryId
        uint72            xfAmount        -->  data0 [111: 40]
        address  indexed  referrerAddr
    */
    event XfLobbyExit(
        uint256 data0,
        address indexed memberAddr,
        uint256 indexed entryId,
        address indexed referrerAddr
    );

    /*  DailyDataUpdate   (auto-generated event)

        uint40            timestamp       -->  data0 [ 39:  0]
        uint16            beginDay        -->  data0 [ 55: 40]
        uint16            endDay          -->  data0 [ 71: 56]
        bool              isAutoUpdate    -->  data0 [ 79: 72]
        address  indexed  updaterAddr
    */
    event DailyDataUpdate(
        uint256 data0,
        address indexed updaterAddr
    );

    /*  Claim             (auto-generated event)

        uint40            timestamp       -->  data0 [ 39:  0]
        bytes20  indexed  btcAddr
        uint56            rawSatoshis     -->  data0 [ 95: 40]
        uint56            adjSatoshis     -->  data0 [151: 96]
        address  indexed  claimToAddr
        uint8             claimFlags      -->  data0 [159:152]
        uint72            claimedHearts   -->  data0 [231:160]
        address  indexed  referrerAddr
        address           senderAddr      -->  data1 [159:  0]
    */
    event Claim(
        uint256 data0,
        uint256 data1,
        bytes20 indexed btcAddr,
        address indexed claimToAddr,
        address indexed referrerAddr
    );

    /*  ClaimAssist       (auto-generated event)

        uint40            timestamp       -->  data0 [ 39:  0]
        bytes20           btcAddr         -->  data0 [199: 40]
        uint56            rawSatoshis     -->  data0 [255:200]
        uint56            adjSatoshis     -->  data1 [ 55:  0]
        address           claimToAddr     -->  data1 [215: 56]
        uint8             claimFlags      -->  data1 [223:216]
        uint72            claimedHearts   -->  data2 [ 71:  0]
        address           referrerAddr    -->  data2 [231: 72]
        address  indexed  senderAddr
    */
    event ClaimAssist(
        uint256 data0,
        uint256 data1,
        uint256 data2,
        address indexed senderAddr
    );

    /*  StakeStart        (auto-generated event)

        uint40            timestamp       -->  data0 [ 39:  0]
        address  indexed  stakerAddr
        uint40   indexed  stakeId
        uint72            stakedHearts    -->  data0 [111: 40]
        uint72            stakeShares     -->  data0 [183:112]
        uint16            stakedDays      -->  data0 [199:184]
        bool              isAutoStake     -->  data0 [207:200]
    */
    event StakeStart(
        uint256 data0,
        address indexed stakerAddr,
        uint40 indexed stakeId
    );

    /*  StakeGoodAccounting(auto-generated event)

        uint40            timestamp       -->  data0 [ 39:  0]
        address  indexed  stakerAddr
        uint40   indexed  stakeId
        uint72            stakedHearts    -->  data0 [111: 40]
        uint72            stakeShares     -->  data0 [183:112]
        uint72            payout          -->  data0 [255:184]
        uint72            penalty         -->  data1 [ 71:  0]
        address  indexed  senderAddr
    */
    event StakeGoodAccounting(
        uint256 data0,
        uint256 data1,
        address indexed stakerAddr,
        uint40 indexed stakeId,
        address indexed senderAddr
    );

    /*  StakeEnd          (auto-generated event)

        uint40            timestamp       -->  data0 [ 39:  0]
        address  indexed  stakerAddr
        uint40   indexed  stakeId
        uint72            stakedHearts    -->  data0 [111: 40]
        uint72            stakeShares     -->  data0 [183:112]
        uint72            payout          -->  data0 [255:184]
        uint72            penalty         -->  data1 [ 71:  0]
        uint16            servedDays      -->  data1 [ 87: 72]
        bool              prevUnlocked    -->  data1 [ 95: 88]
    */
    event StakeEnd(
        uint256 data0,
        uint256 data1,
        address indexed stakerAddr,
        uint40 indexed stakeId
    );

    /*  ShareRateChange   (auto-generated event)

        uint40            timestamp       -->  data0 [ 39:  0]
        uint40            shareRate       -->  data0 [ 79: 40]
        uint40   indexed  stakeId
    */
    event ShareRateChange(
        uint256 data0,
        uint40 indexed stakeId
    );

    /* Origin address */
    address internal constant ORIGIN_ADDR = 0x9A6a414D6F3497c05E3b1De90520765fA1E07c03;

    /* Flush address */
    address payable internal constant FLUSH_ADDR = 0xDEC9f2793e3c17cd26eeFb21C4762fA5128E0399;

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

    /* Hearts per Satoshi = 10,000 * 1e8 / 1e8 = 1e4 */
    uint256 private constant HEARTS_PER_HEX = 10 ** uint256(decimals); // 1e8
    uint256 private constant HEX_PER_BTC = 1e4;
    uint256 private constant SATOSHIS_PER_BTC = 1e8;
    uint256 internal constant HEARTS_PER_SATOSHI = HEARTS_PER_HEX / SATOSHIS_PER_BTC * HEX_PER_BTC;

    /* Time of contract launch (2019-12-03T00:00:00Z) */
    uint256 internal constant LAUNCH_TIME = 1575331200;

    /* Size of a Hearts or Shares uint */
    uint256 internal constant HEART_UINT_SIZE = 72;

    /* Size of a transform lobby entry index uint */
    uint256 internal constant XF_LOBBY_ENTRY_INDEX_SIZE = 40;
    uint256 internal constant XF_LOBBY_ENTRY_INDEX_MASK = (1 << XF_LOBBY_ENTRY_INDEX_SIZE) - 1;

    /* Seed for WAAS Lobby */
    uint256 internal constant WAAS_LOBBY_SEED_HEX = 1e9;
    uint256 internal constant WAAS_LOBBY_SEED_HEARTS = WAAS_LOBBY_SEED_HEX * HEARTS_PER_HEX;

    /* Start of claim phase */
    uint256 internal constant PRE_CLAIM_DAYS = 1;
    uint256 internal constant CLAIM_PHASE_START_DAY = PRE_CLAIM_DAYS;

    /* Length of claim phase */
    uint256 private constant CLAIM_PHASE_WEEKS = 50;
    uint256 internal constant CLAIM_PHASE_DAYS = CLAIM_PHASE_WEEKS * 7;

    /* End of claim phase */
    uint256 internal constant CLAIM_PHASE_END_DAY = CLAIM_PHASE_START_DAY + CLAIM_PHASE_DAYS;

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

    /* BigPayDay */
    uint256 internal constant BIG_PAY_DAY = CLAIM_PHASE_END_DAY + 1;

    /* Root hash of the UTXO Merkle tree */
    bytes32 internal constant MERKLE_TREE_ROOT = 0x4e831acb4223b66de3b3d2e54a2edeefb0de3d7916e2886a4b134d9764d41bec;

    /* Size of a Satoshi claim uint in a Merkle leaf */
    uint256 internal constant MERKLE_LEAF_SATOSHI_SIZE = 45;

    /* Zero-fill between BTC address and Satoshis in a Merkle leaf */
    uint256 internal constant MERKLE_LEAF_FILL_SIZE = 256 - 160 - MERKLE_LEAF_SATOSHI_SIZE;
    uint256 internal constant MERKLE_LEAF_FILL_BASE = (1 << MERKLE_LEAF_FILL_SIZE) - 1;
    uint256 internal constant MERKLE_LEAF_FILL_MASK = MERKLE_LEAF_FILL_BASE << MERKLE_LEAF_SATOSHI_SIZE;

    /* Size of a Satoshi total uint */
    uint256 internal constant SATOSHI_UINT_SIZE = 51;
    uint256 internal constant SATOSHI_UINT_MASK = (1 << SATOSHI_UINT_SIZE) - 1;

    /* Total Satoshis from all BTC addresses in UTXO snapshot */
    uint256 internal constant FULL_SATOSHIS_TOTAL = 1807766732160668;

    /* Total Satoshis from supported BTC addresses in UTXO snapshot after applying Silly Whale */
    uint256 internal constant CLAIMABLE_SATOSHIS_TOTAL = 910087996911001;

    /* Number of claimable BTC addresses in UTXO snapshot */
    uint256 internal constant CLAIMABLE_BTC_ADDR_COUNT = 27997742;

    /* Largest BTC address Satoshis balance in UTXO snapshot (sanity check) */
    uint256 internal constant MAX_BTC_ADDR_BALANCE_SATOSHIS = 25550214098481;

    /* Percentage of total claimed Hearts that will be auto-staked from a claim */
    uint256 internal constant AUTO_STAKE_CLAIM_PERCENT = 90;

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

    uint256 internal constant MAX_STAKE_DAYS = 5555; // Approx 15 years

    uint256 internal constant EARLY_PENALTY_MIN_DAYS = 90;

    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 _stakeStartBonusHearts() */
    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 _stakeStartBonusHearts() */
    uint256 private constant BPB_BONUS_PERCENT = 10;
    uint256 private constant BPB_MAX_HEX = 150 * 1e6;
    uint256 internal constant BPB_MAX_HEARTS = BPB_MAX_HEX * HEARTS_PER_HEX;
    uint256 internal constant BPB = BPB_MAX_HEARTS * 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;

    /* Constants for preparing the claim message text */
    uint8 internal constant ETH_ADDRESS_BYTE_LEN = 20;
    uint8 internal constant ETH_ADDRESS_HEX_LEN = ETH_ADDRESS_BYTE_LEN * 2;

    uint8 internal constant CLAIM_PARAM_HASH_BYTE_LEN = 12;
    uint8 internal constant CLAIM_PARAM_HASH_HEX_LEN = CLAIM_PARAM_HASH_BYTE_LEN * 2;

    uint8 internal constant BITCOIN_SIG_PREFIX_LEN = 24;
    bytes24 internal constant BITCOIN_SIG_PREFIX_STR = "Bitcoin Signed Message:\n";

    bytes internal constant STD_CLAIM_PREFIX_STR = "Claim_HEX_to_0x";
    bytes internal constant OLD_CLAIM_PREFIX_STR = "Claim_BitcoinHEX_to_0x";

    bytes16 internal constant HEX_DIGITS = "0123456789abcdef";

    /* Claim flags passed to btcAddressClaim()  */
    uint8 internal constant CLAIM_FLAG_MSG_PREFIX_OLD = 1 << 0;
    uint8 internal constant CLAIM_FLAG_BTC_ADDR_COMPRESSED = 1 << 1;
    uint8 internal constant CLAIM_FLAG_BTC_ADDR_P2WPKH_IN_P2SH = 1 << 2;
    uint8 internal constant CLAIM_FLAG_BTC_ADDR_BECH32 = 1 << 3;
    uint8 internal constant CLAIM_FLAG_ETH_ADDR_LOWERCASE = 1 << 4;

    /* Globals expanded for memory (except _latestStakeId) and compact for storage */
    struct GlobalsCache {
        // 1
        uint256 _lockedHeartsTotal;
        uint256 _nextStakeSharesTotal;
        uint256 _shareRate;
        uint256 _stakePenaltyTotal;
        // 2
        uint256 _dailyDataCount;
        uint256 _stakeSharesTotal;
        uint40 _latestStakeId;
        uint256 _unclaimedSatoshisTotal;
        uint256 _claimedSatoshisTotal;
        uint256 _claimedBtcAddrCount;
        //
        uint256 _currentDay;
    }

    struct GlobalsStore {
        // 1
        uint72 lockedHeartsTotal;
        uint72 nextStakeSharesTotal;
        uint40 shareRate;
        uint72 stakePenaltyTotal;
        // 2
        uint16 dailyDataCount;
        uint72 stakeSharesTotal;
        uint40 latestStakeId;
        uint128 claimStats;
    }

    GlobalsStore public globals;

    /* Claimed BTC addresses */
    mapping(bytes20 => bool) public btcAddressClaims;

    /* Daily data */
    struct DailyDataStore {
        uint72 dayPayoutTotal;
        uint72 dayStakeSharesTotal;
        uint56 dayUnclaimedSatoshisTotal;
    }

    mapping(uint256 => DailyDataStore) public dailyData;

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

    struct StakeStore {
        uint40 stakeId;
        uint72 stakedHearts;
        uint72 stakeShares;
        uint16 lockedDay;
        uint16 stakedDays;
        uint16 unlockedDay;
        bool isAutoStake;
    }

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

    /* Temporary state for calculating daily rounds */
    struct DailyRoundState {
        uint256 _allocSupplyCached;
        uint256 _mintOriginBatch;
        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, "HEX: Too early");

        if (beforeDay != 0) {
            require(beforeDay <= g._currentDay, "HEX: 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. Ugly implementation due to limitations of the standard ABI encoder.
     * @param beginDay First day of data range
     * @param endDay Last day (non-inclusive) of data range
     * @return Fixed array of packed values
     */
    function dailyDataRange(uint256 beginDay, uint256 endDay)
        external
        view
        returns (uint256[] memory list)
    {
        require(beginDay < endDay && endDay <= globals.dailyDataCount, "HEX: range invalid");

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

        uint256 src = beginDay;
        uint256 dst = 0;
        uint256 v;
        do {
            v = uint256(dailyData[src].dayUnclaimedSatoshisTotal) << (HEART_UINT_SIZE * 2);
            v |= uint256(dailyData[src].dayStakeSharesTotal) << HEART_UINT_SIZE;
            v |= uint256(dailyData[src].dayPayoutTotal);

            list[dst++] = v;
        } while (++src < endDay);

        return list;
    }

    /**
     * @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[13] memory)
    {
        uint256 _claimedBtcAddrCount;
        uint256 _claimedSatoshisTotal;
        uint256 _unclaimedSatoshisTotal;

        (_claimedBtcAddrCount, _claimedSatoshisTotal, _unclaimedSatoshisTotal) = _claimStatsDecode(
            globals.claimStats
        );

        return [
            // 1
            globals.lockedHeartsTotal,
            globals.nextStakeSharesTotal,
            globals.shareRate,
            globals.stakePenaltyTotal,
            // 2
            globals.dailyDataCount,
            globals.stakeSharesTotal,
            globals.latestStakeId,
            _unclaimedSatoshisTotal,
            _claimedSatoshisTotal,
            _claimedBtcAddrCount,
            //
            block.timestamp,
            totalSupply(),
            xfLobby[_currentDay()]
        ];
    }

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

    /**
     * @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)
    {
        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
    {
        // 1
        g._lockedHeartsTotal = globals.lockedHeartsTotal;
        g._nextStakeSharesTotal = globals.nextStakeSharesTotal;
        g._shareRate = globals.shareRate;
        g._stakePenaltyTotal = globals.stakePenaltyTotal;
        // 2
        g._dailyDataCount = globals.dailyDataCount;
        g._stakeSharesTotal = globals.stakeSharesTotal;
        g._latestStakeId = globals.latestStakeId;
        (g._claimedBtcAddrCount, g._claimedSatoshisTotal, g._unclaimedSatoshisTotal) = _claimStatsDecode(
            globals.claimStats
        );
        //
        g._currentDay = _currentDay();

        _globalsCacheSnapshot(g, gSnapshot);
    }

    function _globalsCacheSnapshot(GlobalsCache memory g, GlobalsCache memory gSnapshot)
        internal
        pure
    {
        // 1
        gSnapshot._lockedHeartsTotal = g._lockedHeartsTotal;
        gSnapshot._nextStakeSharesTotal = g._nextStakeSharesTotal;
        gSnapshot._shareRate = g._shareRate;
        gSnapshot._stakePenaltyTotal = g._stakePenaltyTotal;
        // 2
        gSnapshot._dailyDataCount = g._dailyDataCount;
        gSnapshot._stakeSharesTotal = g._stakeSharesTotal;
        gSnapshot._latestStakeId = g._latestStakeId;
        gSnapshot._unclaimedSatoshisTotal = g._unclaimedSatoshisTotal;
        gSnapshot._claimedSatoshisTotal = g._claimedSatoshisTotal;
        gSnapshot._claimedBtcAddrCount = g._claimedBtcAddrCount;
    }

    function _globalsSync(GlobalsCache memory g, GlobalsCache memory gSnapshot)
        internal
    {
        if (g._lockedHeartsTotal != gSnapshot._lockedHeartsTotal
            || g._nextStakeSharesTotal != gSnapshot._nextStakeSharesTotal
            || g._shareRate != gSnapshot._shareRate
            || g._stakePenaltyTotal != gSnapshot._stakePenaltyTotal) {
            // 1
            globals.lockedHeartsTotal = uint72(g._lockedHeartsTotal);
            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
            || g._unclaimedSatoshisTotal != gSnapshot._unclaimedSatoshisTotal
            || g._claimedSatoshisTotal != gSnapshot._claimedSatoshisTotal
            || g._claimedBtcAddrCount != gSnapshot._claimedBtcAddrCount) {
            // 2
            globals.dailyDataCount = uint16(g._dailyDataCount);
            globals.stakeSharesTotal = uint72(g._stakeSharesTotal);
            globals.latestStakeId = g._latestStakeId;
            globals.claimStats = _claimStatsEncode(
                g._claimedBtcAddrCount,
                g._claimedSatoshisTotal,
                g._unclaimedSatoshisTotal
            );
        }
    }

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

        st._stakeId = stRef.stakeId;
        st._stakedHearts = stRef.stakedHearts;
        st._stakeShares = stRef.stakeShares;
        st._lockedDay = stRef.lockedDay;
        st._stakedDays = stRef.stakedDays;
        st._unlockedDay = stRef.unlockedDay;
        st._isAutoStake = stRef.isAutoStake;
    }

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

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

    /**
     * @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();
    }

    function _claimStatsEncode(
        uint256 _claimedBtcAddrCount,
        uint256 _claimedSatoshisTotal,
        uint256 _unclaimedSatoshisTotal
    )
        internal
        pure
        returns (uint128)
    {
        uint256 v = _claimedBtcAddrCount << (SATOSHI_UINT_SIZE * 2);
        v |= _claimedSatoshisTotal << SATOSHI_UINT_SIZE;
        v |= _unclaimedSatoshisTotal;

        return uint128(v);
    }

    function _claimStatsDecode(uint128 v)
        internal
        pure
        returns (uint256 _claimedBtcAddrCount, uint256 _claimedSatoshisTotal, uint256 _unclaimedSatoshisTotal)
    {
        _claimedBtcAddrCount = v >> (SATOSHI_UINT_SIZE * 2);
        _claimedSatoshisTotal = (v >> SATOSHI_UINT_SIZE) & SATOSHI_UINT_MASK;
        _unclaimedSatoshisTotal = v & SATOSHI_UINT_MASK;

        return (_claimedBtcAddrCount, _claimedSatoshisTotal, _unclaimedSatoshisTotal);
    }

    /**
     * @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 Hearts
     */
    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._lockedHeartsTotal;

        _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;

        if (day == BIG_PAY_DAY) {
            uint256 bigPaySlice = gTmp._unclaimedSatoshisTotal * HEARTS_PER_SATOSHI * stakeSharesParam
                / gTmp._stakeSharesTotal;
            payout += bigPaySlice + _calcAdoptionBonus(gTmp, bigPaySlice);
        }

        return payout;
    }

    function _calcAdoptionBonus(GlobalsCache memory g, uint256 payout)
        internal
        pure
        returns (uint256)
    {
        /*
            VIRAL REWARDS: Add adoption percentage bonus to payout

            viral = payout * (claimedBtcAddrCount / CLAIMABLE_BTC_ADDR_COUNT)
        */
        uint256 viral = payout * g._claimedBtcAddrCount / CLAIMABLE_BTC_ADDR_COUNT;

        /*
            CRIT MASS REWARDS: Add adoption percentage bonus to payout

            crit  = payout * (claimedSatoshisTotal / CLAIMABLE_SATOSHIS_TOTAL)
        */
        uint256 crit = payout * g._claimedSatoshisTotal / CLAIMABLE_SATOSHIS_TOTAL;

        return viral + crit;
    }

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

            Inflation of 3.69% inflation per 364 days             (approx 1 year)
            dailyInterestRate   = exp(log(1 + 3.69%)  / 364) - 1
                                = exp(log(1 + 0.0369) / 364) - 1
                                = exp(log(1.0369) / 364) - 1
                                = 0.000099553011616349            (approx)

            payout  = allocSupply * dailyInterestRate
                    = allocSupply / (1 / dailyInterestRate)
                    = allocSupply / (1 / 0.000099553011616349)
                    = allocSupply / 10044.899534066692            (approx)
                    = allocSupply * 10000 / 100448995             (* 10000/10000 for int precision)
        */
        rs._payoutTotal = rs._allocSupplyCached * 10000 / 100448995;

        if (day < CLAIM_PHASE_END_DAY) {
            uint256 bigPaySlice = g._unclaimedSatoshisTotal * HEARTS_PER_SATOSHI / CLAIM_PHASE_DAYS;

            uint256 originBonus = bigPaySlice + _calcAdoptionBonus(g, rs._payoutTotal + bigPaySlice);
            rs._mintOriginBatch += originBonus;
            rs._allocSupplyCached += originBonus;

            rs._payoutTotal += _calcAdoptionBonus(g, rs._payoutTotal);
        }

        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].dayStakeSharesTotal = uint72(g._stakeSharesTotal);
        dailyData[day].dayUnclaimedSatoshisTotal = uint56(g._unclaimedSatoshisTotal);
    }

    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._lockedHeartsTotal;

        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);
        }

        _emitDailyDataUpdate(g._dailyDataCount, day, isAutoUpdate);
        g._dailyDataCount = day;

        if (rs._mintOriginBatch != 0) {
            _mint(ORIGIN_ADDR, rs._mintOriginBatch);
        }
    }

    function _emitDailyDataUpdate(uint256 beginDay, uint256 endDay, bool isAutoUpdate)
        private
    {
        emit DailyDataUpdate( // (auto-generated event)
            uint256(uint40(block.timestamp))
                | (uint256(uint16(beginDay)) << 40)
                | (uint256(uint16(endDay)) << 56)
                | (isAutoUpdate ? (1 << 72) : 0),
            msg.sender
        );
    }
}

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

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

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

        _stakeStart(g, newStakedHearts, newStakedDays, false);

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

        _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, "HEX: Empty stake list");
        require(stakeIndex < stakeLists[stakerAddr].length, "HEX: 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, "HEX: Stake not fully served");

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

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

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

        /* stakeReturn value is unused here */
        (, uint256 payout, uint256 penalty, uint256 cappedPenalty) = _stakePerformance(
            g,
            st,
            st._stakedDays
        );

        _emitStakeGoodAccounting(
            stakerAddr,
            stakeIdParam,
            st._stakedHearts,
            st._stakeShares,
            payout,
            penalty
        );

        if (cappedPenalty != 0) {
            _splitPenaltyProceeds(g, 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, "HEX: Empty stake list");
        require(stakeIndex < stakeListRef.length, "HEX: 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 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;
                } else {
                    /* Deny early-unstake before an auto-stake minimum has been served */
                    if (servedDays < MIN_AUTO_STAKE_DAYS) {
                        require(!st._isAutoStake, "HEX: Auto-stake still locked");
                    }
                }
            }

            (stakeReturn, payout, penalty, cappedPenalty) = _stakePerformance(g, st, servedDays);
        } else {
            /* Deny early-unstake before an auto-stake minimum has been served */
            require(!st._isAutoStake, "HEX: Auto-stake still locked");

            /* Stake hasn't been added to the total yet, so no penalties or rewards apply */
            g._nextStakeSharesTotal -= st._stakeShares;

            stakeReturn = st._stakedHearts;
        }

        _emitStakeEnd(
            stakeIdParam,
            st._stakedHearts,
            st._stakeShares,
            payout,
            penalty,
            servedDays,
            prevUnlocked
        );

        if (cappedPenalty != 0 && !prevUnlocked) {
            /* Split penalty proceeds only if not previously unlocked by stakeGoodAccounting() */
            _splitPenaltyProceeds(g, 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._lockedHeartsTotal -= st._stakedHearts;

        _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 newStakedHearts Number of Hearts to stake
     * @param newStakedDays Number of days to stake
     * @param newAutoStake Stake is automatic directly from a new claim
     */
    function _stakeStart(
        GlobalsCache memory g,
        uint256 newStakedHearts,
        uint256 newStakedDays,
        bool newAutoStake
    )
        internal
    {
        /* Enforce the maximum stake time */
        require(newStakedDays <= MAX_STAKE_DAYS, "HEX: newStakedDays higher than maximum");

        uint256 bonusHearts = _stakeStartBonusHearts(newStakedHearts, newStakedDays);
        uint256 newStakeShares = (newStakedHearts + bonusHearts) * SHARE_RATE_SCALE / g._shareRate;

        /* Ensure newStakedHearts is enough for at least one stake share */
        require(newStakeShares != 0, "HEX: newStakedHearts 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 < CLAIM_PHASE_START_DAY
            ? CLAIM_PHASE_START_DAY + 1
            : g._currentDay + 1;

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

        _emitStakeStart(newStakeId, newStakedHearts, newStakeShares, newStakedDays, newAutoStake);

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

        /* Track total staked Hearts for inflation calculations */
        g._lockedHeartsTotal += newStakedHearts;
    }

    /**
     * @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 Hearts
     */
    function _calcPayoutRewards(
        GlobalsCache memory g,
        uint256 stakeSharesParam,
        uint256 beginDay,
        uint256 endDay
    )
        private
        view
        returns (uint256 payout)
    {
        for (uint256 day = beginDay; day < endDay; day++) {
            payout += dailyData[day].dayPayoutTotal * stakeSharesParam
                / dailyData[day].dayStakeSharesTotal;
        }

        /* Less expensive to re-read storage than to have the condition inside the loop */
        if (beginDay <= BIG_PAY_DAY && endDay > BIG_PAY_DAY) {
            uint256 bigPaySlice = g._unclaimedSatoshisTotal * HEARTS_PER_SATOSHI * stakeSharesParam
                / dailyData[BIG_PAY_DAY].dayStakeSharesTotal;

            payout += bigPaySlice + _calcAdoptionBonus(g, bigPaySlice);
        }
        return payout;
    }

    /**
     * @dev Calculate bonus Hearts for a new stake, if any
     * @param newStakedHearts Number of Hearts to stake
     * @param newStakedDays Number of days to stake
     */
    function _stakeStartBonusHearts(uint256 newStakedHearts, uint256 newStakedDays)
        private
        pure
        returns (uint256 bonusHearts)
    {
        /*
            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 150M HEX of stake.

            biggerBonus%    = (cappedHearts /  BPB_MAX_HEARTS) * 10%
                            = (cappedHearts /  BPB_MAX_HEARTS) / 10
                            =  cappedHearts / (BPB_MAX_HEARTS * 10)
                            =  cappedHearts /  BPB

            COMBINED:

            combinedBonus%  =            longerBonus%  +  biggerBonus%

                                      cappedExtraDays     cappedHearts
                            =         ---------------  +  ------------
                                            LPB               BPB

                                cappedExtraDays * BPB     cappedHearts * LPB
                            =   ---------------------  +  ------------------
                                      LPB * BPB               LPB * BPB

                                cappedExtraDays * BPB  +  cappedHearts * LPB
                            =   --------------------------------------------
                                                  LPB  *  BPB

            bonusHearts     = hearts * combinedBonus%
                            = hearts * (cappedExtraDays * BPB  +  cappedHearts * 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 cappedStakedHearts = newStakedHearts <= BPB_MAX_HEARTS
            ? newStakedHearts
            : BPB_MAX_HEARTS;

        bonusHearts = cappedExtraDays * BPB + cappedStakedHearts * LPB;
        bonusHearts = newStakedHearts * bonusHearts / (LPB * BPB);

        return bonusHearts;
    }

    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 penalty, uint256 cappedPenalty)
    {
        if (servedDays < st._stakedDays) {
            (payout, penalty) = _calcPayoutAndEarlyPenalty(
                g,
                st._lockedDay,
                st._stakedDays,
                servedDays,
                st._stakeShares
            );
            stakeReturn = st._stakedHearts + payout;
        } else {
            // servedDays must == stakedDays here
            payout = _calcPayoutRewards(
                g,
                st._stakeShares,
                st._lockedDay,
                st._lockedDay + servedDays
            );
            stakeReturn = st._stakedHearts + 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, 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 _splitPenaltyProceeds(GlobalsCache memory g, uint256 penalty)
        private
    {
        /* Split a penalty 50:50 between Origin and stakePenaltyTotal */
        uint256 splitPenalty = penalty / 2;

        if (splitPenalty != 0) {
            _mint(ORIGIN_ADDR, splitPenalty);
        }

        /* Use the other half of the penalty to account for an odd-numbered penalty */
        splitPenalty = penalty - splitPenalty;
        g._stakePenaltyTotal += splitPenalty;
    }

    function _shareRateUpdate(GlobalsCache memory g, StakeCache memory st, uint256 stakeReturn)
        private
    {
        if (stakeReturn > st._stakedHearts) {
            /*
                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 bonusHearts = _stakeStartBonusHearts(stakeReturn, st._stakedDays);
            uint256 newShareRate = (stakeReturn + bonusHearts) * 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;

                _emitShareRateChange(newShareRate, st._stakeId);
            }
        }
    }

    function _emitStakeStart(
        uint40 stakeId,
        uint256 stakedHearts,
        uint256 stakeShares,
        uint256 stakedDays,
        bool isAutoStake
    )
        private
    {
        emit StakeStart( // (auto-generated event)
            uint256(uint40(block.timestamp))
                | (uint256(uint72(stakedHearts)) << 40)
                | (uint256(uint72(stakeShares)) << 112)
                | (uint256(uint16(stakedDays)) << 184)
                | (isAutoStake ? (1 << 200) : 0),
            msg.sender,
            stakeId
        );
    }

    function _emitStakeGoodAccounting(
        address stakerAddr,
        uint40 stakeId,
        uint256 stakedHearts,
        uint256 stakeShares,
        uint256 payout,
        uint256 penalty
    )
        private
    {
        emit StakeGoodAccounting( // (auto-generated event)
            uint256(uint40(block.timestamp))
                | (uint256(uint72(stakedHearts)) << 40)
                | (uint256(uint72(stakeShares)) << 112)
                | (uint256(uint72(payout)) << 184),
            uint256(uint72(penalty)),
            stakerAddr,
            stakeId,
            msg.sender
        );
    }

    function _emitStakeEnd(
        uint40 stakeId,
        uint256 stakedHearts,
        uint256 stakeShares,
        uint256 payout,
        uint256 penalty,
        uint256 servedDays,
        bool prevUnlocked
    )
        private
    {
        emit StakeEnd( // (auto-generated event)
            uint256(uint40(block.timestamp))
                | (uint256(uint72(stakedHearts)) << 40)
                | (uint256(uint72(stakeShares)) << 112)
                | (uint256(uint72(payout)) << 184),
            uint256(uint72(penalty))
                | (uint256(uint16(servedDays)) << 72)
                | (prevUnlocked ? (1 << 88) : 0),
            msg.sender,
            stakeId
        );
    }

    function _emitShareRateChange(uint256 shareRate, uint40 stakeId)
        private
    {
        emit ShareRateChange( // (auto-generated event)
            uint256(uint40(block.timestamp))
                | (uint256(uint40(shareRate)) << 40),
            stakeId
        );
    }
}

/**
 * @dev These functions deal with verification of Merkle trees (hash trees),
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        bytes32 computedHash = leaf;

        for (uint256 i = 0; i < proof.length; i++) {
            bytes32 proofElement = proof[i];

            if (computedHash < proofElement) {
                // Hash(current computed hash + current element of the proof)
                computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
            } else {
                // Hash(current element of the proof + current computed hash)
                computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
            }
        }

        // Check if the computed hash (root) is equal to the provided root
        return computedHash == root;
    }
}

contract UTXOClaimValidation is StakeableToken {
    /**
     * @dev PUBLIC FACING: Verify a BTC address and balance are unclaimed and part of the Merkle tree
     * @param btcAddr Bitcoin address (binary; no base58-check encoding)
     * @param rawSatoshis Raw BTC address balance in Satoshis
     * @param proof Merkle tree proof
     * @return True if can be claimed
     */
    function btcAddressIsClaimable(bytes20 btcAddr, uint256 rawSatoshis, bytes32[] calldata proof)
        external
        view
        returns (bool)
    {
        uint256 day = _currentDay();

        require(day >= CLAIM_PHASE_START_DAY, "HEX: Claim phase has not yet started");
        require(day < CLAIM_PHASE_END_DAY, "HEX: Claim phase has ended");

        /* Don't need to check Merkle proof if UTXO BTC address has already been claimed    */
        if (btcAddressClaims[btcAddr]) {
            return false;
        }

        /* Verify the Merkle tree proof */
        return _btcAddressIsValid(btcAddr, rawSatoshis, proof);
    }

    /**
     * @dev PUBLIC FACING: Verify a BTC address and balance are part of the Merkle tree
     * @param btcAddr Bitcoin address (binary; no base58-check encoding)
     * @param rawSatoshis Raw BTC address balance in Satoshis
     * @param proof Merkle tree proof
     * @return True if valid
     */
    function btcAddressIsValid(bytes20 btcAddr, uint256 rawSatoshis, bytes32[] calldata proof)
        external
        pure
        returns (bool)
    {
        return _btcAddressIsValid(btcAddr, rawSatoshis, proof);
    }

    /**
     * @dev PUBLIC FACING: Verify a Merkle proof using the UTXO Merkle tree
     * @param merkleLeaf Leaf asserted to be present in the Merkle tree
     * @param proof Generated Merkle tree proof
     * @return True if valid
     */
    function merkleProofIsValid(bytes32 merkleLeaf, bytes32[] calldata proof)
        external
        pure
        returns (bool)
    {
        return _merkleProofIsValid(merkleLeaf, proof);
    }

    /**
     * @dev PUBLIC FACING: Verify that a Bitcoin signature matches the claim message containing
     * the Ethereum address and claim param hash
     * @param claimToAddr Eth address within the signed claim message
     * @param claimParamHash Param hash within the signed claim message
     * @param pubKeyX First  half of uncompressed ECDSA public key
     * @param pubKeyY Second half of uncompressed ECDSA public key
     * @param claimFlags Claim flags specifying address and message formats
     * @param v v parameter of ECDSA signature
     * @param r r parameter of ECDSA signature
     * @param s s parameter of ECDSA signature
     * @return True if matching
     */
    function claimMessageMatchesSignature(
        address claimToAddr,
        bytes32 claimParamHash,
        bytes32 pubKeyX,
        bytes32 pubKeyY,
        uint8 claimFlags,
        uint8 v,
        bytes32 r,
        bytes32 s
    )
        public
        pure
        returns (bool)
    {
        require(v >= 27 && v <= 30, "HEX: v invalid");

        /*
            ecrecover() returns an Eth address rather than a public key, so
            we must do the same to compare.
        */
        address pubKeyEthAddr = pubKeyToEthAddress(pubKeyX, pubKeyY);

        /* Create and hash the claim message text */
        bytes32 messageHash = _hash256(
            _claimMessageCreate(claimToAddr, claimParamHash, claimFlags)
        );

        /* Verify the public key */
        return ecrecover(messageHash, v, r, s) == pubKeyEthAddr;
    }

    /**
     * @dev PUBLIC FACING: Derive an Ethereum address from an ECDSA public key
     * @param pubKeyX First  half of uncompressed ECDSA public key
     * @param pubKeyY Second half of uncompressed ECDSA public key
     * @return Derived Eth address
     */
    function pubKeyToEthAddress(bytes32 pubKeyX, bytes32 pubKeyY)
        public
        pure
        returns (address)
    {
        return address(uint160(uint256(keccak256(abi.encodePacked(pubKeyX, pubKeyY)))));
    }

    /**
     * @dev PUBLIC FACING: Derive a Bitcoin address from an ECDSA public key
     * @param pubKeyX First  half of uncompressed ECDSA public key
     * @param pubKeyY Second half of uncompressed ECDSA public key
     * @param claimFlags Claim flags specifying address and message formats
     * @return Derived Bitcoin address (binary; no base58-check encoding)
     */
    function pubKeyToBtcAddress(bytes32 pubKeyX, bytes32 pubKeyY, uint8 claimFlags)
        public
        pure
        returns (bytes20)
    {
        /*
            Helpful references:
             - https://en.bitcoin.it/wiki/Technical_background_of_version_1_Bitcoin_addresses
             - https://github.com/cryptocoinjs/ecurve/blob/master/lib/point.js
        */
        uint8 startingByte;
        bytes memory pubKey;
        bool compressed = (claimFlags & CLAIM_FLAG_BTC_ADDR_COMPRESSED) != 0;
        bool nested = (claimFlags & CLAIM_FLAG_BTC_ADDR_P2WPKH_IN_P2SH) != 0;
        bool bech32 = (claimFlags & CLAIM_FLAG_BTC_ADDR_BECH32) != 0;

        if (compressed) {
            /* Compressed public key format */
            require(!(nested && bech32), "HEX: claimFlags invalid");

            startingByte = (pubKeyY[31] & 0x01) == 0 ? 0x02 : 0x03;
            pubKey = abi.encodePacked(startingByte, pubKeyX);
        } else {
            /* Uncompressed public key format */
            require(!nested && !bech32, "HEX: claimFlags invalid");

            startingByte = 0x04;
            pubKey = abi.encodePacked(startingByte, pubKeyX, pubKeyY);
        }

        bytes20 pubKeyHash = _hash160(pubKey);
        if (nested) {
            return _hash160(abi.encodePacked(hex"0014", pubKeyHash));
        }
        return pubKeyHash;
    }

    /**
     * @dev Verify a BTC address and balance are part of the Merkle tree
     * @param btcAddr Bitcoin address (binary; no base58-check encoding)
     * @param rawSatoshis Raw BTC address balance in Satoshis
     * @param proof Merkle tree proof
     * @return True if valid
     */
    function _btcAddressIsValid(bytes20 btcAddr, uint256 rawSatoshis, bytes32[] memory proof)
        internal
        pure
        returns (bool)
    {
        /*
            Ensure the proof does not attempt to treat a Merkle leaf as if it were an
            internal Merkle tree node. A leaf will always have the zero-fill. An
            internal node will never have the zero-fill, as guaranteed by HEX's Merkle
            tree construction.

            The first element, proof[0], will always be a leaf because it is the pair
            of the leaf being validated. The rest of the elements, proof[1..length-1],
            must be internal nodes.

            The number of leaves (CLAIMABLE_BTC_ADDR_COUNT) is even, as guaranteed by
            HEX's Merkle tree construction, which eliminates the only edge-case where
            this validation would not apply.
        */
        require((uint256(proof[0]) & MERKLE_LEAF_FILL_MASK) == 0, "HEX: proof invalid");
        for (uint256 i = 1; i < proof.length; i++) {
            require((uint256(proof[i]) & MERKLE_LEAF_FILL_MASK) != 0, "HEX: proof invalid");
        }

        /*
            Calculate the 32 byte Merkle leaf associated with this BTC address and balance
                160 bits: BTC address
                 52 bits: Zero-fill
                 45 bits: Satoshis (limited by MAX_BTC_ADDR_BALANCE_SATOSHIS)
        */
        bytes32 merkleLeaf = bytes32(btcAddr) | bytes32(rawSatoshis);

        /* Verify the Merkle tree proof */
        return _merkleProofIsValid(merkleLeaf, proof);
    }

    /**
     * @dev Verify a Merkle proof using the UTXO Merkle tree
     * @param merkleLeaf Leaf asserted to be present in the Merkle tree
     * @param proof Generated Merkle tree proof
     * @return True if valid
     */
    function _merkleProofIsValid(bytes32 merkleLeaf, bytes32[] memory proof)
        private
        pure
        returns (bool)
    {
        return MerkleProof.verify(proof, MERKLE_TREE_ROOT, merkleLeaf);
    }

    function _claimMessageCreate(address claimToAddr, bytes32 claimParamHash, uint8 claimFlags)
        private
        pure
        returns (bytes memory)
    {
        bytes memory prefixStr = (claimFlags & CLAIM_FLAG_MSG_PREFIX_OLD) != 0
            ? OLD_CLAIM_PREFIX_STR
            : STD_CLAIM_PREFIX_STR;

        bool includeAddrChecksum = (claimFlags & CLAIM_FLAG_ETH_ADDR_LOWERCASE) == 0;

        bytes memory addrStr = _addressStringCreate(claimToAddr, includeAddrChecksum);

        if (claimParamHash == 0) {
            return abi.encodePacked(
                BITCOIN_SIG_PREFIX_LEN,
                BITCOIN_SIG_PREFIX_STR,
                uint8(prefixStr.length) + ETH_ADDRESS_HEX_LEN,
                prefixStr,
                addrStr
            );
        }

        bytes memory claimParamHashStr = new bytes(CLAIM_PARAM_HASH_HEX_LEN);

        _hexStringFromData(claimParamHashStr, claimParamHash, CLAIM_PARAM_HASH_BYTE_LEN);

        return abi.encodePacked(
            BITCOIN_SIG_PREFIX_LEN,
            BITCOIN_SIG_PREFIX_STR,
            uint8(prefixStr.length) + ETH_ADDRESS_HEX_LEN + 1 + CLAIM_PARAM_HASH_HEX_LEN,
            prefixStr,
            addrStr,
            "_",
            claimParamHashStr
        );
    }

    function _addressStringCreate(address addr, bool includeAddrChecksum)
        private
        pure
        returns (bytes memory addrStr)
    {
        addrStr = new bytes(ETH_ADDRESS_HEX_LEN);
        _hexStringFromData(addrStr, bytes32(bytes20(addr)), ETH_ADDRESS_BYTE_LEN);

        if (includeAddrChecksum) {
            bytes32 addrStrHash = keccak256(addrStr);

            uint256 offset = 0;

            for (uint256 i = 0; i < ETH_ADDRESS_BYTE_LEN; i++) {
                uint8 b = uint8(addrStrHash[i]);

                _addressStringChecksumChar(addrStr, offset++, b >> 4);
                _addressStringChecksumChar(addrStr, offset++, b & 0x0f);
            }
        }

        return addrStr;
    }

    function _addressStringChecksumChar(bytes memory addrStr, uint256 offset, uint8 hashNybble)
        private
        pure
    {
        bytes1 ch = addrStr[offset];

        if (ch >= "a" && hashNybble >= 8) {
            addrStr[offset] = ch ^ 0x20;
        }
    }

    function _hexStringFromData(bytes memory hexStr, bytes32 data, uint256 dataLen)
        private
        pure
    {
        uint256 offset = 0;

        for (uint256 i = 0; i < dataLen; i++) {
            uint8 b = uint8(data[i]);

            hexStr[offset++] = HEX_DIGITS[b >> 4];
            hexStr[offset++] = HEX_DIGITS[b & 0x0f];
        }
    }

    /**
     * @dev sha256(sha256(data))
     * @param data Data to be hashed
     * @return 32-byte hash
     */
    function _hash256(bytes memory data)
        private
        pure
        returns (bytes32)
    {
        return sha256(abi.encodePacked(sha256(data)));
    }

    /**
     * @dev ripemd160(sha256(data))
     * @param data Data to be hashed
     * @return 20-byte hash
     */
    function _hash160(bytes memory data)
        private
        pure
        returns (bytes20)
    {
        return ripemd160(abi.encodePacked(sha256(data)));
    }
}

contract UTXORedeemableToken is UTXOClaimValidation {
    /**
     * @dev PUBLIC FACING: Claim a BTC address and its Satoshi balance in Hearts
     * crediting the appropriate amount to a specified Eth address. Bitcoin ECDSA
     * signature must be from that BTC address and must match the claim message
     * for the Eth address.
     * @param rawSatoshis Raw BTC address balance in Satoshis
     * @param proof Merkle tree proof
     * @param claimToAddr Destination Eth address to credit Hearts to
     * @param pubKeyX First  half of uncompressed ECDSA public key for the BTC address
     * @param pubKeyY Second half of uncompressed ECDSA public key for the BTC address
     * @param claimFlags Claim flags specifying address and message formats
     * @param v v parameter of ECDSA signature
     * @param r r parameter of ECDSA signature
     * @param s s parameter of ECDSA signature
     * @param autoStakeDays Number of days to auto-stake, subject to minimum auto-stake days
     * @param referrerAddr Eth address of referring user (optional; 0x0 for no referrer)
     * @return Total number of Hearts credited, if successful
     */
    function btcAddressClaim(
        uint256 rawSatoshis,
        bytes32[] calldata proof,
        address claimToAddr,
        bytes32 pubKeyX,
        bytes32 pubKeyY,
        uint8 claimFlags,
        uint8 v,
        bytes32 r,
        bytes32 s,
        uint256 autoStakeDays,
        address referrerAddr
    )
        external
        returns (uint256)
    {
        /* Sanity check */
        require(rawSatoshis <= MAX_BTC_ADDR_BALANCE_SATOSHIS, "HEX: CHK: rawSatoshis");

        /* Enforce the minimum stake time for the auto-stake from this claim */
        require(autoStakeDays >= MIN_AUTO_STAKE_DAYS, "HEX: autoStakeDays lower than minimum");

        /* Ensure signature matches the claim message containing the Eth address and claimParamHash */
        {
            bytes32 claimParamHash = 0;

            if (claimToAddr != msg.sender) {
                /* Claimer did not send this, so claim params must be signed */
                claimParamHash = keccak256(
                    abi.encodePacked(MERKLE_TREE_ROOT, autoStakeDays, referrerAddr)
                );
            }

            require(
                claimMessageMatchesSignature(
                    claimToAddr,
                    claimParamHash,
                    pubKeyX,
                    pubKeyY,
                    claimFlags,
                    v,
                    r,
                    s
                ),
                "HEX: Signature mismatch"
            );
        }

        /* Derive BTC address from public key */
        bytes20 btcAddr = pubKeyToBtcAddress(pubKeyX, pubKeyY, claimFlags);

        /* Ensure BTC address has not yet been claimed */
        require(!btcAddressClaims[btcAddr], "HEX: BTC address balance already claimed");

        /* Ensure BTC address is part of the Merkle tree */
        require(
            _btcAddressIsValid(btcAddr, rawSatoshis, proof),
            "HEX: BTC address or balance unknown"
        );

        /* Mark BTC address as claimed */
        btcAddressClaims[btcAddr] = true;

        return _satoshisClaimSync(
            rawSatoshis,
            claimToAddr,
            btcAddr,
            claimFlags,
            autoStakeDays,
            referrerAddr
        );
    }

    function _satoshisClaimSync(
        uint256 rawSatoshis,
        address claimToAddr,
        bytes20 btcAddr,
        uint8 claimFlags,
        uint256 autoStakeDays,
        address referrerAddr
    )
        private
        returns (uint256 totalClaimedHearts)
    {
        GlobalsCache memory g;
        GlobalsCache memory gSnapshot;
        _globalsLoad(g, gSnapshot);

        totalClaimedHearts = _satoshisClaim(
            g,
            rawSatoshis,
            claimToAddr,
            btcAddr,
            claimFlags,
            autoStakeDays,
            referrerAddr
        );

        _globalsSync(g, gSnapshot);

        return totalClaimedHearts;
    }

    /**
     * @dev Credit an Eth address with the Hearts value of a raw Satoshis balance
     * @param g Cache of stored globals
     * @param rawSatoshis Raw BTC address balance in Satoshis
     * @param claimToAddr Destination Eth address for the claimed Hearts to be sent
     * @param btcAddr Bitcoin address (binary; no base58-check encoding)
     * @param autoStakeDays Number of days to auto-stake, subject to minimum auto-stake days
     * @param referrerAddr Eth address of referring user (optional; 0x0 for no referrer)
     * @return Total number of Hearts credited, if successful
     */
    function _satoshisClaim(
        GlobalsCache memory g,
        uint256 rawSatoshis,
        address claimToAddr,
        bytes20 btcAddr,
        uint8 claimFlags,
        uint256 autoStakeDays,
        address referrerAddr
    )
        private
        returns (uint256 totalClaimedHearts)
    {
        /* Allowed only during the claim phase */
        require(g._currentDay >= CLAIM_PHASE_START_DAY, "HEX: Claim phase has not yet started");
        require(g._currentDay < CLAIM_PHASE_END_DAY, "HEX: Claim phase has ended");

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

        /* Sanity check */
        require(
            g._claimedBtcAddrCount < CLAIMABLE_BTC_ADDR_COUNT,
            "HEX: CHK: _claimedBtcAddrCount"
        );

        (uint256 adjSatoshis, uint256 claimedHearts, uint256 claimBonusHearts) = _calcClaimValues(
            g,
            rawSatoshis
        );

        /* Increment claim count to track viral rewards */
        g._claimedBtcAddrCount++;

        totalClaimedHearts = _remitBonuses(
            claimToAddr,
            btcAddr,
            claimFlags,
            rawSatoshis,
            adjSatoshis,
            claimedHearts,
            claimBonusHearts,
            referrerAddr
        );

        /* Auto-stake a percentage of the successful claim */
        uint256 autoStakeHearts = totalClaimedHearts * AUTO_STAKE_CLAIM_PERCENT / 100;
        _stakeStart(g, autoStakeHearts, autoStakeDays, true);

        /* Mint remaining claimed Hearts to claim address */
        _mint(claimToAddr, totalClaimedHearts - autoStakeHearts);

        return totalClaimedHearts;
    }

    function _remitBonuses(
        address claimToAddr,
        bytes20 btcAddr,
        uint8 claimFlags,
        uint256 rawSatoshis,
        uint256 adjSatoshis,
        uint256 claimedHearts,
        uint256 claimBonusHearts,
        address referrerAddr
    )
        private
        returns (uint256 totalClaimedHearts)
    {
        totalClaimedHearts = claimedHearts + claimBonusHearts;

        uint256 originBonusHearts = claimBonusHearts;

        if (referrerAddr == address(0)) {
            /* No referrer */
            _emitClaim(
                claimToAddr,
                btcAddr,
                claimFlags,
                rawSatoshis,
                adjSatoshis,
                totalClaimedHearts,
                referrerAddr
            );
        } else {
            /* Referral bonus of 10% of total claimed Hearts to claimer */
            uint256 referralBonusHearts = totalClaimedHearts / 10;

            totalClaimedHearts += referralBonusHearts;

            /* Then a cumulative referrer bonus of 20% to referrer */
            uint256 referrerBonusHearts = totalClaimedHearts / 5;

            originBonusHearts += referralBonusHearts + referrerBonusHearts;

            if (referrerAddr == claimToAddr) {
                /* Self-referred */
                totalClaimedHearts += referrerBonusHearts;
                _emitClaim(
                    claimToAddr,
                    btcAddr,
                    claimFlags,
                    rawSatoshis,
                    adjSatoshis,
                    totalClaimedHearts,
                    referrerAddr
                );
            } else {
                /* Referred by different address */
                _emitClaim(
                    claimToAddr,
                    btcAddr,
                    claimFlags,
                    rawSatoshis,
                    adjSatoshis,
                    totalClaimedHearts,
                    referrerAddr
                );
                _mint(referrerAddr, referrerBonusHearts);
            }
        }

        _mint(ORIGIN_ADDR, originBonusHearts);

        return totalClaimedHearts;
    }

    function _emitClaim(
        address claimToAddr,
        bytes20 btcAddr,
        uint8 claimFlags,
        uint256 rawSatoshis,
        uint256 adjSatoshis,
        uint256 claimedHearts,
        address referrerAddr
    )
        private
    {
        emit Claim( // (auto-generated event)
            uint256(uint40(block.timestamp))
                | (uint256(uint56(rawSatoshis)) << 40)
                | (uint256(uint56(adjSatoshis)) << 96)
                | (uint256(claimFlags) << 152)
                | (uint256(uint72(claimedHearts)) << 160),
            uint256(uint160(msg.sender)),
            btcAddr,
            claimToAddr,
            referrerAddr
        );

        if (claimToAddr == msg.sender) {
            return;
        }

        emit ClaimAssist( // (auto-generated event)
            uint256(uint40(block.timestamp))
                | (uint256(uint160(btcAddr)) << 40)
                | (uint256(uint56(rawSatoshis)) << 200),
            uint256(uint56(adjSatoshis))
                | (uint256(uint160(claimToAddr)) << 56)
                | (uint256(claimFlags) << 216),
            uint256(uint72(claimedHearts))
                | (uint256(uint160(referrerAddr)) << 72),
            msg.sender
        );
    }

    function _calcClaimValues(GlobalsCache memory g, uint256 rawSatoshis)
        private
        pure
        returns (uint256 adjSatoshis, uint256 claimedHearts, uint256 claimBonusHearts)
    {
        /* Apply Silly Whale reduction */
        adjSatoshis = _adjustSillyWhale(rawSatoshis);
        require(
            g._claimedSatoshisTotal + adjSatoshis <= CLAIMABLE_SATOSHIS_TOTAL,
            "HEX: CHK: _claimedSatoshisTotal"
        );
        g._claimedSatoshisTotal += adjSatoshis;

        uint256 daysRemaining = CLAIM_PHASE_END_DAY - g._currentDay;

        /* Apply late-claim reduction */
        adjSatoshis = _adjustLateClaim(adjSatoshis, daysRemaining);
        g._unclaimedSatoshisTotal -= adjSatoshis;

        /* Convert to Hearts and calculate speed bonus */
        claimedHearts = adjSatoshis * HEARTS_PER_SATOSHI;
        claimBonusHearts = _calcSpeedBonus(claimedHearts, daysRemaining);

        return (adjSatoshis, claimedHearts, claimBonusHearts);
    }

    /**
     * @dev Apply Silly Whale adjustment
     * @param rawSatoshis Raw BTC address balance in Satoshis
     * @return Adjusted BTC address balance in Satoshis
     */
    function _adjustSillyWhale(uint256 rawSatoshis)
        private
        pure
        returns (uint256)
    {
        if (rawSatoshis < 1000e8) {
            /* For < 1,000 BTC: no penalty */
            return rawSatoshis;
        }
        if (rawSatoshis >= 10000e8) {
            /* For >= 10,000 BTC: penalty is 75%, leaving 25% */
            return rawSatoshis / 4;
        }
        /*
            For 1,000 <= BTC < 10,000: penalty scales linearly from 50% to 75%

            penaltyPercent  = (btc - 1000) / (10000 - 1000) * (75 - 50) + 50
                            = (btc - 1000) / 9000 * 25 + 50
                            = (btc - 1000) / 360 + 50

            appliedPercent  = 100 - penaltyPercent
                            = 100 - ((btc - 1000) / 360 + 50)
                            = 100 - (btc - 1000) / 360 - 50
                            = 50 - (btc - 1000) / 360
                            = (18000 - (btc - 1000)) / 360
                            = (18000 - btc + 1000) / 360
                            = (19000 - btc) / 360

            adjustedBtc     = btc * appliedPercent / 100
                            = btc * ((19000 - btc) / 360) / 100
                            = btc * (19000 - btc) / 36000

            adjustedSat     = 1e8 * adjustedBtc
                            = 1e8 * (btc * (19000 - btc) / 36000)
                            = 1e8 * ((sat / 1e8) * (19000 - (sat / 1e8)) / 36000)
                            = 1e8 * (sat / 1e8) * (19000 - (sat / 1e8)) / 36000
                            = (sat / 1e8) * 1e8 * (19000 - (sat / 1e8)) / 36000
                            = (sat / 1e8) * (19000e8 - sat) / 36000
                            = sat * (19000e8 - sat) / 36000e8
        */
        return rawSatoshis * (19000e8 - rawSatoshis) / 36000e8;
    }

    /**
     * @dev Apply late-claim adjustment to scale claim to zero by end of claim phase
     * @param adjSatoshis Adjusted BTC address balance in Satoshis (after Silly Whale)
     * @param daysRemaining Number of reward days remaining in claim phase
     * @return Adjusted BTC address balance in Satoshis (after Silly Whale and Late-Claim)
     */
    function _adjustLateClaim(uint256 adjSatoshis, uint256 daysRemaining)
        private
        pure
        returns (uint256)
    {
        /*
            Only valid from CLAIM_PHASE_DAYS to 1, and only used during that time.

            adjustedSat = sat * (daysRemaining / CLAIM_PHASE_DAYS) * 100%
                        = sat *  daysRemaining / CLAIM_PHASE_DAYS
        */
        return adjSatoshis * daysRemaining / CLAIM_PHASE_DAYS;
    }

    /**
     * @dev Calculates speed bonus for claiming earlier in the claim phase
     * @param claimedHearts Hearts claimed from adjusted BTC address balance Satoshis
     * @param daysRemaining Number of claim days remaining in claim phase
     * @return Speed bonus in Hearts
     */
    function _calcSpeedBonus(uint256 claimedHearts, uint256 daysRemaining)
        private
        pure
        returns (uint256)
    {
        /*
            Only valid from CLAIM_PHASE_DAYS to 1, and only used during that time.
            Speed bonus is 20% ... 0% inclusive.

            bonusHearts = claimedHearts  * ((daysRemaining - 1)  /  (CLAIM_PHASE_DAYS - 1)) * 20%
                        = claimedHearts  * ((daysRemaining - 1)  /  (CLAIM_PHASE_DAYS - 1)) * 20/100
                        = claimedHearts  * ((daysRemaining - 1)  /  (CLAIM_PHASE_DAYS - 1)) / 5
                        = claimedHearts  *  (daysRemaining - 1)  / ((CLAIM_PHASE_DAYS - 1)  * 5)
        */
        return claimedHearts * (daysRemaining - 1) / ((CLAIM_PHASE_DAYS - 1) * 5);
    }
}

contract TransformableToken is UTXORedeemableToken {
    /**
     * @dev PUBLIC FACING: Enter the tranform lobby for the current round
     * @param referrerAddr Eth address of referring user (optional; 0x0 for no referrer)
     */
    function xfLobbyEnter(address referrerAddr)
        external
        payable
    {
        uint256 enterDay = _currentDay();
        require(enterDay < CLAIM_PHASE_END_DAY, "HEX: Lobbies have ended");

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

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

        uint256 entryIndex = qRef.tailIndex++;

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

        xfLobby[enterDay] += rawAmount;

        _emitXfLobbyEnter(enterDay, entryIndex, rawAmount, referrerAddr);
    }

    /**
     * @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(), "HEX: 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, "HEX: count invalid");
            endIndex = headIndex + count;
        } else {
            endIndex = qRef.tailIndex;
            require(headIndex < endIndex, "HEX: count invalid");
        }

        uint256 waasLobby = _waasLobby(enterDay);
        uint256 _xfLobby = xfLobby[enterDay];
        uint256 totalXfAmount = 0;
        uint256 originBonusHearts = 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)) {
                /* No referrer */
                _emitXfLobbyExit(enterDay, headIndex, xfAmount, referrerAddr);
            } else {
                /* Referral bonus of 10% of xfAmount to member */
                uint256 referralBonusHearts = xfAmount / 10;

                xfAmount += referralBonusHearts;

                /* Then a cumulative referrer bonus of 20% to referrer */
                uint256 referrerBonusHearts = xfAmount / 5;

                if (referrerAddr == msg.sender) {
                    /* Self-referred */
                    xfAmount += referrerBonusHearts;
                    _emitXfLobbyExit(enterDay, headIndex, xfAmount, referrerAddr);
                } else {
                    /* Referred by different address */
                    _emitXfLobbyExit(enterDay, headIndex, xfAmount, referrerAddr);
                    _mint(referrerAddr, referrerBonusHearts);
                }
                originBonusHearts += referralBonusHearts + referrerBonusHearts;
            }

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

        qRef.headIndex = uint40(headIndex);

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

    /**
     * @dev PUBLIC FACING: Release any value that has been sent to the contract
     */
    function xfLobbyFlush()
        external
    {
        require(address(this).balance != 0, "HEX: No value");

        FLUSH_ADDR.transfer(address(this).balance);
    }

    /**
     * @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 <= CLAIM_PHASE_END_DAY && endDay <= _currentDay(),
            "HEX: 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 Eth address of the lobby member
     * @param entryId 49 bit compound value. Top 9 bits: enterDay, Bottom 40 bits: entryIndex
     * @return 1: Raw amount that was entered with; 2: Referring Eth addr (optional; 0x0 for no referrer)
     */
    function xfLobbyEntry(address memberAddr, uint256 entryId)
        external
        view
        returns (uint256 rawAmount, address referrerAddr)
    {
        uint256 enterDay = entryId >> XF_LOBBY_ENTRY_INDEX_SIZE;
        uint256 entryIndex = entryId & XF_LOBBY_ENTRY_INDEX_MASK;

        XfLobbyEntryStore storage entry = xfLobbyMembers[enterDay][memberAddr].entries[entryIndex];

        require(entry.rawAmount != 0, "HEX: 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 Eth 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;

        if (day > CLAIM_PHASE_END_DAY) {
            day = CLAIM_PHASE_END_DAY;
        }

        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)
    {
        if (enterDay >= CLAIM_PHASE_START_DAY) {
            GlobalsCache memory g;
            GlobalsCache memory gSnapshot;
            _globalsLoad(g, gSnapshot);

            _dailyDataUpdateAuto(g);

            uint256 unclaimed = dailyData[enterDay].dayUnclaimedSatoshisTotal;
            waasLobby = unclaimed * HEARTS_PER_SATOSHI / CLAIM_PHASE_DAYS;

            _globalsSync(g, gSnapshot);
        } else {
            waasLobby = WAAS_LOBBY_SEED_HEARTS;
        }
        return waasLobby;
    }

    function _emitXfLobbyEnter(
        uint256 enterDay,
        uint256 entryIndex,
        uint256 rawAmount,
        address referrerAddr
    )
        private
    {
        emit XfLobbyEnter( // (auto-generated event)
            uint256(uint40(block.timestamp))
                | (uint256(uint96(rawAmount)) << 40),
            msg.sender,
            (enterDay << XF_LOBBY_ENTRY_INDEX_SIZE) | entryIndex,
            referrerAddr
        );
    }

    function _emitXfLobbyExit(
        uint256 enterDay,
        uint256 entryIndex,
        uint256 xfAmount,
        address referrerAddr
    )
        private
    {
        emit XfLobbyExit( // (auto-generated event)
            uint256(uint40(block.timestamp))
                | (uint256(uint72(xfAmount)) << 40),
            msg.sender,
            (enterDay << XF_LOBBY_ENTRY_INDEX_SIZE) | entryIndex,
            referrerAddr
        );
    }
}

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

        /* Initialize dailyDataCount to skip pre-claim period */
        globals.dailyDataCount = uint16(PRE_CLAIM_DAYS);

        /* Add all Satoshis from UTXO snapshot to contract */
        globals.claimStats = _claimStatsEncode(
            0, // _claimedBtcAddrCount
            0, // _claimedSatoshisTotal
            FULL_SATOSHIS_TOTAL // _unclaimedSatoshisTotal
        );
    }

    function() external payable {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"data0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"data1","type":"uint256"},{"indexed":true,"internalType":"bytes20","name":"btcAddr","type":"bytes20"},{"indexed":true,"internalType":"address","name":"claimToAddr","type":"address"},{"indexed":true,"internalType":"address","name":"referrerAddr","type":"address"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"data0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"data1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"data2","type":"uint256"},{"indexed":true,"internalType":"address","name":"senderAddr","type":"address"}],"name":"ClaimAssist","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"data0","type":"uint256"},{"indexed":true,"internalType":"address","name":"updaterAddr","type":"address"}],"name":"DailyDataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"data0","type":"uint256"},{"indexed":true,"internalType":"uint40","name":"stakeId","type":"uint40"}],"name":"ShareRateChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"data0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"data1","type":"uint256"},{"indexed":true,"internalType":"address","name":"stakerAddr","type":"address"},{"indexed":true,"internalType":"uint40","name":"stakeId","type":"uint40"}],"name":"StakeEnd","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"data0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"data1","type":"uint256"},{"indexed":true,"internalType":"address","name":"stakerAddr","type":"address"},{"indexed":true,"internalType":"uint40","name":"stakeId","type":"uint40"},{"indexed":true,"internalType":"address","name":"senderAddr","type":"address"}],"name":"StakeGoodAccounting","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"data0","type":"uint256"},{"indexed":true,"internalType":"address","name":"stakerAddr","type":"address"},{"indexed":true,"internalType":"uint40","name":"stakeId","type":"uint40"}],"name":"StakeStart","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"data0","type":"uint256"},{"indexed":true,"internalType":"address","name":"memberAddr","type":"address"},{"indexed":true,"internalType":"uint256","name":"entryId","type":"uint256"},{"indexed":true,"internalType":"address","name":"referrerAddr","type":"address"}],"name":"XfLobbyEnter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"data0","type":"uint256"},{"indexed":true,"internalType":"address","name":"memberAddr","type":"address"},{"indexed":true,"internalType":"uint256","name":"entryId","type":"uint256"},{"indexed":true,"internalType":"address","name":"referrerAddr","type":"address"}],"name":"XfLobbyExit","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":true,"inputs":[],"name":"allocatedSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"rawSatoshis","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"address","name":"claimToAddr","type":"address"},{"internalType":"bytes32","name":"pubKeyX","type":"bytes32"},{"internalType":"bytes32","name":"pubKeyY","type":"bytes32"},{"internalType":"uint8","name":"claimFlags","type":"uint8"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint256","name":"autoStakeDays","type":"uint256"},{"internalType":"address","name":"referrerAddr","type":"address"}],"name":"btcAddressClaim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes20","name":"","type":"bytes20"}],"name":"btcAddressClaims","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes20","name":"btcAddr","type":"bytes20"},{"internalType":"uint256","name":"rawSatoshis","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"btcAddressIsClaimable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes20","name":"btcAddr","type":"bytes20"},{"internalType":"uint256","name":"rawSatoshis","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"btcAddressIsValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"claimToAddr","type":"address"},{"internalType":"bytes32","name":"claimParamHash","type":"bytes32"},{"internalType":"bytes32","name":"pubKeyX","type":"bytes32"},{"internalType":"bytes32","name":"pubKeyY","type":"bytes32"},{"internalType":"uint8","name":"claimFlags","type":"uint8"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"claimMessageMatchesSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"currentDay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"dailyData","outputs":[{"internalType":"uint72","name":"dayPayoutTotal","type":"uint72"},{"internalType":"uint72","name":"dayStakeSharesTotal","type":"uint72"},{"internalType":"uint56","name":"dayUnclaimedSatoshisTotal","type":"uint56"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"beginDay","type":"uint256"},{"internalType":"uint256","name":"endDay","type":"uint256"}],"name":"dailyDataRange","outputs":[{"internalType":"uint256[]","name":"list","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"beforeDay","type":"uint256"}],"name":"dailyDataUpdate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"globalInfo","outputs":[{"internalType":"uint256[13]","name":"","type":"uint256[13]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"globals","outputs":[{"internalType":"uint72","name":"lockedHeartsTotal","type":"uint72"},{"internalType":"uint72","name":"nextStakeSharesTotal","type":"uint72"},{"internalType":"uint40","name":"shareRate","type":"uint40"},{"internalType":"uint72","name":"stakePenaltyTotal","type":"uint72"},{"internalType":"uint16","name":"dailyDataCount","type":"uint16"},{"internalType":"uint72","name":"stakeSharesTotal","type":"uint72"},{"internalType":"uint40","name":"latestStakeId","type":"uint40"},{"internalType":"uint128","name":"claimStats","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"merkleLeaf","type":"bytes32"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"merkleProofIsValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"pubKeyX","type":"bytes32"},{"internalType":"bytes32","name":"pubKeyY","type":"bytes32"},{"internalType":"uint8","name":"claimFlags","type":"uint8"}],"name":"pubKeyToBtcAddress","outputs":[{"internalType":"bytes20","name":"","type":"bytes20"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"pubKeyX","type":"bytes32"},{"internalType":"bytes32","name":"pubKeyY","type":"bytes32"}],"name":"pubKeyToEthAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"stakerAddr","type":"address"}],"name":"stakeCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"stakeIndex","type":"uint256"},{"internalType":"uint40","name":"stakeIdParam","type":"uint40"}],"name":"stakeEnd","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"stakerAddr","type":"address"},{"internalType":"uint256","name":"stakeIndex","type":"uint256"},{"internalType":"uint40","name":"stakeIdParam","type":"uint40"}],"name":"stakeGoodAccounting","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakeLists","outputs":[{"internalType":"uint40","name":"stakeId","type":"uint40"},{"internalType":"uint72","name":"stakedHearts","type":"uint72"},{"internalType":"uint72","name":"stakeShares","type":"uint72"},{"internalType":"uint16","name":"lockedDay","type":"uint16"},{"internalType":"uint16","name":"stakedDays","type":"uint16"},{"internalType":"uint16","name":"unlockedDay","type":"uint16"},{"internalType":"bool","name":"isAutoStake","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newStakedHearts","type":"uint256"},{"internalType":"uint256","name":"newStakedDays","type":"uint256"}],"name":"stakeStart","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"xfLobby","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"referrerAddr","type":"address"}],"name":"xfLobbyEnter","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"memberAddr","type":"address"},{"internalType":"uint256","name":"entryId","type":"uint256"}],"name":"xfLobbyEntry","outputs":[{"internalType":"uint256","name":"rawAmount","type":"uint256"},{"internalType":"address","name":"referrerAddr","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"enterDay","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"xfLobbyExit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"xfLobbyFlush","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"xfLobbyMembers","outputs":[{"internalType":"uint40","name":"headIndex","type":"uint40"},{"internalType":"uint40","name":"tailIndex","type":"uint40"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"memberAddr","type":"address"}],"name":"xfLobbyPendingDays","outputs":[{"internalType":"uint256[2]","name":"words","type":"uint256[2]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"beginDay","type":"uint256"},{"internalType":"uint256","name":"endDay","type":"uint256"}],"name":"xfLobbyRange","outputs":[{"internalType":"uint256[]","name":"list","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"}]

60806040523480156200001157600080fd5b506003805464ffffffffff60901b1916740186a00000000000000000000000000000000000001790556004805461ffff191660011790556200005d60008066066c277de83e9c6200008d565b600480546001600160801b039283167001000000000000000000000000000000000292169190911790556200009e565b60669290921b60339190911b171790565b6151fd80620000ae6000396000f3fe6080604052600436106102305760003560e01c80636a210a0e1161012e578063a9059cbb116100ab578063d5a373ff1161006f578063d5a373ff14610bff578063dd62ed3e14610c64578063ec9a191714610c9f578063f04b5fa014610d30578063f57a1b3c14610d5b57610230565b8063a9059cbb14610a9b578063bd926ed314610ad4578063c312452514610b2e578063cbb151d314610ba9578063ce7d1f7714610bd957610230565b80638f1c65c0116100f25780638f1c65c01461091357806390de68711461093d57806395d89b411461023257806396f62b9d1461099a578063a457c2d714610a6257610230565b80636a210a0e1461077157806370a08231146107f15780637c4266201461082457806387a0f31c146108585780638e21aa011461088257610230565b806333060d90116101bc57806344f0de751161018057806344f0de751461066357806352a438b8146106d15780635ac1f357146107015780635c9302c91461071657806365cf71b21461072b57610230565b806333060d901461054e578063343009a21461058157806339509351146105b85780633a70a5ca146105f157806344203faf1461060657610230565b80632607443b116102035780632607443b1461037357806327aa6018146103ff578063283a5baf1461048157806330c1a785146104d7578063313ce5671461052357610230565b806306fdde0314610232578063095ea7b3146102bc57806318160ddd1461030957806323b872dd14610330575b005b34801561023e57600080fd5b50610247610d8b565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610281578181015183820152602001610269565b50505050905090810190601f1680156102ae5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156102c857600080fd5b506102f5600480360360408110156102df57600080fd5b506001600160a01b038135169060200135610daa565b604080519115158252519081900360200190f35b34801561031557600080fd5b5061031e610dc7565b60408051918252519081900360200190f35b34801561033c57600080fd5b506102f56004803603606081101561035357600080fd5b506001600160a01b03813581169160208101359091169060400135610dcd565b34801561037f57600080fd5b506103ac6004803603604081101561039657600080fd5b506001600160a01b038135169060200135610e5b565b6040805164ffffffffff90981688526001600160481b039687166020890152949095168685015261ffff928316606087015290821660808601521660a084015290151560c0830152519081900360e00190f35b34801561040b57600080fd5b506102f56004803603604081101561042257600080fd5b81359190810190604081016020820135600160201b81111561044357600080fd5b82018360208201111561045557600080fd5b803590602001918460208302840111600160201b8311171561047657600080fd5b509092509050610ed4565b34801561048d57600080fd5b506104ba600480360360608110156104a457600080fd5b508035906020810135906040013560ff16610f1b565b604080516001600160601b03199092168252519081900360200190f35b3480156104e357600080fd5b50610507600480360360408110156104fa57600080fd5b50803590602001356110d9565b604080516001600160a01b039092168252519081900360200190f35b34801561052f57600080fd5b50610538611105565b6040805160ff9092168252519081900360200190f35b34801561055a57600080fd5b5061031e6004803603602081101561057157600080fd5b50356001600160a01b031661110a565b34801561058d57600080fd5b50610230600480360360408110156105a457600080fd5b508035906020013564ffffffffff16611129565b3480156105c457600080fd5b506102f5600480360360408110156105db57600080fd5b506001600160a01b0381351690602001356113e7565b3480156105fd57600080fd5b5061031e61143b565b34801561061257600080fd5b5061063f6004803603604081101561062957600080fd5b50803590602001356001600160a01b0316611458565b6040805164ffffffffff938416815291909216602082015281519081900390910190f35b34801561066f57600080fd5b506106966004803603602081101561068657600080fd5b50356001600160a01b0316611487565b6040518082600260200280838360005b838110156106be5781810151838201526020016106a6565b5050505090500191505060405180910390f35b3480156106dd57600080fd5b50610230600480360360408110156106f457600080fd5b5080359060200135611521565b34801561070d57600080fd5b506102306115ab565b34801561072257600080fd5b5061031e611632565b34801561073757600080fd5b506102306004803603606081101561074e57600080fd5b5080356001600160a01b0316906020810135906040013564ffffffffff16611641565b34801561077d57600080fd5b506107a16004803603604081101561079457600080fd5b5080359060200135611895565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156107dd5781810151838201526020016107c5565b505050509050019250505060405180910390f35b3480156107fd57600080fd5b5061031e6004803603602081101561081457600080fd5b50356001600160a01b03166119b1565b34801561083057600080fd5b506102f56004803603602081101561084757600080fd5b50356001600160601b0319166119cc565b34801561086457600080fd5b5061031e6004803603602081101561087b57600080fd5b50356119e1565b34801561088e57600080fd5b506102f5600480360360608110156108a557600080fd5b6001600160601b031982351691602081013591810190606081016040820135600160201b8111156108d557600080fd5b8201836020820111156108e757600080fd5b803590602001918460208302840111600160201b8311171561090857600080fd5b5090925090506119f3565b34801561091f57600080fd5b506102306004803603602081101561093657600080fd5b5035611b0a565b34801561094957600080fd5b506109676004803603602081101561096057600080fd5b5035611bea565b604080516001600160481b03948516815292909316602083015266ffffffffffffff168183015290519081900360600190f35b3480156109a657600080fd5b5061031e60048036036101608110156109be57600080fd5b81359190810190604081016020820135600160201b8111156109df57600080fd5b8201836020820111156109f157600080fd5b803590602001918460208302840111600160201b83111715610a1257600080fd5b91935091506001600160a01b03813581169160208101359160408201359160ff606082013581169260808301359091169160a08101359160c08201359160e0810135916101009091013516611c23565b348015610a6e57600080fd5b506102f560048036036040811015610a8557600080fd5b506001600160a01b038135169060200135611eb3565b348015610aa757600080fd5b506102f560048036036040811015610abe57600080fd5b506001600160a01b038135169060200135611f21565b348015610ae057600080fd5b50610b0d60048036036040811015610af757600080fd5b506001600160a01b038135169060200135611f35565b604080519283526001600160a01b0390911660208301528051918290030190f35b348015610b3a57600080fd5b50610b43611ff1565b604080516001600160481b03998a168152978916602089015264ffffffffff96871688820152948816606088015261ffff9093166080870152951660a08501529390911660c08301526001600160801b0390921660e08201529051908190036101000190f35b348015610bb557600080fd5b5061023060048036036040811015610bcc57600080fd5b5080359060200135612055565b61023060048036036020811015610bef57600080fd5b50356001600160a01b03166122d2565b348015610c0b57600080fd5b506102f56004803603610100811015610c2357600080fd5b506001600160a01b038135169060208101359060408101359060608101359060ff608082013581169160a08101359091169060c08101359060e00135612443565b348015610c7057600080fd5b5061031e60048036036040811015610c8757600080fd5b506001600160a01b038135811691602001351661254f565b348015610cab57600080fd5b506102f560048036036060811015610cc257600080fd5b6001600160601b031982351691602081013591810190606081016040820135600160201b811115610cf257600080fd5b820183602082011115610d0457600080fd5b803590602001918460208302840111600160201b83111715610d2557600080fd5b50909250905061257a565b348015610d3c57600080fd5b50610d456125c3565b6040518151815280826101a080838360206106a6565b348015610d6757600080fd5b506107a160048036036040811015610d7e57600080fd5b50803590602001356126c4565b604051806040016040528060038152602001620908ab60eb1b81525081565b6000610dbe610db76127a2565b84846127a6565b50600192915050565b60025490565b6000610dda848484612892565b610e5084610de66127a2565b610e4b856040518060600160405280602881526020016150a2602891396001600160a01b038a16600090815260016020526040812090610e246127a2565b6001600160a01b03168152602081019190915260400160002054919063ffffffff6129ee16565b6127a6565b5060015b9392505050565b60076020528160005260406000208181548110610e7457fe5b60009182526020909120015464ffffffffff811692506001600160481b03600160281b820481169250600160701b8204169061ffff600160b81b8204811691600160c81b8104821691600160d81b8204169060ff600160e81b9091041687565b6000610f1384848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612a8592505050565b949350505050565b600080606060028416158015906004861615159060088716151590610fe657818015610f445750805b15610f90576040805162461bcd60e51b81526020600482015260176024820152761211560e8818db185a5b519b1859dcc81a5b9d985b1a59604a1b604482015290519081900360640190fd5b600160f81b60f889901b1615610fa7576003610faa565b60025b604080516001600160f81b031960f884901b16602082015260218082018d90528251808303909101815260419091019091529095509350611073565b81158015610ff2575080155b61103d576040805162461bcd60e51b81526020600482015260176024820152761211560e8818db185a5b519b1859dcc81a5b9d985b1a59604a1b604482015290519081900360640190fd5b60408051600160fa1b6020820152602181018b905260418082018b90528251808303909101815260619091019091526004955093505b600061107e85612ab2565b905082156110cc5760408051600560f21b60208201526001600160601b0319831660228201528151601681830301815260369091019091526110bf90612ab2565b9650505050505050610e54565b9998505050505050505050565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b600881565b6001600160a01b0381166000908152600760205260409020545b919050565b611131614e43565b611139614e43565b6111438282612bd7565b336000908152600760205260409020805461119d576040805162461bcd60e51b81526020600482015260156024820152741211560e88115b5c1d1e481cdd185ad9481b1a5cdd605a1b604482015290519081900360640190fd5b805485106111ec576040805162461bcd60e51b81526020600482015260176024820152761211560e881cdd185ad9525b99195e081a5b9d985b1a59604a1b604482015290519081900360640190fd5b6111f4614ea4565b61121482878154811061120357fe5b906000526020600020018683612c89565b61121d84612d5c565b60a081015160608201516101408601516000921515918391829182918291116112fd57841561125257866080015195506112e3565b61125c8a88612d6d565b86606001518a6101400151039550866080015186111561128257866080015195506112e3565b61015e8610156112e3578660c00151156112e3576040805162461bcd60e51b815260206004820152601c60248201527f4845583a204175746f2d7374616b65207374696c6c206c6f636b656400000000604482015290519081900360640190fd5b6112ee8a8888612d8c565b9296509094509250905061136d565b8660c0015115611354576040805162461bcd60e51b815260206004820152601c60248201527f4845583a204175746f2d7374616b65207374696c6c206c6f636b656400000000604482015290519081900360640190fd5b60408701516020808c0180519290920390915287015193505b6113848b8860200151896040015186868b8b612e30565b8015801590611391575084155b156113a0576113a08a82612eed565b83156113bb576113b03385612f28565b6113bb8a8886613018565b60208701518a51038a526113cf888d613084565b6113d98a8a6131e2565b505050505050505050505050565b6000610dbe6113f46127a2565b84610e4b85600160006114056127a2565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff6133d516565b6003546000906001600160481b0316611452610dc7565b01905090565b600960209081526000928352604080842090915290825290205464ffffffffff80821691600160281b90041682565b61148f614eea565b600061149961342f565b600101905061015f8111156114ad575061015f5b6000198101901561151b5760008181526009602090815260408083206001600160a01b038716845290915290205464ffffffffff808216600160281b90920416111561151657600160ff82161b82600883901c6002811061150a57fe5b60200201805190911790525b6114ad565b50919050565b611529614e43565b611531614e43565b61153b8282612bd7565b600183101561157b5760405162461bcd60e51b815260040180806020018281038252602581526020018061517f6025913960400191505060405180910390fd5b61158482612d5c565b611591828585600061343f565b61159b3385613560565b6115a582826131e2565b50505050565b30316115ee576040805162461bcd60e51b815260206004820152600d60248201526c4845583a204e6f2076616c756560981b604482015290519081900360640190fd5b60405173dec9f2793e3c17cd26eefb21c4762fa5128e039990303180156108fc02916000818181858888f1935050505015801561162f573d6000803e3d6000fd5b50565b600061163c61342f565b905090565b611649614e43565b611651614e43565b61165b8282612bd7565b6001600160a01b0385166000908152600760205260409020546116bd576040805162461bcd60e51b81526020600482015260156024820152741211560e88115b5c1d1e481cdd185ad9481b1a5cdd605a1b604482015290519081900360640190fd5b6001600160a01b0385166000908152600760205260409020548410611723576040805162461bcd60e51b81526020600482015260176024820152761211560e881cdd185ad9525b99195e081a5b9d985b1a59604a1b604482015290519081900360640190fd5b6001600160a01b038516600090815260076020526040812080548690811061174757fe5b90600052602060002001905061175b614ea4565b611766828683612c89565b806080015181606001510184610140015110156117ca576040805162461bcd60e51b815260206004820152601b60248201527f4845583a205374616b65206e6f742066756c6c79207365727665640000000000604482015290519081900360640190fd5b60a081015115611821576040805162461bcd60e51b815260206004820152601b60248201527f4845583a205374616b6520616c726561647920756e6c6f636b65640000000000604482015290519081900360640190fd5b61182a84612d5c565b6118348482612d6d565b600080600061184887858660800151612d8c565b935093509350506118658a8986602001518760400151878761365c565b8015611875576118758782612eed565b61187f85856136f9565b61188987876131e2565b50505050505050505050565b606081831080156118ac575060045461ffff168211155b6118f2576040805162461bcd60e51b81526020600482015260126024820152711211560e881c985b99d9481a5b9d985b1a5960721b604482015290519081900360640190fd5b82820360405190808252806020026020018201604052801561191e578160200160208202803883390190505b509050826000805b5060008281526006602052604090205483516001830192600160901b830460901b66ffffffffffffff60901b16600160481b840460481b71ffffffffffffffffff00000000000000000016176001600160481b0390931692909217918291869190811061198f57fe5b6020026020010181815250508483600101935083106119265750505092915050565b6001600160a01b031660009081526020819052604090205490565b60056020526000908152604090205460ff1681565b60086020526000908152604090205481565b6000806119fe61342f565b90506001811015611a405760405162461bcd60e51b8152600401808060200182810382526024815260200180614fd66024913960400191505060405180910390fd5b61015f8110611a96576040805162461bcd60e51b815260206004820152601a60248201527f4845583a20436c61696d2070686173652068617320656e646564000000000000604482015290519081900360640190fd5b6001600160601b0319861660009081526005602052604090205460ff1615611ac2576000915050610f13565b611b0086868686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506137d192505050565b9695505050505050565b611b12614e43565b611b1a614e43565b611b248282612bd7565b600182610140015111611b6f576040805162461bcd60e51b815260206004820152600e60248201526d4845583a20546f6f206561726c7960901b604482015290519081900360640190fd5b8215611bca57816101400151831115611bb95760405162461bcd60e51b8152600401808060200182810382526026815260200180614f6c6026913960400191505060405180910390fd5b611bc5828460006138e1565b611bdb565b611bdb8283610140015160006138e1565b611be582826131e2565b505050565b6006602052600090815260409020546001600160481b0380821691600160481b810490911690600160901b900466ffffffffffffff1683565b600065173cdf6f6e318d1115611c78576040805162461bcd60e51b81526020600482015260156024820152744845583a2043484b3a207261775361746f7368697360581b604482015290519081900360640190fd5b61015e831015611cb95760405162461bcd60e51b81526004018080602001828103825260258152602001806151116025913960400191505060405180910390fd5b60006001600160a01b038b163314611d2b5750604080517f4e831acb4223b66de3b3d2e54a2edeefb0de3d7916e2886a4b134d9764d41bec602080830191909152818301869052606085811b6001600160601b0319169083015282518083036054018152607490920190925280519101205b611d3b8b828c8c8c8c8c8c612443565b611d8c576040805162461bcd60e51b815260206004820152601760248201527f4845583a205369676e6174757265206d69736d61746368000000000000000000604482015290519081900360640190fd5b506000611d9a8a8a8a610f1b565b6001600160601b0319811660009081526005602052604090205490915060ff1615611df65760405162461bcd60e51b815260040180806020018281038252602881526020018061507a6028913960400191505060405180910390fd5b611e34818f8f8f808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506137d192505050565b611e6f5760405162461bcd60e51b81526004018080602001828103825260238152602001806150576023913960400191505060405180910390fd5b6001600160601b031981166000908152600560205260409020805460ff19166001179055611ea18e8c838b8888613993565b9e9d5050505050505050505050505050565b6000610dbe611ec06127a2565b84610e4b856040518060600160405280602581526020016151a46025913960016000611eea6127a2565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff6129ee16565b6000610dbe611f2e6127a2565b8484612892565b602881901c60008181526009602090815260408083206001600160a01b0387168452825280832064ffffffffff861680855260019091019092528220805492938493909291906001600160601b0316611fca576040805162461bcd60e51b81526020600482015260126024820152711211560e8814185c985b481a5b9d985b1a5960721b604482015290519081900360640190fd5b546001600160601b03811697600160601b9091046001600160a01b03169650945050505050565b6003546004546001600160481b0380831692600160481b810482169264ffffffffff600160901b8304811693600160b81b90930483169261ffff83169262010000810490911691600160581b820416906001600160801b03600160801b9091041688565b61205d61342f565b82106120b0576040805162461bcd60e51b815260206004820152601a60248201527f4845583a20526f756e64206973206e6f7420636f6d706c657465000000000000604482015290519081900360640190fd5b600082815260096020908152604080832033845290915281208054909164ffffffffff909116908315612142578254600160281b900464ffffffffff16829003841115612139576040805162461bcd60e51b81526020600482015260126024820152711211560e8818dbdd5b9d081a5b9d985b1a5960721b604482015290519081900360640190fd5b5080830161219c565b508154600160281b900464ffffffffff1680821061219c576040805162461bcd60e51b81526020600482015260126024820152711211560e8818dbdd5b9d081a5b9d985b1a5960721b604482015290519081900360640190fd5b60006121a7866139d6565b600087815260086020526040812054919250805b600086815260018801602052604081208054908290556001600160601b03811691600160601b9091046001600160a01b03169085878402816121f957fe5b0490506001600160a01b03821661221b576122168c8a8385613a4e565b61226a565b600a81049081019060058204336001600160a01b038516141561224d57918201916122488e8c8587613a4e565b612263565b6122598e8c8587613a4e565b6122638482612f28565b0193909301925b600190980197939093019250508486106121bb57865464ffffffffff191664ffffffffff871617875580156122b7576122b7739a6a414d6f3497c05e3b1de90520765fa1e07c0382612f28565b81156122c7576122c73383612f28565b505050505050505050565b60006122dc61342f565b905061015f8110612334576040805162461bcd60e51b815260206004820152601760248201527f4845583a204c6f6262696573206861766520656e646564000000000000000000604482015290519081900360640190fd5b348061237e576040805162461bcd60e51b81526020600482015260146024820152731211560e88105b5bdd5b9d081c995c5d5a5c995960621b604482015290519081900360640190fd5b600082815260096020908152604080832033845282528083208054600164ffffffffff600160281b80840482168381019092160269ffffffffff000000000019909316929092178355835180850185526001600160601b0380891682526001600160a01b038b8116838901908152858a529386018852868920925183549451909116600160601b029082166001600160601b031990941693909317169190911790558685526008909352922080548401905561243c84828588613abc565b5050505050565b6000601b8460ff161015801561245d5750601e8460ff1611155b61249f576040805162461bcd60e51b815260206004820152600e60248201526d1211560e881d881a5b9d985b1a5960921b604482015290519081900360640190fd5b60006124ab88886110d9565b905060006124c26124bd8c8c8a613b2a565b613e66565b9050816001600160a01b031660018288888860405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561252b573d6000803e3d6000fd5b505050602060405103516001600160a01b0316149250505098975050505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60006125ba85858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506137d192505050565b95945050505050565b6125cb614f08565b600454600090819081906125ee90600160801b90046001600160801b0316613f97565b604080516101a0810182526003546001600160481b038082168352600160481b82048116602084015264ffffffffff600160901b8304811694840194909452600160b81b9091048116606083015260045461ffff8116608084015262010000810490911660a0830152600160581b900490911660c082015260e08101829052610100810183905261012081018490524261014082015292955090935091506101608101612699610dc7565b8152602001600860006126aa61342f565b815260200190815260200160002054815250935050505090565b606081831080156126d7575061015f8211155b80156126ea57506126e661342f565b8211155b612730576040805162461bcd60e51b81526020600482015260126024820152714845583a20696e76616c69642072616e676560701b604482015290519081900360640190fd5b82820360405190808252806020026020018201604052801561275c578160200160208202803883390190505b5090508260005b60008281526008602052604090205483516001938401938301928591811061278757fe5b60200260200101818152505083821061276357505092915050565b3390565b6001600160a01b0383166127eb5760405162461bcd60e51b815260040180806020018281038252602481526020018061515b6024913960400191505060405180910390fd5b6001600160a01b0382166128305760405162461bcd60e51b8152600401808060200182810382526022815260200180614fb46022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166128d75760405162461bcd60e51b81526004018080602001828103825260258152602001806151366025913960400191505060405180910390fd5b6001600160a01b03821661291c5760405162461bcd60e51b8152600401808060200182810382526023815260200180614f496023913960400191505060405180910390fd5b61295f81604051806060016040528060268152602001615031602691396001600160a01b038616600090815260208190526040902054919063ffffffff6129ee16565b6001600160a01b038085166000908152602081905260408082209390935590841681522054612994908263ffffffff6133d516565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115612a7d5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612a42578181015183820152602001612a2a565b50505050905090810190601f168015612a6f5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000610e54827f4e831acb4223b66de3b3d2e54a2edeefb0de3d7916e2886a4b134d9764d41bec85613fb7565b600060036002836040518082805190602001908083835b60208310612ae85780518252601f199092019160209182019101612ac9565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015612b27573d6000803e3d6000fd5b5050506040513d6020811015612b3c57600080fd5b50516040805160208181019390935281518082038401815290820191829052805190928291908401908083835b60208310612b885780518252601f199092019160209182019101612b69565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015612bc7573d6000803e3d6000fd5b50506040515160601b9392505050565b6003546001600160481b038082168452600160481b82048116602085015264ffffffffff600160901b830481166040860152600160b81b9092048116606085015260045461ffff8116608086015262010000810490911660a0850152600160581b810490911660c0840152612c5c906001600160801b03600160801b90910416613f97565b60e0850152610100840152610120830152612c7561342f565b610140830152612c858282614061565b5050565b825464ffffffffff838116911614612ce8576040805162461bcd60e51b815260206004820152601e60248201527f4845583a207374616b654964506172616d206e6f7420696e207374616b650000604482015290519081900360640190fd5b915464ffffffffff811683526001600160481b03600160281b820481166020850152600160701b820416604084015261ffff600160b81b820481166060850152600160c81b820481166080850152600160d81b82041660a084015260ff600160e81b90910416151560c09092019190915250565b61162f8182610140015160016138e1565b604081015160a080840180519290920390915261014090920151910152565b6000806000808560800151851015612dca57612db78787606001518860800151888a604001516140c9565b6020880151820195509093509150612e08565b60408601516060870151612de2918991888101614172565b9250828660200151019350612e05866060015187608001518860a0015187614240565b91505b8115612e275783821115612e1f5750600092612e27565b509182900391805b93509350935093565b8664ffffffffff16336001600160a01b03167f72d9c5a7ab13846e08d9c838f9e866a1bb4a66a2fd3ba3c9e7da3cf9e394dfd760b8876001600160481b0316901b6070896001600160481b0316901b60288b6001600160481b0316901b4264ffffffffff1617171784612ea4576000612eaa565b600160581b5b6001600160601b031660488761ffff16901b886001600160481b03161717604051808381526020018281526020019250505060405180910390a350505050505050565b600281048015612f1557612f15739a6a414d6f3497c05e3b1de90520765fa1e07c0382612f28565b6060909201805192909103919091019052565b6001600160a01b038216612f83576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b600254612f96908263ffffffff6133d516565b6002556001600160a01b038216600090815260208190526040902054612fc2908263ffffffff6133d516565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b8160200151811115611be557600061303482846080015161426c565b905060008360400151620186a0838501028161304c57fe5b04905064ffffffffff811115613064575064ffffffffff5b846040015181111561243c5760408501819052835161243c9082906142de565b8154600019018181146131b15782818154811061309d57fe5b906000526020600020018383815481106130b357fe5b6000918252602090912082549101805464ffffffffff90921664ffffffffff199092169190911780825582546dffffffffffffffffff000000000019909116600160281b918290046001600160481b0390811690920217808355835468ffffffffffffffffff60701b19909116600160701b918290049092160217808255825461ffff60b81b19909116600160b81b9182900461ffff90811690920217808355835461ffff60c81b19909116600160c81b91829004831690910217808355835461ffff60d81b19909116600160d81b918290049092160217808255915460ff60e81b19909216600160e81b9283900460ff1615159092029190911790555b828054806131bb57fe5b600082815260209020810160001990810180546001600160f01b0319169055019055505050565b805182511415806131fb57508060200151826020015114155b8061320e57508060400151826040015114155b8061322157508060600151826060015114155b156132af5781516003805460208501516040860151606087015168ffffffffffffffffff199093166001600160481b039586161768ffffffffffffffffff60481b1916600160481b928616929092029190911764ffffffffff60901b1916600160901b64ffffffffff90921691909102176001600160b81b0316600160b81b93909116929092029190911790555b806080015182608001511415806132ce57508060a001518260a0015114155b806132ef57508060c0015164ffffffffff168260c0015164ffffffffff1614155b8061330257508060e001518260e0015114155b80613317575080610100015182610100015114155b8061332c575080610120015182610120015114155b15612c855760808201516004805460a085015160c086015164ffffffffff16600160581b0264ffffffffff60581b196001600160481b0390921662010000026affffffffffffffffff00001961ffff90961661ffff199094169390931794909416919091171691909117905561012082015161010083015160e08401516133b4929190614335565b600480546001600160801b03928316600160801b0292169190911790555050565b600082820183811015610e54576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6201518042635de5a57f19010490565b6115b38211156134805760405162461bcd60e51b81526004018080602001828103825260268152602001806150ca6026913960400191505060405180910390fd5b600061348c848461426c565b905060008560400151620186a083870102816134a457fe5b049050806134e35760405162461bcd60e51b8152600401808060200182810382526037815260200180614ffa6037913960400191505060405180910390fd5b600060018761014001511061350057866101400151600101613503565b60025b60c08801805160010164ffffffffff16908190523360009081526007602052604090209192509061353990828986868b8b614346565b6135468188858989614474565b505060208601805190910190525050825190910190915250565b6001600160a01b0382166135a55760405162461bcd60e51b81526004018080602001828103825260218152602001806150f06021913960400191505060405180910390fd5b6135e881604051806060016040528060228152602001614f92602291396001600160a01b038516600090815260208190526040902054919063ffffffff6129ee16565b6001600160a01b038316600090815260208190526040902055600254613614908263ffffffff61450616565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b604080514264ffffffffff9081166dffffffffffffffffff0000000000602889901b161768ffffffffffffffffff60701b607088901b16176001600160b81b031960b887901b161782526001600160481b038416602083015282513393918916926001600160a01b038b16927fd824970a2cf19cc2b630c87ce5b00f67301cac3ac60513d027c7a39129f93b4692918290030190a4505050505050565b80518254602083015160408401516060850151608086015160a087015160c09097015164ffffffffff1990951664ffffffffff909616959095176dffffffffffffffffff00000000001916600160281b6001600160481b03948516021768ffffffffffffffffff60701b1916600160701b93909216929092021761ffff60b81b1916600160b81b61ffff928316021761ffff60c81b1916600160c81b938216939093029290921761ffff60d81b1916600160d81b92909316919091029190911760ff60e81b1916600160e81b91151591909102179055565b80516000906bffffffffffffe0000000000090839083906137ee57fe5b602002602001015160001c16600014613843576040805162461bcd60e51b81526020600482015260126024820152711211560e881c1c9bdbd9881a5b9d985b1a5960721b604482015290519081900360640190fd5b60015b82518110156138c95782516bffffffffffffe000000000009084908390811061386b57fe5b602002602001015160001c16600014156138c1576040805162461bcd60e51b81526020600482015260126024820152711211560e881c1c9bdbd9881a5b9d985b1a5960721b604482015290519081900360640190fd5b600101613846565b506001600160601b0319841683176125ba8184612a85565b818360800151106138f157611be5565b6138f9614f27565b8351613903610dc7565b0181526080840151613916858383614548565b6020850151156139365760208501805160a0870180519091019052600090525b600101838110156139515761394c858383614548565b613936565b613960856080015182856145d3565b6080850181905260208201511561243c5761243c739a6a414d6f3497c05e3b1de90520765fa1e07c038360200151612f28565b600061399d614e43565b6139a5614e43565b6139af8282612bd7565b6139be828a8a8a8a8a8a61464a565b92506139ca82826131e2565b50509695505050505050565b600060018210613a3f576139e8614e43565b6139f0614e43565b6139fa8282612bd7565b613a0382612d5c565b600084815260066020526040902054600160901b900466ffffffffffffff1661015e6127108202049350613a3783836131e2565b505050611124565b5067016345785d8a0000919050565b806001600160a01b031683602886901b17336001600160a01b03167fa6b19fa7f41317a186e1d58e9d81f86a52f1102b6bce10b4eca83f37aaa584686028866001600160481b0316901b4264ffffffffff16176040518082815260200191505060405180910390a450505050565b806001600160a01b031683602886901b17336001600160a01b03167f25ecdb937d5c5cc78f0d18dfb1ac82c44086b5dc608380ba357d06c9868f0b1d6028866001600160601b0316901b4264ffffffffff16176040518082815260200191505060405180910390a450505050565b60608060018316613b62576040518060400160405280600f81526020016e086d8c2d2dabe908ab0bee8debe60f608b1b815250613b92565b60405180604001604052806016815260200175086d8c2d2dabe84d2e8c6ded2dc908ab0bee8debe60f60531b8152505b905060108316156060613ba587836147b5565b905085613cca576018772134ba31b7b4b71029b4b3b732b21026b2b9b9b0b3b29d0560411b60146002028551018584604051602001808660ff1660ff1660f81b81526001018567ffffffffffffffff191667ffffffffffffffff191681526018018460ff1660ff1660f81b815260010183805190602001908083835b60208310613c405780518252601f199092019160209182019101613c21565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310613c885780518252601f199092019160209182019101613c69565b6001836020036101000a038019825116818451168082178552505050505050905001955050505050506040516020818303038152906040529350505050610e54565b604080516018808252818301909252606091602082018180388339019050509050613cf78188600c614858565b8351604051600360fb1b6020808301918252772134ba31b7b4b71029b4b3b732b21026b2b9b9b0b3b29d0560411b60218401819052604190940160f881901b6001600160f81b031916603985015288516018959491938a9389938993603a909101918601908083835b60208310613d7f5780518252601f199092019160209182019101613d60565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b60208310613dc75780518252601f199092019160209182019101613da8565b6001836020036101000a03801982511681845116808217855250505050505090500180605f60f81b81525060010182805190602001908083835b60208310613e205780518252601f199092019160209182019101613e01565b6001836020036101000a03801982511681845116808217855250505050505090500196505050505050506040516020818303038152906040529450505050509392505050565b6000600280836040518082805190602001908083835b60208310613e9b5780518252601f199092019160209182019101613e7c565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015613eda573d6000803e3d6000fd5b5050506040513d6020811015613eef57600080fd5b50516040805160208181019390935281518082038401815290820191829052805190928291908401908083835b60208310613f3b5780518252601f199092019160209182019101613f1c565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015613f7a573d6000803e3d6000fd5b5050506040513d6020811015613f8f57600080fd5b505192915050565b606681901c6303ffffff16916607ffffffffffff603383901c8116921690565b600081815b8551811015614056576000868281518110613fd357fe5b602002602001015190508083101561401b578281604051602001808381526020018281526020019250505060405160208183030381529060405280519060200120925061404d565b808360405160200180838152602001828152602001925050506040516020818303038152906040528051906020012092505b50600101613fbc565b509092149392505050565b815181526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0808301519082015260c08083015164ffffffffff169082015260e08083015190820152610100808301519082015261012091820151910152565b60008083860160026001870104605a8110156140e35750605a5b856141035760006140f58a878b614920565b919091029250614168915050565b858110156141385787810161411a8a878b84614172565b9350600061412a8b888487614172565b850195506141689350505050565b61414489868a85614172565b93508581141561415657839250614165565b858185028161416157fe5b0492505b50505b9550959350505050565b6000825b828110156141b7576000818152600660205260409020546001600160481b03600160481b8204811691168602816141a957fe5b049190910190600101614176565b5061016083118015906141cb575061016082115b15610f1357610160600090815260066020527f5bc747bd71b549e015c2e31a0d21c276f82136338c6c7203a3f9911f7240314a54600160481b90046001600160481b0316856127106305f5e1008004028860e0015102028161422957fe5b04905061423686826149b3565b0101949350505050565b6000848401600e01808411614259576000915050610f13565b6102bc8185038402049695505050505050565b600080600183111561429257610e3883111561428a57610e3861428f565b600183035b90505b600066354a6ba7a180008511156142b05766354a6ba7a180006142b2565b845b670214e8348c4f0000830261071c82020193509050680ecca2d59581a400008584020495945050505050565b8064ffffffffff167f9861fa0ed101659f7a59b4583fcc798dfa4f3b419bea371c8ee2ad0ffe13a31e60288464ffffffffff16901b4264ffffffffff16176040518082815260200191505060405180910390a25050565b60669290921b60339190911b171790565b6040805160e08101825264ffffffffff97881681526001600160481b03968716602080830191825296881692820192835261ffff9586166060830190815294861660808301908152600060a0840181815295151560c085019081528c54600181018e559c8252989020925192909a0180549151935195519a519451975164ffffffffff1990921692909916919091176dffffffffffffffffff00000000001916600160281b928816929092029190911768ffffffffffffffffff60701b1916600160701b93909616929092029490941761ffff60b81b1916600160b81b968316969096029590951761ffff60c81b1916600160c81b938216939093029290921761ffff60d81b1916600160d81b91909216021760ff60e81b1916600160e81b92151592909202919091179055565b64ffffffffff8516337f14872dc760f33532684e68e1b6d5fd3f71ba7b07dee76bdb2b084f28b74233ef836144aa5760006144b0565b600160c81b5b6001600160d01b031660b88661ffff16901b6070886001600160481b0316901b60288a6001600160481b0316901b4264ffffffffff16171717176040518082815260200191505060405180910390a35050505050565b6000610e5483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506129ee565b6145538383836149f3565b60409182015160009182526006602052919020805460a084015160e09094015168ffffffffffffffffff199091166001600160481b039384161768ffffffffffffffffff60481b1916600160481b93909416929092029290921766ffffffffffffff60901b1916600160901b66ffffffffffffff90921691909102179055565b337fb8d6eb541ded1720cc657b719f57abcb1fe4711cb7ead82751b135f5d94bc94482614601576000614607565b600160481b5b69ffffffffffffffffffff1660388561ffff16901b60288761ffff16901b4264ffffffffff161717176040518082815260200191505060405180910390a2505050565b6000600188610140015110156146915760405162461bcd60e51b8152600401808060200182810382526024815260200180614fd66024913960400191505060405180910390fd5b61014088015161015f116146ec576040805162461bcd60e51b815260206004820152601a60248201527f4845583a20436c61696d2070686173652068617320656e646564000000000000604482015290519081900360640190fd5b6146f588612d5c565b6301ab362e88610120015110614752576040805162461bcd60e51b815260206004820152601e60248201527f4845583a2043484b3a205f636c61696d656442746341646472436f756e740000604482015290519081900360640190fd5b60008060006147618b8b614a8d565b6101208e0180516001019052919450925090506147848989898d8787878c614b47565b93506064605a85020461479a8c8289600161343f565b6147a68a828703612f28565b50505050979650505050505050565b60408051602880825260608281019093526020820181803883390190505090506147ef816001600160601b0319606086901b166014614858565b811561485257805160208201206000805b601481101561484e57600083826020811061481757fe5b600185019491901a9150614831908690600484901c614bf4565b614845858480600101955083600f16614bf4565b50600101614800565b5050505b92915050565b6000805b8281101561243c57600084826020811061487257fe5b1a90506f181899199a1a9b1b9c1cb0b131b232b360811b600482901c60ff166010811061489b57fe5b1a60f81b8684806001019550815181106148b157fe5b60200101906001600160f81b031916908160001a9053506f181899199a1a9b1b9c1cb0b131b232b360811b600f8216601081106148ea57fe5b1a60f81b86848060010195508151811061490057fe5b60200101906001600160f81b031916908160001a9053505060010161485c565b600061492a614e43565b6149348582614061565b61493c614f27565b8551614946610dc7565b0181526149548282866149f3565b60a082018051860190819052604082015186028161496e57fe5b0492506101608414156149aa5760a082015160e0830151600091908702612710028161499657fe5b0490506149a383826149b3565b0192909201915b50509392505050565b6000806301ab362e8461012001518402816149ca57fe5b049050600066033bb85fc52d998561010001518502816149e657fe5b0491909101949350505050565b81516305fcbae3906127100204604083015261015f811015614a695760e083015160009061015e90612710020490506000614a3485838660400151016149b3565b60208501805191840191820190528451810185526040850151909150614a5b9086906149b3565b604085018051909101905250505b606083015115611be557606083018051604084018051909101905260009052505050565b6000806000614a9b84614c60565b925066033bb85fc52d9983866101000151011115614b00576040805162461bcd60e51b815260206004820152601f60248201527f4845583a2043484b3a205f636c61696d65645361746f73686973546f74616c00604482015290519081900360640190fd5b610100850180518401905261014085015161015f03614b1f8482614cac565b60e0870180518290039052935061271084029250614b3d8382614cbd565b9150509250925092565b828201826001600160a01b038316614b6d57614b688a8a8a8a8a8789614cce565b614bc9565b600a8204918201916005830480820192909201916001600160a01b03858116908d161415614bad5792830192614ba88c8c8c8c8c898b614cce565b614bc6565b614bbc8c8c8c8c8c898b614cce565b614bc68582612f28565b50505b614be7739a6a414d6f3497c05e3b1de90520765fa1e07c0382612f28565b5098975050505050505050565b6000838381518110614c0257fe5b01602001516001600160f81b0319169050606160f81b8110801590614c2b575060088260ff1610155b156115a55780602060f81b18848481518110614c4357fe5b60200101906001600160f81b031916908160001a90535050505050565b600064174876e800821015614c76575080611124565b64e8d4a510008210614c8c575060048104611124565b65034630b8a000826501ba60d3380003830281614ca557fe5b0492915050565b600061015e8383025b049392505050565b60006106d160001983018402614cb5565b6040805164ffffffffff42166bffffffffffffff0000000000602888901b161766ffffffffffffff60601b606087901b161760ff60981b609889901b161768ffffffffffffffffff60a01b60a086901b1617815233602082015281516001600160a01b0380851693908b16926001600160601b03198b16927f41e3c7dc6eebc97a48a437ff2afdc629613f12c48ba37a2c94563f80acba9725929181900390910190a46001600160a01b038716331415614d8757614e3a565b336001600160a01b03167f3a84b2d9dac24683628d63034c6949797f15fab735e16232518ee4e753fd49b760c88666ffffffffffffff16901b60288960601c6001600160a01b0316901b4264ffffffffff16171760d88860ff16901b60388b6001600160a01b0316901b8766ffffffffffffff1617176048856001600160a01b0316901b866001600160481b03161760405180848152602001838152602001828152602001935050505060405180910390a25b50505050505050565b604051806101600160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600064ffffffffff168152602001600081526020016000815260200160008152602001600081525090565b6040518060e00160405280600064ffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581525090565b60405180604001604052806002906020820280388339509192915050565b604051806101a00160405280600d906020820280388339509192915050565b6040518060600160405280600081526020016000815260200160008152509056fe45524332303a207472616e7366657220746f20746865207a65726f20616464726573734845583a206265666f72654461792063616e6e6f7420626520696e207468652066757475726545524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f20616464726573734845583a20436c61696d20706861736520686173206e6f742079657420737461727465644845583a206e65775374616b6564486561727473206d757374206265206174206c65617374206d696e696d756d2073686172655261746545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63654845583a204254432061646472657373206f722062616c616e636520756e6b6e6f776e4845583a2042544320616464726573732062616c616e636520616c726561647920636c61696d656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654845583a206e65775374616b65644461797320686967686572207468616e206d6178696d756d45524332303a206275726e2066726f6d20746865207a65726f20616464726573734845583a206175746f5374616b6544617973206c6f776572207468616e206d696e696d756d45524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573734845583a206e65775374616b656444617973206c6f776572207468616e206d696e696d756d45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a72315820e1386410ff82a380822a5c5fb950ec31ad42ac34f1e670c4d9b8c7329878472b64736f6c634300050d0032

Deployed Bytecode

0x6080604052600436106102305760003560e01c80636a210a0e1161012e578063a9059cbb116100ab578063d5a373ff1161006f578063d5a373ff14610bff578063dd62ed3e14610c64578063ec9a191714610c9f578063f04b5fa014610d30578063f57a1b3c14610d5b57610230565b8063a9059cbb14610a9b578063bd926ed314610ad4578063c312452514610b2e578063cbb151d314610ba9578063ce7d1f7714610bd957610230565b80638f1c65c0116100f25780638f1c65c01461091357806390de68711461093d57806395d89b411461023257806396f62b9d1461099a578063a457c2d714610a6257610230565b80636a210a0e1461077157806370a08231146107f15780637c4266201461082457806387a0f31c146108585780638e21aa011461088257610230565b806333060d90116101bc57806344f0de751161018057806344f0de751461066357806352a438b8146106d15780635ac1f357146107015780635c9302c91461071657806365cf71b21461072b57610230565b806333060d901461054e578063343009a21461058157806339509351146105b85780633a70a5ca146105f157806344203faf1461060657610230565b80632607443b116102035780632607443b1461037357806327aa6018146103ff578063283a5baf1461048157806330c1a785146104d7578063313ce5671461052357610230565b806306fdde0314610232578063095ea7b3146102bc57806318160ddd1461030957806323b872dd14610330575b005b34801561023e57600080fd5b50610247610d8b565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610281578181015183820152602001610269565b50505050905090810190601f1680156102ae5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156102c857600080fd5b506102f5600480360360408110156102df57600080fd5b506001600160a01b038135169060200135610daa565b604080519115158252519081900360200190f35b34801561031557600080fd5b5061031e610dc7565b60408051918252519081900360200190f35b34801561033c57600080fd5b506102f56004803603606081101561035357600080fd5b506001600160a01b03813581169160208101359091169060400135610dcd565b34801561037f57600080fd5b506103ac6004803603604081101561039657600080fd5b506001600160a01b038135169060200135610e5b565b6040805164ffffffffff90981688526001600160481b039687166020890152949095168685015261ffff928316606087015290821660808601521660a084015290151560c0830152519081900360e00190f35b34801561040b57600080fd5b506102f56004803603604081101561042257600080fd5b81359190810190604081016020820135600160201b81111561044357600080fd5b82018360208201111561045557600080fd5b803590602001918460208302840111600160201b8311171561047657600080fd5b509092509050610ed4565b34801561048d57600080fd5b506104ba600480360360608110156104a457600080fd5b508035906020810135906040013560ff16610f1b565b604080516001600160601b03199092168252519081900360200190f35b3480156104e357600080fd5b50610507600480360360408110156104fa57600080fd5b50803590602001356110d9565b604080516001600160a01b039092168252519081900360200190f35b34801561052f57600080fd5b50610538611105565b6040805160ff9092168252519081900360200190f35b34801561055a57600080fd5b5061031e6004803603602081101561057157600080fd5b50356001600160a01b031661110a565b34801561058d57600080fd5b50610230600480360360408110156105a457600080fd5b508035906020013564ffffffffff16611129565b3480156105c457600080fd5b506102f5600480360360408110156105db57600080fd5b506001600160a01b0381351690602001356113e7565b3480156105fd57600080fd5b5061031e61143b565b34801561061257600080fd5b5061063f6004803603604081101561062957600080fd5b50803590602001356001600160a01b0316611458565b6040805164ffffffffff938416815291909216602082015281519081900390910190f35b34801561066f57600080fd5b506106966004803603602081101561068657600080fd5b50356001600160a01b0316611487565b6040518082600260200280838360005b838110156106be5781810151838201526020016106a6565b5050505090500191505060405180910390f35b3480156106dd57600080fd5b50610230600480360360408110156106f457600080fd5b5080359060200135611521565b34801561070d57600080fd5b506102306115ab565b34801561072257600080fd5b5061031e611632565b34801561073757600080fd5b506102306004803603606081101561074e57600080fd5b5080356001600160a01b0316906020810135906040013564ffffffffff16611641565b34801561077d57600080fd5b506107a16004803603604081101561079457600080fd5b5080359060200135611895565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156107dd5781810151838201526020016107c5565b505050509050019250505060405180910390f35b3480156107fd57600080fd5b5061031e6004803603602081101561081457600080fd5b50356001600160a01b03166119b1565b34801561083057600080fd5b506102f56004803603602081101561084757600080fd5b50356001600160601b0319166119cc565b34801561086457600080fd5b5061031e6004803603602081101561087b57600080fd5b50356119e1565b34801561088e57600080fd5b506102f5600480360360608110156108a557600080fd5b6001600160601b031982351691602081013591810190606081016040820135600160201b8111156108d557600080fd5b8201836020820111156108e757600080fd5b803590602001918460208302840111600160201b8311171561090857600080fd5b5090925090506119f3565b34801561091f57600080fd5b506102306004803603602081101561093657600080fd5b5035611b0a565b34801561094957600080fd5b506109676004803603602081101561096057600080fd5b5035611bea565b604080516001600160481b03948516815292909316602083015266ffffffffffffff168183015290519081900360600190f35b3480156109a657600080fd5b5061031e60048036036101608110156109be57600080fd5b81359190810190604081016020820135600160201b8111156109df57600080fd5b8201836020820111156109f157600080fd5b803590602001918460208302840111600160201b83111715610a1257600080fd5b91935091506001600160a01b03813581169160208101359160408201359160ff606082013581169260808301359091169160a08101359160c08201359160e0810135916101009091013516611c23565b348015610a6e57600080fd5b506102f560048036036040811015610a8557600080fd5b506001600160a01b038135169060200135611eb3565b348015610aa757600080fd5b506102f560048036036040811015610abe57600080fd5b506001600160a01b038135169060200135611f21565b348015610ae057600080fd5b50610b0d60048036036040811015610af757600080fd5b506001600160a01b038135169060200135611f35565b604080519283526001600160a01b0390911660208301528051918290030190f35b348015610b3a57600080fd5b50610b43611ff1565b604080516001600160481b03998a168152978916602089015264ffffffffff96871688820152948816606088015261ffff9093166080870152951660a08501529390911660c08301526001600160801b0390921660e08201529051908190036101000190f35b348015610bb557600080fd5b5061023060048036036040811015610bcc57600080fd5b5080359060200135612055565b61023060048036036020811015610bef57600080fd5b50356001600160a01b03166122d2565b348015610c0b57600080fd5b506102f56004803603610100811015610c2357600080fd5b506001600160a01b038135169060208101359060408101359060608101359060ff608082013581169160a08101359091169060c08101359060e00135612443565b348015610c7057600080fd5b5061031e60048036036040811015610c8757600080fd5b506001600160a01b038135811691602001351661254f565b348015610cab57600080fd5b506102f560048036036060811015610cc257600080fd5b6001600160601b031982351691602081013591810190606081016040820135600160201b811115610cf257600080fd5b820183602082011115610d0457600080fd5b803590602001918460208302840111600160201b83111715610d2557600080fd5b50909250905061257a565b348015610d3c57600080fd5b50610d456125c3565b6040518151815280826101a080838360206106a6565b348015610d6757600080fd5b506107a160048036036040811015610d7e57600080fd5b50803590602001356126c4565b604051806040016040528060038152602001620908ab60eb1b81525081565b6000610dbe610db76127a2565b84846127a6565b50600192915050565b60025490565b6000610dda848484612892565b610e5084610de66127a2565b610e4b856040518060600160405280602881526020016150a2602891396001600160a01b038a16600090815260016020526040812090610e246127a2565b6001600160a01b03168152602081019190915260400160002054919063ffffffff6129ee16565b6127a6565b5060015b9392505050565b60076020528160005260406000208181548110610e7457fe5b60009182526020909120015464ffffffffff811692506001600160481b03600160281b820481169250600160701b8204169061ffff600160b81b8204811691600160c81b8104821691600160d81b8204169060ff600160e81b9091041687565b6000610f1384848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612a8592505050565b949350505050565b600080606060028416158015906004861615159060088716151590610fe657818015610f445750805b15610f90576040805162461bcd60e51b81526020600482015260176024820152761211560e8818db185a5b519b1859dcc81a5b9d985b1a59604a1b604482015290519081900360640190fd5b600160f81b60f889901b1615610fa7576003610faa565b60025b604080516001600160f81b031960f884901b16602082015260218082018d90528251808303909101815260419091019091529095509350611073565b81158015610ff2575080155b61103d576040805162461bcd60e51b81526020600482015260176024820152761211560e8818db185a5b519b1859dcc81a5b9d985b1a59604a1b604482015290519081900360640190fd5b60408051600160fa1b6020820152602181018b905260418082018b90528251808303909101815260619091019091526004955093505b600061107e85612ab2565b905082156110cc5760408051600560f21b60208201526001600160601b0319831660228201528151601681830301815260369091019091526110bf90612ab2565b9650505050505050610e54565b9998505050505050505050565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b600881565b6001600160a01b0381166000908152600760205260409020545b919050565b611131614e43565b611139614e43565b6111438282612bd7565b336000908152600760205260409020805461119d576040805162461bcd60e51b81526020600482015260156024820152741211560e88115b5c1d1e481cdd185ad9481b1a5cdd605a1b604482015290519081900360640190fd5b805485106111ec576040805162461bcd60e51b81526020600482015260176024820152761211560e881cdd185ad9525b99195e081a5b9d985b1a59604a1b604482015290519081900360640190fd5b6111f4614ea4565b61121482878154811061120357fe5b906000526020600020018683612c89565b61121d84612d5c565b60a081015160608201516101408601516000921515918391829182918291116112fd57841561125257866080015195506112e3565b61125c8a88612d6d565b86606001518a6101400151039550866080015186111561128257866080015195506112e3565b61015e8610156112e3578660c00151156112e3576040805162461bcd60e51b815260206004820152601c60248201527f4845583a204175746f2d7374616b65207374696c6c206c6f636b656400000000604482015290519081900360640190fd5b6112ee8a8888612d8c565b9296509094509250905061136d565b8660c0015115611354576040805162461bcd60e51b815260206004820152601c60248201527f4845583a204175746f2d7374616b65207374696c6c206c6f636b656400000000604482015290519081900360640190fd5b60408701516020808c0180519290920390915287015193505b6113848b8860200151896040015186868b8b612e30565b8015801590611391575084155b156113a0576113a08a82612eed565b83156113bb576113b03385612f28565b6113bb8a8886613018565b60208701518a51038a526113cf888d613084565b6113d98a8a6131e2565b505050505050505050505050565b6000610dbe6113f46127a2565b84610e4b85600160006114056127a2565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff6133d516565b6003546000906001600160481b0316611452610dc7565b01905090565b600960209081526000928352604080842090915290825290205464ffffffffff80821691600160281b90041682565b61148f614eea565b600061149961342f565b600101905061015f8111156114ad575061015f5b6000198101901561151b5760008181526009602090815260408083206001600160a01b038716845290915290205464ffffffffff808216600160281b90920416111561151657600160ff82161b82600883901c6002811061150a57fe5b60200201805190911790525b6114ad565b50919050565b611529614e43565b611531614e43565b61153b8282612bd7565b600183101561157b5760405162461bcd60e51b815260040180806020018281038252602581526020018061517f6025913960400191505060405180910390fd5b61158482612d5c565b611591828585600061343f565b61159b3385613560565b6115a582826131e2565b50505050565b30316115ee576040805162461bcd60e51b815260206004820152600d60248201526c4845583a204e6f2076616c756560981b604482015290519081900360640190fd5b60405173dec9f2793e3c17cd26eefb21c4762fa5128e039990303180156108fc02916000818181858888f1935050505015801561162f573d6000803e3d6000fd5b50565b600061163c61342f565b905090565b611649614e43565b611651614e43565b61165b8282612bd7565b6001600160a01b0385166000908152600760205260409020546116bd576040805162461bcd60e51b81526020600482015260156024820152741211560e88115b5c1d1e481cdd185ad9481b1a5cdd605a1b604482015290519081900360640190fd5b6001600160a01b0385166000908152600760205260409020548410611723576040805162461bcd60e51b81526020600482015260176024820152761211560e881cdd185ad9525b99195e081a5b9d985b1a59604a1b604482015290519081900360640190fd5b6001600160a01b038516600090815260076020526040812080548690811061174757fe5b90600052602060002001905061175b614ea4565b611766828683612c89565b806080015181606001510184610140015110156117ca576040805162461bcd60e51b815260206004820152601b60248201527f4845583a205374616b65206e6f742066756c6c79207365727665640000000000604482015290519081900360640190fd5b60a081015115611821576040805162461bcd60e51b815260206004820152601b60248201527f4845583a205374616b6520616c726561647920756e6c6f636b65640000000000604482015290519081900360640190fd5b61182a84612d5c565b6118348482612d6d565b600080600061184887858660800151612d8c565b935093509350506118658a8986602001518760400151878761365c565b8015611875576118758782612eed565b61187f85856136f9565b61188987876131e2565b50505050505050505050565b606081831080156118ac575060045461ffff168211155b6118f2576040805162461bcd60e51b81526020600482015260126024820152711211560e881c985b99d9481a5b9d985b1a5960721b604482015290519081900360640190fd5b82820360405190808252806020026020018201604052801561191e578160200160208202803883390190505b509050826000805b5060008281526006602052604090205483516001830192600160901b830460901b66ffffffffffffff60901b16600160481b840460481b71ffffffffffffffffff00000000000000000016176001600160481b0390931692909217918291869190811061198f57fe5b6020026020010181815250508483600101935083106119265750505092915050565b6001600160a01b031660009081526020819052604090205490565b60056020526000908152604090205460ff1681565b60086020526000908152604090205481565b6000806119fe61342f565b90506001811015611a405760405162461bcd60e51b8152600401808060200182810382526024815260200180614fd66024913960400191505060405180910390fd5b61015f8110611a96576040805162461bcd60e51b815260206004820152601a60248201527f4845583a20436c61696d2070686173652068617320656e646564000000000000604482015290519081900360640190fd5b6001600160601b0319861660009081526005602052604090205460ff1615611ac2576000915050610f13565b611b0086868686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506137d192505050565b9695505050505050565b611b12614e43565b611b1a614e43565b611b248282612bd7565b600182610140015111611b6f576040805162461bcd60e51b815260206004820152600e60248201526d4845583a20546f6f206561726c7960901b604482015290519081900360640190fd5b8215611bca57816101400151831115611bb95760405162461bcd60e51b8152600401808060200182810382526026815260200180614f6c6026913960400191505060405180910390fd5b611bc5828460006138e1565b611bdb565b611bdb8283610140015160006138e1565b611be582826131e2565b505050565b6006602052600090815260409020546001600160481b0380821691600160481b810490911690600160901b900466ffffffffffffff1683565b600065173cdf6f6e318d1115611c78576040805162461bcd60e51b81526020600482015260156024820152744845583a2043484b3a207261775361746f7368697360581b604482015290519081900360640190fd5b61015e831015611cb95760405162461bcd60e51b81526004018080602001828103825260258152602001806151116025913960400191505060405180910390fd5b60006001600160a01b038b163314611d2b5750604080517f4e831acb4223b66de3b3d2e54a2edeefb0de3d7916e2886a4b134d9764d41bec602080830191909152818301869052606085811b6001600160601b0319169083015282518083036054018152607490920190925280519101205b611d3b8b828c8c8c8c8c8c612443565b611d8c576040805162461bcd60e51b815260206004820152601760248201527f4845583a205369676e6174757265206d69736d61746368000000000000000000604482015290519081900360640190fd5b506000611d9a8a8a8a610f1b565b6001600160601b0319811660009081526005602052604090205490915060ff1615611df65760405162461bcd60e51b815260040180806020018281038252602881526020018061507a6028913960400191505060405180910390fd5b611e34818f8f8f808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506137d192505050565b611e6f5760405162461bcd60e51b81526004018080602001828103825260238152602001806150576023913960400191505060405180910390fd5b6001600160601b031981166000908152600560205260409020805460ff19166001179055611ea18e8c838b8888613993565b9e9d5050505050505050505050505050565b6000610dbe611ec06127a2565b84610e4b856040518060600160405280602581526020016151a46025913960016000611eea6127a2565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff6129ee16565b6000610dbe611f2e6127a2565b8484612892565b602881901c60008181526009602090815260408083206001600160a01b0387168452825280832064ffffffffff861680855260019091019092528220805492938493909291906001600160601b0316611fca576040805162461bcd60e51b81526020600482015260126024820152711211560e8814185c985b481a5b9d985b1a5960721b604482015290519081900360640190fd5b546001600160601b03811697600160601b9091046001600160a01b03169650945050505050565b6003546004546001600160481b0380831692600160481b810482169264ffffffffff600160901b8304811693600160b81b90930483169261ffff83169262010000810490911691600160581b820416906001600160801b03600160801b9091041688565b61205d61342f565b82106120b0576040805162461bcd60e51b815260206004820152601a60248201527f4845583a20526f756e64206973206e6f7420636f6d706c657465000000000000604482015290519081900360640190fd5b600082815260096020908152604080832033845290915281208054909164ffffffffff909116908315612142578254600160281b900464ffffffffff16829003841115612139576040805162461bcd60e51b81526020600482015260126024820152711211560e8818dbdd5b9d081a5b9d985b1a5960721b604482015290519081900360640190fd5b5080830161219c565b508154600160281b900464ffffffffff1680821061219c576040805162461bcd60e51b81526020600482015260126024820152711211560e8818dbdd5b9d081a5b9d985b1a5960721b604482015290519081900360640190fd5b60006121a7866139d6565b600087815260086020526040812054919250805b600086815260018801602052604081208054908290556001600160601b03811691600160601b9091046001600160a01b03169085878402816121f957fe5b0490506001600160a01b03821661221b576122168c8a8385613a4e565b61226a565b600a81049081019060058204336001600160a01b038516141561224d57918201916122488e8c8587613a4e565b612263565b6122598e8c8587613a4e565b6122638482612f28565b0193909301925b600190980197939093019250508486106121bb57865464ffffffffff191664ffffffffff871617875580156122b7576122b7739a6a414d6f3497c05e3b1de90520765fa1e07c0382612f28565b81156122c7576122c73383612f28565b505050505050505050565b60006122dc61342f565b905061015f8110612334576040805162461bcd60e51b815260206004820152601760248201527f4845583a204c6f6262696573206861766520656e646564000000000000000000604482015290519081900360640190fd5b348061237e576040805162461bcd60e51b81526020600482015260146024820152731211560e88105b5bdd5b9d081c995c5d5a5c995960621b604482015290519081900360640190fd5b600082815260096020908152604080832033845282528083208054600164ffffffffff600160281b80840482168381019092160269ffffffffff000000000019909316929092178355835180850185526001600160601b0380891682526001600160a01b038b8116838901908152858a529386018852868920925183549451909116600160601b029082166001600160601b031990941693909317169190911790558685526008909352922080548401905561243c84828588613abc565b5050505050565b6000601b8460ff161015801561245d5750601e8460ff1611155b61249f576040805162461bcd60e51b815260206004820152600e60248201526d1211560e881d881a5b9d985b1a5960921b604482015290519081900360640190fd5b60006124ab88886110d9565b905060006124c26124bd8c8c8a613b2a565b613e66565b9050816001600160a01b031660018288888860405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561252b573d6000803e3d6000fd5b505050602060405103516001600160a01b0316149250505098975050505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b60006125ba85858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506137d192505050565b95945050505050565b6125cb614f08565b600454600090819081906125ee90600160801b90046001600160801b0316613f97565b604080516101a0810182526003546001600160481b038082168352600160481b82048116602084015264ffffffffff600160901b8304811694840194909452600160b81b9091048116606083015260045461ffff8116608084015262010000810490911660a0830152600160581b900490911660c082015260e08101829052610100810183905261012081018490524261014082015292955090935091506101608101612699610dc7565b8152602001600860006126aa61342f565b815260200190815260200160002054815250935050505090565b606081831080156126d7575061015f8211155b80156126ea57506126e661342f565b8211155b612730576040805162461bcd60e51b81526020600482015260126024820152714845583a20696e76616c69642072616e676560701b604482015290519081900360640190fd5b82820360405190808252806020026020018201604052801561275c578160200160208202803883390190505b5090508260005b60008281526008602052604090205483516001938401938301928591811061278757fe5b60200260200101818152505083821061276357505092915050565b3390565b6001600160a01b0383166127eb5760405162461bcd60e51b815260040180806020018281038252602481526020018061515b6024913960400191505060405180910390fd5b6001600160a01b0382166128305760405162461bcd60e51b8152600401808060200182810382526022815260200180614fb46022913960400191505060405180910390fd5b6001600160a01b03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b6001600160a01b0383166128d75760405162461bcd60e51b81526004018080602001828103825260258152602001806151366025913960400191505060405180910390fd5b6001600160a01b03821661291c5760405162461bcd60e51b8152600401808060200182810382526023815260200180614f496023913960400191505060405180910390fd5b61295f81604051806060016040528060268152602001615031602691396001600160a01b038616600090815260208190526040902054919063ffffffff6129ee16565b6001600160a01b038085166000908152602081905260408082209390935590841681522054612994908263ffffffff6133d516565b6001600160a01b038084166000818152602081815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b60008184841115612a7d5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612a42578181015183820152602001612a2a565b50505050905090810190601f168015612a6f5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000610e54827f4e831acb4223b66de3b3d2e54a2edeefb0de3d7916e2886a4b134d9764d41bec85613fb7565b600060036002836040518082805190602001908083835b60208310612ae85780518252601f199092019160209182019101612ac9565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015612b27573d6000803e3d6000fd5b5050506040513d6020811015612b3c57600080fd5b50516040805160208181019390935281518082038401815290820191829052805190928291908401908083835b60208310612b885780518252601f199092019160209182019101612b69565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015612bc7573d6000803e3d6000fd5b50506040515160601b9392505050565b6003546001600160481b038082168452600160481b82048116602085015264ffffffffff600160901b830481166040860152600160b81b9092048116606085015260045461ffff8116608086015262010000810490911660a0850152600160581b810490911660c0840152612c5c906001600160801b03600160801b90910416613f97565b60e0850152610100840152610120830152612c7561342f565b610140830152612c858282614061565b5050565b825464ffffffffff838116911614612ce8576040805162461bcd60e51b815260206004820152601e60248201527f4845583a207374616b654964506172616d206e6f7420696e207374616b650000604482015290519081900360640190fd5b915464ffffffffff811683526001600160481b03600160281b820481166020850152600160701b820416604084015261ffff600160b81b820481166060850152600160c81b820481166080850152600160d81b82041660a084015260ff600160e81b90910416151560c09092019190915250565b61162f8182610140015160016138e1565b604081015160a080840180519290920390915261014090920151910152565b6000806000808560800151851015612dca57612db78787606001518860800151888a604001516140c9565b6020880151820195509093509150612e08565b60408601516060870151612de2918991888101614172565b9250828660200151019350612e05866060015187608001518860a0015187614240565b91505b8115612e275783821115612e1f5750600092612e27565b509182900391805b93509350935093565b8664ffffffffff16336001600160a01b03167f72d9c5a7ab13846e08d9c838f9e866a1bb4a66a2fd3ba3c9e7da3cf9e394dfd760b8876001600160481b0316901b6070896001600160481b0316901b60288b6001600160481b0316901b4264ffffffffff1617171784612ea4576000612eaa565b600160581b5b6001600160601b031660488761ffff16901b886001600160481b03161717604051808381526020018281526020019250505060405180910390a350505050505050565b600281048015612f1557612f15739a6a414d6f3497c05e3b1de90520765fa1e07c0382612f28565b6060909201805192909103919091019052565b6001600160a01b038216612f83576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b600254612f96908263ffffffff6133d516565b6002556001600160a01b038216600090815260208190526040902054612fc2908263ffffffff6133d516565b6001600160a01b0383166000818152602081815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b8160200151811115611be557600061303482846080015161426c565b905060008360400151620186a0838501028161304c57fe5b04905064ffffffffff811115613064575064ffffffffff5b846040015181111561243c5760408501819052835161243c9082906142de565b8154600019018181146131b15782818154811061309d57fe5b906000526020600020018383815481106130b357fe5b6000918252602090912082549101805464ffffffffff90921664ffffffffff199092169190911780825582546dffffffffffffffffff000000000019909116600160281b918290046001600160481b0390811690920217808355835468ffffffffffffffffff60701b19909116600160701b918290049092160217808255825461ffff60b81b19909116600160b81b9182900461ffff90811690920217808355835461ffff60c81b19909116600160c81b91829004831690910217808355835461ffff60d81b19909116600160d81b918290049092160217808255915460ff60e81b19909216600160e81b9283900460ff1615159092029190911790555b828054806131bb57fe5b600082815260209020810160001990810180546001600160f01b0319169055019055505050565b805182511415806131fb57508060200151826020015114155b8061320e57508060400151826040015114155b8061322157508060600151826060015114155b156132af5781516003805460208501516040860151606087015168ffffffffffffffffff199093166001600160481b039586161768ffffffffffffffffff60481b1916600160481b928616929092029190911764ffffffffff60901b1916600160901b64ffffffffff90921691909102176001600160b81b0316600160b81b93909116929092029190911790555b806080015182608001511415806132ce57508060a001518260a0015114155b806132ef57508060c0015164ffffffffff168260c0015164ffffffffff1614155b8061330257508060e001518260e0015114155b80613317575080610100015182610100015114155b8061332c575080610120015182610120015114155b15612c855760808201516004805460a085015160c086015164ffffffffff16600160581b0264ffffffffff60581b196001600160481b0390921662010000026affffffffffffffffff00001961ffff90961661ffff199094169390931794909416919091171691909117905561012082015161010083015160e08401516133b4929190614335565b600480546001600160801b03928316600160801b0292169190911790555050565b600082820183811015610e54576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6201518042635de5a57f19010490565b6115b38211156134805760405162461bcd60e51b81526004018080602001828103825260268152602001806150ca6026913960400191505060405180910390fd5b600061348c848461426c565b905060008560400151620186a083870102816134a457fe5b049050806134e35760405162461bcd60e51b8152600401808060200182810382526037815260200180614ffa6037913960400191505060405180910390fd5b600060018761014001511061350057866101400151600101613503565b60025b60c08801805160010164ffffffffff16908190523360009081526007602052604090209192509061353990828986868b8b614346565b6135468188858989614474565b505060208601805190910190525050825190910190915250565b6001600160a01b0382166135a55760405162461bcd60e51b81526004018080602001828103825260218152602001806150f06021913960400191505060405180910390fd5b6135e881604051806060016040528060228152602001614f92602291396001600160a01b038516600090815260208190526040902054919063ffffffff6129ee16565b6001600160a01b038316600090815260208190526040902055600254613614908263ffffffff61450616565b6002556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b604080514264ffffffffff9081166dffffffffffffffffff0000000000602889901b161768ffffffffffffffffff60701b607088901b16176001600160b81b031960b887901b161782526001600160481b038416602083015282513393918916926001600160a01b038b16927fd824970a2cf19cc2b630c87ce5b00f67301cac3ac60513d027c7a39129f93b4692918290030190a4505050505050565b80518254602083015160408401516060850151608086015160a087015160c09097015164ffffffffff1990951664ffffffffff909616959095176dffffffffffffffffff00000000001916600160281b6001600160481b03948516021768ffffffffffffffffff60701b1916600160701b93909216929092021761ffff60b81b1916600160b81b61ffff928316021761ffff60c81b1916600160c81b938216939093029290921761ffff60d81b1916600160d81b92909316919091029190911760ff60e81b1916600160e81b91151591909102179055565b80516000906bffffffffffffe0000000000090839083906137ee57fe5b602002602001015160001c16600014613843576040805162461bcd60e51b81526020600482015260126024820152711211560e881c1c9bdbd9881a5b9d985b1a5960721b604482015290519081900360640190fd5b60015b82518110156138c95782516bffffffffffffe000000000009084908390811061386b57fe5b602002602001015160001c16600014156138c1576040805162461bcd60e51b81526020600482015260126024820152711211560e881c1c9bdbd9881a5b9d985b1a5960721b604482015290519081900360640190fd5b600101613846565b506001600160601b0319841683176125ba8184612a85565b818360800151106138f157611be5565b6138f9614f27565b8351613903610dc7565b0181526080840151613916858383614548565b6020850151156139365760208501805160a0870180519091019052600090525b600101838110156139515761394c858383614548565b613936565b613960856080015182856145d3565b6080850181905260208201511561243c5761243c739a6a414d6f3497c05e3b1de90520765fa1e07c038360200151612f28565b600061399d614e43565b6139a5614e43565b6139af8282612bd7565b6139be828a8a8a8a8a8a61464a565b92506139ca82826131e2565b50509695505050505050565b600060018210613a3f576139e8614e43565b6139f0614e43565b6139fa8282612bd7565b613a0382612d5c565b600084815260066020526040902054600160901b900466ffffffffffffff1661015e6127108202049350613a3783836131e2565b505050611124565b5067016345785d8a0000919050565b806001600160a01b031683602886901b17336001600160a01b03167fa6b19fa7f41317a186e1d58e9d81f86a52f1102b6bce10b4eca83f37aaa584686028866001600160481b0316901b4264ffffffffff16176040518082815260200191505060405180910390a450505050565b806001600160a01b031683602886901b17336001600160a01b03167f25ecdb937d5c5cc78f0d18dfb1ac82c44086b5dc608380ba357d06c9868f0b1d6028866001600160601b0316901b4264ffffffffff16176040518082815260200191505060405180910390a450505050565b60608060018316613b62576040518060400160405280600f81526020016e086d8c2d2dabe908ab0bee8debe60f608b1b815250613b92565b60405180604001604052806016815260200175086d8c2d2dabe84d2e8c6ded2dc908ab0bee8debe60f60531b8152505b905060108316156060613ba587836147b5565b905085613cca576018772134ba31b7b4b71029b4b3b732b21026b2b9b9b0b3b29d0560411b60146002028551018584604051602001808660ff1660ff1660f81b81526001018567ffffffffffffffff191667ffffffffffffffff191681526018018460ff1660ff1660f81b815260010183805190602001908083835b60208310613c405780518252601f199092019160209182019101613c21565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b60208310613c885780518252601f199092019160209182019101613c69565b6001836020036101000a038019825116818451168082178552505050505050905001955050505050506040516020818303038152906040529350505050610e54565b604080516018808252818301909252606091602082018180388339019050509050613cf78188600c614858565b8351604051600360fb1b6020808301918252772134ba31b7b4b71029b4b3b732b21026b2b9b9b0b3b29d0560411b60218401819052604190940160f881901b6001600160f81b031916603985015288516018959491938a9389938993603a909101918601908083835b60208310613d7f5780518252601f199092019160209182019101613d60565b51815160209384036101000a600019018019909216911617905286519190930192860191508083835b60208310613dc75780518252601f199092019160209182019101613da8565b6001836020036101000a03801982511681845116808217855250505050505090500180605f60f81b81525060010182805190602001908083835b60208310613e205780518252601f199092019160209182019101613e01565b6001836020036101000a03801982511681845116808217855250505050505090500196505050505050506040516020818303038152906040529450505050509392505050565b6000600280836040518082805190602001908083835b60208310613e9b5780518252601f199092019160209182019101613e7c565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015613eda573d6000803e3d6000fd5b5050506040513d6020811015613eef57600080fd5b50516040805160208181019390935281518082038401815290820191829052805190928291908401908083835b60208310613f3b5780518252601f199092019160209182019101613f1c565b51815160209384036101000a60001901801990921691161790526040519190930194509192505080830381855afa158015613f7a573d6000803e3d6000fd5b5050506040513d6020811015613f8f57600080fd5b505192915050565b606681901c6303ffffff16916607ffffffffffff603383901c8116921690565b600081815b8551811015614056576000868281518110613fd357fe5b602002602001015190508083101561401b578281604051602001808381526020018281526020019250505060405160208183030381529060405280519060200120925061404d565b808360405160200180838152602001828152602001925050506040516020818303038152906040528051906020012092505b50600101613fbc565b509092149392505050565b815181526020808301519082015260408083015190820152606080830151908201526080808301519082015260a0808301519082015260c08083015164ffffffffff169082015260e08083015190820152610100808301519082015261012091820151910152565b60008083860160026001870104605a8110156140e35750605a5b856141035760006140f58a878b614920565b919091029250614168915050565b858110156141385787810161411a8a878b84614172565b9350600061412a8b888487614172565b850195506141689350505050565b61414489868a85614172565b93508581141561415657839250614165565b858185028161416157fe5b0492505b50505b9550959350505050565b6000825b828110156141b7576000818152600660205260409020546001600160481b03600160481b8204811691168602816141a957fe5b049190910190600101614176565b5061016083118015906141cb575061016082115b15610f1357610160600090815260066020527f5bc747bd71b549e015c2e31a0d21c276f82136338c6c7203a3f9911f7240314a54600160481b90046001600160481b0316856127106305f5e1008004028860e0015102028161422957fe5b04905061423686826149b3565b0101949350505050565b6000848401600e01808411614259576000915050610f13565b6102bc8185038402049695505050505050565b600080600183111561429257610e3883111561428a57610e3861428f565b600183035b90505b600066354a6ba7a180008511156142b05766354a6ba7a180006142b2565b845b670214e8348c4f0000830261071c82020193509050680ecca2d59581a400008584020495945050505050565b8064ffffffffff167f9861fa0ed101659f7a59b4583fcc798dfa4f3b419bea371c8ee2ad0ffe13a31e60288464ffffffffff16901b4264ffffffffff16176040518082815260200191505060405180910390a25050565b60669290921b60339190911b171790565b6040805160e08101825264ffffffffff97881681526001600160481b03968716602080830191825296881692820192835261ffff9586166060830190815294861660808301908152600060a0840181815295151560c085019081528c54600181018e559c8252989020925192909a0180549151935195519a519451975164ffffffffff1990921692909916919091176dffffffffffffffffff00000000001916600160281b928816929092029190911768ffffffffffffffffff60701b1916600160701b93909616929092029490941761ffff60b81b1916600160b81b968316969096029590951761ffff60c81b1916600160c81b938216939093029290921761ffff60d81b1916600160d81b91909216021760ff60e81b1916600160e81b92151592909202919091179055565b64ffffffffff8516337f14872dc760f33532684e68e1b6d5fd3f71ba7b07dee76bdb2b084f28b74233ef836144aa5760006144b0565b600160c81b5b6001600160d01b031660b88661ffff16901b6070886001600160481b0316901b60288a6001600160481b0316901b4264ffffffffff16171717176040518082815260200191505060405180910390a35050505050565b6000610e5483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506129ee565b6145538383836149f3565b60409182015160009182526006602052919020805460a084015160e09094015168ffffffffffffffffff199091166001600160481b039384161768ffffffffffffffffff60481b1916600160481b93909416929092029290921766ffffffffffffff60901b1916600160901b66ffffffffffffff90921691909102179055565b337fb8d6eb541ded1720cc657b719f57abcb1fe4711cb7ead82751b135f5d94bc94482614601576000614607565b600160481b5b69ffffffffffffffffffff1660388561ffff16901b60288761ffff16901b4264ffffffffff161717176040518082815260200191505060405180910390a2505050565b6000600188610140015110156146915760405162461bcd60e51b8152600401808060200182810382526024815260200180614fd66024913960400191505060405180910390fd5b61014088015161015f116146ec576040805162461bcd60e51b815260206004820152601a60248201527f4845583a20436c61696d2070686173652068617320656e646564000000000000604482015290519081900360640190fd5b6146f588612d5c565b6301ab362e88610120015110614752576040805162461bcd60e51b815260206004820152601e60248201527f4845583a2043484b3a205f636c61696d656442746341646472436f756e740000604482015290519081900360640190fd5b60008060006147618b8b614a8d565b6101208e0180516001019052919450925090506147848989898d8787878c614b47565b93506064605a85020461479a8c8289600161343f565b6147a68a828703612f28565b50505050979650505050505050565b60408051602880825260608281019093526020820181803883390190505090506147ef816001600160601b0319606086901b166014614858565b811561485257805160208201206000805b601481101561484e57600083826020811061481757fe5b600185019491901a9150614831908690600484901c614bf4565b614845858480600101955083600f16614bf4565b50600101614800565b5050505b92915050565b6000805b8281101561243c57600084826020811061487257fe5b1a90506f181899199a1a9b1b9c1cb0b131b232b360811b600482901c60ff166010811061489b57fe5b1a60f81b8684806001019550815181106148b157fe5b60200101906001600160f81b031916908160001a9053506f181899199a1a9b1b9c1cb0b131b232b360811b600f8216601081106148ea57fe5b1a60f81b86848060010195508151811061490057fe5b60200101906001600160f81b031916908160001a9053505060010161485c565b600061492a614e43565b6149348582614061565b61493c614f27565b8551614946610dc7565b0181526149548282866149f3565b60a082018051860190819052604082015186028161496e57fe5b0492506101608414156149aa5760a082015160e0830151600091908702612710028161499657fe5b0490506149a383826149b3565b0192909201915b50509392505050565b6000806301ab362e8461012001518402816149ca57fe5b049050600066033bb85fc52d998561010001518502816149e657fe5b0491909101949350505050565b81516305fcbae3906127100204604083015261015f811015614a695760e083015160009061015e90612710020490506000614a3485838660400151016149b3565b60208501805191840191820190528451810185526040850151909150614a5b9086906149b3565b604085018051909101905250505b606083015115611be557606083018051604084018051909101905260009052505050565b6000806000614a9b84614c60565b925066033bb85fc52d9983866101000151011115614b00576040805162461bcd60e51b815260206004820152601f60248201527f4845583a2043484b3a205f636c61696d65645361746f73686973546f74616c00604482015290519081900360640190fd5b610100850180518401905261014085015161015f03614b1f8482614cac565b60e0870180518290039052935061271084029250614b3d8382614cbd565b9150509250925092565b828201826001600160a01b038316614b6d57614b688a8a8a8a8a8789614cce565b614bc9565b600a8204918201916005830480820192909201916001600160a01b03858116908d161415614bad5792830192614ba88c8c8c8c8c898b614cce565b614bc6565b614bbc8c8c8c8c8c898b614cce565b614bc68582612f28565b50505b614be7739a6a414d6f3497c05e3b1de90520765fa1e07c0382612f28565b5098975050505050505050565b6000838381518110614c0257fe5b01602001516001600160f81b0319169050606160f81b8110801590614c2b575060088260ff1610155b156115a55780602060f81b18848481518110614c4357fe5b60200101906001600160f81b031916908160001a90535050505050565b600064174876e800821015614c76575080611124565b64e8d4a510008210614c8c575060048104611124565b65034630b8a000826501ba60d3380003830281614ca557fe5b0492915050565b600061015e8383025b049392505050565b60006106d160001983018402614cb5565b6040805164ffffffffff42166bffffffffffffff0000000000602888901b161766ffffffffffffff60601b606087901b161760ff60981b609889901b161768ffffffffffffffffff60a01b60a086901b1617815233602082015281516001600160a01b0380851693908b16926001600160601b03198b16927f41e3c7dc6eebc97a48a437ff2afdc629613f12c48ba37a2c94563f80acba9725929181900390910190a46001600160a01b038716331415614d8757614e3a565b336001600160a01b03167f3a84b2d9dac24683628d63034c6949797f15fab735e16232518ee4e753fd49b760c88666ffffffffffffff16901b60288960601c6001600160a01b0316901b4264ffffffffff16171760d88860ff16901b60388b6001600160a01b0316901b8766ffffffffffffff1617176048856001600160a01b0316901b866001600160481b03161760405180848152602001838152602001828152602001935050505060405180910390a25b50505050505050565b604051806101600160405280600081526020016000815260200160008152602001600081526020016000815260200160008152602001600064ffffffffff168152602001600081526020016000815260200160008152602001600081525090565b6040518060e00160405280600064ffffffffff16815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581525090565b60405180604001604052806002906020820280388339509192915050565b604051806101a00160405280600d906020820280388339509192915050565b6040518060600160405280600081526020016000815260200160008152509056fe45524332303a207472616e7366657220746f20746865207a65726f20616464726573734845583a206265666f72654461792063616e6e6f7420626520696e207468652066757475726545524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a20617070726f766520746f20746865207a65726f20616464726573734845583a20436c61696d20706861736520686173206e6f742079657420737461727465644845583a206e65775374616b6564486561727473206d757374206265206174206c65617374206d696e696d756d2073686172655261746545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63654845583a204254432061646472657373206f722062616c616e636520756e6b6e6f776e4845583a2042544320616464726573732062616c616e636520616c726561647920636c61696d656445524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e63654845583a206e65775374616b65644461797320686967686572207468616e206d6178696d756d45524332303a206275726e2066726f6d20746865207a65726f20616464726573734845583a206175746f5374616b6544617973206c6f776572207468616e206d696e696d756d45524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573734845583a206e65775374616b656444617973206c6f776572207468616e206d696e696d756d45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa265627a7a72315820e1386410ff82a380822a5c5fb950ec31ad42ac34f1e670c4d9b8c7329878472b64736f6c634300050d0032

Deployed Bytecode Sourcemap

105077:626:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23081:35;;8:9:-1;5:2;;;30:1;27;20:12;5:2;23081: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;23081:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11826:152;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11826:152:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;11826:152:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;10847:91;;8:9:-1;5:2;;;30:1;27;20:12;5:2;10847:91:0;;;:::i;:::-;;;;;;;;;;;;;;;;12450:304;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12450:304:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;12450:304:0;;;;;;;;;;;;;;;;;:::i;30932:50::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;30932:50:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;30932:50:0;;;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;;;30932:50:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;72420:199;;8:9:-1;5:2;;;30:1;27;20:12;5:2;72420:199:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;72420:199:0;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;72420:199:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;72420:199:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;72420:199:0;;-1:-1:-1;72420:199:0;-1:-1:-1;72420:199:0;:::i;75093:1390::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;75093:1390:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;75093:1390:0;;;;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;75093:1390:0;;;;;;;;;;;;;;74479:222;;8:9:-1;5:2;;;30:1;27;20:12;5:2;74479:222:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;74479:222:0;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;74479:222:0;;;;;;;;;;;;;;23167:34;;8:9:-1;5:2;;;30:1;27;20:12;5:2;23167:34:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;54248:159;;8:9:-1;5:2;;;30:1;27;20:12;5:2;54248:159:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;54248:159:0;-1:-1:-1;;;;;54248:159:0;;:::i;51083:3015::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;51083:3015:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;51083:3015:0;;;;;;;;;:::i;13163:210::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;13163:210:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;13163:210:0;;;;;;;;:::i;34931:158::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;34931:158:0;;;:::i;31488:79::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;31488:79:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;31488:79:0;;;;;;-1:-1:-1;;;;;31488:79:0;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102967:533;;8:9:-1;5:2;;;30:1;27;20:12;5:2;102967:533:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;102967:533:0;-1:-1:-1;;;;;102967:533: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;102967:533:0;;;;;;;;;;;;;;;;48085:648;;8:9:-1;5:2;;;30:1;27;20:12;5:2;48085:648:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;48085:648:0;;;;;;;:::i;100821:173::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;100821:173:0;;;:::i;35252:125::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;35252:125:0;;;:::i;49101:1716::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;49101:1716:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;49101:1716:0;;-1:-1:-1;;;;;49101:1716:0;;;;;;;;;;;;;:::i;32839:710::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;32839:710:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;32839:710: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;32839:710:0;;;;;;;;;;;;;;;;;11001:110;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11001:110:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;11001:110:0;-1:-1:-1;;;;;11001:110:0;;:::i;30094:48::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;30094:48:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;30094:48:0;-1:-1:-1;;;;;;30094:48:0;;:::i;31439:42::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;31439:42:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;31439:42:0;;:::i;70963:656::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;70963:656:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;70963:656:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;70963:656:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;70963:656:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;70963:656:0;;-1:-1:-1;70963:656:0;-1:-1:-1;70963:656:0;:::i;31820:659::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;31820:659:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;31820:659:0;;:::i;30323:51::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;30323:51:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;30323:51:0;;:::i;:::-;;;;-1:-1:-1;;;;;30323:51:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83298:2307;;8:9:-1;5:2;;;30:1;27;20:12;5:2;83298:2307:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;83298:2307:0;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;83298:2307:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;83298:2307:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;83298:2307:0;;-1:-1:-1;83298:2307:0;-1:-1:-1;;;;;;83298:2307:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;13876:261::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;13876:261:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;13876:261:0;;;;;;;;:::i;11324:158::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11324:158:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;11324:158:0;;;;;;;;:::i;102236:520::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;102236:520:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;102236:520:0;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;102236:520:0;;;;;;;;;;;;;;;;30025:27;;8:9:-1;5:2;;;30:1;27;20:12;5:2;30025:27:0;;;:::i;:::-;;;;-1:-1:-1;;;;;30025:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;30025:27:0;;;;;;;;;;;;;;;;;98251:2463;;8:9:-1;5:2;;;30:1;27;20:12;5:2;98251:2463:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;98251:2463:0;;;;;;;:::i;97355:654::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;97355:654:0;-1:-1:-1;;;;;97355:654:0;;:::i;73326:875::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;73326:875:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;73326:875:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;11545:134::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;11545:134:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;11545:134:0;;;;;;;;;;:::i;71940:225::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;71940:225:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;71940:225:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;71940:225:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;71940:225:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;-1:-1;71940:225:0;;-1:-1:-1;71940:225:0;-1:-1:-1;71940:225:0;:::i;33780:927::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33780:927:0;;;:::i;:::-;;;84:18:-1;;64:39;;33780:927:0;;;;;;52:2:-1;8:100;;101277:534:0;;8:9:-1;5:2;;;30:1;27;20:12;5:2;101277:534:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;101277:534:0;;;;;;;:::i;23081:35::-;;;;;;;;;;;;;;-1:-1:-1;;;23081:35:0;;;;:::o;11826:152::-;11892:4;11909:39;11918:12;:10;:12::i;:::-;11932:7;11941:6;11909:8;:39::i;:::-;-1:-1:-1;11966:4:0;11826:152;;;;:::o;10847:91::-;10918:12;;10847:91;:::o;12450:304::-;12539:4;12556:36;12566:6;12574:9;12585:6;12556:9;:36::i;:::-;12603:121;12612:6;12620:12;:10;:12::i;:::-;12634:89;12672:6;12634:89;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;12634:19:0;;;;;;:11;:19;;;;;;12654:12;:10;:12::i;:::-;-1:-1:-1;;;;;12634:33:0;;;;;;;;;;;;-1:-1:-1;12634:33:0;;;:89;;:37;:89;:::i;:::-;12603:8;:121::i;:::-;-1:-1:-1;12742:4:0;12450:304;;;;;;:::o;30932:50::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;30932:50:0;;;;;-1:-1:-1;;;;30932:50:0;;;;;-1:-1:-1;;;30932:50:0;;;;;-1:-1:-1;;;30932:50:0;;;;;-1:-1:-1;;;30932:50:0;;;;;-1:-1:-1;;;30932:50:0;;;;;:::o;72420:199::-;72544:4;72573:38;72593:10;72605:5;;72573:38;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;72573:19:0;;-1:-1:-1;;;72573:38:0:i;:::-;72566:45;72420:199;-1:-1:-1;;;;72420:199:0:o;75093:1390::-;75221:7;;75507:19;28917:6;75556:43;;75555:50;;;;28991:6;75631:47;;75630:54;;;29057:6;75710:39;;75709:46;;;75768:525;;75857:6;:16;;;;;75867:6;75857:16;75855:19;75847:55;;;;;-1:-1:-1;;;75847:55:0;;;;;;;;;;;;-1:-1:-1;;;75847:55:0;;;;;;;;;;;;;;;-1:-1:-1;;;75935:11:0;;;;:18;75934:25;:39;;75969:4;75934:39;;;75962:4;75934:39;75997;;;-1:-1:-1;;;;;;75997:39:0;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;75997:39:0;;;;;;;75919:54;;-1:-1:-1;75997:39:0;-1:-1:-1;75768:525:0;;;76128:6;76127:7;:18;;;;;76139:6;76138:7;76127:18;76119:54;;;;;-1:-1:-1;;;76119:54:0;;;;;;;;;;;;-1:-1:-1;;;76119:54:0;;;;;;;;;;;;;;;76233:48;;;-1:-1:-1;;;76233:48:0;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;76233:48:0;;;;;;;76205:4;;-1:-1:-1;76233:48:0;-1:-1:-1;75768:525:0;76305:18;76326:16;76335:6;76326:8;:16::i;:::-;76305:37;;76357:6;76353:95;;;76396:39;;;-1:-1:-1;;;76396:39:0;;;;-1:-1:-1;;;;;;76396:39:0;;;;;;;;22:32:-1;26:21;;;22:32;6:49;;76396:39:0;;;;;;;76387:49;;:8;:49::i;:::-;76380:56;;;;;;;;;;76353:95;76465:10;75093:1390;-1:-1:-1;;;;;;;;;75093:1390:0:o;74479:222::-;74655:34;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;6:49;;74655:34:0;;;;;;74645:45;;;;;;74479:222::o;23167:34::-;23200:1;23167:34;:::o;54248:159::-;-1:-1:-1;;;;;54370:22:0;;54338:7;54370:22;;;:10;:22;;;;;:29;54248:159;;;;:::o;51083:3015::-;51176:21;;:::i;:::-;51208:29;;:::i;:::-;51248:26;51261:1;51264:9;51248:12;:26::i;:::-;51334:10;51287:33;51323:22;;;:10;:22;;;;;51437:19;;51429:58;;;;;-1:-1:-1;;;51429:58:0;;;;;;;;;;;;-1:-1:-1;;;51429:58:0;;;;;;;;;;;;;;;51519:19;;51506:32;;51498:68;;;;;-1:-1:-1;;;51498:68:0;;;;;;;;;;;;-1:-1:-1;;;51498:68:0;;;;;;;;;;;;;;;51609:20;;:::i;:::-;51640:54;51651:12;51664:10;51651:24;;;;;;;;;;;;;;;51677:12;51691:2;51640:10;:54::i;:::-;51760:23;51781:1;51760:20;:23::i;:::-;51852:15;;;;52032:13;;;;52015;;;;51796:18;;51852:20;;;51796:18;;;;;;;;-1:-1:-1;52011:1244:0;;52066:12;52062:708;;;52211:2;:14;;;52198:27;;52062:708;;;52266:19;52279:1;52282:2;52266:12;:19::i;:::-;52335:2;:13;;;52319:1;:13;;;:29;52306:42;;52384:2;:14;;;52371:10;:27;52367:388;;;52436:2;:14;;;52423:27;;52367:388;;;26579:3;52594:10;:32;52590:146;;;52664:2;:15;;;52663:16;52655:57;;;;;-1:-1:-1;;;52655:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;52834:36;52852:1;52855:2;52859:10;52834:17;:36::i;:::-;52786:84;;-1:-1:-1;52786:84:0;;-1:-1:-1;52786:84:0;-1:-1:-1;52786:84:0;-1:-1:-1;52011:1244:0;;;52995:2;:15;;;52994:16;52986:57;;;;;-1:-1:-1;;;52986:57:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;53181:15;;;;53154:23;;;;:42;;;;;;;;;53227:16;;;;-1:-1:-1;52011:1244:0;53267:207;53295:12;53322:2;:16;;;53353:2;:15;;;53383:6;53404:7;53426:10;53451:12;53267:13;:207::i;:::-;53491:18;;;;;:35;;;53514:12;53513:13;53491:35;53487:206;;;53642:39;53664:1;53667:13;53642:21;:39::i;:::-;53768:16;;53764:186;;53801:30;53807:10;53819:11;53801:5;:30::i;:::-;53902:36;53919:1;53922:2;53926:11;53902:16;:36::i;:::-;53984:16;;;;53960:40;;;;;54013:38;54026:12;54040:10;54013:12;:38::i;:::-;54064:26;54077:1;54080:9;54064:12;:26::i;:::-;51083:3015;;;;;;;;;;;;:::o;13163:210::-;13243:4;13260:83;13269:12;:10;:12::i;:::-;13283:7;13292:50;13331:10;13292:11;:25;13304:12;:10;:12::i;:::-;-1:-1:-1;;;;;13292:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;13292:25:0;;;:34;;;;;;;;;;;:50;:38;:50;:::i;34931:158::-;35056:7;:25;35008:7;;-1:-1:-1;;;;;35056:25:0;35040:13;:11;:13::i;:::-;:41;35033:48;;34931:158;:::o;31488:79::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;31488:79:0;;;;:::o;102967:533::-;103065:40;;:::i;:::-;103123:11;103137:13;:11;:13::i;:::-;103153:1;103137:17;;-1:-1:-1;24564:40:0;103171:25;;103167:83;;;-1:-1:-1;24564:40:0;103167:83;-1:-1:-1;;103269:5:0;;;:10;103262:206;;103344:19;;;;:14;:19;;;;;;;;-1:-1:-1;;;;;103344:31:0;;;;;;;;;:41;;;;;-1:-1:-1;;;103300:41:0;;;;:85;103296:161;;;103425:1;103437:3;103431:9;;103425:16;103406:5;103419:1;103412:8;;;103406:15;;;;;;;;;;:35;;;;;;;103296:161;103262:206;;;-1:-1:-1;102967:533:0;;;:::o;48085:648::-;48187:21;;:::i;:::-;48219:29;;:::i;:::-;48259:26;48272:1;48275:9;48259:12;:26::i;:::-;26523:1;48352:13;:31;;48344:81;;;;-1:-1:-1;;;48344:81:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48491:23;48512:1;48491:20;:23::i;:::-;48527:53;48539:1;48542:15;48559:13;48574:5;48527:11;:53::i;:::-;48652:34;48658:10;48670:15;48652:5;:34::i;:::-;48699:26;48712:1;48715:9;48699:12;:26::i;:::-;48085:648;;;;:::o;100821:173::-;100895:4;100887:21;100879:52;;;;;-1:-1:-1;;;100879:52:0;;;;;;;;;;;;-1:-1:-1;;;100879:52:0;;;;;;;;;;;;;;;100944:42;;23003;;100972:4;100964:21;100944:42;;;;;;;;;100964:21;23003:42;100944;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;100944:42:0;100821:173::o;35252:125::-;35324:7;35356:13;:11;:13::i;:::-;35349:20;;35252:125;:::o;49101:1716::-;49225:21;;:::i;:::-;49257:29;;:::i;:::-;49297:26;49310:1;49313:9;49297:12;:26::i;:::-;-1:-1:-1;;;;;49415:22:0;;;;;;:10;:22;;;;;:29;49407:68;;;;;-1:-1:-1;;;49407:68:0;;;;;;;;;;;;-1:-1:-1;;;49407:68:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;49507:22:0;;;;;;:10;:22;;;;;:29;49494:42;;49486:78;;;;;-1:-1:-1;;;49486:78:0;;;;;;;;;;;;-1:-1:-1;;;49486:78:0;;;;;;;;;;;;;;;-1:-1:-1;;;;;49604:22:0;;49577:24;49604:22;;;:10;:22;;;;;:34;;49627:10;;49604:34;;;;;;;;;;;;;49577:61;;49681:20;;:::i;:::-;49712:35;49723:5;49730:12;49744:2;49712:10;:35::i;:::-;49849:2;:14;;;49833:2;:13;;;:30;49816:1;:13;;;:47;;49808:87;;;;;-1:-1:-1;;;49808:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;49958:15;;;;:20;49950:60;;;;;-1:-1:-1;;;49950:60:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;50076:23;50097:1;50076:20;:23::i;:::-;50154:19;50167:1;50170:2;50154:12;:19::i;:::-;50237:14;50253:15;50270:21;50295:90;50327:1;50343:2;50360;:14;;;50295:17;:90::i;:::-;50234:151;;;;;;;50398:191;50437:10;50462:12;50489:2;:16;;;50520:2;:15;;;50550:6;50571:7;50398:24;:191::i;:::-;50606:18;;50602:90;;50641:39;50663:1;50666:13;50641:21;:39::i;:::-;50747:23;50760:5;50767:2;50747:12;:23::i;:::-;50783:26;50796:1;50799:9;50783:12;:26::i;:::-;49101:1716;;;;;;;;;;:::o;32839:710::-;32947:21;33005:6;32994:8;:17;:53;;;;-1:-1:-1;33025:22:0;;;;33015:32;;;32994:53;32986:84;;;;;-1:-1:-1;;;32986:84:0;;;;;;;;;;;;-1:-1:-1;;;32986:84:0;;;;;;;;;;;;;;;33113:8;33104:6;:17;33090:32;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;33090:32:0;-1:-1:-1;33083:39:0;-1:-1:-1;33149:8:0;33135:11;;33214:304;-1:-1:-1;33244:14:0;;;;:9;:14;;;;;:40;33467:11;;33420:29;33472:5;;;-1:-1:-1;;;33244:40:0;;33290:19;33236:74;-1:-1:-1;;;33236:74:0;-1:-1:-1;;;33338:34:0;;23756:2;33330:62;;;33325:67;-1:-1:-1;;;;;33420:29:0;;;33407:43;;;;;;;33467:11;;33472:5;33467:11;;;;;;;;;;;:15;;;;;33510:6;33502:5;;;;;;:14;33214:304;;-1:-1:-1;;;32839:710:0;;;;:::o;11001:110::-;-1:-1:-1;;;;;11085:18:0;11058:7;11085:18;;;;;;;;;;;;11001:110::o;30094:48::-;;;;;;;;;;;;;;;:::o;31439:42::-;;;;;;;;;;;;;:::o;70963:656::-;71108:4;71130:11;71144:13;:11;:13::i;:::-;71130:27;;24243:1;71178:3;:28;;71170:77;;;;-1:-1:-1;;;71170:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24564:40;71266:25;;71258:64;;;;;-1:-1:-1;;;71258:64:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;71435:25:0;;;;;;:16;:25;;;;;;;;71431:70;;;71484:5;71477:12;;;;;71431:70;71564:47;71583:7;71592:11;71605:5;;71564:47;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;71564:18:0;;-1:-1:-1;;;71564:47:0:i;:::-;71557:54;70963:656;-1:-1:-1;;;;;;70963:656:0:o;31820:659::-;31898:21;;:::i;:::-;31930:29;;:::i;:::-;31970:26;31983:1;31986:9;31970:12;:26::i;:::-;24243:1;32054;:13;;;:37;32046:64;;;;;-1:-1:-1;;;32046:64:0;;;;;;;;;;;;-1:-1:-1;;;32046:64:0;;;;;;;;;;;;;;;32127:14;;32123:310;;32179:1;:13;;;32166:9;:26;;32158:77;;;;-1:-1:-1;;;32158:77:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32252:37;32269:1;32272:9;32283:5;32252:16;:37::i;:::-;32123:310;;;32380:41;32397:1;32400;:13;;;32415:5;32380:16;:41::i;:::-;32445:26;32458:1;32461:9;32445:12;:26::i;:::-;31820:659;;;:::o;30323:51::-;;;;;;;;;;;;-1:-1:-1;;;;;30323:51:0;;;;-1:-1:-1;;;30323:51:0;;;;;;-1:-1:-1;;;30323:51:0;;;;;:::o;83298:2307::-;83661:7;26274:14;83722:11;:44;;83714:78;;;;;-1:-1:-1;;;83714:78:0;;;;;;;;;;;;-1:-1:-1;;;83714:78:0;;;;;;;;;;;;;;;26579:3;83894:13;:36;;83886:86;;;;-1:-1:-1;;;83886:86:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84104:22;-1:-1:-1;;;;;84151:25:0;;84166:10;84151:25;84147:278;;-1:-1:-1;84327:63:0;;;24954:66;84327:63;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;84327:63:0;;;;;;;26:21:-1;;;22:32;;6:49;;84327:63:0;;;;;;;84295:114;;;;;84147:278;84467:283;84518:11;84552:14;84589:7;84619;84649:10;84682:1;84706;84730;84467:28;:283::i;:::-;84441:368;;;;;-1:-1:-1;;;84441:368:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;83298:2307;84883:15;84901:48;84920:7;84929;84938:10;84901:18;:48::i;:::-;-1:-1:-1;;;;;;85030:25:0;;;;;;:16;:25;;;;;;84883:66;;-1:-1:-1;85030:25:0;;85029:26;85021:79;;;;-1:-1:-1;;;85021:79:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;85196:47;85215:7;85224:11;85237:5;;85196:47;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;85196:18:0;;-1:-1:-1;;;85196:47:0:i;:::-;85174:132;;;;-1:-1:-1;;;85174:132:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;85362:25:0;;;;;;:16;:25;;;;;:32;;-1:-1:-1;;85362:32:0;85390:4;85362:32;;;85414:183;85447:11;85473;85379:7;85521:10;85546:13;85574:12;85414:18;:183::i;:::-;85407:190;83298:2307;-1:-1:-1;;;;;;;;;;;;;;83298:2307:0:o;13876:261::-;13961:4;13978:129;13987:12;:10;:12::i;:::-;14001:7;14010:96;14049:15;14010:96;;;;;;;;;;;;;;;;;:11;:25;14022:12;:10;:12::i;:::-;-1:-1:-1;;;;;14010:25:0;;;;;;;;;;;;;;;;;-1:-1:-1;14010:25:0;;;:34;;;;;;;;;;;:96;;:38;:96;:::i;11324:158::-;11393:4;11410:42;11420:12;:10;:12::i;:::-;11434:9;11445:6;11410:9;:42::i;102236:520::-;23875:2;102421:36;;;102345:17;102571:24;;;:14;:24;;;;;;;;-1:-1:-1;;;;;102571:36:0;;;;;;;;;23938;102489:35;;102571:56;;;23973:1;102571:44;;;:56;;;;;102648:15;;102345:17;;;;102421:36;;102489:35;102571:56;-1:-1:-1;;;;;102648:15:0;102640:51;;;;;-1:-1:-1;;;102640:51:0;;;;;;;;;;;;-1:-1:-1;;;102640:51:0;;;;;;;;;;;;;;;102712:15;-1:-1:-1;;;;;102712:15:0;;;-1:-1:-1;;;102729:18:0;;;-1:-1:-1;;;;;102729:18:0;;-1:-1:-1;102236:520:0;-1:-1:-1;;;;;102236:520:0:o;30025:27::-;;;;;-1:-1:-1;;;;;30025:27:0;;;;-1:-1:-1;;;30025:27:0;;;;;;-1:-1:-1;;;30025:27:0;;;;;-1:-1:-1;;;30025:27:0;;;;;;;;;;;;;;;;;-1:-1:-1;;;30025:27:0;;;;-1:-1:-1;;;;;;;;30025:27:0;;;;;:::o;98251:2463::-;98358:13;:11;:13::i;:::-;98347:8;:24;98339:63;;;;;-1:-1:-1;;;98339:63:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;98415:30;98448:24;;;:14;:24;;;;;;;;98473:10;98448:36;;;;;;;98517:14;;98448:36;;98517:14;;;;;98575:10;;98571:276;;98619:14;;-1:-1:-1;;;98619:14:0;;;;:26;;;98610:35;;;98602:66;;;;;-1:-1:-1;;;98602:66:0;;;;;;;;;;;;-1:-1:-1;;;98602:66:0;;;;;;;;;;;;;;;-1:-1:-1;98694:17:0;;;98571:276;;;-1:-1:-1;98755:14:0;;-1:-1:-1;;;98755:14:0;;;;98792:20;;;98784:51;;;;;-1:-1:-1;;;98784:51:0;;;;;;;;;;;;-1:-1:-1;;;98784:51:0;;;;;;;;;;;;;;;98859:17;98879:20;98890:8;98879:10;:20::i;:::-;98910:16;98929:17;;;:7;:17;;;;;;98859:40;;-1:-1:-1;98910:16:0;99035:1428;99053:17;99073:23;;;:12;;;:23;;;;;:33;;99197:30;;;;-1:-1:-1;;;;;99073:33:0;;;-1:-1:-1;;;99144:36:0;;;-1:-1:-1;;;;;99144:36:0;;99287:8;99263:21;;;99287:8;99263:32;;;;;;-1:-1:-1;;;;;;99316:26:0;;99312:1066;;99398:61;99415:8;99425:9;99436:8;99446:12;99398:16;:61::i;:::-;99312:1066;;;99608:2;99597:13;;99631:31;;;;99799:1;99788:12;;99841:10;-1:-1:-1;;;;;99825:26:0;;;99821:461;;;99917:31;;;;99971:61;99988:8;99998:9;99917:31;100019:12;99971:16;:61::i;:::-;99821:461;;;100138:61;100155:8;100165:9;100176:8;100186:12;100138:16;:61::i;:::-;100222:40;100228:12;100242:19;100222:5;:40::i;:::-;100321:41;100300:62;;;;;99312:1066;100439:11;;;;;100394:25;;;;;-1:-1:-1;;100439:22:0;;;99035:1428;;100475:34;;-1:-1:-1;;100475:34:0;;;;;;;100526:22;;100522:92;;100565:37;22880:42;100584:17;100565:5;:37::i;:::-;100628:18;;100624:83;;100663:32;100669:10;100681:13;100663:5;:32::i;:::-;98251:2463;;;;;;;;;:::o;97355:654::-;97450:16;97469:13;:11;:13::i;:::-;97450:32;-1:-1:-1;24564:40:0;97501:30;;97493:66;;;;;-1:-1:-1;;;97493:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;97592:9;97620:14;97612:47;;;;;-1:-1:-1;;;97612:47:0;;;;;;;;;;;;-1:-1:-1;;;97612:47:0;;;;;;;;;;;;;;;97672:30;97705:24;;;:14;:24;;;;;;;;97730:10;97705:36;;;;;;;97775:16;;;;-1:-1:-1;;;97775:16:0;;;;;;;;;;;;-1:-1:-1;;97775:16:0;;;;;;;;;97831:50;;;;;;;-1:-1:-1;;;;;97831:50:0;;;;;-1:-1:-1;;;;;97831:50:0;;;;;;;;;97804:24;;;:12;;;:24;;;;;:77;;;;;;;;;-1:-1:-1;;;97804:77:0;;;;-1:-1:-1;;;;;;97804:77:0;;;;;;;;;;;;;;97894:17;;;:7;:17;;;;;:30;;;;;;97937:64;97720:8;97775:16;97856:9;97868:12;97937:17;:64::i;:::-;97355:654;;;;;:::o;73326:875::-;73619:4;73654:2;73649:1;:7;;;;:18;;;;;73665:2;73660:1;:7;;;;73649:18;73641:45;;;;;-1:-1:-1;;;73641:45:0;;;;;;;;;;;;-1:-1:-1;;;73641:45:0;;;;;;;;;;;;;;;73845:21;73869:36;73888:7;73897;73869:18;:36::i;:::-;73845:60;;73972:19;73994:94;74017:60;74037:11;74050:14;74066:10;74017:19;:60::i;:::-;73994:8;:94::i;:::-;73972:116;;74180:13;-1:-1:-1;;;;;74145:48:0;:31;74155:11;74168:1;74171;74174;74145:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;74145:31:0;;;;;;;;-1:-1:-1;;;;;74145:48:0;;74138:55;;;;73326:875;;;;;;;;;;:::o;11545:134::-;-1:-1:-1;;;;;11644:18:0;;;11617:7;11644:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;11545:134::o;71940:225::-;72081:4;72110:47;72129:7;72138:11;72151:5;;72110:47;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;72110:18:0;;-1:-1:-1;;;72110:47:0:i;:::-;72103:54;71940:225;-1:-1:-1;;;;;71940:225:0:o;33780:927::-;33852:18;;:::i;:::-;34116;;33888:28;;;;;;34084:61;;-1:-1:-1;;;34116:18:0;;-1:-1:-1;;;;;34116:18:0;34084:17;:61::i;:::-;34158:541;;;;;;;;34198:7;:25;-1:-1:-1;;;;;34198:25:0;;;34158:541;;-1:-1:-1;;;34238:28:0;;;;34158:541;;;;34281:17;-1:-1:-1;;;34281:17:0;;;;34158:541;;;;;;;-1:-1:-1;;;34313:25:0;;;;;34158:541;;;;34371:22;;;;;34158:541;;;;34408:24;;;;;;34158:541;;;;-1:-1:-1;;;34447:21:0;;;;;34158:541;;;;;;;;;;34198:25;34158:541;;;;;;;;;;;34608:15;34158:541;;;;34011:134;;-1:-1:-1;34011:134:0;;-1:-1:-1;34011:134:0;-1:-1:-1;34158:541:0;;;34638:13;:11;:13::i;:::-;34158:541;;;;34666:7;:22;34674:13;:11;:13::i;:::-;34666:22;;;;;;;;;;;;34158:541;;;;;;;;33780:927;:::o;101277:534::-;101383:21;101455:6;101444:8;:17;:50;;;;-1:-1:-1;24564:40:0;101465:29;;;101444:50;:77;;;;;101508:13;:11;:13::i;:::-;101498:6;:23;;101444:77;101422:145;;;;;-1:-1:-1;;;101422:145:0;;;;;;;;;;;;-1:-1:-1;;;101422:145:0;;;;;;;;;;;;;;;101610:8;101601:6;:17;101587:32;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;101587:32:0;-1:-1:-1;101580:39:0;-1:-1:-1;101646:8:0;101632:11;101691:89;101731:14;;;;:7;:14;;;;;;101709:11;;101739:5;;;;;101714;;;101709:4;;:11;;;;;;;;;;;:37;;;;;101772:6;101766:3;:12;101691:89;;-1:-1:-1;;101277:534:0;;;;:::o;806:98::-;886:10;806:98;:::o;16808:338::-;-1:-1:-1;;;;;16902:19:0;;16894:68;;;;-1:-1:-1;;;16894:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;16981:21:0;;16973:68;;;;-1:-1:-1;;;16973:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;17054:18:0;;;;;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;:36;;;17106:32;;;;;;;;;;;;;;;;;16808:338;;;:::o;14627:471::-;-1:-1:-1;;;;;14725:20:0;;14717:70;;;;-1:-1:-1;;;14717:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;14806:23:0;;14798:71;;;;-1:-1:-1;;;14798:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14902;14924:6;14902:71;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;14902:17:0;;:9;:17;;;;;;;;;;;;:71;;:21;:71;:::i;:::-;-1:-1:-1;;;;;14882:17:0;;;:9;:17;;;;;;;;;;;:91;;;;15007:20;;;;;;;:32;;15032:6;15007:32;:24;:32;:::i;:::-;-1:-1:-1;;;;;14984:20:0;;;:9;:20;;;;;;;;;;;;:55;;;;15055:35;;;;;;;14984:20;;15055:35;;;;;;;;;;;;;14627:471;;;:::o;5699:192::-;5785:7;5821:12;5813:6;;;;5805:29;;;;-1:-1:-1;;;5805: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;5805:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5857:5:0;;;5699:192::o;78632:214::-;78754:4;78783:55;78802:5;24954:66;78827:10;78783:18;:55::i;81955:167::-;82041:7;82073:41;82100:12;82107:4;82100:12;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;82100:12:0;;;;;;;-1:-1:-1;263:2;;-1:-1;;82100:12:0;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;82100:12:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;82100:12:0;82083:30;;;82100:12;82083:30;;;;;;;;;26:21:-1;;;22:32;;6:49;;82083:30:0;;;;;;;82073:41;;82083:30;;;;82073:41;;;;;82083:30;82073:41;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;82073:41:0;;;;;;;-1:-1:-1;263:2;;-1:-1;;82073:41:0;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;82073:41:0;;;;;;81955:167;-1:-1:-1;;;81955:167:0:o;35689:787::-;35850:7;:25;-1:-1:-1;;;;;35850:25:0;;;35827:48;;-1:-1:-1;;;35912:28:0;;;;35886:23;;;:54;35966:17;-1:-1:-1;;;35966:17:0;;;;35951:12;;;:32;-1:-1:-1;;;36017:25:0;;;;;35994:20;;;:48;36087:22;;;;;36067:17;;;:42;36142:24;;;;;;36120:19;;;:46;-1:-1:-1;;;36196:21:0;;;;;36177:16;;;:40;36307:61;;-1:-1:-1;;;;;;;;36339:18:0;;;;36307:17;:61::i;:::-;36278:25;;;36228:140;36253:23;;;36228:140;36229:22;;;36228:140;36407:13;:11;:13::i;:::-;36391;;;:29;36433:35;36391:1;36458:9;36433:21;:35::i;:::-;35689:787;;:::o;38779:588::-;38999:13;;;38983:29;;;38999:13;;38983:29;38975:72;;;;;-1:-1:-1;;;38975:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;39074:13;;;;;39060:27;;-1:-1:-1;;;;;;;;39117:18:0;;;;39098:16;;;:37;-1:-1:-1;;;39164:17:0;;;39146:15;;;:35;39208:15;-1:-1:-1;;;39208:15:0;;;;39192:13;;;:31;-1:-1:-1;;;39251:16:0;;;;39234:14;;;:33;-1:-1:-1;;;39296:17:0;;;39278:15;;;:35;39342:17;-1:-1:-1;;;39342:17:0;;;;39324:35;;:15;;;;:35;;;;-1:-1:-1;38779:588:0:o;35546:135::-;35633:40;35650:1;35653;:13;;;35668:4;35633:16;:40::i;60832:202::-;60969:15;;;;60946:19;;;;:38;;;;;;;;;61013:13;;;;;60995:15;;:31;60832:202::o;61042:1449::-;61183:19;61204:14;61220:15;61237:21;61293:2;:14;;;61280:10;:27;61276:738;;;61344:189;61389:1;61409:2;:13;;;61441:2;:14;;;61474:10;61503:2;:15;;;61344:26;:189::i;:::-;61562:16;;;;:25;;;-1:-1:-1;61324:209:0;;-1:-1:-1;61324:209:0;-1:-1:-1;61276:738:0;;;61737:15;;;;61771:13;;;;61680:164;;61717:1;;61803:26;;;61680:18;:164::i;:::-;61671:173;;61892:6;61873:2;:16;;;:25;61859:39;;61925:77;61942:2;:13;;;61957:2;:14;;;61973:2;:15;;;61990:11;61925:16;:77::i;:::-;61915:87;;61276:738;62028:12;;62024:397;;62071:11;62061:7;:21;62057:353;;;-1:-1:-1;62222:1:0;;62057:353;;;-1:-1:-1;62366:28:0;;;;;62340:7;62057:353;61042:1449;;;;;;;:::o;68302:719::-;68995:7;68564:449;;68970:10;-1:-1:-1;;;;;68564:449:0;;68807:3;68795:6;-1:-1:-1;;;;;68780:23:0;:30;;68755:3;68738:11;-1:-1:-1;;;;;68723:28:0;:35;;68699:2;68681:12;-1:-1:-1;;;;;68666:29:0;:35;;68628:15;68613:32;;:89;:146;:198;68926:12;:28;;68953:1;68926:28;;;-1:-1:-1;;;68926:28:0;-1:-1:-1;;;;;68826:129:0;68902:2;68886:10;68871:27;;:33;;68841:7;-1:-1:-1;;;;;68826:24:0;:79;:129;68564:449;;;;;;;;;;;;;;;;;;;;;;;;68302:719;;;;;;;:::o;65367:499::-;65578:1;65568:11;;65596:17;;65592:82;;65630:32;22880:42;65649:12;65630:5;:32::i;:::-;65822:20;;;;:36;;65789:22;;;;65822:36;;;;;;65367:499::o;15379:308::-;-1:-1:-1;;;;;15455:21:0;;15447:65;;;;;-1:-1:-1;;;15447:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;15540:12;;:24;;15557:6;15540:24;:16;:24;:::i;:::-;15525:12;:39;-1:-1:-1;;;;;15596:18:0;;:9;:18;;;;;;;;;;;:30;;15619:6;15596:30;:22;:30;:::i;:::-;-1:-1:-1;;;;;15575:18:0;;:9;:18;;;;;;;;;;;:51;;;;15642:37;;;;;;;15575:18;;:9;;15642:37;;;;;;;;;;15379:308;;:::o;65874:1190::-;66017:2;:16;;;66003:11;:30;65999:1058;;;66305:19;66327:51;66350:11;66363:2;:14;;;66327:22;:51::i;:::-;66305:73;;66393:20;66465:2;:15;;;27843:3;66431:11;66417;:25;66416:46;:64;;;;;;;-1:-1:-1;27998:31:0;66501:29;;66497:370;;;-1:-1:-1;27998:31:0;66497:370;66902:1;:12;;;66887;:27;66883:163;;;66935:12;;;:27;;;67018:11;;66983:47;;66950:12;;66983:20;:47::i;40937:647::-;41068:19;;-1:-1:-1;;41068:23:0;41190;;;41186:177;;41328:12;41341:9;41328:23;;;;;;;;;;;;;;;41301:12;41314:10;41301:24;;;;;;;;;;;;;;;;:50;;:24;;:50;;;;;;-1:-1:-1;;41301:50:0;;;;;;;;;;;;-1:-1:-1;;41301:50:0;;;-1:-1:-1;;;41301:50:0;;;;-1:-1:-1;;;;;41301:50:0;;;;;;;;;;;;-1:-1:-1;;;;41301:50:0;;;-1:-1:-1;;;41301:50:0;;;;;;;;;;;;;;-1:-1:-1;;;;41301:50:0;;;-1:-1:-1;;;41301:50:0;;;;;;;;;;;;;;;;;-1:-1:-1;;;;41301:50:0;;;-1:-1:-1;;;41301:50:0;;;;;;;;;;;;;;;-1:-1:-1;;;;41301:50:0;;;-1:-1:-1;;;41301:50:0;;;;;;;;;;;;;;-1:-1:-1;;;;41301:50:0;;;-1:-1:-1;;;41301:50:0;;;;;;;;;;;;;;;;;41186:177;41558:12;:18;;;;;;;;;;;;;;;;-1:-1:-1;;41558:18:0;;;;;-1:-1:-1;;;;;;41558:18:0;;;;;;-1:-1:-1;;;40937:647:0:o;37264:1507::-;37402:28;;37378:20;;:52;;;:127;;;37474:9;:31;;;37447:1;:23;;;:58;;37378:127;:180;;;;37538:9;:20;;;37522:1;:12;;;:36;;37378:180;:249;;;;37599:9;:28;;;37575:1;:20;;;:52;;37378:249;37374:559;;;37697:20;;37662:7;:56;;37771:23;;;;37837:12;;;;37900:20;;;;-1:-1:-1;;37662:56:0;;;-1:-1:-1;;;;;37662:56:0;;;;-1:-1:-1;;;;37733:62:0;-1:-1:-1;;;37733:62:0;;;;;;;;;;;-1:-1:-1;;;;37810:40:0;-1:-1:-1;;;37810:40:0;;;;;;;;;-1:-1:-1;;;;;37865:56:0;-1:-1:-1;;;37865:56:0;;;;;;;;;;;;;;37374:559;37968:9;:25;;;37947:1;:17;;;:46;;:113;;;;38033:9;:27;;;38010:1;:19;;;:50;;37947:113;:174;;;;38097:9;:24;;;38077:44;;:1;:16;;;:44;;;;37947:174;:253;;;;38167:9;:33;;;38138:1;:25;;;:62;;37947:253;:328;;;;38244:9;:31;;;38217:1;:23;;;:58;;37947:328;:401;;;;38318:9;:30;;;38292:1;:22;;;:56;;37947:401;37943:821;;;38415:17;;;;38383:22;:50;;38482:19;;;;38541:16;;;;38517:40;;-1:-1:-1;;;38517:40:0;-1:-1:-1;;;;;;;;;38448:54:0;;;;;-1:-1:-1;;38383:50:0;;;;-1:-1:-1;;38383:50:0;;;;;;;38448:54;;;;;;;;38517:40;;;;;;;38629:22;;;;38383:50;38670:23;;;38712:25;;;;38593:159;;38629:22;38670:23;38593:17;:159::i;:::-;38572:18;:180;;-1:-1:-1;;;;;38572:180:0;;;-1:-1:-1;;;38572:180:0;;;;;;;;;37264:1507;;:::o;4770:181::-;4828:7;4860:5;;;4884:6;;;;4876:46;;;;;-1:-1:-1;;;4876:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;35385:153;35524:6;35491:15;-1:-1:-1;;35491:29:0;35490:40;;35385:153::o;54684:1839::-;26634:4;54926:13;:31;;54918:82;;;;-1:-1:-1;;;54918:82:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55013:19;55035:54;55058:15;55075:13;55035:22;:54::i;:::-;55013:76;;55100:22;55178:1;:12;;;27843:3;55144:11;55126:15;:29;55125:50;:65;;;;;;;-1:-1:-1;55288:19:0;55280:87;;;;-1:-1:-1;;;55280:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55712:20;24243:1;55735;:13;;;:37;:111;;55829:1;:13;;;55845:1;55829:17;55735:111;;;55788:25;55735:111;55909:16;;;55907:18;;;;;;;;;;55971:10;-1:-1:-1;55960:22:0;;;:10;:22;;;;;55712:134;;-1:-1:-1;55907:18:0;55936:223;;55907:18;56022:15;56052:14;55712:134;56108:13;56136:12;55936:9;:223::i;:::-;56172:89;56188:10;56200:15;56217:14;56233:13;56248:12;56172:15;:89::i;:::-;-1:-1:-1;;56354:23:0;;;:41;;;;;;;-1:-1:-1;;56476:39:0;;;;;;;;-1:-1:-1;54684:1839:0:o;16020:348::-;-1:-1:-1;;;;;16096:21:0;;16088:67;;;;-1:-1:-1;;;16088:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;16189:68;16212:6;16189:68;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;16189:18:0;;:9;:18;;;;;;;;;;;;:68;;:22;:68;:::i;:::-;-1:-1:-1;;;;;16168:18:0;;:9;:18;;;;;;;;;;:89;16283:12;;:24;;16300:6;16283:24;:16;:24;:::i;:::-;16268:12;:39;16323:37;;;;;;;;16349:1;;-1:-1:-1;;;;;16323:37:0;;;;;;;;;;;;16020:348;;:::o;67661:633::-;67906:380;;;67981:15;67906:380;67966:32;;;68019:35;68052:2;68019:35;;;;67966:89;-1:-1:-1;;;68108:3:0;68076:35;;;;67966:146;-1:-1:-1;;;;;;68160:3:0;68133:30;;;;67966:198;67906:380;;-1:-1:-1;;;;;68179:24:0;;67906:380;;;;;;68265:10;;67906:380;;;;-1:-1:-1;;;;;67906:380:0;;;;;;;;;;;;67661:633;;;;;;:::o;39375:451::-;39495:11;;39479:27;;39545:16;;;;39600:15;;;;39652:13;;;;39703:14;;;;39756:15;;;;39803;;;;;-1:-1:-1;;39479:27:0;;;;;;;;;;;-1:-1:-1;;39517:45:0;-1:-1:-1;;;;;;;;39517:45:0;;;;;-1:-1:-1;;;;39573:43:0;-1:-1:-1;;;39573:43:0;;;;;;;;;-1:-1:-1;;;;39627:39:0;-1:-1:-1;;;39627:39:0;;;;;;-1:-1:-1;;;;39677:41:0;-1:-1:-1;;;39677:41:0;;;;;;;;;;;-1:-1:-1;;;;39729:43:0;-1:-1:-1;;;39729:43:0;;;;;;;;;;;;-1:-1:-1;;;;39783:35:0;-1:-1:-1;;;39783:35:0;;;;;;;;;;39375:451::o;76789:1603::-;77717:8;;76929:4;;25453:49;;77717:5;;76929:4;;77717:8;;;;;;;;;;77709:17;;:41;77755:1;77708:48;77700:79;;;;;-1:-1:-1;;;77700:79:0;;;;;;;;;;;;-1:-1:-1;;;77700:79:0;;;;;;;;;;;;;;;77807:1;77790:149;77814:5;:12;77810:1;:16;77790:149;;;77865:8;;25453:49;;77865:5;;77871:1;;77865:8;;;;;;;;;;;;77857:17;;:41;77903:1;77856:48;;77848:79;;;;;-1:-1:-1;;;77848:79:0;;;;;;;;;;;;-1:-1:-1;;;77848:79:0;;;;;;;;;;;;;;;77828:3;;77790:149;;;-1:-1:-1;;;;;;;78243:16:0;;:39;;78346:38;78243:39;78378:5;78346:19;:38::i;46450:991::-;46595:9;46574:1;:17;;;:30;46570:107;;46659:7;;46570:107;46689:25;;:::i;:::-;46765:20;;46749:13;:11;:13::i;:::-;:36;46725:60;;46812:17;;;;46842:35;46812:1;46725:2;46812:17;46842:23;:35::i;:::-;46976:23;;;;:28;46972:149;;47044:23;;;;;47021:19;;;:46;;;;;;;-1:-1:-1;47082:27:0;;46972:149;47140:5;;:17;;;47133:88;;;47174:35;47198:1;47201:2;47205:3;47174:23;:35::i;:::-;47133:88;;;47233:58;47254:1;:17;;;47273:3;47278:12;47233:20;:58::i;:::-;47302:17;;;:23;;;47342:19;;;;:24;47338:96;;47383:39;22880:42;47402:2;:19;;;47383:5;:39::i;85613:702::-;85859:26;85903:21;;:::i;:::-;85935:29;;:::i;:::-;85975:26;85988:1;85991:9;85975:12;:26::i;:::-;86035:195;86064:1;86080:11;86106;86132:7;86154:10;86179:13;86207:12;86035:14;:195::i;:::-;86014:216;;86243:26;86256:1;86259:9;86243:12;:26::i;:::-;-1:-1:-1;;85613:702:0;;;;;;;;:::o;103508:622::-;103581:17;24243:1;103620:8;:33;103616:480;;103670:21;;:::i;:::-;103706:29;;:::i;:::-;103750:26;103763:1;103766:9;103750:12;:26::i;:::-;103793:23;103814:1;103793:20;:23::i;:::-;103833:17;103853:19;;;:9;:19;;;;;:45;-1:-1:-1;;;103853:45:0;;;;24456:21;23385:3;103925:30;;:49;103913:61;;103991:26;104004:1;104007:9;103991:12;:26::i;:::-;103616:480;;;;;;-1:-1:-1;24123:36:0;103508:622;;;:::o;104610:460::-;105039:12;-1:-1:-1;;;;;104795:267:0;105014:10;23875:2;104973:8;:37;;104972:52;104947:10;-1:-1:-1;;;;;104795:267:0;;104929:2;104915:8;-1:-1:-1;;;;;104900:25:0;:31;;104862:15;104847:32;;:85;104795:267;;;;;;;;;;;;;;;;;;104610:460;;;;:::o;104138:464::-;104571:12;-1:-1:-1;;;;;104325:269:0;104546:10;23875:2;104505:8;:37;;104504:52;104479:10;-1:-1:-1;;;;;104325:269:0;;104461:2;104446:9;-1:-1:-1;;;;;104431:26:0;:32;;104393:15;104378:32;;:86;104325:269;;;;;;;;;;;;;;;;;;104138:464;;;;:::o;78854:1284::-;78995:12;;28847:6;79051:38;;79050:117;;79147:20;;;;;;;;;;;;;-1:-1:-1;;;79147:20:0;;;79050:117;;;79111:20;;;;;;;;;;;;;-1:-1:-1;;;79111:20:0;;;79050:117;79025:142;-1:-1:-1;29126:6:0;79208:42;;79207:49;79269:20;79292:54;79313:11;79207:49;79292:20;:54::i;:::-;79269:77;-1:-1:-1;79363:19:0;79359:290;;28430:2;-1:-1:-1;;;28143:2:0;28221:1;28198:24;79529:9;:16;79523:45;79587:9;79615:7;79406:231;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;79406:231:0;;;;;;;;;;-1:-1:-1;79406:231:0;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;79406:231:0;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;79406:231:0;;;79399:238;;;;;;;79359:290;79694:35;;;28343:29;79694:35;;;;;;;;;79661:30;;79694:35;;;21:6:-1;;104:10;79694:35:0;87:34:-1;135:17;;-1:-1;;79661:68:0;-1:-1:-1;79742:80:0;79661:68;79780:14;28283:2;79742:18;:80::i;:::-;79953:16;;79842:288;;-1:-1:-1;;;79842:288:0;;;;;;;-1:-1:-1;;;79842:288:0;;;;;;79947:76;;;;79842:288;;;;-1:-1:-1;;;;;;79842:288:0;;;;;;;28430:2;;79910:22;79947:76;;79953:16;;80062:7;;80102:17;;79842:288;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;79842:288:0;;;;;;;;;;-1:-1:-1;79842:288:0;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;79842:288:0;;;;;;;-1:-1:-1;;;79842:288:0;;;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;79842:288:0;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;79842:288:0;;;79835:295;;;;;;78854:1284;;;;;:::o;81661:164::-;81747:7;81779:38;81803:12;81810:4;81803:12;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;81803:12:0;;;;;;;-1:-1:-1;263:2;;-1:-1;;81803:12:0;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;81803:12:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;81803:12:0;81786:30;;;81803:12;81786:30;;;;;;;;;26:21:-1;;;22:32;;6:49;;81786:30:0;;;;;;;81779:38;;81786:30;;;;81779:38;;;;;81786:30;81779:38;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;81779:38:0;;;;;;;-1:-1:-1;263:2;;-1:-1;;81779:38:0;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;81779:38:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;81779:38:0;;81661:164;-1:-1:-1;;81661:164:0:o;42024:484::-;42251:21;42245:28;;;;;;25652;25597:2;42309:22;;;42308:44;;;42389:21;;42024:484::o;69771:795::-;69862:4;69902;69862;69919:524;69943:5;:12;69939:1;:16;69919:524;;;69977:20;70000:5;70006:1;70000:8;;;;;;;;;;;;;;69977:31;;70044:12;70029;:27;70025:407;;;70198:12;70212;70181:44;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;70181:44:0;;;70171:55;;;;;;70156:70;;70025:407;;;70388:12;70402;70371:44;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;70371:44:0;;;70361:55;;;;;;70346:70;;70025:407;-1:-1:-1;69957:3:0;;69919:524;;;-1:-1:-1;70538:20:0;;;;69771:795;-1:-1:-1;;;69771:795:0:o;36484:772::-;36662:20;;36631:51;;36727:23;;;;;36693:31;;;:57;36784:12;;;;;36761:20;;;:35;36838:20;;;;;36807:28;;;:51;36911:17;;;;;36883:25;;;:45;36969:19;;;;;36939:27;;;:49;37026:16;;;;;36999:43;;:24;;;:43;37089:25;;;;;37053:33;;;:61;37159:23;;;;;37125:31;;;:57;37226:22;;;;;37193:30;;:55;36484:772::o;62499:2201::-;62754:14;;62826:27;;;62981:1;62976;62958:19;;62957:25;26717:2;62997:36;;62993:105;;;-1:-1:-1;26717:2:0;62993:105;63114:15;63110:309;;63217:16;63236:62;63262:1;63265:16;63283:14;63236:25;:62::i;:::-;63323:22;;;;;-1:-1:-1;63360:24:0;;-1:-1:-1;;63360:24:0;63110:309;63449:10;63435:11;:24;63431:723;;;63840:28;;;63893:70;63912:1;63915:16;63840:14;:28;63893:18;:70::i;:::-;63883:80;;63980:13;63996:68;64015:1;64018:16;64036:13;64051:12;63996:18;:68::i;:::-;64088:15;;;-1:-1:-1;64118:24:0;;-1:-1:-1;;;;64118:24:0;63431:723;64217:69;64236:1;64239:16;64257:14;64273:12;64217:18;:69::i;:::-;64208:78;;64318:10;64303:11;:25;64299:359;;;64355:6;64345:16;;64299:359;;;64636:10;64622:11;64613:6;:20;:33;;;;;;64603:43;;64299:359;-1:-1:-1;;62499:2201:0;;;;;;;;;:::o;56920:863::-;57123:14;57174:8;57155:189;57190:6;57184:3;:12;57155:189;;;57298:14;;;;:9;:14;;;;;:34;-1:-1:-1;;;;;;;;57298:34:0;;;;;57230:29;:48;;57298:34;57230:102;;;;;57220:112;;;;;57198:5;;57155:189;;;-1:-1:-1;24832:23:0;57452;;;;;:47;;-1:-1:-1;24832:23:0;57479:20;;57452:47;57448:304;;;24832:23;57516:19;57623:22;;;:9;:22;;;:42;-1:-1:-1;;;57623:42:0;;-1:-1:-1;;;;;57623:42:0;57587:16;23385:3;23439;;23496:33;:47;57538:1;:25;;;:46;:65;:127;;;;;;57516:149;;57706:34;57725:1;57728:11;57706:18;:34::i;:::-;57692:48;57682:58;56920:863;;;;;;:::o;64708:651::-;64925:7;65031:32;;;26840:28;65031:58;65104:34;;;65100:75;;65162:1;65155:8;;;;;65100:75;26991:28;65291:33;;;65273:52;;:78;;64708:651;-1:-1:-1;;;;;;64708:651:0:o;57979:2845::-;58108:19;;60395:1;60379:17;;60375:132;;;27342:33;60431:29;;;:64;;27342:33;60431:64;;;60479:1;60463:13;:17;60431:64;60413:82;;60375:132;60519:26;27628:28;60548:33;;;:94;;27628:28;60548:94;;;60597:15;60548:94;27695:40;60669:21;;27265:29;60693:24;;60669:48;;-1:-1:-1;60519:123:0;-1:-1:-1;60775:9:0;60742:29;;;:43;;57979:2845;-1:-1:-1;;;;;57979:2845:0:o;69029:286::-;69289:7;69132:175;;;69271:2;69256:9;69241:26;;:32;;69203:15;69188:32;;:86;69132:175;;;;;;;;;;;;;;;;;;69029:286;;:::o;41592:424::-;41859:21;41834:47;;;;25597:2;41897:42;;;;41892:47;41950:28;;41592:424::o;39834:631::-;40156:290;;;;;;;;;;;;;;-1:-1:-1;;;;;40156:290:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;40156:290:0;;;;;;;;;;;;;;;27:10:-1;;39:1;23:18;;45:23;;40124:333:0;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;40124:333:0;;;;;;;;;;;-1:-1:-1;;40124:333:0;-1:-1:-1;;;40124:333:0;;;;;;;;;;;-1:-1:-1;;;;40124:333:0;-1:-1:-1;;;40124:333:0;;;;;;;;;;;;-1:-1:-1;;;;40124:333:0;-1:-1:-1;;;40124:333:0;;;;;;;;;;;-1:-1:-1;;;;40124:333:0;-1:-1:-1;;;40124:333:0;;;;;;;;;;;-1:-1:-1;;;;40124:333:0;-1:-1:-1;;;40124:333:0;;;;;;-1:-1:-1;;;;40124:333:0;-1:-1:-1;;;40124:333:0;;;;;;;;;;;;;39834:631::o;67072:581::-;67284:361;;;67602:10;67284:361;67558:11;:28;;67585:1;67558:28;;;-1:-1:-1;;;67558:28:0;-1:-1:-1;;;;;67335:252:0;67533:3;67517:10;67502:27;;:34;;67477:3;67460:11;-1:-1:-1;;;;;67445:28:0;:35;;67421:2;67403:12;-1:-1:-1;;;;;67388:29:0;:35;;67350:15;67335:32;;:89;:146;:202;:252;67284:361;;;;;;;;;;;;;;;;;;67072:581;;;;;:::o;5226:136::-;5284:7;5311:43;5315:1;5318;5311:43;;;;;;;;;;;;;;;;;:3;:43::i;46048:394::-;46177:27;46193:1;46196:2;46200:3;46177:15;:27::i;:::-;46256:15;;;;;46217:14;;;;:9;:14;;;;;:55;;46327:19;;;;46408:25;;;;;-1:-1:-1;;46217:55:0;;;-1:-1:-1;;;;;46217:55:0;;;;-1:-1:-1;;;;46283:64:0;-1:-1:-1;;;46283:64:0;;;;;;;;;;;;-1:-1:-1;;;;46358:76:0;-1:-1:-1;;;46358:76:0;;;;;;;;;;;46048:394::o;47449:407::-;47827:10;47570:278;47783:12;:28;;47810:1;47783:28;;;-1:-1:-1;;;47783:28:0;47626:186;;47759:2;47747:6;47732:23;;:29;;47708:2;47694:8;47679:25;;:31;;47641:15;47626:32;;:85;:136;:186;47570:278;;;;;;;;;;;;;;;;;;47449:407;;;:::o;86934:1714::-;87208:26;24243:1;87311;:13;;;:38;;87303:87;;;;-1:-1:-1;;;87303:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87409:13;;;;24564:40;-1:-1:-1;87401:74:0;;;;;-1:-1:-1;;;87401:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;87541:23;87562:1;87541:20;:23::i;:::-;26119:8;87627:1;:22;;;:49;87605:129;;;;;-1:-1:-1;;;87605:129:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;87748:19;87769:21;87792:24;87820:69;87851:1;87867:11;87820:16;:69::i;:::-;87962:22;;;:24;;;;;;87747:142;;-1:-1:-1;87747:142:0;-1:-1:-1;87747:142:0;-1:-1:-1;88020:235:0;88048:11;88074:7;88096:10;88121:11;87747:142;;;88232:12;88020:13;:235::i;:::-;87999:256;-1:-1:-1;88405:3:0;26434:2;88357:45;;:51;88419:52;88431:1;88357:51;88451:13;88466:4;88419:11;:52::i;:::-;88546:56;88552:11;88586:15;88565:18;:36;88546:5;:56::i;:::-;-1:-1:-1;;;;86934:1714:0;;;;;;;;;:::o;80146:736::-;80313:30;;;28198:24;80313:30;;;80265:20;80313:30;;;;;;;;;21:6:-1;;104:10;80313:30:0;87:34:-1;135:17;;-1:-1;;80303:40:0;-1:-1:-1;80354:73:0;80303:40;-1:-1:-1;;;;;;80390:13:0;;;;80382:22;28143:2;80354:18;:73::i;:::-;80444:19;80440:408;;;80502:18;;;;;;80480:19;;80572:265;28143:2;80592:24;;80572:265;;;80642:7;80658:11;80670:1;80658:14;;;;;;;80730:8;;;;80658:14;;;;-1:-1:-1;80694:53:0;;80721:7;;80745:1;80740:6;;;80694:26;:53::i;:::-;80766:55;80793:7;80802:8;;;;;;80812:1;80816:4;80812:8;80766:26;:55::i;:::-;-1:-1:-1;80618:3:0;;80572:265;;;;80440:408;;;80146:736;;;;:::o;81172:362::-;81299:14;;81330:197;81354:7;81350:1;:11;81330:197;;;81383:7;81399:4;81404:1;81399:7;;;;;;;;;-1:-1:-1;;;;81459:1:0;81454:6;;;81393:14;81443:18;;;;;;;;;;;81424:6;81431:8;;;;;;81424:16;;;;;;;;;;;:37;-1:-1:-1;;;;;81424:37:0;;;;;;;;-1:-1:-1;;;;81510:4:0;81506:8;;81495:20;;;;;;;;;;81476:6;81483:8;;;;;;81476:16;;;;;;;;;;;:39;-1:-1:-1;;;;;81476:39:0;;;;;;;;-1:-1:-1;;81363:3:0;;81330:197;;42791:979;42938:14;43028:24;;:::i;:::-;43063:30;43085:1;43088:4;43063:21;:30::i;:::-;43106:25;;:::i;:::-;43182:20;;43166:13;:11;:13::i;:::-;:36;43142:60;;43215:30;43231:4;43142:2;43241:3;43215:15;:30::i;:::-;43342:22;;;:42;;;;;;;;43406:15;;;;:34;;43342:42;43406:59;;;;;;-1:-1:-1;24832:23:0;43482:18;;43478:259;;;43627:22;;;;43539:28;;;;43517:19;;43627:22;43539:68;;23385:3;43539:68;43627:22;43539:110;;;;;43517:132;;43688:37;43707:4;43713:11;43688:18;:37::i;:::-;43674:51;43664:61;;;;;43478:259;-1:-1:-1;;42791:979:0;;;;;:::o;43778:694::-;43895:7;44093:13;26119:8;44118:1;:22;;;44109:6;:31;:58;;;;;;44093:74;;44358:12;25980:15;44382:1;:23;;;44373:6;:32;:59;;;;;;44452:12;;;;;43778:694;-1:-1:-1;;;;43778:694:0:o;44480:1560::-;45407:21;;45439:9;;45431:5;45407:29;:41;45389:15;;;:59;24564:40;45465:25;;45461:424;;;45529:25;;;;45507:19;;24456:21;;23385:3;45529:46;:65;45507:87;;45611:19;45647:52;45666:1;45687:11;45669:2;:15;;;:29;45647:18;:52::i;:::-;45714:19;;;:34;;45633:66;;;45714:34;;;;;45763:36;;;;;;45857:15;;;;45633:66;;-1:-1:-1;45835:38:0;;45854:1;;45835:18;:38::i;:::-;45816:15;;;:57;;;;;;;-1:-1:-1;;45461:424:0;45901:20;;;;:25;45897:136;;45962:20;;;;;45943:15;;;:39;;;;;;;-1:-1:-1;45997:24:0;;44480:1560;;;:::o;92161:1003::-;92280:19;92301:21;92324:24;92423:30;92441:11;92423:17;:30::i;:::-;92409:44;;25980:15;92512:11;92486:1;:23;;;:37;:65;;92464:146;;;;;-1:-1:-1;;;92464:146:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;92621:23;;;:38;;;;;;92718:13;;;;24564:40;92696:35;92800:44;92648:11;92696:35;92800:16;:44::i;:::-;92855:25;;;:40;;;;;;;;-1:-1:-1;23385:3:0;92983:32;;;-1:-1:-1;93045:45:0;92983:32;93076:13;93045:15;:45::i;:::-;93026:64;-1:-1:-1;;92161:1003:0;;;;;:::o;88656:2209::-;89027:32;;;89043:16;-1:-1:-1;;;;;89133:26:0;;89129:1641;;89207:238;89236:11;89266:7;89292:10;89321:11;89351;89381:18;89418:12;89207:10;:238::i;:::-;89129:1641;;;89605:2;89584:23;;89624:41;;;;89804:1;89783:22;;89843:41;;;89822:62;;;;;-1:-1:-1;;;;;89905:27:0;;;;;;;89901:858;;;89990:41;;;;90050:270;90083:11;90117:7;90147:10;90180:11;90214;89990:41;90289:12;90050:10;:270::i;:::-;89901:858;;;90414:270;90447:11;90481:7;90511:10;90544:11;90578;90612:18;90653:12;90414:10;:270::i;:::-;90703:40;90709:12;90723:19;90703:5;:40::i;:::-;89129:1641;;;90782:37;22880:42;90801:17;90782:5;:37::i;:::-;-1:-1:-1;88656:2209:0;;;;;;;;;;:::o;80890:274::-;81029:9;81041:7;81049:6;81041:15;;;;;;;;;;;;-1:-1:-1;;;;;;81041:15:0;;-1:-1:-1;;;;81073:9:0;;;;;:28;;;81100:1;81086:10;:15;;;;81073:28;81069:88;;;81136:2;81141:4;81136:9;;;81118:7;81126:6;81118:15;;;;;;;;;;;:27;-1:-1:-1;;;;;81118:27:0;;;;;;;;;80890:274;;;;:::o;93352:1846::-;93449:7;93492:6;93478:11;:20;93474:118;;;-1:-1:-1;93569:11:0;93562:18;;93474:118;93621:7;93606:11;:22;93602:143;;-1:-1:-1;93732:1:0;93718:15;;93711:22;;93602:143;95183:7;95168:11;95158:7;:21;95143:11;:37;:47;;;;;;;93352:1846;-1:-1:-1;;93352:1846:0:o;95566:457::-;95685:7;24456:21;95969:27;;;:46;;;95566:457;-1:-1:-1;;;95566:457:0:o;96325:782::-;96445:7;97072:26;-1:-1:-1;;97050:17:0;;97033:35;;:66;;90873:1280;91144:426;;;91190:32;91205:15;91190:32;91243:34;91275:2;91243:34;;;;91190:88;-1:-1:-1;;;91331:2:0;91299:34;;;;91190:144;-1:-1:-1;;;91378:3:0;91355:26;;;;91190:192;-1:-1:-1;;;91437:3:0;91403:37;;;;91190:251;91144:426;;91472:10;91144:426;;;;;;-1:-1:-1;;;;;91144:426:0;;;;;;;;-1:-1:-1;;;;;;91144:426:0;;;;;;;;;;;;;;-1:-1:-1;;;;;91587:25:0;;91602:10;91587:25;91583:64;;;91629:7;;91583:64;92124:10;-1:-1:-1;;;;;91664:481:0;;91854:3;91837:11;91822:28;;:35;;91798:2;91785:7;91777:16;;-1:-1:-1;;;;;91769:25:0;:31;;91731:15;91716:32;;:85;:142;92002:3;91987:10;91979:19;;:26;;91955:2;91938:11;-1:-1:-1;;;;;91922:29:0;:35;;91888:11;91873:28;;:85;:133;92106:2;92088:12;-1:-1:-1;;;;;92072:30:0;:36;;92036:13;-1:-1:-1;;;;;92021:30:0;:88;91664:481;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90873:1280;;;;;;;;:::o;105077:626::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;105077:626:0;;;-1:-1:-1;;105077:626:0:o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;105077:626:0;;;-1:-1:-1;;105077:626:0:o;:::-;;;;;;;;;;;;;;;;;;;;;;;;:::o

Swarm Source

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