账户
0x7f...f1a6
0x7F...F1a6

0x7F...F1a6

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.8.19+commit.7dd6d404
语言
Solidity
合同源代码
文件 1 的 8: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;
    }
}
合同源代码
文件 2 的 8:IGT.sol
// SPDX-License-Identifier: MIT
/**
 * @dev @brougkr
 */
pragma solidity 0.8.19;
interface IGT 
{ 
    /**
     * @dev { Golden Token Burn }
     */
    function _LiveMintBurn(uint TicketID) external returns (address Recipient); 
}
合同源代码
文件 3 的 8:IMP.sol
// SPDX-License-Identifier: MIT
/**
 * @dev @brougkr
 */
pragma solidity 0.8.19;
interface IMP 
{ 
    /**
     * @dev { For Instances Where Golden Token Or Artists Have A Bespoke Mint Pass Contract }
     */
    function _LiveMintBurn(uint TicketID) external returns (address Recipient, uint ArtistID); 
}
合同源代码
文件 4 的 8:IMinter.sol
// SPDX-License-Identifier: MIT
/**
 * @title IMinter Minter Interface
 * @author @brougkr
 */
pragma solidity ^0.8.19;
interface IMinter 
{ 
    function purchase(uint256 _projectId) payable external returns (uint tokenID); // Custom
    function purchaseTo(address _to, uint _projectId) payable external returns (uint tokenID); // ArtBlocks Standard Minter
    // function purchaseTo(address _to) external returns (uint tokenID); // Custom
    // function purchaseTo(address _to, uint _projectId, address _ownedNFTAddress, uint _ownedNFTTokenID) payable external returns (uint tokenID); // ArtBlocks PolyMinter
    function tokenURI(uint256 _tokenId) external view returns (string memory);
    function _MintToFactory(uint ProjectID, address To, uint Amount) external; // MintPassFactory
    function _MintToFactory(address To, uint Amount) external; // MintPassBespoke
}
合同源代码
文件 5 的 8:LiveMintParis.sol
// SPDX-License-Identifier: MIT
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                             @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                         @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                             @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                                @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                                    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                                      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                                         @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                                           @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@           @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@             @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@              @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@              @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@             @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                 @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@           @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                  @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@         @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                                           @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                                         @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                                      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                                    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                                @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                             @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                                   @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                             @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@                    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
/**
 * @dev: @brougkr
 */
pragma solidity 0.8.19;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import { MerkleProof } from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import { IMinter } from "./IMinter.sol";
import { IMP } from "./IMP.sol";
import { IGT } from "./IGT.sol";
contract LiveMintParis is Ownable, ReentrancyGuard
{  
    struct City
    {
        string _Name;                       // _Name
        uint _QRCurrentIndex;               // _QRCurrentIndex
        bytes32 _RootEligibility;           // _RootEligibility
        bytes32 _RootAmount;                // _RootAmount
        bool _RemoteMintingEnabledArtists;  // _RemoteMintingEnabledArtists
        bool _RemoteMintingEnabledCitizens; // _RemoteMintingEnabledCitizen
    }

    struct Artist
    {
        address _MintPass;        // _MintPass
        address _Minter;          // _Minter
        address _AlternateMinter; // _AlternateMinter
        uint _MaxSupply;          // _MaxSupply
        uint _ArtBlocksProjectID; // _ArtBlocksProjectID 
        uint _PolyStart;          // _PolyStart
        uint _PolyEnd;            // _PolyEnd
    }

    /*-------------------*/
    /*  STATE VARIABLES  */
    /*-------------------*/

    bytes32 private constant _AUTHORIZED = keccak256("AUTHORIZED");                        // Authorized Role
    bytes32 private constant _MINTER_ROLE = keccak256("MINTER_ROLE");                      // Minter Role
    address private constant _DN = 0x00000000000076A84feF008CDAbe6409d2FE638B;             // delegate.cash Delegation Registry
    uint private constant _CCI = 8;                                                        // Current City Index
    address private constant _GOLDEN_TOKEN = 0x985e1932FFd2aA4bC9cE611DFe12816A248cD2cE;   // Golden Token Address
    address private constant _CITIZEN_MINTER = 0xDd06d8483868Cd0C5E69C24eEaA2A5F2bEaFd42b; // ArtBlocks Minter Contract
    address private constant _BRT_MULTISIG = 0xB96E81f80b3AEEf65CB6d0E280b15FD5DBE71937;   // BRT Multisig
    address public _MARKETPLACE;                                                           // Marketplace Address
    uint public _UniqueArtistsInvoked;                                                     // Unique Artists Invoked
    uint public _MaxQRDelegationsPerDay = 10;                                              // Max QR Delegations Per Day
    bool public _QRDelegationsEnabled = true;                                              // QR Delegations Enabled

    /*-------------------*/
    /*     MAPPINGS      */
    /*-------------------*/
    
    mapping(uint => Artist) public Artists;                              // [ArtistID] => Artist
    mapping(uint => City) public Cities;                                 // [CityIndex] => City Struct
    mapping(uint => mapping(address => bool)) public _QRRedeemed;        // [CityIndex][Wallet] => If User Has Redeemed QR
    mapping(uint => mapping(address => uint)) public _QRAllocation;      // [CityIndex][Wallet] => Wallet's QR Code Allocation
    mapping(uint => mapping(uint => address)) public _BrightListCitizen; // [CityIndex][TicketID] => Address Of CryptoCitizen Minting Recipient 
    mapping(uint => mapping(uint => address)) public _BrightListArtist;  // [ArtistID][TicketID] => Address Of Artist NFT Recipient
    mapping(uint => mapping(uint => uint)) public _MintedTokenIDCitizen; // [CityIndex][TicketID] => MintedTokenID
    mapping(uint => mapping(uint => uint)) public _MintedTokenIDArtist;  // [ArtistID][TicketID] => MintedTokenID
    mapping(uint => mapping(uint => bool)) public _MintedArtist;         // [ArtistID][TicketID] => If Minted
    mapping(uint => mapping(uint => bool)) public _MintedCitizen;        // [CityIndex][TicketID] => If Golden Ticket ID Has Minted Or Not
    mapping(uint => mapping(uint => uint)) public _ArtBlocksProjectID;   // [ArtistID][TicketID] => ArtBlocksProjectID
    mapping(uint => mapping(address => uint)) public _QRsRedeemed;       // [CityIndex][Wallet] => Amount Of QRs Redeemed
    mapping(uint => uint) public AmountRemaining;                        // [ArtistID] => Mints Remaining
    mapping(uint => uint) public DailyCalls;                             // [ElapsedDaysSinceUnixEpoch] => Amount Of Function Calls Today                       
    mapping(address => bytes32) public Role;                             // [Wallet] => BRT Minter Role

    /*-------------------*/
    /*      EVENTS       */
    /*-------------------*/

    /**
     * @dev Emitted When `Redeemer` IRL-mints CryptoCitizen Corresponding To Their Redeemed `TicketID`.
     **/
    event LiveMintComplete(address Redeemer, uint TicketID, uint TokenID);

    /**
     * @dev Emitted When `Redeemer` IRL-mints A Artist NFT Corresponding To Their Redeemed `TicketID`.
     */
    event LiveMintCompleteArtist(address Recipient, uint ArtistID, uint TicketID, uint MintedWorkTokenID);

    /**
     * @dev Emitted When `Redeemer` Redeems Golden Token Corresponding To `TicketID` 
     **/
    event QRRedeemed(address Redeemer, uint TicketID);

    /**
     * @dev Emitted When A Contract Is Authorized
     */
    event AuthorizedContract(address NewAddress);

    /**
     * @dev Emitted When A Contract Is Deauthorized
     */
    event DeauthorizedContract(address NewAddress);

    /**
     * @dev Emitted When A TokenID Is Minted From Marketplace
     */
    event Minted(uint TokenID);

    /*-------------------*/
    /*    CONSTRUCTOR    */
    /*-------------------*/

    constructor()
    { 
        Cities[0]._Name = "CryptoGalacticans";  
        Cities[1]._Name = "CryptoVenetians";    
        Cities[2]._Name = "CryptoNewYorkers";   
        Cities[3]._Name = "CryptoBerliners";    
        Cities[4]._Name = "CryptoLondoners";    
        Cities[5]._Name = "CryptoMexas";        
        Cities[6]._Name = "CryptoTokyites";     
        Cities[7]._Name = "CryptoPatagonians"; 
        Cities[8]._Name = "CryptoParisians";
        Cities[8]._QRCurrentIndex = 999;
        Cities[8]._RootEligibility = 0x302dc7afac84ccea916b1efa18450e9a52cadd533f1e74d596f541fe8a115905;
        Cities[8]._RootAmount = 0x4dd20fff095ef5aaf17d6d33b39873402fdc5ff05a0bf8088b2e01fcde3b22ff;
        Cities[9]._Name = "CryptoVenezians";
        Cities[9]._QRCurrentIndex = 1332; 
        Role[msg.sender] = _AUTHORIZED; 
        Role[0xe06F5FAE754e81Bc050215fF89B03d9e9FF20700] = _AUTHORIZED;  // `operator.brightmoments.eth`
        Role[0x18B7511938FBe2EE08ADf3d4A24edB00A5C9B783] = _AUTHORIZED;  // `phil.brightmoments.eth`
        Role[0x91594b5E5d74FCCB3f71674eE74C5F4D44f333D5] = _AUTHORIZED;  // `future.brightmoments.eth`
        Role[0x1A0a3E3AE390a0710f8A6d00587082273eA8F6C9] = _MINTER_ROLE; // BRT Minter #1
        Role[0x4d8013b0c264034CBf22De9DF33e22f58D52F207] = _MINTER_ROLE; // BRT Minter #2
        Role[0x4D9A8CF2fE52b8D49C7F7EAA87b2886c2bCB4160] = _MINTER_ROLE; // BRT Minter #3
        Role[0x124fd966A0D83aA020D3C54AE2c9f4800b46F460] = _MINTER_ROLE; // BRT Minter #4
        Role[0x100469feA90Ac1Fe1073E1B2b5c020A8413635c4] = _MINTER_ROLE; // BRT Minter #5
        Role[0x756De4236373fd17652b377315954ca327412bBA] = _MINTER_ROLE; // BRT Minter #6
        Role[0xc5Dfba6ef7803665C1BDE478B51Bd7eB257A2Cb9] = _MINTER_ROLE; // BRT Minter #7
        Role[0xFBF32b29Bcf8fEe32d43a4Bfd3e7249daec457C0] = _MINTER_ROLE; // BRT Minter #8
        Role[0xF2A15A83DEE7f03C70936449037d65a1C100FF27] = _MINTER_ROLE; // BRT Minter #9
        Role[0x1D2BAB965a4bB72f177Cd641C7BacF3d8257230D] = _MINTER_ROLE; // BRT Minter #10
        Role[0x2e51E8b950D72BDf003b58E357C2BA28FB77c7fB] = _MINTER_ROLE; // BRT Minter #11
        Role[0x8a7186dECb91Da854090be8226222eA42c5eeCb6] = _MINTER_ROLE; // BRT Minter #12
        _transferOwnership(0xe06F5FAE754e81Bc050215fF89B03d9e9FF20700); // `operator.brightmoments.eth`
    }

    /*---------------------*/
    /*    QR REDEMPTION    */
    /*---------------------*/

    /**
     * @dev Redeems Spot(s) For IRL Minting
     * @param ProofEligibility Proof For Merkle Eligibility
     * @param ProofAmounts Proof For Merkle Amounts
     * @param Vault Address Of Vault For Merkle Eligibility (Delegate.xyz)
     * @param Amount Amount Of QR Codes To Redeem
     */
    function RedeemQR (
        bytes32[] calldata ProofEligibility, 
        bytes32[] calldata ProofAmounts,
        address Vault, 
        uint Amount
   ) external nonReentrant {    
        address Recipient = msg.sender;
        if(Vault != address(0)) { if(IDelegationRegistry(_DN).checkDelegateForAll(msg.sender, Vault)) { Recipient = Vault; } } 
        readQREligibility(Recipient, ProofEligibility, ProofAmounts, Amount);
        _QRsRedeemed[_CCI][Recipient] += Amount;
        if(_QRAllocation[_CCI][Recipient] == 0) // User Is Able To Redeem Explicitly 1 QR Code
        {
            require(!_QRRedeemed[_CCI][Recipient], "LiveMint: User Has Already Redeemed");
            _BrightListCitizen[_CCI][Cities[_CCI]._QRCurrentIndex] = Recipient;
            emit QRRedeemed(Recipient, Cities[_CCI]._QRCurrentIndex);
            Cities[_CCI]._QRCurrentIndex++; 
        }
        else // User Is Able To Redeem More Than 1 QR Code Because Their Allocation Is Greater Than 1
        {
            require (
                _QRsRedeemed[_CCI][Recipient] <= _QRAllocation[_CCI][Recipient],
                "LiveMint: User Has No Remaining Authorized QRs To Redeem"
            );
            uint _CurrentQR = Cities[_CCI]._QRCurrentIndex;
            uint _Limit = Amount + _CurrentQR;
            Cities[_CCI]._QRCurrentIndex = _Limit;
            for(_CurrentQR; _CurrentQR < _Limit; _CurrentQR++)
            {
                _BrightListCitizen[_CCI][_CurrentQR] = Recipient;
                emit QRRedeemed(Recipient, _CurrentQR);
            }
        }
        _QRRedeemed[_CCI][Recipient] = true;
    }

    /**
     * @dev Remote Mints Artist NFTs Via Mint Pass LiveMintBurn
     * @param ArtistIDs Array Of ArtistIDs To Mint
     * @param TicketIDs Array Of TicketIDs To Mint
     */
    function RemoteMintArtists(uint[] calldata ArtistIDs, uint[][] calldata TicketIDs) external nonReentrant
    {
        require(tx.origin == msg.sender, "LiveMint: msg.sender Must Be EOA");
        require(Cities[_CCI]._RemoteMintingEnabledArtists, "LiveMint: Remote Minting Of Artists Not Active");
        address Recipient;
        address MintPass;
        address Minter;
        uint ArtBlocksProjectID;
        uint MintedWorkTokenID;
        uint TicketID;
        uint ActiveArtistID;
        for(uint ArtistIDIndex; ArtistIDIndex < ArtistIDs.length; ArtistIDIndex++)
        {
            ActiveArtistID = ArtistIDs[ArtistIDIndex];
            MintPass = Artists[ActiveArtistID]._MintPass;
            Minter = Artists[ActiveArtistID]._Minter;
            for(uint TicketIDIndex; TicketIDIndex < TicketIDs[ArtistIDIndex].length; TicketIDIndex++)
            {
                TicketID = TicketIDs[ArtistIDIndex][TicketIDIndex];
                require(!_MintedArtist[ActiveArtistID][TicketID], "LiveMint: Artist Mint Pass Already Minted");
                _MintedArtist[ActiveArtistID][TicketID] = true;
                (Recipient, ArtBlocksProjectID) = IMP(MintPass)._LiveMintBurn(TicketID);
                require(Recipient == msg.sender, "LiveMint: msg.sender Is Not The Owner Of Input Mint Pass");
                MintedWorkTokenID = IMinter(Minter).purchaseTo(Recipient, ArtBlocksProjectID);
                _MintedTokenIDArtist[ActiveArtistID][TicketID] = MintedWorkTokenID;
                emit LiveMintCompleteArtist(Recipient, ActiveArtistID, TicketID, MintedWorkTokenID);
            }
        }
    }

    /**
     * @dev Remote Mints GoldenTokens For Citizens
     * @param TicketIDs Array Of TicketIDs To Mint
     */
    function RemoteMintCitizens(uint[] calldata TicketIDs) external nonReentrant
    {
        require(tx.origin == msg.sender, "LiveMint: msg.sender Must Be EOA");
        require(Cities[_CCI]._RemoteMintingEnabledCitizens, "LiveMint: Remote Minting Of Citizens Not Active");
        address Recipient;
        uint MintedWorkTokenID;
        for(uint TicketID; TicketID < TicketIDs.length; TicketID++)
        {
            require(TicketIDs[TicketID] < 999, "LiveMint: Invalid Input TicketID, Must Be Golden Token");
            require(!_MintedCitizen[_CCI][TicketIDs[TicketID]], "LiveMint: Golden Token Already Minted");
            _MintedCitizen[_CCI][TicketIDs[TicketID]] = true;
            Recipient = IGT(_GOLDEN_TOKEN)._LiveMintBurn(TicketIDs[TicketID]);
            require(Recipient == msg.sender, "LiveMint: msg.sender Is Not Owner Of Golden Token");
            MintedWorkTokenID = IMinter(_CITIZEN_MINTER).purchaseTo(Recipient, _CCI);
            _MintedTokenIDCitizen[_CCI][TicketIDs[TicketID]] = MintedWorkTokenID;
            emit LiveMintComplete(Recipient, TicketIDs[TicketID], MintedWorkTokenID); 
        }
    }

    /*--------------------*/
    /*    LIVE MINTING    */
    /*--------------------*/

    /**
     * @dev Batch Mints Verified Users On The Brightlist CryptoCitizens
     * @param TicketIDs Array Of TicketIDs To Mint
     * note: { For CryptoCitizen Cities }
     */
    function _LiveMintCitizen(uint[] calldata TicketIDs) external onlyMinter
    {
        address Recipient;
        uint MintedWorkTokenID;
        for(uint TicketID; TicketID < TicketIDs.length; TicketID++)
        {
            require(!_MintedCitizen[_CCI][TicketIDs[TicketID]], "LiveMint: Golden Token Already Minted");
            if(_BrightListCitizen[_CCI][TicketIDs[TicketID]] != address(0)) { Recipient = _BrightListCitizen[_CCI][TicketIDs[TicketID]]; }
            else if (TicketIDs[TicketID] < 999) { Recipient = IGT(_GOLDEN_TOKEN)._LiveMintBurn(TicketIDs[TicketID]); }
            else { revert("LiveMint: TicketID Is Not Eligible To Mint Citizen"); }
            require(Recipient != address(0), "LiveMint: Invalid Recipient");
            _MintedCitizen[_CCI][TicketIDs[TicketID]] = true;
            MintedWorkTokenID = IMinter(_CITIZEN_MINTER).purchaseTo(Recipient, _CCI);
            _MintedTokenIDCitizen[_CCI][TicketIDs[TicketID]] = MintedWorkTokenID;
            emit LiveMintComplete(Recipient, TicketIDs[TicketID], MintedWorkTokenID); 
        }
    }

    /**
     * @dev Burns Artist Mint Pass In Exchange For The Minted Work
     * @param ArtistID ArtistID To Mint
     * @param TicketIDs Array Of TicketIDs To Mint
     * note: { For Instances Where Multiple Artists Share The Same Mint Pass & Return (Recipient, ArtBlocksProjectID) }
     */
    function _LiveMintArtist(uint ArtistID, uint[] calldata TicketIDs) external onlyMinter
    {
        address Recipient;
        address MintPass = Artists[ArtistID]._MintPass;
        address Minter = Artists[ArtistID]._Minter;
        uint ArtBlocksProjectID;
        uint MintedWorkTokenID;
        uint TicketID;
        require(AmountRemaining[ArtistID] > 0, "LiveMint: ArtistID Mint Limit Reached");
        require(TicketIDs.length <= AmountRemaining[ArtistID], "LiveMint: TicketID Length Exceeds ArtistID Mint Limit");
        AmountRemaining[ArtistID] = AmountRemaining[ArtistID] - TicketIDs.length;
        for(uint x; x < TicketIDs.length; x++)
        {
            TicketID = TicketIDs[x];
            require(!_MintedArtist[ArtistID][TicketID], "LiveMint: Artist Mint Pass Already Minted");
            _MintedArtist[ArtistID][TicketID] = true;
            (Recipient, ArtBlocksProjectID) = IMP(MintPass)._LiveMintBurn(TicketID);
            MintedWorkTokenID = IMinter(Minter).purchaseTo(Recipient, ArtBlocksProjectID); // Pre-Defined Minter Contract
            _MintedTokenIDArtist[ArtistID][TicketID] = MintedWorkTokenID;
            emit LiveMintCompleteArtist(Recipient, ArtistID, TicketID, MintedWorkTokenID);
        }
    }

    /**
     * @dev Burns Artist Mint Pass In Exchange For The Minted Work
     * @param ArtistIDs Array Of ArtistIDs To Mint
     * @param TicketIDs 2D-Array Of TicketIDs To Mint
     * note: { For Instances Where Multiple Artists Share The Same Mint Pass & Return (Recipient, ArtBlocksProjectID) }
     */
    function _LiveMintArtistBatch(uint[] calldata ArtistIDs, uint[][] calldata TicketIDs) external onlyMinter
    {
        address Recipient;
        address MintPass;
        address Minter;
        uint ArtBlocksProjectID;
        uint MintedWorkTokenID;
        uint TicketID;
        uint ActiveArtistID;
        for(uint ArtistIDIndex; ArtistIDIndex < ArtistIDs.length; ArtistIDIndex++)
        {
            ActiveArtistID = ArtistIDs[ArtistIDIndex];
            MintPass = Artists[ActiveArtistID]._MintPass;
            Minter = Artists[ActiveArtistID]._Minter;
            for(uint TicketIDIndex; TicketIDIndex < TicketIDs[ArtistIDIndex].length; TicketIDIndex++)
            {
                TicketID = TicketIDs[ArtistIDIndex][TicketIDIndex];
                require(!_MintedArtist[ActiveArtistID][TicketID], "LiveMint: Artist Mint Pass Already Minted");
                _MintedArtist[ActiveArtistID][TicketID] = true;
                (Recipient, ArtBlocksProjectID) = IMP(MintPass)._LiveMintBurn(TicketID);
                MintedWorkTokenID = IMinter(Minter).purchaseTo(Recipient, ArtBlocksProjectID);
                _MintedTokenIDArtist[ActiveArtistID][TicketID] = MintedWorkTokenID;
                emit LiveMintCompleteArtist(Recipient, ActiveArtistID, TicketID, MintedWorkTokenID);
            }
        }
    }

    /**
     * @dev Mints An Artist Work Directly From Marketplace
     * @param Recipient Address To Mint To
     * @param ArtistID ArtistID To Mint
     * @param Amount Amount To Mint
     */
    function _LiveMintMarketplace(address Recipient, uint ArtistID, uint Amount) external onlyMarketplace
    {
        uint _AmountRemaining = AmountRemaining[ArtistID];
        require(Amount <= _AmountRemaining, "LiveMint: Not Enough Mints Remaining For Desired ArtistID");
        AmountRemaining[ArtistID] = _AmountRemaining - Amount;
        address _Minter = Artists[ArtistID]._Minter;
        uint _ABProjectID = Artists[ArtistID]._ArtBlocksProjectID;
        uint _TokenID;
        for(uint PurchaseAmt; PurchaseAmt < Amount; PurchaseAmt++)
        {
            _TokenID = IMinter(_Minter).purchaseTo(Recipient, _ABProjectID);
            emit Minted (_TokenID);
        }
    }

    /*-------------------*/
    /*  OWNER FUNCTIONS  */
    /*-------------------*/

    /**
     * @dev Initializes A LiveMint Artist
     */
    function __InitLiveMint (Artist memory _Params) external onlyAdmin returns (uint ArtistID)
    {
        ArtistID = _UniqueArtistsInvoked;
        AmountRemaining[ArtistID] = _Params._MaxSupply;
        Artists[ArtistID] = _Params;
        _UniqueArtistsInvoked = ArtistID + 1;
        return ArtistID;
    }

    /**
     * @dev Changes The Current Active Marketplace Address
     */
    function __DelegateQR (address Recipient) external onlyAdmin
    {
        require(_QRDelegationsEnabled, "LiveMint: QR Delegations Not Enabled");
        uint _DaysElapsed = block.timestamp / 86400;
        require(DailyCalls[_DaysElapsed] + 1 <= _MaxQRDelegationsPerDay, "LiveMint: Max Per Day Reached");
        require(!_QRRedeemed[_CCI][Recipient], "LiveMint: User Has Already Redeemed");
        DailyCalls[_DaysElapsed]++;
        _QRRedeemed[_CCI][Recipient] = true;
        _BrightListCitizen[_CCI][Cities[_CCI]._QRCurrentIndex] = Recipient;
        emit QRRedeemed(Recipient, Cities[_CCI]._QRCurrentIndex);
        Cities[_CCI]._QRCurrentIndex++;
    }

    /**
     * @dev Changes Merkle Root For Citizen LiveMint Eligibility
     * @param NewRoot The New Merkle Root To Seed
     */
    function __ChangeRootEligibility (bytes32 NewRoot) external onlyAdmin { Cities[_CCI]._RootEligibility = NewRoot; }

    /**
     * @dev Changes Merkle Root For Citizen LiveMint Amounts
     * @param NewRoot The New Merkle Root To Seed
     */
    function __ChangeRootAmounts (bytes32 NewRoot) external onlyAdmin { Cities[_CCI]._RootAmount = NewRoot; }

    /**
     * @dev Changes Merkle Root For Artist LiveMints
     * @param EligibilityRoot The New Merkle Eligibility Root To Seed
     * @param EligibilityAmount The New Merkle Amount Root To Seed
     */
    function __ChangeRoots (bytes32 EligibilityRoot, bytes32 EligibilityAmount) external onlyAdmin
    {
        Cities[_CCI]._RootEligibility = EligibilityRoot;
        Cities[_CCI]._RootAmount = EligibilityAmount;
    }

    /**
     * @dev Overwrites QR Allocation(s)
     * @param Addresses Array Of Addresses To Overwrite
     * @param Amounts Array Of Amounts To Overwrite
     */
    function __QRAllocationsOverwrite (address[] calldata Addresses, uint[] calldata Amounts) external onlyAdmin
    {
        require(Addresses.length == Amounts.length, "LiveMint: Input Arrays Must Match");
        for(uint x; x < Addresses.length; x++) { _QRAllocation[_CCI][Addresses[x]] = Amounts[x]; }
    }

    /**
     * @dev Increments QR Allocation(s)
     * @param Addresses Array Of Addresses To Increment
     * @param Amounts Array Of Amounts To Increment
     */
    function __QRAllocationsIncrement (address[] calldata Addresses, uint[] calldata Amounts) external onlyAdmin
    {
        require(Addresses.length == Amounts.length, "LiveMint: Input Arrays Must Match");
        for(uint x; x < Addresses.length; x++) { _QRAllocation[_CCI][Addresses[x]] += Amounts[x]; }
    }

    /**
     * @dev Overrides QR To Mint To Multisig
     * @param TicketIDs Array Of TicketIDs To Override
     */
    function __QRAllocationsSetNoShow (uint[] calldata TicketIDs) external onlyAdmin
    {
        for(uint TicketIndex; TicketIndex < TicketIDs.length; TicketIndex++)
        {
            require(!_MintedCitizen[_CCI][TicketIDs[TicketIndex]], "LiveMint: Ticket ID Already Minted");
            require(TicketIDs[TicketIndex] > 999, "LiveMint: Invalid TicketID");
            _BrightListCitizen[_CCI][TicketIDs[TicketIndex]] = _BRT_MULTISIG;
        }
    }

    /*-------------------*/
    /*  OWNER FUNCTIONS  */
    /*-------------------*/

    /**
     * @dev Changes Max QR Delegations Per Day
     */
    function __ChangeQRDelegationsEnabled(bool NewState) external onlyOwner { _QRDelegationsEnabled = NewState; }
    
    /**
     * @dev Changes Max QR Delegations Per Day
     */
    function __ChangeMaxPerDay(uint NewMax) external onlyOwner { _MaxQRDelegationsPerDay = NewMax; }

    /**
     * @dev Changes The Current Active Marketplace Address
     * @param NewAddress The New Address To Seed
     */
    function __ChangeMarketplaceAddress(address NewAddress) external onlyOwner { _MARKETPLACE = NewAddress; }

    /**
     * @dev Flips Remote Minting State For CryptoCitizens (True or False)
     */
    function __FlipRemoteMintingCitizens() external onlyOwner 
    { 
        Cities[_CCI]._RemoteMintingEnabledCitizens = !Cities[_CCI]._RemoteMintingEnabledCitizens; 
    }

    /**
     * @dev Flips Remote Minting State For Artists
     */
    function __FlipRemoteMintingArtists() external onlyOwner 
    { 
        Cities[_CCI]._RemoteMintingEnabledArtists = !Cities[_CCI]._RemoteMintingEnabledArtists; 
    }

    /**
     * @dev Flips Remote Minting State For Both Artists & Citizens
     */
    function __FlipRemoteMintingStates() external onlyOwner
    {
        Cities[_CCI]._RemoteMintingEnabledArtists = !Cities[_CCI]._RemoteMintingEnabledArtists; 
        Cities[_CCI]._RemoteMintingEnabledCitizens = !Cities[_CCI]._RemoteMintingEnabledCitizens;
    }

    /**
     * @dev Grants Address BRT Minter Role
     * @param Minter Address To Grant Role
     * note: BRT Minter Role Is Required To Mint NFTs
     **/
    function __AddMinter(address Minter) external onlyOwner { Role[Minter] = _MINTER_ROLE; }
    
    /**
     * @dev Deactivates Address From BRT Minter Role
     * @param Minter Address To Remove Role
     * note: BRT Minter Role Is Required To Mint NFTs
     **/
    function __RemoveMinter(address Minter) external onlyOwner { Role[Minter] = 0x0; }

    /**
     * @dev Changes Mint Pass Address For Artist LiveMints
     * @param ProjectID Artist ProjectID
     * @param Contract Mint Pass Contract Address
     * note: Mint Pass Is Burned In Exchange For Minted Work
     */
    function __ChangeMintPass(uint ProjectID, address Contract) external onlyOwner { Artists[ProjectID]._MintPass = Contract; }

    /**
     * @dev Changes Minter Address For Artist LiveMints
     * @param ProjectID Artist ProjectID
     * @param Contract Minter Contract Address
     */
    function __ChangeMinter(uint ProjectID, address Contract) external onlyOwner { Artists[ProjectID]._Minter = Contract; }

    /**
     * @dev Changes QR Current Index
     * @param NewIndex The Next QR Index To Redeem
     */
    function __ChangeQRIndex(uint NewIndex) external onlyOwner { Cities[_CCI]._QRCurrentIndex = NewIndex; }

    /**
     * @dev Instantiates New City
     * @param Name Name Of City
     * @param CityIndex CityIndex Of City
     * @param QRIndex QRIndex Of City
     * @param RemoteMintingEnabledArtists Remote Minting Enabled For Artists
     * @param RemoteMintingEnabledCitizens Remote Minting Enabled For Citizens
     * note: CityIndex Always Corresponds To ArtBlocks ProjectID For CryptoCitizens
     */
    function __NewCity (
        string calldata Name,
        uint CityIndex,
        uint QRIndex,
        bool RemoteMintingEnabledArtists,
        bool RemoteMintingEnabledCitizens
   ) external onlyOwner {
        Cities[CityIndex] = City(
            Name,
            QRIndex,
            0x6942069420694206942069420694206942069420694206942069420694206942,
            0x6942069420694206942069420694206942069420694206942069420694206942,
            RemoteMintingEnabledArtists,
            RemoteMintingEnabledCitizens
        );
    }

    /**
     * @dev Changes The Amount Remaining For An Artist Mint
     * @param ArtistID ArtistID To Change
     * @param Amount Amount To Change To
     */
    function __NewAmountRemaining(uint ArtistID, uint Amount) external onlyOwner
    {
        AmountRemaining[ArtistID] = Amount;
    }
    
    /**
     * @dev Instantiates A New City
     * @param CityIndex CityIndex Of New City
     * @param NewCity The City Struct
     */
    function __NewCityStruct(uint CityIndex, City memory NewCity) external onlyOwner { Cities[CityIndex] = NewCity; }

    /**
     * @dev Returns An Artist Struct
     * @param ArtistID The ArtistID To Change
     * @param NewArtist The Artist Struct
     */
    function __NewArtistStruct(uint ArtistID, Artist memory NewArtist) external onlyOwner { Artists[ArtistID] = NewArtist; }

    /**
     * @dev Changes The Minter Address For An Artist
     * @param ArtistID ArtistID To Change
     * @param Minter New Minter Address
     */
    function __NewArtistMinter(uint ArtistID, address Minter) external onlyOwner { Artists[ArtistID]._Minter = Minter; }

    /**
     * @dev Withdraws Any Ether Mistakenly Sent to Contract to Multisig
     **/
    function __WithdrawEther() external onlyOwner { payable(msg.sender).transfer(address(this).balance); }

    /**
     * @dev Executes Arbitrary Transaction(s)
     * @param Targets Array Of Addresses To Execute Transactions On
     * @param Values Array Of Values To Execute Transactions With
     * @param Datas Array Of Datas To Execute Transactions With
     */
    function __InitTransaction(address[] memory Targets, uint[] memory Values, bytes[] memory Datas) external onlyOwner
    {
        for(uint x; x < Targets.length; x++) 
        {
            (bool success,) = Targets[x].call{value:(Values[x])}(Datas[x]);
            require(success, "i have failed u anakin");
        }
    }

    /**
     * @dev Authorizes An Address
     * @param NewAddress Address To Authorize
     */
    function ____AddressAuthorize(address NewAddress) external onlyOwner 
    { 
        Role[NewAddress] = _AUTHORIZED; 
        emit AuthorizedContract(NewAddress);
    }

    /**
     * @dev Deauthorizes An Address
     * @param NewAddress Address To Deauthorize
     */
    function ____AddressDeauthorize(address NewAddress) external onlyOwner 
    { 
        Role[NewAddress] = 0x0; 
        emit DeauthorizedContract(NewAddress);
    }
    
    /*-------------------*/
    /*    PUBLIC VIEW    */
    /*-------------------*/

    /**
     * @dev Returns A User's QR Allocation Amount, Or 0 If Not Eligible
     */
    function readEligibility (
        address Recipient, 
        bytes32[] memory Proof, 
        bytes32[] memory ProofAmount, 
        uint Amount
    ) public view returns (uint ) {
        bool Eligible = readQREligibility(Recipient, Proof, ProofAmount, Amount);
        uint Allocation = _QRAllocation[_CCI][Recipient];
        uint AmountRedeemed = _QRsRedeemed[_CCI][Recipient];
        if(Eligible && Allocation > AmountRedeemed) { return Allocation - AmountRedeemed; }
        else if (Eligible && Allocation == 0 && AmountRedeemed == 0) { return 1; }
        else { return 0; }
    }

    /**
     * @dev Returns If User Is Eligible To Redeem QR Code
     */
    function readQREligibility (
        address Recipient, 
        bytes32[] memory ProofEligibility, 
        bytes32[] memory ProofAmount, 
        uint Amount
    ) public view returns (bool) {
        require(Amount > 0, "LiveMint: QR Redemption Amount Must Be > 0");
        bytes32 Leaf = keccak256(abi.encodePacked(Recipient));
        bytes32 LeafAmount = keccak256(abi.encodePacked(Recipient, Amount));
        require(MerkleProof.verify(ProofEligibility, Cities[_CCI]._RootEligibility, Leaf), "LiveMint: Invalid Merkle Eligibility Proof");
        require(MerkleProof.verify(ProofAmount, Cities[_CCI]._RootAmount, LeafAmount), "LiveMint: Invalid Merkle Amount Proof");
        return true;
    }

    /**
     * @dev Returns How Many QR Codes A User Has Redeemed
     */
    function readAmountRedeemed(address Recipient) public view returns(uint) { return _QRsRedeemed[_CCI][Recipient]; }

    /**
     * @dev Returns An Array Of Unminted Golden Tokens
     */
    function readCitizenUnmintedTicketIDs() public view returns(uint[] memory)
    {
        uint[] memory UnmintedTokenIDs = new uint[](1000);
        uint Counter;
        uint CityIDBuffer = _CCI % 6 * 333;
        uint _TokenID;
        for(uint TokenID; TokenID < 1000; TokenID++)
        {
            _TokenID = TokenID + CityIDBuffer;
            if
            (
                (!_MintedCitizen[_CCI][_TokenID]
                &&
                _BrightListCitizen[_CCI][_TokenID] != address(0))
                ||
                (!_MintedCitizen[_CCI][_TokenID] && _TokenID < 999)
            ) 
            { 
                UnmintedTokenIDs[Counter] = _TokenID; 
                Counter++;
            }
        }
        uint[] memory FormattedUnMintedTokenIDs = new uint[](Counter);
        for(uint Index; Index < Counter; Index++)
        {
            FormattedUnMintedTokenIDs[Index] = UnmintedTokenIDs[Index];
        }
        return FormattedUnMintedTokenIDs;
    }

    /**
     * @dev Returns An Array Of Unminted Golden Tokens
     */
    function readCitizenMintedTicketIDs(uint CityID) public view returns(uint[] memory)
    {
        uint[] memory MintedTokenIDs = new uint[](1000);
        uint Counter;
        uint CityIDBuffer = (CityID % 6) * 333;
        uint _TicketID;
        for(uint TicketID; TicketID < 1000; TicketID++)
        {
            _TicketID = TicketID + CityIDBuffer;
            if(_MintedCitizen[CityID][_TicketID]) 
            { 
                MintedTokenIDs[Counter] = _TicketID; 
                Counter++;
            }
        }
        uint[] memory FormattedMintedTokenIDs = new uint[](Counter);
        uint Found;
        for(uint FormattedTokenID; FormattedTokenID < Counter; FormattedTokenID++)
        {
            if(MintedTokenIDs[FormattedTokenID] != 0 || (MintedTokenIDs[FormattedTokenID] == 0 && FormattedTokenID == 0))
            {
                FormattedMintedTokenIDs[Found] = MintedTokenIDs[FormattedTokenID];
                Found++;
            }
        }
        return FormattedMintedTokenIDs;
    }

    /**
     * @dev Returns A 2d Array Of Checked In & Unminted TicketIDs Awaiting A Mint
     */
    function readCitizenCheckedInTicketIDs() public view returns(uint[] memory TokenIDs)
    {
        uint[] memory _TokenIDs = new uint[](1000);
        uint CityIDBuffer = (_CCI % 6) * 333;
        uint _TicketID;
        uint Counter;
        for(uint TicketID; TicketID < 1000; TicketID++)
        {
            _TicketID = TicketID + CityIDBuffer;
            if(
                !_MintedCitizen[_CCI][_TicketID]
                &&
                _BrightListCitizen[_CCI][_TicketID] != address(0)
            ) 
            { 
                _TokenIDs[Counter] = _TicketID; 
                Counter++;
            }
        }
        uint[] memory FormattedCheckedInTickets = new uint[](Counter);
        uint Found;
        for(uint x; x < Counter; x++)
        {
            if(_TokenIDs[x] != 0 || (_TokenIDs[x] == 0 && x == 0))
            {
                FormattedCheckedInTickets[Found] = _TokenIDs[x];
                Found++;
            }
        }
        return FormattedCheckedInTickets;
    }

    /**
     * @dev Returns A 2d Array Of Minted ArtistIDs
     */
    function readArtistUnmintedTicketIDs(uint[] calldata ArtistIDs, uint Range) public view returns(uint[][] memory TokenIDs)
    {
        uint[][] memory _TokenIDs = new uint[][](ArtistIDs.length);
        uint Index;
        for(uint ArtistID; ArtistID < ArtistIDs.length; ArtistID++)
        {
            uint[] memory UnmintedArtistTokenIDs = new uint[](Range);
            uint Counter;
            for(uint TokenID; TokenID < Range; TokenID++)
            {
                if(!_MintedArtist[ArtistIDs[ArtistID]][TokenID]) 
                { 
                    UnmintedArtistTokenIDs[Counter] = TokenID; 
                    Counter++;
                }
            }
            uint[] memory FormattedUnMintedArtistIDs = new uint[](Counter);
            uint Found;
            for(uint x; x < Counter; x++)
            {
                if(UnmintedArtistTokenIDs[x] != 0 || (UnmintedArtistTokenIDs[x] == 0 && x == 0))
                {
                    FormattedUnMintedArtistIDs[Found] = UnmintedArtistTokenIDs[x];
                    Found++;
                }
            }
            _TokenIDs[Index] = FormattedUnMintedArtistIDs;
            Index++;
        }
        return (_TokenIDs);
    }

    /**
     * @dev Returns A 2d Array Of Minted ArtistIDs
     */
    function readArtistMintedTicketIDs(uint[] calldata ArtistIDs, uint Range) public view returns(uint[][] memory TokenIDs)
    {
        uint[][] memory _TokenIDs = new uint[][](ArtistIDs.length);
        uint Index;
        for(uint ArtistID; ArtistID < ArtistIDs.length; ArtistID++)
        {
            uint[] memory MintedTokenIDs = new uint[](Range);
            uint Counter;
            for(uint TokenID; TokenID < Range; TokenID++)
            {
                if(_MintedArtist[ArtistIDs[ArtistID]][TokenID])
                { 
                    MintedTokenIDs[Counter] = TokenID; 
                    Counter++;
                }
            }
            uint[] memory FormattedMintedTokenIDs = new uint[](Counter);
            uint Found;
            for(uint x; x < Counter; x++)
            {
                if(MintedTokenIDs[x] != 0 || (MintedTokenIDs[x] == 0 && x == 0))
                {
                    FormattedMintedTokenIDs[Found] = MintedTokenIDs[x];
                    Found++;
                }
            }
            _TokenIDs[Index] = FormattedMintedTokenIDs;
            Index++;
        }
        return (_TokenIDs);
    }

    /**
     * @dev Returns Original Recipients Of CryptoCitizens
     */
    function readCitizenBrightList(uint CityIndex) public view returns(address[] memory Recipients)
    {
        address[] memory _Recipients = new address[](1000);
        uint Start = (CityIndex % 6) * 333;
        for(uint x; x < 1000; x++) { _Recipients[x] = _BrightListCitizen[CityIndex][Start+x]; }
        return _Recipients;
    }

    /**
     * @dev Returns Original Recipient Of Artist NFTs
     */
    function readArtistBrightList(uint ArtistID, uint Range) public view returns(address[] memory Recipients)
    {
        address[] memory _Recipients = new address[](Range);
        for(uint x; x < Range; x++) { _Recipients[x] = _BrightListArtist[ArtistID][x]; }
        return _Recipients;    
    }

    /**
     * @dev Returns The City Struct At Index Of `CityIndex`
     */
    function readCitizenCity(uint CityIndex) public view returns(City memory) { return Cities[CityIndex]; }

    /**
     * @dev Returns The Artist Struct At Index Of `ArtistID`
     */
    function readArtist(uint ArtistID) public view returns(Artist memory) { return Artists[ArtistID]; }

    /**
     * @dev Returns A Minted Work TokenID Corresponding To The Input Artist TicketID 
     */
    function readArtistMintedTokenID(uint ArtistID, uint TicketID) external view returns (uint)
    {
        if(!_MintedArtist[ArtistID][TicketID]) { return 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; }
        else { return _MintedTokenIDArtist[ArtistID][TicketID]; }
    }

    /**
     * @dev Returns A Minted Citizen TokenID Corresponding To Input TicketID
     */
    function readCitizenMintedTokenID(uint CityIndex, uint TicketID) external view returns(uint)
    {
        if(!_MintedCitizen[CityIndex][TicketID]) { return type(uint).max; }
        else { return _MintedTokenIDCitizen[CityIndex][TicketID]; }  
    }

    /*-------------------------*/
    /*     ACCESS MODIFIERS    */
    /*-------------------------*/

    /**
     * @dev Access Modifier That Allows Only BrightListed BRT Minters
     **/
    modifier onlyMinter() 
    {
        require(Role[msg.sender] == _MINTER_ROLE, "LiveMint | onlyMinter | Caller Is Not Approved BRT Minter");
        _;
    }

    /**
     * @dev Access Modifier That Allows Only Authorized Contracts
     */
    modifier onlyAdmin()
    {
        require(Role[msg.sender] == _AUTHORIZED || msg.sender == owner(), "LiveMint | onlyAdmin | Caller Is Not Approved Admin");
        _;
    }

    /**
     * @dev onlyMarketplace Access Modifier
     */
    modifier onlyMarketplace
    {
        require(_MARKETPLACE == msg.sender, "LiveMint | onlyMarketplace | Caller Is Not Marketplace");
        _;
    }
}

/**
 * @dev Interface For Delegate.cash
 */
interface IDelegationRegistry
{
    /**
     * @dev Checks If A Vault Has Delegated To The Delegate
     */
    function checkDelegateForAll(address delegate, address delegator) external view returns (bool);
}
合同源代码
文件 6 的 8:MerkleProof.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.2) (utils/cryptography/MerkleProof.sol)

pragma solidity ^0.8.0;

/**
 * @dev These functions deal with verification of Merkle Tree proofs.
 *
 * The tree and the proofs can be generated using our
 * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
 * You will find a quickstart guide in the readme.
 *
 * WARNING: You should avoid using leaf values that are 64 bytes long prior to
 * hashing, or use a hash function other than keccak256 for hashing leaves.
 * This is because the concatenation of a sorted pair of internal nodes in
 * the merkle tree could be reinterpreted as a leaf value.
 * OpenZeppelin's JavaScript library generates merkle trees that are safe
 * against this attack out of the box.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Calldata version of {verify}
     *
     * _Available since v4.7._
     */
    function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {
        return processProofCalldata(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     *
     * _Available since v4.4._
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Calldata version of {processProof}
     *
     * _Available since v4.7._
     */
    function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    /**
     * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by
     * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Calldata version of {multiProofVerify}
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    /**
     * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction
     * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another
     * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false
     * respectively.
     *
     * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree
     * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the
     * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer).
     *
     * _Available since v4.7._
     */
    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofLen = proof.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            require(proofPos == proofLen, "MerkleProof: invalid multiproof");
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    /**
     * @dev Calldata version of {processMultiProof}.
     *
     * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details.
     *
     * _Available since v4.7._
     */
    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by
        // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the
        // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of
        // the merkle tree.
        uint256 leavesLen = leaves.length;
        uint256 proofLen = proof.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof");

        // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using
        // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop".
        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        // At each step, we compute the next hash using two values:
        // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we
        //   get the next hash.
        // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the
        //   `proof` array.
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            require(proofPos == proofLen, "MerkleProof: invalid multiproof");
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}
合同源代码
文件 7 的 8:Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

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

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

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

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

    /**
     * @dev 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. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling 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);
    }
}
合同源代码
文件 8 的 8:ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

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

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

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

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

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

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}
设置
{
  "compilationTarget": {
    "contracts/LiveMintParis.sol": "LiveMintParis"
  },
  "evmVersion": "paris",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "remappings": [],
  "viaIR": true
}
ABI
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"NewAddress","type":"address"}],"name":"AuthorizedContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"NewAddress","type":"address"}],"name":"DeauthorizedContract","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"Redeemer","type":"address"},{"indexed":false,"internalType":"uint256","name":"TicketID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"TokenID","type":"uint256"}],"name":"LiveMintComplete","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"Recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"ArtistID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"TicketID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"MintedWorkTokenID","type":"uint256"}],"name":"LiveMintCompleteArtist","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"TokenID","type":"uint256"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"Redeemer","type":"address"},{"indexed":false,"internalType":"uint256","name":"TicketID","type":"uint256"}],"name":"QRRedeemed","type":"event"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"AmountRemaining","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"Artists","outputs":[{"internalType":"address","name":"_MintPass","type":"address"},{"internalType":"address","name":"_Minter","type":"address"},{"internalType":"address","name":"_AlternateMinter","type":"address"},{"internalType":"uint256","name":"_MaxSupply","type":"uint256"},{"internalType":"uint256","name":"_ArtBlocksProjectID","type":"uint256"},{"internalType":"uint256","name":"_PolyStart","type":"uint256"},{"internalType":"uint256","name":"_PolyEnd","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"Cities","outputs":[{"internalType":"string","name":"_Name","type":"string"},{"internalType":"uint256","name":"_QRCurrentIndex","type":"uint256"},{"internalType":"bytes32","name":"_RootEligibility","type":"bytes32"},{"internalType":"bytes32","name":"_RootAmount","type":"bytes32"},{"internalType":"bool","name":"_RemoteMintingEnabledArtists","type":"bool"},{"internalType":"bool","name":"_RemoteMintingEnabledCitizens","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"DailyCalls","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"ProofEligibility","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ProofAmounts","type":"bytes32[]"},{"internalType":"address","name":"Vault","type":"address"},{"internalType":"uint256","name":"Amount","type":"uint256"}],"name":"RedeemQR","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ArtistIDs","type":"uint256[]"},{"internalType":"uint256[][]","name":"TicketIDs","type":"uint256[][]"}],"name":"RemoteMintArtists","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"TicketIDs","type":"uint256[]"}],"name":"RemoteMintCitizens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"Role","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"_ArtBlocksProjectID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"_BrightListArtist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"_BrightListCitizen","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ArtistID","type":"uint256"},{"internalType":"uint256[]","name":"TicketIDs","type":"uint256[]"}],"name":"_LiveMintArtist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ArtistIDs","type":"uint256[]"},{"internalType":"uint256[][]","name":"TicketIDs","type":"uint256[][]"}],"name":"_LiveMintArtistBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"TicketIDs","type":"uint256[]"}],"name":"_LiveMintCitizen","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"Recipient","type":"address"},{"internalType":"uint256","name":"ArtistID","type":"uint256"},{"internalType":"uint256","name":"Amount","type":"uint256"}],"name":"_LiveMintMarketplace","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"_MARKETPLACE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_MaxQRDelegationsPerDay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"_MintedArtist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"_MintedCitizen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"_MintedTokenIDArtist","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"_MintedTokenIDCitizen","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"_QRAllocation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_QRDelegationsEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"_QRRedeemed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"_QRsRedeemed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_UniqueArtistsInvoked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"Minter","type":"address"}],"name":"__AddMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"NewAddress","type":"address"}],"name":"__ChangeMarketplaceAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"NewMax","type":"uint256"}],"name":"__ChangeMaxPerDay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ProjectID","type":"uint256"},{"internalType":"address","name":"Contract","type":"address"}],"name":"__ChangeMintPass","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ProjectID","type":"uint256"},{"internalType":"address","name":"Contract","type":"address"}],"name":"__ChangeMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"NewState","type":"bool"}],"name":"__ChangeQRDelegationsEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"NewIndex","type":"uint256"}],"name":"__ChangeQRIndex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"NewRoot","type":"bytes32"}],"name":"__ChangeRootAmounts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"NewRoot","type":"bytes32"}],"name":"__ChangeRootEligibility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"EligibilityRoot","type":"bytes32"},{"internalType":"bytes32","name":"EligibilityAmount","type":"bytes32"}],"name":"__ChangeRoots","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"Recipient","type":"address"}],"name":"__DelegateQR","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"__FlipRemoteMintingArtists","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"__FlipRemoteMintingCitizens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"__FlipRemoteMintingStates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"_MintPass","type":"address"},{"internalType":"address","name":"_Minter","type":"address"},{"internalType":"address","name":"_AlternateMinter","type":"address"},{"internalType":"uint256","name":"_MaxSupply","type":"uint256"},{"internalType":"uint256","name":"_ArtBlocksProjectID","type":"uint256"},{"internalType":"uint256","name":"_PolyStart","type":"uint256"},{"internalType":"uint256","name":"_PolyEnd","type":"uint256"}],"internalType":"struct LiveMintParis.Artist","name":"_Params","type":"tuple"}],"name":"__InitLiveMint","outputs":[{"internalType":"uint256","name":"ArtistID","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"Targets","type":"address[]"},{"internalType":"uint256[]","name":"Values","type":"uint256[]"},{"internalType":"bytes[]","name":"Datas","type":"bytes[]"}],"name":"__InitTransaction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ArtistID","type":"uint256"},{"internalType":"uint256","name":"Amount","type":"uint256"}],"name":"__NewAmountRemaining","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ArtistID","type":"uint256"},{"internalType":"address","name":"Minter","type":"address"}],"name":"__NewArtistMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ArtistID","type":"uint256"},{"components":[{"internalType":"address","name":"_MintPass","type":"address"},{"internalType":"address","name":"_Minter","type":"address"},{"internalType":"address","name":"_AlternateMinter","type":"address"},{"internalType":"uint256","name":"_MaxSupply","type":"uint256"},{"internalType":"uint256","name":"_ArtBlocksProjectID","type":"uint256"},{"internalType":"uint256","name":"_PolyStart","type":"uint256"},{"internalType":"uint256","name":"_PolyEnd","type":"uint256"}],"internalType":"struct LiveMintParis.Artist","name":"NewArtist","type":"tuple"}],"name":"__NewArtistStruct","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"Name","type":"string"},{"internalType":"uint256","name":"CityIndex","type":"uint256"},{"internalType":"uint256","name":"QRIndex","type":"uint256"},{"internalType":"bool","name":"RemoteMintingEnabledArtists","type":"bool"},{"internalType":"bool","name":"RemoteMintingEnabledCitizens","type":"bool"}],"name":"__NewCity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"CityIndex","type":"uint256"},{"components":[{"internalType":"string","name":"_Name","type":"string"},{"internalType":"uint256","name":"_QRCurrentIndex","type":"uint256"},{"internalType":"bytes32","name":"_RootEligibility","type":"bytes32"},{"internalType":"bytes32","name":"_RootAmount","type":"bytes32"},{"internalType":"bool","name":"_RemoteMintingEnabledArtists","type":"bool"},{"internalType":"bool","name":"_RemoteMintingEnabledCitizens","type":"bool"}],"internalType":"struct LiveMintParis.City","name":"NewCity","type":"tuple"}],"name":"__NewCityStruct","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"Addresses","type":"address[]"},{"internalType":"uint256[]","name":"Amounts","type":"uint256[]"}],"name":"__QRAllocationsIncrement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"Addresses","type":"address[]"},{"internalType":"uint256[]","name":"Amounts","type":"uint256[]"}],"name":"__QRAllocationsOverwrite","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"TicketIDs","type":"uint256[]"}],"name":"__QRAllocationsSetNoShow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"Minter","type":"address"}],"name":"__RemoveMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"__WithdrawEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"NewAddress","type":"address"}],"name":"____AddressAuthorize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"NewAddress","type":"address"}],"name":"____AddressDeauthorize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"Recipient","type":"address"}],"name":"readAmountRedeemed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ArtistID","type":"uint256"}],"name":"readArtist","outputs":[{"components":[{"internalType":"address","name":"_MintPass","type":"address"},{"internalType":"address","name":"_Minter","type":"address"},{"internalType":"address","name":"_AlternateMinter","type":"address"},{"internalType":"uint256","name":"_MaxSupply","type":"uint256"},{"internalType":"uint256","name":"_ArtBlocksProjectID","type":"uint256"},{"internalType":"uint256","name":"_PolyStart","type":"uint256"},{"internalType":"uint256","name":"_PolyEnd","type":"uint256"}],"internalType":"struct LiveMintParis.Artist","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ArtistID","type":"uint256"},{"internalType":"uint256","name":"Range","type":"uint256"}],"name":"readArtistBrightList","outputs":[{"internalType":"address[]","name":"Recipients","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ArtistIDs","type":"uint256[]"},{"internalType":"uint256","name":"Range","type":"uint256"}],"name":"readArtistMintedTicketIDs","outputs":[{"internalType":"uint256[][]","name":"TokenIDs","type":"uint256[][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ArtistID","type":"uint256"},{"internalType":"uint256","name":"TicketID","type":"uint256"}],"name":"readArtistMintedTokenID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ArtistIDs","type":"uint256[]"},{"internalType":"uint256","name":"Range","type":"uint256"}],"name":"readArtistUnmintedTicketIDs","outputs":[{"internalType":"uint256[][]","name":"TokenIDs","type":"uint256[][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"CityIndex","type":"uint256"}],"name":"readCitizenBrightList","outputs":[{"internalType":"address[]","name":"Recipients","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"readCitizenCheckedInTicketIDs","outputs":[{"internalType":"uint256[]","name":"TokenIDs","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"CityIndex","type":"uint256"}],"name":"readCitizenCity","outputs":[{"components":[{"internalType":"string","name":"_Name","type":"string"},{"internalType":"uint256","name":"_QRCurrentIndex","type":"uint256"},{"internalType":"bytes32","name":"_RootEligibility","type":"bytes32"},{"internalType":"bytes32","name":"_RootAmount","type":"bytes32"},{"internalType":"bool","name":"_RemoteMintingEnabledArtists","type":"bool"},{"internalType":"bool","name":"_RemoteMintingEnabledCitizens","type":"bool"}],"internalType":"struct LiveMintParis.City","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"CityID","type":"uint256"}],"name":"readCitizenMintedTicketIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"CityIndex","type":"uint256"},{"internalType":"uint256","name":"TicketID","type":"uint256"}],"name":"readCitizenMintedTokenID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"readCitizenUnmintedTicketIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"Recipient","type":"address"},{"internalType":"bytes32[]","name":"Proof","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ProofAmount","type":"bytes32[]"},{"internalType":"uint256","name":"Amount","type":"uint256"}],"name":"readEligibility","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"Recipient","type":"address"},{"internalType":"bytes32[]","name":"ProofEligibility","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ProofAmount","type":"bytes32[]"},{"internalType":"uint256","name":"Amount","type":"uint256"}],"name":"readQREligibility","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]