QuantumRenderer

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": {
    "src/QuantumRenderer.sol": {
      "content": "// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;

import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/Base64.sol";
import "utility-contracts/TwoStepOwnable.sol";
import "./interfaces/IQuantumTraits.sol";

interface IQuantumEntities {
    function getCurrentPhase(uint256 tokenId) external view returns (uint32);
    function getPhaseProgress(uint256 tokenId) external view returns (uint32);
}

/**
 * @title QuantumRenderer
 * @notice Stateless-ish renderer with pre-reveal system.
 *         During pre-reveal: shows generic preview for all tokens
 *         After reveal: shows complete traits and metadata
 */
contract QuantumRenderer is TwoStepOwnable {
    using Strings for uint256;
    using Strings for uint32;
    
    // =============================================================
    //                            STORAGE
    // =============================================================
    
    IQuantumTraits public quantumTraits;
    IQuantumEntities public quantumEntities;
    string public baseAnimationURI;
    string public baseImageURI;
    
    // REVEAL SYSTEM
    bool public revealed = false;
    uint256 public revealTime;
    string public preRevealAnimationURI;
    string public preRevealDescription;
    
    // =============================================================
    //                            EVENTS
    // =============================================================
    
    event RevealActivated(uint256 timestamp);
    event PreRevealConfigUpdated(string animationURI, string description);
    
    // =============================================================
    //                          CONSTRUCTOR
    // =============================================================
    
    constructor(address _quantumTraits, address _quantumEntities) {
        quantumTraits = IQuantumTraits(_quantumTraits);
        quantumEntities = IQuantumEntities(_quantumEntities);
        
        // Initial pre-reveal configuration
        preRevealDescription = "A quantum consciousness in dormant state, gathering energy for manifestation. This entity sleeps in the digital void, its true form protected until awakening.";
        preRevealAnimationURI = ""; // EMPTY = no animation until configured
    }
    
    // =============================================================
    //                      METADATA GENERATION
    // =============================================================
    
    function tokenURI(uint256 tokenId, uint256 seed, uint8[9] memory traits) external view returns (string memory) {
        // If not revealed, return preview metadata
        if (!revealed && (revealTime == 0 || block.timestamp < revealTime)) {
            return _generatePreRevealMetadata(tokenId, seed);
        }
        
        // If revealed, return complete metadata
        return _generateRevealedMetadata(tokenId, seed, traits);
    }
    
    function _generatePreRevealMetadata(uint256 tokenId, uint256 seed) internal view returns (string memory) {
        // Generic preview for ALL tokens - does not reveal traits
        string memory json = string(abi.encodePacked(
            '{"name":"Quantum Entity #',
            tokenId.toString(),
            '","description":"',
            preRevealDescription,
            '","image":"',
            _getPreRevealImageURI(tokenId),
            '","animation_url":"',
            _getPreRevealAnimationURI(tokenId),
            '","attributes":[',
            _buildPreRevealAttributes(seed),
            ']}'
        ));
        
        return string(abi.encodePacked(
            "data:application/json;base64,",
            Base64.encode(bytes(json))
        ));
    }
    
    function _generateRevealedMetadata(uint256 tokenId, uint256 seed, uint8[9] memory traits) internal view returns (string memory) {
        // Complete metadata (original code)
        string[9] memory traitNames = quantumTraits.getTraitNames(traits);
        string memory rarity = quantumTraits.getRarityTier(seed);
        bool isLegendary = quantumTraits.isLegendary(traits[0]);
        uint32 currentPhase = quantumEntities.getCurrentPhase(tokenId);
        uint32 phaseProgress = quantumEntities.getPhaseProgress(tokenId);
        
        string memory json = string(abi.encodePacked(
            '{"name":"Quantum Entity #',
            tokenId.toString(),
            '","description":"',
            _getDescription(traitNames[0], rarity, currentPhase),
            '","image":"',
            _getImageURI(tokenId, seed),
            '","animation_url":"',
            _getAnimationURI(tokenId, seed),
            '","attributes":[',
            _buildAttributes(traitNames, rarity, isLegendary, seed, currentPhase, phaseProgress),
            ']}'
        ));
        
        return string(abi.encodePacked(
            "data:application/json;base64,",
            Base64.encode(bytes(json))
        ));
    }
    
    // =============================================================
    //                    PRE-REVEAL FUNCTIONS
    // =============================================================
    
    function _getPreRevealImageURI(uint256 tokenId) internal pure returns (string memory) {
        // ALWAYS returns generic SVG - never uses baseImageURI during pre-reveal
        return _generateDormantSVG(tokenId);
    }
    
    function _getPreRevealAnimationURI(uint256 tokenId) internal view returns (string memory) {
        // Only returns URL if explicitly configured
        if (bytes(preRevealAnimationURI).length > 0) {
            return string(abi.encodePacked(
                preRevealAnimationURI,
                "?tokenId=",
                tokenId.toString()
            ));
        }
        
        // If not configured, returns empty (no animation)
        return "";
    }
    
    function _buildPreRevealAttributes(uint256 seed) internal pure returns (string memory) {
        uint256 truncatedSeed = seed % 100000000;
        
        return string(abi.encodePacked(
            '{"trait_type":"Status","value":"Dormant"},',
            '{"trait_type":"Manifestation Phase","value":"0 - Sleeping"},',
            '{"trait_type":"Quantum Seed","value":"',
            truncatedSeed.toString(),
            '"},{"trait_type":"Energy Level","value":"Gathering"}'
        ));
    }
    
    function _generateDormantSVG(uint256 tokenId) internal pure returns (string memory) {
        // Generic identical SVG for ALL tokens
        string memory svg = string(abi.encodePacked(
            '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400">',
            '<defs>',
            '<radialGradient id="dormant" cx="50%" cy="50%" r="70%">',
            '<stop offset="0%" style="stop-color:#1a1a2e;stop-opacity:0.9"/>',
            '<stop offset="100%" style="stop-color:#0f0f23;stop-opacity:1"/>',
            '</radialGradient>',
            '<filter id="pulse">',
            '<feGaussianBlur stdDeviation="2"/>',
            '</filter>',
            '</defs>',
            '<rect width="400" height="400" fill="url(#dormant)"/>',
            '<circle cx="200" cy="200" r="40" fill="#16213e" opacity="0.6">',
            '<animate attributeName="opacity" values="0.3;0.8;0.3" dur="3s" repeatCount="indefinite"/>',
            '</circle>',
            '<circle cx="200" cy="200" r="20" fill="#0e3460" opacity="0.8">',
            '<animate attributeName="r" values="15;25;15" dur="4s" repeatCount="indefinite"/>',
            '</circle>',
            '<text x="200" y="280" text-anchor="middle" fill="#4a5568" font-family="monospace" font-size="10" opacity="0.7">',
            'DORMANT STATE',
            '</text>',
            '<text x="200" y="300" text-anchor="middle" fill="#2d3748" font-family="monospace" font-size="8" opacity="0.5">',
            'Entity #',
            _toString(tokenId),
            '</text>',
            '</svg>'
        ));
        
        return string(abi.encodePacked(
            "data:image/svg+xml;base64,",
            Base64.encode(bytes(svg))
        ));
    }
    
    // =============================================================
    //                    REVEALED METADATA (ORIGINAL)
    // =============================================================
    
    function _getDescription(string memory entityType, string memory rarity, uint32 currentPhase) internal pure returns (string memory) {
        return string(abi.encodePacked(
            "A ",
            rarity,
            " ",
            entityType,
            " in Phase ",
            currentPhase.toString(),
            "/5 of manifestation. This animated quantum consciousness emerges through progressive phases, each revealing new behaviors and mystical properties. These beings exist in the space between digital and metaphysical realms, their forms stabilizing as they gain coherence through time."
        ));
    }
    
    function _getImageURI(uint256 tokenId, uint256 seed) internal view returns (string memory) {
        if (bytes(baseImageURI).length > 0) {
            return string(abi.encodePacked(baseImageURI, "/", tokenId.toString(), ".png"));
        }
        
        return _generateSVG(tokenId, seed);
    }
    
    function _getAnimationURI(uint256 tokenId, uint256 seed) internal view returns (string memory) {
        if (bytes(baseAnimationURI).length > 0) {
            return string(abi.encodePacked(
                baseAnimationURI,
                "?tokenId=",
                tokenId.toString(),
                "&seed=",
                seed.toString()
            ));
        }
        
        return string(abi.encodePacked(
            "https://fractalswarm.xyz/quantum_viewer.html?tokenId=",
            tokenId.toString()
        ));
    }
    
    function _buildAttributes(
        string[9] memory traitNames,
        string memory rarity,
        bool isLegendary,
        uint256 seed,
        uint32 currentPhase,
        uint32 phaseProgress
    ) internal pure returns (string memory) {
        string memory attributes = string(abi.encodePacked(
            '{"trait_type":"Entity Type","value":"',
            traitNames[0],
            '"},{"trait_type":"Color Palette","value":"',
            traitNames[1],
            '"},{"trait_type":"Eyes","value":"',
            traitNames[2],
            '"},{"trait_type":"Weapon","value":"',
            traitNames[3],
            '"},{"trait_type":"Headgear","value":"',
            traitNames[4],
            '"}'
        ));
        
        attributes = string(abi.encodePacked(
            attributes,
            ',{"trait_type":"Pose","value":"',
            traitNames[5],
            '"},{"trait_type":"Size","value":"',
            traitNames[6],
            '"},{"trait_type":"Background","value":"',
            traitNames[7],
            '"},{"trait_type":"Ambient Effect","value":"',
            traitNames[8],
            '"}'
        ));
        
        uint256 truncatedSeed = seed % 100000000;
        
        attributes = string(abi.encodePacked(
            attributes,
            ',{"trait_type":"Current Phase","value":"',
            currentPhase.toString(),
            '"},{"trait_type":"Phase Progress","value":"',
            phaseProgress.toString(),
            '%"},{"trait_type":"Rarity","value":"',
            rarity,
            '"},{"trait_type":"Legendary","value":"',
            isLegendary ? "Yes" : "No",
            '"},{"trait_type":"Quantum Seed","value":"',
            truncatedSeed.toString(),
            '"}'
        ));
        
        string memory manifestationStatus;
        if (currentPhase == 1) manifestationStatus = "Chaos";
        else if (currentPhase == 2) manifestationStatus = "Emergence";
        else if (currentPhase == 3) manifestationStatus = "Formation";
        else if (currentPhase == 4) manifestationStatus = "Stabilization";
        else manifestationStatus = "Full Consciousness";
        
        attributes = string(abi.encodePacked(
            attributes,
            ',{"trait_type":"Manifestation Status","value":"',
            manifestationStatus,
            '"}'
        ));
        
        return attributes;
    }
    
    function _generateSVG(uint256 tokenId, uint256 seed) internal pure returns (string memory) {
        uint256 hue1 = (seed >> 8) % 360;
        uint256 hue2 = (seed >> 16) % 360;
        uint256 hue3 = (seed >> 24) % 360;
        
        string memory svg = string(abi.encodePacked(
            '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400">',
            '<defs>',
            '<radialGradient id="bg" cx="50%" cy="50%" r="70%">',
            '<stop offset="0%" style="stop-color:hsl(',
            _toString(hue1),
            ',80%,20%);stop-opacity:0.9"/>',
            '<stop offset="100%" style="stop-color:hsl(',
            _toString(hue2),
            ',60%,10%);stop-opacity:1"/>',
            '</radialGradient>',
            '<filter id="glow">',
            '<feGaussianBlur stdDeviation="4" result="coloredBlur"/>',
            '<feMerge><feMergeNode in="coloredBlur"/><feMergeNode in="SourceGraphic"/></feMerge>',
            '</filter>',
            '</defs>',
            '<rect width="400" height="400" fill="url(#bg)"/>',
            '<g filter="url(#glow)">',
            '<circle cx="200" cy="150" r="',
            _toString(30 + (seed % 20)),
            '" fill="hsl(',
            _toString(hue3),
            ',90%,70%)" opacity="0.8">',
            '<animateTransform attributeName="transform" type="rotate" values="0 200 150;360 200 150" dur="15s" repeatCount="indefinite"/>',
            '</circle>',
            '<ellipse cx="200" cy="200" rx="25" ry="50" fill="hsl(',
            _toString((hue1 + 120) % 360),
            ',80%,60%)" opacity="0.7"/>',
            '</g>',
            '<text x="200" y="350" text-anchor="middle" fill="hsl(',
            _toString(hue2),
            ',70%,80%)" font-family="monospace" font-size="12">',
            'Quantum Entity #',
            _toString(tokenId),
            '</text>',
            '</svg>'
        ));
        
        return string(abi.encodePacked(
            "data:image/svg+xml;base64,",
            Base64.encode(bytes(svg))
        ));
    }
    
    // =============================================================
    //                        REVEAL ADMIN
    // =============================================================
    
    function activateReveal() external onlyOwner {
        revealed = true;
        revealTime = block.timestamp;
        emit RevealActivated(block.timestamp);
    }
    
    function setRevealTime(uint256 _revealTime) external onlyOwner {
        revealTime = _revealTime;
    }
    
    function setPreRevealConfig(
        string calldata _preRevealAnimationURI,
        string calldata _preRevealDescription
    ) external onlyOwner {
        preRevealAnimationURI = _preRevealAnimationURI;
        preRevealDescription = _preRevealDescription;
        emit PreRevealConfigUpdated(_preRevealAnimationURI, _preRevealDescription);
    }
    
    // =============================================================
    //                        ADMIN FUNCTIONS
    // =============================================================
    
    function setBaseAnimationURI(string calldata _baseAnimationURI) external onlyOwner {
        baseAnimationURI = _baseAnimationURI;
    }
    
    function setBaseImageURI(string calldata _baseImageURI) external onlyOwner {
        baseImageURI = _baseImageURI;
    }
    
    function setQuantumTraits(address _quantumTraits) external onlyOwner {
        quantumTraits = IQuantumTraits(_quantumTraits);
    }
    
    function setQuantumEntities(address _quantumEntities) external onlyOwner {
        quantumEntities = IQuantumEntities(_quantumEntities);
    }
    
    // =============================================================
    //                        VIEW FUNCTIONS
    // =============================================================
    
    function isRevealed() external view returns (bool) {
        if (revealed) return true;
        if (revealTime > 0 && block.timestamp >= revealTime) return true;
        return false;
    }
    
    function getRevealInfo() external view returns (
        bool _revealed,
        uint256 _revealTime,
        uint256 _timeRemaining
    ) {
        _revealed = revealed;
        _revealTime = revealTime;
        
        if (revealTime > 0 && block.timestamp < revealTime) {
            _timeRemaining = revealTime - block.timestamp;
        } else {
            _timeRemaining = 0;
        }
        
        return (_revealed, _revealTime, _timeRemaining);
    }
    
    // =============================================================
    //                        HELPER FUNCTIONS
    // =============================================================
    
    function _toString(uint256 value) internal pure returns (string memory) {
        if (value == 0) return "0";
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }
}"
    },
    "lib/openzeppelin-contracts/contracts/utils/Strings.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

import "./math/Math.sol";
import "./math/SignedMath.sol";

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

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toString(int256 value) internal pure returns (string memory) {
        return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

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

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return keccak256(bytes(a)) == keccak256(bytes(b));
    }
}
"
    },
    "lib/openzeppelin-contracts/contracts/utils/Base64.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Base64.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides a set of functions to operate with Base64 strings.
 *
 * _Available since v4.5._
 */
library Base64 {
    /**
     * @dev Base64 Encoding/Decoding Table
     */
    string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    /**
     * @dev Converts a `bytes` to its Bytes64 `string` representation.
     */
    function encode(bytes memory data) internal pure returns (string memory) {
        /**
         * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence
         * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol
         */
        if (data.length == 0) return "";

        // Loads the table into memory
        string memory table = _TABLE;

        // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter
        // and split into 4 numbers of 6 bits.
        // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up
        // - `data.length + 2`  -> Round up
        // - `/ 3`              -> Number of 3-bytes chunks
        // - `4 *`              -> 4 characters for each chunk
        string memory result = new string(4 * ((data.length + 2) / 3));

        /// @solidity memory-safe-assembly
        assembly {
            // Prepare the lookup table (skip the first "length" byte)
            let tablePtr := add(table, 1)

            // Prepare result pointer, jump over length
            let resultPtr := add(result, 32)

            // Run over the input, 3 bytes at a time
            for {
                let dataPtr := data
                let endPtr := add(data, mload(data))
            } lt(dataPtr, endPtr) {

            } {
                // Advance 3 bytes
                dataPtr := add(dataPtr, 3)
                let input := mload(dataPtr)

                // To write each character, shift the 3 bytes (18 bits) chunk
                // 4 times in blocks of 6 bits for each character (18, 12, 6, 0)
                // and apply logical AND with 0x3F which is the number of
                // the previous character in the ASCII table prior to the Base64 Table
                // The result is then added to the table to get the character to write,
                // and finally write it in the result pointer but with a left shift
                // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits

                mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance

                mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
                resultPtr := add(resultPtr, 1) // Advance
            }

            // When data `bytes` is not exactly 3 bytes long
            // it is padded with `=` characters at the end
            switch mod(mload(data), 3)
            case 1 {
                mstore8(sub(resultPtr, 1), 0x3d)
                mstore8(sub(resultPtr, 2), 0x3d)
            }
            case 2 {
                mstore8(sub(resultPtr, 1), 0x3d)
            }
        }

        return result;
    }
}
"
    },
    "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/openzeppelin-contracts/contracts/utils/math/Math.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}
"
    },
    "lib/openzeppelin-contracts/contracts/utils/math/SignedMath.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}
"
    },
    "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:
Multisig, Upgradeable, Multi-Signature, Factory|addr:0x65a2298f35bbb6dfbe60637721013d254ffea62f|verified:true|block:23387793|tx:0x231000ffa852941dea1371aa2244e60f140d331d05654213cd8ee6d5372f5f04|first_check:1758189810

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

Comments

Log in to comment.

No comments yet.