ETH Price: $3,450.66 (+0.94%)

Token

Paintings of Forgotten Souls (SOULS)
 

Overview

Max Total Supply

0 SOULS

Holders

125

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A

Other Info

Balance
1 SOULS
0xeEfbADa5539f9ae2c87C1151Cdb2057398383342
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:
Souls

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion
File 1 of 11 : Souls.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./ERC721.sol";
import "./utils/Base64.sol";

import "./SoulsDescriptor.sol";

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract Souls is ERC721 {

    address public owner = 0xaF69610ea9ddc95883f97a6a3171d52165b69B03; // for opensea integration. doesn't do anything else.

    address public collector; // address authorised to withdraw funds recipient
    address payable public recipient; // in this instance, it will be a mirror split on mainnet. 0xec0ef86a3872829F3EC40de1b1b9Df54a3D4a4b3

    uint256 public buyableSoulSupply;

    // minting time
    uint256 public startDate;
    uint256 public endDate;

    mapping(uint256 => bool) public soulsType; // true == full soul

    SoulsDescriptor public descriptor;

    ERC721 public anchorCertificates;

    // uint256 public newlyMinted;

    mapping(uint256 => bool) public claimedACIDs;

    event Claim(address indexed claimer, uint256 indexed tokenId);

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor (string memory name_, string memory symbol_, address collector_, address payable recipient_, uint256 startDate_, uint256 endDate_, address certificates_) ERC721(name_, symbol_) {
        collector = collector_; 
        recipient = recipient_;
        startDate = startDate_;
        endDate = endDate_;
        descriptor = new SoulsDescriptor();
        anchorCertificates = ERC721(certificates_);

        /* INITIAL CLAIM/MINT */
        // initial claim for un_frontier outside campaign window.
        // allows metadata + graph + storefronts to propagate before launch.
        // let this initial claim come from simondlr's personal collection of anchor certificates.
        // it is default certificate #1.
        // https://opensea.io/assets/0x600a4446094c341693c415e6743567b9bfc8a4a8/86944833354306826451453519009172227432197817959411860297499850535918774474487
        claimedACIDs[86944833354306826451453519009172227432197817959411860297499850535918774474487] = true;
        _createSoul(true,address(0xaF69610ea9ddc95883f97a6a3171d52165b69B03)); // claim the soul for untitled frontier, not simondlr.
        emit Claim(0xaF69610ea9ddc95883f97a6a3171d52165b69B03, 86944833354306826451453519009172227432197817959411860297499850535918774474487);
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory soulType = "Sketched";
        if(soulsType[tokenId] == true) {
            soulType = "Fully Painted";
        }

        string memory name = descriptor.generateName(soulType, tokenId); 
        string memory description = "Paintings of forgotten souls by various simulated minds that try to remember those who they once knew in the default world.";

        string memory image = generateBase64Image(tokenId);
        string memory attributes = generateTraits(tokenId);
        return string(
            abi.encodePacked(
                'data:application/json;base64,',
                Base64.encode(
                    bytes(
                        abi.encodePacked(
                            '{"name":"', 
                            name,
                            '", "description":"', 
                            description,
                            '", "image": "', 
                            'data:image/svg+xml;base64,', 
                            image,'",',
                            attributes,
                            '}'
                        )
                    )
                )
            )
        );
    }

    function generateBase64Image(uint256 tokenId) public view returns (string memory) {
        bytes memory img = bytes(generateImage(tokenId));
        return Base64.encode(img);
    }

    function generateImage(uint256 tokenId) public view returns (string memory) {
        return descriptor.generateImage(tokenId, soulsType[tokenId]);
    }

    function generateTraits(uint256 tokenId) public view returns (string memory) {
        return descriptor.generateTraits(tokenId, soulsType[tokenId]);
    }

    /*
    Owners of Anchor Certificates can claim a full soul.
    Max 160.
    */
    function claimSoul(uint ACID) public  {
        require(block.timestamp > startDate, "NOT_STARTED"); // ~ 2000 gas
        require(block.timestamp < endDate, "ENDED");
        require(claimedACIDs[ACID] == false, "AC_ID ALREADY CLAIMED");
        require(anchorCertificates.ownerOf(ACID) == msg.sender, "AC_ID NOT OWNED BY SENDER");

        claimedACIDs[ACID] = true;
        _createSoul(true, msg.sender);
        emit Claim(msg.sender, ACID);
    }

    function mintSoul() public payable {
        require(block.timestamp > startDate, "NOT_STARTED"); // ~ 2000 gas
        require(block.timestamp < endDate, "ENDED");
        require(msg.value >= 0.010 ether, 'MORE ETH NEEDED'); //~$30

        if(msg.value >= 0.068 ether) { //~$200
            buyableSoulSupply += 1;
            require(buyableSoulSupply <= 96, "MAX_SOLD_96");
            _createSoul(true, msg.sender);
        } else { // don't need to check ETH amount here since it is checked in the require above
            _createSoul(false, msg.sender);
        }
    }

    function _createSoul(bool fullSoul, address _owner) internal {
        uint256 tokenId = uint(keccak256(abi.encodePacked(block.timestamp, _owner)));
        soulsType[tokenId] = fullSoul;
        // newlyMinted = tokenId; // tests
        super._mint(_owner, tokenId);
    }

    function withdrawETH() public {
        require(msg.sender == collector, "NOT_COLLECTOR");
        recipient.transfer(address(this).balance);
    }
}

File 2 of 11 : ERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./interfaces/IERC721.sol";
import "./interfaces/IERC721Receiver.sol";
import "./interfaces/IERC721Metadata.sol";
import "./utils/Address.sol";
// import "../../utils/Context.sol";
import "./utils/Strings.sol";
import "./ERC165.sol";

/**
 * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
 * the Metadata extension, but not including the Enumerable extension, which is available separately as
 * {ERC721Enumerable}.
 */
contract ERC721 is ERC165, IERC721, IERC721Metadata {
    using Address for address;
    using Strings for uint256;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

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

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

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

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
     */
    constructor (string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

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

    /**
     * @dev See {IERC721-balanceOf}.
     */
    function balanceOf(address owner) public view virtual override returns (uint256) {
        require(owner != address(0), "ERC721: balance query for the zero address");
        return _balances[owner];
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        address owner = _owners[tokenId];
        require(owner != address(0), "ERC721: owner query for nonexistent token");
        return owner;
    }

    /**
     * @dev See {IERC721Metadata-name}.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev See {IERC721Metadata-symbol}.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev See {IERC721Metadata-tokenURI}.
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory baseURI = _baseURI();
        return bytes(baseURI).length > 0
            ? string(abi.encodePacked(baseURI, tokenId.toString()))
            : '';
    }

    /**
     * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
     * token will be the concatenation of the `baseURI` and the `tokenId`. Empty 
     * by default, can be overriden in child contracts.
     */
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = ERC721.ownerOf(tokenId);
        require(to != owner, "ERC721: approval to current owner");

        require(msg.sender == owner || isApprovedForAll(owner, msg.sender),
            "ERC721: approve caller is not owner nor approved for all"
        );

        _approve(to, tokenId);
    }

    /**
     * @dev See {IERC721-getApproved}.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        require(_exists(tokenId), "ERC721: approved query for nonexistent token");

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        require(operator != msg.sender, "ERC721: approve to caller");

        _operatorApprovals[msg.sender][operator] = approved;
        emit ApprovalForAll(msg.sender, operator, approved);
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return _operatorApprovals[owner][operator];
    }

    /**
     * @dev See {IERC721-transferFrom}.
     */
    function transferFrom(address from, address to, uint256 tokenId) public virtual override {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: transfer caller is not owner nor approved");

        _transfer(from, to, tokenId);
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) public virtual override {
        safeTransferFrom(from, to, tokenId, "");
    }

    /**
     * @dev See {IERC721-safeTransferFrom}.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public virtual override {
        require(_isApprovedOrOwner(msg.sender, tokenId), "ERC721: transfer caller is not owner nor approved");
        _safeTransfer(from, to, tokenId, _data);
    }

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * `_data` is additional data, it has no specified format and it is sent in call to `to`.
     *
     * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
     * implement alternative mechanisms to perform token transfer, such as signature-based.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeTransfer(address from, address to, uint256 tokenId, bytes memory _data) internal virtual {
        _transfer(from, to, tokenId);
        require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Returns whether `tokenId` exists.
     *
     * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
     *
     * Tokens start existing when they are minted (`_mint`),
     * and stop existing when they are burned (`_burn`).
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool) {
        return _owners[tokenId] != address(0);
    }

    /**
     * @dev Returns whether `spender` is allowed to manage `tokenId`.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        require(_exists(tokenId), "ERC721: operator query for nonexistent token");
        address owner = ERC721.ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function _safeMint(address to, uint256 tokenId) internal virtual {
        _safeMint(to, tokenId, "");
    }

    /**
     * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
     * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
     */
    function _safeMint(address to, uint256 tokenId, bytes memory _data) internal virtual {
        _mint(to, tokenId);
        require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
    }

    /**
     * @dev Mints `tokenId` and transfers it to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
     *
     * Requirements:
     *
     * - `tokenId` must not exist.
     * - `to` cannot be the zero address.
     *
     * Emits a {Transfer} event.
     */
    function _mint(address to, uint256 tokenId) internal virtual {
        require(to != address(0), "ERC721: mint to the zero address");
        require(!_exists(tokenId), "ERC721: token already minted");

        // _beforeTokenTransfer(address(0), to, tokenId);

        _balances[to] += 1;
        _owners[tokenId] = to;

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

    /**
     * @dev Destroys `tokenId`.
     * The approval is cleared when the token is burned.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     *
     * Emits a {Transfer} event.
     */
    function _burn(uint256 tokenId) internal virtual {
        address owner = ERC721.ownerOf(tokenId);

        // _beforeTokenTransfer(owner, address(0), tokenId);

        // Clear approvals
        _approve(address(0), tokenId);

        _balances[owner] -= 1;
        delete _owners[tokenId];

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

    /**
     * @dev Transfers `tokenId` from `from` to `to`.
     *  As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     *
     * Emits a {Transfer} event.
     */
    function _transfer(address from, address to, uint256 tokenId) internal virtual {
        require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
        require(to != address(0), "ERC721: transfer to the zero address");

        // _beforeTokenTransfer(from, to, tokenId);

        // Clear approvals from the previous owner
        _approve(address(0), tokenId);

        _balances[from] -= 1;
        _balances[to] += 1;
        _owners[tokenId] = to;

        emit Transfer(from, to, tokenId);
    }

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits a {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        _tokenApprovals[tokenId] = to;
        emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
    }

    /**
     * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
     * The call is not executed if the target address is not a contract.
     *
     * @param from address representing the previous owner of the given token ID
     * @param to target address that will receive the tokens
     * @param tokenId uint256 ID of the token to be transferred
     * @param _data bytes optional data to send along with the call
     * @return bool whether the call correctly returned the expected magic value
     */
    function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
        private returns (bool)
    {
        if (to.isContract()) {
            try IERC721Receiver(to).onERC721Received(msg.sender, from, tokenId, _data) returns (bytes4 retval) {
                return retval == IERC721Receiver(to).onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert("ERC721: transfer to non ERC721Receiver implementer");
                } else {
                    // solhint-disable-next-line no-inline-assembly
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }

    // modified from ERC721 template:
    // removed BeforeTokenTransfer
}

File 3 of 11 : Base64.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @title Base64
/// @author Brecht Devos - <[email protected]>
/// @notice Provides a function for encoding some bytes in base64
library Base64 {
    string internal constant TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

    function encode(bytes memory data) internal pure returns (string memory) {
        if (data.length == 0) return '';
        
        // load the table into memory
        string memory table = TABLE;

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

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

        assembly {
            // set the actual output length
            mstore(result, encodedLen)
            
            // prepare the lookup table
            let tablePtr := add(table, 1)
            
            // input ptr
            let dataPtr := data
            let endPtr := add(dataPtr, mload(data))
            
            // result ptr, jump over length
            let resultPtr := add(result, 32)
            
            // run over the input, 3 bytes at a time
            for {} lt(dataPtr, endPtr) {}
            {
               dataPtr := add(dataPtr, 3)
               
               // read 3 bytes
               let input := mload(dataPtr)
               
               // write 4 characters
               mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F)))))
               resultPtr := add(resultPtr, 1)
               mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F)))))
               resultPtr := add(resultPtr, 1)
               mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr( 6, input), 0x3F)))))
               resultPtr := add(resultPtr, 1)
               mstore(resultPtr, shl(248, mload(add(tablePtr, and(        input,  0x3F)))))
               resultPtr := add(resultPtr, 1)
            }
            
            // padding with '='
            switch mod(mload(data), 3)
            case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) }
            case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) }
        }
        
        return result;
    }
}

File 4 of 11 : SoulsDescriptor.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/*
Contract that's primarily responsible for generating the metadata, including the image itself in SVG.
Parts of the SVG is encapsulated into custom re-usable components specific to this collection.
*/
contract SoulsDescriptor {

    function generateName(string memory soulType, uint soulNr) public pure returns (string memory) {
        return string(abi.encodePacked(soulType, ' Forgotten Soul #', substring(toString(soulNr),0,8)));
    }

    function generateTraits(uint256 tokenId, bool fullSoul) public pure returns (string memory) {
        bytes memory hash = abi.encodePacked(bytes32(tokenId));

        string memory paintingTraits = "";

        string memory paintingType = string(abi.encodePacked('{"trait_type": "Type", "value": "Fully Painted"},'));
        if(fullSoul == false) { paintingType = string(abi.encodePacked('{"trait_type": "Type", "value": "Sketch"},'));}

        (uint colour1, uint colour2, uint colour3) = generateColours(hash);
        string memory compositionType = getColourCompositionType(toUint8(hash,2));
        uint saturation = 60 - uint256(toUint8(hash,30))*55/255;

        string memory layersTrait = "";
        uint layers;

        bool colours;
        if(toUint8(hash,22) < 128 || fullSoul == true) { 
            paintingTraits = string(abi.encodePacked(paintingTraits, '{"value": "Background"}, {"trait_type": "Colour 1", "value":"',toString(colour1),'" },')); 
            layers++;
            colours = true;
        }
        if(toUint8(hash,23) < 128 || fullSoul == true) { paintingTraits = string(abi.encodePacked(paintingTraits, '{"value": "Frame"},')); layers++; }
        if(toUint8(hash,24) < 128 || fullSoul == true) { paintingTraits = string(abi.encodePacked(paintingTraits, '{"value": "Back Splash"},')); layers++; }
        if(toUint8(hash,25) < 128 || fullSoul == true) { paintingTraits = string(abi.encodePacked(paintingTraits, '{"value": "Body"},')); layers++; }
        if(toUint8(hash,26) < 128 || fullSoul == true) { 
            paintingTraits = string(abi.encodePacked(paintingTraits, '{"value": "Back Head"}, {"trait_type": "Colour 2", "value": "',toString(colour2),'" },')); 
            layers++; 
            colours = true;
        }
        if(toUint8(hash,27) < 128 || fullSoul == true) { 
            paintingTraits = string(abi.encodePacked(paintingTraits, '{"value": "Front Head"}, {"trait_type": "Colour 3", "value": "',toString(colour3),'" },')); 
            layers++; 
            colours = true; 
        }
        if(toUint8(hash,28) < 128 || fullSoul == true) { paintingTraits = string(abi.encodePacked(paintingTraits, '{"value": "Rings"},')); layers++; }
        if(toUint8(hash,29) < 128 || fullSoul == true) { paintingTraits = string(abi.encodePacked(paintingTraits, '{"value": "Eyes"},')); layers++; }

        layersTrait = string(abi.encodePacked('{"trait_type": "Layers", "value": "',toString(layers),'"}'));

        string memory colourCompositionTrait;
        if(colours == true) { colourCompositionTrait = string(abi.encodePacked('{"trait_type": "Colour Composition Type", "value": "',compositionType,'" }, {"trait_type": "Saturation", "value": "',toString(saturation),'" },')); }

        return string(abi.encodePacked(
            '"attributes": [',
            paintingType,
            colourCompositionTrait,
            paintingTraits,
            layersTrait,
            ']'
        ));
    }

    function generateImage(uint256 tokenId, bool fullSoul) public pure returns (string memory) {
        bytes memory hash = abi.encodePacked(bytes32(tokenId));

        (uint colour1, uint colour2, uint colour3) = generateColours(hash);

        string memory background = "";
        string memory innerFrame = "";
        string memory backSplash = "";
        string memory body = "";
        string memory backHead = "";
        string memory frontHead = "";
        string memory rings = "";
        string memory eyes = "";

        // Hash Bytes used to this point-> 21
        if(toUint8(hash,22) < 128 || fullSoul == true) { background = generateBackground(hash, colour1); }
        if(toUint8(hash,23) < 128 || fullSoul == true) { innerFrame = generateInnerFrame(hash); }
        if(toUint8(hash,24) < 128 || fullSoul == true) { backSplash = generateBackSplash(hash); }
        if(toUint8(hash,25) < 128 || fullSoul == true) { body = generateBody(hash); }
        if(toUint8(hash,26) < 128 || fullSoul == true) { backHead = generateBackHead(hash, colour2); }
        if(toUint8(hash,27) < 128 || fullSoul == true) { frontHead = generateFrontHead(hash, colour3); }
        if(toUint8(hash,28) < 128 || fullSoul == true) { rings = generateRings(hash);}
        if(toUint8(hash,29) < 128 || fullSoul == true) { eyes = generateEyes(hash); }

        return string(
            abi.encodePacked(
                '<svg width="600" height="600" viewBox="0 0 600 600" xmlns="http://www.w3.org/2000/svg">',
                '<rect x="0" y="0" width="600" height="600" fill="white" />',
                background,
                innerFrame,
                backSplash,
                body,
                backHead,
                frontHead,
                rings,
                eyes,
                '</svg>'
            )
        );
    }

    function generateColours(bytes memory hash) public pure returns (uint, uint, uint) {
        uint colour1 = uint256(toUint8(hash,1))*360/255; 
        uint colourCompositionByte = toUint8(hash,2);
        uint colour2;
        uint colour3;
        string memory compositionType = getColourCompositionType(colourCompositionByte);

        if(keccak256(bytes(compositionType)) == keccak256(bytes('Split Composition'))) {
            //split composition
            colour2 = (colour1+150) % 360;
            colour3 = (colour1+210) % 360;
        } else if(keccak256(bytes(compositionType)) == keccak256(bytes('Triad Composition'))) {
            // triad composition
            colour2 = (colour1+120) % 360;
            colour3 = (colour1+240) % 360;
        } else {
            // analogous composition
            colour2 = (colour1+30) % 360;
            colour3 = (colour1+90) % 360;
        }

        return (colour1, colour2, colour3);
    }

    function getColourCompositionType(uint compositionByte) public pure returns (string memory) {
        if(compositionByte >= 0 && compositionByte < 85) {
            return 'Split Composition';
        } else if(compositionByte >=85 && compositionByte < 170) {
            return 'Triad Composition';
        } else {
            return 'Analogous Composition';
        }
    }

    /* GENERATION FUNCTIONS (in order of layers) */

    // Layer 1 - Background.
    // Hash Bytes Used - 3,4,5
    function generateBackground(bytes memory hash, uint colour1) public pure returns (string memory) {
        uint backgroundFrequency = uint256(toUint8(hash,3))*1000/255; 
        uint backgroundSurfaceScale = uint256(toUint8(hash,4))*10/255;
        uint elevation = 50 + uint256(toUint8(hash,5))*90/255; 
        uint saturation = 60 - uint256(toUint8(hash,30))*55/255;
        return string(abi.encodePacked(
            svgFilter("backgroundDisplacement"),
            svgFeTurbulence("100",generateDecimalString(backgroundFrequency,2)),
            '<feMorphology in="turbulence" result="morphed" operator="erode" radius="1"></feMorphology>',
            '<feDiffuseLighting in="morphed" lighting-color="hsl(',toString(colour1),', ',toString(saturation),'%, 50%)" surfaceScale="',toString(backgroundSurfaceScale),'"><feDistantLight azimuth="45" elevation="',toString(elevation),'" /></feDiffuseLighting>',
            '</filter><rect x="0" y="0" width="600" height="600" style="filter: url(#backgroundDisplacement)" />'
        ));
    }

    // Layer 2 - Inner Frame
    // Hash Bytes Used - 6,7
    function generateInnerFrame(bytes memory hash) public pure returns (string memory) {
        uint frameFrequency = uint256(toUint8(hash,6))*1000/255; 
        uint frameSeed = uint256(toUint8(hash,6))*1000/255; // added in post. more variation.
        uint frameStrokeWidth = uint256(toUint8(hash,7))*40/255;

        return string(abi.encodePacked(
            svgFilter("frameDisplacement"),
            svgFeTurbulence(toString(frameSeed),generateDecimalString(frameFrequency,4)),
            '<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="50" xChannelSelector="G" yChannelSelector="A"/></filter>',
            '<rect x="50" y="50" width="500" height="500" stroke="black" opacity="0.5" fill="white" stroke-width="',toString(frameStrokeWidth),'" style="filter: url(#frameDisplacement)"/>'
        ));
    }

    // Layer 3 - Back Splash
    // Hash Bytes Used - 8,9
    function generateBackSplash(bytes memory hash) public pure returns (string memory) {
        uint8 radii = toUint8(hash,0)/3;
        uint backSplashFrequency = uint256(toUint8(hash,8))*1000/255; 
        uint backStrokeWidth = uint256(toUint8(hash,9))*40/255;

        return string(abi.encodePacked(
            '<defs>',
            '<linearGradient id="backSplashGrad" x2="0%" y2="100%">',
            '<stop offset="0%" stop-color="black" />',
            '<stop offset="50%" stop-color="white" />',
            '</linearGradient>',
            '</defs>',
            svgFilter("backSplash"),
            svgFeTurbulence("2000",generateDecimalString(backSplashFrequency,4)),
            '<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="200" xChannelSelector="G" yChannelSelector="A"/></filter>',
            svgCircle("300","270",toString(170-radii),"url(#backSplashGrad)",toString(backStrokeWidth),"none", "filter: url(#backSplash)")
        ));
    }

    // Layer 4 - Body
    // Hash Bytes Used - 10
    function generateBody(bytes memory hash) public pure returns (string memory) {
        uint8 radii = toUint8(hash,0)/3;
        uint bodyFrequency = uint256(toUint8(hash,10))*1000/255;  

        return string(abi.encodePacked(
            svgFilter("bodyDisplacement"),
            svgFeTurbulence("100",generateDecimalString(bodyFrequency,4)),
            '<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="50" xChannelSelector="R" yChannelSelector="G"/> </filter>',
            svgCircle("300",toString(700-radii),toString(180-radii),"black","0","black","filter: url(#bodyDisplacement)")
        ));
    }

    // Layer 5 - Back Head
    // Hash Bytes Used - 11,12
    function generateBackHead(bytes memory hash, uint colour2) public pure returns (string memory) {
        uint8 radii = toUint8(hash,0)/3;
        uint backHeadFrequency = uint256(toUint8(hash,11))*1000/255; 
        uint backHeadScale = uint256(toUint8(hash,12))*400/255;
        uint saturation = 60 - uint256(toUint8(hash,30))*55/255;

        string memory fill = string(abi.encodePacked('hsl(',toString(colour2),', ',toString(saturation),'%, 50%)'));

        return string(abi.encodePacked(
            svgFilter("headDisplacement"), 
            svgFeTurbulence("100",generateDecimalString(backHeadFrequency,3)),
            '<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="',toString(backHeadScale),'" xChannelSelector="G" yChannelSelector="A"/> </filter>',
            svgCircle("300","270",toString(140-radii), "none", "0", fill, "filter: url(#headDisplacement)")
        ));
    }

    // Layer 6 - Front Head
    // Hash Bytes Used - 13,14
    function generateFrontHead(bytes memory hash, uint colour3) public pure returns (string memory) {
        uint8 radii = toUint8(hash,0)/3;
        uint frontHeadFrequency = uint256(toUint8(hash,13))*1000/255; 
        uint frontHeadFrequency2 = uint256(toUint8(hash,14))*1000/255; // added in post. more variation.
        uint frontHeadScale = uint256(toUint8(hash,14))*400/255;
        uint saturation = 60 - uint256(toUint8(hash,30))*55/255;

        string memory fill = string(abi.encodePacked('hsl(',toString(colour3),', ',toString(saturation),'%, 50%)'));
        
        return string(abi.encodePacked(
            svgFilter("headDisplacement2"), 
            '<feTurbulence type="turbulence" seed="50" baseFrequency="',generateDecimalString(frontHeadFrequency,3),',',generateDecimalString(frontHeadFrequency2,3),'" numOctaves="5" result="turbulence"/>'
            '<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="',toString(frontHeadScale),'" xChannelSelector="G" yChannelSelector="R"/> </filter>',
            svgCircle("300","270",toString(120-radii), "none", "0", fill, "filter: url(#headDisplacement2)")
        ));
    }

    // Layer 7 - Rings
    // Hash Bytes Used - 15,16,17,18,19,20
    function generateRings(bytes memory hash) public pure returns (string memory) {
        string memory ring1 = generateRing(hash, "ringDisplacement1", 15, 16, "grey", "R", "filter: url(#ringDisplacement1)");        
        string memory ring2 = generateRing(hash, "ringDisplacement2", 17, 18, "black", "G", "filter: url(#ringDisplacement2)");        
        string memory ring3 = generateRing(hash, "ringDisplacement3", 19, 20, "black", "B", "filter: url(#ringDisplacement3)");        

        return string(abi.encodePacked(ring1, ring2, ring3));
    }

    function generateRing(bytes memory hash, string memory id, uint seedIndex1, uint seedIndex2, string memory stroke, string memory xChannel, string memory style) public pure returns (string memory) {
        uint8 radii = toUint8(hash,0)/3;
        uint ringSeed = uint256(toUint8(hash,seedIndex1))*1000/255;
        uint ringFrequency = uint256(toUint8(hash,seedIndex2))*1000/255;  

        return string(abi.encodePacked(
            svgFilter(id), 
            svgFeTurbulence(toString(ringSeed), generateDecimalString(ringFrequency,4)),
            '<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="200" xChannelSelector="',xChannel,'" yChannelSelector="A" /> </filter>',
            svgCircle("300","270",toString(140-radii),stroke,"4","none",style)
        ));
    }

    // Layer 8 - Eyes
    // Hash Bytes Used - 21
    function generateEyes(bytes memory hash) public pure returns (string memory) {
        uint eyesFrequency = uint256(toUint8(hash,21))*1000/255; 
        uint eyesRadius = 25 - uint256(toUint8(hash,21))*15/255; 

        string memory eyeDisplacement = string(abi.encodePacked(
            svgFilter("eyeDisplacement"),
            svgFeTurbulence("100", generateDecimalString(eyesFrequency,4)),
            '<feDisplacementMap in2="turbulence" in="SourceGraphic" scale="100" xChannelSelector="R" yChannelSelector="G"/></filter>'
        ));

        string memory eyes = string(abi.encodePacked(
            svgCircle("250","270",toString(eyesRadius),"black","1","white","filter: url(#eyeDisplacement)"),
            svgCircle("320","270",toString(eyesRadius),"black","1","white","filter: url(#eyeDisplacement)")
        ));

        return string(abi.encodePacked(eyeDisplacement,eyes));
    }

    function svgCircle(string memory cx, string memory cy, string memory r, string memory stroke, string memory strokeWidth, string memory fill, string memory style) public pure returns (string memory) {
        return string(abi.encodePacked(
            '<circle cx="',cx,'" cy="',cy,'" r="',r,'" stroke="',stroke,'" fill="',fill,'" stroke-width="',strokeWidth,'" style="',style,'"/>'
        ));
    }

    function svgFilter(string memory id) public pure returns (string memory) {
        return string(abi.encodePacked('<filter id="',id,'" width="300%" height="300%">'));
    }

    function svgFeTurbulence(string memory seed, string memory baseFrequency) public pure returns (string memory) {
        return string(abi.encodePacked(
            '<feTurbulence type="turbulence" seed="',seed,'" baseFrequency="',baseFrequency,'" numOctaves="5" result="turbulence"/>'
        ));
    }

    // helper function for generation
    // from: https://github.com/GNSPS/solidity-bytes-utils/blob/master/contracts/BytesLib.sol 
    function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
        require(_start + 1 >= _start, "toUint8_overflow");
        require(_bytes.length >= _start + 1 , "toUint8_outOfBounds");
        uint8 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x1), _start))
        }
        return tempUint;
    }

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

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

    function generateDecimalString(uint nr, uint decimals) public pure returns (string memory) {
        if(decimals == 1) { return string(abi.encodePacked('0.',toString(nr))); }
        if(decimals == 2) { return string(abi.encodePacked('0.0',toString(nr))); }
        if(decimals == 3) { return string(abi.encodePacked('0.00',toString(nr))); }
        if(decimals == 4) { return string(abi.encodePacked('0.000',toString(nr))); }
    }

    // from: https://ethereum.stackexchange.com/questions/31457/substring-in-solidity/31470
    function substring(string memory str, uint startIndex, uint endIndex) internal pure returns (string memory) {
        bytes memory strBytes = bytes(str);
        bytes memory result = new bytes(endIndex-startIndex);
        for(uint i = startIndex; i < endIndex; i++) {
            result[i-startIndex] = strBytes[i];
        }
        return string(result);
    }
}

File 5 of 11 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the caller.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool _approved) external;

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);

    /**
      * @dev Safely transfers `tokenId` token from `from` to `to`.
      *
      * Requirements:
      *
      * - `from` cannot be the zero address.
      * - `to` cannot be the zero address.
      * - `tokenId` token must exist and be owned by `from`.
      * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
      * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
      *
      * Emits a {Transfer} event.
      */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
}

File 6 of 11 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}

File 7 of 11 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {

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

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

    /**
     * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
     */
    function tokenURI(uint256 tokenId) external view returns (string memory);
}

File 8 of 11 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 9 of 11 : Strings.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

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

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @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] = alphabet[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

}

File 10 of 11 : ERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./interfaces/IERC165.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;
    }
}

File 11 of 11 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

Settings
{
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"address","name":"collector_","type":"address"},{"internalType":"address payable","name":"recipient_","type":"address"},{"internalType":"uint256","name":"startDate_","type":"uint256"},{"internalType":"uint256","name":"endDate_","type":"uint256"},{"internalType":"address","name":"certificates_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"claimer","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"anchorCertificates","outputs":[{"internalType":"contract ERC721","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyableSoulSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ACID","type":"uint256"}],"name":"claimSoul","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"claimedACIDs","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"collector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"descriptor","outputs":[{"internalType":"contract SoulsDescriptor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"generateBase64Image","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"generateImage","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"generateTraits","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintSoul","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"recipient","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"soulsType","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"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":[],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405273af69610ea9ddc95883f97a6a3171d52165b69b03600660006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503480156200006657600080fd5b506040516200a2423803806200a24283398181016040528101906200008c919062000723565b86868160009080519060200190620000a6929190620005ae565b508060019080519060200190620000bf929190620005ae565b50505084600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600860006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600a8190555081600b8190555060405162000160906200063f565b604051809103906000f0801580156200017d573d6000803e3d6000fd5b50600d60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001600f60007fc03908227b9ddbb28e7cd646d0909dddfb65717c255c11bef4ea97790ecf56f7815260200190815260200160002060006101000a81548160ff02191690831515021790555062000272600173af69610ea9ddc95883f97a6a3171d52165b69b03620002f760201b60201c565b7fc03908227b9ddbb28e7cd646d0909dddfb65717c255c11bef4ea97790ecf56f773af69610ea9ddc95883f97a6a3171d52165b69b0373ffffffffffffffffffffffffffffffffffffffff167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d460405160405180910390a35050505050505062000c38565b600042826040516020016200030e92919062000886565b6040516020818303038152906040528051906020012060001c905082600c600083815260200190815260200160002060006101000a81548160ff0219169083151502179055506200036b82826200037060201b620018f21760201c565b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415620003e3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003da90620008d8565b60405180910390fd5b620003f4816200054260201b60201c565b1562000437576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200042e90620008b6565b60405180910390fd5b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546200048991906200096a565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b828054620005bc9062000a4f565b90600052602060002090601f016020900481019282620005e057600085556200062c565b82601f10620005fb57805160ff19168380011785556200062c565b828001600101855582156200062c579182015b828111156200062b5782518255916020019190600101906200060e565b5b5090506200063b91906200064d565b5090565b6158ff806200494383390190565b5b80821115620006685760008160009055506001016200064e565b5090565b6000620006836200067d8462000923565b620008fa565b9050828152602081018484840111156200069c57600080fd5b620006a984828562000a19565b509392505050565b600081519050620006c28162000bea565b92915050565b600081519050620006d98162000c04565b92915050565b600082601f830112620006f157600080fd5b8151620007038482602086016200066c565b91505092915050565b6000815190506200071d8162000c1e565b92915050565b600080600080600080600060e0888a0312156200073f57600080fd5b600088015167ffffffffffffffff8111156200075a57600080fd5b620007688a828b01620006df565b975050602088015167ffffffffffffffff8111156200078657600080fd5b620007948a828b01620006df565b9650506040620007a78a828b01620006b1565b9550506060620007ba8a828b01620006c8565b9450506080620007cd8a828b016200070c565b93505060a0620007e08a828b016200070c565b92505060c0620007f38a828b01620006b1565b91505092959891949750929550565b620008176200081182620009c7565b62000abb565b82525050565b60006200082c601c8362000959565b9150620008398262000b98565b602082019050919050565b60006200085360208362000959565b9150620008608262000bc1565b602082019050919050565b620008806200087a8262000a0f565b62000ae3565b82525050565b60006200089482856200086b565b602082019150620008a6828462000802565b6014820191508190509392505050565b60006020820190508181036000830152620008d1816200081d565b9050919050565b60006020820190508181036000830152620008f38162000844565b9050919050565b60006200090662000919565b905062000914828262000a85565b919050565b6000604051905090565b600067ffffffffffffffff82111562000941576200094062000b4b565b5b6200094c8262000b7a565b9050602081019050919050565b600082825260208201905092915050565b6000620009778262000a0f565b9150620009848362000a0f565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115620009bc57620009bb62000aed565b5b828201905092915050565b6000620009d482620009ef565b9050919050565b6000620009e882620009ef565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60005b8381101562000a3957808201518184015260208101905062000a1c565b8381111562000a49576000848401525b50505050565b6000600282049050600182168062000a6857607f821691505b6020821081141562000a7f5762000a7e62000b1c565b5b50919050565b62000a908262000b7a565b810181811067ffffffffffffffff8211171562000ab25762000ab162000b4b565b5b80604052505050565b600062000ac88262000acf565b9050919050565b600062000adc8262000b8b565b9050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b60008160601b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b62000bf581620009c7565b811462000c0157600080fd5b50565b62000c0f81620009db565b811462000c1b57600080fd5b50565b62000c298162000a0f565b811462000c3557600080fd5b50565b613cfb8062000c486000396000f3fe6080604052600436106101c25760003560e01c806370a08231116100f7578063b88d4fde11610095578063dd74533b11610064578063dd74533b14610690578063e086e5ec146106cd578063e39e867d146106e4578063e985e9c5146106ee576101c2565b8063b88d4fde146105d4578063c24a0f8b146105fd578063c87b56dd14610628578063d638bead14610665576101c2565b8063913e77ad116100d1578063913e77ad1461051857806395d89b4114610543578063a22cb4651461056e578063a48b3b8f14610597576101c2565b806370a082311461047357806379b92f27146104b05780638da5cb5b146104ed576101c2565b8063303e74df116101645780634b44d8121161013e5780634b44d812146103a35780636352211e146103e057806365ec57951461041d57806366d003ac14610448576101c2565b8063303e74df14610312578063324165021461033d57806342842e0e1461037a576101c2565b8063095ea7b3116101a0578063095ea7b31461026c5780630b97bc861461029557806317dd4dcd146102c057806323b872dd146102e9576101c2565b806301ffc9a7146101c757806306fdde0314610204578063081812fc1461022f575b600080fd5b3480156101d357600080fd5b506101ee60048036038101906101e991906126a4565b61072b565b6040516101fb9190612daf565b60405180910390f35b34801561021057600080fd5b5061021961080d565b6040516102269190612e00565b60405180910390f35b34801561023b57600080fd5b5061025660048036038101906102519190612737565b61089f565b6040516102639190612d2d565b60405180910390f35b34801561027857600080fd5b50610293600480360381019061028e9190612668565b610924565b005b3480156102a157600080fd5b506102aa610a2e565b6040516102b791906130f2565b60405180910390f35b3480156102cc57600080fd5b506102e760048036038101906102e29190612737565b610a34565b005b3480156102f557600080fd5b50610310600480360381019061030b9190612562565b610cb9565b005b34801561031e57600080fd5b50610327610d12565b6040516103349190612de5565b60405180910390f35b34801561034957600080fd5b50610364600480360381019061035f9190612737565b610d38565b6040516103719190612daf565b60405180910390f35b34801561038657600080fd5b506103a1600480360381019061039c9190612562565b610d58565b005b3480156103af57600080fd5b506103ca60048036038101906103c59190612737565b610d78565b6040516103d79190612e00565b60405180910390f35b3480156103ec57600080fd5b5061040760048036038101906104029190612737565b610e53565b6040516104149190612d2d565b60405180910390f35b34801561042957600080fd5b50610432610f05565b60405161043f91906130f2565b60405180910390f35b34801561045457600080fd5b5061045d610f0b565b60405161046a9190612d48565b60405180910390f35b34801561047f57600080fd5b5061049a600480360381019061049591906124d4565b610f31565b6040516104a791906130f2565b60405180910390f35b3480156104bc57600080fd5b506104d760048036038101906104d29190612737565b610fe9565b6040516104e49190612e00565b60405180910390f35b3480156104f957600080fd5b506105026110c4565b60405161050f9190612d2d565b60405180910390f35b34801561052457600080fd5b5061052d6110ea565b60405161053a9190612d2d565b60405180910390f35b34801561054f57600080fd5b50610558611110565b6040516105659190612e00565b60405180910390f35b34801561057a57600080fd5b506105956004803603810190610590919061262c565b6111a2565b005b3480156105a357600080fd5b506105be60048036038101906105b99190612737565b61130e565b6040516105cb9190612e00565b60405180910390f35b3480156105e057600080fd5b506105fb60048036038101906105f691906125b1565b61132e565b005b34801561060957600080fd5b50610612611389565b60405161061f91906130f2565b60405180910390f35b34801561063457600080fd5b5061064f600480360381019061064a9190612737565b61138f565b60405161065c9190612e00565b60405180910390f35b34801561067157600080fd5b5061067a6115bf565b6040516106879190612dca565b60405180910390f35b34801561069c57600080fd5b506106b760048036038101906106b29190612737565b6115e5565b6040516106c49190612daf565b60405180910390f35b3480156106d957600080fd5b506106e2611605565b005b6106ec611700565b005b3480156106fa57600080fd5b5061071560048036038101906107109190612526565b61185e565b6040516107229190612daf565b60405180910390f35b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107f657507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610806575061080582611ab4565b5b9050919050565b60606000805461081c90613425565b80601f016020809104026020016040519081016040528092919081815260200182805461084890613425565b80156108955780601f1061086a57610100808354040283529160200191610895565b820191906000526020600020905b81548152906001019060200180831161087857829003601f168201915b5050505050905090565b60006108aa82611b1e565b6108e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e090613012565b60405180910390fd5b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600061092f82610e53565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156109a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099790613072565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806109e057506109df813361185e565b5b610a1f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a1690612f72565b60405180910390fd5b610a298383611b8a565b505050565b600a5481565b600a544211610a78576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6f90613092565b60405180910390fd5b600b544210610abc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ab390612ef2565b60405180910390fd5b60001515600f600083815260200190815260200160002060009054906101000a900460ff16151514610b23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1a90612e72565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401610b9591906130f2565b60206040518083038186803b158015610bad57600080fd5b505afa158015610bc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be591906124fd565b73ffffffffffffffffffffffffffffffffffffffff1614610c3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c3290612fd2565b60405180910390fd5b6001600f600083815260200190815260200160002060006101000a81548160ff021916908315150217905550610c72600133611c43565b803373ffffffffffffffffffffffffffffffffffffffff167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d460405160405180910390a350565b610cc33382611cad565b610d02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cf9906130b2565b60405180910390fd5b610d0d838383611d8b565b505050565b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600c6020528060005260406000206000915054906101000a900460ff1681565b610d738383836040518060200160405280600081525061132e565b505050565b6060600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663effaaf6a83600c600086815260200190815260200160002060009054906101000a900460ff166040518363ffffffff1660e01b8152600401610df792919061310d565b60006040518083038186803b158015610e0f57600080fd5b505afa158015610e23573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610e4c91906126f6565b9050919050565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610efc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef390612fb2565b60405180910390fd5b80915050919050565b60095481565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610fa2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f9990612f92565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6060600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166337ee03ec83600c600086815260200190815260200160002060009054906101000a900460ff166040518363ffffffff1660e01b815260040161106892919061310d565b60006040518083038186803b15801561108057600080fd5b505afa158015611094573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906110bd91906126f6565b9050919050565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606001805461111f90613425565b80601f016020809104026020016040519081016040528092919081815260200182805461114b90613425565b80156111985780601f1061116d57610100808354040283529160200191611198565b820191906000526020600020905b81548152906001019060200180831161117b57829003601f168201915b5050505050905090565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611211576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120890612ed2565b60405180910390fd5b80600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516113029190612daf565b60405180910390a35050565b6060600061131b83610d78565b905061132681611fdc565b915050919050565b6113383383611cad565b611377576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161136e906130b2565b60405180910390fd5b61138384848484612187565b50505050565b600b5481565b606061139a82611b1e565b6113d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113d090613052565b60405180910390fd5b60006040518060400160405280600881526020017f536b657463686564000000000000000000000000000000000000000000000000815250905060011515600c600085815260200190815260200160002060009054906101000a900460ff1615151415611479576040518060400160405280600d81526020017f46756c6c79205061696e7465640000000000000000000000000000000000000081525090505b6000600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c94123f083866040518363ffffffff1660e01b81526004016114d8929190612e22565b60006040518083038186803b1580156114f057600080fd5b505afa158015611504573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061152d91906126f6565b905060006040518060a00160405280607b8152602001613c4b607b9139905060006115578661130e565b9050600061156487610fe9565b9050611594848484846040516020016115809493929190612c5f565b604051602081830303815290604052611fdc565b6040516020016115a49190612cdf565b60405160208183030381529060405295505050505050919050565b600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600f6020528060005260406000206000915054906101000a900460ff1681565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611695576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161168c90612f32565b60405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f193505050501580156116fd573d6000803e3d6000fd5b50565b600a544211611744576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161173b90613092565b60405180910390fd5b600b544210611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161177f90612ef2565b60405180910390fd5b662386f26fc100003410156117d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117c990612f52565b60405180910390fd5b66f195a3c4ba00003410611850576001600960008282546117f39190613200565b9250508190555060606009541115611840576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611837906130d2565b60405180910390fd5b61184b600133611c43565b61185c565b61185b600033611c43565b5b565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611962576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195990612ff2565b60405180910390fd5b61196b81611b1e565b156119ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119a290612e92565b60405180910390fd5b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546119fb9190613200565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16611bfd83610e53565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60004282604051602001611c58929190612d01565b6040516020818303038152906040528051906020012060001c905082600c600083815260200190815260200160002060006101000a81548160ff021916908315150217905550611ca882826118f2565b505050565b6000611cb882611b1e565b611cf7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cee90612f12565b60405180910390fd5b6000611d0283610e53565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611d7157508373ffffffffffffffffffffffffffffffffffffffff16611d598461089f565b73ffffffffffffffffffffffffffffffffffffffff16145b80611d825750611d81818561185e565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16611dab82610e53565b73ffffffffffffffffffffffffffffffffffffffff1614611e01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611df890613032565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611e71576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e6890612eb2565b60405180910390fd5b611e7c600082611b8a565b6001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611ecc91906132e1565b925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611f239190613200565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6060600082511415611fff57604051806020016040528060008152509050612182565b6000604051806060016040528060408152602001613c0b604091399050600060036002855161202e9190613200565b6120389190613256565b60046120449190613287565b905060006020826120559190613200565b67ffffffffffffffff811115612094577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156120c65781602001600182028036833780820191505090505b509050818152600183018586518101602084015b81831015612141576003830192508251603f8160121c1685015160f81b8252600182019150603f81600c1c1685015160f81b8252600182019150603f8160061c1685015160f81b8252600182019150603f811685015160f81b8252600182019150506120da565b60038951066001811461215b576002811461216b57612176565b613d3d60f01b6002830352612176565b603d60f81b60018303525b50505050508093505050505b919050565b612192848484611d8b565b61219e848484846121e3565b6121dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121d490612e52565b60405180910390fd5b50505050565b60006122048473ffffffffffffffffffffffffffffffffffffffff16612373565b15612366578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02338786866040518563ffffffff1660e01b81526004016122489493929190612d63565b602060405180830381600087803b15801561226257600080fd5b505af192505050801561229357506040513d601f19601f8201168201806040525081019061229091906126cd565b60015b612316573d80600081146122c3576040519150601f19603f3d011682016040523d82523d6000602084013e6122c8565b606091505b5060008151141561230e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161230590612e52565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161491505061236b565b600190505b949350505050565b600080823b905060008111915050919050565b60006123996123948461315b565b613136565b9050828152602081018484840111156123b157600080fd5b6123bc8482856133e3565b509392505050565b60006123d76123d28461318c565b613136565b9050828152602081018484840111156123ef57600080fd5b6123fa8482856133f2565b509392505050565b60008135905061241181613bae565b92915050565b60008151905061242681613bae565b92915050565b60008135905061243b81613bc5565b92915050565b60008135905061245081613bdc565b92915050565b60008151905061246581613bdc565b92915050565b600082601f83011261247c57600080fd5b813561248c848260208601612386565b91505092915050565b600082601f8301126124a657600080fd5b81516124b68482602086016123c4565b91505092915050565b6000813590506124ce81613bf3565b92915050565b6000602082840312156124e657600080fd5b60006124f484828501612402565b91505092915050565b60006020828403121561250f57600080fd5b600061251d84828501612417565b91505092915050565b6000806040838503121561253957600080fd5b600061254785828601612402565b925050602061255885828601612402565b9150509250929050565b60008060006060848603121561257757600080fd5b600061258586828701612402565b935050602061259686828701612402565b92505060406125a7868287016124bf565b9150509250925092565b600080600080608085870312156125c757600080fd5b60006125d587828801612402565b94505060206125e687828801612402565b93505060406125f7878288016124bf565b925050606085013567ffffffffffffffff81111561261457600080fd5b6126208782880161246b565b91505092959194509250565b6000806040838503121561263f57600080fd5b600061264d85828601612402565b925050602061265e8582860161242c565b9150509250929050565b6000806040838503121561267b57600080fd5b600061268985828601612402565b925050602061269a858286016124bf565b9150509250929050565b6000602082840312156126b657600080fd5b60006126c484828501612441565b91505092915050565b6000602082840312156126df57600080fd5b60006126ed84828501612456565b91505092915050565b60006020828403121561270857600080fd5b600082015167ffffffffffffffff81111561272257600080fd5b61272e84828501612495565b91505092915050565b60006020828403121561274957600080fd5b6000612757848285016124bf565b91505092915050565b61276981613327565b82525050565b61277881613315565b82525050565b61278f61278a82613315565b613488565b82525050565b61279e81613339565b82525050565b60006127af826131bd565b6127b981856131d3565b93506127c98185602086016133f2565b6127d281613572565b840191505092915050565b6127e68161339b565b82525050565b6127f5816133bf565b82525050565b6000612806826131c8565b61281081856131e4565b93506128208185602086016133f2565b61282981613572565b840191505092915050565b600061283f826131c8565b61284981856131f5565b93506128598185602086016133f2565b80840191505092915050565b60006128726009836131f5565b915061287d82613590565b600982019050919050565b60006128956032836131e4565b91506128a0826135b9565b604082019050919050565b60006128b86015836131e4565b91506128c382613608565b602082019050919050565b60006128db6002836131f5565b91506128e682613631565b600282019050919050565b60006128fe601c836131e4565b91506129098261365a565b602082019050919050565b60006129216024836131e4565b915061292c82613683565b604082019050919050565b60006129446019836131e4565b915061294f826136d2565b602082019050919050565b60006129676005836131e4565b9150612972826136fb565b602082019050919050565b600061298a602c836131e4565b915061299582613724565b604082019050919050565b60006129ad600d836131e4565b91506129b882613773565b602082019050919050565b60006129d0600f836131e4565b91506129db8261379c565b602082019050919050565b60006129f36038836131e4565b91506129fe826137c5565b604082019050919050565b6000612a16602a836131e4565b9150612a2182613814565b604082019050919050565b6000612a396029836131e4565b9150612a4482613863565b604082019050919050565b6000612a5c6019836131e4565b9150612a67826138b2565b602082019050919050565b6000612a7f6020836131e4565b9150612a8a826138db565b602082019050919050565b6000612aa2600d836131f5565b9150612aad82613904565b600d82019050919050565b6000612ac56001836131f5565b9150612ad08261392d565b600182019050919050565b6000612ae8602c836131e4565b9150612af382613956565b604082019050919050565b6000612b0b6012836131f5565b9150612b16826139a5565b601282019050919050565b6000612b2e6029836131e4565b9150612b39826139ce565b604082019050919050565b6000612b51602f836131e4565b9150612b5c82613a1d565b604082019050919050565b6000612b746021836131e4565b9150612b7f82613a6c565b604082019050919050565b6000612b97601d836131f5565b9150612ba282613abb565b601d82019050919050565b6000612bba600b836131e4565b9150612bc582613ae4565b602082019050919050565b6000612bdd6031836131e4565b9150612be882613b0d565b604082019050919050565b6000612c00600b836131e4565b9150612c0b82613b5c565b602082019050919050565b6000612c23601a836131f5565b9150612c2e82613b85565b601a82019050919050565b612c4281613391565b82525050565b612c59612c5482613391565b6134ac565b82525050565b6000612c6a82612865565b9150612c768287612834565b9150612c8182612afe565b9150612c8d8286612834565b9150612c9882612a95565b9150612ca382612c16565b9150612caf8285612834565b9150612cba826128ce565b9150612cc68284612834565b9150612cd182612ab8565b915081905095945050505050565b6000612cea82612b8a565b9150612cf68284612834565b915081905092915050565b6000612d0d8285612c48565b602082019150612d1d828461277e565b6014820191508190509392505050565b6000602082019050612d42600083018461276f565b92915050565b6000602082019050612d5d6000830184612760565b92915050565b6000608082019050612d78600083018761276f565b612d85602083018661276f565b612d926040830185612c39565b8181036060830152612da481846127a4565b905095945050505050565b6000602082019050612dc46000830184612795565b92915050565b6000602082019050612ddf60008301846127dd565b92915050565b6000602082019050612dfa60008301846127ec565b92915050565b60006020820190508181036000830152612e1a81846127fb565b905092915050565b60006040820190508181036000830152612e3c81856127fb565b9050612e4b6020830184612c39565b9392505050565b60006020820190508181036000830152612e6b81612888565b9050919050565b60006020820190508181036000830152612e8b816128ab565b9050919050565b60006020820190508181036000830152612eab816128f1565b9050919050565b60006020820190508181036000830152612ecb81612914565b9050919050565b60006020820190508181036000830152612eeb81612937565b9050919050565b60006020820190508181036000830152612f0b8161295a565b9050919050565b60006020820190508181036000830152612f2b8161297d565b9050919050565b60006020820190508181036000830152612f4b816129a0565b9050919050565b60006020820190508181036000830152612f6b816129c3565b9050919050565b60006020820190508181036000830152612f8b816129e6565b9050919050565b60006020820190508181036000830152612fab81612a09565b9050919050565b60006020820190508181036000830152612fcb81612a2c565b9050919050565b60006020820190508181036000830152612feb81612a4f565b9050919050565b6000602082019050818103600083015261300b81612a72565b9050919050565b6000602082019050818103600083015261302b81612adb565b9050919050565b6000602082019050818103600083015261304b81612b21565b9050919050565b6000602082019050818103600083015261306b81612b44565b9050919050565b6000602082019050818103600083015261308b81612b67565b9050919050565b600060208201905081810360008301526130ab81612bad565b9050919050565b600060208201905081810360008301526130cb81612bd0565b9050919050565b600060208201905081810360008301526130eb81612bf3565b9050919050565b60006020820190506131076000830184612c39565b92915050565b60006040820190506131226000830185612c39565b61312f6020830184612795565b9392505050565b6000613140613151565b905061314c8282613457565b919050565b6000604051905090565b600067ffffffffffffffff82111561317657613175613543565b5b61317f82613572565b9050602081019050919050565b600067ffffffffffffffff8211156131a7576131a6613543565b5b6131b082613572565b9050602081019050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600061320b82613391565b915061321683613391565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561324b5761324a6134b6565b5b828201905092915050565b600061326182613391565b915061326c83613391565b92508261327c5761327b6134e5565b5b828204905092915050565b600061329282613391565b915061329d83613391565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156132d6576132d56134b6565b5b828202905092915050565b60006132ec82613391565b91506132f783613391565b92508282101561330a576133096134b6565b5b828203905092915050565b600061332082613371565b9050919050565b600061333282613371565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006133a6826133ad565b9050919050565b60006133b882613371565b9050919050565b60006133ca826133d1565b9050919050565b60006133dc82613371565b9050919050565b82818337600083830152505050565b60005b838110156134105780820151818401526020810190506133f5565b8381111561341f576000848401525b50505050565b6000600282049050600182168061343d57607f821691505b6020821081141561345157613450613514565b5b50919050565b61346082613572565b810181811067ffffffffffffffff8211171561347f5761347e613543565b5b80604052505050565b60006134938261349a565b9050919050565b60006134a582613583565b9050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b60008160601b9050919050565b7f7b226e616d65223a220000000000000000000000000000000000000000000000600082015250565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b7f41435f494420414c524541445920434c41494d45440000000000000000000000600082015250565b7f222c000000000000000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b7f454e444544000000000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f4e4f545f434f4c4c4543544f5200000000000000000000000000000000000000600082015250565b7f4d4f524520455448204e45454445440000000000000000000000000000000000600082015250565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b7f41435f4944204e4f54204f574e45442042592053454e44455200000000000000600082015250565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b7f222c2022696d616765223a202200000000000000000000000000000000000000600082015250565b7f7d00000000000000000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f222c20226465736372697074696f6e223a220000000000000000000000000000600082015250565b7f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008201527f73206e6f74206f776e0000000000000000000000000000000000000000000000602082015250565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000600082015250565b7f4e4f545f53544152544544000000000000000000000000000000000000000000600082015250565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b7f4d41585f534f4c445f3936000000000000000000000000000000000000000000600082015250565b7f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000600082015250565b613bb781613315565b8114613bc257600080fd5b50565b613bce81613339565b8114613bd957600080fd5b50565b613be581613345565b8114613bf057600080fd5b50565b613bfc81613391565b8114613c0757600080fd5b5056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f5061696e74696e6773206f6620666f72676f7474656e20736f756c7320627920766172696f75732073696d756c61746564206d696e647320746861742074727920746f2072656d656d6265722074686f73652077686f2074686579206f6e6365206b6e657720696e207468652064656661756c7420776f726c642ea26469706673582212204a120aa6acbfed0c15ede9f9b2cd7f260b9e4b708eab91e0c852482dab86724864736f6c63430008040033608060405234801561001057600080fd5b506158de80620000216000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c806398a8716a116100a2578063cadbdaad11610071578063cadbdaad1461038d578063d7568479146103bd578063dcaf635d146103ed578063effaaf6a1461041d578063f41b75231461044d57610116565b806398a8716a146102cd5780639a2227f9146102fd5780639f42c2a81461032d578063c94123f01461035d57610116565b8063352fc7ee116100e9578063352fc7ee146101db57806337ee03ec1461020b578063724441dd1461023b57806388de3fb21461026d57806397959a881461029d57610116565b80631381a8461461011b5780631411e4e51461014b57806319c561e81461017b57806332a35430146101ab575b600080fd5b61013560048036038101906101309190612eb2565b61047d565b6040516101429190614162565b60405180910390f35b61016560048036038101906101609190612a5b565b610566565b6040516101729190614162565b60405180910390f35b61019560048036038101906101909190612e4d565b610851565b6040516101a29190614162565b60405180910390f35b6101c560048036038101906101c09190612a5b565b610937565b6040516101d29190614162565b60405180910390f35b6101f560048036038101906101f09190612bb2565b610a47565b6040516102029190614162565b60405180910390f35b61022560048036038101906102209190612e76565b610be5565b6040516102329190614162565b60405180910390f35b61025560048036038101906102509190612a5b565b611067565b604051610264939291906141c4565b60405180910390f35b61028760048036038101906102829190612c06565b611217565b6040516102949190614162565b60405180910390f35b6102b760048036038101906102b29190612bb2565b611240565b6040516102c49190614162565b60405180910390f35b6102e760048036038101906102e29190612a9c565b61150d565b6040516102f49190614162565b60405180910390f35b61031760048036038101906103129190612cb3565b6116d0565b6040516103249190614162565b60405180910390f35b61034760048036038101906103429190612bb2565b61170b565b6040516103549190614162565b60405180910390f35b61037760048036038101906103729190612df9565b6119d2565b6040516103849190614162565b60405180910390f35b6103a760048036038101906103a29190612a5b565b611a12565b6040516103b49190614162565b60405180910390f35b6103d760048036038101906103d29190612a5b565b611c56565b6040516103e49190614162565b60405180910390f35b61040760048036038101906104029190612c47565b61205f565b6040516104149190614162565b60405180910390f35b61043760048036038101906104329190612e76565b61208b565b6040516104449190614162565b60405180910390f35b61046760048036038101906104629190612a5b565b612335565b6040516104749190614162565b60405180910390f35b606060018214156104b75761049183612590565b6040516020016104a19190613e89565b6040516020818303038152906040529050610560565b60028214156104ef576104c983612590565b6040516020016104d99190613f32565b6040516020818303038152906040529050610560565b60038214156105275761050183612590565b6040516020016105119190613d65565b6040516020818303038152906040529050610560565b600482141561055f5761053983612590565b6040516020016105499190613f54565b6040516020818303038152906040529050610560565b5b92915050565b6060600061064f836040518060400160405280601181526020017f72696e67446973706c6163656d656e7431000000000000000000000000000000815250600f60106040518060400160405280600481526020017f67726579000000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f52000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280601f81526020017f66696c7465723a2075726c282372696e67446973706c6163656d656e7431290081525061150d565b90506000610738846040518060400160405280601181526020017f72696e67446973706c6163656d656e7432000000000000000000000000000000815250601160126040518060400160405280600581526020017f626c61636b0000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f47000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280601f81526020017f66696c7465723a2075726c282372696e67446973706c6163656d656e7432290081525061150d565b90506000610821856040518060400160405280601181526020017f72696e67446973706c6163656d656e7433000000000000000000000000000000815250601360146040518060400160405280600581526020017f626c61636b0000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f42000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280601f81526020017f66696c7465723a2075726c282372696e67446973706c6163656d656e7433290081525061150d565b90508282826040516020016108389392919061392c565b6040516020818303038152906040529350505050919050565b6060600082101580156108645750605582105b156108a6576040518060400160405280601181526020017f53706c697420436f6d706f736974696f6e0000000000000000000000000000008152509050610932565b605582101580156108b7575060aa82105b156108f9576040518060400160405280601181526020017f547269616420436f6d706f736974696f6e0000000000000000000000000000008152509050610932565b6040518060400160405280601581526020017f416e616c6f676f757320436f6d706f736974696f6e000000000000000000000081525090505b919050565b6060600060ff6103e861094b85600661273d565b60ff166109589190614361565b61096291906142ff565b9050600060ff6103e861097686600661273d565b60ff166109839190614361565b61098d91906142ff565b9050600060ff60286109a087600761273d565b60ff166109ad9190614361565b6109b791906142ff565b90506109f76040518060400160405280601181526020017f6672616d65446973706c6163656d656e74000000000000000000000000000000815250611217565b610a13610a0384612590565b610a0e86600461047d565b61205f565b610a1c83612590565b604051602001610a2e9392919061395d565b6040516020818303038152906040529350505050919050565b6060600060ff6103e8610a5b86600361273d565b60ff16610a689190614361565b610a7291906142ff565b9050600060ff600a610a8587600461273d565b60ff16610a929190614361565b610a9c91906142ff565b9050600060ff605a610aaf88600561273d565b60ff16610abc9190614361565b610ac691906142ff565b6032610ad291906142a9565b9050600060ff6037610ae589601e61273d565b60ff16610af29190614361565b610afc91906142ff565b603c610b0891906143ef565b9050610b486040518060400160405280601681526020017f6261636b67726f756e64446973706c6163656d656e7400000000000000000000815250611217565b610b916040518060400160405280600381526020017f3130300000000000000000000000000000000000000000000000000000000000815250610b8c87600261047d565b61205f565b610b9a88612590565b610ba384612590565b610bac87612590565b610bb587612590565b604051602001610bca969594939291906139af565b60405160208183030381529060405294505050505092915050565b606060008360001b604051602001610bfd91906138ed565b604051602081830303815290604052905060006040518060200160405280600081525090506000604051602001610c339061414d565b6040516020818303038152906040529050600015158515151415610c7257604051602001610c6090613f1d565b60405160208183030381529060405290505b6000806000610c8086611067565b9250925092506000610c9e610c9688600261273d565b60ff16610851565b9050600060ff6037610cb18a601e61273d565b60ff16610cbe9190614361565b610cc891906142ff565b603c610cd491906143ef565b905060006040518060200160405280600081525090506000806080610cfa8c601661273d565b60ff161080610d0d5750600115158d1515145b15610d515789610d1c89612590565b604051602001610d2d929190613c51565b60405160208183030381529060405299508180610d4990614505565b925050600190505b6080610d5e8c601761273d565b60ff161080610d715750600115158d1515145b15610da75789604051602001610d879190613c2f565b60405160208183030381529060405299508180610da390614505565b9250505b6080610db48c601861273d565b60ff161080610dc75750600115158d1515145b15610dfd5789604051602001610ddd9190613c8b565b60405160208183030381529060405299508180610df990614505565b9250505b6080610e0a8c601961273d565b60ff161080610e1d5750600115158d1515145b15610e535789604051602001610e339190613d21565b60405160208183030381529060405299508180610e4f90614505565b9250505b6080610e608c601a61273d565b60ff161080610e735750600115158d1515145b15610eb75789610e8288612590565b604051602001610e93929190613cad565b60405160208183030381529060405299508180610eaf90614505565b925050600190505b6080610ec48c601b61273d565b60ff161080610ed75750600115158d1515145b15610f1b5789610ee687612590565b604051602001610ef7929190613ce7565b60405160208183030381529060405299508180610f1390614505565b925050600190505b6080610f288c601c61273d565b60ff161080610f3b5750600115158d1515145b15610f715789604051602001610f519190613b96565b60405160208183030381529060405299508180610f6d90614505565b9250505b6080610f7e8c601d61273d565b60ff161080610f915750600115158d1515145b15610fc75789604051602001610fa79190613d43565b60405160208183030381529060405299508180610fc390614505565b9250505b610fd082612590565b604051602001610fe09190614120565b6040516020818303038152906040529250606060011515821515141561102d578561100a86612590565b60405160200161101b92919061405d565b60405160208183030381529060405290505b89818c866040516020016110449493929190614009565b6040516020818303038152906040529c5050505050505050505050505092915050565b60008060008060ff61016861107d87600161273d565b60ff1661108a9190614361565b61109491906142ff565b905060006110a386600261273d565b60ff16905060008060006110b684610851565b90506040518060400160405280601181526020017f53706c697420436f6d706f736974696f6e00000000000000000000000000000081525080519060200120818051906020012014156111405761016860968661111391906142a9565b61111d9190614558565b925061016860d28661112f91906142a9565b6111399190614558565b9150611202565b6040518060400160405280601181526020017f547269616420436f6d706f736974696f6e00000000000000000000000000000081525080519060200120818051906020012014156111c85761016860788661119b91906142a9565b6111a59190614558565b925061016860f0866111b791906142a9565b6111c19190614558565b9150611201565b610168601e866111d891906142a9565b6111e29190614558565b9250610168605a866111f491906142a9565b6111fe9190614558565b91505b5b84838397509750975050505050509193909250565b60608160405160200161122a9190613ef0565b6040516020818303038152906040529050919050565b60606000600361125185600061273d565b61125b9190614330565b9050600060ff6103e861126f87600b61273d565b60ff1661127c9190614361565b61128691906142ff565b9050600060ff61019061129a88600c61273d565b60ff166112a79190614361565b6112b191906142ff565b9050600060ff60376112c489601e61273d565b60ff166112d19190614361565b6112db91906142ff565b603c6112e791906143ef565b905060006112f487612590565b6112fd83612590565b60405160200161130e929190613eab565b604051602081830303815290604052905061135d6040518060400160405280601081526020017f68656164446973706c6163656d656e7400000000000000000000000000000000815250611217565b6113a66040518060400160405280600381526020017f31303000000000000000000000000000000000000000000000000000000000008152506113a187600361047d565b61205f565b6113af85612590565b6114de6040518060400160405280600381526020017f33303000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f32373000000000000000000000000000000000000000000000000000000000008152506114368b608c61142e9190614423565b60ff16612590565b6040518060400160405280600481526020017f6e6f6e65000000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250896040518060400160405280601e81526020017f66696c7465723a2075726c282368656164446973706c6163656d656e742900008152506116d0565b6040516020016114f19493929190613a54565b6040516020818303038152906040529550505050505092915050565b60606000600361151e8a600061273d565b6115289190614330565b9050600060ff6103e861153b8c8b61273d565b60ff166115489190614361565b61155291906142ff565b9050600060ff6103e86115658d8b61273d565b60ff166115729190614361565b61157c91906142ff565b90506115878a611217565b6115a361159384612590565b61159e84600461047d565b61205f565b8761169e6040518060400160405280600381526020017f33303000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f323730000000000000000000000000000000000000000000000000000000000081525061162b89608c6116239190614423565b60ff16612590565b8d6040518060400160405280600181526020017f34000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600481526020017f6e6f6e65000000000000000000000000000000000000000000000000000000008152508e6116d0565b6040516020016116b19493929190613b13565b6040516020818303038152906040529350505050979650505050505050565b6060878787878688876040516020016116ef9796959493929190613d87565b6040516020818303038152906040529050979650505050505050565b60606000600361171c85600061273d565b6117269190614330565b9050600060ff6103e861173a87600d61273d565b60ff166117479190614361565b61175191906142ff565b9050600060ff6103e861176588600e61273d565b60ff166117729190614361565b61177c91906142ff565b9050600060ff61019061179089600e61273d565b60ff1661179d9190614361565b6117a791906142ff565b9050600060ff60376117ba8a601e61273d565b60ff166117c79190614361565b6117d191906142ff565b603c6117dd91906143ef565b905060006117ea88612590565b6117f383612590565b604051602001611804929190613eab565b60405160208183030381529060405290506118536040518060400160405280601181526020017f68656164446973706c6163656d656e7432000000000000000000000000000000815250611217565b61185e86600361047d565b61186986600361047d565b61187286612590565b6119a16040518060400160405280600381526020017f33303000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f32373000000000000000000000000000000000000000000000000000000000008152506118f98d60786118f19190614423565b60ff16612590565b6040518060400160405280600481526020017f6e6f6e65000000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152508a6040518060400160405280601f81526020017f66696c7465723a2075726c282368656164446973706c6163656d656e743229008152506116d0565b6040516020016119b5959493929190613bb8565b604051602081830303815290604052965050505050505092915050565b6060826119ea6119e184612590565b600060086127f3565b6040516020016119fb929190613b67565b604051602081830303815290604052905092915050565b606060006003611a2384600061273d565b611a2d9190614330565b9050600060ff6103e8611a4186600a61273d565b60ff16611a4e9190614361565b611a5891906142ff565b9050611a986040518060400160405280601081526020017f626f6479446973706c6163656d656e7400000000000000000000000000000000815250611217565b611ae16040518060400160405280600381526020017f3130300000000000000000000000000000000000000000000000000000000000815250611adc84600461047d565b61205f565b611c2c6040518060400160405280600381526020017f3330300000000000000000000000000000000000000000000000000000000000815250611b378660ff166102bc611b2e91906143bb565b61ffff16612590565b611b4f8760b4611b479190614423565b60ff16612590565b6040518060400160405280600581526020017f626c61636b0000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600581526020017f626c61636b0000000000000000000000000000000000000000000000000000008152506040518060400160405280601e81526020017f66696c7465723a2075726c2823626f6479446973706c6163656d656e742900008152506116d0565b604051602001611c3e93929190613aa8565b60405160208183030381529060405292505050919050565b6060600060ff6103e8611c6a85601561273d565b60ff16611c779190614361565b611c8191906142ff565b9050600060ff600f611c9486601561273d565b60ff16611ca19190614361565b611cab91906142ff565b6019611cb791906143ef565b90506000611cf96040518060400160405280600f81526020017f657965446973706c6163656d656e740000000000000000000000000000000000815250611217565b611d426040518060400160405280600381526020017f3130300000000000000000000000000000000000000000000000000000000000815250611d3d86600461047d565b61205f565b604051602001611d53929190613ae4565b60405160208183030381529060405290506000611ebb6040518060400160405280600381526020017f32353000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f3237300000000000000000000000000000000000000000000000000000000000815250611dde86612590565b6040518060400160405280600581526020017f626c61636b0000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600581526020017f77686974650000000000000000000000000000000000000000000000000000008152506040518060400160405280601d81526020017f66696c7465723a2075726c2823657965446973706c6163656d656e74290000008152506116d0565b6120106040518060400160405280600381526020017f33323000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f3237300000000000000000000000000000000000000000000000000000000000815250611f3387612590565b6040518060400160405280600581526020017f626c61636b0000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f31000000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600581526020017f77686974650000000000000000000000000000000000000000000000000000008152506040518060400160405280601d81526020017f66696c7465723a2075726c2823657965446973706c6163656d656e74290000008152506116d0565b604051602001612021929190613908565b60405160208183030381529060405290508181604051602001612045929190613908565b604051602081830303815290604052945050505050919050565b60608282604051602001612074929190613e44565b604051602081830303815290604052905092915050565b606060008360001b6040516020016120a391906138ed565b604051602081830303815290604052905060008060006120c284611067565b9250925092506000604051806020016040528060008152509050600060405180602001604052806000815250905060006040518060200160405280600081525090506000604051806020016040528060008152509050600060405180602001604052806000815250905060006040518060200160405280600081525090506000604051806020016040528060008152509050600060405180602001604052806000815250905060806121758d601661273d565b60ff1610806121885750600115158e1515145b1561219a576121978c8c610a47565b97505b60806121a78d601761273d565b60ff1610806121ba5750600115158e1515145b156121cb576121c88c610937565b96505b60806121d88d601861273d565b60ff1610806121eb5750600115158e1515145b156121fc576121f98c612335565b95505b60806122098d601961273d565b60ff16108061221c5750600115158e1515145b1561222d5761222a8c611a12565b94505b608061223a8d601a61273d565b60ff16108061224d5750600115158e1515145b1561225f5761225c8c8b611240565b93505b608061226c8d601b61273d565b60ff16108061227f5750600115158e1515145b156122915761228e8c8a61170b565b92505b608061229e8d601c61273d565b60ff1610806122b15750600115158e1515145b156122c2576122bf8c610566565b91505b60806122cf8d601d61273d565b60ff1610806122e25750600115158e1515145b156122f3576122f08c611c56565b90505b8787878787878787604051602001612312989796959493929190613f76565b6040516020818303038152906040529c5050505050505050505050505092915050565b60606000600361234684600061273d565b6123509190614330565b9050600060ff6103e861236486600861273d565b60ff166123719190614361565b61237b91906142ff565b9050600060ff602861238e87600961273d565b60ff1661239b9190614361565b6123a591906142ff565b90506123e56040518060400160405280600a81526020017f6261636b53706c61736800000000000000000000000000000000000000000000815250611217565b61242e6040518060400160405280600481526020017f323030300000000000000000000000000000000000000000000000000000000081525061242985600461047d565b61205f565b6125656040518060400160405280600381526020017f33303000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f32373000000000000000000000000000000000000000000000000000000000008152506124b58860aa6124ad9190614423565b60ff16612590565b6040518060400160405280601481526020017f75726c28236261636b53706c61736847726164290000000000000000000000008152506124f488612590565b6040518060400160405280600481526020017f6e6f6e65000000000000000000000000000000000000000000000000000000008152506040518060400160405280601881526020017f66696c7465723a2075726c28236261636b53706c6173682900000000000000008152506116d0565b604051602001612577939291906140a2565b6040516020818303038152906040529350505050919050565b606060008214156125d8576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612738565b600082905060005b6000821461260a5780806125f390614505565b915050600a8261260391906142ff565b91506125e0565b60008167ffffffffffffffff81111561264c577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561267e5781602001600182028036833780820191505090505b5090505b600085146127315760018261269791906143ef565b9150600a856126a69190614558565b60306126b291906142a9565b60f81b8183815181106126ee577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8561272a91906142ff565b9450612682565b8093505050505b919050565b60008160018361274d91906142a9565b101561278e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161278590614184565b60405180910390fd5b60018261279b91906142a9565b835110156127de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127d5906141a4565b60405180910390fd5b60008260018501015190508091505092915050565b606060008490506000848461280891906143ef565b67ffffffffffffffff811115612847577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156128795781602001600182028036833780820191505090505b50905060008590505b84811015612954578281815181106128c3577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b602001015160f81c60f81b8287836128db91906143ef565b81518110612912577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350808061294c90614505565b915050612882565b5080925050509392505050565b600061297461296f84614220565b6141fb565b90508281526020810184848401111561298c57600080fd5b612997848285614492565b509392505050565b60006129b26129ad84614251565b6141fb565b9050828152602081018484840111156129ca57600080fd5b6129d5848285614492565b509392505050565b6000813590506129ec8161587a565b92915050565b600082601f830112612a0357600080fd5b8135612a13848260208601612961565b91505092915050565b600082601f830112612a2d57600080fd5b8135612a3d84826020860161299f565b91505092915050565b600081359050612a5581615891565b92915050565b600060208284031215612a6d57600080fd5b600082013567ffffffffffffffff811115612a8757600080fd5b612a93848285016129f2565b91505092915050565b600080600080600080600060e0888a031215612ab757600080fd5b600088013567ffffffffffffffff811115612ad157600080fd5b612add8a828b016129f2565b975050602088013567ffffffffffffffff811115612afa57600080fd5b612b068a828b01612a1c565b9650506040612b178a828b01612a46565b9550506060612b288a828b01612a46565b945050608088013567ffffffffffffffff811115612b4557600080fd5b612b518a828b01612a1c565b93505060a088013567ffffffffffffffff811115612b6e57600080fd5b612b7a8a828b01612a1c565b92505060c088013567ffffffffffffffff811115612b9757600080fd5b612ba38a828b01612a1c565b91505092959891949750929550565b60008060408385031215612bc557600080fd5b600083013567ffffffffffffffff811115612bdf57600080fd5b612beb858286016129f2565b9250506020612bfc85828601612a46565b9150509250929050565b600060208284031215612c1857600080fd5b600082013567ffffffffffffffff811115612c3257600080fd5b612c3e84828501612a1c565b91505092915050565b60008060408385031215612c5a57600080fd5b600083013567ffffffffffffffff811115612c7457600080fd5b612c8085828601612a1c565b925050602083013567ffffffffffffffff811115612c9d57600080fd5b612ca985828601612a1c565b9150509250929050565b600080600080600080600060e0888a031215612cce57600080fd5b600088013567ffffffffffffffff811115612ce857600080fd5b612cf48a828b01612a1c565b975050602088013567ffffffffffffffff811115612d1157600080fd5b612d1d8a828b01612a1c565b965050604088013567ffffffffffffffff811115612d3a57600080fd5b612d468a828b01612a1c565b955050606088013567ffffffffffffffff811115612d6357600080fd5b612d6f8a828b01612a1c565b945050608088013567ffffffffffffffff811115612d8c57600080fd5b612d988a828b01612a1c565b93505060a088013567ffffffffffffffff811115612db557600080fd5b612dc18a828b01612a1c565b92505060c088013567ffffffffffffffff811115612dde57600080fd5b612dea8a828b01612a1c565b91505092959891949750929550565b60008060408385031215612e0c57600080fd5b600083013567ffffffffffffffff811115612e2657600080fd5b612e3285828601612a1c565b9250506020612e4385828601612a46565b9150509250929050565b600060208284031215612e5f57600080fd5b6000612e6d84828501612a46565b91505092915050565b60008060408385031215612e8957600080fd5b6000612e9785828601612a46565b9250506020612ea8858286016129dd565b9150509250929050565b60008060408385031215612ec557600080fd5b6000612ed385828601612a46565b9250506020612ee485828601612a46565b9150509250929050565b612eff612efa82614463565b61454e565b82525050565b6000612f1082614282565b612f1a818561428d565b9350612f2a8185602086016144a1565b612f3381614616565b840191505092915050565b6000612f4982614282565b612f53818561429e565b9350612f638185602086016144a1565b80840191505092915050565b6000612f7c60048361429e565b9150612f8782614627565b600482019050919050565b6000612f9f60118361429e565b9150612faa82614650565b601182019050919050565b6000612fc260768361429e565b9150612fcd82614679565b607682019050919050565b6000612fe560068361429e565b9150612ff082614714565b600682019050919050565b6000613008600c8361429e565b91506130138261473d565b600c82019050919050565b600061302b60138361429e565b915061303682614766565b601382019050919050565b600061304e602c8361429e565b91506130598261478f565b602c82019050919050565b6000613071605a8361429e565b915061307c826147de565b605a82019050919050565b600061309460098361429e565b915061309f82614853565b600982019050919050565b60006130b760278361429e565b91506130c28261487c565b602782019050919050565b60006130da60268361429e565b91506130e5826148cb565b602682019050919050565b60006130fd60398361429e565b91506131088261491a565b603982019050919050565b600061312060368361429e565b915061312b82614969565b603682019050919050565b600061314360378361429e565b915061314e826149b8565b603782019050919050565b600061316660348361429e565b915061317182614a07565b603482019050919050565b6000613189603e8361429e565b915061319482614a56565b603e82019050919050565b60006131ac60138361429e565b91506131b782614aa5565b601382019050919050565b60006131cf600a8361429e565b91506131da82614ace565b600a82019050919050565b60006131f260018361429e565b91506131fd82614af7565b600182019050919050565b600061321560028361429e565b915061322082614b20565b600282019050919050565b600061323860288361429e565b915061324382614b49565b602882019050919050565b600061325b60268361429e565b915061326682614b98565b602682019050919050565b600061327e60638361429e565b915061328982614be7565b606382019050919050565b60006132a1603d8361429e565b91506132ac82614c82565b603d82019050919050565b60006132c460048361429e565b91506132cf82614cd1565b600482019050919050565b60006132e760118361429e565b91506132f282614cfa565b601182019050919050565b600061330a60078361429e565b915061331582614d23565b600782019050919050565b600061332d600c8361429e565b915061333882614d4c565b600c82019050919050565b600061335060198361429e565b915061335b82614d75565b601982019050919050565b6000613373603d8361429e565b915061337e82614d9e565b603d82019050919050565b6000613396603a8361429e565b91506133a182614ded565b603a82019050919050565b60006133b9602a8361429e565b91506133c482614e3c565b602a82019050919050565b60006133dc60778361429e565b91506133e782614e8b565b607782019050919050565b60006133ff60038361429e565b915061340a82614f26565b600382019050919050565b600061342260028361429e565b915061342d82614f4f565b600282019050919050565b600061344560058361429e565b915061345082614f78565b600582019050919050565b600061346860778361429e565b915061347382614fa1565b607782019050919050565b600061348b60648361429e565b91506134968261503c565b606482019050919050565b60006134ae60058361429e565b91506134b9826150d7565b600582019050919050565b60006134d160118361429e565b91506134dc82615100565b601182019050919050565b60006134f460578361429e565b91506134ff82615129565b605782019050919050565b6000613517601d8361429e565b91506135228261519e565b601d82019050919050565b600061353a60178361429e565b9150613545826151c7565b601782019050919050565b600061355d60108361429e565b9150613568826151f0565b601082019050919050565b6000613580602a8361429e565b915061358b82615219565b602a82019050919050565b60006135a3600f8361429e565b91506135ae82615268565b600f82019050919050565b60006135c660778361429e565b91506135d182615291565b607782019050919050565b60006135e960038361429e565b91506135f48261532c565b600382019050919050565b600061360c60018361429e565b915061361782615355565b600182019050919050565b600061362f60658361429e565b915061363a8261537e565b606582019050919050565b600061365260378361429e565b915061365d82615419565b603782019050919050565b600061367560028361429e565b915061368082615468565b600282019050919050565b600061369860078361429e565b91506136a382615491565b600782019050919050565b60006136bb60108361428d565b91506136c6826154ba565b602082019050919050565b60006136de60088361429e565b91506136e9826154e3565b600882019050919050565b600061370160188361429e565b915061370c8261550c565b601882019050919050565b600061372460348361429e565b915061372f82615535565b603482019050919050565b6000613747602b8361429e565b915061375282615584565b602b82019050919050565b600061376a60068361429e565b9150613775826155d3565b600682019050919050565b600061378d60138361428d565b9150613798826155fc565b602082019050919050565b60006137b060048361429e565b91506137bb82615625565b600482019050919050565b60006137d360238361429e565b91506137de8261564e565b602382019050919050565b60006137f660238361429e565b91506138018261569d565b602382019050919050565b600061381960558361429e565b9150613824826156ec565b605582019050919050565b600061383c60068361429e565b915061384782615761565b600682019050919050565b600061385f603e8361429e565b915061386a8261578a565b603e82019050919050565b600061388260128361429e565b915061388d826157d9565b601282019050919050565b60006138a560318361429e565b91506138b082615802565b603182019050919050565b60006138c860128361429e565b91506138d382615851565b601282019050919050565b6138e78161447b565b82525050565b60006138f98284612eee565b60208201915081905092915050565b60006139148285612f3e565b91506139208284612f3e565b91508190509392505050565b60006139388286612f3e565b91506139448285612f3e565b91506139508284612f3e565b9150819050949350505050565b60006139698286612f3e565b91506139758285612f3e565b915061398082612fb5565b915061398b82613622565b91506139978284612f3e565b91506139a28261373a565b9150819050949350505050565b60006139bb8289612f3e565b91506139c78288612f3e565b91506139d282613064565b91506139dd82613159565b91506139e98287612f3e565b91506139f482613668565b9150613a008286612f3e565b9150613a0b8261352d565b9150613a178285612f3e565b9150613a2282613573565b9150613a2e8284612f3e565b9150613a39826136f4565b9150613a4482613271565b9150819050979650505050505050565b6000613a608287612f3e565b9150613a6c8286612f3e565b9150613a778261317c565b9150613a838285612f3e565b9150613a8e82613645565b9150613a9a8284612f3e565b915081905095945050505050565b6000613ab48286612f3e565b9150613ac08285612f3e565b9150613acb8261345b565b9150613ad78284612f3e565b9150819050949350505050565b6000613af08285612f3e565b9150613afc8284612f3e565b9150613b07826135b9565b91508190509392505050565b6000613b1f8287612f3e565b9150613b2b8286612f3e565b9150613b368261380c565b9150613b428285612f3e565b9150613b4d826137c6565b9150613b598284612f3e565b915081905095945050505050565b6000613b738285612f3e565b9150613b7e82612f92565b9150613b8a8284612f3e565b91508190509392505050565b6000613ba28284612f3e565b9150613bad8261301e565b915081905092915050565b6000613bc48288612f3e565b9150613bcf826130f0565b9150613bdb8287612f3e565b9150613be6826131e5565b9150613bf28286612f3e565b9150613bfd8261347e565b9150613c098285612f3e565b9150613c1482613136565b9150613c208284612f3e565b91508190509695505050505050565b6000613c3b8284612f3e565b9150613c468261319f565b915081905092915050565b6000613c5d8285612f3e565b9150613c6882613294565b9150613c748284612f3e565b9150613c7f826137a3565b91508190509392505050565b6000613c978284612f3e565b9150613ca282613343565b915081905092915050565b6000613cb98285612f3e565b9150613cc482613366565b9150613cd08284612f3e565b9150613cdb826137a3565b91508190509392505050565b6000613cf38285612f3e565b9150613cfe82613852565b9150613d0a8284612f3e565b9150613d15826137a3565b91508190509392505050565b6000613d2d8284612f3e565b9150613d3882613875565b915081905092915050565b6000613d4f8284612f3e565b9150613d5a826138bb565b915081905092915050565b6000613d7082612f6f565b9150613d7c8284612f3e565b915081905092915050565b6000613d9282612ffb565b9150613d9e828a612f3e565b9150613da982612fd8565b9150613db58289612f3e565b9150613dc082613438565b9150613dcc8288612f3e565b9150613dd7826131c2565b9150613de38287612f3e565b9150613dee826136d1565b9150613dfa8286612f3e565b9150613e0582613550565b9150613e118285612f3e565b9150613e1c82613087565b9150613e288284612f3e565b9150613e33826135dc565b915081905098975050505050505050565b6000613e4f826130cd565b9150613e5b8285612f3e565b9150613e66826134c4565b9150613e728284612f3e565b9150613e7d8261324e565b91508190509392505050565b6000613e9482613208565b9150613ea08284612f3e565b915081905092915050565b6000613eb6826132b7565b9150613ec28285612f3e565b9150613ecd82613668565b9150613ed98284612f3e565b9150613ee4826132fd565b91508190509392505050565b6000613efb82613320565b9150613f078284612f3e565b9150613f128261350a565b915081905092915050565b6000613f28826133ac565b9150819050919050565b6000613f3d826133f2565b9150613f498284612f3e565b915081905092915050565b6000613f5f826134a1565b9150613f6b8284612f3e565b915081905092915050565b6000613f81826134e7565b9150613f8c82613389565b9150613f98828b612f3e565b9150613fa4828a612f3e565b9150613fb08289612f3e565b9150613fbc8288612f3e565b9150613fc88287612f3e565b9150613fd48286612f3e565b9150613fe08285612f3e565b9150613fec8284612f3e565b9150613ff78261382f565b91508190509998505050505050505050565b600061401482613596565b91506140208287612f3e565b915061402c8286612f3e565b91506140388285612f3e565b91506140448284612f3e565b915061404f826135ff565b915081905095945050505050565b600061406882613717565b91506140748285612f3e565b915061407f82613041565b915061408b8284612f3e565b9150614096826137a3565b91508190509392505050565b60006140ad8261375d565b91506140b882613113565b91506140c3826130aa565b91506140ce8261322b565b91506140d9826132da565b91506140e48261368b565b91506140f08286612f3e565b91506140fc8285612f3e565b9150614107826133cf565b91506141138284612f3e565b9150819050949350505050565b600061412b826137e9565b91506141378284612f3e565b915061414282613415565b915081905092915050565b600061415882613898565b9150819050919050565b6000602082019050818103600083015261417c8184612f05565b905092915050565b6000602082019050818103600083015261419d816136ae565b9050919050565b600060208201905081810360008301526141bd81613780565b9050919050565b60006060820190506141d960008301866138de565b6141e660208301856138de565b6141f360408301846138de565b949350505050565b6000614205614216565b905061421182826144d4565b919050565b6000604051905090565b600067ffffffffffffffff82111561423b5761423a6145e7565b5b61424482614616565b9050602081019050919050565b600067ffffffffffffffff82111561426c5761426b6145e7565b5b61427582614616565b9050602081019050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b60006142b48261447b565b91506142bf8361447b565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156142f4576142f3614589565b5b828201905092915050565b600061430a8261447b565b91506143158361447b565b925082614325576143246145b8565b5b828204905092915050565b600061433b82614485565b915061434683614485565b925082614356576143556145b8565b5b828204905092915050565b600061436c8261447b565b91506143778361447b565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156143b0576143af614589565b5b828202905092915050565b60006143c68261446d565b91506143d18361446d565b9250828210156143e4576143e3614589565b5b828203905092915050565b60006143fa8261447b565b91506144058361447b565b92508282101561441857614417614589565b5b828203905092915050565b600061442e82614485565b915061443983614485565b92508282101561444c5761444b614589565b5b828203905092915050565b60008115159050919050565b6000819050919050565b600061ffff82169050919050565b6000819050919050565b600060ff82169050919050565b82818337600083830152505050565b60005b838110156144bf5780820151818401526020810190506144a4565b838111156144ce576000848401525b50505050565b6144dd82614616565b810181811067ffffffffffffffff821117156144fc576144fb6145e7565b5b80604052505050565b60006145108261447b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561454357614542614589565b5b600182019050919050565b6000819050919050565b60006145638261447b565b915061456e8361447b565b92508261457e5761457d6145b8565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f302e303000000000000000000000000000000000000000000000000000000000600082015250565b7f20466f72676f7474656e20536f756c2023000000000000000000000000000000600082015250565b7f3c6665446973706c6163656d656e744d617020696e323d2274757262756c656e60008201527f63652220696e3d22536f757263654772617068696322207363616c653d22353060208201527f2220784368616e6e656c53656c6563746f723d22472220794368616e6e656c5360408201527f656c6563746f723d2241222f3e3c2f66696c7465723e00000000000000000000606082015250565b7f222063793d220000000000000000000000000000000000000000000000000000600082015250565b7f3c636972636c652063783d220000000000000000000000000000000000000000600082015250565b7f7b2276616c7565223a202252696e6773227d2c00000000000000000000000000600082015250565b7f22207d2c207b2274726169745f74797065223a202253617475726174696f6e2260008201527f2c202276616c7565223a20220000000000000000000000000000000000000000602082015250565b7f3c66654d6f7270686f6c6f677920696e3d2274757262756c656e63652220726560008201527f73756c743d226d6f727068656422206f70657261746f723d2265726f6465222060208201527f7261646975733d2231223e3c2f66654d6f7270686f6c6f67793e000000000000604082015250565b7f22207374796c653d220000000000000000000000000000000000000000000000600082015250565b7f3c73746f70206f66667365743d223025222073746f702d636f6c6f723d22626c60008201527f61636b22202f3e00000000000000000000000000000000000000000000000000602082015250565b7f3c666554757262756c656e636520747970653d2274757262756c656e6365222060008201527f736565643d220000000000000000000000000000000000000000000000000000602082015250565b7f3c666554757262756c656e636520747970653d2274757262756c656e6365222060008201527f736565643d2235302220626173654672657175656e63793d2200000000000000602082015250565b7f3c6c696e6561724772616469656e742069643d226261636b53706c617368477260008201527f6164222078323d223025222079323d2231303025223e00000000000000000000602082015250565b7f2220784368616e6e656c53656c6563746f723d22472220794368616e6e656c5360008201527f656c6563746f723d2252222f3e203c2f66696c7465723e000000000000000000602082015250565b7f3c6665446966667573654c69676874696e6720696e3d226d6f7270686564222060008201527f6c69676874696e672d636f6c6f723d2268736c28000000000000000000000000602082015250565b7f3c6665446973706c6163656d656e744d617020696e323d2274757262756c656e60008201527f63652220696e3d22536f757263654772617068696322207363616c653d220000602082015250565b7f7b2276616c7565223a20224672616d65227d2c00000000000000000000000000600082015250565b7f22207374726f6b653d2200000000000000000000000000000000000000000000600082015250565b7f2c00000000000000000000000000000000000000000000000000000000000000600082015250565b7f302e000000000000000000000000000000000000000000000000000000000000600082015250565b7f3c73746f70206f66667365743d22353025222073746f702d636f6c6f723d227760008201527f6869746522202f3e000000000000000000000000000000000000000000000000602082015250565b7f22206e756d4f6374617665733d22352220726573756c743d2274757262756c6560008201527f6e6365222f3e0000000000000000000000000000000000000000000000000000602082015250565b7f3c2f66696c7465723e3c7265637420783d22302220793d22302220776964746860008201527f3d2236303022206865696768743d2236303022207374796c653d2266696c746560208201527f723a2075726c28236261636b67726f756e64446973706c6163656d656e74292260408201527f202f3e0000000000000000000000000000000000000000000000000000000000606082015250565b7f7b2276616c7565223a20224261636b67726f756e64227d2c207b22747261697460008201527f5f74797065223a2022436f6c6f75722031222c202276616c7565223a22000000602082015250565b7f68736c2800000000000000000000000000000000000000000000000000000000600082015250565b7f3c2f6c696e6561724772616469656e743e000000000000000000000000000000600082015250565b7f252c203530252900000000000000000000000000000000000000000000000000600082015250565b7f3c66696c7465722069643d220000000000000000000000000000000000000000600082015250565b7f7b2276616c7565223a20224261636b2053706c617368227d2c00000000000000600082015250565b7f7b2276616c7565223a20224261636b2048656164227d2c207b2274726169745f60008201527f74797065223a2022436f6c6f75722032222c202276616c7565223a2022000000602082015250565b7f3c7265637420783d22302220793d2230222077696474683d223630302220686560008201527f696768743d22363030222066696c6c3d22776869746522202f3e000000000000602082015250565b7f7b2274726169745f74797065223a202254797065222c202276616c7565223a2060008201527f22536b65746368227d2c00000000000000000000000000000000000000000000602082015250565b7f3c6665446973706c6163656d656e744d617020696e323d2274757262756c656e60008201527f63652220696e3d22536f757263654772617068696322207363616c653d22323060208201527f302220784368616e6e656c53656c6563746f723d22472220794368616e6e656c60408201527f53656c6563746f723d2241222f3e3c2f66696c7465723e000000000000000000606082015250565b7f302e300000000000000000000000000000000000000000000000000000000000600082015250565b7f227d000000000000000000000000000000000000000000000000000000000000600082015250565b7f2220723d22000000000000000000000000000000000000000000000000000000600082015250565b7f3c6665446973706c6163656d656e744d617020696e323d2274757262756c656e60008201527f63652220696e3d22536f757263654772617068696322207363616c653d22353060208201527f2220784368616e6e656c53656c6563746f723d22522220794368616e6e656c5360408201527f656c6563746f723d2247222f3e203c2f66696c7465723e000000000000000000606082015250565b7f22206e756d4f6374617665733d22352220726573756c743d2274757262756c6560008201527f6e6365222f3e3c6665446973706c6163656d656e744d617020696e323d22747560208201527f7262756c656e63652220696e3d22536f7572636547726170686963222073636160408201527f6c653d2200000000000000000000000000000000000000000000000000000000606082015250565b7f302e303030000000000000000000000000000000000000000000000000000000600082015250565b7f2220626173654672657175656e63793d22000000000000000000000000000000600082015250565b7f3c7376672077696474683d2236303022206865696768743d223630302220766960008201527f6577426f783d2230203020363030203630302220786d6c6e733d22687474703a60208201527f2f2f7777772e77332e6f72672f323030302f737667223e000000000000000000604082015250565b7f222077696474683d223330302522206865696768743d2233303025223e000000600082015250565b7f252c20353025292220737572666163655363616c653d22000000000000000000600082015250565b7f22207374726f6b652d77696474683d2200000000000000000000000000000000600082015250565b7f223e3c666544697374616e744c6967687420617a696d7574683d22343522206560008201527f6c65766174696f6e3d2200000000000000000000000000000000000000000000602082015250565b7f2261747472696275746573223a205b0000000000000000000000000000000000600082015250565b7f3c6665446973706c6163656d656e744d617020696e323d2274757262756c656e60008201527f63652220696e3d22536f757263654772617068696322207363616c653d22313060208201527f302220784368616e6e656c53656c6563746f723d22522220794368616e6e656c60408201527f53656c6563746f723d2247222f3e3c2f66696c7465723e000000000000000000606082015250565b7f222f3e0000000000000000000000000000000000000000000000000000000000600082015250565b7f5d00000000000000000000000000000000000000000000000000000000000000600082015250565b7f3c7265637420783d2235302220793d223530222077696474683d22353030222060008201527f6865696768743d2235303022207374726f6b653d22626c61636b22206f70616360208201527f6974793d22302e35222066696c6c3d22776869746522207374726f6b652d776960408201527f6474683d22000000000000000000000000000000000000000000000000000000606082015250565b7f2220784368616e6e656c53656c6563746f723d22472220794368616e6e656c5360008201527f656c6563746f723d2241222f3e203c2f66696c7465723e000000000000000000602082015250565b7f2c20000000000000000000000000000000000000000000000000000000000000600082015250565b7f3c2f646566733e00000000000000000000000000000000000000000000000000600082015250565b7f746f55696e74385f6f766572666c6f7700000000000000000000000000000000600082015250565b7f222066696c6c3d22000000000000000000000000000000000000000000000000600082015250565b7f22202f3e3c2f6665446966667573654c69676874696e673e0000000000000000600082015250565b7f7b2274726169745f74797065223a2022436f6c6f757220436f6d706f7369746960008201527f6f6e2054797065222c202276616c7565223a2022000000000000000000000000602082015250565b7f22207374796c653d2266696c7465723a2075726c28236672616d65446973706c60008201527f6163656d656e7429222f3e000000000000000000000000000000000000000000602082015250565b7f3c646566733e0000000000000000000000000000000000000000000000000000600082015250565b7f746f55696e74385f6f75744f66426f756e647300000000000000000000000000600082015250565b7f22207d2c00000000000000000000000000000000000000000000000000000000600082015250565b7f2220794368616e6e656c53656c6563746f723d224122202f3e203c2f66696c7460008201527f65723e0000000000000000000000000000000000000000000000000000000000602082015250565b7f7b2274726169745f74797065223a20224c6179657273222c202276616c75652260008201527f3a20220000000000000000000000000000000000000000000000000000000000602082015250565b7f3c6665446973706c6163656d656e744d617020696e323d2274757262756c656e60008201527f63652220696e3d22536f757263654772617068696322207363616c653d22323060208201527f302220784368616e6e656c53656c6563746f723d220000000000000000000000604082015250565b7f3c2f7376673e0000000000000000000000000000000000000000000000000000600082015250565b7f7b2276616c7565223a202246726f6e742048656164227d2c207b22747261697460008201527f5f74797065223a2022436f6c6f75722033222c202276616c7565223a20220000602082015250565b7f7b2276616c7565223a2022426f6479227d2c0000000000000000000000000000600082015250565b7f7b2274726169745f74797065223a202254797065222c202276616c7565223a2060008201527f2246756c6c79205061696e746564227d2c000000000000000000000000000000602082015250565b7f7b2276616c7565223a202245796573227d2c0000000000000000000000000000600082015250565b61588381614457565b811461588e57600080fd5b50565b61589a8161447b565b81146158a557600080fd5b5056fea26469706673582212203c3beb57ed64c29aebd937e849700d2474d23d35feb41b8c5edc41530ca200b064736f6c6343000804003300000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000af69610ea9ddc95883f97a6a3171d52165b69b03000000000000000000000000ec0ef86a3872829f3ec40de1b1b9df54a3d4a4b300000000000000000000000000000000000000000000000000000000614dd9e0000000000000000000000000000000000000000000000000000000006172c3e0000000000000000000000000600a4446094c341693c415e6743567b9bfc8a4a8000000000000000000000000000000000000000000000000000000000000001c5061696e74696e6773206f6620466f72676f7474656e20536f756c73000000000000000000000000000000000000000000000000000000000000000000000005534f554c53000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106101c25760003560e01c806370a08231116100f7578063b88d4fde11610095578063dd74533b11610064578063dd74533b14610690578063e086e5ec146106cd578063e39e867d146106e4578063e985e9c5146106ee576101c2565b8063b88d4fde146105d4578063c24a0f8b146105fd578063c87b56dd14610628578063d638bead14610665576101c2565b8063913e77ad116100d1578063913e77ad1461051857806395d89b4114610543578063a22cb4651461056e578063a48b3b8f14610597576101c2565b806370a082311461047357806379b92f27146104b05780638da5cb5b146104ed576101c2565b8063303e74df116101645780634b44d8121161013e5780634b44d812146103a35780636352211e146103e057806365ec57951461041d57806366d003ac14610448576101c2565b8063303e74df14610312578063324165021461033d57806342842e0e1461037a576101c2565b8063095ea7b3116101a0578063095ea7b31461026c5780630b97bc861461029557806317dd4dcd146102c057806323b872dd146102e9576101c2565b806301ffc9a7146101c757806306fdde0314610204578063081812fc1461022f575b600080fd5b3480156101d357600080fd5b506101ee60048036038101906101e991906126a4565b61072b565b6040516101fb9190612daf565b60405180910390f35b34801561021057600080fd5b5061021961080d565b6040516102269190612e00565b60405180910390f35b34801561023b57600080fd5b5061025660048036038101906102519190612737565b61089f565b6040516102639190612d2d565b60405180910390f35b34801561027857600080fd5b50610293600480360381019061028e9190612668565b610924565b005b3480156102a157600080fd5b506102aa610a2e565b6040516102b791906130f2565b60405180910390f35b3480156102cc57600080fd5b506102e760048036038101906102e29190612737565b610a34565b005b3480156102f557600080fd5b50610310600480360381019061030b9190612562565b610cb9565b005b34801561031e57600080fd5b50610327610d12565b6040516103349190612de5565b60405180910390f35b34801561034957600080fd5b50610364600480360381019061035f9190612737565b610d38565b6040516103719190612daf565b60405180910390f35b34801561038657600080fd5b506103a1600480360381019061039c9190612562565b610d58565b005b3480156103af57600080fd5b506103ca60048036038101906103c59190612737565b610d78565b6040516103d79190612e00565b60405180910390f35b3480156103ec57600080fd5b5061040760048036038101906104029190612737565b610e53565b6040516104149190612d2d565b60405180910390f35b34801561042957600080fd5b50610432610f05565b60405161043f91906130f2565b60405180910390f35b34801561045457600080fd5b5061045d610f0b565b60405161046a9190612d48565b60405180910390f35b34801561047f57600080fd5b5061049a600480360381019061049591906124d4565b610f31565b6040516104a791906130f2565b60405180910390f35b3480156104bc57600080fd5b506104d760048036038101906104d29190612737565b610fe9565b6040516104e49190612e00565b60405180910390f35b3480156104f957600080fd5b506105026110c4565b60405161050f9190612d2d565b60405180910390f35b34801561052457600080fd5b5061052d6110ea565b60405161053a9190612d2d565b60405180910390f35b34801561054f57600080fd5b50610558611110565b6040516105659190612e00565b60405180910390f35b34801561057a57600080fd5b506105956004803603810190610590919061262c565b6111a2565b005b3480156105a357600080fd5b506105be60048036038101906105b99190612737565b61130e565b6040516105cb9190612e00565b60405180910390f35b3480156105e057600080fd5b506105fb60048036038101906105f691906125b1565b61132e565b005b34801561060957600080fd5b50610612611389565b60405161061f91906130f2565b60405180910390f35b34801561063457600080fd5b5061064f600480360381019061064a9190612737565b61138f565b60405161065c9190612e00565b60405180910390f35b34801561067157600080fd5b5061067a6115bf565b6040516106879190612dca565b60405180910390f35b34801561069c57600080fd5b506106b760048036038101906106b29190612737565b6115e5565b6040516106c49190612daf565b60405180910390f35b3480156106d957600080fd5b506106e2611605565b005b6106ec611700565b005b3480156106fa57600080fd5b5061071560048036038101906107109190612526565b61185e565b6040516107229190612daf565b60405180910390f35b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107f657507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610806575061080582611ab4565b5b9050919050565b60606000805461081c90613425565b80601f016020809104026020016040519081016040528092919081815260200182805461084890613425565b80156108955780601f1061086a57610100808354040283529160200191610895565b820191906000526020600020905b81548152906001019060200180831161087857829003601f168201915b5050505050905090565b60006108aa82611b1e565b6108e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e090613012565b60405180910390fd5b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600061092f82610e53565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614156109a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099790613072565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806109e057506109df813361185e565b5b610a1f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a1690612f72565b60405180910390fd5b610a298383611b8a565b505050565b600a5481565b600a544211610a78576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6f90613092565b60405180910390fd5b600b544210610abc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ab390612ef2565b60405180910390fd5b60001515600f600083815260200190815260200160002060009054906101000a900460ff16151514610b23576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b1a90612e72565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff16600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401610b9591906130f2565b60206040518083038186803b158015610bad57600080fd5b505afa158015610bc1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be591906124fd565b73ffffffffffffffffffffffffffffffffffffffff1614610c3b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c3290612fd2565b60405180910390fd5b6001600f600083815260200190815260200160002060006101000a81548160ff021916908315150217905550610c72600133611c43565b803373ffffffffffffffffffffffffffffffffffffffff167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d460405160405180910390a350565b610cc33382611cad565b610d02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cf9906130b2565b60405180910390fd5b610d0d838383611d8b565b505050565b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600c6020528060005260406000206000915054906101000a900460ff1681565b610d738383836040518060200160405280600081525061132e565b505050565b6060600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663effaaf6a83600c600086815260200190815260200160002060009054906101000a900460ff166040518363ffffffff1660e01b8152600401610df792919061310d565b60006040518083038186803b158015610e0f57600080fd5b505afa158015610e23573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610e4c91906126f6565b9050919050565b6000806002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610efc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef390612fb2565b60405180910390fd5b80915050919050565b60095481565b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610fa2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f9990612f92565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6060600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166337ee03ec83600c600086815260200190815260200160002060009054906101000a900460ff166040518363ffffffff1660e01b815260040161106892919061310d565b60006040518083038186803b15801561108057600080fd5b505afa158015611094573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906110bd91906126f6565b9050919050565b600660009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606001805461111f90613425565b80601f016020809104026020016040519081016040528092919081815260200182805461114b90613425565b80156111985780601f1061116d57610100808354040283529160200191611198565b820191906000526020600020905b81548152906001019060200180831161117b57829003601f168201915b5050505050905090565b3373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611211576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120890612ed2565b60405180910390fd5b80600560003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516113029190612daf565b60405180910390a35050565b6060600061131b83610d78565b905061132681611fdc565b915050919050565b6113383383611cad565b611377576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161136e906130b2565b60405180910390fd5b61138384848484612187565b50505050565b600b5481565b606061139a82611b1e565b6113d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113d090613052565b60405180910390fd5b60006040518060400160405280600881526020017f536b657463686564000000000000000000000000000000000000000000000000815250905060011515600c600085815260200190815260200160002060009054906101000a900460ff1615151415611479576040518060400160405280600d81526020017f46756c6c79205061696e7465640000000000000000000000000000000000000081525090505b6000600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c94123f083866040518363ffffffff1660e01b81526004016114d8929190612e22565b60006040518083038186803b1580156114f057600080fd5b505afa158015611504573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061152d91906126f6565b905060006040518060a00160405280607b8152602001613c4b607b9139905060006115578661130e565b9050600061156487610fe9565b9050611594848484846040516020016115809493929190612c5f565b604051602081830303815290604052611fdc565b6040516020016115a49190612cdf565b60405160208183030381529060405295505050505050919050565b600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600f6020528060005260406000206000915054906101000a900460ff1681565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611695576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161168c90612f32565b60405180910390fd5b600860009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc479081150290604051600060405180830381858888f193505050501580156116fd573d6000803e3d6000fd5b50565b600a544211611744576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161173b90613092565b60405180910390fd5b600b544210611788576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161177f90612ef2565b60405180910390fd5b662386f26fc100003410156117d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117c990612f52565b60405180910390fd5b66f195a3c4ba00003410611850576001600960008282546117f39190613200565b9250508190555060606009541115611840576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611837906130d2565b60405180910390fd5b61184b600133611c43565b61185c565b61185b600033611c43565b5b565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611962576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161195990612ff2565b60405180910390fd5b61196b81611b1e565b156119ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119a290612e92565b60405180910390fd5b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546119fb9190613200565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166002600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16611bfd83610e53565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60004282604051602001611c58929190612d01565b6040516020818303038152906040528051906020012060001c905082600c600083815260200190815260200160002060006101000a81548160ff021916908315150217905550611ca882826118f2565b505050565b6000611cb882611b1e565b611cf7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cee90612f12565b60405180910390fd5b6000611d0283610e53565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611d7157508373ffffffffffffffffffffffffffffffffffffffff16611d598461089f565b73ffffffffffffffffffffffffffffffffffffffff16145b80611d825750611d81818561185e565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16611dab82610e53565b73ffffffffffffffffffffffffffffffffffffffff1614611e01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611df890613032565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611e71576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e6890612eb2565b60405180910390fd5b611e7c600082611b8a565b6001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611ecc91906132e1565b925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611f239190613200565b92505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6060600082511415611fff57604051806020016040528060008152509050612182565b6000604051806060016040528060408152602001613c0b604091399050600060036002855161202e9190613200565b6120389190613256565b60046120449190613287565b905060006020826120559190613200565b67ffffffffffffffff811115612094577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519080825280601f01601f1916602001820160405280156120c65781602001600182028036833780820191505090505b509050818152600183018586518101602084015b81831015612141576003830192508251603f8160121c1685015160f81b8252600182019150603f81600c1c1685015160f81b8252600182019150603f8160061c1685015160f81b8252600182019150603f811685015160f81b8252600182019150506120da565b60038951066001811461215b576002811461216b57612176565b613d3d60f01b6002830352612176565b603d60f81b60018303525b50505050508093505050505b919050565b612192848484611d8b565b61219e848484846121e3565b6121dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121d490612e52565b60405180910390fd5b50505050565b60006122048473ffffffffffffffffffffffffffffffffffffffff16612373565b15612366578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02338786866040518563ffffffff1660e01b81526004016122489493929190612d63565b602060405180830381600087803b15801561226257600080fd5b505af192505050801561229357506040513d601f19601f8201168201806040525081019061229091906126cd565b60015b612316573d80600081146122c3576040519150601f19603f3d011682016040523d82523d6000602084013e6122c8565b606091505b5060008151141561230e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161230590612e52565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161491505061236b565b600190505b949350505050565b600080823b905060008111915050919050565b60006123996123948461315b565b613136565b9050828152602081018484840111156123b157600080fd5b6123bc8482856133e3565b509392505050565b60006123d76123d28461318c565b613136565b9050828152602081018484840111156123ef57600080fd5b6123fa8482856133f2565b509392505050565b60008135905061241181613bae565b92915050565b60008151905061242681613bae565b92915050565b60008135905061243b81613bc5565b92915050565b60008135905061245081613bdc565b92915050565b60008151905061246581613bdc565b92915050565b600082601f83011261247c57600080fd5b813561248c848260208601612386565b91505092915050565b600082601f8301126124a657600080fd5b81516124b68482602086016123c4565b91505092915050565b6000813590506124ce81613bf3565b92915050565b6000602082840312156124e657600080fd5b60006124f484828501612402565b91505092915050565b60006020828403121561250f57600080fd5b600061251d84828501612417565b91505092915050565b6000806040838503121561253957600080fd5b600061254785828601612402565b925050602061255885828601612402565b9150509250929050565b60008060006060848603121561257757600080fd5b600061258586828701612402565b935050602061259686828701612402565b92505060406125a7868287016124bf565b9150509250925092565b600080600080608085870312156125c757600080fd5b60006125d587828801612402565b94505060206125e687828801612402565b93505060406125f7878288016124bf565b925050606085013567ffffffffffffffff81111561261457600080fd5b6126208782880161246b565b91505092959194509250565b6000806040838503121561263f57600080fd5b600061264d85828601612402565b925050602061265e8582860161242c565b9150509250929050565b6000806040838503121561267b57600080fd5b600061268985828601612402565b925050602061269a858286016124bf565b9150509250929050565b6000602082840312156126b657600080fd5b60006126c484828501612441565b91505092915050565b6000602082840312156126df57600080fd5b60006126ed84828501612456565b91505092915050565b60006020828403121561270857600080fd5b600082015167ffffffffffffffff81111561272257600080fd5b61272e84828501612495565b91505092915050565b60006020828403121561274957600080fd5b6000612757848285016124bf565b91505092915050565b61276981613327565b82525050565b61277881613315565b82525050565b61278f61278a82613315565b613488565b82525050565b61279e81613339565b82525050565b60006127af826131bd565b6127b981856131d3565b93506127c98185602086016133f2565b6127d281613572565b840191505092915050565b6127e68161339b565b82525050565b6127f5816133bf565b82525050565b6000612806826131c8565b61281081856131e4565b93506128208185602086016133f2565b61282981613572565b840191505092915050565b600061283f826131c8565b61284981856131f5565b93506128598185602086016133f2565b80840191505092915050565b60006128726009836131f5565b915061287d82613590565b600982019050919050565b60006128956032836131e4565b91506128a0826135b9565b604082019050919050565b60006128b86015836131e4565b91506128c382613608565b602082019050919050565b60006128db6002836131f5565b91506128e682613631565b600282019050919050565b60006128fe601c836131e4565b91506129098261365a565b602082019050919050565b60006129216024836131e4565b915061292c82613683565b604082019050919050565b60006129446019836131e4565b915061294f826136d2565b602082019050919050565b60006129676005836131e4565b9150612972826136fb565b602082019050919050565b600061298a602c836131e4565b915061299582613724565b604082019050919050565b60006129ad600d836131e4565b91506129b882613773565b602082019050919050565b60006129d0600f836131e4565b91506129db8261379c565b602082019050919050565b60006129f36038836131e4565b91506129fe826137c5565b604082019050919050565b6000612a16602a836131e4565b9150612a2182613814565b604082019050919050565b6000612a396029836131e4565b9150612a4482613863565b604082019050919050565b6000612a5c6019836131e4565b9150612a67826138b2565b602082019050919050565b6000612a7f6020836131e4565b9150612a8a826138db565b602082019050919050565b6000612aa2600d836131f5565b9150612aad82613904565b600d82019050919050565b6000612ac56001836131f5565b9150612ad08261392d565b600182019050919050565b6000612ae8602c836131e4565b9150612af382613956565b604082019050919050565b6000612b0b6012836131f5565b9150612b16826139a5565b601282019050919050565b6000612b2e6029836131e4565b9150612b39826139ce565b604082019050919050565b6000612b51602f836131e4565b9150612b5c82613a1d565b604082019050919050565b6000612b746021836131e4565b9150612b7f82613a6c565b604082019050919050565b6000612b97601d836131f5565b9150612ba282613abb565b601d82019050919050565b6000612bba600b836131e4565b9150612bc582613ae4565b602082019050919050565b6000612bdd6031836131e4565b9150612be882613b0d565b604082019050919050565b6000612c00600b836131e4565b9150612c0b82613b5c565b602082019050919050565b6000612c23601a836131f5565b9150612c2e82613b85565b601a82019050919050565b612c4281613391565b82525050565b612c59612c5482613391565b6134ac565b82525050565b6000612c6a82612865565b9150612c768287612834565b9150612c8182612afe565b9150612c8d8286612834565b9150612c9882612a95565b9150612ca382612c16565b9150612caf8285612834565b9150612cba826128ce565b9150612cc68284612834565b9150612cd182612ab8565b915081905095945050505050565b6000612cea82612b8a565b9150612cf68284612834565b915081905092915050565b6000612d0d8285612c48565b602082019150612d1d828461277e565b6014820191508190509392505050565b6000602082019050612d42600083018461276f565b92915050565b6000602082019050612d5d6000830184612760565b92915050565b6000608082019050612d78600083018761276f565b612d85602083018661276f565b612d926040830185612c39565b8181036060830152612da481846127a4565b905095945050505050565b6000602082019050612dc46000830184612795565b92915050565b6000602082019050612ddf60008301846127dd565b92915050565b6000602082019050612dfa60008301846127ec565b92915050565b60006020820190508181036000830152612e1a81846127fb565b905092915050565b60006040820190508181036000830152612e3c81856127fb565b9050612e4b6020830184612c39565b9392505050565b60006020820190508181036000830152612e6b81612888565b9050919050565b60006020820190508181036000830152612e8b816128ab565b9050919050565b60006020820190508181036000830152612eab816128f1565b9050919050565b60006020820190508181036000830152612ecb81612914565b9050919050565b60006020820190508181036000830152612eeb81612937565b9050919050565b60006020820190508181036000830152612f0b8161295a565b9050919050565b60006020820190508181036000830152612f2b8161297d565b9050919050565b60006020820190508181036000830152612f4b816129a0565b9050919050565b60006020820190508181036000830152612f6b816129c3565b9050919050565b60006020820190508181036000830152612f8b816129e6565b9050919050565b60006020820190508181036000830152612fab81612a09565b9050919050565b60006020820190508181036000830152612fcb81612a2c565b9050919050565b60006020820190508181036000830152612feb81612a4f565b9050919050565b6000602082019050818103600083015261300b81612a72565b9050919050565b6000602082019050818103600083015261302b81612adb565b9050919050565b6000602082019050818103600083015261304b81612b21565b9050919050565b6000602082019050818103600083015261306b81612b44565b9050919050565b6000602082019050818103600083015261308b81612b67565b9050919050565b600060208201905081810360008301526130ab81612bad565b9050919050565b600060208201905081810360008301526130cb81612bd0565b9050919050565b600060208201905081810360008301526130eb81612bf3565b9050919050565b60006020820190506131076000830184612c39565b92915050565b60006040820190506131226000830185612c39565b61312f6020830184612795565b9392505050565b6000613140613151565b905061314c8282613457565b919050565b6000604051905090565b600067ffffffffffffffff82111561317657613175613543565b5b61317f82613572565b9050602081019050919050565b600067ffffffffffffffff8211156131a7576131a6613543565b5b6131b082613572565b9050602081019050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600061320b82613391565b915061321683613391565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561324b5761324a6134b6565b5b828201905092915050565b600061326182613391565b915061326c83613391565b92508261327c5761327b6134e5565b5b828204905092915050565b600061329282613391565b915061329d83613391565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156132d6576132d56134b6565b5b828202905092915050565b60006132ec82613391565b91506132f783613391565b92508282101561330a576133096134b6565b5b828203905092915050565b600061332082613371565b9050919050565b600061333282613371565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006133a6826133ad565b9050919050565b60006133b882613371565b9050919050565b60006133ca826133d1565b9050919050565b60006133dc82613371565b9050919050565b82818337600083830152505050565b60005b838110156134105780820151818401526020810190506133f5565b8381111561341f576000848401525b50505050565b6000600282049050600182168061343d57607f821691505b6020821081141561345157613450613514565b5b50919050565b61346082613572565b810181811067ffffffffffffffff8211171561347f5761347e613543565b5b80604052505050565b60006134938261349a565b9050919050565b60006134a582613583565b9050919050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b60008160601b9050919050565b7f7b226e616d65223a220000000000000000000000000000000000000000000000600082015250565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b7f41435f494420414c524541445920434c41494d45440000000000000000000000600082015250565b7f222c000000000000000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b7f454e444544000000000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f4e4f545f434f4c4c4543544f5200000000000000000000000000000000000000600082015250565b7f4d4f524520455448204e45454445440000000000000000000000000000000000600082015250565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b7f41435f4944204e4f54204f574e45442042592053454e44455200000000000000600082015250565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b7f222c2022696d616765223a202200000000000000000000000000000000000000600082015250565b7f7d00000000000000000000000000000000000000000000000000000000000000600082015250565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b7f222c20226465736372697074696f6e223a220000000000000000000000000000600082015250565b7f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008201527f73206e6f74206f776e0000000000000000000000000000000000000000000000602082015250565b7f4552433732314d657461646174613a2055524920717565727920666f72206e6f60008201527f6e6578697374656e7420746f6b656e0000000000000000000000000000000000602082015250565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000600082015250565b7f4e4f545f53544152544544000000000000000000000000000000000000000000600082015250565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b7f4d41585f534f4c445f3936000000000000000000000000000000000000000000600082015250565b7f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000600082015250565b613bb781613315565b8114613bc257600080fd5b50565b613bce81613339565b8114613bd957600080fd5b50565b613be581613345565b8114613bf057600080fd5b50565b613bfc81613391565b8114613c0757600080fd5b5056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f5061696e74696e6773206f6620666f72676f7474656e20736f756c7320627920766172696f75732073696d756c61746564206d696e647320746861742074727920746f2072656d656d6265722074686f73652077686f2074686579206f6e6365206b6e657720696e207468652064656661756c7420776f726c642ea26469706673582212204a120aa6acbfed0c15ede9f9b2cd7f260b9e4b708eab91e0c852482dab86724864736f6c63430008040033

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

00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000af69610ea9ddc95883f97a6a3171d52165b69b03000000000000000000000000ec0ef86a3872829f3ec40de1b1b9df54a3d4a4b300000000000000000000000000000000000000000000000000000000614dd9e0000000000000000000000000000000000000000000000000000000006172c3e0000000000000000000000000600a4446094c341693c415e6743567b9bfc8a4a8000000000000000000000000000000000000000000000000000000000000001c5061696e74696e6773206f6620466f72676f7474656e20536f756c73000000000000000000000000000000000000000000000000000000000000000000000005534f554c53000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : name_ (string): Paintings of Forgotten Souls
Arg [1] : symbol_ (string): SOULS
Arg [2] : collector_ (address): 0xaF69610ea9ddc95883f97a6a3171d52165b69B03
Arg [3] : recipient_ (address): 0xec0ef86a3872829F3EC40de1b1b9Df54a3D4a4b3
Arg [4] : startDate_ (uint256): 1632492000
Arg [5] : endDate_ (uint256): 1634911200
Arg [6] : certificates_ (address): 0x600a4446094C341693C415E6743567b9bfc8a4A8

-----Encoded View---------------
11 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [2] : 000000000000000000000000af69610ea9ddc95883f97a6a3171d52165b69b03
Arg [3] : 000000000000000000000000ec0ef86a3872829f3ec40de1b1b9df54a3d4a4b3
Arg [4] : 00000000000000000000000000000000000000000000000000000000614dd9e0
Arg [5] : 000000000000000000000000000000000000000000000000000000006172c3e0
Arg [6] : 000000000000000000000000600a4446094c341693c415e6743567b9bfc8a4a8
Arg [7] : 000000000000000000000000000000000000000000000000000000000000001c
Arg [8] : 5061696e74696e6773206f6620466f72676f7474656e20536f756c7300000000
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [10] : 534f554c53000000000000000000000000000000000000000000000000000000


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.