EthereumEthereum
0x13...082f
Mythics Eggs

Mythics Eggs

EGG

Collection
Floor Price
0.019954 ETH
$2,345.34
Size
1,348
Collectibles
Owners
1,031
76% Unique Owners
This contract's source code is verified!
Contract Metadata
Compiler
0.8.19+commit.7dd6d404
Language
Solidity
Contract Source Code
File 1 of 38: AccessControl.sol
Contract Source Code
File 2 of 38: AccessControlEnumerable.sol
Contract Source Code
File 3 of 38: AccessControlPausable.sol
Contract Source Code
File 4 of 38: Address.sol
Contract Source Code
File 5 of 38: BaseRedeemableToken.sol
Contract Source Code
File 6 of 38: BaseSellable.sol
Contract Source Code
File 7 of 38: BaseTokenURI.sol
Contract Source Code
File 8 of 38: BitMaps.sol
Contract Source Code
File 9 of 38: Constants.sol
Contract Source Code
File 10 of 38: Context.sol
Contract Source Code
File 11 of 38: DefaultOperatorFilterer.sol
Contract Source Code
File 12 of 38: ERC165.sol
Contract Source Code
File 13 of 38: ERC2981.sol
Contract Source Code
File 14 of 38: ERC4906.sol
Contract Source Code
File 15 of 38: ERC721A.sol
Contract Source Code
File 16 of 38: ERC721ACommon.sol
Contract Source Code
File 17 of 38: EnumerableSet.sol
Contract Source Code
File 18 of 38: IAccessControl.sol
Contract Source Code
File 19 of 38: IAccessControlEnumerable.sol
Contract Source Code
File 20 of 38: IERC165.sol
Contract Source Code
File 21 of 38: IERC2981.sol
Contract Source Code
File 22 of 38: IERC721A.sol
Contract Source Code
File 23 of 38: IEntropyOracle.sol
Contract Source Code
File 24 of 38: IOperatorFilterRegistry.sol
Contract Source Code
File 25 of 38: IRedeemableToken.sol
Contract Source Code
File 26 of 38: ISellable.sol
Contract Source Code
File 27 of 38: Math.sol
Contract Source Code
File 28 of 38: MythicEggActivator.sol
// SPDX-License-Identifier: MIT
// Copyright 2023 PROOF Holdings Inc
pragma solidity ^0.8.15;

import {BitMaps} from "openzeppelin-contracts/utils/structs/BitMaps.sol";
import {ERC4906} from "ethier/erc721/ERC4906.sol";

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

interface MythicEggActivatorEvents {
    /**
     * @notice Emitted when an egg has been activated.
     */
    event EggActivated(uint256 indexed tokenId);
}

/**
 * @title Mythics: Egg activation module
 * @author David Huber (@cxkoda)
 * @custom:reviewer Arran Schlosberg (@divergencearran)
 */
abstract contract MythicEggActivator is ERC4906, MythicsEggErrors, MythicEggActivatorEvents {
    using BitMaps for BitMaps.BitMap;

    /**
     * @notice Throws if activating an egg that has already been activated.
     */
    error EggAlreadyActivated(uint256);

    /**
     * @notice Thrown if one tries to activate too many eggs at once.
     */
    error ActivatingTooManyEggs(uint256 requested, uint256 numLeft);

    /**
     * @notice Keeps track of eggs that have already been activated.
     */
    BitMaps.BitMap private _activated;

    /**
     * @notice The maximum number of eggs that can be activated during one day.
     */
    uint32 internal _maxNumActivationsPerDay = 50;

    /**
     * @notice The last day on which an egg was activated.
     */
    uint32 private _lastActivationDay;

    /**
     * @notice The number of eggs that have been activated today.
     * @dev Will be reset to 0 in `_activate` at the start of each day.
     */
    uint32 private _numActivatedToday;

    /**
     * @notice Helper function to get the current day number.
     */
    function _currentDay() private view returns (uint32) {
        return uint32(block.timestamp / (1 days));
    }

    /**
     * @notice Sets the maximum number of activations per day.
     */
    function _setMaxNumActivationsPerDay(uint32 maxNumActivationsPerDay) internal {
        _maxNumActivationsPerDay = maxNumActivationsPerDay;
    }

    /**
     * @notice Activates an array of eggs.
     * @dev Will revert if the number of eggs to activate exceeds the maximum number of activations per day.
     */
    function _activate(uint256[] calldata tokenIds) internal {
        if (_currentDay() > _lastActivationDay) {
            _numActivatedToday = 0;
            _lastActivationDay = _currentDay();
        }

        uint256 numLeft = _maxNumActivationsPerDay - _numActivatedToday;
        if (tokenIds.length > numLeft) {
            revert ActivatingTooManyEggs(tokenIds.length, numLeft);
        }

        for (uint256 i; i < tokenIds.length; ++i) {
            uint256 tokenId = tokenIds[i];

            if (activated(tokenId)) {
                revert EggAlreadyActivated(tokenId);
            }

            if (!_exists(tokenId)) {
                revert NonexistentEgg(tokenId);
            }

            _activated.set(tokenId);
            _refreshMetadata(tokenId);
            emit EggActivated(tokenId);
        }
        _numActivatedToday += uint32(tokenIds.length);
    }

    /**
     * @notice Returns whether an egg has already been activated.
     */
    function activated(uint256 tokenId) public view returns (bool) {
        if (!_exists(tokenId)) {
            revert NonexistentEgg(tokenId);
        }

        return _activated.get(tokenId);
    }

    /**
     * @notice Returns whether a token exists.
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool);
}
Contract Source Code
File 29 of 38: MythicEggSampler.sol
// SPDX-License-Identifier: MIT
// Copyright 2023 PROOF Holdings Inc
pragma solidity ^0.8.15;

import {IEntropyOracle} from "proof/entropy/IEntropyOracle.sol";

import {MythicsEggErrors} from "./MythicsEggErrors.sol";
import {
    StochasticSampler, StochasticSamplerWithCDFStorage, StochasticSamplerWithOracle
} from "./StochasticSampling.sol";

/**
 * @title Mythics: Egg type sampling module
 * @author David Huber (@cxkoda)
 * @custom:reviewer Arran Schlosberg (@divergencearran)
 */
abstract contract MythicEggSampler is StochasticSamplerWithCDFStorage, StochasticSamplerWithOracle, MythicsEggErrors {
    /**
     * @notice The different types of eggs.
     */
    enum EggType {
        Stone,
        Runic,
        Legendary
    }

    /**
     * @notice Number of egg types
     */
    uint8 public constant NUM_EGG_TYPES = 3;

    /**
     * @notice Trait ID for the egg type
     */
    uint8 private constant _EGG_TYPE_TRAIT_ID = 0;

    /**
     * @notice Token-specific parameters for sampling the egg type
     * @dev Will be determined at mint.
     * @param revealBlockNumber Number of the block whose entropy will be used to reaveal the egg type.
     * @param distributionVersion The version/index of probability distribution to sample the egg type.
     * @param mixHash Part of the block mixHash to blind the entropy oracle.
     */
    struct SamplingParams {
        uint64 revealBlockNumber;
        uint16 distributionVersion;
        uint128 mixHash;
    }

    /**
     * @notice Egg-type sampling parameters keyed by token ID.
     */
    mapping(uint256 => SamplingParams) private _samplingParams;

    /**
     * @dev Constructor helper function.
     */
    function _numPerTrait() private pure returns (uint256[] memory) {
        uint256[] memory numPerTrait = new uint256[](1);
        numPerTrait[_EGG_TYPE_TRAIT_ID] = NUM_EGG_TYPES;
        return numPerTrait;
    }

    constructor(IEntropyOracle oracle)
        StochasticSamplerWithCDFStorage(_numPerTrait())
        StochasticSamplerWithOracle(oracle)
    {}

    /**
     * @notice Returns the egg-type sampling parameters for a given token ID.
     */
    function samplingParams(uint256 tokenId) public view returns (SamplingParams memory) {
        if (!_exists(tokenId)) {
            revert NonexistentEgg(tokenId);
        }

        return _samplingParams[tokenId];
    }

    /**
     * @inheritdoc StochasticSamplerWithCDFStorage
     * @dev Reads the token-specific parameters.
     */
    function _distributionVersion(uint256 tokenId, uint256 traitId) internal view virtual override returns (uint256) {
        assert(traitId == _EGG_TYPE_TRAIT_ID);
        return _samplingParams[tokenId].distributionVersion;
    }

    /**
     * @inheritdoc StochasticSamplerWithOracle
     * @dev Reads the token-specific parameters.
     */
    function _revealBlockNumber(uint256 tokenId) internal view virtual override returns (uint256) {
        return _samplingParams[tokenId].revealBlockNumber;
    }

    /**
     * @notice Registers a token for egg-type sampling using the currently set probability distribution.
     * @dev Must be called upon token mint.
     */
    function _registerForSampling(uint256 tokenId) internal {
        uint256 revealBlockNumber = block.number;

        _samplingParams[tokenId] = SamplingParams({
            revealBlockNumber: uint64(revealBlockNumber),
            distributionVersion: uint16(_latestDistributionVersion(_EGG_TYPE_TRAIT_ID)),
            // Smearing out single-bit-of-influence from the prevrandao since we're just using 128 bits (mainly to
            // prevent the forge fuzzer from finding breaking runs which would force us to add circular testing logic).
            mixHash: uint128(uint256(keccak256(abi.encode(block.prevrandao))))
        });
        entropyOracle.requestEntropy(revealBlockNumber);
    }

    /**
     * @notice Sets the probability distribution for egg types.
     */
    function _setEggProbabilities(uint64[NUM_EGG_TYPES] memory pdf) internal {
        uint64[] memory p = new uint64[](NUM_EGG_TYPES);
        for (uint256 i = 0; i < NUM_EGG_TYPES; i++) {
            p[i] = pdf[i];
        }
        _pushProbabilities(_EGG_TYPE_TRAIT_ID, p);
    }

    /**
     * @inheritdoc StochasticSamplerWithOracle
     * @dev Mixes the seed with the token-specific parameters to blind the EntropyOracle.
     */
    function _seed(uint256 tokenId)
        internal
        view
        virtual
        override(StochasticSampler, StochasticSamplerWithOracle)
        returns (bytes32, bool)
    {
        (bytes32 seed, bool revealed) = StochasticSamplerWithOracle._seed(tokenId);
        return (keccak256(abi.encode(seed, samplingParams(tokenId))), revealed);
    }

    /**
     * @notice Returns the egg type of a given token ID and a boolean flag to indicate whether it was already revealed.
     */
    function eggType(uint256 tokenId) public view returns (EggType, bool) {
        (uint256 sample, bool revealed) = _sampleTrait(tokenId, _EGG_TYPE_TRAIT_ID);
        return (EggType(sample), revealed);
    }

    /**
     * @notice Returns whether a token exists.
     */
    function _exists(uint256 tokenId) internal view virtual returns (bool);
}
Contract Source Code
File 30 of 38: MythicsEgg.sol
// SPDX-License-Identifier: MIT
// Copyright 2023 PROOF Holdings Inc
pragma solidity ^0.8.15;

import {ERC721A, ERC721ACommon, BaseTokenURI, ERC721ACommonBaseTokenURI} from "ethier/erc721/BaseTokenURI.sol";
import {OperatorFilterOS} from "ethier/erc721/OperatorFilterOS.sol";
import {ERC4906} from "ethier/erc721/ERC4906.sol";

import {IEntropyOracle} from "proof/entropy/IEntropyOracle.sol";
import {RedeemableERC721ACommon} from "proof/redemption/voucher/RedeemableERC721ACommon.sol";
import {SellableERC721ACommon} from "proof/sellers/sellable/SellableERC721ACommon.sol";

import {MythicEggSampler} from "./MythicEggSampler.sol";
import {MythicEggActivator} from "./MythicEggActivator.sol";

/**
 * @title Mythics: Egg
 * @notice A redeemable token claimable by all diamond nested Moonbirds.
 * @author David Huber (@cxkoda)
 * @custom:reviewer Arran Schlosberg (@divergencearran)
 */
contract MythicsEgg is
    ERC721ACommonBaseTokenURI,
    OperatorFilterOS,
    SellableERC721ACommon,
    RedeemableERC721ACommon,
    MythicEggSampler,
    MythicEggActivator
{
    constructor(address admin, address steerer, address payable secondaryReceiver, IEntropyOracle oracle)
        ERC721ACommon(admin, steerer, "Mythics: Egg", "EGG", secondaryReceiver, 500)
        BaseTokenURI("https://metadata.proof.xyz/mythics/egg/")
        MythicEggSampler(oracle)
    {
        _setEggProbabilities([uint64(0), uint64(40), uint64(60)]);
    }

    // =================================================================================================================
    //                          Information Getter
    // =================================================================================================================

    /**
     * @notice Encodes information about a token.
     * @dev Intended to be used off-chain.
     */
    struct TokenInfo {
        bool revealed;
        EggType eggType;
        bool activated;
    }

    /**
     * @notice Returns information about given egg token.
     * @dev Not optimised, intended to be used off-chain only.
     */
    function tokenInfos(uint256[] calldata tokenIds) external view returns (TokenInfo[] memory) {
        TokenInfo[] memory infos = new TokenInfo[](tokenIds.length);
        for (uint256 i = 0; i < tokenIds.length; i++) {
            (EggType eggT, bool revealed) = eggType(tokenIds[i]);
            infos[i] = TokenInfo({revealed: revealed, eggType: eggT, activated: activated(tokenIds[i])});
        }
        return infos;
    }

    // =================================================================================================================
    //                          Steering
    // =================================================================================================================

    /**
     * @notice Sets the probability distribution for egg types.
     */
    function setEggProbabilities(uint64[NUM_EGG_TYPES] memory pdf) external onlyRole(DEFAULT_STEERING_ROLE) {
        _setEggProbabilities(pdf);
    }

    /**
     * @notice Sets the entropy oracle.
     */
    function setEntropyOracle(IEntropyOracle newOracle) external onlyRole(DEFAULT_STEERING_ROLE) {
        entropyOracle = newOracle;
    }

    /**
     * @notice Sets the maximum number of activations per day.
     */
    function setMaxNumActivationsPerDay(uint32 maxNumActivationsPerDay) external onlyRole(DEFAULT_STEERING_ROLE) {
        _setMaxNumActivationsPerDay(maxNumActivationsPerDay);
    }

    /**
     * @notice Activates an array of eggs.
     */
    function activate(uint256[] calldata tokenIds) external onlyRole(DEFAULT_STEERING_ROLE) {
        _activate(tokenIds);
    }

    // =================================================================================================================
    //                          Inheritance Resolution
    // =================================================================================================================

    /**
     * @inheritdoc SellableERC721ACommon
     * @dev Registers the minted tokens for sampling.
     */
    function _handleSale(address to, uint64 num, bytes calldata data) internal virtual override {
        uint256 startTokenId = _nextTokenId();
        for (uint256 i; i < num; ++i) {
            _registerForSampling(startTokenId + i);
        }

        super._handleSale(to, num, data);
    }

    function _exists(uint256 tokenId)
        internal
        view
        virtual
        override(ERC721A, MythicEggActivator, MythicEggSampler)
        returns (bool)
    {
        return ERC721A._exists(tokenId);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC721ACommon, ERC721ACommonBaseTokenURI, SellableERC721ACommon, RedeemableERC721ACommon, ERC4906)
        returns (bool)
    {
        return RedeemableERC721ACommon.supportsInterface(interfaceId)
            || SellableERC721ACommon.supportsInterface(interfaceId) || ERC4906.supportsInterface(interfaceId)
            || ERC721ACommonBaseTokenURI.supportsInterface(interfaceId);
    }

    function _baseURI() internal view virtual override(ERC721A, ERC721ACommonBaseTokenURI) returns (string memory) {
        return ERC721ACommonBaseTokenURI._baseURI();
    }

    function setApprovalForAll(address operator, bool approved) public virtual override(ERC721A, OperatorFilterOS) {
        OperatorFilterOS.setApprovalForAll(operator, approved);
    }

    function approve(address operator, uint256 tokenId) public payable virtual override(ERC721A, OperatorFilterOS) {
        OperatorFilterOS.approve(operator, tokenId);
    }

    function transferFrom(address from, address to, uint256 tokenId)
        public
        payable
        virtual
        override(ERC721A, OperatorFilterOS)
    {
        OperatorFilterOS.transferFrom(from, to, tokenId);
    }

    function safeTransferFrom(address from, address to, uint256 tokenId)
        public
        payable
        virtual
        override(ERC721A, OperatorFilterOS)
    {
        OperatorFilterOS.safeTransferFrom(from, to, tokenId);
    }

    function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data)
        public
        payable
        virtual
        override(ERC721A, OperatorFilterOS)
    {
        OperatorFilterOS.safeTransferFrom(from, to, tokenId, data);
    }
}
Contract Source Code
File 31 of 38: MythicsEggErrors.sol
// SPDX-License-Identifier: MIT
// Copyright 2023 PROOF Holdings Inc
pragma solidity ^0.8.15;

interface MythicsEggErrors {
    /**
     * @notice Thrown if one attempts an action on a nonexistent egg.
     */
    error NonexistentEgg(uint256 tokenId);
}
Contract Source Code
File 32 of 38: OperatorFilterOS.sol
Contract Source Code
File 33 of 38: OperatorFilterer.sol
Contract Source Code
File 34 of 38: Pausable.sol
Contract Source Code
File 35 of 38: RedeemableERC721ACommon.sol
Contract Source Code
File 36 of 38: SellableERC721ACommon.sol
Contract Source Code
File 37 of 38: StochasticSampling.sol
// SPDX-License-Identifier: MIT
// Copyright 2023 PROOF Holdings Inc
pragma solidity ^0.8.15;

import {IEntropyOracle} from "proof/entropy/IEntropyOracle.sol";

/**
 * @notice Helper libray for sampling from a discrete probability distribution.
 */
library StochasticSamplingLib {
    /**
     * @notice Computes the cumulative probability distribution from a discrete probability distribution.
     */
    function computeCDF(uint64[] memory pdf) internal pure returns (uint64[] memory) {
        uint64[] memory cdf = new uint64[](pdf.length);
        cdf[0] = pdf[0];
        for (uint256 i = 1; i < pdf.length; ++i) {
            cdf[i] = cdf[i - 1] + pdf[i];
        }

        return cdf;
    }

    /**
     * @notice Samples from a discrete cumulative probability distribution.
     * @dev This function assumes that rand is uniform in [0,2^256) and that `cdf[cdf.length - 1] << 2^256`. If not the
     * outcome will be biased
     */
    function sampleWithCDF(uint256 rand, uint64[] memory cdf) internal pure returns (uint256) {
        rand = rand % cdf[cdf.length - 1];

        for (uint256 i; i < cdf.length; ++i) {
            if (rand < cdf[i]) {
                return i;
            }
        }

        // This will never be reached given the above bounds of rand.
        assert(false);
        return 0;
    }
}

/**
 * @notice A contract that can sample token traits from discrete probability distributions.
 * @dev The probability distributions and seed derivation functions are implemented in the inheriting contracts.
 * @dev The functions defined here might be gas-heavy and are therefore intended to be used in view-calls only.
 */
abstract contract StochasticSampler {
    /**
     * @notice Returns a random seed for a given token and a boolean indicating whether the seed is available.
     */
    function _seed(uint256 tokenId) internal view virtual returns (bytes32, bool);

    /**
     * @notice Returns the cumulative probability distribution for a given trait of a given token.
     */
    function _cdf(uint256 tokenId, uint256 traitId) internal view virtual returns (uint64[] memory);

    /**
     * @notice Samples a trait for a given token.
     * @dev Returns the sampled trait and a boolean indicating whether the trait was already revealed (i.e. if the seed
     * for the given token is available).
     */
    function _sampleTrait(uint256 tokenId, uint256 traitId) internal view returns (uint256, bool) {
        (bytes32 seed, bool revealed) = _seed(tokenId);
        seed = keccak256(abi.encodePacked(seed, traitId));
        return (StochasticSamplingLib.sampleWithCDF(uint256(seed), _cdf(tokenId, traitId)), revealed);
    }
}

/**
 * @notice A contract that can sample token traits from discrete probability distributions loaded from storage.
 */
abstract contract StochasticSamplerWithCDFStorage is StochasticSampler {
    using StochasticSamplingLib for uint64[];

    /**
     * @notice Thrown if the traitId is invalid, i.e. if it exceeds the number of traits.
     */
    error InvalidTraitId(uint256 traitId);

    /**
     * @notice Thrown if the length of the given PDF does not match the number of realisations in a given trait.
     */
    error IncorrectPDFLength(uint256 gotLength, uint256 traitId, uint256 wantLength);

    /**
     * @notice Thrown if the given PDF cannot be normalised, i.e. if the sum of the probabilities is zero.
     */
    error ConstantZeroPDF();

    /**
     * @notice The number of realisations for each trait.
     */
    uint256[] private _numPerTrait;

    /**
     * @notice The cumulative probability distributions for each trait.
     * @dev Indexed by traitId, distributionVersion, sample.
     * @dev The distributionVersion is intended to allow having multiple "versions" of the probability distributions.
     */
    uint64[][][] private _cdfs;

    constructor(uint256[] memory numPerTrait) {
        _numPerTrait = numPerTrait;
        for (uint256 i; i < numPerTrait.length; ++i) {
            _cdfs.push(new uint64[][](0));
        }
        assert(_cdfs.length == numPerTrait.length);
    }

    /**
     * @notice Adds a new probability distribution for a given trait.
     */
    function _pushProbabilities(uint256 traitId, uint64[] memory pdf) internal {
        if (traitId >= _numPerTrait.length) {
            revert InvalidTraitId(traitId);
        }

        if (pdf.length != _numPerTrait[traitId]) {
            revert IncorrectPDFLength(pdf.length, traitId, _numPerTrait[traitId]);
        }

        uint64[] memory cdf = pdf.computeCDF();
        if (cdf[cdf.length - 1] == 0) {
            revert ConstantZeroPDF();
        }
        _cdfs[traitId].push(cdf);
    }

    /**
     * @notice Returns the version/index of the latest probability distribution for a given trait.
     */
    function _latestDistributionVersion(uint256 traitId) internal view returns (uint256) {
        return _cdfs[traitId].length - 1;
    }

    /**
     * @notice Returns the version/index of the probability distribution that is used for a given token and trait.
     * @dev This function is intended to be overridden by inheriting contracts.
     */
    function _distributionVersion(uint256 tokenId, uint256 traitId) internal view virtual returns (uint256);

    /**
     * @inheritdoc StochasticSampler
     * @dev Returns the probability distribution that is index by `_distributionVersion`.
     */
    function _cdf(uint256 tokenId, uint256 traitId) internal view virtual override returns (uint64[] memory) {
        if (traitId >= _numPerTrait.length) {
            revert InvalidTraitId(traitId);
        }
        return _cdfs[traitId][_distributionVersion(tokenId, traitId)];
    }
}

/**
 * @notice A contract that can sample token traits from discrete probability distributions using entropy provided by the
 * EntropyOracle.
 */
abstract contract StochasticSamplerWithOracle is StochasticSampler {
    /**
     * @notice The entropy oracle.
     */
    IEntropyOracle public entropyOracle;

    constructor(IEntropyOracle entropyOracle_) {
        entropyOracle = entropyOracle_;
    }

    /**
     * @inheritdoc StochasticSampler
     * @dev Uses the entropy of the block at `_revealBlockNumber(tokenId)`.
     */
    function _seed(uint256 tokenId) internal view virtual override returns (bytes32, bool) {
        bytes32 entropy = entropyOracle.blockEntropy(_revealBlockNumber(tokenId));
        return (keccak256(abi.encode(entropy, tokenId)), entropy != 0);
    }

    /**
     * @notice The blocknumber at which a given token will be revealed.
     * @dev The entropy provided by `entropyOracle` for this block will be used as seed for trait sampling.
     */
    function _revealBlockNumber(uint256 tokenId) internal view virtual returns (uint256);
}
Contract Source Code
File 38 of 38: Strings.sol
Settings
{
  "compilationTarget": {
    "src/MythicsEgg.sol": "MythicsEgg"
  },
  "evmVersion": "london",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 9999
  },
  "remappings": [
    ":@divergencetech/ethier/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/ethier_0-55-0/",
    ":@openzeppelin/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/openzeppelin-contracts_4-8-1/",
    ":ERC721A/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/ERC721A_4-2-3/contracts/",
    ":ERC721A_root/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/ERC721A_4-2-3/",
    ":delegation-registry/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/delegation-registry_2d1a158b/src/",
    ":delegation-registry_root/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/delegation-registry_2d1a158b/",
    ":ds-test/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/ds-test_013e6c64/src/",
    ":ds-test_root/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/ds-test_013e6c64/",
    ":erc721a/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/ERC721A_4-2-3/",
    ":ethier/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/ethier_0-55-0/contracts/",
    ":ethier_root/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/ethier_0-55-0/",
    ":forge-std/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/forge-std_1-4-0/src/",
    ":openzeppelin-contracts/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/openzeppelin-contracts_4-8-1/contracts/",
    ":openzeppelin-contracts/contracts/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/openzeppelin-contracts_4-8-1/contracts/",
    ":openzeppelin-contracts_root/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/openzeppelin-contracts_4-8-1/",
    ":operator-filter-registry/src/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/operator-filter-registry_1-4-1/src/",
    ":operator-filter-registry_root/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/operator-filter-registry_1-4-1/",
    ":proof/constants/=/home/dave/proof/proof-seller/contracts/constants/src/",
    ":proof/entropy/=/home/dave/proof/proof-seller/contracts/entropy/",
    ":proof/redemption/=/home/dave/proof/proof-seller/contracts/redemption/src/",
    ":proof/sellers/=/home/dave/proof/proof-seller/contracts/sellers/src/"
  ]
}
ABI
[{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"steerer","type":"address"},{"internalType":"address payable","name":"secondaryReceiver","type":"address"},{"internalType":"contract IEntropyOracle","name":"oracle","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"requested","type":"uint256"},{"internalType":"uint256","name":"numLeft","type":"uint256"}],"name":"ActivatingTooManyEggs","type":"error"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"ConstantZeroPDF","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"EggAlreadyActivated","type":"error"},{"inputs":[{"internalType":"uint256","name":"gotLength","type":"uint256"},{"internalType":"uint256","name":"traitId","type":"uint256"},{"internalType":"uint256","name":"wantLength","type":"uint256"}],"name":"IncorrectPDFLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"traitId","type":"uint256"}],"name":"InvalidTraitId","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NonexistentEgg","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"OperatorNotAllowed","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"RedeemerCallerNotAllowedToSpendVoucher","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"EggActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"MetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"AUTHORISED_SELLER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_STEERING_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NUM_EGG_TYPES","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPERATOR_FILTER_REGISTRY","outputs":[{"internalType":"contract IOperatorFilterRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REDEEMER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"activate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"activated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"cdata","type":"bytes"}],"name":"callOperatorFilterRegistry","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"eggType","outputs":[{"internalType":"enum MythicEggSampler.EggType","name":"","type":"uint8"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emitMetadataUpdateForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"entropyOracle","outputs":[{"internalType":"contract IEntropyOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint64","name":"num","type":"uint64"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"handleSale","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockRedeemers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockSellers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"samplingParams","outputs":[{"components":[{"internalType":"uint64","name":"revealBlockNumber","type":"uint64"},{"internalType":"uint16","name":"distributionVersion","type":"uint16"},{"internalType":"uint128","name":"mixHash","type":"uint128"}],"internalType":"struct MythicEggSampler.SamplingParams","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseTokenURI_","type":"string"}],"name":"setBaseTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint96","name":"basisPoints","type":"uint96"}],"name":"setDefaultRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64[3]","name":"pdf","type":"uint64[3]"}],"name":"setEggProbabilities","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IEntropyOracle","name":"newOracle","type":"address"}],"name":"setEntropyOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"maxNumActivationsPerDay","type":"uint32"}],"name":"setMaxNumActivationsPerDay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"tokenInfos","outputs":[{"components":[{"internalType":"bool","name":"revealed","type":"bool"},{"internalType":"enum MythicEggSampler.EggType","name":"eggType","type":"uint8"},{"internalType":"bool","name":"activated","type":"bool"}],"internalType":"struct MythicsEgg.TokenInfo[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]