ETH Price: $1,949.63 (-1.88%)
Gas: 0.05 Gwei
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

More Info

Private Name Tags

ContractCreator

TokenTracker

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Safe Transfer Fr...245130582026-02-22 14:38:3517 mins ago1771771115IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245129682026-02-22 14:20:1136 mins ago1771770011IN
merge.: m Token
0 ETH0.000011510.12
Set Approval For...245129562026-02-22 14:17:4738 mins ago1771769867IN
merge.: m Token
0 ETH0.000095312.0670135
Safe Transfer Fr...245129302026-02-22 14:12:3543 mins ago1771769555IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245128872026-02-22 14:03:5952 mins ago1771769039IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245128692026-02-22 14:00:2355 mins ago1771768823IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245127962026-02-22 13:45:471 hr ago1771767947IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245127922026-02-22 13:44:591 hr ago1771767899IN
merge.: m Token
0 ETH0.000011510.12
Set Approval For...245127412026-02-22 13:34:471 hr ago1771767287IN
merge.: m Token
0 ETH0.000094882.05768502
Safe Transfer Fr...245124322026-02-22 12:32:472 hrs ago1771763567IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245121002026-02-22 11:26:233 hrs ago1771759583IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245120822026-02-22 11:22:473 hrs ago1771759367IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245120702026-02-22 11:20:233 hrs ago1771759223IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245118542026-02-22 10:36:594 hrs ago1771756619IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245117762026-02-22 10:21:234 hrs ago1771755683IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245116522026-02-22 9:56:234 hrs ago1771754183IN
merge.: m Token
0 ETH0.000003140.03420536
Safe Transfer Fr...245103772026-02-22 5:40:239 hrs ago1771738823IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245102412026-02-22 5:13:119 hrs ago1771737191IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245101852026-02-22 5:01:599 hrs ago1771736519IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245099282026-02-22 4:10:3510 hrs ago1771733435IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245095912026-02-22 3:02:3511 hrs ago1771729355IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245095372026-02-22 2:51:4712 hrs ago1771728707IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245095162026-02-22 2:47:3512 hrs ago1771728455IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245090102026-02-22 1:05:4713 hrs ago1771722347IN
merge.: m Token
0 ETH0.000011510.12
Safe Transfer Fr...245089852026-02-22 1:00:4713 hrs ago1771722047IN
merge.: m Token
0 ETH0.000011510.12
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Merge

Compiler Version
v0.8.6+commit.11564f7e

Optimization Enabled:
Yes with 1000 runs

Other Settings:
default evmVersion, MIT license
File 1 of 6 : Merge.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

/** 
 * smatthewenglish oOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOo niftynathan
 * OoOoOoOoOoOoOoOoOoOoOoOoOoO                          OoOoOoOoOoOoOoOoOoOoOoOoOoOo
 * OoOoOoOoOoOoOoOoOoOoO                                      OoOoOoOoOoOoOoOoOoOoOo
 * OoOoOoOoOoOoOoOoOo                                             OoOoOoOoOoOoOoOoOo
 * OoOoOoOoOoOoOo                                                    oOoOoOoOoOoOoOo
 * OoOoOoOoOoOo                                                         OoOoOoOoOoOo
 * OoOoOoOoOo                                                             OoOoOoOoOo
 * OoOoOoOo                                                                 OoOoOoOo
 * OoOoOo                                                                     OoOoOo
 * OoOoO                                                                       oOoOo
 * OoOo                                                                         OoOo
 * OoO                                                                           oOo
 * Oo                                                                             oO
 * Oo                                                                             oO
 * O                                                                               O
 * O                                                                               O
 * O                                                                               O
 * O                                                                               O
 * O                                                                               O
 * Oo                                                                             oO
 * Oo                                                                             oO
 * OoO                                                                           oOo
 * OoOo                                                                         OoOo
 * OoOoO                                                                       oOoOo
 * OoOoOo                                                                     OoOoOo
 * OoOoOoOo                                                                 OoOoOoOo
 * OoOoOoOoOo                                                             OoOoOoOoOo
 * OoOoOoOoOoOo                                                         OoOoOoOoOoOo
 * OoOoOoOoOoOoOo                                                    oOoOoOoOoOoOoOo
 * OoOoOoOoOoOoOoOoOo                                             OoOoOoOoOoOoOoOoOo
 * OoOoOoOoOoOoOoOoOoOoO                                      OoOoOoOoOoOoOoOoOoOoOo
 * OoOoOoOoOoOoOoOoOoOoOoOoOoO                          OoOoOoOoOoOoOoOoOoOoOoOoOoOo
 * soliditygoldminerz oOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOo reviewed by manifold.xyz
 */

import {IMergeMetadata} from "./MergeMetadata.sol";

interface INiftyRegistry {
   function isValidNiftySender(address sending_key) external view returns (bool);
}

interface IERC721Receiver {
    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}

interface IERC165 {
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

interface ERC721 is IERC165 {
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed fromAddress, address indexed toAddress);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    function balanceOf(address owner) external view returns (uint256 balance);
    function ownerOf(uint256 tokenId) external view returns (address owner);
    function safeTransferFrom(address from, address to, uint256 tokenId) external;
    function transferFrom(address from, address to, uint256 tokenId) external;

    function approve(address to, uint256 tokenId) external;
    function getApproved(uint256 tokenId) external view returns (address operator);
    function setApprovalForAll(address operator, bool _approved) external;
    function isApprovedForAll(address owner, address operator) external view returns (bool);
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}

interface ERC721Metadata {
    function name() external view returns (string memory _name);
    function symbol() external view returns (string memory _symbol);
    function tokenURI(uint256 _tokenId) external view returns (string memory);
}

contract Merge is ERC721, ERC721Metadata {
 
    IMergeMetadata public _metadataGenerator;

    
    string private _name;

    string private _symbol;

    uint256 constant private CLASS_MULTIPLIER = 100 * 1000 * 1000; // 100 million

    // valid classes are in the range [1, 4]
    uint256 constant private MIN_CLASS_INCL = 1; 
    uint256 constant private MAX_CLASS_INCL = 4;

    function ensureValidClass(uint256 class) private pure {
        require(MIN_CLASS_INCL <= class && class <= MAX_CLASS_INCL, "Merge: Class must be [1, 4].");
    }

    // valid masses are in the range [1, 100m - 1)
    uint256 constant private MIN_MASS_INCL = 1; 
    uint256 constant private MAX_MASS_EXCL = CLASS_MULTIPLIER - 1;

    function ensureValidMass(uint256 mass) private pure {
        require(MIN_MASS_INCL <= mass && mass < MAX_MASS_EXCL, "Merge: Mass must be [1, 100m - 1).");
    }

    function isSentinelMass(uint256 value) private pure returns (bool) {
        return (value % CLASS_MULTIPLIER) == MAX_MASS_EXCL;
    }


    bool public _mintingFinalized;
    bool public frozen;

 
    uint256 public _nextMintId;
 
    uint256 public _countToken;

    uint256 immutable public _percentageTotal;
    uint256 public _percentageRoyalty;


    uint256 public _alphaMass;

    uint256 public _alphaId;


    uint256 public _massTotal;


    address public _pak;

    address constant public _dead = 0x000000000000000000000000000000000000dEaD;

    address public _omnibus;

    address public _receiver;

    address immutable public _registry;


    event AlphaMassUpdate(uint256 indexed tokenId, uint256 alphaMass);


    event MassUpdate(uint256 indexed tokenIdBurned, uint256 indexed tokenIdPersist, uint256 mass);


    // Mapping of addresses disbarred from holding any token.
    mapping (address => bool) private _blacklistAddress;

    // Mapping of address allowed to hold multiple tokens.
    mapping (address => bool) private _whitelistAddress;

    // Mapping from owner address to token ID.
    mapping (address => uint256) private _tokens;

    // Mapping owner address to token count.
    mapping (address => uint256) private _balances;


    // Mapping from token ID to owner address.
    mapping (uint256 => address) private _owners;

    // Mapping from token ID to approved address.
    mapping (uint256 => address) private _tokenApprovals;

    // Mapping from owner to operator approvals.
    mapping (address => mapping (address => bool)) private _operatorApprovals;

    

    // Mapping token ID to mass value.
    mapping (uint256 => uint256) private _values;

    // Mapping token ID to all quantity merged into it.
    mapping (uint256 => uint256) private _mergeCount;


    function getMergeCount(uint256 tokenId) public view returns (uint256 mergeCount) {
        require(_exists(tokenId), "ERC721: nonexistent token");
        return _mergeCount[tokenId];
    }

    modifier onlyPak() {
        require(_msgSender() == _pak, "Merge: msg.sender is not pak");
        _;
    }

    modifier onlyValidWhitelist() {
        require(_whitelistAddress[_msgSender()], "Merge: Invalid msg.sender");
        _;
    }

    modifier onlyValidSender() {
        require(INiftyRegistry(_registry).isValidNiftySender(_msgSender()), "Merge: Invalid msg.sender");
        _;
    }

    modifier notFrozen() {
        require(!frozen, "Merge: movement frozen");
        _;
    }

    /**
     * @dev Set the values carefully!
     *
     * Requirements:
     *
     * - `registry_` enforce access control on state-changing ops
     * - `omnibus_` for efficient minting of initial token stock
     * - `metadataGenerator_` 
     * - `pak_` - Initial pak address (0x2Ce780D7c743A57791B835a9d6F998B15BBbA5a4)
     *
     */    
    constructor(address registry_, address omnibus_, address metadataGenerator_, address pak_) {
        _nextMintId = 1;
        _registry = registry_;
        _omnibus = omnibus_;
        _metadataGenerator = IMergeMetadata(metadataGenerator_);
        _name = "merge.";
        _symbol = "m";

        _pak = pak_;
        _receiver = pak_;

        _percentageTotal = 10000;
        _percentageRoyalty = 1000;


        _blacklistAddress[address(this)] = true;

        _whitelistAddress[omnibus_] = true;              
    }
        
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    } 

    function totalSupply() public view returns (uint256) {
        return _countToken;
    }
 
    function merge(uint256 tokenIdRcvr, uint256 tokenIdSndr) external onlyValidWhitelist notFrozen returns (uint256 tokenIdDead) {        
        address owner = ownerOf(tokenIdRcvr);
        require(owner == ownerOf(tokenIdSndr), "Merge: Illegal argument disparate owner.");
        require(_msgSender() == owner, "ERC721: msg.sender is not token owner.");

        // owners are same, so decrement their balance as we are merging
        _balances[owner] -= 1;

        tokenIdDead = _merge(tokenIdRcvr, tokenIdSndr);

        // clear ownership of dead token
        delete _owners[tokenIdDead];

        // owners are the same; burn dead token from common owner
        emit Transfer(owner, address(0), tokenIdDead);
    }

    function _transfer(address owner, address from, address to, uint256 tokenId) internal notFrozen {
        require(owner == from, "ERC721: transfer of token that is not own");
        require(to != address(0), "ERC721: transfer to the zero address");
        require(!_blacklistAddress[to], "Merge: transfer attempt to blacklist address");

        // if transferring to `_dead_` then `_transfer` is interpreted as a burn
        if (to == _dead) {
            _burnNoEmitTransfer(owner, tokenId);

            emit Transfer(from, _dead, tokenId);
            emit Transfer(_dead, address(0), tokenId);
        } else {
            // Clear any prior approvals
            // includes an emit of Approval to zero
            _approve(owner, address(0), tokenId);

            // in all cases we first wish to log the transfer
            // no merging later can deny the fact that `from` transferred to `to`
            emit Transfer(from, to, tokenId);

            if (from == to) {
                // !non-local control flow!
                // we make an exception here, as it’s easy to follow that a self transfer
                // can skip _all_ following state changes
                return;
            }

            // if all addresses were whitelisted, then transfer would be like any other ERC-721
            // _balances[from] -= 1;
            // _balances[to] += 1;
            // _owners[tokenId] = to;

            // _balances (1) and _owners (2) are the main mappings to update
            // for non-whitelisted addresses there is also the _tokens (3) mapping
            //
            // Our updates will be
            //   - 1a: decrement balance of `from`
            //   - 1b: update balance of `to` (not guaranteed to increase)
            //   - 2: assign ownership of `tokenId`
            //   - 3a: assign unique token of `to`
            //   - 3b: unassign unique token of `from`

            bool fromIsWhitelisted = isWhitelisted(from);
            bool toIsWhitelisted = isWhitelisted(to);

            // BEGIN PART 1: update _balances
            //
            // PART 1a: decrease balance of `from`
            //   the classic implementation would be
            //   _balances[from] -= 1;
            if (fromIsWhitelisted) {
                // from the reasoning:
                // > if all addresses were whitelisted, then transfer would be like any other ERC-721
                _balances[from] -= 1;
            } else {
                // for non-whitelisted addresses, we have the invariant that
                //   _balances[a] <= 1
                // we known that `from` was the owner so the only possible state is
                //   _balances[from] == 1
                // to save an SLOAD, we can assign a balance of 0 (or delete)
                delete _balances[from];
            }
            // PART 1b: increase balance of `to`
            //   the classic implementation would be
            //   _balances[to] += 1;
            if (toIsWhitelisted) {
                // from the reasoning:
                // > if all addresses were whitelisted, then transfer would be like any other ERC-721
                _balances[to] += 1;
            } else if (_tokens[to] == 0) {
                // for non-whitelisted addresses, we have the invariant that
                //   _balances[a] <= 1
                // if _tokens[to] == 0 then _balances[to] == 0
                // to save an SLOAD, we can assign a balance of 1
                _balances[to] = 1;
            } else {
                // for non-whitelisted addresses, we have the invariant that
                //   _balances[a] <= 1
                // if _tokens[to] != 0 then _balance[to] == 1
                // to preserve the invariant, we have nothing to do (the balance is already 1)
            }
            // END PART 1

            if (toIsWhitelisted) {
                // PART 2: update _owners
                // assign ownership of token
                //   the classic implementation would be
                //   _owners[tokenId] = to;
                //
                // from the reasoning:
                // > if all addresses were whitelisted, then transfer would be like any other ERC-721
                _owners[tokenId] = to;
            } else {
                // label current and sent token with respect to address `to`
                uint256 currentTokenId = _tokens[to];

                if (currentTokenId == 0) {
                    // PART 2: update _owners
                    // assign ownership of token
                    _owners[tokenId] = to;

                    // PART 3a
                    // assign unique token of `to`
                    _tokens[to] = tokenId;
                } else {
                    uint256 sentTokenId = tokenId;

                    // compute token merge, returning the dead token
                    uint256 deadTokenId = _merge(currentTokenId, sentTokenId);

                    // logically, the token has already been transferred to `to`
                    // so log the burning of the dead token id as originating ‘from’ `to`
                    emit Transfer(to, address(0), deadTokenId);

                    // thus inferring the alive token
                    uint256 aliveTokenId = currentTokenId;
                    if (currentTokenId == deadTokenId) {
                        aliveTokenId = sentTokenId;
                    }

                    // PART 2 continued:
                    // and ownership of dead token is deleted
                    delete _owners[deadTokenId];

                    // if received token surplanted the current token
                    if (currentTokenId != aliveTokenId) {
                        // PART 2 continued:
                        // to takes ownership of alive token
                        _owners[aliveTokenId] = to;

                        // PART 3a
                        // assign unique token of `to`
                        _tokens[to] = aliveTokenId;
                    }
                }
            }

            // PART 3b:
            // unassign unique token of `from`
            //
            // _tokens is only defined for non-whitelisted addresses
            if (!fromIsWhitelisted) {
                delete _tokens[from];
            }
        }
    }

    function _merge(uint256 tokenIdRcvr, uint256 tokenIdSndr) internal returns (uint256 tokenIdDead) {
        require(tokenIdRcvr != tokenIdSndr, "Merge: Illegal argument identical tokenId.");

        uint256 massRcvr = decodeMass(_values[tokenIdRcvr]);
        uint256 massSndr = decodeMass(_values[tokenIdSndr]);
        
        uint256 massSmall = massRcvr;
        uint256 massLarge = massSndr;

        uint256 tokenIdSmall = tokenIdRcvr;
        uint256 tokenIdLarge = tokenIdSndr;

        if (massRcvr >= massSndr) {

            massSmall = massSndr;
            massLarge = massRcvr;

            tokenIdSmall = tokenIdSndr;
            tokenIdLarge = tokenIdRcvr;
        }

        _values[tokenIdLarge] += massSmall;

        uint256 combinedMass = massLarge + massSmall;

        if(combinedMass > _alphaMass) {
            _alphaId = tokenIdLarge;
            _alphaMass = combinedMass;
            emit AlphaMassUpdate(_alphaId, combinedMass);
        }
        
        _mergeCount[tokenIdLarge]++;

        delete _values[tokenIdSmall];

        _countToken -= 1;

        emit MassUpdate(tokenIdSmall, tokenIdLarge, combinedMass);

        return tokenIdSmall;
    }

    function setRoyaltyBips(uint256 percentageRoyalty_) external onlyPak {
        require(percentageRoyalty_ <= _percentageTotal, "Merge: Illegal argument more than 100%");
        _percentageRoyalty = percentageRoyalty_;
    }

    function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address, uint256) {
        uint256 royaltyAmount = (salePrice * _percentageRoyalty) / _percentageTotal;
        return (_receiver, royaltyAmount);
    }

    function setBlacklistAddress(address address_, bool status) external onlyPak {
        require(address_ != _omnibus, "Merge: Illegal argument address_ is _omnibus.");
        _blacklistAddress[address_] = status;
    }

    function setPak(address pak_) external onlyPak {  
        _pak = pak_;
    }

    function setRoyaltyReceiver(address receiver_) external onlyPak {  
        _receiver = receiver_;
    }
    
    function setMetadataGenerator(address metadataGenerator_) external onlyPak {  
        _metadataGenerator = IMergeMetadata(metadataGenerator_);
    }
   
    function whitelistUpdate(address address_, bool status) external onlyPak {
        if(address_ == _omnibus){
            require(status != false, "Merge: Illegal argument _omnibus can't be removed.");
        }

        if(status == false) {
            require(balanceOf(address_) <= 1, "Merge: Address with more than one token can't be removed.");
        }

        _whitelistAddress[address_] = status;
    }

    function isWhitelisted(address address_) public view returns (bool) {
        return _whitelistAddress[address_];
    }

    function isBlacklisted(address address_) public view returns (bool) {
        return _blacklistAddress[address_];
    }

    function ownerOf(uint256 tokenId) public view override returns (address owner) {
        owner = _owners[tokenId]; 
        require(owner != address(0), "ERC721: nonexistent token");
    }

    /**
     * @dev Generate the NFTs of this collection. 
     *
     * [20001000, 20000900, ]
     *
     * Requirements:
     *
     * - `values_` provided as a list of addresses, each of
     *             which implicitly corresponds to a tokenId, 
     *             derrived by the index of the value in the 
     *             input array. The values map to a color
     *             attribute.
     *
     * Emits a series of {Transfer} events.
     */
     function mint(uint256[] calldata values_) external onlyValidSender {
        require(!_mintingFinalized, "Merge: Minting is finalized.");        
        
        // for efficiency reasons copy from storage into local variables
        uint256 index = _nextMintId;                
        uint256 alphaId = _alphaId;
        uint256 alphaMass = _alphaMass;
        address omnibus = _omnibus;

        // initialize accumulators and counters
        uint256 massAdded = 0;
        uint256 newlyMintedCount = 0;
        uint256 valueIx = 0;

        while (valueIx < values_.length) {            

            if (isSentinelMass(values_[valueIx])) {
                // SKIP FLAG SET - DON'T MINT
            } else {
                newlyMintedCount++;

                _values[index] = values_[valueIx];            
                _owners[index] = omnibus;

                (/* uint256 class */, uint256 mass) = decodeClassAndMass(values_[valueIx]);

                if (alphaMass < mass){
                    alphaMass = mass;
                    alphaId = index;
                }

                massAdded += mass;

                emit Transfer(address(0), omnibus, index);
            }
            
            // update counters for loop
            valueIx++;
            index++;
        }

        // return new token id index to storage
        _nextMintId = index;  

        // update token supply and balances based on batch mint
        _countToken += newlyMintedCount;
        _balances[omnibus] += newlyMintedCount;

        // update total mass in system with aggregate mass of batch mint
        // we must fail if we attempt to mint sufficient mass such that it
        // new total mass in the system becomes unrepresentable
        // i.e., total mass must be bounded by MAX_MASS_EXCL
        uint256 prevMassTotal = _massTotal;
        uint256 newMassTotal = prevMassTotal + massAdded;
        require(newMassTotal < MAX_MASS_EXCL, "Merge: Mass total overflow");
        _massTotal = newMassTotal;

        // if the alpha was supplanted during minting,
        // then return that new state to storage
        if(_alphaId != alphaId) {
            _alphaId = alphaId;
            _alphaMass = alphaMass;
            emit AlphaMassUpdate(alphaId, alphaMass);
        }        
    }

    function batchSetMergeCountFromSnapshot(uint256[] calldata tokenIds_, uint256[] calldata mergeCounts_) external onlyValidSender {
        require(!_mintingFinalized, "Merge: Minting is finalized.");
        require(tokenIds_.length == mergeCounts_.length, "");
        for(uint256 i = 0 ; i < tokenIds_.length; i++) {
            _mergeCount[tokenIds_[i]] = mergeCounts_[i];
        }                   
    }
   
    function finalize() external onlyPak {
        thaw();        
        _mintingFinalized = true;        
    }

    function freeze() external onlyPak {
        require(!_mintingFinalized);
        frozen = true;
    }

    function thaw() public onlyPak {        
        frozen = false;
    }

    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {
        transferFrom(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    function transferFrom(address from, address to, uint256 tokenId) public virtual override {
        (address owner, bool isApprovedOrOwner) = _isApprovedOrOwner(_msgSender(), tokenId);
        require(isApprovedOrOwner, "ERC721: transfer caller is not owner nor approved");
        _transfer(owner, from, to, tokenId);
    }

    function balanceOf(address owner) public view override returns (uint256) {
        return _balances[owner];        
    }

    function massOf(uint256 tokenId) public view virtual returns (uint256) {
        uint256 value = getValueOf(tokenId);
        return decodeMass(value);
    }

    function getValueOf(uint256 tokenId) public view virtual returns (uint256 value) {
        value = _values[tokenId];
        require(value != 0, "ERC721: nonexistent token");
    }

    function tokenOf(address owner) public view virtual returns (uint256) {
        require(!isWhitelisted(owner), "Merge: tokenOf undefined");
        uint256 token = _tokens[owner];
        return token;
    }

    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721: approve caller is not owner nor approved for all"
        );
        _approve(owner, to, tokenId);
    }

    function _approve(address owner, address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(owner, to, tokenId);
    }

    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "ERC721: nonexistent token");       
        return _tokenApprovals[tokenId];
    }

    function setApprovalForAll(address operator, bool approved) public virtual override {
        require(operator != _msgSender(), "ERC721: approve to caller");
        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }

    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    function exists(uint256 tokenId) public view returns (bool) {
        return _exists(tokenId);
    }

    function _exists(uint256 tokenId) internal view returns (bool) {
        return _owners[tokenId] != address(0);
    }

    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (address owner, bool isApprovedOrOwner) {
        owner = _owners[tokenId];

        require(owner != address(0), "ERC721: nonexistent token");

        isApprovedOrOwner = (spender == owner || _tokenApprovals[tokenId] == spender || isApprovedForAll(owner, spender));
    }   

    function tokenURI(uint256 tokenId) public virtual view override returns (string memory) {
        require(_exists(tokenId), "ERC721: nonexistent token");
        
        return _metadataGenerator.tokenMetadata(
            tokenId, 
            decodeClass(_values[tokenId]), 
            decodeMass(_values[tokenId]), 
            decodeMass(_values[_alphaId]), 
            tokenId == _alphaId,
            getMergeCount(tokenId));
    }

    function encodeClassAndMass(uint256 class, uint256 mass) public pure returns (uint256) {
        ensureValidClass(class);
        ensureValidMass(mass);
        return ((class * CLASS_MULTIPLIER) + mass);
    }

    function decodeClassAndMass(uint256 value) public pure returns (uint256, uint256) {
        uint256 class = decodeClass(value);
        uint256 mass = decodeMass(value);
        return (class, mass);
    }

    function decodeClass(uint256 value) public pure returns (uint256 class) {
        class = value / CLASS_MULTIPLIER; // integer division is ‘checked’ in Solidity 0.8.x
        ensureValidClass(class);
    }    

    function decodeMass(uint256 value) public pure returns (uint256 mass) {
        mass = value % CLASS_MULTIPLIER; // integer modulo is ‘checked’ in Solidity 0.8.x
        ensureValidMass(mass);
    }

    function _msgSender() internal view returns (address) {
        return msg.sender;
    }
     
    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) private returns (bool) {
        if (isContract(to)) {
            try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721Receiver(to).onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                }
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    revert(add(32, reason), mload(reason))
                }
            }
        }
        return true;
    }    

    function isContract(address account) internal view returns (bool) {
        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        bytes4 _ERC165_ = 0x01ffc9a7;
        bytes4 _ERC721_ = 0x80ac58cd;
        bytes4 _ERC2981_ = 0x2a55205a;
        bytes4 _ERC721Metadata_ = 0x5b5e139f;
        return interfaceId == _ERC165_ 
            || interfaceId == _ERC721_
            || interfaceId == _ERC2981_
            || interfaceId == _ERC721Metadata_;
    }


    function burn(uint256 tokenId) public notFrozen {
        (address owner, bool isApprovedOrOwner) = _isApprovedOrOwner(_msgSender(), tokenId);
        require(isApprovedOrOwner, "ERC721: caller is not owner nor approved");

        _burnNoEmitTransfer(owner, tokenId);

        emit Transfer(owner, address(0), tokenId);
    }

    function _burnNoEmitTransfer(address owner, uint256 tokenId) internal {
        _approve(owner, address(0), tokenId);

        _massTotal -= decodeMass(_values[tokenId]);

        delete _tokens[owner];
        delete _owners[tokenId];
        delete _values[tokenId];

        _countToken -= 1;
        _balances[owner] -= 1;        

        emit MassUpdate(tokenId, 0, 0);
    }
}

File 2 of 6 : MergeMetadata.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.6;

/** 
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  .***   XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  ,*********  XXXXXXXXXXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  ***************  XXXXXXXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  .*******************  XXXXXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX  ***********    **********  XXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX   ***********       ***********  XXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXX  ***********         ***************  XXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXX  ***********           ****    ********* XXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXX *********      ***    ***      *********  XXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXX  **********  *****          *********** XXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXX   /////.*************         ***********  XXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXX  /////////...***********      ************  XXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXX/ ///////////..... /////////   ///////////   XXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXX  /    //////.........///////////////////   XXXXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXX .///////...........//////////////   XXXXXXXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXX .///////.....//..////  /////////  XXXXXXXXXXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXX# /////////////////////  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXX   ////////////////////   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXX   ////////////// //////   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 */

import {ABDKMath64x64} from "../util/ABDKMath64x64.sol";
import {Base64} from "../util/Base64.sol";
import {Roots} from "../util/Roots.sol";
import {Strings} from "../util/Strings.sol";

interface IMergeMetadata {    
    function tokenMetadata(
        uint256 tokenId, 
        uint256 rarity, 
        uint256 tokenMass, 
        uint256 alphaMass, 
        bool isAlpha, 
        uint256 mergeCount) external view returns (string memory);
}

contract MergeMetadata is IMergeMetadata {
    
    struct ERC721MetadataStructure {
        bool isImageLinked;
        string name;
        string description;
        string createdBy;
        string image;
        ERC721MetadataAttribute[] attributes;
    }

    struct ERC721MetadataAttribute {
        bool includeDisplayType;
        bool includeTraitType;
        bool isValueAString;
        string displayType;
        string traitType;
        string value;
    }
    
    using ABDKMath64x64 for int128;    
    using Base64 for string;
    using Roots for uint;    
    using Strings for uint256;    
    
    address public owner;  

    string private _name;
    string private _imageBaseURI;
    string private _imageExtension;
    uint256 private _maxRadius;
    string[] private _imageParts;
    mapping (string => string) private _classStyles;
  
    string constant private _RADIUS_TAG = '<RADIUS>';
    string constant private _CLASS_TAG = '<CLASS>';  
    string constant private _CLASS_STYLE_TAG = '<CLASS_STYLE>';  
  
    constructor() {
        owner = msg.sender;
        _name = "m";
        _imageBaseURI = ""; // Set to empty string - results in on-chain SVG generation by default unless this is set later
        _imageExtension = ""; // Set to empty string - can be changed later to remain empty, .png, .mp4, etc
        _maxRadius = 1000;

        // Deploy with default SVG image parts - can be completely replaced later
        _imageParts.push("<svg xmlns='http://www.w3.org/2000/svg' version='1.1' width='2000' height='2000'>");
            _imageParts.push("<style>");
                _imageParts.push(".m1 #c{fill: #fff;}");
                _imageParts.push(".m1 #r{fill: #000;}");
                _imageParts.push(".m2 #c{fill: #fc3;}");
                _imageParts.push(".m2 #r{fill: #000;}");
                _imageParts.push(".m3 #c{fill: #fff;}");
                _imageParts.push(".m3 #r{fill: #33f;}");
                _imageParts.push(".m4 #c{fill: #fff;}");
                _imageParts.push(".m4 #r{fill: #f33;}");
                _imageParts.push(".a #c{fill: #000 !important;}");
                _imageParts.push(".a #r{fill: #fff !important;}");
                _imageParts.push(_CLASS_STYLE_TAG);
            _imageParts.push("</style>");
            _imageParts.push("<g class='");
                _imageParts.push(_CLASS_TAG);
                _imageParts.push("'>");
                    _imageParts.push("<rect id='r' width='2000' height='2000'/>");
                    _imageParts.push("<circle id='c' cx='1000' cy='1000' r='");
                        _imageParts.push(_RADIUS_TAG);
                    _imageParts.push("'/>");
            _imageParts.push("</g>");                
        _imageParts.push("</svg>");
    }        
    
    function setName(string calldata name_) external { 
        _requireOnlyOwner();       
        _name = name_;
    }

    function setImageBaseURI(string calldata imageBaseURI_, string calldata imageExtension_) external {        
        _requireOnlyOwner();
        _imageBaseURI = imageBaseURI_;
        _imageExtension = imageExtension_;
    }

    function setMaxRadius(uint256 maxRadius_) external {
        _requireOnlyOwner();
        _maxRadius = maxRadius_;
    }    

    function tokenMetadata(uint256 tokenId, uint256 rarity, uint256 tokenMass, uint256 alphaMass, bool isAlpha, uint256 mergeCount) external view override returns (string memory) {        
        string memory base64Json = Base64.encode(bytes(string(abi.encodePacked(_getJson(tokenId, rarity, tokenMass, alphaMass, isAlpha, mergeCount)))));
        return string(abi.encodePacked('data:application/json;base64,', base64Json));
    }

    function updateImageParts(string[] memory imageParts_) public {
        _requireOnlyOwner();
        _imageParts = imageParts_;
    }

    function updateClassStyle(string calldata cssClass, string calldata cssStyle) external {
        _requireOnlyOwner();
        _classStyles[cssClass] = cssStyle;
    }

    function getClassStyle(string memory cssClass) public view returns (string memory) {
        return _classStyles[cssClass];
    }

    function name() public view returns (string memory) {
        return _name;
    }

    function imageBaseURI() public view returns (string memory) {
        return _imageBaseURI;
    }

    function imageExtension() public view returns (string memory) {
        return _imageExtension;
    }

    function maxRadius() public view returns (uint256) {
        return _maxRadius;
    }            

    function getClassString(uint256 tokenId, uint256 rarity, bool isAlpha, bool offchainImage) public pure returns (string memory) {
        return _getClassString(tokenId, rarity, isAlpha, offchainImage);
    }

    function _getJson(uint256 tokenId, uint256 rarity, uint256 tokenMass, uint256 alphaMass, bool isAlpha, uint256 mergeCount) private view returns (string memory) {        
        string memory imageData = 
            bytes(_imageBaseURI).length == 0 ? 
                _getSvg(tokenId, rarity, tokenMass, alphaMass, isAlpha) :
                string(abi.encodePacked(imageBaseURI(), _getClassString(tokenId, rarity, isAlpha, true), "_", uint256(int256(_getScaledRadius(tokenMass, alphaMass, _maxRadius).toInt())).toString(), imageExtension()));

        ERC721MetadataStructure memory metadata = ERC721MetadataStructure({
            isImageLinked: bytes(_imageBaseURI).length > 0, 
            name: string(abi.encodePacked(name(), "(", tokenMass.toString(), ") #", tokenId.toString())),
            description: tokenMass.toString(),
            createdBy: "Pak",
            image: imageData,
            attributes: _getJsonAttributes(tokenId, rarity, tokenMass, mergeCount, isAlpha)
        });

        return _generateERC721Metadata(metadata);
    }        

    function _getJsonAttributes(uint256 tokenId, uint256 rarity, uint256 tokenMass, uint256 mergeCount, bool isAlpha) private pure returns (ERC721MetadataAttribute[] memory) {
        uint256 tensDigit = tokenId % 100 / 10;
        uint256 onesDigit = tokenId % 10;
        uint256 class = tensDigit * 10 + onesDigit;

        ERC721MetadataAttribute[] memory metadataAttributes = new ERC721MetadataAttribute[](5);
        metadataAttributes[0] = _getERC721MetadataAttribute(false, true, false, "", "Mass", tokenMass.toString());
        metadataAttributes[1] = _getERC721MetadataAttribute(false, true, false, "", "Alpha", isAlpha ? "1" : "0");
        metadataAttributes[2] = _getERC721MetadataAttribute(false, true, false, "", "Tier", rarity.toString());
        metadataAttributes[3] = _getERC721MetadataAttribute(false, true, false, "", "Class", class.toString());
        metadataAttributes[4] = _getERC721MetadataAttribute(false, true, false, "", "Merges", mergeCount.toString());
        return metadataAttributes;
    }    

    function _getERC721MetadataAttribute(bool includeDisplayType, bool includeTraitType, bool isValueAString, string memory displayType, string memory traitType, string memory value) private pure returns (ERC721MetadataAttribute memory) {
        ERC721MetadataAttribute memory attribute = ERC721MetadataAttribute({
            includeDisplayType: includeDisplayType,
            includeTraitType: includeTraitType,
            isValueAString: isValueAString,
            displayType: displayType,
            traitType: traitType,
            value: value
        });

        return attribute;
    }    

    function _getSvg(uint256 tokenId, uint256 rarity, uint256 tokenMass, uint256 alphaMass, bool isAlpha) private view returns (string memory) {
        bytes memory byteString;
        for (uint i = 0; i < _imageParts.length; i++) {
          if (_checkTag(_imageParts[i], _RADIUS_TAG)) {
            byteString = abi.encodePacked(byteString, _floatToString(_getScaledRadius(tokenMass, alphaMass, _maxRadius)));
          } else if (_checkTag(_imageParts[i], _CLASS_TAG)) {
            byteString = abi.encodePacked(byteString, _getClassString(tokenId, rarity, isAlpha, false));
          } else if (_checkTag(_imageParts[i], _CLASS_STYLE_TAG)) {
              uint256 tensDigit = tokenId % 100 / 10;
              uint256 onesDigit = tokenId % 10;
              uint256 class = tensDigit * 10 + onesDigit;
              string memory classCss = getClassStyle(_getTokenIdClass(class));
              if(bytes(classCss).length > 0) {
                  byteString = abi.encodePacked(byteString, classCss);
              }            
          } else {
            byteString = abi.encodePacked(byteString, _imageParts[i]);
          }
        }
        return string(byteString); 
    }

    function _getScaledRadius(uint256 tokenMass, uint256 alphaMass, uint256 maximumRadius) private pure returns (int128) {
        int128 radiusMass = _getRadius64x64(tokenMass);
        int128 radiusAlphaMass = _getRadius64x64(alphaMass);
        int128 scalePercentage = ABDKMath64x64.div(radiusMass, radiusAlphaMass);                
        int128 scaledRadius = ABDKMath64x64.mul(ABDKMath64x64.fromUInt(maximumRadius), scalePercentage);
        if(uint256(int256(scaledRadius.toInt())) == 0) {
            scaledRadius = ABDKMath64x64.fromUInt(1);
        }
        return scaledRadius;
    }

    // Radius = Cube Root(Mass) * Cube Root (0.23873241463)
    // Radius = Cube Root(Mass) * 0.62035049089
    function _getRadius64x64(uint256 mass) private pure returns (int128) {        
        int128 cubeRootScalar = ABDKMath64x64.divu(62035049089, 100000000000);
        int128 cubeRootMass = ABDKMath64x64.divu(mass.nthRoot(3, 6, 32), 1000000);
        int128 radius = ABDKMath64x64.mul(cubeRootMass, cubeRootScalar);        
        return radius;
    }            

    function _generateERC721Metadata(ERC721MetadataStructure memory metadata) private pure returns (string memory) {
      bytes memory byteString;    
    
        byteString = abi.encodePacked(
          byteString,
          _openJsonObject());
    
        byteString = abi.encodePacked(
          byteString,
          _pushJsonPrimitiveStringAttribute("name", metadata.name, true));
    
        byteString = abi.encodePacked(
          byteString,
          _pushJsonPrimitiveStringAttribute("description", metadata.description, true));
    
        byteString = abi.encodePacked(
          byteString,
          _pushJsonPrimitiveStringAttribute("created_by", metadata.createdBy, true));
    
        if(metadata.isImageLinked) {
            byteString = abi.encodePacked(
                byteString,
                _pushJsonPrimitiveStringAttribute("image", metadata.image, true));
        } else {
            byteString = abi.encodePacked(
                byteString,
                _pushJsonPrimitiveStringAttribute("image_data", metadata.image, true));
        }

        byteString = abi.encodePacked(
          byteString,
          _pushJsonComplexAttribute("attributes", _getAttributes(metadata.attributes), false));
    
        byteString = abi.encodePacked(
          byteString,
          _closeJsonObject());
    
        return string(byteString);
    }

    function _getAttributes(ERC721MetadataAttribute[] memory attributes) private pure returns (string memory) {
        bytes memory byteString;
    
        byteString = abi.encodePacked(
          byteString,
          _openJsonArray());
    
        for (uint i = 0; i < attributes.length; i++) {
          ERC721MetadataAttribute memory attribute = attributes[i];

          byteString = abi.encodePacked(
            byteString,
            _pushJsonArrayElement(_getAttribute(attribute), i < (attributes.length - 1)));
        }
    
        byteString = abi.encodePacked(
          byteString,
          _closeJsonArray());
    
        return string(byteString);
    }

    function _getAttribute(ERC721MetadataAttribute memory attribute) private pure returns (string memory) {
        bytes memory byteString;
        
        byteString = abi.encodePacked(
          byteString,
          _openJsonObject());
    
        if(attribute.includeDisplayType) {
          byteString = abi.encodePacked(
            byteString,
            _pushJsonPrimitiveStringAttribute("display_type", attribute.displayType, true));
        }
    
        if(attribute.includeTraitType) {
          byteString = abi.encodePacked(
            byteString,
            _pushJsonPrimitiveStringAttribute("trait_type", attribute.traitType, true));
        }
    
        if(attribute.isValueAString) {
          byteString = abi.encodePacked(
            byteString,
            _pushJsonPrimitiveStringAttribute("value", attribute.value, false));
        } else {
          byteString = abi.encodePacked(
            byteString,
            _pushJsonPrimitiveNonStringAttribute("value", attribute.value, false));
        }
    
        byteString = abi.encodePacked(
          byteString,
          _closeJsonObject());
    
        return string(byteString);
    }

    function _getClassString(uint256 tokenId, uint256 rarity, bool isAlpha, bool offchainImage) private pure returns (string memory) {
        bytes memory byteString;    
    
        byteString = abi.encodePacked(byteString, _getRarityClass(rarity));
        
        if(isAlpha) {
            byteString = abi.encodePacked(
              byteString,
              string(abi.encodePacked(offchainImage ? "_" : " ", "a")));
        }

        uint256 tensDigit = tokenId % 100 / 10;
        uint256 onesDigit = tokenId % 10;
        uint256 class = tensDigit * 10 + onesDigit;

        byteString = abi.encodePacked(
          byteString,
          string(abi.encodePacked(offchainImage ? "_" : " ", _getTokenIdClass(class))));

        return string(byteString);    
    }

    function _getRarityClass(uint256 rarity) private pure returns (string memory) {
        return string(abi.encodePacked("m", rarity.toString()));
    }

    function _getTokenIdClass(uint256 class) private pure returns (string memory) {
        return string(abi.encodePacked("c", class.toString()));
    }

    function _checkTag(string storage a, string memory b) private pure returns (bool) {
        return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));
    }

    function _floatToString(int128 value) private pure returns (string memory) {
        uint256 decimal4 = (value & 0xFFFFFFFFFFFFFFFF).mulu(10000);
        return string(abi.encodePacked(uint256(int256(value.toInt())).toString(), '.', _decimal4ToString(decimal4)));
    }
  
    function _decimal4ToString(uint256 decimal4) private pure returns (string memory) {
        bytes memory decimal4Characters = new bytes(4);
        for (uint i = 0; i < 4; i++) {
          decimal4Characters[3 - i] = bytes1(uint8(0x30 + decimal4 % 10));
          decimal4 /= 10;
        }
        return string(abi.encodePacked(decimal4Characters));
    }

    function _requireOnlyOwner() private view {
        require(msg.sender == owner, "You are not the owner");
    }

    function _openJsonObject() private pure returns (string memory) {        
        return string(abi.encodePacked("{"));
    }

    function _closeJsonObject() private pure returns (string memory) {
        return string(abi.encodePacked("}"));
    }

    function _openJsonArray() private pure returns (string memory) {        
        return string(abi.encodePacked("["));
    }

    function _closeJsonArray() private pure returns (string memory) {        
        return string(abi.encodePacked("]"));
    }

    function _pushJsonPrimitiveStringAttribute(string memory key, string memory value, bool insertComma) private pure returns (string memory) {
        return string(abi.encodePacked('"', key, '": "', value, '"', insertComma ? ',' : ''));
    }

    function _pushJsonPrimitiveNonStringAttribute(string memory key, string memory value, bool insertComma) private pure returns (string memory) {
        return string(abi.encodePacked('"', key, '": ', value, insertComma ? ',' : ''));
    }

    function _pushJsonComplexAttribute(string memory key, string memory value, bool insertComma) private pure returns (string memory) {
        return string(abi.encodePacked('"', key, '": ', value, insertComma ? ',' : ''));
    }

    function _pushJsonArrayElement(string memory value, bool insertComma) private pure returns (string memory) {
        return string(abi.encodePacked(value, insertComma ? ',' : ''));
    }
}

// SPDX-License-Identifier: BSD-4-Clause
/*
 * ABDK Math 64.64 Smart Contract Library.  Copyright © 2019 by ABDK Consulting.
 * Author: Mikhail Vladimirov <mikhail.vladimirov@gmail.com>
 */
pragma solidity ^0.8.6;

/**
 * Smart contract library of mathematical functions operating with signed
 * 64.64-bit fixed point numbers.  Signed 64.64-bit fixed point number is
 * basically a simple fraction whose numerator is signed 128-bit integer and
 * denominator is 2^64.  As long as denominator is always the same, there is no
 * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are
 * represented by int128 type holding only the numerator.
 */
library ABDKMath64x64 {
  /*
   * Minimum value signed 64.64-bit fixed point number may have. 
   */
  int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;

  /*
   * Maximum value signed 64.64-bit fixed point number may have. 
   */
  int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

  /**
   * Convert signed 256-bit integer number into signed 64.64-bit fixed point
   * number.  Revert on overflow.
   *
   * @param x signed 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function fromInt (int256 x) internal pure returns (int128) {
    unchecked {
      require (x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF);
      return int128 (x << 64);
    }
  }

  /**
   * Convert signed 64.64 fixed point number into signed 64-bit integer number
   * rounding down.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64-bit integer number
   */
  function toInt (int128 x) internal pure returns (int64) {
    unchecked {
      return int64 (x >> 64);
    }
  }

  /**
   * Convert unsigned 256-bit integer number into signed 64.64-bit fixed point
   * number.  Revert on overflow.
   *
   * @param x unsigned 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function fromUInt (uint256 x) internal pure returns (int128) {
    unchecked {
      require (x <= 0x7FFFFFFFFFFFFFFF);
      return int128 (int256 (x << 64));
    }
  }

  /**
   * Convert signed 64.64 fixed point number into unsigned 64-bit integer
   * number rounding down.  Revert on underflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return unsigned 64-bit integer number
   */
  function toUInt (int128 x) internal pure returns (uint64) {
    unchecked {
      require (x >= 0);
      return uint64 (uint128 (x >> 64));
    }
  }

  /**
   * Convert signed 128.128 fixed point number into signed 64.64-bit fixed point
   * number rounding down.  Revert on overflow.
   *
   * @param x signed 128.128-bin fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function from128x128 (int256 x) internal pure returns (int128) {
    unchecked {
      int256 result = x >> 64;
      require (result >= MIN_64x64 && result <= MAX_64x64);
      return int128 (result);
    }
  }

  /**
   * Convert signed 64.64 fixed point number into signed 128.128 fixed point
   * number.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 128.128 fixed point number
   */
  function to128x128 (int128 x) internal pure returns (int256) {
    unchecked {
      return int256 (x) << 64;
    }
  }

  /**
   * Calculate x + y.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function add (int128 x, int128 y) internal pure returns (int128) {
    unchecked {
      int256 result = int256(x) + y;
      require (result >= MIN_64x64 && result <= MAX_64x64);
      return int128 (result);
    }
  }

  /**
   * Calculate x - y.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function sub (int128 x, int128 y) internal pure returns (int128) {
    unchecked {
      int256 result = int256(x) - y;
      require (result >= MIN_64x64 && result <= MAX_64x64);
      return int128 (result);
    }
  }

  /**
   * Calculate x * y rounding down.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function mul (int128 x, int128 y) internal pure returns (int128) {
    unchecked {
      int256 result = int256(x) * y >> 64;
      require (result >= MIN_64x64 && result <= MAX_64x64);
      return int128 (result);
    }
  }

  /**
   * Calculate x * y rounding towards zero, where x is signed 64.64 fixed point
   * number and y is signed 256-bit integer number.  Revert on overflow.
   *
   * @param x signed 64.64 fixed point number
   * @param y signed 256-bit integer number
   * @return signed 256-bit integer number
   */
  function muli (int128 x, int256 y) internal pure returns (int256) {
    unchecked {
      if (x == MIN_64x64) {
        require (y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF &&
          y <= 0x1000000000000000000000000000000000000000000000000);
        return -y << 63;
      } else {
        bool negativeResult = false;
        if (x < 0) {
          x = -x;
          negativeResult = true;
        }
        if (y < 0) {
          y = -y; // We rely on overflow behavior here
          negativeResult = !negativeResult;
        }
        uint256 absoluteResult = mulu (x, uint256 (y));
        if (negativeResult) {
          require (absoluteResult <=
            0x8000000000000000000000000000000000000000000000000000000000000000);
          return -int256 (absoluteResult); // We rely on overflow behavior here
        } else {
          require (absoluteResult <=
            0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
          return int256 (absoluteResult);
        }
      }
    }
  }

  /**
   * Calculate x * y rounding down, where x is signed 64.64 fixed point number
   * and y is unsigned 256-bit integer number.  Revert on overflow.
   *
   * @param x signed 64.64 fixed point number
   * @param y unsigned 256-bit integer number
   * @return unsigned 256-bit integer number
   */
  function mulu (int128 x, uint256 y) internal pure returns (uint256) {
    unchecked {
      if (y == 0) return 0;

      require (x >= 0);

      uint256 lo = (uint256 (int256 (x)) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;
      uint256 hi = uint256 (int256 (x)) * (y >> 128);

      require (hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      hi <<= 64;

      require (hi <=
        0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo);
      return hi + lo;
    }
  }

  /**
   * Calculate x / y rounding towards zero.  Revert on overflow or when y is
   * zero.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function div (int128 x, int128 y) internal pure returns (int128) {
    unchecked {
      require (y != 0);
      int256 result = (int256 (x) << 64) / y;
      require (result >= MIN_64x64 && result <= MAX_64x64);
      return int128 (result);
    }
  }

  /**
   * Calculate x / y rounding towards zero, where x and y are signed 256-bit
   * integer numbers.  Revert on overflow or when y is zero.
   *
   * @param x signed 256-bit integer number
   * @param y signed 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function divi (int256 x, int256 y) internal pure returns (int128) {
    unchecked {
      require (y != 0);

      bool negativeResult = false;
      if (x < 0) {
        x = -x; // We rely on overflow behavior here
        negativeResult = true;
      }
      if (y < 0) {
        y = -y; // We rely on overflow behavior here
        negativeResult = !negativeResult;
      }
      uint128 absoluteResult = divuu (uint256 (x), uint256 (y));
      if (negativeResult) {
        require (absoluteResult <= 0x80000000000000000000000000000000);
        return -int128 (absoluteResult); // We rely on overflow behavior here
      } else {
        require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
        return int128 (absoluteResult); // We rely on overflow behavior here
      }
    }
  }

  /**
   * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
   * integer numbers.  Revert on overflow or when y is zero.
   *
   * @param x unsigned 256-bit integer number
   * @param y unsigned 256-bit integer number
   * @return signed 64.64-bit fixed point number
   */
  function divu (uint256 x, uint256 y) internal pure returns (int128) {
    unchecked {
      require (y != 0);
      uint128 result = divuu (x, y);
      require (result <= uint128 (MAX_64x64));
      return int128 (result);
    }
  }

  /**
   * Calculate -x.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function neg (int128 x) internal pure returns (int128) {
    unchecked {
      require (x != MIN_64x64);
      return -x;
    }
  }

  /**
   * Calculate |x|.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function abs (int128 x) internal pure returns (int128) {
    unchecked {
      require (x != MIN_64x64);
      return x < 0 ? -x : x;
    }
  }

  /**
   * Calculate 1 / x rounding towards zero.  Revert on overflow or when x is
   * zero.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function inv (int128 x) internal pure returns (int128) {
    unchecked {
      require (x != 0);
      int256 result = int256 (0x100000000000000000000000000000000) / x;
      require (result >= MIN_64x64 && result <= MAX_64x64);
      return int128 (result);
    }
  }

  /**
   * Calculate arithmetics average of x and y, i.e. (x + y) / 2 rounding down.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function avg (int128 x, int128 y) internal pure returns (int128) {
    unchecked {
      return int128 ((int256 (x) + int256 (y)) >> 1);
    }
  }

  /**
   * Calculate geometric average of x and y, i.e. sqrt (x * y) rounding down.
   * Revert on overflow or in case x * y is negative.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function gavg (int128 x, int128 y) internal pure returns (int128) {
    unchecked {
      int256 m = int256 (x) * int256 (y);
      require (m >= 0);
      require (m <
          0x4000000000000000000000000000000000000000000000000000000000000000);
      return int128 (sqrtu (uint256 (m)));
    }
  }

  /**
   * Calculate x^y assuming 0^0 is 1, where x is signed 64.64 fixed point number
   * and y is unsigned 256-bit integer number.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @param y uint256 value
   * @return signed 64.64-bit fixed point number
   */
  function pow (int128 x, uint256 y) internal pure returns (int128) {
    unchecked {
      bool negative = x < 0 && y & 1 == 1;

      uint256 absX = uint128 (x < 0 ? -x : x);
      uint256 absResult;
      absResult = 0x100000000000000000000000000000000;

      if (absX <= 0x10000000000000000) {
        absX <<= 63;
        while (y != 0) {
          if (y & 0x1 != 0) {
            absResult = absResult * absX >> 127;
          }
          absX = absX * absX >> 127;

          if (y & 0x2 != 0) {
            absResult = absResult * absX >> 127;
          }
          absX = absX * absX >> 127;

          if (y & 0x4 != 0) {
            absResult = absResult * absX >> 127;
          }
          absX = absX * absX >> 127;

          if (y & 0x8 != 0) {
            absResult = absResult * absX >> 127;
          }
          absX = absX * absX >> 127;

          y >>= 4;
        }

        absResult >>= 64;
      } else {
        uint256 absXShift = 63;
        if (absX < 0x1000000000000000000000000) { absX <<= 32; absXShift -= 32; }
        if (absX < 0x10000000000000000000000000000) { absX <<= 16; absXShift -= 16; }
        if (absX < 0x1000000000000000000000000000000) { absX <<= 8; absXShift -= 8; }
        if (absX < 0x10000000000000000000000000000000) { absX <<= 4; absXShift -= 4; }
        if (absX < 0x40000000000000000000000000000000) { absX <<= 2; absXShift -= 2; }
        if (absX < 0x80000000000000000000000000000000) { absX <<= 1; absXShift -= 1; }

        uint256 resultShift = 0;
        while (y != 0) {
          require (absXShift < 64);

          if (y & 0x1 != 0) {
            absResult = absResult * absX >> 127;
            resultShift += absXShift;
            if (absResult > 0x100000000000000000000000000000000) {
              absResult >>= 1;
              resultShift += 1;
            }
          }
          absX = absX * absX >> 127;
          absXShift <<= 1;
          if (absX >= 0x100000000000000000000000000000000) {
              absX >>= 1;
              absXShift += 1;
          }

          y >>= 1;
        }

        require (resultShift < 64);
        absResult >>= 64 - resultShift;
      }
      int256 result = negative ? -int256 (absResult) : int256 (absResult);
      require (result >= MIN_64x64 && result <= MAX_64x64);
      return int128 (result);
    }
  }

  /**
   * Calculate sqrt (x) rounding down.  Revert if x < 0.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function sqrt (int128 x) internal pure returns (int128) {
    unchecked {
      require (x >= 0);
      return int128 (sqrtu (uint256 (int256 (x)) << 64));
    }
  }

  /**
   * Calculate binary logarithm of x.  Revert if x <= 0.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function log_2 (int128 x) internal pure returns (int128) {
    unchecked {
      require (x > 0);

      int256 msb = 0;
      int256 xc = x;
      if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; }
      if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
      if (xc >= 0x10000) { xc >>= 16; msb += 16; }
      if (xc >= 0x100) { xc >>= 8; msb += 8; }
      if (xc >= 0x10) { xc >>= 4; msb += 4; }
      if (xc >= 0x4) { xc >>= 2; msb += 2; }
      if (xc >= 0x2) msb += 1;  // No need to shift xc anymore

      int256 result = msb - 64 << 64;
      uint256 ux = uint256 (int256 (x)) << uint256 (127 - msb);
      for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {
        ux *= ux;
        uint256 b = ux >> 255;
        ux >>= 127 + b;
        result += bit * int256 (b);
      }

      return int128 (result);
    }
  }

  /**
   * Calculate natural logarithm of x.  Revert if x <= 0.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function ln (int128 x) internal pure returns (int128) {
    unchecked {
      require (x > 0);

      return int128 (int256 (
          uint256 (int256 (log_2 (x))) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF >> 128));
    }
  }

  /**
   * Calculate binary exponent of x.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function exp_2 (int128 x) internal pure returns (int128) {
    unchecked {
      require (x < 0x400000000000000000); // Overflow

      if (x < -0x400000000000000000) return 0; // Underflow

      uint256 result = 0x80000000000000000000000000000000;

      if (x & 0x8000000000000000 > 0)
        result = result * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128;
      if (x & 0x4000000000000000 > 0)
        result = result * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128;
      if (x & 0x2000000000000000 > 0)
        result = result * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128;
      if (x & 0x1000000000000000 > 0)
        result = result * 0x10B5586CF9890F6298B92B71842A98363 >> 128;
      if (x & 0x800000000000000 > 0)
        result = result * 0x1059B0D31585743AE7C548EB68CA417FD >> 128;
      if (x & 0x400000000000000 > 0)
        result = result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128;
      if (x & 0x200000000000000 > 0)
        result = result * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128;
      if (x & 0x100000000000000 > 0)
        result = result * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128;
      if (x & 0x80000000000000 > 0)
        result = result * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128;
      if (x & 0x40000000000000 > 0)
        result = result * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128;
      if (x & 0x20000000000000 > 0)
        result = result * 0x100162F3904051FA128BCA9C55C31E5DF >> 128;
      if (x & 0x10000000000000 > 0)
        result = result * 0x1000B175EFFDC76BA38E31671CA939725 >> 128;
      if (x & 0x8000000000000 > 0)
        result = result * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128;
      if (x & 0x4000000000000 > 0)
        result = result * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128;
      if (x & 0x2000000000000 > 0)
        result = result * 0x1000162E525EE054754457D5995292026 >> 128;
      if (x & 0x1000000000000 > 0)
        result = result * 0x10000B17255775C040618BF4A4ADE83FC >> 128;
      if (x & 0x800000000000 > 0)
        result = result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128;
      if (x & 0x400000000000 > 0)
        result = result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128;
      if (x & 0x200000000000 > 0)
        result = result * 0x10000162E43F4F831060E02D839A9D16D >> 128;
      if (x & 0x100000000000 > 0)
        result = result * 0x100000B1721BCFC99D9F890EA06911763 >> 128;
      if (x & 0x80000000000 > 0)
        result = result * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128;
      if (x & 0x40000000000 > 0)
        result = result * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128;
      if (x & 0x20000000000 > 0)
        result = result * 0x100000162E430E5A18F6119E3C02282A5 >> 128;
      if (x & 0x10000000000 > 0)
        result = result * 0x1000000B1721835514B86E6D96EFD1BFE >> 128;
      if (x & 0x8000000000 > 0)
        result = result * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128;
      if (x & 0x4000000000 > 0)
        result = result * 0x10000002C5C8601CC6B9E94213C72737A >> 128;
      if (x & 0x2000000000 > 0)
        result = result * 0x1000000162E42FFF037DF38AA2B219F06 >> 128;
      if (x & 0x1000000000 > 0)
        result = result * 0x10000000B17217FBA9C739AA5819F44F9 >> 128;
      if (x & 0x800000000 > 0)
        result = result * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128;
      if (x & 0x400000000 > 0)
        result = result * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128;
      if (x & 0x200000000 > 0)
        result = result * 0x10000000162E42FF0999CE3541B9FFFCF >> 128;
      if (x & 0x100000000 > 0)
        result = result * 0x100000000B17217F80F4EF5AADDA45554 >> 128;
      if (x & 0x80000000 > 0)
        result = result * 0x10000000058B90BFBF8479BD5A81B51AD >> 128;
      if (x & 0x40000000 > 0)
        result = result * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128;
      if (x & 0x20000000 > 0)
        result = result * 0x100000000162E42FEFB2FED257559BDAA >> 128;
      if (x & 0x10000000 > 0)
        result = result * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128;
      if (x & 0x8000000 > 0)
        result = result * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128;
      if (x & 0x4000000 > 0)
        result = result * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128;
      if (x & 0x2000000 > 0)
        result = result * 0x1000000000162E42FEFA494F1478FDE05 >> 128;
      if (x & 0x1000000 > 0)
        result = result * 0x10000000000B17217F7D20CF927C8E94C >> 128;
      if (x & 0x800000 > 0)
        result = result * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128;
      if (x & 0x400000 > 0)
        result = result * 0x100000000002C5C85FDF477B662B26945 >> 128;
      if (x & 0x200000 > 0)
        result = result * 0x10000000000162E42FEFA3AE53369388C >> 128;
      if (x & 0x100000 > 0)
        result = result * 0x100000000000B17217F7D1D351A389D40 >> 128;
      if (x & 0x80000 > 0)
        result = result * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128;
      if (x & 0x40000 > 0)
        result = result * 0x1000000000002C5C85FDF4741BEA6E77E >> 128;
      if (x & 0x20000 > 0)
        result = result * 0x100000000000162E42FEFA39FE95583C2 >> 128;
      if (x & 0x10000 > 0)
        result = result * 0x1000000000000B17217F7D1CFB72B45E1 >> 128;
      if (x & 0x8000 > 0)
        result = result * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128;
      if (x & 0x4000 > 0)
        result = result * 0x10000000000002C5C85FDF473E242EA38 >> 128;
      if (x & 0x2000 > 0)
        result = result * 0x1000000000000162E42FEFA39F02B772C >> 128;
      if (x & 0x1000 > 0)
        result = result * 0x10000000000000B17217F7D1CF7D83C1A >> 128;
      if (x & 0x800 > 0)
        result = result * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128;
      if (x & 0x400 > 0)
        result = result * 0x100000000000002C5C85FDF473DEA871F >> 128;
      if (x & 0x200 > 0)
        result = result * 0x10000000000000162E42FEFA39EF44D91 >> 128;
      if (x & 0x100 > 0)
        result = result * 0x100000000000000B17217F7D1CF79E949 >> 128;
      if (x & 0x80 > 0)
        result = result * 0x10000000000000058B90BFBE8E7BCE544 >> 128;
      if (x & 0x40 > 0)
        result = result * 0x1000000000000002C5C85FDF473DE6ECA >> 128;
      if (x & 0x20 > 0)
        result = result * 0x100000000000000162E42FEFA39EF366F >> 128;
      if (x & 0x10 > 0)
        result = result * 0x1000000000000000B17217F7D1CF79AFA >> 128;
      if (x & 0x8 > 0)
        result = result * 0x100000000000000058B90BFBE8E7BCD6D >> 128;
      if (x & 0x4 > 0)
        result = result * 0x10000000000000002C5C85FDF473DE6B2 >> 128;
      if (x & 0x2 > 0)
        result = result * 0x1000000000000000162E42FEFA39EF358 >> 128;
      if (x & 0x1 > 0)
        result = result * 0x10000000000000000B17217F7D1CF79AB >> 128;

      result >>= uint256 (int256 (63 - (x >> 64)));
      require (result <= uint256 (int256 (MAX_64x64)));

      return int128 (int256 (result));
    }
  }

  /**
   * Calculate natural exponent of x.  Revert on overflow.
   *
   * @param x signed 64.64-bit fixed point number
   * @return signed 64.64-bit fixed point number
   */
  function exp (int128 x) internal pure returns (int128) {
    unchecked {
      require (x < 0x400000000000000000); // Overflow

      if (x < -0x400000000000000000) return 0; // Underflow

      return exp_2 (
          int128 (int256 (x) * 0x171547652B82FE1777D0FFDA0D23A7D12 >> 128));
    }
  }

  /**
   * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit
   * integer numbers.  Revert on overflow or when y is zero.
   *
   * @param x unsigned 256-bit integer number
   * @param y unsigned 256-bit integer number
   * @return unsigned 64.64-bit fixed point number
   */
  function divuu (uint256 x, uint256 y) private pure returns (uint128) {
    unchecked {
      require (y != 0);

      uint256 result;

      if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
        result = (x << 64) / y;
      else {
        uint256 msb = 192;
        uint256 xc = x >> 192;
        if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
        if (xc >= 0x10000) { xc >>= 16; msb += 16; }
        if (xc >= 0x100) { xc >>= 8; msb += 8; }
        if (xc >= 0x10) { xc >>= 4; msb += 4; }
        if (xc >= 0x4) { xc >>= 2; msb += 2; }
        if (xc >= 0x2) msb += 1;  // No need to shift xc anymore

        result = (x << 255 - msb) / ((y - 1 >> msb - 191) + 1);
        require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

        uint256 hi = result * (y >> 128);
        uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);

        uint256 xh = x >> 192;
        uint256 xl = x << 64;

        if (xl < lo) xh -= 1;
        xl -= lo; // We rely on overflow behavior here
        lo = hi << 128;
        if (xl < lo) xh -= 1;
        xl -= lo; // We rely on overflow behavior here

        assert (xh == hi >> 128);

        result += xl / y;
      }

      require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
      return uint128 (result);
    }
  }

  /**
   * Calculate sqrt (x) rounding down, where x is unsigned 256-bit integer
   * number.
   *
   * @param x unsigned 256-bit integer number
   * @return unsigned 128-bit integer number
   */
  function sqrtu (uint256 x) private pure returns (uint128) {
    unchecked {
      if (x == 0) return 0;
      else {
        uint256 xx = x;
        uint256 r = 1;
        if (xx >= 0x100000000000000000000000000000000) { xx >>= 128; r <<= 64; }
        if (xx >= 0x10000000000000000) { xx >>= 64; r <<= 32; }
        if (xx >= 0x100000000) { xx >>= 32; r <<= 16; }
        if (xx >= 0x10000) { xx >>= 16; r <<= 8; }
        if (xx >= 0x100) { xx >>= 8; r <<= 4; }
        if (xx >= 0x10) { xx >>= 4; r <<= 2; }
        if (xx >= 0x8) { r <<= 1; }
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1;
        r = (r + x / r) >> 1; // Seven iterations should be enough
        uint256 r1 = x / r;
        return uint128 (r < r1 ? r : r1);
      }
    }
  }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0;

/// @title Base64
/// @author Brecht Devos - <brecht@loopring.org>
/// @notice Provides functions for encoding/decoding base64
library Base64 {
    string internal constant TABLE_ENCODE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    bytes  internal constant TABLE_DECODE = hex"0000000000000000000000000000000000000000000000000000000000000000"
                                            hex"00000000000000000000003e0000003f3435363738393a3b3c3d000000000000"
                                            hex"00000102030405060708090a0b0c0d0e0f101112131415161718190000000000"
                                            hex"001a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132330000000000";

    function encode(bytes memory data) internal pure returns (string memory) {
        if (data.length == 0) return '';

        // load the table into memory
        string memory table = TABLE_ENCODE;

        // multiply by 4/3 rounded up
        uint256 encodedLen = 4 * ((data.length + 2) / 3);

        // add some extra buffer at the end required for the writing
        string memory result = new string(encodedLen + 32);

        assembly {
            // set the actual output length
            mstore(result, encodedLen)

            // prepare the lookup table
            let tablePtr := add(table, 1)

            // input ptr
            let dataPtr := data
            let endPtr := add(dataPtr, mload(data))

            // result ptr, jump over length
            let resultPtr := add(result, 32)

            // run over the input, 3 bytes at a time
            for {} lt(dataPtr, endPtr) {}
            {
                // read 3 bytes
                dataPtr := add(dataPtr, 3)
                let input := mload(dataPtr)

                // write 4 characters
                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(shr( 6, input), 0x3F))))
                resultPtr := add(resultPtr, 1)
                mstore8(resultPtr, mload(add(tablePtr, and(        input,  0x3F))))
                resultPtr := add(resultPtr, 1)
            }

            // padding with '='
            switch mod(mload(data), 3)
            case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) }
            case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) }
        }

        return result;
    }

    function decode(string memory _data) internal pure returns (bytes memory) {
        bytes memory data = bytes(_data);

        if (data.length == 0) return new bytes(0);
        require(data.length % 4 == 0, "invalid base64 decoder input");

        // load the table into memory
        bytes memory table = TABLE_DECODE;

        // every 4 characters represent 3 bytes
        uint256 decodedLen = (data.length / 4) * 3;

        // add some extra buffer at the end required for the writing
        bytes memory result = new bytes(decodedLen + 32);

        assembly {
            // padding with '='
            let lastBytes := mload(add(data, mload(data)))
            if eq(and(lastBytes, 0xFF), 0x3d) {
                decodedLen := sub(decodedLen, 1)
                if eq(and(lastBytes, 0xFFFF), 0x3d3d) {
                    decodedLen := sub(decodedLen, 1)
                }
            }

            // set the actual output length
            mstore(result, decodedLen)

            // prepare the lookup table
            let tablePtr := add(table, 1)

            // input ptr
            let dataPtr := data
            let endPtr := add(dataPtr, mload(data))

            // result ptr, jump over length
            let resultPtr := add(result, 32)

            // run over the input, 4 characters at a time
            for {} lt(dataPtr, endPtr) {}
            {
               // read 4 characters
               dataPtr := add(dataPtr, 4)
               let input := mload(dataPtr)

               // write 3 bytes
               let output := add(
                   add(
                       shl(18, and(mload(add(tablePtr, and(shr(24, input), 0xFF))), 0xFF)),
                       shl(12, and(mload(add(tablePtr, and(shr(16, input), 0xFF))), 0xFF))),
                   add(
                       shl( 6, and(mload(add(tablePtr, and(shr( 8, input), 0xFF))), 0xFF)),
                               and(mload(add(tablePtr, and(        input , 0xFF))), 0xFF)
                    )
                )
                mstore(resultPtr, shl(232, output))
                resultPtr := add(resultPtr, 3)
            }
        }

        return result;
    }
}

pragma solidity ^0.8.6;

library Roots {

// calculates a^(1/n) to dp decimal places
    // maxIts bounds the number of iterations performed
    function nthRoot(uint _a, uint _n, uint _dp, uint _maxIts) pure internal returns(uint) {
        assert (_n > 1);

        // The scale factor is a crude way to turn everything into integer calcs.
        // Actually do (a * (10 ^ ((dp + 1) * n))) ^ (1/n)
        // We calculate to one extra dp and round at the end
        uint one = 10 ** (1 + _dp);
        uint a0 = one ** _n * _a;

        // Initial guess: 1.0
        uint xNew = one;

        uint iter = 0;
        while (iter < _maxIts) {
            uint x = xNew;
            uint t0 = x ** (_n - 1);
            if (x * t0 > a0) {
                xNew = x - (x - a0 / t0) / _n;
            } else {
                xNew = x + (a0 / t0 - x) / _n;
            }
            ++iter;
            if(xNew == x) {
                break;
            }
        }

        // Round to nearest in the last dp.
        return (xNew + 5) / 10;
    }
}

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant alphabet = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 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);
    }

}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 1000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"registry_","type":"address"},{"internalType":"address","name":"omnibus_","type":"address"},{"internalType":"address","name":"metadataGenerator_","type":"address"},{"internalType":"address","name":"pak_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"alphaMass","type":"uint256"}],"name":"AlphaMassUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"fromAddress","type":"address"},{"indexed":true,"internalType":"address","name":"toAddress","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenIdBurned","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"tokenIdPersist","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mass","type":"uint256"}],"name":"MassUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"_alphaId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_alphaMass","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_countToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_dead","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_massTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_metadataGenerator","outputs":[{"internalType":"contract IMergeMetadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_mintingFinalized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_nextMintId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_omnibus","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_pak","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_percentageRoyalty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_percentageTotal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_receiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_registry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds_","type":"uint256[]"},{"internalType":"uint256[]","name":"mergeCounts_","type":"uint256[]"}],"name":"batchSetMergeCountFromSnapshot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"decodeClass","outputs":[{"internalType":"uint256","name":"class","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"decodeClassAndMass","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"decodeMass","outputs":[{"internalType":"uint256","name":"mass","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"class","type":"uint256"},{"internalType":"uint256","name":"mass","type":"uint256"}],"name":"encodeClassAndMass","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"finalize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"freeze","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"frozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getMergeCount","outputs":[{"internalType":"uint256","name":"mergeCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getValueOf","outputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"address_","type":"address"}],"name":"isBlacklisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"address_","type":"address"}],"name":"isWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"massOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenIdRcvr","type":"uint256"},{"internalType":"uint256","name":"tokenIdSndr","type":"uint256"}],"name":"merge","outputs":[{"internalType":"uint256","name":"tokenIdDead","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"values_","type":"uint256[]"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"address_","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setBlacklistAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"metadataGenerator_","type":"address"}],"name":"setMetadataGenerator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pak_","type":"address"}],"name":"setPak","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percentageRoyalty_","type":"uint256"}],"name":"setRoyaltyBips","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver_","type":"address"}],"name":"setRoyaltyReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"thaw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokenOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","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":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"address_","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"whitelistUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c06040523480156200001157600080fd5b50604051620035e7380380620035e7833981016040819052620000349162000213565b600160048190556001600160601b0319606086901b1660a052600b80546001600160a01b038681166001600160a01b03199283161790925560008054928616929091169190911790556040805180820190915260068082526536b2b933b29760d11b6020909201918252620000ab92919062000150565b50604080518082019091526001808252606d60f81b6020909201918252620000d69160029162000150565b50600a80546001600160a01b039283166001600160a01b03199182168117909255600c805490911690911790556127106080526103e8600655306000908152600d60209081526040808320805460ff199081166001908117909255969094168352600e909152902080549093161790915550620002ad9050565b8280546200015e9062000270565b90600052602060002090601f016020900481019282620001825760008555620001cd565b82601f106200019d57805160ff1916838001178555620001cd565b82800160010185558215620001cd579182015b82811115620001cd578251825591602001919060010190620001b0565b50620001db929150620001df565b5090565b5b80821115620001db5760008155600101620001e0565b80516001600160a01b03811681146200020e57600080fd5b919050565b600080600080608085870312156200022a57600080fd5b6200023585620001f6565b93506200024560208601620001f6565b92506200025560408601620001f6565b91506200026560608601620001f6565b905092959194509250565b600181811c908216806200028557607f821691505b60208210811415620002a757634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160601c6132f5620002f2600039600081816105f101528181610cee0152611d7d01526000818161062b01528181610c1d015261122401526132f56000f3fe608060405234801561001057600080fd5b50600436106103625760003560e01c8063629a5334116101c8578063bf3e6d9a11610104578063e985e9c5116100a2578063f8e93ef91161007c578063f8e93ef914610781578063fb1fac1814610794578063fe575a871461079d578063ff5b6ab1146107c957600080fd5b8063e985e9c514610729578063eafe706e14610765578063ef0ceec71461077857600080fd5b8063d1c2babb116100de578063d1c2babb146106ed578063dbf65de014610700578063dcfb383314610713578063e2da569b1461071c57600080fd5b8063bf3e6d9a146106b4578063c87b56dd146106c7578063c94e3c97146106da57600080fd5b80639121ac0d11610171578063a22cb4651161014b578063a22cb46514610668578063a75551601461067b578063a8bbd7331461068e578063b88d4fde146106a157600080fd5b80639121ac0d14610626578063937773691461064d57806395d89b411461066057600080fd5b806370a08231116101a257806370a08231146105c357806379cbc5fa146105ec5780638dc251e31461061357600080fd5b8063629a53341461059557806362a5af3b146105a85780636352211e146105b057600080fd5b8063330f5208116102a257806343fa2c9c116102405780635342271d1161021a5780635342271d1461055457806355d5f963146105675780635920375c1461057a57806361ec1bb61461058257600080fd5b806343fa2c9c146105305780634bb278f3146105395780634f558e791461054157600080fd5b8063426a64a41161027c578063426a64a4146104ee57806342842e0e146104f757806342966c681461050a57806342ec38e21461051d57600080fd5b8063330f52081461049c578063351c56b5146104af5780633af32abf146104c257600080fd5b8063095ea7b31161030f57806323b872dd116102e957806323b872dd1461043b5780632a55205a1461044e5780632bddccdc146104805780632ca1aa1b1461048957600080fd5b8063095ea7b31461040b5780630ab2b6b91461042057806318160ddd1461043357600080fd5b8063054f7d9c11610340578063054f7d9c146103d157806306fdde03146103e3578063081812fc146103f857600080fd5b806301ffc9a714610367578063029108911461038f57806302964ff1146103a6575b600080fd5b61037a610375366004612f95565b6107f1565b60405190151581526020015b60405180910390f35b61039860085481565b604051908152602001610386565b600c546103b9906001600160a01b031681565b6040516001600160a01b039091168152602001610386565b60035461037a90610100900460ff1681565b6103eb6108d3565b60405161038691906130df565b6103b9610406366004613046565b610965565b61041e610419366004612ea0565b6109ea565b005b61039861042e366004613046565b610b1d565b600554610398565b61041e610449366004612d82565b610b7e565b61046161045c36600461305f565b610c16565b604080516001600160a01b039093168352602083019190915201610386565b61039860045481565b610398610497366004613046565b610c6d565b61041e6104aa366004612f0c565b610ce4565b600b546103b9906001600160a01b031681565b61037a6104d0366004612d3d565b6001600160a01b03166000908152600e602052604090205460ff1690565b61039860075481565b61041e610505366004612d82565b610eb9565b61041e610518366004613046565b610ed4565b61039861052b366004612d3d565b610ff6565b61039860065481565b61041e61107b565b61037a61054f366004613046565b6110f5565b610398610562366004613046565b611116565b6000546103b9906001600160a01b031681565b61041e611131565b610398610590366004613046565b6111a1565b61041e6105a3366004613046565b6111bf565b61041e6112bd565b6103b96105be366004613046565b611341565b6103986105d1366004612d3d565b6001600160a01b031660009081526010602052604090205490565b6103b97f000000000000000000000000000000000000000000000000000000000000000081565b61041e610621366004612d3d565b6113a6565b6103987f000000000000000000000000000000000000000000000000000000000000000081565b61041e61065b366004612d3d565b61142b565b6103eb6114b0565b61041e610676366004612e69565b6114bf565b61041e610689366004612e69565b611585565b61041e61069c366004612d3d565b611697565b61041e6106af366004612dbe565b61171c565b6103986106c236600461305f565b6117ab565b6103eb6106d5366004613046565b6117d8565b600a546103b9906001600160a01b031681565b6103986106fb36600461305f565b611943565b61041e61070e366004612e69565b611ba7565b6103b961dead81565b60035461037a9060ff1681565b61037a610737366004612d58565b6001600160a01b03918216600090815260136020908152604080832093909416825291909152205460ff1690565b610398610773366004613046565b611d58565b61039860095481565b61041e61078f366004612eca565b611d73565b61039860055481565b61037a6107ab366004612d3d565b6001600160a01b03166000908152600d602052604090205460ff1690565b6107dc6107d7366004613046565b612111565b60408051928352602083019190915201610386565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f80ac58cd000000000000000000000000000000000000000000000000000000007f2a55205a000000000000000000000000000000000000000000000000000000007f5b5e139f000000000000000000000000000000000000000000000000000000006001600160e01b0319861684148061089b57506001600160e01b0319868116908416145b806108b257506001600160e01b0319868116908316145b806108c957506001600160e01b0319868116908216145b9695505050505050565b6060600180546108e2906131d9565b80601f016020809104026020016040519081016040528092919081815260200182805461090e906131d9565b801561095b5780601f106109305761010080835404028352916020019161095b565b820191906000526020600020905b81548152906001019060200180831161093e57829003601f168201915b5050505050905090565b6000818152601160205260408120546001600160a01b03166109ce5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a206e6f6e6578697374656e7420746f6b656e0000000000000060448201526064015b60405180910390fd5b506000908152601260205260409020546001600160a01b031690565b60006109f582611341565b9050806001600160a01b0316836001600160a01b03161415610a7f5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f720000000000000000000000000000000000000000000000000000000000000060648201526084016109c5565b336001600160a01b0382161480610a9b5750610a9b8133610737565b610b0d5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c000000000000000060648201526084016109c5565b610b18818484612138565b505050565b60008181526014602052604090205480610b795760405162461bcd60e51b815260206004820152601960248201527f4552433732313a206e6f6e6578697374656e7420746f6b656e0000000000000060448201526064016109c5565b919050565b600080610b8c335b84612194565b9150915080610c035760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f76656400000000000000000000000000000060648201526084016109c5565b610c0f8286868661226c565b5050505050565b60008060007f000000000000000000000000000000000000000000000000000000000000000060065485610c4a9190613177565b610c549190613163565b600c546001600160a01b031693509150505b9250929050565b6000818152601160205260408120546001600160a01b0316610cd15760405162461bcd60e51b815260206004820152601960248201527f4552433732313a206e6f6e6578697374656e7420746f6b656e0000000000000060448201526064016109c5565b5060009081526015602052604090205490565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663e37ce6fa336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b158015610d5357600080fd5b505afa158015610d67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8b9190612f78565b610dd75760405162461bcd60e51b815260206004820152601960248201527f4d657267653a20496e76616c6964206d73672e73656e6465720000000000000060448201526064016109c5565b60035460ff1615610e2a5760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a204d696e74696e672069732066696e616c697a65642e0000000060448201526064016109c5565b828114610e535760405162461bcd60e51b815260206004820152600060248201526044016109c5565b60005b83811015610c0f57828282818110610e7057610e7061326f565b9050602002013560156000878785818110610e8d57610e8d61326f565b905060200201358152602001908152602001600020819055508080610eb190613214565b915050610e56565b610b188383836040518060200160405280600081525061171c565b600354610100900460ff1615610f2c5760405162461bcd60e51b815260206004820152601660248201527f4d657267653a206d6f76656d656e742066726f7a656e0000000000000000000060448201526064016109c5565b600080610f3833610b86565b9150915080610faf5760405162461bcd60e51b815260206004820152602860248201527f4552433732313a2063616c6c6572206973206e6f74206f776e6572206e6f722060448201527f617070726f76656400000000000000000000000000000000000000000000000060648201526084016109c5565b610fb982846127ac565b60405183906000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a4505050565b6001600160a01b0381166000908152600e602052604081205460ff161561105f5760405162461bcd60e51b815260206004820152601860248201527f4d657267653a20746f6b656e4f6620756e646566696e6564000000000000000060448201526064016109c5565b506001600160a01b03166000908152600f602052604090205490565b600a546001600160a01b0316336001600160a01b0316146110de5760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b6110e6611131565b6003805460ff19166001179055565b6000818152601160205260408120546001600160a01b031615155b92915050565b60006111266305f5e1008361322f565b9050610b79816128a1565b600a546001600160a01b0316336001600160a01b0316146111945760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b6003805461ff0019169055565b6000806111ad83610b1d565b90506111b881611116565b9392505050565b600a546001600160a01b0316336001600160a01b0316146112225760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b7f00000000000000000000000000000000000000000000000000000000000000008111156112b85760405162461bcd60e51b815260206004820152602660248201527f4d657267653a20496c6c6567616c20617267756d656e74206d6f72652074686160448201527f6e2031303025000000000000000000000000000000000000000000000000000060648201526084016109c5565b600655565b600a546001600160a01b0316336001600160a01b0316146113205760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b60035460ff161561133057600080fd5b6003805461ff001916610100179055565b6000818152601160205260409020546001600160a01b031680610b795760405162461bcd60e51b815260206004820152601960248201527f4552433732313a206e6f6e6578697374656e7420746f6b656e0000000000000060448201526064016109c5565b600a546001600160a01b0316336001600160a01b0316146114095760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b600a546001600160a01b0316336001600160a01b03161461148e5760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6060600280546108e2906131d9565b6001600160a01b0382163314156115185760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016109c5565b3360008181526013602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3191015b60405180910390a35050565b600a546001600160a01b0316336001600160a01b0316146115e85760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b600b546001600160a01b038381169116141561166c5760405162461bcd60e51b815260206004820152602d60248201527f4d657267653a20496c6c6567616c20617267756d656e7420616464726573735f60448201527f206973205f6f6d6e696275732e0000000000000000000000000000000000000060648201526084016109c5565b6001600160a01b03919091166000908152600d60205260409020805460ff1916911515919091179055565b600a546001600160a01b0316336001600160a01b0316146116fa5760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b611727848484610b7e565b61173384848484612934565b6117a55760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e746572000000000000000000000000000060648201526084016109c5565b50505050565b60006117b683612a8f565b6117bf826128a1565b816117ce6305f5e10085613177565b6111b8919061314b565b6000818152601160205260409020546060906001600160a01b031661183f5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a206e6f6e6578697374656e7420746f6b656e0000000000000060448201526064016109c5565b6000805483825260146020526040909120546001600160a01b039091169063592fa5cc90849061186e90611d58565b60008681526014602052604090205461188690611116565b6008546000908152601460205260409020546118a190611116565b60085488146118af89610c6d565b6040516001600160e01b031960e089901b16815260048101969096526024860194909452604485019290925260648401521515608483015260a482015260c40160006040518083038186803b15801561190757600080fd5b505afa15801561191b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111109190810190612fcf565b336000908152600e602052604081205460ff166119a25760405162461bcd60e51b815260206004820152601960248201527f4d657267653a20496e76616c6964206d73672e73656e6465720000000000000060448201526064016109c5565b600354610100900460ff16156119fa5760405162461bcd60e51b815260206004820152601660248201527f4d657267653a206d6f76656d656e742066726f7a656e0000000000000000000060448201526064016109c5565b6000611a0584611341565b9050611a1083611341565b6001600160a01b0316816001600160a01b031614611a965760405162461bcd60e51b815260206004820152602860248201527f4d657267653a20496c6c6567616c20617267756d656e7420646973706172617460448201527f65206f776e65722e00000000000000000000000000000000000000000000000060648201526084016109c5565b336001600160a01b03821614611b145760405162461bcd60e51b815260206004820152602660248201527f4552433732313a206d73672e73656e646572206973206e6f7420746f6b656e2060448201527f6f776e65722e000000000000000000000000000000000000000000000000000060648201526084016109c5565b6001600160a01b0381166000908152601060205260408120805460019290611b3d908490613196565b90915550611b4d90508484612aed565b60008181526011602052604080822080546001600160a01b03191690555191935083916001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45092915050565b600a546001600160a01b0316336001600160a01b031614611c0a5760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b600b546001600160a01b0383811691161415611c935780611c935760405162461bcd60e51b815260206004820152603260248201527f4d657267653a20496c6c6567616c20617267756d656e74205f6f6d6e6962757360448201527f2063616e27742062652072656d6f7665642e000000000000000000000000000060648201526084016109c5565b80611d2d576001611cb9836001600160a01b031660009081526010602052604090205490565b1115611d2d5760405162461bcd60e51b815260206004820152603960248201527f4d657267653a20416464726573732077697468206d6f7265207468616e206f6e60448201527f6520746f6b656e2063616e27742062652072656d6f7665642e0000000000000060648201526084016109c5565b6001600160a01b03919091166000908152600e60205260409020805460ff1916911515919091179055565b6000611d686305f5e10083613163565b9050610b7981612a8f565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663e37ce6fa336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b158015611de257600080fd5b505afa158015611df6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1a9190612f78565b611e665760405162461bcd60e51b815260206004820152601960248201527f4d657267653a20496e76616c6964206d73672e73656e6465720000000000000060448201526064016109c5565b60035460ff1615611eb95760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a204d696e74696e672069732066696e616c697a65642e0000000060448201526064016109c5565b600454600854600754600b546001600160a01b0316600080805b87811015611ffd57611efc898983818110611ef057611ef061326f565b90506020020135612cbb565b15611f0657611fdd565b81611f1081613214565b925050888882818110611f2557611f2561326f565b60008a81526014602090815260408083209382029590950135909255601190915291822080546001600160a01b0319166001600160a01b03881617905550611f848a8a84818110611f7857611f7861326f565b90506020020135612111565b91505080861015611f96578095508796505b611fa0818561314b565b60405190945088906001600160a01b038716906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505b80611fe781613214565b9150508680611ff590613214565b975050611ed3565b866004819055508160056000828254612016919061314b565b90915550506001600160a01b0384166000908152601060205260408120805484929061204390849061314b565b90915550506009546000612057858361314b565b905061206860016305f5e100613196565b81106120b65760405162461bcd60e51b815260206004820152601a60248201527f4d657267653a204d61737320746f74616c206f766572666c6f7700000000000060448201526064016109c5565b60098190556008548814612104576008889055600787905560405187815288907fdd1fd86a575cfed4833cea35236e5c94a92cead19b6d0e8e1b89ed586981ab509060200160405180910390a25b5050505050505050505050565b600080600061211f84611d58565b9050600061212c85611116565b91959194509092505050565b60008181526012602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000818152601160205260408120546001600160a01b031690816121fa5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a206e6f6e6578697374656e7420746f6b656e0000000000000060448201526064016109c5565b816001600160a01b0316846001600160a01b0316148061223357506000838152601260205260409020546001600160a01b038581169116145b8061226357506001600160a01b0380831660009081526013602090815260408083209388168352929052205460ff165b90509250929050565b600354610100900460ff16156122c45760405162461bcd60e51b815260206004820152601660248201527f4d657267653a206d6f76656d656e742066726f7a656e0000000000000000000060448201526064016109c5565b826001600160a01b0316846001600160a01b03161461234b5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201527f73206e6f74206f776e000000000000000000000000000000000000000000000060648201526084016109c5565b6001600160a01b0382166123c65760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016109c5565b6001600160a01b0382166000908152600d602052604090205460ff16156124555760405162461bcd60e51b815260206004820152602c60248201527f4d657267653a207472616e7366657220617474656d707420746f20626c61636b60448201527f6c6973742061646472657373000000000000000000000000000000000000000060648201526084016109c5565b6001600160a01b03821661dead14156124e25761247284826127ac565b604051819061dead906001600160a01b038616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90600090a4604051819060009061dead907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a46117a5565b6124ee84600083612138565b80826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4816001600160a01b0316836001600160a01b0316141561254e576117a5565b6001600160a01b038381166000908152600e602052604080822054928516825290205460ff918216911681156125b2576001600160a01b03851660009081526010602052604081208054600192906125a7908490613196565b909155506125cc9050565b6001600160a01b0385166000908152601060205260408120555b8015612606576001600160a01b03841660009081526010602052604081208054600192906125fb90849061314b565b909155506126409050565b6001600160a01b0384166000908152600f6020526040902054612640576001600160a01b0384166000908152601060205260409020600190555b801561267257600083815260116020526040902080546001600160a01b0319166001600160a01b038616179055612785565b6001600160a01b0384166000908152600f6020526040902054806126ce57600084815260116020908152604080832080546001600160a01b0319166001600160a01b038a169081179091558352600f9091529020849055612783565b8360006126db8383612aed565b60405190915081906000906001600160a01b038a16907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a482818114156127225750815b600082815260116020526040902080546001600160a01b031916905583811461277f57600081815260116020908152604080832080546001600160a01b0319166001600160a01b038d169081179091558352600f90915290208190555b5050505b505b816127a4576001600160a01b0385166000908152600f60205260408120555b505050505050565b6127b882600083612138565b6000818152601460205260409020546127d090611116565b600960008282546127e19190613196565b90915550506001600160a01b0382166000908152600f602090815260408083208390558383526011825280832080546001600160a01b0319169055601490915281208190556005805460019290612839908490613196565b90915550506001600160a01b0382166000908152601060205260408120805460019290612867908490613196565b909155505060405160008082529082907f7ba170514e8ea35827dbbd10c6d3376ca77ff64b62e4b0a395bac9b142dc81dc90602001611579565b806001111580156128bf57506128bc60016305f5e100613196565b81105b6129315760405162461bcd60e51b815260206004820152602260248201527f4d657267653a204d617373206d757374206265205b312c203130306d202d203160448201527f292e00000000000000000000000000000000000000000000000000000000000060648201526084016109c5565b50565b6000833b15612a8357604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061296f9033908990889088906004016130ad565b602060405180830381600087803b15801561298957600080fd5b505af19250505080156129b9575060408051601f3d908101601f191682019092526129b691810190612fb2565b60015b612a69573d8080156129e7576040519150601f19603f3d011682016040523d82523d6000602084013e6129ec565b606091505b508051612a615760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e746572000000000000000000000000000060648201526084016109c5565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050612a87565b5060015b949350505050565b80600111158015612aa1575060048111155b6129315760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a20436c617373206d757374206265205b312c20345d2e0000000060448201526064016109c5565b600081831415612b655760405162461bcd60e51b815260206004820152602a60248201527f4d657267653a20496c6c6567616c20617267756d656e74206964656e7469636160448201527f6c20746f6b656e49642e0000000000000000000000000000000000000000000060648201526084016109c5565b600083815260146020526040812054612b7d90611116565b60008481526014602052604081205491925090612b9990611116565b905081818686828410612bb25750839250849150869050875b60008181526014602052604081208054869290612bd090849061314b565b9091555060009050612be2858561314b565b9050600754811115612c2e576008829055600781905560405181815282907fdd1fd86a575cfed4833cea35236e5c94a92cead19b6d0e8e1b89ed586981ab509060200160405180910390a25b6000828152601560205260408120805491612c4883613214565b909155505060008381526014602052604081208190556005805460019290612c71908490613196565b9091555050604051818152829084907f7ba170514e8ea35827dbbd10c6d3376ca77ff64b62e4b0a395bac9b142dc81dc9060200160405180910390a3509098975050505050505050565b6000612ccc60016305f5e100613196565b612cda6305f5e1008461322f565b1492915050565b80356001600160a01b0381168114610b7957600080fd5b60008083601f840112612d0a57600080fd5b50813567ffffffffffffffff811115612d2257600080fd5b6020830191508360208260051b8501011115610c6657600080fd5b600060208284031215612d4f57600080fd5b6111b882612ce1565b60008060408385031215612d6b57600080fd5b612d7483612ce1565b915061226360208401612ce1565b600080600060608486031215612d9757600080fd5b612da084612ce1565b9250612dae60208501612ce1565b9150604084013590509250925092565b60008060008060808587031215612dd457600080fd5b612ddd85612ce1565b9350612deb60208601612ce1565b925060408501359150606085013567ffffffffffffffff811115612e0e57600080fd5b8501601f81018713612e1f57600080fd5b8035612e32612e2d82613123565b6130f2565b818152886020838501011115612e4757600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060408385031215612e7c57600080fd5b612e8583612ce1565b91506020830135612e958161329b565b809150509250929050565b60008060408385031215612eb357600080fd5b612ebc83612ce1565b946020939093013593505050565b60008060208385031215612edd57600080fd5b823567ffffffffffffffff811115612ef457600080fd5b612f0085828601612cf8565b90969095509350505050565b60008060008060408587031215612f2257600080fd5b843567ffffffffffffffff80821115612f3a57600080fd5b612f4688838901612cf8565b90965094506020870135915080821115612f5f57600080fd5b50612f6c87828801612cf8565b95989497509550505050565b600060208284031215612f8a57600080fd5b81516111b88161329b565b600060208284031215612fa757600080fd5b81356111b8816132a9565b600060208284031215612fc457600080fd5b81516111b8816132a9565b600060208284031215612fe157600080fd5b815167ffffffffffffffff811115612ff857600080fd5b8201601f8101841361300957600080fd5b8051613017612e2d82613123565b81815285602083850101111561302c57600080fd5b61303d8260208301602086016131ad565b95945050505050565b60006020828403121561305857600080fd5b5035919050565b6000806040838503121561307257600080fd5b50508035926020909101359150565b600081518084526130998160208601602086016131ad565b601f01601f19169290920160200192915050565b60006001600160a01b038087168352808616602084015250836040830152608060608301526108c96080830184613081565b6020815260006111b86020830184613081565b604051601f8201601f1916810167ffffffffffffffff8111828210171561311b5761311b613285565b604052919050565b600067ffffffffffffffff82111561313d5761313d613285565b50601f01601f191660200190565b6000821982111561315e5761315e613243565b500190565b60008261317257613172613259565b500490565b600081600019048311821515161561319157613191613243565b500290565b6000828210156131a8576131a8613243565b500390565b60005b838110156131c85781810151838201526020016131b0565b838111156117a55750506000910152565b600181811c908216806131ed57607f821691505b6020821081141561320e57634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561322857613228613243565b5060010190565b60008261323e5761323e613259565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b801515811461293157600080fd5b6001600160e01b03198116811461293157600080fdfea26469706673582212201f3e53657040451a6e8f596dca0e1fb8d03f1361b0a4ed6f4dc592d65ce32da464736f6c634300080600330000000000000000000000006e53130ddff21e3bc963ee902005223b9a202106000000000000000000000000e052113bd7d7700d623414a0a4585bcae754e9d50000000000000000000000004e1e18aaccdf9acfd2e8847654a3871dfd234f020000000000000000000000002ce780d7c743a57791b835a9d6f998b15bbba5a4

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106103625760003560e01c8063629a5334116101c8578063bf3e6d9a11610104578063e985e9c5116100a2578063f8e93ef91161007c578063f8e93ef914610781578063fb1fac1814610794578063fe575a871461079d578063ff5b6ab1146107c957600080fd5b8063e985e9c514610729578063eafe706e14610765578063ef0ceec71461077857600080fd5b8063d1c2babb116100de578063d1c2babb146106ed578063dbf65de014610700578063dcfb383314610713578063e2da569b1461071c57600080fd5b8063bf3e6d9a146106b4578063c87b56dd146106c7578063c94e3c97146106da57600080fd5b80639121ac0d11610171578063a22cb4651161014b578063a22cb46514610668578063a75551601461067b578063a8bbd7331461068e578063b88d4fde146106a157600080fd5b80639121ac0d14610626578063937773691461064d57806395d89b411461066057600080fd5b806370a08231116101a257806370a08231146105c357806379cbc5fa146105ec5780638dc251e31461061357600080fd5b8063629a53341461059557806362a5af3b146105a85780636352211e146105b057600080fd5b8063330f5208116102a257806343fa2c9c116102405780635342271d1161021a5780635342271d1461055457806355d5f963146105675780635920375c1461057a57806361ec1bb61461058257600080fd5b806343fa2c9c146105305780634bb278f3146105395780634f558e791461054157600080fd5b8063426a64a41161027c578063426a64a4146104ee57806342842e0e146104f757806342966c681461050a57806342ec38e21461051d57600080fd5b8063330f52081461049c578063351c56b5146104af5780633af32abf146104c257600080fd5b8063095ea7b31161030f57806323b872dd116102e957806323b872dd1461043b5780632a55205a1461044e5780632bddccdc146104805780632ca1aa1b1461048957600080fd5b8063095ea7b31461040b5780630ab2b6b91461042057806318160ddd1461043357600080fd5b8063054f7d9c11610340578063054f7d9c146103d157806306fdde03146103e3578063081812fc146103f857600080fd5b806301ffc9a714610367578063029108911461038f57806302964ff1146103a6575b600080fd5b61037a610375366004612f95565b6107f1565b60405190151581526020015b60405180910390f35b61039860085481565b604051908152602001610386565b600c546103b9906001600160a01b031681565b6040516001600160a01b039091168152602001610386565b60035461037a90610100900460ff1681565b6103eb6108d3565b60405161038691906130df565b6103b9610406366004613046565b610965565b61041e610419366004612ea0565b6109ea565b005b61039861042e366004613046565b610b1d565b600554610398565b61041e610449366004612d82565b610b7e565b61046161045c36600461305f565b610c16565b604080516001600160a01b039093168352602083019190915201610386565b61039860045481565b610398610497366004613046565b610c6d565b61041e6104aa366004612f0c565b610ce4565b600b546103b9906001600160a01b031681565b61037a6104d0366004612d3d565b6001600160a01b03166000908152600e602052604090205460ff1690565b61039860075481565b61041e610505366004612d82565b610eb9565b61041e610518366004613046565b610ed4565b61039861052b366004612d3d565b610ff6565b61039860065481565b61041e61107b565b61037a61054f366004613046565b6110f5565b610398610562366004613046565b611116565b6000546103b9906001600160a01b031681565b61041e611131565b610398610590366004613046565b6111a1565b61041e6105a3366004613046565b6111bf565b61041e6112bd565b6103b96105be366004613046565b611341565b6103986105d1366004612d3d565b6001600160a01b031660009081526010602052604090205490565b6103b97f0000000000000000000000006e53130ddff21e3bc963ee902005223b9a20210681565b61041e610621366004612d3d565b6113a6565b6103987f000000000000000000000000000000000000000000000000000000000000271081565b61041e61065b366004612d3d565b61142b565b6103eb6114b0565b61041e610676366004612e69565b6114bf565b61041e610689366004612e69565b611585565b61041e61069c366004612d3d565b611697565b61041e6106af366004612dbe565b61171c565b6103986106c236600461305f565b6117ab565b6103eb6106d5366004613046565b6117d8565b600a546103b9906001600160a01b031681565b6103986106fb36600461305f565b611943565b61041e61070e366004612e69565b611ba7565b6103b961dead81565b60035461037a9060ff1681565b61037a610737366004612d58565b6001600160a01b03918216600090815260136020908152604080832093909416825291909152205460ff1690565b610398610773366004613046565b611d58565b61039860095481565b61041e61078f366004612eca565b611d73565b61039860055481565b61037a6107ab366004612d3d565b6001600160a01b03166000908152600d602052604090205460ff1690565b6107dc6107d7366004613046565b612111565b60408051928352602083019190915201610386565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007f80ac58cd000000000000000000000000000000000000000000000000000000007f2a55205a000000000000000000000000000000000000000000000000000000007f5b5e139f000000000000000000000000000000000000000000000000000000006001600160e01b0319861684148061089b57506001600160e01b0319868116908416145b806108b257506001600160e01b0319868116908316145b806108c957506001600160e01b0319868116908216145b9695505050505050565b6060600180546108e2906131d9565b80601f016020809104026020016040519081016040528092919081815260200182805461090e906131d9565b801561095b5780601f106109305761010080835404028352916020019161095b565b820191906000526020600020905b81548152906001019060200180831161093e57829003601f168201915b5050505050905090565b6000818152601160205260408120546001600160a01b03166109ce5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a206e6f6e6578697374656e7420746f6b656e0000000000000060448201526064015b60405180910390fd5b506000908152601260205260409020546001600160a01b031690565b60006109f582611341565b9050806001600160a01b0316836001600160a01b03161415610a7f5760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f720000000000000000000000000000000000000000000000000000000000000060648201526084016109c5565b336001600160a01b0382161480610a9b5750610a9b8133610737565b610b0d5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c000000000000000060648201526084016109c5565b610b18818484612138565b505050565b60008181526014602052604090205480610b795760405162461bcd60e51b815260206004820152601960248201527f4552433732313a206e6f6e6578697374656e7420746f6b656e0000000000000060448201526064016109c5565b919050565b600080610b8c335b84612194565b9150915080610c035760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f76656400000000000000000000000000000060648201526084016109c5565b610c0f8286868661226c565b5050505050565b60008060007f000000000000000000000000000000000000000000000000000000000000271060065485610c4a9190613177565b610c549190613163565b600c546001600160a01b031693509150505b9250929050565b6000818152601160205260408120546001600160a01b0316610cd15760405162461bcd60e51b815260206004820152601960248201527f4552433732313a206e6f6e6578697374656e7420746f6b656e0000000000000060448201526064016109c5565b5060009081526015602052604090205490565b6001600160a01b037f0000000000000000000000006e53130ddff21e3bc963ee902005223b9a2021061663e37ce6fa336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b158015610d5357600080fd5b505afa158015610d67573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8b9190612f78565b610dd75760405162461bcd60e51b815260206004820152601960248201527f4d657267653a20496e76616c6964206d73672e73656e6465720000000000000060448201526064016109c5565b60035460ff1615610e2a5760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a204d696e74696e672069732066696e616c697a65642e0000000060448201526064016109c5565b828114610e535760405162461bcd60e51b815260206004820152600060248201526044016109c5565b60005b83811015610c0f57828282818110610e7057610e7061326f565b9050602002013560156000878785818110610e8d57610e8d61326f565b905060200201358152602001908152602001600020819055508080610eb190613214565b915050610e56565b610b188383836040518060200160405280600081525061171c565b600354610100900460ff1615610f2c5760405162461bcd60e51b815260206004820152601660248201527f4d657267653a206d6f76656d656e742066726f7a656e0000000000000000000060448201526064016109c5565b600080610f3833610b86565b9150915080610faf5760405162461bcd60e51b815260206004820152602860248201527f4552433732313a2063616c6c6572206973206e6f74206f776e6572206e6f722060448201527f617070726f76656400000000000000000000000000000000000000000000000060648201526084016109c5565b610fb982846127ac565b60405183906000906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a4505050565b6001600160a01b0381166000908152600e602052604081205460ff161561105f5760405162461bcd60e51b815260206004820152601860248201527f4d657267653a20746f6b656e4f6620756e646566696e6564000000000000000060448201526064016109c5565b506001600160a01b03166000908152600f602052604090205490565b600a546001600160a01b0316336001600160a01b0316146110de5760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b6110e6611131565b6003805460ff19166001179055565b6000818152601160205260408120546001600160a01b031615155b92915050565b60006111266305f5e1008361322f565b9050610b79816128a1565b600a546001600160a01b0316336001600160a01b0316146111945760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b6003805461ff0019169055565b6000806111ad83610b1d565b90506111b881611116565b9392505050565b600a546001600160a01b0316336001600160a01b0316146112225760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b7f00000000000000000000000000000000000000000000000000000000000027108111156112b85760405162461bcd60e51b815260206004820152602660248201527f4d657267653a20496c6c6567616c20617267756d656e74206d6f72652074686160448201527f6e2031303025000000000000000000000000000000000000000000000000000060648201526084016109c5565b600655565b600a546001600160a01b0316336001600160a01b0316146113205760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b60035460ff161561133057600080fd5b6003805461ff001916610100179055565b6000818152601160205260409020546001600160a01b031680610b795760405162461bcd60e51b815260206004820152601960248201527f4552433732313a206e6f6e6578697374656e7420746f6b656e0000000000000060448201526064016109c5565b600a546001600160a01b0316336001600160a01b0316146114095760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b600a546001600160a01b0316336001600160a01b03161461148e5760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6060600280546108e2906131d9565b6001600160a01b0382163314156115185760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016109c5565b3360008181526013602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3191015b60405180910390a35050565b600a546001600160a01b0316336001600160a01b0316146115e85760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b600b546001600160a01b038381169116141561166c5760405162461bcd60e51b815260206004820152602d60248201527f4d657267653a20496c6c6567616c20617267756d656e7420616464726573735f60448201527f206973205f6f6d6e696275732e0000000000000000000000000000000000000060648201526084016109c5565b6001600160a01b03919091166000908152600d60205260409020805460ff1916911515919091179055565b600a546001600160a01b0316336001600160a01b0316146116fa5760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b611727848484610b7e565b61173384848484612934565b6117a55760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e746572000000000000000000000000000060648201526084016109c5565b50505050565b60006117b683612a8f565b6117bf826128a1565b816117ce6305f5e10085613177565b6111b8919061314b565b6000818152601160205260409020546060906001600160a01b031661183f5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a206e6f6e6578697374656e7420746f6b656e0000000000000060448201526064016109c5565b6000805483825260146020526040909120546001600160a01b039091169063592fa5cc90849061186e90611d58565b60008681526014602052604090205461188690611116565b6008546000908152601460205260409020546118a190611116565b60085488146118af89610c6d565b6040516001600160e01b031960e089901b16815260048101969096526024860194909452604485019290925260648401521515608483015260a482015260c40160006040518083038186803b15801561190757600080fd5b505afa15801561191b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111109190810190612fcf565b336000908152600e602052604081205460ff166119a25760405162461bcd60e51b815260206004820152601960248201527f4d657267653a20496e76616c6964206d73672e73656e6465720000000000000060448201526064016109c5565b600354610100900460ff16156119fa5760405162461bcd60e51b815260206004820152601660248201527f4d657267653a206d6f76656d656e742066726f7a656e0000000000000000000060448201526064016109c5565b6000611a0584611341565b9050611a1083611341565b6001600160a01b0316816001600160a01b031614611a965760405162461bcd60e51b815260206004820152602860248201527f4d657267653a20496c6c6567616c20617267756d656e7420646973706172617460448201527f65206f776e65722e00000000000000000000000000000000000000000000000060648201526084016109c5565b336001600160a01b03821614611b145760405162461bcd60e51b815260206004820152602660248201527f4552433732313a206d73672e73656e646572206973206e6f7420746f6b656e2060448201527f6f776e65722e000000000000000000000000000000000000000000000000000060648201526084016109c5565b6001600160a01b0381166000908152601060205260408120805460019290611b3d908490613196565b90915550611b4d90508484612aed565b60008181526011602052604080822080546001600160a01b03191690555191935083916001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45092915050565b600a546001600160a01b0316336001600160a01b031614611c0a5760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a206d73672e73656e646572206973206e6f742070616b0000000060448201526064016109c5565b600b546001600160a01b0383811691161415611c935780611c935760405162461bcd60e51b815260206004820152603260248201527f4d657267653a20496c6c6567616c20617267756d656e74205f6f6d6e6962757360448201527f2063616e27742062652072656d6f7665642e000000000000000000000000000060648201526084016109c5565b80611d2d576001611cb9836001600160a01b031660009081526010602052604090205490565b1115611d2d5760405162461bcd60e51b815260206004820152603960248201527f4d657267653a20416464726573732077697468206d6f7265207468616e206f6e60448201527f6520746f6b656e2063616e27742062652072656d6f7665642e0000000000000060648201526084016109c5565b6001600160a01b03919091166000908152600e60205260409020805460ff1916911515919091179055565b6000611d686305f5e10083613163565b9050610b7981612a8f565b6001600160a01b037f0000000000000000000000006e53130ddff21e3bc963ee902005223b9a2021061663e37ce6fa336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260240160206040518083038186803b158015611de257600080fd5b505afa158015611df6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1a9190612f78565b611e665760405162461bcd60e51b815260206004820152601960248201527f4d657267653a20496e76616c6964206d73672e73656e6465720000000000000060448201526064016109c5565b60035460ff1615611eb95760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a204d696e74696e672069732066696e616c697a65642e0000000060448201526064016109c5565b600454600854600754600b546001600160a01b0316600080805b87811015611ffd57611efc898983818110611ef057611ef061326f565b90506020020135612cbb565b15611f0657611fdd565b81611f1081613214565b925050888882818110611f2557611f2561326f565b60008a81526014602090815260408083209382029590950135909255601190915291822080546001600160a01b0319166001600160a01b03881617905550611f848a8a84818110611f7857611f7861326f565b90506020020135612111565b91505080861015611f96578095508796505b611fa0818561314b565b60405190945088906001600160a01b038716906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4505b80611fe781613214565b9150508680611ff590613214565b975050611ed3565b866004819055508160056000828254612016919061314b565b90915550506001600160a01b0384166000908152601060205260408120805484929061204390849061314b565b90915550506009546000612057858361314b565b905061206860016305f5e100613196565b81106120b65760405162461bcd60e51b815260206004820152601a60248201527f4d657267653a204d61737320746f74616c206f766572666c6f7700000000000060448201526064016109c5565b60098190556008548814612104576008889055600787905560405187815288907fdd1fd86a575cfed4833cea35236e5c94a92cead19b6d0e8e1b89ed586981ab509060200160405180910390a25b5050505050505050505050565b600080600061211f84611d58565b9050600061212c85611116565b91959194509092505050565b60008181526012602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000818152601160205260408120546001600160a01b031690816121fa5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a206e6f6e6578697374656e7420746f6b656e0000000000000060448201526064016109c5565b816001600160a01b0316846001600160a01b0316148061223357506000838152601260205260409020546001600160a01b038581169116145b8061226357506001600160a01b0380831660009081526013602090815260408083209388168352929052205460ff165b90509250929050565b600354610100900460ff16156122c45760405162461bcd60e51b815260206004820152601660248201527f4d657267653a206d6f76656d656e742066726f7a656e0000000000000000000060448201526064016109c5565b826001600160a01b0316846001600160a01b03161461234b5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201527f73206e6f74206f776e000000000000000000000000000000000000000000000060648201526084016109c5565b6001600160a01b0382166123c65760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016109c5565b6001600160a01b0382166000908152600d602052604090205460ff16156124555760405162461bcd60e51b815260206004820152602c60248201527f4d657267653a207472616e7366657220617474656d707420746f20626c61636b60448201527f6c6973742061646472657373000000000000000000000000000000000000000060648201526084016109c5565b6001600160a01b03821661dead14156124e25761247284826127ac565b604051819061dead906001600160a01b038616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90600090a4604051819060009061dead907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a46117a5565b6124ee84600083612138565b80826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4816001600160a01b0316836001600160a01b0316141561254e576117a5565b6001600160a01b038381166000908152600e602052604080822054928516825290205460ff918216911681156125b2576001600160a01b03851660009081526010602052604081208054600192906125a7908490613196565b909155506125cc9050565b6001600160a01b0385166000908152601060205260408120555b8015612606576001600160a01b03841660009081526010602052604081208054600192906125fb90849061314b565b909155506126409050565b6001600160a01b0384166000908152600f6020526040902054612640576001600160a01b0384166000908152601060205260409020600190555b801561267257600083815260116020526040902080546001600160a01b0319166001600160a01b038616179055612785565b6001600160a01b0384166000908152600f6020526040902054806126ce57600084815260116020908152604080832080546001600160a01b0319166001600160a01b038a169081179091558352600f9091529020849055612783565b8360006126db8383612aed565b60405190915081906000906001600160a01b038a16907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a482818114156127225750815b600082815260116020526040902080546001600160a01b031916905583811461277f57600081815260116020908152604080832080546001600160a01b0319166001600160a01b038d169081179091558352600f90915290208190555b5050505b505b816127a4576001600160a01b0385166000908152600f60205260408120555b505050505050565b6127b882600083612138565b6000818152601460205260409020546127d090611116565b600960008282546127e19190613196565b90915550506001600160a01b0382166000908152600f602090815260408083208390558383526011825280832080546001600160a01b0319169055601490915281208190556005805460019290612839908490613196565b90915550506001600160a01b0382166000908152601060205260408120805460019290612867908490613196565b909155505060405160008082529082907f7ba170514e8ea35827dbbd10c6d3376ca77ff64b62e4b0a395bac9b142dc81dc90602001611579565b806001111580156128bf57506128bc60016305f5e100613196565b81105b6129315760405162461bcd60e51b815260206004820152602260248201527f4d657267653a204d617373206d757374206265205b312c203130306d202d203160448201527f292e00000000000000000000000000000000000000000000000000000000000060648201526084016109c5565b50565b6000833b15612a8357604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061296f9033908990889088906004016130ad565b602060405180830381600087803b15801561298957600080fd5b505af19250505080156129b9575060408051601f3d908101601f191682019092526129b691810190612fb2565b60015b612a69573d8080156129e7576040519150601f19603f3d011682016040523d82523d6000602084013e6129ec565b606091505b508051612a615760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e746572000000000000000000000000000060648201526084016109c5565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050612a87565b5060015b949350505050565b80600111158015612aa1575060048111155b6129315760405162461bcd60e51b815260206004820152601c60248201527f4d657267653a20436c617373206d757374206265205b312c20345d2e0000000060448201526064016109c5565b600081831415612b655760405162461bcd60e51b815260206004820152602a60248201527f4d657267653a20496c6c6567616c20617267756d656e74206964656e7469636160448201527f6c20746f6b656e49642e0000000000000000000000000000000000000000000060648201526084016109c5565b600083815260146020526040812054612b7d90611116565b60008481526014602052604081205491925090612b9990611116565b905081818686828410612bb25750839250849150869050875b60008181526014602052604081208054869290612bd090849061314b565b9091555060009050612be2858561314b565b9050600754811115612c2e576008829055600781905560405181815282907fdd1fd86a575cfed4833cea35236e5c94a92cead19b6d0e8e1b89ed586981ab509060200160405180910390a25b6000828152601560205260408120805491612c4883613214565b909155505060008381526014602052604081208190556005805460019290612c71908490613196565b9091555050604051818152829084907f7ba170514e8ea35827dbbd10c6d3376ca77ff64b62e4b0a395bac9b142dc81dc9060200160405180910390a3509098975050505050505050565b6000612ccc60016305f5e100613196565b612cda6305f5e1008461322f565b1492915050565b80356001600160a01b0381168114610b7957600080fd5b60008083601f840112612d0a57600080fd5b50813567ffffffffffffffff811115612d2257600080fd5b6020830191508360208260051b8501011115610c6657600080fd5b600060208284031215612d4f57600080fd5b6111b882612ce1565b60008060408385031215612d6b57600080fd5b612d7483612ce1565b915061226360208401612ce1565b600080600060608486031215612d9757600080fd5b612da084612ce1565b9250612dae60208501612ce1565b9150604084013590509250925092565b60008060008060808587031215612dd457600080fd5b612ddd85612ce1565b9350612deb60208601612ce1565b925060408501359150606085013567ffffffffffffffff811115612e0e57600080fd5b8501601f81018713612e1f57600080fd5b8035612e32612e2d82613123565b6130f2565b818152886020838501011115612e4757600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b60008060408385031215612e7c57600080fd5b612e8583612ce1565b91506020830135612e958161329b565b809150509250929050565b60008060408385031215612eb357600080fd5b612ebc83612ce1565b946020939093013593505050565b60008060208385031215612edd57600080fd5b823567ffffffffffffffff811115612ef457600080fd5b612f0085828601612cf8565b90969095509350505050565b60008060008060408587031215612f2257600080fd5b843567ffffffffffffffff80821115612f3a57600080fd5b612f4688838901612cf8565b90965094506020870135915080821115612f5f57600080fd5b50612f6c87828801612cf8565b95989497509550505050565b600060208284031215612f8a57600080fd5b81516111b88161329b565b600060208284031215612fa757600080fd5b81356111b8816132a9565b600060208284031215612fc457600080fd5b81516111b8816132a9565b600060208284031215612fe157600080fd5b815167ffffffffffffffff811115612ff857600080fd5b8201601f8101841361300957600080fd5b8051613017612e2d82613123565b81815285602083850101111561302c57600080fd5b61303d8260208301602086016131ad565b95945050505050565b60006020828403121561305857600080fd5b5035919050565b6000806040838503121561307257600080fd5b50508035926020909101359150565b600081518084526130998160208601602086016131ad565b601f01601f19169290920160200192915050565b60006001600160a01b038087168352808616602084015250836040830152608060608301526108c96080830184613081565b6020815260006111b86020830184613081565b604051601f8201601f1916810167ffffffffffffffff8111828210171561311b5761311b613285565b604052919050565b600067ffffffffffffffff82111561313d5761313d613285565b50601f01601f191660200190565b6000821982111561315e5761315e613243565b500190565b60008261317257613172613259565b500490565b600081600019048311821515161561319157613191613243565b500290565b6000828210156131a8576131a8613243565b500390565b60005b838110156131c85781810151838201526020016131b0565b838111156117a55750506000910152565b600181811c908216806131ed57607f821691505b6020821081141561320e57634e487b7160e01b600052602260045260246000fd5b50919050565b600060001982141561322857613228613243565b5060010190565b60008261323e5761323e613259565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b801515811461293157600080fd5b6001600160e01b03198116811461293157600080fdfea26469706673582212201f3e53657040451a6e8f596dca0e1fb8d03f1361b0a4ed6f4dc592d65ce32da464736f6c63430008060033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000006e53130ddff21e3bc963ee902005223b9a202106000000000000000000000000e052113bd7d7700d623414a0a4585bcae754e9d50000000000000000000000004e1e18aaccdf9acfd2e8847654a3871dfd234f020000000000000000000000002ce780d7c743a57791b835a9d6f998b15bbba5a4

-----Decoded View---------------
Arg [0] : registry_ (address): 0x6e53130dDfF21E3BC963Ee902005223b9A202106
Arg [1] : omnibus_ (address): 0xE052113bd7D7700d623414a0a4585BCaE754E9d5
Arg [2] : metadataGenerator_ (address): 0x4e1e18aaCCDf9acFd2E8847654A3871dfD234F02
Arg [3] : pak_ (address): 0x2Ce780D7c743A57791B835a9d6F998B15BBbA5a4

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000006e53130ddff21e3bc963ee902005223b9a202106
Arg [1] : 000000000000000000000000e052113bd7d7700d623414a0a4585bcae754e9d5
Arg [2] : 0000000000000000000000004e1e18aaccdf9acfd2e8847654a3871dfd234f02
Arg [3] : 0000000000000000000000002ce780d7c743a57791b835a9d6f998b15bbba5a4


Deployed Bytecode Sourcemap

4717:25110:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28679:426;;;;;;:::i;:::-;;:::i;:::-;;;7376:14:6;;7369:22;7351:41;;7339:2;7324:18;28679:426:0;;;;;;;;5995:23;;;;;;;;;7811:25:6;;;7799:2;7784:18;5995:23:0;7766:76:6;6196:24:0;;;;;-1:-1:-1;;;;;6196:24:0;;;;;;-1:-1:-1;;;;;6326:55:6;;;6308:74;;6296:2;6281:18;6196:24:0;6263:125:6;5781:18:0;;;;;;;;;;;;9001:98;;;:::i;:::-;;;;;;;:::i;25013:204::-;;;;;;:::i;:::-;;:::i;24446:387::-;;;;;;:::i;:::-;;:::i;:::-;;24047:180;;;;;;:::i;:::-;;:::i;9214:88::-;9284:11;;9214:88;;23428:323;;;;;;:::i;:::-;;:::i;17810:233::-;;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;7101:55:6;;;7083:74;;7188:2;7173:18;;7166:34;;;;7056:18;17810:233:0;7038:168:6;5808:26:0;;;;;;7421:189;;;;;;:::i;:::-;;:::i;22267:409::-;;;;;;:::i;:::-;;:::i;6166:23::-;;;;;-1:-1:-1;;;;;6166:23:0;;;19046:119;;;;;;:::i;:::-;-1:-1:-1;;;;;19131:27:0;19108:4;19131:27;;;:17;:27;;;;;;;;;19046:119;5963:25;;;;;;22985:149;;;;;;:::i;:::-;;:::i;29112:326::-;;;;;;:::i;:::-;;:::i;24233:207::-;;;;;;:::i;:::-;;:::i;5922:33::-;;;;;;22685:110;;;:::i;25686:100::-;;;;;;:::i;:::-;;:::i;27381:202::-;;;;;;:::i;:::-;;:::i;4766:40::-;;;;;-1:-1:-1;;;;;4766:40:0;;;22909:70;;;:::i;23884:157::-;;;;;;:::i;:::-;;:::i;17580:224::-;;;;;;:::i;:::-;;:::i;22801:102::-;;;:::i;19296:188::-;;;;;;:::i;:::-;;:::i;23757:121::-;;;;;;:::i;:::-;-1:-1:-1;;;;;23847:16:0;23821:7;23847:16;;;:9;:16;;;;;;;23757:121;6227:34;;;;;18356:104;;;;;;:::i;:::-;;:::i;5875:41::-;;;;;18470:149;;;;;;:::i;:::-;;:::i;9105:102::-;;;:::i;25223:289::-;;;;;;:::i;:::-;;:::i;18049:218::-;;;;;;:::i;:::-;;:::i;18273:77::-;;;;;;:::i;:::-;;:::i;23140:282::-;;;;;;:::i;:::-;;:::i;26735:210::-;;;;;;:::i;:::-;;:::i;26289:440::-;;;;;;:::i;:::-;;:::i;6059:19::-;;;;;-1:-1:-1;;;;;6059:19:0;;;9309:723;;;;;;:::i;:::-;;:::i;18628:412::-;;;;;;:::i;:::-;;:::i;6085:74::-;;6117:42;6085:74;;5746:29;;;;;;;;;25518:162;;;;;;:::i;:::-;-1:-1:-1;;;;;25638:25:0;;;25615:4;25638:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;25518:162;27162:209;;;;;;:::i;:::-;;:::i;6026:25::-;;;;;;19954:2307;;;;;;:::i;:::-;;:::i;5842:26::-;;;;;;19171:119;;;;;;:::i;:::-;-1:-1:-1;;;;;19256:27:0;19233:4;19256:27;;;:17;:27;;;;;;;;;19171:119;26951:205;;;;;;:::i;:::-;;:::i;:::-;;;;18505:25:6;;;18561:2;18546:18;;18539:34;;;;18478:18;26951:205:0;18460:119:6;28679:426:0;28764:4;28780:28;28818;28856:29;28895:36;-1:-1:-1;;;;;;28948:23:0;;;;;:63;;-1:-1:-1;;;;;;;28988:23:0;;;;;;;28948:63;:103;;;-1:-1:-1;;;;;;;29027:24:0;;;;;;;28948:103;:150;;;-1:-1:-1;;;;;;;29067:31:0;;;;;;;28948:150;28941:157;28679:426;-1:-1:-1;;;;;;28679:426:0:o;9001:98::-;9055:13;9087:5;9080:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9001:98;:::o;25013:204::-;25089:7;25872:16;;;:7;:16;;;;;;-1:-1:-1;;;;;25872:16:0;25108:54;;;;-1:-1:-1;;;25108:54:0;;14583:2:6;25108:54:0;;;14565:21:6;14622:2;14602:18;;;14595:30;14661:27;14641:18;;;14634:55;14706:18;;25108:54:0;;;;;;;;;-1:-1:-1;25186:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;25186:24:0;;25013:204::o;24446:387::-;24526:13;24542:16;24550:7;24542;:16::i;:::-;24526:32;;24582:5;-1:-1:-1;;;;;24576:11:0;:2;-1:-1:-1;;;;;24576:11:0;;;24568:57;;;;-1:-1:-1;;;24568:57:0;;14937:2:6;24568:57:0;;;14919:21:6;14976:2;14956:18;;;14949:30;15015:34;14995:18;;;14988:62;15086:3;15066:18;;;15059:31;15107:19;;24568:57:0;14909:223:6;24568:57:0;27660:10;-1:-1:-1;;;;;24644:21:0;;;;:62;;-1:-1:-1;24669:37:0;24686:5;27660:10;25518:162;:::i;24669:37::-;24636:152;;;;-1:-1:-1;;;24636:152:0;;12568:2:6;24636:152:0;;;12550:21:6;12607:2;12587:18;;;12580:30;12646:34;12626:18;;;12619:62;12717:26;12697:18;;;12690:54;12761:19;;24636:152:0;12540:246:6;24636:152:0;24798:28;24807:5;24814:2;24818:7;24798:8;:28::i;:::-;24516:317;24446:387;;:::o;24047:180::-;24113:13;24146:16;;;:7;:16;;;;;;24180:10;24172:48;;;;-1:-1:-1;;;24172:48:0;;14583:2:6;24172:48:0;;;14565:21:6;14622:2;14602:18;;;14595:30;14661:27;14641:18;;;14634:55;14706:18;;24172:48:0;14555:175:6;24172:48:0;24047:180;;;:::o;23428:323::-;23528:13;;23569:41;27660:10;23588:12;23602:7;23569:18;:41::i;:::-;23527:83;;;;23628:17;23620:79;;;;-1:-1:-1;;;23620:79:0;;16391:2:6;23620:79:0;;;16373:21:6;16430:2;16410:18;;;16403:30;16469:34;16449:18;;;16442:62;16540:19;16520:18;;;16513:47;16577:19;;23620:79:0;16363:239:6;23620:79:0;23709:35;23719:5;23726:4;23732:2;23736:7;23709:9;:35::i;:::-;23517:234;;23428:323;;;:::o;17810:233::-;17890:7;17899;17918:21;17977:16;17955:18;;17943:9;:30;;;;:::i;:::-;17942:51;;;;:::i;:::-;18011:9;;-1:-1:-1;;;;;18011:9:0;;-1:-1:-1;17918:75:0;-1:-1:-1;;17810:233:0;;;;;;:::o;7421:189::-;7482:18;25872:16;;;:7;:16;;;;;;-1:-1:-1;;;;;25872:16:0;7512:54;;;;-1:-1:-1;;;7512:54:0;;14583:2:6;7512:54:0;;;14565:21:6;14622:2;14602:18;;;14595:30;14661:27;14641:18;;;14634:55;14706:18;;7512:54:0;14555:175:6;7512:54:0;-1:-1:-1;7583:20:0;;;;:11;:20;;;;;;;7421:189::o;22267:409::-;-1:-1:-1;;;;;7923:9:0;7908:44;;27660:10;7908:58;;-1:-1:-1;;;;;;7908:58:0;;;;;;;-1:-1:-1;;;;;6326:55:6;;;7908:58:0;;;6308:74:6;6281:18;;7908:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7900:96;;;;-1:-1:-1;;;7900:96:0;;15339:2:6;7900:96:0;;;15321:21:6;15378:2;15358:18;;;15351:30;15417:27;15397:18;;;15390:55;15462:18;;7900:96:0;15311:175:6;7900:96:0;22414:17:::1;::::0;::::1;;22413:18;22405:59;;;::::0;-1:-1:-1;;;22405:59:0;;13407:2:6;22405:59:0::1;::::0;::::1;13389:21:6::0;13446:2;13426:18;;;13419:30;13485;13465:18;;;13458:58;13533:18;;22405:59:0::1;13379:178:6::0;22405:59:0::1;22482:39:::0;;::::1;22474:52;;;::::0;-1:-1:-1;;;22474:52:0;;16102:2:6;22474:52:0::1;::::0;::::1;16084:21:6::0;-1:-1:-1;16121:18:6;;;16114:29;16160:18;;22474:52:0::1;16074:110:6::0;22474:52:0::1;22540:9;22536:115;22556:20:::0;;::::1;22536:115;;;22625:12;;22638:1;22625:15;;;;;;;:::i;:::-;;;;;;;22597:11;:25;22609:9;;22619:1;22609:12;;;;;;;:::i;:::-;;;;;;;22597:25;;;;;;;;;;;:43;;;;22578:3;;;;;:::i;:::-;;;;22536:115;;22985:149:::0;23088:39;23105:4;23111:2;23115:7;23088:39;;;;;;;;;;;;:16;:39::i;29112:326::-;8060:6;;;;;;;8059:7;8051:42;;;;-1:-1:-1;;;8051:42:0;;11407:2:6;8051:42:0;;;11389:21:6;11446:2;11426:18;;;11419:30;11485:24;11465:18;;;11458:52;11527:18;;8051:42:0;11379:172:6;8051:42:0;29171:13:::1;::::0;29212:41:::1;27660:10:::0;29231:12:::1;27589:88:::0;29212:41:::1;29170:83;;;;29271:17;29263:70;;;::::0;-1:-1:-1;;;29263:70:0;;13764:2:6;29263:70:0::1;::::0;::::1;13746:21:6::0;13803:2;13783:18;;;13776:30;13842:34;13822:18;;;13815:62;13913:10;13893:18;;;13886:38;13941:19;;29263:70:0::1;13736:230:6::0;29263:70:0::1;29344:35;29364:5;29371:7;29344:19;:35::i;:::-;29395:36;::::0;29423:7;;29419:1:::1;::::0;-1:-1:-1;;;;;29395:36:0;::::1;::::0;::::1;::::0;29419:1;;29395:36:::1;29160:278;;29112:326:::0;:::o;24233:207::-;-1:-1:-1;;;;;19131:27:0;;24294:7;19131:27;;;:17;:27;;;;;;;;24321:21;24313:58;;;;-1:-1:-1;;;24313:58:0;;9093:2:6;24313:58:0;;;9075:21:6;9132:2;9112:18;;;9105:30;9171:26;9151:18;;;9144:54;9215:18;;24313:58:0;9065:174:6;24313:58:0;-1:-1:-1;;;;;;24397:14:0;24381:13;24397:14;;;:7;:14;;;;;;;24233:207::o;22685:110::-;7669:4;;-1:-1:-1;;;;;7669:4:0;27660:10;-1:-1:-1;;;;;7653:20:0;;7645:61;;;;-1:-1:-1;;;7645:61:0;;9446:2:6;7645:61:0;;;9428:21:6;9485:2;9465:18;;;9458:30;9524;9504:18;;;9497:58;9572:18;;7645:61:0;9418:178:6;7645:61:0;22732:6:::1;:4;:6::i;:::-;22756:17;:24:::0;;-1:-1:-1;;22756:24:0::1;22776:4;22756:24;::::0;;22685:110::o;25686:100::-;25740:4;25872:16;;;:7;:16;;;;;;-1:-1:-1;;;;;25872:16:0;:30;;25763:16;25756:23;25686:100;-1:-1:-1;;25686:100:0:o;27381:202::-;27437:12;27468:24;4918:17;27468:5;:24;:::i;:::-;27461:31;;27555:21;27571:4;27555:15;:21::i;22909:70::-;7669:4;;-1:-1:-1;;;;;7669:4:0;27660:10;-1:-1:-1;;;;;7653:20:0;;7645:61;;;;-1:-1:-1;;;7645:61:0;;9446:2:6;7645:61:0;;;9428:21:6;9485:2;9465:18;;;9458:30;9524;9504:18;;;9497:58;9572:18;;7645:61:0;9418:178:6;7645:61:0;22958:6:::1;:14:::0;;-1:-1:-1;;22958:14:0::1;::::0;;22909:70::o;23884:157::-;23946:7;23965:13;23981:19;23992:7;23981:10;:19::i;:::-;23965:35;;24017:17;24028:5;24017:10;:17::i;:::-;24010:24;23884:157;-1:-1:-1;;;23884:157:0:o;17580:224::-;7669:4;;-1:-1:-1;;;;;7669:4:0;27660:10;-1:-1:-1;;;;;7653:20:0;;7645:61;;;;-1:-1:-1;;;7645:61:0;;9446:2:6;7645:61:0;;;9428:21:6;9485:2;9465:18;;;9458:30;9524;9504:18;;;9497:58;9572:18;;7645:61:0;9418:178:6;7645:61:0;17689:16:::1;17667:18;:38;;17659:89;;;::::0;-1:-1:-1;;;17659:89:0;;8273:2:6;17659:89:0::1;::::0;::::1;8255:21:6::0;8312:2;8292:18;;;8285:30;8351:34;8331:18;;;8324:62;8422:8;8402:18;;;8395:36;8448:19;;17659:89:0::1;8245:228:6::0;17659:89:0::1;17758:18;:39:::0;17580:224::o;22801:102::-;7669:4;;-1:-1:-1;;;;;7669:4:0;27660:10;-1:-1:-1;;;;;7653:20:0;;7645:61;;;;-1:-1:-1;;;7645:61:0;;9446:2:6;7645:61:0;;;9428:21:6;9485:2;9465:18;;;9458:30;9524;9504:18;;;9497:58;9572:18;;7645:61:0;9418:178:6;7645:61:0;22855:17:::1;::::0;::::1;;22854:18;22846:27;;;::::0;::::1;;22883:6;:13:::0;;-1:-1:-1;;22883:13:0::1;;;::::0;;22801:102::o;19296:188::-;19360:13;19393:16;;;:7;:16;;;;;;-1:-1:-1;;;;;19393:16:0;19428:19;19420:57;;;;-1:-1:-1;;;19420:57:0;;14583:2:6;19420:57:0;;;14565:21:6;14622:2;14602:18;;;14595:30;14661:27;14641:18;;;14634:55;14706:18;;19420:57:0;14555:175:6;18356:104:0;7669:4;;-1:-1:-1;;;;;7669:4:0;27660:10;-1:-1:-1;;;;;7653:20:0;;7645:61;;;;-1:-1:-1;;;7645:61:0;;9446:2:6;7645:61:0;;;9428:21:6;9485:2;9465:18;;;9458:30;9524;9504:18;;;9497:58;9572:18;;7645:61:0;9418:178:6;7645:61:0;18432:9:::1;:21:::0;;-1:-1:-1;;;;;;18432:21:0::1;-1:-1:-1::0;;;;;18432:21:0;;;::::1;::::0;;;::::1;::::0;;18356:104::o;18470:149::-;7669:4;;-1:-1:-1;;;;;7669:4:0;27660:10;-1:-1:-1;;;;;7653:20:0;;7645:61;;;;-1:-1:-1;;;7645:61:0;;9446:2:6;7645:61:0;;;9428:21:6;9485:2;9465:18;;;9458:30;9524;9504:18;;;9497:58;9572:18;;7645:61:0;9418:178:6;7645:61:0;18557:18:::1;:55:::0;;-1:-1:-1;;;;;;18557:55:0::1;-1:-1:-1::0;;;;;18557:55:0;;;::::1;::::0;;;::::1;::::0;;18470:149::o;9105:102::-;9161:13;9193:7;9186:14;;;;;:::i;25223:289::-;-1:-1:-1;;;;;25325:24:0;;27660:10;25325:24;;25317:62;;;;-1:-1:-1;;;25317:62:0;;11053:2:6;25317:62:0;;;11035:21:6;11092:2;11072:18;;;11065:30;11131:27;11111:18;;;11104:55;11176:18;;25317:62:0;11025:175:6;25317:62:0;27660:10;25389:32;;;;:18;:32;;;;;;;;-1:-1:-1;;;;;25389:42:0;;;;;;;;;;;;:53;;-1:-1:-1;;25389:53:0;;;;;;;;;;25457:48;;7351:41:6;;;25389:42:0;;27660:10;25457:48;;7324:18:6;25457:48:0;;;;;;;;25223:289;;:::o;18049:218::-;7669:4;;-1:-1:-1;;;;;7669:4:0;27660:10;-1:-1:-1;;;;;7653:20:0;;7645:61;;;;-1:-1:-1;;;7645:61:0;;9446:2:6;7645:61:0;;;9428:21:6;9485:2;9465:18;;;9458:30;9524;9504:18;;;9497:58;9572:18;;7645:61:0;9418:178:6;7645:61:0;18156:8:::1;::::0;-1:-1:-1;;;;;18144:20:0;;::::1;18156:8:::0;::::1;18144:20;;18136:78;;;::::0;-1:-1:-1;;;18136:78:0;;12993:2:6;18136:78:0::1;::::0;::::1;12975:21:6::0;13032:2;13012:18;;;13005:30;13071:34;13051:18;;;13044:62;13142:15;13122:18;;;13115:43;13175:19;;18136:78:0::1;12965:235:6::0;18136:78:0::1;-1:-1:-1::0;;;;;18224:27:0;;;::::1;;::::0;;;:17:::1;:27;::::0;;;;:36;;-1:-1:-1;;18224:36:0::1;::::0;::::1;;::::0;;;::::1;::::0;;18049:218::o;18273:77::-;7669:4;;-1:-1:-1;;;;;7669:4:0;27660:10;-1:-1:-1;;;;;7653:20:0;;7645:61;;;;-1:-1:-1;;;7645:61:0;;9446:2:6;7645:61:0;;;9428:21:6;9485:2;9465:18;;;9458:30;9524;9504:18;;;9497:58;9572:18;;7645:61:0;9418:178:6;7645:61:0;18332:4:::1;:11:::0;;-1:-1:-1;;;;;;18332:11:0::1;-1:-1:-1::0;;;;;18332:11:0;;;::::1;::::0;;;::::1;::::0;;18273:77::o;23140:282::-;23263:31;23276:4;23282:2;23286:7;23263:12;:31::i;:::-;23312:48;23335:4;23341:2;23345:7;23354:5;23312:22;:48::i;:::-;23304:111;;;;-1:-1:-1;;;23304:111:0;;9803:2:6;23304:111:0;;;9785:21:6;9842:2;9822:18;;;9815:30;9881:34;9861:18;;;9854:62;9952:20;9932:18;;;9925:48;9990:19;;23304:111:0;9775:240:6;23304:111:0;23140:282;;;;:::o;26735:210::-;26813:7;26832:23;26849:5;26832:16;:23::i;:::-;26865:21;26881:4;26865:15;:21::i;:::-;26933:4;26905:24;4918:17;26905:5;:24;:::i;:::-;26904:33;;;;:::i;26289:440::-;25849:4;25872:16;;;:7;:16;;;;;;26362:13;;-1:-1:-1;;;;;25872:16:0;26387:54;;;;-1:-1:-1;;;26387:54:0;;14583:2:6;26387:54:0;;;14565:21:6;14622:2;14602:18;;;14595:30;14661:27;14641:18;;;14634:55;14706:18;;26387:54:0;14555:175:6;26387:54:0;26467:18;;;26547:16;;;:7;:16;;;;;;;-1:-1:-1;;;;;26467:18:0;;;;:32;;26513:7;;26535:29;;:11;:29::i;:::-;26590:16;;;;:7;:16;;;;;;26579:28;;:10;:28::i;:::-;26641:8;;26633:17;;;;:7;:17;;;;;;26622:29;;:10;:29::i;:::-;26677:8;;26666:7;:19;26699:22;26713:7;26699:13;:22::i;:::-;26467:255;;-1:-1:-1;;;;;;26467:255:0;;;;;;;;;;18865:25:6;;;;18906:18;;;18899:34;;;;18949:18;;;18942:34;;;;18992:18;;;18985:34;19063:14;19056:22;19035:19;;;19028:51;19095:19;;;19088:35;18837:19;;26467:255:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;26467:255:0;;;;;;;;;;;;:::i;9309:723::-;27660:10;9413:19;7778:31;;;:17;:31;;;;;;;;7770:69;;;;-1:-1:-1;;;7770:69:0;;15339:2:6;7770:69:0;;;15321:21:6;15378:2;15358:18;;;15351:30;15417:27;15397:18;;;15390:55;15462:18;;7770:69:0;15311:175:6;7770:69:0;8060:6:::1;::::0;::::1;::::0;::::1;;;8059:7;8051:42;;;::::0;-1:-1:-1;;;8051:42:0;;11407:2:6;8051:42:0::1;::::0;::::1;11389:21:6::0;11446:2;11426:18;;;11419:30;11485:24;11465:18;;;11458:52;11527:18;;8051:42:0::1;11379:172:6::0;8051:42:0::1;9452:13:::2;9468:20;9476:11;9468:7;:20::i;:::-;9452:36;;9515:20;9523:11;9515:7;:20::i;:::-;-1:-1:-1::0;;;;;9506:29:0::2;:5;-1:-1:-1::0;;;;;9506:29:0::2;;9498:82;;;::::0;-1:-1:-1;;;9498:82:0;;15693:2:6;9498:82:0::2;::::0;::::2;15675:21:6::0;15732:2;15712:18;;;15705:30;15771:34;15751:18;;;15744:62;15842:10;15822:18;;;15815:38;15870:19;;9498:82:0::2;15665:230:6::0;9498:82:0::2;27660:10:::0;-1:-1:-1;;;;;9598:21:0;::::2;;9590:72;;;::::0;-1:-1:-1;;;9590:72:0;;11758:2:6;9590:72:0::2;::::0;::::2;11740:21:6::0;11797:2;11777:18;;;11770:30;11836:34;11816:18;;;11809:62;11907:8;11887:18;;;11880:36;11933:19;;9590:72:0::2;11730:228:6::0;9590:72:0::2;-1:-1:-1::0;;;;;9746:16:0;::::2;;::::0;;;:9:::2;:16;::::0;;;;:21;;9766:1:::2;::::0;9746:16;:21:::2;::::0;9766:1;;9746:21:::2;:::i;:::-;::::0;;;-1:-1:-1;9792:32:0::2;::::0;-1:-1:-1;9799:11:0;9812;9792:6:::2;:32::i;:::-;9883:20;::::0;;;:7:::2;:20;::::0;;;;;9876:27;;-1:-1:-1;;;;;;9876:27:0::2;::::0;;9985:40;9778:46;;-1:-1:-1;9778:46:0;;-1:-1:-1;;;;;9985:40:0;::::2;::::0;::::2;::::0;9883:20;;9985:40:::2;9434:598;9309:723:::0;;;;:::o;18628:412::-;7669:4;;-1:-1:-1;;;;;7669:4:0;27660:10;-1:-1:-1;;;;;7653:20:0;;7645:61;;;;-1:-1:-1;;;7645:61:0;;9446:2:6;7645:61:0;;;9428:21:6;9485:2;9465:18;;;9458:30;9524;9504:18;;;9497:58;9572:18;;7645:61:0;9418:178:6;7645:61:0;18726:8:::1;::::0;-1:-1:-1;;;;;18714:20:0;;::::1;18726:8:::0;::::1;18714:20;18711:127;;;18757:15:::0;18749:78:::1;;;::::0;-1:-1:-1;;;18749:78:0;;17932:2:6;18749:78:0::1;::::0;::::1;17914:21:6::0;17971:2;17951:18;;;17944:30;18010:34;17990:18;;;17983:62;18081:20;18061:18;;;18054:48;18119:19;;18749:78:0::1;17904:240:6::0;18749:78:0::1;18851:15:::0;18848:139:::1;;18913:1;18890:19;18900:8;-1:-1:-1::0;;;;;23847:16:0;23821:7;23847:16;;;:9;:16;;;;;;;23757:121;18890:19:::1;:24;;18882:94;;;::::0;-1:-1:-1;;;18882:94:0;;10222:2:6;18882:94:0::1;::::0;::::1;10204:21:6::0;10261:2;10241:18;;;10234:30;10300:34;10280:18;;;10273:62;10371:27;10351:18;;;10344:55;10416:19;;18882:94:0::1;10194:247:6::0;18882:94:0::1;-1:-1:-1::0;;;;;18997:27:0;;;::::1;;::::0;;;:17:::1;:27;::::0;;;;:36;;-1:-1:-1;;18997:36:0::1;::::0;::::1;;::::0;;;::::1;::::0;;18628:412::o;27162:209::-;27219:13;27252:24;4918:17;27252:5;:24;:::i;:::-;27244:32;;27341:23;27358:5;27341:16;:23::i;19954:2307::-;-1:-1:-1;;;;;7923:9:0;7908:44;;27660:10;7908:58;;-1:-1:-1;;;;;;7908:58:0;;;;;;;-1:-1:-1;;;;;6326:55:6;;;7908:58:0;;;6308:74:6;6281:18;;7908:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7900:96;;;;-1:-1:-1;;;7900:96:0;;15339:2:6;7900:96:0;;;15321:21:6;15378:2;15358:18;;;15351:30;15417:27;15397:18;;;15390:55;15462:18;;7900:96:0;15311:175:6;7900:96:0;20040:17:::1;::::0;::::1;;20039:18;20031:59;;;::::0;-1:-1:-1;;;20031:59:0;;13407:2:6;20031:59:0::1;::::0;::::1;13389:21:6::0;13446:2;13426:18;;;13419:30;13485;13465:18;;;13458:58;13533:18;;20031:59:0::1;13379:178:6::0;20031:59:0::1;20206:11;::::0;20261:8:::1;::::0;20299:10:::1;::::0;20337:8:::1;::::0;-1:-1:-1;;;;;20337:8:0::1;20190:13;::::0;;20503:751:::1;20510:24:::0;;::::1;20503:751;;;20567:32;20582:7;;20590;20582:16;;;;;;;:::i;:::-;;;;;;;20567:14;:32::i;:::-;20563:584;;;;;;20686:18:::0;::::1;::::0;::::1;:::i;:::-;;;;20740:7;;20748;20740:16;;;;;;;:::i;:::-;20723:14;::::0;;;:7:::1;20740:16;20723:14:::0;;;;;;;20740:16;;::::1;::::0;;;::::1;;20723:33:::0;;;20786:7:::1;:14:::0;;;;;;:24;;-1:-1:-1;;;;;;20786:24:0::1;-1:-1:-1::0;;;;;20786:24:0;::::1;;::::0;;-1:-1:-1;20867:36:0::1;20886:7:::0;;20894;20886:16;;::::1;;;;;:::i;:::-;;;;;;;20867:18;:36::i;:::-;20829:74;;;20938:4;20926:9;:16;20922:115;;;20977:4;20965:16;;21013:5;21003:15;;20922:115;21055:17;21068:4:::0;21055:17;::::1;:::i;:::-;21096:36;::::0;21055:17;;-1:-1:-1;21126:5:0;;-1:-1:-1;;;;;21096:36:0;::::1;::::0;21113:1:::1;::::0;21096:36:::1;::::0;21113:1;;21096:36:::1;20668:479;20563:584;21213:9:::0;::::1;::::0;::::1;:::i;:::-;;;;21236:7;;;;;:::i;:::-;;;;20503:751;;;21326:5;21312:11;:19;;;;21423:16;21408:11;;:31;;;;;;;:::i;:::-;::::0;;;-1:-1:-1;;;;;;;21449:18:0;::::1;;::::0;;;:9:::1;:18;::::0;;;;:38;;21471:16;;21449:18;:38:::1;::::0;21471:16;;21449:38:::1;:::i;:::-;::::0;;;-1:-1:-1;;21795:10:0::1;::::0;21771:21:::1;21838:25;21854:9:::0;21795:10;21838:25:::1;:::i;:::-;21815:48:::0;-1:-1:-1;5411:20:0::1;5430:1;4918:17;5411:20;:::i;:::-;21881:12;:28;21873:67;;;::::0;-1:-1:-1;;;21873:67:0;;17577:2:6;21873:67:0::1;::::0;::::1;17559:21:6::0;17616:2;17596:18;;;17589:30;17655:28;17635:18;;;17628:56;17701:18;;21873:67:0::1;17549:176:6::0;21873:67:0::1;21950:10;:25:::0;;;22093:8:::1;::::0;:19;::::1;22090:157;;22128:8;:18:::0;;;22160:10:::1;:22:::0;;;22201:35:::1;::::0;7811:25:6;;;22128:18:0;;22201:35:::1;::::0;7799:2:6;7784:18;22201:35:0::1;;;;;;;22090:157;20021:2240;;;;;;;;;19954:2307:::0;;:::o;26951:205::-;27015:7;27024;27043:13;27059:18;27071:5;27059:11;:18::i;:::-;27043:34;;27087:12;27102:17;27113:5;27102:10;:17::i;:::-;27137:5;;27087:32;;-1:-1:-1;26951:205:0;;-1:-1:-1;;;26951:205:0:o;24839:168::-;24928:24;;;;:15;:24;;;;;;:29;;-1:-1:-1;;;;;;24928:29:0;-1:-1:-1;;;;;24928:29:0;;;;;;;;;24972:28;;24928:24;;24972:28;;;;;;;24839:168;;;:::o;25915:365::-;26008:13;26065:16;;;:7;:16;;;;;;-1:-1:-1;;;;;26065:16:0;;26100:19;26092:57;;;;-1:-1:-1;;;26092:57:0;;14583:2:6;26092:57:0;;;14565:21:6;14622:2;14602:18;;;14595:30;14661:27;14641:18;;;14634:55;14706:18;;26092:57:0;14555:175:6;26092:57:0;26192:5;-1:-1:-1;;;;;26181:16:0;:7;-1:-1:-1;;;;;26181:16:0;;:55;;;-1:-1:-1;26201:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;26201:35:0;;;:24;;:35;26181:55;:91;;;-1:-1:-1;;;;;;25638:25:0;;;25615:4;25638:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;26240:32;26160:113;;25915:365;;;;;:::o;10038:6346::-;8060:6;;;;;;;8059:7;8051:42;;;;-1:-1:-1;;;8051:42:0;;11407:2:6;8051:42:0;;;11389:21:6;11446:2;11426:18;;;11419:30;11485:24;11465:18;;;11458:52;11527:18;;8051:42:0;11379:172:6;8051:42:0;10161:4:::1;-1:-1:-1::0;;;;;10152:13:0::1;:5;-1:-1:-1::0;;;;;10152:13:0::1;;10144:67;;;::::0;-1:-1:-1;;;10144:67:0;;14173:2:6;10144:67:0::1;::::0;::::1;14155:21:6::0;14212:2;14192:18;;;14185:30;14251:34;14231:18;;;14224:62;14322:11;14302:18;;;14295:39;14351:19;;10144:67:0::1;14145:231:6::0;10144:67:0::1;-1:-1:-1::0;;;;;10229:16:0;::::1;10221:65;;;::::0;-1:-1:-1;;;10221:65:0;;10648:2:6;10221:65:0::1;::::0;::::1;10630:21:6::0;10687:2;10667:18;;;10660:30;10726:34;10706:18;;;10699:62;10797:6;10777:18;;;10770:34;10821:19;;10221:65:0::1;10620:226:6::0;10221:65:0::1;-1:-1:-1::0;;;;;10305:21:0;::::1;;::::0;;;:17:::1;:21;::::0;;;;;::::1;;10304:22;10296:79;;;::::0;-1:-1:-1;;;10296:79:0;;8680:2:6;10296:79:0::1;::::0;::::1;8662:21:6::0;8719:2;8699:18;;;8692:30;8758:34;8738:18;;;8731:62;8829:14;8809:18;;;8802:42;8861:19;;10296:79:0::1;8652:234:6::0;10296:79:0::1;-1:-1:-1::0;;;;;10471:11:0;::::1;6117:42;10471:11;10467:5911;;;10498:35;10518:5;10525:7;10498:19;:35::i;:::-;10553:30;::::0;10575:7;;6117:42:::1;::::0;-1:-1:-1;;;;;10553:30:0;::::1;::::0;::::1;::::0;;;::::1;10602:36;::::0;10630:7;;10626:1:::1;::::0;6117:42:::1;::::0;10602:36:::1;::::0;10626:1;;10602:36:::1;10467:5911;;;10762:36;10771:5;10786:1;10790:7;10762:8;:36::i;:::-;10981:7;10977:2;-1:-1:-1::0;;;;;10962:27:0::1;10971:4;-1:-1:-1::0;;;;;10962:27:0::1;;;;;;;;;;;11016:2;-1:-1:-1::0;;;;;11008:10:0::1;:4;-1:-1:-1::0;;;;;11008:10:0::1;;11004:249;;;11232:7;;11004:249;-1:-1:-1::0;;;;;19131:27:0;;;11969:22:::1;19131:27:::0;;;:17;:27;;;;;;;;;;;;;;;;;;;;;12286:598;::::1;;;-1:-1:-1::0;;;;;12468:15:0;::::1;;::::0;;;:9:::1;:15;::::0;;;;:20;;12487:1:::1;::::0;12468:15;:20:::1;::::0;12487:1;;12468:20:::1;:::i;:::-;::::0;;;-1:-1:-1;12286:598:0::1;::::0;-1:-1:-1;12286:598:0::1;;-1:-1:-1::0;;;;;12854:15:0;::::1;;::::0;;;:9:::1;:15;::::0;;;;12847:22;12286:598:::1;13040:15;13036:830;;;-1:-1:-1::0;;;;;13216:13:0;::::1;;::::0;;;:9:::1;:13;::::0;;;;:18;;13233:1:::1;::::0;13216:13;:18:::1;::::0;13233:1;;13216:18:::1;:::i;:::-;::::0;;;-1:-1:-1;13036:830:0::1;::::0;-1:-1:-1;13036:830:0::1;;-1:-1:-1::0;;;;;13259:11:0;::::1;;::::0;;;:7:::1;:11;::::0;;;;;13255:611:::1;;-1:-1:-1::0;;;;;13540:13:0;::::1;;::::0;;;:9:::1;:13;::::0;;;;13556:1:::1;13540:17:::0;;13255:611:::1;13910:15;13906:2216;;;14293:16;::::0;;;:7:::1;:16;::::0;;;;:21;;-1:-1:-1;;;;;;14293:21:0::1;-1:-1:-1::0;;;;;14293:21:0;::::1;;::::0;;13906:2216:::1;;;-1:-1:-1::0;;;;;14455:11:0;::::1;14430:22;14455:11:::0;;;:7:::1;:11;::::0;;;;;14489:19;14485:1623:::1;;14627:16;::::0;;;:7:::1;:16;::::0;;;;;;;:21;;-1:-1:-1;;;;;;14627:21:0::1;-1:-1:-1::0;;;;;14627:21:0;::::1;::::0;;::::1;::::0;;;14753:11;;:7:::1;:11:::0;;;;;:21;;;14485:1623:::1;;;14843:7:::0;14821:19:::1;14964:35;14971:14:::0;14843:7;14964:6:::1;:35::i;:::-;15202:37;::::0;14942:57;;-1:-1:-1;14942:57:0;;15223:1:::1;::::0;-1:-1:-1;;;;;15202:37:0;::::1;::::0;::::1;::::0;15223:1;;15202:37:::1;15339:14:::0;15379:29;;::::1;15375:110;;;-1:-1:-1::0;15451:11:0;15375:110:::1;15617:20;::::0;;;:7:::1;:20;::::0;;;;15610:27;;-1:-1:-1;;;;;;15610:27:0::1;::::0;;15734:30;;::::1;15730:360;;15898:21;::::0;;;:7:::1;:21;::::0;;;;;;;:26;;-1:-1:-1;;;;;;15898:26:0::1;-1:-1:-1::0;;;;;15898:26:0;::::1;::::0;;::::1;::::0;;;16041:11;;:7:::1;:11:::0;;;;;:26;;;15730:360:::1;14799:1309;;;14485:1623;14335:1787;13906:2216;16296:17;16291:77;;-1:-1:-1::0;;;;;16340:13:0;::::1;;::::0;;;:7:::1;:13;::::0;;;;16333:20;16291:77:::1;10655:5723;;10038:6346:::0;;;;:::o;29444:381::-;29524:36;29533:5;29548:1;29552:7;29524:8;:36::i;:::-;29596:16;;;;:7;:16;;;;;;29585:28;;:10;:28::i;:::-;29571:10;;:42;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;29631:14:0;;;;;;:7;:14;;;;;;;;29624:21;;;29662:16;;;:7;:16;;;;;29655:23;;-1:-1:-1;;;;;;29655:23:0;;;29695:7;:16;;;;;29688:23;;;29722:11;:16;;29655:23;;29631:14;29722:16;;29655:23;;29722:16;:::i;:::-;;;;-1:-1:-1;;;;;;;29748:16:0;;;;;;:9;:16;;;;;:21;;29768:1;;29748:16;:21;;29768:1;;29748:21;:::i;:::-;;;;-1:-1:-1;;29793:25:0;;29813:1;7811:25:6;;;29813:1:0;29804:7;;29793:25;;7799:2:6;7784:18;29793:25:0;7766:76:6;5438:161:0;5525:4;5362:1;5508:21;;:45;;;;-1:-1:-1;5411:20:0;5430:1;4918:17;5411:20;:::i;:::-;5533:4;:20;5508:45;5500:92;;;;-1:-1:-1;;;5500:92:0;;12165:2:6;5500:92:0;;;12147:21:6;12204:2;12184:18;;;12177:30;12243:34;12223:18;;;12216:62;12314:4;12294:18;;;12287:32;12336:19;;5500:92:0;12137:224:6;5500:92:0;5438:161;:::o;27688:749::-;27800:4;28620:20;;28658:8;27816:594;;27854:72;;-1:-1:-1;;;27854:72:0;;-1:-1:-1;;;;;27854:36:0;;;;;:72;;27660:10;;27905:4;;27911:7;;27920:5;;27854:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;27854:72:0;;;;;;;;-1:-1:-1;;27854:72:0;;;;;;;;;;;;:::i;:::-;;;27850:550;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;28097:13:0;;28093:125;;28139:60;;-1:-1:-1;;;28139:60:0;;9803:2:6;28139:60:0;;;9785:21:6;9842:2;9822:18;;;9815:30;9881:34;9861:18;;;9854:62;9952:20;9932:18;;;9925:48;9990:19;;28139:60:0;9775:240:6;28093:125:0;28360:6;28354:13;28345:6;28341:2;28337:15;28330:38;27850:550;-1:-1:-1;;;;;;27976:55:0;-1:-1:-1;;;27976:55:0;;-1:-1:-1;27969:62:0;;27850:550;-1:-1:-1;28426:4:0;27688:749;;;;;;;:::o;5102:162::-;5192:5;5044:1;5174:23;;:50;;;;;5094:1;5201:5;:23;;5174:50;5166:91;;;;-1:-1:-1;;;5166:91:0;;17220:2:6;5166:91:0;;;17202:21:6;17259:2;17239:18;;;17232:30;17298;17278:18;;;17271:58;17346:18;;5166:91:0;17192:178:6;16390:1184:0;16466:19;16520:11;16505;:26;;16497:81;;;;-1:-1:-1;;;16497:81:0;;16809:2:6;16497:81:0;;;16791:21:6;16848:2;16828:18;;;16821:30;16887:34;16867:18;;;16860:62;16958:12;16938:18;;;16931:40;16988:19;;16497:81:0;16781:232:6;16497:81:0;16589:16;16619:20;;;:7;:20;;;;;;16608:32;;:10;:32::i;:::-;16650:16;16680:20;;;:7;:20;;;;;;16589:51;;-1:-1:-1;16650:16:0;16669:32;;:10;:32::i;:::-;16650:51;-1:-1:-1;16740:8:0;16650:51;16820:11;16864;16890:20;;;16886:187;;-1:-1:-1;16939:8:0;;-1:-1:-1;16973:8:0;;-1:-1:-1;17011:11:0;;-1:-1:-1;17051:11:0;16886:187;17083:21;;;;:7;:21;;;;;:34;;17108:9;;17083:21;:34;;17108:9;;17083:34;:::i;:::-;;;;-1:-1:-1;17128:20:0;;-1:-1:-1;17151:21:0;17163:9;17151;:21;:::i;:::-;17128:44;;17201:10;;17186:12;:25;17183:175;;;17227:8;:23;;;17264:10;:25;;;17308:39;;7811:25:6;;;17227:23:0;;17308:39;;7799:2:6;7784:18;17308:39:0;;;;;;;17183:175;17376:25;;;;:11;:25;;;;;:27;;;;;;:::i;:::-;;;;-1:-1:-1;;17421:21:0;;;;:7;:21;;;;;17414:28;;;17453:11;:16;;17468:1;;17421:21;17453:16;;17468:1;;17453:16;:::i;:::-;;;;-1:-1:-1;;17485:52:0;;7811:25:6;;;17510:12:0;;17496;;17485:52;;7799:2:6;7784:18;17485:52:0;;;;;;;-1:-1:-1;17555:12:0;;16390:1184;-1:-1:-1;;;;;;;;16390:1184:0:o;5605:134::-;5666:4;5411:20;5430:1;4918:17;5411:20;:::i;:::-;5690:24;4918:17;5690:5;:24;:::i;:::-;5689:43;;5605:134;-1:-1:-1;;5605:134:0:o;14:196:6:-;82:20;;-1:-1:-1;;;;;131:54:6;;121:65;;111:2;;200:1;197;190:12;215:367;278:8;288:6;342:3;335:4;327:6;323:17;319:27;309:2;;360:1;357;350:12;309:2;-1:-1:-1;383:20:6;;426:18;415:30;;412:2;;;458:1;455;448:12;412:2;495:4;487:6;483:17;471:29;;555:3;548:4;538:6;535:1;531:14;523:6;519:27;515:38;512:47;509:2;;;572:1;569;562:12;587:186;646:6;699:2;687:9;678:7;674:23;670:32;667:2;;;715:1;712;705:12;667:2;738:29;757:9;738:29;:::i;778:260::-;846:6;854;907:2;895:9;886:7;882:23;878:32;875:2;;;923:1;920;913:12;875:2;946:29;965:9;946:29;:::i;:::-;936:39;;994:38;1028:2;1017:9;1013:18;994:38;:::i;1043:328::-;1120:6;1128;1136;1189:2;1177:9;1168:7;1164:23;1160:32;1157:2;;;1205:1;1202;1195:12;1157:2;1228:29;1247:9;1228:29;:::i;:::-;1218:39;;1276:38;1310:2;1299:9;1295:18;1276:38;:::i;:::-;1266:48;;1361:2;1350:9;1346:18;1333:32;1323:42;;1147:224;;;;;:::o;1376:888::-;1471:6;1479;1487;1495;1548:3;1536:9;1527:7;1523:23;1519:33;1516:2;;;1565:1;1562;1555:12;1516:2;1588:29;1607:9;1588:29;:::i;:::-;1578:39;;1636:38;1670:2;1659:9;1655:18;1636:38;:::i;:::-;1626:48;;1721:2;1710:9;1706:18;1693:32;1683:42;;1776:2;1765:9;1761:18;1748:32;1803:18;1795:6;1792:30;1789:2;;;1835:1;1832;1825:12;1789:2;1858:22;;1911:4;1903:13;;1899:27;-1:-1:-1;1889:2:6;;1940:1;1937;1930:12;1889:2;1976;1963:16;2001:48;2017:31;2045:2;2017:31;:::i;:::-;2001:48;:::i;:::-;2072:2;2065:5;2058:17;2112:7;2107:2;2102;2098;2094:11;2090:20;2087:33;2084:2;;;2133:1;2130;2123:12;2084:2;2188;2183;2179;2175:11;2170:2;2163:5;2159:14;2146:45;2232:1;2227:2;2222;2215:5;2211:14;2207:23;2200:34;2253:5;2243:15;;;;;1506:758;;;;;;;:::o;2269:315::-;2334:6;2342;2395:2;2383:9;2374:7;2370:23;2366:32;2363:2;;;2411:1;2408;2401:12;2363:2;2434:29;2453:9;2434:29;:::i;:::-;2424:39;;2513:2;2502:9;2498:18;2485:32;2526:28;2548:5;2526:28;:::i;:::-;2573:5;2563:15;;;2353:231;;;;;:::o;2589:254::-;2657:6;2665;2718:2;2706:9;2697:7;2693:23;2689:32;2686:2;;;2734:1;2731;2724:12;2686:2;2757:29;2776:9;2757:29;:::i;:::-;2747:39;2833:2;2818:18;;;;2805:32;;-1:-1:-1;;;2676:167:6:o;2848:437::-;2934:6;2942;2995:2;2983:9;2974:7;2970:23;2966:32;2963:2;;;3011:1;3008;3001:12;2963:2;3051:9;3038:23;3084:18;3076:6;3073:30;3070:2;;;3116:1;3113;3106:12;3070:2;3155:70;3217:7;3208:6;3197:9;3193:22;3155:70;:::i;:::-;3244:8;;3129:96;;-1:-1:-1;2953:332:6;-1:-1:-1;;;;2953:332:6:o;3290:773::-;3412:6;3420;3428;3436;3489:2;3477:9;3468:7;3464:23;3460:32;3457:2;;;3505:1;3502;3495:12;3457:2;3545:9;3532:23;3574:18;3615:2;3607:6;3604:14;3601:2;;;3631:1;3628;3621:12;3601:2;3670:70;3732:7;3723:6;3712:9;3708:22;3670:70;:::i;:::-;3759:8;;-1:-1:-1;3644:96:6;-1:-1:-1;3847:2:6;3832:18;;3819:32;;-1:-1:-1;3863:16:6;;;3860:2;;;3892:1;3889;3882:12;3860:2;;3931:72;3995:7;3984:8;3973:9;3969:24;3931:72;:::i;:::-;3447:616;;;;-1:-1:-1;4022:8:6;-1:-1:-1;;;;3447:616:6:o;4068:245::-;4135:6;4188:2;4176:9;4167:7;4163:23;4159:32;4156:2;;;4204:1;4201;4194:12;4156:2;4236:9;4230:16;4255:28;4277:5;4255:28;:::i;4318:245::-;4376:6;4429:2;4417:9;4408:7;4404:23;4400:32;4397:2;;;4445:1;4442;4435:12;4397:2;4484:9;4471:23;4503:30;4527:5;4503:30;:::i;4568:249::-;4637:6;4690:2;4678:9;4669:7;4665:23;4661:32;4658:2;;;4706:1;4703;4696:12;4658:2;4738:9;4732:16;4757:30;4781:5;4757:30;:::i;4822:635::-;4902:6;4955:2;4943:9;4934:7;4930:23;4926:32;4923:2;;;4971:1;4968;4961:12;4923:2;5004:9;4998:16;5037:18;5029:6;5026:30;5023:2;;;5069:1;5066;5059:12;5023:2;5092:22;;5145:4;5137:13;;5133:27;-1:-1:-1;5123:2:6;;5174:1;5171;5164:12;5123:2;5203;5197:9;5228:48;5244:31;5272:2;5244:31;:::i;5228:48::-;5299:2;5292:5;5285:17;5339:7;5334:2;5329;5325;5321:11;5317:20;5314:33;5311:2;;;5360:1;5357;5350:12;5311:2;5373:54;5424:2;5419;5412:5;5408:14;5403:2;5399;5395:11;5373:54;:::i;:::-;5446:5;4913:544;-1:-1:-1;;;;;4913:544:6:o;5462:180::-;5521:6;5574:2;5562:9;5553:7;5549:23;5545:32;5542:2;;;5590:1;5587;5580:12;5542:2;-1:-1:-1;5613:23:6;;5532:110;-1:-1:-1;5532:110:6:o;5647:248::-;5715:6;5723;5776:2;5764:9;5755:7;5751:23;5747:32;5744:2;;;5792:1;5789;5782:12;5744:2;-1:-1:-1;;5815:23:6;;;5885:2;5870:18;;;5857:32;;-1:-1:-1;5734:161:6:o;5900:257::-;5941:3;5979:5;5973:12;6006:6;6001:3;5994:19;6022:63;6078:6;6071:4;6066:3;6062:14;6055:4;6048:5;6044:16;6022:63;:::i;:::-;6139:2;6118:15;-1:-1:-1;;6114:29:6;6105:39;;;;6146:4;6101:50;;5949:208;-1:-1:-1;;5949:208:6:o;6393:511::-;6587:4;-1:-1:-1;;;;;6697:2:6;6689:6;6685:15;6674:9;6667:34;6749:2;6741:6;6737:15;6732:2;6721:9;6717:18;6710:43;;6789:6;6784:2;6773:9;6769:18;6762:34;6832:3;6827:2;6816:9;6812:18;6805:31;6853:45;6893:3;6882:9;6878:19;6870:6;6853:45;:::i;7847:219::-;7996:2;7985:9;7978:21;7959:4;8016:44;8056:2;8045:9;8041:18;8033:6;8016:44;:::i;19134:275::-;19205:2;19199:9;19270:2;19251:13;;-1:-1:-1;;19247:27:6;19235:40;;19305:18;19290:34;;19326:22;;;19287:62;19284:2;;;19352:18;;:::i;:::-;19388:2;19381:22;19179:230;;-1:-1:-1;19179:230:6:o;19414:186::-;19462:4;19495:18;19487:6;19484:30;19481:2;;;19517:18;;:::i;:::-;-1:-1:-1;19583:2:6;19562:15;-1:-1:-1;;19558:29:6;19589:4;19554:40;;19471:129::o;19605:128::-;19645:3;19676:1;19672:6;19669:1;19666:13;19663:2;;;19682:18;;:::i;:::-;-1:-1:-1;19718:9:6;;19653:80::o;19738:120::-;19778:1;19804;19794:2;;19809:18;;:::i;:::-;-1:-1:-1;19843:9:6;;19784:74::o;19863:168::-;19903:7;19969:1;19965;19961:6;19957:14;19954:1;19951:21;19946:1;19939:9;19932:17;19928:45;19925:2;;;19976:18;;:::i;:::-;-1:-1:-1;20016:9:6;;19915:116::o;20036:125::-;20076:4;20104:1;20101;20098:8;20095:2;;;20109:18;;:::i;:::-;-1:-1:-1;20146:9:6;;20085:76::o;20166:258::-;20238:1;20248:113;20262:6;20259:1;20256:13;20248:113;;;20338:11;;;20332:18;20319:11;;;20312:39;20284:2;20277:10;20248:113;;;20379:6;20376:1;20373:13;20370:2;;;-1:-1:-1;;20414:1:6;20396:16;;20389:27;20219:205::o;20429:437::-;20508:1;20504:12;;;;20551;;;20572:2;;20626:4;20618:6;20614:17;20604:27;;20572:2;20679;20671:6;20668:14;20648:18;20645:38;20642:2;;;-1:-1:-1;;;20713:1:6;20706:88;20817:4;20814:1;20807:15;20845:4;20842:1;20835:15;20642:2;;20484:382;;;:::o;20871:135::-;20910:3;-1:-1:-1;;20931:17:6;;20928:2;;;20951:18;;:::i;:::-;-1:-1:-1;20998:1:6;20987:13;;20918:88::o;21011:112::-;21043:1;21069;21059:2;;21074:18;;:::i;:::-;-1:-1:-1;21108:9:6;;21049:74::o;21128:184::-;-1:-1:-1;;;21177:1:6;21170:88;21277:4;21274:1;21267:15;21301:4;21298:1;21291:15;21317:184;-1:-1:-1;;;21366:1:6;21359:88;21466:4;21463:1;21456:15;21490:4;21487:1;21480:15;21506:184;-1:-1:-1;;;21555:1:6;21548:88;21655:4;21652:1;21645:15;21679:4;21676:1;21669:15;21695:184;-1:-1:-1;;;21744:1:6;21737:88;21844:4;21841:1;21834:15;21868:4;21865:1;21858:15;21884:118;21970:5;21963:13;21956:21;21949:5;21946:32;21936:2;;21992:1;21989;21982:12;22007:177;-1:-1:-1;;;;;;22085:5:6;22081:78;22074:5;22071:89;22061:2;;22174:1;22171;22164:12

Swarm Source

ipfs://1f3e53657040451a6e8f596dca0e1fb8d03f1361b0a4ed6f4dc592d65ce32da4

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

OVERVIEW

Merge is a game of extinction.

Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.