WantedTributes

Description:

Multi-signature wallet contract requiring multiple confirmations for transaction execution.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "WantedTributes.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
pragma solidity ^0.8.29;\r
\r
 //            _       __            __           __     \r
 //           | |     / /___ _____  / /____  ____/ /      \r
 //           | | /| / / __ `/ __ \/ __/ _ \/ __  /       \r
 //           | |/ |/ / /_/ / / / / /_/  __/ /_/ /        \r
 //           |__/|__/\__,_/_/ /_/\__/\___/\__,_/         \r
 //          ______     _ __          __           \r
 //         /_  __/____(_) /_  __  __/ /____  _____\r
 //          / / / ___/ / __ \/ / / / __/ _ \/ ___/\r
 //         / / / /  / / /_/ / /_/ / /_/  __(__  ) \r
 //        /_/ /_/  /_/_.___/\__,_/\__/\___/____/                                       \r
 //\r
 // Creator: MadV0x\r
 // Deployer: Syntetik Labs\r
\r
import { ERC1155TransferValidator } from "src/lib/ERC1155TransferValidator.sol";\r
import { ICreatorToken, ILegacyCreatorToken } from "src/interfaces/ICreatorToken.sol";\r
import { ReentrancyGuard } from "lib/openzeppelin-contracts/contracts/security/ReentrancyGuard.sol";\r
import { ITransferValidator1155 } from "src/interfaces/ITransferValidator.sol";\r
import { ERC1155Airdrops } from "WANTED/lib/ERC1155Airdrops.sol";\r
import { WCTDropErrorsAndEvents } from "WANTED/lib/WCTDropErrorsAndEvents.sol";\r
\r
/**\r
* @title  WantedTributes: WANTED Cyborgs Tributes (WCT).\r
* @notice Implements ERC1155Airdrops: Enables batch transfers of ERC1155 tokens.\r
*         Implements Limit Break's Creator Token Standards transfer\r
*            validation for security and royalty enforcement.\r
*         Implements Approvals restrictions : Only the owner or admin can approve operators \r
*            until the contract is unlocked or ownership has been renounced.\r
*         Implements Admin role management: Allows assignment of an admin address with\r
*            privileged permissions. \r
* @notice Implements Royalties Gamification: Dynamic royalty mechanisms, \r
*            active only if/after ownership has been renounced.\r
**/\r
\r
contract WantedTributes is ERC1155Airdrops, ERC1155TransferValidator, ReentrancyGuard, WCTDropErrorsAndEvents {\r
    \r
    address public Admin;\r
    address public WCTMaster;\r
    uint256 public tokenControlledByMaster;\r
    bool public marketsUnLocked = false;\r
\r
    constructor(\r
        string memory _name,\r
        string memory _symbol)\r
        ERC1155Airdrops(_name, _symbol) {\r
        }\r
\r
    /**\r
     * @dev ICreatorToken Interface implementation.\r
     */\r
    function supportsInterface(bytes4 interfaceId) public view override(ERC1155Airdrops) returns (bool) {\r
        return\r
            interfaceId == type(ICreatorToken).interfaceId ||\r
            interfaceId == type(ILegacyCreatorToken).interfaceId ||\r
            interfaceId == 0x49064906 || // ERC-4906\r
            super.supportsInterface(interfaceId);\r
    }\r
\r
    /**\r
    * @dev Internal helper function to verify if the caller is either the contract owner or the designated admin.\r
    *      Reverts with `NotOwnerNorAdmin` error if unauthorized.\r
    */ \r
    function _isOwnerOrAdmin() private view {\r
        if(msg.sender != owner() && msg.sender != Admin) {\r
        revert NotAdminOrOwner();\r
        }\r
    }\r
\r
    /**\r
    * @notice Grants the Admin role to a specified account. Use zero address to revoke.\r
    * @dev Can only be called by the owner or current admin.\r
    *\r
    * @param newAdmin The address to assign as Admin. Use `address(0)` to revoke the role.\r
    */\r
    function grantAdminRole(address newAdmin) external {\r
        _isOwnerOrAdmin();\r
        Admin = newAdmin; // Grant the role to an address\r
        emit ContractAdminRoleGranted(newAdmin);\r
    }\r
\r
    /**\r
    * @notice Returns the selector of the transfer validation function used by the contract.\r
    * @dev Indicates whether the function is a view or modifies state.\r
    *\r
    * @return functionSignature The function selector of `validateTransfer`.\r
    * @return isViewFunction Boolean indicating if the function is a view function (false in this case).\r
    */\r
    function getTransferValidationFunction() external override pure returns (bytes4 functionSignature, bool isViewFunction) {\r
        functionSignature = ITransferValidator1155.validateTransfer.selector;\r
        isViewFunction = false;\r
    }\r
\r
    /**\r
    * @notice Sets the address of the transfer validator contract (Admin only).\r
    * @dev The transfer validator enforces custom rules on token transfers.\r
    *\r
    * @param newValidator The address of the new transfer validator contract.\r
    */\r
    function setTransferValidator(address newValidator) external override {\r
        _isOwnerOrAdmin();\r
        super._setTransferValidator(newValidator);\r
    }\r
\r
    /**\r
    * @dev Internal hook called before any token transfer, including minting.\r
    *      Enforces royalty or transfer restrictions via an external validator contract, if set.\r
    *\r
    * Note Derived from Limit Break's ERC1155-C implementation.\r
    *      Allows configurable transfer validation logics for on-chain royalty enforcement,\r
    *      operator filtering, and marketplace restrictions.\r
    *       \r
    * Requirements:\r
    * - If both `from` and `to` are non-zero (i.e., not mint or burn), the transfer validator (if configured)\r
    *   is called to validate the transfer.\r
    */\r
    function _beforeTokenTransfers(\r
        address from,\r
        address to,\r
        uint256 id,\r
        uint256 quantity,\r
        bytes memory //*data//* \r
    ) internal override {\r
        if (from != address(0) && to != address(0)) {\r
            // Call the transfer validator if one is set.\r
            address transferValidator = _transferValidator;\r
            if (transferValidator != address(0)) {\r
                ITransferValidator1155(transferValidator).validateTransfer(\r
                    msg.sender,\r
                    from,\r
                    to,\r
                    id,\r
                    quantity\r
                );\r
            }\r
        }\r
        super._beforeTokenTransfers(from, to, id, quantity,"");\r
    }\r
\r
    /**\r
    * @notice Updates the royalty recipient address and royalty fee basis points (Admin only).\r
    * @dev Reverts if the royalty address is zero or if the basis points exceed 10,000 (100%).\r
    *\r
    * @param RoyaltyAddress The address to receive royalty payments.\r
    * @param RoyaltyFeesInBips The royalty fee in basis points (1 basis point = 0.01%).\r
    */\r
    function setRoyaltyInfo(address RoyaltyAddress, uint96 RoyaltyFeesInBips) external virtual {\r
        _isOwnerOrAdmin();\r
        // Revert if the new royalty address is the zero address.\r
        if (RoyaltyAddress == address(0)) {\r
            revert RoyaltyAddressCannotBeZeroAddress();\r
        }\r
\r
        // Revert if the new basis points is greater than 10_000.\r
        if (RoyaltyFeesInBips > 10_000) {\r
            revert InvalidRoyaltyBasisPoints(RoyaltyFeesInBips);\r
        }\r
\r
        // Set the new royalty info.\r
        _setDefaultRoyalty(RoyaltyAddress, RoyaltyFeesInBips);\r
\r
        // Emit an event with the updated params.\r
        emit RoyaltyInfoUpdated(RoyaltyAddress, RoyaltyFeesInBips);\r
    }\r
\r
    /**\r
    * @dev Overrides ERC1155 `setApprovalForAll` to restrict operator approvals\r
    *      while the contract remains locked or ownership has not been renounced.\r
    *      Until then, only the owner or Admin can grant approvals, enforcing a\r
    *      temporary soulbound-like behavior.\r
    *\r
    * @param operator The address to grant or revoke approval for as an operator.\r
    * @param approved Boolean indicating the approval status (`true` = approve, `false` = revoke).\r
    */\r
    function setApprovalForAll(address operator, bool approved) public virtual override {\r
        \r
        if (!marketsUnLocked || owner() != address(0) || msg.sender != owner() || msg.sender != Admin) {\r
            revert ContractNotUnLocked();\r
        }\r
\r
        super.setApprovalForAll(operator, approved);\r
    }\r
\r
    /**\r
    * @notice Permanently unlocks contract-wide approvals.\r
    * @dev Can only be called once by the contract owner or admin.\r
    *      Sets `marketsUnLocked` to true, enabling unrestricted approvals.\r
    *      Reverts if the contract is already unlocked.\r
    */\r
    function unlockMarkets() external {\r
        require(!marketsUnLocked, "unlocked");\r
        _isOwnerOrAdmin();\r
        marketsUnLocked = true;\r
    }\r
\r
    /**\r
    * @notice On-chain gamification and community engagement feature:\r
    *         Allows a user to claim the title of "WCT Leader" for a specific tokenId by owning\r
    *         more than 0.5% of that token’s total supply and exceeding the previous claimer's balance.\r
    *         Claiming temporarily transfers the token’s royalty share to the new leader until someone else claims it.\r
    *         \r
    *         Activation requires that the contract ownership has been renounced (owner == address(0)).\r
    *\r
    * @param tokenId The specific token ID for which the WCT Leader title is being claimed.\r
    *\r
    * Reverts if:\r
    * - Contract ownership is not renounced.\r
    * - The token does not exist or is controlled by the WCTMaster.\r
    * - Caller does not hold a sufficient quantity (<1%) or does not exceed the previous leader’s balance.\r
    */\r
    function claimWCTLeader(uint256 tokenId) external nonReentrant {\r
\r
        if(owner() != address(0)) {\r
            revert OwnershipNotRenounced();\r
        }\r
\r
        if(totalSupply(tokenId) == 0 || getWCTLeader(tokenId) == WCTMaster) {\r
            revert TokenControlledByWCTMasterOrDoNotExist();\r
        } \r
        RoyaltyInfo storage _royaltyInfo = _tokenRoyaltyInfo[tokenId];\r
\r
        // Claimer must hold >0.5% of the token supply and more tokenId than previous claimer.\r
        if(balanceOf(msg.sender, tokenId) < (totalSupply(tokenId) * 1/100) \r
        && balanceOf(msg.sender, tokenId) <= balanceOf(_royaltyInfo.receiver, tokenId)) {\r
            revert NotMajorityTokenOwner(msg.sender, tokenId);\r
        }\r
        // Set the new royalty info to the default contract royalties.\r
        uint96 royalty = _defaultRoyaltyInfo.royaltyFraction;\r
        _setTokenRoyalty(tokenId, msg.sender, royalty);\r
\r
        // Emit an event with the updated params.\r
        emit TokenRoyaltyInfoUpdated(tokenId, msg.sender, royalty);\r
        emit WCTLeaderClaimed(msg.sender, tokenId);\r
    }\r
\r
    /**\r
    * @notice Returns the current WCT Leader (royalty recipient) for the specified tokenId.\r
    * @param tokenId The token ID to query.\r
    * @return The address of the current WCT Leader for that token.\r
    */\r
    function getWCTLeader(uint256 tokenId) public view returns (address) {\r
        return _tokenRoyaltyInfo[tokenId].receiver;\r
    }\r
\r
    /**\r
    * @notice On-chain gamification: Claim the title of **WCT Master** by owning a significant share of WCT tokens.\r
    * @dev Caller becomes the global contract Leader ("WCT Master") and takes over any one tokenId’s royalties.\r
    *      Can only be claimed if contract ownership has been renounced (`owner == address(0)`).\r
    *      WCT Master must:\r
    *      - Own more than 0.05% of the total WCT supply.\r
    *      - Hold more WCT tokens than the previous WCT Master.\r
    *      - Not already be the current WCT Master.\r
    *\r
    *      The newly claimed tokenId will be assigned to the WCT Master for royalty control.\r
    *      If a previous token was controlled by the WCT Master, its royalty will be reset to default.\r
    *\r
    * @param tokenId The tokenId for which the caller wants to take over royalty control.\r
    *\r
    * Reverts if:\r
    * - Contract ownership is not renounced.\r
    * - tokenId is invalid or already controlled.\r
    * - Caller doesn't meet the supply ownership conditions.\r
    */\r
    function claimWCTMaster(uint256 tokenId) external nonReentrant {\r
\r
        if(owner() != address(0)) {\r
            revert OwnershipNotRenounced();\r
        }\r
\r
        if(tokenId > totalTokenIdsMinted || WCTMaster == msg.sender) {\r
            revert WCTMasterAlreadyClaimedorTokenDoNotExist();\r
        } \r
\r
        // Claimer must hold >0.05% of the total WCTs supply and more WCTs than previous Master.\r
        if(totalBalanceOf(msg.sender) < (globalSupply() *5/10000)\r
        && totalBalanceOf(msg.sender) <= totalBalanceOf(WCTMaster)) {\r
            revert NotWCTMaster(msg.sender);\r
        }\r
\r
        uint96 royalty = _defaultRoyaltyInfo.royaltyFraction;\r
        // Reset previous tokenId to default royalties.\r
        if (tokenControlledByMaster != 0) {\r
            _setTokenRoyalty(tokenControlledByMaster, _defaultRoyaltyInfo.receiver, royalty);\r
            emit TokenRoyaltyInfoUpdated(tokenControlledByMaster, _defaultRoyaltyInfo.receiver, royalty);\r
            tokenControlledByMaster = tokenId;\r
        }    \r
        \r
        // Set the new tokenroyalty info to the WCTLeader's address.\r
        WCTMaster = msg.sender;\r
        _setTokenRoyalty(tokenId, WCTMaster, royalty);\r
\r
        // Emit an event with the updated params.\r
        emit TokenRoyaltyInfoUpdated(tokenId, WCTMaster, royalty);\r
        emit WCTMasterClaimed(WCTMaster, tokenId);\r
    }\r
\r
    /**\r
    * @notice Burn a specific amount of tokens of a given tokenId from an account (irreversible).\r
    * @dev Caller must be the token owner or an approved operator.\r
    *\r
    * @param account The address from which tokens will be burned.\r
    * @param tokenId The token ID to burn.\r
    * @param amount The number of tokens to burn.\r
    */\r
    function burn(address account, uint256 tokenId, uint256 amount) external {\r
        require(account == msg.sender || isApprovedForAll(account, msg.sender), "Not authorized");\r
        _burn(account, tokenId, amount);\r
    }\r
\r
    /**\r
    * @notice Withdraw all POL from the contract to the owner's address.\r
    * @dev Only callable by the contract owner. Reverts if no balance is available or if the transfer fails.\r
    */ \r
    function withdraw() external nonReentrant {\r
        _isOwnerOrAdmin();\r
        uint256 balance = address(this).balance;\r
        require(balance > 0, "No funds to withdraw");\r
\r
        (bool success, ) = payable(msg.sender).call{value: balance}("");\r
        require(success, "Withdrawal to owner failed");\r
    }\r
\r
}"
    },
    "WANTED/lib/WCTDropErrorsAndEvents.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
pragma solidity ^0.8.29;\r
\r
interface WCTDropErrorsAndEvents {\r
\r
    /**\r
     * @dev Emit an event when Manager Role is granted.\r
     */\r
    event ContractAdminRoleGranted(address account);\r
\r
    /**\r
     * @dev Emit an event when the royalties info is updated.\r
     */\r
    event RoyaltyInfoUpdated(address receiver, uint256 bps);\r
\r
    /**\r
     * @dev Emit an event when the token royalties info is updated.\r
     */\r
    event TokenRoyaltyInfoUpdated (uint256 tokenId, address receiver, uint256 royalties);\r
\r
    /**\r
     * @dev Emit an event when a Token's Leadership is claimed.\r
     */\r
    event WCTLeaderClaimed(address account, uint256 tokenId);\r
\r
    /**\r
     * @dev Emit an event when the Contract's Master Position is claimed.\r
     */\r
    event WCTMasterClaimed(address account, uint256 tokenId);\r
\r
    /**\r
     * @dev Emit an event when the Contract's metadata is Frozen.\r
     */\r
    event MetadataFrozen();\r
\r
    /**\r
     * @dev Revert if the royalty basis points is greater than 10_000.\r
     */\r
    error InvalidRoyaltyBasisPoints(uint256 basisPoints);\r
\r
    /**\r
     * @dev Revert if the royalty address is being set to the zero address.\r
     */\r
    error RoyaltyAddressCannotBeZeroAddress();\r
\r
    /**\r
     * @dev Revert if the caller is not Majority holder.\r
     */\r
    error NotMajorityTokenOwner(address caller, uint256 tokenId);\r
\r
    /**\r
     * @dev Revert if the caller is not eligible as Contract Master.\r
     */\r
    error NotWCTMaster(address account);\r
\r
    /**\r
     * @dev Revert if caller is not Admin or Owner.\r
     */\r
    error NotAdminOrOwner();\r
\r
    /**\r
     * @dev Revert if the Contract isn't unlocked.\r
     */\r
    error ContractNotUnLocked();\r
\r
    /**\r
     * @dev Revert if ownership not renounced.\r
     */\r
    error OwnershipNotRenounced();\r
\r
    /**\r
     * @dev Revert if the caller isn't eligible as Token Leader.\r
     */\r
    error TokenControlledByWCTMasterOrDoNotExist();\r
\r
    /**\r
     * @dev Revert if the caller isn't eligible as WCT Master.\r
     */\r
    error WCTMasterAlreadyClaimedorTokenDoNotExist();\r
\r
}"
    },
    "WANTED/lib/ERC1155Airdrops.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
pragma solidity ^0.8.29;\r
\r
import { IERC1155MetadataURI } from ".deps/npm/@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol";\r
import { ERC1155Utils } from ".deps/npm/@openzeppelin/contracts/token/ERC1155/utils/ERC1155Utils.sol";\r
import { ERC1155Supply } from ".deps/npm/@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol";\r
import { Context } from ".deps/npm/@openzeppelin/contracts/utils/Context.sol";\r
import { IERC165, ERC165 } from ".deps/npm/@openzeppelin/contracts/utils/introspection/ERC165.sol";\r
import { Arrays } from ".deps/npm/@openzeppelin/contracts/utils/Arrays.sol";\r
import { Strings } from "lib/openzeppelin-contracts/contracts/utils/Strings.sol";\r
import { ERC2981 } from "@openzeppelin/contracts/token/common/ERC2981.sol";\r
import { IERC2981 } from "lib/openzeppelin-contracts/contracts/interfaces/IERC2981.sol";\r
import { ERC1155AirdropsErrorsAndEvents } from "WANTED/lib/ERC1155AirdropsErrorsAndEvents.sol";\r
import { Ownable } from ".deps/npm/@openzeppelin/contracts/access/Ownable.sol";\r
\r
/**\r
* @title  ERC1155Airdrops\r
* @custom:creator MadV0x\r
* @notice Implements mintFor of newTokenId to an address.\r
*         Implements batchMintFor of newTokenIds to an address. \r
*         Implements bulkDropTo (Bulk transfers tokenId to a list of addresses). \r
*         Implements batchDropTo (Batch transfers tokenIds to a list of addresses).   \r
*         Implements totalBalanceOf (returns global balance of an address for all tokenIds).\r
*         Implements totalSupply (returns the total supply of all tokens in the contract).\r
*         Implements getTokenIdsByWallet to return all tokenIds owned by a wallet.\r
*         Implements isContractFrozen: freeze metadata and minting functions.\r
*         IMPORTANT: Ownable library not implemented (all mint functions public).\r
**/\r
\r
contract ERC1155Airdrops is \r
    Context,\r
    Ownable, \r
    ERC165, \r
    IERC1155MetadataURI,\r
    ERC1155AirdropsErrorsAndEvents, \r
    ERC2981 {\r
    \r
    string public name;\r
    string public symbol;\r
    uint256 public totalTokenIdsMinted;\r
\r
    /// @notice returns the contract URI for contract Metadata.\r
    string contractURI;\r
\r
    /// @notice Check if contract (Metadata + Mint) is frozen. \r
    /// @dev emit an event when frozen.\r
    bool public isContractFrozen = false;\r
    event contractFrozen();\r
\r
    //@dev Mapping to store the uri for each tokenId\r
    mapping(uint256 => string) private _tokenURI;\r
\r
    //@dev mapping tokenId balances to addresses\r
    mapping(uint256 id => mapping(address account => uint256)) private _balances;\r
\r
    //@dev mapping of approvals\r
    mapping(address account => mapping(address operator => bool)) private _operatorApprovals;\r
\r
    //@dev Mapping to store the total supply of each tokenId\r
    mapping(uint256 => uint256) private _totalSupply;\r
\r
    constructor(\r
        string memory _name,\r
        string memory _symbol) Ownable(msg.sender) {\r
        name = _name;\r
        symbol = _symbol;\r
    }\r
\r
    /**\r
     * @dev See {IERC165-supportsInterface}.\r
     */\r
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165, ERC2981) returns (bool) {\r
        return\r
            interfaceId == type(IERC165).interfaceId ||\r
            interfaceId == type(IERC1155MetadataURI).interfaceId ||\r
            interfaceId == type(IERC2981).interfaceId ||\r
            interfaceId == 0x49064906 || // ERC-4906\r
            super.supportsInterface(interfaceId);\r
    }\r
\r
    /**\r
    * @notice Mint a new TokenId with a given supply.\r
    * @dev Allows minting the next sequential tokenId with specified supply and URI.\r
    * @param recipient The address receiving the minted tokens.\r
    * @param supply The number of tokens to mint for this tokenId.\r
    * @param tokenURI The URI associated with the new tokenId.\r
    */\r
    function mintFor(address recipient, uint256 supply, string memory tokenURI) onlyOwner public virtual {\r
\r
        if(isContractFrozen) {revert ContractFrozen();} \r
\r
        uint256 nextTokenId = totalTokenIdsMinted + 1;\r
\r
        // Mint the tokens to the caller (owner or authorized address)\r
        _mint(recipient, nextTokenId, supply, "");\r
        _tokenURI[nextTokenId] = tokenURI;\r
        totalTokenIdsMinted += 1;\r
\r
        // Update the total supply for the tokenId\r
        _totalSupply[nextTokenId] += supply;\r
\r
        // Emit an event for the minting\r
        emit Minted(recipient, nextTokenId, supply);\r
    }\r
\r
    /**\r
    * @notice Batch mint multiple new token IDs of given supplies to a recipient.\r
    * @param recipient The address to receive the minted tokens.\r
    * @param supplies The number of tokens to mint for each new tokenId.\r
    * @param tokenURIs The URIs corresponding to each new tokenId.\r
    */\r
    function batchMintFor(address recipient, uint256[] calldata supplies, string[] memory tokenURIs) onlyOwner public virtual {\r
\r
        if(isContractFrozen) {revert ContractFrozen();} \r
\r
        if (supplies.length <= 0) {revert SuppliesMissing();}\r
        if (supplies.length != tokenURIs.length) {revert DataLengthMismatch();}\r
\r
        uint256 nextTokenId = totalTokenIdsMinted + 1;\r
        uint256[] memory tokenIds = new uint256[](supplies.length);\r
\r
        // Create new token IDs based on the nextTokenId\r
        for (uint256 i = 0; i < supplies.length; i++) {\r
            tokenIds[i] = nextTokenId;  // Assign current nextTokenId\r
            _totalSupply[nextTokenId] += supplies[i];  // Update the supply for the current tokenId\r
            _tokenURI[nextTokenId] = tokenURIs[i];  // Set the URI for the current tokenId\r
            nextTokenId++;  // Increment nextTokenId after using it\r
            totalTokenIdsMinted++;  // Increment the totalTokenIdsMinted\r
        }\r
        // Mint the tokens to the recipient.\r
        _mintBatch(recipient, tokenIds, supplies, "");\r
\r
        // Emit an event for the minting.\r
        emit BatchMinted(recipient, tokenIds, supplies);\r
    }\r
\r
    /**\r
    * @notice Transfers amounts of a specified tokenId to recipients.\r
    * @dev Caller must own sufficient balance of `tokenId` to cover total amounts.\r
    * @param recipients Array of recipient addresses.\r
    * @param tokenId Token ID to airdrop. Must be minted and exist.\r
    * @param amounts Array of amounts corresponding to each recipient.\r
    *\r
    * Requirements:\r
    * - `recipients` and `amounts` arrays must be of the same length and not empty.\r
    * - Caller must have enough balance of `tokenId` to cover the sum of `amounts`.\r
    */\r
    function bulkDropTo(\r
        address[] calldata recipients, \r
        uint256 tokenId, \r
        uint256[] calldata amounts\r
    ) public virtual {\r
       uint256 recipientsCount = recipients.length;\r
        uint256 totalAmount = 0;\r
\r
        // Ensure there are recipients\r
        if (recipientsCount == 0) {revert NoRecipients();} \r
        if (tokenId > totalTokenIdsMinted) {revert TokenDoesNotExist();}\r
        if (recipientsCount != amounts.length) {\r
            revert ERC1155InvalidArrayLength(recipientsCount, amounts.length);\r
        }\r
\r
        uint256 remaining = balanceOf(msg.sender, tokenId);\r
\r
        for (uint256 i = 0; i < recipients.length; i++) {\r
            if (remaining < amounts[i]) {revert LowTokenBalance();} \r
            remaining -= amounts[i];\r
            _safeTransferFrom(msg.sender, recipients[i], tokenId, amounts[i], "");\r
            totalAmount += amounts[i];\r
        }\r
\r
        // Emit an event for the airdrop\r
        emit BulkDropped(msg.sender, tokenId, totalAmount, recipientsCount);\r
    }\r
\r
    /**\r
    * @notice Transfers amounts of different tokenIds to recipients.\r
    * @param recipients List of recipient addresses.\r
    * @param tokenIds List of token IDs corresponding to amounts and recipients.\r
    * @param amounts List of token amounts for each tokenId to send to respective recipient.\r
    */\r
    function batchDropTo(\r
        address[] calldata recipients, \r
        uint256[] calldata tokenIds, \r
        uint256[] calldata amounts\r
    ) public virtual {\r
        uint256 recipientsCount = recipients.length;\r
        uint256 totalAmount = 0;\r
        uint256 length = recipients.length;\r
\r
        // Ensure there are recipients\r
        if (recipientsCount == 0) {revert NoRecipients();} \r
        if (length != tokenIds.length \r
        && length != amounts.length) {revert DataLengthMismatch();}\r
\r
        // Loop through the recipients and transfer amount to each one\r
        for (uint256 i = 0; i < recipientsCount; i++) {\r
            address recipient = recipients[i];\r
            uint256 amount = amounts[i];\r
            uint256 tokenId = tokenIds[i];\r
            if (tokenId > totalTokenIdsMinted) {revert TokenDoesNotExist();}\r
            if (balanceOf(msg.sender, tokenId) < amount) {revert LowTokenBalance();} \r
            totalAmount += amount;\r
            // Transfer the specified amount of tokenId to the recipient\r
            _safeTransferFrom(msg.sender, recipient, tokenId, amount, "");\r
        }\r
\r
        // Emit an event for the batch airdrop\r
        emit BatchDropped(msg.sender, tokenIds, totalAmount, recipientsCount);\r
    }\r
\r
    /**\r
     * @notice Returns the total supply of a given tokenId.\r
     * @param tokenId The tokenId to query.\r
     */\r
    function totalSupply(uint256 tokenId) public virtual view returns (uint256) {\r
        return _totalSupply[tokenId];\r
    }\r
\r
    /**\r
    * @notice Returns the total supply of all tokenIds (cumulative, global) in the contract.\r
    * @dev Iterates through all minted token IDs and sums their individual total supplies.\r
    *      May be expensive in gas if called on-chain when many token IDs exist.\r
    */\r
    function globalSupply() public virtual view returns (uint256) {\r
        uint256 cumulSupply = 0;\r
        for(uint256 i = 1; i <= totalTokenIdsMinted; i++ ) {\r
            cumulSupply += _totalSupply[i];\r
        }\r
        return cumulSupply;\r
    }\r
\r
    /**\r
    * @notice Returns all token IDs owned by an address.\r
    * @dev Iterates over all minted token IDs to check ownership.\r
    *      Uses two passes: first counts tokens owned, second fills the result array.\r
    *      This can be gas-heavy and fail if totalTokenIdsMinted is large; \r
    */\r
    function getTokenIdsByWallet(address wallet) external view returns (uint256[] memory) {\r
        uint256[] memory temp = new uint256[](totalTokenIdsMinted);\r
        uint256 count = 0;\r
\r
        for (uint256 i = 1; i <= totalTokenIdsMinted; i++) {\r
            if (balanceOf(wallet, i) > 0) {\r
                temp[count] = i;\r
                count++;\r
            }\r
        }\r
\r
        // Create a fixed-size array to return\r
        uint256[] memory tokenIds = new uint256[](count);\r
        for (uint256 j = 0; j < count; j++) {\r
            tokenIds[j] = temp[j];\r
        }\r
\r
        return tokenIds;\r
    }\r
\r
    /**\r
    * @notice Returns the URI of a given tokenId.\r
    * @dev Reverts if tokenId does not exist.\r
    */\r
    function uri(uint256 tokenId) public view returns (string memory) {\r
        return _tokenURI[tokenId];\r
    }\r
\r
    /**\r
    * @dev Sets the URI for a specific token.\r
    * @param tokenId The token ID to update.\r
    * @param newTokenURI The new URI string to set.\r
    */\r
    function setTokenURI(uint256 tokenId, string memory newTokenURI) public onlyOwner virtual {\r
        if(isContractFrozen) {revert ContractFrozen();}\r
        if (tokenId > totalTokenIdsMinted) {revert TokenDoesNotExist();}\r
        _tokenURI[tokenId] = newTokenURI;\r
        emit TokenURIUpdated(tokenId, newTokenURI);\r
    }\r
\r
    /**\r
    * @notice Sets the contract URI for contract metadata.\r
    *\r
    * @param newContractURI The new contract URI.\r
    */\r
    function setContractURI(string calldata newContractURI) public onlyOwner virtual {\r
        if(isContractFrozen) {revert ContractFrozen();}\r
\r
        // Set the new contract URI.\r
        contractURI = newContractURI;\r
\r
        // Emit an event with the update.\r
        emit ContractURIUpdated(newContractURI);\r
    }\r
\r
    /**\r
     * @notice Freeze Metadata + Mint (only Owner). \r
     * @dev This Action is irreversible.\r
     */\r
    function freezeContract() external onlyOwner virtual {\r
        // Freeze contract\r
        isContractFrozen = true;\r
\r
        // Emit an event with the update.\r
        emit contractFrozen();\r
    }\r
\r
    /**\r
     * @notice Emit an event notifying metadata updates for\r
     *         a range of token ids, according to EIP-4906.\r
     *\r
     * @param fromTokenId The start token id.\r
     * @param toTokenId   The end token id.\r
     */\r
    function emitBatchMetadataUpdate(uint256 fromTokenId, uint256 toTokenId) external {\r
        // Emit an event with the update.\r
        emit BatchMetadataUpdate(fromTokenId, toTokenId);\r
    }\r
\r
    /**\r
     * @dev See {IERC1155-balanceOf}.\r
     */\r
    function totalBalanceOf(address account) public view returns (uint256) {\r
        uint256 cumulBalance = 0;\r
        for(uint256 i = 1; i <= totalTokenIdsMinted; i++ ) {\r
            cumulBalance = cumulBalance + balanceOf(account, i);\r
        }\r
        return cumulBalance;\r
    }\r
\r
    /**\r
     * @dev See {IERC1155-balanceOf}.\r
     */\r
    function balanceOf(address account, uint256 tokenId) public view virtual returns (uint256) {\r
        return _balances[tokenId][account];\r
    }\r
\r
    /**\r
     * @dev See {IERC1155-balanceOfBatch}.\r
     *\r
     * Requirements:\r
     *\r
     * - `accounts` and `ids` must have the same length.\r
     */\r
    function balanceOfBatch(\r
        address[] memory accounts,\r
        uint256[] memory ids\r
    ) public view virtual returns (uint256[] memory) {\r
        if (accounts.length != ids.length) {\r
            revert ERC1155InvalidArrayLength(ids.length, accounts.length);\r
        }\r
\r
        uint256[] memory batchBalances = new uint256[](accounts.length);\r
\r
        for (uint256 i = 0; i < accounts.length; ++i) {\r
            batchBalances[i] = balanceOf(accounts[i], ids[i]);\r
        }\r
\r
        return batchBalances;\r
    }\r
\r
    /**\r
     * @dev See {IERC1155-setApprovalForAll}.\r
     */\r
    function setApprovalForAll(address operator, bool approved) public virtual {\r
        _setApprovalForAll(_msgSender(), operator, approved);\r
    }\r
\r
    /**\r
     * @dev See {IERC1155-isApprovedForAll}.\r
     */\r
    function isApprovedForAll(address account, address operator) public view virtual returns (bool) {\r
        return _operatorApprovals[account][operator];\r
    }\r
\r
    /**\r
     * @dev See {IERC1155-safeTransferFrom}.\r
     */\r
    function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) public virtual {\r
        address sender = _msgSender();\r
        if (from != sender && !isApprovedForAll(from, sender)) {\r
            revert ERC1155MissingApprovalForAll(sender, from);\r
        }\r
        _beforeTokenTransfers(from, to, id, value, data);\r
        _safeTransferFrom(from, to, id, value, data);\r
    }\r
\r
    /**\r
     * @dev See {IERC1155-safeBatchTransferFrom}.\r
     */\r
    function safeBatchTransferFrom(\r
        address from,\r
        address to,\r
        uint256[] memory ids,\r
        uint256[] memory values,\r
        bytes memory data\r
    ) public virtual {\r
        address sender = _msgSender();\r
        if (from != sender && !isApprovedForAll(from, sender)) {\r
            revert ERC1155MissingApprovalForAll(sender, from);\r
        }\r
        for (uint256 i = 1; i <= totalTokenIdsMinted; i++ ) {\r
            _beforeTokenTransfers(from, to, i, values[i], data);\r
        }\r
        _safeBatchTransferFrom(from, to, ids, values, data);\r
    }\r
\r
    /**\r
     * @dev Hook that is called before any token transfer.\r
     *      This includes minting.\r
     */\r
    function _beforeTokenTransfers(\r
        address from,\r
        address to,\r
        uint256 id,\r
        uint256 value,\r
        bytes memory //*data//* \r
    ) internal virtual {\r
    }\r
\r
    /**\r
     * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. Will mint (or burn) if `from`\r
     * (or `to`) is the zero address.\r
     *\r
     * Emits a {TransferSingle} event if the arrays contain one element, and {TransferBatch} otherwise.\r
     *\r
     * Requirements:\r
     *\r
     * - If `to` refers to a smart contract, it must implement either {IERC1155Receiver-onERC1155Received}\r
     *   or {IERC1155Receiver-onERC1155BatchReceived} and return the acceptance magic value.\r
     * - `ids` and `values` must have the same length.\r
     *\r
     * NOTE: The ERC-1155 acceptance check is not performed in this function. See {_updateWithAcceptanceCheck} instead.\r
     */\r
    function _update(address from, address to, uint256[] memory ids, uint256[] memory values) internal virtual {\r
        if (ids.length != values.length) {\r
            revert ERC1155InvalidArrayLength(ids.length, values.length);\r
        }\r
\r
        address operator = _msgSender();\r
\r
        for (uint256 i = 0; i < ids.length; ++i) {\r
            uint256 id = ids[i];\r
            uint256 value = values[i];\r
\r
            if (from != address(0)) {\r
                uint256 fromBalance = _balances[id][from];\r
                if (fromBalance < value) {\r
                    revert ERC1155InsufficientBalance(from, fromBalance, value, id);\r
                }\r
                unchecked {\r
                    // Overflow not possible: value <= fromBalance\r
                    _balances[id][from] = fromBalance - value;\r
                }\r
            }\r
\r
            if (to != address(0)) {\r
                _balances[id][to] += value;\r
            }\r
        }\r
\r
        if (ids.length == 1) {\r
            uint256 id = ids[0];\r
            uint256 value = values[0];\r
            emit TransferSingle(operator, from, to, id, value);\r
        } else {\r
            emit TransferBatch(operator, from, to, ids, values);\r
        }\r
    }\r
\r
    /**\r
     * @dev Version of {_update} that performs the token acceptance check by calling\r
     * {IERC1155Receiver-onERC1155Received} or {IERC1155Receiver-onERC1155BatchReceived} on the receiver address if it\r
     * contains code (eg. is a smart contract at the moment of execution).\r
     *\r
     * IMPORTANT: Overriding this function is discouraged because it poses a reentrancy risk from the receiver. So any\r
     * update to the contract state after this function would break the check-effect-interaction pattern. Consider\r
     * overriding {_update} instead.\r
     */\r
    function _updateWithAcceptanceCheck(\r
        address from,\r
        address to,\r
        uint256[] memory ids,\r
        uint256[] memory values,\r
        bytes memory data\r
    ) internal virtual {\r
        _update(from, to, ids, values);\r
        if (to != address(0)) {\r
            address operator = _msgSender();\r
            if (ids.length == 1) {\r
                uint256 id = ids[0];\r
                uint256 value = values[0];\r
                ERC1155Utils.checkOnERC1155Received(operator, from, to, id, value, data);\r
            } else {\r
                ERC1155Utils.checkOnERC1155BatchReceived(operator, from, to, ids, values, data);\r
            }\r
        }\r
    }\r
\r
    /**\r
     * @dev Transfers a `value` tokens of token type `id` from `from` to `to`.\r
     *\r
     * Emits a {TransferSingle} event.\r
     *\r
     * Requirements:\r
     *\r
     * - `to` cannot be the zero address.\r
     * - `from` must have a balance of tokens of type `id` of at least `value` amount.\r
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\r
     * acceptance magic value.\r
     */\r
    function _safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) internal {\r
        if (to == address(0)) {\r
            revert ERC1155InvalidReceiver(address(0));\r
        }\r
        if (from == address(0)) {\r
            revert ERC1155InvalidSender(address(0));\r
        }\r
        (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\r
        _updateWithAcceptanceCheck(from, to, ids, values, data);\r
    }\r
\r
    /**\r
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\r
     *\r
     * Emits a {TransferBatch} event.\r
     *\r
     * Requirements:\r
     *\r
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\r
     * acceptance magic value.\r
     * - `ids` and `values` must have the same length.\r
     */\r
    function _safeBatchTransferFrom(\r
        address from,\r
        address to,\r
        uint256[] memory ids,\r
        uint256[] memory values,\r
        bytes memory data\r
    ) internal {\r
        if (to == address(0)) {\r
            revert ERC1155InvalidReceiver(address(0));\r
        }\r
        if (from == address(0)) {\r
            revert ERC1155InvalidSender(address(0));\r
        }\r
        _updateWithAcceptanceCheck(from, to, ids, values, data);\r
    }\r
\r
\r
    /**\r
     * @dev Creates a `value` amount of tokens of type `id`, and assigns them to `to`.\r
     *\r
     * Emits a {TransferSingle} event.\r
     *\r
     * Requirements:\r
     *\r
     * - `to` cannot be the zero address.\r
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\r
     * acceptance magic value.\r
     */\r
    function _mint(address to, uint256 id, uint256 value, bytes memory data) internal virtual {\r
        if (to == address(0)) {\r
            revert ERC1155InvalidReceiver(address(0));\r
        }\r
        (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\r
        _updateWithAcceptanceCheck(address(0), to, ids, values, data);\r
    }\r
\r
    /**\r
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\r
     *\r
     * Emits a {TransferBatch} event.\r
     *\r
     * Requirements:\r
     *\r
     * - `ids` and `values` must have the same length.\r
     * - `to` cannot be the zero address.\r
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\r
     * acceptance magic value.\r
     */\r
    function _mintBatch(address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal {\r
        if (to == address(0)) {\r
            revert ERC1155InvalidReceiver(address(0));\r
        }\r
        _updateWithAcceptanceCheck(address(0), to, ids, values, data);\r
    }\r
\r
    /**\r
     * @dev Destroys a `value` amount of tokens of type `id` from `from`\r
     *\r
     * Emits a {TransferSingle} event.\r
     *\r
     * Requirements:\r
     *\r
     * - `from` cannot be the zero address.\r
     * - `from` must have at least `value` amount of tokens of type `id`.\r
     */\r
    function _burn(address from, uint256 id, uint256 value) internal {\r
        if (from == address(0)) {\r
            revert ERC1155InvalidSender(address(0));\r
        }\r
        (uint256[] memory ids, uint256[] memory values) = _asSingletonArrays(id, value);\r
        _updateWithAcceptanceCheck(from, address(0), ids, values, "");\r
        _totalSupply[id] -= value;\r
    }\r
\r
    /**\r
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\r
     *\r
     * Emits a {TransferBatch} event.\r
     *\r
     * Requirements:\r
     *\r
     * - `from` cannot be the zero address.\r
     * - `from` must have at least `value` amount of tokens of type `id`.\r
     * - `ids` and `values` must have the same length.\r
    */\r
    function _burnBatch(address from, uint256[] memory ids, uint256[] memory values) internal {\r
        if (from == address(0)) {\r
            revert ERC1155InvalidSender(address(0));\r
        }\r
        _updateWithAcceptanceCheck(from, address(0), ids, values, "");\r
        for(uint256 i = 0; i < ids.length; i++) {\r
        _totalSupply[ids[i]] -= values[i];\r
        }\r
    }\r
\r
    /**\r
     * @dev Approve `operator` to operate on all of `owner` tokens\r
     *\r
     * Emits an {ApprovalForAll} event.\r
     *\r
     * Requirements:\r
     *\r
     * - `operator` cannot be the zero address.\r
     */\r
    function _setApprovalForAll(address owner, address operator, bool approved) internal virtual {\r
        if (operator == address(0)) {\r
            revert ERC1155InvalidOperator(address(0));\r
        }\r
        _operatorApprovals[owner][operator] = approved;\r
        emit ApprovalForAll(owner, operator, approved);\r
    }\r
\r
    /**\r
     * @dev Creates an array in memory with only one value for each of the elements provided.\r
     */\r
    function _asSingletonArrays(\r
        uint256 element1,\r
        uint256 element2\r
    ) private pure returns (uint256[] memory array1, uint256[] memory array2) {\r
        assembly ("memory-safe") {\r
            // Load the free memory pointer\r
            array1 := mload(0x40)\r
            // Set array length to 1\r
            mstore(array1, 1)\r
            // Store the single element at the next word after the length (where content starts)\r
            mstore(add(array1, 0x20), element1)\r
\r
            // Repeat for next array locating it right after the first array\r
            array2 := add(array1, 0x40)\r
            mstore(array2, 1)\r
            mstore(add(array2, 0x20), element2)\r
\r
            // Update the free memory pointer by pointing after the second array\r
            mstore(0x40, add(array2, 0x40))\r
        }\r
    }\r
\r
}"
    },
    "src/interfaces/ITransferValidator.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
pragma solidity ^0.8.17;\r
\r
interface ITransferValidator721 {\r
    /// @notice Ensure that a transfer has been authorized for a specific tokenId\r
    function validateTransfer(\r
        address caller,\r
        address from,\r
        address to,\r
        uint256 tokenId\r
    ) external view;\r
}\r
\r
interface ITransferValidator1155 {\r
    /// @notice Ensure that a transfer has been authorized for a specific amount of a specific tokenId, and reduce the transferable amount remaining\r
    function validateTransfer(\r
        address caller,\r
        address from,\r
        address to,\r
        uint256 tokenId,\r
        uint256 amount\r
    ) external;\r
}\r
"
    },
    "lib/openzeppelin-contracts/contracts/security/ReentrancyGuard.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (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, _notEntered will be true
        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;
    }
}
"
    },
    "src/interfaces/ICreatorToken.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
pragma solidity ^0.8.4;\r
\r
interface ICreatorToken {\r
    event TransferValidatorUpdated(address oldValidator, address newValidator);\r
\r
    function getTransferValidator() external view returns (address validator);\r
\r
    function getTransferValidationFunction()\r
        external\r
        view\r
        returns (bytes4 functionSignature, bool isViewFunction);\r
\r
    function setTransferValidator(address validator) external;\r
}\r
\r
interface ILegacyCreatorToken {\r
    event TransferValidatorUpdated(address oldValidator, address newValidator);\r
\r
    function getTransferValidator() external view returns (address validator);\r
\r
    function setTransferValidator(address validator) external;\r
}\r
"
    },
    "src/lib/ERC1155TransferValidator.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
pragma solidity ^0.8.17;\r
\r
import { ICreatorToken } from "../interfaces/ICreatorToken.sol";\r
\r
/**\r
 * @title  ERC721TransferValidator\r
 * @notice Functionality to use a transfer validator.\r
 */\r
abstract contract ERC1155TransferValidator is ICreatorToken {\r
    /// @dev Store the transfer validator. The null address means no transfer validator is set.\r
    address internal _transferValidator;\r
\r
    /// @notice Revert with an error if the transfer validator is being set to the same address.\r
    error SameTransferValidator();\r
\r
    /// @notice Returns the currently active transfer validator.\r
    ///         The null address means no transfer validator is set.\r
    function getTransferValidator() external view returns (address) {\r
        return _transferValidator;\r
    }\r
\r
    /// @notice Set the transfer validator.\r
    ///         The external method that uses this must include access control.\r
    function _setTransferValidator(address newValidator) internal virtual {\r
        address oldValidator = _transferValidator;\r
        if (oldValidator == newValidator) {\r
            revert SameTransferValidator();\r
        }\r
        _transferValidator = newValidator;\r
        emit TransferValidatorUpdated(oldValidator, newValidator);\r
    }\r
}"
    },
    ".deps/npm/@openzeppelin/contracts/access/Ownable.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../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.
 *
 * The initial owner is set to the address provided by the deployer. 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;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @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 {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @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 payable 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 {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _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);
    }
}
"
    },
    "WANTED/lib/ERC1155AirdropsErrorsAndEvents.sol": {
      "content": "// SPDX-License-Identifier: MIT\r
pragma solidity ^0.8.29;\r
\r
/**\r
 * @dev Standard ERC-1155 Errors\r
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.\r
 */\r
\r
interface ERC1155AirdropsErrorsAndEvents {\r
\r
    /**\r
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.\r
     * @param sender Address whose tokens are being transferred.\r
     * @param balance Current balance for the interacting account.\r
     * @param needed Minimum amount required to perform a transfer.\r
     * @param tokenId Identifier number of a token.\r
     */\r
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);\r
\r
    /**\r
     * @dev Indicates a failure with the token `sender`. Used in transfers.\r
     * @param sender Address whose tokens are being transferred.\r
     */\r
    error ERC1155InvalidSender(address sender);\r
\r
    /**\r
     * @dev Indicates a failure with the token `receiver`. Used in transfers.\r
     * @param receiver Address to which tokens are being transferred.\r
     */\r
    error ERC1155InvalidReceiver(address receiver);\r
\r
    /**\r
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.\r
     * @param operator Address that may be allowed to operate on tokens without being their owner.\r
     * @param owner Address of the current owner of a token.\r
     */\r
    error ERC1155MissingApprovalForAll(address operator, address owner);\r
\r
    /**\r
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.\r
     * @param approver Address initiating an approval operation.\r
     */\r
    error ERC1155InvalidApprover(address approver);\r
\r
    /**\r
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.\r
     * @param operator Address that may be allowed to operate on tokens without being their owner.\r
     */\r
    error ERC1155InvalidOperator(address operator);\r
\r
    /**\r
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.\r
     * Used in batch transfers.\r
     * @param idsLength Length of the array of token identifiers\r
     * @param valuesLength Length of the array of token amounts\r
     */\r
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);\r
\r
    // @dev Thrown when a referenced token does not exist.\r
    error TokenDoesNotExist();\r
\r
    // @dev Thrown when initial token supply values are missing or invalid.\r
    error SuppliesMissing();\r
\r
    // @dev Thrown when the provided data arrays (e.g., IDs and supplies) have mismatched lengths.\r
    error DataLengthMismatch();\r
\r
    // @dev Thrown when no recipient addresses are provided where required.\r
    error NoRecipients();\r
\r
    // @dev Thrown when an action is attempted on a frozen contract.\r
    error ContractFrozen();\r
\r
    // @dev Thrown when an account's token balance is too low to perform the requested operation.\r
    error LowTokenBalance();\r
\r
    // @dev Event to notify new token minting.\r
    event Minted(address account, uint256 indexed tokenId, uint256 supply);\r
\r
    // @dev Event to notify new tokenIds are batch minted (single recipient, several tokenIds).\r
    event BatchMinted(address account, uint256[] indexed tokenIds, uint256[] supplies);\r
\r
    // @dev Event when tokenId is bulk Airdropped (to multiple recipients).\r
    event BulkDropped(address from, uint256 indexed tokenId, uint256 totalAmount, uint256 recipientsCount);\r
\r
    // @dev Event when multiple tokenIds are batch Airdropped (to multiple recipients).\r
    event BatchDropped(address from, uint256[] indexed tokenIds, uint256 totalAmount, uint256 recipientsCount);\r
\r
    /**\r
     * @dev Emit an event for token metadata reveals/updates,\r
     *      according to EIP-4906.\r
     *\r
     * @param _fromTokenId The start token id.\r
     * @param _toTokenId   The end token id.\r
     */\r
    event BatchMetadataUpdate(uint256 _fromTokenId, uint256 _toTokenId);\r
\r
    /**\r
     * @dev Emit an event when the URI of a token is updated.\r
     */\r
    event TokenURIUpdated(uint256 tokenId, string newTokentURI);\r
\r
    /**\r
     * @dev Emit an event when the contract URI is updated.\r
     */\r
    event ContractURIUpdated(string newContractURI);\r
\r
\r
}"
    },
    "lib/openzeppelin-contracts/contracts/interfaces/IERC2981.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)

pragma solidity ^0.8.0;

import "../utils/introspection/IERC165.sol";

/**
 * @dev Interface for the NFT Royalty Standard.
 *
 * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
 * support for royalty payments across all NFT marketplaces and ecosystem participants.
 *
 * _Available since v4.5._
 */
interface IERC2981 is IERC165 {
    /**
     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount);
}
"
    },
    "@openzeppelin/contracts/token/common/ERC2981.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/common/ERC2981.sol)

pragma solidity ^0.8.20;

import {IERC2981} from "../../interfaces/IERC2981.sol";
import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol";

/**
 * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
 *
 * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
 * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
 *
 * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
 * fee is specified in basis points by default.
 *
 * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
 * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the ERC. Marketplaces are expected to
 * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
 */
abstract contract ERC2981 is IERC2981, ERC165 {
    struct RoyaltyInfo {
        address receiver;
        uint96 royaltyFraction;
    }

    RoyaltyInfo internal _defaultRoyaltyInfo;
    mapping(uint256 tokenId => RoyaltyInfo) internal _tokenRoyaltyInfo;

    /**
     * @dev The default royalty set is invalid (eg. (numerator / denominator) >= 1).
     */
    error ERC2981InvalidDefaultRoyalty(uint256 numerator, uint256 denominator);

    /**
     * @dev The default royalty receiver is invalid.
     */
    error ERC2981InvalidDefaultRoyaltyReceiver(address receiver);

    /**
     * @dev The royalty set for a specific `tokenId` is invalid (eg. (numerator / denominator) >= 1).
     */
    error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator);

    /**
     * @dev The royalty receiver for `tokenId` is invalid.
     */
    error ERC2981InvalidTokenRoyaltyReceiver(uint256 tokenId, address receiver);

    /// @inheritdoc IERC165
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
        return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
    }

    /// @inheritdoc IERC2981
    function royaltyInfo(
        uint256 tokenId,
        uint256 salePrice
    ) public view virtual returns (address receiver, uint256 amount) {
        RoyaltyInfo storage _royaltyInfo = _tokenRoyaltyInfo[tokenId];
        address royaltyReceiver = _royaltyInfo.receiver;
        uint96 royaltyFraction = _royaltyInfo.royaltyFraction;

        if (royaltyReceiver == address(0)) {
            royaltyReceiver = _defaultRoyaltyInfo.receiver;
            royaltyFraction = _defaultRoyaltyInfo.royaltyFraction;
        }

        uint256 royaltyAmount = (salePrice * royaltyFraction) / _feeDenominator();

        return (royaltyReceiver, royaltyAmount);
    }

        /**
     * @notice Returns the address that receives royalties.
     */
    function royaltyAddress() external view returns (address) {
        return _defaultRoyaltyInfo.receiver;
    }

    /**
     * @notice Returns the royalty basis points out of 10_000.
     */
    function royaltyBasisPoints() external view returns (uint256) {
        return _defaultRoyaltyInfo.royaltyFraction;
    }

    /**
     * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
     * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
     * override.
     */
    function _feeDenominator() internal pure virtual returns (uint96) {
        return 10000;
    }

    /**
     * @dev Sets the royalty information that all ids in this contract will default to.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
        uint256 denominator = _feeDenominator();
        if (feeNumerator > denominator) {
            // Royalty fee will exceed the sale price
            revert ERC2981InvalidDefaultRoyalty(feeNumerator, denominator);
        }
        if (receiver == address(0)) {
            revert ERC2981InvalidDefaultRoyaltyReceiver(address(0));
        }

        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Removes default royalty information.
     */
    function _deleteDefaultRoyalty() internal virtual {
        delete _defaultRoyaltyInfo;
    }

    /**
     * @dev Sets the royalty information for a specific token id, overriding the global default.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual {
        uint256 denominator = _feeDenominator();
        if (feeNumerator > denominator) {
            // Royalty fee will exceed the sale price
            revert ERC2981InvalidTokenRoyalty(tokenId, feeNumerator, denominator);
        }
        if (receiver == address(0)) {
            revert ERC2981InvalidTokenRoyaltyReceiver(tokenId, address(0));
        }

        _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Resets royalty information for the token id back to the global default.
     */
    function _resetTokenRoyalty(uint256 tokenId) internal virtual {
        delete _tokenRoyaltyInfo[tokenId];\

Tags:
ERC1155, ERC165, Multisig, Non-Fungible, Upgradeable, Multi-Signature, Factory|addr:0x27031d97d1f32e7a6a81d616fb44eecb5e50255a|verified:true|block:23639166|tx:0x66970c0fe4064a9bba27f2d4aa9e90b204a68e44abbde46c0275ba3529b6563d|first_check:1761305266

Submitted on: 2025-10-24 13:27:49

Comments

Log in to comment.

No comments yet.