Contract 0x8fa77bFf25B6b557FA2d333b05C2De259Ce33eCA 2

 

Contract Overview

Balance:
95.1375 MATIC

MATIC Value:
$69.57 (@ $0.73/MATIC)

Token:
 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xaf395980074f3d9c40b0b5246ca7d223f994af0902d125db099986747f1378a3Mint_NFT335086822022-09-24 13:21:413 days 21 hrs ago0x47bac34570d7b5c097f59860f36832cb4263cc3c IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.007110344639 40.232583076
0xc38d269f9c9f7a88baf0ef18bb9c9e7c9e52edd8d00e93f9a2098897f347c183Mint_and_send_un...334996482022-09-24 8:03:144 days 2 hrs ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.006554670003 30.000000014
0x51acaa572e14931879e5d93d27fa2fc0e336e02e575dbc6af66b40d63323c1c3Mint_and_send334704512022-09-23 15:01:104 days 19 hrs ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.004522222251 30.000147616
0x982c2089484bd8fde3a9c3bc30ff8c88541d2841d556f212828601995d8a59f9Set Approval For...334504722022-09-23 3:23:055 days 7 hrs ago0x463d9332beaa8b678568cdf86b774f54abebfcc6 IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0 MATIC0.001424229661 30.555000023
0x0e6153c6619ff6346ff97e2882967d0e92b287b83ba96e3b9e784ca3daf1c358Set Approval For...333090902022-09-19 16:33:468 days 18 hrs ago0xad54a04e203e432b391493b4736a7348c0511ff5 IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0 MATIC0.001405239931 30.1476
0x1adff83baa830215a8d941dc370b3156a4c4e294a3f1508e42aa7e260dcc3996Mint_and_send332285872022-09-17 18:03:1010 days 16 hrs ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.004529400002 30.000000015
0x8118445b4370af87af42cd80b1e247cc911e1671f660e34c78349fc27bb48f03Mint_and_send331820492022-09-16 14:50:1111 days 20 hrs ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.019016239886 31.203218549
0xe8b0d6affcd2de5adef9f3847dc5564bf0f3137a14b2e56bef8fa65d37658a61Mint_and_send331717092022-09-16 8:52:1012 days 1 hr ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.004555037778 30.227469134
0x8008eb14379c1be3fcd221c3997054d9184bef18a389467e5628e2ded8ec515eSet Approval For...331687082022-09-16 7:06:5512 days 3 hrs ago0x759411106f4a43b9d528b478eb368a8a6a052e8c IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0 MATIC0.00139836 30.000000015
0xcb394e3897ef97ffb4e4766f4e80d7f26a12590ec20b51b72686d1977f8010c3Mint_and_send331683682022-09-16 6:55:1112 days 3 hrs ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.00795174001 30.000000038
0x53d79c3b52e72f2105eb17043eb20323b0d71654c53594bea16d9dcfab8baac4Mint_and_send331428002022-09-15 16:09:0912 days 18 hrs ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.011162505551 31.265508249
0x88463a19c2641b2c96897424524d4b150bb87ce34c6c3cdf0366e13c995cd448Mint_and_send331416672022-09-15 15:30:1112 days 19 hrs ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.019990930206 101.842816857
0xf416ed4378a1385c5e6e8d350e4bf4462f038cbded46c35e22f65998c5eb1620Safe Transfer Fr...331362282022-09-15 12:22:5812 days 22 hrs ago0x94e7594f43cfb19ed7922c7286aa1d158081d1cc IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0 MATIC0.002858106327 44.657213601
0x1e1e7cc8c15aab3ccd006e74e0da7e8dd199f7d16a62a5c65b6bce3b33ad1e1cMint_and_send331081362022-09-14 20:12:0913 days 14 hrs ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.317020884562 30.10880001
0xc4d9cab2838a537cbacaa21331ae47df5d19d4600149510b2f37f12c83c7a25fMint_and_send330892592022-09-14 9:23:1114 days 1 hr ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.005884080002 30.000000014
0xf189e30137ca2f07d13d42b431ba85cba1d4efcc64c288e7f22e961ead9d9660Mint_and_send330885312022-09-14 8:58:1014 days 1 hr ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.004528320348 30.000002311
0x1d3e9149cc226b361740265c39a932a78cd0b3a87ee358964eeeba435ef8c149Mint_and_send330819852022-09-14 5:13:0914 days 5 hrs ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.004525080001 30.000000012
0x823e253088f475e6fbff2ef94d67e47fc7d020af844eaea5bea1ccfe55a54201Mint_and_send330684682022-09-13 21:26:1014 days 13 hrs ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.00453166928 30.070000001
0x6f82429adcf8535f522fb26f4c96b4e87f6c5ef99032309d8d97c7260230de8fMint_and_send329250772022-09-10 10:26:1018 days 24 mins ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.004524000004 30.000000033
0x50e7f2821dccf46ff058a4f5f9eca5916013b8e4d02e52c78a5991a68aef1425Safe Transfer Fr...329143692022-09-10 4:15:2518 days 6 hrs ago0x44107ec4f5afccfa60a014f64a27c8a45bc31744 IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0 MATIC0.001407030007 30.000000167
0xaf5b601f6bef2d2d86b413fe45efb4ad3be8b77a55c15aa037d0c25b1867b0ebMint_and_send328912492022-09-09 14:45:1118 days 20 hrs ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.00679675 31
0x243afd120e798bb4f0e7c49b96e70a22c4d37ae9dd849d50fe5384c3a9bb79d5Mint_and_send327759092022-09-06 20:03:0921 days 14 hrs ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.045390076198 30.156693757
0x45250372fd82e919c616cabaa23e175c294e666a1f208ef638414f7fbbe94ce1Delist_for_sale326610862022-09-04 1:36:4724 days 9 hrs ago0x44107ec4f5afccfa60a014f64a27c8a45bc31744 IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0 MATIC0.000819277384 31.049700001
0xb30ddd095e84ffe69ba89f140a0bc23d671654277d245739b697ebd53d1a4684Mint_and_send325068192022-08-31 5:17:1328 days 5 hrs ago0xf82bb087676f578448cb98f09a150b5e31b91b2a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC0.006578220002 30.000000013
0x472b206f2264ea41b806ce60881a79a112358f1d72c400fea12a44e6bbd6898dList_for_sale324478962022-08-29 12:10:3329 days 22 hrs ago0xd4e8bbf50aa02bce34e02143ebc8b9270a46185a IN  0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0 MATIC0.00167975868 31.369799995
[ Download CSV Export 
Latest 23 internal transactions
Parent Txn Hash Block From To Value
0xaca9583620cb9498aede222f4c69307e598b4fb474ec212c9e1eff3cc7777520320810912022-08-19 18:19:4239 days 16 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0x0470a3310c49810041138332d9edda0adbde78ef32 MATIC
0xaca9583620cb9498aede222f4c69307e598b4fb474ec212c9e1eff3cc7777520320810912022-08-19 18:19:4239 days 16 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0xee5ab4a027be5ce32340a47e49729772e5d0f468128 MATIC
0x604b15b67231950bdbf4945c078dfd3205ca87e8cf5166453739f304acc116cf320809772022-08-19 18:15:4639 days 16 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0x0470a3310c49810041138332d9edda0adbde78ef16 MATIC
0x604b15b67231950bdbf4945c078dfd3205ca87e8cf5166453739f304acc116cf320809772022-08-19 18:15:4639 days 16 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0xac26f59b96dc2f3efb9f8e1970a08345e88e010964 MATIC
0x853aa13bd2bb627bbfbe70cc07ccdb0b2e1677b4fae91c880e9bbc36467c4e2b320808172022-08-19 18:10:1439 days 16 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0x0470a3310c49810041138332d9edda0adbde78ef40 MATIC
0x853aa13bd2bb627bbfbe70cc07ccdb0b2e1677b4fae91c880e9bbc36467c4e2b320808172022-08-19 18:10:1439 days 16 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0x2603e2758dea41a699c78b589920dbbd3129c199160 MATIC
0xe51f276958e1aa8deabe4523f37e00978b22901c54e9a2b1d897d15731d49b80320803772022-08-19 17:55:0639 days 16 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0x0470a3310c49810041138332d9edda0adbde78ef20 MATIC
0xe51f276958e1aa8deabe4523f37e00978b22901c54e9a2b1d897d15731d49b80320803772022-08-19 17:55:0639 days 16 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0xee5ab4a027be5ce32340a47e49729772e5d0f46880 MATIC
0x4269cf90cef533367dc946f5f03f1ecb7c0f247cc02a4980293f788b37600a9f320799622022-08-19 17:40:5239 days 17 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0x0470a3310c49810041138332d9edda0adbde78ef2 MATIC
0x4269cf90cef533367dc946f5f03f1ecb7c0f247cc02a4980293f788b37600a9f320799622022-08-19 17:40:5239 days 17 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0x0470a3310c49810041138332d9edda0adbde78ef8 MATIC
0x16ab66deb52a36c444067818f1577db94465788301c5eab37ce17eb9a6e529d1318144302022-08-12 18:10:5846 days 16 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0x3653edbd6208ddeee1bd8905baac25866a3f383d1 MATIC
0x16ab66deb52a36c444067818f1577db94465788301c5eab37ce17eb9a6e529d1318144302022-08-12 18:10:5846 days 16 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0x3653edbd6208ddeee1bd8905baac25866a3f383d4 MATIC
0x1c4798a363c6b01078688a4590b223f2e591cffdfd10d46a9412e520b9935928314145652022-08-02 1:11:2257 days 9 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0x2603e2758dea41a699c78b589920dbbd3129c199100 MATIC
0x1c4798a363c6b01078688a4590b223f2e591cffdfd10d46a9412e520b9935928314145652022-08-02 1:11:2257 days 9 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0x2603e2758dea41a699c78b589920dbbd3129c199400 MATIC
0x5ea09e818ec3d31690a8575299588f34d8c324bb22bb154f3e964c2f91765d68314145402022-08-02 1:10:3257 days 9 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0x3ad1cad593ef4d0e012dd8e8db2efaa6cce44acf152 MATIC
0x5ea09e818ec3d31690a8575299588f34d8c324bb22bb154f3e964c2f91765d68314145402022-08-02 1:10:3257 days 9 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0x3ad1cad593ef4d0e012dd8e8db2efaa6cce44acf608 MATIC
0x32f5a26e984475da7528f4af195edb8a2f92e1a87cf79f59e3c3952089050c54314144662022-08-02 1:08:0057 days 9 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0xee5ab4a027be5ce32340a47e49729772e5d0f468160 MATIC
0x32f5a26e984475da7528f4af195edb8a2f92e1a87cf79f59e3c3952089050c54314144662022-08-02 1:08:0057 days 9 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0xee5ab4a027be5ce32340a47e49729772e5d0f468640 MATIC
0x9f68e55e0c362a14b736ef83f6241c9babe96016afab3f271e65b822f3645e02314142332022-08-02 0:59:5857 days 9 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0x313de5d83a2d12bd1f5a9977ea4d3455d16d2ac4177.6 MATIC
0x9f68e55e0c362a14b736ef83f6241c9babe96016afab3f271e65b822f3645e02314142332022-08-02 0:59:5857 days 9 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0x313de5d83a2d12bd1f5a9977ea4d3455d16d2ac4710.4 MATIC
0x937c6e1308e0e421fa1ce625bfd3c8ff1520ee1e1e34188a0c197b037fb52025314113662022-08-01 23:17:3857 days 11 hrs ago 0x21c8f59bb813f71a0188e9b2e591a1fcbe0a9a78 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca1 MATIC
0x1c2882e660327b18df32db80eb4c7b0b7adfdb3e07fae2ed9d19013e0418241f308246902022-07-17 13:43:1072 days 21 hrs ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0xff8c0d5dd989951d821ca5306f9323b2ef62d0cd1 MATIC
0xf476cdfa7bbef68a1ab893e05a4e352ef3f65dc1a1be6853ed666013c2b07fec307833672022-07-16 10:06:0974 days 44 mins ago 0x8fa77bff25b6b557fa2d333b05c2de259ce33eca0xab643b6506b3950154cc0f434429e7877514424e1 MATIC
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
InWriting

Compiler Version
v0.8.12+commit.f00d7308

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 13 : inWriting.sol
//Contract based on [https://docs.openzeppelin.com/contracts/3.x/erc721](https://docs.openzeppelin.com/contracts/3.x/erc721)
// SPDX-License-Identifier: MIT

//               ____ ____ _________ ____ ____ ____ ____ ____ ____ ____
//              ||I |||n |||       |||W |||r |||i |||t |||i |||n |||g ||
//              ||__|||__|||_______|||__|||__|||__|||__|||__|||__|||__||
//              |/__\|/__\|/_______\|/__\|/__\|/__\|/__\|/__\|/__\|/__\|

//                             https://www.inwriting.io/

pragma solidity ^0.8.12;

import {Context, ERC165, IERC721, IERC721Metadata, Address, Strings, IERC165, IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; // implementation of the erc721 standard, string nft inherits from this
import {Counters} from "@openzeppelin/contracts/utils/Counters.sol"; // counters that can only be incremented or decremented by 1
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; // sets up access control so that only the owner can interact
import {Base64} from "base64-sol/base64.sol"; // gets enoding functions

//import {strings} from "artifacts/solidity-stringutils/src/strings.sol";

contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, Ownable {
    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"
        );
    }

    mapping(uint256 => address) private originalMinter;

    /**
     * @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;
        originalMinter[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 {
        require(
            forSale[tokenId] == 0,
            "This token is up for sale, it must be de-listed before it can burned"
        );
        address owner = ERC721.ownerOf(tokenId);

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

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

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

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

    /**
     * @dev Approve `to` to operate on `tokenId`
     *
     * Emits a {Approval} event.
     */
    function _approve(address to, uint256 tokenId) internal virtual {
        require(
            forSale[tokenId] == 0,
            "This token is up for sale, it must be de-listed before it can approve an address"
        );
        _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 {}

    // ------------------------------------
    // implement buy and sell functionality
    // ------------------------------------

    mapping(uint256 => uint256) private forSale; // initialize mapping of token ID to sale price

    event Listed(uint256 tokenId, uint256 price); // event for when a token is listed for sale
    event Bought(uint256 tokenId, uint256 price); // event for when a token is bought

    uint8 royalty = 0; // "0%", if it was 10 it would be "10%, 20 would be 20%, etc..."
    uint8 minterRoyalty = 20;

    /**
     * @dev Adds a token to the forSale mapping
     *
     * Requirements:
     *
     * - `price` must be greater than 0.
     * - msg.sender is the owner of the token.
     *
     * Emits a {Listed} event.
     */
    function list_for_sale(uint256 tokenId, uint256 price)
        public
        returns (bool)
    {
        require(price > 99, "price must be greater than 99 wei");
        require(
            msg.sender == ownerOf(tokenId),
            "you are not the owner of this token, you can not sell it"
        );

        approve(address(0), tokenId);
        forSale[tokenId] = price;

        emit Listed(tokenId, price);

        return true;
    }

    /**
     * @dev Removes token from the forSale mapping
     *
     * Requirements:
     *
     * - `tokenId` must be for sale (in `forSale` mapping).
     * - msg.sender is the owner of the token.
     *
     * Emits a {Bought} event.
     *   - Bought events with price = 0 are counted as `delisted`
     */
    function delist_for_sale(uint256 tokenId) public returns (bool) {
        require(forSale[tokenId] != 0, "token not for sale");
        require(
            msg.sender == ownerOf(tokenId),
            "you are not the owner of this token, so you cannot de-list it"
        );

        delete forSale[tokenId];

        emit Bought(tokenId, 0);

        return true;
    }

    /**
     * @dev Returns the price (plus a fee) for the token in the forSale mapping
     *
     * Requirements:
     *
     * - `tokenId` must be for sale (in `forSale` mapping).
     *
     */
    function get_price(uint256 tokenId) public view returns (uint256) {
        require(forSale[tokenId] != 0, "token not for sale");

        return forSale[tokenId] + ((forSale[tokenId] * royalty) / 100);
    }

    function is_token_for_sale(uint256 tokenId) internal view returns (bool) {
        return forSale[tokenId] != 0;
    }

    /**
     * @dev Returns the fee of buying a token on the marketplace
     *
     */

    function get_minter_royalty() public view returns (uint8) {
        return minterRoyalty;
    }

    function set_minter_royalty(uint8 new_royalty) public onlyOwner {
        require(new_royalty < 100, "royalty must be below 100%");
        minterRoyalty = new_royalty;
    }

    /**
     * @dev Allows user to purchase a token from a buyer.
     *  transfers token from seller to buyer
     *  transfers funds from buyer to seller, deducts platform fee if enabled
     *
     * Requirements:
     *
     * - `tokenId` must be for sale (in `forSale` mapping).
     * - msg.value must be greater than or equal to the sale price (forSale[tokenId]).
     *
     * Emits a {Bought} event.
     */
    function buy(uint256 tokenId) public payable returns (bool) {
        return buy_and_send(tokenId, msg.sender);
    }

    function buy_and_send(uint256 tokenId, address addr)
        public
        payable
        returns (bool)
    {
        require(forSale[tokenId] != 0, "token not for sale");
        uint256 price = get_price(tokenId);
        require(msg.value >= price, "insufficient value");

        uint256 seller_price = forSale[tokenId];
        address seller = ownerOf(tokenId);

        delete forSale[tokenId];

        _transfer(seller, addr, tokenId);

        payable(seller).transfer((seller_price * (100 - minterRoyalty)) / 100);
        payable(get_original_minter(tokenId)).transfer(
            (seller_price * minterRoyalty) / 100
        );

        emit Bought(tokenId, price);

        if (msg.value > price) {
            payable(addr).transfer(msg.value - price);
        }

        return true;
    }

    /**
     * @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`.
     * - `tokenId` token must not be up for sale.
     *
     * 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");
        require(
            forSale[tokenId] == 0,
            "This token is up for sale, it must be de-listed before it can be transferred"
        );

        _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);
    }

    // contract owner can set and change a fee for purchasing an nft on platform

    // owner can change the royalty
    function update_royalty(uint8 newRoyalty) public onlyOwner {
        require(newRoyalty < 100, "royalty must be below 100%");
        royalty = newRoyalty;
    }

    // returns the cost (gas excluded) of royalty fee in wei
    function get_royalty() public view returns (uint256) {
        return royalty;
    }

    function get_original_minter(uint256 tokenId)
        public
        view
        returns (address)
    {
        require(_exists(tokenId), "TokenID does not exist!"); // make sure the tokenID is valid
        return originalMinter[tokenId]; // get the string from the mapping
    }
}

// start contract code

contract InWriting is ERC721 {
    using Counters for Counters.Counter; // set counter object path
    Counters.Counter private _tokenIds; // initialize counter object
    using Strings for uint256;
    mapping(string => bool) private usedStrings; // initialize mapping for keeping track of unique strings
    mapping(uint256 => string) private tokenIDtoString; // initialize mapping of token ID to string
    mapping(uint256 => bool) private unlocked; // initialize mapping of locked stated of tokens
    mapping(address => uint256) private noCostMinters; // initialize mapping of people who can mint for free
    uint256 cost = 2500000000000000; // set the minting fee to 0

    event Appended(uint256 tokenId, address addr); // event for when a token appended to

    constructor() ERC721("InWriting", "WRITE") {} // smart contract's name, smart contract's symbol

    // image variables
    string image_url =
        "https://inwritingapi.com/inwriting/get_svg.php?tokenID=";

    // change image url after deployment if needed
    function change_image_url(string memory str) public onlyOwner {
        image_url = str;
    }

    // checks to see if a string has been minted already
    function check_if_used(string memory str) public view returns (bool) {
        // view means that we can look at the value of a state variable in the contract
        return usedStrings[str]; // tell us if the string is in the mapping (true if there, false if not)
    }

    // given tokenId, returns the string associated with that token
    function get_string(uint256 tokenId) public view returns (string memory) {
        require(_exists(tokenId), "TokenID does not exist!"); // make sure the tokenID is valid
        return tokenIDtoString[tokenId]; // get the string from the mapping
    }

    string description = "";

    // change description after deployment if needed
    function change_description(string memory desc) public onlyOwner {
        description = desc;
    }

    string external_url = "https://inwriting.io/text/?tokenID=";

    // change external url after deployment if needed
    function change_external_url(string memory url) public onlyOwner {
        external_url = url;
    }

    // override the default function and wrap the string in a nice little base64'd json format
    function tokenURI(uint256 tokenId)
        public
        view
        override
        returns (string memory)
    {
        string memory base = "data:application/json;base64,"; // base string telling the browser the json is in base64
        string memory tokenID = tokenId.toString();
        string memory json = string(
            abi.encodePacked(
                '{\n\t"name": "In Writing #',
                tokenID,
                '",\n\t"string": "',
                Base64.encode(bytes(get_string(tokenId))), // base64 encoded so it doesn't break the json
                '",\n\t"external_url": "',
                external_url,
                tokenID,
                '",\n\t"description": "',
                description,
                '",\n\t"tokenId": "',
                tokenID,
                '",\n\t"image_data": "',
                string(abi.encodePacked(image_url, tokenID)),
                '"\n}'
            )
        ); // format the json

        return string(abi.encodePacked(base, Base64.encode(bytes(json)))); // return the full concatenated string
    }

    // owner can withdraw from the contract address
    function withdraw(uint256 amt) public onlyOwner {
        require(amt <= address(this).balance);
        payable(owner()).transfer(amt);
    }

    // owner can change the minting cost
    function update_minting_cost(uint256 newCost) public onlyOwner {
        cost = newCost;
    }

    // returns the cost (gas excluded) of minting a string in wei
    function get_minting_cost() public view returns (uint256) {
        return cost;
    }

    function set_no_cost_minter(address addr, uint256 num) public onlyOwner {
        noCostMinters[addr] = num;
    }

    // mint the token
    function mint_NFT(string memory str) public payable returns (uint256) {
        return mint_and_send(str, msg.sender);
    }

    // mint a token and immediately list it for sale
    function mint_and_list_NFT(string memory str, uint256 price)
        public
        payable
        returns (uint256)
    {
        uint256 tokenId = mint_NFT(str);
        list_for_sale(tokenId, price);
        return tokenId;
    }

    // mint a token in the unlocked state so that more characters can be added to it
    function mint_unlocked_NFT(string memory str)
        public
        payable
        returns (uint256)
    {
        return mint_and_send_unlocked_NFT(str, msg.sender);
    }

    // mint an unlocked token and immediately list it for sale
    function mint_and_list_unlocked_NFT(string memory str, uint256 price)
        public
        payable
        returns (uint256)
    {
        uint256 tokenId = mint_unlocked_NFT(str);
        list_for_sale(tokenId, price);
        return tokenId;
    }

    // add more charcters to the token
    function append_to_NFT(uint256 tokenId, string memory str) public {
        require(
            msg.sender == ownerOf(tokenId),
            "you are not the owner of this token, so you cannot append to it"
        );
        require(
            unlocked[tokenId],
            "this token is locked, so it may not be modified"
        );
        require(
            !is_token_for_sale(tokenId),
            "this token is up for sale, so it cannot be appened to"
        );
        string memory oldString = tokenIDtoString[tokenId];
        string memory newString = string(abi.encodePacked(oldString, str));
        require(!usedStrings[newString], "this string has already been minted"); // check to make sure the string is unique

        tokenIDtoString[tokenId] = newString;
        string storage newString_ = tokenIDtoString[tokenId];
        usedStrings[newString_] = true;

        delete usedStrings[oldString];

        emit Appended(tokenId, msg.sender);
    }

    // lock the token so it can no longer be modified
    function lock_NFT(uint256 tokenId) public {
        require(
            _isApprovedOrOwner(msg.sender, tokenId),
            "you are not the owner of this token"
        );
        delete unlocked[tokenId];
    }

    // return the total number of In Writing NFTs that exist
    function totalSupply() public view returns (uint256) {
        return _tokenIds.current();
    }

    function mint_and_send(string memory str, address addr)
        public
        payable
        returns (uint256)
    {
        uint8 free_mint_coef = 1;
        if (noCostMinters[msg.sender] > 0) {
            noCostMinters[msg.sender] -= 1;
            free_mint_coef = 0;
        } else if (noCostMinters[addr] > 0) {
            noCostMinters[addr] -= 1;
            free_mint_coef = 0;
        } else {
            require(msg.value >= cost, "payment not sufficient"); // msg.value must be larger than the minting fee
        }

        require(!usedStrings[str], "this string has already been minted"); // check to make sure the string is unique

        uint256 newItemId = _tokenIds.current(); // get the current itemID
        _tokenIds.increment(); // increment the tokenID

        tokenIDtoString[newItemId] = str; // update the mapping
        string storage str_at_pointer = tokenIDtoString[newItemId]; // get pointer for the string so we don't write twice
        usedStrings[str_at_pointer] = true; // overwrite mapping, this time with the storage pointer string for efficiency

        _mint(addr, newItemId); // mint the nft and send it to the person who called the contract

        if (msg.value > cost * free_mint_coef) {
            payable(addr).transfer(msg.value - cost * free_mint_coef);
        }

        return newItemId;
    }

    function mint_and_send_unlocked_NFT(string memory str, address addr)
        public
        payable
        returns (uint256)
    {
        uint256 tokenId = mint_and_send(str, addr);
        unlocked[tokenId] = true;
        return tokenId;
    }
}

File 2 of 13 : ERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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 13 : Counters.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)

pragma solidity ^0.8.0;

/**
 * @title Counters
 * @author Matt Condon (@shrugs)
 * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
 * of elements in a mapping, issuing ERC721 ids, or counting request ids.
 *
 * Include with `using Counters for Counters.Counter;`
 */
library Counters {
    struct Counter {
        // This variable should never be directly accessed by users of the library: interactions must be restricted to
        // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
        // this feature: see https://github.com/ethereum/solidity/issues/4637
        uint256 _value; // default: 0
    }

    function current(Counter storage counter) internal view returns (uint256) {
        return counter._value;
    }

    function increment(Counter storage counter) internal {
        unchecked {
            counter._value += 1;
        }
    }

    function decrement(Counter storage counter) internal {
        uint256 value = counter._value;
        require(value > 0, "Counter: decrement overflow");
        unchecked {
            counter._value = value - 1;
        }
    }

    function reset(Counter storage counter) internal {
        counter._value = 0;
    }
}

File 4 of 13 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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 5 of 13 : base64.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0;

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

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

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

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

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

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

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

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

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

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

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

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

        return result;
    }

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

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

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

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

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

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

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

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

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

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

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

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

        return result;
    }
}

File 6 of 13 : IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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 7 of 13 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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 8 of 13 : IERC721Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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 9 of 13 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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 10 of 13 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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 11 of 13 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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 12 of 13 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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 13 of 13 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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);
}

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

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"Appended","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"Bought","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"Listed","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":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"str","type":"string"}],"name":"append_to_NFT","outputs":[],"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":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"buy","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"addr","type":"address"}],"name":"buy_and_send","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"desc","type":"string"}],"name":"change_description","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"url","type":"string"}],"name":"change_external_url","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"change_image_url","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"check_if_used","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"delist_for_sale","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"get_minter_royalty","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"get_minting_cost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"get_original_minter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"get_price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"get_royalty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"get_string","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"list_for_sale","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"lock_NFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"mint_NFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"str","type":"string"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"mint_and_list_NFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"str","type":"string"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"mint_and_list_unlocked_NFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"str","type":"string"},{"internalType":"address","name":"addr","type":"address"}],"name":"mint_and_send","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"str","type":"string"},{"internalType":"address","name":"addr","type":"address"}],"name":"mint_and_send_unlocked_NFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"str","type":"string"}],"name":"mint_unlocked_NFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","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":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"new_royalty","type":"uint8"}],"name":"set_minter_royalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint256","name":"num","type":"uint256"}],"name":"set_no_cost_minter","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":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newCost","type":"uint256"}],"name":"update_minting_cost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"newRoyalty","type":"uint8"}],"name":"update_royalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526000600960006101000a81548160ff021916908360ff1602179055506014600960016101000a81548160ff021916908360ff1602179055506608e1bc9bf04000600f5560405180606001604052806037815260200162005e0360379139601090805190602001906200007892919062000273565b506040518060200160405280600081525060119080519060200190620000a092919062000273565b5060405180606001604052806023815260200162005de06023913960129080519060200190620000d292919062000273565b50348015620000e057600080fd5b506040518060400160405280600981526020017f496e57726974696e6700000000000000000000000000000000000000000000008152506040518060400160405280600581526020017f57524954450000000000000000000000000000000000000000000000000000008152506200016d62000161620001a760201b60201c565b620001af60201b60201c565b81600190805190602001906200018592919062000273565b5080600290805190602001906200019e92919062000273565b50505062000388565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b828054620002819062000352565b90600052602060002090601f016020900481019282620002a55760008555620002f1565b82601f10620002c057805160ff1916838001178555620002f1565b82800160010185558215620002f1579182015b82811115620002f0578251825591602001919060010190620002d3565b5b50905062000300919062000304565b5090565b5b808211156200031f57600081600090555060010162000305565b5090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200036b57607f821691505b6020821081141562000382576200038162000323565b5b50919050565b615a4880620003986000396000f3fe6080604052600436106102675760003560e01c80638824073911610144578063c87b56dd116100b6578063d96a094a1161007a578063d96a094a14610984578063df30ea46146109b4578063e985e9c5146109dd578063edacec6a14610a1a578063f1d1490314610a4a578063f2fde38b14610a7357610267565b8063c87b56dd14610888578063c99457d1146108c5578063d28e3fff146108f5578063d70035f01461091e578063d93580ff1461094757610267565b806398f4bd671161010857806398f4bd6714610789578063a22cb465146107b9578063a73a253f146107e2578063b5ee622b1461080b578063b88d4fde14610836578063c1b486731461085f57610267565b806388240739146106aa5780638d2e41e5146106da5780638da5cb5b1461070a57806391126b0a1461073557806395d89b411461075e57610267565b80632e1a7d4d116101dd5780636352211e116101a15780636352211e146105835780636eb02583146105c057806370a08231146105f0578063715018a61461062d5780638044c0d414610644578063834ca1001461066d57610267565b80632e1a7d4d1461048c578063361809bf146104b557806342842e0e146104e05780634c1fbab0146105095780634c24c4391461054657610267565b8063095ea7b31161022f578063095ea7b3146103795780630eb4d8cb146103a257806318160ddd146103d257806323b872dd146103fd57806328f4cc7c146104265780632ab8a2981461044f57610267565b806301b71aec1461026c57806301ffc9a7146102a957806306487b60146102e657806306fdde0314610311578063081812fc1461033c575b600080fd5b34801561027857600080fd5b50610293600480360381019061028e9190613845565b610a9c565b6040516102a091906138a0565b60405180910390f35b3480156102b557600080fd5b506102d060048036038101906102cb9190613913565b610bbd565b6040516102dd91906138a0565b60405180910390f35b3480156102f257600080fd5b506102fb610c9f565b604051610308919061395c565b60405180910390f35b34801561031d57600080fd5b50610326610cb6565b6040516103339190613a10565b60405180910390f35b34801561034857600080fd5b50610363600480360381019061035e9190613a32565b610d48565b6040516103709190613aa0565b60405180910390f35b34801561038557600080fd5b506103a0600480360381019061039b9190613ae7565b610dcd565b005b6103bc60048036038101906103b79190613c5c565b610ee5565b6040516103c99190613cc7565b60405180910390f35b3480156103de57600080fd5b506103e7610f08565b6040516103f49190613cc7565b60405180910390f35b34801561040957600080fd5b50610424600480360381019061041f9190613ce2565b610f19565b005b34801561043257600080fd5b5061044d60048036038101906104489190613d35565b610f79565b005b34801561045b57600080fd5b5061047660048036038101906104719190613a32565b61100f565b60405161048391906138a0565b60405180910390f35b34801561049857600080fd5b506104b360048036038101906104ae9190613a32565b611137565b005b3480156104c157600080fd5b506104ca611211565b6040516104d79190613cc7565b60405180910390f35b3480156104ec57600080fd5b5061050760048036038101906105029190613ce2565b61122b565b005b34801561051557600080fd5b50610530600480360381019061052b9190613a32565b61124b565b60405161053d9190613aa0565b60405180910390f35b34801561055257600080fd5b5061056d60048036038101906105689190613d35565b6112d0565b60405161057a91906138a0565b60405180910390f35b34801561058f57600080fd5b506105aa60048036038101906105a59190613a32565b611305565b6040516105b79190613aa0565b60405180910390f35b6105da60048036038101906105d59190613c5c565b6113b7565b6040516105e79190613cc7565b60405180910390f35b3480156105fc57600080fd5b5061061760048036038101906106129190613d7e565b6113da565b6040516106249190613cc7565b60405180910390f35b34801561063957600080fd5b50610642611492565b005b34801561065057600080fd5b5061066b60048036038101906106669190613a32565b61151a565b005b34801561067957600080fd5b50610694600480360381019061068f9190613a32565b6115a0565b6040516106a19190613a10565b60405180910390f35b6106c460048036038101906106bf9190613dab565b61168d565b6040516106d19190613cc7565b60405180910390f35b6106f460048036038101906106ef9190613d35565b6119b6565b6040516107019190613cc7565b60405180910390f35b34801561071657600080fd5b5061071f6119c9565b60405161072c9190613aa0565b60405180910390f35b34801561074157600080fd5b5061075c60048036038101906107579190613e07565b6119f2565b005b34801561076a57600080fd5b50610773611d27565b6040516107809190613a10565b60405180910390f35b6107a3600480360381019061079e9190613dab565b611db9565b6040516107b09190613cc7565b60405180910390f35b3480156107c557600080fd5b506107e060048036038101906107db9190613e8f565b611dfe565b005b3480156107ee57600080fd5b5061080960048036038101906108049190613d35565b611e14565b005b34801561081757600080fd5b50610820611eaa565b60405161082d9190613cc7565b60405180910390f35b34801561084257600080fd5b5061085d60048036038101906108589190613f70565b611eb4565b005b34801561086b57600080fd5b506108866004803603810190610881919061401f565b611f16565b005b34801561089457600080fd5b506108af60048036038101906108aa9190613a32565b611ff6565b6040516108bc9190613a10565b60405180910390f35b6108df60048036038101906108da9190613d35565b6120d7565b6040516108ec9190613cc7565b60405180910390f35b34801561090157600080fd5b5061091c60048036038101906109179190613ae7565b6120ea565b005b34801561092a57600080fd5b506109456004803603810190610940919061401f565b6121ae565b005b34801561095357600080fd5b5061096e60048036038101906109699190613a32565b61228e565b60405161097b9190613cc7565b60405180910390f35b61099e60048036038101906109999190613a32565b612348565b6040516109ab91906138a0565b60405180910390f35b3480156109c057600080fd5b506109db60048036038101906109d69190613d35565b61235b565b005b3480156109e957600080fd5b50610a0460048036038101906109ff919061404c565b6123f1565b604051610a1191906138a0565b60405180910390f35b610a346004803603810190610a2f919061408c565b612485565b604051610a4191906138a0565b60405180910390f35b348015610a5657600080fd5b50610a716004803603810190610a6c9190613a32565b612709565b005b348015610a7f57600080fd5b50610a9a6004803603810190610a959190613d7e565b612778565b005b600060638211610ae1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad89061413e565b60405180910390fd5b610aea83611305565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610b57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b4e906141d0565b60405180910390fd5b610b62600084610dcd565b8160086000858152602001908152602001600020819055507f1ea45e30b31292f9d7c5d37d275b2feca555f13f47dce0fdea2f47e8852ecd788383604051610bab9291906141f0565b60405180910390a16001905092915050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610c8857507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80610c985750610c9782612870565b5b9050919050565b6000600960019054906101000a900460ff16905090565b606060018054610cc590614248565b80601f0160208091040260200160405190810160405280929190818152602001828054610cf190614248565b8015610d3e5780601f10610d1357610100808354040283529160200191610d3e565b820191906000526020600020905b815481529060010190602001808311610d2157829003601f168201915b5050505050905090565b6000610d53826128da565b610d92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d89906142ec565b60405180910390fd5b6005600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000610dd882611305565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610e49576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e409061437e565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610e68612946565b73ffffffffffffffffffffffffffffffffffffffff161480610e975750610e9681610e91612946565b6123f1565b5b610ed6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ecd90614410565b60405180910390fd5b610ee0838361294e565b505050565b600080610ef1846119b6565b9050610efd8184610a9c565b508091505092915050565b6000610f14600a612a5d565b905090565b610f2a610f24612946565b82612a6b565b610f69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f60906144a2565b60405180910390fd5b610f74838383612b49565b505050565b610f81612946565b73ffffffffffffffffffffffffffffffffffffffff16610f9f6119c9565b73ffffffffffffffffffffffffffffffffffffffff1614610ff5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fec9061450e565b60405180910390fd5b806010908051906020019061100b929190613758565b5050565b60008060086000848152602001908152602001600020541415611067576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105e9061457a565b60405180910390fd5b61107082611305565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146110dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110d49061460c565b60405180910390fd5b60086000838152602001908152602001600020600090557f3ccb2ab6980b218b1dd4974b07365cd90a191e170c611da46262fecc208bd661826000604051611126929190614671565b60405180910390a160019050919050565b61113f612946565b73ffffffffffffffffffffffffffffffffffffffff1661115d6119c9565b73ffffffffffffffffffffffffffffffffffffffff16146111b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111aa9061450e565b60405180910390fd5b478111156111c057600080fd5b6111c86119c9565b73ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015801561120d573d6000803e3d6000fd5b5050565b6000600960009054906101000a900460ff1660ff16905090565b61124683838360405180602001604052806000815250611eb4565b505050565b6000611256826128da565b611295576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161128c906146e6565b60405180910390fd5b6007600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6000600b826040516112e29190614742565b908152602001604051809103902060009054906101000a900460ff169050919050565b6000806003600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156113ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113a5906147cb565b60405180910390fd5b80915050919050565b6000806113c3846120d7565b90506113cf8184610a9c565b508091505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561144b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114429061485d565b60405180910390fd5b600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b61149a612946565b73ffffffffffffffffffffffffffffffffffffffff166114b86119c9565b73ffffffffffffffffffffffffffffffffffffffff161461150e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115059061450e565b60405180910390fd5b6115186000612dfb565b565b611522612946565b73ffffffffffffffffffffffffffffffffffffffff166115406119c9565b73ffffffffffffffffffffffffffffffffffffffff1614611596576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161158d9061450e565b60405180910390fd5b80600f8190555050565b60606115ab826128da565b6115ea576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115e1906146e6565b60405180910390fd5b600c6000838152602001908152602001600020805461160890614248565b80601f016020809104026020016040519081016040528092919081815260200182805461163490614248565b80156116815780601f1061165657610100808354040283529160200191611681565b820191906000526020600020905b81548152906001019060200180831161166457829003601f168201915b50505050509050919050565b600080600190506000600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054111561173c576001600e60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461172c91906148ac565b925050819055506000905061182b565b6000600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205411156117e4576001600e60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546117d491906148ac565b925050819055506000905061182a565b600f54341015611829576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118209061492c565b60405180910390fd5b5b5b600b8460405161183b9190614742565b908152602001604051809103902060009054906101000a900460ff1615611897576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161188e906149be565b60405180910390fd5b60006118a3600a612a5d565b90506118af600a612ebf565b84600c600083815260200190815260200160002090805190602001906118d6929190613758565b506000600c600083815260200190815260200160002090506001600b826040516119009190614a72565b908152602001604051809103902060006101000a81548160ff02191690831515021790555061192f8583612ed5565b8260ff16600f546119409190614a89565b3411156119aa578473ffffffffffffffffffffffffffffffffffffffff166108fc8460ff16600f546119729190614a89565b3461197d91906148ac565b9081150290604051600060405180830381858888f193505050501580156119a8573d6000803e3d6000fd5b505b81935050505092915050565b60006119c2823361168d565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6119fb82611305565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611a68576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a5f90614b55565b60405180910390fd5b600d600083815260200190815260200160002060009054906101000a900460ff16611ac8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611abf90614be7565b60405180910390fd5b611ad1826130f5565b15611b11576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b0890614c79565b60405180910390fd5b6000600c60008481526020019081526020016000208054611b3190614248565b80601f0160208091040260200160405190810160405280929190818152602001828054611b5d90614248565b8015611baa5780601f10611b7f57610100808354040283529160200191611baa565b820191906000526020600020905b815481529060010190602001808311611b8d57829003601f168201915b5050505050905060008183604051602001611bc6929190614c99565b6040516020818303038152906040529050600b81604051611be79190614742565b908152602001604051809103902060009054906101000a900460ff1615611c43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c3a906149be565b60405180910390fd5b80600c60008681526020019081526020016000209080519060200190611c6a929190613758565b506000600c600086815260200190815260200160002090506001600b82604051611c949190614a72565b908152602001604051809103902060006101000a81548160ff021916908315150217905550600b83604051611cc99190614742565b908152602001604051809103902060006101000a81549060ff02191690557fb77ac2cf2bae3b1d3a17f92a68edca0b214181c2b72dbc133de7491fa2b557518533604051611d18929190614cbd565b60405180910390a15050505050565b606060028054611d3690614248565b80601f0160208091040260200160405190810160405280929190818152602001828054611d6290614248565b8015611daf5780601f10611d8457610100808354040283529160200191611daf565b820191906000526020600020905b815481529060010190602001808311611d9257829003601f168201915b5050505050905090565b600080611dc6848461168d565b90506001600d600083815260200190815260200160002060006101000a81548160ff0219169083151502179055508091505092915050565b611e10611e09612946565b8383613115565b5050565b611e1c612946565b73ffffffffffffffffffffffffffffffffffffffff16611e3a6119c9565b73ffffffffffffffffffffffffffffffffffffffff1614611e90576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e879061450e565b60405180910390fd5b8060129080519060200190611ea6929190613758565b5050565b6000600f54905090565b611ec5611ebf612946565b83612a6b565b611f04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611efb906144a2565b60405180910390fd5b611f1084848484613282565b50505050565b611f1e612946565b73ffffffffffffffffffffffffffffffffffffffff16611f3c6119c9565b73ffffffffffffffffffffffffffffffffffffffff1614611f92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f899061450e565b60405180910390fd5b60648160ff1610611fd8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fcf90614d32565b60405180910390fd5b80600960016101000a81548160ff021916908360ff16021790555050565b606060006040518060400160405280601d81526020017f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152509050600061203d846132de565b905060008161205361204e876115a0565b61343f565b60128460118660108860405160200161206d929190614de6565b604051602081830303815290604052604051602001612092979695949392919061501e565b6040516020818303038152906040529050826120ad8261343f565b6040516020016120be929190614c99565b6040516020818303038152906040529350505050919050565b60006120e38233611db9565b9050919050565b6120f2612946565b73ffffffffffffffffffffffffffffffffffffffff166121106119c9565b73ffffffffffffffffffffffffffffffffffffffff1614612166576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161215d9061450e565b60405180910390fd5b80600e60008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050565b6121b6612946565b73ffffffffffffffffffffffffffffffffffffffff166121d46119c9565b73ffffffffffffffffffffffffffffffffffffffff161461222a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122219061450e565b60405180910390fd5b60648160ff1610612270576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161226790614d32565b60405180910390fd5b80600960006101000a81548160ff021916908360ff16021790555050565b600080600860008481526020019081526020016000205414156122e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122dd9061457a565b60405180910390fd5b6064600960009054906101000a900460ff1660ff1660086000858152602001908152602001600020546123199190614a89565b61232391906150ff565b60086000848152602001908152602001600020546123419190615130565b9050919050565b60006123548233612485565b9050919050565b612363612946565b73ffffffffffffffffffffffffffffffffffffffff166123816119c9565b73ffffffffffffffffffffffffffffffffffffffff16146123d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123ce9061450e565b60405180910390fd5b80601190805190602001906123ed929190613758565b5050565b6000600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600080600860008581526020019081526020016000205414156124dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124d49061457a565b60405180910390fd5b60006124e88461228e565b90508034101561252d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612524906151d2565b60405180910390fd5b600060086000868152602001908152602001600020549050600061255086611305565b90506008600087815260200190815260200160002060009055612574818688612b49565b8073ffffffffffffffffffffffffffffffffffffffff166108fc6064600960019054906101000a900460ff1660646125ac91906151f2565b60ff16856125ba9190614a89565b6125c491906150ff565b9081150290604051600060405180830381858888f193505050501580156125ef573d6000803e3d6000fd5b506125f98661124b565b73ffffffffffffffffffffffffffffffffffffffff166108fc6064600960019054906101000a900460ff1660ff16856126329190614a89565b61263c91906150ff565b9081150290604051600060405180830381858888f19350505050158015612667573d6000803e3d6000fd5b507f3ccb2ab6980b218b1dd4974b07365cd90a191e170c611da46262fecc208bd66186846040516126999291906141f0565b60405180910390a1823411156126fc578473ffffffffffffffffffffffffffffffffffffffff166108fc84346126cf91906148ac565b9081150290604051600060405180830381858888f193505050501580156126fa573d6000803e3d6000fd5b505b6001935050505092915050565b6127133382612a6b565b612752576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161274990615298565b60405180910390fd5b600d600082815260200190815260200160002060006101000a81549060ff021916905550565b612780612946565b73ffffffffffffffffffffffffffffffffffffffff1661279e6119c9565b73ffffffffffffffffffffffffffffffffffffffff16146127f4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127eb9061450e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612864576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161285b9061532a565b60405180910390fd5b61286d81612dfb565b50565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166003600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b60006008600083815260200190815260200160002054146129a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161299b906153e2565b60405180910390fd5b816005600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16612a1783611305565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600081600001549050919050565b6000612a76826128da565b612ab5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612aac90615474565b60405180910390fd5b6000612ac083611305565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612b2f57508373ffffffffffffffffffffffffffffffffffffffff16612b1784610d48565b73ffffffffffffffffffffffffffffffffffffffff16145b80612b405750612b3f81856123f1565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16612b6982611305565b73ffffffffffffffffffffffffffffffffffffffff1614612bbf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bb690615506565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612c2f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c2690615598565b60405180910390fd5b6000600860008381526020019081526020016000205414612c85576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c7c90615650565b60405180910390fd5b612c908383836135b8565b612c9b60008261294e565b6001600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612ceb91906148ac565b925050819055506001600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612d429190615130565b92505081905550816003600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6001816000016000828254019250508190555050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612f45576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f3c906156bc565b60405180910390fd5b612f4e816128da565b15612f8e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f8590615728565b60405180910390fd5b612f9a600083836135b8565b6001600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612fea9190615130565b92505081905550816003600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550816007600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600080600860008481526020019081526020016000205414159050919050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415613184576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161317b90615794565b60405180910390fd5b80600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405161327591906138a0565b60405180910390a3505050565b61328d848484612b49565b613299848484846135bd565b6132d8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132cf90615826565b60405180910390fd5b50505050565b60606000821415613326576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061343a565b600082905060005b6000821461335857808061334190615846565b915050600a8261335191906150ff565b915061332e565b60008167ffffffffffffffff81111561337457613373613b31565b5b6040519080825280601f01601f1916602001820160405280156133a65781602001600182028036833780820191505090505b5090505b60008514613433576001826133bf91906148ac565b9150600a856133ce919061588f565b60306133da9190615130565b60f81b8183815181106133f0576133ef6158c0565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8561342c91906150ff565b94506133aa565b8093505050505b919050565b6060600082511415613462576040518060200160405280600081525090506135b3565b60006040518060600160405280604081526020016159d360409139905060006003600285516134919190615130565b61349b91906150ff565b60046134a79190614a89565b905060006020826134b89190615130565b67ffffffffffffffff8111156134d1576134d0613b31565b5b6040519080825280601f01601f1916602001820160405280156135035781602001600182028036833780820191505090505b509050818152600183018586518101602084015b81831015613572576003830192508251603f8160121c168501518253600182019150603f81600c1c168501518253600182019150603f8160061c168501518253600182019150603f8116850151825360018201915050613517565b60038951066001811461358c576002811461359c576135a7565b613d3d60f01b60028303526135a7565b603d60f81b60018303525b50505050508093505050505b919050565b505050565b60006135de8473ffffffffffffffffffffffffffffffffffffffff16613745565b15613738578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02613607612946565b8786866040518563ffffffff1660e01b81526004016136299493929190615944565b6020604051808303816000875af192505050801561366557506040513d601f19601f8201168201806040525081019061366291906159a5565b60015b6136e8573d8060008114613695576040519150601f19603f3d011682016040523d82523d6000602084013e61369a565b606091505b506000815114156136e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136d790615826565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161491505061373d565b600190505b949350505050565b600080823b905060008111915050919050565b82805461376490614248565b90600052602060002090601f01602090048101928261378657600085556137cd565b82601f1061379f57805160ff19168380011785556137cd565b828001600101855582156137cd579182015b828111156137cc5782518255916020019190600101906137b1565b5b5090506137da91906137de565b5090565b5b808211156137f75760008160009055506001016137df565b5090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b6138228161380f565b811461382d57600080fd5b50565b60008135905061383f81613819565b92915050565b6000806040838503121561385c5761385b613805565b5b600061386a85828601613830565b925050602061387b85828601613830565b9150509250929050565b60008115159050919050565b61389a81613885565b82525050565b60006020820190506138b56000830184613891565b92915050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6138f0816138bb565b81146138fb57600080fd5b50565b60008135905061390d816138e7565b92915050565b60006020828403121561392957613928613805565b5b6000613937848285016138fe565b91505092915050565b600060ff82169050919050565b61395681613940565b82525050565b6000602082019050613971600083018461394d565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156139b1578082015181840152602081019050613996565b838111156139c0576000848401525b50505050565b6000601f19601f8301169050919050565b60006139e282613977565b6139ec8185613982565b93506139fc818560208601613993565b613a05816139c6565b840191505092915050565b60006020820190508181036000830152613a2a81846139d7565b905092915050565b600060208284031215613a4857613a47613805565b5b6000613a5684828501613830565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000613a8a82613a5f565b9050919050565b613a9a81613a7f565b82525050565b6000602082019050613ab56000830184613a91565b92915050565b613ac481613a7f565b8114613acf57600080fd5b50565b600081359050613ae181613abb565b92915050565b60008060408385031215613afe57613afd613805565b5b6000613b0c85828601613ad2565b9250506020613b1d85828601613830565b9150509250929050565b600080fd5b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613b69826139c6565b810181811067ffffffffffffffff82111715613b8857613b87613b31565b5b80604052505050565b6000613b9b6137fb565b9050613ba78282613b60565b919050565b600067ffffffffffffffff821115613bc757613bc6613b31565b5b613bd0826139c6565b9050602081019050919050565b82818337600083830152505050565b6000613bff613bfa84613bac565b613b91565b905082815260208101848484011115613c1b57613c1a613b2c565b5b613c26848285613bdd565b509392505050565b600082601f830112613c4357613c42613b27565b5b8135613c53848260208601613bec565b91505092915050565b60008060408385031215613c7357613c72613805565b5b600083013567ffffffffffffffff811115613c9157613c9061380a565b5b613c9d85828601613c2e565b9250506020613cae85828601613830565b9150509250929050565b613cc18161380f565b82525050565b6000602082019050613cdc6000830184613cb8565b92915050565b600080600060608486031215613cfb57613cfa613805565b5b6000613d0986828701613ad2565b9350506020613d1a86828701613ad2565b9250506040613d2b86828701613830565b9150509250925092565b600060208284031215613d4b57613d4a613805565b5b600082013567ffffffffffffffff811115613d6957613d6861380a565b5b613d7584828501613c2e565b91505092915050565b600060208284031215613d9457613d93613805565b5b6000613da284828501613ad2565b91505092915050565b60008060408385031215613dc257613dc1613805565b5b600083013567ffffffffffffffff811115613de057613ddf61380a565b5b613dec85828601613c2e565b9250506020613dfd85828601613ad2565b9150509250929050565b60008060408385031215613e1e57613e1d613805565b5b6000613e2c85828601613830565b925050602083013567ffffffffffffffff811115613e4d57613e4c61380a565b5b613e5985828601613c2e565b9150509250929050565b613e6c81613885565b8114613e7757600080fd5b50565b600081359050613e8981613e63565b92915050565b60008060408385031215613ea657613ea5613805565b5b6000613eb485828601613ad2565b9250506020613ec585828601613e7a565b9150509250929050565b600067ffffffffffffffff821115613eea57613ee9613b31565b5b613ef3826139c6565b9050602081019050919050565b6000613f13613f0e84613ecf565b613b91565b905082815260208101848484011115613f2f57613f2e613b2c565b5b613f3a848285613bdd565b509392505050565b600082601f830112613f5757613f56613b27565b5b8135613f67848260208601613f00565b91505092915050565b60008060008060808587031215613f8a57613f89613805565b5b6000613f9887828801613ad2565b9450506020613fa987828801613ad2565b9350506040613fba87828801613830565b925050606085013567ffffffffffffffff811115613fdb57613fda61380a565b5b613fe787828801613f42565b91505092959194509250565b613ffc81613940565b811461400757600080fd5b50565b60008135905061401981613ff3565b92915050565b60006020828403121561403557614034613805565b5b60006140438482850161400a565b91505092915050565b6000806040838503121561406357614062613805565b5b600061407185828601613ad2565b925050602061408285828601613ad2565b9150509250929050565b600080604083850312156140a3576140a2613805565b5b60006140b185828601613830565b92505060206140c285828601613ad2565b9150509250929050565b7f7072696365206d7573742062652067726561746572207468616e20393920776560008201527f6900000000000000000000000000000000000000000000000000000000000000602082015250565b6000614128602183613982565b9150614133826140cc565b604082019050919050565b600060208201905081810360008301526141578161411b565b9050919050565b7f796f7520617265206e6f7420746865206f776e6572206f66207468697320746f60008201527f6b656e2c20796f752063616e206e6f742073656c6c2069740000000000000000602082015250565b60006141ba603883613982565b91506141c58261415e565b604082019050919050565b600060208201905081810360008301526141e9816141ad565b9050919050565b60006040820190506142056000830185613cb8565b6142126020830184613cb8565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061426057607f821691505b6020821081141561427457614273614219565b5b50919050565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b60006142d6602c83613982565b91506142e18261427a565b604082019050919050565b60006020820190508181036000830152614305816142c9565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b6000614368602183613982565b91506143738261430c565b604082019050919050565b600060208201905081810360008301526143978161435b565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b60006143fa603883613982565b91506144058261439e565b604082019050919050565b60006020820190508181036000830152614429816143ed565b9050919050565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b600061448c603183613982565b915061449782614430565b604082019050919050565b600060208201905081810360008301526144bb8161447f565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006144f8602083613982565b9150614503826144c2565b602082019050919050565b60006020820190508181036000830152614527816144eb565b9050919050565b7f746f6b656e206e6f7420666f722073616c650000000000000000000000000000600082015250565b6000614564601283613982565b915061456f8261452e565b602082019050919050565b6000602082019050818103600083015261459381614557565b9050919050565b7f796f7520617265206e6f7420746865206f776e6572206f66207468697320746f60008201527f6b656e2c20736f20796f752063616e6e6f742064652d6c697374206974000000602082015250565b60006145f6603d83613982565b91506146018261459a565b604082019050919050565b60006020820190508181036000830152614625816145e9565b9050919050565b6000819050919050565b6000819050919050565b600061465b6146566146518461462c565b614636565b61380f565b9050919050565b61466b81614640565b82525050565b60006040820190506146866000830185613cb8565b6146936020830184614662565b9392505050565b7f546f6b656e494420646f6573206e6f7420657869737421000000000000000000600082015250565b60006146d0601783613982565b91506146db8261469a565b602082019050919050565b600060208201905081810360008301526146ff816146c3565b9050919050565b600081905092915050565b600061471c82613977565b6147268185614706565b9350614736818560208601613993565b80840191505092915050565b600061474e8284614711565b915081905092915050565b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b60006147b5602983613982565b91506147c082614759565b604082019050919050565b600060208201905081810360008301526147e4816147a8565b9050919050565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b6000614847602a83613982565b9150614852826147eb565b604082019050919050565b600060208201905081810360008301526148768161483a565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006148b78261380f565b91506148c28361380f565b9250828210156148d5576148d461487d565b5b828203905092915050565b7f7061796d656e74206e6f742073756666696369656e7400000000000000000000600082015250565b6000614916601683613982565b9150614921826148e0565b602082019050919050565b6000602082019050818103600083015261494581614909565b9050919050565b7f7468697320737472696e672068617320616c7265616479206265656e206d696e60008201527f7465640000000000000000000000000000000000000000000000000000000000602082015250565b60006149a8602383613982565b91506149b38261494c565b604082019050919050565b600060208201905081810360008301526149d78161499b565b9050919050565b60008190508160005260206000209050919050565b60008154614a0081614248565b614a0a8186614706565b94506001821660008114614a255760018114614a3657614a69565b60ff19831686528186019350614a69565b614a3f856149de565b60005b83811015614a6157815481890152600182019150602081019050614a42565b838801955050505b50505092915050565b6000614a7e82846149f3565b915081905092915050565b6000614a948261380f565b9150614a9f8361380f565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615614ad857614ad761487d565b5b828202905092915050565b7f796f7520617265206e6f7420746865206f776e6572206f66207468697320746f60008201527f6b656e2c20736f20796f752063616e6e6f7420617070656e6420746f20697400602082015250565b6000614b3f603f83613982565b9150614b4a82614ae3565b604082019050919050565b60006020820190508181036000830152614b6e81614b32565b9050919050565b7f7468697320746f6b656e206973206c6f636b65642c20736f206974206d61792060008201527f6e6f74206265206d6f6469666965640000000000000000000000000000000000602082015250565b6000614bd1602f83613982565b9150614bdc82614b75565b604082019050919050565b60006020820190508181036000830152614c0081614bc4565b9050919050565b7f7468697320746f6b656e20697320757020666f722073616c652c20736f20697460008201527f2063616e6e6f7420626520617070656e656420746f0000000000000000000000602082015250565b6000614c63603583613982565b9150614c6e82614c07565b604082019050919050565b60006020820190508181036000830152614c9281614c56565b9050919050565b6000614ca58285614711565b9150614cb18284614711565b91508190509392505050565b6000604082019050614cd26000830185613cb8565b614cdf6020830184613a91565b9392505050565b7f726f79616c7479206d7573742062652062656c6f772031303025000000000000600082015250565b6000614d1c601a83613982565b9150614d2782614ce6565b602082019050919050565b60006020820190508181036000830152614d4b81614d0f565b9050919050565b60008190508160005260206000209050919050565b60008154614d7481614248565b614d7e8186614706565b94506001821660008114614d995760018114614daa57614ddd565b60ff19831686528186019350614ddd565b614db385614d52565b60005b83811015614dd557815481890152600182019150602081019050614db6565b838801955050505b50505092915050565b6000614df28285614d67565b9150614dfe8284614711565b91508190509392505050565b7f7b0a09226e616d65223a2022496e2057726974696e6720230000000000000000600082015250565b6000614e40601883614706565b9150614e4b82614e0a565b601882019050919050565b7f222c0a0922737472696e67223a20220000000000000000000000000000000000600082015250565b6000614e8c600f83614706565b9150614e9782614e56565b600f82019050919050565b7f222c0a092265787465726e616c5f75726c223a20220000000000000000000000600082015250565b6000614ed8601583614706565b9150614ee382614ea2565b601582019050919050565b7f222c0a09226465736372697074696f6e223a2022000000000000000000000000600082015250565b6000614f24601483614706565b9150614f2f82614eee565b601482019050919050565b7f222c0a0922746f6b656e4964223a202200000000000000000000000000000000600082015250565b6000614f70601083614706565b9150614f7b82614f3a565b601082019050919050565b7f222c0a0922696d6167655f64617461223a202200000000000000000000000000600082015250565b6000614fbc601383614706565b9150614fc782614f86565b601382019050919050565b7f220a7d0000000000000000000000000000000000000000000000000000000000600082015250565b6000615008600383614706565b915061501382614fd2565b600382019050919050565b600061502982614e33565b9150615035828a614711565b915061504082614e7f565b915061504c8289614711565b915061505782614ecb565b91506150638288614d67565b915061506f8287614711565b915061507a82614f17565b91506150868286614d67565b915061509182614f63565b915061509d8285614711565b91506150a882614faf565b91506150b48284614711565b91506150bf82614ffb565b915081905098975050505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061510a8261380f565b91506151158361380f565b925082615125576151246150d0565b5b828204905092915050565b600061513b8261380f565b91506151468361380f565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0382111561517b5761517a61487d565b5b828201905092915050565b7f696e73756666696369656e742076616c75650000000000000000000000000000600082015250565b60006151bc601283613982565b91506151c782615186565b602082019050919050565b600060208201905081810360008301526151eb816151af565b9050919050565b60006151fd82613940565b915061520883613940565b92508282101561521b5761521a61487d565b5b828203905092915050565b7f796f7520617265206e6f7420746865206f776e6572206f66207468697320746f60008201527f6b656e0000000000000000000000000000000000000000000000000000000000602082015250565b6000615282602383613982565b915061528d82615226565b604082019050919050565b600060208201905081810360008301526152b181615275565b9050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b6000615314602683613982565b915061531f826152b8565b604082019050919050565b6000602082019050818103600083015261534381615307565b9050919050565b7f5468697320746f6b656e20697320757020666f722073616c652c206974206d7560008201527f73742062652064652d6c6973746564206265666f72652069742063616e20617060208201527f70726f766520616e206164647265737300000000000000000000000000000000604082015250565b60006153cc605083613982565b91506153d78261534a565b606082019050919050565b600060208201905081810360008301526153fb816153bf565b9050919050565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b600061545e602c83613982565b915061546982615402565b604082019050919050565b6000602082019050818103600083015261548d81615451565b9050919050565b7f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008201527f73206e6f74206f776e0000000000000000000000000000000000000000000000602082015250565b60006154f0602983613982565b91506154fb82615494565b604082019050919050565b6000602082019050818103600083015261551f816154e3565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000615582602483613982565b915061558d82615526565b604082019050919050565b600060208201905081810360008301526155b181615575565b9050919050565b7f5468697320746f6b656e20697320757020666f722073616c652c206974206d7560008201527f73742062652064652d6c6973746564206265666f72652069742063616e20626560208201527f207472616e736665727265640000000000000000000000000000000000000000604082015250565b600061563a604c83613982565b9150615645826155b8565b606082019050919050565b600060208201905081810360008301526156698161562d565b9050919050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b60006156a6602083613982565b91506156b182615670565b602082019050919050565b600060208201905081810360008301526156d581615699565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000615712601c83613982565b915061571d826156dc565b602082019050919050565b6000602082019050818103600083015261574181615705565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b600061577e601983613982565b915061578982615748565b602082019050919050565b600060208201905081810360008301526157ad81615771565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000615810603283613982565b915061581b826157b4565b604082019050919050565b6000602082019050818103600083015261583f81615803565b9050919050565b60006158518261380f565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156158845761588361487d565b5b600182019050919050565b600061589a8261380f565b91506158a58361380f565b9250826158b5576158b46150d0565b5b828206905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050919050565b600082825260208201905092915050565b6000615916826158ef565b61592081856158fa565b9350615930818560208601613993565b615939816139c6565b840191505092915050565b60006080820190506159596000830187613a91565b6159666020830186613a91565b6159736040830185613cb8565b8181036060830152615985818461590b565b905095945050505050565b60008151905061599f816138e7565b92915050565b6000602082840312156159bb576159ba613805565b5b60006159c984828501615990565b9150509291505056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212203799ab1ed95b01be7f24eed57c4daaaee06793d3582d43dbe881221a76a9791464736f6c634300080c003368747470733a2f2f696e77726974696e672e696f2f746578742f3f746f6b656e49443d68747470733a2f2f696e77726974696e676170692e636f6d2f696e77726974696e672f6765745f7376672e7068703f746f6b656e49443d

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.