ETH Price: $3,282.85 (-1.99%)
Gas: 14.4 Gwei

Contract

0xdFC243bb46DbDBC5923a52Cb46dD237b3648f20c
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Set Token URI Pr...133592032021-10-05 12:55:091144 days ago1633438509IN
0xdFC243bb...b3648f20c
0 ETH0.0036720897.12719439
Purchase131226122021-08-29 20:47:241180 days ago1630270044IN
0xdFC243bb...b3648f20c
0 ETH0.59909418,000
Purchase131226102021-08-29 20:46:531180 days ago1630270013IN
0xdFC243bb...b3648f20c
0 ETH0.59909418,000
Withdraw130444762021-08-17 19:01:121193 days ago1629226872IN
0xdFC243bb...b3648f20c
0 ETH0.0013185139.17985749
Withdraw130444632021-08-17 18:57:421193 days ago1629226662IN
0xdFC243bb...b3648f20c
0 ETH0.0012388436.81217597
Withdraw130444542021-08-17 18:56:141193 days ago1629226574IN
0xdFC243bb...b3648f20c
0 ETH0.0011507234.20607957
Set Token URI Pr...130443702021-08-17 18:40:521193 days ago1629225652IN
0xdFC243bb...b3648f20c
0 ETH0.00179944.0329307
Purchase129979982021-08-10 14:32:441200 days ago1628605964IN
0xdFC243bb...b3648f20c
0.4169 ETH0.0017225251.75400856
Purchase129974192021-08-10 12:33:011200 days ago1628598781IN
0xdFC243bb...b3648f20c
0.4169 ETH0.0013313240
Purchase129947742021-08-10 2:42:171200 days ago1628563337IN
0xdFC243bb...b3648f20c
0.4169 ETH0.0026342279.14631408
Purchase129943872021-08-10 1:14:461200 days ago1628558086IN
0xdFC243bb...b3648f20c
0.4169 ETH0.0011316234
Purchase129929602021-08-09 19:49:201200 days ago1628538560IN
0xdFC243bb...b3648f20c
0.8338 ETH0.00299289.89596978
Purchase129929602021-08-09 19:49:201200 days ago1628538560IN
0xdFC243bb...b3648f20c
0.8338 ETH0.0017373752.20005658
Purchase129929112021-08-09 19:39:531200 days ago1628537993IN
0xdFC243bb...b3648f20c
0.4169 ETH0.036959181,110.45243952
Purchase129928342021-08-09 19:22:121200 days ago1628536932IN
0xdFC243bb...b3648f20c
0.4169 ETH0.0026626480
Purchase129928212021-08-09 19:18:201200 days ago1628536700IN
0xdFC243bb...b3648f20c
0.4169 ETH0.0033916101.9020397
Purchase129928112021-08-09 19:17:001200 days ago1628536620IN
0xdFC243bb...b3648f20c
0.4169 ETH0.0018945956.92382817
Purchase129928112021-08-09 19:17:001200 days ago1628536620IN
0xdFC243bb...b3648f20c
1.6676 ETH0.0019574358.8119348
Purchase129927962021-08-09 19:14:161201 days ago1628536456IN
0xdFC243bb...b3648f20c
2.0845 ETH0.0022632468
Purchase129927952021-08-09 19:14:131201 days ago1628536453IN
0xdFC243bb...b3648f20c
0.4169 ETH0.0017995754.0690064
Purchase129927952021-08-09 19:14:131201 days ago1628536453IN
0xdFC243bb...b3648f20c
0.4169 ETH0.0017995754.0690064
Purchase129927952021-08-09 19:14:131201 days ago1628536453IN
0xdFC243bb...b3648f20c
0.4169 ETH0.0021026163.1737535
Purchase129927952021-08-09 19:14:131201 days ago1628536453IN
0xdFC243bb...b3648f20c
0.4169 ETH0.0017995754.0690064
Purchase129927942021-08-09 19:14:061201 days ago1628536446IN
0xdFC243bb...b3648f20c
2.0845 ETH0.0022965269
Purchase129927912021-08-09 19:13:261201 days ago1628536406IN
0xdFC243bb...b3648f20c
0.4169 ETH0.0026726280.3
View all transactions

Latest 5 internal transactions

Advanced mode:
Parent Transaction Hash Block From To
130444762021-08-17 19:01:121193 days ago1629226872
0xdFC243bb...b3648f20c
167.1769 ETH
130444632021-08-17 18:57:421193 days ago1629226662
0xdFC243bb...b3648f20c
667.7076 ETH
130444542021-08-17 18:56:141193 days ago1629226574
0xdFC243bb...b3648f20c
1 ETH
129927202021-08-09 18:59:201201 days ago1628535560
0xdFC243bb...b3648f20c
2.0845 ETH
129927202021-08-09 18:59:201201 days ago1628535560
0xdFC243bb...b3648f20c
2.0845 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FVCKCRYSTAL

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 300 runs

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

pragma solidity ^0.8.0;

/// @artist: FVCKRENDER
/// @author: manifold.xyz

//////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                          //
//                                                                                          //
//        _______    __________ __     ____________  ________________    __       __ __     //
//       / ____/ |  / / ____/ //_/    / ____/ __ \ \/ / ___/_  __/   |  / /     _/_//_/     //
//      / /_   | | / / /   / ,<      / /   / /_/ /\  /\__ \ / / / /| | / /    _/_//_/       //
//     / __/   | |/ / /___/ /| |    / /___/ _, _/ / /___/ // / / ___ |/ /____/_//_/         //
//    /_/      |___/\____/_/ |_|____\____/_/ |_| /_//____//_/ /_/  |_/_____/_//_/           //
//                                                                                          //
//                                                                                          //
//                                                                                          //
//                                                                                          //
//                                                                                          //
//                                                           69                             //
//                                                         #@,  @@*                         //
//                                                       @&        ,@@.                     //
//                                                    %@.              (@@                  //
//                                                 .@@%                    &@#              //
//                                                @%@%                         @@*          //
//                                              *@ @%                             ,@@.      //
//                                             @& @&                                 %@     //
//                                           ,@  @%                                  @@     //
//                                          @@%.@&                                  @#@     //
//                                          @/   @,                                *@ @     //
//                                          %&    #@                               @. @     //
//                                          *@      @&                            &&  @     //
//                                           @        @,                          @   @     //
//                                           @*        *@@*                      @/   @     //
//                                           @%         /@  %@@.4169,/%@@@@@@@&#*@    @     //
//                                           /@          @&    @(                @    @     //
//                                            @           @, &@                  @    @     //
//                                            @.           @@.                   @    @     //
//                                            @%           @&                    @    @     //
//                                            (@          .@@                    @    @     //
//                                            .@          &@@*                   @   .@     //
//                                             @          @./@                   @   .@     //
//                                             @(        .@  @.                  @   .@     //
//                                             %@        &&  &&                  @   .@     //
//                                              @@       @,   @                  @   (@.    //
//                                               @&@,   .@    @(                 @  @@@     //
//                                                %@.@( %@    *@                 @(@ @/     //
//                                                 .@  @@,     @,               @@# .@      //
//                                                   @( #@     #@              @.@@ &&      //
//                                                    %@ (@     @            .@   @&@       //
//                                                     .@ (@    @%          *@     @.       //
//                                                       @#/@   .@         (@    @&         //
//                                                        %@/@   @*       %@   @@           //
//                                                          @*@  (@      @&  (@             //
//                                                           @&@  @     @% ,@.              //
//                                                            %@@ &&   @/ @(                //
//                                                             .@@.@  @,@&                  //
//                                                               @FVCK@                     //
//                                                                %@@@                      //
//                                                                 69                       //
//                                                                                          //
//                                                                                          //
//////////////////////////////////////////////////////////////////////////////////////////////

import "@manifoldxyz/libraries-solidity/contracts/access/AdminControl.sol";
import "./core/IERC721CreatorCore.sol";
import "./extensions/ICreatorExtensionTokenURI.sol";
import "./redeem/ERC721BurnRedeem.sol";

import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";

/**
 * FVCK_CRYSTAL//
 */
contract FVCKCRYSTAL is AdminControl, ERC721BurnRedeem, ICreatorExtensionTokenURI {

    using Strings for uint256;

    bool private _active;
    uint256 private _activeTime;
    string private _tokenURIPrefix;

    event Unveil(uint256 collectibleId, address tokenAddress, uint256 tokenId);

    constructor(address creator) ERC721BurnRedeem(creator, 1, 4169) {}

    function supportsInterface(bytes4 interfaceId) public view virtual override(AdminControl, ERC721BurnRedeem, IERC165) returns (bool) {
        return interfaceId == type(ICreatorExtensionTokenURI).interfaceId || AdminControl.supportsInterface(interfaceId) || ERC721BurnRedeem.supportsInterface(interfaceId);
    }

    /**
     * @dev Is contract active
     */
    function active() external view returns(bool) {
        return _active;
    }

    /**
     * @dev Time to sale (in seconds)
     */
    function timeToSale() external view returns(uint256) {
        require(_active, "Inactive");
        if (block.timestamp >= (_activeTime + 3600)) return 0;
        return (_activeTime + 3600) - block.timestamp;
    }

    /**
     * @dev Pre-mine
     */
    function premine(uint256 amount) external adminRequired {
        require(!_active, "Already active");
        for (uint i = 0; i < amount; i++) {
            uint256 tokenId = super._mintRedemption(owner());
            emit Unveil(_mintNumbers[tokenId], _creator, tokenId);
        }
    }

    /**
     * @dev Activate the contract
     */
    function activate() external adminRequired {
        require(!_active, "Already active");
        _activeTime = block.timestamp;
        _active = true;
    }

    /**
     * @dev Withdraw funds
     */
    function withdraw(address payable recipient, uint256 amount) external adminRequired {
        recipient.transfer(amount);
    }

    /**
     *  @dev set the tokenURI prefix
     */
    function setTokenURIPrefix(string calldata prefix) external adminRequired {
        _tokenURIPrefix = prefix;
    }

    /**
     * @dev purchase a crystal
     */
    function purchase(uint256 amount) external payable nonReentrant {
        require(_active, "Inactive");
        require(block.timestamp >= _activeTime + 3600, "Purchasing not active");
        require(amount <= redemptionRemaining() && amount <= 5, "Too many requested");
        require(msg.value == amount*416900000000000000, "Invalid purchase amount sent");
        for (uint i = 0; i < amount; i++) {
            uint256 tokenId = super._mintRedemption(msg.sender);
            emit Unveil(_mintNumbers[tokenId], _creator, tokenId);
        }
    }

    /**
     * @dev See {IRedeemBase-redeemable}.
     */
    function redeemable(address contract_, uint256 tokenId) public view virtual override returns(bool) {
        require(_active, "Inactive");
        return super.redeemable(contract_, tokenId);
    }

    /**
     * @dev See {ERC721RedeemBase-_mintRedemption}
     */
    function _mintRedemption(address to) internal override returns(uint256) {
       // Burn redemptions will result in two crystals
       uint256 tokenId;
       tokenId = super._mintRedemption(to);
       emit Unveil(_mintNumbers[tokenId], _creator, tokenId);
       tokenId = super._mintRedemption(to);
       emit Unveil(_mintNumbers[tokenId], _creator, tokenId);
       return 0;
    }

    /**
     * @dev See {ICreatorExtensionTokenURI-tokenURI}.
     */
    function tokenURI(address creator, uint256 tokenId) external view override returns (string memory) {
        require(creator == _creator && _mintNumbers[tokenId] != 0, "Invalid token");
        return string(abi.encodePacked(_tokenURIPrefix, _mintNumbers[tokenId].toString()));
    }
}

File 2 of 27 : AdminControl.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./IAdminControl.sol";

abstract contract AdminControl is Ownable, IAdminControl, ERC165 {
    using EnumerableSet for EnumerableSet.AddressSet;

    // Track registered admins
    EnumerableSet.AddressSet private _admins;

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

    /**
     * @dev Only allows approved admins to call the specified function
     */
    modifier adminRequired() {
        require(owner() == msg.sender || _admins.contains(msg.sender), "AdminControl: Must be owner or admin");
        _;
    }   

    /**
     * @dev See {IAdminControl-getAdmins}.
     */
    function getAdmins() external view override returns (address[] memory admins) {
        admins = new address[](_admins.length());
        for (uint i = 0; i < _admins.length(); i++) {
            admins[i] = _admins.at(i);
        }
        return admins;
    }

    /**
     * @dev See {IAdminControl-approveAdmin}.
     */
    function approveAdmin(address admin) external override onlyOwner {
        if (!_admins.contains(admin)) {
            emit AdminApproved(admin, msg.sender);
            _admins.add(admin);
        }
    }

    /**
     * @dev See {IAdminControl-revokeAdmin}.
     */
    function revokeAdmin(address admin) external override onlyOwner {
        if (_admins.contains(admin)) {
            emit AdminRevoked(admin, msg.sender);
            _admins.remove(admin);
        }
    }

    /**
     * @dev See {IAdminControl-isAdmin}.
     */
    function isAdmin(address admin) public override view returns (bool) {
        return (owner() == admin || _admins.contains(admin));
    }

}

File 3 of 27 : IERC721CreatorCore.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "./ICreatorCore.sol";

/**
 * @dev Core ERC721 creator interface
 */
interface IERC721CreatorCore is ICreatorCore {

    /**
     * @dev mint a token with no extension. Can only be called by an admin.
     * Returns tokenId minted
     */
    function mintBase(address to) external returns (uint256);

    /**
     * @dev mint a token with no extension. Can only be called by an admin.
     * Returns tokenId minted
     */
    function mintBase(address to, string calldata uri) external returns (uint256);

    /**
     * @dev batch mint a token with no extension. Can only be called by an admin.
     * Returns tokenId minted
     */
    function mintBaseBatch(address to, uint16 count) external returns (uint256[] memory);

    /**
     * @dev batch mint a token with no extension. Can only be called by an admin.
     * Returns tokenId minted
     */
    function mintBaseBatch(address to, string[] calldata uris) external returns (uint256[] memory);

    /**
     * @dev mint a token. Can only be called by a registered extension.
     * Returns tokenId minted
     */
    function mintExtension(address to) external returns (uint256);

    /**
     * @dev mint a token. Can only be called by a registered extension.
     * Returns tokenId minted
     */
    function mintExtension(address to, string calldata uri) external returns (uint256);

    /**
     * @dev batch mint a token. Can only be called by a registered extension.
     * Returns tokenIds minted
     */
    function mintExtensionBatch(address to, uint16 count) external returns (uint256[] memory);

    /**
     * @dev batch mint a token. Can only be called by a registered extension.
     * Returns tokenId minted
     */
    function mintExtensionBatch(address to, string[] calldata uris) external returns (uint256[] memory);

    /**
     * @dev burn a token. Can only be called by token owner or approved address.
     * On burn, calls back to the registered extension's onBurn method
     */
    function burn(uint256 tokenId) external;

}

File 4 of 27 : ICreatorExtensionTokenURI.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "@openzeppelin/contracts/utils/introspection/IERC165.sol";

/**
 * @dev Implement this if you want your extension to have overloadable URI's
 */
interface ICreatorExtensionTokenURI is IERC165 {

    /**
     * Get the uri for a given creator/tokenId
     */
    function tokenURI(address creator, uint256 tokenId) external view returns (string memory);
}

File 5 of 27 : ERC721BurnRedeem.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

import "../core/IERC721CreatorCore.sol";

import "./ERC721RedeemBase.sol";
import "./IERC721BurnRedeem.sol";

/**
 * @dev Burn NFT's to receive another lazy minted NFT
 */
contract ERC721BurnRedeem is ReentrancyGuard, ERC721RedeemBase, IERC721BurnRedeem {
    using EnumerableSet for EnumerableSet.UintSet;

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

    constructor(address creator, uint16 redemptionRate, uint16 redemptionMax) ERC721RedeemBase(creator, redemptionRate, redemptionMax) {}

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

    /**
     * @dev See {IERC721BurnRedeem-setERC721Recoverable}
     */
    function setERC721Recoverable(address contract_, uint256 tokenId, address recoverer) external virtual override adminRequired {
        require(ERC165Checker.supportsInterface(contract_, type(IERC721).interfaceId), "BurnRedeem: Must implement IERC721");
        _recoverableERC721[contract_][tokenId] = recoverer;
    }

    /**
     * @dev See {IERC721BurnRedeem-recoverERC721}
     */
    function recoverERC721(address contract_, uint256 tokenId) external virtual override {
        address recoverer = _recoverableERC721[contract_][tokenId];
        require(recoverer == msg.sender, "BurnRedeem: Permission denied");
        IERC721(contract_).safeTransferFrom(address(this), msg.sender, tokenId);
    }

    /**
     * @dev See {IERC721BurnRedeem-redeemERC721}
     */
    function redeemERC721(address[] calldata contracts, uint256[] calldata tokenIds) external virtual override nonReentrant {
        require(contracts.length == tokenIds.length, "BurnRedeem: Invalid parameters");
        require(contracts.length == _redemptionRate, "BurnRedeem: Incorrect number of NFTs being redeemed");

        // Attempt Burn
        for (uint i=0; i<contracts.length; i++) {
            // Check that we can burn
            require(redeemable(contracts[i], tokenIds[i]), "BurnRedeem: Invalid NFT");

            try IERC721(contracts[i]).ownerOf(tokenIds[i]) returns (address ownerOfAddress) {
                require(ownerOfAddress == msg.sender, "BurnRedeem: Caller must own NFTs");
            } catch (bytes memory) {
                revert("BurnRedeem: Bad token contract");
            }

            try IERC721(contracts[i]).getApproved(tokenIds[i]) returns (address approvedAddress) {
                require(approvedAddress == address(this), "BurnRedeem: Contract must be given approval to burn NFT");
            } catch (bytes memory) {
                revert("BurnRedeem: Bad token contract");
            }
            

            // Then burn
            try IERC721(contracts[i]).transferFrom(msg.sender, address(0xdEaD), tokenIds[i]) {
            } catch (bytes memory) {
                revert("BurnRedeem: Burn failure");
            }
        }

        // Mint reward
        _mintRedemption(msg.sender);
    }

    /**
     * @dev See {IERC721Receiver-onERC721Received}.
     */
    function onERC721Received(address, address from, uint256 tokenId, bytes calldata data) external override nonReentrant returns (bytes4) {
        require(redeemable(msg.sender, tokenId), "BurnRedeem: Invalid NFT");
        require(_redemptionRate == 1, "BurnRedeem: Can only allow direct receiving of redemptions of 1 NFT");
        
        
        // Burn it
        try IERC721(msg.sender).safeTransferFrom(address(this), address(0xdEaD), tokenId, data) {
        } catch (bytes memory) {
            revert("BurnRedeem: Burn failure");
        }

        // Mint reward
        _mintRedemption(from);

        return this.onERC721Received.selector;
    }


    /**
     * @dev See {IERC1155Receiver-onERC1155Received}.
     */
    function onERC1155Received(
        address,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external override nonReentrant returns(bytes4) {
        require(redeemable(msg.sender, id), "BurnRedeem: Invalid NFT");
        require(value == _redemptionRate, "BurnRedeem: Incorrect number of NFTs being redeemed");

        // Burn it
        try IERC1155(msg.sender).safeTransferFrom(address(this), address(0xdEaD), id, value, data) {
        } catch (bytes memory) {
            revert("BurnRedeem: Burn failure");
        }

        // Mint reward
        _mintRedemption(from);

        return this.onERC1155Received.selector;
    }

    /**
     * @dev See {IERC1155Receiver-onERC1155BatchReceived}.
     */
    function onERC1155BatchReceived(
        address,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external override nonReentrant returns(bytes4) {
        require(ids.length == values.length, "BurnRedeem: Invalid input");

        uint256 totalValue = 0;
        for (uint i=0; i<ids.length; i++) {
            require(redeemable(msg.sender, ids[i]), "BurnRedeem: Invalid NFT");
            totalValue += values[i];
        }

        require(totalValue == _redemptionRate, "BurnRedeem: Incorrect number of NFTs being redeemed");

        // Burn it
        try IERC1155(msg.sender).safeBatchTransferFrom(address(this), address(0xdEaD), ids, values, data) {
        } catch (bytes memory) {
            revert("BurnRedeem: Burn failure");
        }

        // Mint reward
        _mintRedemption(from);

        return this.onERC1155BatchReceived.selector;
    }

}

File 6 of 27 : Strings.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "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] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

File 7 of 27 : ERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./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 8 of 27 : EnumerableSet.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            if (lastIndex != toDeleteIndex) {
                bytes32 lastvalue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastvalue;
                // Update the index for the moved value
                set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}

File 9 of 27 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _setOwner(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _setOwner(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 10 of 27 : IAdminControl.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "@openzeppelin/contracts/utils/introspection/IERC165.sol";

/**
 * @dev Interface for admin control
 */
interface IAdminControl is IERC165 {

    event AdminApproved(address indexed account, address indexed sender);
    event AdminRevoked(address indexed account, address indexed sender);

    /**
     * @dev gets address of all admins
     */
    function getAdmins() external view returns (address[] memory);

    /**
     * @dev add an admin.  Can only be called by contract owner.
     */
    function approveAdmin(address admin) external;

    /**
     * @dev remove an admin.  Can only be called by contract owner.
     */
    function revokeAdmin(address admin) external;

    /**
     * @dev checks whether or not given address is an admin
     * Returns True if they are
     */
    function isAdmin(address admin) external view returns (bool);

}

File 11 of 27 : 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);
}

File 12 of 27 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

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

File 13 of 27 : ICreatorCore.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "@openzeppelin/contracts/utils/introspection/IERC165.sol";

/**
 * @dev Core creator interface
 */
interface ICreatorCore is IERC165 {

    event ExtensionRegistered(address indexed extension, address indexed sender);
    event ExtensionUnregistered(address indexed extension, address indexed sender);
    event ExtensionBlacklisted(address indexed extension, address indexed sender);
    event MintPermissionsUpdated(address indexed extension, address indexed permissions, address indexed sender);
    event RoyaltiesUpdated(uint256 indexed tokenId, address payable[] receivers, uint256[] basisPoints);
    event DefaultRoyaltiesUpdated(address payable[] receivers, uint256[] basisPoints);
    event ExtensionRoyaltiesUpdated(address indexed extension, address payable[] receivers, uint256[] basisPoints);
    event ExtensionApproveTransferUpdated(address indexed extension, bool enabled);

    /**
     * @dev gets address of all extensions
     */
    function getExtensions() external view returns (address[] memory);

    /**
     * @dev add an extension.  Can only be called by contract owner or admin.
     * extension address must point to a contract implementing ICreatorExtension.
     * Returns True if newly added, False if already added.
     */
    function registerExtension(address extension, string calldata baseURI) external;

    /**
     * @dev add an extension.  Can only be called by contract owner or admin.
     * extension address must point to a contract implementing ICreatorExtension.
     * Returns True if newly added, False if already added.
     */
    function registerExtension(address extension, string calldata baseURI, bool baseURIIdentical) external;

    /**
     * @dev add an extension.  Can only be called by contract owner or admin.
     * Returns True if removed, False if already removed.
     */
    function unregisterExtension(address extension) external;

    /**
     * @dev blacklist an extension.  Can only be called by contract owner or admin.
     * This function will destroy all ability to reference the metadata of any tokens created
     * by the specified extension. It will also unregister the extension if needed.
     * Returns True if removed, False if already removed.
     */
    function blacklistExtension(address extension) external;

    /**
     * @dev set the baseTokenURI of an extension.  Can only be called by extension.
     */
    function setBaseTokenURIExtension(string calldata uri) external;

    /**
     * @dev set the baseTokenURI of an extension.  Can only be called by extension.
     * For tokens with no uri configured, tokenURI will return "uri+tokenId"
     */
    function setBaseTokenURIExtension(string calldata uri, bool identical) external;

    /**
     * @dev set the common prefix of an extension.  Can only be called by extension.
     * If configured, and a token has a uri set, tokenURI will return "prefixURI+tokenURI"
     * Useful if you want to use ipfs/arweave
     */
    function setTokenURIPrefixExtension(string calldata prefix) external;

    /**
     * @dev set the tokenURI of a token extension.  Can only be called by extension that minted token.
     */
    function setTokenURIExtension(uint256 tokenId, string calldata uri) external;

    /**
     * @dev set the tokenURI of a token extension for multiple tokens.  Can only be called by extension that minted token.
     */
    function setTokenURIExtension(uint256[] memory tokenId, string[] calldata uri) external;

    /**
     * @dev set the baseTokenURI for tokens with no extension.  Can only be called by owner/admin.
     * For tokens with no uri configured, tokenURI will return "uri+tokenId"
     */
    function setBaseTokenURI(string calldata uri) external;

    /**
     * @dev set the common prefix for tokens with no extension.  Can only be called by owner/admin.
     * If configured, and a token has a uri set, tokenURI will return "prefixURI+tokenURI"
     * Useful if you want to use ipfs/arweave
     */
    function setTokenURIPrefix(string calldata prefix) external;

    /**
     * @dev set the tokenURI of a token with no extension.  Can only be called by owner/admin.
     */
    function setTokenURI(uint256 tokenId, string calldata uri) external;

    /**
     * @dev set the tokenURI of multiple tokens with no extension.  Can only be called by owner/admin.
     */
    function setTokenURI(uint256[] memory tokenIds, string[] calldata uris) external;

    /**
     * @dev set a permissions contract for an extension.  Used to control minting.
     */
    function setMintPermissions(address extension, address permissions) external;

    /**
     * @dev Configure so transfers of tokens created by the caller (must be extension) gets approval
     * from the extension before transferring
     */
    function setApproveTransferExtension(bool enabled) external;

    /**
     * @dev get the extension of a given token
     */
    function tokenExtension(uint256 tokenId) external view returns (address);

    /**
     * @dev Set default royalties
     */
    function setRoyalties(address payable[] calldata receivers, uint256[] calldata basisPoints) external;

    /**
     * @dev Set royalties of a token
     */
    function setRoyalties(uint256 tokenId, address payable[] calldata receivers, uint256[] calldata basisPoints) external;

    /**
     * @dev Set royalties of an extension
     */
    function setRoyaltiesExtension(address extension, address payable[] calldata receivers, uint256[] calldata basisPoints) external;

    /**
     * @dev Get royalites of a token.  Returns list of receivers and basisPoints
     */
    function getRoyalties(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory);
    
    // Royalty support for various other standards
    function getFeeRecipients(uint256 tokenId) external view returns (address payable[] memory);
    function getFeeBps(uint256 tokenId) external view returns (uint[] memory);
    function getFees(uint256 tokenId) external view returns (address payable[] memory, uint256[] memory);
    function royaltyInfo(uint256 tokenId, uint256 value) external view returns (address, uint256);

}

File 14 of 27 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

        _;

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

File 15 of 27 : IERC1155.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] values
    );

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the amount of tokens of token type `id` owned by `account`.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)
        external
        view
        returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the caller.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) external;
}

File 16 of 27 : IERC721.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../../utils/introspection/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 17 of 27 : ERC165Checker.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Library used to query support of an interface declared via {IERC165}.
 *
 * Note that these functions return the actual result of the query: they do not
 * `revert` if an interface is not supported. It is up to the caller to decide
 * what to do in these cases.
 */
library ERC165Checker {
    // As per the EIP-165 spec, no interface should ever match 0xffffffff
    bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;

    /**
     * @dev Returns true if `account` supports the {IERC165} interface,
     */
    function supportsERC165(address account) internal view returns (bool) {
        // Any contract that implements ERC165 must explicitly indicate support of
        // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
        return
            _supportsERC165Interface(account, type(IERC165).interfaceId) &&
            !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
    }

    /**
     * @dev Returns true if `account` supports the interface defined by
     * `interfaceId`. Support for {IERC165} itself is queried automatically.
     *
     * See {IERC165-supportsInterface}.
     */
    function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
        // query support of both ERC165 as per the spec and support of _interfaceId
        return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);
    }

    /**
     * @dev Returns a boolean array where each value corresponds to the
     * interfaces passed in and whether they're supported or not. This allows
     * you to batch check interfaces for a contract where your expectation
     * is that some interfaces may not be supported.
     *
     * See {IERC165-supportsInterface}.
     *
     * _Available since v3.4._
     */
    function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)
        internal
        view
        returns (bool[] memory)
    {
        // an array of booleans corresponding to interfaceIds and whether they're supported or not
        bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);

        // query support of ERC165 itself
        if (supportsERC165(account)) {
            // query support of each interface in interfaceIds
            for (uint256 i = 0; i < interfaceIds.length; i++) {
                interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);
            }
        }

        return interfaceIdsSupported;
    }

    /**
     * @dev Returns true if `account` supports all the interfaces defined in
     * `interfaceIds`. Support for {IERC165} itself is queried automatically.
     *
     * Batch-querying can lead to gas savings by skipping repeated checks for
     * {IERC165} support.
     *
     * See {IERC165-supportsInterface}.
     */
    function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
        // query support of ERC165 itself
        if (!supportsERC165(account)) {
            return false;
        }

        // query support of each interface in _interfaceIds
        for (uint256 i = 0; i < interfaceIds.length; i++) {
            if (!_supportsERC165Interface(account, interfaceIds[i])) {
                return false;
            }
        }

        // all interfaces supported
        return true;
    }

    /**
     * @notice Query if a contract implements an interface, does not check ERC165 support
     * @param account The address of the contract to query for support of an interface
     * @param interfaceId The interface identifier, as specified in ERC-165
     * @return true if the contract at account indicates support of the interface with
     * identifier interfaceId, false otherwise
     * @dev Assumes that account contains a contract that supports ERC165, otherwise
     * the behavior of this method is undefined. This precondition can be checked
     * with {supportsERC165}.
     * Interface identification is specified in ERC-165.
     */
    function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
        bytes memory encodedParams = abi.encodeWithSelector(IERC165(account).supportsInterface.selector, interfaceId);
        (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);
        if (result.length < 32) return false;
        return success && abi.decode(result, (bool));
    }
}

File 18 of 27 : ERC721RedeemBase.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";

import "../core/IERC721CreatorCore.sol";
import "../extensions/CreatorExtension.sol";

import "../libraries/SingleCreatorExtension.sol";

import "./RedeemBase.sol";
import "./IERC721RedeemBase.sol";

/**
 * @dev Redeem NFT base logic
 */
abstract contract ERC721RedeemBase is ERC721SingleCreatorExtension, RedeemBase, CreatorExtension, IERC721RedeemBase {

    uint16 internal immutable _redemptionRate;
    uint16 private _redemptionMax;
    uint16 private _redemptionCount;
    uint256[] private _mintedTokens;
    mapping(uint256 => uint256) internal _mintNumbers;

    constructor(address creator, uint16 redemptionRate_, uint16 redemptionMax_) ERC721SingleCreatorExtension(creator) {
        require(ERC165Checker.supportsInterface(creator, type(IERC721CreatorCore).interfaceId) ||
                ERC165Checker.supportsInterface(creator, LegacyInterfaces.IERC721CreatorCore_v1), 
                "Redeem: Minting reward contract must implement IERC721CreatorCore");
        _redemptionRate = redemptionRate_;
        _redemptionMax = redemptionMax_;
    }     

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

    /**
     * @dev See {IERC721RedeemBase-redemptionMax}
     */
    function redemptionMax() external view virtual override returns(uint16) {
        return _redemptionMax;
    }

    /**
     * @dev See {IERC721RedeemBase-redemptionRate}
     */
    function redemptionRate() external view virtual override returns(uint16) {
        return _redemptionRate;
    }

    /**
     * @dev See {IERC721RedeemBase-redemptionRemaining}
     */
    function redemptionRemaining() public view virtual override returns(uint16) {
        return _redemptionMax-_redemptionCount;
    }

    /**
     * @dev See {IERC721RedeemBase-mintNumber}.
     */
    function mintNumber(uint256 tokenId) external view virtual override returns(uint256) {
        return _mintNumbers[tokenId];
    }

    /**
     * @dev See {IERC721RedeemBase-mintedTokens}.
     */
    function mintedTokens() external view override returns(uint256[] memory) {
        return _mintedTokens;
    }

    /**
     * @dev mint token that was redeemed for
     */
    function _mintRedemption(address to) internal virtual returns (uint256) {
        require(_redemptionCount < _redemptionMax, "Redeem: No redemptions remaining");
        _redemptionCount++;
        
        // Mint token
        uint256 tokenId = _mint(to, _redemptionCount);

        _mintedTokens.push(tokenId);
        _mintNumbers[tokenId] = _redemptionCount;
        return tokenId;
    }

    /**
     * @dev override if you want to perform different mint functionality
     */
    function _mint(address to, uint16) internal returns (uint256) {
        return IERC721CreatorCore(_creator).mintExtension(to);
    }

}

File 19 of 27 : IERC721BurnRedeem.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";

import "./IERC721RedeemBase.sol";

/**
 * @dev Burn NFT's to receive another lazy minted NFT
 */
interface IERC721BurnRedeem is IERC721RedeemBase, IERC1155Receiver, IERC721Receiver {

    /**
     * @dev Enable recovery of a given token. Can only be called by contract owner/admin.
     * This is a special function used in case someone accidentally sends a token to this contract.
     */
    function setERC721Recoverable(address contract_, uint256 tokenId, address recoverer) external;

    /**
     * @dev Recover a token.  Returns it to the recoverer set by setERC721Recoverable
     * This is a special function used in case someone accidentally sends a token to this contract.
     */
    function recoverERC721(address contract_, uint256 tokenId) external;

    /**
     * @dev Redeem ERC721 tokens for redemption reward NFT.
     * Requires the user to grant approval beforehand by calling contract's 'approve' function.
     * If the it cannot redeem the NFT, it will clear approvals
     */
    function redeemERC721(address[] calldata contracts, uint256[] calldata tokenIds) external;

}

File 20 of 27 : CreatorExtension.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "@openzeppelin/contracts/utils/introspection/ERC165.sol";

/**
 * @dev Base creator extension variables
 */
abstract contract CreatorExtension is ERC165 {

    /**
     * @dev Legacy extension interface identifiers
     *
     * {IERC165-supportsInterface} needs to return 'true' for this interface
     * in order backwards compatible with older creator contracts
     */
    bytes4 constant internal LEGACY_EXTENSION_INTERFACE = 0x7005caad;

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

File 21 of 27 : SingleCreatorExtension.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import "../core/IERC721CreatorCore.sol";

import "./LegacyInterfaces.sol";

abstract contract SingleCreatorBase {
    address internal _creator;
}

/**
 * @dev Extension that only uses a single creator contract instance
 */
abstract contract ERC721SingleCreatorExtension is SingleCreatorBase {

    constructor(address creator) {
        require(ERC165Checker.supportsInterface(creator, type(IERC721CreatorCore).interfaceId) ||
                ERC165Checker.supportsInterface(creator, LegacyInterfaces.IERC721CreatorCore_v1), 
                "Redeem: Minting reward contract must implement IERC721CreatorCore");
        _creator = creator;
    }

}

File 22 of 27 : RedeemBase.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

import "@manifoldxyz/libraries-solidity/contracts/access/AdminControl.sol";

import "./IRedeemBase.sol";

struct range{
   uint256 min;
   uint256 max;
}

/**
 * @dev Burn NFT's to receive another lazy minted NFT
 */
abstract contract RedeemBase is AdminControl, IRedeemBase {
     using EnumerableSet for EnumerableSet.UintSet;

     // approved contract tokens
    mapping(address => bool) private _approvedContracts;

    // approved specific tokens
    mapping(address => EnumerableSet.UintSet) private _approvedTokens;
    mapping(address => range[]) private _approvedTokenRange;
     
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(AdminControl, IERC165) returns (bool) {
        return interfaceId == type(IRedeemBase).interfaceId
            || super.supportsInterface(interfaceId);
    }

    /**
     * @dev See {IRedeemBase-updateApprovedContracts}
     */
    function updateApprovedContracts(address[] memory contracts, bool[] memory approved) public virtual override adminRequired {
        require(contracts.length == approved.length, "Redeem: Invalid input parameters");
        for (uint i=0; i < contracts.length; i++) {
            _approvedContracts[contracts[i]] = approved[i];
        }
        emit UpdateApprovedContracts(contracts, approved);
    }
    
    /**
     * @dev See {IRedeemBase-updateApprovedTokens}
     */
    function updateApprovedTokens(address contract_, uint256[] memory tokenIds, bool[] memory approved) public virtual override adminRequired {
        require(tokenIds.length == approved.length, "Redeem: Invalid input parameters");

        for (uint i=0; i < tokenIds.length; i++) {
            if (approved[i] && !_approvedTokens[contract_].contains(tokenIds[i])) {
                _approvedTokens[contract_].add(tokenIds[i]);
            } else if (!approved[i] && _approvedTokens[contract_].contains(tokenIds[i])) {
                _approvedTokens[contract_].remove(tokenIds[i]);
            }
        }
        emit UpdateApprovedTokens(contract_, tokenIds, approved);
    }

    /**
     * @dev See {IRedeemBase-updateApprovedTokenRanges}
     */
    function updateApprovedTokenRanges(address contract_, uint256[] memory minTokenIds, uint256[] memory maxTokenIds) public virtual override adminRequired {
        require(minTokenIds.length == maxTokenIds.length, "Redeem: Invalid input parameters");
        
        uint existingRangesLength = _approvedTokenRange[contract_].length;
        for (uint i=0; i < existingRangesLength; i++) {
            _approvedTokenRange[contract_][i].min = 0;
            _approvedTokenRange[contract_][i].max = 0;
        }
        
        for (uint i=0; i < minTokenIds.length; i++) {
            require(minTokenIds[i] < maxTokenIds[i], "Redeem: min must be less than max");
            if (i < existingRangesLength) {
                _approvedTokenRange[contract_][i].min = minTokenIds[i];
                _approvedTokenRange[contract_][i].max = maxTokenIds[i];
            } else {
                _approvedTokenRange[contract_].push(range(minTokenIds[i], maxTokenIds[i]));
            }
        }
        emit UpdateApprovedTokenRanges(contract_, minTokenIds, maxTokenIds);
    }

    /**
     * @dev See {IRedeemBase-redeemable}
     */    
    function redeemable(address contract_, uint256 tokenId) public view virtual override returns(bool) {
         if (_approvedContracts[contract_]) {
             return true;
         }
         if (_approvedTokens[contract_].contains(tokenId)) {
             return true;
         }
         if (_approvedTokenRange[contract_].length > 0) {
             for (uint i=0; i < _approvedTokenRange[contract_].length; i++) {
                 if (_approvedTokenRange[contract_][i].max != 0 && tokenId >= _approvedTokenRange[contract_][i].min && tokenId <= _approvedTokenRange[contract_][i].max) {
                     return true;
                 }
             }
         }
         return false;
    }


}

File 23 of 27 : IERC721RedeemBase.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "./IRedeemBase.sol";

/**
 * @dev Base redemption interface
 */
interface IERC721RedeemBase is IRedeemBase {
    /**
     * @dev Get the max number of redemptions
     */
    function redemptionMax() external view returns(uint16);

    /**
     * @dev Get the redemption rate
     */
    function redemptionRate() external view returns(uint16);

    /**
     * @dev Get number of redemptions left
     */
    function redemptionRemaining() external view returns(uint16);

    /**
     * @dev Get the mint number of a created token id
     */
    function mintNumber(uint256 tokenId) external view returns(uint256);

    /**
     * @dev Get list of all minted tokens
     */
    function mintedTokens() external view returns(uint256[] memory);

}

File 24 of 27 : LegacyInterfaces.sol
// SPDX-License-Identifier: BSD-4-Clause

pragma solidity ^0.8.0;

/// @author: manifold.xyz

/**
 * Library of legacy interface constants
 */
library LegacyInterfaces {

    // LEGACY ERC721CreatorCore interface
    bytes4 internal constant IERC721CreatorCore_v1 = 0x478c8530;

}

File 25 of 27 : IRedeemBase.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @author: manifold.xyz

import "@manifoldxyz/libraries-solidity/contracts/access/IAdminControl.sol";

/**
 * @dev Base redemption interface
 */
interface IRedeemBase is IAdminControl {

    event UpdateApprovedContracts(address[] contracts, bool[] approved);
    event UpdateApprovedTokens(address contract_, uint256[] tokenIds, bool[] approved);
    event UpdateApprovedTokenRanges(address contract_, uint256[] minTokenIds, uint256[] maxTokenIds);

    /**
     * @dev Update approved contracts that can be used to redeem. Can only be called by contract owner/admin.
     */
    function updateApprovedContracts(address[] calldata contracts, bool[] calldata approved) external;

    /**
     * @dev Update approved tokens that can be used to redeem. Can only be called by contract owner/admin.
     */
    function updateApprovedTokens(address contract_, uint256[] calldata tokenIds, bool[] calldata approved) external;

    /**
     * @dev Update approved token ranges that can be used to redeem. Can only be called by contract owner/admin.
     * Clears out old ranges
     */
    function updateApprovedTokenRanges(address contract_, uint256[] calldata minTokenIds, uint256[] calldata maxTokenIds) external;

    /**
     * @dev Check if an NFT is redeemable
     */
    function redeemable(address contract_, uint256 tokenId) external view returns(bool);

}

File 26 of 27 : IERC1155Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../../utils/introspection/IERC165.sol";

/**
 * @dev _Available since v3.1._
 */
interface IERC1155Receiver is IERC165 {
    /**
        @dev Handles the receipt of a single ERC1155 token type. This function is
        called at the end of a `safeTransferFrom` after the balance has been updated.
        To accept the transfer, this must return
        `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
        (i.e. 0xf23a6e61, or its own function selector).
        @param operator The address which initiated the transfer (i.e. msg.sender)
        @param from The address which previously owned the token
        @param id The ID of the token being transferred
        @param value The amount of tokens being transferred
        @param data Additional data with no specified format
        @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
    */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
        @dev Handles the receipt of a multiple ERC1155 token types. This function
        is called at the end of a `safeBatchTransferFrom` after the balances have
        been updated. To accept the transfer(s), this must return
        `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
        (i.e. 0xbc197c81, or its own function selector).
        @param operator The address which initiated the batch transfer (i.e. msg.sender)
        @param from The address which previously owned the token
        @param ids An array containing ids of each token being transferred (order and length must match values array)
        @param values An array containing amounts of each token being transferred (order and length must match ids array)
        @param data Additional data with no specified format
        @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
    */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}

File 27 of 27 : 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);
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"creator","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"AdminApproved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"AdminRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"collectibleId","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Unveil","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"contracts","type":"address[]"},{"indexed":false,"internalType":"bool[]","name":"approved","type":"bool[]"}],"name":"UpdateApprovedContracts","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"contract_","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"minTokenIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"maxTokenIds","type":"uint256[]"}],"name":"UpdateApprovedTokenRanges","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"contract_","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"indexed":false,"internalType":"bool[]","name":"approved","type":"bool[]"}],"name":"UpdateApprovedTokens","type":"event"},{"inputs":[],"name":"activate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"active","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"approveAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAdmins","outputs":[{"internalType":"address[]","name":"admins","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"isAdmin","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"mintNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintedTokens","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"premine","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"purchase","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"recoverERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"contracts","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"redeemERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"redeemable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionMax","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionRate","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"redemptionRemaining","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"revokeAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"recoverer","type":"address"}],"name":"setERC721Recoverable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"prefix","type":"string"}],"name":"setTokenURIPrefix","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeToSale","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"creator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"contracts","type":"address[]"},{"internalType":"bool[]","name":"approved","type":"bool[]"}],"name":"updateApprovedContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256[]","name":"minTokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"maxTokenIds","type":"uint256[]"}],"name":"updateApprovedTokenRanges","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"contract_","type":"address"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bool[]","name":"approved","type":"bool[]"}],"name":"updateApprovedTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a06040523480156200001157600080fd5b506040516200429338038062004293833981016040819052620000349162000394565b8060016110498282828260016000819055506200006481639088c20760e01b620001ee60201b6200267e1760201c565b80620000895750620000898163478c853060e01b620001ee60201b6200267e1760201c565b620000e95760405162461bcd60e51b81526020600482015260416024820152600080516020620042538339815191526044820152600080516020620042738339815191526064820152606560f81b608482015260a4015b60405180910390fd5b600180546001600160a01b0319166001600160a01b03929092169190911790556200011b620001153390565b62000218565b6200013983639088c20760e01b620001ee60201b6200267e1760201c565b806200015e57506200015e8363478c853060e01b620001ee60201b6200267e1760201c565b620001ba5760405162461bcd60e51b81526020600482015260416024820152600080516020620042538339815191526044820152600080516020620042738339815191526064820152606560f81b608482015260a401620000e0565b60f09190911b6001600160f01b0319166080526008805461ffff191661ffff90921691909117905550620004229350505050565b6000620001fb836200026a565b80156200020f57506200020f8383620002a2565b90505b92915050565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60006200027f826301ffc9a760e01b620002a2565b80156200021257506200029b826001600160e01b0319620002a2565b1592915050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b179052905160009190829081906001600160a01b03871690617530906200030b908690620003e6565b6000604051808303818686fa925050503d806000811462000349576040519150601f19603f3d011682016040523d82523d6000602084013e6200034e565b606091505b50915091506020815110156200036b576000935050505062000212565b8180156200038a5750808060200190518101906200038a9190620003c4565b9695505050505050565b600060208284031215620003a6578081fd5b81516001600160a01b0381168114620003bd578182fd5b9392505050565b600060208284031215620003d6578081fd5b81518015158114620003bd578182fd5b60008251815b81811015620004085760208186018101518583015201620003ec565b81811115620004175782828501525b509190910192915050565b60805160f01c613df66200045d600039600081816103530152818161079e01528181611a1a01528181611ba6015261244b0152613df66000f3fe6080604052600436106101d85760003560e01c8063819d4cc611610102578063bc197c8111610095578063f23a6e6111610064578063f23a6e6114610572578063f2fde38b14610592578063f3fef3a3146105b2578063f79f20b5146105d257600080fd5b8063bc197c81146104f2578063d3e3ac8c14610512578063e9dc637514610532578063efef39a11461055f57600080fd5b80639932495e116100d15780639932495e1461047957806399e0dd7c14610499578063ac4cc148146104b9578063ac52e644146104d257600080fd5b8063819d4cc6146103ec578063889dd09d1461040c5780638d75fe051461042f5780638da5cb5b1461045157600080fd5b80632d3456701161017a57806367627b621161014957806367627b62146103775780636c2ab4ba146103975780636d73e669146103b7578063715018a6146103d757600080fd5b80632d345670146102e257806331ae450b1461030257806348efee0a14610324578063540385a31461034457600080fd5b80630f15f4c0116101b65780630f15f4c014610252578063150b7a021461026957806324d7806c146102a25780632af8a413146102c257600080fd5b806301ffc9a7146101dd57806302fb0c5e1461021257806304c9fdb01461022a575b600080fd5b3480156101e957600080fd5b506101fd6101f83660046136cb565b6105ff565b60405190151581526020015b60405180910390f35b34801561021e57600080fd5b50600c5460ff166101fd565b34801561023657600080fd5b5061023f610639565b60405161ffff9091168152602001610209565b34801561025e57600080fd5b5061026761065a565b005b34801561027557600080fd5b50610289610284366004613369565b610704565b6040516001600160e01b03199091168152602001610209565b3480156102ae57600080fd5b506101fd6102bd36600461324b565b610937565b3480156102ce57600080fd5b506102676102dd3660046134c7565b610970565b3480156102ee57600080fd5b506102676102fd36600461324b565b610d9e565b34801561030e57600080fd5b50610317610e4e565b6040516102099190613a90565b34801561033057600080fd5b5061026761033f366004613454565b610f19565b34801561035057600080fd5b507f000000000000000000000000000000000000000000000000000000000000000061023f565b34801561038357600080fd5b506101fd610392366004613530565b6111c3565b3480156103a357600080fd5b506102676103b2366004613542565b611214565b3480156103c357600080fd5b506102676103d236600461324b565b611301565b3480156103e357600080fd5b506102676113ab565b3480156103f857600080fd5b50610267610407366004613530565b611411565b34801561041857600080fd5b506104216114f1565b604051908152602001610209565b34801561043b57600080fd5b50610444611567565b6040516102099190613ac8565b34801561045d57600080fd5b506002546040516001600160a01b039091168152602001610209565b34801561048557600080fd5b50610267610494366004613733565b6115bf565b3480156104a557600080fd5b506102676104b43660046136f3565b6116e8565b3480156104c557600080fd5b5060085461ffff1661023f565b3480156104de57600080fd5b506102676104ed3660046135ec565b611743565b3480156104fe57600080fd5b5061028961050d3660046132ae565b6118b8565b34801561051e57600080fd5b5061026761052d366004613583565b611b0c565b34801561053e57600080fd5b5061055261054d366004613530565b6120d4565b6040516102099190613adb565b61026761056d366004613733565b612180565b34801561057e57600080fd5b5061028961058d3660046133da565b6123b1565b34801561059e57600080fd5b506102676105ad36600461324b565b612536565b3480156105be57600080fd5b506102676105cd366004613283565b6125fe565b3480156105de57600080fd5b506104216105ed366004613733565b6000908152600a602052604090205490565b60006001600160e01b0319821663e9dc637560e01b148061062457506106248261269a565b806106335750610633826126cf565b92915050565b6008546000906106559061ffff62010000820481169116613c45565b905090565b3361066d6002546001600160a01b031690565b6001600160a01b0316148061068857506106886003336126f4565b6106ad5760405162461bcd60e51b81526004016106a490613b0e565b60405180910390fd5b600c5460ff16156106f15760405162461bcd60e51b815260206004820152600e60248201526d416c72656164792061637469766560901b60448201526064016106a4565b42600d55600c805460ff19166001179055565b6000600260005414156107475760405162461bcd60e51b815260206004820152601f6024820152600080516020613da183398151915260448201526064016106a4565b600260005561075633856111c3565b61079c5760405162461bcd60e51b8152602060048201526017602482015276109d5c9b94995919595b4e88125b9d985b1a5908139195604a1b60448201526064016106a4565b7f000000000000000000000000000000000000000000000000000000000000000061ffff166001146108425760405162461bcd60e51b815260206004820152604360248201527f4275726e52656465656d3a2043616e206f6e6c7920616c6c6f7720646972656360448201527f7420726563656976696e67206f6620726564656d7074696f6e73206f6620312060648201526213919560ea1b608482015260a4016106a4565b604051635c46a7ef60e11b8152339063b88d4fde9061086f90309061dead908990899089906004016139a5565b600060405180830381600087803b15801561088957600080fd5b505af192505050801561089a575060015b610916573d8080156108c8576040519150601f19603f3d011682016040523d82523d6000602084013e6108cd565b606091505b5060405162461bcd60e51b815260206004820152601860248201527f4275726e52656465656d3a204275726e206661696c757265000000000000000060448201526064016106a4565b61091f85612716565b5050600160005550630a85bd0160e11b949350505050565b6000816001600160a01b03166109556002546001600160a01b031690565b6001600160a01b0316148061063357506106336003836126f4565b336109836002546001600160a01b031690565b6001600160a01b0316148061099e575061099e6003336126f4565b6109ba5760405162461bcd60e51b81526004016106a490613b0e565b8051825114610a0b5760405162461bcd60e51b815260206004820181905260248201527f52656465656d3a20496e76616c696420696e70757420706172616d657465727360448201526064016106a4565b6001600160a01b038316600090815260076020526040812054905b81811015610ad7576001600160a01b0385166000908152600760205260408120805483908110610a6657634e487b7160e01b600052603260045260246000fd5b600091825260208083206002909202909101929092556001600160a01b0387168152600790915260408120805483908110610ab157634e487b7160e01b600052603260045260246000fd5b600091825260209091206001600290920201015580610acf81613d0c565b915050610a26565b5060005b8351811015610d5c57828181518110610b0457634e487b7160e01b600052603260045260246000fd5b6020026020010151848281518110610b2c57634e487b7160e01b600052603260045260246000fd5b602002602001015110610b8b5760405162461bcd60e51b815260206004820152602160248201527f52656465656d3a206d696e206d757374206265206c657373207468616e206d616044820152600f60fb1b60648201526084016106a4565b81811015610c9a57838181518110610bb357634e487b7160e01b600052603260045260246000fd5b602002602001015160076000876001600160a01b03166001600160a01b031681526020019081526020016000208281548110610bff57634e487b7160e01b600052603260045260246000fd5b906000526020600020906002020160000181905550828181518110610c3457634e487b7160e01b600052603260045260246000fd5b602002602001015160076000876001600160a01b03166001600160a01b031681526020019081526020016000208281548110610c8057634e487b7160e01b600052603260045260246000fd5b906000526020600020906002020160010181905550610d4a565b60076000866001600160a01b03166001600160a01b031681526020019081526020016000206040518060400160405280868481518110610cea57634e487b7160e01b600052603260045260246000fd5b60200260200101518152602001858481518110610d1757634e487b7160e01b600052603260045260246000fd5b60209081029190910181015190915282546001818101855560009485529382902083516002909202019081559101519101555b80610d5481613d0c565b915050610adb565b507fc834fb6349b577e8519e3cb6df7274bdd4957d7388d8cc9b54467d8af9d6537b848484604051610d9093929190613a5c565b60405180910390a150505050565b6002546001600160a01b03163314610df85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106a4565b610e036003826126f4565b15610e4b5760405133906001600160a01b038316907f7c0c3c84c67c85fcac635147348bfe374c24a1a93d0366d1cfe9d8853cbf89d590600090a3610e496003826127f6565b505b50565b6060610e5a600361280b565b67ffffffffffffffff811115610e8057634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610ea9578160200160208202803683370190505b50905060005b610eb9600361280b565b811015610f1557610ecb600382612815565b828281518110610eeb57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280610f0d81613d0c565b915050610eaf565b5090565b33610f2c6002546001600160a01b031690565b6001600160a01b03161480610f475750610f476003336126f4565b610f635760405162461bcd60e51b81526004016106a490613b0e565b8051825114610fb45760405162461bcd60e51b815260206004820181905260248201527f52656465656d3a20496e76616c696420696e70757420706172616d657465727360448201526064016106a4565b60005b825181101561118257818181518110610fe057634e487b7160e01b600052603260045260246000fd5b6020026020010151801561104f575061104d83828151811061101257634e487b7160e01b600052603260045260246000fd5b602002602001015160066000876001600160a01b03166001600160a01b0316815260200190815260200160002061282190919063ffffffff16565b155b156110b8576110b283828151811061107757634e487b7160e01b600052603260045260246000fd5b602002602001015160066000876001600160a01b03166001600160a01b0316815260200190815260200160002061283990919063ffffffff16565b50611170565b8181815181106110d857634e487b7160e01b600052603260045260246000fd5b602002602001015115801561110b575061110b83828151811061101257634e487b7160e01b600052603260045260246000fd5b156111705761116e83828151811061113357634e487b7160e01b600052603260045260246000fd5b602002602001015160066000876001600160a01b03166001600160a01b0316815260200190815260200160002061284590919063ffffffff16565b505b8061117a81613d0c565b915050610fb7565b507f0ed1ede59c177063e00a17d07584b15a0eb10205d90702aeff646f55bb33aa898383836040516111b693929190613a28565b60405180910390a1505050565b600c5460009060ff166112035760405162461bcd60e51b8152602060048201526008602482015267496e61637469766560c01b60448201526064016106a4565b61120d8383612851565b9392505050565b336112276002546001600160a01b031690565b6001600160a01b0316148061124257506112426003336126f4565b61125e5760405162461bcd60e51b81526004016106a490613b0e565b61126f836380ac58cd60e01b61267e565b6112c65760405162461bcd60e51b815260206004820152602260248201527f4275726e52656465656d3a204d75737420696d706c656d656e74204945524337604482015261323160f01b60648201526084016106a4565b6001600160a01b039283166000908152600b602090815260408083209483529390529190912080546001600160a01b03191691909216179055565b6002546001600160a01b0316331461135b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106a4565b6113666003826126f4565b610e4b5760405133906001600160a01b038316907f7e1a1a08d52e4ba0e21554733d66165fd5151f99460116223d9e3a608eec5cb190600090a3610e49600382612a0e565b6002546001600160a01b031633146114055760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106a4565b61140f6000612a23565b565b6001600160a01b038083166000908152600b60209081526040808320858452909152902054163381146114865760405162461bcd60e51b815260206004820152601d60248201527f4275726e52656465656d3a205065726d697373696f6e2064656e69656400000060448201526064016106a4565b604051632142170760e11b8152306004820152336024820152604481018390526001600160a01b038416906342842e0e90606401600060405180830381600087803b1580156114d457600080fd5b505af11580156114e8573d6000803e3d6000fd5b50505050505050565b600c5460009060ff166115315760405162461bcd60e51b8152602060048201526008602482015267496e61637469766560c01b60448201526064016106a4565b600d5461154090610e10613bfa565b421061154c5750600090565b42600d54610e1061155d9190613bfa565b6106559190613c68565b606060098054806020026020016040519081016040528092919081815260200182805480156115b557602002820191906000526020600020905b8154815260200190600101908083116115a1575b5050505050905090565b336115d26002546001600160a01b031690565b6001600160a01b031614806115ed57506115ed6003336126f4565b6116095760405162461bcd60e51b81526004016106a490613b0e565b600c5460ff161561164d5760405162461bcd60e51b815260206004820152600e60248201526d416c72656164792061637469766560901b60448201526064016106a4565b60005b81811015610e4957600061167461166f6002546001600160a01b031690565b612a75565b6000818152600a60209081526040918290205460015483519182526001600160a01b0316918101919091529081018290529091507f7a607f1ab973d85727d0ff44300699ee672c0e1d76f35013f36c02772f524ba39060600160405180910390a150806116e081613d0c565b915050611650565b336116fb6002546001600160a01b031690565b6001600160a01b0316148061171657506117166003336126f4565b6117325760405162461bcd60e51b81526004016106a490613b0e565b61173e600e838361305c565b505050565b336117566002546001600160a01b031690565b6001600160a01b0316148061177157506117716003336126f4565b61178d5760405162461bcd60e51b81526004016106a490613b0e565b80518251146117de5760405162461bcd60e51b815260206004820181905260248201527f52656465656d3a20496e76616c696420696e70757420706172616d657465727360448201526064016106a4565b60005b825181101561187a5781818151811061180a57634e487b7160e01b600052603260045260246000fd5b60200260200101516005600085848151811061183657634e487b7160e01b600052603260045260246000fd5b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff19169115159190911790558061187281613d0c565b9150506117e1565b507fb987f16cb95c27617d184f54a4a9d80cfa894b91e2d679ed760424939544814882826040516118ac929190613aa3565b60405180910390a15050565b6000600260005414156118fb5760405162461bcd60e51b815260206004820152601f6024820152600080516020613da183398151915260448201526064016106a4565b600260005585841461194f5760405162461bcd60e51b815260206004820152601960248201527f4275726e52656465656d3a20496e76616c696420696e7075740000000000000060448201526064016106a4565b6000805b87811015611a175761198b338a8a8481811061197f57634e487b7160e01b600052603260045260246000fd5b905060200201356111c3565b6119d15760405162461bcd60e51b8152602060048201526017602482015276109d5c9b94995919595b4e88125b9d985b1a5908139195604a1b60448201526064016106a4565b8686828181106119f157634e487b7160e01b600052603260045260246000fd5b9050602002013582611a039190613bfa565b915080611a0f81613d0c565b915050611953565b507f000000000000000000000000000000000000000000000000000000000000000061ffff168114611a5b5760405162461bcd60e51b81526004016106a490613b52565b604051631759616b60e11b81523390632eb2c2d690611a8e90309061dead908d908d908d908d908d908d90600401613941565b600060405180830381600087803b158015611aa857600080fd5b505af1925050508015611ab9575060015b611ae7573d8080156108c8576040519150601f19603f3d011682016040523d82523d6000602084013e6108cd565b611af089612716565b505060016000555063bc197c8160e01b98975050505050505050565b60026000541415611b4d5760405162461bcd60e51b815260206004820152601f6024820152600080516020613da183398151915260448201526064016106a4565b6002600055828114611ba15760405162461bcd60e51b815260206004820152601e60248201527f4275726e52656465656d3a20496e76616c696420706172616d6574657273000060448201526064016106a4565b61ffff7f0000000000000000000000000000000000000000000000000000000000000000168314611be45760405162461bcd60e51b81526004016106a490613b52565b60005b838110156120be57611c47858583818110611c1257634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611c27919061324b565b84848481811061197f57634e487b7160e01b600052603260045260246000fd5b611c8d5760405162461bcd60e51b8152602060048201526017602482015276109d5c9b94995919595b4e88125b9d985b1a5908139195604a1b60448201526064016106a4565b848482818110611cad57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611cc2919061324b565b6001600160a01b0316636352211e848484818110611cf057634e487b7160e01b600052603260045260246000fd5b905060200201356040518263ffffffff1660e01b8152600401611d1591815260200190565b60206040518083038186803b158015611d2d57600080fd5b505afa925050508015611d5d575060408051601f3d908101601f19168201909252611d5a91810190613267565b60015b611dd9573d808015611d8b576040519150601f19603f3d011682016040523d82523d6000602084013e611d90565b606091505b5060405162461bcd60e51b815260206004820152601e60248201527f4275726e52656465656d3a2042616420746f6b656e20636f6e7472616374000060448201526064016106a4565b6001600160a01b0381163314611e315760405162461bcd60e51b815260206004820181905260248201527f4275726e52656465656d3a2043616c6c6572206d757374206f776e204e46547360448201526064016106a4565b50848482818110611e5257634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611e67919061324b565b6001600160a01b031663081812fc848484818110611e9557634e487b7160e01b600052603260045260246000fd5b905060200201356040518263ffffffff1660e01b8152600401611eba91815260200190565b60206040518083038186803b158015611ed257600080fd5b505afa925050508015611f02575060408051601f3d908101601f19168201909252611eff91810190613267565b60015b611f30573d808015611d8b576040519150601f19603f3d011682016040523d82523d6000602084013e611d90565b6001600160a01b0381163014611fae5760405162461bcd60e51b815260206004820152603760248201527f4275726e52656465656d3a20436f6e7472616374206d7573742062652067697660448201527f656e20617070726f76616c20746f206275726e204e465400000000000000000060648201526084016106a4565b50848482818110611fcf57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611fe4919061324b565b6001600160a01b03166323b872dd3361dead86868681811061201657634e487b7160e01b600052603260045260246000fd5b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b15801561206d57600080fd5b505af192505050801561207e575060015b6120ac573d8080156108c8576040519150601f19603f3d011682016040523d82523d6000602084013e6108cd565b806120b681613d0c565b915050611be7565b506120c833612716565b50506001600055505050565b6001546060906001600160a01b03848116911614801561210157506000828152600a602052604090205415155b61213d5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b60448201526064016106a4565b6000828152600a6020526040902054600e9061215890612b7c565b60405160200161216992919061389b565b604051602081830303815290604052905092915050565b600260005414156121c15760405162461bcd60e51b815260206004820152601f6024820152600080516020613da183398151915260448201526064016106a4565b6002600055600c5460ff166122035760405162461bcd60e51b8152602060048201526008602482015267496e61637469766560c01b60448201526064016106a4565b600d5461221290610e10613bfa565b4210156122615760405162461bcd60e51b815260206004820152601560248201527f50757263686173696e67206e6f7420616374697665000000000000000000000060448201526064016106a4565b612269610639565b61ffff16811115801561227d575060058111155b6122be5760405162461bcd60e51b8152602060048201526012602482015271151bdbc81b585b9e481c995c5d595cdd195960721b60448201526064016106a4565b6122d0816705c9205756dc4000613c26565b341461231e5760405162461bcd60e51b815260206004820152601c60248201527f496e76616c696420707572636861736520616d6f756e742073656e740000000060448201526064016106a4565b60005b818110156123a857600061233433612a75565b6000818152600a60209081526040918290205460015483519182526001600160a01b0316918101919091529081018290529091507f7a607f1ab973d85727d0ff44300699ee672c0e1d76f35013f36c02772f524ba39060600160405180910390a150806123a081613d0c565b915050612321565b50506001600055565b6000600260005414156123f45760405162461bcd60e51b815260206004820152601f6024820152600080516020613da183398151915260448201526064016106a4565b600260005561240333866111c3565b6124495760405162461bcd60e51b8152602060048201526017602482015276109d5c9b94995919595b4e88125b9d985b1a5908139195604a1b60448201526064016106a4565b7f000000000000000000000000000000000000000000000000000000000000000061ffff16841461248c5760405162461bcd60e51b81526004016106a490613b52565b604051637921219560e11b8152339063f242432a906124bb90309061dead908a908a908a908a906004016139e3565b600060405180830381600087803b1580156124d557600080fd5b505af19250505080156124e6575060015b612514573d8080156108c8576040519150601f19603f3d011682016040523d82523d6000602084013e6108cd565b61251d86612716565b505060016000555063f23a6e6160e01b95945050505050565b6002546001600160a01b031633146125905760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106a4565b6001600160a01b0381166125f55760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016106a4565b610e4b81612a23565b336126116002546001600160a01b031690565b6001600160a01b0316148061262c575061262c6003336126f4565b6126485760405162461bcd60e51b81526004016106a490613b0e565b6040516001600160a01b0383169082156108fc029083906000818181858888f1935050505015801561173e573d6000803e3d6000fd5b600061268983612c9e565b801561120d575061120d8383612cd1565b60006001600160e01b03198216632a9f3abf60e11b148061063357506301ffc9a760e01b6001600160e01b0319831614610633565b60006001600160e01b031982166303e5454f60e41b1480610633575061063382612dba565b6001600160a01b0381166000908152600183016020526040812054151561120d565b60008061272283612a75565b6000818152600a60209081526040918290205460015483519182526001600160a01b0316918101919091529081018290529091507f7a607f1ab973d85727d0ff44300699ee672c0e1d76f35013f36c02772f524ba39060600160405180910390a161278c83612a75565b6000818152600a60209081526040918290205460015483519182526001600160a01b0316918101919091529081018290529091507f7a607f1ab973d85727d0ff44300699ee672c0e1d76f35013f36c02772f524ba39060600160405180910390a150600092915050565b600061120d836001600160a01b038416612dee565b6000610633825490565b600061120d8383612f0b565b6000818152600183016020526040812054151561120d565b600061120d8383612f43565b600061120d8383612dee565b6001600160a01b03821660009081526005602052604081205460ff161561287a57506001610633565b6001600160a01b038316600090815260066020526040902061289c9083612821565b156128a957506001610633565b6001600160a01b03831660009081526007602052604090205415612a055760005b6001600160a01b038416600090815260076020526040902054811015612a03576001600160a01b038416600090815260076020526040902080548290811061292257634e487b7160e01b600052603260045260246000fd5b90600052602060002090600202016001015460001415801561298d57506001600160a01b038416600090815260076020526040902080548290811061297757634e487b7160e01b600052603260045260246000fd5b9060005260206000209060020201600001548310155b80156129e257506001600160a01b03841660009081526007602052604090208054829081106129cc57634e487b7160e01b600052603260045260246000fd5b9060005260206000209060020201600101548311155b156129f1576001915050610633565b806129fb81613d0c565b9150506128ca565b505b50600092915050565b600061120d836001600160a01b038416612f43565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60085460009061ffff808216620100009092041610612ad65760405162461bcd60e51b815260206004820181905260248201527f52656465656d3a204e6f20726564656d7074696f6e732072656d61696e696e6760448201526064016106a4565b6008805462010000900461ffff16906002612af083613cea565b91906101000a81548161ffff021916908361ffff160217905550506000612b2783600860029054906101000a900461ffff16612f92565b60098054600181019091557f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af018190556008546000828152600a602052604090206201000090910461ffff1690559392505050565b606081612ba05750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612bca5780612bb481613d0c565b9150612bc39050600a83613c12565b9150612ba4565b60008167ffffffffffffffff811115612bf357634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015612c1d576020820181803683370190505b5090505b8415612c9657612c32600183613c68565b9150612c3f600a86613d27565b612c4a906030613bfa565b60f81b818381518110612c6d57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350612c8f600a86613c12565b9450612c21565b949350505050565b6000612cb1826301ffc9a760e01b612cd1565b80156106335750612cca826001600160e01b0319612cd1565b1592915050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b179052905160009190829081906001600160a01b0387169061753090612d3890869061387f565b6000604051808303818686fa925050503d8060008114612d74576040519150601f19603f3d011682016040523d82523d6000602084013e612d79565b606091505b5091509150602081511015612d945760009350505050610633565b818015612db0575080806020019051810190612db091906136af565b9695505050505050565b60006001600160e01b0319821663866c67eb60e01b1480612ddf5750612ddf82613012565b80610633575061063382613037565b60008181526001830160205260408120548015612f01576000612e12600183613c68565b8554909150600090612e2690600190613c68565b9050818114612ea7576000866000018281548110612e5457634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905080876000018481548110612e8557634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ec657634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610633565b6000915050610633565b6000826000018281548110612f3057634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b6000818152600183016020526040812054612f8a57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610633565b506000610633565b600154604051630525194b60e31b81526001600160a01b0384811660048301526000921690632928ca5890602401602060405180830381600087803b158015612fda57600080fd5b505af1158015612fee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120d919061374b565b60006001600160e01b0319821663a927d73f60e01b148061063357506106338261269a565b60006001600160e01b03198216637005caad60e01b1480610633575061063382613012565b82805461306890613caf565b90600052602060002090601f01602090048101928261308a57600085556130d0565b82601f106130a35782800160ff198235161785556130d0565b828001600101855582156130d0579182015b828111156130d05782358255916020019190600101906130b5565b50610f159291505b80821115610f1557600081556001016130d8565b60008083601f8401126130fd578182fd5b50813567ffffffffffffffff811115613114578182fd5b6020830191508360208260051b850101111561312f57600080fd5b9250929050565b600082601f830112613146578081fd5b8135602061315b61315683613bd6565b613ba5565b80838252828201915082860187848660051b890101111561317a578586fd5b855b858110156131a157813561318f81613d92565b8452928401929084019060010161317c565b5090979650505050505050565b600082601f8301126131be578081fd5b813560206131ce61315683613bd6565b80838252828201915082860187848660051b89010111156131ed578586fd5b855b858110156131a1578135845292840192908401906001016131ef565b60008083601f84011261321c578182fd5b50813567ffffffffffffffff811115613233578182fd5b60208301915083602082850101111561312f57600080fd5b60006020828403121561325c578081fd5b813561120d81613d7d565b600060208284031215613278578081fd5b815161120d81613d7d565b60008060408385031215613295578081fd5b82356132a081613d7d565b946020939093013593505050565b60008060008060008060008060a0898b0312156132c9578384fd5b88356132d481613d7d565b975060208901356132e481613d7d565b9650604089013567ffffffffffffffff80821115613300578586fd5b61330c8c838d016130ec565b909850965060608b0135915080821115613324578586fd5b6133308c838d016130ec565b909650945060808b0135915080821115613348578384fd5b506133558b828c0161320b565b999c989b5096995094979396929594505050565b600080600080600060808688031215613380578081fd5b853561338b81613d7d565b9450602086013561339b81613d7d565b935060408601359250606086013567ffffffffffffffff8111156133bd578182fd5b6133c98882890161320b565b969995985093965092949392505050565b60008060008060008060a087890312156133f2578384fd5b86356133fd81613d7d565b9550602087013561340d81613d7d565b94506040870135935060608701359250608087013567ffffffffffffffff811115613436578283fd5b61344289828a0161320b565b979a9699509497509295939492505050565b600080600060608486031215613468578081fd5b833561347381613d7d565b9250602084013567ffffffffffffffff8082111561348f578283fd5b61349b878388016131ae565b935060408601359150808211156134b0578283fd5b506134bd86828701613136565b9150509250925092565b6000806000606084860312156134db578081fd5b83356134e681613d7d565b9250602084013567ffffffffffffffff80821115613502578283fd5b61350e878388016131ae565b93506040860135915080821115613523578283fd5b506134bd868287016131ae565b60008060408385031215613295578182fd5b600080600060608486031215613556578081fd5b833561356181613d7d565b925060208401359150604084013561357881613d7d565b809150509250925092565b60008060008060408587031215613598578182fd5b843567ffffffffffffffff808211156135af578384fd5b6135bb888389016130ec565b909650945060208701359150808211156135d3578384fd5b506135e0878288016130ec565b95989497509550505050565b600080604083850312156135fe578182fd5b823567ffffffffffffffff80821115613615578384fd5b818501915085601f830112613628578384fd5b8135602061363861315683613bd6565b8083825282820191508286018a848660051b8901011115613657578889fd5b8896505b8487101561368257803561366e81613d7d565b83526001969096019591830191830161365b565b5096505086013592505080821115613698578283fd5b506136a585828601613136565b9150509250929050565b6000602082840312156136c0578081fd5b815161120d81613d92565b6000602082840312156136dc578081fd5b81356001600160e01b03198116811461120d578182fd5b60008060208385031215613705578182fd5b823567ffffffffffffffff81111561371b578283fd5b6137278582860161320b565b90969095509350505050565b600060208284031215613744578081fd5b5035919050565b60006020828403121561375c578081fd5b5051919050565b6000815180845260208085019450808401835b8381101561379b5781516001600160a01b031687529582019590820190600101613776565b509495945050505050565b6000815180845260208085019450808401835b8381101561379b5781511515875295820195908201906001016137b9565b81835260006001600160fb1b038311156137ef578081fd5b8260051b80836020870137939093016020019283525090919050565b6000815180845260208085019450808401835b8381101561379b5781518752958201959082019060010161381e565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60008151613875818560208601613c7f565b9290920192915050565b60008251613891818460208701613c7f565b9190910192915050565b600080845482600182811c9150808316806138b757607f831692505b60208084108214156138d757634e487b7160e01b87526022600452602487fd5b8180156138eb57600181146138fc57613928565b60ff19861689528489019650613928565b60008b815260209020885b868110156139205781548b820152908501908301613907565b505084890196505b5050505050506139388185613863565b95945050505050565b60006001600160a01b03808b168352808a1660208401525060a0604083015261396e60a08301888a6137d7565b82810360608401526139818187896137d7565b9050828103608084015261399681858761383a565b9b9a5050505050505050505050565b60006001600160a01b038088168352808716602084015250846040830152608060608301526139d860808301848661383a565b979650505050505050565b60006001600160a01b03808916835280881660208401525085604083015284606083015260a06080830152613a1c60a08301848661383a565b98975050505050505050565b6001600160a01b0384168152606060208201526000613a4a606083018561380b565b8281036040840152612db081856137a6565b6001600160a01b0384168152606060208201526000613a7e606083018561380b565b8281036040840152612db0818561380b565b60208152600061120d6020830184613763565b604081526000613ab66040830185613763565b828103602084015261393881856137a6565b60208152600061120d602083018461380b565b6020815260008251806020840152613afa816040850160208701613c7f565b601f01601f19169190910160400192915050565b60208082526024908201527f41646d696e436f6e74726f6c3a204d757374206265206f776e6572206f7220616040820152633236b4b760e11b606082015260800190565b60208082526033908201527f4275726e52656465656d3a20496e636f7272656374206e756d626572206f66206040820152721391951cc818995a5b99c81c995919595b5959606a1b606082015260800190565b604051601f8201601f1916810167ffffffffffffffff81118282101715613bce57613bce613d67565b604052919050565b600067ffffffffffffffff821115613bf057613bf0613d67565b5060051b60200190565b60008219821115613c0d57613c0d613d3b565b500190565b600082613c2157613c21613d51565b500490565b6000816000190483118215151615613c4057613c40613d3b565b500290565b600061ffff83811690831681811015613c6057613c60613d3b565b039392505050565b600082821015613c7a57613c7a613d3b565b500390565b60005b83811015613c9a578181015183820152602001613c82565b83811115613ca9576000848401525b50505050565b600181811c90821680613cc357607f821691505b60208210811415613ce457634e487b7160e01b600052602260045260246000fd5b50919050565b600061ffff80831681811415613d0257613d02613d3b565b6001019392505050565b6000600019821415613d2057613d20613d3b565b5060010190565b600082613d3657613d36613d51565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610e4b57600080fd5b8015158114610e4b57600080fdfe5265656e7472616e637947756172643a207265656e7472616e742063616c6c00a26469706673582212201668a9ae8d165204c5f976f3907c4e391d0400c2aa7c68c982f4ba193bf3b94d64736f6c6343000804003352656465656d3a204d696e74696e672072657761726420636f6e7472616374206d75737420696d706c656d656e74204945524337323143726561746f72436f720000000000000000000000007afeda4c714e1c0a2a1248332c100924506ac8e6

Deployed Bytecode

0x6080604052600436106101d85760003560e01c8063819d4cc611610102578063bc197c8111610095578063f23a6e6111610064578063f23a6e6114610572578063f2fde38b14610592578063f3fef3a3146105b2578063f79f20b5146105d257600080fd5b8063bc197c81146104f2578063d3e3ac8c14610512578063e9dc637514610532578063efef39a11461055f57600080fd5b80639932495e116100d15780639932495e1461047957806399e0dd7c14610499578063ac4cc148146104b9578063ac52e644146104d257600080fd5b8063819d4cc6146103ec578063889dd09d1461040c5780638d75fe051461042f5780638da5cb5b1461045157600080fd5b80632d3456701161017a57806367627b621161014957806367627b62146103775780636c2ab4ba146103975780636d73e669146103b7578063715018a6146103d757600080fd5b80632d345670146102e257806331ae450b1461030257806348efee0a14610324578063540385a31461034457600080fd5b80630f15f4c0116101b65780630f15f4c014610252578063150b7a021461026957806324d7806c146102a25780632af8a413146102c257600080fd5b806301ffc9a7146101dd57806302fb0c5e1461021257806304c9fdb01461022a575b600080fd5b3480156101e957600080fd5b506101fd6101f83660046136cb565b6105ff565b60405190151581526020015b60405180910390f35b34801561021e57600080fd5b50600c5460ff166101fd565b34801561023657600080fd5b5061023f610639565b60405161ffff9091168152602001610209565b34801561025e57600080fd5b5061026761065a565b005b34801561027557600080fd5b50610289610284366004613369565b610704565b6040516001600160e01b03199091168152602001610209565b3480156102ae57600080fd5b506101fd6102bd36600461324b565b610937565b3480156102ce57600080fd5b506102676102dd3660046134c7565b610970565b3480156102ee57600080fd5b506102676102fd36600461324b565b610d9e565b34801561030e57600080fd5b50610317610e4e565b6040516102099190613a90565b34801561033057600080fd5b5061026761033f366004613454565b610f19565b34801561035057600080fd5b507f000000000000000000000000000000000000000000000000000000000000000161023f565b34801561038357600080fd5b506101fd610392366004613530565b6111c3565b3480156103a357600080fd5b506102676103b2366004613542565b611214565b3480156103c357600080fd5b506102676103d236600461324b565b611301565b3480156103e357600080fd5b506102676113ab565b3480156103f857600080fd5b50610267610407366004613530565b611411565b34801561041857600080fd5b506104216114f1565b604051908152602001610209565b34801561043b57600080fd5b50610444611567565b6040516102099190613ac8565b34801561045d57600080fd5b506002546040516001600160a01b039091168152602001610209565b34801561048557600080fd5b50610267610494366004613733565b6115bf565b3480156104a557600080fd5b506102676104b43660046136f3565b6116e8565b3480156104c557600080fd5b5060085461ffff1661023f565b3480156104de57600080fd5b506102676104ed3660046135ec565b611743565b3480156104fe57600080fd5b5061028961050d3660046132ae565b6118b8565b34801561051e57600080fd5b5061026761052d366004613583565b611b0c565b34801561053e57600080fd5b5061055261054d366004613530565b6120d4565b6040516102099190613adb565b61026761056d366004613733565b612180565b34801561057e57600080fd5b5061028961058d3660046133da565b6123b1565b34801561059e57600080fd5b506102676105ad36600461324b565b612536565b3480156105be57600080fd5b506102676105cd366004613283565b6125fe565b3480156105de57600080fd5b506104216105ed366004613733565b6000908152600a602052604090205490565b60006001600160e01b0319821663e9dc637560e01b148061062457506106248261269a565b806106335750610633826126cf565b92915050565b6008546000906106559061ffff62010000820481169116613c45565b905090565b3361066d6002546001600160a01b031690565b6001600160a01b0316148061068857506106886003336126f4565b6106ad5760405162461bcd60e51b81526004016106a490613b0e565b60405180910390fd5b600c5460ff16156106f15760405162461bcd60e51b815260206004820152600e60248201526d416c72656164792061637469766560901b60448201526064016106a4565b42600d55600c805460ff19166001179055565b6000600260005414156107475760405162461bcd60e51b815260206004820152601f6024820152600080516020613da183398151915260448201526064016106a4565b600260005561075633856111c3565b61079c5760405162461bcd60e51b8152602060048201526017602482015276109d5c9b94995919595b4e88125b9d985b1a5908139195604a1b60448201526064016106a4565b7f000000000000000000000000000000000000000000000000000000000000000161ffff166001146108425760405162461bcd60e51b815260206004820152604360248201527f4275726e52656465656d3a2043616e206f6e6c7920616c6c6f7720646972656360448201527f7420726563656976696e67206f6620726564656d7074696f6e73206f6620312060648201526213919560ea1b608482015260a4016106a4565b604051635c46a7ef60e11b8152339063b88d4fde9061086f90309061dead908990899089906004016139a5565b600060405180830381600087803b15801561088957600080fd5b505af192505050801561089a575060015b610916573d8080156108c8576040519150601f19603f3d011682016040523d82523d6000602084013e6108cd565b606091505b5060405162461bcd60e51b815260206004820152601860248201527f4275726e52656465656d3a204275726e206661696c757265000000000000000060448201526064016106a4565b61091f85612716565b5050600160005550630a85bd0160e11b949350505050565b6000816001600160a01b03166109556002546001600160a01b031690565b6001600160a01b0316148061063357506106336003836126f4565b336109836002546001600160a01b031690565b6001600160a01b0316148061099e575061099e6003336126f4565b6109ba5760405162461bcd60e51b81526004016106a490613b0e565b8051825114610a0b5760405162461bcd60e51b815260206004820181905260248201527f52656465656d3a20496e76616c696420696e70757420706172616d657465727360448201526064016106a4565b6001600160a01b038316600090815260076020526040812054905b81811015610ad7576001600160a01b0385166000908152600760205260408120805483908110610a6657634e487b7160e01b600052603260045260246000fd5b600091825260208083206002909202909101929092556001600160a01b0387168152600790915260408120805483908110610ab157634e487b7160e01b600052603260045260246000fd5b600091825260209091206001600290920201015580610acf81613d0c565b915050610a26565b5060005b8351811015610d5c57828181518110610b0457634e487b7160e01b600052603260045260246000fd5b6020026020010151848281518110610b2c57634e487b7160e01b600052603260045260246000fd5b602002602001015110610b8b5760405162461bcd60e51b815260206004820152602160248201527f52656465656d3a206d696e206d757374206265206c657373207468616e206d616044820152600f60fb1b60648201526084016106a4565b81811015610c9a57838181518110610bb357634e487b7160e01b600052603260045260246000fd5b602002602001015160076000876001600160a01b03166001600160a01b031681526020019081526020016000208281548110610bff57634e487b7160e01b600052603260045260246000fd5b906000526020600020906002020160000181905550828181518110610c3457634e487b7160e01b600052603260045260246000fd5b602002602001015160076000876001600160a01b03166001600160a01b031681526020019081526020016000208281548110610c8057634e487b7160e01b600052603260045260246000fd5b906000526020600020906002020160010181905550610d4a565b60076000866001600160a01b03166001600160a01b031681526020019081526020016000206040518060400160405280868481518110610cea57634e487b7160e01b600052603260045260246000fd5b60200260200101518152602001858481518110610d1757634e487b7160e01b600052603260045260246000fd5b60209081029190910181015190915282546001818101855560009485529382902083516002909202019081559101519101555b80610d5481613d0c565b915050610adb565b507fc834fb6349b577e8519e3cb6df7274bdd4957d7388d8cc9b54467d8af9d6537b848484604051610d9093929190613a5c565b60405180910390a150505050565b6002546001600160a01b03163314610df85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106a4565b610e036003826126f4565b15610e4b5760405133906001600160a01b038316907f7c0c3c84c67c85fcac635147348bfe374c24a1a93d0366d1cfe9d8853cbf89d590600090a3610e496003826127f6565b505b50565b6060610e5a600361280b565b67ffffffffffffffff811115610e8057634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610ea9578160200160208202803683370190505b50905060005b610eb9600361280b565b811015610f1557610ecb600382612815565b828281518110610eeb57634e487b7160e01b600052603260045260246000fd5b6001600160a01b039092166020928302919091019091015280610f0d81613d0c565b915050610eaf565b5090565b33610f2c6002546001600160a01b031690565b6001600160a01b03161480610f475750610f476003336126f4565b610f635760405162461bcd60e51b81526004016106a490613b0e565b8051825114610fb45760405162461bcd60e51b815260206004820181905260248201527f52656465656d3a20496e76616c696420696e70757420706172616d657465727360448201526064016106a4565b60005b825181101561118257818181518110610fe057634e487b7160e01b600052603260045260246000fd5b6020026020010151801561104f575061104d83828151811061101257634e487b7160e01b600052603260045260246000fd5b602002602001015160066000876001600160a01b03166001600160a01b0316815260200190815260200160002061282190919063ffffffff16565b155b156110b8576110b283828151811061107757634e487b7160e01b600052603260045260246000fd5b602002602001015160066000876001600160a01b03166001600160a01b0316815260200190815260200160002061283990919063ffffffff16565b50611170565b8181815181106110d857634e487b7160e01b600052603260045260246000fd5b602002602001015115801561110b575061110b83828151811061101257634e487b7160e01b600052603260045260246000fd5b156111705761116e83828151811061113357634e487b7160e01b600052603260045260246000fd5b602002602001015160066000876001600160a01b03166001600160a01b0316815260200190815260200160002061284590919063ffffffff16565b505b8061117a81613d0c565b915050610fb7565b507f0ed1ede59c177063e00a17d07584b15a0eb10205d90702aeff646f55bb33aa898383836040516111b693929190613a28565b60405180910390a1505050565b600c5460009060ff166112035760405162461bcd60e51b8152602060048201526008602482015267496e61637469766560c01b60448201526064016106a4565b61120d8383612851565b9392505050565b336112276002546001600160a01b031690565b6001600160a01b0316148061124257506112426003336126f4565b61125e5760405162461bcd60e51b81526004016106a490613b0e565b61126f836380ac58cd60e01b61267e565b6112c65760405162461bcd60e51b815260206004820152602260248201527f4275726e52656465656d3a204d75737420696d706c656d656e74204945524337604482015261323160f01b60648201526084016106a4565b6001600160a01b039283166000908152600b602090815260408083209483529390529190912080546001600160a01b03191691909216179055565b6002546001600160a01b0316331461135b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106a4565b6113666003826126f4565b610e4b5760405133906001600160a01b038316907f7e1a1a08d52e4ba0e21554733d66165fd5151f99460116223d9e3a608eec5cb190600090a3610e49600382612a0e565b6002546001600160a01b031633146114055760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106a4565b61140f6000612a23565b565b6001600160a01b038083166000908152600b60209081526040808320858452909152902054163381146114865760405162461bcd60e51b815260206004820152601d60248201527f4275726e52656465656d3a205065726d697373696f6e2064656e69656400000060448201526064016106a4565b604051632142170760e11b8152306004820152336024820152604481018390526001600160a01b038416906342842e0e90606401600060405180830381600087803b1580156114d457600080fd5b505af11580156114e8573d6000803e3d6000fd5b50505050505050565b600c5460009060ff166115315760405162461bcd60e51b8152602060048201526008602482015267496e61637469766560c01b60448201526064016106a4565b600d5461154090610e10613bfa565b421061154c5750600090565b42600d54610e1061155d9190613bfa565b6106559190613c68565b606060098054806020026020016040519081016040528092919081815260200182805480156115b557602002820191906000526020600020905b8154815260200190600101908083116115a1575b5050505050905090565b336115d26002546001600160a01b031690565b6001600160a01b031614806115ed57506115ed6003336126f4565b6116095760405162461bcd60e51b81526004016106a490613b0e565b600c5460ff161561164d5760405162461bcd60e51b815260206004820152600e60248201526d416c72656164792061637469766560901b60448201526064016106a4565b60005b81811015610e4957600061167461166f6002546001600160a01b031690565b612a75565b6000818152600a60209081526040918290205460015483519182526001600160a01b0316918101919091529081018290529091507f7a607f1ab973d85727d0ff44300699ee672c0e1d76f35013f36c02772f524ba39060600160405180910390a150806116e081613d0c565b915050611650565b336116fb6002546001600160a01b031690565b6001600160a01b0316148061171657506117166003336126f4565b6117325760405162461bcd60e51b81526004016106a490613b0e565b61173e600e838361305c565b505050565b336117566002546001600160a01b031690565b6001600160a01b0316148061177157506117716003336126f4565b61178d5760405162461bcd60e51b81526004016106a490613b0e565b80518251146117de5760405162461bcd60e51b815260206004820181905260248201527f52656465656d3a20496e76616c696420696e70757420706172616d657465727360448201526064016106a4565b60005b825181101561187a5781818151811061180a57634e487b7160e01b600052603260045260246000fd5b60200260200101516005600085848151811061183657634e487b7160e01b600052603260045260246000fd5b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff19169115159190911790558061187281613d0c565b9150506117e1565b507fb987f16cb95c27617d184f54a4a9d80cfa894b91e2d679ed760424939544814882826040516118ac929190613aa3565b60405180910390a15050565b6000600260005414156118fb5760405162461bcd60e51b815260206004820152601f6024820152600080516020613da183398151915260448201526064016106a4565b600260005585841461194f5760405162461bcd60e51b815260206004820152601960248201527f4275726e52656465656d3a20496e76616c696420696e7075740000000000000060448201526064016106a4565b6000805b87811015611a175761198b338a8a8481811061197f57634e487b7160e01b600052603260045260246000fd5b905060200201356111c3565b6119d15760405162461bcd60e51b8152602060048201526017602482015276109d5c9b94995919595b4e88125b9d985b1a5908139195604a1b60448201526064016106a4565b8686828181106119f157634e487b7160e01b600052603260045260246000fd5b9050602002013582611a039190613bfa565b915080611a0f81613d0c565b915050611953565b507f000000000000000000000000000000000000000000000000000000000000000161ffff168114611a5b5760405162461bcd60e51b81526004016106a490613b52565b604051631759616b60e11b81523390632eb2c2d690611a8e90309061dead908d908d908d908d908d908d90600401613941565b600060405180830381600087803b158015611aa857600080fd5b505af1925050508015611ab9575060015b611ae7573d8080156108c8576040519150601f19603f3d011682016040523d82523d6000602084013e6108cd565b611af089612716565b505060016000555063bc197c8160e01b98975050505050505050565b60026000541415611b4d5760405162461bcd60e51b815260206004820152601f6024820152600080516020613da183398151915260448201526064016106a4565b6002600055828114611ba15760405162461bcd60e51b815260206004820152601e60248201527f4275726e52656465656d3a20496e76616c696420706172616d6574657273000060448201526064016106a4565b61ffff7f0000000000000000000000000000000000000000000000000000000000000001168314611be45760405162461bcd60e51b81526004016106a490613b52565b60005b838110156120be57611c47858583818110611c1257634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611c27919061324b565b84848481811061197f57634e487b7160e01b600052603260045260246000fd5b611c8d5760405162461bcd60e51b8152602060048201526017602482015276109d5c9b94995919595b4e88125b9d985b1a5908139195604a1b60448201526064016106a4565b848482818110611cad57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611cc2919061324b565b6001600160a01b0316636352211e848484818110611cf057634e487b7160e01b600052603260045260246000fd5b905060200201356040518263ffffffff1660e01b8152600401611d1591815260200190565b60206040518083038186803b158015611d2d57600080fd5b505afa925050508015611d5d575060408051601f3d908101601f19168201909252611d5a91810190613267565b60015b611dd9573d808015611d8b576040519150601f19603f3d011682016040523d82523d6000602084013e611d90565b606091505b5060405162461bcd60e51b815260206004820152601e60248201527f4275726e52656465656d3a2042616420746f6b656e20636f6e7472616374000060448201526064016106a4565b6001600160a01b0381163314611e315760405162461bcd60e51b815260206004820181905260248201527f4275726e52656465656d3a2043616c6c6572206d757374206f776e204e46547360448201526064016106a4565b50848482818110611e5257634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611e67919061324b565b6001600160a01b031663081812fc848484818110611e9557634e487b7160e01b600052603260045260246000fd5b905060200201356040518263ffffffff1660e01b8152600401611eba91815260200190565b60206040518083038186803b158015611ed257600080fd5b505afa925050508015611f02575060408051601f3d908101601f19168201909252611eff91810190613267565b60015b611f30573d808015611d8b576040519150601f19603f3d011682016040523d82523d6000602084013e611d90565b6001600160a01b0381163014611fae5760405162461bcd60e51b815260206004820152603760248201527f4275726e52656465656d3a20436f6e7472616374206d7573742062652067697660448201527f656e20617070726f76616c20746f206275726e204e465400000000000000000060648201526084016106a4565b50848482818110611fcf57634e487b7160e01b600052603260045260246000fd5b9050602002016020810190611fe4919061324b565b6001600160a01b03166323b872dd3361dead86868681811061201657634e487b7160e01b600052603260045260246000fd5b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b15801561206d57600080fd5b505af192505050801561207e575060015b6120ac573d8080156108c8576040519150601f19603f3d011682016040523d82523d6000602084013e6108cd565b806120b681613d0c565b915050611be7565b506120c833612716565b50506001600055505050565b6001546060906001600160a01b03848116911614801561210157506000828152600a602052604090205415155b61213d5760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b2103a37b5b2b760991b60448201526064016106a4565b6000828152600a6020526040902054600e9061215890612b7c565b60405160200161216992919061389b565b604051602081830303815290604052905092915050565b600260005414156121c15760405162461bcd60e51b815260206004820152601f6024820152600080516020613da183398151915260448201526064016106a4565b6002600055600c5460ff166122035760405162461bcd60e51b8152602060048201526008602482015267496e61637469766560c01b60448201526064016106a4565b600d5461221290610e10613bfa565b4210156122615760405162461bcd60e51b815260206004820152601560248201527f50757263686173696e67206e6f7420616374697665000000000000000000000060448201526064016106a4565b612269610639565b61ffff16811115801561227d575060058111155b6122be5760405162461bcd60e51b8152602060048201526012602482015271151bdbc81b585b9e481c995c5d595cdd195960721b60448201526064016106a4565b6122d0816705c9205756dc4000613c26565b341461231e5760405162461bcd60e51b815260206004820152601c60248201527f496e76616c696420707572636861736520616d6f756e742073656e740000000060448201526064016106a4565b60005b818110156123a857600061233433612a75565b6000818152600a60209081526040918290205460015483519182526001600160a01b0316918101919091529081018290529091507f7a607f1ab973d85727d0ff44300699ee672c0e1d76f35013f36c02772f524ba39060600160405180910390a150806123a081613d0c565b915050612321565b50506001600055565b6000600260005414156123f45760405162461bcd60e51b815260206004820152601f6024820152600080516020613da183398151915260448201526064016106a4565b600260005561240333866111c3565b6124495760405162461bcd60e51b8152602060048201526017602482015276109d5c9b94995919595b4e88125b9d985b1a5908139195604a1b60448201526064016106a4565b7f000000000000000000000000000000000000000000000000000000000000000161ffff16841461248c5760405162461bcd60e51b81526004016106a490613b52565b604051637921219560e11b8152339063f242432a906124bb90309061dead908a908a908a908a906004016139e3565b600060405180830381600087803b1580156124d557600080fd5b505af19250505080156124e6575060015b612514573d8080156108c8576040519150601f19603f3d011682016040523d82523d6000602084013e6108cd565b61251d86612716565b505060016000555063f23a6e6160e01b95945050505050565b6002546001600160a01b031633146125905760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106a4565b6001600160a01b0381166125f55760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016106a4565b610e4b81612a23565b336126116002546001600160a01b031690565b6001600160a01b0316148061262c575061262c6003336126f4565b6126485760405162461bcd60e51b81526004016106a490613b0e565b6040516001600160a01b0383169082156108fc029083906000818181858888f1935050505015801561173e573d6000803e3d6000fd5b600061268983612c9e565b801561120d575061120d8383612cd1565b60006001600160e01b03198216632a9f3abf60e11b148061063357506301ffc9a760e01b6001600160e01b0319831614610633565b60006001600160e01b031982166303e5454f60e41b1480610633575061063382612dba565b6001600160a01b0381166000908152600183016020526040812054151561120d565b60008061272283612a75565b6000818152600a60209081526040918290205460015483519182526001600160a01b0316918101919091529081018290529091507f7a607f1ab973d85727d0ff44300699ee672c0e1d76f35013f36c02772f524ba39060600160405180910390a161278c83612a75565b6000818152600a60209081526040918290205460015483519182526001600160a01b0316918101919091529081018290529091507f7a607f1ab973d85727d0ff44300699ee672c0e1d76f35013f36c02772f524ba39060600160405180910390a150600092915050565b600061120d836001600160a01b038416612dee565b6000610633825490565b600061120d8383612f0b565b6000818152600183016020526040812054151561120d565b600061120d8383612f43565b600061120d8383612dee565b6001600160a01b03821660009081526005602052604081205460ff161561287a57506001610633565b6001600160a01b038316600090815260066020526040902061289c9083612821565b156128a957506001610633565b6001600160a01b03831660009081526007602052604090205415612a055760005b6001600160a01b038416600090815260076020526040902054811015612a03576001600160a01b038416600090815260076020526040902080548290811061292257634e487b7160e01b600052603260045260246000fd5b90600052602060002090600202016001015460001415801561298d57506001600160a01b038416600090815260076020526040902080548290811061297757634e487b7160e01b600052603260045260246000fd5b9060005260206000209060020201600001548310155b80156129e257506001600160a01b03841660009081526007602052604090208054829081106129cc57634e487b7160e01b600052603260045260246000fd5b9060005260206000209060020201600101548311155b156129f1576001915050610633565b806129fb81613d0c565b9150506128ca565b505b50600092915050565b600061120d836001600160a01b038416612f43565b600280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60085460009061ffff808216620100009092041610612ad65760405162461bcd60e51b815260206004820181905260248201527f52656465656d3a204e6f20726564656d7074696f6e732072656d61696e696e6760448201526064016106a4565b6008805462010000900461ffff16906002612af083613cea565b91906101000a81548161ffff021916908361ffff160217905550506000612b2783600860029054906101000a900461ffff16612f92565b60098054600181019091557f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af018190556008546000828152600a602052604090206201000090910461ffff1690559392505050565b606081612ba05750506040805180820190915260018152600360fc1b602082015290565b8160005b8115612bca5780612bb481613d0c565b9150612bc39050600a83613c12565b9150612ba4565b60008167ffffffffffffffff811115612bf357634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015612c1d576020820181803683370190505b5090505b8415612c9657612c32600183613c68565b9150612c3f600a86613d27565b612c4a906030613bfa565b60f81b818381518110612c6d57634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350612c8f600a86613c12565b9450612c21565b949350505050565b6000612cb1826301ffc9a760e01b612cd1565b80156106335750612cca826001600160e01b0319612cd1565b1592915050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b179052905160009190829081906001600160a01b0387169061753090612d3890869061387f565b6000604051808303818686fa925050503d8060008114612d74576040519150601f19603f3d011682016040523d82523d6000602084013e612d79565b606091505b5091509150602081511015612d945760009350505050610633565b818015612db0575080806020019051810190612db091906136af565b9695505050505050565b60006001600160e01b0319821663866c67eb60e01b1480612ddf5750612ddf82613012565b80610633575061063382613037565b60008181526001830160205260408120548015612f01576000612e12600183613c68565b8554909150600090612e2690600190613c68565b9050818114612ea7576000866000018281548110612e5457634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905080876000018481548110612e8557634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612ec657634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610633565b6000915050610633565b6000826000018281548110612f3057634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b6000818152600183016020526040812054612f8a57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610633565b506000610633565b600154604051630525194b60e31b81526001600160a01b0384811660048301526000921690632928ca5890602401602060405180830381600087803b158015612fda57600080fd5b505af1158015612fee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120d919061374b565b60006001600160e01b0319821663a927d73f60e01b148061063357506106338261269a565b60006001600160e01b03198216637005caad60e01b1480610633575061063382613012565b82805461306890613caf565b90600052602060002090601f01602090048101928261308a57600085556130d0565b82601f106130a35782800160ff198235161785556130d0565b828001600101855582156130d0579182015b828111156130d05782358255916020019190600101906130b5565b50610f159291505b80821115610f1557600081556001016130d8565b60008083601f8401126130fd578182fd5b50813567ffffffffffffffff811115613114578182fd5b6020830191508360208260051b850101111561312f57600080fd5b9250929050565b600082601f830112613146578081fd5b8135602061315b61315683613bd6565b613ba5565b80838252828201915082860187848660051b890101111561317a578586fd5b855b858110156131a157813561318f81613d92565b8452928401929084019060010161317c565b5090979650505050505050565b600082601f8301126131be578081fd5b813560206131ce61315683613bd6565b80838252828201915082860187848660051b89010111156131ed578586fd5b855b858110156131a1578135845292840192908401906001016131ef565b60008083601f84011261321c578182fd5b50813567ffffffffffffffff811115613233578182fd5b60208301915083602082850101111561312f57600080fd5b60006020828403121561325c578081fd5b813561120d81613d7d565b600060208284031215613278578081fd5b815161120d81613d7d565b60008060408385031215613295578081fd5b82356132a081613d7d565b946020939093013593505050565b60008060008060008060008060a0898b0312156132c9578384fd5b88356132d481613d7d565b975060208901356132e481613d7d565b9650604089013567ffffffffffffffff80821115613300578586fd5b61330c8c838d016130ec565b909850965060608b0135915080821115613324578586fd5b6133308c838d016130ec565b909650945060808b0135915080821115613348578384fd5b506133558b828c0161320b565b999c989b5096995094979396929594505050565b600080600080600060808688031215613380578081fd5b853561338b81613d7d565b9450602086013561339b81613d7d565b935060408601359250606086013567ffffffffffffffff8111156133bd578182fd5b6133c98882890161320b565b969995985093965092949392505050565b60008060008060008060a087890312156133f2578384fd5b86356133fd81613d7d565b9550602087013561340d81613d7d565b94506040870135935060608701359250608087013567ffffffffffffffff811115613436578283fd5b61344289828a0161320b565b979a9699509497509295939492505050565b600080600060608486031215613468578081fd5b833561347381613d7d565b9250602084013567ffffffffffffffff8082111561348f578283fd5b61349b878388016131ae565b935060408601359150808211156134b0578283fd5b506134bd86828701613136565b9150509250925092565b6000806000606084860312156134db578081fd5b83356134e681613d7d565b9250602084013567ffffffffffffffff80821115613502578283fd5b61350e878388016131ae565b93506040860135915080821115613523578283fd5b506134bd868287016131ae565b60008060408385031215613295578182fd5b600080600060608486031215613556578081fd5b833561356181613d7d565b925060208401359150604084013561357881613d7d565b809150509250925092565b60008060008060408587031215613598578182fd5b843567ffffffffffffffff808211156135af578384fd5b6135bb888389016130ec565b909650945060208701359150808211156135d3578384fd5b506135e0878288016130ec565b95989497509550505050565b600080604083850312156135fe578182fd5b823567ffffffffffffffff80821115613615578384fd5b818501915085601f830112613628578384fd5b8135602061363861315683613bd6565b8083825282820191508286018a848660051b8901011115613657578889fd5b8896505b8487101561368257803561366e81613d7d565b83526001969096019591830191830161365b565b5096505086013592505080821115613698578283fd5b506136a585828601613136565b9150509250929050565b6000602082840312156136c0578081fd5b815161120d81613d92565b6000602082840312156136dc578081fd5b81356001600160e01b03198116811461120d578182fd5b60008060208385031215613705578182fd5b823567ffffffffffffffff81111561371b578283fd5b6137278582860161320b565b90969095509350505050565b600060208284031215613744578081fd5b5035919050565b60006020828403121561375c578081fd5b5051919050565b6000815180845260208085019450808401835b8381101561379b5781516001600160a01b031687529582019590820190600101613776565b509495945050505050565b6000815180845260208085019450808401835b8381101561379b5781511515875295820195908201906001016137b9565b81835260006001600160fb1b038311156137ef578081fd5b8260051b80836020870137939093016020019283525090919050565b6000815180845260208085019450808401835b8381101561379b5781518752958201959082019060010161381e565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60008151613875818560208601613c7f565b9290920192915050565b60008251613891818460208701613c7f565b9190910192915050565b600080845482600182811c9150808316806138b757607f831692505b60208084108214156138d757634e487b7160e01b87526022600452602487fd5b8180156138eb57600181146138fc57613928565b60ff19861689528489019650613928565b60008b815260209020885b868110156139205781548b820152908501908301613907565b505084890196505b5050505050506139388185613863565b95945050505050565b60006001600160a01b03808b168352808a1660208401525060a0604083015261396e60a08301888a6137d7565b82810360608401526139818187896137d7565b9050828103608084015261399681858761383a565b9b9a5050505050505050505050565b60006001600160a01b038088168352808716602084015250846040830152608060608301526139d860808301848661383a565b979650505050505050565b60006001600160a01b03808916835280881660208401525085604083015284606083015260a06080830152613a1c60a08301848661383a565b98975050505050505050565b6001600160a01b0384168152606060208201526000613a4a606083018561380b565b8281036040840152612db081856137a6565b6001600160a01b0384168152606060208201526000613a7e606083018561380b565b8281036040840152612db0818561380b565b60208152600061120d6020830184613763565b604081526000613ab66040830185613763565b828103602084015261393881856137a6565b60208152600061120d602083018461380b565b6020815260008251806020840152613afa816040850160208701613c7f565b601f01601f19169190910160400192915050565b60208082526024908201527f41646d696e436f6e74726f6c3a204d757374206265206f776e6572206f7220616040820152633236b4b760e11b606082015260800190565b60208082526033908201527f4275726e52656465656d3a20496e636f7272656374206e756d626572206f66206040820152721391951cc818995a5b99c81c995919595b5959606a1b606082015260800190565b604051601f8201601f1916810167ffffffffffffffff81118282101715613bce57613bce613d67565b604052919050565b600067ffffffffffffffff821115613bf057613bf0613d67565b5060051b60200190565b60008219821115613c0d57613c0d613d3b565b500190565b600082613c2157613c21613d51565b500490565b6000816000190483118215151615613c4057613c40613d3b565b500290565b600061ffff83811690831681811015613c6057613c60613d3b565b039392505050565b600082821015613c7a57613c7a613d3b565b500390565b60005b83811015613c9a578181015183820152602001613c82565b83811115613ca9576000848401525b50505050565b600181811c90821680613cc357607f821691505b60208210811415613ce457634e487b7160e01b600052602260045260246000fd5b50919050565b600061ffff80831681811415613d0257613d02613d3b565b6001019392505050565b6000600019821415613d2057613d20613d3b565b5060010190565b600082613d3657613d36613d51565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610e4b57600080fd5b8015158114610e4b57600080fdfe5265656e7472616e637947756172643a207265656e7472616e742063616c6c00a26469706673582212201668a9ae8d165204c5f976f3907c4e391d0400c2aa7c68c982f4ba193bf3b94d64736f6c63430008040033

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

0000000000000000000000007afeda4c714e1c0a2a1248332c100924506ac8e6

-----Decoded View---------------
Arg [0] : creator (address): 0x7AfEdA4c714e1C0A2a1248332c100924506aC8e6

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000007afeda4c714e1c0a2a1248332c100924506ac8e6


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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