Mumbai Testnet

Token

Soulbound Card (SCARD)
ERC-721

Overview

Max Total Supply

0 SCARD

Holders

3

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-
Balance
0 SCARD
0xc26880a0af2ea0c7e8130e6ec47af756465452e8
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information

Contract Source Code Verified (Exact Match)

Contract Name:
SoulboundCard

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
No with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Multiple files format)

File 16 of 17: SoulboundCard.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./BusinessCard.sol";
import "./Ownable.sol";
import "./IERC721.sol";
import "./IERC721Enumerable.sol";
import "./IERC721Metadata.sol";
import "./Address.sol";
import "./Strings.sol";
import "./ERC165Storage.sol";
import "./SafeMath.sol";
import "./EnumerableSet.sol";

contract SoulboundCard is ERC165Storage, IERC721, IERC721Metadata, IERC721Enumerable, Ownable {
    using SafeMath for uint256;
    using Address for address;
    using EnumerableSet for EnumerableSet.UintSet;
    using EnumerableSet for EnumerableSet.AddressSet;
    using Strings for uint256;

    // Mapping from address to their (enumerable) set of received Soulbound Cards
    mapping (address => EnumerableSet.UintSet) private _receivedTokens;

    // Mapping from token IDs to their (enumerable) set of receiver addresses
    mapping (uint256 => EnumerableSet.AddressSet) private _tokenReceivers;

    // Mapping of addresses that have blakclisted the receiving of Soulbound Cards
    mapping (address => bool) private _blacklistedReceivers;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Main Business Card smart contract
    BusinessCard bCard;

    constructor (string memory name_, string memory symbol_, address _bCard) {

        _name = name_;
        _symbol = symbol_;
        bCard = BusinessCard(_bCard);

        // register the supported interfaces to conform to ERC721 via ERC165
        /*
        *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231
        *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
        *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
        *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
        *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
        *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
        *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
        *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
        *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
        *
        *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
        *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
        */
        _registerInterface(0x80ac58cd);

        /*
        *     bytes4(keccak256('name()')) == 0x06fdde03
        *     bytes4(keccak256('symbol()')) == 0x95d89b41
        *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
        *
        *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
        */
        _registerInterface(0x5b5e139f);

        /*
        *     bytes4(keccak256('totalSupply()')) == 0x18160ddd
        *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
        *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
        *
        *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
        */
        _registerInterface(0x780e9d63);
    }

    /**
     * @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 Sends a copy of the Business Card specified by tokenId as a Soulbound Card to the
     * specified address
     */
    function sendSoulboundCard(address from, address receiver, uint256 tokenId) external {
        require(_isApprovedOrOwner(msg.sender, tokenId), "SCARD: caller is not owner nor approved");
        require(bCard.ownerOf(tokenId) == from, "SCARD: sending card that is not own");
        require(receiver != address(0), "SCARD: sending to zero address");
        require(receiver != from, "SCARD: sending to owner");
        require(!_blacklistedReceivers[receiver], "SCARD: receiver blacklisted themselves");
        require(!_receivedTokens[receiver].contains(tokenId), "SCARD: receiver was already sent the Soulbound Card");

        _receivedTokens[receiver].add(tokenId);
        _tokenReceivers[tokenId].add(receiver);

        emit Transfer(from, receiver, tokenId);
    }

    /**
     * @dev Burns a specific Soulbound Card that was sent to msg.sender
     */
    function burnSoulboundCard(address receiver, uint256 toBurn) external {
        require(
            msg.sender == receiver || _isApprovedOrOwner(msg.sender, toBurn),
            "SCARD: caller is not owner nor approved"   
        );
        require(_receivedTokens[receiver].contains(toBurn), "SCARD: token not in receiver's list");
        _burnSoulboundCard(receiver, toBurn);
    }

    /**
     * @dev Burns a specific Soulbound Card that was sent to msg.sender
     */
    function _burnSoulboundCard(address receiver, uint256 toBurn) internal {
        require(
            // Remove the Soulbound Card from the set of tokens address `receiver` received
            _receivedTokens[receiver].remove(toBurn)
            &&
            // Remove the address `receiver` from the set of receivers for the Soulbound Card `tokenId`
            _tokenReceivers[toBurn].remove(receiver)
            ,
            "SCARD: token not on the set"
        );
        
        emit Transfer(receiver, address(0), toBurn);
    }

    /**
     * @dev Burns the specified Soulbound Cards associated with a Business Card `tokenId`
     */
    function burnSoulboundCardsOfToken(uint256 tokenId, address[] calldata toBurn) external { 
        require(
            msg.sender == address(bCard) || _isApprovedOrOwner(msg.sender, tokenId),
            "SCARD: caller is not BCARD contract nor owner nor approved"   
        );
        // To clean an EnumerableSet, we remove all elements one by one
        for (uint256 i = 0; i < toBurn.length; i++) {
            address receiver = toBurn[i];
            _burnSoulboundCard(receiver, tokenId);
        }
    }
    
    /**
     * @dev Burns the specified Soulbound Cards associated with a Business Card `tokenId`
     */
    function burnAllSoulboundCardsOfToken(uint256 tokenId) external { 
        require(
            msg.sender == address(bCard) || _isApprovedOrOwner(msg.sender, tokenId),
            "SCARD: caller is not BCARD contract nor owner nor approved"   
        );
        // To clean an EnumerableSet, we remove all elements one by one
        address[] memory toBurn = _tokenReceivers[tokenId].values();
        for (uint256 i = 0; i < toBurn.length; i++) {
            address receiver = toBurn[i];
            _burnSoulboundCard(receiver, tokenId);
        }
    }
    

    /**
     * @dev Burns all the Soulbound Cards that were sent to the specified address `toDisable`
     * Caller must be the specified address or an approved operator
     */
    function burnReceivedSoulboundCards(address receiver, uint256[] calldata toBurn) external {
        require(
            msg.sender == receiver || isApprovedForAll(receiver, msg.sender)
            , 
            "SCARD: caller is not receiver nor approved for all"
        );
        // To clean an EnumerableSet, we remove all elements one by one
        for (uint256 i = 0; i < toBurn.length; ++i) {
            uint256 cardId = toBurn[i];
            _burnSoulboundCard(receiver, cardId);
        }
    }

    /**
     * @dev Blacklists the specified address from receiving any additional sCards
     * Caller must be the specified address or an approved operator
     */
    function disableSoulboundCardsForAddress(address toDisable) external {
        require(msg.sender == toDisable || isApprovedForAll(toDisable, msg.sender), "SCARD: caller is not owner nor approved for all");
        _blacklistedReceivers[toDisable] = true;
    }

    /**
     * @dev Returns if address `receiver` is blacklisted from getting Soulbound Cards 
     */
    function isBlacklisted(address receiver) external view returns (bool blacklisted) {
        blacklisted = _blacklistedReceivers[receiver];
    }

    /**
     * @dev Returns the Soulbound Card tokenURI, which is linked to the Business Card tokenURI
     */
    function tokenURI(uint256 tokenId) external view override returns (string memory) {
        return bCard.tokenURI(tokenId);
    }
    
    /**
     * @dev See {IERC721-ownerOf}.
     *
     * Here owner represents ownership of the original Business Card
     */
    function ownerOf(uint256 _tokenId) public view virtual override returns (address) {
        return bCard.ownerOf(_tokenId);
    }

    /**
     * @dev See {IERC721-balanceOf}.
     *
     * Returns the number of Soulbound Cards received by an address
     */
    function balanceOf(address _owner) public view virtual override returns (uint256) {
        require(_owner != address(0), "ERC721: balance query for the zero address");
        return _receivedTokens[_owner].length();
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     *
     * The `totalSupply` is defined as the number of Soulbound Cards that have been sent
     */
    function totalSupply() public view virtual override returns (uint256 count) {
        uint256 nTokens = bCard.totalSupply();
        for (uint256 i = 1; i <= nTokens; ++i) {
            count += _tokenReceivers[i].length();
        }
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     *
     * Returns the Soulbound Card received by an address at a given index
     */
    function tokenOfOwnerByIndex(address _owner, uint256 index) public view virtual override returns (uint256) {
        require(index < balanceOf(_owner), "Index out of bounds");
        return _receivedTokens[_owner].at(index);
    }

    /**
     * @dev Returns the list of addresses that received a copy of a given `tokenId` Business Card
     * as a Soulbound Card
     */
    function soulboundCardReceivers(uint256 tokenId) public view returns (address[] memory) {
        return _tokenReceivers[tokenId].values();
    }

    /**
     * @dev Returns the list of Soulbound Cards that an address `receiver` got
     */
    function receivedSoulboundCards(address receiver) public view returns (uint256[] memory) {
        return _receivedTokens[receiver].values();
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     *
     * Returns the corresponding Business Card by index
     */
    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
        return bCard.tokenByIndex(index);
    }

    /**
     * @dev See {IERC721-approve}.
     *
     * Only present to be ERC721 compliant. Soulbound Cards cannot be approved for spending
     * as they are not transferable. Granting the corresponding Business Card approval for
     * spending also allows them to send Soulbound Cards.
     */
    function approve(address /* _approved */, uint256 /* _tokenId */) public pure virtual override {
        revert("SCARD: cannot approve Soulbound Cards");
    }

    /**
     * @dev See {IERC721-getApproved}.
     *
     * Returns the address that is approved to spend the BusinessCard `tokenId`.
     */
    function getApproved(uint256 tokenId) public view virtual override returns (address) {
        return bCard.getApproved(tokenId);
    }

    /**
     * @dev See {IERC721-setApprovalForAll}.
     *
     * Only present to be ERC721 compliant. Soulbound Cards cannot be approved for spending
     * as they are not transferable. Granting the corresponding Business Card approval for
     * spending also allows them to send Soulbound Cards.
     */
    function setApprovalForAll(address /* _operator */, bool /* _approved */) public pure virtual override {
        revert("SCARD: cannot approve Soulbound Cards");
    }

    /**
     * @dev See {IERC721-isApprovedForAll}.
     *
     * Returns if an address is approved to spend any of the `owner`'s Business Cards.
     */
    function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {
        return bCard.isApprovedForAll(owner, operator);
    }

    /**
     * @dev See {IERC721-transferFrom}.
     *
     * Only present to be ERC721 compliant. Soulbound Cards cannot be transferred. They can
     * be sent by the Business Card owner or approved address, and can be burned by either
     * the recipient or Business Card owner or approved address.
     */
    function transferFrom(address /* from */, address /* to */, uint256 /* tokenId */) public pure virtual override {
        revert("SCARD: cannot transfer Soulbound Cards");
    }

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

    /**
     * @dev See {IERC721-safeTransferFrom}.
     *
     * Only present to be ERC721 compliant. Soulbound Cards cannot be transferred. They can
     * be sent by the Business Card owner or approved address, and can be burned by either
     * the recipient or Business Card owner or approved address.
     */
    function safeTransferFrom(address /* from */, address /* to */, uint256 /* tokenId */, bytes memory /* _data */) public pure virtual override {
        revert("SCARD: cannot transfer Soulbound Cards");
    }

    /**
     * @dev Returns whether `spender` is allowed to manage the BusinessCard `tokenId`.
     *
     * Requirements:
     *
     * - A Business Card by `tokenId` must exist.
     */
    function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {
        address owner = bCard.ownerOf(tokenId);
        return (spender == owner || bCard.getApproved(tokenId) == spender || bCard.isApprovedForAll(owner, spender));
    }
    
}

File 1 of 17: Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @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
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 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
                /// @solidity memory-safe-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 2 of 17: BusinessCard.sol
// SPDX-License-Identifier: MIT

// Because every self-respected businessman needs his business card

pragma solidity ^0.8.0;

import "./BusinessCardUtils.sol";
import "./Ownable.sol";
import "./IERC721.sol";
import "./IERC721Enumerable.sol";
import "./IERC721Metadata.sol";
import "./IERC721Receiver.sol";
import "./Address.sol";
import "./Context.sol";
import "./Strings.sol";
import "./ERC165Storage.sol";
import "./SafeMath.sol";
import "./EnumerableMap.sol";
import "./EnumerableSet.sol";

contract ISoulboundCard {

    function burnAllSoulboundCardsOfToken(uint256 tokenId) external { }

} 

/**
 * @title NFT Business Card smart contract
 * @dev compliant with https://eips.ethereum.org/EIPS/eip-721
 */
contract BusinessCard is ERC165Storage, IERC721, IERC721Metadata, IERC721Enumerable, Ownable {
    using SafeMath for uint256;
    using Address for address;
    using EnumerableSet for EnumerableSet.UintSet;
    using EnumerableMap for EnumerableMap.UintToAddressMap;
    using Strings for uint256;

    // Mapping from holder address to their (enumerable) set of owned tokens
    mapping (address => EnumerableSet.UintSet) private _holderTokens;

    // Enumerable mapping from token ids to their owners
    EnumerableMap.UintToAddressMap private _tokenOwners;

    // 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;

    // Token name
    string private _name;

    // Token symbol
    string private _symbol;

    // Mapping for token URIs
    mapping (uint256 => string) private _tokenURIs;

    // Base URI
    string private _baseURI;

    // Public variables
    uint256 public constant maxSupply = 1111;
    bool public saleStarted;

    // Random nonce for generating genes
    uint256 private randNonce;

    struct Card {
        uint256 genes;
        string name;
    }

    // Mapping from token ID to genes
    mapping (uint256 => Card) private _tokenStats;
    // Mapping for reserved names, reserved names are stored in lowercase
    mapping (string => bool) private _nameReserved;

    // Values sent in the event when minting / updating a card
    // All the metadata attributes that do NOT get stored on chain
    struct CardProperties {
        string position;
        string twitterAccount;
        string telegramAccount;
        string telegramGroup;
        uint256 discordAccount;
        string discordGroup;
        string githubUsername;
        string website;
    }

    // Default URI
    string private _defaultURI;

    // Address of the oracle
    address private serverOracle;
    // Requests made to the NFT oracle
    mapping(uint256 => bool) public requests;

    // Marketplace address
    address private bCardMarketplace;
    // sCard address - SoulboundCards
    ISoulboundCard private sCard;

    // Token mint price
    uint256 public mintPrice = 0.1 ether;
    // Token URI update / swap price
    uint256 public updatePrice = 0.05 ether;
    // Oracle update transaction gas price
    uint256 public oraclePrice = 0.015 ether;

    // Oracle related events
    event UpdateRequest(uint256 tokenId, uint256 genes, string name, CardProperties cardProperties);
    event SwapRequest(uint256 tokenId1, uint256 tokenId2, uint256 genes1, uint256 genes2);
    event TokenURIUpdated(uint256 tokenId, string tokenURI);

    /**
     * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection, and defining base and default URIs.
     */
    constructor (string memory name_, string memory symbol_, string memory baseURI_, string memory defaultURI_) {
        _name = name_;
        _symbol = symbol_;
        _baseURI = baseURI_;
        _defaultURI = defaultURI_;

        // register the supported interfaces to conform to ERC721 via ERC165
        /*
        *     bytes4(keccak256('balanceOf(address)')) == 0x70a08231
        *     bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
        *     bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
        *     bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
        *     bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
        *     bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
        *     bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
        *     bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
        *     bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
        *
        *     => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
        *        0xa22cb465 ^ 0xe985e9c5 ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
        */
        _registerInterface(0x80ac58cd);

        /*
        *     bytes4(keccak256('name()')) == 0x06fdde03
        *     bytes4(keccak256('symbol()')) == 0x95d89b41
        *     bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
        *
        *     => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
        */
        _registerInterface(0x5b5e139f);

        /*
        *     bytes4(keccak256('totalSupply()')) == 0x18160ddd
        *     bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
        *     bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
        *
        *     => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
        */
        _registerInterface(0x780e9d63);
    }
    
    /**
     * @dev Sets up a new oracle that handles the dynamic aspect of the NFT
     */
    function setOracle(address _serverOracle) external onlyOwner {
        serverOracle = _serverOracle;
    }

    /**
     * @dev Sets up a Marketplace allowing the native trading of Business Cards
     */
    function setMarketplace(address _marketplace) external onlyOwner {
        bCardMarketplace = _marketplace;
    }

    /**
     * @dev Sets up the sCard address for interaction
     */
    function setSoulboundCard(address _soulbound) external onlyOwner {
        sCard = ISoulboundCard(_soulbound);
    }

    /**
     * @dev Changes the update price for the usage of the oracle
     */
    function modifyUpdatePrice(uint256 newUpdatePrice) external onlyOwner {
        require(newUpdatePrice >= oraclePrice); // dev: Update price must always cover the gas costs of running the oracle
        updatePrice = newUpdatePrice;
    }

    /**
     * @dev Calls the oracle to update a certain token URI with the newly defined Card struct
     */
    function _updateTokenURI(uint256 _tokenId, uint256 _genes, string calldata _cardName, CardProperties calldata _cardProperties) internal {
        require(BusinessCardUtils.validateOtherProperties(_cardProperties));  // Other properties are not valid
        require(_exists(_tokenId));
        // Calls for updating the token can only be made if it is not being processed already
        require(requests[_tokenId] == false, "Update being processed");
        requests[_tokenId] = true;
        // Fund the server oracle with enough funds for the updateCallback transaction
        payable(serverOracle).transfer(oraclePrice);
        // Emit event to be catched by the server oracle running off-chain
        emit UpdateRequest(_tokenId, _genes, _cardName, _cardProperties);
    }

    /**
     * @dev Updates a certain token URI and clears the corresponding update request
     * Only the assigned server oracle is allowed to call this function
     */
     function updateCallback(uint256 _tokenId, string memory _tokenURI) external {
        _callback(_tokenId, _tokenURI);
    }

    /**
     * @dev Updates a certain token URI and clears the corresponding update request
     * Only the assigned server oracle is allowed to call this function
     */
     function swapCallback(uint256 _tokenId1, uint256 _tokenId2, string memory _tokenURI1, string memory _tokenURI2) external {
        _callback(_tokenId1, _tokenURI1);
        _callback(_tokenId2, _tokenURI2);
    }

    /**
     * @dev Updates a certain token URI and clears the corresponding update request
     * Only the assigned server oracle is allowed to call this function
     */
     function _callback(uint256 _tokenId, string memory _tokenURI) internal {
        require(_msgSender() == serverOracle); // dev: Only the assigned oracle can call this function
        require(requests[_tokenId]); // dev: Request not in pending list
        _tokenURIs[_tokenId] = _tokenURI;
        delete requests[_tokenId];
        emit TokenURIUpdated(_tokenId, _tokenURI);
     }

     /**
     * @dev Mints a new NFT Business Card
     */
    function getCard(string calldata _cardName, CardProperties calldata _cardProperties) public payable {
        require(saleStarted == true);  // dev: sale not started or paused, can be managed on frontend
        require(totalSupply() < maxSupply);  // dev: sale has ended, can be managed on frontend
        require(msg.value >= mintPrice);  // dev: value sent is below the price, can be managed on frontend
        // Minting a new NFT with the name and position provided
        _safeMint(_msgSender(), totalSupply() + 1, _cardName, _cardProperties);
    }

    /**
     * @dev Safely mints `tokenId` and transfers it to `to`.
     *
     * Requirements:
     d*
     * - `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, string calldata _cardName, CardProperties calldata _cardProperties) internal virtual {
        require(
            BusinessCardUtils.validateName(_cardName) &&
            isNameReserved(_cardName) == false, 
            "Name taken or not valid"
        );
        require(
            BusinessCardUtils.validatePosition(_cardProperties.position), 
            "Position not valid"
        );

        // Generating the random genes, defined by a 26 digit number
        // The server oracle will convert the genes to a string and add leading zeros, as tokenURIs are generated with this constraint
        uint256 genes = uint(keccak256(abi.encodePacked(block.timestamp, msg.sender, _cardName, randNonce))) % 10**30;
        randNonce++;
        
        // Generating a new card
        toggleReserveName(_cardName, true);
        _tokenStats[_tokenId] = Card(genes, _cardName);
        _safeMint(_to, _tokenId, abi.encodePacked(_cardName, genes));
        _updateTokenURI(_tokenId, genes, _cardName, _cardProperties);
    }

    /**
     * @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 Changes the name and/or position of a given NFT, must be owned by the caller.
     * Whenever such change is made, it is first immediately reflected in the Card struct, and in the metadata after oracle updates.
     * User can change both name and position, just the name, or just the position (by leaving those inputs empty)
     */
    function updateCard(uint256 tokenId, string calldata newName, CardProperties calldata newCardProperties) public payable {
        require(saleStarted == true);  // dev: updates paused, can be managed on frontend
        require(_isApprovedOrOwner(_msgSender(), tokenId), "Caller is not owner nor approved");
        require(
            isNameReserved(newName) == false &&
            (
                bytes(newName).length == 0 
                ||
                BusinessCardUtils.validateName(newName) == true
            )
            , 
            "Name taken or not valid"
        );
        require(
            bytes(newCardProperties.position).length == 0
            ||
            BusinessCardUtils.validatePosition(newCardProperties.position) == true
            , 
            "Position not valid"
        );
        require(
            msg.value >= updatePrice || _msgSender() == bCardMarketplace
        );  // dev: value sent is below the price, can be managed on frontend

        // Only change the name if specified
        if (bytes(newName).length > 0) {
            // De-reserve the old name
            toggleReserveName(_tokenStats[tokenId].name, false);
            // Reserve the new name
            toggleReserveName(newName, true);
            // Changing the token name
            _tokenStats[tokenId].name = newName;
        }

        // Make new tokenURI update request
        _updateTokenURI(tokenId, _tokenStats[tokenId].genes, newName, newCardProperties);
    }

    /**
     * @dev Swaps the name and position between two NFTs, must be owned by the caller.
     * This is to give customers the ability to directly shuffle name and positions of their
     * cards, and prevent possible "name snipers"
     */
    function swapCards(uint256 tokenId1, uint256 tokenId2) public payable {
        require(saleStarted == true);  // dev: updates paused, can be managed on frontend
        require(
            _isApprovedOrOwner(_msgSender(), tokenId1) &&
            _isApprovedOrOwner(_msgSender(), tokenId2), 
            "Caller is not owner nor approved"
        );
        require(msg.value >= updatePrice);  // dev: value sent is below the price, can be managed on frontend
        // Calls for updating the token can only be made if it is not being processed already
        require(requests[tokenId1] == false && requests[tokenId2] == false, "Update being processed");

        // Swapping names between tokens
        string memory name1 = _tokenStats[tokenId1].name;
        _tokenStats[tokenId1].name = _tokenStats[tokenId2].name;
        _tokenStats[tokenId2].name = name1;

        // Requests now pending
        requests[tokenId1] = true;
        requests[tokenId2] = true;

        // Emitting a single swap request to the oracle -- processed differently
        emit SwapRequest(tokenId1, tokenId2, _tokenStats[tokenId1].genes, _tokenStats[tokenId2].genes);

        // Fund the server oracle with enough funds for the swapCallback transaction
        payable(serverOracle).transfer(oraclePrice);
    }

    /**
     * @dev Updates the tokenURI, intented to be used only when oracle fails to update a tokenURI
     */
    function updateTokenURI(uint256 tokenId, string calldata cardName, CardProperties calldata _cardProperties) external onlyOwner {
        _updateTokenURI(tokenId, _tokenStats[tokenId].genes, cardName, _cardProperties);
    }

    /**
     * @dev Starts the sale, cannot do so until the oracle is defined
     */
    function startSale() external onlyOwner {
        require(serverOracle != address(0));  // dev: Oracle not defined
        saleStarted = true;
    }

    /**
     * @dev Pauses the sale
     */
    function pauseSale() external onlyOwner {
        saleStarted = false;
    }

    /**
     * @dev Returns the stats of a token
     */
    function tokenStats(uint256 tokenId) public view returns (Card memory) {
        return _tokenStats[tokenId];
    }

    /**
     * @dev Overrides the default tokenURI behaviour to include the default URI
     */
    function tokenURI(uint256 tokenId) external view override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        string memory token = _tokenURIs[tokenId];

        // If there is no tokenURI, returns the defaultURI, which must be defined after deployment
        if (bytes(token).length == 0) {
            return string(abi.encodePacked( baseURI(), defaultURI() ));
        } else {
            return string(abi.encodePacked( baseURI(), token ));
        }
    }

    /**
     * @dev For setting the baseURI for all tokenId's.
     */
    function setBaseURI(string memory newBaseURI) external onlyOwner {
        require(bytes(newBaseURI).length > 0);
        _baseURI = newBaseURI;
    }

    /**
    * @dev Returns the default URI set via {_setBaseURI}. This will be
    * automatically added as a prefix in {tokenURI} to each token's URI, or
    * to the token ID if no specific URI is set for that token ID.
    */
    function defaultURI() public view virtual returns (string memory) {
        return _defaultURI;
    }

    /**
     * @dev For setting the default URI for all tokenId's. 
     */
    function setDefaultURI(string calldata newDefaultURI) external onlyOwner {
        require(bytes(newDefaultURI).length > 0);  // dev: cannot be set to empty string
        _defaultURI = newDefaultURI;
    }

    /**
     * @dev Returns if the name has been reserved.
     * Name reservation checks are made in lowercase
     */
    function isNameReserved(string calldata nameString) public view returns (bool) {
        return _nameReserved[BusinessCardUtils.toLower(nameString)];
    }

    /**
     * @dev Reserves the name if isReserve is set to true, de-reserves if set to false
     * Names are reserved in lowercase, but stored in whatever case the user gave
     */
    function toggleReserveName(string memory str, bool isReserve) internal {
        _nameReserved[BusinessCardUtils.toLower(str)] = isReserve;
    }

    /**
     * @dev Withdraw balance from this contract (Callable by owner)
    */
    function withdraw() onlyOwner external {
        uint balance = address(this).balance;
        payable(msg.sender).transfer(balance);
    }

    /**
     * @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 _holderTokens[owner].length();
    }

    /**
     * @dev See {IERC721-ownerOf}.
     */
    function ownerOf(uint256 tokenId) public view virtual override returns (address) {
        return _tokenOwners.get(tokenId, "ERC721: owner query for nonexistent token");
    }

    /**
     * @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 Returns the base URI set via {_setBaseURI}. This will be
    * automatically added as a prefix in {tokenURI} to each token's URI, or
    * to the token ID if no specific URI is set for that token ID.
    */
    function baseURI() public view virtual returns (string memory) {
        return _baseURI;
    }

    /**
     * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) {
        require(index < balanceOf(owner));  // @dev: index out of bounds
        return _holderTokens[owner].at(index);
    }

    /**
     * @dev See {IERC721Enumerable-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        // _tokenOwners are indexed by tokenIds, so .length() returns the number of tokenIds
        return _tokenOwners.length();
    }

    /**
     * @dev See {IERC721Enumerable-tokenByIndex}.
     */
    function tokenByIndex(uint256 index) public view virtual override returns (uint256) {
        require(index < totalSupply());  // @dev: index out of bounds
        (uint256 tokenId, ) = _tokenOwners.at(index);
        return tokenId;
    }

    /**
     * @dev See {IERC721-approve}.
     */
    function approve(address to, uint256 tokenId) public virtual override {
        address owner = 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 {
        require(operator != _msgSender(), "ERC721: approve to caller");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_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}.
     *
     * If the sCard smart contract was specified, it burns all Soulbound Cards associated 
     * with the Business Card `tokenId` in the process
     */
    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, true);
    }

    /**
     * @dev Works as `transferFrom`, but will not burn the associated Soulbound Cards 
     */
    function transferFromWithoutBurn(address from, address to, uint256 tokenId) public virtual {
        //solhint-disable-next-line max-line-length
        require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
        _transfer(from, to, tokenId, false);
    }

    /**
     * @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, true);
        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 _tokenOwners.contains(tokenId);
    }

    /**
     * @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 = ownerOf(tokenId);
        return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
    }

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

        _holderTokens[_to].add(_tokenId);

        _tokenOwners.set(_tokenId, _to);

        emit Transfer(address(0), _to, _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, bool burn) internal virtual {
        require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); // internal owner
        require(to != address(0), "ERC721: transfer to the zero address");

        // Burn the associated Soulbound Cards
        if (address(sCard) != address(0) && burn) {
            sCard.burnAllSoulboundCardsOfToken(tokenId);
        }

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

        _holderTokens[from].remove(tokenId);
        _holderTokens[to].add(tokenId);

        _tokenOwners.set(tokenId, to);

        emit Transfer(from, to, tokenId);
    }

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

    /**
     * @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()) {
            return true;
        }
        bytes memory returndata = to.functionCall(abi.encodeWithSelector(
            IERC721Receiver(to).onERC721Received.selector,
            _msgSender(),
            from,
            tokenId,
            _data
        ), "ERC721: transfer to non ERC721Receiver implementer");
        bytes4 retval = abi.decode(returndata, (bytes4));
        return (retval == 0x150b7a02);
    }

}

File 3 of 17: BusinessCardUtils.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./BusinessCard.sol";

/**
 * @dev Useful functions for validating the name and position of Business Cards
 */
library BusinessCardUtils {
    /**
     * @dev Check if the name string is valid:
     * Alphanumeric and spaces without leading or trailing space, with maximum characters
     * Must contain at most one space, ensuring a Name SURNAME input.
     */
    function validateName(string calldata str) internal pure returns (bool) {
        bytes memory b = bytes(str);
        // String length requirements
        if(
            b.length == 0 || b.length > 22 || b[0] == 0x20 || b[b.length - 1] == 0x20
        ) return false;
        // Characters check
        require(validateString(str), "Non valid characters");

        // Name is validated 
        return true;
    }

    /**
     * @dev Check if the position string is valid:
     * Alphanumeric and spaces without leading or trailing space, with maximum characters
     */
    function validatePosition(string calldata str) internal pure returns (bool) {
        bytes memory b = bytes(str);
        // String length requirements
        if(
            b.length == 0 || b.length > 32 || b[0] == 0x20 || b[b.length - 1] == 0x20
        ) return false;
        // Characters check
        require(validateString(str), "Non valid characters");

        // Position is validated
        return true;
    }

    /**
     * @dev Validates that string contains valid characters, alphanumerical and some special symbols
     */
    function validateString(string calldata str) internal pure returns (bool) {
        bytes memory b = bytes(str);
        bytes1 lastChar = b[0];

        for(uint i; i<b.length; ++i){
            bytes1 char = b[i];

            if (char == 0x20 && lastChar == 0x20) return false; // Cannot contain continuous spaces

            if(
                !(char >= 0x20 && char <= 0x3F) &&  // Special characters and numbers
                !(char >= 0x41 && char <= 0x5A) &&  // A-Z
                !(char >= 0x61 && char <= 0x7A)  // a-z
            )
                return false;

            lastChar = char;
        }
        return true;
    }

    function validateOtherProperties(BusinessCard.CardProperties calldata cardProperties) internal pure returns (bool) {
        if(
            bytes(cardProperties.twitterAccount).length < 15 &&
            bytes(cardProperties.telegramAccount).length < 32 &&
            bytes(cardProperties.telegramGroup).length < 32 &&
            ((cardProperties.discordAccount >= 10**17 && cardProperties.discordAccount < 10**18) || cardProperties.discordAccount == 0) &&
            bytes(cardProperties.discordGroup).length < 32 &&
            bytes(cardProperties.githubUsername).length < 39 &&
            bytes(cardProperties.website).length < 50
        )
            return true;
        
        return false;
    }

    /**
     * @dev Converts the string to lowercase
     */
    function toLower(string memory str) internal pure returns (string memory){
        bytes memory bStr = bytes(str);
        bytes memory bLower = new bytes(bStr.length);

        for (uint i = 0; i < bStr.length; ++i) {
            // Uppercase character
            if ((uint8(bStr[i]) >= 65) && (uint8(bStr[i]) <= 90)) {
                bLower[i] = bytes1(uint8(bStr[i]) + 32);
            } else {
                bLower[i] = bStr[i];
            }
        }
        return string(bLower);
    }

}

File 4 of 17: 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 5 of 17: EnumerableMap.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableMap.sol)

pragma solidity ^0.8.0;

import "./EnumerableSet.sol";

/**
 * @dev Library for managing an enumerable variant of Solidity's
 * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
 * type.
 *
 * Maps have the following properties:
 *
 * - Entries are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Entries are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableMap for EnumerableMap.UintToAddressMap;
 *
 *     // Declare a set state variable
 *     EnumerableMap.UintToAddressMap private myMap;
 * }
 * ```
 *
 * The following map types are supported:
 *
 * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0
 * - `address -> uint256` (`AddressToUintMap`) since v4.6.0
 * - `bytes32 -> bytes32` (`Bytes32ToBytes32`) since v4.6.0
 * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0
 * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0
 *
 * [WARNING]
 * ====
 *  Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable.
 *  See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 *  In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an array of EnumerableMap.
 * ====
 */
library EnumerableMap {
    using EnumerableSet for EnumerableSet.Bytes32Set;

    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Map type with
    // bytes32 keys and values.
    // The Map implementation uses private functions, and user-facing
    // implementations (such as Uint256ToAddressMap) are just wrappers around
    // the underlying Map.
    // This means that we can only create new EnumerableMaps for types that fit
    // in bytes32.

    struct Bytes32ToBytes32Map {
        // Storage of keys
        EnumerableSet.Bytes32Set _keys;
        mapping(bytes32 => bytes32) _values;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function set(
        Bytes32ToBytes32Map storage map,
        bytes32 key,
        bytes32 value
    ) internal returns (bool) {
        map._values[key] = value;
        return map._keys.add(key);
    }

    /**
     * @dev Removes a key-value pair from a map. O(1).
     *
     * Returns true if the key was removed from the map, that is if it was present.
     */
    function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {
        delete map._values[key];
        return map._keys.remove(key);
    }

    /**
     * @dev Returns true if the key is in the map. O(1).
     */
    function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {
        return map._keys.contains(key);
    }

    /**
     * @dev Returns the number of key-value pairs in the map. O(1).
     */
    function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {
        return map._keys.length();
    }

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

    /**
     * @dev Tries to returns the value associated with `key`.  O(1).
     * Does not revert if `key` is not in the map.
     */
    function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) {
        bytes32 value = map._values[key];
        if (value == bytes32(0)) {
            return (contains(map, key), bytes32(0));
        } else {
            return (true, value);
        }
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) {
        bytes32 value = map._values[key];
        require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key");
        return value;
    }

    /**
     * @dev Same as {_get}, with a custom error message when `key` is not in the map.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {_tryGet}.
     */
    function get(
        Bytes32ToBytes32Map storage map,
        bytes32 key,
        string memory errorMessage
    ) internal view returns (bytes32) {
        bytes32 value = map._values[key];
        require(value != 0 || contains(map, key), errorMessage);
        return value;
    }

    // UintToUintMap

    struct UintToUintMap {
        Bytes32ToBytes32Map _inner;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function set(
        UintToUintMap storage map,
        uint256 key,
        uint256 value
    ) internal returns (bool) {
        return set(map._inner, bytes32(key), bytes32(value));
    }

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

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

    /**
     * @dev Returns the number of elements in the map. O(1).
     */
    function length(UintToUintMap storage map) internal view returns (uint256) {
        return length(map._inner);
    }

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

    /**
     * @dev Tries to returns the value associated with `key`.  O(1).
     * Does not revert if `key` is not in the map.
     */
    function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) {
        (bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
        return (success, uint256(value));
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) {
        return uint256(get(map._inner, bytes32(key)));
    }

    /**
     * @dev Same as {get}, with a custom error message when `key` is not in the map.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryGet}.
     */
    function get(
        UintToUintMap storage map,
        uint256 key,
        string memory errorMessage
    ) internal view returns (uint256) {
        return uint256(get(map._inner, bytes32(key), errorMessage));
    }

    // UintToAddressMap

    struct UintToAddressMap {
        Bytes32ToBytes32Map _inner;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function set(
        UintToAddressMap storage map,
        uint256 key,
        address value
    ) internal returns (bool) {
        return set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
    }

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

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

    /**
     * @dev Returns the number of elements in the map. O(1).
     */
    function length(UintToAddressMap storage map) internal view returns (uint256) {
        return length(map._inner);
    }

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

    /**
     * @dev Tries to returns the value associated with `key`.  O(1).
     * Does not revert if `key` is not in the map.
     *
     * _Available since v3.4._
     */
    function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
        (bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
        return (success, address(uint160(uint256(value))));
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
        return address(uint160(uint256(get(map._inner, bytes32(key)))));
    }

    /**
     * @dev Same as {get}, with a custom error message when `key` is not in the map.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryGet}.
     */
    function get(
        UintToAddressMap storage map,
        uint256 key,
        string memory errorMessage
    ) internal view returns (address) {
        return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage))));
    }

    // AddressToUintMap

    struct AddressToUintMap {
        Bytes32ToBytes32Map _inner;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function set(
        AddressToUintMap storage map,
        address key,
        uint256 value
    ) internal returns (bool) {
        return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value));
    }

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

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

    /**
     * @dev Returns the number of elements in the map. O(1).
     */
    function length(AddressToUintMap storage map) internal view returns (uint256) {
        return length(map._inner);
    }

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

    /**
     * @dev Tries to returns the value associated with `key`.  O(1).
     * Does not revert if `key` is not in the map.
     */
    function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) {
        (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key))));
        return (success, uint256(value));
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function get(AddressToUintMap storage map, address key) internal view returns (uint256) {
        return uint256(get(map._inner, bytes32(uint256(uint160(key)))));
    }

    /**
     * @dev Same as {get}, with a custom error message when `key` is not in the map.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryGet}.
     */
    function get(
        AddressToUintMap storage map,
        address key,
        string memory errorMessage
    ) internal view returns (uint256) {
        return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage));
    }

    // Bytes32ToUintMap

    struct Bytes32ToUintMap {
        Bytes32ToBytes32Map _inner;
    }

    /**
     * @dev Adds a key-value pair to a map, or updates the value for an existing
     * key. O(1).
     *
     * Returns true if the key was added to the map, that is if it was not
     * already present.
     */
    function set(
        Bytes32ToUintMap storage map,
        bytes32 key,
        uint256 value
    ) internal returns (bool) {
        return set(map._inner, key, bytes32(value));
    }

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

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

    /**
     * @dev Returns the number of elements in the map. O(1).
     */
    function length(Bytes32ToUintMap storage map) internal view returns (uint256) {
        return length(map._inner);
    }

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

    /**
     * @dev Tries to returns the value associated with `key`.  O(1).
     * Does not revert if `key` is not in the map.
     */
    function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) {
        (bool success, bytes32 value) = tryGet(map._inner, key);
        return (success, uint256(value));
    }

    /**
     * @dev Returns the value associated with `key`.  O(1).
     *
     * Requirements:
     *
     * - `key` must be in the map.
     */
    function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) {
        return uint256(get(map._inner, key));
    }

    /**
     * @dev Same as {get}, with a custom error message when `key` is not in the map.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryGet}.
     */
    function get(
        Bytes32ToUintMap storage map,
        bytes32 key,
        string memory errorMessage
    ) internal view returns (uint256) {
        return uint256(get(map._inner, key, errorMessage));
    }
}

File 6 of 17: EnumerableSet.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/structs/EnumerableSet.sol)

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 *  Trying to delete such a structure from storage will likely result in data corruption, rendering the structure unusable.
 *  See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 *  In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

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

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

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

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

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

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

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

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

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

            return true;
        } else {
            return false;
        }
    }

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

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

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

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

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

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

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

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        return _values(set._inner);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

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

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

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

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

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

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

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

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

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

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

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

File 7 of 17: 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 8 of 17: ERC165Storage.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Storage.sol)

pragma solidity ^0.8.0;

import "./ERC165.sol";

/**
 * @dev Storage based implementation of the {IERC165} interface.
 *
 * Contracts may inherit from this and call {_registerInterface} to declare
 * their support of an interface.
 */
abstract contract ERC165Storage is ERC165 {
    /**
     * @dev Mapping of interface ids to whether or not it's supported.
     */
    mapping(bytes4 => bool) private _supportedInterfaces;

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

    /**
     * @dev Registers the contract as an implementer of the interface defined by
     * `interfaceId`. Support of the actual ERC165 interface is automatic and
     * registering its interface id is not required.
     *
     * See {IERC165-supportsInterface}.
     *
     * Requirements:
     *
     * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
     */
    function _registerInterface(bytes4 interfaceId) internal virtual {
        require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
        _supportedInterfaces[interfaceId] = true;
    }
}

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

File 10 of 17: IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

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

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

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

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

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

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * 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;

    /**
     * @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 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 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 the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

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

File 11 of 17: IERC721Enumerable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.0;

import "./IERC721.sol";

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}

File 12 of 17: 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 13 of 17: IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

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

File 14 of 17: Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "./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 Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        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 15 of 17: SafeMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (utils/math/SafeMath.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

File 17 of 17: Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

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

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // 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);
    }

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

Contract ABI

[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"address","name":"_bCard","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"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":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"pure","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":"burnAllSoulboundCardsOfToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256[]","name":"toBurn","type":"uint256[]"}],"name":"burnReceivedSoulboundCards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"toBurn","type":"uint256"}],"name":"burnSoulboundCard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address[]","name":"toBurn","type":"address[]"}],"name":"burnSoulboundCardsOfToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"toDisable","type":"address"}],"name":"disableSoulboundCardsForAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"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":"address","name":"receiver","type":"address"}],"name":"isBlacklisted","outputs":[{"internalType":"bool","name":"blacklisted","type":"bool"}],"stateMutability":"view","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":[{"internalType":"address","name":"receiver","type":"address"}],"name":"receivedSoulboundCards","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"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":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"sendSoulboundCard","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bool","name":"","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"soulboundCardReceivers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"count","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b5060405162003e3638038062003e368339818101604052810190620000379190620003fa565b620000576200004b6200011b60201b60201c565b6200012360201b60201c565b82600590805190602001906200006f929190620002c1565b50816006908051906020019062000088929190620002c1565b5080600760006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620000e26380ac58cd60e01b620001e960201b60201c565b620000fa635b5e139f60e01b620001e960201b60201c565b6200011263780e9d6360e01b620001e960201b60201c565b505050620006c3565b600033905090565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b63ffffffff60e01b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141562000255576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200024c90620004a9565b60405180910390fd5b6001600080837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b828054620002cf90620005a5565b90600052602060002090601f016020900481019282620002f357600085556200033f565b82601f106200030e57805160ff19168380011785556200033f565b828001600101855582156200033f579182015b828111156200033e57825182559160200191906001019062000321565b5b5090506200034e919062000352565b5090565b5b808211156200036d57600081600090555060010162000353565b5090565b6000620003886200038284620004f4565b620004cb565b905082815260208101848484011115620003a157600080fd5b620003ae8482856200056f565b509392505050565b600081519050620003c781620006a9565b92915050565b600082601f830112620003df57600080fd5b8151620003f184826020860162000371565b91505092915050565b6000806000606084860312156200041057600080fd5b600084015167ffffffffffffffff8111156200042b57600080fd5b6200043986828701620003cd565b935050602084015167ffffffffffffffff8111156200045757600080fd5b6200046586828701620003cd565b92505060406200047886828701620003b6565b9150509250925092565b600062000491601c836200052a565b91506200049e8262000680565b602082019050919050565b60006020820190508181036000830152620004c48162000482565b9050919050565b6000620004d7620004ea565b9050620004e58282620005db565b919050565b6000604051905090565b600067ffffffffffffffff82111562000512576200051162000640565b5b6200051d826200066f565b9050602081019050919050565b600082825260208201905092915050565b600062000548826200054f565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60005b838110156200058f57808201518184015260208101905062000572565b838111156200059f576000848401525b50505050565b60006002820490506001821680620005be57607f821691505b60208210811415620005d557620005d462000611565b5b50919050565b620005e6826200066f565b810181811067ffffffffffffffff8211171562000608576200060762000640565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f4552433136353a20696e76616c696420696e7465726661636520696400000000600082015250565b620006b4816200053b565b8114620006c057600080fd5b50565b61376380620006d36000396000f3fe608060405234801561001057600080fd5b50600436106101c45760003560e01c806370a08231116100f9578063a22cb46511610097578063ca3c5c0711610071578063ca3c5c0714610513578063e985e9c51461052f578063f2fde38b1461055f578063fe575a871461057b576101c4565b8063a22cb465146104ab578063b88d4fde146104c7578063c87b56dd146104e3576101c4565b80638777a38e116100d35780638777a38e146104235780638da5cb5b1461043f578063947aea3b1461045d57806395d89b411461048d576101c4565b806370a08231146103cd578063715018a6146103fd57806373f8c0e814610407576101c4565b80632f745c59116101665780634f6ccce7116101405780634f6ccce7146103355780636352211e14610365578063644f943714610395578063667b7062146103b1576101c4565b80632f745c59146102b95780633701e582146102e957806342842e0e14610319576101c4565b8063095ea7b3116101a2578063095ea7b31461024757806318160ddd1461026357806323b872dd1461028157806329759ae91461029d576101c4565b806301ffc9a7146101c957806306fdde03146101f9578063081812fc14610217575b600080fd5b6101e360048036038101906101de91906126da565b6105ab565b6040516101f09190612c39565b60405180910390f35b610201610622565b60405161020e9190612c54565b60405180910390f35b610231600480360381019061022c9190612744565b6106b4565b60405161023e9190612bb1565b60405180910390f35b610261600480360381019061025c9190612675565b610768565b005b61026b6107a3565b6040516102789190612e96565b60405180910390f35b61029b60048036038101906102969190612517565b610894565b005b6102b760048036038101906102b29190612675565b6108cf565b005b6102d360048036038101906102ce9190612675565b6109ec565b6040516102e09190612e96565b60405180910390f35b61030360048036038101906102fe9190612489565b610a91565b6040516103109190612c17565b60405180910390f35b610333600480360381019061032e9190612517565b610ae1565b005b61034f600480360381019061034a9190612744565b610b01565b60405161035c9190612e96565b60405180910390f35b61037f600480360381019061037a9190612744565b610bb5565b60405161038c9190612bb1565b60405180910390f35b6103af60048036038101906103aa9190612489565b610c69565b005b6103cb60048036038101906103c69190612796565b610d43565b005b6103e760048036038101906103e29190612489565b610e68565b6040516103f49190612e96565b60405180910390f35b610405610f27565b005b610421600480360381019061041c9190612517565b610f3b565b005b61043d600480360381019061043891906125e1565b611371565b005b610447611464565b6040516104549190612bb1565b60405180910390f35b61047760048036038101906104729190612744565b61148e565b6040516104849190612bf5565b60405180910390f35b6104956114b2565b6040516104a29190612c54565b60405180910390f35b6104c560048036038101906104c09190612639565b611544565b005b6104e160048036038101906104dc9190612566565b61157f565b005b6104fd60048036038101906104f89190612744565b6115ba565b60405161050a9190612c54565b60405180910390f35b61052d60048036038101906105289190612744565b611673565b005b610549600480360381019061054491906124db565b6117a7565b6040516105569190612c39565b60405180910390f35b61057960048036038101906105749190612489565b61185e565b005b61059560048036038101906105909190612489565b6118e2565b6040516105a29190612c39565b60405180910390f35b60006105b682611938565b8061061b5750600080837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff165b9050919050565b60606005805461063190613106565b80601f016020809104026020016040519081016040528092919081815260200182805461065d90613106565b80156106aa5780601f1061067f576101008083540402835291602001916106aa565b820191906000526020600020905b81548152906001019060200180831161068d57829003601f168201915b5050505050905090565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663081812fc836040518263ffffffff1660e01b81526004016107119190612e96565b60206040518083038186803b15801561072957600080fd5b505afa15801561073d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076191906124b2565b9050919050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079a90612cf6565b60405180910390fd5b600080600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561080e57600080fd5b505afa158015610822573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610846919061276d565b90506000600190505b81811161088f57610871600360008381526020019081526020016000206119a2565b8361087c9190612fc6565b92508061088890613169565b905061084f565b505090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c690612db6565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061090f575061090e33826119b7565b5b61094e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161094590612cb6565b60405180910390fd5b61099f81600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611c3390919063ffffffff16565b6109de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109d590612d16565b60405180910390fd5b6109e88282611c4d565b5050565b60006109f783610e68565b8210610a38576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a2f90612e16565b60405180910390fd5b610a8982600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d6a90919063ffffffff16565b905092915050565b6060610ada600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d84565b9050919050565b610afc8383836040518060200160405280600081525061157f565b505050565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634f6ccce7836040518263ffffffff1660e01b8152600401610b5e9190612e96565b60206040518083038186803b158015610b7657600080fd5b505afa158015610b8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bae919061276d565b9050919050565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401610c129190612e96565b60206040518083038186803b158015610c2a57600080fd5b505afa158015610c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6291906124b2565b9050919050565b8073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610ca95750610ca881336117a7565b5b610ce8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cdf90612dd6565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610da55750610da433846119b7565b5b610de4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ddb90612c76565b60405180910390fd5b60005b82829050811015610e62576000838383818110610e2d577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9050602002016020810190610e429190612489565b9050610e4e8186611c4d565b508080610e5a90613169565b915050610de7565b50505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ed9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed090612d36565b60405180910390fd5b610f20600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611da5565b9050919050565b610f2f611dba565b610f396000611e38565b565b610f4533826119b7565b610f84576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f7b90612cb6565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401610ff69190612e96565b60206040518083038186803b15801561100e57600080fd5b505afa158015611022573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104691906124b2565b73ffffffffffffffffffffffffffffffffffffffff161461109c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109390612e36565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561110c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161110390612d76565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561117b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161117290612d56565b60405180910390fd5b600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615611208576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111ff90612e56565b60405180910390fd5b61125981600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611c3390919063ffffffff16565b15611299576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129090612cd6565b60405180910390fd5b6112ea81600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611efe90919063ffffffff16565b506113108260036000848152602001908152602001600020611f1890919063ffffffff16565b50808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806113b157506113b083336117a7565b5b6113f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e790612e76565b60405180910390fd5b60005b8282905081101561145e576000838383818110611439577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020135905061144c8582611c4d565b508061145790613169565b90506113f3565b50505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606114ab60036000848152602001908152602001600020611f48565b9050919050565b6060600680546114c190613106565b80601f01602080910402602001604051908101604052809291908181526020018280546114ed90613106565b801561153a5780601f1061150f5761010080835404028352916020019161153a565b820191906000526020600020905b81548152906001019060200180831161151d57829003601f168201915b5050505050905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161157690612cf6565b60405180910390fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115b190612db6565b60405180910390fd5b6060600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c87b56dd836040518263ffffffff1660e01b81526004016116179190612e96565b60006040518083038186803b15801561162f57600080fd5b505afa158015611643573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061166c9190612703565b9050919050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806116d557506116d433826119b7565b5b611714576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161170b90612c76565b60405180910390fd5b600061173160036000848152602001908152602001600020611f48565b905060005b81518110156117a257600082828151811061177a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020026020010151905061178e8185611c4d565b50808061179a90613169565b915050611736565b505050565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e985e9c584846040518363ffffffff1660e01b8152600401611806929190612bcc565b60206040518083038186803b15801561181e57600080fd5b505afa158015611832573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185691906126b1565b905092915050565b611866611dba565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156118d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118cd90612c96565b60405180910390fd5b6118df81611e38565b50565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60006119b082600001611f69565b9050919050565b600080600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e846040518263ffffffff1660e01b8152600401611a159190612e96565b60206040518083038186803b158015611a2d57600080fd5b505afa158015611a41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6591906124b2565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611b7657508373ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663081812fc856040518263ffffffff1660e01b8152600401611b0e9190612e96565b60206040518083038186803b158015611b2657600080fd5b505afa158015611b3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5e91906124b2565b73ffffffffffffffffffffffffffffffffffffffff16145b80611c2a5750600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e985e9c582866040518363ffffffff1660e01b8152600401611bd9929190612bcc565b60206040518083038186803b158015611bf157600080fd5b505afa158015611c05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2991906126b1565b5b91505092915050565b6000611c45836000018360001b611f7a565b905092915050565b611c9e81600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611f9d90919063ffffffff16565b8015611ccb5750611cca8260036000848152602001908152602001600020611fb790919063ffffffff16565b5b611d0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d0190612df6565b60405180910390fd5b80600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b6000611d798360000183611fe7565b60001c905092915050565b60606000611d9483600001612038565b905060608190508092505050919050565b6000611db382600001611f69565b9050919050565b611dc2612094565b73ffffffffffffffffffffffffffffffffffffffff16611de0611464565b73ffffffffffffffffffffffffffffffffffffffff1614611e36576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e2d90612d96565b60405180910390fd5b565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000611f10836000018360001b61209c565b905092915050565b6000611f40836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61209c565b905092915050565b60606000611f5883600001612038565b905060608190508092505050919050565b600081600001805490509050919050565b600080836001016000848152602001908152602001600020541415905092915050565b6000611faf836000018360001b61210c565b905092915050565b6000611fdf836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61210c565b905092915050565b6000826000018281548110612025577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905092915050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561208857602002820191906000526020600020905b815481526020019060010190808311612074575b50505050509050919050565b600033905090565b60006120a88383611f7a565b612101578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050612106565b600090505b92915050565b6000808360010160008481526020019081526020016000205490506000811461228657600060018261213e919061301c565b9050600060018660000180549050612156919061301c565b905081811461221157600086600001828154811061219d577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001549050808760000184815481106121e7577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055508387600101600083815260200190815260200160002081905550505b8560000180548061224b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061228c565b60009150505b92915050565b60006122a56122a084612ed6565b612eb1565b9050828152602081018484840111156122bd57600080fd5b6122c88482856130c4565b509392505050565b60006122e36122de84612f07565b612eb1565b9050828152602081018484840111156122fb57600080fd5b6123068482856130d3565b509392505050565b60008135905061231d816136d1565b92915050565b600081519050612332816136d1565b92915050565b60008083601f84011261234a57600080fd5b8235905067ffffffffffffffff81111561236357600080fd5b60208301915083602082028301111561237b57600080fd5b9250929050565b60008083601f84011261239457600080fd5b8235905067ffffffffffffffff8111156123ad57600080fd5b6020830191508360208202830111156123c557600080fd5b9250929050565b6000813590506123db816136e8565b92915050565b6000815190506123f0816136e8565b92915050565b600081359050612405816136ff565b92915050565b600082601f83011261241c57600080fd5b813561242c848260208601612292565b91505092915050565b600082601f83011261244657600080fd5b81516124568482602086016122d0565b91505092915050565b60008135905061246e81613716565b92915050565b60008151905061248381613716565b92915050565b60006020828403121561249b57600080fd5b60006124a98482850161230e565b91505092915050565b6000602082840312156124c457600080fd5b60006124d284828501612323565b91505092915050565b600080604083850312156124ee57600080fd5b60006124fc8582860161230e565b925050602061250d8582860161230e565b9150509250929050565b60008060006060848603121561252c57600080fd5b600061253a8682870161230e565b935050602061254b8682870161230e565b925050604061255c8682870161245f565b9150509250925092565b6000806000806080858703121561257c57600080fd5b600061258a8782880161230e565b945050602061259b8782880161230e565b93505060406125ac8782880161245f565b925050606085013567ffffffffffffffff8111156125c957600080fd5b6125d58782880161240b565b91505092959194509250565b6000806000604084860312156125f657600080fd5b60006126048682870161230e565b935050602084013567ffffffffffffffff81111561262157600080fd5b61262d86828701612382565b92509250509250925092565b6000806040838503121561264c57600080fd5b600061265a8582860161230e565b925050602061266b858286016123cc565b9150509250929050565b6000806040838503121561268857600080fd5b60006126968582860161230e565b92505060206126a78582860161245f565b9150509250929050565b6000602082840312156126c357600080fd5b60006126d1848285016123e1565b91505092915050565b6000602082840312156126ec57600080fd5b60006126fa848285016123f6565b91505092915050565b60006020828403121561271557600080fd5b600082015167ffffffffffffffff81111561272f57600080fd5b61273b84828501612435565b91505092915050565b60006020828403121561275657600080fd5b60006127648482850161245f565b91505092915050565b60006020828403121561277f57600080fd5b600061278d84828501612474565b91505092915050565b6000806000604084860312156127ab57600080fd5b60006127b98682870161245f565b935050602084013567ffffffffffffffff8111156127d657600080fd5b6127e286828701612338565b92509250509250925092565b60006127fa838361281e565b60208301905092915050565b60006128128383612b93565b60208301905092915050565b61282781613050565b82525050565b61283681613050565b82525050565b600061284782612f58565b6128518185612f93565b935061285c83612f38565b8060005b8381101561288d57815161287488826127ee565b975061287f83612f79565b925050600181019050612860565b5085935050505092915050565b60006128a582612f63565b6128af8185612fa4565b93506128ba83612f48565b8060005b838110156128eb5781516128d28882612806565b97506128dd83612f86565b9250506001810190506128be565b5085935050505092915050565b61290181613062565b82525050565b600061291282612f6e565b61291c8185612fb5565b935061292c8185602086016130d3565b6129358161323f565b840191505092915050565b600061294d603a83612fb5565b915061295882613250565b604082019050919050565b6000612970602683612fb5565b915061297b8261329f565b604082019050919050565b6000612993602783612fb5565b915061299e826132ee565b604082019050919050565b60006129b6603383612fb5565b91506129c18261333d565b604082019050919050565b60006129d9602583612fb5565b91506129e48261338c565b604082019050919050565b60006129fc602383612fb5565b9150612a07826133db565b604082019050919050565b6000612a1f602a83612fb5565b9150612a2a8261342a565b604082019050919050565b6000612a42601783612fb5565b9150612a4d82613479565b602082019050919050565b6000612a65601e83612fb5565b9150612a70826134a2565b602082019050919050565b6000612a88602083612fb5565b9150612a93826134cb565b602082019050919050565b6000612aab602683612fb5565b9150612ab6826134f4565b604082019050919050565b6000612ace602f83612fb5565b9150612ad982613543565b604082019050919050565b6000612af1601b83612fb5565b9150612afc82613592565b602082019050919050565b6000612b14601383612fb5565b9150612b1f826135bb565b602082019050919050565b6000612b37602383612fb5565b9150612b42826135e4565b604082019050919050565b6000612b5a602683612fb5565b9150612b6582613633565b604082019050919050565b6000612b7d603283612fb5565b9150612b8882613682565b604082019050919050565b612b9c816130ba565b82525050565b612bab816130ba565b82525050565b6000602082019050612bc6600083018461282d565b92915050565b6000604082019050612be1600083018561282d565b612bee602083018461282d565b9392505050565b60006020820190508181036000830152612c0f818461283c565b905092915050565b60006020820190508181036000830152612c31818461289a565b905092915050565b6000602082019050612c4e60008301846128f8565b92915050565b60006020820190508181036000830152612c6e8184612907565b905092915050565b60006020820190508181036000830152612c8f81612940565b9050919050565b60006020820190508181036000830152612caf81612963565b9050919050565b60006020820190508181036000830152612ccf81612986565b9050919050565b60006020820190508181036000830152612cef816129a9565b9050919050565b60006020820190508181036000830152612d0f816129cc565b9050919050565b60006020820190508181036000830152612d2f816129ef565b9050919050565b60006020820190508181036000830152612d4f81612a12565b9050919050565b60006020820190508181036000830152612d6f81612a35565b9050919050565b60006020820190508181036000830152612d8f81612a58565b9050919050565b60006020820190508181036000830152612daf81612a7b565b9050919050565b60006020820190508181036000830152612dcf81612a9e565b9050919050565b60006020820190508181036000830152612def81612ac1565b9050919050565b60006020820190508181036000830152612e0f81612ae4565b9050919050565b60006020820190508181036000830152612e2f81612b07565b9050919050565b60006020820190508181036000830152612e4f81612b2a565b9050919050565b60006020820190508181036000830152612e6f81612b4d565b9050919050565b60006020820190508181036000830152612e8f81612b70565b9050919050565b6000602082019050612eab6000830184612ba2565b92915050565b6000612ebb612ecc565b9050612ec78282613138565b919050565b6000604051905090565b600067ffffffffffffffff821115612ef157612ef0613210565b5b612efa8261323f565b9050602081019050919050565b600067ffffffffffffffff821115612f2257612f21613210565b5b612f2b8261323f565b9050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b6000612fd1826130ba565b9150612fdc836130ba565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115613011576130106131b2565b5b828201905092915050565b6000613027826130ba565b9150613032836130ba565b925082821015613045576130446131b2565b5b828203905092915050565b600061305b8261309a565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b838110156130f15780820151818401526020810190506130d6565b83811115613100576000848401525b50505050565b6000600282049050600182168061311e57607f821691505b60208210811415613132576131316131e1565b5b50919050565b6131418261323f565b810181811067ffffffffffffffff821117156131605761315f613210565b5b80604052505050565b6000613174826130ba565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156131a7576131a66131b2565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f53434152443a2063616c6c6572206973206e6f7420424341524420636f6e747260008201527f616374206e6f72206f776e6572206e6f7220617070726f766564000000000000602082015250565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f53434152443a2063616c6c6572206973206e6f74206f776e6572206e6f72206160008201527f7070726f76656400000000000000000000000000000000000000000000000000602082015250565b7f53434152443a2072656365697665722077617320616c72656164792073656e7460008201527f2074686520536f756c626f756e64204361726400000000000000000000000000602082015250565b7f53434152443a2063616e6e6f7420617070726f766520536f756c626f756e642060008201527f4361726473000000000000000000000000000000000000000000000000000000602082015250565b7f53434152443a20746f6b656e206e6f7420696e2072656365697665722773206c60008201527f6973740000000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b7f53434152443a2073656e64696e6720746f206f776e6572000000000000000000600082015250565b7f53434152443a2073656e64696e6720746f207a65726f20616464726573730000600082015250565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b7f53434152443a2063616e6e6f74207472616e7366657220536f756c626f756e6460008201527f2043617264730000000000000000000000000000000000000000000000000000602082015250565b7f53434152443a2063616c6c6572206973206e6f74206f776e6572206e6f72206160008201527f7070726f76656420666f7220616c6c0000000000000000000000000000000000602082015250565b7f53434152443a20746f6b656e206e6f74206f6e20746865207365740000000000600082015250565b7f496e646578206f7574206f6620626f756e647300000000000000000000000000600082015250565b7f53434152443a2073656e64696e6720636172642074686174206973206e6f742060008201527f6f776e0000000000000000000000000000000000000000000000000000000000602082015250565b7f53434152443a20726563656976657220626c61636b6c6973746564207468656d60008201527f73656c7665730000000000000000000000000000000000000000000000000000602082015250565b7f53434152443a2063616c6c6572206973206e6f74207265636569766572206e6f60008201527f7220617070726f76656420666f7220616c6c0000000000000000000000000000602082015250565b6136da81613050565b81146136e557600080fd5b50565b6136f181613062565b81146136fc57600080fd5b50565b6137088161306e565b811461371357600080fd5b50565b61371f816130ba565b811461372a57600080fd5b5056fea264697066735822122031628b23795ebcc7aee1a200d8f4a4c3f997784b255f55f068073ba235c5f14a64736f6c63430008040033000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000384c8072da488698df87c02cdf04499262d4697f000000000000000000000000000000000000000000000000000000000000000e536f756c626f756e64204361726400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055343415244000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101c45760003560e01c806370a08231116100f9578063a22cb46511610097578063ca3c5c0711610071578063ca3c5c0714610513578063e985e9c51461052f578063f2fde38b1461055f578063fe575a871461057b576101c4565b8063a22cb465146104ab578063b88d4fde146104c7578063c87b56dd146104e3576101c4565b80638777a38e116100d35780638777a38e146104235780638da5cb5b1461043f578063947aea3b1461045d57806395d89b411461048d576101c4565b806370a08231146103cd578063715018a6146103fd57806373f8c0e814610407576101c4565b80632f745c59116101665780634f6ccce7116101405780634f6ccce7146103355780636352211e14610365578063644f943714610395578063667b7062146103b1576101c4565b80632f745c59146102b95780633701e582146102e957806342842e0e14610319576101c4565b8063095ea7b3116101a2578063095ea7b31461024757806318160ddd1461026357806323b872dd1461028157806329759ae91461029d576101c4565b806301ffc9a7146101c957806306fdde03146101f9578063081812fc14610217575b600080fd5b6101e360048036038101906101de91906126da565b6105ab565b6040516101f09190612c39565b60405180910390f35b610201610622565b60405161020e9190612c54565b60405180910390f35b610231600480360381019061022c9190612744565b6106b4565b60405161023e9190612bb1565b60405180910390f35b610261600480360381019061025c9190612675565b610768565b005b61026b6107a3565b6040516102789190612e96565b60405180910390f35b61029b60048036038101906102969190612517565b610894565b005b6102b760048036038101906102b29190612675565b6108cf565b005b6102d360048036038101906102ce9190612675565b6109ec565b6040516102e09190612e96565b60405180910390f35b61030360048036038101906102fe9190612489565b610a91565b6040516103109190612c17565b60405180910390f35b610333600480360381019061032e9190612517565b610ae1565b005b61034f600480360381019061034a9190612744565b610b01565b60405161035c9190612e96565b60405180910390f35b61037f600480360381019061037a9190612744565b610bb5565b60405161038c9190612bb1565b60405180910390f35b6103af60048036038101906103aa9190612489565b610c69565b005b6103cb60048036038101906103c69190612796565b610d43565b005b6103e760048036038101906103e29190612489565b610e68565b6040516103f49190612e96565b60405180910390f35b610405610f27565b005b610421600480360381019061041c9190612517565b610f3b565b005b61043d600480360381019061043891906125e1565b611371565b005b610447611464565b6040516104549190612bb1565b60405180910390f35b61047760048036038101906104729190612744565b61148e565b6040516104849190612bf5565b60405180910390f35b6104956114b2565b6040516104a29190612c54565b60405180910390f35b6104c560048036038101906104c09190612639565b611544565b005b6104e160048036038101906104dc9190612566565b61157f565b005b6104fd60048036038101906104f89190612744565b6115ba565b60405161050a9190612c54565b60405180910390f35b61052d60048036038101906105289190612744565b611673565b005b610549600480360381019061054491906124db565b6117a7565b6040516105569190612c39565b60405180910390f35b61057960048036038101906105749190612489565b61185e565b005b61059560048036038101906105909190612489565b6118e2565b6040516105a29190612c39565b60405180910390f35b60006105b682611938565b8061061b5750600080837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff165b9050919050565b60606005805461063190613106565b80601f016020809104026020016040519081016040528092919081815260200182805461065d90613106565b80156106aa5780601f1061067f576101008083540402835291602001916106aa565b820191906000526020600020905b81548152906001019060200180831161068d57829003601f168201915b5050505050905090565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663081812fc836040518263ffffffff1660e01b81526004016107119190612e96565b60206040518083038186803b15801561072957600080fd5b505afa15801561073d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076191906124b2565b9050919050565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079a90612cf6565b60405180910390fd5b600080600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166318160ddd6040518163ffffffff1660e01b815260040160206040518083038186803b15801561080e57600080fd5b505afa158015610822573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610846919061276d565b90506000600190505b81811161088f57610871600360008381526020019081526020016000206119a2565b8361087c9190612fc6565b92508061088890613169565b905061084f565b505090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c690612db6565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061090f575061090e33826119b7565b5b61094e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161094590612cb6565b60405180910390fd5b61099f81600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611c3390919063ffffffff16565b6109de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109d590612d16565b60405180910390fd5b6109e88282611c4d565b5050565b60006109f783610e68565b8210610a38576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a2f90612e16565b60405180910390fd5b610a8982600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d6a90919063ffffffff16565b905092915050565b6060610ada600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611d84565b9050919050565b610afc8383836040518060200160405280600081525061157f565b505050565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634f6ccce7836040518263ffffffff1660e01b8152600401610b5e9190612e96565b60206040518083038186803b158015610b7657600080fd5b505afa158015610b8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bae919061276d565b9050919050565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401610c129190612e96565b60206040518083038186803b158015610c2a57600080fd5b505afa158015610c3e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6291906124b2565b9050919050565b8073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610ca95750610ca881336117a7565b5b610ce8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610cdf90612dd6565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610da55750610da433846119b7565b5b610de4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ddb90612c76565b60405180910390fd5b60005b82829050811015610e62576000838383818110610e2d577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9050602002016020810190610e429190612489565b9050610e4e8186611c4d565b508080610e5a90613169565b915050610de7565b50505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ed9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ed090612d36565b60405180910390fd5b610f20600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611da5565b9050919050565b610f2f611dba565b610f396000611e38565b565b610f4533826119b7565b610f84576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f7b90612cb6565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401610ff69190612e96565b60206040518083038186803b15801561100e57600080fd5b505afa158015611022573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104691906124b2565b73ffffffffffffffffffffffffffffffffffffffff161461109c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109390612e36565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561110c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161110390612d76565b60405180910390fd5b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561117b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161117290612d56565b60405180910390fd5b600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615611208576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111ff90612e56565b60405180910390fd5b61125981600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611c3390919063ffffffff16565b15611299576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129090612cd6565b60405180910390fd5b6112ea81600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611efe90919063ffffffff16565b506113108260036000848152602001908152602001600020611f1890919063ffffffff16565b50808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b8273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806113b157506113b083336117a7565b5b6113f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113e790612e76565b60405180910390fd5b60005b8282905081101561145e576000838383818110611439577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90506020020135905061144c8582611c4d565b508061145790613169565b90506113f3565b50505050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606114ab60036000848152602001908152602001600020611f48565b9050919050565b6060600680546114c190613106565b80601f01602080910402602001604051908101604052809291908181526020018280546114ed90613106565b801561153a5780601f1061150f5761010080835404028352916020019161153a565b820191906000526020600020905b81548152906001019060200180831161151d57829003601f168201915b5050505050905090565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161157690612cf6565b60405180910390fd5b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115b190612db6565b60405180910390fd5b6060600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c87b56dd836040518263ffffffff1660e01b81526004016116179190612e96565b60006040518083038186803b15801561162f57600080fd5b505afa158015611643573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061166c9190612703565b9050919050565b600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806116d557506116d433826119b7565b5b611714576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161170b90612c76565b60405180910390fd5b600061173160036000848152602001908152602001600020611f48565b905060005b81518110156117a257600082828151811061177a577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020026020010151905061178e8185611c4d565b50808061179a90613169565b915050611736565b505050565b6000600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e985e9c584846040518363ffffffff1660e01b8152600401611806929190612bcc565b60206040518083038186803b15801561181e57600080fd5b505afa158015611832573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185691906126b1565b905092915050565b611866611dba565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156118d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118cd90612c96565b60405180910390fd5b6118df81611e38565b50565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60006119b082600001611f69565b9050919050565b600080600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16636352211e846040518263ffffffff1660e01b8152600401611a159190612e96565b60206040518083038186803b158015611a2d57600080fd5b505afa158015611a41573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a6591906124b2565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611b7657508373ffffffffffffffffffffffffffffffffffffffff16600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663081812fc856040518263ffffffff1660e01b8152600401611b0e9190612e96565b60206040518083038186803b158015611b2657600080fd5b505afa158015611b3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5e91906124b2565b73ffffffffffffffffffffffffffffffffffffffff16145b80611c2a5750600760009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663e985e9c582866040518363ffffffff1660e01b8152600401611bd9929190612bcc565b60206040518083038186803b158015611bf157600080fd5b505afa158015611c05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2991906126b1565b5b91505092915050565b6000611c45836000018360001b611f7a565b905092915050565b611c9e81600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020611f9d90919063ffffffff16565b8015611ccb5750611cca8260036000848152602001908152602001600020611fb790919063ffffffff16565b5b611d0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d0190612df6565b60405180910390fd5b80600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b6000611d798360000183611fe7565b60001c905092915050565b60606000611d9483600001612038565b905060608190508092505050919050565b6000611db382600001611f69565b9050919050565b611dc2612094565b73ffffffffffffffffffffffffffffffffffffffff16611de0611464565b73ffffffffffffffffffffffffffffffffffffffff1614611e36576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e2d90612d96565b60405180910390fd5b565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000611f10836000018360001b61209c565b905092915050565b6000611f40836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61209c565b905092915050565b60606000611f5883600001612038565b905060608190508092505050919050565b600081600001805490509050919050565b600080836001016000848152602001908152602001600020541415905092915050565b6000611faf836000018360001b61210c565b905092915050565b6000611fdf836000018373ffffffffffffffffffffffffffffffffffffffff1660001b61210c565b905092915050565b6000826000018281548110612025577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9060005260206000200154905092915050565b60608160000180548060200260200160405190810160405280929190818152602001828054801561208857602002820191906000526020600020905b815481526020019060010190808311612074575b50505050509050919050565b600033905090565b60006120a88383611f7a565b612101578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050612106565b600090505b92915050565b6000808360010160008481526020019081526020016000205490506000811461228657600060018261213e919061301c565b9050600060018660000180549050612156919061301c565b905081811461221157600086600001828154811061219d577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001549050808760000184815481106121e7577f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90600052602060002001819055508387600101600083815260200190815260200160002081905550505b8560000180548061224b577f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061228c565b60009150505b92915050565b60006122a56122a084612ed6565b612eb1565b9050828152602081018484840111156122bd57600080fd5b6122c88482856130c4565b509392505050565b60006122e36122de84612f07565b612eb1565b9050828152602081018484840111156122fb57600080fd5b6123068482856130d3565b509392505050565b60008135905061231d816136d1565b92915050565b600081519050612332816136d1565b92915050565b60008083601f84011261234a57600080fd5b8235905067ffffffffffffffff81111561236357600080fd5b60208301915083602082028301111561237b57600080fd5b9250929050565b60008083601f84011261239457600080fd5b8235905067ffffffffffffffff8111156123ad57600080fd5b6020830191508360208202830111156123c557600080fd5b9250929050565b6000813590506123db816136e8565b92915050565b6000815190506123f0816136e8565b92915050565b600081359050612405816136ff565b92915050565b600082601f83011261241c57600080fd5b813561242c848260208601612292565b91505092915050565b600082601f83011261244657600080fd5b81516124568482602086016122d0565b91505092915050565b60008135905061246e81613716565b92915050565b60008151905061248381613716565b92915050565b60006020828403121561249b57600080fd5b60006124a98482850161230e565b91505092915050565b6000602082840312156124c457600080fd5b60006124d284828501612323565b91505092915050565b600080604083850312156124ee57600080fd5b60006124fc8582860161230e565b925050602061250d8582860161230e565b9150509250929050565b60008060006060848603121561252c57600080fd5b600061253a8682870161230e565b935050602061254b8682870161230e565b925050604061255c8682870161245f565b9150509250925092565b6000806000806080858703121561257c57600080fd5b600061258a8782880161230e565b945050602061259b8782880161230e565b93505060406125ac8782880161245f565b925050606085013567ffffffffffffffff8111156125c957600080fd5b6125d58782880161240b565b91505092959194509250565b6000806000604084860312156125f657600080fd5b60006126048682870161230e565b935050602084013567ffffffffffffffff81111561262157600080fd5b61262d86828701612382565b92509250509250925092565b6000806040838503121561264c57600080fd5b600061265a8582860161230e565b925050602061266b858286016123cc565b9150509250929050565b6000806040838503121561268857600080fd5b60006126968582860161230e565b92505060206126a78582860161245f565b9150509250929050565b6000602082840312156126c357600080fd5b60006126d1848285016123e1565b91505092915050565b6000602082840312156126ec57600080fd5b60006126fa848285016123f6565b91505092915050565b60006020828403121561271557600080fd5b600082015167ffffffffffffffff81111561272f57600080fd5b61273b84828501612435565b91505092915050565b60006020828403121561275657600080fd5b60006127648482850161245f565b91505092915050565b60006020828403121561277f57600080fd5b600061278d84828501612474565b91505092915050565b6000806000604084860312156127ab57600080fd5b60006127b98682870161245f565b935050602084013567ffffffffffffffff8111156127d657600080fd5b6127e286828701612338565b92509250509250925092565b60006127fa838361281e565b60208301905092915050565b60006128128383612b93565b60208301905092915050565b61282781613050565b82525050565b61283681613050565b82525050565b600061284782612f58565b6128518185612f93565b935061285c83612f38565b8060005b8381101561288d57815161287488826127ee565b975061287f83612f79565b925050600181019050612860565b5085935050505092915050565b60006128a582612f63565b6128af8185612fa4565b93506128ba83612f48565b8060005b838110156128eb5781516128d28882612806565b97506128dd83612f86565b9250506001810190506128be565b5085935050505092915050565b61290181613062565b82525050565b600061291282612f6e565b61291c8185612fb5565b935061292c8185602086016130d3565b6129358161323f565b840191505092915050565b600061294d603a83612fb5565b915061295882613250565b604082019050919050565b6000612970602683612fb5565b915061297b8261329f565b604082019050919050565b6000612993602783612fb5565b915061299e826132ee565b604082019050919050565b60006129b6603383612fb5565b91506129c18261333d565b604082019050919050565b60006129d9602583612fb5565b91506129e48261338c565b604082019050919050565b60006129fc602383612fb5565b9150612a07826133db565b604082019050919050565b6000612a1f602a83612fb5565b9150612a2a8261342a565b604082019050919050565b6000612a42601783612fb5565b9150612a4d82613479565b602082019050919050565b6000612a65601e83612fb5565b9150612a70826134a2565b602082019050919050565b6000612a88602083612fb5565b9150612a93826134cb565b602082019050919050565b6000612aab602683612fb5565b9150612ab6826134f4565b604082019050919050565b6000612ace602f83612fb5565b9150612ad982613543565b604082019050919050565b6000612af1601b83612fb5565b9150612afc82613592565b602082019050919050565b6000612b14601383612fb5565b9150612b1f826135bb565b602082019050919050565b6000612b37602383612fb5565b9150612b42826135e4565b604082019050919050565b6000612b5a602683612fb5565b9150612b6582613633565b604082019050919050565b6000612b7d603283612fb5565b9150612b8882613682565b604082019050919050565b612b9c816130ba565b82525050565b612bab816130ba565b82525050565b6000602082019050612bc6600083018461282d565b92915050565b6000604082019050612be1600083018561282d565b612bee602083018461282d565b9392505050565b60006020820190508181036000830152612c0f818461283c565b905092915050565b60006020820190508181036000830152612c31818461289a565b905092915050565b6000602082019050612c4e60008301846128f8565b92915050565b60006020820190508181036000830152612c6e8184612907565b905092915050565b60006020820190508181036000830152612c8f81612940565b9050919050565b60006020820190508181036000830152612caf81612963565b9050919050565b60006020820190508181036000830152612ccf81612986565b9050919050565b60006020820190508181036000830152612cef816129a9565b9050919050565b60006020820190508181036000830152612d0f816129cc565b9050919050565b60006020820190508181036000830152612d2f816129ef565b9050919050565b60006020820190508181036000830152612d4f81612a12565b9050919050565b60006020820190508181036000830152612d6f81612a35565b9050919050565b60006020820190508181036000830152612d8f81612a58565b9050919050565b60006020820190508181036000830152612daf81612a7b565b9050919050565b60006020820190508181036000830152612dcf81612a9e565b9050919050565b60006020820190508181036000830152612def81612ac1565b9050919050565b60006020820190508181036000830152612e0f81612ae4565b9050919050565b60006020820190508181036000830152612e2f81612b07565b9050919050565b60006020820190508181036000830152612e4f81612b2a565b9050919050565b60006020820190508181036000830152612e6f81612b4d565b9050919050565b60006020820190508181036000830152612e8f81612b70565b9050919050565b6000602082019050612eab6000830184612ba2565b92915050565b6000612ebb612ecc565b9050612ec78282613138565b919050565b6000604051905090565b600067ffffffffffffffff821115612ef157612ef0613210565b5b612efa8261323f565b9050602081019050919050565b600067ffffffffffffffff821115612f2257612f21613210565b5b612f2b8261323f565b9050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b6000612fd1826130ba565b9150612fdc836130ba565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115613011576130106131b2565b5b828201905092915050565b6000613027826130ba565b9150613032836130ba565b925082821015613045576130446131b2565b5b828203905092915050565b600061305b8261309a565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b82818337600083830152505050565b60005b838110156130f15780820151818401526020810190506130d6565b83811115613100576000848401525b50505050565b6000600282049050600182168061311e57607f821691505b60208210811415613132576131316131e1565b5b50919050565b6131418261323f565b810181811067ffffffffffffffff821117156131605761315f613210565b5b80604052505050565b6000613174826130ba565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156131a7576131a66131b2565b5b600182019050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f53434152443a2063616c6c6572206973206e6f7420424341524420636f6e747260008201527f616374206e6f72206f776e6572206e6f7220617070726f766564000000000000602082015250565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b7f53434152443a2063616c6c6572206973206e6f74206f776e6572206e6f72206160008201527f7070726f76656400000000000000000000000000000000000000000000000000602082015250565b7f53434152443a2072656365697665722077617320616c72656164792073656e7460008201527f2074686520536f756c626f756e64204361726400000000000000000000000000602082015250565b7f53434152443a2063616e6e6f7420617070726f766520536f756c626f756e642060008201527f4361726473000000000000000000000000000000000000000000000000000000602082015250565b7f53434152443a20746f6b656e206e6f7420696e2072656365697665722773206c60008201527f6973740000000000000000000000000000000000000000000000000000000000602082015250565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b7f53434152443a2073656e64696e6720746f206f776e6572000000000000000000600082015250565b7f53434152443a2073656e64696e6720746f207a65726f20616464726573730000600082015250565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b7f53434152443a2063616e6e6f74207472616e7366657220536f756c626f756e6460008201527f2043617264730000000000000000000000000000000000000000000000000000602082015250565b7f53434152443a2063616c6c6572206973206e6f74206f776e6572206e6f72206160008201527f7070726f76656420666f7220616c6c0000000000000000000000000000000000602082015250565b7f53434152443a20746f6b656e206e6f74206f6e20746865207365740000000000600082015250565b7f496e646578206f7574206f6620626f756e647300000000000000000000000000600082015250565b7f53434152443a2073656e64696e6720636172642074686174206973206e6f742060008201527f6f776e0000000000000000000000000000000000000000000000000000000000602082015250565b7f53434152443a20726563656976657220626c61636b6c6973746564207468656d60008201527f73656c7665730000000000000000000000000000000000000000000000000000602082015250565b7f53434152443a2063616c6c6572206973206e6f74207265636569766572206e6f60008201527f7220617070726f76656420666f7220616c6c0000000000000000000000000000602082015250565b6136da81613050565b81146136e557600080fd5b50565b6136f181613062565b81146136fc57600080fd5b50565b6137088161306e565b811461371357600080fd5b50565b61371f816130ba565b811461372a57600080fd5b5056fea264697066735822122031628b23795ebcc7aee1a200d8f4a4c3f997784b255f55f068073ba235c5f14a64736f6c63430008040033

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

000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000384c8072da488698df87c02cdf04499262d4697f000000000000000000000000000000000000000000000000000000000000000e536f756c626f756e64204361726400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000055343415244000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : name_ (string): Soulbound Card
Arg [1] : symbol_ (string): SCARD
Arg [2] : _bCard (address): 0x384c8072DA488698Df87c02cDf04499262D4697f

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [2] : 000000000000000000000000384c8072da488698df87c02cdf04499262d4697f
Arg [3] : 000000000000000000000000000000000000000000000000000000000000000e
Arg [4] : 536f756c626f756e642043617264000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000005
Arg [6] : 5343415244000000000000000000000000000000000000000000000000000000


Deployed Bytecode Sourcemap

350:13923:15:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;596:188:5;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3278:100:15;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11555:137;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;11238:161;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;9447:244;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;12846:179;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4584:393;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;9858:234;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;10498:149;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;13096:151;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;10789:135;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;8775:131;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7854:264;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;5746:524;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;9047:226;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1824:101:13;;;:::i;:::-;;3698:787:15;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;7157:519;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;1194:85:13;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;10245:147:15;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3447:104;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;12016:169;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;13577:209;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;8500:131;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;6391:570;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;12352:168;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2074:198:13;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;8232:146:15;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;596:188:5;681:4;704:36;728:11;704:23;:36::i;:::-;:73;;;;744:20;:33;765:11;744:33;;;;;;;;;;;;;;;;;;;;;;;;;;;704:73;697:80;;596:188;;;:::o;3278:100:15:-;3332:13;3365:5;3358:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3278:100;:::o;11555:137::-;11631:7;11658:5;;;;;;;;;;;:17;;;11676:7;11658:26;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11651:33;;11555:137;;;:::o;11238:161::-;11344:47;;;;;;;;;;:::i;:::-;;;;;;;;9447:244;9508:13;9534:15;9552:5;;;;;;;;;;;:17;;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;9534:37;;9587:9;9599:1;9587:13;;9582:102;9607:7;9602:1;:12;9582:102;;9645:27;:15;:18;9661:1;9645:18;;;;;;;;;;;:25;:27::i;:::-;9636:36;;;;;:::i;:::-;;;9616:3;;;;:::i;:::-;;;9582:102;;;;9447:244;;:::o;12846:179::-;12969:48;;;;;;;;;;:::i;:::-;;;;;;;;4584:393;4701:8;4687:22;;:10;:22;;;:64;;;;4713:38;4732:10;4744:6;4713:18;:38::i;:::-;4687:64;4665:156;;;;;;;;;;;;:::i;:::-;;;;;;;;;4840:42;4875:6;4840:15;:25;4856:8;4840:25;;;;;;;;;;;;;;;:34;;:42;;;;:::i;:::-;4832:90;;;;;;;;;;;;:::i;:::-;;;;;;;;;4933:36;4952:8;4962:6;4933:18;:36::i;:::-;4584:393;;:::o;9858:234::-;9956:7;9992:17;10002:6;9992:9;:17::i;:::-;9984:5;:25;9976:57;;;;;;;;;;;;:::i;:::-;;;;;;;;;10051:33;10078:5;10051:15;:23;10067:6;10051:23;;;;;;;;;;;;;;;:26;;:33;;;;:::i;:::-;10044:40;;9858:234;;;;:::o;10498:149::-;10569:16;10605:34;:15;:25;10621:8;10605:25;;;;;;;;;;;;;;;:32;:34::i;:::-;10598:41;;10498:149;;;:::o;13096:151::-;13200:39;13217:4;13223:2;13227:7;13200:39;;;;;;;;;;;;:16;:39::i;:::-;13096:151;;;:::o;10789:135::-;10864:7;10891:5;;;;;;;;;;;:18;;;10910:5;10891:25;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;10884:32;;10789:135;;;:::o;8775:131::-;8848:7;8875:5;;;;;;;;;;;:13;;;8889:8;8875:23;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8868:30;;8775:131;;;:::o;7854:264::-;7956:9;7942:23;;:10;:23;;;:66;;;;7969:39;7986:9;7997:10;7969:16;:39::i;:::-;7942:66;7934:126;;;;;;;;;;;;:::i;:::-;;;;;;;;;8106:4;8071:21;:32;8093:9;8071:32;;;;;;;;;;;;;;;;:39;;;;;;;;;;;;;;;;;;7854:264;:::o;5746:524::-;5890:5;;;;;;;;;;;5868:28;;:10;:28;;;:71;;;;5900:39;5919:10;5931:7;5900:18;:39::i;:::-;5868:71;5846:182;;;;;;;;;;;;:::i;:::-;;;;;;;;;6117:9;6112:151;6136:6;;:13;;6132:1;:17;6112:151;;;6171:16;6190:6;;6197:1;6190:9;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6171:28;;6214:37;6233:8;6243:7;6214:18;:37::i;:::-;6112:151;6151:3;;;;;:::i;:::-;;;;6112:151;;;;5746:524;;;:::o;9047:226::-;9120:7;9166:1;9148:20;;:6;:20;;;;9140:75;;;;;;;;;;;;:::i;:::-;;;;;;;;;9233:32;:15;:23;9249:6;9233:23;;;;;;;;;;;;;;;:30;:32::i;:::-;9226:39;;9047:226;;;:::o;1824:101:13:-;1087:13;:11;:13::i;:::-;1888:30:::1;1915:1;1888:18;:30::i;:::-;1824:101::o:0;3698:787:15:-;3802:39;3821:10;3833:7;3802:18;:39::i;:::-;3794:91;;;;;;;;;;;;:::i;:::-;;;;;;;;;3930:4;3904:30;;:5;;;;;;;;;;;:13;;;3918:7;3904:22;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:30;;;3896:78;;;;;;;;;;;;:::i;:::-;;;;;;;;;4013:1;3993:22;;:8;:22;;;;3985:65;;;;;;;;;;;;:::i;:::-;;;;;;;;;4081:4;4069:16;;:8;:16;;;;4061:52;;;;;;;;;;;;:::i;:::-;;;;;;;;;4133:21;:31;4155:8;4133:31;;;;;;;;;;;;;;;;;;;;;;;;;4132:32;4124:83;;;;;;;;;;;;:::i;:::-;;;;;;;;;4227:43;4262:7;4227:15;:25;4243:8;4227:25;;;;;;;;;;;;;;;:34;;:43;;;;:::i;:::-;4226:44;4218:108;;;;;;;;;;;;:::i;:::-;;;;;;;;;4339:38;4369:7;4339:15;:25;4355:8;4339:25;;;;;;;;;;;;;;;:29;;:38;;;;:::i;:::-;;4388;4417:8;4388:15;:24;4404:7;4388:24;;;;;;;;;;;:28;;:38;;;;:::i;:::-;;4469:7;4459:8;4444:33;;4453:4;4444:33;;;;;;;;;;;;3698:787;;;:::o;7157:519::-;7294:8;7280:22;;:10;:22;;;:64;;;;7306:38;7323:8;7333:10;7306:16;:38::i;:::-;7280:64;7258:179;;;;;;;;;;;;:::i;:::-;;;;;;;;;7526:9;7521:148;7545:6;;:13;;7541:1;:17;7521:148;;;7580:14;7597:6;;7604:1;7597:9;;;;;;;;;;;;;;;;;;;;;7580:26;;7621:36;7640:8;7650:6;7621:18;:36::i;:::-;7521:148;7560:3;;;;:::i;:::-;;;7521:148;;;;7157:519;;;:::o;1194:85:13:-;1240:7;1266:6;;;;;;;;;;;1259:13;;1194:85;:::o;10245:147:15:-;10315:16;10351:33;:15;:24;10367:7;10351:24;;;;;;;;;;;:31;:33::i;:::-;10344:40;;10245:147;;;:::o;3447:104::-;3503:13;3536:7;3529:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3447:104;:::o;12016:169::-;12130:47;;;;;;;;;;:::i;:::-;;;;;;;;13577:209;13730:48;;;;;;;;;;:::i;:::-;;;;;;;;8500:131;8567:13;8600:5;;;;;;;;;;;:14;;;8615:7;8600:23;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8593:30;;8500:131;;;:::o;6391:570::-;6511:5;;;;;;;;;;;6489:28;;:10;:28;;;:71;;;;6521:39;6540:10;6552:7;6521:18;:39::i;:::-;6489:71;6467:182;;;;;;;;;;;;:::i;:::-;;;;;;;;;6733:23;6759:33;:15;:24;6775:7;6759:24;;;;;;;;;;;:31;:33::i;:::-;6733:59;;6808:9;6803:151;6827:6;:13;6823:1;:17;6803:151;;;6862:16;6881:6;6888:1;6881:9;;;;;;;;;;;;;;;;;;;;;;6862:28;;6905:37;6924:8;6934:7;6905:18;:37::i;:::-;6803:151;6842:3;;;;;:::i;:::-;;;;6803:151;;;;6391:570;;:::o;12352:168::-;12449:4;12473:5;;;;;;;;;;;:22;;;12496:5;12503:8;12473:39;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12466:46;;12352:168;;;;:::o;2074:198:13:-;1087:13;:11;:13::i;:::-;2182:1:::1;2162:22;;:8;:22;;;;2154:73;;;;;;;;;;;;:::i;:::-;;;;;;;;;2237:28;2256:8;2237:18;:28::i;:::-;2074:198:::0;:::o;8232:146:15:-;8296:16;8339:21;:31;8361:8;8339:31;;;;;;;;;;;;;;;;;;;;;;;;;8325:45;;8232:146;;;:::o;829:155:4:-;914:4;952:25;937:40;;;:11;:40;;;;930:47;;829:155;;;:::o;8829:115:7:-;8892:7;8918:19;8926:3;:10;;8918:7;:19::i;:::-;8911:26;;8829:115;;;:::o;13989:275:15:-;14082:4;14099:13;14115:5;;;;;;;;;;;:13;;;14129:7;14115:22;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14099:38;;14167:5;14156:16;;:7;:16;;;:57;;;;14206:7;14176:37;;:5;;;;;;;;;;;:17;;;14194:7;14176:26;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:37;;;14156:57;:99;;;;14217:5;;;;;;;;;;;:22;;;14240:5;14247:7;14217:38;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;14156:99;14148:108;;;13989:275;;;;:::o;11029:144:7:-;11106:4;11129:37;11139:3;:10;;11159:5;11151:14;;11129:9;:37::i;:::-;11122:44;;11029:144;;;;:::o;5076:553:15:-;5273:40;5306:6;5273:15;:25;5289:8;5273:25;;;;;;;;;;;;;;;:32;;:40;;;;:::i;:::-;:215;;;;;5448:40;5479:8;5448:15;:23;5464:6;5448:23;;;;;;;;;;;:30;;:40;;;;:::i;:::-;5273:215;5158:399;;;;;;;;;;;;:::i;:::-;;;;;;;;;5614:6;5610:1;5583:38;;5592:8;5583:38;;;;;;;;;;;;5076:553;;:::o;11708:135:7:-;11779:7;11813:22;11817:3;:10;;11829:5;11813:3;:22::i;:::-;11805:31;;11798:38;;11708:135;;;;:::o;12383:297::-;12443:16;12471:22;12496:19;12504:3;:10;;12496:7;:19::i;:::-;12471:44;;12525:23;12635:5;12625:15;;12667:6;12660:13;;;;12383:297;;;:::o;11254:112::-;11314:7;11340:19;11348:3;:10;;11340:7;:19::i;:::-;11333:26;;11254:112;;;:::o;1352:130:13:-;1426:12;:10;:12::i;:::-;1415:23;;:7;:5;:7::i;:::-;:23;;;1407:68;;;;;;;;;;;;:::i;:::-;;;;;;;;;1352:130::o;2426:187::-;2499:16;2518:6;;;;;;;;;;;2499:25;;2543:8;2534:6;;:17;;;;;;;;;;;;;;;;;;2597:8;2566:40;;2587:8;2566:40;;;;;;;;;;;;2426:187;;:::o;10516:129:7:-;10583:4;10606:32;10611:3;:10;;10631:5;10623:14;;10606:4;:32::i;:::-;10599:39;;10516:129;;;;:::o;8028:150::-;8098:4;8121:50;8126:3;:10;;8162:5;8146:23;;8138:32;;8121:4;:50::i;:::-;8114:57;;8028:150;;;;:::o;9982:300::-;10045:16;10073:22;10098:19;10106:3;:10;;10098:7;:19::i;:::-;10073:44;;10127:23;10237:5;10227:15;;10269:6;10262:13;;;;9982:300;;;:::o;4362:107::-;4418:7;4444:3;:11;;:18;;;;4437:25;;4362:107;;;:::o;4154:127::-;4227:4;4273:1;4250:3;:12;;:19;4263:5;4250:19;;;;;;;;;;;;:24;;4243:31;;4154:127;;;;:::o;10813:135::-;10883:4;10906:35;10914:3;:10;;10934:5;10926:14;;10906:7;:35::i;:::-;10899:42;;10813:135;;;;:::o;8346:156::-;8419:4;8442:53;8450:3;:10;;8486:5;8470:23;;8462:32;;8442:7;:53::i;:::-;8435:60;;8346:156;;;;:::o;4811:118::-;4878:7;4904:3;:11;;4916:5;4904:18;;;;;;;;;;;;;;;;;;;;;;;;4897:25;;4811:118;;;;:::o;5469:109::-;5525:16;5560:3;:11;;5553:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5469:109;;;:::o;640:96:3:-;693:7;719:10;712:17;;640:96;:::o;2113:404:7:-;2176:4;2197:21;2207:3;2212:5;2197:9;:21::i;:::-;2192:319;;2234:3;:11;;2251:5;2234:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2414:3;:11;;:18;;;;2392:3;:12;;:19;2405:5;2392:19;;;;;;;;;;;:40;;;;2453:4;2446:11;;;;2192:319;2495:5;2488:12;;2113:404;;;;;:::o;2685:1388::-;2751:4;2867:18;2888:3;:12;;:19;2901:5;2888:19;;;;;;;;;;;;2867:40;;2936:1;2922:10;:15;2918:1149;;3291:21;3328:1;3315:10;:14;;;;:::i;:::-;3291:38;;3343:17;3384:1;3363:3;:11;;:18;;;;:22;;;;:::i;:::-;3343:42;;3417:13;3404:9;:26;3400:398;;3450:17;3470:3;:11;;3482:9;3470:22;;;;;;;;;;;;;;;;;;;;;;;;3450:42;;3621:9;3592:3;:11;;3604:13;3592:26;;;;;;;;;;;;;;;;;;;;;;;:38;;;;3730:10;3704:3;:12;;:23;3717:9;3704:23;;;;;;;;;;;:36;;;;3400:398;;3876:3;:11;;:17;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3968:3;:12;;:19;3981:5;3968:19;;;;;;;;;;;3961:26;;;4009:4;4002:11;;;;;;;2918:1149;4051:5;4044:12;;;2685:1388;;;;;:::o;7:343:17:-;84:5;109:65;125:48;166:6;125:48;:::i;:::-;109:65;:::i;:::-;100:74;;197:6;190:5;183:21;235:4;228:5;224:16;273:3;264:6;259:3;255:16;252:25;249:2;;;290:1;287;280:12;249:2;303:41;337:6;332:3;327;303:41;:::i;:::-;90:260;;;;;;:::o;356:354::-;445:5;470:66;486:49;528:6;486:49;:::i;:::-;470:66;:::i;:::-;461:75;;559:6;552:5;545:21;597:4;590:5;586:16;635:3;626:6;621:3;617:16;614:25;611:2;;;652:1;649;642:12;611:2;665:39;697:6;692:3;687;665:39;:::i;:::-;451:259;;;;;;:::o;716:139::-;762:5;800:6;787:20;778:29;;816:33;843:5;816:33;:::i;:::-;768:87;;;;:::o;861:143::-;918:5;949:6;943:13;934:22;;965:33;992:5;965:33;:::i;:::-;924:80;;;;:::o;1027:367::-;1100:8;1110:6;1160:3;1153:4;1145:6;1141:17;1137:27;1127:2;;1178:1;1175;1168:12;1127:2;1214:6;1201:20;1191:30;;1244:18;1236:6;1233:30;1230:2;;;1276:1;1273;1266:12;1230:2;1313:4;1305:6;1301:17;1289:29;;1367:3;1359:4;1351:6;1347:17;1337:8;1333:32;1330:41;1327:2;;;1384:1;1381;1374:12;1327:2;1117:277;;;;;:::o;1417:367::-;1490:8;1500:6;1550:3;1543:4;1535:6;1531:17;1527:27;1517:2;;1568:1;1565;1558:12;1517:2;1604:6;1591:20;1581:30;;1634:18;1626:6;1623:30;1620:2;;;1666:1;1663;1656:12;1620:2;1703:4;1695:6;1691:17;1679:29;;1757:3;1749:4;1741:6;1737:17;1727:8;1723:32;1720:41;1717:2;;;1774:1;1771;1764:12;1717:2;1507:277;;;;;:::o;1790:133::-;1833:5;1871:6;1858:20;1849:29;;1887:30;1911:5;1887:30;:::i;:::-;1839:84;;;;:::o;1929:137::-;1983:5;2014:6;2008:13;1999:22;;2030:30;2054:5;2030:30;:::i;:::-;1989:77;;;;:::o;2072:137::-;2117:5;2155:6;2142:20;2133:29;;2171:32;2197:5;2171:32;:::i;:::-;2123:86;;;;:::o;2228:271::-;2283:5;2332:3;2325:4;2317:6;2313:17;2309:27;2299:2;;2350:1;2347;2340:12;2299:2;2390:6;2377:20;2415:78;2489:3;2481:6;2474:4;2466:6;2462:17;2415:78;:::i;:::-;2406:87;;2289:210;;;;;:::o;2519:288::-;2586:5;2635:3;2628:4;2620:6;2616:17;2612:27;2602:2;;2653:1;2650;2643:12;2602:2;2686:6;2680:13;2711:90;2797:3;2789:6;2782:4;2774:6;2770:17;2711:90;:::i;:::-;2702:99;;2592:215;;;;;:::o;2813:139::-;2859:5;2897:6;2884:20;2875:29;;2913:33;2940:5;2913:33;:::i;:::-;2865:87;;;;:::o;2958:143::-;3015:5;3046:6;3040:13;3031:22;;3062:33;3089:5;3062:33;:::i;:::-;3021:80;;;;:::o;3107:262::-;3166:6;3215:2;3203:9;3194:7;3190:23;3186:32;3183:2;;;3231:1;3228;3221:12;3183:2;3274:1;3299:53;3344:7;3335:6;3324:9;3320:22;3299:53;:::i;:::-;3289:63;;3245:117;3173:196;;;;:::o;3375:284::-;3445:6;3494:2;3482:9;3473:7;3469:23;3465:32;3462:2;;;3510:1;3507;3500:12;3462:2;3553:1;3578:64;3634:7;3625:6;3614:9;3610:22;3578:64;:::i;:::-;3568:74;;3524:128;3452:207;;;;:::o;3665:407::-;3733:6;3741;3790:2;3778:9;3769:7;3765:23;3761:32;3758:2;;;3806:1;3803;3796:12;3758:2;3849:1;3874:53;3919:7;3910:6;3899:9;3895:22;3874:53;:::i;:::-;3864:63;;3820:117;3976:2;4002:53;4047:7;4038:6;4027:9;4023:22;4002:53;:::i;:::-;3992:63;;3947:118;3748:324;;;;;:::o;4078:552::-;4155:6;4163;4171;4220:2;4208:9;4199:7;4195:23;4191:32;4188:2;;;4236:1;4233;4226:12;4188:2;4279:1;4304:53;4349:7;4340:6;4329:9;4325:22;4304:53;:::i;:::-;4294:63;;4250:117;4406:2;4432:53;4477:7;4468:6;4457:9;4453:22;4432:53;:::i;:::-;4422:63;;4377:118;4534:2;4560:53;4605:7;4596:6;4585:9;4581:22;4560:53;:::i;:::-;4550:63;;4505:118;4178:452;;;;;:::o;4636:809::-;4731:6;4739;4747;4755;4804:3;4792:9;4783:7;4779:23;4775:33;4772:2;;;4821:1;4818;4811:12;4772:2;4864:1;4889:53;4934:7;4925:6;4914:9;4910:22;4889:53;:::i;:::-;4879:63;;4835:117;4991:2;5017:53;5062:7;5053:6;5042:9;5038:22;5017:53;:::i;:::-;5007:63;;4962:118;5119:2;5145:53;5190:7;5181:6;5170:9;5166:22;5145:53;:::i;:::-;5135:63;;5090:118;5275:2;5264:9;5260:18;5247:32;5306:18;5298:6;5295:30;5292:2;;;5338:1;5335;5328:12;5292:2;5366:62;5420:7;5411:6;5400:9;5396:22;5366:62;:::i;:::-;5356:72;;5218:220;4762:683;;;;;;;:::o;5451:570::-;5546:6;5554;5562;5611:2;5599:9;5590:7;5586:23;5582:32;5579:2;;;5627:1;5624;5617:12;5579:2;5670:1;5695:53;5740:7;5731:6;5720:9;5716:22;5695:53;:::i;:::-;5685:63;;5641:117;5825:2;5814:9;5810:18;5797:32;5856:18;5848:6;5845:30;5842:2;;;5888:1;5885;5878:12;5842:2;5924:80;5996:7;5987:6;5976:9;5972:22;5924:80;:::i;:::-;5906:98;;;;5768:246;5569:452;;;;;:::o;6027:401::-;6092:6;6100;6149:2;6137:9;6128:7;6124:23;6120:32;6117:2;;;6165:1;6162;6155:12;6117:2;6208:1;6233:53;6278:7;6269:6;6258:9;6254:22;6233:53;:::i;:::-;6223:63;;6179:117;6335:2;6361:50;6403:7;6394:6;6383:9;6379:22;6361:50;:::i;:::-;6351:60;;6306:115;6107:321;;;;;:::o;6434:407::-;6502:6;6510;6559:2;6547:9;6538:7;6534:23;6530:32;6527:2;;;6575:1;6572;6565:12;6527:2;6618:1;6643:53;6688:7;6679:6;6668:9;6664:22;6643:53;:::i;:::-;6633:63;;6589:117;6745:2;6771:53;6816:7;6807:6;6796:9;6792:22;6771:53;:::i;:::-;6761:63;;6716:118;6517:324;;;;;:::o;6847:278::-;6914:6;6963:2;6951:9;6942:7;6938:23;6934:32;6931:2;;;6979:1;6976;6969:12;6931:2;7022:1;7047:61;7100:7;7091:6;7080:9;7076:22;7047:61;:::i;:::-;7037:71;;6993:125;6921:204;;;;:::o;7131:260::-;7189:6;7238:2;7226:9;7217:7;7213:23;7209:32;7206:2;;;7254:1;7251;7244:12;7206:2;7297:1;7322:52;7366:7;7357:6;7346:9;7342:22;7322:52;:::i;:::-;7312:62;;7268:116;7196:195;;;;:::o;7397:390::-;7477:6;7526:2;7514:9;7505:7;7501:23;7497:32;7494:2;;;7542:1;7539;7532:12;7494:2;7606:1;7595:9;7591:17;7585:24;7636:18;7628:6;7625:30;7622:2;;;7668:1;7665;7658:12;7622:2;7696:74;7762:7;7753:6;7742:9;7738:22;7696:74;:::i;:::-;7686:84;;7556:224;7484:303;;;;:::o;7793:262::-;7852:6;7901:2;7889:9;7880:7;7876:23;7872:32;7869:2;;;7917:1;7914;7907:12;7869:2;7960:1;7985:53;8030:7;8021:6;8010:9;8006:22;7985:53;:::i;:::-;7975:63;;7931:117;7859:196;;;;:::o;8061:284::-;8131:6;8180:2;8168:9;8159:7;8155:23;8151:32;8148:2;;;8196:1;8193;8186:12;8148:2;8239:1;8264:64;8320:7;8311:6;8300:9;8296:22;8264:64;:::i;:::-;8254:74;;8210:128;8138:207;;;;:::o;8351:570::-;8446:6;8454;8462;8511:2;8499:9;8490:7;8486:23;8482:32;8479:2;;;8527:1;8524;8517:12;8479:2;8570:1;8595:53;8640:7;8631:6;8620:9;8616:22;8595:53;:::i;:::-;8585:63;;8541:117;8725:2;8714:9;8710:18;8697:32;8756:18;8748:6;8745:30;8742:2;;;8788:1;8785;8778:12;8742:2;8824:80;8896:7;8887:6;8876:9;8872:22;8824:80;:::i;:::-;8806:98;;;;8668:246;8469:452;;;;;:::o;8927:179::-;8996:10;9017:46;9059:3;9051:6;9017:46;:::i;:::-;9095:4;9090:3;9086:14;9072:28;;9007:99;;;;:::o;9112:179::-;9181:10;9202:46;9244:3;9236:6;9202:46;:::i;:::-;9280:4;9275:3;9271:14;9257:28;;9192:99;;;;:::o;9297:108::-;9374:24;9392:5;9374:24;:::i;:::-;9369:3;9362:37;9352:53;;:::o;9411:118::-;9498:24;9516:5;9498:24;:::i;:::-;9493:3;9486:37;9476:53;;:::o;9565:732::-;9684:3;9713:54;9761:5;9713:54;:::i;:::-;9783:86;9862:6;9857:3;9783:86;:::i;:::-;9776:93;;9893:56;9943:5;9893:56;:::i;:::-;9972:7;10003:1;9988:284;10013:6;10010:1;10007:13;9988:284;;;10089:6;10083:13;10116:63;10175:3;10160:13;10116:63;:::i;:::-;10109:70;;10202:60;10255:6;10202:60;:::i;:::-;10192:70;;10048:224;10035:1;10032;10028:9;10023:14;;9988:284;;;9992:14;10288:3;10281:10;;9689:608;;;;;;;:::o;10333:732::-;10452:3;10481:54;10529:5;10481:54;:::i;:::-;10551:86;10630:6;10625:3;10551:86;:::i;:::-;10544:93;;10661:56;10711:5;10661:56;:::i;:::-;10740:7;10771:1;10756:284;10781:6;10778:1;10775:13;10756:284;;;10857:6;10851:13;10884:63;10943:3;10928:13;10884:63;:::i;:::-;10877:70;;10970:60;11023:6;10970:60;:::i;:::-;10960:70;;10816:224;10803:1;10800;10796:9;10791:14;;10756:284;;;10760:14;11056:3;11049:10;;10457:608;;;;;;;:::o;11071:109::-;11152:21;11167:5;11152:21;:::i;:::-;11147:3;11140:34;11130:50;;:::o;11186:364::-;11274:3;11302:39;11335:5;11302:39;:::i;:::-;11357:71;11421:6;11416:3;11357:71;:::i;:::-;11350:78;;11437:52;11482:6;11477:3;11470:4;11463:5;11459:16;11437:52;:::i;:::-;11514:29;11536:6;11514:29;:::i;:::-;11509:3;11505:39;11498:46;;11278:272;;;;;:::o;11556:366::-;11698:3;11719:67;11783:2;11778:3;11719:67;:::i;:::-;11712:74;;11795:93;11884:3;11795:93;:::i;:::-;11913:2;11908:3;11904:12;11897:19;;11702:220;;;:::o;11928:366::-;12070:3;12091:67;12155:2;12150:3;12091:67;:::i;:::-;12084:74;;12167:93;12256:3;12167:93;:::i;:::-;12285:2;12280:3;12276:12;12269:19;;12074:220;;;:::o;12300:366::-;12442:3;12463:67;12527:2;12522:3;12463:67;:::i;:::-;12456:74;;12539:93;12628:3;12539:93;:::i;:::-;12657:2;12652:3;12648:12;12641:19;;12446:220;;;:::o;12672:366::-;12814:3;12835:67;12899:2;12894:3;12835:67;:::i;:::-;12828:74;;12911:93;13000:3;12911:93;:::i;:::-;13029:2;13024:3;13020:12;13013:19;;12818:220;;;:::o;13044:366::-;13186:3;13207:67;13271:2;13266:3;13207:67;:::i;:::-;13200:74;;13283:93;13372:3;13283:93;:::i;:::-;13401:2;13396:3;13392:12;13385:19;;13190:220;;;:::o;13416:366::-;13558:3;13579:67;13643:2;13638:3;13579:67;:::i;:::-;13572:74;;13655:93;13744:3;13655:93;:::i;:::-;13773:2;13768:3;13764:12;13757:19;;13562:220;;;:::o;13788:366::-;13930:3;13951:67;14015:2;14010:3;13951:67;:::i;:::-;13944:74;;14027:93;14116:3;14027:93;:::i;:::-;14145:2;14140:3;14136:12;14129:19;;13934:220;;;:::o;14160:366::-;14302:3;14323:67;14387:2;14382:3;14323:67;:::i;:::-;14316:74;;14399:93;14488:3;14399:93;:::i;:::-;14517:2;14512:3;14508:12;14501:19;;14306:220;;;:::o;14532:366::-;14674:3;14695:67;14759:2;14754:3;14695:67;:::i;:::-;14688:74;;14771:93;14860:3;14771:93;:::i;:::-;14889:2;14884:3;14880:12;14873:19;;14678:220;;;:::o;14904:366::-;15046:3;15067:67;15131:2;15126:3;15067:67;:::i;:::-;15060:74;;15143:93;15232:3;15143:93;:::i;:::-;15261:2;15256:3;15252:12;15245:19;;15050:220;;;:::o;15276:366::-;15418:3;15439:67;15503:2;15498:3;15439:67;:::i;:::-;15432:74;;15515:93;15604:3;15515:93;:::i;:::-;15633:2;15628:3;15624:12;15617:19;;15422:220;;;:::o;15648:366::-;15790:3;15811:67;15875:2;15870:3;15811:67;:::i;:::-;15804:74;;15887:93;15976:3;15887:93;:::i;:::-;16005:2;16000:3;15996:12;15989:19;;15794:220;;;:::o;16020:366::-;16162:3;16183:67;16247:2;16242:3;16183:67;:::i;:::-;16176:74;;16259:93;16348:3;16259:93;:::i;:::-;16377:2;16372:3;16368:12;16361:19;;16166:220;;;:::o;16392:366::-;16534:3;16555:67;16619:2;16614:3;16555:67;:::i;:::-;16548:74;;16631:93;16720:3;16631:93;:::i;:::-;16749:2;16744:3;16740:12;16733:19;;16538:220;;;:::o;16764:366::-;16906:3;16927:67;16991:2;16986:3;16927:67;:::i;:::-;16920:74;;17003:93;17092:3;17003:93;:::i;:::-;17121:2;17116:3;17112:12;17105:19;;16910:220;;;:::o;17136:366::-;17278:3;17299:67;17363:2;17358:3;17299:67;:::i;:::-;17292:74;;17375:93;17464:3;17375:93;:::i;:::-;17493:2;17488:3;17484:12;17477:19;;17282:220;;;:::o;17508:366::-;17650:3;17671:67;17735:2;17730:3;17671:67;:::i;:::-;17664:74;;17747:93;17836:3;17747:93;:::i;:::-;17865:2;17860:3;17856:12;17849:19;;17654:220;;;:::o;17880:108::-;17957:24;17975:5;17957:24;:::i;:::-;17952:3;17945:37;17935:53;;:::o;17994:118::-;18081:24;18099:5;18081:24;:::i;:::-;18076:3;18069:37;18059:53;;:::o;18118:222::-;18211:4;18249:2;18238:9;18234:18;18226:26;;18262:71;18330:1;18319:9;18315:17;18306:6;18262:71;:::i;:::-;18216:124;;;;:::o;18346:332::-;18467:4;18505:2;18494:9;18490:18;18482:26;;18518:71;18586:1;18575:9;18571:17;18562:6;18518:71;:::i;:::-;18599:72;18667:2;18656:9;18652:18;18643:6;18599:72;:::i;:::-;18472:206;;;;;:::o;18684:373::-;18827:4;18865:2;18854:9;18850:18;18842:26;;18914:9;18908:4;18904:20;18900:1;18889:9;18885:17;18878:47;18942:108;19045:4;19036:6;18942:108;:::i;:::-;18934:116;;18832:225;;;;:::o;19063:373::-;19206:4;19244:2;19233:9;19229:18;19221:26;;19293:9;19287:4;19283:20;19279:1;19268:9;19264:17;19257:47;19321:108;19424:4;19415:6;19321:108;:::i;:::-;19313:116;;19211:225;;;;:::o;19442:210::-;19529:4;19567:2;19556:9;19552:18;19544:26;;19580:65;19642:1;19631:9;19627:17;19618:6;19580:65;:::i;:::-;19534:118;;;;:::o;19658:313::-;19771:4;19809:2;19798:9;19794:18;19786:26;;19858:9;19852:4;19848:20;19844:1;19833:9;19829:17;19822:47;19886:78;19959:4;19950:6;19886:78;:::i;:::-;19878:86;;19776:195;;;;:::o;19977:419::-;20143:4;20181:2;20170:9;20166:18;20158:26;;20230:9;20224:4;20220:20;20216:1;20205:9;20201:17;20194:47;20258:131;20384:4;20258:131;:::i;:::-;20250:139;;20148:248;;;:::o;20402:419::-;20568:4;20606:2;20595:9;20591:18;20583:26;;20655:9;20649:4;20645:20;20641:1;20630:9;20626:17;20619:47;20683:131;20809:4;20683:131;:::i;:::-;20675:139;;20573:248;;;:::o;20827:419::-;20993:4;21031:2;21020:9;21016:18;21008:26;;21080:9;21074:4;21070:20;21066:1;21055:9;21051:17;21044:47;21108:131;21234:4;21108:131;:::i;:::-;21100:139;;20998:248;;;:::o;21252:419::-;21418:4;21456:2;21445:9;21441:18;21433:26;;21505:9;21499:4;21495:20;21491:1;21480:9;21476:17;21469:47;21533:131;21659:4;21533:131;:::i;:::-;21525:139;;21423:248;;;:::o;21677:419::-;21843:4;21881:2;21870:9;21866:18;21858:26;;21930:9;21924:4;21920:20;21916:1;21905:9;21901:17;21894:47;21958:131;22084:4;21958:131;:::i;:::-;21950:139;;21848:248;;;:::o;22102:419::-;22268:4;22306:2;22295:9;22291:18;22283:26;;22355:9;22349:4;22345:20;22341:1;22330:9;22326:17;22319:47;22383:131;22509:4;22383:131;:::i;:::-;22375:139;;22273:248;;;:::o;22527:419::-;22693:4;22731:2;22720:9;22716:18;22708:26;;22780:9;22774:4;22770:20;22766:1;22755:9;22751:17;22744:47;22808:131;22934:4;22808:131;:::i;:::-;22800:139;;22698:248;;;:::o;22952:419::-;23118:4;23156:2;23145:9;23141:18;23133:26;;23205:9;23199:4;23195:20;23191:1;23180:9;23176:17;23169:47;23233:131;23359:4;23233:131;:::i;:::-;23225:139;;23123:248;;;:::o;23377:419::-;23543:4;23581:2;23570:9;23566:18;23558:26;;23630:9;23624:4;23620:20;23616:1;23605:9;23601:17;23594:47;23658:131;23784:4;23658:131;:::i;:::-;23650:139;;23548:248;;;:::o;23802:419::-;23968:4;24006:2;23995:9;23991:18;23983:26;;24055:9;24049:4;24045:20;24041:1;24030:9;24026:17;24019:47;24083:131;24209:4;24083:131;:::i;:::-;24075:139;;23973:248;;;:::o;24227:419::-;24393:4;24431:2;24420:9;24416:18;24408:26;;24480:9;24474:4;24470:20;24466:1;24455:9;24451:17;24444:47;24508:131;24634:4;24508:131;:::i;:::-;24500:139;;24398:248;;;:::o;24652:419::-;24818:4;24856:2;24845:9;24841:18;24833:26;;24905:9;24899:4;24895:20;24891:1;24880:9;24876:17;24869:47;24933:131;25059:4;24933:131;:::i;:::-;24925:139;;24823:248;;;:::o;25077:419::-;25243:4;25281:2;25270:9;25266:18;25258:26;;25330:9;25324:4;25320:20;25316:1;25305:9;25301:17;25294:47;25358:131;25484:4;25358:131;:::i;:::-;25350:139;;25248:248;;;:::o;25502:419::-;25668:4;25706:2;25695:9;25691:18;25683:26;;25755:9;25749:4;25745:20;25741:1;25730:9;25726:17;25719:47;25783:131;25909:4;25783:131;:::i;:::-;25775:139;;25673:248;;;:::o;25927:419::-;26093:4;26131:2;26120:9;26116:18;26108:26;;26180:9;26174:4;26170:20;26166:1;26155:9;26151:17;26144:47;26208:131;26334:4;26208:131;:::i;:::-;26200:139;;26098:248;;;:::o;26352:419::-;26518:4;26556:2;26545:9;26541:18;26533:26;;26605:9;26599:4;26595:20;26591:1;26580:9;26576:17;26569:47;26633:131;26759:4;26633:131;:::i;:::-;26625:139;;26523:248;;;:::o;26777:419::-;26943:4;26981:2;26970:9;26966:18;26958:26;;27030:9;27024:4;27020:20;27016:1;27005:9;27001:17;26994:47;27058:131;27184:4;27058:131;:::i;:::-;27050:139;;26948:248;;;:::o;27202:222::-;27295:4;27333:2;27322:9;27318:18;27310:26;;27346:71;27414:1;27403:9;27399:17;27390:6;27346:71;:::i;:::-;27300:124;;;;:::o;27430:129::-;27464:6;27491:20;;:::i;:::-;27481:30;;27520:33;27548:4;27540:6;27520:33;:::i;:::-;27471:88;;;:::o;27565:75::-;27598:6;27631:2;27625:9;27615:19;;27605:35;:::o;27646:307::-;27707:4;27797:18;27789:6;27786:30;27783:2;;;27819:18;;:::i;:::-;27783:2;27857:29;27879:6;27857:29;:::i;:::-;27849:37;;27941:4;27935;27931:15;27923:23;;27712:241;;;:::o;27959:308::-;28021:4;28111:18;28103:6;28100:30;28097:2;;;28133:18;;:::i;:::-;28097:2;28171:29;28193:6;28171:29;:::i;:::-;28163:37;;28255:4;28249;28245:15;28237:23;;28026:241;;;:::o;28273:132::-;28340:4;28363:3;28355:11;;28393:4;28388:3;28384:14;28376:22;;28345:60;;;:::o;28411:132::-;28478:4;28501:3;28493:11;;28531:4;28526:3;28522:14;28514:22;;28483:60;;;:::o;28549:114::-;28616:6;28650:5;28644:12;28634:22;;28623:40;;;:::o;28669:114::-;28736:6;28770:5;28764:12;28754:22;;28743:40;;;:::o;28789:99::-;28841:6;28875:5;28869:12;28859:22;;28848:40;;;:::o;28894:113::-;28964:4;28996;28991:3;28987:14;28979:22;;28969:38;;;:::o;29013:113::-;29083:4;29115;29110:3;29106:14;29098:22;;29088:38;;;:::o;29132:184::-;29231:11;29265:6;29260:3;29253:19;29305:4;29300:3;29296:14;29281:29;;29243:73;;;;:::o;29322:184::-;29421:11;29455:6;29450:3;29443:19;29495:4;29490:3;29486:14;29471:29;;29433:73;;;;:::o;29512:169::-;29596:11;29630:6;29625:3;29618:19;29670:4;29665:3;29661:14;29646:29;;29608:73;;;;:::o;29687:305::-;29727:3;29746:20;29764:1;29746:20;:::i;:::-;29741:25;;29780:20;29798:1;29780:20;:::i;:::-;29775:25;;29934:1;29866:66;29862:74;29859:1;29856:81;29853:2;;;29940:18;;:::i;:::-;29853:2;29984:1;29981;29977:9;29970:16;;29731:261;;;;:::o;29998:191::-;30038:4;30058:20;30076:1;30058:20;:::i;:::-;30053:25;;30092:20;30110:1;30092:20;:::i;:::-;30087:25;;30131:1;30128;30125:8;30122:2;;;30136:18;;:::i;:::-;30122:2;30181:1;30178;30174:9;30166:17;;30043:146;;;;:::o;30195:96::-;30232:7;30261:24;30279:5;30261:24;:::i;:::-;30250:35;;30240:51;;;:::o;30297:90::-;30331:7;30374:5;30367:13;30360:21;30349:32;;30339:48;;;:::o;30393:149::-;30429:7;30469:66;30462:5;30458:78;30447:89;;30437:105;;;:::o;30548:126::-;30585:7;30625:42;30618:5;30614:54;30603:65;;30593:81;;;:::o;30680:77::-;30717:7;30746:5;30735:16;;30725:32;;;:::o;30763:154::-;30847:6;30842:3;30837;30824:30;30909:1;30900:6;30895:3;30891:16;30884:27;30814:103;;;:::o;30923:307::-;30991:1;31001:113;31015:6;31012:1;31009:13;31001:113;;;31100:1;31095:3;31091:11;31085:18;31081:1;31076:3;31072:11;31065:39;31037:2;31034:1;31030:10;31025:15;;31001:113;;;31132:6;31129:1;31126:13;31123:2;;;31212:1;31203:6;31198:3;31194:16;31187:27;31123:2;30972:258;;;;:::o;31236:320::-;31280:6;31317:1;31311:4;31307:12;31297:22;;31364:1;31358:4;31354:12;31385:18;31375:2;;31441:4;31433:6;31429:17;31419:27;;31375:2;31503;31495:6;31492:14;31472:18;31469:38;31466:2;;;31522:18;;:::i;:::-;31466:2;31287:269;;;;:::o;31562:281::-;31645:27;31667:4;31645:27;:::i;:::-;31637:6;31633:40;31775:6;31763:10;31760:22;31739:18;31727:10;31724:34;31721:62;31718:2;;;31786:18;;:::i;:::-;31718:2;31826:10;31822:2;31815:22;31605:238;;;:::o;31849:233::-;31888:3;31911:24;31929:5;31911:24;:::i;:::-;31902:33;;31957:66;31950:5;31947:77;31944:2;;;32027:18;;:::i;:::-;31944:2;32074:1;32067:5;32063:13;32056:20;;31892:190;;;:::o;32088:180::-;32136:77;32133:1;32126:88;32233:4;32230:1;32223:15;32257:4;32254:1;32247:15;32274:180;32322:77;32319:1;32312:88;32419:4;32416:1;32409:15;32443:4;32440:1;32433:15;32460:180;32508:77;32505:1;32498:88;32605:4;32602:1;32595:15;32629:4;32626:1;32619:15;32646:102;32687:6;32738:2;32734:7;32729:2;32722:5;32718:14;32714:28;32704:38;;32694:54;;;:::o;32754:245::-;32894:34;32890:1;32882:6;32878:14;32871:58;32963:28;32958:2;32950:6;32946:15;32939:53;32860:139;:::o;33005:225::-;33145:34;33141:1;33133:6;33129:14;33122:58;33214:8;33209:2;33201:6;33197:15;33190:33;33111:119;:::o;33236:226::-;33376:34;33372:1;33364:6;33360:14;33353:58;33445:9;33440:2;33432:6;33428:15;33421:34;33342:120;:::o;33468:238::-;33608:34;33604:1;33596:6;33592:14;33585:58;33677:21;33672:2;33664:6;33660:15;33653:46;33574:132;:::o;33712:224::-;33852:34;33848:1;33840:6;33836:14;33829:58;33921:7;33916:2;33908:6;33904:15;33897:32;33818:118;:::o;33942:222::-;34082:34;34078:1;34070:6;34066:14;34059:58;34151:5;34146:2;34138:6;34134:15;34127:30;34048:116;:::o;34170:229::-;34310:34;34306:1;34298:6;34294:14;34287:58;34379:12;34374:2;34366:6;34362:15;34355:37;34276:123;:::o;34405:173::-;34545:25;34541:1;34533:6;34529:14;34522:49;34511:67;:::o;34584:180::-;34724:32;34720:1;34712:6;34708:14;34701:56;34690:74;:::o;34770:182::-;34910:34;34906:1;34898:6;34894:14;34887:58;34876:76;:::o;34958:225::-;35098:34;35094:1;35086:6;35082:14;35075:58;35167:8;35162:2;35154:6;35150:15;35143:33;35064:119;:::o;35189:234::-;35329:34;35325:1;35317:6;35313:14;35306:58;35398:17;35393:2;35385:6;35381:15;35374:42;35295:128;:::o;35429:177::-;35569:29;35565:1;35557:6;35553:14;35546:53;35535:71;:::o;35612:169::-;35752:21;35748:1;35740:6;35736:14;35729:45;35718:63;:::o;35787:222::-;35927:34;35923:1;35915:6;35911:14;35904:58;35996:5;35991:2;35983:6;35979:15;35972:30;35893:116;:::o;36015:225::-;36155:34;36151:1;36143:6;36139:14;36132:58;36224:8;36219:2;36211:6;36207:15;36200:33;36121:119;:::o;36246:237::-;36386:34;36382:1;36374:6;36370:14;36363:58;36455:20;36450:2;36442:6;36438:15;36431:45;36352:131;:::o;36489:122::-;36562:24;36580:5;36562:24;:::i;:::-;36555:5;36552:35;36542:2;;36601:1;36598;36591:12;36542:2;36532:79;:::o;36617:116::-;36687:21;36702:5;36687:21;:::i;:::-;36680:5;36677:32;36667:2;;36723:1;36720;36713:12;36667:2;36657:76;:::o;36739:120::-;36811:23;36828:5;36811:23;:::i;:::-;36804:5;36801:34;36791:2;;36849:1;36846;36839:12;36791:2;36781:78;:::o;36865:122::-;36938:24;36956:5;36938:24;:::i;:::-;36931:5;36928:35;36918:2;;36977:1;36974;36967:12;36918:2;36908:79;:::o

Swarm Source

ipfs://31628b23795ebcc7aee1a200d8f4a4c3f997784b255f55f068073ba235c5f14a
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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