ETH Price: $2,290.97 (-2.26%)

Token

BonSAIMaker (bMKR)
 

Overview

Max Total Supply

112 bMKR

Holders

86

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Filtered by Token Holder
metabreeder.eth
Balance
2 bMKR
0x86a050eb5ebe79a9d53da8ed4351ba59a3f4d81d
Loading...
Loading
Loading...
Loading
Loading...
Loading

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

Contract Source Code Verified (Exact Match)

Contract Name:
BonsaiMaker

Compiler Version
v0.8.17+commit.8df45f5f

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, None license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2022-12-21
*/

// SPDX-License-Identifier: VPL - VIRAL PUBLIC LICENSE
pragma solidity ^0.8.13;

/*
*  bbbbbbbb                                                                              
*  b::::::b                                                  
*  b::::::b                                                
*  b::::::b                                               
*   b:::::b                                               
*   b:::::bbbbbbbbb       ooooooooooo   nnnn  nnnnnnnn      
*   b::::::::::::::bb   oo:::::::::::oo n:::nn::::::::nn    
*   b::::::::::::::::b o:::::::::::::::on::::::::::::::nn    
*   b:::::bbbbb:::::::bo:::::ooooo:::::onn:::::::::::::::n    
*   b:::::b    b::::::bo::::o     o::::o  n:::::nnnn:::::n      
*   b:::::b     b:::::bo::::o     o::::o  n::::n    n::::n  
*   b:::::b     b:::::bo::::o     o::::o  n::::n    n::::n  
*   b:::::b     b:::::bo::::o     o::::o  n::::n    n::::n
*   b:::::bbbbbb::::::bo:::::ooooo:::::o  n::::n    n::::n
*   b::::::::::::::::b o:::::::::::::::o  n::::n    n::::n
*   b:::::::::::::::b   oo:::::::::::oo   n::::n    n::::n
*   bbbbbbbbbbbbbbbb      ooooooooooo     nnnnnn    nnnnnn
*                         SSSSSSSSSSSSSSS              AAA               IIIIIIIIII
*                       SS:::::::::::::::S            A:::A              I::::::::I
*                      S:::::SSSSSS::::::S           A:::::A             I::::::::I
*                      S:::::S     SSSSSSS          A:::::::A            II::::::II
*                      S:::::S                     A:::::::::A             I::::I  
*                      S:::::S                    A:::::A:::::A            I::::I  
*                       S::::SSSS                A:::::A A:::::A           I::::I  
*                        SS::::::SSSSS          A:::::A   A:::::A          I::::I  
*                          SSS::::::::SS       A:::::A     A:::::A         I::::I  
*                             SSSSSS::::S     A:::::AAAAAAAAA:::::A        I::::I  
*                                  S:::::S   A:::::::::::::::::::::A       I::::I  
*                                  S:::::S  A:::::AAAAAAAAAAAAA:::::A      I::::I  
*                      SSSSSSS     S:::::S A:::::A             A:::::A   II::::::II
*                      S::::::SSSSSS:::::SA:::::A               A:::::A  I::::::::I
*                      S:::::::::::::::SSA:::::A                 A:::::A I::::::::I
*                       SSSSSSSSSSSSSSS AAAAAAA                   AAAAAAAIIIIIIIIII
*
*
*   Living Collectibles
*
*   The first dispatch from NO_SIDE
*    
*    
*                                            @@@@                                    
*                                       ,@@@@@@@@%,@@@@@                             
*                                     /@@@@@@@@@@@@@@@@@@@.                          
*                                    @@@@@@@@@@@@@@@@@@@@@@&                         
*                                   @@@@@@@@@@@@@@@@@@@@@@@@*                        
*                                  @@@@@@@@@@@@@@@@@@@@@@@@@@                        
*                                  @@@@@@@@@@@@@@@@@@@@@@@@@@                        
*         *%@@@@@@@@@@@@%          @@@@@@@@@@@@@@@@@@@@@@@@@@                        
*       @@@@@@@@@@@@@@@@@@@@@*     @@@@@@@@@@@@@@@@@@@@@@@@@*                        
*         @@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@&                         
*    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(@@@@@@@@@@@@@@@@@@@@@@@       ((%@@@(((          
*    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&%@@@@@@@@@@@@@@@@@@@@@%    
*    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
*     &@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@&    &@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@. 
*       @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(  .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(
*         (@@@@@@@@@@@@@@@@@@@@@@@@.   /@@@@@@@@.    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*             *@@@@@@@@@@@@@@@@@@@@/   @@@@@@@@@@  ,@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 
*                       %%%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@(  
*                   .&@@@@@@@@@@@@@@@     @@@@    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*    
*               ,@@@@@@@@@@@@@@@@@@@@@%*@@@@@@.  ,@@@@@@@@@@@@@@@@@@@@@@@@@@,        
*             @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                      
*           @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@,                   
*         ,@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@/                 
*         @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                
*        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  @@@@@@@@@@@@@@@@@@@@@@@@@@@@               
*        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@@@@@@@@@@@@#              
*        @@@@@@@@@@@@@@@@@@@@@@@@@@@@      @@@@@@@@@@@@@@@@@@@@@@@@@@@@              
*         ,,, &@@@@@@@@@@@@@@@@@@@@         @@@@@@@@@@@@@@@@@@@@@@@@@@@              
*            &@@@@@@@@@@@@@@@@@/              @@@@@@@@@@@@@@@@@@@@@@@@(              
*               ,%@@@@@@@%                      @@@@@@@@@@@@@@@@@@@@@@               
*                                                 *@@@@@@@@@@@@@/(@@%                
*                                                     .@@@@@@@@@                     
*    
*    
*        
* bonSAI Living Collectibles is a limited, generative art collection living entirely "in-chain". 
* Each piece requires a prescribed amount of care to reach its full potential. 
*
* Mint your bonSAI via the payable external
*
*     `mint(address to)` 
*
* function including ETH value as a multiple of PRICE_PER_TOKEN = 0.0721 ether. This multiple
* determines the quantity minted and is capped by MAX_QTY.
* 
* Both bots and humans can mint these pieces, however the humans have access to a greater 
* range of plants with rarer qualities.
*
* There is a `freeMint` available for a limited run. Read the smart contract for details.
*
* The bonSAI is best viewed on https://www.nftviewer.xyz/ or https://opensea.io.
* Note: The bonSAI's appearance changes as it grows, with about 36 new sprouts per day. 
*   At this rate, changes are noticeable after about a day. To view changes from 
*   this growth, you may need to click "refresh metadata" on the OpenSea 
*   profile of your bonsai.
* 
* Once minted, the bonSAI must be watered weekly until about 6 weeks when it reaches 
* maturity, otherwise it will dry out and die.
* 
*   - To water a bonSAI call the `water(uint256 tokenId)` external function.
*     The caller only pays for gas. See etherscan history for idea of watering gas cost.
* 
* The form, ratio, and growth steps, are unique to each bonSAI where some may even grow blossoms. 
* At any point, a bonSAI owner can influence their piece by pruning to varying degrees.
* Of course, pruning is not necessary if you are satisfied with the original growth pattern 
* of your plant.
* Pruning changes the growth steps which can give more aesthetic branching, body, and may 
* even induce blossoming. Note that pruning extends the watering and maturation period 
* proportionally. Also pruning is restricted to the range above and cannot affect the 
* trunk or first layer of branching. These caveats aside, a plain bonSAI can be sculpted 
* to a striking beauty with just a few clips.
*
* The PRUNE_COST_PER_DEGREE is PRICE_PER_TOKEN/4, aka 0.018025 ether.  
*   - To prune a bonSAI call the `prune(uint256 tokenId)` payable external function with eth value
*       1 * PRUNE_COST_PER_DEGREE for LOW
*       2 * PRUNE_COST_PER_DEGREE for MEDIUM
*       3 * PRUNE_COST_PER_DEGREE for HIGH PruningDegrees
* 
* Your bonSAI's latest growth is rendered "in-chain" in real-time via the standard 
* 
*     `tokenURI(uint256 tokenId)` 
* 
* external view function returning a JSON array with latest attributes and svg image. 
* 
* Be sure to call this `tokenURI` view function using `callStatic`.
* 
* Keep posted for other upcoming projects from our group.
* 
*     - NO_SIDE
* 
**/

/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    event Approval(address indexed owner, address indexed spender, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /*//////////////////////////////////////////////////////////////
                         METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                      ERC721 BALANCE/OWNER STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) internal _ownerOf;

    mapping(address => uint256) internal _balanceOf;

    function ownerOf(uint256 id) public view virtual returns (address owner) {
        require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
    }

    function balanceOf(address owner) public view virtual returns (uint256) {
        require(owner != address(0), "ZERO_ADDRESS");

        return _balanceOf[owner];
    }

    /*//////////////////////////////////////////////////////////////
                         ERC721 APPROVAL STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) public getApproved;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*//////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 id) public virtual {
        address owner = _ownerOf[id];

        require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");

        getApproved[id] = spender;

        emit Approval(owner, spender, id);
    }

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        require(from == _ownerOf[id], "WRONG_FROM");

        require(to != address(0), "INVALID_RECIPIENT");

        require(
            msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],
            "NOT_AUTHORIZED"
        );

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        unchecked {
            _balanceOf[from]--;

            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        delete getApproved[id];

        emit Transfer(from, to, id);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes calldata data
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 id) internal virtual {
        require(to != address(0), "INVALID_RECIPIENT");

        require(_ownerOf[id] == address(0), "ALREADY_MINTED");

        // Counter overflow is incredibly unrealistic.
        unchecked {
            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        emit Transfer(address(0), to, id);
    }

    function _burn(uint256 id) internal virtual {
        address owner = _ownerOf[id];

        require(owner != address(0), "NOT_MINTED");

        // Ownership check above ensures no underflow.
        unchecked {
            _balanceOf[owner]--;
        }

        delete _ownerOf[id];

        delete getApproved[id];

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

    /*//////////////////////////////////////////////////////////////
                        INTERNAL SAFE MINT LOGIC
    //////////////////////////////////////////////////////////////*/

    function _safeMint(address to, uint256 id) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _safeMint(
        address to,
        uint256 id,
        bytes memory data
    ) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }
}

/// @notice A generic interface for a contract which properly accepts ERC721 tokens.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721TokenReceiver {
    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC721TokenReceiver.onERC721Received.selector;
    }
}

interface IOperatorFilterRegistry {
    function isOperatorAllowed(address registrant, address operator) external view returns (bool);
    function register(address registrant) external;
    function registerAndSubscribe(address registrant, address subscription) external;
    function registerAndCopyEntries(address registrant, address registrantToCopy) external;
    function unregister(address addr) external;
    function updateOperator(address registrant, address operator, bool filtered) external;
    function updateOperators(address registrant, address[] calldata operators, bool filtered) external;
    function updateCodeHash(address registrant, bytes32 codehash, bool filtered) external;
    function updateCodeHashes(address registrant, bytes32[] calldata codeHashes, bool filtered) external;
    function subscribe(address registrant, address registrantToSubscribe) external;
    function unsubscribe(address registrant, bool copyExistingEntries) external;
    function subscriptionOf(address addr) external returns (address registrant);
    function subscribers(address registrant) external returns (address[] memory);
    function subscriberAt(address registrant, uint256 index) external returns (address);
    function copyEntriesOf(address registrant, address registrantToCopy) external;
    function isOperatorFiltered(address registrant, address operator) external returns (bool);
    function isCodeHashOfFiltered(address registrant, address operatorWithCode) external returns (bool);
    function isCodeHashFiltered(address registrant, bytes32 codeHash) external returns (bool);
    function filteredOperators(address addr) external returns (address[] memory);
    function filteredCodeHashes(address addr) external returns (bytes32[] memory);
    function filteredOperatorAt(address registrant, uint256 index) external returns (address);
    function filteredCodeHashAt(address registrant, uint256 index) external returns (bytes32);
    function isRegistered(address addr) external returns (bool);
    function codeHashOf(address addr) external returns (bytes32);
}

/**
 * @title  OperatorFilterer
 * @notice Abstract contract whose constructor automatically registers and optionally subscribes to or copies another
 *         registrant's entries in the OperatorFilterRegistry.
 * @dev    This smart contract is meant to be inherited by token contracts so they can use the following:
 *         - `onlyAllowedOperator` modifier for `transferFrom` and `safeTransferFrom` methods.
 *         - `onlyAllowedOperatorApproval` modifier for `approve` and `setApprovalForAll` methods.
 */
abstract contract OperatorFilterer {
    error OperatorNotAllowed(address operator);

    IOperatorFilterRegistry public constant OPERATOR_FILTER_REGISTRY =
        IOperatorFilterRegistry(0x000000000000AAeB6D7670E522A718067333cd4E);

    constructor(address subscriptionOrRegistrantToCopy, bool subscribe) {
        // If an inheriting token contract is deployed to a network without the registry deployed, the modifier
        // will not revert, but the contract will need to be registered with the registry once it is deployed in
        // order for the modifier to filter addresses.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            if (subscribe) {
                OPERATOR_FILTER_REGISTRY.registerAndSubscribe(address(this), subscriptionOrRegistrantToCopy);
            } else {
                if (subscriptionOrRegistrantToCopy != address(0)) {
                    OPERATOR_FILTER_REGISTRY.registerAndCopyEntries(address(this), subscriptionOrRegistrantToCopy);
                } else {
                    OPERATOR_FILTER_REGISTRY.register(address(this));
                }
            }
        }
    }

    modifier onlyAllowedOperator(address from) virtual {
        // Allow spending tokens from addresses with balance
        // Note that this still allows listings and marketplaces with escrow to transfer tokens if transferred
        // from an EOA.
        if (from != msg.sender) {
            _checkFilterOperator(msg.sender);
        }
        _;
    }

    modifier onlyAllowedOperatorApproval(address operator) virtual {
        _checkFilterOperator(operator);
        _;
    }

    function _checkFilterOperator(address operator) internal view virtual {
        // Check registry code length to facilitate testing in environments without a deployed registry.
        if (address(OPERATOR_FILTER_REGISTRY).code.length > 0) {
            if (!OPERATOR_FILTER_REGISTRY.isOperatorAllowed(address(this), operator)) {
                revert OperatorNotAllowed(operator);
            }
        }
    }
}

/**
 * @title  DefaultOperatorFilterer
 * @notice Inherits from OperatorFilterer and automatically subscribes to the default OpenSea subscription.
 */
abstract contract DefaultOperatorFilterer is OperatorFilterer {
    address constant DEFAULT_SUBSCRIPTION = address(0x3cc6CddA760b79bAfa08dF41ECFA224f810dCeB6);

    constructor() OperatorFilterer(DEFAULT_SUBSCRIPTION, true) {}
}

abstract contract OperatorFilteredERC721 is ERC721, DefaultOperatorFilterer {

    constructor(
        string memory name_,
        string memory symbol_
    ) ERC721(name_, symbol_) {}

    // overrides for DefaultOperatorFilterer, which enables creator fees on opensea

    function setApprovalForAll(address operator, bool approved) public override onlyAllowedOperatorApproval(operator) {
        super.setApprovalForAll(operator, approved);
    }

    function approve(address operator, uint256 tokenId) public override onlyAllowedOperatorApproval(operator) {
        super.approve(operator, tokenId);
    }

    function transferFrom(address from, address to, uint256 tokenId) public override onlyAllowedOperator(from) {
        super.transferFrom(from, to, tokenId);
    }

    function safeTransferFrom(address from, address to, uint256 tokenId) public override onlyAllowedOperator(from) {
        super.safeTransferFrom(from, to, tokenId);
    }

    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data)
        public
        override
        onlyAllowedOperator(from)
    {
        super.safeTransferFrom(from, to, tokenId, data);
    }
}

enum PruneDegrees {NONE, LOW, MEDIUM, HIGH}

enum HealthStatus {OK, DRY, DEAD}

struct BonsaiProfile {
    uint256 modifiedSteps;

    uint64 adjustedStartTime;
    uint64 ratio;
    uint32 seed;
    uint8 trunkSVGNumber;

    uint64 lastWatered;
}

struct WateringStatus {
    uint64 lastWatered; 
    HealthStatus healthStatus;
    string status;
}

struct Vars {
    uint256 layer;
    uint256 strokeWidth;
    bytes32[12] gradients;
}

struct RawAttributes {
    bytes32 backgroundColor;
    bytes32 blossomColor;
    bytes32 wateringStatus;

    uint32 seed;
    uint64 ratio;
    uint64 adjustedStartTime;
    uint64 lastWatered;
    uint8 trunkSVGNumber;
    HealthStatus healthStatus;

    uint256[] modifiedSteps;
}

interface IBonsaiRenderer {
    function numTrunks() external view returns(uint256);
    function renderForHumans(uint256 tokenId) external view returns(string memory);
    function renderForRobots(uint256 tokenId) external view returns(RawAttributes memory);
}

interface IBonsaiState {
    function getBonsaiProfile(uint256 tokenId) external view returns(BonsaiProfile memory);
    function initializeBonsai(uint256 tokenId, bool mayBeBot) external;
    function water(uint256 tokenId) external returns(WateringStatus memory);
    function wateringStatus(uint256 tokenId) external view returns(WateringStatus memory);
    function wateringStatusForRender(uint64 lastWatered, uint64 adjustedStartTime, bool watering) external view returns(WateringStatus memory ws);
    function prune(uint256 tokenId, PruneDegrees degree) external;
}

/// @notice Library to encode strings in Base64.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Base64.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Base64.sol)
/// @author Modified from (https://github.com/Brechtpd/base64/blob/main/base64.sol) by Brecht Devos - <[email protected]>.
library Base64 {
    /// @dev Encodes `data` using the base64 encoding described in RFC 4648.
    /// See: https://datatracker.ietf.org/doc/html/rfc4648
    /// @param fileSafe  Whether to replace '+' with '-' and '/' with '_'.
    /// @param noPadding Whether to strip away the padding.
    function encode(bytes memory data, bool fileSafe, bool noPadding)
        internal
        pure
        returns (string memory result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let dataLength := mload(data)

            if dataLength {
                // Multiply by 4/3 rounded up.
                // The `shl(2, ...)` is equivalent to multiplying by 4.
                let encodedLength := shl(2, div(add(dataLength, 2), 3))

                // Set `result` to point to the start of the free memory.
                result := mload(0x40)

                // Store the table into the scratch space.
                // Offsetted by -1 byte so that the `mload` will load the character.
                // We will rewrite the free memory pointer at `0x40` later with
                // the allocated size.
                // The magic constant 0x0230 will translate "-_" + "+/".
                mstore(0x1f, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef")
                mstore(0x3f, sub("ghijklmnopqrstuvwxyz0123456789-_", mul(iszero(fileSafe), 0x0230)))

                // Skip the first slot, which stores the length.
                let ptr := add(result, 0x20)
                let end := add(ptr, encodedLength)

                // Run over the input, 3 bytes at a time.
                for {} 1 {} {
                    data := add(data, 3) // Advance 3 bytes.
                    let input := mload(data)

                    // Write 4 bytes. Optimized for fewer stack operations.
                    mstore8(ptr, mload(and(shr(18, input), 0x3F)))
                    mstore8(add(ptr, 1), mload(and(shr(12, input), 0x3F)))
                    mstore8(add(ptr, 2), mload(and(shr(6, input), 0x3F)))
                    mstore8(add(ptr, 3), mload(and(input, 0x3F)))

                    ptr := add(ptr, 4) // Advance 4 bytes.

                    if iszero(lt(ptr, end)) { break }
                }

                let r := mod(dataLength, 3)

                switch noPadding
                case 0 {
                    // Offset `ptr` and pad with '='. We can simply write over the end.
                    mstore8(sub(ptr, iszero(iszero(r))), 0x3d) // Pad at `ptr - 1` if `r > 0`.
                    mstore8(sub(ptr, shl(1, eq(r, 1))), 0x3d) // Pad at `ptr - 2` if `r == 1`.
                    // Write the length of the string.
                    mstore(result, encodedLength)
                }
                default {
                    // Write the length of the string.
                    mstore(result, sub(encodedLength, add(iszero(iszero(r)), eq(r, 1))))
                }

                // Allocate the memory for the string.
                // Add 31 and mask with `not(31)` to round the
                // free memory pointer up the next multiple of 32.
                mstore(0x40, and(add(end, 31), not(31)))
            }
        }
    }

    /// @dev Encodes `data` using the base64 encoding described in RFC 4648.
    /// Equivalent to `encode(data, false, false)`.
    function encode(bytes memory data) internal pure returns (string memory result) {
        result = encode(data, false, false);
    }

    /// @dev Encodes `data` using the base64 encoding described in RFC 4648.
    /// Equivalent to `encode(data, fileSafe, false)`.
    function encode(bytes memory data, bool fileSafe)
        internal
        pure
        returns (string memory result)
    {
        result = encode(data, fileSafe, false);
    }

    /// @dev Encodes base64 encoded `data`.
    ///
    /// Supports:
    /// - RFC 4648 (both standard and file-safe mode).
    /// - RFC 3501 (63: ',').
    ///
    /// Does not support:
    /// - Line breaks.
    ///
    /// Note: For performance reasons,
    /// this function will NOT revert on invalid `data` inputs.
    /// Outputs for invalid inputs will simply be undefined behaviour.
    /// It is the user's responsibility to ensure that the `data`
    /// is a valid base64 encoded string.
    function decode(string memory data) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            let dataLength := mload(data)

            if dataLength {
                let end := add(data, dataLength)
                let decodedLength := mul(shr(2, dataLength), 3)

                switch and(dataLength, 3)
                case 0 {
                    // If padded.
                    // forgefmt: disable-next-item
                    decodedLength := sub(
                        decodedLength,
                        add(eq(and(mload(end), 0xFF), 0x3d), eq(and(mload(end), 0xFFFF), 0x3d3d))
                    )
                }
                default {
                    // If non-padded.
                    decodedLength := add(decodedLength, sub(and(dataLength, 3), 1))
                }

                result := mload(0x40)

                // Write the length of the string.
                mstore(result, decodedLength)

                // Skip the first slot, which stores the length.
                let ptr := add(result, 0x20)

                // Load the table into the scratch space.
                // Constants are optimized for smaller bytecode with zero gas overhead.
                // `m` also doubles as the mask of the upper 6 bits.
                let m := 0xfc000000fc00686c7074787c8084888c9094989ca0a4a8acb0b4b8bcc0c4c8cc
                mstore(0x5b, m)
                mstore(0x3b, 0x04080c1014181c2024282c3034383c4044484c5054585c6064)
                mstore(0x1a, 0xf8fcf800fcd0d4d8dce0e4e8ecf0f4)

                for {} 1 {} {
                    // Read 4 bytes.
                    data := add(data, 4)
                    let input := mload(data)

                    // Write 3 bytes.
                    // forgefmt: disable-next-item
                    mstore(ptr, or(
                        and(m, mload(byte(28, input))),
                        shr(6, or(
                            and(m, mload(byte(29, input))),
                            shr(6, or(
                                and(m, mload(byte(30, input))),
                                shr(6, mload(byte(31, input)))
                            ))
                        ))
                    ))

                    ptr := add(ptr, 3)

                    if iszero(lt(data, end)) { break }
                }

                // Allocate the memory for the string.
                // Add 32 + 31 and mask with `not(31)` to round the
                // free memory pointer up the next multiple of 32.
                mstore(0x40, and(add(add(result, decodedLength), 63), not(31)))

                // Restore the zero slot.
                mstore(0x60, 0)
            }
        }
    }
}

// OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol)

// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)

// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

/**
 * @dev Interface for the NFT Royalty Standard.
 *
 * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
 * support for royalty payments across all NFT marketplaces and ecosystem participants.
 *
 * _Available since v4.5._
 */
interface IERC2981 is IERC165 {
    /**
     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount);
}

// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

/**
 * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
 *
 * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
 * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
 *
 * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
 * fee is specified in basis points by default.
 *
 * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
 * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
 * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
 *
 * _Available since v4.5._
 */
abstract contract ERC2981 is IERC2981, ERC165 {
    struct RoyaltyInfo {
        address receiver;
        uint96 royaltyFraction;
    }

    RoyaltyInfo private _defaultRoyaltyInfo;
    mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
        return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @inheritdoc IERC2981
     */
    function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) {
        RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];

        if (royalty.receiver == address(0)) {
            royalty = _defaultRoyaltyInfo;
        }

        uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator();

        return (royalty.receiver, royaltyAmount);
    }

    /**
     * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
     * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
     * override.
     */
    function _feeDenominator() internal pure virtual returns (uint96) {
        return 10000;
    }

    /**
     * @dev Sets the royalty information that all ids in this contract will default to.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
        require(receiver != address(0), "ERC2981: invalid receiver");

        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Removes default royalty information.
     */
    function _deleteDefaultRoyalty() internal virtual {
        delete _defaultRoyaltyInfo;
    }

    /**
     * @dev Sets the royalty information for a specific token id, overriding the global default.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setTokenRoyalty(
        uint256 tokenId,
        address receiver,
        uint96 feeNumerator
    ) internal virtual {
        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
        require(receiver != address(0), "ERC2981: Invalid parameters");

        _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Resets royalty information for the token id back to the global default.
     */
    function _resetTokenRoyalty(uint256 tokenId) internal virtual {
        delete _tokenRoyaltyInfo[tokenId];
    }
}

// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)

// OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol)

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(
        uint256 x,
        uint256 y,
        uint256 denominator,
        Rounding rounding
    ) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10**64) {
                value /= 10**64;
                result += 64;
            }
            if (value >= 10**32) {
                value /= 10**32;
                result += 32;
            }
            if (value >= 10**16) {
                value /= 10**16;
                result += 16;
            }
            if (value >= 10**8) {
                value /= 10**8;
                result += 8;
            }
            if (value >= 10**4) {
                value /= 10**4;
                result += 4;
            }
            if (value >= 10**2) {
                value /= 10**2;
                result += 2;
            }
            if (value >= 10**1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

/// @notice Read and write to persistent storage at a fraction of the cost.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SSTORE2.sol)
/// @author Modified from 0xSequence (https://github.com/0xSequence/sstore2/blob/master/contracts/SSTORE2.sol)
library SSTORE2 {
    uint256 internal constant DATA_OFFSET = 1; // We skip the first byte as it's a STOP opcode to ensure the contract can't be called.

    /*//////////////////////////////////////////////////////////////
                               WRITE LOGIC
    //////////////////////////////////////////////////////////////*/

    function write(bytes memory data) internal returns (address pointer) {
        // Prefix the bytecode with a STOP opcode to ensure it cannot be called.
        bytes memory runtimeCode = abi.encodePacked(hex"00", data);

        bytes memory creationCode = abi.encodePacked(
            //---------------------------------------------------------------------------------------------------------------//
            // Opcode  | Opcode + Arguments  | Description  | Stack View                                                     //
            //---------------------------------------------------------------------------------------------------------------//
            // 0x60    |  0x600B             | PUSH1 11     | codeOffset                                                     //
            // 0x59    |  0x59               | MSIZE        | 0 codeOffset                                                   //
            // 0x81    |  0x81               | DUP2         | codeOffset 0 codeOffset                                        //
            // 0x38    |  0x38               | CODESIZE     | codeSize codeOffset 0 codeOffset                               //
            // 0x03    |  0x03               | SUB          | (codeSize - codeOffset) 0 codeOffset                           //
            // 0x80    |  0x80               | DUP          | (codeSize - codeOffset) (codeSize - codeOffset) 0 codeOffset   //
            // 0x92    |  0x92               | SWAP3        | codeOffset (codeSize - codeOffset) 0 (codeSize - codeOffset)   //
            // 0x59    |  0x59               | MSIZE        | 0 codeOffset (codeSize - codeOffset) 0 (codeSize - codeOffset) //
            // 0x39    |  0x39               | CODECOPY     | 0 (codeSize - codeOffset)                                      //
            // 0xf3    |  0xf3               | RETURN       |                                                                //
            //---------------------------------------------------------------------------------------------------------------//
            hex"60_0B_59_81_38_03_80_92_59_39_F3", // Returns all code in the contract except for the first 11 (0B in hex) bytes.
            runtimeCode // The bytecode we want the contract to have after deployment. Capped at 1 byte less than the code size limit.
        );

        /// @solidity memory-safe-assembly
        assembly {
            // Deploy a new contract with the generated creation code.
            // We start 32 bytes into the code to avoid copying the byte length.
            pointer := create(0, add(creationCode, 32), mload(creationCode))
        }

        require(pointer != address(0), "DEPLOYMENT_FAILED");
    }

    /*//////////////////////////////////////////////////////////////
                               READ LOGIC
    //////////////////////////////////////////////////////////////*/

    function read(address pointer) internal view returns (bytes memory) {
        return readBytecode(pointer, DATA_OFFSET, pointer.code.length - DATA_OFFSET);
    }

    function read(address pointer, uint256 start) internal view returns (bytes memory) {
        start += DATA_OFFSET;

        return readBytecode(pointer, start, pointer.code.length - start);
    }

    function read(
        address pointer,
        uint256 start,
        uint256 end
    ) internal view returns (bytes memory) {
        start += DATA_OFFSET;
        end += DATA_OFFSET;

        require(pointer.code.length >= end, "OUT_OF_BOUNDS");

        return readBytecode(pointer, start, end - start);
    }

    /*//////////////////////////////////////////////////////////////
                          INTERNAL HELPER LOGIC
    //////////////////////////////////////////////////////////////*/

    function readBytecode(
        address pointer,
        uint256 start,
        uint256 size
    ) private view returns (bytes memory data) {
        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            data := mload(0x40)

            // Update the free memory pointer to prevent overriding our data.
            // We use and(x, not(31)) as a cheaper equivalent to sub(x, mod(x, 32)).
            // Adding 31 to size and running the result through the logic above ensures
            // the memory pointer remains word-aligned, following the Solidity convention.
            mstore(0x40, add(data, and(add(add(size, 32), 31), not(31))))

            // Store the size of the data in the first 32 byte chunk of free memory.
            mstore(data, size)

            // Copy the code into memory right after the 32 bytes we used to store the size.
            extcodecopy(pointer, add(data, 32), start, size)
        }
    }
}

abstract contract MarketWares is ERC2981 {

    address public immutable OWNER;
    address public immutable SECURITY_ADVISOR;

    address private _logoPointer;

    constructor(address owner_, address securityAdvisor_) {
        // assumption: admin addresses are auditted contracts or verified to be EOA's
        OWNER = owner_;
        SECURITY_ADVISOR = securityAdvisor_;

        _setDefaultRoyalty(OWNER, 100); // ERC2981 1% royalty on secondary sales
    }
      
    // needed for opensea
    function contractURI() public view returns(string memory) {
        return string(abi.encodePacked(
                  "data:application/json;base64,", 
                  Base64.encode(abi.encodePacked("{\"name\": \"bonSAI\","
                       " \"description\": \"Limited, generative art collection living entirely 'in-chain'.\","
                       " \"image\": \"", 
                       "data:image/svg+xml;base64,",
                       Base64.encode(SSTORE2.read(_logoPointer)), 
                       "\",",
                       " \"seller_fee_basis_points:\": \"100\","
                       " \"fee_recipient\": \"", Strings.toHexString(OWNER) ,"\"}"))));
    }

    function sendETH() external {
        // assumption: admin addresses are auditted contracts or verified to be EOA's
        (bool success,) = SECURITY_ADVISOR.call{value: address(this).balance/10}("");
        require(success, "call0: breaks EOA assumption.");
        (success,) = OWNER.call{value: address(this).balance}("");
        require(success, "call1: breaks EOA assumption.");
    }

    function setLogo(string memory logo) external {
        require(msg.sender == OWNER, "not owner.");
        _logoPointer = SSTORE2.write(bytes(logo));
    }
}

contract BonsaiMaker is OperatorFilteredERC721, MarketWares {

    uint256 constant public PRICE_PER_TOKEN = 0.0721 ether;
    uint256 constant public MAX_TOKENS = 10_000;
    uint256 constant public MAX_QTY = 70;
    uint256 constant public FREE_MINT = 100;

    uint256 constant public PRUNE_COST_PER_DEGREE = PRICE_PER_TOKEN / 4; 

    uint256 public totalSupply;

    IBonsaiState public bonsaiState;
    IBonsaiRenderer public bonsaiRenderer;

    mapping(address => uint256) private _freeMintedTime;
    mapping(address => uint256) private _numMinted;

    constructor(
        address owner_, 
        // security advisement was provided by Nomoi Web3 Hacker Collective, nomoi.xyz
        address securityAdvisor_, 
        address bonsaiState_,
        address bonsaiRenderer_
    ) OperatorFilteredERC721("BonSAIMaker", "bMKR") MarketWares(owner_, securityAdvisor_) { // see `MarketWares` for royalty stuffs

        bonsaiState = IBonsaiState(bonsaiState_);
        bonsaiRenderer = IBonsaiRenderer(bonsaiRenderer_);
    }

    function _mayBeBot() internal view returns(bool) {
        return tx.origin != msg.sender;
    }

    // minting

    function mintFree(address to) external returns(uint256 tokenId) {
        unchecked{
        if (msg.sender != OWNER) {
            require(!_mayBeBot(), "no freebies for bots.");
            require(totalSupply < FREE_MINT, "no more free mints.");
            require(block.timestamp > _freeMintedTime[tx.origin] + 1 days, "1 free mint /EOA /day.");
            _freeMintedTime[msg.sender] = block.timestamp; // since !_mayBeBot
        }
        tokenId = ++totalSupply;
        _mint(to, tokenId);
        bonsaiState.initializeBonsai({tokenId: tokenId, mayBeBot: false});
        }//uc
    }

    function mint(address to) external payable returns(uint256 lastTokenId) {
        unchecked{
        require(msg.value % PRICE_PER_TOKEN == 0, "msg.value != n * price.");
        uint256 qty = msg.value / PRICE_PER_TOKEN;
        require(qty > 0, "call mint with n * PRICE_PER_TOKEN.");
        require(_numMinted[msg.sender] + qty <= MAX_QTY, "minting too many.");
        _numMinted[msg.sender] += qty;
        uint256 tokenId = totalSupply;
        require(tokenId + qty <= MAX_TOKENS, "new tokens exceed max.");

        bool mayBeBot = _mayBeBot(); // bots ok but they get limited options
        for (uint256 i; i < qty; ++i) {
            _mint(to, ++tokenId); 
            bonsaiState.initializeBonsai(tokenId, mayBeBot);
        }
        lastTokenId = tokenId;
        totalSupply = lastTokenId;
        }//uc
    }

    // enjoyment

    // viewing

    function tokenURI(uint256 tokenId) public view override returns(string memory) {
        require(_ownerOf[tokenId] != address(0), "Bonsai dne.");
        return bonsaiRenderer.renderForHumans(tokenId);
    }

    function tokenURIForRobots(uint256 tokenId) public view returns(RawAttributes memory) {
        require(_ownerOf[tokenId] != address(0), "Bonsai dne.");
        return bonsaiRenderer.renderForRobots(tokenId);
    }

    // bonsai care

    // watering

    event Watered(uint256 indexed tokenId, string indexed status);

    // anyone can water :)
    function water(uint256 tokenId) external returns(WateringStatus memory ws) {
        require(_ownerOf[tokenId] != address(0), "Bonsai dne.");
        ws = bonsaiState.water(tokenId);    
        emit Watered(tokenId, ws.status);
    }

    function wateringStatus(uint256 tokenId) external view returns(WateringStatus memory) {
        require(_ownerOf[tokenId] != address(0), "Bonsai dne.");
        return bonsaiState.wateringStatus(tokenId);
    }

    // pruning

    event Pruned(uint256 indexed tokenId, PruneDegrees indexed degree);

    function prune(uint256 tokenId) external payable {
        require(msg.sender == _ownerOf[tokenId], "you don't mow another man's lawn.");
        require(msg.value % PRUNE_COST_PER_DEGREE == 0, "incongruent pruning payment.");
        uint256 degreeNumber = (msg.value / PRUNE_COST_PER_DEGREE);
        require(degreeNumber > 0, "call prune with value n * PRUNE_COST_PER_DEGREE.");
        require(degreeNumber < 4, "max prune degree is 3 (HIGH)");
        PruneDegrees degree = PruneDegrees(degreeNumber);
        bonsaiState.prune(tokenId, degree);
        emit Pruned(tokenId, degree);
    }

    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721, ERC2981) returns (bool) {
        return interfaceId == type(IERC2981).interfaceId || 
               interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
               interfaceId == 0x5b5e139f || // ERC165 Interface ID for ERC721Metadata
               super.supportsInterface(interfaceId);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"securityAdvisor_","type":"address"},{"internalType":"address","name":"bonsaiState_","type":"address"},{"internalType":"address","name":"bonsaiRenderer_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","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":"tokenId","type":"uint256"},{"indexed":true,"internalType":"enum PruneDegrees","name":"degree","type":"uint8"}],"name":"Pruned","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":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"string","name":"status","type":"string"}],"name":"Watered","type":"event"},{"inputs":[],"name":"FREE_MINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_QTY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_FILTER_REGISTRY","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OWNER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_PER_TOKEN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRUNE_COST_PER_DEGREE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SECURITY_ADVISOR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","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":[],"name":"bonsaiRenderer","outputs":[{"internalType":"contract IBonsaiRenderer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bonsaiState","outputs":[{"internalType":"contract IBonsaiState","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"lastTokenId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mintFree","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"prune","outputs":[],"stateMutability":"payable","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":[],"name":"sendETH","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":"string","name":"logo","type":"string"}],"name":"setLogo","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":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURIForRobots","outputs":[{"components":[{"internalType":"bytes32","name":"backgroundColor","type":"bytes32"},{"internalType":"bytes32","name":"blossomColor","type":"bytes32"},{"internalType":"bytes32","name":"wateringStatus","type":"bytes32"},{"internalType":"uint32","name":"seed","type":"uint32"},{"internalType":"uint64","name":"ratio","type":"uint64"},{"internalType":"uint64","name":"adjustedStartTime","type":"uint64"},{"internalType":"uint64","name":"lastWatered","type":"uint64"},{"internalType":"uint8","name":"trunkSVGNumber","type":"uint8"},{"internalType":"enum HealthStatus","name":"healthStatus","type":"uint8"},{"internalType":"uint256[]","name":"modifiedSteps","type":"uint256[]"}],"internalType":"struct RawAttributes","name":"","type":"tuple"}],"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":"uint256","name":"tokenId","type":"uint256"}],"name":"water","outputs":[{"components":[{"internalType":"uint64","name":"lastWatered","type":"uint64"},{"internalType":"enum HealthStatus","name":"healthStatus","type":"uint8"},{"internalType":"string","name":"status","type":"string"}],"internalType":"struct WateringStatus","name":"ws","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"wateringStatus","outputs":[{"components":[{"internalType":"uint64","name":"lastWatered","type":"uint64"},{"internalType":"enum HealthStatus","name":"healthStatus","type":"uint8"},{"internalType":"string","name":"status","type":"string"}],"internalType":"struct WateringStatus","name":"","type":"tuple"}],"stateMutability":"view","type":"function"}]

60c06040523480156200001157600080fd5b506040516200322138038062003221833981016040819052620000349162000378565b83836040518060400160405280600b81526020016a2137b729a0a4a6b0b5b2b960a91b815250604051806040016040528060048152602001633126a5a960e11b815250733cc6cdda760b79bafa08df41ecfa224f810dceb6600183838160009081620000a191906200047a565b506001620000b082826200047a565b5050506daaeb6d7670e522a718067333cd4e3b15620001f85780156200014657604051633e9f1edf60e11b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e90637d3e3dbe906044015b600060405180830381600087803b1580156200012757600080fd5b505af11580156200013c573d6000803e3d6000fd5b50505050620001f8565b6001600160a01b03821615620001975760405163a0af290360e01b81523060048201526001600160a01b03831660248201526daaeb6d7670e522a718067333cd4e9063a0af2903906044016200010c565b604051632210724360e11b81523060048201526daaeb6d7670e522a718067333cd4e90634420e48690602401600060405180830381600087803b158015620001de57600080fd5b505af1158015620001f3573d6000803e3d6000fd5b505050505b5050506001600160a01b03808416608081905290831660a0526200021f9150606462000256565b5050600a80546001600160a01b039384166001600160a01b031991821617909155600b805492909316911617905550620005469050565b6127106001600160601b0382161115620002ca5760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b60648201526084015b60405180910390fd5b6001600160a01b038216620003225760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c6964207265636569766572000000000000006044820152606401620002c1565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600655565b80516001600160a01b03811681146200037357600080fd5b919050565b600080600080608085870312156200038f57600080fd5b6200039a856200035b565b9350620003aa602086016200035b565b9250620003ba604086016200035b565b9150620003ca606086016200035b565b905092959194509250565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200040057607f821691505b6020821081036200042157634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200047557600081815260208120601f850160051c81016020861015620004505750805b601f850160051c820191505b8181101562000471578281556001016200045c565b5050505b505050565b81516001600160401b03811115620004965762000496620003d5565b620004ae81620004a78454620003eb565b8462000427565b602080601f831160018114620004e65760008415620004cd5750858301515b600019600386901b1c1916600185901b17855562000471565b600085815260208120601f198616915b828110156200051757888601518255948401946001909101908401620004f6565b5085821015620005365787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a051612c926200058f6000396000818161056001526108670152600081816103240152818161093101528181610aca0152818161137801526115450152612c926000f3fe6080604052600436106101f95760003560e01c80635e2893dd1161010d578063a22cb465116100a0578063db065b1d1161006f578063db065b1d14610602578063e55fcf2d14610617578063e8a3d48514610637578063e985e9c51461064c578063f47c84c51461068757600080fd5b8063a22cb46514610582578063a7eec44b146105a2578063b88d4fde146105c2578063c87b56dd146105e257600080fd5b8063784eb67d116100dc578063784eb67d146104f0578063833b94991461051d57806395d89b41146105395780639621026e1461054e57600080fd5b80635e2893dd1461048a5780636352211e1461049d5780636a627842146104bd57806370a08231146104d057600080fd5b80631c96cae9116101905780632fe319621161015f5780632fe31962146103f357806333043dbf1461041357806341f434341461043357806342842e0e1461045557806347bf8d311461047557600080fd5b80631c96cae91461036a5780631d16d9a01461037f57806323b872dd146103945780632a55205a146103b457600080fd5b806309a1f9c6116101cc57806309a1f9c6146102c557806310414d6d146102e5578063117803e31461031257806318160ddd1461034657600080fd5b806301ffc9a7146101fe57806306fdde0314610233578063081812fc14610255578063095ea7b3146102a3575b600080fd5b34801561020a57600080fd5b5061021e6102193660046120ce565b61069d565b60405190151581526020015b60405180910390f35b34801561023f57600080fd5b506102486106fe565b60405161022a919061213b565b34801561026157600080fd5b5061028b61027036600461214e565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161022a565b3480156102af57600080fd5b506102c36102be36600461217e565b61078c565b005b3480156102d157600080fd5b50600a5461028b906001600160a01b031681565b3480156102f157600080fd5b5061030561030036600461214e565b6107a5565b60405161022a919061220d565b34801561031e57600080fd5b5061028b7f000000000000000000000000000000000000000000000000000000000000000081565b34801561035257600080fd5b5061035c60095481565b60405190815260200161022a565b34801561037657600080fd5b5061035c604681565b34801561038b57600080fd5b506102c361085b565b3480156103a057600080fd5b506102c36103af3660046122d1565b6109e8565b3480156103c057600080fd5b506103d46103cf36600461230d565b610a13565b604080516001600160a01b03909316835260208301919091520161022a565b3480156103ff57600080fd5b506102c361040e3660046123c5565b610abf565b34801561041f57600080fd5b50600b5461028b906001600160a01b031681565b34801561043f57600080fd5b5061028b6daaeb6d7670e522a718067333cd4e81565b34801561046157600080fd5b506102c36104703660046122d1565b610b50565b34801561048157600080fd5b5061035c610b75565b6102c361049836600461214e565b610b8b565b3480156104a957600080fd5b5061028b6104b836600461214e565b610dfa565b61035c6104cb366004612444565b610e51565b3480156104dc57600080fd5b5061035c6104eb366004612444565b611069565b3480156104fc57600080fd5b5061051061050b36600461214e565b6110cc565b60405161022a919061245f565b34801561052957600080fd5b5061035c6701002691684e400081565b34801561054557600080fd5b50610248611179565b34801561055a57600080fd5b5061028b7f000000000000000000000000000000000000000000000000000000000000000081565b34801561058e57600080fd5b506102c361059d3660046124ae565b611186565b3480156105ae57600080fd5b506105106105bd36600461214e565b61119a565b3480156105ce57600080fd5b506102c36105dd3660046124e5565b611294565b3480156105ee57600080fd5b506102486105fd36600461214e565b6112c3565b34801561060e57600080fd5b5061035c606481565b34801561062357600080fd5b5061035c610632366004612444565b61136b565b34801561064357600080fd5b5061024861151b565b34801561065857600080fd5b5061021e61066736600461257f565b600560209081526000928352604080842090915290825290205460ff1681565b34801561069357600080fd5b5061035c61271081565b60006001600160e01b0319821663152a902d60e11b14806106ce57506380ac58cd60e01b6001600160e01b03198316145b806106e95750635b5e139f60e01b6001600160e01b03198316145b806106f857506106f8826115b2565b92915050565b6000805461070b906125b2565b80601f0160208091040260200160405190810160405280929190818152602001828054610737906125b2565b80156107845780601f1061075957610100808354040283529160200191610784565b820191906000526020600020905b81548152906001019060200180831161076757829003601f168201915b505050505081565b81610796816115e7565b6107a083836116a0565b505050565b6107ad612049565b6000828152600260205260409020546001600160a01b03166107ea5760405162461bcd60e51b81526004016107e1906125ec565b60405180910390fd5b600b5460405163aaf1e61160e01b8152600481018490526001600160a01b039091169063aaf1e61190602401600060405180830381865afa158015610833573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106f891908101906126db565b60006001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016610892600a476127fd565b604051600081818185875af1925050503d80600081146108ce576040519150601f19603f3d011682016040523d82523d6000602084013e6108d3565b606091505b50509050806109245760405162461bcd60e51b815260206004820152601d60248201527f63616c6c303a20627265616b7320454f4120617373756d7074696f6e2e00000060448201526064016107e1565b6040516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016904790600081818185875af1925050503d806000811461098d576040519150601f19603f3d011682016040523d82523d6000602084013e610992565b606091505b505080915050806109e55760405162461bcd60e51b815260206004820152601d60248201527f63616c6c313a20627265616b7320454f4120617373756d7074696f6e2e00000060448201526064016107e1565b50565b826001600160a01b0381163314610a0257610a02336115e7565b610a0d848484611782565b50505050565b60008281526007602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092528291610a885750604080518082019091526006546001600160a01b0381168252600160a01b90046001600160601b031660208201525b602081015160009061271090610aa7906001600160601b031687612811565b610ab191906127fd565b915196919550909350505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b245760405162461bcd60e51b815260206004820152600a6024820152693737ba1037bbb732b91760b11b60448201526064016107e1565b610b2d81611949565b600880546001600160a01b0319166001600160a01b039290921691909117905550565b826001600160a01b0381163314610b6a57610b6a336115e7565b610a0d8484846119ee565b610b8860046701002691684e40006127fd565b81565b6000818152600260205260409020546001600160a01b03163314610bfb5760405162461bcd60e51b815260206004820152602160248201527f796f7520646f6e2774206d6f7720616e6f74686572206d616e2773206c61776e6044820152601760f91b60648201526084016107e1565b610c0e60046701002691684e40006127fd565b610c189034612828565b15610c655760405162461bcd60e51b815260206004820152601c60248201527f696e636f6e677275656e74207072756e696e67207061796d656e742e0000000060448201526064016107e1565b6000610c7a60046701002691684e40006127fd565b610c8490346127fd565b905060008111610cef5760405162461bcd60e51b815260206004820152603060248201527f63616c6c207072756e6520776974682076616c7565206e202a205052554e455f60448201526f21a7a9aa2fa822a92fa222a3a922a29760811b60648201526084016107e1565b60048110610d3f5760405162461bcd60e51b815260206004820152601c60248201527f6d6178207072756e65206465677265652069732033202848494748290000000060448201526064016107e1565b6000816003811115610d5357610d536121a8565b600a54604051630320f0dd60e61b81529192506001600160a01b03169063c83c374090610d86908690859060040161283c565b600060405180830381600087803b158015610da057600080fd5b505af1158015610db4573d6000803e3d6000fd5b50505050806003811115610dca57610dca6121a8565b60405184907fbb9360aa013e49a3091c9b89863774bc1ba5d5b25bc14fc6d17c8a27b0e021de90600090a3505050565b6000818152600260205260409020546001600160a01b031680610e4c5760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b60448201526064016107e1565b919050565b60006701002691684e4000340615610eab5760405162461bcd60e51b815260206004820152601760248201527f6d73672e76616c756520213d206e202a2070726963652e00000000000000000060448201526064016107e1565b6701002691684e4000340480610f0f5760405162461bcd60e51b815260206004820152602360248201527f63616c6c206d696e742077697468206e202a2050524943455f5045525f544f4b60448201526222a71760e91b60648201526084016107e1565b336000908152600d602052604090205460469082011115610f665760405162461bcd60e51b815260206004820152601160248201527036b4b73a34b733903a37b79036b0b73c9760791b60448201526064016107e1565b336000908152600d602052604090208054820190556009546127108183011115610fcb5760405162461bcd60e51b81526020600482015260166024820152753732bb903a37b5b2b7399032bc31b2b2b21036b0bc1760511b60448201526064016107e1565b3233141560005b8381101561105b57610fea8684600101945084611ae1565b600a5460405163d1aa8c6560e01b81526004810185905283151560248201526001600160a01b039091169063d1aa8c6590604401600060405180830381600087803b15801561103857600080fd5b505af115801561104c573d6000803e3d6000fd5b50505050806001019050610fd2565b505060098190559392505050565b60006001600160a01b0382166110b05760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b60448201526064016107e1565b506001600160a01b031660009081526003602052604090205490565b6110d461209e565b6000828152600260205260409020546001600160a01b03166111085760405162461bcd60e51b81526004016107e1906125ec565b600a5460405163784eb67d60e01b8152600481018490526001600160a01b039091169063784eb67d90602401600060405180830381865afa158015611151573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106f891908101906128a5565b6001805461070b906125b2565b81611190816115e7565b6107a08383611bec565b6111a261209e565b6000828152600260205260409020546001600160a01b03166111d65760405162461bcd60e51b81526004016107e1906125ec565b600a5460405163a7eec44b60e01b8152600481018490526001600160a01b039091169063a7eec44b906024016000604051808303816000875af1158015611221573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261124991908101906128a5565b9050806040015160405161125d9190612949565b6040519081900381209083907f45f022ebaef0359458bda97ad02c7e8c572b5705a168151dee77f29fecb2d37690600090a3919050565b846001600160a01b03811633146112ae576112ae336115e7565b6112bb8686868686611c58565b505050505050565b6000818152600260205260409020546060906001600160a01b03166112fa5760405162461bcd60e51b81526004016107e1906125ec565b600b546040516379f2b5cf60e11b8152600481018490526001600160a01b039091169063f3e56b9e90602401600060405180830381865afa158015611343573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106f89190810190612965565b6000336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461149b573332146113e45760405162461bcd60e51b8152602060048201526015602482015274373790333932b2b134b2b9903337b9103137ba399760591b60448201526064016107e1565b60646009541061142c5760405162461bcd60e51b815260206004820152601360248201527237379036b7b93290333932b29036b4b73a399760691b60448201526064016107e1565b326000908152600c6020526040902054620151800142116114885760405162461bcd60e51b81526020600482015260166024820152751890333932b29036b4b73a1017a2a7a09017b230bc9760511b60448201526064016107e1565b336000908152600c602052604090204290555b5060098054600101908190556114b18282611ae1565b600a5460405163d1aa8c6560e01b815260048101839052600060248201526001600160a01b039091169063d1aa8c6590604401600060405180830381600087803b1580156114fe57600080fd5b505af1158015611512573d6000803e3d6000fd5b50505050919050565b60085460609061158e906115409061153b906001600160a01b0316611d40565b611d61565b6115697f0000000000000000000000000000000000000000000000000000000000000000611d6f565b60405160200161157a929190612999565b604051602081830303815290604052611d61565b60405160200161159e9190612adc565b604051602081830303815290604052905090565b60006001600160e01b0319821663152a902d60e11b14806106f857506301ffc9a760e01b6001600160e01b03198316146106f8565b6daaeb6d7670e522a718067333cd4e3b156109e557604051633185c44d60e21b81523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015611654573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116789190612b21565b6109e557604051633b79c77360e21b81526001600160a01b03821660048201526024016107e1565b6000818152600260205260409020546001600160a01b0316338114806116e957506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b6117265760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064016107e1565b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000818152600260205260409020546001600160a01b038481169116146117d85760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b60448201526064016107e1565b6001600160a01b0382166118225760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b60448201526064016107e1565b336001600160a01b038416148061185c57506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b8061187d57506000818152600460205260409020546001600160a01b031633145b6118ba5760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064016107e1565b6001600160a01b0380841660008181526003602090815260408083208054600019019055938616808352848320805460010190558583526002825284832080546001600160a01b03199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6000808260405160200161195d9190612b3e565b60405160208183030381529060405290506000816040516020016119819190612b64565b60405160208183030381529060405290508051602082016000f092506001600160a01b0383166119e75760405162461bcd60e51b81526020600482015260116024820152701111541313d65351539517d19052531151607a1b60448201526064016107e1565b5050919050565b6119f98383836109e8565b6001600160a01b0382163b1580611aa25750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015611a72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a969190612b98565b6001600160e01b031916145b6107a05760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016107e1565b6001600160a01b038216611b2b5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b60448201526064016107e1565b6000818152600260205260409020546001600160a01b031615611b815760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b60448201526064016107e1565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b611c638585856109e8565b6001600160a01b0384163b1580611cfa5750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a0290611cab9033908a90899089908990600401612bb5565b6020604051808303816000875af1158015611cca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cee9190612b98565b6001600160e01b031916145b611d395760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016107e1565b5050505050565b60606106f8826001611d5c816001600160a01b0384163b612c09565b611d85565b60606106f882600080611da8565b60606106f86001600160a01b0383166014611ea7565b60408051603f8301601f19168101909152818152818360208301863c9392505050565b606083518015611e9f576003600282010460021b60405192507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f526102308515027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f03603f52602083018181015b6003880197508751603f8160121c16518353603f81600c1c16516001840153603f8160061c16516002840153603f811651600384015350600482019150808210611e185760038406868015611e7857600182148215150185038752611e90565b603d821515850353603d6001831460011b8503538487525b5050601f01601f191660405250505b509392505050565b60606000611eb6836002612811565b611ec1906002612c1c565b6001600160401b03811115611ed857611ed861232f565b6040519080825280601f01601f191660200182016040528015611f02576020820181803683370190505b509050600360fc1b81600081518110611f1d57611f1d612c2f565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611f4c57611f4c612c2f565b60200101906001600160f81b031916908160001a9053506000611f70846002612811565b611f7b906001612c1c565b90505b6001811115611ff3576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110611faf57611faf612c2f565b1a60f81b828281518110611fc557611fc5612c2f565b60200101906001600160f81b031916908160001a90535060049490941c93611fec81612c45565b9050611f7e565b5083156120425760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016107e1565b9392505050565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052906101008201905b8152602001606081525090565b604080516060810190915260008082526020820190612091565b6001600160e01b0319811681146109e557600080fd5b6000602082840312156120e057600080fd5b8135612042816120b8565b60005b838110156121065781810151838201526020016120ee565b50506000910152565b600081518084526121278160208601602086016120eb565b601f01601f19169290920160200192915050565b602081526000612042602083018461210f565b60006020828403121561216057600080fd5b5035919050565b80356001600160a01b0381168114610e4c57600080fd5b6000806040838503121561219157600080fd5b61219a83612167565b946020939093013593505050565b634e487b7160e01b600052602160045260246000fd5b600381106121ce576121ce6121a8565b9052565b600081518084526020808501945080840160005b83811015612202578151875295820195908201906001016121e6565b509495945050505050565b6020815281516020820152602082015160408201526040820151606082015260006060830151612245608084018263ffffffff169052565b5060808301516001600160401b03811660a08401525060a08301516001600160401b03811660c08401525060c08301516001600160401b03811660e08401525060e083015161010061229b8185018360ff169052565b84015190506101206122af848201836121be565b8401516101408481015290506122c96101608401826121d2565b949350505050565b6000806000606084860312156122e657600080fd5b6122ef84612167565b92506122fd60208501612167565b9150604084013590509250925092565b6000806040838503121561232057600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b60405161014081016001600160401b03811182821017156123685761236861232f565b60405290565b604051601f8201601f191681016001600160401b03811182821017156123965761239661232f565b604052919050565b60006001600160401b038211156123b7576123b761232f565b50601f01601f191660200190565b6000602082840312156123d757600080fd5b81356001600160401b038111156123ed57600080fd5b8201601f810184136123fe57600080fd5b803561241161240c8261239e565b61236e565b81815285602083850101111561242657600080fd5b81602084016020830137600091810160200191909152949350505050565b60006020828403121561245657600080fd5b61204282612167565b602081526001600160401b0382511660208201526000602083015161248760408401826121be565b5060408301516060808401526122c9608084018261210f565b80151581146109e557600080fd5b600080604083850312156124c157600080fd5b6124ca83612167565b915060208301356124da816124a0565b809150509250929050565b6000806000806000608086880312156124fd57600080fd5b61250686612167565b945061251460208701612167565b93506040860135925060608601356001600160401b038082111561253757600080fd5b818801915088601f83011261254b57600080fd5b81358181111561255a57600080fd5b89602082850101111561256c57600080fd5b9699959850939650602001949392505050565b6000806040838503121561259257600080fd5b61259b83612167565b91506125a960208401612167565b90509250929050565b600181811c908216806125c657607f821691505b6020821081036125e657634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600b908201526a2137b739b0b4903237329760a91b604082015260600190565b805163ffffffff81168114610e4c57600080fd5b80516001600160401b0381168114610e4c57600080fd5b805160ff81168114610e4c57600080fd5b805160038110610e4c57600080fd5b600082601f83011261266d57600080fd5b815160206001600160401b038211156126885761268861232f565b8160051b61269782820161236e565b92835284810182019282810190878511156126b157600080fd5b83870192505b848310156126d0578251825291830191908301906126b7565b979650505050505050565b6000602082840312156126ed57600080fd5b81516001600160401b038082111561270457600080fd5b90830190610140828603121561271957600080fd5b612721612345565b82518152602083015160208201526040830151604082015261274560608401612611565b606082015261275660808401612625565b608082015261276760a08401612625565b60a082015261277860c08401612625565b60c082015261278960e0840161263c565b60e082015261010061279c81850161264d565b9082015261012083810151838111156127b457600080fd5b6127c08882870161265c565b918301919091525095945050505050565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008261280c5761280c6127d1565b500490565b80820281158282048414176106f8576106f86127e7565b600082612837576128376127d1565b500690565b8281526040810160048310612853576128536121a8565b8260208301529392505050565b600082601f83011261287157600080fd5b815161287f61240c8261239e565b81815284602083860101111561289457600080fd5b6122c98260208301602087016120eb565b6000602082840312156128b757600080fd5b81516001600160401b03808211156128ce57600080fd5b90830190606082860312156128e257600080fd5b6040516060810181811083821117156128fd576128fd61232f565b60405261290983612625565b81526129176020840161264d565b602082015260408301518281111561292e57600080fd5b61293a87828601612860565b60408301525095945050505050565b6000825161295b8184602087016120eb565b9190910192915050565b60006020828403121561297757600080fd5b81516001600160401b0381111561298d57600080fd5b6122c984828501612860565b7f7b226e616d65223a2022626f6e534149222c20226465736372697074696f6e2281527f3a20224c696d697465642c2067656e657261746976652061727420636f6c6c6560208201527f6374696f6e206c6976696e6720656e746972656c792027696e2d636861696e2760408201526d171116101134b6b0b3b2911d101160911b60608201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000606e82015260008351612a5a8160888501602088016120eb565b61088b60f21b6088918401918201527f202273656c6c65725f6665655f62617369735f706f696e74733a223a20223130608a8201527518111610113332b2afb932b1b4b834b2b73a111d101160511b60aa8201528351612ac18160c08401602088016120eb565b61227d60f01b60c0929091019182015260c201949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000815260008251612b1481601d8501602087016120eb565b91909101601d0192915050565b600060208284031215612b3357600080fd5b8151612042816124a0565b6000815260008251612b578160018501602087016120eb565b9190910160010192915050565b6a600b5981380380925939f360a81b81528151600090612b8b81600b8501602087016120eb565b91909101600b0192915050565b600060208284031215612baa57600080fd5b8151612042816120b8565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b818103818111156106f8576106f86127e7565b808201808211156106f8576106f86127e7565b634e487b7160e01b600052603260045260246000fd5b600081612c5457612c546127e7565b50600019019056fea26469706673582212200a818f8f65358f192c7cceb0f2f6dd2e30cf8e48298a42d5f485a088c7ee977964736f6c63430008110033000000000000000000000000d64e3c25b0cc9afb535157cbb96eb601a47650fa000000000000000000000000ec4a325e273f031c136def19c5920065055d912b000000000000000000000000c2ddd87ef19b10ab491b9af808b039d98914f2e50000000000000000000000004feaf4cd57f111345b5ce82241f5b9d7c7f2bc96

Deployed Bytecode

0x6080604052600436106101f95760003560e01c80635e2893dd1161010d578063a22cb465116100a0578063db065b1d1161006f578063db065b1d14610602578063e55fcf2d14610617578063e8a3d48514610637578063e985e9c51461064c578063f47c84c51461068757600080fd5b8063a22cb46514610582578063a7eec44b146105a2578063b88d4fde146105c2578063c87b56dd146105e257600080fd5b8063784eb67d116100dc578063784eb67d146104f0578063833b94991461051d57806395d89b41146105395780639621026e1461054e57600080fd5b80635e2893dd1461048a5780636352211e1461049d5780636a627842146104bd57806370a08231146104d057600080fd5b80631c96cae9116101905780632fe319621161015f5780632fe31962146103f357806333043dbf1461041357806341f434341461043357806342842e0e1461045557806347bf8d311461047557600080fd5b80631c96cae91461036a5780631d16d9a01461037f57806323b872dd146103945780632a55205a146103b457600080fd5b806309a1f9c6116101cc57806309a1f9c6146102c557806310414d6d146102e5578063117803e31461031257806318160ddd1461034657600080fd5b806301ffc9a7146101fe57806306fdde0314610233578063081812fc14610255578063095ea7b3146102a3575b600080fd5b34801561020a57600080fd5b5061021e6102193660046120ce565b61069d565b60405190151581526020015b60405180910390f35b34801561023f57600080fd5b506102486106fe565b60405161022a919061213b565b34801561026157600080fd5b5061028b61027036600461214e565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b03909116815260200161022a565b3480156102af57600080fd5b506102c36102be36600461217e565b61078c565b005b3480156102d157600080fd5b50600a5461028b906001600160a01b031681565b3480156102f157600080fd5b5061030561030036600461214e565b6107a5565b60405161022a919061220d565b34801561031e57600080fd5b5061028b7f000000000000000000000000d64e3c25b0cc9afb535157cbb96eb601a47650fa81565b34801561035257600080fd5b5061035c60095481565b60405190815260200161022a565b34801561037657600080fd5b5061035c604681565b34801561038b57600080fd5b506102c361085b565b3480156103a057600080fd5b506102c36103af3660046122d1565b6109e8565b3480156103c057600080fd5b506103d46103cf36600461230d565b610a13565b604080516001600160a01b03909316835260208301919091520161022a565b3480156103ff57600080fd5b506102c361040e3660046123c5565b610abf565b34801561041f57600080fd5b50600b5461028b906001600160a01b031681565b34801561043f57600080fd5b5061028b6daaeb6d7670e522a718067333cd4e81565b34801561046157600080fd5b506102c36104703660046122d1565b610b50565b34801561048157600080fd5b5061035c610b75565b6102c361049836600461214e565b610b8b565b3480156104a957600080fd5b5061028b6104b836600461214e565b610dfa565b61035c6104cb366004612444565b610e51565b3480156104dc57600080fd5b5061035c6104eb366004612444565b611069565b3480156104fc57600080fd5b5061051061050b36600461214e565b6110cc565b60405161022a919061245f565b34801561052957600080fd5b5061035c6701002691684e400081565b34801561054557600080fd5b50610248611179565b34801561055a57600080fd5b5061028b7f000000000000000000000000ec4a325e273f031c136def19c5920065055d912b81565b34801561058e57600080fd5b506102c361059d3660046124ae565b611186565b3480156105ae57600080fd5b506105106105bd36600461214e565b61119a565b3480156105ce57600080fd5b506102c36105dd3660046124e5565b611294565b3480156105ee57600080fd5b506102486105fd36600461214e565b6112c3565b34801561060e57600080fd5b5061035c606481565b34801561062357600080fd5b5061035c610632366004612444565b61136b565b34801561064357600080fd5b5061024861151b565b34801561065857600080fd5b5061021e61066736600461257f565b600560209081526000928352604080842090915290825290205460ff1681565b34801561069357600080fd5b5061035c61271081565b60006001600160e01b0319821663152a902d60e11b14806106ce57506380ac58cd60e01b6001600160e01b03198316145b806106e95750635b5e139f60e01b6001600160e01b03198316145b806106f857506106f8826115b2565b92915050565b6000805461070b906125b2565b80601f0160208091040260200160405190810160405280929190818152602001828054610737906125b2565b80156107845780601f1061075957610100808354040283529160200191610784565b820191906000526020600020905b81548152906001019060200180831161076757829003601f168201915b505050505081565b81610796816115e7565b6107a083836116a0565b505050565b6107ad612049565b6000828152600260205260409020546001600160a01b03166107ea5760405162461bcd60e51b81526004016107e1906125ec565b60405180910390fd5b600b5460405163aaf1e61160e01b8152600481018490526001600160a01b039091169063aaf1e61190602401600060405180830381865afa158015610833573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106f891908101906126db565b60006001600160a01b037f000000000000000000000000ec4a325e273f031c136def19c5920065055d912b16610892600a476127fd565b604051600081818185875af1925050503d80600081146108ce576040519150601f19603f3d011682016040523d82523d6000602084013e6108d3565b606091505b50509050806109245760405162461bcd60e51b815260206004820152601d60248201527f63616c6c303a20627265616b7320454f4120617373756d7074696f6e2e00000060448201526064016107e1565b6040516001600160a01b037f000000000000000000000000d64e3c25b0cc9afb535157cbb96eb601a47650fa16904790600081818185875af1925050503d806000811461098d576040519150601f19603f3d011682016040523d82523d6000602084013e610992565b606091505b505080915050806109e55760405162461bcd60e51b815260206004820152601d60248201527f63616c6c313a20627265616b7320454f4120617373756d7074696f6e2e00000060448201526064016107e1565b50565b826001600160a01b0381163314610a0257610a02336115e7565b610a0d848484611782565b50505050565b60008281526007602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b0316928201929092528291610a885750604080518082019091526006546001600160a01b0381168252600160a01b90046001600160601b031660208201525b602081015160009061271090610aa7906001600160601b031687612811565b610ab191906127fd565b915196919550909350505050565b336001600160a01b037f000000000000000000000000d64e3c25b0cc9afb535157cbb96eb601a47650fa1614610b245760405162461bcd60e51b815260206004820152600a6024820152693737ba1037bbb732b91760b11b60448201526064016107e1565b610b2d81611949565b600880546001600160a01b0319166001600160a01b039290921691909117905550565b826001600160a01b0381163314610b6a57610b6a336115e7565b610a0d8484846119ee565b610b8860046701002691684e40006127fd565b81565b6000818152600260205260409020546001600160a01b03163314610bfb5760405162461bcd60e51b815260206004820152602160248201527f796f7520646f6e2774206d6f7720616e6f74686572206d616e2773206c61776e6044820152601760f91b60648201526084016107e1565b610c0e60046701002691684e40006127fd565b610c189034612828565b15610c655760405162461bcd60e51b815260206004820152601c60248201527f696e636f6e677275656e74207072756e696e67207061796d656e742e0000000060448201526064016107e1565b6000610c7a60046701002691684e40006127fd565b610c8490346127fd565b905060008111610cef5760405162461bcd60e51b815260206004820152603060248201527f63616c6c207072756e6520776974682076616c7565206e202a205052554e455f60448201526f21a7a9aa2fa822a92fa222a3a922a29760811b60648201526084016107e1565b60048110610d3f5760405162461bcd60e51b815260206004820152601c60248201527f6d6178207072756e65206465677265652069732033202848494748290000000060448201526064016107e1565b6000816003811115610d5357610d536121a8565b600a54604051630320f0dd60e61b81529192506001600160a01b03169063c83c374090610d86908690859060040161283c565b600060405180830381600087803b158015610da057600080fd5b505af1158015610db4573d6000803e3d6000fd5b50505050806003811115610dca57610dca6121a8565b60405184907fbb9360aa013e49a3091c9b89863774bc1ba5d5b25bc14fc6d17c8a27b0e021de90600090a3505050565b6000818152600260205260409020546001600160a01b031680610e4c5760405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b60448201526064016107e1565b919050565b60006701002691684e4000340615610eab5760405162461bcd60e51b815260206004820152601760248201527f6d73672e76616c756520213d206e202a2070726963652e00000000000000000060448201526064016107e1565b6701002691684e4000340480610f0f5760405162461bcd60e51b815260206004820152602360248201527f63616c6c206d696e742077697468206e202a2050524943455f5045525f544f4b60448201526222a71760e91b60648201526084016107e1565b336000908152600d602052604090205460469082011115610f665760405162461bcd60e51b815260206004820152601160248201527036b4b73a34b733903a37b79036b0b73c9760791b60448201526064016107e1565b336000908152600d602052604090208054820190556009546127108183011115610fcb5760405162461bcd60e51b81526020600482015260166024820152753732bb903a37b5b2b7399032bc31b2b2b21036b0bc1760511b60448201526064016107e1565b3233141560005b8381101561105b57610fea8684600101945084611ae1565b600a5460405163d1aa8c6560e01b81526004810185905283151560248201526001600160a01b039091169063d1aa8c6590604401600060405180830381600087803b15801561103857600080fd5b505af115801561104c573d6000803e3d6000fd5b50505050806001019050610fd2565b505060098190559392505050565b60006001600160a01b0382166110b05760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b60448201526064016107e1565b506001600160a01b031660009081526003602052604090205490565b6110d461209e565b6000828152600260205260409020546001600160a01b03166111085760405162461bcd60e51b81526004016107e1906125ec565b600a5460405163784eb67d60e01b8152600481018490526001600160a01b039091169063784eb67d90602401600060405180830381865afa158015611151573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106f891908101906128a5565b6001805461070b906125b2565b81611190816115e7565b6107a08383611bec565b6111a261209e565b6000828152600260205260409020546001600160a01b03166111d65760405162461bcd60e51b81526004016107e1906125ec565b600a5460405163a7eec44b60e01b8152600481018490526001600160a01b039091169063a7eec44b906024016000604051808303816000875af1158015611221573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261124991908101906128a5565b9050806040015160405161125d9190612949565b6040519081900381209083907f45f022ebaef0359458bda97ad02c7e8c572b5705a168151dee77f29fecb2d37690600090a3919050565b846001600160a01b03811633146112ae576112ae336115e7565b6112bb8686868686611c58565b505050505050565b6000818152600260205260409020546060906001600160a01b03166112fa5760405162461bcd60e51b81526004016107e1906125ec565b600b546040516379f2b5cf60e11b8152600481018490526001600160a01b039091169063f3e56b9e90602401600060405180830381865afa158015611343573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106f89190810190612965565b6000336001600160a01b037f000000000000000000000000d64e3c25b0cc9afb535157cbb96eb601a47650fa161461149b573332146113e45760405162461bcd60e51b8152602060048201526015602482015274373790333932b2b134b2b9903337b9103137ba399760591b60448201526064016107e1565b60646009541061142c5760405162461bcd60e51b815260206004820152601360248201527237379036b7b93290333932b29036b4b73a399760691b60448201526064016107e1565b326000908152600c6020526040902054620151800142116114885760405162461bcd60e51b81526020600482015260166024820152751890333932b29036b4b73a1017a2a7a09017b230bc9760511b60448201526064016107e1565b336000908152600c602052604090204290555b5060098054600101908190556114b18282611ae1565b600a5460405163d1aa8c6560e01b815260048101839052600060248201526001600160a01b039091169063d1aa8c6590604401600060405180830381600087803b1580156114fe57600080fd5b505af1158015611512573d6000803e3d6000fd5b50505050919050565b60085460609061158e906115409061153b906001600160a01b0316611d40565b611d61565b6115697f000000000000000000000000d64e3c25b0cc9afb535157cbb96eb601a47650fa611d6f565b60405160200161157a929190612999565b604051602081830303815290604052611d61565b60405160200161159e9190612adc565b604051602081830303815290604052905090565b60006001600160e01b0319821663152a902d60e11b14806106f857506301ffc9a760e01b6001600160e01b03198316146106f8565b6daaeb6d7670e522a718067333cd4e3b156109e557604051633185c44d60e21b81523060048201526001600160a01b03821660248201526daaeb6d7670e522a718067333cd4e9063c617113490604401602060405180830381865afa158015611654573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116789190612b21565b6109e557604051633b79c77360e21b81526001600160a01b03821660048201526024016107e1565b6000818152600260205260409020546001600160a01b0316338114806116e957506001600160a01b038116600090815260056020908152604080832033845290915290205460ff165b6117265760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064016107e1565b60008281526004602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b6000818152600260205260409020546001600160a01b038481169116146117d85760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b60448201526064016107e1565b6001600160a01b0382166118225760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b60448201526064016107e1565b336001600160a01b038416148061185c57506001600160a01b038316600090815260056020908152604080832033845290915290205460ff165b8061187d57506000818152600460205260409020546001600160a01b031633145b6118ba5760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064016107e1565b6001600160a01b0380841660008181526003602090815260408083208054600019019055938616808352848320805460010190558583526002825284832080546001600160a01b03199081168317909155600490925284832080549092169091559251849392917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6000808260405160200161195d9190612b3e565b60405160208183030381529060405290506000816040516020016119819190612b64565b60405160208183030381529060405290508051602082016000f092506001600160a01b0383166119e75760405162461bcd60e51b81526020600482015260116024820152701111541313d65351539517d19052531151607a1b60448201526064016107e1565b5050919050565b6119f98383836109e8565b6001600160a01b0382163b1580611aa25750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015611a72573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a969190612b98565b6001600160e01b031916145b6107a05760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016107e1565b6001600160a01b038216611b2b5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b60448201526064016107e1565b6000818152600260205260409020546001600160a01b031615611b815760405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b60448201526064016107e1565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b3360008181526005602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b611c638585856109e8565b6001600160a01b0384163b1580611cfa5750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a0290611cab9033908a90899089908990600401612bb5565b6020604051808303816000875af1158015611cca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cee9190612b98565b6001600160e01b031916145b611d395760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016107e1565b5050505050565b60606106f8826001611d5c816001600160a01b0384163b612c09565b611d85565b60606106f882600080611da8565b60606106f86001600160a01b0383166014611ea7565b60408051603f8301601f19168101909152818152818360208301863c9392505050565b606083518015611e9f576003600282010460021b60405192507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f526102308515027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f03603f52602083018181015b6003880197508751603f8160121c16518353603f81600c1c16516001840153603f8160061c16516002840153603f811651600384015350600482019150808210611e185760038406868015611e7857600182148215150185038752611e90565b603d821515850353603d6001831460011b8503538487525b5050601f01601f191660405250505b509392505050565b60606000611eb6836002612811565b611ec1906002612c1c565b6001600160401b03811115611ed857611ed861232f565b6040519080825280601f01601f191660200182016040528015611f02576020820181803683370190505b509050600360fc1b81600081518110611f1d57611f1d612c2f565b60200101906001600160f81b031916908160001a905350600f60fb1b81600181518110611f4c57611f4c612c2f565b60200101906001600160f81b031916908160001a9053506000611f70846002612811565b611f7b906001612c1c565b90505b6001811115611ff3576f181899199a1a9b1b9c1cb0b131b232b360811b85600f1660108110611faf57611faf612c2f565b1a60f81b828281518110611fc557611fc5612c2f565b60200101906001600160f81b031916908160001a90535060049490941c93611fec81612c45565b9050611f7e565b5083156120425760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e7460448201526064016107e1565b9392505050565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052906101008201905b8152602001606081525090565b604080516060810190915260008082526020820190612091565b6001600160e01b0319811681146109e557600080fd5b6000602082840312156120e057600080fd5b8135612042816120b8565b60005b838110156121065781810151838201526020016120ee565b50506000910152565b600081518084526121278160208601602086016120eb565b601f01601f19169290920160200192915050565b602081526000612042602083018461210f565b60006020828403121561216057600080fd5b5035919050565b80356001600160a01b0381168114610e4c57600080fd5b6000806040838503121561219157600080fd5b61219a83612167565b946020939093013593505050565b634e487b7160e01b600052602160045260246000fd5b600381106121ce576121ce6121a8565b9052565b600081518084526020808501945080840160005b83811015612202578151875295820195908201906001016121e6565b509495945050505050565b6020815281516020820152602082015160408201526040820151606082015260006060830151612245608084018263ffffffff169052565b5060808301516001600160401b03811660a08401525060a08301516001600160401b03811660c08401525060c08301516001600160401b03811660e08401525060e083015161010061229b8185018360ff169052565b84015190506101206122af848201836121be565b8401516101408481015290506122c96101608401826121d2565b949350505050565b6000806000606084860312156122e657600080fd5b6122ef84612167565b92506122fd60208501612167565b9150604084013590509250925092565b6000806040838503121561232057600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b60405161014081016001600160401b03811182821017156123685761236861232f565b60405290565b604051601f8201601f191681016001600160401b03811182821017156123965761239661232f565b604052919050565b60006001600160401b038211156123b7576123b761232f565b50601f01601f191660200190565b6000602082840312156123d757600080fd5b81356001600160401b038111156123ed57600080fd5b8201601f810184136123fe57600080fd5b803561241161240c8261239e565b61236e565b81815285602083850101111561242657600080fd5b81602084016020830137600091810160200191909152949350505050565b60006020828403121561245657600080fd5b61204282612167565b602081526001600160401b0382511660208201526000602083015161248760408401826121be565b5060408301516060808401526122c9608084018261210f565b80151581146109e557600080fd5b600080604083850312156124c157600080fd5b6124ca83612167565b915060208301356124da816124a0565b809150509250929050565b6000806000806000608086880312156124fd57600080fd5b61250686612167565b945061251460208701612167565b93506040860135925060608601356001600160401b038082111561253757600080fd5b818801915088601f83011261254b57600080fd5b81358181111561255a57600080fd5b89602082850101111561256c57600080fd5b9699959850939650602001949392505050565b6000806040838503121561259257600080fd5b61259b83612167565b91506125a960208401612167565b90509250929050565b600181811c908216806125c657607f821691505b6020821081036125e657634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600b908201526a2137b739b0b4903237329760a91b604082015260600190565b805163ffffffff81168114610e4c57600080fd5b80516001600160401b0381168114610e4c57600080fd5b805160ff81168114610e4c57600080fd5b805160038110610e4c57600080fd5b600082601f83011261266d57600080fd5b815160206001600160401b038211156126885761268861232f565b8160051b61269782820161236e565b92835284810182019282810190878511156126b157600080fd5b83870192505b848310156126d0578251825291830191908301906126b7565b979650505050505050565b6000602082840312156126ed57600080fd5b81516001600160401b038082111561270457600080fd5b90830190610140828603121561271957600080fd5b612721612345565b82518152602083015160208201526040830151604082015261274560608401612611565b606082015261275660808401612625565b608082015261276760a08401612625565b60a082015261277860c08401612625565b60c082015261278960e0840161263c565b60e082015261010061279c81850161264d565b9082015261012083810151838111156127b457600080fd5b6127c08882870161265c565b918301919091525095945050505050565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60008261280c5761280c6127d1565b500490565b80820281158282048414176106f8576106f86127e7565b600082612837576128376127d1565b500690565b8281526040810160048310612853576128536121a8565b8260208301529392505050565b600082601f83011261287157600080fd5b815161287f61240c8261239e565b81815284602083860101111561289457600080fd5b6122c98260208301602087016120eb565b6000602082840312156128b757600080fd5b81516001600160401b03808211156128ce57600080fd5b90830190606082860312156128e257600080fd5b6040516060810181811083821117156128fd576128fd61232f565b60405261290983612625565b81526129176020840161264d565b602082015260408301518281111561292e57600080fd5b61293a87828601612860565b60408301525095945050505050565b6000825161295b8184602087016120eb565b9190910192915050565b60006020828403121561297757600080fd5b81516001600160401b0381111561298d57600080fd5b6122c984828501612860565b7f7b226e616d65223a2022626f6e534149222c20226465736372697074696f6e2281527f3a20224c696d697465642c2067656e657261746976652061727420636f6c6c6560208201527f6374696f6e206c6976696e6720656e746972656c792027696e2d636861696e2760408201526d171116101134b6b0b3b2911d101160911b60608201527f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000606e82015260008351612a5a8160888501602088016120eb565b61088b60f21b6088918401918201527f202273656c6c65725f6665655f62617369735f706f696e74733a223a20223130608a8201527518111610113332b2afb932b1b4b834b2b73a111d101160511b60aa8201528351612ac18160c08401602088016120eb565b61227d60f01b60c0929091019182015260c201949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000815260008251612b1481601d8501602087016120eb565b91909101601d0192915050565b600060208284031215612b3357600080fd5b8151612042816124a0565b6000815260008251612b578160018501602087016120eb565b9190910160010192915050565b6a600b5981380380925939f360a81b81528151600090612b8b81600b8501602087016120eb565b91909101600b0192915050565b600060208284031215612baa57600080fd5b8151612042816120b8565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b818103818111156106f8576106f86127e7565b808201808211156106f8576106f86127e7565b634e487b7160e01b600052603260045260246000fd5b600081612c5457612c546127e7565b50600019019056fea26469706673582212200a818f8f65358f192c7cceb0f2f6dd2e30cf8e48298a42d5f485a088c7ee977964736f6c63430008110033

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

000000000000000000000000d64e3c25b0cc9afb535157cbb96eb601a47650fa000000000000000000000000ec4a325e273f031c136def19c5920065055d912b000000000000000000000000c2ddd87ef19b10ab491b9af808b039d98914f2e50000000000000000000000004feaf4cd57f111345b5ce82241f5b9d7c7f2bc96

-----Decoded View---------------
Arg [0] : owner_ (address): 0xd64e3c25B0cC9AFb535157cBB96eb601a47650fa
Arg [1] : securityAdvisor_ (address): 0xEC4A325E273f031c136Def19c5920065055D912B
Arg [2] : bonsaiState_ (address): 0xC2ddd87ef19B10AB491b9aF808b039D98914f2E5
Arg [3] : bonsaiRenderer_ (address): 0x4FeAF4Cd57f111345B5CE82241f5B9D7C7F2bc96

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000d64e3c25b0cc9afb535157cbb96eb601a47650fa
Arg [1] : 000000000000000000000000ec4a325e273f031c136def19c5920065055d912b
Arg [2] : 000000000000000000000000c2ddd87ef19b10ab491b9af808b039d98914f2e5
Arg [3] : 0000000000000000000000004feaf4cd57f111345b5ce82241f5b9d7c7f2bc96


Deployed Bytecode Sourcemap

60199:4849:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64647:398;;;;;;;;;;-1:-1:-1;64647:398:0;;;;;:::i;:::-;;:::i;:::-;;;565:14:1;;558:22;540:41;;528:2;513:18;64647:398:0;;;;;;;;9011:18;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;9984:46::-;;;;;;;;;;-1:-1:-1;9984:46:0;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;9984:46:0;;;;;;-1:-1:-1;;;;;1697:32:1;;;1679:51;;1667:2;1652:18;9984:46:0;1533:203:1;21291:157:0;;;;;;;;;;-1:-1:-1;21291:157:0;;;;;:::i;:::-;;:::i;:::-;;60582:31;;;;;;;;;;-1:-1:-1;60582:31:0;;;;-1:-1:-1;;;;;60582:31:0;;;63112:217;;;;;;;;;;-1:-1:-1;63112:217:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;58452:30::-;;;;;;;;;;;;;;;60547:26;;;;;;;;;;;;;;;;;;;4879:25:1;;;4867:2;4852:18;60547:26:0;4733:177:1;60379:36:0;;;;;;;;;;;;60413:2;60379:36;;59627:398;;;;;;;;;;;;;:::i;21456:163::-;;;;;;;;;;-1:-1:-1;21456:163:0;;;;;:::i;:::-;;:::i;35386:442::-;;;;;;;;;;-1:-1:-1;35386:442:0;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;5693:32:1;;;5675:51;;5757:2;5742:18;;5735:34;;;;5648:18;35386:442:0;5501:274:1;60033:159:0;;;;;;;;;;-1:-1:-1;60033:159:0;;;;;:::i;:::-;;:::i;60620:37::-;;;;;;;;;;-1:-1:-1;60620:37:0;;;;-1:-1:-1;;;;;60620:37:0;;;18424:143;;;;;;;;;;;;18524:42;18424:143;;21627:171;;;;;;;;;;-1:-1:-1;21627:171:0;;;;;:::i;:::-;;:::i;60470:67::-;;;;;;;;;;;;;:::i;64036:603::-;;;;;;:::i;:::-;;:::i;9453:151::-;;;;;;;;;;-1:-1:-1;9453:151:0;;;;;:::i;:::-;;:::i;62005:843::-;;;;;;:::i;:::-;;:::i;9612:172::-;;;;;;;;;;-1:-1:-1;9612:172:0;;;;;:::i;:::-;;:::i;63722:213::-;;;;;;;;;;-1:-1:-1;63722:213:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;60268:54::-;;;;;;;;;;;;60310:12;60268:54;;9038:20;;;;;;;;;;;;;:::i;58489:41::-;;;;;;;;;;;;;;;21107:176;;;;;;;;;;-1:-1:-1;21107:176:0;;;;;:::i;:::-;;:::i;63476:238::-;;;;;;;;;;-1:-1:-1;63476:238:0;;;;;:::i;:::-;;:::i;21806:230::-;;;;;;;;;;-1:-1:-1;21806:230:0;;;;;:::i;:::-;;:::i;62894:210::-;;;;;;;;;;-1:-1:-1;62894:210:0;;;;;:::i;:::-;;:::i;60422:39::-;;;;;;;;;;;;60458:3;60422:39;;61390:607;;;;;;;;;;-1:-1:-1;61390:607:0;;;;;:::i;:::-;;:::i;58921:698::-;;;;;;;;;;;;;:::i;10039:68::-;;;;;;;;;;-1:-1:-1;10039:68:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;60329:43;;;;;;;;;;;;60366:6;60329:43;;64647:398;64749:4;-1:-1:-1;;;;;;64773:41:0;;-1:-1:-1;;;64773:41:0;;:87;;-1:-1:-1;;;;;;;;;;64835:25:0;;;64773:87;:166;;;-1:-1:-1;;;;;;;;;;64914:25:0;;;64773:166;:264;;;;65001:36;65025:11;65001:23;:36::i;:::-;64766:271;64647:398;-1:-1:-1;;64647:398:0:o;9011:18::-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;21291:157::-;21387:8;19945:30;19966:8;19945:20;:30::i;:::-;21408:32:::1;21422:8;21432:7;21408:13;:32::i;:::-;21291:157:::0;;;:::o;63112:217::-;63176:20;;:::i;:::-;63246:1;63217:17;;;:8;:17;;;;;;-1:-1:-1;;;;;63217:17:0;63209:55;;;;-1:-1:-1;;;63209:55:0;;;;;;;:::i;:::-;;;;;;;;;63282:14;;:39;;-1:-1:-1;;;63282:39:0;;;;;4879:25:1;;;-1:-1:-1;;;;;63282:14:0;;;;:30;;4852:18:1;;63282:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;63282:39:0;;;;;;;;;;;;:::i;59627:398::-;59754:12;-1:-1:-1;;;;;59771:16:0;:21;59800:24;59822:2;59800:21;:24;:::i;:::-;59771:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59753:76;;;59848:7;59840:49;;;;-1:-1:-1;;;59840:49:0;;14295:2:1;59840:49:0;;;14277:21:1;14334:2;14314:18;;;14307:30;14373:31;14353:18;;;14346:59;14422:18;;59840:49:0;14093:353:1;59840:49:0;59913:44;;-1:-1:-1;;;;;59913:5:0;:10;;59931:21;;59913:44;;;;59931:21;59913:10;:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;59900:57;;;;;59976:7;59968:49;;;;-1:-1:-1;;;59968:49:0;;14653:2:1;59968:49:0;;;14635:21:1;14692:2;14672:18;;;14665:30;14731:31;14711:18;;;14704:59;14780:18;;59968:49:0;14451:353:1;59968:49:0;59655:370;59627:398::o;21456:163::-;21557:4;-1:-1:-1;;;;;19765:18:0;;19773:10;19765:18;19761:83;;19800:32;19821:10;19800:20;:32::i;:::-;21574:37:::1;21593:4;21599:2;21603:7;21574:18;:37::i;:::-;21456:163:::0;;;;:::o;35386:442::-;35483:7;35541:27;;;:17;:27;;;;;;;;35512:56;;;;;;;;;-1:-1:-1;;;;;35512:56:0;;;;;-1:-1:-1;;;35512:56:0;;;-1:-1:-1;;;;;35512:56:0;;;;;;;;35483:7;;35581:92;;-1:-1:-1;35632:29:0;;;;;;;;;35642:19;35632:29;-1:-1:-1;;;;;35632:29:0;;;;-1:-1:-1;;;35632:29:0;;-1:-1:-1;;;;;35632:29:0;;;;;35581:92;35723:23;;;;35685:21;;36194:5;;35710:36;;-1:-1:-1;;;;;35710:36:0;:10;:36;:::i;:::-;35709:58;;;;:::i;:::-;35788:16;;;;;-1:-1:-1;35386:442:0;;-1:-1:-1;;;;35386:442:0:o;60033:159::-;60098:10;-1:-1:-1;;;;;60112:5:0;60098:19;;60090:42;;;;-1:-1:-1;;;60090:42:0;;15184:2:1;60090:42:0;;;15166:21:1;15223:2;15203:18;;;15196:30;-1:-1:-1;;;15242:18:1;;;15235:40;15292:18;;60090:42:0;14982:334:1;60090:42:0;60158:26;60178:4;60158:13;:26::i;:::-;60143:12;:41;;-1:-1:-1;;;;;;60143:41:0;-1:-1:-1;;;;;60143:41:0;;;;;;;;;;-1:-1:-1;60033:159:0:o;21627:171::-;21732:4;-1:-1:-1;;;;;19765:18:0;;19773:10;19765:18;19761:83;;19800:32;19821:10;19800:20;:32::i;:::-;21749:41:::1;21772:4;21778:2;21782:7;21749:22;:41::i;60470:67::-:0;60518:19;60536:1;60310:12;60518:19;:::i;:::-;60470:67;:::o;64036:603::-;64118:17;;;;:8;:17;;;;;;-1:-1:-1;;;;;64118:17:0;64104:10;:31;64096:77;;;;-1:-1:-1;;;64096:77:0;;15523:2:1;64096:77:0;;;15505:21:1;15562:2;15542:18;;;15535:30;15601:34;15581:18;;;15574:62;-1:-1:-1;;;15652:18:1;;;15645:31;15693:19;;64096:77:0;15321:397:1;64096:77:0;60518:19;60536:1;60310:12;60518:19;:::i;:::-;64192:33;;:9;:33;:::i;:::-;:38;64184:79;;;;-1:-1:-1;;;64184:79:0;;16042:2:1;64184:79:0;;;16024:21:1;16081:2;16061:18;;;16054:30;16120;16100:18;;;16093:58;16168:18;;64184:79:0;15840:352:1;64184:79:0;64274:20;60518:19;60536:1;60310:12;60518:19;:::i;:::-;64298:33;;:9;:33;:::i;:::-;64274:58;;64366:1;64351:12;:16;64343:77;;;;-1:-1:-1;;;64343:77:0;;16399:2:1;64343:77:0;;;16381:21:1;16438:2;16418:18;;;16411:30;16477:34;16457:18;;;16450:62;-1:-1:-1;;;16528:18:1;;;16521:46;16584:19;;64343:77:0;16197:412:1;64343:77:0;64454:1;64439:12;:16;64431:57;;;;-1:-1:-1;;;64431:57:0;;16816:2:1;64431:57:0;;;16798:21:1;16855:2;16835:18;;;16828:30;16894;16874:18;;;16867:58;16942:18;;64431:57:0;16614:352:1;64431:57:0;64499:19;64534:12;64521:26;;;;;;;;:::i;:::-;64558:11;;:34;;-1:-1:-1;;;64558:34:0;;64499:48;;-1:-1:-1;;;;;;64558:11:0;;:17;;:34;;64576:7;;64499:48;;64558:34;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;64624:6;64608:23;;;;;;;;:::i;:::-;;;64615:7;;64608:23;;;;;64085:554;;64036:603;:::o;9453:151::-;9511:13;9554:12;;;:8;:12;;;;;;-1:-1:-1;;;;;9554:12:0;;9537:59;;;;-1:-1:-1;;;9537:59:0;;17497:2:1;9537:59:0;;;17479:21:1;17536:2;17516:18;;;17509:30;-1:-1:-1;;;17555:18:1;;;17548:40;17605:18;;9537:59:0;17295:334:1;9537:59:0;9453:151;;;:::o;62005:843::-;62056:19;60310:12;62116:9;:27;:32;62108:68;;;;-1:-1:-1;;;62108:68:0;;17836:2:1;62108:68:0;;;17818:21:1;17875:2;17855:18;;;17848:30;17914:25;17894:18;;;17887:53;17957:18;;62108:68:0;17634:347:1;62108:68:0;60310:12;62201:9;:27;62247:7;62239:55;;;;-1:-1:-1;;;62239:55:0;;18188:2:1;62239:55:0;;;18170:21:1;18227:2;18207:18;;;18200:30;18266:34;18246:18;;;18239:62;-1:-1:-1;;;18317:18:1;;;18310:33;18360:19;;62239:55:0;17986:399:1;62239:55:0;62324:10;62313:22;;;;:10;:22;;;;;;60413:2;62313:28;;;:39;;62305:69;;;;-1:-1:-1;;;62305:69:0;;18592:2:1;62305:69:0;;;18574:21:1;18631:2;18611:18;;;18604:30;-1:-1:-1;;;18650:18:1;;;18643:47;18707:18;;62305:69:0;18390:341:1;62305:69:0;62396:10;62385:22;;;;:10;:22;;;;;:29;;;;;;62443:11;;60366:6;62473:13;;;:27;;62465:62;;;;-1:-1:-1;;;62465:62:0;;18938:2:1;62465:62:0;;;18920:21:1;18977:2;18957:18;;;18950:30;-1:-1:-1;;;18996:18:1;;;18989:52;19058:18;;62465:62:0;18736:346:1;62465:62:0;61333:9;61346:10;61333:23;;62540:13;62618:140;62638:3;62634:1;:7;62618:140;;;62663:20;62669:2;62673:9;;;;;;62663:5;:20::i;:::-;62699:11;;:47;;-1:-1:-1;;;62699:47:0;;;;;19255:25:1;;;19323:14;;19316:22;19296:18;;;19289:50;-1:-1:-1;;;;;62699:11:0;;;;:28;;19228:18:1;;62699:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62643:3;;;;;62618:140;;;-1:-1:-1;;62800:11:0;:25;;;62782:7;62005:843;-1:-1:-1;;;62005:843:0:o;9612:172::-;9675:7;-1:-1:-1;;;;;9703:19:0;;9695:44;;;;-1:-1:-1;;;9695:44:0;;19552:2:1;9695:44:0;;;19534:21:1;19591:2;19571:18;;;19564:30;-1:-1:-1;;;19610:18:1;;;19603:42;19662:18;;9695:44:0;19350:336:1;9695:44:0;-1:-1:-1;;;;;;9759:17:0;;;;;:10;:17;;;;;;;9612:172::o;63722:213::-;63785:21;;:::i;:::-;63856:1;63827:17;;;:8;:17;;;;;;-1:-1:-1;;;;;63827:17:0;63819:55;;;;-1:-1:-1;;;63819:55:0;;;;;;;:::i;:::-;63892:11;;:35;;-1:-1:-1;;;63892:35:0;;;;;4879:25:1;;;-1:-1:-1;;;;;63892:11:0;;;;:26;;4852:18:1;;63892:35:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;63892:35:0;;;;;;;;;;;;:::i;9038:20::-;;;;;;;:::i;21107:176::-;21211:8;19945:30;19966:8;19945:20;:30::i;:::-;21232:43:::1;21256:8;21266;21232:23;:43::i;63476:238::-:0;63525:24;;:::i;:::-;63599:1;63570:17;;;:8;:17;;;;;;-1:-1:-1;;;;;63570:17:0;63562:55;;;;-1:-1:-1;;;63562:55:0;;;;;;;:::i;:::-;63633:11;;:26;;-1:-1:-1;;;63633:26:0;;;;;4879:25:1;;;-1:-1:-1;;;;;63633:11:0;;;;:17;;4852:18:1;;63633:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;63633:26:0;;;;;;;;;;;;:::i;:::-;63628:31;;63696:2;:9;;;63679:27;;;;;;:::i;:::-;;;;;;;;;;63687:7;;63679:27;;;;;63476:238;;;:::o;21806:230::-;21959:4;-1:-1:-1;;;;;19765:18:0;;19773:10;19765:18;19761:83;;19800:32;19821:10;19800:20;:32::i;:::-;21981:47:::1;22004:4;22010:2;22014:7;22023:4;;21981:22;:47::i;:::-;21806:230:::0;;;;;;:::o;62894:210::-;63021:1;62992:17;;;:8;:17;;;;;;62958:13;;-1:-1:-1;;;;;62992:17:0;62984:55;;;;-1:-1:-1;;;62984:55:0;;;;;;;:::i;:::-;63057:14;;:39;;-1:-1:-1;;;63057:39:0;;;;;4879:25:1;;;-1:-1:-1;;;;;63057:14:0;;;;:30;;4852:18:1;;63057:39:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;63057:39:0;;;;;;;;;;;;:::i;61390:607::-;61437:15;61489:10;-1:-1:-1;;;;;61503:5:0;61489:19;;61485:351;;61346:10;61333:9;:23;61525:46;;;;-1:-1:-1;;;61525:46:0;;21913:2:1;61525:46:0;;;21895:21:1;21952:2;21932:18;;;21925:30;-1:-1:-1;;;21971:18:1;;;21964:51;22032:18;;61525:46:0;21711:345:1;61525:46:0;60458:3;61594:11;;:23;61586:55;;;;-1:-1:-1;;;61586:55:0;;22263:2:1;61586:55:0;;;22245:21:1;22302:2;22282:18;;;22275:30;-1:-1:-1;;;22321:18:1;;;22314:49;22380:18;;61586:55:0;22061:343:1;61586:55:0;61698:9;61682:26;;;;:15;:26;;;;;;61711:6;61682:35;61664:15;:53;61656:88;;;;-1:-1:-1;;;61656:88:0;;22611:2:1;61656:88:0;;;22593:21:1;22650:2;22630:18;;;22623:30;-1:-1:-1;;;22669:18:1;;;22662:52;22731:18;;61656:88:0;22409:346:1;61656:88:0;61775:10;61759:27;;;;:15;:27;;;;;61789:15;61759:45;;61485:351;-1:-1:-1;61858:11:0;61856:13;;;;;;;;61880:18;61886:2;61856:13;61880:5;:18::i;:::-;61909:11;;:65;;-1:-1:-1;;;61909:65:0;;;;;19255:25:1;;;61909:11:0;19296:18:1;;;19289:50;-1:-1:-1;;;;;61909:11:0;;;;:28;;19228:18:1;;61909:65:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;61390:607;;;:::o;58921:698::-;59410:12;;58964:13;;59094:515;;59383:41;;59397:26;;-1:-1:-1;;;;;59410:12:0;59397;:26::i;:::-;59383:13;:41::i;:::-;59574:26;59594:5;59574:19;:26::i;:::-;59108:500;;;;;;;;;:::i;:::-;;;;;;;;;;;;;59094:13;:515::i;:::-;59004:606;;;;;;;;:::i;:::-;;;;;;;;;;;;;58990:621;;58921:698;:::o;35116:215::-;35218:4;-1:-1:-1;;;;;;35242:41:0;;-1:-1:-1;;;35242:41:0;;:81;;-1:-1:-1;;;;;;;;;;33847:40:0;;;35287:36;33738:157;20003:419;18524:42;20194:45;:49;20190:225;;20265:67;;-1:-1:-1;;;20265:67:0;;20316:4;20265:67;;;25136:34:1;-1:-1:-1;;;;;25206:15:1;;25186:18;;;25179:43;18524:42:0;;20265;;25071:18:1;;20265:67:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;20260:144;;20360:28;;-1:-1:-1;;;20360:28:0;;-1:-1:-1;;;;;1697:32:1;;20360:28:0;;;1679:51:1;1652:18;;20360:28:0;1533:203:1;10610:290:0;10682:13;10698:12;;;:8;:12;;;;;;-1:-1:-1;;;;;10698:12:0;10731:10;:19;;;:58;;-1:-1:-1;;;;;;10754:23:0;;;;;;:16;:23;;;;;;;;10778:10;10754:35;;;;;;;;;;10731:58;10723:85;;;;-1:-1:-1;;;10723:85:0;;25685:2:1;10723:85:0;;;25667:21:1;25724:2;25704:18;;;25697:30;-1:-1:-1;;;25743:18:1;;;25736:44;25797:18;;10723:85:0;25483:338:1;10723:85:0;10821:15;;;;:11;:15;;;;;;:25;;-1:-1:-1;;;;;;10821:25:0;-1:-1:-1;;;;;10821:25:0;;;;;;;;;10864:28;;10821:15;;10864:28;;;;;;;10671:229;10610:290;;:::o;11123:768::-;11259:12;;;;:8;:12;;;;;;-1:-1:-1;;;;;11251:20:0;;;11259:12;;11251:20;11243:43;;;;-1:-1:-1;;;11243:43:0;;26028:2:1;11243:43:0;;;26010:21:1;26067:2;26047:18;;;26040:30;-1:-1:-1;;;26086:18:1;;;26079:40;26136:18;;11243:43:0;25826:334:1;11243:43:0;-1:-1:-1;;;;;11307:16:0;;11299:46;;;;-1:-1:-1;;;11299:46:0;;26367:2:1;11299:46:0;;;26349:21:1;26406:2;26386:18;;;26379:30;-1:-1:-1;;;26425:18:1;;;26418:47;26482:18;;11299:46:0;26165:341:1;11299:46:0;11380:10;-1:-1:-1;;;;;11380:18:0;;;;:56;;-1:-1:-1;;;;;;11402:22:0;;;;;;:16;:22;;;;;;;;11425:10;11402:34;;;;;;;;;;11380:56;:89;;;-1:-1:-1;11454:15:0;;;;:11;:15;;;;;;-1:-1:-1;;;;;11454:15:0;11440:10;:29;11380:89;11358:153;;;;-1:-1:-1;;;11358:153:0;;25685:2:1;11358:153:0;;;25667:21:1;25724:2;25704:18;;;25697:30;-1:-1:-1;;;25743:18:1;;;25736:44;25797:18;;11358:153:0;25483:338:1;11358:153:0;-1:-1:-1;;;;;11716:16:0;;;;;;;:10;:16;;;;;;;;:18;;-1:-1:-1;;11716:18:0;;;11751:14;;;;;;;;;:16;;11716:18;11751:16;;;11791:12;;;:8;:12;;;;;:17;;-1:-1:-1;;;;;;11791:17:0;;;;;;;;11828:11;:15;;;;;;11821:22;;;;;;;;11861;;11800:2;;11751:14;11716:16;11861:22;;;11123:768;;;:::o;53547:2743::-;53599:15;53709:24;53762:4;53736:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;53709:58;;53780:25;55776:11;53808:2101;;;;;;;;:::i;:::-;;;;;;;;;;;;;53780:2129;;56194:12;56188:19;56183:2;56169:12;56165:21;56162:1;56155:53;56144:64;-1:-1:-1;;;;;;56239:21:0;;56231:51;;;;-1:-1:-1;;;56231:51:0;;27612:2:1;56231:51:0;;;27594:21:1;27651:2;27631:18;;;27624:30;-1:-1:-1;;;27670:18:1;;;27663:47;27727:18;;56231:51:0;27410:341:1;56231:51:0;53616:2674;;53547:2743;;;:::o;11899:409::-;12023:26;12036:4;12042:2;12046;12023:12;:26::i;:::-;-1:-1:-1;;;;;12084:14:0;;;:19;;:172;;-1:-1:-1;12124:66:0;;-1:-1:-1;;;12124:66:0;;;12165:10;12124:66;;;28061:34:1;-1:-1:-1;;;;;28131:15:1;;;28111:18;;;28104:43;28163:18;;;28156:34;;;28226:3;28206:18;;;28199:31;-1:-1:-1;28246:19:1;;;28239:30;12211:45:0;;12124:40;;;;12211:45;;28286:19:1;;12124:66:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;;12124:132:0;;12084:172;12062:238;;;;-1:-1:-1;;;12062:238:0;;28772:2:1;12062:238:0;;;28754:21:1;28811:2;28791:18;;;28784:30;-1:-1:-1;;;28830:18:1;;;28823:46;28886:18;;12062:238:0;28570:340:1;13491:384:0;-1:-1:-1;;;;;13566:16:0;;13558:46;;;;-1:-1:-1;;;13558:46:0;;26367:2:1;13558:46:0;;;26349:21:1;26406:2;26386:18;;;26379:30;-1:-1:-1;;;26425:18:1;;;26418:47;26482:18;;13558:46:0;26165:341:1;13558:46:0;13649:1;13625:12;;;:8;:12;;;;;;-1:-1:-1;;;;;13625:12:0;:26;13617:53;;;;-1:-1:-1;;;13617:53:0;;29117:2:1;13617:53:0;;;29099:21:1;29156:2;29136:18;;;29129:30;-1:-1:-1;;;29175:18:1;;;29168:44;29229:18;;13617:53:0;28915:338:1;13617:53:0;-1:-1:-1;;;;;13764:14:0;;;;;;:10;:14;;;;;;;;:16;;;;;;13804:12;;;:8;:12;;;;;;:17;;-1:-1:-1;;;;;;13804:17:0;;;;;13839:28;13813:2;;13764:14;;13839:28;;13764:14;;13839:28;13491:384;;:::o;10908:207::-;11011:10;10994:28;;;;:16;:28;;;;;;;;-1:-1:-1;;;;;10994:38:0;;;;;;;;;;;;:49;;-1:-1:-1;;10994:49:0;;;;;;;;;;11061:46;;540:41:1;;;10994:38:0;;11011:10;11061:46;;513:18:1;11061:46:0;;;;;;;10908:207;;:::o;12316:441::-;12470:26;12483:4;12489:2;12493;12470:12;:26::i;:::-;-1:-1:-1;;;;;12531:14:0;;;:19;;:174;;-1:-1:-1;12571:68:0;;-1:-1:-1;;;12571:68:0;;;12660:45;-1:-1:-1;;;;;12571:40:0;;;12660:45;;12571:68;;12612:10;;12624:4;;12630:2;;12634:4;;;;12571:68;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;;12571:134:0;;12531:174;12509:240;;;;-1:-1:-1;;;12509:240:0;;28772:2:1;12509:240:0;;;28754:21:1;28811:2;28791:18;;;28784:30;-1:-1:-1;;;28830:18:1;;;28823:46;28886:18;;12509:240:0;28570:340:1;12509:240:0;12316:441;;;;;:::o;56483:163::-;56537:12;56569:69;56582:7;53263:1;56604:33;53263:1;-1:-1:-1;;;;;56604:19:0;;;:33;:::i;:::-;56569:12;:69::i;27437:134::-;27495:20;27537:26;27544:4;27550:5;27557;27537:6;:26::i;52755:151::-;52813:13;52846:52;-1:-1:-1;;;;;52858:22:0;;50910:2;52846:11;:52::i;57384:1011::-;57671:4;57665:11;;58065:22;;;-1:-1:-1;;58061:36:0;58051:47;;58038:61;;;58201:18;;;58073:4;58365:5;58079:2;58350:13;;58341:7;58329:48;57384:1011;;;;;:::o;24337:2961::-;24453:20;24583:4;24577:11;24607:10;24604:2676;;;24810:1;24806;24794:10;24790:18;24786:26;24783:1;24779:34;24924:4;24918:11;24908:21;;25303:34;25297:4;25290:48;25431:6;25420:8;25413:16;25409:29;25373:34;25369:70;25363:4;25356:84;25549:4;25541:6;25537:17;25592:13;25587:3;25583:23;25685:624;25738:1;25732:4;25728:12;25720:20;;25801:4;25795:11;25946:4;25938:5;25934:2;25930:14;25926:25;25920:32;25915:3;25907:46;26022:4;26014:5;26010:2;26006:14;26002:25;25996:32;25992:1;25987:3;25983:11;25975:54;26097:4;26089:5;26086:1;26082:13;26078:24;26072:31;26068:1;26063:3;26059:11;26051:53;26164:4;26157:5;26153:16;26147:23;26143:1;26138:3;26134:11;26126:45;;26211:1;26206:3;26202:11;26195:18;;26275:3;26270;26267:12;25685:624;26257:33;26354:1;26338:18;;26383:9;26410:415;;;;26993:1;26990;26987:8;26982:1;26975:9;26968:17;26964:32;26949:13;26945:52;26937:6;26930:68;26376:641;;26410:415;26566:4;26560:1;26553:9;26546:17;26541:3;26537:27;26529:42;26661:4;26655:1;26652;26649:8;26646:1;26642:16;26637:3;26633:26;26625:41;26792:13;26784:6;26777:29;26376:641;-1:-1:-1;;27260:2:0;27242:12;-1:-1:-1;;27238:26:0;27232:4;27225:40;-1:-1:-1;;24604:2676:0;;24337:2961;;;;;:::o;52151:447::-;52226:13;52252:19;52284:10;52288:6;52284:1;:10;:::i;:::-;:14;;52297:1;52284:14;:::i;:::-;-1:-1:-1;;;;;52274:25:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;52274:25:0;;52252:47;;-1:-1:-1;;;52310:6:0;52317:1;52310:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;52310:15:0;;;;;;;;;-1:-1:-1;;;52336:6:0;52343:1;52336:9;;;;;;;;:::i;:::-;;;;:15;-1:-1:-1;;;;;52336:15:0;;;;;;;;-1:-1:-1;52367:9:0;52379:10;52383:6;52379:1;:10;:::i;:::-;:14;;52392:1;52379:14;:::i;:::-;52367:26;;52362:131;52399:1;52395;:5;52362:131;;;-1:-1:-1;;;52443:5:0;52451:3;52443:11;52434:21;;;;;;;:::i;:::-;;;;52422:6;52429:1;52422:9;;;;;;;;:::i;:::-;;;;:33;-1:-1:-1;;;;;52422:33:0;;;;;;;;-1:-1:-1;52480:1:0;52470:11;;;;;52402:3;;;:::i;:::-;;;52362:131;;;-1:-1:-1;52511:10:0;;52503:55;;;;-1:-1:-1;;;52503:55:0;;30663:2:1;52503:55:0;;;30645:21:1;;;30682:18;;;30675:30;30741:34;30721:18;;;30714:62;30793:18;;52503:55:0;30461:356:1;52503:55:0;52583:6;52151:447;-1:-1:-1;;;52151:447:0:o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;14:131:1;-1:-1:-1;;;;;;88:32:1;;78:43;;68:71;;135:1;132;125:12;150:245;208:6;261:2;249:9;240:7;236:23;232:32;229:52;;;277:1;274;267:12;229:52;316:9;303:23;335:30;359:5;335:30;:::i;592:250::-;677:1;687:113;701:6;698:1;695:13;687:113;;;777:11;;;771:18;758:11;;;751:39;723:2;716:10;687:113;;;-1:-1:-1;;834:1:1;816:16;;809:27;592:250::o;847:271::-;889:3;927:5;921:12;954:6;949:3;942:19;970:76;1039:6;1032:4;1027:3;1023:14;1016:4;1009:5;1005:16;970:76;:::i;:::-;1100:2;1079:15;-1:-1:-1;;1075:29:1;1066:39;;;;1107:4;1062:50;;847:271;-1:-1:-1;;847:271:1:o;1123:220::-;1272:2;1261:9;1254:21;1235:4;1292:45;1333:2;1322:9;1318:18;1310:6;1292:45;:::i;1348:180::-;1407:6;1460:2;1448:9;1439:7;1435:23;1431:32;1428:52;;;1476:1;1473;1466:12;1428:52;-1:-1:-1;1499:23:1;;1348:180;-1:-1:-1;1348:180:1:o;1741:173::-;1809:20;;-1:-1:-1;;;;;1858:31:1;;1848:42;;1838:70;;1904:1;1901;1894:12;1919:254;1987:6;1995;2048:2;2036:9;2027:7;2023:23;2019:32;2016:52;;;2064:1;2061;2054:12;2016:52;2087:29;2106:9;2087:29;:::i;:::-;2077:39;2163:2;2148:18;;;;2135:32;;-1:-1:-1;;;1919:254:1:o;2693:127::-;2754:10;2749:3;2745:20;2742:1;2735:31;2785:4;2782:1;2775:15;2809:4;2806:1;2799:15;2825:143;2909:1;2902:5;2899:12;2889:46;;2915:18;;:::i;:::-;2944;;2825:143::o;2973:435::-;3026:3;3064:5;3058:12;3091:6;3086:3;3079:19;3117:4;3146:2;3141:3;3137:12;3130:19;;3183:2;3176:5;3172:14;3204:1;3214:169;3228:6;3225:1;3222:13;3214:169;;;3289:13;;3277:26;;3323:12;;;;3358:15;;;;3250:1;3243:9;3214:169;;;-1:-1:-1;3399:3:1;;2973:435;-1:-1:-1;;;;;2973:435:1:o;3413:1315::-;3604:2;3593:9;3586:21;3649:6;3643:13;3638:2;3627:9;3623:18;3616:41;3711:2;3703:6;3699:15;3693:22;3688:2;3677:9;3673:18;3666:50;3770:2;3762:6;3758:15;3752:22;3747:2;3736:9;3732:18;3725:50;3567:4;3822:2;3814:6;3810:15;3804:22;3835:52;3882:3;3871:9;3867:19;3853:12;2483:10;2472:22;2460:35;;2407:94;3835:52;-1:-1:-1;3936:3:1;3924:16;;3918:23;-1:-1:-1;;;;;2571:30:1;;3999:3;3984:19;;2559:43;-1:-1:-1;4053:3:1;4041:16;;4035:23;-1:-1:-1;;;;;2571:30:1;;4116:3;4101:19;;2559:43;-1:-1:-1;4170:3:1;4158:16;;4152:23;-1:-1:-1;;;;;2571:30:1;;4233:3;4218:19;;2559:43;4184:54;4287:3;4279:6;4275:16;4269:23;4311:3;4323:52;4371:2;4360:9;4356:18;4340:14;2680:4;2669:16;2657:29;;2613:75;4323:52;4412:15;;4406:22;;-1:-1:-1;4447:3:1;4459:64;4504:18;;;4406:22;4459:64;:::i;:::-;4560:15;;4554:22;4595:6;4617:18;;;4610:30;4554:22;-1:-1:-1;4657:65:1;4717:3;4702:19;;4554:22;4657:65;:::i;:::-;4649:73;3413:1315;-1:-1:-1;;;;3413:1315:1:o;4915:328::-;4992:6;5000;5008;5061:2;5049:9;5040:7;5036:23;5032:32;5029:52;;;5077:1;5074;5067:12;5029:52;5100:29;5119:9;5100:29;:::i;:::-;5090:39;;5148:38;5182:2;5171:9;5167:18;5148:38;:::i;:::-;5138:48;;5233:2;5222:9;5218:18;5205:32;5195:42;;4915:328;;;;;:::o;5248:248::-;5316:6;5324;5377:2;5365:9;5356:7;5352:23;5348:32;5345:52;;;5393:1;5390;5383:12;5345:52;-1:-1:-1;;5416:23:1;;;5486:2;5471:18;;;5458:32;;-1:-1:-1;5248:248:1:o;5780:127::-;5841:10;5836:3;5832:20;5829:1;5822:31;5872:4;5869:1;5862:15;5896:4;5893:1;5886:15;5912:255;5984:2;5978:9;6026:6;6014:19;;-1:-1:-1;;;;;6048:34:1;;6084:22;;;6045:62;6042:88;;;6110:18;;:::i;:::-;6146:2;6139:22;5912:255;:::o;6172:275::-;6243:2;6237:9;6308:2;6289:13;;-1:-1:-1;;6285:27:1;6273:40;;-1:-1:-1;;;;;6328:34:1;;6364:22;;;6325:62;6322:88;;;6390:18;;:::i;:::-;6426:2;6419:22;6172:275;;-1:-1:-1;6172:275:1:o;6452:187::-;6501:4;-1:-1:-1;;;;;6526:6:1;6523:30;6520:56;;;6556:18;;:::i;:::-;-1:-1:-1;6622:2:1;6601:15;-1:-1:-1;;6597:29:1;6628:4;6593:40;;6452:187::o;6644:673::-;6713:6;6766:2;6754:9;6745:7;6741:23;6737:32;6734:52;;;6782:1;6779;6772:12;6734:52;6822:9;6809:23;-1:-1:-1;;;;;6847:6:1;6844:30;6841:50;;;6887:1;6884;6877:12;6841:50;6910:22;;6963:4;6955:13;;6951:27;-1:-1:-1;6941:55:1;;6992:1;6989;6982:12;6941:55;7028:2;7015:16;7053:49;7069:32;7098:2;7069:32;:::i;:::-;7053:49;:::i;:::-;7125:2;7118:5;7111:17;7165:7;7160:2;7155;7151;7147:11;7143:20;7140:33;7137:53;;;7186:1;7183;7176:12;7137:53;7241:2;7236;7232;7228:11;7223:2;7216:5;7212:14;7199:45;7285:1;7264:14;;;7280:2;7260:23;7253:34;;;;7268:5;6644:673;-1:-1:-1;;;;6644:673:1:o;7793:186::-;7852:6;7905:2;7893:9;7884:7;7880:23;7876:32;7873:52;;;7921:1;7918;7911:12;7873:52;7944:29;7963:9;7944:29;:::i;7984:566::-;8177:2;8166:9;8159:21;-1:-1:-1;;;;;8226:6:1;8220:13;8216:38;8211:2;8200:9;8196:18;8189:66;8140:4;8302:2;8294:6;8290:15;8284:22;8315:62;8373:2;8362:9;8358:18;8344:12;8315:62;:::i;:::-;;8426:2;8418:6;8414:15;8408:22;8468:4;8461;8450:9;8446:20;8439:34;8490:54;8539:3;8528:9;8524:19;8508:14;8490:54;:::i;8555:118::-;8641:5;8634:13;8627:21;8620:5;8617:32;8607:60;;8663:1;8660;8653:12;8678:315;8743:6;8751;8804:2;8792:9;8783:7;8779:23;8775:32;8772:52;;;8820:1;8817;8810:12;8772:52;8843:29;8862:9;8843:29;:::i;:::-;8833:39;;8922:2;8911:9;8907:18;8894:32;8935:28;8957:5;8935:28;:::i;:::-;8982:5;8972:15;;;8678:315;;;;;:::o;8998:808::-;9095:6;9103;9111;9119;9127;9180:3;9168:9;9159:7;9155:23;9151:33;9148:53;;;9197:1;9194;9187:12;9148:53;9220:29;9239:9;9220:29;:::i;:::-;9210:39;;9268:38;9302:2;9291:9;9287:18;9268:38;:::i;:::-;9258:48;;9353:2;9342:9;9338:18;9325:32;9315:42;;9408:2;9397:9;9393:18;9380:32;-1:-1:-1;;;;;9472:2:1;9464:6;9461:14;9458:34;;;9488:1;9485;9478:12;9458:34;9526:6;9515:9;9511:22;9501:32;;9571:7;9564:4;9560:2;9556:13;9552:27;9542:55;;9593:1;9590;9583:12;9542:55;9633:2;9620:16;9659:2;9651:6;9648:14;9645:34;;;9675:1;9672;9665:12;9645:34;9720:7;9715:2;9706:6;9702:2;9698:15;9694:24;9691:37;9688:57;;;9741:1;9738;9731:12;9688:57;8998:808;;;;-1:-1:-1;8998:808:1;;-1:-1:-1;9772:2:1;9764:11;;9794:6;8998:808;-1:-1:-1;;;8998:808:1:o;9811:260::-;9879:6;9887;9940:2;9928:9;9919:7;9915:23;9911:32;9908:52;;;9956:1;9953;9946:12;9908:52;9979:29;9998:9;9979:29;:::i;:::-;9969:39;;10027:38;10061:2;10050:9;10046:18;10027:38;:::i;:::-;10017:48;;9811:260;;;;;:::o;10076:380::-;10155:1;10151:12;;;;10198;;;10219:61;;10273:4;10265:6;10261:17;10251:27;;10219:61;10326:2;10318:6;10315:14;10295:18;10292:38;10289:161;;10372:10;10367:3;10363:20;10360:1;10353:31;10407:4;10404:1;10397:15;10435:4;10432:1;10425:15;10289:161;;10076:380;;;:::o;10461:335::-;10663:2;10645:21;;;10702:2;10682:18;;;10675:30;-1:-1:-1;;;10736:2:1;10721:18;;10714:41;10787:2;10772:18;;10461:335::o;10801:167::-;10879:13;;10932:10;10921:22;;10911:33;;10901:61;;10958:1;10955;10948:12;10973:175;11051:13;;-1:-1:-1;;;;;11093:30:1;;11083:41;;11073:69;;11138:1;11135;11128:12;11153:160;11230:13;;11283:4;11272:16;;11262:27;;11252:55;;11303:1;11300;11293:12;11318:157;11407:13;;11449:1;11439:12;;11429:40;;11465:1;11462;11455:12;11480:709;11545:5;11598:3;11591:4;11583:6;11579:17;11575:27;11565:55;;11616:1;11613;11606:12;11565:55;11645:6;11639:13;11671:4;-1:-1:-1;;;;;11690:2:1;11687:26;11684:52;;;11716:18;;:::i;:::-;11762:2;11759:1;11755:10;11785:28;11809:2;11805;11801:11;11785:28;:::i;:::-;11847:15;;;11917;;;11913:24;;;11878:12;;;;11949:15;;;11946:35;;;11977:1;11974;11967:12;11946:35;12013:2;12005:6;12001:15;11990:26;;12025:135;12041:6;12036:3;12033:15;12025:135;;;12107:10;;12095:23;;12058:12;;;;12138;;;;12025:135;;;12178:5;11480:709;-1:-1:-1;;;;;;;11480:709:1:o;12194:1295::-;12295:6;12348:2;12336:9;12327:7;12323:23;12319:32;12316:52;;;12364:1;12361;12354:12;12316:52;12397:9;12391:16;-1:-1:-1;;;;;12467:2:1;12459:6;12456:14;12453:34;;;12483:1;12480;12473:12;12453:34;12506:22;;;;12562:6;12544:16;;;12540:29;12537:49;;;12582:1;12579;12572:12;12537:49;12608:22;;:::i;:::-;12659:2;12653:9;12646:5;12639:24;12709:2;12705;12701:11;12695:18;12690:2;12683:5;12679:14;12672:42;12760:2;12756;12752:11;12746:18;12741:2;12734:5;12730:14;12723:42;12797:41;12834:2;12830;12826:11;12797:41;:::i;:::-;12792:2;12785:5;12781:14;12774:65;12872:42;12909:3;12905:2;12901:12;12872:42;:::i;:::-;12866:3;12859:5;12855:15;12848:67;12948:42;12985:3;12981:2;12977:12;12948:42;:::i;:::-;12942:3;12935:5;12931:15;12924:67;13024:42;13061:3;13057:2;13053:12;13024:42;:::i;:::-;13018:3;13011:5;13007:15;13000:67;13100:41;13136:3;13132:2;13128:12;13100:41;:::i;:::-;13094:3;13087:5;13083:15;13076:66;13161:3;13196:52;13244:2;13240;13236:11;13196:52;:::i;:::-;13180:14;;;13173:76;13268:3;13302:11;;;13296:18;13326:16;;;13323:36;;;13355:1;13352;13345:12;13323:36;13391:67;13450:7;13439:8;13435:2;13431:17;13391:67;:::i;:::-;13375:14;;;13368:91;;;;-1:-1:-1;13379:5:1;12194:1295;-1:-1:-1;;;;;12194:1295:1:o;13494:127::-;13555:10;13550:3;13546:20;13543:1;13536:31;13586:4;13583:1;13576:15;13610:4;13607:1;13600:15;13626:127;13687:10;13682:3;13678:20;13675:1;13668:31;13718:4;13715:1;13708:15;13742:4;13739:1;13732:15;13758:120;13798:1;13824;13814:35;;13829:18;;:::i;:::-;-1:-1:-1;13863:9:1;;13758:120::o;14809:168::-;14882:9;;;14913;;14930:15;;;14924:22;;14910:37;14900:71;;14951:18;;:::i;15723:112::-;15755:1;15781;15771:35;;15786:18;;:::i;:::-;-1:-1:-1;15820:9:1;;15723:112::o;16971:319::-;17160:25;;;17148:2;17133:18;;17215:1;17204:13;;17194:47;;17221:18;;:::i;:::-;17277:6;17272:2;17261:9;17257:18;17250:34;16971:319;;;;;:::o;19691:443::-;19745:5;19798:3;19791:4;19783:6;19779:17;19775:27;19765:55;;19816:1;19813;19806:12;19765:55;19845:6;19839:13;19876:49;19892:32;19921:2;19892:32;:::i;19876:49::-;19950:2;19941:7;19934:19;19996:3;19989:4;19984:2;19976:6;19972:15;19968:26;19965:35;19962:55;;;20013:1;20010;20003:12;19962:55;20026:77;20100:2;20093:4;20084:7;20080:18;20073:4;20065:6;20061:17;20026:77;:::i;20139:931::-;20241:6;20294:2;20282:9;20273:7;20269:23;20265:32;20262:52;;;20310:1;20307;20300:12;20262:52;20343:9;20337:16;-1:-1:-1;;;;;20413:2:1;20405:6;20402:14;20399:34;;;20429:1;20426;20419:12;20399:34;20452:22;;;;20508:4;20490:16;;;20486:27;20483:47;;;20526:1;20523;20516:12;20483:47;20559:2;20553:9;20601:4;20593:6;20589:17;20656:6;20644:10;20641:22;20636:2;20624:10;20621:18;20618:46;20615:72;;;20667:18;;:::i;:::-;20703:2;20696:22;20742:32;20771:2;20742:32;:::i;:::-;20734:6;20727:48;20808:52;20856:2;20852;20848:11;20808:52;:::i;:::-;20803:2;20795:6;20791:15;20784:77;20900:2;20896;20892:11;20886:18;20929:2;20919:8;20916:16;20913:36;;;20945:1;20942;20935:12;20913:36;20982:56;21030:7;21019:8;21015:2;21011:17;20982:56;:::i;:::-;20977:2;20965:15;;20958:81;-1:-1:-1;20969:6:1;20139:931;-1:-1:-1;;;;;20139:931:1:o;21075:289::-;21206:3;21244:6;21238:13;21260:66;21319:6;21314:3;21307:4;21299:6;21295:17;21260:66;:::i;:::-;21342:16;;;;;21075:289;-1:-1:-1;;21075:289:1:o;21369:337::-;21449:6;21502:2;21490:9;21481:7;21477:23;21473:32;21470:52;;;21518:1;21515;21508:12;21470:52;21551:9;21545:16;-1:-1:-1;;;;;21576:6:1;21573:30;21570:50;;;21616:1;21613;21606:12;21570:50;21639:61;21692:7;21683:6;21672:9;21668:22;21639:61;:::i;22760:1693::-;23474:66;23469:3;23462:79;23571:66;23566:2;23561:3;23557:12;23550:88;23668:34;23663:2;23658:3;23654:12;23647:56;23742:30;23737:3;23733:40;23728:2;23723:3;23719:12;23712:62;23805:28;23799:3;23794;23790:13;23783:51;23444:3;23863:6;23857:13;23879:74;23946:6;23940:3;23935;23931:13;23926:2;23918:6;23914:15;23879:74;:::i;:::-;-1:-1:-1;;;24012:3:1;23972:16;;;24004:12;;;23997:36;24063:66;24057:3;24049:12;;24042:88;-1:-1:-1;;;24154:3:1;24146:12;;24139:77;24241:13;;24263:75;24241:13;24323:3;24315:12;;24310:2;24298:15;;24263:75;:::i;:::-;-1:-1:-1;;;24398:3:1;24357:17;;;;24390:12;;;24383:36;24443:3;24435:12;;22760:1693;-1:-1:-1;;;;22760:1693:1:o;24458:461::-;24720:31;24715:3;24708:44;24690:3;24781:6;24775:13;24797:75;24865:6;24860:2;24855:3;24851:12;24844:4;24836:6;24832:17;24797:75;:::i;:::-;24892:16;;;;24910:2;24888:25;;24458:461;-1:-1:-1;;24458:461:1:o;25233:245::-;25300:6;25353:2;25341:9;25332:7;25328:23;25324:32;25321:52;;;25369:1;25366;25359:12;25321:52;25401:9;25395:16;25420:28;25442:5;25420:28;:::i;26511:427::-;26771:1;26766:3;26759:14;26741:3;26802:6;26796:13;26818:74;26885:6;26881:1;26876:3;26872:11;26865:4;26857:6;26853:17;26818:74;:::i;:::-;26912:16;;;;26930:1;26908:24;;26511:427;-1:-1:-1;;26511:427:1:o;26943:462::-;-1:-1:-1;;;27191:47:1;;27261:13;;27173:3;;27283:75;27261:13;27346:2;27337:12;;27330:4;27318:17;;27283:75;:::i;:::-;27378:16;;;;27396:2;27374:25;;26943:462;-1:-1:-1;;26943:462:1:o;28316:249::-;28385:6;28438:2;28426:9;28417:7;28413:23;28409:32;28406:52;;;28454:1;28451;28444:12;28406:52;28486:9;28480:16;28505:30;28529:5;28505:30;:::i;29258:662::-;-1:-1:-1;;;;;29537:15:1;;;29519:34;;29589:15;;29584:2;29569:18;;29562:43;29636:2;29621:18;;29614:34;;;29684:3;29679:2;29664:18;;29657:31;;;29704:19;;29697:35;;;29462:4;29725:6;29775;29499:3;29754:19;;29741:49;29840:1;29834:3;29825:6;29814:9;29810:22;29806:32;29799:43;29910:3;29903:2;29899:7;29894:2;29886:6;29882:15;29878:29;29867:9;29863:45;29859:55;29851:63;;29258:662;;;;;;;;:::o;29925:128::-;29992:9;;;30013:11;;;30010:37;;;30027:18;;:::i;30058:125::-;30123:9;;;30144:10;;;30141:36;;;30157:18;;:::i;30188:127::-;30249:10;30244:3;30240:20;30237:1;30230:31;30280:4;30277:1;30270:15;30304:4;30301:1;30294:15;30320:136;30359:3;30387:5;30377:39;;30396:18;;:::i;:::-;-1:-1:-1;;;30432:18:1;;30320:136::o

Swarm Source

ipfs://0a818f8f65358f192c7cceb0f2f6dd2e30cf8e48298a42d5f485a088c7ee9779
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.