// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)pragmasolidity ^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.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
}
// SPDX-License-Identifier: MIT/**
* @dev @brougkr
*/pragmasolidity 0.8.19;interfaceIMP{
/**
* @dev { For Instances Where Golden Token Or Artists Have A Bespoke Mint Pass Contract }
*/function_LiveMintBurn(uint TicketID) externalreturns (address Recipient, uint ArtistID);
}
// SPDX-License-Identifier: MIT/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*//**
* @dev: @brougkr
*/pragmasolidity 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";
contractLiveMintVeniceisOwnable, ReentrancyGuard{
structCity
{
string _Name; // _Nameuint _QRCurrentIndex; // _QRCurrentIndexbytes32 _RootEligibility; // _RootEligibilitybytes32 _RootAmount; // _RootAmountbool _RemoteMintingEnabledCitizens; // _RemoteMintingEnabledCitizen
}
/*-------------------*//* STATE VARIABLES *//*-------------------*/bytes32privateconstant _AUTHORIZED =keccak256("AUTHORIZED"); // Authorized Rolebytes32privateconstant _MINTER_ROLE =keccak256("MINTER_ROLE"); // Minter Roleaddressprivateconstant _DN =0x00000000000076A84feF008CDAbe6409d2FE638B; // delegate.cash Delegation Registryaddressprivateconstant _GOLDEN_TOKEN =0x985e1932FFd2aA4bC9cE611DFe12816A248cD2cE; // Golden Token Address addressprivateconstant _CITIZEN_MINTER =0xDd06d8483868Cd0C5E69C24eEaA2A5F2bEaFd42b; // CryptoCitizen Minter Contractaddressprivateconstant _BRT_MULTISIG =0xB96E81f80b3AEEf65CB6d0E280b15FD5DBE71937; // BRT Multisigaddressprivate _FINALE_MINTER =0x6b611F416C9ef3c704540Ce98CdC05B748Ef7C19; // Finale Minteruintprivateconstant _CCI =9; // CryptoCitizen City Indexuintprivate _FMI =0; // Finale Minter Indexuintpublic _MaxQRDelegationsPerDay =25; // Max QR Delegations Per Dayboolpublic _QRDelegationsEnabled =true; // QR Delegations Enabled/*-------------------*//* MAPPINGS *//*-------------------*/mapping(uint=> City) public Cities; // [CityIndex] => City Structmapping(uint=>mapping(address=>bool)) public _QRRedeemed; // [CityIndex][Wallet] => If User Has Redeemed QRmapping(uint=>mapping(address=>uint)) public _QRAllocation; // [CityIndex][Wallet] => Wallet's QR Code Allocationmapping(uint=>mapping(uint=>address)) public _BrightListCitizen; // [CityIndex][TicketID] => Address Of CryptoCitizen Minting Recipient mapping(uint=>mapping(uint=>bool)) public _MintedCitizen; // [CityIndex][TicketID] => If Golden Ticket ID Has Minted Or Notmapping(uint=>mapping(address=>uint)) public _QRsRedeemed; // [CityIndex][Wallet] => Amount Of QRs Redeemedmapping(uint=>uint) public DailyCalls; // [Day] => Amount Of QR Delegations Mademapping(address=>bytes32) public Role; // [Wallet] => BRT Minter Role/*-------------------*//* EVENTS *//*-------------------*//**
* @dev Emitted When `Redeemer` IRL-mints CryptoCitizen Corresponding To Their Redeemed `TicketID`.
**/eventLiveMintComplete(address Redeemer, uint TicketID, uint TokenID, uint TokenID2);
/**
* @dev Emitted When A Finale Batch Mint Is Complete
*/eventLiveMintBatchComplete(address[] Recipients, uint[] TicketIDs, uint[] MintedWorkTokenIDs);
/**
* @dev Emitted When `Redeemer` Redeems Golden Token Corresponding To `TicketID`
**/eventQRRedeemed(address Redeemer, uint TicketID);
/**
* @dev Emitted When A Contract Is Authorized
*/eventAuthorizedContract(address NewAddress);
/**
* @dev Emitted When A Contract Is Deauthorized
*/eventDeauthorizedContract(address NewAddress);
/*-------------------*//* CONSTRUCTOR *//*-------------------*/constructor()
{
Cities[9]._Name ="CryptoVenezians";
Cities[9]._QRCurrentIndex =1332;
Role[0xe06F5FAE754e81Bc050215fF89B03d9e9FF20700] = _AUTHORIZED; // `operator.brightmoments.eth`
Role[0x18B7511938FBe2EE08ADf3d4A24edB00A5C9B783] = _AUTHORIZED; // `phil.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
* note: Will Input ETH For Minting Gas Fee Coverage
*/functionRedeemQR (bytes32[] calldata ProofEligibility,
bytes32[] calldata ProofAmounts,
address Vault,
uint Amount
) externalpayablenonReentrant{
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;
uint _Counter;
Cities[_CCI]._QRCurrentIndex = _Limit;
for(_CurrentQR; _CurrentQR < _Limit; _CurrentQR++)
{
_BrightListCitizen[_CCI][_CurrentQR] = Recipient;
emit QRRedeemed(Recipient, _CurrentQR);
_Counter++;
}
}
_QRRedeemed[_CCI][Recipient] =true;
}
/**
* @dev Remote Mints GoldenTokens For Citizens
* @param TicketIDs Array Of TicketIDs To Mint
*/functionRemoteMintCitizens(uint[] calldata TicketIDs) externalnonReentrant{
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;
uint AdditionalTokenID;
for(uint TicketID; TicketID < TicketIDs.length; TicketID++)
{
require(TicketIDs[TicketID] <1332, "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);
AdditionalTokenID = IMinter(_FINALE_MINTER).purchaseTo(Recipient, _FMI);
emit LiveMintComplete(Recipient, TicketIDs[TicketID], MintedWorkTokenID, AdditionalTokenID);
}
}
/*--------------------*//* 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) externalonlyMinter{
address Recipient;
uint MintedWorkTokenID;
uint AdditionalTokenID;
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]]; }
elseif (TicketIDs[TicketID] <1332) { Recipient = IGT(_GOLDEN_TOKEN)._LiveMintBurn(TicketIDs[TicketID]); }
else { revert("LiveMint: TicketID Is Not Eligible To Mint Citizen"); }
_MintedCitizen[_CCI][TicketIDs[TicketID]] =true;
MintedWorkTokenID = IMinter(_CITIZEN_MINTER).purchaseTo(Recipient, _CCI); // Citizen Mint
AdditionalTokenID = IMinter(_FINALE_MINTER).purchaseTo(Recipient, _FMI); // Finale Mintemit LiveMintComplete(Recipient, TicketIDs[TicketID], MintedWorkTokenID, AdditionalTokenID);
}
}
/**
* @dev Batch Mints Verified Users On The Brightlist CryptoCitizens
*/function_LiveMintCitizenBatch(uint[] calldata TicketIDs) externalonlyMinter{
address[] memory Recipients;
uint[] memory MintedWorkTokenIDs;
for(uint TicketID; TicketID < TicketIDs.length; TicketID++)
{
require(!_MintedCitizen[_CCI][TicketIDs[TicketID]], "LiveMint: Golden Token Already Minted");
if(_BrightListCitizen[_CCI][TicketIDs[TicketID]] !=address(0)) { Recipients[TicketID] = _BrightListCitizen[_CCI][TicketIDs[TicketID]]; }
elseif (TicketIDs[TicketID] <1332) { Recipients[TicketID] = IGT(_GOLDEN_TOKEN)._LiveMintBurn(TicketIDs[TicketID]); }
else { revert("LiveMint: TicketID Is Not Eligible To Mint Citizen"); }
_MintedCitizen[_CCI][TicketIDs[TicketID]] =true;
}
MintedWorkTokenIDs = IMinter(_FINALE_MINTER).purchaseToBatch(Recipients);
emit LiveMintBatchComplete(Recipients, TicketIDs, MintedWorkTokenIDs);
}
/*-------------------*//* ADMIN FUNCTIONS *//*-------------------*//**
* @dev Changes The Current Active Marketplace Address
* @param Recipient The Recipient Of The QR
*/function__DelegateQR (address Recipient) externalonlyAdmin{
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) externalonlyAdmin{ Cities[_CCI]._RootEligibility = NewRoot; }
/**
* @dev Changes Merkle Root For Citizen LiveMint Amounts
* @param NewRoot The New Merkle Root To Seed
*/function__ChangeRootAmounts (bytes32 NewRoot) externalonlyAdmin{ 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) externalonlyAdmin{
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) externalonlyAdmin{
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) externalonlyAdmin{
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) externalonlyAdmin{
for(uint TicketIndex; TicketIndex < TicketIDs.length; TicketIndex++)
{
require(!_MintedCitizen[_CCI][TicketIDs[TicketIndex]], "LiveMint: Ticket ID Already Minted");
require(TicketIDs[TicketIndex] >=1332, "LiveMint: Invalid TicketID");
_BrightListCitizen[_CCI][TicketIDs[TicketIndex]] = _BRT_MULTISIG;
}
}
/*-------------------*//* OWNER FUNCTIONS *//*-------------------*//**
* @dev Flips Remote Minting State For CryptoCitizens (True or False)
*/function__FlipRemoteMintingCitizens() externalonlyOwner{
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) externalonlyOwner{ 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) externalonlyOwner{ Role[Minter] =0x0; }
/**
* @dev Changes QR Current Index
* @param NewIndex The Next QR Index To Redeem
*/function__ChangeQRIndex(uint NewIndex) externalonlyOwner{ Cities[_CCI]._QRCurrentIndex = NewIndex; }
/**
* @dev Changes The Finale Minter
* @param NewMinter The New Minter Address
*/function__ChangeFinaleMinter(address NewMinter) externalonlyOwner{ _FINALE_MINTER = NewMinter; }
/**
* @dev Changes The Finale Minter Index
* @param NewIndex The New Minter Index
*/function__ChangeFinaleMinterIndex(uint NewIndex) externalonlyOwner{ _FMI = NewIndex; }
/**
* @dev Withdraw ETH Call
*/function__WithdrawETHCall() externalonlyOwner{
(bool success,) =msg.sender.call{value:(address(this).balance)}("");
require(success, "i have failed u anakin");
}
/**
* @dev Withdraws Any Ether Mistakenly Sent to Contract to msg sender
**/function__WithdrawEther() externalonlyOwner{ 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) externalonlyOwner{
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) externalonlyOwner{
Role[NewAddress] = _AUTHORIZED;
emit AuthorizedContract(NewAddress);
}
/**
* @dev Deauthorizes An Address
* @param NewAddress Address To Deauthorize
*/function___DeauthorizeAddress(address NewAddress) externalonlyOwner{
Role[NewAddress] =0x0;
emit DeauthorizedContract(NewAddress);
}
/*-------------------*//* PUBLIC VIEW *//*-------------------*//**
* @dev Returns A User's QR Allocation Amount, Or 0 If Not Eligible
*/functionreadEligibility (address Recipient,
bytes32[] memory Proof,
bytes32[] memory ProofAmount,
uint Amount
) publicviewreturns (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; }
elseif (Eligible && Allocation ==0&& AmountRedeemed ==0) { return1; }
else { return0; }
}
/**
* @dev Returns If User Is Eligible To Redeem QR Code
*/functionreadQREligibility (address Recipient,
bytes32[] memory ProofEligibility,
bytes32[] memory ProofAmount,
uint Amount
) publicviewreturns (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");
returntrue;
}
/**
* @dev Returns How Many QR Codes A User Has Redeemed
*/functionreadAmountRedeemed(address Recipient) publicviewreturns(uint) { return _QRsRedeemed[_CCI][Recipient]; }
/**
* @dev Returns An Array Of Unminted Golden Tokens
*/functionreadCitizenUnmintedTicketIDs() publicviewreturns(uint[] memory)
{
uint[] memory UnmintedTokenIDs =newuint[](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 <1332)
)
{
UnmintedTokenIDs[Counter] = _TokenID;
Counter++;
}
}
uint[] memory FormattedUnMintedTokenIDs =newuint[](Counter);
for(uint Index; Index < Counter; Index++)
{
FormattedUnMintedTokenIDs[Index] = UnmintedTokenIDs[Index];
}
return FormattedUnMintedTokenIDs;
}
/**
* @dev Returns An Array Of Unminted Golden Tokens
*/functionreadCitizenMintedTicketIDs(uint CityID) publicviewreturns(uint[] memory)
{
uint[] memory MintedTokenIDs =newuint[](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 =newuint[](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
*/functionreadCitizenCheckedInTicketIDs() publicviewreturns(uint[] memory TokenIDs)
{
uint[] memory _TokenIDs =newuint[](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 =newuint[](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 Original Recipients Of CryptoCitizens
*/functionreadCitizenBrightList(uint CityIndex) publicviewreturns(address[] memory Recipients)
{
address[] memory _Recipients =newaddress[](1000);
uint Start = (CityIndex %6) *333;
for(uint x; x <1000; x++) { _Recipients[x] = _BrightListCitizen[CityIndex][Start+x]; }
return _Recipients;
}
/**
* @dev Returns The City Struct At Index Of `CityIndex`
*/functionreadCitizenCity(uint CityIndex) publicviewreturns(City memory) { return Cities[CityIndex]; }
/*-------------------------*//* ACCESS MODIFIERS *//*-------------------------*//**
* @dev Access Modifier That Allows Only BrightListed BRT Minters
**/modifieronlyMinter()
{
require(Role[msg.sender] == _MINTER_ROLE, "LiveMint | onlyMinter | Caller Is Not Approved BRT Minter");
_;
}
/**
* @dev Access Modifier That Allows Only Authorized Contracts
*/modifieronlyAdmin()
{
require(Role[msg.sender] == _AUTHORIZED ||msg.sender== owner(), "LiveMint | onlyAdmin | Caller Is Not Approved Admin");
_;
}
}
/**
* @dev Interface For Delegate.cash
*/interfaceIDelegationRegistry{
/**
* @dev Checks If A Vault Has Delegated To The Delegate
*/functioncheckDelegateForAll(address delegate, address delegator) externalviewreturns (bool);
}
Contract Source Code
File 6 of 8: MerkleProof.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.9.2) (utils/cryptography/MerkleProof.sol)pragmasolidity ^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.
*/libraryMerkleProof{
/**
* @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.
*/functionverify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internalpurereturns (bool) {
return processProof(proof, leaf) == root;
}
/**
* @dev Calldata version of {verify}
*
* _Available since v4.7._
*/functionverifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internalpurereturns (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._
*/functionprocessProof(bytes32[] memory proof, bytes32 leaf) internalpurereturns (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._
*/functionprocessProofCalldata(bytes32[] calldata proof, bytes32 leaf) internalpurereturns (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._
*/functionmultiProofVerify(bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves
) internalpurereturns (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._
*/functionmultiProofVerifyCalldata(bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves
) internalpurereturns (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._
*/functionprocessMultiProof(bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves
) internalpurereturns (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 =newbytes32[](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];
}
} elseif (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._
*/functionprocessMultiProofCalldata(bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves
) internalpurereturns (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 =newbytes32[](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];
}
} elseif (leavesLen >0) {
return leaves[0];
} else {
return proof[0];
}
}
function_hashPair(bytes32 a, bytes32 b) privatepurereturns (bytes32) {
return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
}
function_efficientHash(bytes32 a, bytes32 b) privatepurereturns (bytes32 value) {
/// @solidity memory-safe-assemblyassembly {
mstore(0x00, a)
mstore(0x20, b)
value :=keccak256(0x00, 0x40)
}
}
}
Contract Source Code
File 7 of 8: Ownable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)pragmasolidity ^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.
*/abstractcontractOwnableisContext{
addressprivate _owner;
eventOwnershipTransferred(addressindexed previousOwner, addressindexed 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.
*/modifieronlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/function_checkOwner() internalviewvirtual{
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.
*/functionrenounceOwnership() publicvirtualonlyOwner{
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
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) internalvirtual{
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
Contract Source Code
File 8 of 8: ReentrancyGuard.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)pragmasolidity ^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].
*/abstractcontractReentrancyGuard{
// 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.uint256privateconstant _NOT_ENTERED =1;
uint256privateconstant _ENTERED =2;
uint256private _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.
*/modifiernonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function_nonReentrantBefore() private{
// On the first call to nonReentrant, _status will be _NOT_ENTEREDrequire(_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() internalviewreturns (bool) {
return _status == _ENTERED;
}
}