ETH Price: $3,555.86 (-0.17%)
 

Overview

Max Total Supply

210,000,000 JELLI

Holders

65,137

Market

Price

$0.00 @ 0.000000 ETH

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 9 Decimals)

Balance
0.07 JELLI

Value
$0.00
0xdfd315c0304bc2a459a88b47380de0f2f89e448f
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
Jelli

Compiler Version
v0.8.22+commit.4fc1097e

Optimization Enabled:
Yes with 200 runs

Other Settings:
london EvmVersion
File 1 of 9 : Jelli.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "./Erc20.sol";
import "./PoolCreatableErc20i.sol";
import "../Generator.sol";

library ExtraSeedLibrary {
    function extra(address account) internal pure returns (uint256) {
        return uint(keccak256(abi.encode(account)));
    }

    function seed_data(
        address account,
        uint seed
    ) internal pure returns (SeedData memory) {
        return SeedData(seed, extra(account));
    }
}

abstract contract Medusas is PoolCreatableErc20i {
    using ExtraSeedLibrary for address;
    mapping(address owner => uint) _counts;
    mapping(address owner => mapping(uint index => SeedData seed_data)) _ownedTokens;
    mapping(address owner => mapping(uint tokenId => uint)) _ownedTokensIndex;
    mapping(address owner => mapping(uint => bool)) _owns;
    mapping(address owner => SeedData seed_data) _polyps;
    mapping(uint index => address user) _holderList;
    mapping(address user => uint index) _holderListIndexes;
    uint _medusasTotalCount;
    uint _holdersCount;
    uint _polypsTotalCount;
    uint blank1; // delete

    event OnMedusaTransfer(
        address indexed from,
        address indexed to,
        SeedData seed_data
    );
    event OnPolypsGrow(address indexed holder, SeedData seed_data);
    event OnPolypsShrink(address indexed holder, SeedData seed_data);

    constructor() PoolCreatableErc20i("jelli", "JELLI", msg.sender) {}

    modifier holder_calculate(address acc1, address acc2) {
        bool before1 = _isHolder(acc1);
        bool before2 = _isHolder(acc2);
        _;
        bool after1 = _isHolder(acc1);
        bool after2 = _isHolder(acc2);
        if (!before1 && after1) _addHolder(acc1);
        if (before1 && !after1) _removeHolder(acc1);
        if (!before2 && after2) _addHolder(acc2);
        if (before2 && !after2) _removeHolder(acc2);
    }

    function _isHolder(address account) private view returns (bool) {
        if (
            account == address(this) ||
            account == _pool ||
            account == address(0)
        ) return false;

        return (_polyps[account].seed + this.medusaCount(account)) > 0;
    }

    function trySeedTransfer(
        address from,
        address to,
        uint amount
    ) internal holder_calculate(from, to) {
        if (from == address(this)) return;
        uint seed = amount / (10 ** decimals());

        if (seed > 0 && from != _pool && to != _pool) {
            // transfer growing medusa
            if (_polyps[from].seed == seed) {
                SeedData memory data = _polyps[from];
                _removeSeedCount(from, seed);
                _addTokenToOwnerEnumeration(to, data);
                emit OnMedusaTransfer(from, to, data);
                return;
            }

            // transfer collected medusa
            if (_owns[from][seed] && !_owns[to][seed]) {
                SeedData memory data = _ownedTokens[from][
                    _ownedTokensIndex[from][seed]
                ];
                _removeTokenFromOwnerEnumeration(from, seed);
                _addTokenToOwnerEnumeration(to, data);
                emit OnMedusaTransfer(from, to, data);
                return;
            }
        }

        // transfer polyps
        uint lastBalanceFromSeed = _balances[from] / (10 ** decimals());
        uint newBalanceFromSeed = (_balances[from] - amount) /
            (10 ** decimals());
        _removeSeedCount(from, lastBalanceFromSeed - newBalanceFromSeed);
        _addSeedCount(to, seed);
    }

    function _addHolder(address account) private {
        _holderList[_holdersCount] = account;
        _holderListIndexes[account] = _holdersCount;
        ++_holdersCount;
    }

    function _removeHolder(address account) private {
        if (_holdersCount == 0) return;
        --_holdersCount;
        uint removingIndex = _holderListIndexes[account];
        _holderList[removingIndex] = _holderList[_holdersCount];
        delete _holderList[_holdersCount];
        delete _holderListIndexes[account];
    }

    function getHolderByIndex(uint index) public view returns (address) {
        return _holderList[index];
    }

    function getHoldersList(
        uint startIndex,
        uint count
    ) public view returns (address[] memory) {
        address[] memory holders = new address[](count);
        for (uint i = 0; i < count; ++i)
            holders[i] = getHolderByIndex(startIndex + i);
        return holders;
    }

    function _addSeedCount(address account, uint seed) private {
        if (seed == 0) return;
        if (account == _pool) return;
        SeedData memory last = _polyps[account];

        _polyps[account].seed += seed;
        _polyps[account].extra = account.extra();

        if (last.seed == 0 && _polyps[account].seed > 0) ++_polypsTotalCount;

        emit OnPolypsGrow(account, _polyps[account]);
    }

    function _removeSeedCount(address account, uint seed) private {
        if (seed == 0) return;
        if (account == _pool) return;
        SeedData memory lastPolyps = _polyps[account];
        if (_polyps[account].seed >= seed) {
            _polyps[account].seed -= seed;
            if (lastPolyps.seed > 0 && _polyps[account].seed == 0)
                --_polypsTotalCount;
            emit OnPolypsShrink(account, _polyps[account]);
            return;
        }
        uint seedRemains = seed - _polyps[account].seed;
        _polyps[account].seed = 0;

        // remove medusas
        uint count = _counts[account];
        uint removed;
        for (uint i = 0; i < count && removed < seedRemains; ++i) {
            removed += _removeFirstTokenFromOwner(account);
        }

        if (removed > seedRemains)
            _polyps[account].seed += removed - seedRemains;
        if (lastPolyps.seed > 0 && _polyps[account].seed == 0)
            --_polypsTotalCount;
        emit OnPolypsShrink(account, _polyps[account]);
    }

    function _addTokenToOwnerEnumeration(
        address to,
        SeedData memory data
    ) private {
        if (to == _pool) return;
        ++_counts[to];
        ++_medusasTotalCount;
        uint length = _counts[to] - 1;
        _ownedTokens[to][length] = data;
        _ownedTokensIndex[to][data.seed] = length;
        _owns[to][data.seed] = true;
    }

    function _removeTokenFromOwnerEnumeration(address from, uint seed) private {
        if (from == _pool) return;
        --_counts[from];
        --_medusasTotalCount;
        _owns[from][seed] = false;
        uint lastTokenIndex = _counts[from];
        uint tokenIndex = _ownedTokensIndex[from][seed];
        SeedData memory data = _ownedTokens[from][tokenIndex];

        // When the token to delete is the last token, the swap operation is unnecessary
        if (tokenIndex != lastTokenIndex) {
            SeedData memory lastTokenId = _ownedTokens[from][lastTokenIndex];

            _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
            _ownedTokensIndex[from][lastTokenId.seed] = tokenIndex; // Update the moved token's index
        }

        delete _ownedTokensIndex[from][data.seed];
        delete _ownedTokens[from][lastTokenIndex];
    }

    function _removeFirstTokenFromOwner(address owner) private returns (uint) {
        uint count = _counts[owner];
        if (count == 0) return 0;
        uint seed = _ownedTokens[owner][0].seed;
        _removeTokenFromOwnerEnumeration(owner, seed);
        return seed;
    }

    function isOwnerOf(address owner, uint seed) external view returns (bool) {
        return _owns[owner][seed];
    }

    function polypsDegree(
        address owner
    ) external view returns (SeedData memory data) {
        return _polyps[owner];
    }

    function medusaCount(address owner) external view returns (uint) {
        return _counts[owner];
    }

    function medusaOfOwnerByIndex(
        address owner,
        uint index
    ) external view returns (SeedData memory data) {
        return _ownedTokens[owner][index];
    }

    function medusasTotalCount() external view returns (uint) {
        return _medusasTotalCount;
    }

    function holdersCount() external view returns (uint) {
        return _holdersCount;
    }

    function polypsTotalCount() external view returns (uint) {
        return _polypsTotalCount;
    }
}

contract Jelli is Medusas, Generator, ReentrancyGuard {
    uint constant _startTotalSupply = 210e6 * (10 ** _decimals);
    uint constant _startMaxBuyCount = (_startTotalSupply * 3) / 1000;  
    uint constant _addMaxBuyPercentPerSec = 5; // 100%=_addMaxBuyPrecesion add 0.005%/second
    uint constant _addMaxBuyPrecesion = 100000;

    constructor() {
        _mint(msg.sender, _startTotalSupply);
    }

    modifier maxBuyLimit(uint256 amount) {
        require(amount <= maxBuy(), "max buy limit");
        // require(balanceOf(msg.sender) + amount <= maxBuy(), "max buy limit");
        _;
    }

    function maxBuy() public view returns (uint256) {
        if (!isStarted()) return _startTotalSupply;
        uint256 count = _startMaxBuyCount +
            (_startTotalSupply *
                (block.timestamp - _startTime) *
                _addMaxBuyPercentPerSec) /
            _addMaxBuyPrecesion;
        if (count > _startTotalSupply) count = _startTotalSupply;
        return count;
    }

    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal override {
        if (isStarted()) {
            trySeedTransfer(from, to, amount);
        } else {
            require(from == _owner || to == _owner, "not started");
        }

        // allow burning
        if (to == address(0)) {
            _burn(from, amount);
            return;
        }

        // system transfers
        if (from == address(this)) {
            super._transfer(from, to, amount);
            return;
        }

        if (_feeLocked) {
            super._transfer(from, to, amount);
            return;
        } else {
            if (from == _pool) {
                buy(to, amount);
                return;
            }
        }

        super._transfer(from, to, amount);
    }

    function buy(
        address to,
        uint256 amount
    ) private maxBuyLimit(amount) lockFee {
        super._transfer(_pool, to, amount);
    }

    function burnCount() public view returns (uint256) {
        return _startTotalSupply - totalSupply();
    }
}

File 2 of 9 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
 * consider using {ReentrancyGuardTransient} instead.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}

File 3 of 9 : Erc20.sol
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/utils/Context.sol";

contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) internal _balances;

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

    uint256 internal _totalSupply;
    uint8 internal constant _decimals = 9;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the default value returned by this function, unless
     * it's overridden.
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public pure returns (uint8) {
        return _decimals;
    }

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

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

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

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

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(
        address spender,
        uint256 amount
    ) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, 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}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

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

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(
        address spender,
        uint256 subtractedValue
    ) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(
            currentAllowance >= subtractedValue,
            "ERC20: decreased allowance below zero"
        );
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `from` to `to`.
     *
     * This 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:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");

        uint256 fromBalance = _balances[from];
        require(
            fromBalance >= amount,
            "ERC20: transfer amount exceeds balance"
        );
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, 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:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);
    }

    /**
     * @dev Erases `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

        emit Transfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(
                currentAllowance >= amount,
                "ERC20: insufficient allowance"
            );
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }
}

File 4 of 9 : PoolCreatableErc20i.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import "./Erc20.sol";

abstract contract PoolCreatableErc20i is ERC20 {
    address internal _pool;
    uint256 internal _startTime;
    bool internal _feeLocked;
    address immutable _pairCreator;

    constructor(
        string memory name_,
        string memory symbol_,
        address pairCreator
    ) ERC20(name_, symbol_) {
        _pairCreator = pairCreator;
    }

    modifier lockFee() {
        _feeLocked = true;
        _;
        _feeLocked = false;
    }

    function launch(address poolAddress) external payable {
        require(msg.sender == _pairCreator);
        require(!isStarted());
        _pool = poolAddress;
        _startTime = block.timestamp;
    }

    function isStarted() internal view returns (bool) {
        return _pool != address(0);
    }

    function pool() external view returns (address) {
        return _pool;
    }
}

File 5 of 9 : Generator.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "./lib/Ownable.sol";

uint constant levelsCount = 5;
uint constant bcgroundsCount = 6;
uint constant groundsCount = 1;
uint8 constant pixelsCount = 24;
uint constant seedLevel1 = 1000; // not actually used 
uint constant seedLevel2 = 21000; // 0.01%
uint constant seedLevel3 = 105000; // 0.05%
uint constant seedLevel4 = 420000; // 0.2%
uint constant seedLevel5 = 1050000; // 0.5%                         




struct MedusaData {
    uint lvl;
    string background;
    string background2;
    bool hasGround;
    uint ground;
    string groundColor;
    bool hasBubble;
    uint bubble;
    string bubbleColor;
    bool hasWeed;
    uint weed;
    string weedColor;
    uint mirrorTime;
    uint bobTime;
    uint tentacle;
    string tentacleColor;
    uint bell;
    string bellColor;
    // bool hasDots;
    // string dotsColor;
}

struct Rect {
    uint8 x;
    uint8 y;
    uint8 width;
    uint8 height;
}

struct FileData {
    uint lvl;
    uint file;
    Rect[] rects;
}

struct ColorsData {
    string[] lvl0;
    string[] lvl1;
    string[] lvl2;
    string[] lvl3;
    string[] lvl4;
}

struct SeedData {
    uint seed;
    uint extra;
}

struct Rand {
    uint seed;
    uint nonce;
    uint extra;
}

library RandLib {
    function next(Rand memory rnd) internal pure returns (uint) {
        return
            uint(
                keccak256(
                    abi.encodePacked(rnd.seed + rnd.nonce++ - 1, rnd.extra)
                )
            );
    }

    function lvl(Rand memory rnd) internal pure returns (uint) {
        if (rnd.seed < seedLevel1) return 0;
        if (rnd.seed < seedLevel2) return 1;
        if (rnd.seed < seedLevel3) return 2;
        if (rnd.seed < seedLevel4) return 3;
        if (rnd.seed < seedLevel5) return 4;
        return 5;
    }

    function random(
        string[] memory data,
        Rand memory rnd
    ) internal pure returns (string memory) {
        return data[randomIndex(data, rnd)];
    }

    function randomIndex(
        string[] memory data,
        Rand memory rnd
    ) internal pure returns (uint) {
        return next(rnd) % data.length;
    }
}

library LayersLib {
    function setLayers(
        mapping(uint => mapping(uint => Rect[])) storage rects,
        FileData[] calldata data
    ) internal {
        for (uint i = 0; i < data.length; ++i) {
            setFile(rects, data[i]);
        }
    }

    function setFile(
        mapping(uint => mapping(uint => Rect[])) storage rects,
        FileData calldata input
    ) internal {
        Rect[] storage storageFile = rects[input.lvl][input.file];
        for (uint i = 0; i < input.rects.length; ++i) {
            storageFile.push(input.rects[i]);
        }
    }

    function getLvl(
        mapping(uint => mapping(uint => Rect[])) storage rects,
        uint lvl
    ) internal view returns (mapping(uint => Rect[]) storage) {
        return rects[lvl];
    }

    function to_lvl_1(uint l) internal pure returns (uint) {
        if (l > 0) --l;
        return l;
    }
}

library Converter {
    function toString(uint value) internal pure returns (string memory) {
        if (value == 0) {
            return "0";
        }
        uint temp = value;
        uint digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }
}

library RectLib {
    using RectLib for Rect;
    using RandLib for Rand;
    using RandLib for string[];
    using Converter for uint8;

    function toSvg(
        Rect memory r,
        string memory color
    ) internal pure returns (string memory) {
        return
            string(
                abi.encodePacked(
                    "<rect x='",
                    r.x.toString(),
                    "' y='",
                    r.y.toString(),
                    "' width='",
                    r.width.toString(),
                    "' height='",
                    r.height.toString(),
                    "' fill='",
                    color,
                    "'/>"
                )
            );
    }

    function toSvg(
        Rect[] storage rects,
        string[] storage colors,
        Rand memory rnd
    ) internal view returns (string memory) {
        string memory res;
        for (uint i = 0; i < rects.length; ++i) {
            res = string(
                abi.encodePacked(res, rects[i].toSvg(colors.random(rnd)))
            );
        }
        return res;
    }

    function toSvg(
        Rect[] storage rects,
        string memory color
    ) internal view returns (string memory) {
        string memory res;
        for (uint i = 0; i < rects.length; ++i) {
            res = string(abi.encodePacked(res, rects[i].toSvg(color)));
        }
        return res;
    }
}

contract Generator is Ownable {
    using LayersLib for mapping(uint => mapping(uint => Rect[]));
    using LayersLib for mapping(uint => string[]);
    using LayersLib for uint;
    using RectLib for Rect;
    using RectLib for Rect[];
    using RandLib for Rand;
    using RandLib for string[];
    using Converter for uint;

    // uint8 polyps_count = 7;
    uint8[levelsCount] weedLevelCounts = [7, 7, 7, 7, 7];
    uint8[levelsCount] bubbleLevelCounts = [8, 8, 8, 8, 8];
    uint8[levelsCount] tentacleLevelCounts = [5, 5, 5, 6, 10];
    uint8[levelsCount] bellLevelCounts = [7, 10, 10, 10, 10];    
    // uint8[levelsCount] dotLevelCounts = [5, 7, 10, 10, 10];

    // mapping(uint => Rect[]) polyps;
    mapping(uint => mapping(uint => Rect[])) weeds;
    mapping(uint => mapping(uint => Rect[])) bubbles;
    mapping(uint => mapping(uint => Rect[])) tentacles;
    mapping(uint => mapping(uint => Rect[])) bells;    
    // mapping(uint => mapping(uint => Rect[])) dots;
    mapping(uint => Rect[]) grounds;

    string[] private backgroundColors0 = [
        "#CC93B1",
        "#E0BCA3",
        "#DDAFB7",
        "#A9D8C5",
        "#72C7CC",
        "#DBC9C9",
        "#D6CAA0",
        "#9ED3CB",
        "#4876AF",
        "#95C4B7",
        "#BDC19E",
        "#50B6BF",
        "#D3BAD3"
    ];

    string[] private backgroundColors1 = [
        "#B0E8BE",
        "#76E2D0",
        "#D8CE8F",
        "#F7C5C5",
        "#DCEA96",
        "#BF8FD6",
        "#EABFB9",
        "#E0D6BA",
        "#8B96DD",
        "#C2EFDF",
        "#B1E0E0",
        "#B6D99B",
        "#FFD8DD"
    ];

    string[] private backgroundColors2 = [
        "#96D1CB",
        "#65CEC2",
        "#43CC93",
        "#59DBCD",
        "#86C0D8",
        "#958DD6",
        "#B0E8BE",
        "#D3B3CD",
        "#8AA8CC",
        "#77E5DA",
        "#7D91E0",
        "#E8BECD",
        "#BFDBB3"
    ];

    string[] private backgroundColors3 = [
        "#FFC300",
        "#FFCF99",
        "#FFBFC1",
        "#FFBCC8",
        "#6DC2CA",
        "#3AA3D3",
        "#D18188",
        "#D3A5D1",
        "#F6FFDD",
        "#FFE4C0",
        "#FFA0BB",
        "#BD97D8",
        "#2B2582",
        "#6DA4CA"
    ];

    string[] private backgroundColors4 = [
        "#FFB2EB",
        "#A3F7D5",
        "#3A85FF",
        "#FFC6F2",
        "#FFB26D",
        "#D000FF",
        "#FFFF21",
        "#FF7716",
        "#FF46CE",
        "#84FCFF",
        "#00FFCB",
        "#BDA5FF",
        "#4FC1FF",
        "#59B4FF",
        "#7FFF7F",
        "#A8FFF9",
        "#BFFFE6",
        "#71C692",
        "#854AC4",
        "#3C00C1",
        "#3C81C1",
        "#FF4473",
        "#D6B7FF",
        "#FFC4A5",
        "#8E7CFF"
    ];

    string[] private backgroundColors42 = [
        // "#FFB2EB",
        "#A3F7D5",
        "#3A85FF",
        "#FFC6F2",
        "#FFB26D",
        "#D000FF",
        "#FFFF21",
        "#FF7716",
        "#FF46CE",
        "#84FCFF",
        "#00FFCB",
        "#BDA5FF",
        "#4FC1FF",
        "#59B4FF",
        "#7FFF7F",
        "#A8FFF9",
        "#BFFFE6",
        "#71C692",
        "#854AC4",
        "#3C00C1",
        "#3C81C1",
        "#FF4473",
        "#D6B7FF",
        "#FFC4A5",
        "#8E7CFF"
    ];    

    string[] private bubbleColors = [
        "#A5FFF1",
        "#FFB26B",
        "#F3FFD6",
        "#D4D8C9",
        "#F5E0FF",
        "#9F9BA0",
        "#D1F1FF",
        "#E2F1FF",
        "#FFFFFF",
        "#FF77D6",
        "#C1FFC8",
        "#FFE595",
        "#E8FFE8",
        "#F5E0FF",
        "#FFE4A7",
        "#F5E0FF"
    ];

    string[] private groundColors0 = [
        "#9B5B71",
        "#5B9B7E",
        "#9E8640",
        "#DD8C7A",
        "#478C7A",
        "#CC9380",
        "#4CA188",
        "#B777A2",
        "#0077A2",
        "#AD9474",
        "#7CAFA5",
        "#A08063",
        "#6A5D77",
        "#436E7F",
        "#428255"
    ];

    string[] private groundColors1 = [
        "#CC8F7E",
        "#77531D",
        "#7BBC45",
        "#23756B",
        "#85A094",
        "#DBAF84",
        "#BC8D97",
        "#7CBA9A",
        "#5460A8",
        "#C65B86",
        "#CC94BC",
        "#C4BA00",
        "#436E7F",
        "#AB72C1"
    ];

    string[] private groundColors2 = [
        "#D7E29E",
        "#C3E074",
        "#C3E074",
        "#5267A8",
        "#90CCB4",
        "#C3E074",
        "#90CCB4",
        "#FFD477",
        "#CC6394",
        "#CCA75D",
        "#CCA7BA",
        "#CC694B",
        "#A59578",
        "#FFC47C",
        "#755D33",
        "#E8B534"
    ];

    string[] private groundColors3 = [
        "#E587A0",
        "#FF664F",
        "#EAA4CA",
        "#FFC47C",
        "#6D88CA",
        "#D8A488",
        "#632577",
        "#6F7552",
        "#2C7FB7",
        "#A85E88",
        "#ADA35A",
        "#77625F",
        "#E0AE8F",
        "#8CB773",
        "#D3B16E",
        "#11A062",
        "#83969E",
        "#B5833D",
        "#FFFFFF"
    ];

    string[] private medusaColors0 = [
        "#BC646B",
        "#BC646B",
        "#8D5BA3",
        "#D3CFA0",
        "#D170B1",
        "#50B2D8",
        "#90C46F",
        "#856ED3",
        "#C471B2",
        "#C4712F",
        "#BDC1BF",
        "#C67584",
        "#74AA78",
        "#A85291",
        "#BF96DD",
        "#DB7D81",
        "#E59B87",
        "#017CBF"
    ];

    string[] private medusaColors1 = [
        "#FF9B2F",
        "#5E33E0",
        "#7C3374",
        "#CEE25D",
        "#12A9CC",
        "#E29CA7",
        "#A67FE0",
        "#D86B65",
        "#5ABC79",
        "#6DA1BA",
        "#913E49",
        "#FF6D81",
        "#DBAF00",
        "#A8AEFF",
        "#E59B87",
        "#635158",
        "#D8505D",
        "#C33374"
    ];

    string[] private medusaColors2 = [
        "#7CFF83",
        "#0093FF",
        "#96FFF4",
        "#ECFFBF",
        "#F26979",
        "#FFE1DF",
        "#A793B2",
        "#F2E479",
        "#B1E0C9",
        "#D3FF66",
        "#36E2CE",
        "#E07CF0",
        "#5E33E0",
        "#FF77A4",
        "#8D80DD",
        "#AFCF93",
        "#A8AEFF"
    ];

    string[] private medusaColors3 = [
        "#FF71D3",
        "#D36DE5",
        "#3AE4EA",
        "#D1FFB7",
        "#FFF9D3",
        "#7FE8B9",
        "#FFFFB9",
        "#CC70C5",
        "#E09C84",
        "#AFCF93",
        "#3D64CE",
        "#CCCC39",
        "#0081B5",
        "#93E5CA",
        "#E2BBB7",
        "#DD9368",
        "#D8778F"
    ];

    string[] private medusaColors4 = [
        "#FFFF84",
        "#F9FFF7",
        "#00FFCB",
        "#D59BFF",
        "#00FFFF",
        "#FF888C",
        "#F3FF9B",
        "#FF9EA1",
        "#1EFF7C",
        "#21ECFF",
        "#B464E5",
        "#FFFFB5",
        "#B6FF00",
        "#14DBFF",
        "#FAFFE5",
        "#FF77A4",
        "#61B6FF",
        "#FA82FF",
        "#A8FFC0",
        "#FFD9FA"
    ];

    string[] private weedColors = [
        "#D3FF66",
        "#FF7CF5",
        "#C400AA",
        "#BCE25A",
        "#804E52",
        "#389942",
        "#635158",
        "#823B40",
        "#FF8E77",
        "#FF9075",
        "#FFCF93",
        "#E28A46",
        "#A793B2",
        "#FF77A4",
        "#A10063",
        "#FF005D",
        "#54CE5C",
        "#3B913F",
        "#E8EA83",
        "#FF5EF4",
        "#00D39B"
    ];

    constructor() {
        grounds[0].push(Rect(0, 20, 24, 4));
    }

    function backgroundColors(
        uint index
    ) private view returns (string[] storage) {
        if (index == 0) return backgroundColors0;
        if (index == 1) return backgroundColors1;
        if (index == 2) return backgroundColors2;
        if (index == 3) return backgroundColors3;
        if (index == 4) return backgroundColors4;
        return backgroundColors0;
    }

    function groundColors(uint index) private view returns (string[] storage) {
        if (index == 0) return groundColors0;
        if (index == 1) return groundColors1;
        if (index == 2) return groundColors2;
        if (index == 3) return groundColors3;
        // if (index == 4) return groundColors4;
        return groundColors0;
    }

    function medusaColors(
        uint index
    ) private view returns (string[] storage) {
        if (index == 0) return medusaColors0;
        if (index == 1) return medusaColors1;
        if (index == 2) return medusaColors2;
        if (index == 3) return medusaColors3;
        if (index == 4) return medusaColors4;
        return medusaColors0;
    }

    // function setPolyps(FileData[] calldata data) external onlyOwner {
    //     for (uint i = 0; i < data.length; ++i) {
    //         FileData memory file = data[i];
    //         Rect[] storage storageFile = polyps[file.file];
    //         for (uint j = 0; j < file.rects.length; ++j) {
    //             storageFile.push(file.rects[j]);
    //         }
    //     }
    // }

    function setWeeds(FileData[] calldata data) external onlyOwner {
        weeds.setLayers(data);
    }

    function setBubbles(FileData[] calldata data) external onlyOwner {
        bubbles.setLayers(data);
    }

    function setTentacles(FileData[] calldata data) external onlyOwner {
        tentacles.setLayers(data);
    }

    function setBells(FileData[] calldata data) external onlyOwner {
        bells.setLayers(data);
    }

    // function setDots(FileData[] calldata data) external onlyOwner {
    //     dots.setLayers(data);
    // }

    function toString(uint value) private pure returns (string memory) {
        if (value == 0) {
            return "0";
        }
        uint temp = value;
        uint digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    function setBcGround(
        MedusaData memory data,
        Rand memory rnd
    ) private view {
        data.background = backgroundColors(rnd.lvl().to_lvl_1()).random(rnd);        
        if (rnd.lvl().to_lvl_1() < 4) {
            data.background2 = data.background;
        } else {
            data.background2 = backgroundColors42.random(rnd);            
        }
    }

    function setGround(MedusaData memory data, Rand memory rnd) private view {
        if (rnd.lvl().to_lvl_1() < 4){
            data.hasGround = true;
            data.ground = rnd.next() % groundsCount;
            data.groundColor = groundColors(rnd.lvl().to_lvl_1()).random(rnd);
        }
    }

    // function setPolyps(MedusaData memory data, Rand memory rnd) private view {
    //     data.tentacle = rnd.next() % polyps_count;
    //     data.tentacleColor = medusaColors(rnd.lvl().to_lvl_1()).random(rnd);
    // }

    function setBubble(MedusaData memory data, Rand memory rnd) private view {
        data.hasBubble = rnd.next() % 4 < 3; // 0,1,2 = 75% chance
        if(data.hasBubble){
            data.bubble = rnd.next() % bubbleLevelCounts[rnd.lvl().to_lvl_1()];
            data.bubbleColor = bubbleColors.random(rnd);
        }        
    }  

    function setWeed(MedusaData memory data, Rand memory rnd) private view {
        if (rnd.lvl() < 4){ // no weed for biggest level
            data.hasWeed = rnd.next() % 4 < 3; // 0,1,2 = 75% chance
            if(data.hasWeed){
                data.weed = rnd.next() % weedLevelCounts[rnd.lvl().to_lvl_1()];
                data.weedColor = medusaColors(rnd.lvl().to_lvl_1()).random(rnd);
            }
        }
    }    

    function setAnimation(MedusaData memory data, Rand memory rnd) private view {
        data.mirrorTime = 3 + rnd.next() % 3;
        if (rnd.lvl().to_lvl_1() < 2){
            data.bobTime = 0;
        } else {
            data.bobTime = 8 + rnd.next() % 8;
        }        
    }
    

    function setTentacle(MedusaData memory data, Rand memory rnd) private view {
        data.tentacle = rnd.next() % tentacleLevelCounts[rnd.lvl().to_lvl_1()];
        data.tentacleColor = medusaColors(rnd.lvl().to_lvl_1()).random(rnd);
    }

    function setBell(MedusaData memory data, Rand memory rnd) private view {
        data.bell = rnd.next() % bellLevelCounts[rnd.lvl().to_lvl_1()];
        data.bellColor = medusaColors(rnd.lvl().to_lvl_1()).random(rnd);
        // data.hasDots = rnd.next() % 4 == 0;
        // if (data.hasDots) {
        //     data.dotsColor = medusaColors(rnd.lvl().to_lvl_1()).random(rnd);
        // }
    }

    function getMedusa(
        SeedData calldata seed_data
    ) external view returns (MedusaData memory) {
        Rand memory rnd = Rand(seed_data.seed, 0, seed_data.extra);
        MedusaData memory data;
        data.lvl = rnd.lvl();
        setBcGround(data, rnd);
        setBubble(data, rnd);
        setGround(data, rnd);        
        setWeed(data, rnd);
        setAnimation(data, rnd);
        setTentacle(data, rnd);
        setBell(data, rnd);
        return data;
    }

    function getUuid(
        SeedData calldata seed_data
    ) internal view returns (string memory) {
        return string(abi.encodePacked(seed_data.seed.toString(), seed_data.extra.toString()));
    }
    

    function getSvg(
        SeedData calldata seed_data
    ) external view returns (string memory) {
        string memory uuid = getUuid(seed_data);
        return toSvg(this.getMedusa(seed_data), uuid);
    }

    function getMeta(
        SeedData calldata seed_data
    ) external view returns (string memory) {
        MedusaData memory data = this.getMedusa(seed_data);
        bytes memory lvl = abi.encodePacked('"level":', data.lvl.toString());
        bytes memory background = abi.encodePacked(
            ',"background":"',
            data.background,
            '"',
            ',"background2":"',
            data.background2,
            '"'
        );
        bytes memory bubble = abi.encodePacked(
            ',"hasBubble":',
            data.hasBubble ? "true" : "false",
            ',"bubble":',
            data.bubble.toString(),
            ',"bubbleColor":"',
            data.bubbleColor,
            '"'
        );        
        bytes memory ground = abi.encodePacked(
            ',"hasGround":',
            data.hasGround ? "true" : "false",
            ',"groundColor":"',
            data.groundColor,
            '"'
        );
        bytes memory weed = abi.encodePacked(
            ',"hasWeed":',
            data.hasWeed ? "true" : "false",
            ',"weed":',
            data.weed.toString(),
            ',"weedColor":"',
            data.weedColor,
            '"'
        );         
        bytes memory animation = abi.encodePacked(
            ',"mirrorTime":',
            data.mirrorTime.toString(),
            ',"bobTime":',
            data.bobTime.toString()
        ); 
        bytes memory tentacle = abi.encodePacked(
            ',"tentacle":',
            data.tentacle.toString(),
            ',"tentacleColor":"',
            data.tentacleColor,
            '"'
        );       
        bytes memory bell = abi.encodePacked(
            ',"bell":',
            data.bell.toString(),
            ',"bellColor":"',
            data.bellColor,
            '"'
        );
        // bytes memory bellDots = abi.encodePacked(
        //     ',"hasDots":',
        //     data.hasDots ? "true" : "false",
        //     ',"dotsColor":"',
        //     data.dotsColor,
        //     '"'
        // );

        return
            string(
                abi.encodePacked(
                    "{",
                    lvl,
                    background,
                    ground,
                    weed, 
                    bubble,         
                    animation,          
                    tentacle,
                    bell,
                    "}"
                )
            );
    }

    function toSvg(
        MedusaData memory data,
        string memory uuid
    ) private view returns (string memory) {
        bytes memory svgStart = abi.encodePacked(
            "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0",
            " ",
            toString(pixelsCount),
            " ",
            toString(pixelsCount),
            "' shape-rendering='crispEdges'>",
            '<style>',
                '@keyframes mirrorK {',
                    '0%, 50% { transform: scaleX(1); }',
                    '50.1%, 100% { transform: scaleX(-1); }',
                '}',
                '@keyframes pumpK {',
                    '0%, 100% { transform: translateY(0.); }',
                    '50% { transform: translateY(-0.4px); }',
                '}',
                '@keyframes bobK {',
                    '0%, 100% { transform: translateY(-2); }',
                    '50% { transform: translateY(1.5px); }',
                '}',
                '@keyframes swayK {',
                    '0%, 100% { transform: translateX(-0.5px); }',
                    '50% { transform: translateX(0.5px); }',
                '}',
                '@keyframes swayWeedK {',
                    '0%, 100% { transform: translateX(-0.15px); }',
                    '50% { transform: translateX(0.15px); }',
                '}',      
                '@keyframes bubbleRiseK {',
                    '0%{ transform: translateY(24px); }',
                    '100% { transform: translateY(-24px); }',
                '}',
                '@keyframes bubbleWobbleK {',
                    '0%, 100% { transform: translateX(0.2px); }',
                    '50% { transform: translateX(-0.2px); }',
                '}',
                '.mirror', uuid, '  {',
                    'animation: mirrorK ',
                    toString(data.mirrorTime),
                    // toString(1),
                    's step-end infinite;',
                    'transform-origin: center center;',
                '}',
                '.pump', uuid, '  {',
                    'animation: pumpK ',
                    toString(data.bobTime),
                    // toString(1),
                    's ease-in-out infinite;',
                '}',
                '.bob', uuid, '  {',
                    'animation: bobK ',
                    toString(data.bobTime),
                    // toString(1),
                    's ease-in-out infinite;',
                '}',
                '.sway', uuid, ' {',
                    'animation: swayK ',toString(6+data.mirrorTime),'s linear infinite;',
                '}',
                '.swayWeed', uuid, ' {',
                    'animation: swayWeedK ',toString(2+data.mirrorTime),'s linear infinite;',
                '}',
                '.bubbleRise', uuid, ' {',
                    'animation: bubbleRiseK ',toString(20+data.mirrorTime),'s linear infinite;',
                '}',
                '.bubbleSway {',
                    'animation: bubbleWobbleK 5s linear infinite;',
                '}',
            '</style>'          
        );

        // if (data.lvl == 0) {
        //     return
        //         string(
        //             abi.encodePacked(
        //                 svgStart,
        //                 backgroundSvg(data),
        //                 groundSvg(data),
        //                 tentacleSvg(data),
        //                 weedSvg(data),
        //                 "</svg>"
        //             )
        //         );
        // } else {
            return
                string(
                    abi.encodePacked(
                        svgStart,
                        // backgroundGradient(data),
                        backgroundSvg(data, uuid),
                        bubbleSvg(data, uuid),
                        groundSvg(data),                        
                        weedSvg(data, uuid),                        
                        tentacleSvg(data, uuid),
                        bellSvg(data, uuid),
                        "</svg>"
                    )
                );
        // }
    }

    function backgroundSvg(
        MedusaData memory data,
        string memory uuid
    ) private pure returns (string memory) {       
        return
            string(
                abi.encodePacked(
                    "<linearGradient id='Gradient", uuid, "' x1='0' x2='0' y1='0' y2='1'>",
                    "<stop offset='0%' stop-color='",
                    data.background,
                    "' />",
                    "<stop offset='100%' stop-color='",
                    data.background2,
                    "' />",
                    "</linearGradient>",
                    "<rect x='0' y='0' width='24' height='24' fill='url(#Gradient", uuid, ")'/>"                                        
                )
            );        
    }

    // function backgroundSvg(
    //     MedusaData memory data
    // ) private pure returns (string memory) {
    //     Rect memory r = Rect(0, 0, pixelsCount, pixelsCount);
    //     return r.toSvg(data.background);
    // }

    function groundSvg(
        MedusaData memory data
    ) private view returns (string memory) {
        if (!data.hasGround) return "";
        return grounds[data.ground].toSvg(data.groundColor);
    }

    function weedSvg(
        MedusaData memory data,
        string memory uuid
    ) private view returns (string memory) {    
        if (!data.hasWeed) return "";
        string memory weedShape = weeds[data.lvl.to_lvl_1()][data.weed].toSvg(data.weedColor);
        return
            string(
                abi.encodePacked(
                    '<g class="swayWeed', uuid, '">',
                        weedShape,
                    '</g>'
                )
            );                
    }  

    function bubbleSvg(
        MedusaData memory data,
        string memory uuid
    ) private view returns (string memory) {    
        if (!data.hasBubble) return "";
        string memory bubbleShape = bubbles[data.lvl.to_lvl_1()][data.bubble].toSvg(data.bubbleColor);
        return
            string(
                abi.encodePacked(
                    "<g class='bubbleRise", uuid, "'>",
                        "<g class='bubbleSway'>",
                            bubbleShape,
                        "</g>",
                    "</g>"
                )
            );
    }       

    function tentacleSvg(
        MedusaData memory data,
        string memory uuid
    ) private view returns (string memory) {
        string memory tentacle = tentacles[data.lvl.to_lvl_1()][data.tentacle].toSvg(data.tentacleColor);
        // always miror
        // if under 2 don't bob pump or sway
        // if under 3 don't pump
        // above do all
        if (data.lvl.to_lvl_1() < 2){
            return
                string(
                    abi.encodePacked(
                        "<g class='mirror", uuid, "'>",
                            tentacle,
                        "</g>"
                    )
                );
        } else if (data.lvl.to_lvl_1() < 3){
            return
                string(
                    abi.encodePacked(                        
                        "<g class='bob", uuid, "'>",
                            "<g class='mirror", uuid, "'>",
                                tentacle,
                            "</g>",
                        "</g>"
                    )
                );
        } else {
            return
                string(
                    abi.encodePacked(                        
                        "<g class='bob", uuid, "'>",
                            "<g class='pump", uuid, "'>",
                                "<g class='mirror", uuid, "'>",
                                    tentacle,
                                "</g>",
                            "</g>",
                        "</g>"
                    )
                );
        }

        return tentacle;
    } 

    function bellSvg(
        MedusaData memory data,
        string memory uuid
    ) private view returns (string memory) {
        string memory bell = bells[data.lvl.to_lvl_1()][data.bell].toSvg(data.bellColor);
        if (data.lvl.to_lvl_1() < 2){
            // only mirror
            return
                string(
                    abi.encodePacked(
                        "<g class='mirror",uuid,"'>",
                            bell,
                        "</g>"
                    )
                );
        // if under 3 mirror, bob, sway
        } else if (data.lvl.to_lvl_1() < 3){
            return
                string(
                    abi.encodePacked(                        
                        "<g class='bob",uuid,"'>",
                            "<g class='mirror",uuid,"'>",
                                bell,
                            "</g>",
                        "</g>"
                    )
                );
        // otherwise bob and sway don't miror
        } else {
            return
                string(
                    abi.encodePacked(
                        "<g class='bob",uuid,"'>",
                            bell,
                        "</g>"
                    )
                );
        }
    }
}

File 6 of 9 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @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 Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

File 7 of 9 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 8 of 9 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @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 meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 9 of 9 : Ownable.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Ownable {
    address _owner;

    event RenounceOwnership();

    constructor() {
        _owner = msg.sender;
    }

    modifier onlyOwner() {
        require(_owner == msg.sender, "only owner");
        _;
    }

    function owner() external view virtual returns (address) {
        return _owner;
    }

    function ownerRenounce() public onlyOwner {
        _owner = address(0);
        emit RenounceOwnership();
    }

    function transferOwnership(address newOwner) external onlyOwner {
        _owner = newOwner;
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "v3-core/=lib/v3-core/",
    "v3-periphery/=lib/v3-periphery/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"indexed":false,"internalType":"struct SeedData","name":"seed_data","type":"tuple"}],"name":"OnMedusaTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"holder","type":"address"},{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"indexed":false,"internalType":"struct SeedData","name":"seed_data","type":"tuple"}],"name":"OnPolypsGrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"holder","type":"address"},{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"indexed":false,"internalType":"struct SeedData","name":"seed_data","type":"tuple"}],"name":"OnPolypsShrink","type":"event"},{"anonymous":false,"inputs":[],"name":"RenounceOwnership","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getHolderByIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"getHoldersList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"internalType":"struct SeedData","name":"seed_data","type":"tuple"}],"name":"getMedusa","outputs":[{"components":[{"internalType":"uint256","name":"lvl","type":"uint256"},{"internalType":"string","name":"background","type":"string"},{"internalType":"string","name":"background2","type":"string"},{"internalType":"bool","name":"hasGround","type":"bool"},{"internalType":"uint256","name":"ground","type":"uint256"},{"internalType":"string","name":"groundColor","type":"string"},{"internalType":"bool","name":"hasBubble","type":"bool"},{"internalType":"uint256","name":"bubble","type":"uint256"},{"internalType":"string","name":"bubbleColor","type":"string"},{"internalType":"bool","name":"hasWeed","type":"bool"},{"internalType":"uint256","name":"weed","type":"uint256"},{"internalType":"string","name":"weedColor","type":"string"},{"internalType":"uint256","name":"mirrorTime","type":"uint256"},{"internalType":"uint256","name":"bobTime","type":"uint256"},{"internalType":"uint256","name":"tentacle","type":"uint256"},{"internalType":"string","name":"tentacleColor","type":"string"},{"internalType":"uint256","name":"bell","type":"uint256"},{"internalType":"string","name":"bellColor","type":"string"}],"internalType":"struct MedusaData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"internalType":"struct SeedData","name":"seed_data","type":"tuple"}],"name":"getMeta","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"internalType":"struct SeedData","name":"seed_data","type":"tuple"}],"name":"getSvg","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"holdersCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"seed","type":"uint256"}],"name":"isOwnerOf","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"poolAddress","type":"address"}],"name":"launch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"maxBuy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"medusaCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"medusaOfOwnerByIndex","outputs":[{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"internalType":"struct SeedData","name":"data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"medusasTotalCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownerRenounce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"polypsDegree","outputs":[{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"internalType":"struct SeedData","name":"data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"polypsTotalCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"lvl","type":"uint256"},{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"uint8","name":"x","type":"uint8"},{"internalType":"uint8","name":"y","type":"uint8"},{"internalType":"uint8","name":"width","type":"uint8"},{"internalType":"uint8","name":"height","type":"uint8"}],"internalType":"struct Rect[]","name":"rects","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"setBells","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"lvl","type":"uint256"},{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"uint8","name":"x","type":"uint8"},{"internalType":"uint8","name":"y","type":"uint8"},{"internalType":"uint8","name":"width","type":"uint8"},{"internalType":"uint8","name":"height","type":"uint8"}],"internalType":"struct Rect[]","name":"rects","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"setBubbles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"lvl","type":"uint256"},{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"uint8","name":"x","type":"uint8"},{"internalType":"uint8","name":"y","type":"uint8"},{"internalType":"uint8","name":"width","type":"uint8"},{"internalType":"uint8","name":"height","type":"uint8"}],"internalType":"struct Rect[]","name":"rects","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"setTentacles","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"lvl","type":"uint256"},{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"uint8","name":"x","type":"uint8"},{"internalType":"uint8","name":"y","type":"uint8"},{"internalType":"uint8","name":"width","type":"uint8"},{"internalType":"uint8","name":"height","type":"uint8"}],"internalType":"struct Rect[]","name":"rects","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"setWeeds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a06040523463000056805763000000176300005750565b60058152646a656c6c6960d81b602082015263000000356300005750565b60058152644a454c4c4960d81b602082015281516001600160401b0381116300003397576300000068600354630000578c565b601f81116300005629575b50602092601f821160011463000055b95763000000ac9293829160009263000054e6575b50508160011b916000199060031b1c19161790565b6003555b80516001600160401b03811163000033975763000000d1600454630000578c565b601f81116300005562575b50602091601f821160011463000054f3576300000112926000918363000054e65750508160011b916000199060031b1c19161790565b6004555b336080819052601380546001600160a01b0319169091179055630000013b6300005685565b600781526007602082015260076040820152600760608201526007608082015260009060005b6005811063000054b45782601455630000017b6300005685565b600881526008602082015260086040820152600860608201526008608082015260009060005b600581106300005482578260155563000001bb6300005685565b60058152600560208201526005604082015260066060820152600a608082015260009060005b600581106300005450578260165563000001fb6300005685565b60078152600a6020820152600a6040820152600a6060820152600a608082015260009060005b60058110630000541e5782601755630000023b63000056a6565b63000002476300005750565b60078152662343433933423160c81b6020820152815263000002696300005750565b60078152662345304243413360c81b60208201526020820152630000028e6300005750565b60078152662344444146423760c81b6020820152604082015263000002b36300005750565b60078152662341394438433560c81b6020820152606082015263000002d86300005750565b60078152662337324337434360c81b6020820152608082015263000002fd6300005750565b60078152662344424339433960c81b602082015260a082015263000003226300005750565b60078152660234436434141360cc1b602082015260c082015263000003476300005750565b6007815266119ca2a219a1a160c91b602082015260e0820152630000036c6300005750565b6007815266119a1c1b9b20a360c91b602082015261010082015263000003926300005750565b60078152662339354334423760c81b602082015261012082015263000003b86300005750565b60078152662342444331394560c81b602082015261014082015263000003de6300005750565b6007815266119a98211b212360c91b602082015261016082015263000004046300005750565b60078152662344334241443360c81b6020820152610180820152601d54600d601d5580600d106300005368575b50601d6000908152600080516020630000a0f7833981519152915b600d8210630000523757630000046263000056a6565b630000046e6300005750565b60078152662342304538424560c81b6020820152815263000004906300005750565b60078152660233736453244360cc1b6020820152602082015263000004b56300005750565b600781526611a21c21a29c2360c91b6020820152604082015263000004da6300005750565b60078152662346374335433560c81b6020820152606082015263000004ff6300005750565b600781526611a221a2a09c9b60c91b6020820152608082015263000005246300005750565b600781526611a1231c23221b60c91b602082015260a082015263000005496300005750565b60078152662345414246423960c81b602082015260c0820152630000056e6300005750565b60078152662345304436424160c81b602082015260e082015263000005936300005750565b600781526608ce108e4d911160ca1b602082015261010082015263000005b96300005750565b600781526611a19922a3222360c91b602082015261012082015263000005df6300005750565b60078152660234231453045360cc1b602082015261014082015263000006056300005750565b600781526611a11b221c9ca160c91b6020820152610160820152630000062b6300005750565b600781526608d191910e111160ca1b6020820152610180820152601e54600d601e5580600d106300005181575b50601e6000908152600080516020630000a1b7833981519152915b600d8210630000505057630000068963000056a6565b63000006956300005750565b6007815266119c9b2218a1a160c91b6020820152815263000006b76300005750565b6007815266119b1aa1a2a19960c91b6020820152602082015263000006dc6300005750565b60078152662334334343393360c81b6020820152604082015263000007016300005750565b600781526608cd4e511090d160ca1b6020820152606082015263000007266300005750565b6007815266046706c866088760cb1b60208201526080820152630000074b6300005750565b6007815266119c9a9c22221b60c91b602082015260a082015263000007706300005750565b60078152662342304538424560c81b602082015260c082015263000007956300005750565b600781526608d10cd08cd0d160ca1b602082015260e082015263000007ba6300005750565b60078152662338414138434360c81b602082015261010082015263000007e06300005750565b60078152662337374535444160c81b602082015261012082015263000008066300005750565b60078152660233744393145360cc1b6020820152610140820152630000082c6300005750565b600781526608d14e109150d160ca1b602082015261016082015263000008526300005750565b60078152662342464442423360c81b6020820152610180820152601f54600d601f5580600d106300004f9a575b50601f6000908152600080516020630000a1f7833981519152915b600d82106300004e695763000008b063000056c8565b63000008bc6300005750565b60078152660234646433330360cc1b6020820152815263000008de6300005750565b60078152662346464346393960c81b6020820152602082015263000009036300005750565b60078152662346464246433160c81b6020820152604082015263000009286300005750565b60078152660468c8c848686760cb1b60208201526060820152630000094d6300005750565b60078152662336444332434160c81b6020820152608082015263000009726300005750565b60078152662333414133443360c81b602082015260a082015263000009976300005750565b60078152660468862706270760cb1b602082015260c082015263000009bc6300005750565b60078152662344334135443160c81b602082015260e082015263000009e16300005750565b600781526608d18d9191911160ca1b60208201526101008201526300000a076300005750565b60078152660234646453443360cc1b60208201526101208201526300000a2d6300005750565b600781526611a3232098212160c91b60208201526101408201526300000a536300005750565b60078152660468488726e88760cb1b60208201526101608201526300000a796300005750565b6007815266119921191a9c1960c91b60208201526101808201526300000a9f6300005750565b60078152662336444134434160c81b60208201526101a0820152602054600e60205580600e106300004db3575b5060206000908152600080516020630000a097833981519152915b600e82106300004c82576040516001600160401b0361032082019081119082111763000033975761032081016040526300000b226300005750565b600781526611a323211922a160c91b602082015281526300000b446300005750565b60078152662341334637443560c81b602082015260208201526300000b696300005750565b60078152661199a09c1aa32360c91b602082015260408201526300000b8e6300005750565b600781526611a323219b231960c91b602082015260608201526300000bb36300005750565b600781526608d191908c8d9160ca1b602082015260808201526300000bd86300005750565b600781526611a2181818232360c91b602082015260a08201526300000bfd6300005750565b60078152662346464646323160c81b602082015260c08201526300000c226300005750565b600781526611a3231b9b989b60c91b602082015260e08201526300000c476300005750565b60078152662346463436434560c81b60208201526101008201526300000c6d6300005750565b6007815266119c1a2321a32360c91b60208201526101208201526300000c936300005750565b6007815266119818232321a160c91b60208201526101408201526300000cb96300005750565b600781526611a122209aa32360c91b60208201526101608201526300000cdf6300005750565b6007815266119a232198a32360c91b60208201526101808201526300000d056300005750565b6007815266119a9ca11a232360c91b60208201526101a08201526300000d2b6300005750565b6007815266119ba323231ba360c91b60208201526101c08201526300000d516300005750565b60078152662341384646463960c81b60208201526101e08201526300000d776300005750565b600781526611a1232323229b60c91b60208201526102008201526300000d9d6300005750565b6007815266119b98a19b1c9960c91b60208201526102208201526300000dc36300005750565b600781526608ce0d4d1050cd60ca1b60208201526102408201526300000de96300005750565b60078152662333433030433160c81b60208201526102608201526300000e0f6300005750565b60078152662333433831433160c81b60208201526102808201526300000e356300005750565b60078152662346463434373360c81b60208201526102a08201526300000e5b6300005750565b600781526611a21b211ba32360c91b60208201526102c08201526300000e816300005750565b60078152662346464334413560c81b60208201526102e08201526300000ea76300005750565b6007815266119c229ba1a32360c91b60208201526103008201526021546019602155806019106300004bcc575b5060216000908152600080516020630000a177833981519152915b601982106300004a9b576040516001600160401b0361030082019081119082111763000033975761030081016040526300000f2a6300005750565b60078152662341334637443560c81b602082015281526300000f4c6300005750565b60078152661199a09c1aa32360c91b602082015260208201526300000f716300005750565b600781526611a323219b231960c91b602082015260408201526300000f966300005750565b600781526608d191908c8d9160ca1b602082015260608201526300000fbb6300005750565b600781526611a2181818232360c91b602082015260808201526300000fe06300005750565b60078152662346464646323160c81b602082015260a082015263000010056300005750565b600781526611a3231b9b989b60c91b602082015260c0820152630000102a6300005750565b60078152662346463436434560c81b602082015260e0820152630000104f6300005750565b6007815266119c1a2321a32360c91b602082015261010082015263000010756300005750565b6007815266119818232321a160c91b6020820152610120820152630000109b6300005750565b600781526611a122209aa32360c91b602082015261014082015263000010c16300005750565b6007815266119a232198a32360c91b602082015261016082015263000010e76300005750565b6007815266119a9ca11a232360c91b6020820152610180820152630000110d6300005750565b6007815266119ba323231ba360c91b60208201526101a082015263000011336300005750565b60078152662341384646463960c81b60208201526101c082015263000011596300005750565b600781526611a1232323229b60c91b60208201526101e0820152630000117f6300005750565b6007815266119b98a19b1c9960c91b602082015261020082015263000011a56300005750565b600781526608ce0d4d1050cd60ca1b602082015261022082015263000011cb6300005750565b60078152662333433030433160c81b602082015261024082015263000011f16300005750565b60078152662333433831433160c81b602082015261026082015263000012176300005750565b60078152662346463434373360c81b6020820152610280820152630000123d6300005750565b600781526611a21b211ba32360c91b60208201526102a082015263000012636300005750565b60078152662346464334413560c81b60208201526102c082015263000012896300005750565b6007815266119c229ba1a32360c91b60208201526102e082015260225460186022558060181063000049e5575b5060226000908152600080516020630000a157833981519152915b6018821063000048b45763000012e763000056ea565b63000012f36300005750565b60078152662341354646463160c81b6020820152815263000013156300005750565b600781526611a32321191b2160c91b60208201526020820152630000133a6300005750565b600781526611a319a323221b60c91b60208201526040820152630000135f6300005750565b60078152662344344438433960c81b6020820152606082015263000013846300005750565b600781526611a31aa298232360c91b90816020820152608083015263000013ab6300005750565b60078152660233946394241360cc1b602082015260a083015263000013d06300005750565b600781526611a218a318a32360c91b602082015260c083015263000013f56300005750565b600781526611a2992318a32360c91b602082015260e0830152630000141a6300005750565b600781526611a3232323232360c91b602082015261010083015263000014406300005750565b600781526611a3231b9ba21b60c91b602082015261012083015263000014666300005750565b600781526604686628c8c86760cb1b6020820152610140830152630000148c6300005750565b60078152662346464535393560c81b602082015261016083015263000014b26300005750565b60078152660468a708c8c8a760cb1b602082015261018083015263000014d86300005750565b600781528160208201526101a083015263000014f46300005750565b60078152662346464534413760c81b60208201526101c0830152630000151a6300005750565b906007825260208201526101e082015260235460106023558060101063000047fe575b5060236000908152600080516020630000a217833981519152915b6010821063000046cd576040516001600160401b036101e08201908111908211176300003397576101e0810160405263000015936300005750565b60078152662339423542373160c81b6020820152815263000015b56300005750565b60078152662335423942374560c81b6020820152602082015263000015da6300005750565b60078152660233945383634360cc1b6020820152604082015263000015ff6300005750565b60078152662344443843374160c81b6020820152606082015263000016246300005750565b60078152662334373843374160c81b6020820152608082015263000016496300005750565b60078152660234343393338360cc1b602082015260a0820152630000166e6300005750565b60078152660466886826270760cb1b602082015260c082015263000016936300005750565b600781526611a11b9b9ba09960c91b602082015260e082015263000016b86300005750565b60078152661198181b9ba09960c91b602082015261010082015263000016de6300005750565b600781526608d0510e4d0dcd60ca1b602082015261012082015263000017046300005750565b60078152662337434146413560c81b6020820152610140820152630000172a6300005750565b60078152662341303830363360c81b602082015261016082015263000017506300005750565b60078152662336413544373760c81b602082015261018082015263000017766300005750565b6007815266119a199b229ba360c91b60208201526101a0820152630000179c6300005750565b60078152662334323832353560c81b60208201526101c0820152602454600f60245580600f106300004617575b5060246000908152600080516020630000a277833981519152915b600f821063000044e65763000017fa63000056c8565b63000018066300005750565b60078152662343433846374560c81b6020820152815263000018286300005750565b600781526608cdcdcd4ccc5160ca1b60208201526020820152630000184d6300005750565b60078152662337424243343560c81b6020820152604082015263000018726300005750565b60078152661199199b9a9b2160c91b6020820152606082015263000018976300005750565b600781526608ce0d504c0e4d60ca1b6020820152608082015263000018bc6300005750565b600781526608d11090518e0d60ca1b602082015260a082015263000018e16300005750565b60078152662342433844393760c81b602082015260c082015263000019066300005750565b60078152662337434241394160c81b602082015260e0820152630000192b6300005750565b60078152660466a686c6082760cb1b602082015261010082015263000019516300005750565b600781526611a19b1aa11c1b60c91b602082015261012082015263000019776300005750565b60078152662343433934424360c81b6020820152610140820152630000199d6300005750565b60078152660234334424130360cc1b602082015261016082015263000019c36300005750565b6007815266119a199b229ba360c91b602082015261018082015263000019e96300005750565b60078152662341423732433160c81b60208201526101a0820152602554600e60255580600e106300004430575b5060256000908152600080516020630000a077833981519152915b600e821063000042ff576300001a4763000056ea565b6300001a536300005750565b60078152662344374532394560c81b602082015281526300001a756300005750565b600781526608d0ccd14c0dcd60ca1b9081602082015260208301526300001a9c6300005750565b6007815281602082015260408301526300001ab76300005750565b60078152660466a646c6e82760cb1b602082015260608301526300001adc6300005750565b90600782526608ce4c10d0d08d60ca1b9182602082015260808401526300001b046300005750565b9060078252602082015260a08301526300001b1f6300005750565b9060078252602082015260c08201526300001b3a6300005750565b60078152662346464434373760c81b602082015260e08201526300001b5f6300005750565b600781526608d0d0cd8cce4d60ca1b60208201526101008201526300001b856300005750565b600781526608d0d0d04dcd5160ca1b60208201526101208201526300001bab6300005750565b60078152662343434137424160c81b60208201526101408201526300001bd16300005750565b600781526611a1a19b1c9a2160c91b60208201526101608201526300001bf76300005750565b6007815266046826a726a6e760cb1b60208201526101808201526300001c1d6300005750565b60078152662346464334374360c81b60208201526101a08201526300001c436300005750565b60078152662337353544333360c81b60208201526101c08201526300001c696300005750565b600781526608d14e108d4ccd60ca1b60208201526101e08201526026546010602655806010106300004249575b5060266000908152600080516020630000a137833981519152915b601082106300004118576040516001600160401b0361026082019081119082111763000033975761026081016040526300001cec6300005750565b60078152660234535383741360cc1b602082015281526300001d0e6300005750565b600781526611a3231b1b1a2360c91b602082015260208201526300001d336300005750565b60078152662345414134434160c81b602082015260408201526300001d586300005750565b60078152662346464334374360c81b602082015260608201526300001d7d6300005750565b60078152662336443838434160c81b602082015260808201526300001da26300005750565b60078152660468870826870760cb1b602082015260a08201526300001dc76300005750565b60078152662336333235373760c81b602082015260c08201526300001dec6300005750565b6007815266119b231b9a9a9960c91b602082015260e08201526300001e116300005750565b60078152662332433746423760c81b60208201526101008201526300001e376300005750565b600781526604682706a8a70760cb1b60208201526101208201526300001e5d6300005750565b60078152662341444133354160c81b60208201526101408201526300001e836300005750565b6007815266119b9b9b191aa360c91b60208201526101608201526300001ea96300005750565b600781526611a29820a29c2360c91b60208201526101808201526300001ecf6300005750565b60078152662338434237373360c81b60208201526101a08201526300001ef56300005750565b60078152662344334231364560c81b60208201526101c08201526300001f1b6300005750565b6007815266119898a0981b1960c91b60208201526101e08201526300001f416300005750565b60078152662338333936394560c81b60208201526102008201526300001f676300005750565b600781526608d08d4e0cccd160ca1b60208201526102208201526300001f8d6300005750565b600781526611a3232323232360c91b60208201526102408201526027546013602755806013106300004062575b5060276000908152600080516020630000a0d7833981519152915b601382106300003f31576300001feb630000570c565b6300001ff76300005750565b600781526611a1219b1a1b2160c91b908160208201528252630000201b6300005750565b90600782526020820152602082015263000020366300005750565b60078152662338443542413360c81b60208201526040820152630000205b6300005750565b60078152660234433434641360cc1b6020820152606082015263000020806300005750565b60078152662344313730423160c81b6020820152608082015263000020a56300005750565b60078152660466a60846488760cb1b602082015260a082015263000020ca6300005750565b6007815266119c98219a1b2360c91b602082015260c082015263000020ef6300005750565b60078152662338353645443360c81b602082015260e082015263000021146300005750565b600781526611a19a1b98a11960c91b6020820152610100820152630000213a6300005750565b600781526611a19a1b98992360c91b602082015261012082015263000021606300005750565b600781526611a1222198a12360c91b602082015261014082015263000021866300005750565b600781526608d0cd8dcd4e0d60ca1b602082015261016082015263000021ac6300005750565b60078152660466e6882826e760cb1b602082015261018082015263000021d26300005750565b60078152662341383532393160c81b60208201526101a082015263000021f86300005750565b600781526608d0918e4d911160ca1b60208201526101c0820152630000221e6300005750565b60078152662344423744383160c81b60208201526101e082015263000022446300005750565b60078152662345353942383760c81b6020820152610200820152630000226a6300005750565b60078152661198189ba1a12360c91b60208201526102208201526028546012602855806012106300003e7b575b5060286000908152600080516020630000a257833981519152915b601282106300003d4a5763000022c8630000570c565b63000022d46300005750565b600781526611a3231ca1192360c91b6020820152815263000022f66300005750565b60078152660233545333345360cc1b60208201526020820152630000231b6300005750565b600781526608cdd0cccccdcd60ca1b6020820152604082015263000023406300005750565b600781526608d0d1514c8d5160ca1b6020820152606082015263000023656300005750565b60078152662331324139434360c81b60208201526080820152630000238a6300005750565b60078152662345323943413760c81b602082015260a082015263000023af6300005750565b60078152660234136374645360cc1b602082015260c082015263000023d46300005750565b60078152662344383642363560c81b602082015260e082015263000023f96300005750565b60078152662335414243373960c81b6020820152610100820152630000241f6300005750565b60078152662336444131424160c81b602082015261012082015263000024456300005750565b60078152662339313345343960c81b6020820152610140820152630000246b6300005750565b60078152662346463644383160c81b602082015261016082015263000024916300005750565b60078152660234442414630360cc1b602082015261018082015263000024b76300005750565b600781526611a09c20a2a32360c91b60208201526101a082015263000024dd6300005750565b60078152662345353942383760c81b60208201526101c082015263000025036300005750565b60078152660466c666a626a760cb1b60208201526101e082015263000025296300005750565b600781526608d10e0d4c0d5160ca1b6020820152610200820152630000254f6300005750565b600781526608d0cccccccdcd60ca1b60208201526102208201526029546012602955806012106300003c94575b5060296000908152600080516020630000a197833981519152915b601282106300003b635763000025ad630000572e565b63000025b96300005750565b60078152662337434646383360c81b6020820152815263000025db6300005750565b60078152661198181c99a32360c91b6020820152602082015263000026006300005750565b600781526608ce4d9191918d60ca1b6020820152604082015263000026256300005750565b600781526611a2a1a323212360c91b60208201526060820152630000264a6300005750565b60078152662346323639373960c81b60208201526080820152630000266f6300005750565b600781526611a3232298a22360c91b602082015260a082015263000026946300005750565b600781526611a09b9c99a11960c91b602082015260c082015263000026b96300005750565b60078152662346324534373960c81b602082015260e082015263000026de6300005750565b60078152662342314530433960c81b602082015261010082015263000027046300005750565b600781526611a219a3231b1b60c91b6020820152610120820152630000272a6300005750565b60078152662333364532434560c81b602082015261014082015263000027506300005750565b60078152660234530374346360cc1b602082015261016082015263000027766300005750565b60078152660233545333345360cc1b6020820152610180820152630000279c6300005750565b600781526608d1918dcdd04d60ca1b60208201526101a082015263000027c26300005750565b600781526608ce110e0c111160ca1b60208201526101c082015263000027e86300005750565b60078152662341464346393360c81b60208201526101e0820152630000280e6300005750565b600781526611a09c20a2a32360c91b6020820152610200820152602a546011602a55806011106300003aad575b50602a6000908152600080516020630000a1d7833981519152915b60118210630000397c57630000286c630000572e565b63000028786300005750565b60078152662346463731443360c81b60208201528152630000289a6300005750565b60078152662344333644453560c81b6020820152602082015263000028bf6300005750565b60078152662333414534454160c81b6020820152604082015263000028e46300005750565b60078152662344314646423760c81b6020820152606082015263000029096300005750565b60078152662346464639443360c81b60208201526080820152630000292e6300005750565b60078152662337464538423960c81b602082015260a082015263000029536300005750565b60078152662346464646423960c81b602082015260c082015263000029786300005750565b60078152662343433730433560c81b602082015260e0820152630000299d6300005750565b600781526608d14c0e50ce0d60ca1b602082015261010082015263000029c36300005750565b60078152662341464346393360c81b602082015261012082015263000029e96300005750565b60078152662333443634434560c81b60208201526101408201526300002a0f6300005750565b60078152662343434343333960c81b60208201526101608201526300002a356300005750565b60078152662330303831423560c81b60208201526101808201526300002a5b6300005750565b60078152662339334535434160c81b60208201526101a08201526300002a816300005750565b60078152662345324242423760c81b60208201526101c08201526300002aa76300005750565b6007815266046888872666c760cb1b60208201526101e08201526300002acd6300005750565b600781526611a21c1b9b9c2360c91b6020820152610200820152602b546011602b558060111063000038c6575b50602b6000908152600080516020630000a237833981519152915b601182106300003795576040516001600160401b0361028082019081119082111763000033975761028081016040526300002b506300005750565b600781526608d19191918e0d60ca1b602082015281526300002b726300005750565b60078152662346394646463760c81b602082015260208201526300002b976300005750565b6007815266119818232321a160c91b602082015260408201526300002bbc6300005750565b600781526611a21a9ca1232360c91b602082015260608201526300002be16300005750565b60078152661198182323232360c91b602082015260808201526300002c066300005750565b60078152662346463838384360c81b602082015260a08201526300002c2b6300005750565b600781526611a319a3231ca160c91b602082015260c08201526300002c506300005750565b60078152662346463945413160c81b602082015260e08201526300002c756300005750565b60078152662331454646374360c81b60208201526101008201526300002c9b6300005750565b6007815266119918a2a1a32360c91b60208201526101208201526300002cc16300005750565b60078152662342343634453560c81b60208201526101408201526300002ce76300005750565b60078152662346464646423560c81b60208201526101608201526300002d0d6300005750565b60078152660234236464630360cc1b60208201526101808201526300002d336300005750565b600781526611989a2221232360c91b60208201526101a08201526300002d596300005750565b60078152662346414646453560c81b60208201526101c08201526300002d7f6300005750565b600781526608d1918dcdd04d60ca1b60208201526101e08201526300002da56300005750565b6007815266119b18a11b232360c91b60208201526102008201526300002dcb6300005750565b600781526611a3209c19232360c91b60208201526102208201526300002df16300005750565b60078152660234138464643360cc1b60208201526102408201526300002e176300005750565b60078152662346464439464160c81b6020820152610260820152602c546014602c558060141063000036df575b50602c6000908152600080516020630000a117833981519152915b6014821063000035ae576040516001600160401b036102a08201908111908211176300003397576102a081016040526300002e9a6300005750565b600781526611a219a3231b1b60c91b602082015281526300002ebc6300005750565b60078152662346463743463560c81b602082015260208201526300002ee16300005750565b60078152662343343030414160c81b602082015260408201526300002f066300005750565b60078152662342434532354160c81b602082015260608201526300002f2b6300005750565b6007815266119c181a229a9960c91b602082015260808201526300002f506300005750565b600781526611999c1c9c9a1960c91b602082015260a08201526300002f756300005750565b60078152660466c666a626a760cb1b602082015260c08201526300002f9a6300005750565b60078152660233832334234360cc1b602082015260e08201526300002fbf6300005750565b60078152662346463845373760c81b60208201526101008201526300002fe56300005750565b60078152662346463930373560c81b6020820152610120820152630000300b6300005750565b60078152662346464346393360c81b602082015261014082015263000030316300005750565b600781526611a2991c209a1b60c91b602082015261016082015263000030576300005750565b600781526611a09b9c99a11960c91b6020820152610180820152630000307d6300005750565b600781526608d1918dcdd04d60ca1b60208201526101a082015263000030a36300005750565b60078152662341313030363360c81b60208201526101c082015263000030c96300005750565b600781526608d1918c0c0d5160ca1b60208201526101e082015263000030ef6300005750565b60078152662335344345354360c81b602082015261020082015263000031156300005750565b60078152661199a11c9899a360c91b6020820152610220820152630000313b6300005750565b60078152662345384541383360c81b602082015261024082015263000031616300005750565b600781526608d1918d51518d60ca1b602082015261026082015263000031876300005750565b600781526611981822199ca160c91b6020820152610280820152602d546015602d558060151063000034f8575b50602d6000908152600080516020630000a0b7833981519152915b6015821063000033ad5760008052601c6020526040517fb9c6de81004e18dedadca3e5eabaab449ca91dff6f58efc9461da635fe77f849608082016001600160401b038111838210176300003397576040526000825260208201906014825260408301601881526060840191600483528054680100000000000000008110156300003397576001810180835581101563000033815760ff9160005260206000200194511663ff00000062ff000061ff008754965160081b16935160101b16935160181b169363ffffffff19161717171790556001602e553315630000333c576002546702ea11e32ad5000090818101809111630000332657600255336000526000602052604060002081815401905560405190815260007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60203393a36040516148aa908163000057cd82396080518161277c0152f35b634e487b7160e01b600052601160045260246000fd5b60405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606490fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b80518051906001600160401b03821163000033975763000033d08554630000578c565b601f811163000034b1575b50602090601f831160011463000034385792630000341a83600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b0193019101909163000031cf565b0151905089806300000097565b908560005260206000209160005b601f1985168110630000349757509260209260019592869583601f19811610630000347c575b505050831b83018655630000341d565b015160001960f88460031b161c19169055878080630000346c565b828201518455600190930192602092830192016300003446565b63000034e490866000526020600020601f850160051c8101916020861063000034ec575b601f0160051c01906300005771565b8563000033db565b909150819063000034d5565b602d600052600080516020630000a0b7833981519152907f4a2cc91ee622da3bc833a54c37ffcb6f3ec23b7793efc5eaf5e71b7b406c5c1b5b8183018110630000354557505063000031b4565b80630000355660019254630000578c565b806300003567575b50016300003531565b601f8111831463000035815750600081555b85630000355e565b60009082825263000035a3601f60208420920160051c82018583016300005771565b818355556300003579565b80518051906001600160401b03821163000033975763000035d18554630000578c565b601f811163000036a5575b50602090601f8311600114630000362c5792630000361b83600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b019301910190916300002e5f565b908560005260206000209160005b601f1985168110630000368b57509260209260019592869583601f198116106300003670575b505050831b83018655630000361e565b015160001960f88460031b161c191690558780806300003660565b82820151845560019093019260209283019201630000363a565b63000036d790866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b8563000035dc565b602c600052600080516020630000a117833981519152907f7416c943b4a09859521022fd2e90eac0dd9026dad28fa317782a135f28a860a55b8183018110630000372c5750506300002e44565b80630000373d60019254630000578c565b80630000374e575b50016300003718565b601f8111831463000037685750600081555b856300003745565b600090828252630000378a601f60208420920160051c82018583016300005771565b818355556300003760565b80518051906001600160401b03821163000033975763000037b88554630000578c565b601f8111630000388c575b50602090601f831160011463000038135792630000380283600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b019301910190916300002b15565b908560005260206000209160005b601f1985168110630000387257509260209260019592869583601f198116106300003857575b505050831b830186556300003805565b015160001960f88460031b161c191690558780806300003847565b828201518455600190930192602092830192016300003821565b63000038be90866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b8563000037c3565b602b600052600080516020630000a237833981519152907f11c44e4875b74d31ff9fd779bf2566af7bd15b87fc985d01f5094b89e3669e605b818301811063000039135750506300002afa565b80630000392460019254630000578c565b806300003935575b500163000038ff565b601f81118314630000394f5750600081555b85630000392c565b6000908282526300003971601f60208420920160051c82018583016300005771565b818355556300003947565b80518051906001600160401b038211630000339757630000399f8554630000578c565b601f81116300003a73575b50602090601f831160011463000039fa579263000039e983600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b019301910190916300002856565b908560005260206000209160005b601f19851681106300003a5957509260209260019592869583601f198116106300003a3e575b505050831b8301865563000039ec565b015160001960f88460031b161c191690558780806300003a2e565b828201518455600190930192602092830192016300003a08565b6300003aa590866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b8563000039aa565b602a600052600080516020630000a1d7833981519152907fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545e35b81830181106300003afa575050630000283b565b806300003b0b60019254630000578c565b806300003b1c575b50016300003ae6565b601f811183146300003b365750600081555b856300003b13565b6000908282526300003b58601f60208420920160051c82018583016300005771565b818355556300003b2e565b80518051906001600160401b0382116300003397576300003b868554630000578c565b601f81116300003c5a575b50602090601f83116001146300003be157926300003bd083600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b019301910190916300002597565b908560005260206000209160005b601f19851681106300003c4057509260209260019592869583601f198116106300003c25575b505050831b830186556300003bd3565b015160001960f88460031b161c191690558780806300003c15565b828201518455600190930192602092830192016300003bef565b6300003c8c90866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b856300003b91565b6029600052600080516020630000a197833981519152907fcb7c14ce178f56e2e8d86ab33ebc0ae081ba8556a00cd122038841867181cabe5b81830181106300003ce1575050630000257c565b806300003cf260019254630000578c565b806300003d03575b50016300003ccd565b601f811183146300003d1d5750600081555b856300003cfa565b6000908282526300003d3f601f60208420920160051c82018583016300005771565b818355556300003d15565b80518051906001600160401b0382116300003397576300003d6d8554630000578c565b601f81116300003e41575b50602090601f83116001146300003dc857926300003db783600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b0193019101909163000022b2565b908560005260206000209160005b601f19851681106300003e2757509260209260019592869583601f198116106300003e0c575b505050831b830186556300003dba565b015160001960f88460031b161c191690558780806300003dfc565b828201518455600190930192602092830192016300003dd6565b6300003e7390866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b856300003d78565b6028600052600080516020630000a257833981519152907fe16da923a2d88192e5070f37b4571d58682c0d66212ec634d495f33de3f77ac75b81830181106300003ec85750506300002297565b806300003ed960019254630000578c565b806300003eea575b50016300003eb4565b601f811183146300003f045750600081555b856300003ee1565b6000908282526300003f26601f60208420920160051c82018583016300005771565b818355556300003efc565b80518051906001600160401b0382116300003397576300003f548554630000578c565b601f81116300004028575b50602090601f83116001146300003faf57926300003f9e83600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b019301910190916300001fd5565b908560005260206000209160005b601f1985168110630000400e57509260209260019592869583601f198116106300003ff3575b505050831b830186556300003fa1565b015160001960f88460031b161c191690558780806300003fe3565b828201518455600190930192602092830192016300003fbd565b630000405a90866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b856300003f5f565b6027600052600080516020630000a0d7833981519152907f98a476f1687bc3d60a2da2adbcba2c46958e61fa2fb4042cd7bc5816a710196e5b818301811063000040af5750506300001fba565b8063000040c060019254630000578c565b8063000040d1575b5001630000409b565b601f8111831463000040eb5750600081555b8563000040c8565b600090828252630000410d601f60208420920160051c82018583016300005771565b8183555563000040e3565b80518051906001600160401b038211630000339757630000413b8554630000578c565b601f8111630000420f575b50602090601f831160011463000041965792630000418583600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b019301910190916300001cb1565b908560005260206000209160005b601f198516811063000041f557509260209260019592869583601f1981161063000041da575b505050831b830186556300004188565b015160001960f88460031b161c1916905587808063000041ca565b8282015184556001909301926020928301920163000041a4565b630000424190866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b856300004146565b6026600052600080516020630000a137833981519152907f744a2cf8fd7008e3d53b67916e73460df9fa5214e3ef23dd4259ca09493a35a45b818301811063000042965750506300001c96565b8063000042a760019254630000578c565b8063000042b8575b50016300004282565b601f8111831463000042d25750600081555b8563000042af565b60009082825263000042f4601f60208420920160051c82018583016300005771565b8183555563000042ca565b80518051906001600160401b03821163000033975763000043228554630000578c565b601f811163000043f6575b50602090601f8311600114630000437d5792630000436c83600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b019301910190916300001a31565b908560005260206000209160005b601f198516811063000043dc57509260209260019592869583601f1981161063000043c1575b505050831b83018655630000436f565b015160001960f88460031b161c1916905587808063000043b1565b82820151845560019093019260209283019201630000438b565b630000442890866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b85630000432d565b6025600052600080516020630000a077833981519152907f401968ff42a154441da5f6c4c935ac46b8671f0e062baaa62a7545ba53bb6e5a5b8183018110630000447d5750506300001a16565b80630000448e60019254630000578c565b80630000449f575b50016300004469565b601f8111831463000044b95750600081555b856300004496565b60009082825263000044db601f60208420920160051c82018583016300005771565b8183555563000044b1565b80518051906001600160401b03821163000033975763000045098554630000578c565b601f811163000045dd575b50602090601f831160011463000045645792630000455383600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b0193019101909163000017e4565b908560005260206000209160005b601f198516811063000045c357509260209260019592869583601f1981161063000045a8575b505050831b830186556300004556565b015160001960f88460031b161c191690558780806300004598565b828201518455600190930192602092830192016300004572565b630000460f90866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b856300004514565b6024600052600080516020630000a277833981519152907f7cd332d19b93bcabe3cce7ca0c18a052f57e5fd03b4758a09f30f5ddc4b22ed35b8183018110630000466457505063000017c9565b80630000467560019254630000578c565b806300004686575b50016300004650565b601f8111831463000046a05750600081555b85630000467d565b60009082825263000046c2601f60208420920160051c82018583016300005771565b818355556300004698565b80518051906001600160401b03821163000033975763000046f08554630000578c565b601f811163000047c4575b50602090601f8311600114630000474b5792630000473a83600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b019301910190916300001558565b908560005260206000209160005b601f198516811063000047aa57509260209260019592869583601f19811610630000478f575b505050831b83018655630000473d565b015160001960f88460031b161c19169055878080630000477f565b828201518455600190930192602092830192016300004759565b63000047f690866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b8563000046fb565b6023600052600080516020630000a217833981519152907fd57b2b5166478fd4318d2acc6cc2c704584312bdd8781b32d5d06abda57f42405b8183018110630000484b575050630000153d565b80630000485c60019254630000578c565b80630000486d575b50016300004837565b601f8111831463000048875750600081555b856300004864565b60009082825263000048a9601f60208420920160051c82018583016300005771565b81835555630000487f565b80518051906001600160401b03821163000033975763000048d78554630000578c565b601f811163000049ab575b50602090601f831160011463000049325792630000492183600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b0193019101909163000012d1565b908560005260206000209160005b601f1985168110630000499157509260209260019592869583601f198116106300004976575b505050831b830186556300004924565b015160001960f88460031b161c191690558780806300004966565b828201518455600190930192602092830192016300004940565b63000049dd90866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b8563000048e2565b6022600052600080516020630000a157833981519152907f61035b26e3e9eee00e0d72fd1ee8ddca6894550dca6916ea2ac6baa90d11e5285b81830181106300004a3257505063000012b6565b806300004a4360019254630000578c565b806300004a54575b50016300004a1e565b601f811183146300004a6e5750600081555b856300004a4b565b6000908282526300004a90601f60208420920160051c82018583016300005771565b818355556300004a66565b80518051906001600160401b0382116300003397576300004abe8554630000578c565b601f81116300004b92575b50602090601f83116001146300004b1957926300004b0883600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b019301910190916300000eef565b908560005260206000209160005b601f19851681106300004b7857509260209260019592869583601f198116106300004b5d575b505050831b830186556300004b0b565b015160001960f88460031b161c191690558780806300004b4d565b828201518455600190930192602092830192016300004b27565b6300004bc490866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b856300004ac9565b6021600052600080516020630000a177833981519152907f3a6357012c1a3ae0a17d304c9920310382d968ebcc4b1771f41c6b304205b5895b81830181106300004c195750506300000ed4565b806300004c2a60019254630000578c565b806300004c3b575b50016300004c05565b601f811183146300004c555750600081555b856300004c32565b6000908282526300004c77601f60208420920160051c82018583016300005771565b818355556300004c4d565b80518051906001600160401b0382116300003397576300004ca58554630000578c565b601f81116300004d79575b50602090601f83116001146300004d0057926300004cef83600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b019301910190916300000ae7565b908560005260206000209160005b601f19851681106300004d5f57509260209260019592869583601f198116106300004d44575b505050831b830186556300004cf2565b015160001960f88460031b161c191690558780806300004d34565b828201518455600190930192602092830192016300004d0e565b6300004dab90866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b856300004cb0565b6020600052600080516020630000a097833981519152907fc97bfaf2f8ee708c303a06d134f5ecd8389ae0432af62dc132a24118292866c95b81830181106300004e005750506300000acc565b806300004e1160019254630000578c565b806300004e22575b50016300004dec565b601f811183146300004e3c5750600081555b856300004e19565b6000908282526300004e5e601f60208420920160051c82018583016300005771565b818355556300004e34565b80518051906001600160401b0382116300003397576300004e8c8554630000578c565b601f81116300004f60575b50602090601f83116001146300004ee757926300004ed683600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b01930191019091630000089a565b908560005260206000209160005b601f19851681106300004f4657509260209260019592869583601f198116106300004f2b575b505050831b830186556300004ed9565b015160001960f88460031b161c191690558780806300004f1b565b828201518455600190930192602092830192016300004ef5565b6300004f9290866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b856300004e97565b601f600052600080516020630000a1f7833981519152907fa03837a25210ee280c2113ff4b77ca23440b19d4866cca721c801278fd08d8145b81830181106300004fe7575050630000087f565b806300004ff860019254630000578c565b806300005009575b50016300004fd3565b601f8111831463000050235750600081555b856300005000565b6000908282526300005045601f60208420920160051c82018583016300005771565b81835555630000501b565b80518051906001600160401b03821163000033975763000050738554630000578c565b601f81116300005147575b50602090601f831160011463000050ce579263000050bd83600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b019301910190916300000673565b908560005260206000209160005b601f1985168110630000512d57509260209260019592869583601f198116106300005112575b505050831b8301865563000050c0565b015160001960f88460031b161c191690558780806300005102565b8282015184556001909301926020928301920163000050dc565b630000517990866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b85630000507e565b601e600052600080516020630000a1b7833981519152907f50bb669a95c7b50b7e8a6f09454034b2b14cf2b85c730dca9a539ca82cb6e35d5b818301811063000051ce5750506300000658565b8063000051df60019254630000578c565b8063000051f0575b500163000051ba565b601f81118314630000520a5750600081555b8563000051e7565b600090828252630000522c601f60208420920160051c82018583016300005771565b818355556300005202565b80518051906001600160401b038211630000339757630000525a8554630000578c565b601f8111630000532e575b50602090601f831160011463000052b5579263000052a483600195946020948796600092630000342b5750508160011b916000199060031b1c19161790565b86555b01930191019091630000044c565b908560005260206000209160005b601f1985168110630000531457509260209260019592869583601f1981161063000052f9575b505050831b8301865563000052a7565b015160001960f88460031b161c1916905587808063000052e9565b8282015184556001909301926020928301920163000052c3565b630000536090866000526020600020601f850160051c8101916020861063000034ec57601f0160051c01906300005771565b856300005265565b601d600052600080516020630000a0f7833981519152907f6d4407e7be21f808e6509aa9fa9143369579dd7d760fe20a2c09680fc146135c5b818301811063000053b55750506300000431565b8063000053c660019254630000578c565b8063000053d7575b500163000053a1565b601f8111831463000053f15750600081555b8563000053ce565b6000908282526300005413601f60208420920160051c82018583016300005771565b8183555563000053e9565b9091602063000054456001928460ff875116919060ff809160031b9316831b921b19161790565b930191016300000221565b9091602063000054776001928460ff875116919060ff809160031b9316831b921b19161790565b9301910163000001e1565b9091602063000054a96001928460ff875116919060ff809160031b9316831b921b19161790565b9301910163000001a1565b9091602063000054db6001928460ff875116919060ff809160031b9316831b921b19161790565b930191016300000161565b0151905038806300000097565b601f19821692600460005260206000209160005b858110630000554857508360019510630000552d575b505050811b016004556300000116565b015160001960f88460031b161c19169055388080630000551d565b919260206001819286850151815501940192016300005507565b600460005263000055b1907f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b601f840160051c8101916020851063000034ec57601f0160051c01906300005771565b3863000000dc565b601f19821693600360005260206000209160005b868110630000560f575083600195961063000055f4575b505050811b0160035563000000b0565b015160001960f88460031b161c1916905538808063000055e4565b9192602060018192868501518155019401920163000055cd565b60036000526300005678907fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b601f840160051c8101916020851063000034ec57601f0160051c01906300005771565b386300000073565b600080fd5b6040519060a082016001600160401b03811183821017630000339757604052565b604051906101a082016001600160401b03811183821017630000339757604052565b604051906101c082016001600160401b03811183821017630000339757604052565b6040519061020082016001600160401b03811183821017630000339757604052565b6040519061024082016001600160401b03811183821017630000339757604052565b6040519061022082016001600160401b03811183821017630000339757604052565b60408051919082016001600160401b03811183821017630000339757604052565b818110630000577e575050565b600081556001016300005771565b90600182811c9216801563000057c0575b602083101463000057aa57565b634e487b7160e01b600052602260045260246000fd5b91607f1691630000579d56fe608080604052600436101561001357600080fd5b60003560e01c90816306fdde031461297257508063095ea7b31461294c57806316f0115b1461292357806318160ddd14612905578063187c03bb146127c6578063214013ca1461275e57806323b872dd146126a0578063313ce56714612684578063333a00721461262857806335ad0cea1461254257806339509351146124f15780633ebccc57146124b7578063422b9e2314611900578063524773ce146118ce57806363f779eb1461178f57806368b77feb1461173a5780636a3ce0c71461171c5780636b4ed21b146116fe57806370a08231146116c457806370db69d6146116a15780638da5cb5b1461167857806391d2e92b14610e885780639477b85214610e6a57806395d89b4114610d5a5780639fc3ef6114610c01578063a285f05b14610a65578063a457c2d7146109be578063a9059cbb1461098d578063c3f4552a1461034f578063c5b8f77214610302578063cb8106f4146102c1578063dd62ed3e14610270578063e5100df8146101e15763f2fde38b1461019557600080fd5b346101dc5760203660031901126101dc576101ae612a7c565b601354906001600160a01b03906101c88284163314612c3f565b6001600160a01b0319909216911617601355005b600080fd5b346101dc5760403660031901126101dc576101fa612a7c565b6000602060405161020a81612af5565b828152015260018060a01b03166000526009602052604060002060243560005260205261026c604060002060016040519161024483612af5565b8054835201546020820152604051918291829190916020806040830194805184520151910152565b0390f35b346101dc5760403660031901126101dc57610289612a7c565b610291612a92565b9060018060a01b038091166000526001602052604060002091166000526020526020604060002054604051908152f35b346101dc5760203660031901126101dc576004356000908152600d60209081526040909120546001600160a01b03166040516001600160a01b039091168152f35b346101dc5760403660031901126101dc576001600160a01b03610323612a7c565b16600052600b6020526040600020602435600052602052602060ff604060002054166040519015158152f35b346101dc5760403660031901126101dc576040516391d2e92b60e01b815260048035908201526024803590820152600081604481305afa80156109815761026c9160009161095e575b5061092160226103a883516134fe565b6103e66028604051809367113632bb32b6111d60c11b60208301526103d68151809260208686019101612a34565b8101036008810184520182612b4a565b60208401519361047b60416040830151966040519788916e16113130b1b5b3b937bab732111d1160891b6020840152610429815180926020602f87019101612a34565b8201601160f91b602f8201526f16113130b1b5b3b937bab73219111d1160811b6030820152610462825180936020604085019101612a34565b01601160f91b6040820152036021810188520186612b4a565b60c0810151156109515761048d612fdb565b610546604861049f60e08501516134fe565b926101008501516040519485926c16113430b9a13ab1313632911d60991b60208501526104d6815180926020602d88019101612a34565b8301691611313ab1313632911d60b11b602d8201526104ff825180936020603785019101612a34565b016f1611313ab1313632a1b7b637b9111d1160811b603782015261052d825180936020604785019101612a34565b01601160f91b6047820152036028810184520182612b4a565b60608201511561094357610558612fdb565b905b6105dd603e60a0850151936040519485916c16113430b9a3b937bab732111d60991b6020840152610595815180926020602d87019101612a34565b82016f161133b937bab73221b7b637b9111d1160811b602d8201526105c4825180936020603d85019101612a34565b01601160f91b603d82015203601e810185520183612b4a565b61012083015115610935576105f0612fdb565b905b6106a560426106056101408701516134fe565b936101608701516040519586926a16113430b9abb2b2b2111d60a91b602085015261063a815180926020602b88019101612a34565b83016716113bb2b2b2111d60c11b602b820152610661825180936020603385019101612a34565b016d16113bb2b2b221b7b637b9111d1160911b603382015261068d825180936020604185019101612a34565b01601160f91b60418201520388810185520183612b4a565b6106b36101808501516134fe565b9161073160396106c76101a08801516134fe565b946040519586916d161136b4b93937b92a34b6b2911d60911b60208401526106f9815180926020602e87019101612a34565b82016a16113137b12a34b6b2911d60a91b602e8201526107228251809360208785019101612a34565b01036019810186520184612b4a565b61073f6101c08601516134fe565b936107c5603f6101e0880151966040519788916b16113a32b73a30b1b632911d60a11b602084015261077b815180926020602c87019101612a34565b82017116113a32b73a30b1b632a1b7b637b9111d1160711b602c8201526107ac825180936020603e85019101612a34565b01601160f91b603e82015203601f810188520186612b4a565b61085060376102206107db6102008a01516134fe565b980151976040519889916716113132b636111d60c11b602084015261080a815180926020602887019101612a34565b82016d16113132b63621b7b637b9111d1160911b6028820152610837825180936020603685019101612a34565b01601160f91b6036820152036017810189520187612b4a565b604051998a97607b60f81b60208a015261087481518092602060218d019101612a34565b880161088a825180936020602185019101612a34565b0161089f825180936020602185019101612a34565b016108b4825180936020602185019101612a34565b016108c9825180936020602185019101612a34565b016108de825180936020602185019101612a34565b016108f3825180936020602185019101612a34565b01610908825180936020602185019101612a34565b01607d60f81b6021820152036002810184520182612b4a565b604051918291602083526020830190612a57565b61093d612fba565b906105f2565b61094b612fba565b9061055a565b610959612fba565b61048d565b61097b91503d806000833e6109738183612b4a565b810190612d1f565b82610398565b6040513d6000823e3d90fd5b346101dc5760403660031901126101dc576109b36109a9612a7c565b60243590336130fd565b602060405160018152f35b346101dc5760403660031901126101dc576109d7612a7c565b60243590336000526001602052604060002060018060a01b03821660005260205260406000205491808310610a12576109b392039033612ffb565b60405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608490fd5b346101dc57610a7336612aa8565b610a8860018060a01b03601354163314612c3f565b6000905b808210610a9557005b8160051b830135605e19843603018112156101dc57839193018035600052601893602091858352604060002083820135600052835260406000209360009260408301935b610ae38585613549565b9050811015610bed57610af68585613549565b821015610bd7578160071b01908754600160401b811015610bc157806001610b2192018a558961357f565b610bab5787838c60ff610b35600197613597565b1663ff00000061ff00610b548754968460ff1989161789558601613597565b60081b1692838361ffff19881617178755610b94606062ff0000610b7a60408901613597565b60101b1696878662ffffff198b16178817178a5501613597565b901b169363ffffffff191617171717905501610ad9565b634e487b7160e01b600052600060045260246000fd5b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b509650949250505060019150019091610a8c565b346101dc57610c0f36612aa8565b90610c2560018060a01b03601354163314612c3f565b6000905b828210610c3257005b8160051b810135605e19823603018112156101dc5781939101908135600052602091601a8352604060002083820135600052835260406000209460009260408301935b610c7f8585613549565b9050811015610d4857610c928585613549565b821015610bd7578160071b01908854600160401b811015610bc157806001610cbd92018b558a61357f565b610bab578260ff610ccf600195613597565b16908254918060ff19841617845561ff00610ceb8c8401613597565b60081b1690818161ffff1986161717855563ff000000610d30606062ff0000610d1660408801613597565b60101b1695868562ffffff198a1617871717895501613597565b60181b169363ffffffff191617171717905501610c75565b50955093915050600191500190610c29565b346101dc5760003660031901126101dc5760405160006004549060018260011c9160018416918215610e60575b6020948585108414610e4a578587948686529182600014610e2a575050600114610dcd575b50610db992500383612b4a565b61026c604051928284938452830190612a57565b84915060046000527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b906000915b858310610e12575050610db9935082010185610dac565b80548389018501528794508693909201918101610dfb565b60ff191685820152610db995151560051b8501019250879150610dac9050565b634e487b7160e01b600052602260045260246000fd5b92607f1692610d87565b346101dc5760003660031901126101dc576020600f54604051908152f35b346101dc5760403660031901126101dc57610ea1612f35565b506040516060810181811067ffffffffffffffff821117610bc1576040526004358152600060208201526024356040820152610edb612f35565b610ee4826133da565b8152610efc610ef2836133da565b8061166a57613ea3565b8054610f0781612c78565b91610f156040519384612b4a565b818352602083019060005260206000206000915b83831061164d578686610f5087610f4a610f4285613eea565b82519061342c565b90612c9d565b5160208201526004610f61836133da565b8061163f575b10156115b157602081015160408201525b600380610f8484613eea565b16108060c08301526114ce575b6004610f9c836133da565b806114c0575b10611412575b6004610fb3836133da565b10611326575b6003610fc483613eea565b0660030180600311611302576101808201526002610fe1836133da565b80611318575b10156112e05760006101a08201525b610fff82613eea565b611008836133da565b90816112d0575b6005821015610bd75760ff8260f86110359460051c601601549160031b161c169061342c565b6101c0820152611051611047836133da565b8061129557613f85565b805461105c81612c78565b9161106a6040519384612b4a565b818352602083019060005260206000206000915b8383106112b357868661109787610f4a610f4285613eea565b516101e08201526110a782613eea565b6110b0836133da565b90816112a3575b6005821015610bd75760ff8260f86110dd9460051c601701549160031b161c169061342c565b6102008201526110ef611047836133da565b9182546110fb81612c78565b936111096040519586612b4a565b818552602085019060005260206000206000915b8383106112785761026c8661113889610f4a610f428a613eea565b51610220820152604051918291602083528051602084015261022061125961121e6111bc61119061117a602087015161024060408b01526102608a0190612a57565b6040870151898203601f190160608b0152612a57565b606086015115156080890152608086015160a089015260a0860151601f198983030160c08a0152612a57565b60c0850151151560e08801526111f060e086015161010090818a01528601519161012092601f198a830301848b0152612a57565b90850151610140901515818901528501516101609081890152850151601f1988830301610180890152612a57565b6101808401516101a090818801528401516101c08701526101c08401516101e08701526101e0840151601f1987830301610200880152612a57565b61020083015185830152910151838203601f1901610240850152612a57565b60016020819261128785612b6c565b81520192019201919061111d565b61129e90613e96565b613f85565b906112ad90613e96565b906110b7565b6001602081926112c285612b6c565b81520192019201919061107e565b906112da90613e96565b9061100f565b60076112eb83613eea565b1660080180600811611302576101a0820152610ff6565b634e487b7160e01b600052601160045260246000fd5b61132190613e96565b610fe7565b60038061133284613eea565b16108061012083015215610fb95761134982613eea565b611352836133da565b9081611402575b6005821015610bd75760ff8260f861137f9460051c601401549160031b161c169061342c565b610140820152611391611047836133da565b805461139c81612c78565b916113aa6040519384612b4a565b818352602083019060005260206000206000915b8383106113e557505050506113d990610f4a610f4285613eea565b51610160820152610fb9565b6001602081926113f485612b6c565b8152019201920191906113be565b9061140c90613e96565b90611359565b600180606083015261142383613eea565b5060006080830152611441611437846133da565b806114b257613f4c565b90815461144d81612c78565b9261145b6040519485612b4a565b818452602084019060005260206000206000915b83831061149657505050505061148b90610f4a610f4285613eea565b5160a0820152610fa8565b84602081926114a485612b6c565b81520192019201919061146f565b6114bb90613e96565b613f4c565b6114c990613e96565b610fa2565b6114d782613eea565b6114e0836133da565b90816115a1575b6005821015610bd75760ff8260f861150d9460051c601501549160031b161c169061342c565b60e082015260235461151e81612c78565b9061152c6040519283612b4a565b8082526020820160236000527fd57b2b5166478fd4318d2acc6cc2c704584312bdd8781b32d5d06abda57f42306000915b838310611584575050505061157890610f4a610f4285613eea565b51610100820152610f91565b60016020819261159385612b6c565b81520192019201919061155d565b906115ab90613e96565b906114e7565b6022546115bd81612c78565b906115cb6040519283612b4a565b8082526020820160226000527f61035b26e3e9eee00e0d72fd1ee8ddca6894550dca6916ea2ac6baa90d11e5106000915b838310611622575050505061161790610f4a610f4285613eea565b516040820152610f78565b60016020819261163185612b6c565b8152019201920191906115fc565b61164890613e96565b610f67565b60016020819261165c85612b6c565b815201920192019190610f29565b61167390613e96565b613ea3565b346101dc5760003660031901126101dc576013546040516001600160a01b039091168152602090f35b346101dc5760003660031901126101dc5760206116bc612eb6565b604051908152f35b346101dc5760203660031901126101dc576001600160a01b036116e5612a7c565b1660005260006020526020604060002054604051908152f35b346101dc5760003660031901126101dc576020601054604051908152f35b346101dc5760003660031901126101dc576020601154604051908152f35b346101dc5760203660031901126101dc57611753612a7c565b6000602060405161176381612af5565b828152015260018060a01b0316600052600c60205261026c604060002060016040519161024483612af5565b346101dc5761179d36612aa8565b906117b360018060a01b03601354163314612c3f565b6000905b8282106117c057005b8160051b810135605e19823603018112156101dc578193910190813560005260209160198352604060002083820135600052835260406000209460009260408301935b61180d8585613549565b90508110156118bc576118208585613549565b821015610bd7578160071b01908854600160401b811015610bc15780600161184b92018b558a61357f565b610bab578260ff61185d600195613597565b16908254918060ff19841617845561ff006118798c8401613597565b60081b1690818161ffff1986161717855563ff0000006118a4606062ff0000610d1660408801613597565b60181b169363ffffffff191617171717905501611803565b509550939150506001915001906117b7565b346101dc5760003660031901126101dc576002546702ea11e32ad5000090810390811161130257602090604051908152f35b346101dc5760403660031901126101dc5761191c6004356134fe565b611965602061192c6024356134fe565b9260405193816119458693518092868087019101612a34565b820161195982518093868085019101612a34565b01038084520182612b4a565b6040516391d2e92b60e01b815260048035908201526024803590820152600081604481305afa9081156109815760009161249c575b506119a361345b565b916119ac61345b565b906101808301916119bd83516134fe565b916101a08501946119d86119d187516134fe565b96516134fe565b855160060180600611611302576119ee906134fe565b9786516002018060021161130257611a05906134fe565b965160140190816014116113025761026c9961240a996109219960269961222296611a326104b7976134fe565b916040519b8c977f3c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323060208a015273030302f737667272076696577426f783d273020360641b60408a01526055611a9d8a600160fd1b9384605483015260208151948593019101612a34565b8901906055820152611ab9825180936020605685019101612a34565b01917f272073686170652d72656e646572696e673d2763726973704564676573273e006056840152661e39ba3cb6329f60c91b607584015273406b65796672616d6573206d6972726f724b207b60601b607c8401527f30252c20353025207b207472616e73666f726d3a207363616c65582831293b206090840152607d60f81b958660b08501527f35302e31252c2031303025207b207472616e73666f726d3a207363616c65582860b1850152652d31293b207d60d01b60d18501528660d785015271406b65796672616d65732070756d704b207b60701b60d88501527f30252c2031303025207b207472616e73666f726d3a207472616e736c617465598060ea8601526628302e293b207d60c81b61010a8601527f353025207b207472616e73666f726d3a207472616e736c61746559282d302e34610111860152657078293b207d60d01b90816101318701528861013787015270406b65796672616d657320626f624b207b60781b61013887015261014986015266282d32293b207d60c81b6101698601527f353025207b207472616e73666f726d3a207472616e736c6174655928312e35706101708601526478293b207d60d81b806101908701528861019587015271406b65796672616d657320737761794b207b60701b6101968701527f30252c2031303025207b207472616e73666f726d3a207472616e736c6174655890816101a88801526a282d302e357078293b207d60a81b6101c88801527f353025207b207472616e73666f726d3a207472616e736c6174655828302e35706101d38801526101f3870152886101f887015275406b65796672616d65732073776179576565644b207b60501b6101f98701528061020f8701526b282d302e31357078293b207d60a01b61022f8701527f353025207b207472616e73666f726d3a207472616e736c6174655828302e313561023b8701528161025b870152886102618701527f406b65796672616d657320627562626c65526973654b207b00000000000000006102628701527f30257b207472616e73666f726d3a207472616e736c617465592832347078293b61027a87015261207d60f01b61029a8701527f31303025207b207472616e73666f726d3a207472616e736c61746559282d323461029c870152816102bc870152886102c28701527f406b65796672616d657320627562626c65576f62626c654b207b0000000000006102c38701526102dd8601526928302e327078293b207d60b01b6102fd8601527f353025207b207472616e73666f726d3a207472616e736c61746558282d302e326103078601526103278501528661032d850152661736b4b93937b960c91b61032e850152737320737465702d656e6420696e66696e6974653b60601b8d61033595611ec38251809360208a85019101612a34565b01936220207b60e81b809686015272030b734b6b0ba34b7b71d1036b4b93937b9259606d1b61033886015261034b94611f058251809360208985019101612a34565b01938401527f7472616e73666f726d2d6f726967696e3a2063656e7465722063656e7465723b61035f8401528661037f8401526402e70756d760dc1b610380840152838d61038594611f608251809360208985019101612a34565b019384015270030b734b6b0ba34b7b71d10383ab6b8259607d1b61038884015261039992611f978251809360208785019101612a34565b01927f7320656173652d696e2d6f757420696e66696e6974653b0000000000000000008093850152866103b085015263173137b160e11b6103b18501528c6103b594611fec8251809360208985019101612a34565b01938401526f030b734b6b0ba34b7b71d103137b125960851b6103b88401526103c8926120228251809360208785019101612a34565b01918201526103df8101849052642e7377617960d81b6103e082015289516103e5916120548284830160208f01612a34565b019461207b60f01b809287015270030b734b6b0ba34b7b71d1039bbb0bca59607d1b6103e78701526103f8956120938251809360208a85019101612a34565b01947173206c696e65617220696e66696e6974653b60701b938480928801528561040a880152680b9cddd85e55d9595960ba1b61040b880152828c610414986120e58251809360208d85019101612a34565b019788015274030b734b6b0ba34b7b71d1039bbb0bcabb2b2b2259605d1b61041688015261042b966121208251809360208b85019101612a34565b019586015261043d85018490526a2e627562626c655269736560a81b61043e8601528951610449956121588288830160208f01612a34565b01948501527f616e696d6174696f6e3a20627562626c65526973654b2000000000000000000061044b8501526104629361219b8251809360208885019101612a34565b0192830152806104748301526c2e627562626c6553776179207b60981b6104758301527f616e696d6174696f6e3a20627562626c65576f62626c654b203573206c696e656104828301526b617220696e66696e6974653b60a01b6104a28301526104ae820152671e17b9ba3cb6329f60c11b6104af82015203610497810186520184612b4a565b6020810151916040820151926123bd60f1604051809660208201947f3c6c696e6561724772616469656e742069643d274772616469656e74000000008652865161227381603c860160208b01612a34565b83017f272078313d2730272078323d2730272079313d2730272079323d2731273e0000603c8201527f3c73746f70206f66667365743d273025272073746f702d636f6c6f723d270000605a8201526122d5825180936020607885019101612a34565b0190631390179f60e11b918260788201527f3c73746f70206f66667365743d2731303025272073746f702d636f6c6f723d27607c820152612320825180936020609c85019101612a34565b0190609c820152701e17b634b732b0b923b930b234b2b73a1f60791b60a08201527f3c7265637420783d27302720793d2730272077696474683d273234272068656960b18201527f6768743d273234272066696c6c3d2775726c28234772616469656e740000000060d18201528551906123a18260ed830160208a01612a34565b01631493979f60e11b60ed8201520360d1810187520185612b4a565b6123c782846138a2565b6123d0846139a3565b916123ef6123de85876139db565b946123e98188613aa2565b96613d29565b9561241a60206040519c8d8b83829d51948593019101612a34565b8901915180936020840190612a34565b0161242e8251809360208085019101612a34565b016124428251809360208085019101612a34565b016124568251809360208085019101612a34565b0161246a8251809360208085019101612a34565b0161247e8251809360208085019101612a34565b01651e17b9bb339f60d11b6020820152036006810184520182612b4a565b6124b191503d806000833e6109738183612b4a565b8261199a565b346101dc5760203660031901126101dc576001600160a01b036124d8612a7c565b1660005260086020526020604060002054604051908152f35b346101dc5760403660031901126101dc576109b361250d612a7c565b336000526001602052604060002060018060a01b03821660005260205261253b602435604060002054612c90565b9033612ffb565b346101dc5760403660031901126101dc5760043560243561256281612c78565b61256f6040519182612b4a565b81815261257b82612c78565b6020938285019391601f190136853760005b8281106125e357505050906040519283926020840190602085525180915260408401929160005b8281106125c357505050500390f35b83516001600160a01b0316855286955093810193928101926001016125b4565b8061260e6125f360019385612c90565b6000908152600d60205260409020546001600160a01b031690565b6126188287612c9d565b90838060a01b031690520161258d565b346101dc5760003660031901126101dc576013546126506001600160a01b0382163314612c3f565b6001600160a01b0319166013557f6e4ee811a17215345b89e3506064ff2d62f4feedff3566e9d09219cda7e8cadb600080a1005b346101dc5760003660031901126101dc57602060405160098152f35b346101dc5760603660031901126101dc576126b9612a7c565b6126c1612a92565b6044359060018060a01b03831660005260016020526040600020336000526020526040600020549260001984036126fd575b6109b393506130fd565b82841061271957612714836109b395033383612ffb565b6126f3565b60405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606490fd5b60203660031901126101dc57612772612a7c565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811633036101dc57600554918183166101dc576001600160a01b031990921691161760055542600655005b346101dc576127d436612aa8565b906127ea60018060a01b03601354163314612c3f565b6000905b8282106127f757005b8160051b810135605e19823603018112156101dc5781939101908135600052602091601b8352604060002083820135600052835260406000209460009260408301935b6128448585613549565b90508110156128f3576128578585613549565b821015610bd7578160071b01908854600160401b811015610bc15780600161288292018b558a61357f565b610bab578260ff612894600195613597565b16908254918060ff19841617845561ff006128b08c8401613597565b60081b1690818161ffff1986161717855563ff0000006128db606062ff0000610d1660408801613597565b60181b169363ffffffff19161717171790550161283a565b509550939150506001915001906127ee565b346101dc5760003660031901126101dc576020600254604051908152f35b346101dc5760003660031901126101dc576005546040516001600160a01b039091168152602090f35b346101dc5760403660031901126101dc576109b3612968612a7c565b6024359033612ffb565b346101dc5760003660031901126101dc5760006003549060018260011c9160018416918215612a2a575b6020948585108414610e4a578587948686529182600014610e2a5750506001146129cd5750610db992500383612b4a565b84915060036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b906000915b858310612a12575050610db9935082010185610dac565b805483890185015287945086939092019181016129fb565b92607f169261299c565b60005b838110612a475750506000910152565b8181015183820152602001612a37565b90602091612a7081518092818552858086019101612a34565b601f01601f1916010190565b600435906001600160a01b03821682036101dc57565b602435906001600160a01b03821682036101dc57565b9060206003198301126101dc5760043567ffffffffffffffff928382116101dc57806023830112156101dc5781600401359384116101dc5760248460051b830101116101dc576024019190565b6040810190811067ffffffffffffffff821117610bc157604052565b610240810190811067ffffffffffffffff821117610bc157604052565b6020810190811067ffffffffffffffff821117610bc157604052565b90601f8019910116810190811067ffffffffffffffff821117610bc157604052565b9060405190600083549060018260011c9060018416968715612c35575b6020948584108914612c215787988489979899529081600014612bff5750600114612bc0575b505050612bbe92500383612b4a565b565b600090815285812095935091905b818310612be7575050612bbe9350820101388080612baf565b85548884018501529485019487945091830191612bce565b92505050612bbe94925060ff191682840152151560051b820101388080612baf565b634e487b7160e01b85526022600452602485fd5b91607f1691612b89565b15612c4657565b60405162461bcd60e51b815260206004820152600a60248201526937b7363c9037bbb732b960b11b6044820152606490fd5b67ffffffffffffffff8111610bc15760051b60200190565b9190820180921161130257565b8051821015610bd75760209160051b010190565b67ffffffffffffffff8111610bc157601f01601f191660200190565b81601f820112156101dc578051612ce381612cb1565b92612cf16040519485612b4a565b818452602082840101116101dc57612d0f9160208085019101612a34565b90565b519081151582036101dc57565b6020818303126101dc57805167ffffffffffffffff918282116101dc5701610240818403126101dc5760405192612d5584612b11565b8151845260208201518381116101dc5781612d71918401612ccd565b602085015260408201518381116101dc5781612d8e918401612ccd565b6040850152612d9f60608301612d12565b60608501526080820151608085015260a08201518381116101dc5781612dc6918401612ccd565b60a0850152612dd760c08301612d12565b60c085015260e082015160e0850152610100808301518481116101dc5782612e00918501612ccd565b90850152610120612e12818401612d12565b908501526101408083015190850152610160808301518481116101dc5782612e3b918501612ccd565b9085015261018080830151908501526101a080830151908501526101c080830151908501526101e0808301518481116101dc5782612e7a918501612ccd565b90850152610200808301519085015261022092838301519081116101dc57612ea29201612ccd565b9082015290565b9190820391821161130257565b6005546001600160a01b031615612f2957612ed360065442612ea9565b6702ea11e32ad5000081810291818304810361130257670e92596fd629000002918083046005149015171561130257620186a066023cfb4e3560009204820180921161130257808211612f24575090565b905090565b6702ea11e32ad5000090565b60405190612f4282612b11565b8161022060009182815260609283602083015283604083015280848301528060808301528360a08301528060c08301528060e08301528361010083015280610120830152806101408301528361016083015280610180830152806101a0830152806101c0830152836101e08301526102008201520152565b60405190612fc782612af5565b600582526466616c736560d81b6020830152565b60405190612fe882612af5565b60048252637472756560e01b6020830152565b6001600160a01b039081169182156130ac571691821561305c5760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925918360005260018252604060002085600052825280604060002055604051908152a3565b60405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608490fd5b60405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608490fd5b6005546001600160a01b03939291908416156133845761311c81613fcc565b61312583613fcc565b906131318585856135a5565b61313a83613fcc565b9061314485613fcc565b9181158061337d575b61336f575b81613366575b50613358575b811580613351575b613343575b8161333a575b5061332c575b838216156132285783811630811461321d576007549460ff8616156131a2575050612bbe935061378a565b600554168091146131b85750612bbe935061378a565b929190506131c4612eb6565b82116131e85760ff199384166001176007556131df9261378a565b60075416600755565b60405162461bcd60e51b815260206004820152600d60248201526c1b585e08189d5e481b1a5b5a5d609a1b6044820152606490fd5b50612bbe935061378a565b90509190911680156132dd5760009181835282602052604083205481811061328d57817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef926020928587528684520360408620558060025403600255604051908152a3565b60405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608490fd5b60405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608490fd5b613335826140f3565b613177565b90501538613171565b61334c846140a1565b61316b565b5080613166565b613361836140f3565b61315e565b90501538613158565b613378856140a1565b613152565b508061314d565b836013541680858316149081156133ce575b506131775760405162461bcd60e51b815260206004820152600b60248201526a1b9bdd081cdd185c9d195960aa1b6044820152606490fd5b90508483161438613396565b516103e881106134265761520881106134205762019a28811061341a57620668a0811061341457621005901161340f57600590565b600490565b50600390565b50600290565b50600190565b50600090565b8115613436570690565b634e487b7160e01b600052601260045260246000fd5b60001981146113025760010190565b6018600081805b6134ea575061347081612cb1565b9061347e6040519283612b4a565b808252601f1961348d82612cb1565b013660208401375b809280156134e3576000198201918211611302578193600a9260309084840682018092116113025785511115610bd75760f81b6001600160f81b03191660001a908401601f01530491613495565b5050905090565b906134f6600a9161344c565b910480613462565b801561352b57600081805b613517575061347081612cb1565b90613523600a9161344c565b910480613509565b5060405161353881612af5565b60018152600360fc1b602082015290565b903590601e19813603018212156101dc570180359067ffffffffffffffff82116101dc57602001918160071b360383136101dc57565b8054821015610bd75760005260206000200190600090565b3560ff811681036101dc5790565b916001600160a01b03919082841630811461378357633b9aca00908183049485151580613775575b80613765575b613612575b5061360d92612bbe9692613607926000526000602052806135ff6040600020549384612ea9565b049104612ea9565b90614172565b614566565b600090828252602091600c835260409081812080548a8114613714575050848152600b8452818120898252845260ff8282205416806136f5575b613658575050506135d8565b6136c99296507f0830300cf61a8f521300ca2944d8490b77b3212f5c2088e4055632d2bef19ad897955098818a866136f0979b94969c5260098c52818120600a8d528282208583528d528282205482528c522099600185519b6136ba8d612af5565b80548d520154908b015261442c565b6136d3878461436f565b519283921695829190916020806040830194805184520151910152565b0390a3565b508288168152600b8452818120898252845260ff82822054161561364c565b6136c99498507f0830300cf61a8f521300ca2944d8490b77b3212f5c2088e4055632d2bef19ad89997506137589b92508395916001916136f0989c95519d8e612af5565b8d520154908b0152614172565b50806005541681861614156135d3565b5080600554168214156135cd565b5050505050565b6001600160a01b0390811691821561384f576000938385528460205260408520548181106137fb577fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9360209383604093888a528987520383892055169586815220818154019055604051908152a3565b60405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608490fd5b60405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608490fd5b60c08101511561398e5760546138e682612d0f935180613980575b6000526019602052604060002060e082015160005260205261010060406000209101519061465a565b92604051938491733c6720636c6173733d27627562626c655269736560601b602084015261391e815180926020603487019101612a34565b820161139f60f11b6034820152751e339031b630b9b99e93b13ab1313632a9bbb0bc939f60511b603682015261395e825180936020604c85019101612a34565b01631e17b39f60e11b80604c8301526050820152036034810184520182612b4a565b61398990613e96565b6138bd565b505060405161399c81612b2e565b6000815290565b6060810151156139ce57806080612d0f920151600052601c60205260a060406000209101519061465a565b5060405161399c81612b2e565b6101208101511561398e576038613a2182612d0f935180613a94575b6000526018602052604060002061014082015160005260205261016060406000209101519061465a565b92604051938491710f19c818db185cdccf489cddd85e55d9595960721b6020840152613a57815180926020603287019101612a34565b820161111f60f11b6032820152613a78825180936020603485019101612a34565b01631e17b39f60e11b6034820152036018810184520182612b4a565b613a9d90613e96565b6139f7565b805180613d1b575b6000526020601a815260406000206101c08301516000528152613ad760406000206101e08401519061465a565b916002815180613d0d575b1015613b5f5750613b4392612d0f926036926040519586936f1e339031b630b9b99e93b6b4b93937b960811b83860152613b258151809285603089019101612a34565b84019161139f60f11b60308401528351938491603285019101612a34565b01631e17b39f60e11b6032820152036016810184520182612b4a565b6003909391935180613cff575b1015613c1d57613bfb92612d0f9260499260405195836c1e339031b630b9b99e93b137b160991b8895860152825181840190613bac81602d890184612a34565b8601613be461139f60f11b9586602d8401526f1e339031b630b9b99e93b6b4b93937b960811b602f840152518093603f840190612a34565b0192603f8401528351938491604185019101612a34565b01631e17b39f60e11b8060418301526045820152036029810184520182612b4a565b613cd792612d0f92605d9260405195836c1e339031b630b9b99e93b137b160991b8895860152825181840190613c5781602d890184612a34565b860193613cc061139f60f11b9586602d8201526d03c6720636c6173733d2770756d760941b602f820152825190613c9282603d830187612a34565b019186603d8401526f1e339031b630b9b99e93b6b4b93937b960811b603f840152518093604f840190612a34565b0192604f8401528351938491605185019101612a34565b01631e17b39f60e11b806051830152806055830152605982015203603d810184520182612b4a565b613d0890613e96565b613b6c565b613d1690613e96565b613ae2565b613d2490613e96565b613aaa565b805180613e88575b6000526020601b815260406000206102008301516000528152613d5e60406000206102208401519061465a565b916002815180613e7a575b1015613dac5750613b4392612d0f926036926040519586936f1e339031b630b9b99e93b6b4b93937b960811b83860152613b258151809285603089019101612a34565b6003909391935180613e6c575b1015613df957613bfb92612d0f9260499260405195836c1e339031b630b9b99e93b137b160991b8895860152825181840190613bac81602d890184612a34565b603390612d0f92613e50946040519586936c1e339031b630b9b99e93b137b160991b83860152613e328151809285602d89019101612a34565b84019161139f60f11b602d8401528351938491602f85019101612a34565b01631e17b39f60e11b602f820152036013810184520182612b4a565b613e7590613e96565b613db9565b613e8390613e96565b613d69565b613e9190613e96565b613d31565b8015611302576000190190565b8015613ee45760018114613ede5760028114613ed85760038114613ed257600414613ecd57601d90565b602190565b50602090565b50601f90565b50601e90565b50601d90565b613f0781516020830190815191613f008361344c565b9052612c90565b600019810191908211611302576040015160405190602082019283526040820152604081526060810181811067ffffffffffffffff821117610bc15760405251902090565b8015613f7f5760018114613f795760028114613f7357600314613f6e57602490565b602790565b50602690565b50602590565b50602490565b8015613fc65760018114613fc05760028114613fba5760038114613fb457600414613faf57602890565b602c90565b50602b90565b50602a90565b50602990565b50602890565b6001600160a01b039081169190308314908115614093575b50801561408b575b61408557600091808352600c602052604083205460405191633ebccc5760e01b83526004830152602082602481305afa91821561407a57849261403b575b50614036929350612c90565b151590565b9091506020813d602011614072575b8161405760209383612b4a565b8101031261406e576140369293505190839261402a565b8380fd5b3d915061404a565b6040513d86823e3d90fd5b60009150565b508115613fec565b905060055416821438613fe4565b6140ee90601054600052600d60205260406000209060018060a01b031690816bffffffffffffffffffffffff60a01b82541617905560105490600052600e6020528060406000205561344c565b601055565b601054801561416e5761410590613e96565b8060105560018060a01b0380921690600092828452600e6020526040842054918452600d602052604084205416908352604083206bffffffffffffffffffffffff60a01b91828254161790556010548352604083209081541690558152600e6020526040812055565b5050565b811561416e576005546001600160a01b03828116939116831461436a57600090838252600c906020908282526040948585208651926141b084612af5565b8154845260018092015485850152888752858552878720805482811015614304575050888752858552878720546141e691612ea9565b90888752858552868881205560088552808888205493889489935b6142be575b505050509261426f95928285899794967fe7e171670f8833f7f8729e86c32fe23ebfc84d75a84681cfe23a2d31d55128409a9711614298575b505051151580614287575b614274575b878352522090518154815260019091015460208201529081906040820190565b0390a2565b61427f601154613e96565b60115561424f565b50878352818152838320541561424a565b6142a191612ea9565b8985528383526142b5868620918254612c90565b9055388061423f565b90919294818610806142fb575b156142f5576142e66142ec916142e085614839565b90612c90565b9561344c565b92919082614201565b94614206565b508481106142cb565b899794507fe7e171670f8833f7f8729e86c32fe23ebfc84d75a84681cfe23a2d31d55128409996935061426f98959261433c91612ea9565b9055511515806142875761427457878352522090518154815260019091015460208201529081906040820190565b505050565b6005546001600160a01b03918216929116821461416e576000908282526020600881526040938484206143a2815461344c565b90556143af600f5461344c565b600f55808452600882528484205460001981019081116144185781855260098352858520818652835285852084518155600184860151910155818552600a8352858520845186528352858520558352600b8152838320915183525220600160ff19825416179055565b634e487b7160e01b85526011600452602485fd5b6005546001600160a01b039182169116811461416e576001906000928184526020600881526040928386206144618154613e96565b905561446e600f54613e96565b600f55808652600b8252838620838752825283862060ff198154169055808652600882528386205492600a835284872090875282528386205481875260098352848720818852835284872090868651926144c784612af5565b80548452015484830152848103614505575b50818752600a835284872090518752825285848120558552600981528285209185525282208281550155565b8288526009845285882085895284528588208787519161452483612af5565b805483520154858201908152848a5260098652878a20838b52865288888b20918351835551910155838952600a855286892090518952845285882055386144d9565b90801561416e576005546001600160a01b039283169216821461416e5761426f7f3901265a2656cafa2d4e8bdd635c0178dc1a4d1c2bc66504e3f0bdb9ba418e4f91600090848252602091600c8352600c60409384938484209060018651926145ce84612af5565b805484520154838301528985528383526145ec868620918254612c90565b90558451828101908a825283815261460381612af5565b519020908985528383528585209160018301555115908161464f575b5061464457878352522090518154815260019091015460208201529081906040820190565b61427f60115461344c565b90505415153861461f565b606090600090825b815483101561483157614675838361357f565b50906040908151926080840184811067ffffffffffffffff821117610bc1578352549260ff9283851694858352602094808087860198818560081c168a52818d87890198828860101c168a52019560181c1685526146d2906134fe565b9851166146de906134fe565b9451166146ea906134fe565b9151166146f6906134fe565b95825196879287840195683c7265637420783d2760b81b8752602993805190818b87890192019161472692612a34565b8501938401642720793d2760d81b9052602e93815191828b87840192019161474d92612a34565b0192830168272077696474683d2760b81b9052603792815191828a86840192019161477792612a34565b019182016927206865696768743d2760b01b905260419181519182898584019201916147a292612a34565b0190810167272066696c6c3d2760c01b90526049908b51908c82898584019201916147cc92612a34565b019081016213979f60e91b905203602c81018652604c016147ed9086612b4a565b51938285935190818680870192019161480592612a34565b83019051918285830161481792612a34565b0103808352016148279082612b4a565b9160010191614662565b935050505090565b6001600160a01b03811660009081526008602052604081205415612f24576040612d0f9160096020528181208180526020522054809261442c56fea2646970667358221220ad526b6dbd16eaf0251a67049ff07ecb475fd50c765568305d28e9c4812502f164736f6c63430008160033401968ff42a154441da5f6c4c935ac46b8671f0e062baaa62a7545ba53bb6e4cc97bfaf2f8ee708c303a06d134f5ecd8389ae0432af62dc132a24118292866bb4a2cc91ee622da3bc833a54c37ffcb6f3ec23b7793efc5eaf5e71b7b406c5c0698a476f1687bc3d60a2da2adbcba2c46958e61fa2fb4042cd7bc5816a710195b6d4407e7be21f808e6509aa9fa9143369579dd7d760fe20a2c09680fc146134f7416c943b4a09859521022fd2e90eac0dd9026dad28fa317782a135f28a86091744a2cf8fd7008e3d53b67916e73460df9fa5214e3ef23dd4259ca09493a359461035b26e3e9eee00e0d72fd1ee8ddca6894550dca6916ea2ac6baa90d11e5103a6357012c1a3ae0a17d304c9920310382d968ebcc4b1771f41c6b304205b570cb7c14ce178f56e2e8d86ab33ebc0ae081ba8556a00cd122038841867181caac50bb669a95c7b50b7e8a6f09454034b2b14cf2b85c730dca9a539ca82cb6e350beced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d2a03837a25210ee280c2113ff4b77ca23440b19d4866cca721c801278fd08d807d57b2b5166478fd4318d2acc6cc2c704584312bdd8781b32d5d06abda57f423011c44e4875b74d31ff9fd779bf2566af7bd15b87fc985d01f5094b89e3669e4fe16da923a2d88192e5070f37b4571d58682c0d66212ec634d495f33de3f77ab57cd332d19b93bcabe3cce7ca0c18a052f57e5fd03b4758a09f30f5ddc4b22ec4

Deployed Bytecode

0x608080604052600436101561001357600080fd5b60003560e01c90816306fdde031461297257508063095ea7b31461294c57806316f0115b1461292357806318160ddd14612905578063187c03bb146127c6578063214013ca1461275e57806323b872dd146126a0578063313ce56714612684578063333a00721461262857806335ad0cea1461254257806339509351146124f15780633ebccc57146124b7578063422b9e2314611900578063524773ce146118ce57806363f779eb1461178f57806368b77feb1461173a5780636a3ce0c71461171c5780636b4ed21b146116fe57806370a08231146116c457806370db69d6146116a15780638da5cb5b1461167857806391d2e92b14610e885780639477b85214610e6a57806395d89b4114610d5a5780639fc3ef6114610c01578063a285f05b14610a65578063a457c2d7146109be578063a9059cbb1461098d578063c3f4552a1461034f578063c5b8f77214610302578063cb8106f4146102c1578063dd62ed3e14610270578063e5100df8146101e15763f2fde38b1461019557600080fd5b346101dc5760203660031901126101dc576101ae612a7c565b601354906001600160a01b03906101c88284163314612c3f565b6001600160a01b0319909216911617601355005b600080fd5b346101dc5760403660031901126101dc576101fa612a7c565b6000602060405161020a81612af5565b828152015260018060a01b03166000526009602052604060002060243560005260205261026c604060002060016040519161024483612af5565b8054835201546020820152604051918291829190916020806040830194805184520151910152565b0390f35b346101dc5760403660031901126101dc57610289612a7c565b610291612a92565b9060018060a01b038091166000526001602052604060002091166000526020526020604060002054604051908152f35b346101dc5760203660031901126101dc576004356000908152600d60209081526040909120546001600160a01b03166040516001600160a01b039091168152f35b346101dc5760403660031901126101dc576001600160a01b03610323612a7c565b16600052600b6020526040600020602435600052602052602060ff604060002054166040519015158152f35b346101dc5760403660031901126101dc576040516391d2e92b60e01b815260048035908201526024803590820152600081604481305afa80156109815761026c9160009161095e575b5061092160226103a883516134fe565b6103e66028604051809367113632bb32b6111d60c11b60208301526103d68151809260208686019101612a34565b8101036008810184520182612b4a565b60208401519361047b60416040830151966040519788916e16113130b1b5b3b937bab732111d1160891b6020840152610429815180926020602f87019101612a34565b8201601160f91b602f8201526f16113130b1b5b3b937bab73219111d1160811b6030820152610462825180936020604085019101612a34565b01601160f91b6040820152036021810188520186612b4a565b60c0810151156109515761048d612fdb565b610546604861049f60e08501516134fe565b926101008501516040519485926c16113430b9a13ab1313632911d60991b60208501526104d6815180926020602d88019101612a34565b8301691611313ab1313632911d60b11b602d8201526104ff825180936020603785019101612a34565b016f1611313ab1313632a1b7b637b9111d1160811b603782015261052d825180936020604785019101612a34565b01601160f91b6047820152036028810184520182612b4a565b60608201511561094357610558612fdb565b905b6105dd603e60a0850151936040519485916c16113430b9a3b937bab732111d60991b6020840152610595815180926020602d87019101612a34565b82016f161133b937bab73221b7b637b9111d1160811b602d8201526105c4825180936020603d85019101612a34565b01601160f91b603d82015203601e810185520183612b4a565b61012083015115610935576105f0612fdb565b905b6106a560426106056101408701516134fe565b936101608701516040519586926a16113430b9abb2b2b2111d60a91b602085015261063a815180926020602b88019101612a34565b83016716113bb2b2b2111d60c11b602b820152610661825180936020603385019101612a34565b016d16113bb2b2b221b7b637b9111d1160911b603382015261068d825180936020604185019101612a34565b01601160f91b60418201520388810185520183612b4a565b6106b36101808501516134fe565b9161073160396106c76101a08801516134fe565b946040519586916d161136b4b93937b92a34b6b2911d60911b60208401526106f9815180926020602e87019101612a34565b82016a16113137b12a34b6b2911d60a91b602e8201526107228251809360208785019101612a34565b01036019810186520184612b4a565b61073f6101c08601516134fe565b936107c5603f6101e0880151966040519788916b16113a32b73a30b1b632911d60a11b602084015261077b815180926020602c87019101612a34565b82017116113a32b73a30b1b632a1b7b637b9111d1160711b602c8201526107ac825180936020603e85019101612a34565b01601160f91b603e82015203601f810188520186612b4a565b61085060376102206107db6102008a01516134fe565b980151976040519889916716113132b636111d60c11b602084015261080a815180926020602887019101612a34565b82016d16113132b63621b7b637b9111d1160911b6028820152610837825180936020603685019101612a34565b01601160f91b6036820152036017810189520187612b4a565b604051998a97607b60f81b60208a015261087481518092602060218d019101612a34565b880161088a825180936020602185019101612a34565b0161089f825180936020602185019101612a34565b016108b4825180936020602185019101612a34565b016108c9825180936020602185019101612a34565b016108de825180936020602185019101612a34565b016108f3825180936020602185019101612a34565b01610908825180936020602185019101612a34565b01607d60f81b6021820152036002810184520182612b4a565b604051918291602083526020830190612a57565b61093d612fba565b906105f2565b61094b612fba565b9061055a565b610959612fba565b61048d565b61097b91503d806000833e6109738183612b4a565b810190612d1f565b82610398565b6040513d6000823e3d90fd5b346101dc5760403660031901126101dc576109b36109a9612a7c565b60243590336130fd565b602060405160018152f35b346101dc5760403660031901126101dc576109d7612a7c565b60243590336000526001602052604060002060018060a01b03821660005260205260406000205491808310610a12576109b392039033612ffb565b60405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608490fd5b346101dc57610a7336612aa8565b610a8860018060a01b03601354163314612c3f565b6000905b808210610a9557005b8160051b830135605e19843603018112156101dc57839193018035600052601893602091858352604060002083820135600052835260406000209360009260408301935b610ae38585613549565b9050811015610bed57610af68585613549565b821015610bd7578160071b01908754600160401b811015610bc157806001610b2192018a558961357f565b610bab5787838c60ff610b35600197613597565b1663ff00000061ff00610b548754968460ff1989161789558601613597565b60081b1692838361ffff19881617178755610b94606062ff0000610b7a60408901613597565b60101b1696878662ffffff198b16178817178a5501613597565b901b169363ffffffff191617171717905501610ad9565b634e487b7160e01b600052600060045260246000fd5b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b509650949250505060019150019091610a8c565b346101dc57610c0f36612aa8565b90610c2560018060a01b03601354163314612c3f565b6000905b828210610c3257005b8160051b810135605e19823603018112156101dc5781939101908135600052602091601a8352604060002083820135600052835260406000209460009260408301935b610c7f8585613549565b9050811015610d4857610c928585613549565b821015610bd7578160071b01908854600160401b811015610bc157806001610cbd92018b558a61357f565b610bab578260ff610ccf600195613597565b16908254918060ff19841617845561ff00610ceb8c8401613597565b60081b1690818161ffff1986161717855563ff000000610d30606062ff0000610d1660408801613597565b60101b1695868562ffffff198a1617871717895501613597565b60181b169363ffffffff191617171717905501610c75565b50955093915050600191500190610c29565b346101dc5760003660031901126101dc5760405160006004549060018260011c9160018416918215610e60575b6020948585108414610e4a578587948686529182600014610e2a575050600114610dcd575b50610db992500383612b4a565b61026c604051928284938452830190612a57565b84915060046000527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b906000915b858310610e12575050610db9935082010185610dac565b80548389018501528794508693909201918101610dfb565b60ff191685820152610db995151560051b8501019250879150610dac9050565b634e487b7160e01b600052602260045260246000fd5b92607f1692610d87565b346101dc5760003660031901126101dc576020600f54604051908152f35b346101dc5760403660031901126101dc57610ea1612f35565b506040516060810181811067ffffffffffffffff821117610bc1576040526004358152600060208201526024356040820152610edb612f35565b610ee4826133da565b8152610efc610ef2836133da565b8061166a57613ea3565b8054610f0781612c78565b91610f156040519384612b4a565b818352602083019060005260206000206000915b83831061164d578686610f5087610f4a610f4285613eea565b82519061342c565b90612c9d565b5160208201526004610f61836133da565b8061163f575b10156115b157602081015160408201525b600380610f8484613eea565b16108060c08301526114ce575b6004610f9c836133da565b806114c0575b10611412575b6004610fb3836133da565b10611326575b6003610fc483613eea565b0660030180600311611302576101808201526002610fe1836133da565b80611318575b10156112e05760006101a08201525b610fff82613eea565b611008836133da565b90816112d0575b6005821015610bd75760ff8260f86110359460051c601601549160031b161c169061342c565b6101c0820152611051611047836133da565b8061129557613f85565b805461105c81612c78565b9161106a6040519384612b4a565b818352602083019060005260206000206000915b8383106112b357868661109787610f4a610f4285613eea565b516101e08201526110a782613eea565b6110b0836133da565b90816112a3575b6005821015610bd75760ff8260f86110dd9460051c601701549160031b161c169061342c565b6102008201526110ef611047836133da565b9182546110fb81612c78565b936111096040519586612b4a565b818552602085019060005260206000206000915b8383106112785761026c8661113889610f4a610f428a613eea565b51610220820152604051918291602083528051602084015261022061125961121e6111bc61119061117a602087015161024060408b01526102608a0190612a57565b6040870151898203601f190160608b0152612a57565b606086015115156080890152608086015160a089015260a0860151601f198983030160c08a0152612a57565b60c0850151151560e08801526111f060e086015161010090818a01528601519161012092601f198a830301848b0152612a57565b90850151610140901515818901528501516101609081890152850151601f1988830301610180890152612a57565b6101808401516101a090818801528401516101c08701526101c08401516101e08701526101e0840151601f1987830301610200880152612a57565b61020083015185830152910151838203601f1901610240850152612a57565b60016020819261128785612b6c565b81520192019201919061111d565b61129e90613e96565b613f85565b906112ad90613e96565b906110b7565b6001602081926112c285612b6c565b81520192019201919061107e565b906112da90613e96565b9061100f565b60076112eb83613eea565b1660080180600811611302576101a0820152610ff6565b634e487b7160e01b600052601160045260246000fd5b61132190613e96565b610fe7565b60038061133284613eea565b16108061012083015215610fb95761134982613eea565b611352836133da565b9081611402575b6005821015610bd75760ff8260f861137f9460051c601401549160031b161c169061342c565b610140820152611391611047836133da565b805461139c81612c78565b916113aa6040519384612b4a565b818352602083019060005260206000206000915b8383106113e557505050506113d990610f4a610f4285613eea565b51610160820152610fb9565b6001602081926113f485612b6c565b8152019201920191906113be565b9061140c90613e96565b90611359565b600180606083015261142383613eea565b5060006080830152611441611437846133da565b806114b257613f4c565b90815461144d81612c78565b9261145b6040519485612b4a565b818452602084019060005260206000206000915b83831061149657505050505061148b90610f4a610f4285613eea565b5160a0820152610fa8565b84602081926114a485612b6c565b81520192019201919061146f565b6114bb90613e96565b613f4c565b6114c990613e96565b610fa2565b6114d782613eea565b6114e0836133da565b90816115a1575b6005821015610bd75760ff8260f861150d9460051c601501549160031b161c169061342c565b60e082015260235461151e81612c78565b9061152c6040519283612b4a565b8082526020820160236000527fd57b2b5166478fd4318d2acc6cc2c704584312bdd8781b32d5d06abda57f42306000915b838310611584575050505061157890610f4a610f4285613eea565b51610100820152610f91565b60016020819261159385612b6c565b81520192019201919061155d565b906115ab90613e96565b906114e7565b6022546115bd81612c78565b906115cb6040519283612b4a565b8082526020820160226000527f61035b26e3e9eee00e0d72fd1ee8ddca6894550dca6916ea2ac6baa90d11e5106000915b838310611622575050505061161790610f4a610f4285613eea565b516040820152610f78565b60016020819261163185612b6c565b8152019201920191906115fc565b61164890613e96565b610f67565b60016020819261165c85612b6c565b815201920192019190610f29565b61167390613e96565b613ea3565b346101dc5760003660031901126101dc576013546040516001600160a01b039091168152602090f35b346101dc5760003660031901126101dc5760206116bc612eb6565b604051908152f35b346101dc5760203660031901126101dc576001600160a01b036116e5612a7c565b1660005260006020526020604060002054604051908152f35b346101dc5760003660031901126101dc576020601054604051908152f35b346101dc5760003660031901126101dc576020601154604051908152f35b346101dc5760203660031901126101dc57611753612a7c565b6000602060405161176381612af5565b828152015260018060a01b0316600052600c60205261026c604060002060016040519161024483612af5565b346101dc5761179d36612aa8565b906117b360018060a01b03601354163314612c3f565b6000905b8282106117c057005b8160051b810135605e19823603018112156101dc578193910190813560005260209160198352604060002083820135600052835260406000209460009260408301935b61180d8585613549565b90508110156118bc576118208585613549565b821015610bd7578160071b01908854600160401b811015610bc15780600161184b92018b558a61357f565b610bab578260ff61185d600195613597565b16908254918060ff19841617845561ff006118798c8401613597565b60081b1690818161ffff1986161717855563ff0000006118a4606062ff0000610d1660408801613597565b60181b169363ffffffff191617171717905501611803565b509550939150506001915001906117b7565b346101dc5760003660031901126101dc576002546702ea11e32ad5000090810390811161130257602090604051908152f35b346101dc5760403660031901126101dc5761191c6004356134fe565b611965602061192c6024356134fe565b9260405193816119458693518092868087019101612a34565b820161195982518093868085019101612a34565b01038084520182612b4a565b6040516391d2e92b60e01b815260048035908201526024803590820152600081604481305afa9081156109815760009161249c575b506119a361345b565b916119ac61345b565b906101808301916119bd83516134fe565b916101a08501946119d86119d187516134fe565b96516134fe565b855160060180600611611302576119ee906134fe565b9786516002018060021161130257611a05906134fe565b965160140190816014116113025761026c9961240a996109219960269961222296611a326104b7976134fe565b916040519b8c977f3c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323060208a015273030302f737667272076696577426f783d273020360641b60408a01526055611a9d8a600160fd1b9384605483015260208151948593019101612a34565b8901906055820152611ab9825180936020605685019101612a34565b01917f272073686170652d72656e646572696e673d2763726973704564676573273e006056840152661e39ba3cb6329f60c91b607584015273406b65796672616d6573206d6972726f724b207b60601b607c8401527f30252c20353025207b207472616e73666f726d3a207363616c65582831293b206090840152607d60f81b958660b08501527f35302e31252c2031303025207b207472616e73666f726d3a207363616c65582860b1850152652d31293b207d60d01b60d18501528660d785015271406b65796672616d65732070756d704b207b60701b60d88501527f30252c2031303025207b207472616e73666f726d3a207472616e736c617465598060ea8601526628302e293b207d60c81b61010a8601527f353025207b207472616e73666f726d3a207472616e736c61746559282d302e34610111860152657078293b207d60d01b90816101318701528861013787015270406b65796672616d657320626f624b207b60781b61013887015261014986015266282d32293b207d60c81b6101698601527f353025207b207472616e73666f726d3a207472616e736c6174655928312e35706101708601526478293b207d60d81b806101908701528861019587015271406b65796672616d657320737761794b207b60701b6101968701527f30252c2031303025207b207472616e73666f726d3a207472616e736c6174655890816101a88801526a282d302e357078293b207d60a81b6101c88801527f353025207b207472616e73666f726d3a207472616e736c6174655828302e35706101d38801526101f3870152886101f887015275406b65796672616d65732073776179576565644b207b60501b6101f98701528061020f8701526b282d302e31357078293b207d60a01b61022f8701527f353025207b207472616e73666f726d3a207472616e736c6174655828302e313561023b8701528161025b870152886102618701527f406b65796672616d657320627562626c65526973654b207b00000000000000006102628701527f30257b207472616e73666f726d3a207472616e736c617465592832347078293b61027a87015261207d60f01b61029a8701527f31303025207b207472616e73666f726d3a207472616e736c61746559282d323461029c870152816102bc870152886102c28701527f406b65796672616d657320627562626c65576f62626c654b207b0000000000006102c38701526102dd8601526928302e327078293b207d60b01b6102fd8601527f353025207b207472616e73666f726d3a207472616e736c61746558282d302e326103078601526103278501528661032d850152661736b4b93937b960c91b61032e850152737320737465702d656e6420696e66696e6974653b60601b8d61033595611ec38251809360208a85019101612a34565b01936220207b60e81b809686015272030b734b6b0ba34b7b71d1036b4b93937b9259606d1b61033886015261034b94611f058251809360208985019101612a34565b01938401527f7472616e73666f726d2d6f726967696e3a2063656e7465722063656e7465723b61035f8401528661037f8401526402e70756d760dc1b610380840152838d61038594611f608251809360208985019101612a34565b019384015270030b734b6b0ba34b7b71d10383ab6b8259607d1b61038884015261039992611f978251809360208785019101612a34565b01927f7320656173652d696e2d6f757420696e66696e6974653b0000000000000000008093850152866103b085015263173137b160e11b6103b18501528c6103b594611fec8251809360208985019101612a34565b01938401526f030b734b6b0ba34b7b71d103137b125960851b6103b88401526103c8926120228251809360208785019101612a34565b01918201526103df8101849052642e7377617960d81b6103e082015289516103e5916120548284830160208f01612a34565b019461207b60f01b809287015270030b734b6b0ba34b7b71d1039bbb0bca59607d1b6103e78701526103f8956120938251809360208a85019101612a34565b01947173206c696e65617220696e66696e6974653b60701b938480928801528561040a880152680b9cddd85e55d9595960ba1b61040b880152828c610414986120e58251809360208d85019101612a34565b019788015274030b734b6b0ba34b7b71d1039bbb0bcabb2b2b2259605d1b61041688015261042b966121208251809360208b85019101612a34565b019586015261043d85018490526a2e627562626c655269736560a81b61043e8601528951610449956121588288830160208f01612a34565b01948501527f616e696d6174696f6e3a20627562626c65526973654b2000000000000000000061044b8501526104629361219b8251809360208885019101612a34565b0192830152806104748301526c2e627562626c6553776179207b60981b6104758301527f616e696d6174696f6e3a20627562626c65576f62626c654b203573206c696e656104828301526b617220696e66696e6974653b60a01b6104a28301526104ae820152671e17b9ba3cb6329f60c11b6104af82015203610497810186520184612b4a565b6020810151916040820151926123bd60f1604051809660208201947f3c6c696e6561724772616469656e742069643d274772616469656e74000000008652865161227381603c860160208b01612a34565b83017f272078313d2730272078323d2730272079313d2730272079323d2731273e0000603c8201527f3c73746f70206f66667365743d273025272073746f702d636f6c6f723d270000605a8201526122d5825180936020607885019101612a34565b0190631390179f60e11b918260788201527f3c73746f70206f66667365743d2731303025272073746f702d636f6c6f723d27607c820152612320825180936020609c85019101612a34565b0190609c820152701e17b634b732b0b923b930b234b2b73a1f60791b60a08201527f3c7265637420783d27302720793d2730272077696474683d273234272068656960b18201527f6768743d273234272066696c6c3d2775726c28234772616469656e740000000060d18201528551906123a18260ed830160208a01612a34565b01631493979f60e11b60ed8201520360d1810187520185612b4a565b6123c782846138a2565b6123d0846139a3565b916123ef6123de85876139db565b946123e98188613aa2565b96613d29565b9561241a60206040519c8d8b83829d51948593019101612a34565b8901915180936020840190612a34565b0161242e8251809360208085019101612a34565b016124428251809360208085019101612a34565b016124568251809360208085019101612a34565b0161246a8251809360208085019101612a34565b0161247e8251809360208085019101612a34565b01651e17b9bb339f60d11b6020820152036006810184520182612b4a565b6124b191503d806000833e6109738183612b4a565b8261199a565b346101dc5760203660031901126101dc576001600160a01b036124d8612a7c565b1660005260086020526020604060002054604051908152f35b346101dc5760403660031901126101dc576109b361250d612a7c565b336000526001602052604060002060018060a01b03821660005260205261253b602435604060002054612c90565b9033612ffb565b346101dc5760403660031901126101dc5760043560243561256281612c78565b61256f6040519182612b4a565b81815261257b82612c78565b6020938285019391601f190136853760005b8281106125e357505050906040519283926020840190602085525180915260408401929160005b8281106125c357505050500390f35b83516001600160a01b0316855286955093810193928101926001016125b4565b8061260e6125f360019385612c90565b6000908152600d60205260409020546001600160a01b031690565b6126188287612c9d565b90838060a01b031690520161258d565b346101dc5760003660031901126101dc576013546126506001600160a01b0382163314612c3f565b6001600160a01b0319166013557f6e4ee811a17215345b89e3506064ff2d62f4feedff3566e9d09219cda7e8cadb600080a1005b346101dc5760003660031901126101dc57602060405160098152f35b346101dc5760603660031901126101dc576126b9612a7c565b6126c1612a92565b6044359060018060a01b03831660005260016020526040600020336000526020526040600020549260001984036126fd575b6109b393506130fd565b82841061271957612714836109b395033383612ffb565b6126f3565b60405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606490fd5b60203660031901126101dc57612772612a7c565b6001600160a01b037f000000000000000000000000a745edbdb2e2d54aced0af9c0f725e6dc74980e1811633036101dc57600554918183166101dc576001600160a01b031990921691161760055542600655005b346101dc576127d436612aa8565b906127ea60018060a01b03601354163314612c3f565b6000905b8282106127f757005b8160051b810135605e19823603018112156101dc5781939101908135600052602091601b8352604060002083820135600052835260406000209460009260408301935b6128448585613549565b90508110156128f3576128578585613549565b821015610bd7578160071b01908854600160401b811015610bc15780600161288292018b558a61357f565b610bab578260ff612894600195613597565b16908254918060ff19841617845561ff006128b08c8401613597565b60081b1690818161ffff1986161717855563ff0000006128db606062ff0000610d1660408801613597565b60181b169363ffffffff19161717171790550161283a565b509550939150506001915001906127ee565b346101dc5760003660031901126101dc576020600254604051908152f35b346101dc5760003660031901126101dc576005546040516001600160a01b039091168152602090f35b346101dc5760403660031901126101dc576109b3612968612a7c565b6024359033612ffb565b346101dc5760003660031901126101dc5760006003549060018260011c9160018416918215612a2a575b6020948585108414610e4a578587948686529182600014610e2a5750506001146129cd5750610db992500383612b4a565b84915060036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b906000915b858310612a12575050610db9935082010185610dac565b805483890185015287945086939092019181016129fb565b92607f169261299c565b60005b838110612a475750506000910152565b8181015183820152602001612a37565b90602091612a7081518092818552858086019101612a34565b601f01601f1916010190565b600435906001600160a01b03821682036101dc57565b602435906001600160a01b03821682036101dc57565b9060206003198301126101dc5760043567ffffffffffffffff928382116101dc57806023830112156101dc5781600401359384116101dc5760248460051b830101116101dc576024019190565b6040810190811067ffffffffffffffff821117610bc157604052565b610240810190811067ffffffffffffffff821117610bc157604052565b6020810190811067ffffffffffffffff821117610bc157604052565b90601f8019910116810190811067ffffffffffffffff821117610bc157604052565b9060405190600083549060018260011c9060018416968715612c35575b6020948584108914612c215787988489979899529081600014612bff5750600114612bc0575b505050612bbe92500383612b4a565b565b600090815285812095935091905b818310612be7575050612bbe9350820101388080612baf565b85548884018501529485019487945091830191612bce565b92505050612bbe94925060ff191682840152151560051b820101388080612baf565b634e487b7160e01b85526022600452602485fd5b91607f1691612b89565b15612c4657565b60405162461bcd60e51b815260206004820152600a60248201526937b7363c9037bbb732b960b11b6044820152606490fd5b67ffffffffffffffff8111610bc15760051b60200190565b9190820180921161130257565b8051821015610bd75760209160051b010190565b67ffffffffffffffff8111610bc157601f01601f191660200190565b81601f820112156101dc578051612ce381612cb1565b92612cf16040519485612b4a565b818452602082840101116101dc57612d0f9160208085019101612a34565b90565b519081151582036101dc57565b6020818303126101dc57805167ffffffffffffffff918282116101dc5701610240818403126101dc5760405192612d5584612b11565b8151845260208201518381116101dc5781612d71918401612ccd565b602085015260408201518381116101dc5781612d8e918401612ccd565b6040850152612d9f60608301612d12565b60608501526080820151608085015260a08201518381116101dc5781612dc6918401612ccd565b60a0850152612dd760c08301612d12565b60c085015260e082015160e0850152610100808301518481116101dc5782612e00918501612ccd565b90850152610120612e12818401612d12565b908501526101408083015190850152610160808301518481116101dc5782612e3b918501612ccd565b9085015261018080830151908501526101a080830151908501526101c080830151908501526101e0808301518481116101dc5782612e7a918501612ccd565b90850152610200808301519085015261022092838301519081116101dc57612ea29201612ccd565b9082015290565b9190820391821161130257565b6005546001600160a01b031615612f2957612ed360065442612ea9565b6702ea11e32ad5000081810291818304810361130257670e92596fd629000002918083046005149015171561130257620186a066023cfb4e3560009204820180921161130257808211612f24575090565b905090565b6702ea11e32ad5000090565b60405190612f4282612b11565b8161022060009182815260609283602083015283604083015280848301528060808301528360a08301528060c08301528060e08301528361010083015280610120830152806101408301528361016083015280610180830152806101a0830152806101c0830152836101e08301526102008201520152565b60405190612fc782612af5565b600582526466616c736560d81b6020830152565b60405190612fe882612af5565b60048252637472756560e01b6020830152565b6001600160a01b039081169182156130ac571691821561305c5760207f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925918360005260018252604060002085600052825280604060002055604051908152a3565b60405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608490fd5b60405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608490fd5b6005546001600160a01b03939291908416156133845761311c81613fcc565b61312583613fcc565b906131318585856135a5565b61313a83613fcc565b9061314485613fcc565b9181158061337d575b61336f575b81613366575b50613358575b811580613351575b613343575b8161333a575b5061332c575b838216156132285783811630811461321d576007549460ff8616156131a2575050612bbe935061378a565b600554168091146131b85750612bbe935061378a565b929190506131c4612eb6565b82116131e85760ff199384166001176007556131df9261378a565b60075416600755565b60405162461bcd60e51b815260206004820152600d60248201526c1b585e08189d5e481b1a5b5a5d609a1b6044820152606490fd5b50612bbe935061378a565b90509190911680156132dd5760009181835282602052604083205481811061328d57817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef926020928587528684520360408620558060025403600255604051908152a3565b60405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b6064820152608490fd5b60405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b6064820152608490fd5b613335826140f3565b613177565b90501538613171565b61334c846140a1565b61316b565b5080613166565b613361836140f3565b61315e565b90501538613158565b613378856140a1565b613152565b508061314d565b836013541680858316149081156133ce575b506131775760405162461bcd60e51b815260206004820152600b60248201526a1b9bdd081cdd185c9d195960aa1b6044820152606490fd5b90508483161438613396565b516103e881106134265761520881106134205762019a28811061341a57620668a0811061341457621005901161340f57600590565b600490565b50600390565b50600290565b50600190565b50600090565b8115613436570690565b634e487b7160e01b600052601260045260246000fd5b60001981146113025760010190565b6018600081805b6134ea575061347081612cb1565b9061347e6040519283612b4a565b808252601f1961348d82612cb1565b013660208401375b809280156134e3576000198201918211611302578193600a9260309084840682018092116113025785511115610bd75760f81b6001600160f81b03191660001a908401601f01530491613495565b5050905090565b906134f6600a9161344c565b910480613462565b801561352b57600081805b613517575061347081612cb1565b90613523600a9161344c565b910480613509565b5060405161353881612af5565b60018152600360fc1b602082015290565b903590601e19813603018212156101dc570180359067ffffffffffffffff82116101dc57602001918160071b360383136101dc57565b8054821015610bd75760005260206000200190600090565b3560ff811681036101dc5790565b916001600160a01b03919082841630811461378357633b9aca00908183049485151580613775575b80613765575b613612575b5061360d92612bbe9692613607926000526000602052806135ff6040600020549384612ea9565b049104612ea9565b90614172565b614566565b600090828252602091600c835260409081812080548a8114613714575050848152600b8452818120898252845260ff8282205416806136f5575b613658575050506135d8565b6136c99296507f0830300cf61a8f521300ca2944d8490b77b3212f5c2088e4055632d2bef19ad897955098818a866136f0979b94969c5260098c52818120600a8d528282208583528d528282205482528c522099600185519b6136ba8d612af5565b80548d520154908b015261442c565b6136d3878461436f565b519283921695829190916020806040830194805184520151910152565b0390a3565b508288168152600b8452818120898252845260ff82822054161561364c565b6136c99498507f0830300cf61a8f521300ca2944d8490b77b3212f5c2088e4055632d2bef19ad89997506137589b92508395916001916136f0989c95519d8e612af5565b8d520154908b0152614172565b50806005541681861614156135d3565b5080600554168214156135cd565b5050505050565b6001600160a01b0390811691821561384f576000938385528460205260408520548181106137fb577fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9360209383604093888a528987520383892055169586815220818154019055604051908152a3565b60405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608490fd5b60405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608490fd5b60c08101511561398e5760546138e682612d0f935180613980575b6000526019602052604060002060e082015160005260205261010060406000209101519061465a565b92604051938491733c6720636c6173733d27627562626c655269736560601b602084015261391e815180926020603487019101612a34565b820161139f60f11b6034820152751e339031b630b9b99e93b13ab1313632a9bbb0bc939f60511b603682015261395e825180936020604c85019101612a34565b01631e17b39f60e11b80604c8301526050820152036034810184520182612b4a565b61398990613e96565b6138bd565b505060405161399c81612b2e565b6000815290565b6060810151156139ce57806080612d0f920151600052601c60205260a060406000209101519061465a565b5060405161399c81612b2e565b6101208101511561398e576038613a2182612d0f935180613a94575b6000526018602052604060002061014082015160005260205261016060406000209101519061465a565b92604051938491710f19c818db185cdccf489cddd85e55d9595960721b6020840152613a57815180926020603287019101612a34565b820161111f60f11b6032820152613a78825180936020603485019101612a34565b01631e17b39f60e11b6034820152036018810184520182612b4a565b613a9d90613e96565b6139f7565b805180613d1b575b6000526020601a815260406000206101c08301516000528152613ad760406000206101e08401519061465a565b916002815180613d0d575b1015613b5f5750613b4392612d0f926036926040519586936f1e339031b630b9b99e93b6b4b93937b960811b83860152613b258151809285603089019101612a34565b84019161139f60f11b60308401528351938491603285019101612a34565b01631e17b39f60e11b6032820152036016810184520182612b4a565b6003909391935180613cff575b1015613c1d57613bfb92612d0f9260499260405195836c1e339031b630b9b99e93b137b160991b8895860152825181840190613bac81602d890184612a34565b8601613be461139f60f11b9586602d8401526f1e339031b630b9b99e93b6b4b93937b960811b602f840152518093603f840190612a34565b0192603f8401528351938491604185019101612a34565b01631e17b39f60e11b8060418301526045820152036029810184520182612b4a565b613cd792612d0f92605d9260405195836c1e339031b630b9b99e93b137b160991b8895860152825181840190613c5781602d890184612a34565b860193613cc061139f60f11b9586602d8201526d03c6720636c6173733d2770756d760941b602f820152825190613c9282603d830187612a34565b019186603d8401526f1e339031b630b9b99e93b6b4b93937b960811b603f840152518093604f840190612a34565b0192604f8401528351938491605185019101612a34565b01631e17b39f60e11b806051830152806055830152605982015203603d810184520182612b4a565b613d0890613e96565b613b6c565b613d1690613e96565b613ae2565b613d2490613e96565b613aaa565b805180613e88575b6000526020601b815260406000206102008301516000528152613d5e60406000206102208401519061465a565b916002815180613e7a575b1015613dac5750613b4392612d0f926036926040519586936f1e339031b630b9b99e93b6b4b93937b960811b83860152613b258151809285603089019101612a34565b6003909391935180613e6c575b1015613df957613bfb92612d0f9260499260405195836c1e339031b630b9b99e93b137b160991b8895860152825181840190613bac81602d890184612a34565b603390612d0f92613e50946040519586936c1e339031b630b9b99e93b137b160991b83860152613e328151809285602d89019101612a34565b84019161139f60f11b602d8401528351938491602f85019101612a34565b01631e17b39f60e11b602f820152036013810184520182612b4a565b613e7590613e96565b613db9565b613e8390613e96565b613d69565b613e9190613e96565b613d31565b8015611302576000190190565b8015613ee45760018114613ede5760028114613ed85760038114613ed257600414613ecd57601d90565b602190565b50602090565b50601f90565b50601e90565b50601d90565b613f0781516020830190815191613f008361344c565b9052612c90565b600019810191908211611302576040015160405190602082019283526040820152604081526060810181811067ffffffffffffffff821117610bc15760405251902090565b8015613f7f5760018114613f795760028114613f7357600314613f6e57602490565b602790565b50602690565b50602590565b50602490565b8015613fc65760018114613fc05760028114613fba5760038114613fb457600414613faf57602890565b602c90565b50602b90565b50602a90565b50602990565b50602890565b6001600160a01b039081169190308314908115614093575b50801561408b575b61408557600091808352600c602052604083205460405191633ebccc5760e01b83526004830152602082602481305afa91821561407a57849261403b575b50614036929350612c90565b151590565b9091506020813d602011614072575b8161405760209383612b4a565b8101031261406e576140369293505190839261402a565b8380fd5b3d915061404a565b6040513d86823e3d90fd5b60009150565b508115613fec565b905060055416821438613fe4565b6140ee90601054600052600d60205260406000209060018060a01b031690816bffffffffffffffffffffffff60a01b82541617905560105490600052600e6020528060406000205561344c565b601055565b601054801561416e5761410590613e96565b8060105560018060a01b0380921690600092828452600e6020526040842054918452600d602052604084205416908352604083206bffffffffffffffffffffffff60a01b91828254161790556010548352604083209081541690558152600e6020526040812055565b5050565b811561416e576005546001600160a01b03828116939116831461436a57600090838252600c906020908282526040948585208651926141b084612af5565b8154845260018092015485850152888752858552878720805482811015614304575050888752858552878720546141e691612ea9565b90888752858552868881205560088552808888205493889489935b6142be575b505050509261426f95928285899794967fe7e171670f8833f7f8729e86c32fe23ebfc84d75a84681cfe23a2d31d55128409a9711614298575b505051151580614287575b614274575b878352522090518154815260019091015460208201529081906040820190565b0390a2565b61427f601154613e96565b60115561424f565b50878352818152838320541561424a565b6142a191612ea9565b8985528383526142b5868620918254612c90565b9055388061423f565b90919294818610806142fb575b156142f5576142e66142ec916142e085614839565b90612c90565b9561344c565b92919082614201565b94614206565b508481106142cb565b899794507fe7e171670f8833f7f8729e86c32fe23ebfc84d75a84681cfe23a2d31d55128409996935061426f98959261433c91612ea9565b9055511515806142875761427457878352522090518154815260019091015460208201529081906040820190565b505050565b6005546001600160a01b03918216929116821461416e576000908282526020600881526040938484206143a2815461344c565b90556143af600f5461344c565b600f55808452600882528484205460001981019081116144185781855260098352858520818652835285852084518155600184860151910155818552600a8352858520845186528352858520558352600b8152838320915183525220600160ff19825416179055565b634e487b7160e01b85526011600452602485fd5b6005546001600160a01b039182169116811461416e576001906000928184526020600881526040928386206144618154613e96565b905561446e600f54613e96565b600f55808652600b8252838620838752825283862060ff198154169055808652600882528386205492600a835284872090875282528386205481875260098352848720818852835284872090868651926144c784612af5565b80548452015484830152848103614505575b50818752600a835284872090518752825285848120558552600981528285209185525282208281550155565b8288526009845285882085895284528588208787519161452483612af5565b805483520154858201908152848a5260098652878a20838b52865288888b20918351835551910155838952600a855286892090518952845285882055386144d9565b90801561416e576005546001600160a01b039283169216821461416e5761426f7f3901265a2656cafa2d4e8bdd635c0178dc1a4d1c2bc66504e3f0bdb9ba418e4f91600090848252602091600c8352600c60409384938484209060018651926145ce84612af5565b805484520154838301528985528383526145ec868620918254612c90565b90558451828101908a825283815261460381612af5565b519020908985528383528585209160018301555115908161464f575b5061464457878352522090518154815260019091015460208201529081906040820190565b61427f60115461344c565b90505415153861461f565b606090600090825b815483101561483157614675838361357f565b50906040908151926080840184811067ffffffffffffffff821117610bc1578352549260ff9283851694858352602094808087860198818560081c168a52818d87890198828860101c168a52019560181c1685526146d2906134fe565b9851166146de906134fe565b9451166146ea906134fe565b9151166146f6906134fe565b95825196879287840195683c7265637420783d2760b81b8752602993805190818b87890192019161472692612a34565b8501938401642720793d2760d81b9052602e93815191828b87840192019161474d92612a34565b0192830168272077696474683d2760b81b9052603792815191828a86840192019161477792612a34565b019182016927206865696768743d2760b01b905260419181519182898584019201916147a292612a34565b0190810167272066696c6c3d2760c01b90526049908b51908c82898584019201916147cc92612a34565b019081016213979f60e91b905203602c81018652604c016147ed9086612b4a565b51938285935190818680870192019161480592612a34565b83019051918285830161481792612a34565b0103808352016148279082612b4a565b9160010191614662565b935050505090565b6001600160a01b03811660009081526008602052604081205415612f24576040612d0f9160096020528181208180526020522054809261442c56fea2646970667358221220ad526b6dbd16eaf0251a67049ff07ecb475fd50c765568305d28e9c4812502f164736f6c63430008160033

[ 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.