ETH Price: $3,823.40 (+5.69%)

Token

Mechanized Abstractions (MA)
 

Overview

Max Total Supply

0 MA

Holders

577

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
1 MA
0xcc2b438a6945ecae97babb08f8db504335045d09
Loading...
Loading
Loading...
Loading
Loading...
Loading

OVERVIEW

Mechanized Abstractions is a collection of 1,234 on-chain generative abstract art pieces. Unlike NFT projects that are optimized for use in a profile picture, Mechanized Abstractions optimizes for the wide aspect ratio that can be used in banners.

# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
MechanizedAbstractions

Compiler Version
v0.8.0+commit.c7dfd78e

Optimization Enabled:
Yes with 1 runs

Other Settings:
default evmVersion
File 1 of 18 : MechanizedAbstractions.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";

// Opensea: represents a proxy contract of a user
contract OwnableDelegateProxy {}

/**
 Opensea:
 This represents Opensea's ProxyRegistry contract.
 We use it to find and approve the opensea proxy contract of a 
 user so our contract is better integrated with opensea.
*/
contract ProxyRegistry {
    mapping(address => OwnableDelegateProxy) public proxies;
}

contract MechanizedAbstractions is AccessControl, Ownable, ERC721, VRFConsumerBase {
    using SafeMath for uint256;
    using Strings for uint256;
    using ECDSA for bytes32; 

    // Addresses
    address public proxyRegistryAddress; // Opensea: the address of the Opensea ProxyRegistry 

    // Strings
    string public p5ScriptArweaveAddress; // points to the p5 script on arweave https://55mcex7dtd5xf4c627v6hadwoq6lgw6jr4oeacqd5k2mazhunejq.arweave.net/71giX-OY-3LwXtfr44B2dDyzW8mPHEAKA-q0wGT0aRM
    string public baseURIString = "";   // represents the baseURI of the metadata
    string public p5script = "function mechanizedAbstractionRenderer(e){let[t,o]=function(e){const t=parseInt(e.slice(0,Math.floor(e.length/2)))%1e10,o=parseInt(e.slice(Math.floor(e.length/2),e.length))%1e10;return[t,o]}(e);var l,n,r,a,F,d,i,s,v,D,A,h=60,E=255,B={};let b={},c={'Mid-century':{v:['#F1B680','#E98355','#D24227','#274274','#4787A8','#89B6AB','#8AAAA2'],w:7,bbl:['#D24227','#F1B680','#E98355']},Unpacked:{v:['#00000B','#87F8DF','#DE4338','#F4C0D9','#2E34C5','#E7E96D'],w:7,bbl:[]},Boardwalk:{v:['#B8E2D3','#5B9AF5','#FD2B73','#FE8233','#D40C0C','#FFCA35','#1F7340','#0343C1','#66093E'],w:3,bbl:['#5B9AF5','#FE8233','#D40C0C','#FFCA35','#1F7340','#0343C1','#66093E']},'Pop!':{v:['#E7147F','#179AED','#2C2A87','#F4EF19','#7A4A95','#9DD340','#DC132A'],w:6,bbl:['#DC132A','#']},Sunburst:{v:['#143642','#ec9a29','#0f8b8d','#dad2d8'],w:3,bbl:[]},Ethereal:{v:['#03B87A','#6139D0','#60A0F4','#FFDE3A','#F4FCFF','#2A2F4D','#F6C1FF'],w:7,bbl:['#FFDE3A','#F6C1FF']},Coral:{v:['#FF8A71','#DB82A8','#55BCF5','#7CD3C5','#0246C9','#FFBAAB'],w:5,bbl:[]},Paradise:{v:['#FD9672','#FAA34F','#6BACB5','#3F7088','#EDC1BE'],w:4,bbl:['#FD9672','#FAA34F']},'Ultra Red':{v:['#313B42','#FFEEE4','#E54F2D','#FD7A6E','#FFBDB7'],w:4,bbl:['#E54F2D','']},'Ocean Blues':{v:['#3073AD','#78B0E2','#9CC2E3','#D9EDFF','#0788D9'],w:2,bbl:['#D94F30']},Dreamscape:{v:['#E0CEFA','#88A0E4','#5991FF','#FFA794','#FF8282','#B9FDDD'],w:5,bbl:['#FFA794','#FF8282']},Blossom:{v:['#2A764B','#55A578','#F5F5D9','#FFC4B2','#DC934C'],w:3,bbl:['','','']},Mystique:{v:['#A57AFF','#C4F500','#03CCBF','#80FFD4','#03A0FF','#0469A6','#30337A'],w:5,bbl:['#03A0FF','#C4F500']},Nautical:{v:['#FAC998','#EB9C44','#D9492A','#A12425','#347D95'],w:4,bbl:['#D9492A','#EB9C44']},Retro:{v:['#F4EE97','#F9D74D','#EC9E43','#E2693C','#4A6076'],w:2,bbl:['#','#']},'Ode to Van Gogh':{v:['#2A4184','#5A87C2','#94C0D2','#EFE986','#1B2424'],w:3,bbl:['#EFE986']},'Ode to Mondrian':{v:['#D2BA49','#B7B8B2','#143675','#9E2F2A','#DDDDD9'],w:3,bbl:['#9E2F2A','#143675']},'Ode to Monet':{v:['#C4C7BA','#344147','#6A8993','#D46E60','#D18D74'],w:3,bbl:['#D46E60']},'Midnight Blue':{v:['#000421','#1BC5D2'],w:2,bbl:['#1BC5D2']},Monochrome:{v:['#F0EFEF','#373737'],w:2},Punkable:{v:['#6C91A6','#D77247','#CBEDEC','#FFF0B5','#313131','#9BC989','#BEBEBE'],w:3,bbl:['#D77247']},Apeable:{v:['#9A9B6B','#B9CBDC','#F3B468','#396785','#74D4B4','#9979A0','#F2F29C'],w:3,bbl:['#ED041F']}},w={Solid:{v:'solid',w:80},Translucent:{v:'translucent',w:20}},m={Low:{v:{mean:15,std:5,floor:20},w:60},Medium:{v:{mean:30,std:5,floor:20},w:20},High:{v:{mean:40,std:5,floor:20},w:10}},C={None:{v:0,w:89},Thick:{v:1.5,w:10},Thin:{v:1,w:1}},u={White:{v:'rgba(255,255,255,.8)',w:1},Black:{v:'rgba(0,0,0,.6)',w:1}},f={Short:{v:{mean:200,std:150},w:1},Normal:{v:{mean:400,std:300},w:1},Long:{v:{mean:1500,std:250},w:1}},g={Thin:{v:{mean:3,std:.1},w:25},Normal:{v:{mean:10,std:5},w:60},Thick:{v:{mean:20,std:5},w:15}},p={Normal:{v:2e-4,w:85},Straight:{v:1e-6,w:15}},k={Normal:{v:{mean:25e3,std:25e3},w:1},None:{v:{mean:0,std:0},w:1}},M={'No Border':{v:-25,w:85},Border:{v:35,w:15}};var S=function(e,t){var o=Object.keys(e),l=[];for(let t=0;t<o.length;t++){let n=e[o[t]].w;for(let e=0;e<n;e++)l.push(o[t])}return l[t.floor(t.random()*l.length)]};function y(e,t,o,l){let n=e.randomGaussian(2,10);var r=[],a=[];for(var F=0;F<13;F++){let l=n+e.random(-n/35,n/35);r[F]=t+l*e.cos(360*F/13),a[F]=o+l*e.sin(360*F/13)}e.beginShape();for(let t=0;t<r.length;t++)e.curveVertex(r[t],a[t]);e.endShape(e.CLOSE)}function x(e,t,o){let l=o.randomGaussian(D,10);return e<l||e>o.width-l||t<l||t>o.height-l}function N(e,t,o){let l=e.randomGaussian(i.mean,i.std),n=e.randomGaussian(s.mean,s.std);var r=[],F=[];r.push(t);for(let t=0;t<l;t++){let o=e.createVector(r[t].x+n,r[t].y+n);if(x(r[t].x+n,r[t].y+n,e))--t,--l;else{F.push(o);var v=e.map(e.noise(r[t].x*d,r[t].y*d),0,1,0,720);if(x(r[t].x+e.cos(v),r[t].y+e.sin(v),e))--t,--l;else{var D=e.createVector(r[t].x+e.cos(v),r[t].y+e.sin(v));r.push(D)}}}for(e.beginShape(),t=0;t<r.length;t++){let o=r[t];e.vertex(o.x,o.y)}for(t=F.length-1;t>=0;t--){let o=F[t];e.vertex(o.x,o.y)}e.endShape(),e.stroke(a);let A=e.color(o);A.setAlpha(E),e.fill(A)}return{renderer:e=>{e.setup=function(){e.randomSeed(t),e.noiseSeed(o);let x=e.createCanvas(1500,500);var G;for(e.angleMode(e.DEGREES),function(e){B.randomSeed=t,B.noiseSeed=o;let v=S(w,e);B['fill type']=v,'translucent'==w[v].v&&(delete c.Monochrome,delete c['Midnight Blue'],delete C.Thick,delete m.Low,delete m.Medium,h=80,E=200);let b=S(M,e);B.borderStyle=b,(D=M[b].v)>0&&(delete m.Low,delete m.Medium);let y=S(m,e);B.density=y,F=m[y].v;let x=S(c,e);B.colors=x,l=c[x].v,n=c[x].bbl,'Midnight Blue'==x&&(delete u.Black,delete C.None,delete C.Thick),'Monochrome'==x&&(delete u.White,delete C.None,delete C.Thick);let N=S(C,e);B.strokeThickness=N,r=C[N].v;let G=S(u,e);B.strokeColor=G,a=u[G].v;let T=S(f,e);B.curveLength=T,i=f[T].v;let L=S(g,e);B.curveWidth=L,s=g[L].v;let O=S(p,e);B.curveRate=O,d=p[O].v;let R=S(k,e);B.textureDensity=R,A=k[R].v}(e);null==G;){let t=l[e.floor(e.random()*l.length)];null!=n&&n.includes(t)||(G=t)}e.background(G),l=l.filter(e=>e!=G),e.strokeWeight(r);let T=e.floor(e.max(e.randomGaussian(F.mean,F.std),F.floor));for(var L=e.width/T,O=D;O<e.width-D;O+=L)for(var R=D;R<e.height-D;R+=L)if(e.floor(100*e.random())<=h){var U=e.createVector(O+e.random(-10,10),R+e.random(-10,10));N(e,U,l[e.floor(e.random()*l.length)])}else e.random(),e.width,e.random(),e.height,y(e,O+e.randomGaussian(20,20),R+e.random(20,20),l[e.floor(e.random()*l.length)]);v=e.randomGaussian(A.mean,A.std),function(e,t){let o=e.floor(e.random(50,90)),l=e.color(20,20,20,o);e.noStroke(),e.fill(l);for(let o=0;o<t;o++){let t=e.random()*e.width,o=e.random()*e.height,l=e.random(0,1.5);e.ellipse(t,o,l)}}(e,v),b.dataUrl=x.canvas.toDataURL()},e.draw=function(){e.noLoop()}},properties:B,dataUrl:b}}";
    string public arweaveGateway = "https://arweave.net/";

    // Flags
    bool public isContractOpen = true;

    // Token data 
    uint256 public nextTokenId = 1;  

    /** ROLES */
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");

    // Arweave metadata
    uint256[] public arweaveManifestBatches; // excluding the token of the value itself
    string[] public  arweaveManifestIds;

    // Chainlink VRF variables
    bytes32 private keyHash; // public key used to generate random values
    uint256 private fee; // fee paid to chainlink node for random value
    uint256 public baseSeed = 0;

    // MechanizedAbstractions seed values
    mapping(uint256 => uint256) private _vrfValues;
    mapping(uint256 => uint256) public seedValues; // maps token id to seed value

    // events
    event Minted(address minter, uint256 tokenId);
    event VRFRequested(bytes32 requestId);
    event VRFReceived(bytes32 requestId);
    event ReceivedEther(uint256 amount, address _from);

    // modifiers
    modifier modifiable {
        require(isContractOpen, "NOT MODIFIABLE");
        _;
    }

    constructor(
        string memory _name,
        string memory _symbol,
        address _proxyRegistryAddress,
        string memory _p5ScriptArweaveAddress,
        address _vrfCoordinator,
        address _linkTokenAddress,
        uint256 _vrfFee,
        bytes32 _keyHash
    ) Ownable() ERC721(_name, _symbol) VRFConsumerBase(
        _vrfCoordinator,
        _linkTokenAddress
    ) {
        proxyRegistryAddress = _proxyRegistryAddress; // set the provided ProxyRegistry address to our own state variable
        p5ScriptArweaveAddress = _p5ScriptArweaveAddress; // set arweave address of p5 script
        keyHash = _keyHash; // set the keyhash used for rng
        fee = _vrfFee; // fee paid to chainlink VRF node, varies per network (0.1 * 10 ** 18) = 0.1 link

        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
    }    

    /** === ERC-721 & METADATA functions === */
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, ERC721) returns (bool) {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            interfaceId == type(IAccessControl).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /**
    * @dev returns the baseURI for the metadata. Used by the tokenURI method.
    * @return the URI of the metadata
    */
    function _baseURI() internal override view returns (string memory) {
        return baseURIString;
    }

    /**
     * @dev returns the tokenUri of a token
     * First it checks if the token exists, if not it reverts
     * Then it tries to find the batch index of the token
     * If the batch index is not found it returns a link to the server
     * Otherwise it returns a link to the corresponding arweave manifest
     *
     * @param tokenId the tokenId of the token
     */
    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        require(_exists(tokenId), "TOKEN DOESN'T EXIST");

        // Look for the arweave batch index of the token
        uint256 index = 0;
        bool found = false;
        for (uint i = 0; i < arweaveManifestBatches.length; i++) {
            if (tokenId < arweaveManifestBatches[i]) {
                index = i;
                found = true;
                break;
            }
        }

        // If no arweave manifest was uploaded for tokenId return a link to the server
        if (!found) {
            return string(abi.encodePacked(_baseURI(), tokenId.toString()));
        }

        // Otherwise return the arweave link
        return string(abi.encodePacked(arweaveGateway, arweaveManifestIds[index], "/", tokenId.toString()));
    }

    /** === ONLY OWNER === */

    /**
     * @dev Allows the signatureProvider to set a new manifestId
     * for a given batch.
     *
     * @param batchId the batch Id
     * @param manifestId the manifest Id
     */
    function setArweaveManifestId(uint256 batchId, string memory manifestId) external onlyOwner {
        if (arweaveManifestBatches.length > 0) {
            require(arweaveManifestBatches[arweaveManifestBatches.length - 1] < batchId, "BATCH ID SHOULD EXCEED PREVIOUS ONE");
        }

        arweaveManifestBatches.push(batchId);
        arweaveManifestIds.push(manifestId);
    }

    function resetArweave() external onlyOwner modifiable {
        delete arweaveManifestBatches;
        delete arweaveManifestIds;
    }

    function setP5(string calldata _p5) external onlyOwner modifiable {
        p5script = _p5;
    }

    function setP5Address(string calldata _address) external onlyOwner modifiable {
        p5ScriptArweaveAddress = _address;
    }

    /**
    * @dev function to change the baseURI of the metadata
    */
    function setBaseURI(string memory _newBaseURI) public onlyOwner modifiable {
        baseURIString = _newBaseURI;
    }

    function setArweaveGateway(string calldata _gateway) external onlyOwner modifiable {
        arweaveGateway = _gateway;
    }

    /**
     * @dev Allows the owner to withdraw link
     */
    function withdrawLink() external onlyOwner {
        require(LINK.transfer(msg.sender, LINK.balanceOf(address(this))), "LINK Transfer failed");
    }

    /**
     * @dev Allows the owner to withdraw ether
     */
    function withdrawEth() external onlyOwner {
        (bool success, ) = msg.sender.call{value: address(this).balance}("");
        require(success, "ETH Transfer failed");
    }

    function disableModifications() external onlyOwner {
        isContractOpen = false;
    }

    /** === OPENSEA FUNCTIONS === */

    /**
    * @dev Override isApprovedForAll to whitelist user's OpenSea proxy accounts to enable gas-less listings.
    */
    function isApprovedForAll(address owner, address operator)
        override
        public
        view
        returns (bool)
    {
        // Create an instance of the ProxyRegistry contract from Opensea
        ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);
        // whitelist the ProxyContract of the owner of the NFT
        if (address(proxyRegistry.proxies(owner)) == operator) {
            return true;
        }

        return super.isApprovedForAll(owner, operator);
    }

    /** === MINT METHODS === */

    /**
     * @dev mints numberOfTokens tokens.
     * - A new VRF request is made before each 15 tokens are minted
     * - Creates a new tokenData struct
     * - Increments the tokenId
     * - Checks if the VRF value for this batch is ready
     * - If so it mints the token
     * - If not it adds to token to pending mints array for current requestId
     * - And it adds one to the pending mints of the users
     * 
     * @param numberOfTokens the number of tokens to mint
     */
    function doMint(uint256 numberOfTokens, address _to) external onlyRole(MINTER_ROLE) {
        for (uint i = 0; i < numberOfTokens; i++) {       

            _safeMint(_to, nextTokenId); 
            seedValues[nextTokenId] = (uint256(keccak256(abi.encode(nextTokenId, baseSeed, msg.sender, block.timestamp, blockhash(block.number)))));

            emit Minted(_to, nextTokenId); 
            nextTokenId = nextTokenId.add(1);
        }
    }

    function burn(uint256 tokenId) external onlyRole(BURNER_ROLE) {
        _burn(tokenId);
    }

    /** === CHAINLINK VRF METHODS === */

    /** 
     * Requests randomness 
     */
    function _requestNewVRN() external onlyOwner modifiable returns (bytes32) {
        require(LINK.balanceOf(address(this)) >= fee, "NOT ENOUGH LINK");
        bytes32 requestId = requestRandomness(keyHash, fee);
        emit VRFRequested(requestId);
        return requestId;
    }

    /**
     * @dev Callback function used by VRF Coordinator
     * Pushed new VRF value to array
     * Mints any pending tokens
     */
    function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
        baseSeed = randomness;
        emit VRFReceived(requestId);
    }

    /** === MISC === */
    
    /**
     * @dev Fallback function for receiving Ether
     */
    receive() external payable {
        emit ReceivedEther(msg.value, msg.sender);
    }        

    /**
     * @dev returns the amount fo arweave batches that have been uploaded
     */
     function arweaveBatchLength() external view returns(uint256) {
         return arweaveManifestBatches.length;
     }
}

File 2 of 18 : ERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;

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

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

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        _approve(to, tokenId);
    }

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

        return _tokenApprovals[tokenId];
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     */
    function setApprovalForAll(address operator, bool approved) public virtual override {
        _setApprovalForAll(_msgSender(), operator, approved);
    }

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

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

        _transfer(from, to, tokenId);
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        _beforeTokenTransfer(from, to, tokenId);

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

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

        emit Transfer(from, to, tokenId);
    }

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

    /**
     * @dev Approve `operator` to operate on all of `owner` tokens
     *
     * Emits a {ApprovalForAll} event.
     */
    function _setApprovalForAll(
        address owner,
        address operator,
        bool approved
    ) internal virtual {
        require(owner != operator, "ERC721: approve to caller");
        _operatorApprovals[owner][operator] = approved;
        emit ApprovalForAll(owner, operator, approved);
    }

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

    /**
     * @dev Hook that is called before any token transfer. This includes minting
     * and burning.
     *
     * Calling conditions:
     *
     * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be
     * transferred to `to`.
     * - When `from` is zero, `tokenId` will be minted for `to`.
     * - When `to` is zero, ``from``'s `tokenId` will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal virtual {}
}

File 3 of 18 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (access/Ownable.sol)

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() {
        _transferOwnership(_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 {
        _transferOwnership(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");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 4 of 18 : AccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (access/AccessControl.sol)

pragma solidity ^0.8.0;

import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role, _msgSender());
        _;
    }

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

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view override returns (bool) {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        Strings.toHexString(uint160(account), 20),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     *
     * NOTE: This function is deprecated in favor of {_grantRole}.
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * Internal function without access restriction.
     */
    function _grantRole(bytes32 role, address account) internal virtual {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * Internal function without access restriction.
     */
    function _revokeRole(bytes32 role, address account) internal virtual {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

File 5 of 18 : SafeMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.

/**
 * @dev Wrappers over Solidity's arithmetic operations.
 *
 * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
 * now has built in overflow checking.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

File 6 of 18 : ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "../Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        // Check the signature length
        // - case 65: r,s,v signature (standard)
        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else if (signature.length == 64) {
            bytes32 r;
            bytes32 vs;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                vs := mload(add(signature, 0x40))
            }
            return tryRecover(hash, r, vs);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s;
        uint8 v;
        assembly {
            s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
            v := add(shr(255, vs), 27)
        }
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }
        if (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

File 7 of 18 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Strings.sol)

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 8 of 18 : VRFConsumerBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./interfaces/LinkTokenInterface.sol";

import "./VRFRequestIDBase.sol";

/** ****************************************************************************
 * @notice Interface for contracts using VRF randomness
 * *****************************************************************************
 * @dev PURPOSE
 *
 * @dev Reggie the Random Oracle (not his real job) wants to provide randomness
 * @dev to Vera the verifier in such a way that Vera can be sure he's not
 * @dev making his output up to suit himself. Reggie provides Vera a public key
 * @dev to which he knows the secret key. Each time Vera provides a seed to
 * @dev Reggie, he gives back a value which is computed completely
 * @dev deterministically from the seed and the secret key.
 *
 * @dev Reggie provides a proof by which Vera can verify that the output was
 * @dev correctly computed once Reggie tells it to her, but without that proof,
 * @dev the output is indistinguishable to her from a uniform random sample
 * @dev from the output space.
 *
 * @dev The purpose of this contract is to make it easy for unrelated contracts
 * @dev to talk to Vera the verifier about the work Reggie is doing, to provide
 * @dev simple access to a verifiable source of randomness.
 * *****************************************************************************
 * @dev USAGE
 *
 * @dev Calling contracts must inherit from VRFConsumerBase, and can
 * @dev initialize VRFConsumerBase's attributes in their constructor as
 * @dev shown:
 *
 * @dev   contract VRFConsumer {
 * @dev     constuctor(<other arguments>, address _vrfCoordinator, address _link)
 * @dev       VRFConsumerBase(_vrfCoordinator, _link) public {
 * @dev         <initialization with other arguments goes here>
 * @dev       }
 * @dev   }
 *
 * @dev The oracle will have given you an ID for the VRF keypair they have
 * @dev committed to (let's call it keyHash), and have told you the minimum LINK
 * @dev price for VRF service. Make sure your contract has sufficient LINK, and
 * @dev call requestRandomness(keyHash, fee, seed), where seed is the input you
 * @dev want to generate randomness from.
 *
 * @dev Once the VRFCoordinator has received and validated the oracle's response
 * @dev to your request, it will call your contract's fulfillRandomness method.
 *
 * @dev The randomness argument to fulfillRandomness is the actual random value
 * @dev generated from your seed.
 *
 * @dev The requestId argument is generated from the keyHash and the seed by
 * @dev makeRequestId(keyHash, seed). If your contract could have concurrent
 * @dev requests open, you can use the requestId to track which seed is
 * @dev associated with which randomness. See VRFRequestIDBase.sol for more
 * @dev details. (See "SECURITY CONSIDERATIONS" for principles to keep in mind,
 * @dev if your contract could have multiple requests in flight simultaneously.)
 *
 * @dev Colliding `requestId`s are cryptographically impossible as long as seeds
 * @dev differ. (Which is critical to making unpredictable randomness! See the
 * @dev next section.)
 *
 * *****************************************************************************
 * @dev SECURITY CONSIDERATIONS
 *
 * @dev A method with the ability to call your fulfillRandomness method directly
 * @dev could spoof a VRF response with any random value, so it's critical that
 * @dev it cannot be directly called by anything other than this base contract
 * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method).
 *
 * @dev For your users to trust that your contract's random behavior is free
 * @dev from malicious interference, it's best if you can write it so that all
 * @dev behaviors implied by a VRF response are executed *during* your
 * @dev fulfillRandomness method. If your contract must store the response (or
 * @dev anything derived from it) and use it later, you must ensure that any
 * @dev user-significant behavior which depends on that stored value cannot be
 * @dev manipulated by a subsequent VRF request.
 *
 * @dev Similarly, both miners and the VRF oracle itself have some influence
 * @dev over the order in which VRF responses appear on the blockchain, so if
 * @dev your contract could have multiple VRF requests in flight simultaneously,
 * @dev you must ensure that the order in which the VRF responses arrive cannot
 * @dev be used to manipulate your contract's user-significant behavior.
 *
 * @dev Since the ultimate input to the VRF is mixed with the block hash of the
 * @dev block in which the request is made, user-provided seeds have no impact
 * @dev on its economic security properties. They are only included for API
 * @dev compatability with previous versions of this contract.
 *
 * @dev Since the block hash of the block which contains the requestRandomness
 * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful
 * @dev miner could, in principle, fork the blockchain to evict the block
 * @dev containing the request, forcing the request to be included in a
 * @dev different block with a different hash, and therefore a different input
 * @dev to the VRF. However, such an attack would incur a substantial economic
 * @dev cost. This cost scales with the number of blocks the VRF oracle waits
 * @dev until it calls responds to a request.
 */
abstract contract VRFConsumerBase is VRFRequestIDBase {

  /**
   * @notice fulfillRandomness handles the VRF response. Your contract must
   * @notice implement it. See "SECURITY CONSIDERATIONS" above for important
   * @notice principles to keep in mind when implementing your fulfillRandomness
   * @notice method.
   *
   * @dev VRFConsumerBase expects its subcontracts to have a method with this
   * @dev signature, and will call it once it has verified the proof
   * @dev associated with the randomness. (It is triggered via a call to
   * @dev rawFulfillRandomness, below.)
   *
   * @param requestId The Id initially returned by requestRandomness
   * @param randomness the VRF output
   */
  function fulfillRandomness(
    bytes32 requestId,
    uint256 randomness
  )
    internal
    virtual;

  /**
   * @dev In order to keep backwards compatibility we have kept the user
   * seed field around. We remove the use of it because given that the blockhash
   * enters later, it overrides whatever randomness the used seed provides.
   * Given that it adds no security, and can easily lead to misunderstandings,
   * we have removed it from usage and can now provide a simpler API.
   */
  uint256 constant private USER_SEED_PLACEHOLDER = 0;

  /**
   * @notice requestRandomness initiates a request for VRF output given _seed
   *
   * @dev The fulfillRandomness method receives the output, once it's provided
   * @dev by the Oracle, and verified by the vrfCoordinator.
   *
   * @dev The _keyHash must already be registered with the VRFCoordinator, and
   * @dev the _fee must exceed the fee specified during registration of the
   * @dev _keyHash.
   *
   * @dev The _seed parameter is vestigial, and is kept only for API
   * @dev compatibility with older versions. It can't *hurt* to mix in some of
   * @dev your own randomness, here, but it's not necessary because the VRF
   * @dev oracle will mix the hash of the block containing your request into the
   * @dev VRF seed it ultimately uses.
   *
   * @param _keyHash ID of public key against which randomness is generated
   * @param _fee The amount of LINK to send with the request
   *
   * @return requestId unique ID for this request
   *
   * @dev The returned requestId can be used to distinguish responses to
   * @dev concurrent requests. It is passed as the first argument to
   * @dev fulfillRandomness.
   */
  function requestRandomness(
    bytes32 _keyHash,
    uint256 _fee
  )
    internal
    returns (
      bytes32 requestId
    )
  {
    LINK.transferAndCall(vrfCoordinator, _fee, abi.encode(_keyHash, USER_SEED_PLACEHOLDER));
    // This is the seed passed to VRFCoordinator. The oracle will mix this with
    // the hash of the block containing this request to obtain the seed/input
    // which is finally passed to the VRF cryptographic machinery.
    uint256 vRFSeed  = makeVRFInputSeed(_keyHash, USER_SEED_PLACEHOLDER, address(this), nonces[_keyHash]);
    // nonces[_keyHash] must stay in sync with
    // VRFCoordinator.nonces[_keyHash][this], which was incremented by the above
    // successful LINK.transferAndCall (in VRFCoordinator.randomnessRequest).
    // This provides protection against the user repeating their input seed,
    // which would result in a predictable/duplicate output, if multiple such
    // requests appeared in the same block.
    nonces[_keyHash] = nonces[_keyHash] + 1;
    return makeRequestId(_keyHash, vRFSeed);
  }

  LinkTokenInterface immutable internal LINK;
  address immutable private vrfCoordinator;

  // Nonces for each VRF key from which randomness has been requested.
  //
  // Must stay in sync with VRFCoordinator[_keyHash][this]
  mapping(bytes32 /* keyHash */ => uint256 /* nonce */) private nonces;

  /**
   * @param _vrfCoordinator address of VRFCoordinator contract
   * @param _link address of LINK token contract
   *
   * @dev https://docs.chain.link/docs/link-token-contracts
   */
  constructor(
    address _vrfCoordinator,
    address _link
  ) {
    vrfCoordinator = _vrfCoordinator;
    LINK = LinkTokenInterface(_link);
  }

  // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF
  // proof. rawFulfillRandomness then calls fulfillRandomness, after validating
  // the origin of the call
  function rawFulfillRandomness(
    bytes32 requestId,
    uint256 randomness
  )
    external
  {
    require(msg.sender == vrfCoordinator, "Only VRFCoordinator can fulfill");
    fulfillRandomness(requestId, randomness);
  }
}

File 9 of 18 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC721/IERC721.sol)

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 10 of 18 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

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

File 11 of 18 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (token/ERC721/extensions/IERC721Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional metadata extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Metadata is IERC721 {
    /**
     * @dev Returns the token collection name.
     */
    function name() external view returns (string memory);

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

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

File 12 of 18 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Address.sol)

pragma solidity ^0.8.0;

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

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

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

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

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

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

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

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

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

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

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

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

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

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

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 13 of 18 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/Context.sol)

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 14 of 18 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/introspection/ERC165.sol)

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 15 of 18 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (utils/introspection/IERC165.sol)

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 16 of 18 : IAccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.0 (access/IAccessControl.sol)

pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

File 17 of 18 : LinkTokenInterface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface LinkTokenInterface {

  function allowance(
    address owner,
    address spender
  )
    external
    view
    returns (
      uint256 remaining
    );

  function approve(
    address spender,
    uint256 value
  )
    external
    returns (
      bool success
    );

  function balanceOf(
    address owner
  )
    external
    view
    returns (
      uint256 balance
    );

  function decimals()
    external
    view
    returns (
      uint8 decimalPlaces
    );

  function decreaseApproval(
    address spender,
    uint256 addedValue
  )
    external
    returns (
      bool success
    );

  function increaseApproval(
    address spender,
    uint256 subtractedValue
  ) external;

  function name()
    external
    view
    returns (
      string memory tokenName
    );

  function symbol()
    external
    view
    returns (
      string memory tokenSymbol
    );

  function totalSupply()
    external
    view
    returns (
      uint256 totalTokensIssued
    );

  function transfer(
    address to,
    uint256 value
  )
    external
    returns (
      bool success
    );

  function transferAndCall(
    address to,
    uint256 value,
    bytes calldata data
  )
    external
    returns (
      bool success
    );

  function transferFrom(
    address from,
    address to,
    uint256 value
  )
    external
    returns (
      bool success
    );

}

File 18 of 18 : VRFRequestIDBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract VRFRequestIDBase {

  /**
   * @notice returns the seed which is actually input to the VRF coordinator
   *
   * @dev To prevent repetition of VRF output due to repetition of the
   * @dev user-supplied seed, that seed is combined in a hash with the
   * @dev user-specific nonce, and the address of the consuming contract. The
   * @dev risk of repetition is mostly mitigated by inclusion of a blockhash in
   * @dev the final seed, but the nonce does protect against repetition in
   * @dev requests which are included in a single block.
   *
   * @param _userSeed VRF seed input provided by user
   * @param _requester Address of the requesting contract
   * @param _nonce User-specific nonce at the time of the request
   */
  function makeVRFInputSeed(
    bytes32 _keyHash,
    uint256 _userSeed,
    address _requester,
    uint256 _nonce
  )
    internal
    pure
    returns (
      uint256
    )
  {
    return uint256(keccak256(abi.encode(_keyHash, _userSeed, _requester, _nonce)));
  }

  /**
   * @notice Returns the id for this request
   * @param _keyHash The serviceAgreement ID to be used for this request
   * @param _vRFInputSeed The seed to be passed directly to the VRF
   * @return The id for this request
   *
   * @dev Note that _vRFInputSeed is not the seed passed by the consuming
   * @dev contract, but the one generated by makeVRFInputSeed
   */
  function makeRequestId(
    bytes32 _keyHash,
    uint256 _vRFInputSeed
  )
    internal
    pure
    returns (
      bytes32
    )
  {
    return keccak256(abi.encodePacked(_keyHash, _vRFInputSeed));
  }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 1
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_proxyRegistryAddress","type":"address"},{"internalType":"string","name":"_p5ScriptArweaveAddress","type":"string"},{"internalType":"address","name":"_vrfCoordinator","type":"address"},{"internalType":"address","name":"_linkTokenAddress","type":"address"},{"internalType":"uint256","name":"_vrfFee","type":"uint256"},{"internalType":"bytes32","name":"_keyHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Minted","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":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"_from","type":"address"}],"name":"ReceivedEther","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"requestId","type":"bytes32"}],"name":"VRFReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"requestId","type":"bytes32"}],"name":"VRFRequested","type":"event"},{"inputs":[],"name":"BURNER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_requestNewVRN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"arweaveBatchLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"arweaveGateway","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"arweaveManifestBatches","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"arweaveManifestIds","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseSeed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURIString","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableModifications","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numberOfTokens","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"doMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isContractOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"p5ScriptArweaveAddress","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"p5script","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxyRegistryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"rawFulfillRandomness","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resetArweave","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"seedValues","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_gateway","type":"string"}],"name":"setArweaveGateway","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"batchId","type":"uint256"},{"internalType":"string","name":"manifestId","type":"string"}],"name":"setArweaveManifestId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newBaseURI","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_p5","type":"string"}],"name":"setP5","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_address","type":"string"}],"name":"setP5Address","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60e06040819052600060c08190526200001b91600b91620002ae565b506040518061170001604052806116c2815260200162003b146116c2913980516200004f91600c91602090910190620002ae565b506040805180820190915260148082527f68747470733a2f2f617277656176652e6e65742f00000000000000000000000060209092019182526200009691600d91620002ae565b50600e805460ff19166001908117909155600f556000601455348015620000bc57600080fd5b50604051620051d6380380620051d6833981016040819052620000df916200041c565b83838989620000f7620000f162000195565b62000199565b81516200010c906002906020850190620002ae565b50805162000122906003906020840190620002ae565b505050606091821b6001600160601b031990811660a052911b16608052600980546001600160a01b0319166001600160a01b03881617905584516200016f90600a906020880190620002ae565b506012819055601382905562000187600033620001eb565b505050505050505062000547565b3390565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b620001f78282620001fb565b5050565b62000207828262000285565b620001f7576000828152602081815260408083206001600160a01b03851684529091529020805460ff191660011790556200024162000195565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b828054620002bc90620004f4565b90600052602060002090601f016020900481019282620002e057600085556200032b565b82601f10620002fb57805160ff19168380011785556200032b565b828001600101855582156200032b579182015b828111156200032b5782518255916020019190600101906200030e565b50620003399291506200033d565b5090565b5b808211156200033957600081556001016200033e565b80516001600160a01b03811681146200036c57600080fd5b919050565b600082601f83011262000382578081fd5b81516001600160401b03808211156200039f576200039f62000531565b6040516020601f8401601f1916820181018381118382101715620003c757620003c762000531565b6040528382528584018101871015620003de578485fd5b8492505b83831015620004015785830181015182840182015291820191620003e2565b838311156200041257848185840101525b5095945050505050565b600080600080600080600080610100898b03121562000439578384fd5b88516001600160401b038082111562000450578586fd5b6200045e8c838d0162000371565b995060208b015191508082111562000474578586fd5b620004828c838d0162000371565b98506200049260408c0162000354565b975060608b0151915080821115620004a8578586fd5b50620004b78b828c0162000371565b955050620004c860808a0162000354565b9350620004d860a08a0162000354565b60c08a015160e0909a0151989b979a5095989497939692505050565b6002810460018216806200050957607f821691505b602082108114156200052b57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052604160045260246000fd5b60805160601c60a05160601c61358c62000588600039600081816113340152611d04015260008181610dd2015281816111e40152611cd5015261358c6000f3fe6080604052600436106102325760003560e01c806301ffc9a71461027757806304da5304146102ad57806306fdde03146102cf57806307ba3196146102f1578063081812fc14610306578063095ea7b31461033357806314d53c25146103535780631c8a173914610380578063231871d6146103a057806323b872dd146103b5578063248a9ca3146103d5578063282c51f3146103f55780632d2b26ee1461040a5780632f2ff15d1461042a57806336568abe1461044a578063374145ce1461046a57806342842e0e1461048a57806342966c68146104aa5780634417d216146104ca5780634f638a40146104df578063506eb3f8146104ff57806355f804b3146105145780635b2906d0146105345780636352211e146105495780636602529214610569578063684297de1461057e57806370a0823114610593578063715018a6146105b357806375794a3c146105c85780638da5cb5b146105dd5780638dc654a2146105f257806391d148541461060757806394985ddd1461062757806395d89b41146106475780639e8ed6f71461065c578063a0ef91df14610671578063a217fddf14610686578063a22cb4651461069b578063b07fe3a1146106bb578063b88d4fde146106d0578063c8321c78146106f0578063c87b56dd14610710578063cd7c032614610730578063cf76a15314610745578063d53913931461075a578063d547741f1461076f578063e985e9c51461078f578063f2bfb811146107af578063f2fde38b146107cf57610272565b36610272577ffc0190751e68e3a764092e8161dc292f90c0e10e38ddf16a6b42670667bcac47343360405161026892919061331d565b60405180910390a1005b600080fd5b34801561028357600080fd5b50610297610292366004612957565b6107ef565b6040516102a49190612cee565b60405180910390f35b3480156102b957600080fd5b506102cd6102c83660046129ab565b610852565b005b3480156102db57600080fd5b506102e46108cd565b6040516102a49190612d26565b3480156102fd57600080fd5b506102e461095f565b34801561031257600080fd5b506103266103213660046128fa565b6109ed565b6040516102a49190612c54565b34801561033f57600080fd5b506102cd61034e3660046128b3565b610a30565b34801561035f57600080fd5b5061037361036e3660046128fa565b610ac3565b6040516102a49190612cf9565b34801561038c57600080fd5b506102cd61039b3660046129ab565b610ad5565b3480156103ac57600080fd5b50610373610b42565b3480156103c157600080fd5b506102cd6103d03660046127ca565b610b48565b3480156103e157600080fd5b506103736103f03660046128fa565b610b80565b34801561040157600080fd5b50610373610b95565b34801561041657600080fd5b506102cd610425366004612912565b610ba7565b34801561043657600080fd5b506102cd610445366004612912565b610c86565b34801561045657600080fd5b506102cd610465366004612912565b610ca5565b34801561047657600080fd5b506102e46104853660046128fa565b610ceb565b34801561049657600080fd5b506102cd6104a53660046127ca565b610d16565b3480156104b657600080fd5b506102cd6104c53660046128fa565b610d31565b3480156104d657600080fd5b50610373610d55565b3480156104eb57600080fd5b506102cd6104fa366004612a61565b610ec3565b34801561050b57600080fd5b506102e4610fd3565b34801561052057600080fd5b506102cd61052f366004612a17565b610fe0565b34801561054057600080fd5b50610297611054565b34801561055557600080fd5b506103266105643660046128fa565b61105d565b34801561057557600080fd5b506102cd611092565b34801561058a57600080fd5b506102e46110dd565b34801561059f57600080fd5b506103736105ae366004612776565b6110ea565b3480156105bf57600080fd5b506102cd61112e565b3480156105d457600080fd5b50610373611179565b3480156105e957600080fd5b5061032661117f565b3480156105fe57600080fd5b506102cd61118e565b34801561061357600080fd5b50610297610622366004612912565b6112fe565b34801561063357600080fd5b506102cd610642366004612936565b611329565b34801561065357600080fd5b506102e461137b565b34801561066857600080fd5b5061037361138a565b34801561067d57600080fd5b506102cd611390565b34801561069257600080fd5b5061037361144e565b3480156106a757600080fd5b506102cd6106b6366004612886565b611453565b3480156106c757600080fd5b506102cd611465565b3480156106dc57600080fd5b506102cd6106eb36600461280a565b6114de565b3480156106fc57600080fd5b506102cd61070b3660046129ab565b611517565b34801561071c57600080fd5b506102e461072b3660046128fa565b611584565b34801561073c57600080fd5b506103266116ac565b34801561075157600080fd5b506102e46116bb565b34801561076657600080fd5b506103736116c8565b34801561077b57600080fd5b506102cd61078a366004612912565b6116da565b34801561079b57600080fd5b506102976107aa366004612792565b6116f9565b3480156107bb57600080fd5b506103736107ca3660046128fa565b6117ad565b3480156107db57600080fd5b506102cd6107ea366004612776565b6117ce565b60006001600160e01b031982166380ac58cd60e01b148061082057506001600160e01b03198216635b5e139f60e01b145b8061083b57506001600160e01b03198216637965db0b60e01b145b8061084a575061084a8261183c565b90505b919050565b61085a61187c565b6001600160a01b031661086b61117f565b6001600160a01b03161461089a5760405162461bcd60e51b815260040161089190613159565b60405180910390fd5b600e5460ff166108bc5760405162461bcd60e51b815260040161089190613087565b6108c8600a8383612546565b505050565b6060600280546108dc90613411565b80601f016020809104026020016040519081016040528092919081815260200182805461090890613411565b80156109555780601f1061092a57610100808354040283529160200191610955565b820191906000526020600020905b81548152906001019060200180831161093857829003601f168201915b5050505050905090565b600a805461096c90613411565b80601f016020809104026020016040519081016040528092919081815260200182805461099890613411565b80156109e55780601f106109ba576101008083540402835291602001916109e5565b820191906000526020600020905b8154815290600101906020018083116109c857829003601f168201915b505050505081565b60006109f882611880565b610a145760405162461bcd60e51b81526004016108919061310d565b506000908152600660205260409020546001600160a01b031690565b6000610a3b8261105d565b9050806001600160a01b0316836001600160a01b03161415610a6f5760405162461bcd60e51b81526004016108919061320e565b806001600160a01b0316610a8161187c565b6001600160a01b03161480610a9d5750610a9d816107aa61187c565b610ab95760405162461bcd60e51b815260040161089190612f9c565b6108c8838361189d565b60166020526000908152604090205481565b610add61187c565b6001600160a01b0316610aee61117f565b6001600160a01b031614610b145760405162461bcd60e51b815260040161089190613159565b600e5460ff16610b365760405162461bcd60e51b815260040161089190613087565b6108c8600d8383612546565b60105490565b610b59610b5361187c565b8261190b565b610b755760405162461bcd60e51b81526004016108919061324f565b6108c8838383611988565b60009081526020819052604090206001015490565b6000805160206134f783398151915281565b600080516020613517833981519152610bc781610bc261187c565b611aa3565b60005b83811015610c8057610bde83600f54611b07565b600f5460145433424340604051602001610bfc959493929190613334565b60408051601f198184030181528282528051602091820120600f8054600090815260169093529290912055547f30385c845b448a36257a6a1716e6ad2e1bc2cbe333cde1e69fe849ad6511adfe91610c55918691612ca5565b60405180910390a1600f54610c6b906001611b21565b600f5580610c788161344c565b915050610bca565b50505050565b610c8f82610b80565b610c9b81610bc261187c565b6108c88383611b34565b610cad61187c565b6001600160a01b0316816001600160a01b031614610cdd5760405162461bcd60e51b8152600401610891906132ce565b610ce78282611bb9565b5050565b60118181548110610cfb57600080fd5b90600052602060002001600091509050805461096c90613411565b6108c8838383604051806020016040528060008152506114de565b6000805160206134f7833981519152610d4c81610bc261187c565b610ce782611c3c565b6000610d5f61187c565b6001600160a01b0316610d7061117f565b6001600160a01b031614610d965760405162461bcd60e51b815260040161089190613159565b600e5460ff16610db85760405162461bcd60e51b815260040161089190613087565b6013546040516370a0823160e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190610e07903090600401612c54565b60206040518083038186803b158015610e1f57600080fd5b505afa158015610e33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e579190612a49565b1015610e755760405162461bcd60e51b8152600401610891906130af565b6000610e85601254601354611cd1565b90507f0a2d241dbb61e3eff8f8c6dd39c403577e294dd102fe1b2880ede8145656b1f681604051610eb69190612cf9565b60405180910390a1905090565b610ecb61187c565b6001600160a01b0316610edc61117f565b6001600160a01b031614610f025760405162461bcd60e51b815260040161089190613159565b60105415610f635760108054839190610f1d906001906133b7565b81548110610f3b57634e487b7160e01b600052603260045260246000fd5b906000526020600020015410610f635760405162461bcd60e51b815260040161089190612ee0565b6010805460018181019092557f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6720183905560118054918201815560005281516108c8917f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c68019060208401906125ca565b600c805461096c90613411565b610fe861187c565b6001600160a01b0316610ff961117f565b6001600160a01b03161461101f5760405162461bcd60e51b815260040161089190613159565b600e5460ff166110415760405162461bcd60e51b815260040161089190613087565b8051610ce790600b9060208401906125ca565b600e5460ff1681565b6000818152600460205260408120546001600160a01b03168061084a5760405162461bcd60e51b81526004016108919061303e565b61109a61187c565b6001600160a01b03166110ab61117f565b6001600160a01b0316146110d15760405162461bcd60e51b815260040161089190613159565b600e805460ff19169055565b600d805461096c90613411565b60006001600160a01b0382166111125760405162461bcd60e51b815260040161089190612ff4565b506001600160a01b031660009081526005602052604090205490565b61113661187c565b6001600160a01b031661114761117f565b6001600160a01b03161461116d5760405162461bcd60e51b815260040161089190613159565b6111776000611e0c565b565b600f5481565b6001546001600160a01b031690565b61119661187c565b6001600160a01b03166111a761117f565b6001600160a01b0316146111cd5760405162461bcd60e51b815260040161089190613159565b6040516370a0823160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb90339083906370a0823190611223903090600401612c54565b60206040518083038186803b15801561123b57600080fd5b505afa15801561124f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112739190612a49565b6040518363ffffffff1660e01b8152600401611290929190612ca5565b602060405180830381600087803b1580156112aa57600080fd5b505af11580156112be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e291906128de565b6111775760405162461bcd60e51b8152600401610891906132a0565b6000828152602081815260408083206001600160a01b038516845290915290205460ff165b92915050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146113715760405162461bcd60e51b8152600401610891906131d7565b610ce78282611e5e565b6060600380546108dc90613411565b60145481565b61139861187c565b6001600160a01b03166113a961117f565b6001600160a01b0316146113cf5760405162461bcd60e51b815260040161089190613159565b6000336001600160a01b0316476040516113e890612be2565b60006040518083038185875af1925050503d8060008114611425576040519150601f19603f3d011682016040523d82523d6000602084013e61142a565b606091505b505090508061144b5760405162461bcd60e51b815260040161089190612f6f565b50565b600081565b610ce761145e61187c565b8383611e9f565b61146d61187c565b6001600160a01b031661147e61117f565b6001600160a01b0316146114a45760405162461bcd60e51b815260040161089190613159565b600e5460ff166114c65760405162461bcd60e51b815260040161089190613087565b6114d26010600061263e565b6111776011600061265c565b6114ef6114e961187c565b8361190b565b61150b5760405162461bcd60e51b81526004016108919061324f565b610c8084848484611f42565b61151f61187c565b6001600160a01b031661153061117f565b6001600160a01b0316146115565760405162461bcd60e51b815260040161089190613159565b600e5460ff166115785760405162461bcd60e51b815260040161089190613087565b6108c8600c8383612546565b606061158f82611880565b6115ab5760405162461bcd60e51b815260040161089190612d39565b60008060005b60105481101561160c57601081815481106115dc57634e487b7160e01b600052603260045260246000fd5b90600052602060002001548510156115fa578092506001915061160c565b806116048161344c565b9150506115b1565b508061164c5761161a611f75565b61162385611f84565b604051602001611634929190612b77565b6040516020818303038152906040529250505061084d565b600d6011838154811061166f57634e487b7160e01b600052603260045260246000fd5b9060005260206000200161168286611f84565b60405160200161169493929190612ba6565b60405160208183030381529060405292505050919050565b6009546001600160a01b031681565b600b805461096c90613411565b60008051602061351783398151915281565b6116e382610b80565b6116ef81610bc261187c565b6108c88383611bb9565b60095460405163c455279160e01b81526000916001600160a01b039081169190841690829063c455279190611732908890600401612c54565b60206040518083038186803b15801561174a57600080fd5b505afa15801561175e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611782919061298f565b6001600160a01b0316141561179b576001915050611323565b6117a5848461209e565b949350505050565b601081815481106117bd57600080fd5b600091825260209091200154905081565b6117d661187c565b6001600160a01b03166117e761117f565b6001600160a01b03161461180d5760405162461bcd60e51b815260040161089190613159565b6001600160a01b0381166118335760405162461bcd60e51b815260040161089190612ded565b61144b81611e0c565b60006001600160e01b031982166380ac58cd60e01b148061186d57506001600160e01b03198216635b5e139f60e01b145b8061084a575061084a826120cc565b3390565b6000908152600460205260409020546001600160a01b0316151590565b600081815260066020526040902080546001600160a01b0319166001600160a01b03841690811790915581906118d28261105d565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061191682611880565b6119325760405162461bcd60e51b815260040161089190612f23565b600061193d8361105d565b9050806001600160a01b0316846001600160a01b031614806119785750836001600160a01b031661196d846109ed565b6001600160a01b0316145b806117a557506117a581856116f9565b826001600160a01b031661199b8261105d565b6001600160a01b0316146119c15760405162461bcd60e51b81526004016108919061318e565b6001600160a01b0382166119e75760405162461bcd60e51b815260040161089190612e69565b6119f28383836108c8565b6119fd60008261189d565b6001600160a01b0383166000908152600560205260408120805460019290611a269084906133b7565b90915550506001600160a01b0382166000908152600560205260408120805460019290611a5490849061336c565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b03868116918217909255915184939187169160008051602061353783398151915291a4505050565b611aad82826112fe565b610ce757611ac5816001600160a01b031660146120f1565b611ad08360206120f1565b604051602001611ae1929190612be5565b60408051601f198184030181529082905262461bcd60e51b825261089191600401612d26565b610ce78282604051806020016040528060008152506122a2565b6000611b2d828461336c565b9392505050565b611b3e82826112fe565b610ce7576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055611b7561187c565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b611bc382826112fe565b15610ce7576000828152602081815260408083206001600160a01b03851684529091529020805460ff19169055611bf861187c565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b6000611c478261105d565b9050611c55816000846108c8565b611c6060008361189d565b6001600160a01b0381166000908152600560205260408120805460019290611c899084906133b7565b909155505060008281526004602052604080822080546001600160a01b0319169055518391906001600160a01b03841690600080516020613537833981519152908390a45050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634000aea07f000000000000000000000000000000000000000000000000000000000000000084866000604051602001611d38929190612b69565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401611d6593929190612cbe565b602060405180830381600087803b158015611d7f57600080fd5b505af1158015611d93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db791906128de565b50600083815260086020526040812054611dd6908590839030906122d5565b600085815260086020526040902054909150611df390600161336c565b6000858152600860205260409020556117a5848261230f565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60148190556040517f201bfd6a460f81d26c819af2ca157f01e3c82f32d4d322fa1715cb4a394203c590611e93908490612cf9565b60405180910390a15050565b816001600160a01b0316836001600160a01b03161415611ed15760405162461bcd60e51b815260040161089190612ead565b6001600160a01b0383811660008181526007602090815260408083209487168084529490915290819020805460ff1916851515179055517f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3190611f35908590612cee565b60405180910390a3505050565b611f4d848484611988565b611f5984848484612342565b610c805760405162461bcd60e51b815260040161089190612d9b565b6060600b80546108dc90613411565b606081611fa957506040805180820190915260018152600360fc1b602082015261084d565b8160005b8115611fd35780611fbd8161344c565b9150611fcc9050600a83613384565b9150611fad565b6000816001600160401b03811115611ffb57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015612025576020820181803683370190505b5090505b84156117a55761203a6001836133b7565b9150612047600a86613467565b61205290603061336c565b60f81b81838151811061207557634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350612097600a86613384565b9450612029565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b60006001600160e01b03198216637965db0b60e01b148061084a575061084a8261245a565b60606000612100836002613398565b61210b90600261336c565b6001600160401b0381111561213057634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561215a576020820181803683370190505b509050600360fc1b8160008151811061218357634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106121c057634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060006121e4846002613398565b6121ef90600161336c565b90505b6001811115612283576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061223157634e487b7160e01b600052603260045260246000fd5b1a60f81b82828151811061225557634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c9361227c816133fa565b90506121f2565b508315611b2d5760405162461bcd60e51b815260040161089190612d66565b6122ac8383612473565b6122b96000848484612342565b6108c85760405162461bcd60e51b815260040161089190612d9b565b6000848484846040516020016122ee9493929190612d02565b60408051601f19818403018152919052805160209091012095945050505050565b60008282604051602001612324929190612b69565b60405160208183030381529060405280519060200120905092915050565b6000612356846001600160a01b0316612540565b1561245257836001600160a01b031663150b7a0261237261187c565b8786866040518563ffffffff1660e01b81526004016123949493929190612c68565b602060405180830381600087803b1580156123ae57600080fd5b505af19250505080156123de575060408051601f3d908101601f191682019092526123db91810190612973565b60015b612438573d80801561240c576040519150601f19603f3d011682016040523d82523d6000602084013e612411565b606091505b5080516124305760405162461bcd60e51b815260040161089190612d9b565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506117a5565b5060016117a5565b6001600160e01b031981166301ffc9a760e01b14919050565b6001600160a01b0382166124995760405162461bcd60e51b8152600401610891906130d8565b6124a281611880565b156124bf5760405162461bcd60e51b815260040161089190612e33565b6124cb600083836108c8565b6001600160a01b03821660009081526005602052604081208054600192906124f490849061336c565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b0386169081179091559051839290600080516020613537833981519152908290a45050565b3b151590565b82805461255290613411565b90600052602060002090601f01602090048101928261257457600085556125ba565b82601f1061258d5782800160ff198235161785556125ba565b828001600101855582156125ba579182015b828111156125ba57823582559160200191906001019061259f565b506125c692915061267a565b5090565b8280546125d690613411565b90600052602060002090601f0160209004810192826125f857600085556125ba565b82601f1061261157805160ff19168380011785556125ba565b828001600101855582156125ba579182015b828111156125ba578251825591602001919060010190612623565b508054600082559060005260206000209081019061144b919061267a565b508054600082559060005260206000209081019061144b919061268f565b5b808211156125c6576000815560010161267b565b808211156125c65760006126a382826126ac565b5060010161268f565b5080546126b890613411565b6000825580601f106126ca575061144b565b601f01602090049060005260206000209081019061144b919061267a565b60006001600160401b0380841115612702576127026134a7565b604051601f8501601f191681016020018281118282101715612726576127266134a7565b60405284815291508183850186101561273e57600080fd5b8484602083013760006020868301015250509392505050565b600082601f830112612767578081fd5b611b2d838335602085016126e8565b600060208284031215612787578081fd5b8135611b2d816134bd565b600080604083850312156127a4578081fd5b82356127af816134bd565b915060208301356127bf816134bd565b809150509250929050565b6000806000606084860312156127de578081fd5b83356127e9816134bd565b925060208401356127f9816134bd565b929592945050506040919091013590565b6000806000806080858703121561281f578081fd5b843561282a816134bd565b9350602085013561283a816134bd565b92506040850135915060608501356001600160401b0381111561285b578182fd5b8501601f8101871361286b578182fd5b61287a878235602084016126e8565b91505092959194509250565b60008060408385031215612898578182fd5b82356128a3816134bd565b915060208301356127bf816134d2565b600080604083850312156128c5578182fd5b82356128d0816134bd565b946020939093013593505050565b6000602082840312156128ef578081fd5b8151611b2d816134d2565b60006020828403121561290b578081fd5b5035919050565b60008060408385031215612924578182fd5b8235915060208301356127bf816134bd565b60008060408385031215612948578182fd5b50508035926020909101359150565b600060208284031215612968578081fd5b8135611b2d816134e0565b600060208284031215612984578081fd5b8151611b2d816134e0565b6000602082840312156129a0578081fd5b8151611b2d816134bd565b600080602083850312156129bd578182fd5b82356001600160401b03808211156129d3578384fd5b818501915085601f8301126129e6578384fd5b8135818111156129f4578485fd5b866020828501011115612a05578485fd5b60209290920196919550909350505050565b600060208284031215612a28578081fd5b81356001600160401b03811115612a3d578182fd5b6117a584828501612757565b600060208284031215612a5a578081fd5b5051919050565b60008060408385031215612a73578182fd5b8235915060208301356001600160401b03811115612a8f578182fd5b612a9b85828601612757565b9150509250929050565b60008151808452612abd8160208601602086016133ce565b601f01601f19169290920160200192915050565b805460009060028104600180831680612aeb57607f831692505b6020808410821415612b0b57634e487b7160e01b86526022600452602486fd5b818015612b1f5760018114612b3057612b5d565b60ff19861689528489019650612b5d565b612b3988613360565b60005b86811015612b555781548b820152908501908301612b3c565b505084890196505b50505050505092915050565b918252602082015260400190565b60008351612b898184602088016133ce565b835190830190612b9d8183602088016133ce565b01949350505050565b6000612bbb612bb58387612ad1565b85612ad1565b602f60f81b81528351612bd58160018401602088016133ce565b0160010195945050505050565b90565b600076020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b82528351612c178160178501602088016133ce565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351612c488160288401602088016133ce565b01602801949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612c9b90830184612aa5565b9695505050505050565b6001600160a01b03929092168252602082015260400190565b600060018060a01b038516825283602083015260606040830152612ce56060830184612aa5565b95945050505050565b901515815260200190565b90815260200190565b93845260208401929092526001600160a01b03166040830152606082015260800190565b600060208252611b2d6020830184612aa5565b6020808252601390820152721513d2d153881113d154d389d50811561254d5606a1b604082015260600190565b6020808252818101527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604082015260600190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601c908201527b115490cdcc8c4e881d1bdad95b88185b1c9958591e481b5a5b9d195960221b604082015260600190565b60208082526024908201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526019908201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b604082015260600190565b60208082526023908201527f42415443482049442053484f554c44204558434545442050524556494f5553206040820152624f4e4560e81b606082015260800190565b6020808252602c908201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b60208082526013908201527211551208151c985b9cd9995c8819985a5b1959606a1b604082015260600190565b60208082526038908201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776040820152771b995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b60421b606082015260800190565b6020808252602a908201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604082015269726f206164647265737360b01b606082015260800190565b60208082526029908201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460408201526832b73a103a37b5b2b760b91b606082015260800190565b6020808252600e908201526d4e4f54204d4f4449464941424c4560901b604082015260600190565b6020808252600f908201526e4e4f5420454e4f554748204c494e4b60881b604082015260600190565b6020808252818101527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604082015260600190565b6020808252602c908201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960408201526839903737ba1037bbb760b91b606082015260800190565b6020808252601f908201527f4f6e6c7920565246436f6f7264696e61746f722063616e2066756c66696c6c00604082015260600190565b60208082526021908201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656040820152603960f91b606082015260800190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b60208082526014908201527313125392c8151c985b9cd9995c8819985a5b195960621b604082015260600190565b6020808252602f908201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560408201526e103937b632b9903337b91039b2b63360891b606082015260800190565b9182526001600160a01b0316602082015260400190565b94855260208501939093526001600160a01b039190911660408401526060830152608082015260a00190565b60009081526020902090565b6000821982111561337f5761337f61347b565b500190565b60008261339357613393613491565b500490565b60008160001904831182151516156133b2576133b261347b565b500290565b6000828210156133c9576133c961347b565b500390565b60005b838110156133e95781810151838201526020016133d1565b83811115610c805750506000910152565b6000816134095761340961347b565b506000190190565b60028104600182168061342557607f821691505b6020821081141561344657634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156134605761346061347b565b5060010190565b60008261347657613476613491565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461144b57600080fd5b801515811461144b57600080fd5b6001600160e01b03198116811461144b57600080fdfe3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a8489f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220c420e3c344454a68d64da6eaabb0a3c9902d7cdcf884ca7519271eec4d79548164736f6c6343000800003366756e6374696f6e206d656368616e697a65644162737472616374696f6e52656e64657265722865297b6c65745b742c6f5d3d66756e6374696f6e2865297b636f6e737420743d7061727365496e7428652e736c69636528302c4d6174682e666c6f6f7228652e6c656e6774682f3229292925316531302c6f3d7061727365496e7428652e736c696365284d6174682e666c6f6f7228652e6c656e6774682f32292c652e6c656e677468292925316531303b72657475726e5b742c6f5d7d2865293b766172206c2c6e2c722c612c462c642c692c732c762c442c412c683d36302c453d3235352c423d7b7d3b6c657420623d7b7d2c633d7b274d69642d63656e74757279273a7b763a5b2723463142363830272c2723453938333535272c2723443234323237272c2723323734323734272c2723343738374138272c2723383942364142272c2723384141414132275d2c773a372c62626c3a5b2723443234323237272c2723463142363830272c2723453938333535275d7d2c556e7061636b65643a7b763a5b2723303030303042272c2723383746384446272c2723444534333338272c2723463443304439272c2723324533344335272c2723453745393644275d2c773a372c62626c3a5b5d7d2c426f61726477616c6b3a7b763a5b2723423845324433272c2723354239414635272c2723464432423733272c2723464538323333272c2723443430433043272c2723464643413335272c2723314637333430272c2723303334334331272c2723363630393345275d2c773a332c62626c3a5b2723354239414635272c2723464538323333272c2723443430433043272c2723464643413335272c2723314637333430272c2723303334334331272c2723363630393345275d7d2c27506f7021273a7b763a5b2723453731343746272c2723313739414544272c2723324332413837272c2723463445463139272c2723374134413935272c2723394444333430272c2723444331333241275d2c773a362c62626c3a5b2723444331333241272c2723275d7d2c53756e62757273743a7b763a5b2723313433363432272c2723656339613239272c2723306638623864272c2723646164326438275d2c773a332c62626c3a5b5d7d2c457468657265616c3a7b763a5b2723303342383741272c2723363133394430272c2723363041304634272c2723464644453341272c2723463446434646272c2723324132463444272c2723463643314646275d2c773a372c62626c3a5b2723464644453341272c2723463643314646275d7d2c436f72616c3a7b763a5b2723464638413731272c2723444238324138272c2723353542434635272c2723374344334335272c2723303234364339272c2723464642414142275d2c773a352c62626c3a5b5d7d2c50617261646973653a7b763a5b2723464439363732272c2723464141333446272c2723364241434235272c2723334637303838272c2723454443314245275d2c773a342c62626c3a5b2723464439363732272c2723464141333446275d7d2c27556c74726120526564273a7b763a5b2723333133423432272c2723464645454534272c2723453534463244272c2723464437413645272c2723464642444237275d2c773a342c62626c3a5b2723453534463244272c27275d7d2c274f6365616e20426c756573273a7b763a5b2723333037334144272c2723373842304532272c2723394343324533272c2723443945444646272c2723303738384439275d2c773a322c62626c3a5b2723443934463330275d7d2c447265616d73636170653a7b763a5b2723453043454641272c2723383841304534272c2723353939314646272c2723464641373934272c2723464638323832272c2723423946444444275d2c773a352c62626c3a5b2723464641373934272c2723464638323832275d7d2c426c6f73736f6d3a7b763a5b2723324137363442272c2723353541353738272c2723463546354439272c2723464643344232272c2723444339333443275d2c773a332c62626c3a5b27272c27272c27275d7d2c4d797374697175653a7b763a5b2723413537414646272c2723433446353030272c2723303343434246272c2723383046464434272c2723303341304646272c2723303436394136272c2723333033333741275d2c773a352c62626c3a5b2723303341304646272c2723433446353030275d7d2c4e6175746963616c3a7b763a5b2723464143393938272c2723454239433434272c2723443934393241272c2723413132343235272c2723333437443935275d2c773a342c62626c3a5b2723443934393241272c2723454239433434275d7d2c526574726f3a7b763a5b2723463445453937272c2723463944373444272c2723454339453433272c2723453236393343272c2723344136303736275d2c773a322c62626c3a5b2723272c2723275d7d2c274f646520746f2056616e20476f6768273a7b763a5b2723324134313834272c2723354138374332272c2723393443304432272c2723454645393836272c2723314232343234275d2c773a332c62626c3a5b2723454645393836275d7d2c274f646520746f204d6f6e647269616e273a7b763a5b2723443242413439272c2723423742384232272c2723313433363735272c2723394532463241272c2723444444444439275d2c773a332c62626c3a5b2723394532463241272c2723313433363735275d7d2c274f646520746f204d6f6e6574273a7b763a5b2723433443374241272c2723333434313437272c2723364138393933272c2723443436453630272c2723443138443734275d2c773a332c62626c3a5b2723443436453630275d7d2c274d69646e6967687420426c7565273a7b763a5b2723303030343231272c2723314243354432275d2c773a322c62626c3a5b2723314243354432275d7d2c4d6f6e6f6368726f6d653a7b763a5b2723463045464546272c2723333733373337275d2c773a327d2c50756e6b61626c653a7b763a5b2723364339314136272c2723443737323437272c2723434245444543272c2723464646304235272c2723333133313331272c2723394243393839272c2723424542454245275d2c773a332c62626c3a5b2723443737323437275d7d2c41706561626c653a7b763a5b2723394139423642272c2723423943424443272c2723463342343638272c2723333936373835272c2723373444344234272c2723393937394130272c2723463246323943275d2c773a332c62626c3a5b2723454430343146275d7d7d2c773d7b536f6c69643a7b763a27736f6c6964272c773a38307d2c5472616e736c7563656e743a7b763a277472616e736c7563656e74272c773a32307d7d2c6d3d7b4c6f773a7b763a7b6d65616e3a31352c7374643a352c666c6f6f723a32307d2c773a36307d2c4d656469756d3a7b763a7b6d65616e3a33302c7374643a352c666c6f6f723a32307d2c773a32307d2c486967683a7b763a7b6d65616e3a34302c7374643a352c666c6f6f723a32307d2c773a31307d7d2c433d7b4e6f6e653a7b763a302c773a38397d2c546869636b3a7b763a312e352c773a31307d2c5468696e3a7b763a312c773a317d7d2c753d7b57686974653a7b763a2772676261283235352c3235352c3235352c2e3829272c773a317d2c426c61636b3a7b763a277267626128302c302c302c2e3629272c773a317d7d2c663d7b53686f72743a7b763a7b6d65616e3a3230302c7374643a3135307d2c773a317d2c4e6f726d616c3a7b763a7b6d65616e3a3430302c7374643a3330307d2c773a317d2c4c6f6e673a7b763a7b6d65616e3a313530302c7374643a3235307d2c773a317d7d2c673d7b5468696e3a7b763a7b6d65616e3a332c7374643a2e317d2c773a32357d2c4e6f726d616c3a7b763a7b6d65616e3a31302c7374643a357d2c773a36307d2c546869636b3a7b763a7b6d65616e3a32302c7374643a357d2c773a31357d7d2c703d7b4e6f726d616c3a7b763a32652d342c773a38357d2c53747261696768743a7b763a31652d362c773a31357d7d2c6b3d7b4e6f726d616c3a7b763a7b6d65616e3a323565332c7374643a323565337d2c773a317d2c4e6f6e653a7b763a7b6d65616e3a302c7374643a307d2c773a317d7d2c4d3d7b274e6f20426f72646572273a7b763a2d32352c773a38357d2c426f726465723a7b763a33352c773a31357d7d3b76617220533d66756e6374696f6e28652c74297b766172206f3d4f626a6563742e6b6579732865292c6c3d5b5d3b666f72286c657420743d303b743c6f2e6c656e6774683b742b2b297b6c6574206e3d655b6f5b745d5d2e773b666f72286c657420653d303b653c6e3b652b2b296c2e70757368286f5b745d297d72657475726e206c5b742e666c6f6f7228742e72616e646f6d28292a6c2e6c656e677468295d7d3b66756e6374696f6e207928652c742c6f2c6c297b6c6574206e3d652e72616e646f6d476175737369616e28322c3130293b76617220723d5b5d2c613d5b5d3b666f722876617220463d303b463c31333b462b2b297b6c6574206c3d6e2b652e72616e646f6d282d6e2f33352c6e2f3335293b725b465d3d742b6c2a652e636f73283336302a462f3133292c615b465d3d6f2b6c2a652e73696e283336302a462f3133297d652e626567696e536861706528293b666f72286c657420743d303b743c722e6c656e6774683b742b2b29652e637572766556657274657828725b745d2c615b745d293b652e656e64536861706528652e434c4f5345297d66756e6374696f6e207828652c742c6f297b6c6574206c3d6f2e72616e646f6d476175737369616e28442c3130293b72657475726e20653c6c7c7c653e6f2e77696474682d6c7c7c743c6c7c7c743e6f2e6865696768742d6c7d66756e6374696f6e204e28652c742c6f297b6c6574206c3d652e72616e646f6d476175737369616e28692e6d65616e2c692e737464292c6e3d652e72616e646f6d476175737369616e28732e6d65616e2c732e737464293b76617220723d5b5d2c463d5b5d3b722e707573682874293b666f72286c657420743d303b743c6c3b742b2b297b6c6574206f3d652e637265617465566563746f7228725b745d2e782b6e2c725b745d2e792b6e293b6966287828725b745d2e782b6e2c725b745d2e792b6e2c6529292d2d742c2d2d6c3b656c73657b462e70757368286f293b76617220763d652e6d617028652e6e6f69736528725b745d2e782a642c725b745d2e792a64292c302c312c302c373230293b6966287828725b745d2e782b652e636f732876292c725b745d2e792b652e73696e2876292c6529292d2d742c2d2d6c3b656c73657b76617220443d652e637265617465566563746f7228725b745d2e782b652e636f732876292c725b745d2e792b652e73696e287629293b722e707573682844297d7d7d666f7228652e626567696e536861706528292c743d303b743c722e6c656e6774683b742b2b297b6c6574206f3d725b745d3b652e766572746578286f2e782c6f2e79297d666f7228743d462e6c656e6774682d313b743e3d303b742d2d297b6c6574206f3d465b745d3b652e766572746578286f2e782c6f2e79297d652e656e64536861706528292c652e7374726f6b652861293b6c657420413d652e636f6c6f72286f293b412e736574416c7068612845292c652e66696c6c2841297d72657475726e7b72656e64657265723a653d3e7b652e73657475703d66756e6374696f6e28297b652e72616e646f6d536565642874292c652e6e6f69736553656564286f293b6c657420783d652e63726561746543616e76617328313530302c353030293b76617220473b666f7228652e616e676c654d6f646528652e44454752454553292c66756e6374696f6e2865297b422e72616e646f6d536565643d742c422e6e6f697365536565643d6f3b6c657420763d5328772c65293b425b2766696c6c2074797065275d3d762c277472616e736c7563656e74273d3d775b765d2e7626262864656c65746520632e4d6f6e6f6368726f6d652c64656c65746520635b274d69646e6967687420426c7565275d2c64656c65746520432e546869636b2c64656c657465206d2e4c6f772c64656c657465206d2e4d656469756d2c683d38302c453d323030293b6c657420623d53284d2c65293b422e626f726465725374796c653d622c28443d4d5b625d2e76293e3026262864656c657465206d2e4c6f772c64656c657465206d2e4d656469756d293b6c657420793d53286d2c65293b422e64656e736974793d792c463d6d5b795d2e763b6c657420783d5328632c65293b422e636f6c6f72733d782c6c3d635b785d2e762c6e3d635b785d2e62626c2c274d69646e6967687420426c7565273d3d7826262864656c65746520752e426c61636b2c64656c65746520432e4e6f6e652c64656c65746520432e546869636b292c274d6f6e6f6368726f6d65273d3d7826262864656c65746520752e57686974652c64656c65746520432e4e6f6e652c64656c65746520432e546869636b293b6c6574204e3d5328432c65293b422e7374726f6b65546869636b6e6573733d4e2c723d435b4e5d2e763b6c657420473d5328752c65293b422e7374726f6b65436f6c6f723d472c613d755b475d2e763b6c657420543d5328662c65293b422e63757276654c656e6774683d542c693d665b545d2e763b6c6574204c3d5328672c65293b422e637572766557696474683d4c2c733d675b4c5d2e763b6c6574204f3d5328702c65293b422e6375727665526174653d4f2c643d705b4f5d2e763b6c657420523d53286b2c65293b422e7465787475726544656e736974793d522c413d6b5b525d2e767d2865293b6e756c6c3d3d473b297b6c657420743d6c5b652e666c6f6f7228652e72616e646f6d28292a6c2e6c656e677468295d3b6e756c6c213d6e26266e2e696e636c756465732874297c7c28473d74297d652e6261636b67726f756e642847292c6c3d6c2e66696c74657228653d3e65213d47292c652e7374726f6b655765696768742872293b6c657420543d652e666c6f6f7228652e6d617828652e72616e646f6d476175737369616e28462e6d65616e2c462e737464292c462e666c6f6f7229293b666f7228766172204c3d652e77696474682f542c4f3d443b4f3c652e77696474682d443b4f2b3d4c29666f722876617220523d443b523c652e6865696768742d443b522b3d4c29696628652e666c6f6f72283130302a652e72616e646f6d2829293c3d68297b76617220553d652e637265617465566563746f72284f2b652e72616e646f6d282d31302c3130292c522b652e72616e646f6d282d31302c313029293b4e28652c552c6c5b652e666c6f6f7228652e72616e646f6d28292a6c2e6c656e677468295d297d656c736520652e72616e646f6d28292c652e77696474682c652e72616e646f6d28292c652e6865696768742c7928652c4f2b652e72616e646f6d476175737369616e2832302c3230292c522b652e72616e646f6d2832302c3230292c6c5b652e666c6f6f7228652e72616e646f6d28292a6c2e6c656e677468295d293b763d652e72616e646f6d476175737369616e28412e6d65616e2c412e737464292c66756e6374696f6e28652c74297b6c6574206f3d652e666c6f6f7228652e72616e646f6d2835302c393029292c6c3d652e636f6c6f722832302c32302c32302c6f293b652e6e6f5374726f6b6528292c652e66696c6c286c293b666f72286c6574206f3d303b6f3c743b6f2b2b297b6c657420743d652e72616e646f6d28292a652e77696474682c6f3d652e72616e646f6d28292a652e6865696768742c6c3d652e72616e646f6d28302c312e35293b652e656c6c6970736528742c6f2c6c297d7d28652c76292c622e6461746155726c3d782e63616e7661732e746f4461746155524c28297d2c652e647261773d66756e6374696f6e28297b652e6e6f4c6f6f7028297d7d2c70726f706572746965733a422c6461746155726c3a627d7d00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c10000000000000000000000000000000000000000000000000000000000000180000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb7952000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca0000000000000000000000000000000000000000000000001bc16d674ec80000aa77729d3466ca35ae8d28b3bbac7cc36a5031efdc430821c02bc31a238af44500000000000000000000000000000000000000000000000000000000000000174d656368616e697a6564204162737472616374696f6e7300000000000000000000000000000000000000000000000000000000000000000000000000000000024d41000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002b684265496f56715473705a416e62347a4a62794e464454304b524433646c52336967467843314d65554841000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106102325760003560e01c806301ffc9a71461027757806304da5304146102ad57806306fdde03146102cf57806307ba3196146102f1578063081812fc14610306578063095ea7b31461033357806314d53c25146103535780631c8a173914610380578063231871d6146103a057806323b872dd146103b5578063248a9ca3146103d5578063282c51f3146103f55780632d2b26ee1461040a5780632f2ff15d1461042a57806336568abe1461044a578063374145ce1461046a57806342842e0e1461048a57806342966c68146104aa5780634417d216146104ca5780634f638a40146104df578063506eb3f8146104ff57806355f804b3146105145780635b2906d0146105345780636352211e146105495780636602529214610569578063684297de1461057e57806370a0823114610593578063715018a6146105b357806375794a3c146105c85780638da5cb5b146105dd5780638dc654a2146105f257806391d148541461060757806394985ddd1461062757806395d89b41146106475780639e8ed6f71461065c578063a0ef91df14610671578063a217fddf14610686578063a22cb4651461069b578063b07fe3a1146106bb578063b88d4fde146106d0578063c8321c78146106f0578063c87b56dd14610710578063cd7c032614610730578063cf76a15314610745578063d53913931461075a578063d547741f1461076f578063e985e9c51461078f578063f2bfb811146107af578063f2fde38b146107cf57610272565b36610272577ffc0190751e68e3a764092e8161dc292f90c0e10e38ddf16a6b42670667bcac47343360405161026892919061331d565b60405180910390a1005b600080fd5b34801561028357600080fd5b50610297610292366004612957565b6107ef565b6040516102a49190612cee565b60405180910390f35b3480156102b957600080fd5b506102cd6102c83660046129ab565b610852565b005b3480156102db57600080fd5b506102e46108cd565b6040516102a49190612d26565b3480156102fd57600080fd5b506102e461095f565b34801561031257600080fd5b506103266103213660046128fa565b6109ed565b6040516102a49190612c54565b34801561033f57600080fd5b506102cd61034e3660046128b3565b610a30565b34801561035f57600080fd5b5061037361036e3660046128fa565b610ac3565b6040516102a49190612cf9565b34801561038c57600080fd5b506102cd61039b3660046129ab565b610ad5565b3480156103ac57600080fd5b50610373610b42565b3480156103c157600080fd5b506102cd6103d03660046127ca565b610b48565b3480156103e157600080fd5b506103736103f03660046128fa565b610b80565b34801561040157600080fd5b50610373610b95565b34801561041657600080fd5b506102cd610425366004612912565b610ba7565b34801561043657600080fd5b506102cd610445366004612912565b610c86565b34801561045657600080fd5b506102cd610465366004612912565b610ca5565b34801561047657600080fd5b506102e46104853660046128fa565b610ceb565b34801561049657600080fd5b506102cd6104a53660046127ca565b610d16565b3480156104b657600080fd5b506102cd6104c53660046128fa565b610d31565b3480156104d657600080fd5b50610373610d55565b3480156104eb57600080fd5b506102cd6104fa366004612a61565b610ec3565b34801561050b57600080fd5b506102e4610fd3565b34801561052057600080fd5b506102cd61052f366004612a17565b610fe0565b34801561054057600080fd5b50610297611054565b34801561055557600080fd5b506103266105643660046128fa565b61105d565b34801561057557600080fd5b506102cd611092565b34801561058a57600080fd5b506102e46110dd565b34801561059f57600080fd5b506103736105ae366004612776565b6110ea565b3480156105bf57600080fd5b506102cd61112e565b3480156105d457600080fd5b50610373611179565b3480156105e957600080fd5b5061032661117f565b3480156105fe57600080fd5b506102cd61118e565b34801561061357600080fd5b50610297610622366004612912565b6112fe565b34801561063357600080fd5b506102cd610642366004612936565b611329565b34801561065357600080fd5b506102e461137b565b34801561066857600080fd5b5061037361138a565b34801561067d57600080fd5b506102cd611390565b34801561069257600080fd5b5061037361144e565b3480156106a757600080fd5b506102cd6106b6366004612886565b611453565b3480156106c757600080fd5b506102cd611465565b3480156106dc57600080fd5b506102cd6106eb36600461280a565b6114de565b3480156106fc57600080fd5b506102cd61070b3660046129ab565b611517565b34801561071c57600080fd5b506102e461072b3660046128fa565b611584565b34801561073c57600080fd5b506103266116ac565b34801561075157600080fd5b506102e46116bb565b34801561076657600080fd5b506103736116c8565b34801561077b57600080fd5b506102cd61078a366004612912565b6116da565b34801561079b57600080fd5b506102976107aa366004612792565b6116f9565b3480156107bb57600080fd5b506103736107ca3660046128fa565b6117ad565b3480156107db57600080fd5b506102cd6107ea366004612776565b6117ce565b60006001600160e01b031982166380ac58cd60e01b148061082057506001600160e01b03198216635b5e139f60e01b145b8061083b57506001600160e01b03198216637965db0b60e01b145b8061084a575061084a8261183c565b90505b919050565b61085a61187c565b6001600160a01b031661086b61117f565b6001600160a01b03161461089a5760405162461bcd60e51b815260040161089190613159565b60405180910390fd5b600e5460ff166108bc5760405162461bcd60e51b815260040161089190613087565b6108c8600a8383612546565b505050565b6060600280546108dc90613411565b80601f016020809104026020016040519081016040528092919081815260200182805461090890613411565b80156109555780601f1061092a57610100808354040283529160200191610955565b820191906000526020600020905b81548152906001019060200180831161093857829003601f168201915b5050505050905090565b600a805461096c90613411565b80601f016020809104026020016040519081016040528092919081815260200182805461099890613411565b80156109e55780601f106109ba576101008083540402835291602001916109e5565b820191906000526020600020905b8154815290600101906020018083116109c857829003601f168201915b505050505081565b60006109f882611880565b610a145760405162461bcd60e51b81526004016108919061310d565b506000908152600660205260409020546001600160a01b031690565b6000610a3b8261105d565b9050806001600160a01b0316836001600160a01b03161415610a6f5760405162461bcd60e51b81526004016108919061320e565b806001600160a01b0316610a8161187c565b6001600160a01b03161480610a9d5750610a9d816107aa61187c565b610ab95760405162461bcd60e51b815260040161089190612f9c565b6108c8838361189d565b60166020526000908152604090205481565b610add61187c565b6001600160a01b0316610aee61117f565b6001600160a01b031614610b145760405162461bcd60e51b815260040161089190613159565b600e5460ff16610b365760405162461bcd60e51b815260040161089190613087565b6108c8600d8383612546565b60105490565b610b59610b5361187c565b8261190b565b610b755760405162461bcd60e51b81526004016108919061324f565b6108c8838383611988565b60009081526020819052604090206001015490565b6000805160206134f783398151915281565b600080516020613517833981519152610bc781610bc261187c565b611aa3565b60005b83811015610c8057610bde83600f54611b07565b600f5460145433424340604051602001610bfc959493929190613334565b60408051601f198184030181528282528051602091820120600f8054600090815260169093529290912055547f30385c845b448a36257a6a1716e6ad2e1bc2cbe333cde1e69fe849ad6511adfe91610c55918691612ca5565b60405180910390a1600f54610c6b906001611b21565b600f5580610c788161344c565b915050610bca565b50505050565b610c8f82610b80565b610c9b81610bc261187c565b6108c88383611b34565b610cad61187c565b6001600160a01b0316816001600160a01b031614610cdd5760405162461bcd60e51b8152600401610891906132ce565b610ce78282611bb9565b5050565b60118181548110610cfb57600080fd5b90600052602060002001600091509050805461096c90613411565b6108c8838383604051806020016040528060008152506114de565b6000805160206134f7833981519152610d4c81610bc261187c565b610ce782611c3c565b6000610d5f61187c565b6001600160a01b0316610d7061117f565b6001600160a01b031614610d965760405162461bcd60e51b815260040161089190613159565b600e5460ff16610db85760405162461bcd60e51b815260040161089190613087565b6013546040516370a0823160e01b81526001600160a01b037f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca16906370a0823190610e07903090600401612c54565b60206040518083038186803b158015610e1f57600080fd5b505afa158015610e33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e579190612a49565b1015610e755760405162461bcd60e51b8152600401610891906130af565b6000610e85601254601354611cd1565b90507f0a2d241dbb61e3eff8f8c6dd39c403577e294dd102fe1b2880ede8145656b1f681604051610eb69190612cf9565b60405180910390a1905090565b610ecb61187c565b6001600160a01b0316610edc61117f565b6001600160a01b031614610f025760405162461bcd60e51b815260040161089190613159565b60105415610f635760108054839190610f1d906001906133b7565b81548110610f3b57634e487b7160e01b600052603260045260246000fd5b906000526020600020015410610f635760405162461bcd60e51b815260040161089190612ee0565b6010805460018181019092557f1b6847dc741a1b0cd08d278845f9d819d87b734759afb55fe2de5cb82a9ae6720183905560118054918201815560005281516108c8917f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c68019060208401906125ca565b600c805461096c90613411565b610fe861187c565b6001600160a01b0316610ff961117f565b6001600160a01b03161461101f5760405162461bcd60e51b815260040161089190613159565b600e5460ff166110415760405162461bcd60e51b815260040161089190613087565b8051610ce790600b9060208401906125ca565b600e5460ff1681565b6000818152600460205260408120546001600160a01b03168061084a5760405162461bcd60e51b81526004016108919061303e565b61109a61187c565b6001600160a01b03166110ab61117f565b6001600160a01b0316146110d15760405162461bcd60e51b815260040161089190613159565b600e805460ff19169055565b600d805461096c90613411565b60006001600160a01b0382166111125760405162461bcd60e51b815260040161089190612ff4565b506001600160a01b031660009081526005602052604090205490565b61113661187c565b6001600160a01b031661114761117f565b6001600160a01b03161461116d5760405162461bcd60e51b815260040161089190613159565b6111776000611e0c565b565b600f5481565b6001546001600160a01b031690565b61119661187c565b6001600160a01b03166111a761117f565b6001600160a01b0316146111cd5760405162461bcd60e51b815260040161089190613159565b6040516370a0823160e01b81526001600160a01b037f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca169063a9059cbb90339083906370a0823190611223903090600401612c54565b60206040518083038186803b15801561123b57600080fd5b505afa15801561124f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112739190612a49565b6040518363ffffffff1660e01b8152600401611290929190612ca5565b602060405180830381600087803b1580156112aa57600080fd5b505af11580156112be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e291906128de565b6111775760405162461bcd60e51b8152600401610891906132a0565b6000828152602081815260408083206001600160a01b038516845290915290205460ff165b92915050565b336001600160a01b037f000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb795216146113715760405162461bcd60e51b8152600401610891906131d7565b610ce78282611e5e565b6060600380546108dc90613411565b60145481565b61139861187c565b6001600160a01b03166113a961117f565b6001600160a01b0316146113cf5760405162461bcd60e51b815260040161089190613159565b6000336001600160a01b0316476040516113e890612be2565b60006040518083038185875af1925050503d8060008114611425576040519150601f19603f3d011682016040523d82523d6000602084013e61142a565b606091505b505090508061144b5760405162461bcd60e51b815260040161089190612f6f565b50565b600081565b610ce761145e61187c565b8383611e9f565b61146d61187c565b6001600160a01b031661147e61117f565b6001600160a01b0316146114a45760405162461bcd60e51b815260040161089190613159565b600e5460ff166114c65760405162461bcd60e51b815260040161089190613087565b6114d26010600061263e565b6111776011600061265c565b6114ef6114e961187c565b8361190b565b61150b5760405162461bcd60e51b81526004016108919061324f565b610c8084848484611f42565b61151f61187c565b6001600160a01b031661153061117f565b6001600160a01b0316146115565760405162461bcd60e51b815260040161089190613159565b600e5460ff166115785760405162461bcd60e51b815260040161089190613087565b6108c8600c8383612546565b606061158f82611880565b6115ab5760405162461bcd60e51b815260040161089190612d39565b60008060005b60105481101561160c57601081815481106115dc57634e487b7160e01b600052603260045260246000fd5b90600052602060002001548510156115fa578092506001915061160c565b806116048161344c565b9150506115b1565b508061164c5761161a611f75565b61162385611f84565b604051602001611634929190612b77565b6040516020818303038152906040529250505061084d565b600d6011838154811061166f57634e487b7160e01b600052603260045260246000fd5b9060005260206000200161168286611f84565b60405160200161169493929190612ba6565b60405160208183030381529060405292505050919050565b6009546001600160a01b031681565b600b805461096c90613411565b60008051602061351783398151915281565b6116e382610b80565b6116ef81610bc261187c565b6108c88383611bb9565b60095460405163c455279160e01b81526000916001600160a01b039081169190841690829063c455279190611732908890600401612c54565b60206040518083038186803b15801561174a57600080fd5b505afa15801561175e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611782919061298f565b6001600160a01b0316141561179b576001915050611323565b6117a5848461209e565b949350505050565b601081815481106117bd57600080fd5b600091825260209091200154905081565b6117d661187c565b6001600160a01b03166117e761117f565b6001600160a01b03161461180d5760405162461bcd60e51b815260040161089190613159565b6001600160a01b0381166118335760405162461bcd60e51b815260040161089190612ded565b61144b81611e0c565b60006001600160e01b031982166380ac58cd60e01b148061186d57506001600160e01b03198216635b5e139f60e01b145b8061084a575061084a826120cc565b3390565b6000908152600460205260409020546001600160a01b0316151590565b600081815260066020526040902080546001600160a01b0319166001600160a01b03841690811790915581906118d28261105d565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061191682611880565b6119325760405162461bcd60e51b815260040161089190612f23565b600061193d8361105d565b9050806001600160a01b0316846001600160a01b031614806119785750836001600160a01b031661196d846109ed565b6001600160a01b0316145b806117a557506117a581856116f9565b826001600160a01b031661199b8261105d565b6001600160a01b0316146119c15760405162461bcd60e51b81526004016108919061318e565b6001600160a01b0382166119e75760405162461bcd60e51b815260040161089190612e69565b6119f28383836108c8565b6119fd60008261189d565b6001600160a01b0383166000908152600560205260408120805460019290611a269084906133b7565b90915550506001600160a01b0382166000908152600560205260408120805460019290611a5490849061336c565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b03868116918217909255915184939187169160008051602061353783398151915291a4505050565b611aad82826112fe565b610ce757611ac5816001600160a01b031660146120f1565b611ad08360206120f1565b604051602001611ae1929190612be5565b60408051601f198184030181529082905262461bcd60e51b825261089191600401612d26565b610ce78282604051806020016040528060008152506122a2565b6000611b2d828461336c565b9392505050565b611b3e82826112fe565b610ce7576000828152602081815260408083206001600160a01b03851684529091529020805460ff19166001179055611b7561187c565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b611bc382826112fe565b15610ce7576000828152602081815260408083206001600160a01b03851684529091529020805460ff19169055611bf861187c565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b6000611c478261105d565b9050611c55816000846108c8565b611c6060008361189d565b6001600160a01b0381166000908152600560205260408120805460019290611c899084906133b7565b909155505060008281526004602052604080822080546001600160a01b0319169055518391906001600160a01b03841690600080516020613537833981519152908390a45050565b60007f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca6001600160a01b0316634000aea07f000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb795284866000604051602001611d38929190612b69565b6040516020818303038152906040526040518463ffffffff1660e01b8152600401611d6593929190612cbe565b602060405180830381600087803b158015611d7f57600080fd5b505af1158015611d93573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611db791906128de565b50600083815260086020526040812054611dd6908590839030906122d5565b600085815260086020526040902054909150611df390600161336c565b6000858152600860205260409020556117a5848261230f565b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60148190556040517f201bfd6a460f81d26c819af2ca157f01e3c82f32d4d322fa1715cb4a394203c590611e93908490612cf9565b60405180910390a15050565b816001600160a01b0316836001600160a01b03161415611ed15760405162461bcd60e51b815260040161089190612ead565b6001600160a01b0383811660008181526007602090815260408083209487168084529490915290819020805460ff1916851515179055517f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3190611f35908590612cee565b60405180910390a3505050565b611f4d848484611988565b611f5984848484612342565b610c805760405162461bcd60e51b815260040161089190612d9b565b6060600b80546108dc90613411565b606081611fa957506040805180820190915260018152600360fc1b602082015261084d565b8160005b8115611fd35780611fbd8161344c565b9150611fcc9050600a83613384565b9150611fad565b6000816001600160401b03811115611ffb57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015612025576020820181803683370190505b5090505b84156117a55761203a6001836133b7565b9150612047600a86613467565b61205290603061336c565b60f81b81838151811061207557634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350612097600a86613384565b9450612029565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b60006001600160e01b03198216637965db0b60e01b148061084a575061084a8261245a565b60606000612100836002613398565b61210b90600261336c565b6001600160401b0381111561213057634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f19166020018201604052801561215a576020820181803683370190505b509050600360fc1b8160008151811061218357634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350600f60fb1b816001815181106121c057634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060006121e4846002613398565b6121ef90600161336c565b90505b6001811115612283576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061223157634e487b7160e01b600052603260045260246000fd5b1a60f81b82828151811061225557634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a90535060049490941c9361227c816133fa565b90506121f2565b508315611b2d5760405162461bcd60e51b815260040161089190612d66565b6122ac8383612473565b6122b96000848484612342565b6108c85760405162461bcd60e51b815260040161089190612d9b565b6000848484846040516020016122ee9493929190612d02565b60408051601f19818403018152919052805160209091012095945050505050565b60008282604051602001612324929190612b69565b60405160208183030381529060405280519060200120905092915050565b6000612356846001600160a01b0316612540565b1561245257836001600160a01b031663150b7a0261237261187c565b8786866040518563ffffffff1660e01b81526004016123949493929190612c68565b602060405180830381600087803b1580156123ae57600080fd5b505af19250505080156123de575060408051601f3d908101601f191682019092526123db91810190612973565b60015b612438573d80801561240c576040519150601f19603f3d011682016040523d82523d6000602084013e612411565b606091505b5080516124305760405162461bcd60e51b815260040161089190612d9b565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506117a5565b5060016117a5565b6001600160e01b031981166301ffc9a760e01b14919050565b6001600160a01b0382166124995760405162461bcd60e51b8152600401610891906130d8565b6124a281611880565b156124bf5760405162461bcd60e51b815260040161089190612e33565b6124cb600083836108c8565b6001600160a01b03821660009081526005602052604081208054600192906124f490849061336c565b909155505060008181526004602052604080822080546001600160a01b0319166001600160a01b0386169081179091559051839290600080516020613537833981519152908290a45050565b3b151590565b82805461255290613411565b90600052602060002090601f01602090048101928261257457600085556125ba565b82601f1061258d5782800160ff198235161785556125ba565b828001600101855582156125ba579182015b828111156125ba57823582559160200191906001019061259f565b506125c692915061267a565b5090565b8280546125d690613411565b90600052602060002090601f0160209004810192826125f857600085556125ba565b82601f1061261157805160ff19168380011785556125ba565b828001600101855582156125ba579182015b828111156125ba578251825591602001919060010190612623565b508054600082559060005260206000209081019061144b919061267a565b508054600082559060005260206000209081019061144b919061268f565b5b808211156125c6576000815560010161267b565b808211156125c65760006126a382826126ac565b5060010161268f565b5080546126b890613411565b6000825580601f106126ca575061144b565b601f01602090049060005260206000209081019061144b919061267a565b60006001600160401b0380841115612702576127026134a7565b604051601f8501601f191681016020018281118282101715612726576127266134a7565b60405284815291508183850186101561273e57600080fd5b8484602083013760006020868301015250509392505050565b600082601f830112612767578081fd5b611b2d838335602085016126e8565b600060208284031215612787578081fd5b8135611b2d816134bd565b600080604083850312156127a4578081fd5b82356127af816134bd565b915060208301356127bf816134bd565b809150509250929050565b6000806000606084860312156127de578081fd5b83356127e9816134bd565b925060208401356127f9816134bd565b929592945050506040919091013590565b6000806000806080858703121561281f578081fd5b843561282a816134bd565b9350602085013561283a816134bd565b92506040850135915060608501356001600160401b0381111561285b578182fd5b8501601f8101871361286b578182fd5b61287a878235602084016126e8565b91505092959194509250565b60008060408385031215612898578182fd5b82356128a3816134bd565b915060208301356127bf816134d2565b600080604083850312156128c5578182fd5b82356128d0816134bd565b946020939093013593505050565b6000602082840312156128ef578081fd5b8151611b2d816134d2565b60006020828403121561290b578081fd5b5035919050565b60008060408385031215612924578182fd5b8235915060208301356127bf816134bd565b60008060408385031215612948578182fd5b50508035926020909101359150565b600060208284031215612968578081fd5b8135611b2d816134e0565b600060208284031215612984578081fd5b8151611b2d816134e0565b6000602082840312156129a0578081fd5b8151611b2d816134bd565b600080602083850312156129bd578182fd5b82356001600160401b03808211156129d3578384fd5b818501915085601f8301126129e6578384fd5b8135818111156129f4578485fd5b866020828501011115612a05578485fd5b60209290920196919550909350505050565b600060208284031215612a28578081fd5b81356001600160401b03811115612a3d578182fd5b6117a584828501612757565b600060208284031215612a5a578081fd5b5051919050565b60008060408385031215612a73578182fd5b8235915060208301356001600160401b03811115612a8f578182fd5b612a9b85828601612757565b9150509250929050565b60008151808452612abd8160208601602086016133ce565b601f01601f19169290920160200192915050565b805460009060028104600180831680612aeb57607f831692505b6020808410821415612b0b57634e487b7160e01b86526022600452602486fd5b818015612b1f5760018114612b3057612b5d565b60ff19861689528489019650612b5d565b612b3988613360565b60005b86811015612b555781548b820152908501908301612b3c565b505084890196505b50505050505092915050565b918252602082015260400190565b60008351612b898184602088016133ce565b835190830190612b9d8183602088016133ce565b01949350505050565b6000612bbb612bb58387612ad1565b85612ad1565b602f60f81b81528351612bd58160018401602088016133ce565b0160010195945050505050565b90565b600076020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b82528351612c178160178501602088016133ce565b7001034b99036b4b9b9b4b733903937b6329607d1b6017918401918201528351612c488160288401602088016133ce565b01602801949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612c9b90830184612aa5565b9695505050505050565b6001600160a01b03929092168252602082015260400190565b600060018060a01b038516825283602083015260606040830152612ce56060830184612aa5565b95945050505050565b901515815260200190565b90815260200190565b93845260208401929092526001600160a01b03166040830152606082015260800190565b600060208252611b2d6020830184612aa5565b6020808252601390820152721513d2d153881113d154d389d50811561254d5606a1b604082015260600190565b6020808252818101527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604082015260600190565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601c908201527b115490cdcc8c4e881d1bdad95b88185b1c9958591e481b5a5b9d195960221b604082015260600190565b60208082526024908201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526019908201527822a9219b99189d1030b8383937bb32903a379031b0b63632b960391b604082015260600190565b60208082526023908201527f42415443482049442053484f554c44204558434545442050524556494f5553206040820152624f4e4560e81b606082015260800190565b6020808252602c908201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b60208082526013908201527211551208151c985b9cd9995c8819985a5b1959606a1b604082015260600190565b60208082526038908201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776040820152771b995c881b9bdc88185c1c1c9bdd995908199bdc88185b1b60421b606082015260800190565b6020808252602a908201527f4552433732313a2062616c616e636520717565727920666f7220746865207a65604082015269726f206164647265737360b01b606082015260800190565b60208082526029908201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460408201526832b73a103a37b5b2b760b91b606082015260800190565b6020808252600e908201526d4e4f54204d4f4449464941424c4560901b604082015260600190565b6020808252600f908201526e4e4f5420454e4f554748204c494e4b60881b604082015260600190565b6020808252818101527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604082015260600190565b6020808252602c908201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860408201526b34b9ba32b73a103a37b5b2b760a11b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526029908201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960408201526839903737ba1037bbb760b91b606082015260800190565b6020808252601f908201527f4f6e6c7920565246436f6f7264696e61746f722063616e2066756c66696c6c00604082015260600190565b60208082526021908201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656040820152603960f91b606082015260800190565b60208082526031908201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f6040820152701ddb995c881b9bdc88185c1c1c9bdd9959607a1b606082015260800190565b60208082526014908201527313125392c8151c985b9cd9995c8819985a5b195960621b604082015260600190565b6020808252602f908201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560408201526e103937b632b9903337b91039b2b63360891b606082015260800190565b9182526001600160a01b0316602082015260400190565b94855260208501939093526001600160a01b039190911660408401526060830152608082015260a00190565b60009081526020902090565b6000821982111561337f5761337f61347b565b500190565b60008261339357613393613491565b500490565b60008160001904831182151516156133b2576133b261347b565b500290565b6000828210156133c9576133c961347b565b500390565b60005b838110156133e95781810151838201526020016133d1565b83811115610c805750506000910152565b6000816134095761340961347b565b506000190190565b60028104600182168061342557607f821691505b6020821081141561344657634e487b7160e01b600052602260045260246000fd5b50919050565b60006000198214156134605761346061347b565b5060010190565b60008261347657613476613491565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461144b57600080fd5b801515811461144b57600080fd5b6001600160e01b03198116811461144b57600080fdfe3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a8489f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220c420e3c344454a68d64da6eaabb0a3c9902d7cdcf884ca7519271eec4d79548164736f6c63430008000033

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

00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c10000000000000000000000000000000000000000000000000000000000000180000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb7952000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca0000000000000000000000000000000000000000000000001bc16d674ec80000aa77729d3466ca35ae8d28b3bbac7cc36a5031efdc430821c02bc31a238af44500000000000000000000000000000000000000000000000000000000000000174d656368616e697a6564204162737472616374696f6e7300000000000000000000000000000000000000000000000000000000000000000000000000000000024d41000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002b684265496f56715473705a416e62347a4a62794e464454304b524433646c52336967467843314d65554841000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _name (string): Mechanized Abstractions
Arg [1] : _symbol (string): MA
Arg [2] : _proxyRegistryAddress (address): 0xa5409ec958C83C3f309868babACA7c86DCB077c1
Arg [3] : _p5ScriptArweaveAddress (string): hBeIoVqTspZAnb4zJbyNFDT0KRD3dlR3igFxC1MeUHA
Arg [4] : _vrfCoordinator (address): 0xf0d54349aDdcf704F77AE15b96510dEA15cb7952
Arg [5] : _linkTokenAddress (address): 0x514910771AF9Ca656af840dff83E8264EcF986CA
Arg [6] : _vrfFee (uint256): 2000000000000000000
Arg [7] : _keyHash (bytes32): 0xaa77729d3466ca35ae8d28b3bbac7cc36a5031efdc430821c02bc31a238af445

-----Encoded View---------------
15 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [2] : 000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c1
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [4] : 000000000000000000000000f0d54349addcf704f77ae15b96510dea15cb7952
Arg [5] : 000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca
Arg [6] : 0000000000000000000000000000000000000000000000001bc16d674ec80000
Arg [7] : aa77729d3466ca35ae8d28b3bbac7cc36a5031efdc430821c02bc31a238af445
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000017
Arg [9] : 4d656368616e697a6564204162737472616374696f6e73000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [11] : 4d41000000000000000000000000000000000000000000000000000000000000
Arg [12] : 000000000000000000000000000000000000000000000000000000000000002b
Arg [13] : 684265496f56715473705a416e62347a4a62794e464454304b524433646c5233
Arg [14] : 6967467843314d65554841000000000000000000000000000000000000000000


Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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