QuantumTraits

Description:

Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "src/QuantumTraits.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

// Use TwoStepOwnable from SeaDrop (OpenSea) instead of OpenZeppelin Ownable.
import "utility-contracts/TwoStepOwnable.sol";
import "./interfaces/IQuantumTraits.sol";

/**
 * @title QuantumTraits
 * @notice Holds trait tables and simple logic. Ownership is managed via TwoStepOwnable.
 */
contract QuantumTraits is TwoStepOwnable, IQuantumTraits {
    
    // =============================================================
    //                        STATE VARIABLES
    // =============================================================
    
    mapping(uint8 => bool) public legendaryMinted;
    uint8 public legendariesMintedCount = 0;
    address public quantumEntitiesContract;
    
    modifier onlyQuantumContract() {
        require(msg.sender == quantumEntitiesContract, "Only QuantumEntities contract can call this");
        _;
    }
    
    // =============================================================
    //                        TRAIT DEFINITIONS
    // =============================================================
    
    string[13] private entityTypes = [
        "Ethereal Sage",      // 0 - Common (19%)
        "Quantum Guardian",   // 1 - Common (19%)
        "Digital Shaman",     // 2 - Common (18%)
        "Void Walker",        // 3 - Common (13%)
        "Plasma Entity",      // 4 - Uncommon (16%)
        "Astral Form",        // 5 - Uncommon (14%)
        "Neural Ghost",       // 6 - Rare (0.5%)
        "Code Spirit",        // 7 - Rare (0.5%) - ultra rare non-legendary
        "Ancient Titan",      // 8 - UNIQUE Legendary (only 1 ever)
        "Cosmic Weaver",      // 9 - UNIQUE Legendary (only 1 ever)
        "Time Wraith",        // 10 - UNIQUE Legendary (only 1 ever)
        "Void Leviathan",     // 11 - UNIQUE Legendary (only 1 ever)
        "Crystal Oracle"      // 12 - UNIQUE Ultra Legendary (only 1 ever)
    ];
    
    string[12] private colorPalettes = [
        "Standard Blue",      // 0 - 20% 
        "Crimson Fire",       // 1 - 15%
        "Emerald Dream",      // 2 - 12%
        "Golden Radiance",    // 3 - 10%
        "Shadow Realm",       // 4 - 8%
        "Arctic Frost",       // 5 - 8%
        "Neon Plasma",        // 6 - 6%
        "Deep Ocean",         // 7 - 6%
        "Volcanic Ember",     // 8 - 5%
        "Celestial Silver",   // 9 - 4%
        "Void Black",         // 10 - 0.5% - Ultra rare
        "Prismatic Aurora"    // 11 - 0.5% - Ultra rare
    ];
    
    string[4] private eyeConfigs = [
        "2 Standard",         // 0 - 50%
        "3 Seer",            // 1 - 30%
        "4 Cosmic",          // 2 - 15%
        "6 Ancient"          // 3 - 5%
    ];
    
    string[9] private weapons = [
        "None",              // 0 - 25%
        "Mystic Staff",      // 1 - 15%
        "Energy Sword",      // 2 - 12%
        "Power Orb",         // 3 - 12%
        "Quantum Bow",       // 4 - 10%
        "Focus Crystal",     // 5 - 8%
        "Void Blade",        // 6 - 8%
        "Arcane Wand",       // 7 - 6%
        "War Hammer"         // 8 - 4%
    ];
    
    string[9] private headgear = [
        "None",              // 0 - 30%
        "Hood",              // 1 - 15%
        "Helmet",            // 2 - 12%
        "Circlet",           // 3 - 10%
        "Feathers",          // 4 - 9%
        "Crown",             // 5 - 8%
        "Horns",             // 6 - 6%
        "Halo",              // 7 - 5%
        "Crystal Tiara"      // 8 - 5%
    ];
    
    string[6] private poses = [
        "Standing",          // 0 - 35%
        "Floating",          // 1 - 25%
        "Combat",            // 2 - 15%
        "Meditation",        // 3 - 10%
        "Dancing",           // 4 - 10%
        "Ascending"          // 5 - 5%
    ];
    
    string[4] private sizeClasses = [
        "Medium",            // 0 - 45%
        "Small",             // 1 - 25%
        "Large",             // 2 - 20%
        "Giant"              // 3 - 10%
    ];
    
    string[6] private backgrounds = [
        "Void Space",        // 0 - 25%
        "Cosmic Nebula",     // 1 - 20%
        "Digital Matrix",    // 2 - 20%
        "Mystical Realm",    // 3 - 15%
        "Elemental Storm",   // 4 - 15%
        "Geometric Space"    // 5 - 5%
    ];
    
    string[12] private ambientEffects = [
        "None",              // 0 - 30%
        "Orbs",              // 1 - 15%
        "Sparks",            // 2 - 12%
        "Smoke",             // 3 - 10%
        "Lightning",         // 4 - 8%
        "Stardust",          // 5 - 8%
        "Glitch",            // 6 - 6%
        "Matrix",            // 7 - 5%
        "Debris",            // 8 - 3%
        "Rifts",             // 9 - 2%
        "Echoes",            // 10 - 0.8%
        "Void Cracks"        // 11 - 0.2%
    ];
    
    // =============================================================
    //                        CONSTRUCTOR
    // =============================================================
    
    constructor() {
        for (uint8 i = 8; i <= 12; i++) {
            legendaryMinted[i] = false;
        }
    }
    
    // =============================================================
    //                        ADMIN FUNCTIONS
    // =============================================================
    
    function setQuantumEntitiesContract(address _contract) external onlyOwner {
        require(quantumEntitiesContract == address(0), "Contract already set");
        quantumEntitiesContract = _contract;
    }
    
    // =============================================================
    //                    WEIGHTED TRAIT GENERATION
    // =============================================================
    
    function getNormalEntityFromSeed(uint256 seed) internal pure returns (uint8) {
        uint256 roll = (seed >> 8) % 10000;
        
        if (roll < 1900) return 0;  // Ethereal Sage - 19%
        if (roll < 3800) return 1;  // Quantum Guardian - 19%
        if (roll < 5600) return 2;  // Digital Shaman - 18%
        if (roll < 6900) return 3;  // Void Walker - 13%
        if (roll < 8500) return 4;  // Plasma Entity - 16%
        if (roll < 9900) return 5;  // Astral Form - 14%
        if (roll < 9950) return 6;  // Neural Ghost - 0.5%
        return 7;                   // Code Spirit - 0.5%
    }
    
    function getColorPaletteFromSeed(uint256 seed) internal pure returns (uint8) {
        uint256 roll = (seed >> 16) % 10000;
        
        if (roll < 2000) return 0;   // Standard Blue - 20%
        if (roll < 3500) return 1;   // Crimson Fire - 15%
        if (roll < 4700) return 2;   // Emerald Dream - 12%
        if (roll < 5700) return 3;   // Golden Radiance - 10%
        if (roll < 6500) return 4;   // Shadow Realm - 8%
        if (roll < 7300) return 5;   // Arctic Frost - 8%
        if (roll < 7900) return 6;   // Neon Plasma - 6%
        if (roll < 8500) return 7;   // Deep Ocean - 6%
        if (roll < 9000) return 8;   // Volcanic Ember - 5%
        if (roll < 9400) return 9;   // Celestial Silver - 4%
        if (roll < 9950) return 10;  // Void Black - 0.5%
        return 11;                   // Prismatic Aurora - 0.5%
    }
    
    function getEyeConfigFromSeed(uint256 seed) internal pure returns (uint8) {
        uint256 roll = (seed >> 24) % 10000;
        
        if (roll < 5000) return 0;   // 2 Standard - 50%
        if (roll < 8000) return 1;   // 3 Seer - 30%
        if (roll < 9500) return 2;   // 4 Cosmic - 15%
        return 3;                    // 6 Ancient - 5%
    }
    
    function getWeaponFromSeed(uint256 seed) internal pure returns (uint8) {
        uint256 roll = (seed >> 32) % 10000;
        
        if (roll < 2500) return 0;   // None - 25%
        if (roll < 4000) return 1;   // Mystic Staff - 15%
        if (roll < 5200) return 2;   // Energy Sword - 12%
        if (roll < 6400) return 3;   // Power Orb - 12%
        if (roll < 7400) return 4;   // Quantum Bow - 10%
        if (roll < 8200) return 5;   // Focus Crystal - 8%
        if (roll < 9000) return 6;   // Void Blade - 8%
        if (roll < 9600) return 7;   // Arcane Wand - 6%
        return 8;                    // War Hammer - 4%
    }
    
    function getHeadgearFromSeed(uint256 seed) internal pure returns (uint8) {
        uint256 roll = (seed >> 40) % 10000;
        
        if (roll < 3000) return 0;   // None - 30%
        if (roll < 4500) return 1;   // Hood - 15%
        if (roll < 5700) return 2;   // Helmet - 12%
        if (roll < 6700) return 3;   // Circlet - 10%
        if (roll < 7600) return 4;   // Feathers - 9%
        if (roll < 8400) return 5;   // Crown - 8%
        if (roll < 9000) return 6;   // Horns - 6%
        if (roll < 9500) return 7;   // Halo - 5%
        return 8;                    // Crystal Tiara - 5%
    }
    
    function getPoseFromSeed(uint256 seed) internal pure returns (uint8) {
        uint256 roll = (seed >> 48) % 10000;
        
        if (roll < 3500) return 0;   // Standing - 35%
        if (roll < 6000) return 1;   // Floating - 25%
        if (roll < 7500) return 2;   // Combat - 15%
        if (roll < 8500) return 3;   // Meditation - 10%
        if (roll < 9500) return 4;   // Dancing - 10%
        return 5;                    // Ascending - 5%
    }
    
    function getSizeClassFromSeed(uint256 seed) internal pure returns (uint8) {
        uint256 roll = (seed >> 56) % 10000;
        
        if (roll < 4500) return 0;   // Medium - 45%
        if (roll < 7000) return 1;   // Small - 25%
        if (roll < 9000) return 2;   // Large - 20%
        return 3;                    // Giant - 10%
    }
    
    function getBackgroundFromSeed(uint256 seed) internal pure returns (uint8) {
        uint256 roll = (seed >> 64) % 10000;
        
        if (roll < 2500) return 0;   // Void Space - 25%
        if (roll < 4500) return 1;   // Cosmic Nebula - 20%
        if (roll < 6500) return 2;   // Digital Matrix - 20%
        if (roll < 8000) return 3;   // Mystical Realm - 15%
        if (roll < 9500) return 4;   // Elemental Storm - 15%
        return 5;                    // Geometric Space - 5%
    }
    
    function getAmbientEffectFromSeed(uint256 seed) internal pure returns (uint8) {
        uint256 roll = (seed >> 72) % 10000;
        
        if (roll < 3000) return 0;   // None - 30%
        if (roll < 4500) return 1;   // Orbs - 15%
        if (roll < 5700) return 2;   // Sparks - 12%
        if (roll < 6700) return 3;   // Smoke - 10%
        if (roll < 7500) return 4;   // Lightning - 8%
        if (roll < 8300) return 5;   // Stardust - 8%
        if (roll < 8900) return 6;   // Glitch - 6%
        if (roll < 9400) return 7;   // Matrix - 5%
        if (roll < 9700) return 8;   // Debris - 3%
        if (roll < 9900) return 9;   // Rifts - 2%
        if (roll < 9980) return 10;  // Echoes - 0.8%
        return 11;                   // Void Cracks - 0.2%
    }
    
    function getLegendaryEntity(uint256 seed) internal view returns (uint8) {
        if (legendariesMintedCount >= 5) {
            return getNormalEntityFromSeed(seed);
        }
        
        uint8[] memory available = new uint8[](5 - legendariesMintedCount);
        uint8 availableCount = 0;
        
        for (uint8 i = 8; i <= 12; i++) {
            if (!legendaryMinted[i]) {
                available[availableCount] = i;
                availableCount++;
            }
        }
        
        if (availableCount > 0) {
            uint8 selectedIndex = uint8((seed >> 80) % availableCount);
            return available[selectedIndex];
        }
        
        return getNormalEntityFromSeed(seed);
    }
    
    function getEntityTypeFromSeed(uint256 seed) internal view returns (uint8) {
        uint256 roll = seed % 10000;
        
        if (roll >= 9960) {
            return getLegendaryEntity(seed);
        }
        
        return getNormalEntityFromSeed(seed);
    }
    
    // =============================================================
    //                        LEGENDARY TRACKING
    // =============================================================
    
    function markLegendaryMinted(uint8 entityType) external onlyQuantumContract {
        require(entityType >= 8 && entityType <= 12, "Not a legendary entity");
        require(!legendaryMinted[entityType], "Legendary already minted");
        
        legendaryMinted[entityType] = true;
        legendariesMintedCount++;
    }
    
    function isLegendaryAvailable(uint8 entityType) external view returns (bool) {
        if (entityType < 8 || entityType > 12) return false;
        return !legendaryMinted[entityType];
    }
    
    function getAvailableLegendaries() external view returns (uint8[] memory) {
        uint8[] memory available = new uint8[](5 - legendariesMintedCount);
        uint8 count = 0;
        
        for (uint8 i = 8; i <= 12; i++) {
            if (!legendaryMinted[i]) {
                available[count] = i;
                count++;
            }
        }
        
        return available;
    }
    
    // =============================================================
    //                    HELPER FUNCTIONS
    // =============================================================
    
    function getLegendaryColor(uint8 entityType, uint8 background) internal pure returns (uint8) {
        if (entityType < 8) return 255;
        
        if (entityType == 8) {
            if (background == 3) return 6;
            return 8;
        }
        if (entityType == 9) {
            if (background == 1 || background == 4) return 9;
            return 10;
        }
        if (entityType == 10) {
            if (background == 5) return 11;
            return 9;
        }
        if (entityType == 11) {
            if (background == 0) return 6;
            return 7;
        }
        if (entityType == 12) {
            return 11;
        }
        
        return 255;
    }
    
    function _generateTraits(uint256 seed) internal view returns (uint8[9] memory traits) {
        uint8 entityType = getEntityTypeFromSeed(seed);
        uint8 background = getBackgroundFromSeed(seed);
        
        uint8 colorPalette = getColorPaletteFromSeed(seed);
        uint8 adjustedColor = getLegendaryColor(entityType, background);
        if (adjustedColor != 255) {
            colorPalette = adjustedColor;
        }
        
        traits[0] = entityType;
        traits[1] = colorPalette;
        traits[2] = getEyeConfigFromSeed(seed);
        traits[3] = getWeaponFromSeed(seed);
        traits[4] = getHeadgearFromSeed(seed);
        traits[5] = getPoseFromSeed(seed);
        traits[6] = getSizeClassFromSeed(seed);
        traits[7] = background;
        traits[8] = getAmbientEffectFromSeed(seed);
        
        return traits;
    }
    
    // =============================================================
    //                        EXTERNAL FUNCTIONS
    // =============================================================
    
    function generateTraits(uint256 seed) external view returns (uint8[9] memory) {
        return _generateTraits(seed);
    }
    
    function generateTraitsAndMark(uint256 seed) external onlyQuantumContract returns (uint8[9] memory) {
        uint8[9] memory traits = _generateTraits(seed);
        
        if (traits[0] >= 8 && traits[0] <= 12 && !legendaryMinted[traits[0]]) {
            legendaryMinted[traits[0]] = true;
            legendariesMintedCount++;
        }
        
        return traits;
    }
    
    function getRarityTier(uint256 seed) external view returns (string memory) {
        uint8[9] memory traits = _generateTraits(seed);
        
        if (traits[0] == 12) return "ULTRA LEGENDARY";
        
        if (traits[0] >= 8) {
            if (traits[1] == 11 || traits[2] == 3 || traits[8] == 11) {
                return "MYTHIC";
            }
            return "LEGENDARY";
        }
        
        uint256 rarityScore = 0;
        
        if (traits[0] <= 3) rarityScore += 1;
        else if (traits[0] <= 5) rarityScore += 2;
        else rarityScore += 5;
        
        if (traits[1] >= 10) rarityScore += 8;
        else if (traits[1] >= 9) rarityScore += 4;
        else if (traits[1] >= 6) rarityScore += 2;
        
        if (traits[2] == 3) rarityScore += 5;
        else if (traits[2] >= 2) rarityScore += 2;
        
        if (traits[8] >= 10) rarityScore += 8;
        else if (traits[8] >= 8) rarityScore += 4;
        else if (traits[8] >= 6) rarityScore += 2;
        
        if (traits[3] == 8) rarityScore += 3;
        else if (traits[3] >= 7) rarityScore += 2;
        
        if (traits[4] >= 7) rarityScore += 3;
        else if (traits[4] >= 5) rarityScore += 2;
        
        if (traits[6] == 3) rarityScore += 3;
        if (traits[7] == 5) rarityScore += 3;
        
        if (rarityScore >= 15) return "MYTHIC";
        if (rarityScore >= 10) return "EPIC";
        if (rarityScore >= 6) return "RARE";
        if (rarityScore >= 3) return "UNCOMMON";
        return "COMMON";
    }
    
    // =============================================================
    //                        VIEW FUNCTIONS
    // =============================================================
    
    function getTraitNames(uint8[9] memory traits) external view returns (string[9] memory) {
        return [
            entityTypes[traits[0]],
            colorPalettes[traits[1]],
            eyeConfigs[traits[2]],
            weapons[traits[3]],
            headgear[traits[4]],
            poses[traits[5]],
            sizeClasses[traits[6]],
            backgrounds[traits[7]],
            ambientEffects[traits[8]]
        ];
    }
    
    function getEntityTypeName(uint8 entityType) external view returns (string memory) {
        require(entityType < 13, "Invalid entity type");
        return entityTypes[entityType];
    }
    
    function isLegendary(uint8 entityType) external pure returns (bool) {
        return entityType >= 8;
    }
    
    function getLegendaryStatus() external view returns (bool[5] memory minted, uint8 count) {
        for (uint8 i = 0; i < 5; i++) {
            minted[i] = legendaryMinted[i + 8];
        }
        return (minted, legendariesMintedCount);
    }
    
    function getAllEntityTypes() external view returns (string[13] memory) {
        return entityTypes;
    }
    
    function getAllColorPalettes() external view returns (string[12] memory) {
        return colorPalettes;
    }
    
    function getAllEyeConfigs() external view returns (string[4] memory) {
        return eyeConfigs;
    }
    
    function getAllWeapons() external view returns (string[9] memory) {
        return weapons;
    }
    
    function getAllHeadgear() external view returns (string[9] memory) {
        return headgear;
    }
    
    function getAllPoses() external view returns (string[6] memory) {
        return poses;
    }
    
    function getAllSizeClasses() external view returns (string[4] memory) {
        return sizeClasses;
    }
    
    function getAllBackgrounds() external view returns (string[6] memory) {
        return backgrounds;
    }
    
    function getAllAmbientEffects() external view returns (string[12] memory) {
        return ambientEffects;
    }
}"
    },
    "lib/seadrop/lib/utility-contracts/src/TwoStepOwnable.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

import {ConstructorInitializable} from "./ConstructorInitializable.sol";

/**
@notice A two-step extension of Ownable, where the new owner must claim ownership of the contract after owner initiates transfer
Owner can cancel the transfer at any point before the new owner claims ownership.
Helpful in guarding against transferring ownership to an address that is unable to act as the Owner.
*/
abstract contract TwoStepOwnable is ConstructorInitializable {
    address private _owner;

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

    address internal potentialOwner;

    event PotentialOwnerUpdated(address newPotentialAdministrator);

    error NewOwnerIsZeroAddress();
    error NotNextOwner();
    error OnlyOwner();

    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    constructor() {
        _initialize();
    }

    function _initialize() private onlyConstructor {
        _transferOwnership(msg.sender);
    }

    ///@notice Initiate ownership transfer to newPotentialOwner. Note: new owner will have to manually acceptOwnership
    ///@param newPotentialOwner address of potential new owner
    function transferOwnership(address newPotentialOwner)
        public
        virtual
        onlyOwner
    {
        if (newPotentialOwner == address(0)) {
            revert NewOwnerIsZeroAddress();
        }
        potentialOwner = newPotentialOwner;
        emit PotentialOwnerUpdated(newPotentialOwner);
    }

    ///@notice Claim ownership of smart contract, after the current owner has initiated the process with transferOwnership
    function acceptOwnership() public virtual {
        address _potentialOwner = potentialOwner;
        if (msg.sender != _potentialOwner) {
            revert NotNextOwner();
        }
        delete potentialOwner;
        emit PotentialOwnerUpdated(address(0));
        _transferOwnership(_potentialOwner);
    }

    ///@notice cancel ownership transfer
    function cancelOwnershipTransfer() public virtual onlyOwner {
        delete potentialOwner;
        emit PotentialOwnerUpdated(address(0));
    }

    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 != msg.sender) {
            revert OnlyOwner();
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
"
    },
    "src/interfaces/IQuantumTraits.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

/**
 * @title IQuantumTraits
 * @notice Interface for QuantumTraits contract
 */
interface IQuantumTraits {
    
    // =============================================================
    //                            EVENTS
    // =============================================================
    
    event LegendaryMinted(uint8 indexed entityType);
    
    // =============================================================
    //                        TRAIT GENERATION
    // =============================================================
    
    function generateTraits(uint256 seed) external view returns (uint8[9] memory);
    
    function generateTraitsAndMark(uint256 seed) external returns (uint8[9] memory);
    
    function getRarityTier(uint256 seed) external view returns (string memory);
    
    function getTraitNames(uint8[9] memory traits) external view returns (string[9] memory);
    
    // =============================================================
    //                        LEGENDARY TRACKING
    // =============================================================
    
    function markLegendaryMinted(uint8 entityType) external;
    
    function isLegendaryAvailable(uint8 entityType) external view returns (bool);
    
    function getAvailableLegendaries() external view returns (uint8[] memory);
    
    function getLegendaryStatus() external view returns (bool[5] memory minted, uint8 count);
    
    // =============================================================
    //                        ENTITY FUNCTIONS
    // =============================================================
    
    function getEntityTypeName(uint8 entityType) external view returns (string memory);
    
    function isLegendary(uint8 entityType) external pure returns (bool);
    
    // =============================================================
    //                        TRAIT ARRAYS
    // =============================================================
    
    function getAllEntityTypes() external view returns (string[13] memory);
    
    function getAllColorPalettes() external view returns (string[12] memory);
    
    function getAllEyeConfigs() external view returns (string[4] memory);
    
    function getAllWeapons() external view returns (string[9] memory);
    
    function getAllHeadgear() external view returns (string[9] memory);
    
    function getAllPoses() external view returns (string[6] memory);
    
    function getAllSizeClasses() external view returns (string[4] memory);
    
    function getAllBackgrounds() external view returns (string[6] memory);
    
    function getAllAmbientEffects() external view returns (string[12] memory);
}"
    },
    "lib/seadrop/lib/utility-contracts/src/ConstructorInitializable.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity >=0.8.4;

/**
 * @author emo.eth
 * @notice Abstract smart contract that provides an onlyUninitialized modifier which only allows calling when
 *         from within a constructor of some sort, whether directly instantiating an inherting contract,
 *         or when delegatecalling from a proxy
 */
abstract contract ConstructorInitializable {
    error AlreadyInitialized();

    modifier onlyConstructor() {
        if (address(this).code.length != 0) {
            revert AlreadyInitialized();
        }
        _;
    }
}
"
    }
  },
  "settings": {
    "remappings": [
      "@openzeppelin/=lib/openzeppelin-contracts/",
      "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
      "erc721a-seadrop/=lib/seadrop/",
      "seadrop/=lib/seadrop/src/",
      "forge-std/=lib/forge-std/src/",
      "solmate/=lib/seadrop/lib/solmate/src/",
      "utility-contracts/=lib/seadrop/lib/utility-contracts/src/",
      "ERC721A/=lib/seadrop/lib/ERC721A/contracts/",
      "ERC721A-Upgradeable/=lib/seadrop/lib/ERC721A-Upgradeable/contracts/",
      "create2-helpers/=lib/seadrop/lib/create2-helpers/",
      "create2-scripts/=lib/seadrop/lib/create2-helpers/script/",
      "ds-test/=lib/seadrop/lib/ds-test/src/",
      "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
      "murky/=lib/seadrop/lib/murky/src/",
      "openzeppelin-contracts-upgradeable/=lib/seadrop/lib/openzeppelin-contracts-upgradeable/",
      "openzeppelin/=lib/openzeppelin-contracts/contracts/",
      "operator-filter-registry/=lib/seadrop/lib/operator-filter-registry/src/"
    ],
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "metadata": {
      "useLiteralContent": false,
      "bytecodeHash": "ipfs"
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "evmVersion": "london",
    "viaIR": true
  }
}}

Tags:
Proxy, Upgradeable, Factory, Oracle|addr:0x3ccf9544bb4146770b0758e87b449bfe8455edd6|verified:true|block:23387793|tx:0xe2db3d7a4b6fb848234665b836f209a641ab674ec125c513172b9462ec3c3be0|first_check:1758189806

Submitted on: 2025-09-18 12:03:28

Comments

Log in to comment.

No comments yet.