编译器
0.8.19+commit.7dd6d404
文件 1 的 82:AccessControl.sol
文件 2 的 82:AccessControlEnumerable.sol
文件 3 的 82:AccessControlEnumerableUpgradeable.sol
文件 4 的 82:AccessControlPausable.sol
文件 5 的 82:AccessControlUpgradeable.sol
文件 7 的 82:AddressUpgradeable.sol
文件 8 的 82:BaseRedeemableToken.sol
文件 9 的 82:BaseSellable.sol
文件 10 的 82:BaseSellableUpgradeable.sol
pragma solidity ^0.8.15;
import {Initializable} from "openzeppelin-contracts-upgradeable/proxy/utils/Initializable.sol";
import {ISellable} from "proof/sellers/interfaces/ISellable.sol";
import {
AccessControlEnumerableUpgradeable,
SteerableAccessControlEnumerableUpgradeable
} from "./SteerableAccessControlEnumerableUpgradeable.sol";
abstract contract BaseSellableUpgradeable is Initializable, ISellable, SteerableAccessControlEnumerableUpgradeable {
bytes32 public constant AUTHORISED_SELLER_ROLE = keccak256("AUTHORISED_SELLER_ROLE");
function __BaseSellable_init() internal onlyInitializing {
__AccessControlEnumerable_init();
__BaseSellable_init_unchained();
}
function __BaseSellable_init_unchained() internal onlyInitializing {
_setRoleAdmin(AUTHORISED_SELLER_ROLE, DEFAULT_STEERING_ROLE);
}
function handleSale(address to, uint64 num, bytes calldata data)
external
payable
onlyRole(AUTHORISED_SELLER_ROLE)
{
_handleSale(to, num, data);
}
function _handleSale(address to, uint64 num, bytes calldata data) internal virtual;
function _revokeAllSellers() internal {
uint256 num = getRoleMemberCount(AUTHORISED_SELLER_ROLE);
for (uint256 i = 0; i < num; i++) {
address seller = getRoleMember(AUTHORISED_SELLER_ROLE, 0);
_revokeRole(AUTHORISED_SELLER_ROLE, seller);
}
}
}
文件 11 的 82:BaseTokenURI.sol
文件 13 的 82:CallbackerWithAccessControl.sol
文件 16 的 82:ContextUpgradeable.sol
文件 17 的 82:DefaultOperatorFilterer.sol
文件 18 的 82:DefaultOperatorFiltererUpgradeable.sol
文件 20 的 82:ERC165Upgradeable.sol
文件 21 的 82:ERC1967UpgradeUpgradeable.sol
文件 23 的 82:ERC2981Upgradeable.sol
文件 26 的 82:ERC721ACommon.sol
文件 27 的 82:ERC721PausableUpgradeable.sol
文件 28 的 82:ERC721RoyaltyUpgradeable.sol
文件 29 的 82:ERC721Upgradeable.sol
文件 30 的 82:EnumerableSet.sol
文件 31 的 82:EnumerableSetUpgradeable.sol
文件 32 的 82:IAccessControl.sol
文件 33 的 82:IAccessControlEnumerable.sol
文件 34 的 82:IAccessControlEnumerableUpgradeable.sol
文件 35 的 82:IAccessControlUpgradeable.sol
文件 36 的 82:IBeaconUpgradeable.sol
文件 38 的 82:IERC165Upgradeable.sol
文件 39 的 82:IERC1967Upgradeable.sol
文件 41 的 82:IERC2981Upgradeable.sol
文件 44 的 82:IERC721MetadataUpgradeable.sol
文件 45 的 82:IERC721ReceiverUpgradeable.sol
文件 46 的 82:IERC721Upgradeable.sol
文件 47 的 82:IEntropyOracle.sol
文件 48 的 82:IOperatorFilterRegistry.sol
文件 49 的 82:IRedeemableToken.sol
文件 51 的 82:Initializable.sol
文件 53 的 82:MathUpgradeable.sol
文件 54 的 82:MythicEggActivator.sol
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 {
event EggActivated(uint256 indexed tokenId);
}
abstract contract MythicEggActivator is ERC4906, MythicsEggErrors, MythicEggActivatorEvents {
using BitMaps for BitMaps.BitMap;
error EggAlreadyActivated(uint256);
error ActivatingTooManyEggs(uint256 requested, uint256 numLeft);
BitMaps.BitMap private _activated;
uint32 internal _maxNumActivationsPerDay = 50;
uint32 private _lastActivationDay;
uint32 private _numActivatedToday;
function _currentDay() private view returns (uint32) {
return uint32(block.timestamp / (1 days));
}
function _setMaxNumActivationsPerDay(uint32 maxNumActivationsPerDay) internal {
_maxNumActivationsPerDay = maxNumActivationsPerDay;
}
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);
}
function activated(uint256 tokenId) public view returns (bool) {
if (!_exists(tokenId)) {
revert NonexistentEgg(tokenId);
}
return _activated.get(tokenId);
}
function _exists(uint256 tokenId) internal view virtual returns (bool);
}
文件 55 的 82:MythicEggSampler.sol
pragma solidity ^0.8.15;
import {IEntropyOracle} from "proof/entropy/IEntropyOracle.sol";
import {MythicsEggErrors} from "./MythicsEggErrors.sol";
import {
StochasticSampler, StochasticSamplerWithCDFStorage, StochasticSamplerWithOracle
} from "./StochasticSampling.sol";
abstract contract MythicEggSampler is StochasticSamplerWithCDFStorage, StochasticSamplerWithOracle, MythicsEggErrors {
enum EggType {
Stone,
Runic,
Legendary
}
uint8 public constant NUM_EGG_TYPES = 3;
uint8 private constant _EGG_TYPE_TRAIT_ID = 0;
struct SamplingParams {
uint64 revealBlockNumber;
uint16 distributionVersion;
uint128 mixHash;
}
mapping(uint256 => SamplingParams) private _samplingParams;
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)
{}
function samplingParams(uint256 tokenId) public view returns (SamplingParams memory) {
if (!_exists(tokenId)) {
revert NonexistentEgg(tokenId);
}
return _samplingParams[tokenId];
}
function _distributionVersion(uint256 tokenId, uint256 traitId) internal view virtual override returns (uint256) {
assert(traitId == _EGG_TYPE_TRAIT_ID);
return _samplingParams[tokenId].distributionVersion;
}
function _revealBlockNumber(uint256 tokenId) internal view virtual override returns (uint256) {
return _samplingParams[tokenId].revealBlockNumber;
}
function _registerForSampling(uint256 tokenId) internal {
uint256 revealBlockNumber = block.number;
_samplingParams[tokenId] = SamplingParams({
revealBlockNumber: uint64(revealBlockNumber),
distributionVersion: uint16(_latestDistributionVersion(_EGG_TYPE_TRAIT_ID)),
mixHash: uint128(uint256(keccak256(abi.encode(block.prevrandao))))
});
entropyOracle.requestEntropy(revealBlockNumber);
}
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);
}
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);
}
function eggType(uint256 tokenId) public view returns (EggType, bool) {
(uint256 sample, bool revealed) = _sampleTrait(tokenId, _EGG_TYPE_TRAIT_ID);
return (EggType(sample), revealed);
}
function _exists(uint256 tokenId) internal view virtual returns (bool);
}
文件 56 的 82:MythicsBase.sol
pragma solidity ^0.8.15;
import {Initializable} from "openzeppelin-contracts-upgradeable/proxy/utils/Initializable.sol";
import {UUPSUpgradeable} from "openzeppelin-contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {ERC721Upgradeable} from "openzeppelin-contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import {ERC721RoyaltyUpgradeable} from
"openzeppelin-contracts-upgradeable/token/ERC721/extensions/ERC721RoyaltyUpgradeable.sol";
import {ERC721PausableUpgradeable} from
"openzeppelin-contracts-upgradeable/token/ERC721/extensions/ERC721PausableUpgradeable.sol";
import {
SteerableAccessControlEnumerableUpgradeable,
AccessControlEnumerableUpgradeable
} from "./SteerableAccessControlEnumerableUpgradeable.sol";
contract MythicsBase is
Initializable,
SteerableAccessControlEnumerableUpgradeable,
ERC721Upgradeable,
ERC721RoyaltyUpgradeable,
ERC721PausableUpgradeable,
UUPSUpgradeable
{
constructor() {
_disableInitializers();
}
function __MythicsBase_init() internal onlyInitializing {
__AccessControlEnumerable_init();
__ERC721_init("Moonbirds: Mythics", "MYTHICS");
__ERC721Royalty_init();
__ERC721Pausable_init();
__UUPSUpgradeable_init();
}
function __MythicsBase_init_unchained() internal onlyInitializing {}
function _authorizeUpgrade(address newImplementation) internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {}
function _beforeTokenTransfer(address from, address to, uint256 firstTokenId, uint256 batchSize)
internal
virtual
override(ERC721Upgradeable, ERC721PausableUpgradeable)
{
ERC721PausableUpgradeable._beforeTokenTransfer(from, to, firstTokenId, batchSize);
}
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override(ERC721Upgradeable, AccessControlEnumerableUpgradeable, ERC721RoyaltyUpgradeable)
returns (bool)
{
return ERC721Upgradeable.supportsInterface(interfaceId)
|| ERC721RoyaltyUpgradeable.supportsInterface(interfaceId)
|| AccessControlEnumerableUpgradeable.supportsInterface(interfaceId);
}
function _burn(uint256 tokenId) internal virtual override(ERC721Upgradeable, ERC721RoyaltyUpgradeable) {
ERC721RoyaltyUpgradeable._burn(tokenId);
}
}
文件 57 的 82:MythicsEgg.sol
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";
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)]);
}
struct TokenInfo {
bool revealed;
EggType eggType;
bool activated;
}
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;
}
function setEggProbabilities(uint64[NUM_EGG_TYPES] memory pdf) external onlyRole(DEFAULT_STEERING_ROLE) {
_setEggProbabilities(pdf);
}
function setEntropyOracle(IEntropyOracle newOracle) external onlyRole(DEFAULT_STEERING_ROLE) {
entropyOracle = newOracle;
}
function setMaxNumActivationsPerDay(uint32 maxNumActivationsPerDay) external onlyRole(DEFAULT_STEERING_ROLE) {
_setMaxNumActivationsPerDay(maxNumActivationsPerDay);
}
function activate(uint256[] calldata tokenIds) external onlyRole(DEFAULT_STEERING_ROLE) {
_activate(tokenIds);
}
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);
}
}
文件 58 的 82:MythicsEggErrors.sol
pragma solidity ^0.8.15;
interface MythicsEggErrors {
error NonexistentEgg(uint256 tokenId);
}
文件 59 的 82:MythicsEggRedeemer.sol
pragma solidity >=0.8.0 <0.9.0;
import {IRedeemableToken} from "proof/redemption/interfaces/IRedeemableToken.sol";
import {MythicsV1} from "./MythicsV1.sol";
import {MythicsEgg, MythicEggSampler} from "../Egg/MythicsEgg.sol";
import {ISellable, ImmutableSellableCallbacker, SellableCallbacker} from "proof/sellers/base/SellableCallbacker.sol";
import {Seller} from "proof/sellers/base/Seller.sol";
import {RedeemableTokenRedeemer} from "proof/redemption/RedeemableTokenRedeemer.sol";
library MythicsEggRedemptionLib {
struct PurchasePayload {
uint256 eggId;
MythicEggSampler.EggType eggType;
}
function encode(PurchasePayload[] memory redemptions) internal pure returns (bytes memory) {
return abi.encode(redemptions);
}
function decode(bytes memory data) internal pure returns (PurchasePayload[] memory) {
return abi.decode(data, (PurchasePayload[]));
}
}
contract MythicsEggRedeemer is Seller, ImmutableSellableCallbacker, RedeemableTokenRedeemer {
using MythicsEggRedemptionLib for MythicsEggRedemptionLib.PurchasePayload[];
error EggNotActivated(uint256 eggId);
error EggNotRevealed(uint256 eggId);
MythicsEgg public immutable eggs;
constructor(ISellable mythics, MythicsEgg eggs_) ImmutableSellableCallbacker(mythics) {
eggs = eggs_;
}
function redeem(uint256[] calldata eggIds) external {
MythicsEggRedemptionLib.PurchasePayload[] memory payloads =
new MythicsEggRedemptionLib.PurchasePayload[](eggIds.length);
for (uint256 i = 0; i < eggIds.length; ++i) {
if (!eggs.activated(eggIds[i])) {
revert EggNotActivated(eggIds[i]);
}
(MythicEggSampler.EggType eggType, bool revealed) = eggs.eggType(eggIds[i]);
if (!revealed) {
revert EggNotRevealed(eggIds[i]);
}
_redeem(eggs, eggIds[i]);
payloads[i] = MythicsEggRedemptionLib.PurchasePayload({eggId: eggIds[i], eggType: eggType});
}
_purchase(msg.sender, uint64(eggIds.length), 0, payloads.encode());
}
}
文件 60 的 82:MythicsV1.sol
pragma solidity ^0.8.15;
import {DefaultOperatorFiltererUpgradeable} from
"operator-filter-registry/src/upgradeable/DefaultOperatorFiltererUpgradeable.sol";
import {MythicsBase} from "./MythicsBase.sol";
import {
BaseSellableUpgradeable,
AccessControlEnumerableUpgradeable,
SteerableAccessControlEnumerableUpgradeable
} from "./BaseSellableUpgradeable.sol";
import {Oddsoleum} from "../Oddsoleum/Oddsoleum.sol";
import {MythicsEggRedeemer, MythicsEggRedemptionLib} from "./MythicsEggRedeemer.sol";
import {MythicEggSampler} from "../Egg/MythicEggSampler.sol";
library MythicsStorage {
struct OpenChoice {
address chooser;
uint8 numChoices;
}
struct FinalChoice {
uint8 numChoicesMinusOne;
uint8 choice;
}
bytes32 internal constant STORAGE_SLOT = keccak256("Mythics.storage.location");
struct Layout {
uint256 numMinted;
string baseTokenURI;
uint64 numPurchases;
MythicsEggRedeemer eggRedeemer;
mapping(uint256 purchaseId => OpenChoice) openChoices;
mapping(uint256 tokenId => FinalChoice) finalChoices;
}
function layout() internal pure returns (Layout storage l) {
bytes32 slot = STORAGE_SLOT;
assembly {
l.slot := slot
}
}
}
interface MythicsV1Events {
event RandomiseMythics(uint256 indexed purchaseId, address indexed chooser, uint8 indexed numChoices);
event MythicChosen(uint256 indexed purchaseId, address indexed chooser, uint256 indexed tokenId, uint8 choice);
}
contract MythicsV1 is MythicsBase, BaseSellableUpgradeable, DefaultOperatorFiltererUpgradeable, MythicsV1Events {
error ChoiceOutOfBounds(uint256 purchaseId, uint8 numChoices, uint8 choice);
error PurchaseChoiceAlreadyLockedIn(uint256 purchaseId);
error CallerIsNotChooser(uint256 purchaseId, address chooser, address caller);
struct InitArgsV1 {
address mainAdmin;
address secondaryAdmin;
address steerer;
string baseTokenURI;
MythicsEggRedeemer eggRedeemer;
address royaltyReceiver;
}
function initializeV1(InitArgsV1 memory init) public virtual reinitializer(2) {
__MythicsBase_init();
__BaseSellable_init();
__DefaultOperatorFilterer_init();
_grantRole(DEFAULT_ADMIN_ROLE, init.mainAdmin);
_grantRole(DEFAULT_ADMIN_ROLE, init.secondaryAdmin);
_changeAdmin(init.mainAdmin);
_grantRole(DEFAULT_STEERING_ROLE, init.steerer);
MythicsStorage.layout().baseTokenURI = init.baseTokenURI;
MythicsStorage.layout().eggRedeemer = init.eggRedeemer;
_setDefaultRoyalty(init.royaltyReceiver, 500);
}
function pause() public virtual onlyRole(DEFAULT_STEERING_ROLE) {
_pause();
}
function unpause() public virtual onlyRole(DEFAULT_STEERING_ROLE) {
_unpause();
}
function _baseURI() internal view virtual override returns (string memory) {
return MythicsStorage.layout().baseTokenURI;
}
function setBaseTokenURI(string calldata newBaseTokenURI) public virtual onlyRole(DEFAULT_STEERING_ROLE) {
MythicsStorage.layout().baseTokenURI = newBaseTokenURI;
}
function totalSupply() public view virtual returns (uint256) {
return MythicsStorage.layout().numMinted;
}
function _mint(address to, uint256 tokenId) internal virtual override {
unchecked {
MythicsStorage.layout().numMinted++;
}
super._mint(to, tokenId);
}
function _mintNextTokenId(address to) internal virtual returns (uint256) {
uint256 tokenId = MythicsStorage.layout().numMinted;
_mint(to, tokenId);
return tokenId;
}
function _trackPurchaseAndRandomiseMythics(address chooser, uint8 numChoices) internal returns (uint256) {
assert(numChoices > 0);
MythicsStorage.Layout storage layout = MythicsStorage.layout();
uint256 purchaseId = layout.numPurchases++;
if (numChoices > 1) {
layout.openChoices[purchaseId] = MythicsStorage.OpenChoice({chooser: chooser, numChoices: numChoices});
}
emit RandomiseMythics(purchaseId, chooser, numChoices);
return purchaseId;
}
function _setChoice(address chooser, uint256 purchaseId, uint256 tokenId, uint8 numChoices, uint8 choice)
internal
{
assert(numChoices > 0);
MythicsStorage.Layout storage layout = MythicsStorage.layout();
if (choice >= numChoices) {
revert ChoiceOutOfBounds(purchaseId, numChoices, choice);
}
if (numChoices > 1) {
delete layout.openChoices[purchaseId];
}
layout.finalChoices[tokenId] = MythicsStorage.FinalChoice({numChoicesMinusOne: numChoices - 1, choice: choice});
emit MythicChosen(purchaseId, chooser, tokenId, choice);
}
function _mintWithoutChoice(address to) internal {
uint8 numChoices = 1;
uint256 purchaseId = _trackPurchaseAndRandomiseMythics(to, numChoices);
uint256 tokenId = _mintNextTokenId(to);
_setChoice(to, purchaseId, tokenId, numChoices, 0);
}
struct ChoiceSubmission {
uint256 purchaseId;
uint8 choice;
}
function _chooseAndMint(ChoiceSubmission calldata submission) internal {
MythicsStorage.Layout storage layout = MythicsStorage.layout();
MythicsStorage.OpenChoice memory openChoice = layout.openChoices[submission.purchaseId];
if (openChoice.chooser == address(0)) {
revert PurchaseChoiceAlreadyLockedIn(submission.purchaseId);
}
if (msg.sender != openChoice.chooser) {
revert CallerIsNotChooser(submission.purchaseId, openChoice.chooser, msg.sender);
}
uint8 numChoices = openChoice.numChoices;
uint256 tokenId = _mintNextTokenId(msg.sender);
_setChoice(msg.sender, submission.purchaseId, tokenId, numChoices, submission.choice);
}
function chooseAndMint(ChoiceSubmission[] calldata choices) public whenNotPaused {
for (uint256 i; i < choices.length; ++i) {
_chooseAndMint(choices[i]);
}
}
function _handleSale(address to, uint64 num, bytes calldata data) internal virtual override whenNotPaused {
if (msg.sender != address(MythicsStorage.layout().eggRedeemer)) {
for (uint256 i; i < num; ++i) {
_mintWithoutChoice(to);
}
return;
}
MythicsEggRedemptionLib.PurchasePayload[] memory payloads = MythicsEggRedemptionLib.decode(data);
assert(num == payloads.length);
for (uint256 i; i < num; ++i) {
MythicEggSampler.EggType eggType = payloads[i].eggType;
if (eggType == MythicEggSampler.EggType.Stone) {
_mintWithoutChoice(to);
continue;
}
assert(uint8(eggType) <= 2);
uint8 numChoices = uint8(eggType) + 1;
_trackPurchaseAndRandomiseMythics(to, numChoices);
}
}
function setEggRedeemer(MythicsEggRedeemer newRedeemer) public onlyRole(DEFAULT_STEERING_ROLE) {
MythicsStorage.layout().eggRedeemer = newRedeemer;
}
function eggRedeemer() public view returns (MythicsEggRedeemer) {
return MythicsStorage.layout().eggRedeemer;
}
function setDefaultRoyalty(address receiver, uint96 feeBasisPoints)
public
virtual
onlyRole(DEFAULT_STEERING_ROLE)
{
_setDefaultRoyalty(receiver, feeBasisPoints);
}
function supportsInterface(bytes4 interfaceId)
public
view
virtual
override(MythicsBase, AccessControlEnumerableUpgradeable)
returns (bool)
{
return MythicsBase.supportsInterface(interfaceId);
}
function setApprovalForAll(address operator, bool approved) public override onlyAllowedOperatorApproval(operator) {
super.setApprovalForAll(operator, approved);
}
function approve(address operator, uint256 tokenId) public override onlyAllowedOperatorApproval(operator) {
super.approve(operator, tokenId);
}
function transferFrom(address from, address to, uint256 tokenId) public override onlyAllowedOperator(from) {
super.transferFrom(from, to, tokenId);
}
function safeTransferFrom(address from, address to, uint256 tokenId) public override onlyAllowedOperator(from) {
super.safeTransferFrom(from, to, tokenId);
}
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data)
public
override
onlyAllowedOperator(from)
{
super.safeTransferFrom(from, to, tokenId, data);
}
}
文件 61 的 82:NonRollingRateLimited.sol
pragma solidity ^0.8.15;
contract NonRollingRateLimited {
error ExceedingRateLimit(uint256 requested, uint256 numLeft);
uint64 private immutable _periodLength;
uint64 private _lastPeriod;
uint64 private __maxActionsPerPeriod;
uint64 private __performedCurrentPeriod;
constructor(uint64 maxActionsPerPeriod, uint64 periodLength) {
_periodLength = periodLength;
_setMaxActionsPerPeriod(maxActionsPerPeriod);
}
function _currentPeriod() private view returns (uint64) {
return uint64(block.timestamp / _periodLength);
}
function _setMaxActionsPerPeriod(uint64 maxActionsPerPeriod) internal {
__maxActionsPerPeriod = maxActionsPerPeriod;
}
function _maxActionsPerPeriod() internal view returns (uint64) {
return __maxActionsPerPeriod;
}
function _checkAndTrackRateLimit(uint64 requested) internal {
uint64 performed = _performedCurrentPeriod();
uint64 left = __maxActionsPerPeriod - performed;
if (requested > left) {
revert ExceedingRateLimit(requested, left);
}
__performedCurrentPeriod = performed + requested;
_lastPeriod = _currentPeriod();
}
function _performedCurrentPeriod() internal view returns (uint64) {
if (_currentPeriod() > _lastPeriod) {
return 0;
}
return __performedCurrentPeriod;
}
}
文件 62 的 82:Oddsoleum.sol
pragma solidity ^0.8.15;
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {SettableCallbackerWithAccessControl} from "proof/sellers/presets/CallbackerWithAccessControl.sol";
import {Seller} from "proof/sellers/base/Seller.sol";
import {MythicEggSampler} from "../Egg/MythicEggSampler.sol";
import {NonRollingRateLimited} from "./NonRollingRateLimited.sol";
interface OddsoleumEvents {
event OdditySacrificed(address indexed owner, uint256 tokenId);
event CannotBurnIneligibleOddity(uint256 indexed tokenId, bool queued, bool approved);
}
contract Oddsoleum is Seller, SettableCallbackerWithAccessControl, OddsoleumEvents, NonRollingRateLimited {
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
address public constant BURN_ADDRESS = 0x000000000000000000000000000000000000dEaD;
IERC721 public immutable oddities;
mapping(address owner => mapping(uint256 tokenId => bool)) private _queued;
constructor(address admin, address steerer, IERC721 oddities_)
SettableCallbackerWithAccessControl(admin, steerer)
NonRollingRateLimited(50, 1 days)
{
_setRoleAdmin(BURNER_ROLE, DEFAULT_STEERING_ROLE);
oddities = oddities_;
}
function addToQueue(uint256[] calldata tokenIds) external {
for (uint256 i = 0; i < tokenIds.length; ++i) {
_queued[msg.sender][tokenIds[i]] = true;
}
}
function removeFromQueue(uint256[] calldata tokenIds) external {
for (uint256 i = 0; i < tokenIds.length; ++i) {
_queued[msg.sender][tokenIds[i]] = false;
}
}
function queued(uint256[] calldata tokenIds) public view returns (bool[] memory) {
bool[] memory queued_ = new bool[](tokenIds.length);
for (uint256 i = 0; i < tokenIds.length; ++i) {
address owner = oddities.ownerOf(tokenIds[i]);
queued_[i] = _queued[owner][tokenIds[i]];
}
return queued_;
}
function burnable(uint256[] calldata tokenIds) external view returns (bool[] memory) {
bool[] memory burnable_ = new bool[](tokenIds.length);
for (uint256 i = 0; i < tokenIds.length; ++i) {
address owner = oddities.ownerOf(tokenIds[i]);
burnable_[i] = _burnable(owner, tokenIds[i]);
}
return burnable_;
}
function _burnable(address owner, uint256 tokenId) internal view returns (bool) {
return _queued[owner][tokenId] && _approved(owner, tokenId);
}
function _approved(address owner, uint256 tokenId) internal view returns (bool) {
return (oddities.isApprovedForAll(owner, address(this)) || oddities.getApproved(tokenId) == address(this));
}
function _burn(address owner, uint256 tokenId) internal returns (bool) {
bool queued_ = _queued[owner][tokenId];
bool approved = _approved(owner, tokenId);
if (!(queued_ && approved)) {
emit CannotBurnIneligibleOddity(tokenId, queued_, approved);
return false;
}
oddities.transferFrom(owner, BURN_ADDRESS, tokenId);
emit OdditySacrificed(owner, tokenId);
return true;
}
function _sacrifice(uint256 tokenId) internal returns (bool) {
address owner = oddities.ownerOf(tokenId);
bool burned = _burn(owner, tokenId);
if (!burned) {
return false;
}
_purchase(owner, 1, 0, "");
return true;
}
function sacrifice(uint256[] calldata tokenIds) external onlyRole(BURNER_ROLE) {
uint64 numSacrificed;
for (uint256 i = 0; i < tokenIds.length; ++i) {
bool sacrificed = _sacrifice(tokenIds[i]);
unchecked {
if (sacrificed) {
++numSacrificed;
}
}
}
_checkAndTrackRateLimit(numSacrificed);
}
function setMaxSacrificesPerPeriod(uint32 maxSacrificesPerPeriod) external onlyRole(DEFAULT_STEERING_ROLE) {
_setMaxActionsPerPeriod(maxSacrificesPerPeriod);
}
}
文件 63 的 82:OperatorFilterOS.sol
文件 64 的 82:OperatorFilterer.sol
文件 65 的 82:OperatorFiltererUpgradeable.sol
文件 67 的 82:PausableUpgradeable.sol
文件 68 的 82:PurchaseExecuter.sol
文件 69 的 82:RedeemableERC721ACommon.sol
文件 70 的 82:RedeemableTokenRedeemer.sol
文件 71 的 82:ReentrancyGuard.sol
文件 72 的 82:SellableCallbacker.sol
文件 73 的 82:SellableERC721ACommon.sol
文件 75 的 82:SignedMathUpgradeable.sol
文件 76 的 82:SteerableAccessControlEnumerableUpgradeable.sol
pragma solidity >=0.8.0 <0.9.0;
import {AccessControlEnumerableUpgradeable} from
"openzeppelin-contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol";
contract SteerableAccessControlEnumerableUpgradeable is AccessControlEnumerableUpgradeable {
bytes32 public constant DEFAULT_STEERING_ROLE = keccak256("DEFAULT_STEERING_ROLE");
}
文件 77 的 82:StochasticSampling.sol
pragma solidity ^0.8.15;
import {IEntropyOracle} from "proof/entropy/IEntropyOracle.sol";
library StochasticSamplingLib {
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;
}
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;
}
}
assert(false);
return 0;
}
}
abstract contract StochasticSampler {
function _seed(uint256 tokenId) internal view virtual returns (bytes32, bool);
function _cdf(uint256 tokenId, uint256 traitId) internal view virtual returns (uint64[] memory);
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);
}
}
abstract contract StochasticSamplerWithCDFStorage is StochasticSampler {
using StochasticSamplingLib for uint64[];
error InvalidTraitId(uint256 traitId);
error IncorrectPDFLength(uint256 gotLength, uint256 traitId, uint256 wantLength);
error ConstantZeroPDF();
uint256[] private _numPerTrait;
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);
}
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);
}
function _latestDistributionVersion(uint256 traitId) internal view returns (uint256) {
return _cdfs[traitId].length - 1;
}
function _distributionVersion(uint256 tokenId, uint256 traitId) internal view virtual returns (uint256);
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)];
}
}
abstract contract StochasticSamplerWithOracle is StochasticSampler {
IEntropyOracle public entropyOracle;
constructor(IEntropyOracle entropyOracle_) {
entropyOracle = entropyOracle_;
}
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);
}
function _revealBlockNumber(uint256 tokenId) internal view virtual returns (uint256);
}
文件 78 的 82:StorageSlotUpgradeable.sol
文件 80 的 82:StringsUpgradeable.sol
文件 81 的 82:UUPSUpgradeable.sol
文件 82 的 82:draft-IERC1822Upgradeable.sol
{
"compilationTarget": {
"src/Mythics/MythicsEggRedeemer.sol": "MythicsEggRedeemer"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"appendCBOR": false,
"bytecodeHash": "none"
},
"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/",
":@openzeppelin/contracts-upgradeable/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/openzeppelin-contracts-upgradeable_4-9-0/",
":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/",
":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-5-6/src/",
":forge-std_root/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/forge-std_1-5-6/",
":openzeppelin-contracts-upgradeable/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/openzeppelin-contracts-upgradeable_4-9-0/contracts/",
":openzeppelin-contracts-upgradeable/contracts/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/openzeppelin-contracts-upgradeable_4-9-0/contracts/",
":openzeppelin-contracts-upgradeable_root/=/home/dave/.cache/bazel/_bazel_dave/b9a57168317213f9241a484d2ee2d038/external/openzeppelin-contracts-upgradeable_4-9-0/",
":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/archive/=/home/dave/proof/proof-seller/contracts/archive/src/",
":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/"
]
}
[{"inputs":[{"internalType":"contract ISellable","name":"mythics","type":"address"},{"internalType":"contract MythicsEgg","name":"eggs_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"CallbackFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"eggId","type":"uint256"}],"name":"EggNotActivated","type":"error"},{"inputs":[{"internalType":"uint256","name":"eggId","type":"uint256"}],"name":"EggNotRevealed","type":"error"},{"inputs":[{"internalType":"contract IRedeemableToken","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"RedeemableCallbackFailed","type":"error"},{"inputs":[],"name":"eggs","outputs":[{"internalType":"contract MythicsEgg","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"eggIds","type":"uint256[]"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sellable","outputs":[{"internalType":"contract ISellable","name":"","type":"address"}],"stateMutability":"view","type":"function"}]