-
Notifications
You must be signed in to change notification settings - Fork 34
/
input.json
1 lines (1 loc) · 191 KB
/
input.json
1
{"language":"Solidity","sources":{"contracts/core/interfaces/IMetadataModule.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\n/**\n * @title IMetadataModule\n * @notice The interface for custom metadata modules.\n */\ninterface IMetadataModule {\n /**\n * @dev When implemented, SoundEdition's `tokenURI` redirects execution to this `tokenURI`.\n * @param tokenId The token ID to retrieve the token URI for.\n * @return The token URI string.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n"},"contracts/core/interfaces/ISoundEditionV1_2.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport { IERC721AUpgradeable } from \"chiru-labs/ERC721A-Upgradeable/IERC721AUpgradeable.sol\";\nimport { IERC2981Upgradeable } from \"openzeppelin-upgradeable/interfaces/IERC2981Upgradeable.sol\";\nimport { IERC165Upgradeable } from \"openzeppelin-upgradeable/utils/introspection/IERC165Upgradeable.sol\";\n\nimport { IMetadataModule } from \"./IMetadataModule.sol\";\n\n/**\n * @dev The information pertaining to this edition.\n */\nstruct EditionInfo {\n // Base URI for the tokenId.\n string baseURI;\n // Contract URI for OpenSea storefront.\n string contractURI;\n // Name of the collection.\n string name;\n // Symbol of the collection.\n string symbol;\n // Address that receives primary and secondary royalties.\n address fundingRecipient;\n // The current max mintable amount;\n uint32 editionMaxMintable;\n // The lower limit of the maximum number of tokens that can be minted.\n uint32 editionMaxMintableUpper;\n // The upper limit of the maximum number of tokens that can be minted.\n uint32 editionMaxMintableLower;\n // The timestamp (in seconds since unix epoch) after which the\n // max amount of tokens mintable will drop from\n // `maxMintableUpper` to `maxMintableLower`.\n uint32 editionCutoffTime;\n // Address of metadata module, address(0x00) if not used.\n address metadataModule;\n // The current mint randomness value.\n uint256 mintRandomness;\n // The royalty BPS (basis points).\n uint16 royaltyBPS;\n // Whether the mint randomness is enabled.\n bool mintRandomnessEnabled;\n // Whether the mint has concluded.\n bool mintConcluded;\n // Whether the metadata has been frozen.\n bool isMetadataFrozen;\n // Next token ID to be minted.\n uint256 nextTokenId;\n // Total number of tokens burned.\n uint256 totalBurned;\n // Total number of tokens minted.\n uint256 totalMinted;\n // Total number of tokens currently in existence.\n uint256 totalSupply;\n}\n\n/**\n * @title ISoundEditionV1_2\n * @notice The interface for Sound edition contracts.\n */\ninterface ISoundEditionV1_2 is IERC721AUpgradeable, IERC2981Upgradeable {\n // =============================================================\n // EVENTS\n // =============================================================\n\n /**\n * @dev Emitted when the metadata module is set.\n * @param metadataModule the address of the metadata module.\n */\n event MetadataModuleSet(address metadataModule);\n\n /**\n * @dev Emitted when the `baseURI` is set.\n * @param baseURI the base URI of the edition.\n */\n event BaseURISet(string baseURI);\n\n /**\n * @dev Emitted when the `contractURI` is set.\n * @param contractURI The contract URI of the edition.\n */\n event ContractURISet(string contractURI);\n\n /**\n * @dev Emitted when the metadata is frozen (e.g.: `baseURI` can no longer be changed).\n * @param metadataModule The address of the metadata module.\n * @param baseURI The base URI of the edition.\n * @param contractURI The contract URI of the edition.\n */\n event MetadataFrozen(address metadataModule, string baseURI, string contractURI);\n\n /**\n * @dev Emitted when the `fundingRecipient` is set.\n * @param fundingRecipient The address of the funding recipient.\n */\n event FundingRecipientSet(address fundingRecipient);\n\n /**\n * @dev Emitted when the `royaltyBPS` is set.\n * @param bps The new royalty, measured in basis points.\n */\n event RoyaltySet(uint16 bps);\n\n /**\n * @dev Emitted when the edition's maximum mintable token quantity range is set.\n * @param editionMaxMintableLower_ The lower limit of the maximum number of tokens that can be minted.\n * @param editionMaxMintableUpper_ The upper limit of the maximum number of tokens that can be minted.\n */\n event EditionMaxMintableRangeSet(uint32 editionMaxMintableLower_, uint32 editionMaxMintableUpper_);\n\n /**\n * @dev Emitted when the edition's cutoff time set.\n * @param editionCutoffTime_ The timestamp.\n */\n event EditionCutoffTimeSet(uint32 editionCutoffTime_);\n\n /**\n * @dev Emitted when the `mintRandomnessEnabled` is set.\n * @param mintRandomnessEnabled_ The boolean value.\n */\n event MintRandomnessEnabledSet(bool mintRandomnessEnabled_);\n\n /**\n * @dev Emitted when the `operatorFilteringEnabled` is set.\n * @param operatorFilteringEnabled_ The boolean value.\n */\n event OperatorFilteringEnablededSet(bool operatorFilteringEnabled_);\n\n /**\n * @dev Emitted upon initialization.\n * @param edition_ The address of the edition.\n * @param name_ Name of the collection.\n * @param symbol_ Symbol of the collection.\n * @param metadataModule_ Address of metadata module, address(0x00) if not used.\n * @param baseURI_ Base URI.\n * @param contractURI_ Contract URI for OpenSea storefront.\n * @param fundingRecipient_ Address that receives primary and secondary royalties.\n * @param royaltyBPS_ Royalty amount in bps (basis points).\n * @param editionMaxMintableLower_ The lower bound of the max mintable quantity for the edition.\n * @param editionMaxMintableUpper_ The upper bound of the max mintable quantity for the edition.\n * @param editionCutoffTime_ The timestamp after which `editionMaxMintable` drops from\n * `editionMaxMintableUpper` to\n * `max(_totalMinted(), editionMaxMintableLower)`.\n * @param flags_ The bitwise OR result of the initialization flags.\n * See: {METADATA_IS_FROZEN_FLAG}\n * See: {MINT_RANDOMNESS_ENABLED_FLAG}\n */\n event SoundEditionInitialized(\n address indexed edition_,\n string name_,\n string symbol_,\n address metadataModule_,\n string baseURI_,\n string contractURI_,\n address fundingRecipient_,\n uint16 royaltyBPS_,\n uint32 editionMaxMintableLower_,\n uint32 editionMaxMintableUpper_,\n uint32 editionCutoffTime_,\n uint8 flags_\n );\n\n /**\n * @dev Emitted upon ETH withdrawal.\n * @param recipient The recipient of the withdrawal.\n * @param amount The amount withdrawn.\n * @param caller The account that initiated the withdrawal.\n */\n event ETHWithdrawn(address recipient, uint256 amount, address caller);\n\n /**\n * @dev Emitted upon ERC20 withdrawal.\n * @param recipient The recipient of the withdrawal.\n * @param tokens The addresses of the ERC20 tokens.\n * @param amounts The amount of each token withdrawn.\n * @param caller The account that initiated the withdrawal.\n */\n event ERC20Withdrawn(address recipient, address[] tokens, uint256[] amounts, address caller);\n\n /**\n * @dev Emitted upon a mint.\n * @param to The address to mint to.\n * @param quantity The number of minted.\n * @param fromTokenId The first token ID minted.\n */\n event Minted(address to, uint256 quantity, uint256 fromTokenId);\n\n /**\n * @dev Emitted upon an airdrop.\n * @param to The recipients of the airdrop.\n * @param quantity The number of tokens airdropped to each address in `to`.\n * @param fromTokenId The first token ID minted to the first address in `to`.\n */\n event Airdropped(address[] to, uint256 quantity, uint256 fromTokenId);\n\n /**\n * @dev Emiited when the Sound Automated Market (i.e. bonding curve minter) is set.\n * @param sam_ The Sound Automated Market.\n */\n event SAMSet(address sam_);\n\n // =============================================================\n // ERRORS\n // =============================================================\n\n /**\n * @dev The edition's metadata is frozen (e.g.: `baseURI` can no longer be changed).\n */\n error MetadataIsFrozen();\n\n /**\n * @dev The given `royaltyBPS` is invalid.\n */\n error InvalidRoyaltyBPS();\n\n /**\n * @dev The given `randomnessLockedAfterMinted` value is invalid.\n */\n error InvalidRandomnessLock();\n\n /**\n * @dev The requested quantity exceeds the edition's remaining mintable token quantity.\n * @param available The number of tokens remaining available for mint.\n */\n error ExceedsEditionAvailableSupply(uint32 available);\n\n /**\n * @dev The given amount is invalid.\n */\n error InvalidAmount();\n\n /**\n * @dev The given `fundingRecipient` address is invalid.\n */\n error InvalidFundingRecipient();\n\n /**\n * @dev The `editionMaxMintableLower` must not be greater than `editionMaxMintableUpper`.\n */\n error InvalidEditionMaxMintableRange();\n\n /**\n * @dev The `editionMaxMintable` has already been reached.\n */\n error MaximumHasAlreadyBeenReached();\n\n /**\n * @dev The mint `quantity` cannot exceed `ADDRESS_BATCH_MINT_LIMIT` tokens.\n */\n error ExceedsAddressBatchMintLimit();\n\n /**\n * @dev The mint randomness has already been revealed.\n */\n error MintRandomnessAlreadyRevealed();\n\n /**\n * @dev No addresses to airdrop.\n */\n error NoAddressesToAirdrop();\n\n /**\n * @dev The mint has already concluded.\n */\n error MintHasConcluded();\n\n /**\n * @dev The mint has not concluded.\n */\n error MintNotConcluded();\n\n /**\n * @dev Cannot perform the operation after a token has been minted.\n */\n error MintsAlreadyExist();\n\n /**\n * @dev The token IDs must be in strictly ascending order.\n */\n error TokenIdsNotStrictlyAscending();\n\n // =============================================================\n // PUBLIC / EXTERNAL WRITE FUNCTIONS\n // =============================================================\n\n /**\n * @dev Initializes the contract.\n * @param name_ Name of the collection.\n * @param symbol_ Symbol of the collection.\n * @param metadataModule_ Address of metadata module, address(0x00) if not used.\n * @param baseURI_ Base URI.\n * @param contractURI_ Contract URI for OpenSea storefront.\n * @param fundingRecipient_ Address that receives primary and secondary royalties.\n * @param royaltyBPS_ Royalty amount in bps (basis points).\n * @param editionMaxMintableLower_ The lower bound of the max mintable quantity for the edition.\n * @param editionMaxMintableUpper_ The upper bound of the max mintable quantity for the edition.\n * @param editionCutoffTime_ The timestamp after which `editionMaxMintable` drops from\n * `editionMaxMintableUpper` to\n * `max(_totalMinted(), editionMaxMintableLower)`.\n * @param flags_ The bitwise OR result of the initialization flags.\n * See: {METADATA_IS_FROZEN_FLAG}\n * See: {MINT_RANDOMNESS_ENABLED_FLAG}\n */\n function initialize(\n string memory name_,\n string memory symbol_,\n address metadataModule_,\n string memory baseURI_,\n string memory contractURI_,\n address fundingRecipient_,\n uint16 royaltyBPS_,\n uint32 editionMaxMintableLower_,\n uint32 editionMaxMintableUpper_,\n uint32 editionCutoffTime_,\n uint8 flags_\n ) external;\n\n /**\n * @dev Mints `quantity` tokens to addrress `to`\n * Each token will be assigned a token ID that is consecutively increasing.\n *\n * Calling conditions:\n * - The caller must be the owner of the contract, or have either the\n * `ADMIN_ROLE`, `MINTER_ROLE`, which can be granted via {grantRole}.\n * Multiple minters, such as different minter contracts,\n * can be authorized simultaneously.\n *\n * @param to Address to mint to.\n * @param quantity Number of tokens to mint.\n * @return fromTokenId The first token ID minted.\n */\n function mint(address to, uint256 quantity) external payable returns (uint256 fromTokenId);\n\n /**\n * @dev Mints `quantity` tokens to each of the addresses in `to`.\n *\n * Calling conditions:\n * - The caller must be the owner of the contract, or have the\n * `ADMIN_ROLE`, which can be granted via {grantRole}.\n *\n * @param to Address to mint to.\n * @param quantity Number of tokens to mint.\n * @return fromTokenId The first token ID minted.\n */\n function airdrop(address[] calldata to, uint256 quantity) external returns (uint256 fromTokenId);\n\n /**\n * @dev Mints `quantity` tokens to addrress `to`\n * Each token will be assigned a token ID that is consecutively increasing.\n *\n * Calling conditions:\n * - The caller must be the bonding curve contract.\n *\n * @param to Address to mint to.\n * @param quantity Number of tokens to mint.\n * @return fromTokenId The first token ID minted.\n */\n function samMint(address to, uint256 quantity) external payable returns (uint256 fromTokenId);\n\n /**\n * @dev Burns the `tokenIds`.\n *\n * Calling conditions:\n * - The caller must be the bonding curve contract.\n *\n * @param burner The initiator of the burn.\n * @param tokenIds The list of token IDs to burn.\n */\n function samBurn(address burner, uint256[] calldata tokenIds) external;\n\n /**\n * @dev Withdraws collected ETH royalties to the fundingRecipient.\n */\n function withdrawETH() external;\n\n /**\n * @dev Withdraws collected ERC20 royalties to the fundingRecipient.\n * @param tokens array of ERC20 tokens to withdraw\n */\n function withdrawERC20(address[] calldata tokens) external;\n\n /**\n * @dev Sets metadata module.\n *\n * Calling conditions:\n * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.\n *\n * @param metadataModule Address of metadata module.\n */\n function setMetadataModule(address metadataModule) external;\n\n /**\n * @dev Sets global base URI.\n *\n * Calling conditions:\n * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.\n *\n * @param baseURI The base URI to be set.\n */\n function setBaseURI(string memory baseURI) external;\n\n /**\n * @dev Sets contract URI.\n *\n * Calling conditions:\n * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.\n *\n * @param contractURI The contract URI to be set.\n */\n function setContractURI(string memory contractURI) external;\n\n /**\n * @dev Freezes metadata by preventing any more changes to base URI.\n *\n * Calling conditions:\n * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.\n */\n function freezeMetadata() external;\n\n /**\n * @dev Sets funding recipient address.\n *\n * Calling conditions:\n * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.\n *\n * @param fundingRecipient Address to be set as the new funding recipient.\n */\n function setFundingRecipient(address fundingRecipient) external;\n\n /**\n * @dev Sets royalty amount in bps (basis points).\n *\n * Calling conditions:\n * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.\n *\n * @param bps The new royalty basis points to be set.\n */\n function setRoyalty(uint16 bps) external;\n\n /**\n * @dev Sets the edition max mintable range.\n *\n * Calling conditions:\n * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.\n *\n * @param editionMaxMintableLower_ The lower limit of the maximum number of tokens that can be minted.\n * @param editionMaxMintableUpper_ The upper limit of the maximum number of tokens that can be minted.\n */\n function setEditionMaxMintableRange(uint32 editionMaxMintableLower_, uint32 editionMaxMintableUpper_) external;\n\n /**\n * @dev Sets the timestamp after which, the `editionMaxMintable` drops\n * from `editionMaxMintableUpper` to `editionMaxMintableLower.\n *\n * Calling conditions:\n * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.\n *\n * @param editionCutoffTime_ The timestamp.\n */\n function setEditionCutoffTime(uint32 editionCutoffTime_) external;\n\n /**\n * @dev Sets whether the `mintRandomness` is enabled.\n *\n * Calling conditions:\n * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.\n *\n * @param mintRandomnessEnabled_ The boolean value.\n */\n function setMintRandomnessEnabled(bool mintRandomnessEnabled_) external;\n\n /**\n * @dev Sets whether OpenSea operator filtering is enabled.\n *\n * Calling conditions:\n * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.\n *\n * @param operatorFilteringEnabled_ The boolean value.\n */\n function setOperatorFilteringEnabled(bool operatorFilteringEnabled_) external;\n\n /**\n * @dev Sets the Sound Automated Market (i.e. bonding curve minter).\n *\n * Calling conditions:\n * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`.\n *\n * @param sam_ The Sound Automated Market.\n */\n function setSAM(address sam_) external;\n\n // =============================================================\n // PUBLIC / EXTERNAL VIEW FUNCTIONS\n // =============================================================\n\n /**\n * @dev Returns the edition info.\n * @return editionInfo The latest value.\n */\n function editionInfo() external view returns (EditionInfo memory editionInfo);\n\n /**\n * @dev Returns the minter role flag.\n * @return The constant value.\n */\n function MINTER_ROLE() external view returns (uint256);\n\n /**\n * @dev Returns the admin role flag.\n * @return The constant value.\n */\n function ADMIN_ROLE() external view returns (uint256);\n\n /**\n * @dev Returns the maximum limit for the mint or airdrop `quantity`.\n * Prevents the first-time transfer costs for tokens near the end of large mint batches\n * via ERC721A from becoming too expensive due to the need to scan many storage slots.\n * See: https://chiru-labs.github.io/ERC721A/#/tips?id=batch-size\n * @return The constant value.\n */\n function ADDRESS_BATCH_MINT_LIMIT() external pure returns (uint256);\n\n /**\n * @dev Returns the bit flag to freeze the metadata on initialization.\n * @return The constant value.\n */\n function METADATA_IS_FROZEN_FLAG() external pure returns (uint8);\n\n /**\n * @dev Returns the bit flag to enable the mint randomness feature on initialization.\n * @return The constant value.\n */\n function MINT_RANDOMNESS_ENABLED_FLAG() external pure returns (uint8);\n\n /**\n * @dev Returns the bit flag to enable OpenSea operator filtering.\n * @return The constant value.\n */\n function OPERATOR_FILTERING_ENABLED_FLAG() external pure returns (uint8);\n\n /**\n * @dev Returns the base token URI for the collection.\n * @return The configured value.\n */\n function baseURI() external view returns (string memory);\n\n /**\n * @dev Returns the contract URI to be used by Opensea.\n * See: https://docs.opensea.io/docs/contract-level-metadata\n * @return The configured value.\n */\n function contractURI() external view returns (string memory);\n\n /**\n * @dev Returns the address of the funding recipient.\n * @return The configured value.\n */\n function fundingRecipient() external view returns (address);\n\n /**\n * @dev Returns the maximum amount of tokens mintable for this edition.\n * @return The configured value.\n */\n function editionMaxMintable() external view returns (uint32);\n\n /**\n * @dev Returns the upper bound for the maximum tokens that can be minted for this edition.\n * @return The configured value.\n */\n function editionMaxMintableUpper() external view returns (uint32);\n\n /**\n * @dev Returns the lower bound for the maximum tokens that can be minted for this edition.\n * @return The configured value.\n */\n function editionMaxMintableLower() external view returns (uint32);\n\n /**\n * @dev Returns the timestamp after which `editionMaxMintable` drops from\n * `editionMaxMintableUpper` to `editionMaxMintableLower`.\n * @return The configured value.\n */\n function editionCutoffTime() external view returns (uint32);\n\n /**\n * @dev Returns the address of the metadata module.\n * @return The configured value.\n */\n function metadataModule() external view returns (address);\n\n /**\n * @dev Returns the randomness based on latest block hash, which is stored upon each mint.\n * unless {mintConcluded} is true.\n * Used for game mechanics like the Sound Golden Egg.\n * Returns 0 before revealed.\n * WARNING: This value should NOT be used for any reward of significant monetary\n * value, due to it being computed via a purely on-chain psuedorandom mechanism.\n * @return The latest value.\n */\n function mintRandomness() external view returns (uint256);\n\n /**\n * @dev Returns whether the `mintRandomness` has been enabled.\n * @return The configured value.\n */\n function mintRandomnessEnabled() external view returns (bool);\n\n /**\n * @dev Returns whether the `operatorFilteringEnabled` has been enabled.\n * @return The configured value.\n */\n function operatorFilteringEnabled() external view returns (bool);\n\n /**\n * @dev Returns whether the mint has been concluded.\n * @return The latest value.\n */\n function mintConcluded() external view returns (bool);\n\n /**\n * @dev Returns the royalty basis points.\n * @return The configured value.\n */\n function royaltyBPS() external view returns (uint16);\n\n /**\n * @dev Returns whether the metadata module is frozen.\n * @return The configured value.\n */\n function isMetadataFrozen() external view returns (bool);\n\n /**\n * @dev Returns the sound automated market, if any.\n * @return The configured value.\n */\n function sam() external view returns (address);\n\n /**\n * @dev Returns the next token ID to be minted.\n * @return The latest value.\n */\n function nextTokenId() external view returns (uint256);\n\n /**\n * @dev Returns the number of tokens minted by `owner`.\n * @param owner Address to query for number minted.\n * @return The latest value.\n */\n function numberMinted(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the number of tokens burned by `owner`.\n * @param owner Address to query for number burned.\n * @return The latest value.\n */\n function numberBurned(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the total amount of tokens minted.\n * @return The latest value.\n */\n function totalMinted() external view returns (uint256);\n\n /**\n * @dev Returns the total amount of tokens burned.\n * @return The latest value.\n */\n function totalBurned() external view returns (uint256);\n\n /**\n * @dev Informs other contracts which interfaces this contract supports.\n * Required by https://eips.ethereum.org/EIPS/eip-165\n * @param interfaceId The interface id to check.\n * @return Whether the `interfaceId` is supported.\n */\n function supportsInterface(bytes4 interfaceId)\n external\n view\n override(IERC721AUpgradeable, IERC165Upgradeable)\n returns (bool);\n}\n"},"contracts/modules/SAM.sol":{"content":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.16;\n\nimport { Ownable, OwnableRoles } from \"solady/auth/OwnableRoles.sol\";\nimport { MerkleProofLib } from \"solady/utils/MerkleProofLib.sol\";\nimport { SafeCastLib } from \"solady/utils/SafeCastLib.sol\";\nimport { SafeTransferLib } from \"solady/utils/SafeTransferLib.sol\";\nimport { IERC165 } from \"openzeppelin/utils/introspection/IERC165.sol\";\nimport { ISAM, SAMInfo } from \"./interfaces/ISAM.sol\";\nimport { BondingCurveLib } from \"./utils/BondingCurveLib.sol\";\nimport { ISoundEditionV1_2 } from \"@core/interfaces/ISoundEditionV1_2.sol\";\n\n/*\n * @title SAM\n * @notice Module for Sound automated market.\n * @author Sound.xyz\n */\ncontract SAM is ISAM, Ownable {\n // =============================================================\n // CONSTANTS\n // =============================================================\n\n /**\n * @dev This is the denominator, in basis points (BPS), for any of the fees.\n */\n uint16 public constant BPS_DENOMINATOR = 10_000;\n\n /**\n * @dev The maximum basis points (BPS) limit allowed for the platform fees.\n */\n uint16 public constant MAX_PLATFORM_FEE_BPS = 500;\n\n /**\n * @dev The maximum basis points (BPS) limit allowed for the artist fees.\n */\n uint16 public constant MAX_ARTIST_FEE_BPS = 1_000;\n\n /**\n * @dev The maximum basis points (BPS) limit allowed for the affiliate fees.\n */\n uint16 public constant MAX_AFFILIATE_FEE_BPS = 500;\n\n /**\n * @dev The maximum basis points (BPS) limit allowed for the golden egg fees.\n */\n uint16 public constant MAX_GOLDEN_EGG_FEE_BPS = 500;\n\n // =============================================================\n // STORAGE\n // =============================================================\n\n /**\n * @dev How much platform fees have been accrued.\n */\n uint128 public platformFeesAccrued;\n\n /**\n * @dev The platform fee in basis points.\n */\n uint16 public platformFeeBPS;\n\n /**\n * @dev Just in case. Won't cost much overhead anyway since it is packed.\n */\n bool internal _reentrancyGuard;\n\n /**\n * @dev The platform fee address.\n */\n address public platformFeeAddress;\n\n /**\n * @dev The data for the sound automated markets.\n * edition => SAMData\n */\n mapping(address => SAMData) internal _samData;\n\n /**\n * @dev Maps an address to how much affiliate fees have they accrued.\n */\n mapping(address => uint128) internal _affiliateFeesAccrued;\n\n // =============================================================\n // CONSTRUCTOR\n // =============================================================\n\n constructor() payable {\n _initializeOwner(msg.sender);\n }\n\n // =============================================================\n // PUBLIC / EXTERNAL WRITE FUNCTIONS\n // =============================================================\n\n /**\n * @inheritdoc ISAM\n */\n function create(\n address edition,\n uint96 basePrice,\n uint96 inflectionPrice,\n uint32 inflectionPoint,\n uint16 artistFeeBPS,\n uint16 goldenEggFeeBPS,\n uint16 affiliateFeeBPS\n ) public onlyEditionOwnerOrAdmin(edition) onlyBeforeMintConcluded(edition) {\n // We don't use modifiers here in order to prevent stack too deep.\n if (inflectionPrice == 0) revert InflectionPriceIsZero();\n if (inflectionPoint == 0) revert InflectionPointIsZero();\n if (artistFeeBPS > MAX_ARTIST_FEE_BPS) revert InvalidArtistFeeBPS();\n if (goldenEggFeeBPS > MAX_GOLDEN_EGG_FEE_BPS) revert InvalidGoldenEggFeeBPS();\n if (affiliateFeeBPS > MAX_AFFILIATE_FEE_BPS) revert InvalidAffiliateFeeBPS();\n\n SAMData storage data = _samData[edition];\n\n if (data.inflectionPrice != 0) revert SAMAlreadyExists();\n\n data.basePrice = basePrice;\n data.inflectionPrice = inflectionPrice;\n data.inflectionPoint = inflectionPoint;\n data.artistFeeBPS = artistFeeBPS;\n data.goldenEggFeeBPS = goldenEggFeeBPS;\n data.affiliateFeeBPS = affiliateFeeBPS;\n\n emit Created(\n edition,\n basePrice,\n inflectionPrice,\n inflectionPoint,\n artistFeeBPS,\n goldenEggFeeBPS,\n affiliateFeeBPS\n );\n }\n\n /**\n * For avoiding stack too deep.\n */\n struct _BuyTemps {\n uint256 fromCurveSupply;\n uint256 fromTokenId;\n uint256 requiredEtherValue;\n uint256 feePerBPS;\n uint256 platformFee;\n uint256 artistFee;\n uint256 goldenEggFee;\n uint256 affiliateFee;\n bool affiliated;\n }\n\n /**\n * @inheritdoc ISAM\n */\n function buy(\n address edition,\n address to,\n uint32 quantity,\n address affiliate,\n bytes32[] calldata affiliateProof\n ) public payable nonReentrant {\n _BuyTemps memory t;\n SAMData storage data = _getSAMData(edition);\n t.fromCurveSupply = data.supply; // Cache the `data.supply`.\n\n (t.requiredEtherValue, t.feePerBPS) = _totalBuyPriceAndFeePerBPS(data, uint32(t.fromCurveSupply), quantity);\n\n if (msg.value < t.requiredEtherValue) revert Underpaid(msg.value, t.requiredEtherValue);\n\n if (data.buyFrozen) revert BuyIsFrozen();\n\n unchecked {\n // Compute the artist fee.\n t.artistFee = t.feePerBPS * uint256(data.artistFeeBPS);\n\n // Compute the platform fee.\n t.platformFee = t.feePerBPS * uint256(platformFeeBPS);\n // Accrue the platform fee.\n platformFeesAccrued = SafeCastLib.toUint128(uint256(platformFeesAccrued) + t.platformFee);\n\n // Check if the affiliate is actually affiliated for edition with the affiliate proof.\n t.affiliated = isAffiliatedWithProof(edition, affiliate, affiliateProof);\n // If affiliated, compute and accrue the affiliate fee.\n if (t.affiliated) {\n // Compute the affiliate fee.\n t.affiliateFee = t.feePerBPS * uint256(data.affiliateFeeBPS);\n // Accrue the affiliate fee.\n _affiliateFeesAccrued[affiliate] = SafeCastLib.toUint128(\n uint256(_affiliateFeesAccrued[affiliate]) + t.affiliateFee\n );\n } else {\n // Otherwise, add the affiliate fee to the artist fee instead.\n t.artistFee += t.feePerBPS * uint256(data.affiliateFeeBPS);\n }\n\n // Mint the tokens and transfer the artist fee to the edition contract.\n // Will revert if the `quantity` is zero.\n t.fromTokenId = ISoundEditionV1_2(edition).samMint{ value: t.artistFee }(to, quantity);\n\n // Compute the golden egg fee.\n t.goldenEggFee = t.feePerBPS * uint256(data.goldenEggFeeBPS);\n // Accrue the golden egg fee.\n data.goldenEggFeesAccrued = SafeCastLib.toUint128(uint256(data.goldenEggFeesAccrued) + t.goldenEggFee);\n\n // Add `quantity` to the supply.\n // We add a safecast here just in case.\n data.supply = SafeCastLib.toUint32(t.fromCurveSupply + uint256(quantity));\n\n // Refund any excess ETH.\n if (msg.value > t.requiredEtherValue) {\n SafeTransferLib.forceSafeTransferETH(msg.sender, msg.value - t.requiredEtherValue);\n }\n\n emit Bought(\n edition,\n to,\n t.fromTokenId,\n uint32(t.fromCurveSupply),\n quantity,\n uint128(t.requiredEtherValue),\n uint128(t.platformFee),\n uint128(t.artistFee),\n uint128(t.goldenEggFee),\n uint128(t.affiliateFee),\n affiliate,\n t.affiliated\n );\n }\n }\n\n /**\n * @inheritdoc ISAM\n */\n function sell(\n address edition,\n uint256[] calldata tokenIds,\n uint256 minimumPayout,\n address payoutTo\n ) public nonReentrant {\n unchecked {\n SAMData storage data = _getSAMData(edition);\n\n uint256 quantity = tokenIds.length;\n\n uint256 initialSupply = data.supply;\n\n // The `_totalSellPrice` function will revert with\n // `InsufficientSupply(available = initialSupply, required = quantity)`\n // if `initialSupply < quantity`.\n uint256 payout = _totalSellPrice(data, uint32(initialSupply), 0, uint32(quantity));\n\n if (payout < minimumPayout) revert InsufficientPayout(payout, minimumPayout);\n\n ISoundEditionV1_2(edition).samBurn(msg.sender, tokenIds);\n\n // Decrease the supply. The `_totalSellPrice` function call above\n // has already check that `initialSupply >= quantity`.\n data.supply = uint32(initialSupply - quantity);\n\n SafeTransferLib.forceSafeTransferETH(payoutTo, payout);\n\n emit Sold(edition, payoutTo, uint32(initialSupply), tokenIds, uint128(payout));\n }\n }\n\n /**\n * @inheritdoc ISAM\n */\n function setBasePrice(address edition, uint96 basePrice)\n public\n onlyEditionOwnerOrAdmin(edition)\n onlyBeforeMintConcluded(edition)\n {\n SAMData storage data = _getSAMData(edition);\n data.basePrice = basePrice;\n emit BasePriceSet(edition, basePrice);\n }\n\n /**\n * @inheritdoc ISAM\n */\n function setInflectionPrice(address edition, uint96 inflectionPrice)\n public\n onlyEditionOwnerOrAdmin(edition)\n onlyBeforeMintConcluded(edition)\n {\n SAMData storage data = _getSAMData(edition);\n if (inflectionPrice == 0) revert InflectionPriceIsZero();\n data.inflectionPrice = inflectionPrice;\n emit InflectionPriceSet(edition, inflectionPrice);\n }\n\n /**\n * @inheritdoc ISAM\n */\n function setInflectionPoint(address edition, uint32 inflectionPoint)\n public\n onlyEditionOwnerOrAdmin(edition)\n onlyBeforeMintConcluded(edition)\n {\n SAMData storage data = _getSAMData(edition);\n if (inflectionPoint == 0) revert InflectionPointIsZero();\n data.inflectionPoint = inflectionPoint;\n emit InflectionPointSet(edition, inflectionPoint);\n }\n\n /**\n * @inheritdoc ISAM\n */\n function setArtistFee(address edition, uint16 bps)\n public\n onlyEditionOwnerOrAdmin(edition)\n onlyBeforeMintConcluded(edition)\n {\n SAMData storage data = _getSAMData(edition);\n if (bps > MAX_ARTIST_FEE_BPS) revert InvalidArtistFeeBPS();\n data.artistFeeBPS = bps;\n emit ArtistFeeSet(edition, bps);\n }\n\n /**\n * @inheritdoc ISAM\n */\n function setGoldenEggFee(address edition, uint16 bps)\n public\n onlyEditionOwnerOrAdmin(edition)\n onlyBeforeMintConcluded(edition)\n {\n SAMData storage data = _getSAMData(edition);\n if (bps > MAX_GOLDEN_EGG_FEE_BPS) revert InvalidGoldenEggFeeBPS();\n data.goldenEggFeeBPS = bps;\n emit GoldenEggFeeSet(edition, bps);\n }\n\n /**\n * @inheritdoc ISAM\n */\n function setAffiliateFee(address edition, uint16 bps)\n public\n onlyEditionOwnerOrAdmin(edition)\n onlyBeforeMintConcluded(edition)\n {\n SAMData storage data = _getSAMData(edition);\n if (bps > MAX_AFFILIATE_FEE_BPS) revert InvalidAffiliateFeeBPS();\n data.affiliateFeeBPS = bps;\n emit AffiliateFeeSet(edition, bps);\n }\n\n /**\n * @inheritdoc ISAM\n */\n function setAffiliateMerkleRoot(address edition, bytes32 root) public onlyEditionOwnerOrAdmin(edition) {\n // Note that we want to allow adding a root even while the bonding curve\n // is still ongoing, in case the need to prevent spam arises.\n\n SAMData storage data = _getSAMData(edition);\n data.affiliateMerkleRoot = root;\n emit AffiliateMerkleRootSet(edition, root);\n }\n\n /**\n * @inheritdoc ISAM\n */\n function freezeBuy(address edition) public onlyEditionOwnerOrAdmin(edition) {\n SAMData storage data = _getSAMData(edition);\n if (data.buyFrozen) revert BuyIsFrozen();\n data.buyFrozen = true;\n emit BuyFrozen(edition);\n }\n\n /**\n * @inheritdoc ISAM\n */\n function withdrawForAffiliate(address affiliate) public nonReentrant {\n uint128 accrued = _affiliateFeesAccrued[affiliate];\n if (accrued != 0) {\n _affiliateFeesAccrued[affiliate] = 0;\n SafeTransferLib.forceSafeTransferETH(affiliate, accrued);\n emit AffiliateFeesWithdrawn(affiliate, accrued);\n }\n }\n\n /**\n * @inheritdoc ISAM\n */\n function withdrawForPlatform() public nonReentrant {\n address to = platformFeeAddress;\n if (to == address(0)) revert PlatformFeeAddressIsZero();\n uint128 accrued = platformFeesAccrued;\n if (accrued != 0) {\n platformFeesAccrued = 0;\n SafeTransferLib.forceSafeTransferETH(to, accrued);\n emit PlatformFeesWithdrawn(accrued);\n }\n }\n\n /**\n * @inheritdoc ISAM\n */\n function withdrawForGoldenEgg(address edition) public nonReentrant {\n SAMData storage data = _getSAMData(edition);\n uint128 accrued = data.goldenEggFeesAccrued;\n if (accrued != 0) {\n data.goldenEggFeesAccrued = 0;\n address receipient = goldenEggFeeRecipient(edition);\n SafeTransferLib.forceSafeTransferETH(receipient, accrued);\n emit GoldenEggFeesWithdrawn(edition, receipient, accrued);\n }\n }\n\n /**\n * @inheritdoc ISAM\n */\n function setPlatformFee(uint16 bps) public onlyOwner {\n if (bps > MAX_PLATFORM_FEE_BPS) revert InvalidPlatformFeeBPS();\n platformFeeBPS = bps;\n emit PlatformFeeSet(bps);\n }\n\n /**\n * @inheritdoc ISAM\n */\n function setPlatformFeeAddress(address addr) public onlyOwner {\n if (addr == address(0)) revert PlatformFeeAddressIsZero();\n platformFeeAddress = addr;\n emit PlatformFeeAddressSet(addr);\n }\n\n // =============================================================\n // PUBLIC / EXTERNAL VIEW FUNCTIONS\n // =============================================================\n\n /**\n * @inheritdoc ISAM\n */\n function samInfo(address edition) external view returns (SAMInfo memory info) {\n SAMData storage data = _getSAMData(edition);\n info.basePrice = data.basePrice;\n info.inflectionPrice = data.inflectionPrice;\n info.inflectionPoint = data.inflectionPoint;\n info.goldenEggFeesAccrued = data.goldenEggFeesAccrued;\n info.supply = data.supply;\n info.artistFeeBPS = data.artistFeeBPS;\n info.affiliateFeeBPS = data.affiliateFeeBPS;\n info.goldenEggFeeBPS = data.goldenEggFeeBPS;\n }\n\n /**\n * @inheritdoc ISAM\n */\n function totalValue(\n address edition,\n uint32 fromSupply,\n uint32 quantity\n ) public view returns (uint256 total) {\n unchecked {\n SAMData storage data = _getSAMData(edition);\n total = uint256(data.basePrice) * uint256(quantity);\n total += BondingCurveLib.sigmoid2Sum(data.inflectionPoint, data.inflectionPrice, fromSupply, quantity);\n }\n }\n\n /**\n * @inheritdoc ISAM\n */\n function totalBuyPrice(\n address edition,\n uint32 supplyForwardOffset,\n uint32 quantity\n ) public view returns (uint256 total) {\n unchecked {\n SAMData storage data = _getSAMData(edition);\n uint256 fromSupply = uint256(data.supply) + uint256(supplyForwardOffset);\n (total, ) = _totalBuyPriceAndFeePerBPS(data, SafeCastLib.toUint32(fromSupply), quantity);\n }\n }\n\n /**\n * @inheritdoc ISAM\n */\n function totalSellPrice(\n address edition,\n uint32 supplyBackwardOffset,\n uint32 quantity\n ) public view returns (uint256 total) {\n SAMData storage data = _getSAMData(edition);\n\n // The `_totalSellPrice` function will revert with\n // `InsufficientSupply(available = data.supply, required = supplyBackwardOffset + quantity)`\n // if `data.supply < supplyBackwardOffset + quantity`.\n total = _totalSellPrice(data, data.supply, supplyBackwardOffset, quantity);\n }\n\n /**\n * @inheritdoc ISAM\n */\n function goldenEggFeeRecipient(address edition) public view returns (address receipient) {\n // We use assembly because we don't want to revert\n // if the `metadataModule` is not a valid metadata module contract.\n // Plain solidity requires an extra codesize check.\n assembly {\n // Initialize the receipient to the edition by default.\n receipient := edition\n // Store the function selector of `metadataModule()`.\n mstore(0x00, 0x3684d100)\n\n if iszero(and(eq(returndatasize(), 0x20), staticcall(gas(), edition, 0x1c, 0x04, 0x00, 0x20))) {\n // For better gas estimation, and to require that edition\n // is a contract with the `metadataModule()` function.\n revert(0, 0)\n }\n\n let metadataModule := mload(0x00)\n // Store the function selector of `getGoldenEggTokenId(address)`.\n mstore(0x00, 0x4baca2b5)\n mstore(0x20, edition)\n\n if iszero(staticcall(gas(), metadataModule, 0x1c, 0x24, 0x20, 0x20)) {\n // If there is no returndata upon revert,\n // it is likely due to an out-of-gas error.\n if iszero(returndatasize()) {\n revert(0, 0) // For better gas estimation.\n }\n }\n\n if eq(returndatasize(), 0x20) {\n // Store the function selector of `ownerOf(uint256)`.\n mstore(0x00, 0x6352211e)\n // The `goldenEggTokenId` is already in slot 0x20,\n // as the previous staticcall directly writes the output to slot 0x20.\n\n if iszero(staticcall(gas(), edition, 0x1c, 0x24, 0x00, 0x20)) {\n // If there is no returndata upon revert,\n // it is likely due to an out-of-gas error.\n if iszero(returndatasize()) {\n revert(0, 0) // For better gas estimation.\n }\n }\n\n if eq(returndatasize(), 0x20) {\n receipient := mload(0x00)\n }\n }\n }\n }\n\n /**\n * @inheritdoc ISAM\n */\n function goldenEggFeesAccrued(address edition) public view returns (uint128) {\n return _getSAMData(edition).goldenEggFeesAccrued;\n }\n\n /**\n * @inheritdoc ISAM\n */\n function affiliateFeesAccrued(address affiliate) public view returns (uint128) {\n return _affiliateFeesAccrued[affiliate];\n }\n\n /**\n * @inheritdoc ISAM\n */\n function isAffiliatedWithProof(\n address edition,\n address affiliate,\n bytes32[] calldata affiliateProof\n ) public view returns (bool) {\n bytes32 root = _getSAMData(edition).affiliateMerkleRoot;\n // If the root is empty, then use the default logic.\n if (root == bytes32(0)) {\n return affiliate != address(0);\n }\n // Otherwise, check if the affiliate is in the Merkle tree.\n return MerkleProofLib.verify(affiliateProof, root, keccak256(abi.encodePacked(affiliate)));\n }\n\n /**\n * @inheritdoc ISAM\n */\n function isAffiliated(address edition, address affiliate) public view returns (bool) {\n return isAffiliatedWithProof(edition, affiliate, MerkleProofLib.emptyProof());\n }\n\n /**\n * @inheritdoc ISAM\n */\n function affiliateMerkleRoot(address edition) external view returns (bytes32) {\n return _getSAMData(edition).affiliateMerkleRoot;\n }\n\n /**\n * @inheritdoc IERC165\n */\n function supportsInterface(bytes4 interfaceId) public pure override(IERC165) returns (bool) {\n return interfaceId == this.supportsInterface.selector || interfaceId == type(ISAM).interfaceId;\n }\n\n /**\n * @inheritdoc ISAM\n */\n function moduleInterfaceId() public pure returns (bytes4) {\n return type(ISAM).interfaceId;\n }\n\n // =============================================================\n // INTERNAL / PRIVATE HELPERS\n // =============================================================\n\n /**\n * @dev Restricts the function to be only callable by the owner or admin of `edition`.\n * @param edition The edition address.\n */\n modifier onlyEditionOwnerOrAdmin(address edition) {\n if (msg.sender != OwnableRoles(edition).owner())\n if (!OwnableRoles(edition).hasAnyRole(msg.sender, ISoundEditionV1_2(edition).ADMIN_ROLE()))\n revert Unauthorized();\n _;\n }\n\n /**\n * @dev Requires that the `edition` does not have any tokens minted.\n * @param edition The edition address.\n */\n modifier onlyBeforeMintConcluded(address edition) {\n if (ISoundEditionV1_2(edition).mintConcluded()) revert MintHasConcluded();\n _;\n }\n\n /**\n * @dev Guards the function from reentrancy.\n */\n modifier nonReentrant() {\n require(_reentrancyGuard == false);\n _reentrancyGuard = true;\n _;\n _reentrancyGuard = false;\n }\n\n /**\n * @dev Returns the storage pointer to the SAMData for `edition`.\n * Reverts if the Sound Automated Market does not exist.\n * @param edition The edition address.\n * @return data Storage pointer to a SAMData.\n */\n function _getSAMData(address edition) internal view returns (SAMData storage data) {\n data = _samData[edition];\n if (data.inflectionPrice == 0) revert SAMDoesNotExist();\n }\n\n /**\n * @dev Returns the total buy price and the fee per BPS.\n * @param data Storage pointer to a SAMData.\n * @param fromSupply The starting SAM supply.\n * @param quantity The number of tokens to be minted.\n * @return total The total buy price.\n * @return feePerBPS The amount of fee per BPS.\n */\n function _totalBuyPriceAndFeePerBPS(\n SAMData storage data,\n uint32 fromSupply,\n uint32 quantity\n ) internal view returns (uint256 total, uint256 feePerBPS) {\n unchecked {\n total = uint256(data.basePrice) * uint256(quantity);\n total += BondingCurveLib.sigmoid2Sum(data.inflectionPoint, data.inflectionPrice, fromSupply, quantity);\n uint256 totalFeeBPS = platformFeeBPS;\n totalFeeBPS += data.artistFeeBPS;\n totalFeeBPS += data.affiliateFeeBPS;\n totalFeeBPS += data.goldenEggFeeBPS;\n (total, feePerBPS) = BondingCurveLib.totalBuyPriceAndFeePerBPS(total, totalFeeBPS, BPS_DENOMINATOR);\n }\n }\n\n /**\n * @dev Returns the total sell price.\n * @param data Storage pointer to a SAMData.\n * @param supply The current number of tokens.\n * @param supplyBackwardOffset The backward offset of the supply.\n * @param quantity The number of tokens to be minted.\n * @return total The total buy price.\n */\n function _totalSellPrice(\n SAMData storage data,\n uint32 supply,\n uint32 supplyBackwardOffset,\n uint32 quantity\n ) internal view returns (uint256 total) {\n unchecked {\n uint256 offset = uint256(supplyBackwardOffset) + uint256(quantity);\n // Revert with `InsufficientSupply(available = supply, required = offset)`\n // if `supply < offset`.\n if (supply < offset) revert InsufficientSupply(supply, offset);\n uint32 fromSupply = uint32(uint256(supply) - offset);\n total = uint256(data.basePrice) * uint256(quantity);\n total += BondingCurveLib.sigmoid2Sum(data.inflectionPoint, data.inflectionPrice, fromSupply, quantity);\n }\n }\n}\n"},"contracts/modules/interfaces/ISAM.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.16;\n\nimport { IERC165 } from \"openzeppelin/utils/introspection/IERC165.sol\";\n\n/**\n * @dev Data unique to a Sound Automated Market (i.e. bonding curve mint).\n */\nstruct SAMInfo {\n uint96 basePrice;\n uint96 inflectionPrice;\n uint32 inflectionPoint;\n uint128 goldenEggFeesAccrued;\n uint32 supply;\n uint16 artistFeeBPS;\n uint16 affiliateFeeBPS;\n uint16 goldenEggFeeBPS;\n}\n\n/**\n * @title ISAM\n * @dev Interface for the Sound Automated Market module.\n * @author Sound.xyz\n */\ninterface ISAM is IERC165 {\n // =============================================================\n // STRUCTS\n // =============================================================\n struct SAMData {\n // The price added to the bonding curve price.\n uint96 basePrice;\n // The sigmoid inflection price of the bonding curve.\n uint96 inflectionPrice;\n // The sigmoid inflection point of the bonding curve.\n uint32 inflectionPoint;\n // The amount of fees accrued by the golden egg.\n uint128 goldenEggFeesAccrued;\n // The amount of tokens in the bonding curve.\n uint32 supply;\n // The fee BPS (basis points) to pay the artist.\n uint16 artistFeeBPS;\n // The fee BPS (basis points) to pay affiliates.\n uint16 affiliateFeeBPS;\n // The fee BPS (basis points) to pay the golden egg holder.\n uint16 goldenEggFeeBPS;\n // The buy is forever closed.\n bool buyFrozen;\n // The affiliate Merkle root, if any.\n bytes32 affiliateMerkleRoot;\n }\n\n // =============================================================\n // EVENTS\n // =============================================================\n\n /**\n * @dev Emitted when a bonding curve is created.\n * @param edition The edition address.\n * @param inflectionPrice The sigmoid inflection price of the bonding curve.\n * @param inflectionPoint The sigmoid inflection point of the bonding curve.\n * @param artistFeeBPS The fee BPS (basis points) to pay the artist.\n * @param goldenEggFeeBPS The fee BPS (basis points) to pay the golden egg holder.\n * @param affiliateFeeBPS The fee BPS (basis points) to pay affiliates.\n */\n event Created(\n address indexed edition,\n uint96 basePrice,\n uint96 inflectionPrice,\n uint32 inflectionPoint,\n uint16 artistFeeBPS,\n uint16 goldenEggFeeBPS,\n uint16 affiliateFeeBPS\n );\n\n /**\n * @dev Emitted when tokens are bought from the bonding curve.\n * @param edition The edition address.\n * @param buyer Address of the buyer.\n * @param fromTokenId The starting token ID minted for the batch.\n * @param fromCurveSupply The start of the curve supply for the batch.\n * @param quantity The number of tokens bought.\n * @param totalPayment The total amount of ETH paid.\n * @param platformFee The cut paid to the platform.\n * @param artistFee The cut paid to the artist.\n * @param goldenEggFee The cut paid to the golden egg.\n * @param affiliateFee The cut paid to the affiliate.\n * @param affiliate The affiliate's address.\n * @param affiliated Whether the affiliate is affiliated.\n */\n event Bought(\n address indexed edition,\n address indexed buyer,\n uint256 fromTokenId,\n uint32 fromCurveSupply,\n uint32 quantity,\n uint128 totalPayment,\n uint128 platformFee,\n uint128 artistFee,\n uint128 goldenEggFee,\n uint128 affiliateFee,\n address affiliate,\n bool affiliated\n );\n\n /**\n * @dev Emitted when tokens are sold into the bonding curve.\n * @param edition The edition address.\n * @param seller Address of the seller.\n * @param fromCurveSupply The start of the curve supply for the batch.\n * @param tokenIds The token IDs burned.\n * @param totalPayout The total amount of ETH paid out.\n */\n event Sold(\n address indexed edition,\n address indexed seller,\n uint32 fromCurveSupply,\n uint256[] tokenIds,\n uint128 totalPayout\n );\n\n /**\n * @dev Emitted when the `basePrice` is updated.\n * @param edition The edition address.\n * @param basePrice The price added to the bonding curve price.\n */\n event BasePriceSet(address indexed edition, uint96 basePrice);\n\n /**\n * @dev Emitted when the `inflectionPrice` is updated.\n * @param edition The edition address.\n * @param inflectionPrice The sigmoid inflection price of the bonding curve.\n */\n event InflectionPriceSet(address indexed edition, uint96 inflectionPrice);\n\n /**\n * @dev Emitted when the `inflectionPoint` is updated.\n * @param edition The edition address.\n * @param inflectionPoint The sigmoid inflection point of the bonding curve.\n */\n event InflectionPointSet(address indexed edition, uint32 inflectionPoint);\n\n /**\n * @dev Emitted when the `artistFeeBPS` is updated.\n * @param edition The edition address.\n * @param bps The affiliate fee basis points.\n */\n event ArtistFeeSet(address indexed edition, uint16 bps);\n\n /**\n * @dev Emitted when the `affiliateFeeBPS` is updated.\n * @param edition The edition address.\n * @param bps The affiliate fee basis points.\n */\n event AffiliateFeeSet(address indexed edition, uint16 bps);\n\n /**\n * @dev Emitted when the Merkle root for an affiliate allow list is updated.\n * @param edition The edition address.\n * @param root The Merkle root for the affiliate allow list.\n */\n event AffiliateMerkleRootSet(address indexed edition, bytes32 root);\n\n /**\n * @dev Emitted when the `goldenEggFeeBPS` is updated.\n * @param edition The edition address.\n * @param bps The golden egg fee basis points.\n */\n event GoldenEggFeeSet(address indexed edition, uint16 bps);\n\n /**\n * @dev Emitted when buy for `edition` is closed permanently.\n * @param edition The edition address.\n */\n event BuyFrozen(address indexed edition);\n\n /**\n * @dev Emitted when the `platformFeeBPS` is updated.\n * @param bps The platform fee basis points.\n */\n event PlatformFeeSet(uint16 bps);\n\n /**\n * @dev Emitted when the `platformFeeAddress` is updated.\n * @param addr The platform fee address.\n */\n event PlatformFeeAddressSet(address addr);\n\n /**\n * @dev Emitted when the accrued fees for `affiliate` are withdrawn.\n * @param affiliate The affiliate address.\n * @param accrued The amount of fees withdrawn.\n */\n event AffiliateFeesWithdrawn(address indexed affiliate, uint256 accrued);\n\n /**\n * @dev Emitted when the accrued fees for the golden egg of `edition` are withdrawn.\n * @param edition The edition address.\n * @param receipient The receipient.\n * @param accrued The amount of fees withdrawn.\n */\n event GoldenEggFeesWithdrawn(address indexed edition, address indexed receipient, uint128 accrued);\n\n /**\n * @dev Emitted when the accrued fees for the platform are withdrawn.\n * @param accrued The amount of fees withdrawn.\n */\n event PlatformFeesWithdrawn(uint128 accrued);\n\n // =============================================================\n // ERRORS\n // =============================================================\n\n /**\n * @dev The Ether value paid is below the value required.\n * @param paid The amount sent to the contract.\n * @param required The amount required.\n */\n error Underpaid(uint256 paid, uint256 required);\n\n /**\n * @dev The Ether value paid out is below the value required.\n * @param payout The amount to pau out..\n * @param required The amount required.\n */\n error InsufficientPayout(uint256 payout, uint256 required);\n\n /**\n * @dev There is not enough tokens in the Sound Automated Market for selling back.\n * @param available The number of tokens in the Sound Automated Market.\n * @param required The amount of tokens required.\n */\n error InsufficientSupply(uint256 available, uint256 required);\n\n /**\n * @dev Cannot perform the operation after the mint has already concluded.\n */\n error MintHasConcluded();\n\n /**\n * @dev The inflection price cannot be zero.\n */\n error InflectionPriceIsZero();\n\n /**\n * @dev The inflection point cannot be zero.\n */\n error InflectionPointIsZero();\n\n /**\n * @dev The BPS for the fee cannot exceed the `MAX_PLATFORM_FEE_BPS`.\n */\n error InvalidPlatformFeeBPS();\n\n /**\n * @dev The BPS for the fee cannot exceed the `MAX_ARTIST_FEE_BPS`.\n */\n error InvalidArtistFeeBPS();\n\n /**\n * @dev The BPS for the fee cannot exceed the `MAX_AFFILAITE_FEE_BPS`.\n */\n error InvalidAffiliateFeeBPS();\n\n /**\n * @dev The BPS for the fee cannot exceed the `MAX_GOLDEN_EGG_FEE_BPS`.\n */\n error InvalidGoldenEggFeeBPS();\n\n /**\n * @dev Cannot buy.\n */\n error BuyIsFrozen();\n\n /**\n * @dev The platform fee address cannot be zero.\n */\n error PlatformFeeAddressIsZero();\n\n /**\n * @dev There already is a Sound Automated Market for `edition`.\n */\n error SAMAlreadyExists();\n\n /**\n * @dev There is no Sound Automated Market for `edition`.\n */\n error SAMDoesNotExist();\n\n // =============================================================\n // PUBLIC / EXTERNAL WRITE FUNCTIONS\n // =============================================================\n\n /**\n * @dev Creates a Sound Automated Market on `edition`.\n * @param edition The edition address.\n * @param basePrice The price added to the bonding curve price.\n * @param inflectionPrice The sigmoid inflection price of the bonding curve.\n * @param inflectionPoint The sigmoid inflection point of the bonding curve.\n * @param artistFeeBPS The fee BPS (basis points) to pay the artist.\n * @param goldenEggFeeBPS The fee BPS (basis points) to pay the golden egg holder.\n * @param affiliateFeeBPS The fee BPS (basis points) to pay affiliates.\n */\n function create(\n address edition,\n uint96 basePrice,\n uint96 inflectionPrice,\n uint32 inflectionPoint,\n uint16 artistFeeBPS,\n uint16 goldenEggFeeBPS,\n uint16 affiliateFeeBPS\n ) external;\n\n /**\n * @dev Mints (buys) tokens for a given edition.\n * @param edition The edition address.\n * @param to The address to mint to.\n * @param quantity Token quantity to mint in song `edition`.\n * @param affiliate The affiliate address.\n * @param affiliateProof The Merkle proof needed for verifying the affiliate, if any.\n */\n function buy(\n address edition,\n address to,\n uint32 quantity,\n address affiliate,\n bytes32[] calldata affiliateProof\n ) external payable;\n\n /**\n * @dev Burns (sell) tokens for a given edition.\n * @param edition The edition address.\n * @param tokenIds The token IDs to burn.\n * @param minimumPayout The minimum payout for the transaction to succeed.\n * @param payoutTo The address to send the payout to.\n */\n function sell(\n address edition,\n uint256[] calldata tokenIds,\n uint256 minimumPayout,\n address payoutTo\n ) external;\n\n /**\n * @dev Sets the base price for `edition`.\n * This will be added to the bonding curve price.\n *\n * Calling conditions:\n * - The caller must be the edition's owner or admin.\n *\n * @param edition The edition address.\n * @param basePrice The price added to the bonding curve price.\n */\n function setBasePrice(address edition, uint96 basePrice) external;\n\n /**\n * @dev Sets the bonding curve inflection price for `edition`.\n *\n * Calling conditions:\n * - The caller must be the edition's owner or admin.\n *\n * @param edition The edition address.\n * @param inflectionPrice The sigmoid inflection price of the bonding curve.\n */\n function setInflectionPrice(address edition, uint96 inflectionPrice) external;\n\n /**\n * @dev Sets the bonding curve inflection point for `edition`.\n *\n * Calling conditions:\n * - The caller must be the edition's owner or admin.\n *\n * @param edition The edition address.\n * @param inflectionPoint The sigmoid inflection point of the bonding curve.\n */\n function setInflectionPoint(address edition, uint32 inflectionPoint) external;\n\n /**\n * @dev Sets the artist fee for `edition`.\n *\n * Calling conditions:\n * - The caller must be the edition's owner or admin.\n *\n * @param edition The edition address.\n * @param bps The artist fee in basis points.\n */\n function setArtistFee(address edition, uint16 bps) external;\n\n /**\n * @dev Sets the affiliate fee for `edition`.\n *\n * Calling conditions:\n * - The caller must be the edition's owner or admin.\n *\n * @param edition The edition address.\n * @param bps The affiliate fee in basis points.\n */\n function setAffiliateFee(address edition, uint16 bps) external;\n\n /**\n * @dev Sets the affiliate Merkle root for (`edition`, `mintId`).\n *\n * Calling conditions:\n * - The caller must be the edition's owner or admin.\n *\n * @param edition The edition address.\n * @param root The affiliate Merkle root, if any.\n */\n function setAffiliateMerkleRoot(address edition, bytes32 root) external;\n\n /**\n * @dev Sets the golden egg fee for `edition`.\n *\n * Calling conditions:\n * - The caller must be the edition's owner or admin.\n *\n * @param edition The edition address.\n * @param bps The golden egg fee in basis points.\n */\n function setGoldenEggFee(address edition, uint16 bps) external;\n\n /**\n * @dev Closes the buy for the `edition` permanently.\n *\n * Calling conditions:\n * - The caller must be the edition's owner or admin.\n *\n * @param edition The edition address.\n */\n function freezeBuy(address edition) external;\n\n /**\n * @dev Withdraws all the accrued fees for `affiliate`.\n * @param affiliate The affiliate address.\n */\n function withdrawForAffiliate(address affiliate) external;\n\n /**\n * @dev Withdraws all the accrued fees for the platform.\n */\n function withdrawForPlatform() external;\n\n /**\n * @dev Withdraws all the accrued fees for the golden egg.\n * @param edition The edition address.\n */\n function withdrawForGoldenEgg(address edition) external;\n\n /**\n * @dev Sets the platform fee bps.\n *\n * Calling conditions:\n * - The caller must be the owner of the contract.\n *\n * @param bps The platform fee in basis points.\n */\n function setPlatformFee(uint16 bps) external;\n\n /**\n * @dev Sets the platform fee address.\n *\n * Calling conditions:\n * - The caller must be the owner of the contract.\n *\n * @param addr The platform fee address.\n */\n function setPlatformFeeAddress(address addr) external;\n\n // =============================================================\n // PUBLIC / EXTERNAL VIEW FUNCTIONS\n // =============================================================\n\n /**\n * @dev This is the denominator, in basis points (BPS), for any of the fees.\n * @return The constant value.\n */\n function BPS_DENOMINATOR() external pure returns (uint16);\n\n /**\n * @dev The maximum basis points (BPS) limit allowed for the platform fees.\n * @return The constant value.\n */\n function MAX_PLATFORM_FEE_BPS() external pure returns (uint16);\n\n /**\n * @dev The maximum basis points (BPS) limit allowed for the artist fees.\n * @return The constant value.\n */\n function MAX_ARTIST_FEE_BPS() external pure returns (uint16);\n\n /**\n * @dev The maximum basis points (BPS) limit allowed for the affiliate fees.\n * @return The constant value.\n */\n function MAX_AFFILIATE_FEE_BPS() external pure returns (uint16);\n\n /**\n * @dev The maximum basis points (BPS) limit allowed for the golden egg fees.\n * @return The constant value.\n */\n function MAX_GOLDEN_EGG_FEE_BPS() external pure returns (uint16);\n\n /**\n * @dev Returns the platform fee basis points.\n * @return The configured value.\n */\n function platformFeeBPS() external returns (uint16);\n\n /**\n * @dev Returns the platform fee address.\n * @return The configured value.\n */\n function platformFeeAddress() external returns (address);\n\n /**\n * @dev Returns the information for the Sound Automated Market for `edition`.\n * @param edition The edition address.\n * @return The latest value.\n */\n function samInfo(address edition) external view returns (SAMInfo memory);\n\n /**\n * @dev Returns the total value under the bonding curve for `quantity`, from `fromSupply`.\n * @param edition The edition address.\n * @param fromSupply The starting number of tokens in the bonding curve.\n * @param quantity The number of tokens.\n * @return The computed value.\n */\n function totalValue(\n address edition,\n uint32 fromSupply,\n uint32 quantity\n ) external view returns (uint256);\n\n /**\n * @dev Returns the total amount of ETH required to buy from\n * `supply + supplyForwardOffset` to `supply + supplyForwardOffset + quantity`.\n * @param edition The edition address.\n * @param supplyForwardOffset The offset added to the current supply.\n * @param quantity The number of tokens.\n * @return The computed value.\n */\n function totalBuyPrice(\n address edition,\n uint32 supplyForwardOffset,\n uint32 quantity\n ) external view returns (uint256);\n\n /**\n * @dev Returns the total amount of ETH required to sell from\n * `supply - supplyBackwardOffset` to `supply - supplyBackwardOffset - quantity`.\n * @param edition The edition address.\n * @param supplyBackwardOffset The offset added to the current supply.\n * @param quantity The number of tokens.\n * @return The computed value.\n */\n function totalSellPrice(\n address edition,\n uint32 supplyBackwardOffset,\n uint32 quantity\n ) external view returns (uint256);\n\n /**\n * @dev The total fees accrued for the golden egg on `edition`.\n * @param edition The edition address.\n * @return The latest value.\n */\n function goldenEggFeesAccrued(address edition) external view returns (uint128);\n\n /**\n * @dev The receipient of the golden egg fees on `edition`.\n * If there is no golden egg winner, the `receipient` will be the `edition`.\n * @param edition The edition address.\n * @return receipient The latest value.\n */\n function goldenEggFeeRecipient(address edition) external view returns (address receipient);\n\n /**\n * @dev The total fees accrued for `affiliate`.\n * @param affiliate The affiliate's address.\n * @return The latest value.\n */\n function affiliateFeesAccrued(address affiliate) external view returns (uint128);\n\n /**\n * @dev The total fees accrued for the platform.\n * @return The latest value.\n */\n function platformFeesAccrued() external view returns (uint128);\n\n /**\n * @dev Whether `affiliate` is affiliated for `edition`.\n * @param edition The edition's address.\n * @param affiliate The affiliate's address.\n * @param affiliateProof The Merkle proof needed for verifying the affiliate, if any.\n * @return The computed value.\n */\n function isAffiliatedWithProof(\n address edition,\n address affiliate,\n bytes32[] calldata affiliateProof\n ) external view returns (bool);\n\n /**\n * @dev Whether `affiliate` is affiliated for `edition`.\n * @param edition The edition's address.\n * @param affiliate The affiliate's address.\n * @return The computed value.\n */\n function isAffiliated(address edition, address affiliate) external view returns (bool);\n\n /**\n * @dev Returns the affiliate Merkle root.\n * @param edition The edition's address.\n * @return The latest value.\n */\n function affiliateMerkleRoot(address edition) external view returns (bytes32);\n\n /**\n * @dev Returns the module's interface ID.\n * @return The constant value.\n */\n function moduleInterfaceId() external pure returns (bytes4);\n}\n"},"contracts/modules/utils/BondingCurveLib.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"solady/utils/FixedPointMathLib.sol\";\n\nlibrary BondingCurveLib {\n function sigmoid2(\n uint32 inflectionPoint,\n uint96 inflectionPrice,\n uint32 supply\n ) internal pure returns (uint256) {\n return sigmoid2Sum(inflectionPoint, inflectionPrice, supply, 1);\n }\n\n function sigmoid2Sum(\n uint32 inflectionPoint,\n uint96 inflectionPrice,\n uint32 fromSupply,\n uint32 quantity\n ) internal pure returns (uint256 sum) {\n // We don't need checked arithmetic for the sum because the max possible value\n // is `10384593717069655257060992658309120`,\n // with `inflectionPoint = 1` and `inflectionPrice = 2 ** 96 - 1`.\n // As `10384593717069655257060992658309120 * (2 ** 32 - 1) < 2 ** 256 - 1`,\n // overflow is not possible.\n unchecked {\n uint256 end = uint256(fromSupply) + 1 + uint256(quantity);\n uint256 g = inflectionPoint;\n uint256 h = inflectionPrice;\n for (uint256 s = uint256(fromSupply) + 1; s != end; ++s) {\n if (s >= g) {\n uint256 r = FixedPointMathLib.sqrt((s - ((3 * g) >> 2)) * g);\n sum += FixedPointMathLib.rawDiv((h * r) << 1, g);\n continue;\n }\n sum += FixedPointMathLib.rawDiv(s * s * h, g * g);\n }\n }\n }\n\n function totalBuyPriceAndFeePerBPS(\n uint256 totalSellPrice,\n uint256 totalFeeBPS,\n uint256 maxBPS\n ) internal pure returns (uint256 totalBuyPrice, uint256 feePerBPS) {\n uint256 numer = totalSellPrice * maxBPS;\n uint256 denom = maxBPS - totalFeeBPS;\n unchecked {\n // - Will revert if `denom` is zero.\n // - Won't underflow, as `numer / denom` won't be less than `totalSellPrice`.\n // - Will be zero if `totalFeeBPS` is zero.\n feePerBPS = FixedPointMathLib.rawDiv(numer / denom - totalSellPrice, totalFeeBPS);\n // - Won't overflow.\n totalBuyPrice = feePerBPS * totalFeeBPS + totalSellPrice;\n }\n }\n}\n"},"lib/ERC721A-Upgradeable/contracts/IERC721AUpgradeable.sol":{"content":"// SPDX-License-Identifier: MIT\n// ERC721A Contracts v4.2.3\n// Creator: Chiru Labs\n\npragma solidity ^0.8.4;\n\n/**\n * @dev Interface of ERC721A.\n */\ninterface IERC721AUpgradeable {\n /**\n * The caller must own the token or be an approved operator.\n */\n error ApprovalCallerNotOwnerNorApproved();\n\n /**\n * The token does not exist.\n */\n error ApprovalQueryForNonexistentToken();\n\n /**\n * Cannot query the balance for the zero address.\n */\n error BalanceQueryForZeroAddress();\n\n /**\n * Cannot mint to the zero address.\n */\n error MintToZeroAddress();\n\n /**\n * The quantity of tokens minted must be more than zero.\n */\n error MintZeroQuantity();\n\n /**\n * The token does not exist.\n */\n error OwnerQueryForNonexistentToken();\n\n /**\n * The caller must own the token or be an approved operator.\n */\n error TransferCallerNotOwnerNorApproved();\n\n /**\n * The token must be owned by `from`.\n */\n error TransferFromIncorrectOwner();\n\n /**\n * Cannot safely transfer to a contract that does not implement the\n * ERC721Receiver interface.\n */\n error TransferToNonERC721ReceiverImplementer();\n\n /**\n * Cannot transfer to the zero address.\n */\n error TransferToZeroAddress();\n\n /**\n * The token does not exist.\n */\n error URIQueryForNonexistentToken();\n\n /**\n * The `quantity` minted with ERC2309 exceeds the safety limit.\n */\n error MintERC2309QuantityExceedsLimit();\n\n /**\n * The `extraData` cannot be set on an unintialized ownership slot.\n */\n error OwnershipNotInitializedForExtraData();\n\n // =============================================================\n // STRUCTS\n // =============================================================\n\n struct TokenOwnership {\n // The address of the owner.\n address addr;\n // Stores the start time of ownership with minimal overhead for tokenomics.\n uint64 startTimestamp;\n // Whether the token has been burned.\n bool burned;\n // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.\n uint24 extraData;\n }\n\n // =============================================================\n // TOKEN COUNTERS\n // =============================================================\n\n /**\n * @dev Returns the total number of tokens in existence.\n * Burned tokens will reduce the count.\n * To get the total number of tokens minted, please see {_totalMinted}.\n */\n function totalSupply() external view returns (uint256);\n\n // =============================================================\n // IERC165\n // =============================================================\n\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n\n // =============================================================\n // IERC721\n // =============================================================\n\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables\n * (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in `owner`'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`,\n * checking first that contract recipients are aware of the ERC721 protocol\n * to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be have been allowed to move\n * this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement\n * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external payable;\n\n /**\n * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external payable;\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom}\n * whenever possible.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token\n * by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external payable;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the\n * zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external payable;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom}\n * for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool _approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}.\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n\n // =============================================================\n // IERC721Metadata\n // =============================================================\n\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n\n // =============================================================\n // IERC2309\n // =============================================================\n\n /**\n * @dev Emitted when tokens in `fromTokenId` to `toTokenId`\n * (inclusive) is transferred from `from` to `to`, as defined in the\n * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.\n *\n * See {_mintERC2309} for more details.\n */\n event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to);\n}\n"},"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},"lib/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC2981Upgradeable.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/introspection/IERC165Upgradeable.sol\";\n\n/**\n * @dev Interface for the NFT Royalty Standard.\n *\n * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal\n * support for royalty payments across all NFT marketplaces and ecosystem participants.\n *\n * _Available since v4.5._\n */\ninterface IERC2981Upgradeable is IERC165Upgradeable {\n /**\n * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of\n * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.\n */\n function royaltyInfo(uint256 tokenId, uint256 salePrice)\n external\n view\n returns (address receiver, uint256 royaltyAmount);\n}\n"},"lib/openzeppelin-contracts-upgradeable/contracts/utils/introspection/IERC165Upgradeable.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165Upgradeable {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},"lib/solady/src/auth/Ownable.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Simple single owner authorization mixin.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)\n/// @dev While the ownable portion follows [EIP-173](https://eips.ethereum.org/EIPS/eip-173)\n/// for compatibility, the nomenclature for the 2-step ownership handover\n/// may be unique to this codebase.\nabstract contract Ownable {\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CUSTOM ERRORS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev The caller is not authorized to call the function.\n error Unauthorized();\n\n /// @dev The `newOwner` cannot be the zero address.\n error NewOwnerIsZeroAddress();\n\n /// @dev The `pendingOwner` does not have a valid handover request.\n error NoHandoverRequest();\n\n /// @dev `bytes4(keccak256(bytes(\"Unauthorized()\")))`.\n uint256 private constant _UNAUTHORIZED_ERROR_SELECTOR = 0x82b42900;\n\n /// @dev `bytes4(keccak256(bytes(\"NewOwnerIsZeroAddress()\")))`.\n uint256 private constant _NEW_OWNER_IS_ZERO_ADDRESS_ERROR_SELECTOR = 0x7448fbae;\n\n /// @dev `bytes4(keccak256(bytes(\"NoHandoverRequest()\")))`.\n uint256 private constant _NO_HANDOVER_REQUEST_ERROR_SELECTOR = 0x6f5e8818;\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* EVENTS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev The ownership is transferred from `oldOwner` to `newOwner`.\n /// This event is intentionally kept the same as OpenZeppelin's Ownable to be\n /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),\n /// despite it not being as lightweight as a single argument event.\n event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);\n\n /// @dev An ownership handover to `pendingOwner` has been requested.\n event OwnershipHandoverRequested(address indexed pendingOwner);\n\n /// @dev The ownership handover to `pendingOwner` has been canceled.\n event OwnershipHandoverCanceled(address indexed pendingOwner);\n\n /// @dev `keccak256(bytes(\"OwnershipTransferred(address,address)\"))`.\n uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =\n 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;\n\n /// @dev `keccak256(bytes(\"OwnershipHandoverRequested(address)\"))`.\n uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =\n 0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;\n\n /// @dev `keccak256(bytes(\"OwnershipHandoverCanceled(address)\"))`.\n uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =\n 0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* STORAGE */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev The owner slot is given by: `not(_OWNER_SLOT_NOT)`.\n /// It is intentionally choosen to be a high value\n /// to avoid collision with lower slots.\n /// The choice of manual storage layout is to enable compatibility\n /// with both regular and upgradeable contracts.\n uint256 private constant _OWNER_SLOT_NOT = 0x8b78c6d8;\n\n /// The ownership handover slot of `newOwner` is given by:\n /// ```\n /// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))\n /// let handoverSlot := keccak256(0x00, 0x20)\n /// ```\n /// It stores the expiry timestamp of the two-step ownership handover.\n uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* INTERNAL FUNCTIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Initializes the owner directly without authorization guard.\n /// This function must be called upon initialization,\n /// regardless of whether the contract is upgradeable or not.\n /// This is to enable generalization to both regular and upgradeable contracts,\n /// and to save gas in case the initial owner is not the caller.\n /// For performance reasons, this function will not check if there\n /// is an existing owner.\n function _initializeOwner(address newOwner) internal virtual {\n /// @solidity memory-safe-assembly\n assembly {\n // Clean the upper 96 bits.\n newOwner := shr(96, shl(96, newOwner))\n // Store the new value.\n sstore(not(_OWNER_SLOT_NOT), newOwner)\n // Emit the {OwnershipTransferred} event.\n log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)\n }\n }\n\n /// @dev Sets the owner directly without authorization guard.\n function _setOwner(address newOwner) internal virtual {\n /// @solidity memory-safe-assembly\n assembly {\n let ownerSlot := not(_OWNER_SLOT_NOT)\n // Clean the upper 96 bits.\n newOwner := shr(96, shl(96, newOwner))\n // Emit the {OwnershipTransferred} event.\n log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)\n // Store the new value.\n sstore(ownerSlot, newOwner)\n }\n }\n\n /// @dev Throws if the sender is not the owner.\n function _checkOwner() internal view virtual {\n /// @solidity memory-safe-assembly\n assembly {\n // If the caller is not the stored owner, revert.\n if iszero(eq(caller(), sload(not(_OWNER_SLOT_NOT)))) {\n mstore(0x00, _UNAUTHORIZED_ERROR_SELECTOR)\n revert(0x1c, 0x04)\n }\n }\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* PUBLIC UPDATE FUNCTIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Allows the owner to transfer the ownership to `newOwner`.\n function transferOwnership(address newOwner) public payable virtual onlyOwner {\n /// @solidity memory-safe-assembly\n assembly {\n if iszero(shl(96, newOwner)) {\n mstore(0x00, _NEW_OWNER_IS_ZERO_ADDRESS_ERROR_SELECTOR)\n revert(0x1c, 0x04)\n }\n }\n _setOwner(newOwner);\n }\n\n /// @dev Allows the owner to renounce their ownership.\n function renounceOwnership() public payable virtual onlyOwner {\n _setOwner(address(0));\n }\n\n /// @dev Request a two-step ownership handover to the caller.\n /// The request will be automatically expire in 48 hours (172800 seconds) by default.\n function requestOwnershipHandover() public payable virtual {\n unchecked {\n uint256 expires = block.timestamp + ownershipHandoverValidFor();\n /// @solidity memory-safe-assembly\n assembly {\n // Compute and set the handover slot to `expires`.\n mstore(0x0c, _HANDOVER_SLOT_SEED)\n mstore(0x00, caller())\n sstore(keccak256(0x0c, 0x20), expires)\n // Emit the {OwnershipHandoverRequested} event.\n log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())\n }\n }\n }\n\n /// @dev Cancels the two-step ownership handover to the caller, if any.\n function cancelOwnershipHandover() public payable virtual {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute and set the handover slot to 0.\n mstore(0x0c, _HANDOVER_SLOT_SEED)\n mstore(0x00, caller())\n sstore(keccak256(0x0c, 0x20), 0)\n // Emit the {OwnershipHandoverCanceled} event.\n log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())\n }\n }\n\n /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.\n /// Reverts if there is no existing ownership handover requested by `pendingOwner`.\n function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute and set the handover slot to 0.\n mstore(0x0c, _HANDOVER_SLOT_SEED)\n mstore(0x00, pendingOwner)\n let handoverSlot := keccak256(0x0c, 0x20)\n // If the handover does not exist, or has expired.\n if gt(timestamp(), sload(handoverSlot)) {\n mstore(0x00, _NO_HANDOVER_REQUEST_ERROR_SELECTOR)\n revert(0x1c, 0x04)\n }\n // Set the handover slot to 0.\n sstore(handoverSlot, 0)\n }\n _setOwner(pendingOwner);\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* PUBLIC READ FUNCTIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Returns the owner of the contract.\n function owner() public view virtual returns (address result) {\n /// @solidity memory-safe-assembly\n assembly {\n result := sload(not(_OWNER_SLOT_NOT))\n }\n }\n\n /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.\n function ownershipHandoverExpiresAt(address pendingOwner)\n public\n view\n virtual\n returns (uint256 result)\n {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the handover slot.\n mstore(0x0c, _HANDOVER_SLOT_SEED)\n mstore(0x00, pendingOwner)\n // Load the handover slot.\n result := sload(keccak256(0x0c, 0x20))\n }\n }\n\n /// @dev Returns how long a two-step ownership handover is valid for in seconds.\n function ownershipHandoverValidFor() public view virtual returns (uint64) {\n return 48 * 3600;\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* MODIFIERS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Marks a function as only callable by the owner.\n modifier onlyOwner() virtual {\n _checkOwner();\n _;\n }\n}\n"},"lib/solady/src/auth/OwnableRoles.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"./Ownable.sol\";\n\n/// @notice Simple single owner and multiroles authorization mixin.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)\n/// @dev While the ownable portion follows [EIP-173](https://eips.ethereum.org/EIPS/eip-173)\n/// for compatibility, the nomenclature for the 2-step ownership handover and roles\n/// may be unique to this codebase.\nabstract contract OwnableRoles is Ownable {\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CUSTOM ERRORS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev `bytes4(keccak256(bytes(\"Unauthorized()\")))`.\n uint256 private constant _UNAUTHORIZED_ERROR_SELECTOR = 0x82b42900;\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* EVENTS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev The `user`'s roles is updated to `roles`.\n /// Each bit of `roles` represents whether the role is set.\n event RolesUpdated(address indexed user, uint256 indexed roles);\n\n /// @dev `keccak256(bytes(\"RolesUpdated(address,uint256)\"))`.\n uint256 private constant _ROLES_UPDATED_EVENT_SIGNATURE =\n 0x715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26;\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* STORAGE */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev The role slot of `user` is given by:\n /// ```\n /// mstore(0x00, or(shl(96, user), _ROLE_SLOT_SEED))\n /// let roleSlot := keccak256(0x00, 0x20)\n /// ```\n /// This automatically ignores the upper bits of the `user` in case\n /// they are not clean, as well as keep the `keccak256` under 32-bytes.\n ///\n /// Note: This is equal to `_OWNER_SLOT_NOT` in for gas efficiency.\n uint256 private constant _ROLE_SLOT_SEED = 0x8b78c6d8;\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* INTERNAL FUNCTIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Grants the roles directly without authorization guard.\n /// Each bit of `roles` represents the role to turn on.\n function _grantRoles(address user, uint256 roles) internal virtual {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the role slot.\n mstore(0x0c, _ROLE_SLOT_SEED)\n mstore(0x00, user)\n let roleSlot := keccak256(0x0c, 0x20)\n // Load the current value and `or` it with `roles`.\n roles := or(sload(roleSlot), roles)\n // Store the new value.\n sstore(roleSlot, roles)\n // Emit the {RolesUpdated} event.\n log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles)\n }\n }\n\n /// @dev Removes the roles directly without authorization guard.\n /// Each bit of `roles` represents the role to turn off.\n function _removeRoles(address user, uint256 roles) internal virtual {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the role slot.\n mstore(0x0c, _ROLE_SLOT_SEED)\n mstore(0x00, user)\n let roleSlot := keccak256(0x0c, 0x20)\n // Load the current value.\n let currentRoles := sload(roleSlot)\n // Use `and` to compute the intersection of `currentRoles` and `roles`,\n // `xor` it with `currentRoles` to flip the bits in the intersection.\n roles := xor(currentRoles, and(currentRoles, roles))\n // Then, store the new value.\n sstore(roleSlot, roles)\n // Emit the {RolesUpdated} event.\n log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles)\n }\n }\n\n /// @dev Throws if the sender does not have any of the `roles`.\n function _checkRoles(uint256 roles) internal view virtual {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the role slot.\n mstore(0x0c, _ROLE_SLOT_SEED)\n mstore(0x00, caller())\n // Load the stored value, and if the `and` intersection\n // of the value and `roles` is zero, revert.\n if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {\n mstore(0x00, _UNAUTHORIZED_ERROR_SELECTOR)\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Throws if the sender is not the owner,\n /// and does not have any of the `roles`.\n /// Checks for ownership first, then lazily checks for roles.\n function _checkOwnerOrRoles(uint256 roles) internal view virtual {\n /// @solidity memory-safe-assembly\n assembly {\n // If the caller is not the stored owner.\n // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.\n if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {\n // Compute the role slot.\n mstore(0x0c, _ROLE_SLOT_SEED)\n mstore(0x00, caller())\n // Load the stored value, and if the `and` intersection\n // of the value and `roles` is zero, revert.\n if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {\n mstore(0x00, _UNAUTHORIZED_ERROR_SELECTOR)\n revert(0x1c, 0x04)\n }\n }\n }\n }\n\n /// @dev Throws if the sender does not have any of the `roles`,\n /// and is not the owner.\n /// Checks for roles first, then lazily checks for ownership.\n function _checkRolesOrOwner(uint256 roles) internal view virtual {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the role slot.\n mstore(0x0c, _ROLE_SLOT_SEED)\n mstore(0x00, caller())\n // Load the stored value, and if the `and` intersection\n // of the value and `roles` is zero, revert.\n if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {\n // If the caller is not the stored owner.\n // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.\n if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {\n mstore(0x00, _UNAUTHORIZED_ERROR_SELECTOR)\n revert(0x1c, 0x04)\n }\n }\n }\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* PUBLIC UPDATE FUNCTIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Allows the owner to grant `user` `roles`.\n /// If the `user` already has a role, then it will be an no-op for the role.\n function grantRoles(address user, uint256 roles) public payable virtual onlyOwner {\n _grantRoles(user, roles);\n }\n\n /// @dev Allows the owner to remove `user` `roles`.\n /// If the `user` does not have a role, then it will be an no-op for the role.\n function revokeRoles(address user, uint256 roles) public payable virtual onlyOwner {\n _removeRoles(user, roles);\n }\n\n /// @dev Allow the caller to remove their own roles.\n /// If the caller does not have a role, then it will be an no-op for the role.\n function renounceRoles(uint256 roles) public payable virtual {\n _removeRoles(msg.sender, roles);\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* PUBLIC READ FUNCTIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Returns whether `user` has any of `roles`.\n function hasAnyRole(address user, uint256 roles) public view virtual returns (bool result) {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the role slot.\n mstore(0x0c, _ROLE_SLOT_SEED)\n mstore(0x00, user)\n // Load the stored value, and set the result to whether the\n // `and` intersection of the value and `roles` is not zero.\n result := iszero(iszero(and(sload(keccak256(0x0c, 0x20)), roles)))\n }\n }\n\n /// @dev Returns whether `user` has all of `roles`.\n function hasAllRoles(address user, uint256 roles) public view virtual returns (bool result) {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the role slot.\n mstore(0x0c, _ROLE_SLOT_SEED)\n mstore(0x00, user)\n // Whether the stored value is contains all the set bits in `roles`.\n result := eq(and(sload(keccak256(0x0c, 0x20)), roles), roles)\n }\n }\n\n /// @dev Returns the roles of `user`.\n function rolesOf(address user) public view virtual returns (uint256 roles) {\n /// @solidity memory-safe-assembly\n assembly {\n // Compute the role slot.\n mstore(0x0c, _ROLE_SLOT_SEED)\n mstore(0x00, user)\n // Load the stored value.\n roles := sload(keccak256(0x0c, 0x20))\n }\n }\n\n /// @dev Convenience function to return a `roles` bitmap from an array of `ordinals`.\n /// This is meant for frontends like Etherscan, and is therefore not fully optimized.\n /// Not recommended to be called on-chain.\n function rolesFromOrdinals(uint8[] memory ordinals) public pure returns (uint256 roles) {\n /// @solidity memory-safe-assembly\n assembly {\n for { let i := shl(5, mload(ordinals)) } i { i := sub(i, 0x20) } {\n // We don't need to mask the values of `ordinals`, as Solidity\n // cleans dirty upper bits when storing variables into memory.\n roles := or(shl(mload(add(ordinals, i)), 1), roles)\n }\n }\n }\n\n /// @dev Convenience function to return an array of `ordinals` from the `roles` bitmap.\n /// This is meant for frontends like Etherscan, and is therefore not fully optimized.\n /// Not recommended to be called on-chain.\n function ordinalsFromRoles(uint256 roles) public pure returns (uint8[] memory ordinals) {\n /// @solidity memory-safe-assembly\n assembly {\n // Grab the pointer to the free memory.\n ordinals := mload(0x40)\n let ptr := add(ordinals, 0x20)\n let o := 0\n // The absence of lookup tables, De Bruijn, etc., here is intentional for\n // smaller bytecode, as this function is not meant to be called on-chain.\n for { let t := roles } 1 {} {\n mstore(ptr, o)\n // `shr` 5 is equivalent to multiplying by 0x20.\n // Push back into the ordinals array if the bit is set.\n ptr := add(ptr, shl(5, and(t, 1)))\n o := add(o, 1)\n t := shr(o, roles)\n if iszero(t) { break }\n }\n // Store the length of `ordinals`.\n mstore(ordinals, shr(5, sub(ptr, add(ordinals, 0x20))))\n // Allocate the memory.\n mstore(0x40, ptr)\n }\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* MODIFIERS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Marks a function as only callable by an account with `roles`.\n modifier onlyRoles(uint256 roles) virtual {\n _checkRoles(roles);\n _;\n }\n\n /// @dev Marks a function as only callable by the owner or by an account\n /// with `roles`. Checks for ownership first, then lazily checks for roles.\n modifier onlyOwnerOrRoles(uint256 roles) virtual {\n _checkOwnerOrRoles(roles);\n _;\n }\n\n /// @dev Marks a function as only callable by an account with `roles`\n /// or the owner. Checks for roles first, then lazily checks for ownership.\n modifier onlyRolesOrOwner(uint256 roles) virtual {\n _checkRolesOrOwner(roles);\n _;\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* ROLE CONSTANTS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n // IYKYK\n\n uint256 internal constant _ROLE_0 = 1 << 0;\n uint256 internal constant _ROLE_1 = 1 << 1;\n uint256 internal constant _ROLE_2 = 1 << 2;\n uint256 internal constant _ROLE_3 = 1 << 3;\n uint256 internal constant _ROLE_4 = 1 << 4;\n uint256 internal constant _ROLE_5 = 1 << 5;\n uint256 internal constant _ROLE_6 = 1 << 6;\n uint256 internal constant _ROLE_7 = 1 << 7;\n uint256 internal constant _ROLE_8 = 1 << 8;\n uint256 internal constant _ROLE_9 = 1 << 9;\n uint256 internal constant _ROLE_10 = 1 << 10;\n uint256 internal constant _ROLE_11 = 1 << 11;\n uint256 internal constant _ROLE_12 = 1 << 12;\n uint256 internal constant _ROLE_13 = 1 << 13;\n uint256 internal constant _ROLE_14 = 1 << 14;\n uint256 internal constant _ROLE_15 = 1 << 15;\n uint256 internal constant _ROLE_16 = 1 << 16;\n uint256 internal constant _ROLE_17 = 1 << 17;\n uint256 internal constant _ROLE_18 = 1 << 18;\n uint256 internal constant _ROLE_19 = 1 << 19;\n uint256 internal constant _ROLE_20 = 1 << 20;\n uint256 internal constant _ROLE_21 = 1 << 21;\n uint256 internal constant _ROLE_22 = 1 << 22;\n uint256 internal constant _ROLE_23 = 1 << 23;\n uint256 internal constant _ROLE_24 = 1 << 24;\n uint256 internal constant _ROLE_25 = 1 << 25;\n uint256 internal constant _ROLE_26 = 1 << 26;\n uint256 internal constant _ROLE_27 = 1 << 27;\n uint256 internal constant _ROLE_28 = 1 << 28;\n uint256 internal constant _ROLE_29 = 1 << 29;\n uint256 internal constant _ROLE_30 = 1 << 30;\n uint256 internal constant _ROLE_31 = 1 << 31;\n uint256 internal constant _ROLE_32 = 1 << 32;\n uint256 internal constant _ROLE_33 = 1 << 33;\n uint256 internal constant _ROLE_34 = 1 << 34;\n uint256 internal constant _ROLE_35 = 1 << 35;\n uint256 internal constant _ROLE_36 = 1 << 36;\n uint256 internal constant _ROLE_37 = 1 << 37;\n uint256 internal constant _ROLE_38 = 1 << 38;\n uint256 internal constant _ROLE_39 = 1 << 39;\n uint256 internal constant _ROLE_40 = 1 << 40;\n uint256 internal constant _ROLE_41 = 1 << 41;\n uint256 internal constant _ROLE_42 = 1 << 42;\n uint256 internal constant _ROLE_43 = 1 << 43;\n uint256 internal constant _ROLE_44 = 1 << 44;\n uint256 internal constant _ROLE_45 = 1 << 45;\n uint256 internal constant _ROLE_46 = 1 << 46;\n uint256 internal constant _ROLE_47 = 1 << 47;\n uint256 internal constant _ROLE_48 = 1 << 48;\n uint256 internal constant _ROLE_49 = 1 << 49;\n uint256 internal constant _ROLE_50 = 1 << 50;\n uint256 internal constant _ROLE_51 = 1 << 51;\n uint256 internal constant _ROLE_52 = 1 << 52;\n uint256 internal constant _ROLE_53 = 1 << 53;\n uint256 internal constant _ROLE_54 = 1 << 54;\n uint256 internal constant _ROLE_55 = 1 << 55;\n uint256 internal constant _ROLE_56 = 1 << 56;\n uint256 internal constant _ROLE_57 = 1 << 57;\n uint256 internal constant _ROLE_58 = 1 << 58;\n uint256 internal constant _ROLE_59 = 1 << 59;\n uint256 internal constant _ROLE_60 = 1 << 60;\n uint256 internal constant _ROLE_61 = 1 << 61;\n uint256 internal constant _ROLE_62 = 1 << 62;\n uint256 internal constant _ROLE_63 = 1 << 63;\n uint256 internal constant _ROLE_64 = 1 << 64;\n uint256 internal constant _ROLE_65 = 1 << 65;\n uint256 internal constant _ROLE_66 = 1 << 66;\n uint256 internal constant _ROLE_67 = 1 << 67;\n uint256 internal constant _ROLE_68 = 1 << 68;\n uint256 internal constant _ROLE_69 = 1 << 69;\n uint256 internal constant _ROLE_70 = 1 << 70;\n uint256 internal constant _ROLE_71 = 1 << 71;\n uint256 internal constant _ROLE_72 = 1 << 72;\n uint256 internal constant _ROLE_73 = 1 << 73;\n uint256 internal constant _ROLE_74 = 1 << 74;\n uint256 internal constant _ROLE_75 = 1 << 75;\n uint256 internal constant _ROLE_76 = 1 << 76;\n uint256 internal constant _ROLE_77 = 1 << 77;\n uint256 internal constant _ROLE_78 = 1 << 78;\n uint256 internal constant _ROLE_79 = 1 << 79;\n uint256 internal constant _ROLE_80 = 1 << 80;\n uint256 internal constant _ROLE_81 = 1 << 81;\n uint256 internal constant _ROLE_82 = 1 << 82;\n uint256 internal constant _ROLE_83 = 1 << 83;\n uint256 internal constant _ROLE_84 = 1 << 84;\n uint256 internal constant _ROLE_85 = 1 << 85;\n uint256 internal constant _ROLE_86 = 1 << 86;\n uint256 internal constant _ROLE_87 = 1 << 87;\n uint256 internal constant _ROLE_88 = 1 << 88;\n uint256 internal constant _ROLE_89 = 1 << 89;\n uint256 internal constant _ROLE_90 = 1 << 90;\n uint256 internal constant _ROLE_91 = 1 << 91;\n uint256 internal constant _ROLE_92 = 1 << 92;\n uint256 internal constant _ROLE_93 = 1 << 93;\n uint256 internal constant _ROLE_94 = 1 << 94;\n uint256 internal constant _ROLE_95 = 1 << 95;\n uint256 internal constant _ROLE_96 = 1 << 96;\n uint256 internal constant _ROLE_97 = 1 << 97;\n uint256 internal constant _ROLE_98 = 1 << 98;\n uint256 internal constant _ROLE_99 = 1 << 99;\n uint256 internal constant _ROLE_100 = 1 << 100;\n uint256 internal constant _ROLE_101 = 1 << 101;\n uint256 internal constant _ROLE_102 = 1 << 102;\n uint256 internal constant _ROLE_103 = 1 << 103;\n uint256 internal constant _ROLE_104 = 1 << 104;\n uint256 internal constant _ROLE_105 = 1 << 105;\n uint256 internal constant _ROLE_106 = 1 << 106;\n uint256 internal constant _ROLE_107 = 1 << 107;\n uint256 internal constant _ROLE_108 = 1 << 108;\n uint256 internal constant _ROLE_109 = 1 << 109;\n uint256 internal constant _ROLE_110 = 1 << 110;\n uint256 internal constant _ROLE_111 = 1 << 111;\n uint256 internal constant _ROLE_112 = 1 << 112;\n uint256 internal constant _ROLE_113 = 1 << 113;\n uint256 internal constant _ROLE_114 = 1 << 114;\n uint256 internal constant _ROLE_115 = 1 << 115;\n uint256 internal constant _ROLE_116 = 1 << 116;\n uint256 internal constant _ROLE_117 = 1 << 117;\n uint256 internal constant _ROLE_118 = 1 << 118;\n uint256 internal constant _ROLE_119 = 1 << 119;\n uint256 internal constant _ROLE_120 = 1 << 120;\n uint256 internal constant _ROLE_121 = 1 << 121;\n uint256 internal constant _ROLE_122 = 1 << 122;\n uint256 internal constant _ROLE_123 = 1 << 123;\n uint256 internal constant _ROLE_124 = 1 << 124;\n uint256 internal constant _ROLE_125 = 1 << 125;\n uint256 internal constant _ROLE_126 = 1 << 126;\n uint256 internal constant _ROLE_127 = 1 << 127;\n uint256 internal constant _ROLE_128 = 1 << 128;\n uint256 internal constant _ROLE_129 = 1 << 129;\n uint256 internal constant _ROLE_130 = 1 << 130;\n uint256 internal constant _ROLE_131 = 1 << 131;\n uint256 internal constant _ROLE_132 = 1 << 132;\n uint256 internal constant _ROLE_133 = 1 << 133;\n uint256 internal constant _ROLE_134 = 1 << 134;\n uint256 internal constant _ROLE_135 = 1 << 135;\n uint256 internal constant _ROLE_136 = 1 << 136;\n uint256 internal constant _ROLE_137 = 1 << 137;\n uint256 internal constant _ROLE_138 = 1 << 138;\n uint256 internal constant _ROLE_139 = 1 << 139;\n uint256 internal constant _ROLE_140 = 1 << 140;\n uint256 internal constant _ROLE_141 = 1 << 141;\n uint256 internal constant _ROLE_142 = 1 << 142;\n uint256 internal constant _ROLE_143 = 1 << 143;\n uint256 internal constant _ROLE_144 = 1 << 144;\n uint256 internal constant _ROLE_145 = 1 << 145;\n uint256 internal constant _ROLE_146 = 1 << 146;\n uint256 internal constant _ROLE_147 = 1 << 147;\n uint256 internal constant _ROLE_148 = 1 << 148;\n uint256 internal constant _ROLE_149 = 1 << 149;\n uint256 internal constant _ROLE_150 = 1 << 150;\n uint256 internal constant _ROLE_151 = 1 << 151;\n uint256 internal constant _ROLE_152 = 1 << 152;\n uint256 internal constant _ROLE_153 = 1 << 153;\n uint256 internal constant _ROLE_154 = 1 << 154;\n uint256 internal constant _ROLE_155 = 1 << 155;\n uint256 internal constant _ROLE_156 = 1 << 156;\n uint256 internal constant _ROLE_157 = 1 << 157;\n uint256 internal constant _ROLE_158 = 1 << 158;\n uint256 internal constant _ROLE_159 = 1 << 159;\n uint256 internal constant _ROLE_160 = 1 << 160;\n uint256 internal constant _ROLE_161 = 1 << 161;\n uint256 internal constant _ROLE_162 = 1 << 162;\n uint256 internal constant _ROLE_163 = 1 << 163;\n uint256 internal constant _ROLE_164 = 1 << 164;\n uint256 internal constant _ROLE_165 = 1 << 165;\n uint256 internal constant _ROLE_166 = 1 << 166;\n uint256 internal constant _ROLE_167 = 1 << 167;\n uint256 internal constant _ROLE_168 = 1 << 168;\n uint256 internal constant _ROLE_169 = 1 << 169;\n uint256 internal constant _ROLE_170 = 1 << 170;\n uint256 internal constant _ROLE_171 = 1 << 171;\n uint256 internal constant _ROLE_172 = 1 << 172;\n uint256 internal constant _ROLE_173 = 1 << 173;\n uint256 internal constant _ROLE_174 = 1 << 174;\n uint256 internal constant _ROLE_175 = 1 << 175;\n uint256 internal constant _ROLE_176 = 1 << 176;\n uint256 internal constant _ROLE_177 = 1 << 177;\n uint256 internal constant _ROLE_178 = 1 << 178;\n uint256 internal constant _ROLE_179 = 1 << 179;\n uint256 internal constant _ROLE_180 = 1 << 180;\n uint256 internal constant _ROLE_181 = 1 << 181;\n uint256 internal constant _ROLE_182 = 1 << 182;\n uint256 internal constant _ROLE_183 = 1 << 183;\n uint256 internal constant _ROLE_184 = 1 << 184;\n uint256 internal constant _ROLE_185 = 1 << 185;\n uint256 internal constant _ROLE_186 = 1 << 186;\n uint256 internal constant _ROLE_187 = 1 << 187;\n uint256 internal constant _ROLE_188 = 1 << 188;\n uint256 internal constant _ROLE_189 = 1 << 189;\n uint256 internal constant _ROLE_190 = 1 << 190;\n uint256 internal constant _ROLE_191 = 1 << 191;\n uint256 internal constant _ROLE_192 = 1 << 192;\n uint256 internal constant _ROLE_193 = 1 << 193;\n uint256 internal constant _ROLE_194 = 1 << 194;\n uint256 internal constant _ROLE_195 = 1 << 195;\n uint256 internal constant _ROLE_196 = 1 << 196;\n uint256 internal constant _ROLE_197 = 1 << 197;\n uint256 internal constant _ROLE_198 = 1 << 198;\n uint256 internal constant _ROLE_199 = 1 << 199;\n uint256 internal constant _ROLE_200 = 1 << 200;\n uint256 internal constant _ROLE_201 = 1 << 201;\n uint256 internal constant _ROLE_202 = 1 << 202;\n uint256 internal constant _ROLE_203 = 1 << 203;\n uint256 internal constant _ROLE_204 = 1 << 204;\n uint256 internal constant _ROLE_205 = 1 << 205;\n uint256 internal constant _ROLE_206 = 1 << 206;\n uint256 internal constant _ROLE_207 = 1 << 207;\n uint256 internal constant _ROLE_208 = 1 << 208;\n uint256 internal constant _ROLE_209 = 1 << 209;\n uint256 internal constant _ROLE_210 = 1 << 210;\n uint256 internal constant _ROLE_211 = 1 << 211;\n uint256 internal constant _ROLE_212 = 1 << 212;\n uint256 internal constant _ROLE_213 = 1 << 213;\n uint256 internal constant _ROLE_214 = 1 << 214;\n uint256 internal constant _ROLE_215 = 1 << 215;\n uint256 internal constant _ROLE_216 = 1 << 216;\n uint256 internal constant _ROLE_217 = 1 << 217;\n uint256 internal constant _ROLE_218 = 1 << 218;\n uint256 internal constant _ROLE_219 = 1 << 219;\n uint256 internal constant _ROLE_220 = 1 << 220;\n uint256 internal constant _ROLE_221 = 1 << 221;\n uint256 internal constant _ROLE_222 = 1 << 222;\n uint256 internal constant _ROLE_223 = 1 << 223;\n uint256 internal constant _ROLE_224 = 1 << 224;\n uint256 internal constant _ROLE_225 = 1 << 225;\n uint256 internal constant _ROLE_226 = 1 << 226;\n uint256 internal constant _ROLE_227 = 1 << 227;\n uint256 internal constant _ROLE_228 = 1 << 228;\n uint256 internal constant _ROLE_229 = 1 << 229;\n uint256 internal constant _ROLE_230 = 1 << 230;\n uint256 internal constant _ROLE_231 = 1 << 231;\n uint256 internal constant _ROLE_232 = 1 << 232;\n uint256 internal constant _ROLE_233 = 1 << 233;\n uint256 internal constant _ROLE_234 = 1 << 234;\n uint256 internal constant _ROLE_235 = 1 << 235;\n uint256 internal constant _ROLE_236 = 1 << 236;\n uint256 internal constant _ROLE_237 = 1 << 237;\n uint256 internal constant _ROLE_238 = 1 << 238;\n uint256 internal constant _ROLE_239 = 1 << 239;\n uint256 internal constant _ROLE_240 = 1 << 240;\n uint256 internal constant _ROLE_241 = 1 << 241;\n uint256 internal constant _ROLE_242 = 1 << 242;\n uint256 internal constant _ROLE_243 = 1 << 243;\n uint256 internal constant _ROLE_244 = 1 << 244;\n uint256 internal constant _ROLE_245 = 1 << 245;\n uint256 internal constant _ROLE_246 = 1 << 246;\n uint256 internal constant _ROLE_247 = 1 << 247;\n uint256 internal constant _ROLE_248 = 1 << 248;\n uint256 internal constant _ROLE_249 = 1 << 249;\n uint256 internal constant _ROLE_250 = 1 << 250;\n uint256 internal constant _ROLE_251 = 1 << 251;\n uint256 internal constant _ROLE_252 = 1 << 252;\n uint256 internal constant _ROLE_253 = 1 << 253;\n uint256 internal constant _ROLE_254 = 1 << 254;\n uint256 internal constant _ROLE_255 = 1 << 255;\n}\n"},"lib/solady/src/utils/FixedPointMathLib.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Arithmetic library with operations for fixed-point numbers.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/FixedPointMathLib.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)\nlibrary FixedPointMathLib {\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CUSTOM ERRORS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev The operation failed, as the output exceeds the maximum value of uint256.\n error ExpOverflow();\n\n /// @dev The operation failed, as the output exceeds the maximum value of uint256.\n error FactorialOverflow();\n\n /// @dev The operation failed, due to an multiplication overflow.\n error MulWadFailed();\n\n /// @dev The operation failed, either due to a\n /// multiplication overflow, or a division by a zero.\n error DivWadFailed();\n\n /// @dev The multiply-divide operation failed, either due to a\n /// multiplication overflow, or a division by a zero.\n error MulDivFailed();\n\n /// @dev The division failed, as the denominator is zero.\n error DivFailed();\n\n /// @dev The full precision multiply-divide operation failed, either due\n /// to the result being larger than 256 bits, or a division by a zero.\n error FullMulDivFailed();\n\n /// @dev The output is undefined, as the input is less-than-or-equal to zero.\n error LnWadUndefined();\n\n /// @dev The output is undefined, as the input is zero.\n error Log2Undefined();\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CONSTANTS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev The scalar of ETH and most ERC20s.\n uint256 internal constant WAD = 1e18;\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* SIMPLIFIED FIXED POINT OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Equivalent to `(x * y) / WAD` rounded down.\n function mulWad(uint256 x, uint256 y) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.\n if mul(y, gt(x, div(not(0), y))) {\n // Store the function selector of `MulWadFailed()`.\n mstore(0x00, 0xbac65e5b)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n z := div(mul(x, y), WAD)\n }\n }\n\n /// @dev Equivalent to `(x * y) / WAD` rounded up.\n function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.\n if mul(y, gt(x, div(not(0), y))) {\n // Store the function selector of `MulWadFailed()`.\n mstore(0x00, 0xbac65e5b)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD))\n }\n }\n\n /// @dev Equivalent to `(x * WAD) / y` rounded down.\n function divWad(uint256 x, uint256 y) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n // Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`.\n if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {\n // Store the function selector of `DivWadFailed()`.\n mstore(0x00, 0x7c5f487d)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n z := div(mul(x, WAD), y)\n }\n }\n\n /// @dev Equivalent to `(x * WAD) / y` rounded up.\n function divWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n // Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`.\n if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) {\n // Store the function selector of `DivWadFailed()`.\n mstore(0x00, 0x7c5f487d)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y))\n }\n }\n\n /// @dev Equivalent to `x` to the power of `y`.\n /// because `x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)`.\n function powWad(int256 x, int256 y) internal pure returns (int256) {\n // Using `ln(x)` means `x` must be greater than 0.\n return expWad((lnWad(x) * y) / int256(WAD));\n }\n\n /// @dev Returns `exp(x)`, denominated in `WAD`.\n function expWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n // When the result is < 0.5 we return zero. This happens when\n // x <= floor(log(0.5e18) * 1e18) ~ -42e18\n if (x <= -42139678854452767551) return r;\n\n /// @solidity memory-safe-assembly\n assembly {\n // When the result is > (2**255 - 1) / 1e18 we can not represent it as an\n // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135.\n if iszero(slt(x, 135305999368893231589)) {\n // Store the function selector of `ExpOverflow()`.\n mstore(0x00, 0xa37bfec9)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n }\n\n // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96\n // for more intermediate precision and a binary basis. This base conversion\n // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.\n x = (x << 78) / 5 ** 18;\n\n // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers\n // of two such that exp(x) = exp(x') * 2**k, where k is an integer.\n // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).\n int256 k = ((x << 96) / 54916777467707473351141471128 + 2 ** 95) >> 96;\n x = x - k * 54916777467707473351141471128;\n\n // k is in the range [-61, 195].\n\n // Evaluate using a (6, 7)-term rational approximation.\n // p is made monic, we'll multiply by a scale factor later.\n int256 y = x + 1346386616545796478920950773328;\n y = ((y * x) >> 96) + 57155421227552351082224309758442;\n int256 p = y + x - 94201549194550492254356042504812;\n p = ((p * y) >> 96) + 28719021644029726153956944680412240;\n p = p * x + (4385272521454847904659076985693276 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n int256 q = x - 2855989394907223263936484059900;\n q = ((q * x) >> 96) + 50020603652535783019961831881945;\n q = ((q * x) >> 96) - 533845033583426703283633433725380;\n q = ((q * x) >> 96) + 3604857256930695427073651918091429;\n q = ((q * x) >> 96) - 14423608567350463180887372962807573;\n q = ((q * x) >> 96) + 26449188498355588339934803723976023;\n\n /// @solidity memory-safe-assembly\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial won't have zeros in the domain as all its roots are complex.\n // No scaling is necessary because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r should be in the range (0.09, 0.25) * 2**96.\n\n // We now need to multiply r by:\n // * the scale factor s = ~6.031367120.\n // * the 2**k factor from the range reduction.\n // * the 1e18 / 2**96 factor for base conversion.\n // We do this all at once, with an intermediate result in 2**213\n // basis, so the final right shift is always by a positive amount.\n r = int256(\n (uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k)\n );\n }\n }\n\n /// @dev Returns `ln(x)`, denominated in `WAD`.\n function lnWad(int256 x) internal pure returns (int256 r) {\n unchecked {\n /// @solidity memory-safe-assembly\n assembly {\n if iszero(sgt(x, 0)) {\n // Store the function selector of `LnWadUndefined()`.\n mstore(0x00, 0x1615e638)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n }\n\n // We want to convert x from 10**18 fixed point to 2**96 fixed point.\n // We do this by multiplying by 2**96 / 10**18. But since\n // ln(x * C) = ln(x) + ln(C), we can simply do nothing here\n // and add ln(2**96 / 10**18) at the end.\n\n // Compute k = log2(x) - 96.\n int256 k;\n /// @solidity memory-safe-assembly\n assembly {\n let v := x\n k := shl(7, lt(0xffffffffffffffffffffffffffffffff, v))\n k := or(k, shl(6, lt(0xffffffffffffffff, shr(k, v))))\n k := or(k, shl(5, lt(0xffffffff, shr(k, v))))\n\n // For the remaining 32 bits, use a De Bruijn lookup.\n // See: https://graphics.stanford.edu/~seander/bithacks.html\n v := shr(k, v)\n v := or(v, shr(1, v))\n v := or(v, shr(2, v))\n v := or(v, shr(4, v))\n v := or(v, shr(8, v))\n v := or(v, shr(16, v))\n\n // forgefmt: disable-next-item\n k := sub(or(k, byte(shr(251, mul(v, shl(224, 0x07c4acdd))),\n 0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f)), 96)\n }\n\n // Reduce range of x to (1, 2) * 2**96\n // ln(2^k * x) = k * ln(2) + ln(x)\n x <<= uint256(159 - k);\n x = int256(uint256(x) >> 159);\n\n // Evaluate using a (8, 8)-term rational approximation.\n // p is made monic, we will multiply by a scale factor later.\n int256 p = x + 3273285459638523848632254066296;\n p = ((p * x) >> 96) + 24828157081833163892658089445524;\n p = ((p * x) >> 96) + 43456485725739037958740375743393;\n p = ((p * x) >> 96) - 11111509109440967052023855526967;\n p = ((p * x) >> 96) - 45023709667254063763336534515857;\n p = ((p * x) >> 96) - 14706773417378608786704636184526;\n p = p * x - (795164235651350426258249787498 << 96);\n\n // We leave p in 2**192 basis so we don't need to scale it back up for the division.\n // q is monic by convention.\n int256 q = x + 5573035233440673466300451813936;\n q = ((q * x) >> 96) + 71694874799317883764090561454958;\n q = ((q * x) >> 96) + 283447036172924575727196451306956;\n q = ((q * x) >> 96) + 401686690394027663651624208769553;\n q = ((q * x) >> 96) + 204048457590392012362485061816622;\n q = ((q * x) >> 96) + 31853899698501571402653359427138;\n q = ((q * x) >> 96) + 909429971244387300277376558375;\n /// @solidity memory-safe-assembly\n assembly {\n // Div in assembly because solidity adds a zero check despite the unchecked.\n // The q polynomial is known not to have zeros in the domain.\n // No scaling required because p is already 2**96 too large.\n r := sdiv(p, q)\n }\n\n // r is in the range (0, 0.125) * 2**96\n\n // Finalization, we need to:\n // * multiply by the scale factor s = 5.549…\n // * add ln(2**96 / 10**18)\n // * add k * ln(2)\n // * multiply by 10**18 / 2**96 = 5**18 >> 78\n\n // mul s * 5e18 * 2**96, base is now 5**18 * 2**192\n r *= 1677202110996718588342820967067443963516166;\n // add ln(2) * k * 5e18 * 2**192\n r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k;\n // add ln(2**96 / 10**18) * 5e18 * 2**192\n r += 600920179829731861736702779321621459595472258049074101567377883020018308;\n // base conversion: mul 2**18 / 2**192\n r >>= 174;\n }\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* GENERAL NUMBER UTILITIES */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Calculates `floor(a * b / d)` with full precision.\n /// Throws if result overflows a uint256 or when `d` is zero.\n /// Credit to Remco Bloemen under MIT license: https://2π.com/21/muldiv\n function fullMulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {\n /// @solidity memory-safe-assembly\n assembly {\n // forgefmt: disable-next-item\n for {} 1 {} {\n // 512-bit multiply `[prod1 prod0] = x * y`.\n // Compute the product mod `2**256` and mod `2**256 - 1`\n // then use the Chinese Remainder Theorem to reconstruct\n // the 512 bit result. The result is stored in two 256\n // variables such that `product = prod1 * 2**256 + prod0`.\n\n // Least significant 256 bits of the product.\n let prod0 := mul(x, y)\n let mm := mulmod(x, y, not(0))\n // Most significant 256 bits of the product.\n let prod1 := sub(mm, add(prod0, lt(mm, prod0)))\n\n // Handle non-overflow cases, 256 by 256 division.\n if iszero(prod1) {\n if iszero(d) {\n // Store the function selector of `FullMulDivFailed()`.\n mstore(0x00, 0xae47f702)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n result := div(prod0, d)\n break \n }\n\n // Make sure the result is less than `2**256`.\n // Also prevents `d == 0`.\n if iszero(gt(d, prod1)) {\n // Store the function selector of `FullMulDivFailed()`.\n mstore(0x00, 0xae47f702)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from `[prod1 prod0]`.\n // Compute remainder using mulmod.\n let remainder := mulmod(x, y, d)\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n // Factor powers of two out of `d`.\n // Compute largest power of two divisor of `d`.\n // Always greater or equal to 1.\n let twos := and(d, sub(0, d))\n // Divide d by power of two.\n d := div(d, twos)\n // Divide [prod1 prod0] by the factors of two.\n prod0 := div(prod0, twos)\n // Shift in bits from `prod1` into `prod0`. For this we need\n // to flip `twos` such that it is `2**256 / twos`.\n // If `twos` is zero, then it becomes one.\n prod0 := or(prod0, mul(prod1, add(div(sub(0, twos), twos), 1)))\n // Invert `d mod 2**256`\n // Now that `d` is an odd number, it has an inverse\n // modulo `2**256` such that `d * inv = 1 mod 2**256`.\n // Compute the inverse by starting with a seed that is correct\n // correct for four bits. That is, `d * inv = 1 mod 2**4`.\n let inv := xor(mul(3, d), 2)\n // Now use Newton-Raphson iteration to improve the precision.\n // Thanks to Hensel's lifting lemma, this also works in modular\n // arithmetic, doubling the correct bits in each step.\n inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**8\n inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**16\n inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**32\n inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**64\n inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**128\n result := mul(prod0, mul(inv, sub(2, mul(d, inv)))) // inverse mod 2**256\n break\n }\n }\n }\n\n /// @dev Calculates `floor(x * y / d)` with full precision, rounded up.\n /// Throws if result overflows a uint256 or when `d` is zero.\n /// Credit to Uniswap-v3-core under MIT license:\n /// https://github.com/Uniswap/v3-core/blob/contracts/libraries/FullMath.sol\n function fullMulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) {\n result = fullMulDiv(x, y, d);\n /// @solidity memory-safe-assembly\n assembly {\n if mulmod(x, y, d) {\n if iszero(add(result, 1)) {\n // Store the function selector of `FullMulDivFailed()`.\n mstore(0x00, 0xae47f702)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n result := add(result, 1)\n }\n }\n }\n\n /// @dev Returns `floor(x * y / d)`.\n /// Reverts if `x * y` overflows, or `d` is zero.\n function mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n // Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y))\n if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {\n // Store the function selector of `MulDivFailed()`.\n mstore(0x00, 0xad251c27)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n z := div(mul(x, y), d)\n }\n }\n\n /// @dev Returns `ceil(x * y / d)`.\n /// Reverts if `x * y` overflows, or `d` is zero.\n function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n // Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y))\n if iszero(mul(d, iszero(mul(y, gt(x, div(not(0), y)))))) {\n // Store the function selector of `MulDivFailed()`.\n mstore(0x00, 0xad251c27)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n z := add(iszero(iszero(mod(mul(x, y), d))), div(mul(x, y), d))\n }\n }\n\n /// @dev Returns `ceil(x / d)`.\n /// Reverts if `d` is zero.\n function divUp(uint256 x, uint256 d) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n if iszero(d) {\n // Store the function selector of `DivFailed()`.\n mstore(0x00, 0x65244e4e)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n z := add(iszero(iszero(mod(x, d))), div(x, d))\n }\n }\n\n /// @dev Returns `max(0, x - y)`.\n function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n z := mul(gt(x, y), sub(x, y))\n }\n }\n\n /// @dev Returns the square root of `x`.\n function sqrt(uint256 x) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n // `floor(sqrt(2**15)) = 181`. `sqrt(2**15) - 181 = 2.84`.\n z := 181 // The \"correct\" value is 1, but this saves a multiplication later.\n\n // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad\n // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.\n\n // Let `y = x / 2**r`.\n // We check `y >= 2**(k + 8)` but shift right by `k` bits\n // each branch to ensure that if `x >= 256`, then `y >= 256`.\n let r := shl(7, lt(0xffffffffffffffffffffffffffffffffff, x))\n r := or(r, shl(6, lt(0xffffffffffffffffff, shr(r, x))))\n r := or(r, shl(5, lt(0xffffffffff, shr(r, x))))\n r := or(r, shl(4, lt(0xffffff, shr(r, x))))\n z := shl(shr(1, r), z)\n\n // Goal was to get `z*z*y` within a small factor of `x`. More iterations could\n // get y in a tighter range. Currently, we will have y in `[256, 256*(2**16))`.\n // We ensured `y >= 256` so that the relative difference between `y` and `y+1` is small.\n // That's not possible if `x < 256` but we can just verify those cases exhaustively.\n\n // Now, `z*z*y <= x < z*z*(y+1)`, and `y <= 2**(16+8)`, and either `y >= 256`, or `x < 256`.\n // Correctness can be checked exhaustively for `x < 256`, so we assume `y >= 256`.\n // Then `z*sqrt(y)` is within `sqrt(257)/sqrt(256)` of `sqrt(x)`, or about 20bps.\n\n // For `s` in the range `[1/256, 256]`, the estimate `f(s) = (181/1024) * (s+1)`\n // is in the range `(1/2.84 * sqrt(s), 2.84 * sqrt(s))`,\n // with largest error when `s = 1` and when `s = 256` or `1/256`.\n\n // Since `y` is in `[256, 256*(2**16))`, let `a = y/65536`, so that `a` is in `[1/256, 256)`.\n // Then we can estimate `sqrt(y)` using\n // `sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2**18`.\n\n // There is no overflow risk here since `y < 2**136` after the first branch above.\n z := shr(18, mul(z, add(shr(r, x), 65536))) // A `mul()` is saved from starting `z` at 181.\n\n // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n z := shr(1, add(z, div(x, z)))\n\n // If `x+1` is a perfect square, the Babylonian method cycles between\n // `floor(sqrt(x))` and `ceil(sqrt(x))`. This statement ensures we return floor.\n // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division\n // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.\n // If you don't care whether the floor or ceil square root is returned, you can remove this statement.\n z := sub(z, lt(div(x, z), z))\n }\n }\n\n /// @dev Returns the factorial of `x`.\n function factorial(uint256 x) internal pure returns (uint256 result) {\n /// @solidity memory-safe-assembly\n assembly {\n for {} 1 {} {\n if iszero(lt(10, x)) {\n // forgefmt: disable-next-item\n result := and(\n shr(mul(22, x), 0x375f0016260009d80004ec0002d00001e0000180000180000200000400001),\n 0x3fffff\n )\n break\n }\n if iszero(lt(57, x)) {\n let end := 31\n result := 8222838654177922817725562880000000\n if iszero(lt(end, x)) {\n end := 10\n result := 3628800\n }\n for { let w := not(0) } 1 {} {\n result := mul(result, x)\n x := add(x, w)\n if eq(x, end) { break }\n }\n break\n }\n // Store the function selector of `FactorialOverflow()`.\n mstore(0x00, 0xaba0f2a2)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Returns the log2 of `x`.\n /// Equivalent to computing the index of the most significant bit (MSB) of `x`.\n function log2(uint256 x) internal pure returns (uint256 r) {\n /// @solidity memory-safe-assembly\n assembly {\n if iszero(x) {\n // Store the function selector of `Log2Undefined()`.\n mstore(0x00, 0x5be3aa5c)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n\n r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))\n r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))\n r := or(r, shl(5, lt(0xffffffff, shr(r, x))))\n\n // For the remaining 32 bits, use a De Bruijn lookup.\n // See: https://graphics.stanford.edu/~seander/bithacks.html\n x := shr(r, x)\n x := or(x, shr(1, x))\n x := or(x, shr(2, x))\n x := or(x, shr(4, x))\n x := or(x, shr(8, x))\n x := or(x, shr(16, x))\n\n // forgefmt: disable-next-item\n r := or(r, byte(shr(251, mul(x, shl(224, 0x07c4acdd))),\n 0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f))\n }\n }\n\n /// @dev Returns the log2 of `x`, rounded up.\n function log2Up(uint256 x) internal pure returns (uint256 r) {\n unchecked {\n uint256 isNotPo2;\n assembly {\n isNotPo2 := iszero(iszero(and(x, sub(x, 1))))\n }\n return log2(x) + isNotPo2;\n }\n }\n\n /// @dev Returns the average of `x` and `y`.\n function avg(uint256 x, uint256 y) internal pure returns (uint256 z) {\n unchecked {\n z = (x & y) + ((x ^ y) >> 1);\n }\n }\n\n /// @dev Returns the average of `x` and `y`.\n function avg(int256 x, int256 y) internal pure returns (int256 z) {\n unchecked {\n z = (x >> 1) + (y >> 1) + (((x & 1) + (y & 1)) >> 1);\n }\n }\n\n /// @dev Returns the absolute value of `x`.\n function abs(int256 x) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n let mask := sub(0, shr(255, x))\n z := xor(mask, add(mask, x))\n }\n }\n\n /// @dev Returns the absolute distance between `x` and `y`.\n function dist(int256 x, int256 y) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n let a := sub(y, x)\n z := xor(a, mul(xor(a, sub(x, y)), sgt(x, y)))\n }\n }\n\n /// @dev Returns the minimum of `x` and `y`.\n function min(uint256 x, uint256 y) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n z := xor(x, mul(xor(x, y), lt(y, x)))\n }\n }\n\n /// @dev Returns the minimum of `x` and `y`.\n function min(int256 x, int256 y) internal pure returns (int256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n z := xor(x, mul(xor(x, y), slt(y, x)))\n }\n }\n\n /// @dev Returns the maximum of `x` and `y`.\n function max(uint256 x, uint256 y) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n z := xor(x, mul(xor(x, y), gt(y, x)))\n }\n }\n\n /// @dev Returns the maximum of `x` and `y`.\n function max(int256 x, int256 y) internal pure returns (int256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n z := xor(x, mul(xor(x, y), sgt(y, x)))\n }\n }\n\n /// @dev Returns `x`, bounded to `minValue` and `maxValue`.\n function clamp(uint256 x, uint256 minValue, uint256 maxValue)\n internal\n pure\n returns (uint256 z)\n {\n z = min(max(x, minValue), maxValue);\n }\n\n /// @dev Returns `x`, bounded to `minValue` and `maxValue`.\n function clamp(int256 x, int256 minValue, int256 maxValue) internal pure returns (int256 z) {\n z = min(max(x, minValue), maxValue);\n }\n\n /// @dev Returns greatest common divisor of `x` and `y`.\n function gcd(uint256 x, uint256 y) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n // forgefmt: disable-next-item\n for { z := x } y {} {\n let t := y\n y := mod(z, y)\n z := t\n }\n }\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* RAW NUMBER OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Returns `x + y`, without checking for overflow.\n function rawAdd(uint256 x, uint256 y) internal pure returns (uint256 z) {\n unchecked {\n z = x + y;\n }\n }\n\n /// @dev Returns `x + y`, without checking for overflow.\n function rawAdd(int256 x, int256 y) internal pure returns (int256 z) {\n unchecked {\n z = x + y;\n }\n }\n\n /// @dev Returns `x - y`, without checking for underflow.\n function rawSub(uint256 x, uint256 y) internal pure returns (uint256 z) {\n unchecked {\n z = x - y;\n }\n }\n\n /// @dev Returns `x - y`, without checking for underflow.\n function rawSub(int256 x, int256 y) internal pure returns (int256 z) {\n unchecked {\n z = x - y;\n }\n }\n\n /// @dev Returns `x * y`, without checking for overflow.\n function rawMul(uint256 x, uint256 y) internal pure returns (uint256 z) {\n unchecked {\n z = x * y;\n }\n }\n\n /// @dev Returns `x * y`, without checking for overflow.\n function rawMul(int256 x, int256 y) internal pure returns (int256 z) {\n unchecked {\n z = x * y;\n }\n }\n\n /// @dev Returns `x / y`, returning 0 if `y` is zero.\n function rawDiv(uint256 x, uint256 y) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n z := div(x, y)\n }\n }\n\n /// @dev Returns `x / y`, returning 0 if `y` is zero.\n function rawSDiv(int256 x, int256 y) internal pure returns (int256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n z := sdiv(x, y)\n }\n }\n\n /// @dev Returns `x % y`, returning 0 if `y` is zero.\n function rawMod(uint256 x, uint256 y) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n z := mod(x, y)\n }\n }\n\n /// @dev Returns `x % y`, returning 0 if `y` is zero.\n function rawSMod(int256 x, int256 y) internal pure returns (int256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n z := smod(x, y)\n }\n }\n\n /// @dev Returns `(x + y) % d`, return 0 if `d` if zero.\n function rawAddMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n z := addmod(x, y, d)\n }\n }\n\n /// @dev Returns `(x * y) % d`, return 0 if `d` if zero.\n function rawMulMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {\n /// @solidity memory-safe-assembly\n assembly {\n z := mulmod(x, y, d)\n }\n }\n}\n"},"lib/solady/src/utils/MerkleProofLib.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/MerkleProofLib.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol)\n/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol)\nlibrary MerkleProofLib {\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* MERKLE PROOF VERIFICATION OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`.\n function verify(bytes32[] calldata proof, bytes32 root, bytes32 leaf)\n internal\n pure\n returns (bool isValid)\n {\n /// @solidity memory-safe-assembly\n assembly {\n if proof.length {\n // Left shift by 5 is equivalent to multiplying by 0x20.\n let end := add(proof.offset, shl(5, proof.length))\n // Initialize `offset` to the offset of `proof` in the calldata.\n let offset := proof.offset\n // Iterate over proof elements to compute root hash.\n for {} 1 {} {\n // Slot of `leaf` in scratch space.\n // If the condition is true: 0x20, otherwise: 0x00.\n let scratch := shl(5, gt(leaf, calldataload(offset)))\n // Store elements to hash contiguously in scratch space.\n // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes.\n mstore(scratch, leaf)\n mstore(xor(scratch, 0x20), calldataload(offset))\n // Reuse `leaf` to store the hash to reduce stack operations.\n leaf := keccak256(0x00, 0x40)\n offset := add(offset, 0x20)\n if iszero(lt(offset, end)) { break }\n }\n }\n isValid := eq(leaf, root)\n }\n }\n\n /// @dev Returns whether all `leafs` exist in the Merkle tree with `root`,\n /// given `proof` and `flags`.\n function verifyMultiProof(\n bytes32[] calldata proof,\n bytes32 root,\n bytes32[] calldata leafs,\n bool[] calldata flags\n ) internal pure returns (bool isValid) {\n // Rebuilds the root by consuming and producing values on a queue.\n // The queue starts with the `leafs` array, and goes into a `hashes` array.\n // After the process, the last element on the queue is verified\n // to be equal to the `root`.\n //\n // The `flags` array denotes whether the sibling\n // should be popped from the queue (`flag == true`), or\n // should be popped from the `proof` (`flag == false`).\n /// @solidity memory-safe-assembly\n assembly {\n // If the number of flags is correct.\n for {} eq(add(leafs.length, proof.length), add(flags.length, 1)) {} {\n // For the case where `proof.length + leafs.length == 1`.\n if iszero(flags.length) {\n // `isValid = (proof.length == 1 ? proof[0] : leafs[0]) == root`.\n // forgefmt: disable-next-item\n isValid := eq(\n calldataload(\n xor(leafs.offset, mul(xor(proof.offset, leafs.offset), proof.length))\n ),\n root\n )\n break\n }\n\n // We can use the free memory space for the queue.\n // We don't need to allocate, since the queue is temporary.\n let hashesFront := mload(0x40)\n // Copy the leafs into the hashes.\n // Sometimes, a little memory expansion costs less than branching.\n // Should cost less, even with a high free memory offset of 0x7d00.\n // Left shift by 5 is equivalent to multiplying by 0x20.\n calldatacopy(hashesFront, leafs.offset, shl(5, leafs.length))\n // Compute the back of the hashes.\n let hashesBack := add(hashesFront, shl(5, leafs.length))\n // This is the end of the memory for the queue.\n // We recycle `flags.length` to save on stack variables\n // (this trick may not always save gas).\n flags.length := add(hashesBack, shl(5, flags.length))\n\n // We don't need to make a copy of `proof.offset` or `flags.offset`,\n // as they are pass-by-value (this trick may not always save gas).\n\n for {} 1 {} {\n // Pop from `hashes`.\n let a := mload(hashesFront)\n // Pop from `hashes`.\n let b := mload(add(hashesFront, 0x20))\n hashesFront := add(hashesFront, 0x40)\n\n // If the flag is false, load the next proof,\n // else, pops from the queue.\n if iszero(calldataload(flags.offset)) {\n // Loads the next proof.\n b := calldataload(proof.offset)\n proof.offset := add(proof.offset, 0x20)\n // Unpop from `hashes`.\n hashesFront := sub(hashesFront, 0x20)\n }\n\n // Advance to the next flag offset.\n flags.offset := add(flags.offset, 0x20)\n\n // Slot of `a` in scratch space.\n // If the condition is true: 0x20, otherwise: 0x00.\n let scratch := shl(5, gt(a, b))\n // Hash the scratch space and push the result onto the queue.\n mstore(scratch, a)\n mstore(xor(scratch, 0x20), b)\n mstore(hashesBack, keccak256(0x00, 0x40))\n hashesBack := add(hashesBack, 0x20)\n if iszero(lt(hashesBack, flags.length)) { break }\n }\n // Checks if the last value in the queue is same as the root.\n isValid := eq(mload(sub(hashesBack, 0x20)), root)\n break\n }\n }\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* EMPTY CALLDATA HELPERS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Returns an empty calldata bytes32 array.\n function emptyProof() internal pure returns (bytes32[] calldata proof) {\n /// @solidity memory-safe-assembly\n assembly {\n proof.length := 0\n }\n }\n\n /// @dev Returns an empty calldata bytes32 array.\n function emptyLeafs() internal pure returns (bytes32[] calldata leafs) {\n /// @solidity memory-safe-assembly\n assembly {\n leafs.length := 0\n }\n }\n\n /// @dev Returns an empty calldata bool array.\n function emptyFlags() internal pure returns (bool[] calldata flags) {\n /// @solidity memory-safe-assembly\n assembly {\n flags.length := 0\n }\n }\n}\n"},"lib/solady/src/utils/SafeCastLib.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Safe integer casting library that reverts on overflow.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeCastLib.sol)\n/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol)\nlibrary SafeCastLib {\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CUSTOM ERRORS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n error Overflow();\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* UNSIGNED INTEGER SAFE CASTING OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n function toUint8(uint256 x) internal pure returns (uint8) {\n if (x >= 1 << 8) _revertOverflow();\n return uint8(x);\n }\n\n function toUint16(uint256 x) internal pure returns (uint16) {\n if (x >= 1 << 16) _revertOverflow();\n return uint16(x);\n }\n\n function toUint24(uint256 x) internal pure returns (uint24) {\n if (x >= 1 << 24) _revertOverflow();\n return uint24(x);\n }\n\n function toUint32(uint256 x) internal pure returns (uint32) {\n if (x >= 1 << 32) _revertOverflow();\n return uint32(x);\n }\n\n function toUint40(uint256 x) internal pure returns (uint40) {\n if (x >= 1 << 40) _revertOverflow();\n return uint40(x);\n }\n\n function toUint48(uint256 x) internal pure returns (uint48) {\n if (x >= 1 << 48) _revertOverflow();\n return uint48(x);\n }\n\n function toUint56(uint256 x) internal pure returns (uint56) {\n if (x >= 1 << 56) _revertOverflow();\n return uint56(x);\n }\n\n function toUint64(uint256 x) internal pure returns (uint64) {\n if (x >= 1 << 64) _revertOverflow();\n return uint64(x);\n }\n\n function toUint72(uint256 x) internal pure returns (uint72) {\n if (x >= 1 << 72) _revertOverflow();\n return uint72(x);\n }\n\n function toUint80(uint256 x) internal pure returns (uint80) {\n if (x >= 1 << 80) _revertOverflow();\n return uint80(x);\n }\n\n function toUint88(uint256 x) internal pure returns (uint88) {\n if (x >= 1 << 88) _revertOverflow();\n return uint88(x);\n }\n\n function toUint96(uint256 x) internal pure returns (uint96) {\n if (x >= 1 << 96) _revertOverflow();\n return uint96(x);\n }\n\n function toUint104(uint256 x) internal pure returns (uint104) {\n if (x >= 1 << 104) _revertOverflow();\n return uint104(x);\n }\n\n function toUint112(uint256 x) internal pure returns (uint112) {\n if (x >= 1 << 112) _revertOverflow();\n return uint112(x);\n }\n\n function toUint120(uint256 x) internal pure returns (uint120) {\n if (x >= 1 << 120) _revertOverflow();\n return uint120(x);\n }\n\n function toUint128(uint256 x) internal pure returns (uint128) {\n if (x >= 1 << 128) _revertOverflow();\n return uint128(x);\n }\n\n function toUint136(uint256 x) internal pure returns (uint136) {\n if (x >= 1 << 136) _revertOverflow();\n return uint136(x);\n }\n\n function toUint144(uint256 x) internal pure returns (uint144) {\n if (x >= 1 << 144) _revertOverflow();\n return uint144(x);\n }\n\n function toUint152(uint256 x) internal pure returns (uint152) {\n if (x >= 1 << 152) _revertOverflow();\n return uint152(x);\n }\n\n function toUint160(uint256 x) internal pure returns (uint160) {\n if (x >= 1 << 160) _revertOverflow();\n return uint160(x);\n }\n\n function toUint168(uint256 x) internal pure returns (uint168) {\n if (x >= 1 << 168) _revertOverflow();\n return uint168(x);\n }\n\n function toUint176(uint256 x) internal pure returns (uint176) {\n if (x >= 1 << 176) _revertOverflow();\n return uint176(x);\n }\n\n function toUint184(uint256 x) internal pure returns (uint184) {\n if (x >= 1 << 184) _revertOverflow();\n return uint184(x);\n }\n\n function toUint192(uint256 x) internal pure returns (uint192) {\n if (x >= 1 << 192) _revertOverflow();\n return uint192(x);\n }\n\n function toUint200(uint256 x) internal pure returns (uint200) {\n if (x >= 1 << 200) _revertOverflow();\n return uint200(x);\n }\n\n function toUint208(uint256 x) internal pure returns (uint208) {\n if (x >= 1 << 208) _revertOverflow();\n return uint208(x);\n }\n\n function toUint216(uint256 x) internal pure returns (uint216) {\n if (x >= 1 << 216) _revertOverflow();\n return uint216(x);\n }\n\n function toUint224(uint256 x) internal pure returns (uint224) {\n if (x >= 1 << 224) _revertOverflow();\n return uint224(x);\n }\n\n function toUint232(uint256 x) internal pure returns (uint232) {\n if (x >= 1 << 232) _revertOverflow();\n return uint232(x);\n }\n\n function toUint240(uint256 x) internal pure returns (uint240) {\n if (x >= 1 << 240) _revertOverflow();\n return uint240(x);\n }\n\n function toUint248(uint256 x) internal pure returns (uint248) {\n if (x >= 1 << 248) _revertOverflow();\n return uint248(x);\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* SIGNED INTEGER SAFE CASTING OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n function toInt8(int256 x) internal pure returns (int8) {\n int8 y = int8(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt16(int256 x) internal pure returns (int16) {\n int16 y = int16(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt24(int256 x) internal pure returns (int24) {\n int24 y = int24(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt32(int256 x) internal pure returns (int32) {\n int32 y = int32(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt40(int256 x) internal pure returns (int40) {\n int40 y = int40(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt48(int256 x) internal pure returns (int48) {\n int48 y = int48(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt56(int256 x) internal pure returns (int56) {\n int56 y = int56(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt64(int256 x) internal pure returns (int64) {\n int64 y = int64(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt72(int256 x) internal pure returns (int72) {\n int72 y = int72(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt80(int256 x) internal pure returns (int80) {\n int80 y = int80(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt88(int256 x) internal pure returns (int88) {\n int88 y = int88(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt96(int256 x) internal pure returns (int96) {\n int96 y = int96(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt104(int256 x) internal pure returns (int104) {\n int104 y = int104(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt112(int256 x) internal pure returns (int112) {\n int112 y = int112(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt120(int256 x) internal pure returns (int120) {\n int120 y = int120(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt128(int256 x) internal pure returns (int128) {\n int128 y = int128(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt136(int256 x) internal pure returns (int136) {\n int136 y = int136(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt144(int256 x) internal pure returns (int144) {\n int144 y = int144(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt152(int256 x) internal pure returns (int152) {\n int152 y = int152(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt160(int256 x) internal pure returns (int160) {\n int160 y = int160(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt168(int256 x) internal pure returns (int168) {\n int168 y = int168(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt176(int256 x) internal pure returns (int176) {\n int176 y = int176(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt184(int256 x) internal pure returns (int184) {\n int184 y = int184(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt192(int256 x) internal pure returns (int192) {\n int192 y = int192(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt200(int256 x) internal pure returns (int200) {\n int200 y = int200(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt208(int256 x) internal pure returns (int208) {\n int208 y = int208(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt216(int256 x) internal pure returns (int216) {\n int216 y = int216(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt224(int256 x) internal pure returns (int224) {\n int224 y = int224(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt232(int256 x) internal pure returns (int232) {\n int232 y = int232(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt240(int256 x) internal pure returns (int240) {\n int240 y = int240(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n function toInt248(int256 x) internal pure returns (int248) {\n int248 y = int248(x);\n if (x != y) _revertOverflow();\n return y;\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* PRIVATE HELPERS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n function _revertOverflow() private pure {\n /// @solidity memory-safe-assembly\n assembly {\n // Store the function selector of `Overflow()`.\n mstore(0x00, 0x35278d12)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n }\n}\n"},"lib/solady/src/utils/SafeTransferLib.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\n/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.\n/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)\n/// @dev Caution! This library won't check that a token has code, responsibility is delegated to the caller.\nlibrary SafeTransferLib {\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CUSTOM ERRORS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev The ETH transfer has failed.\n error ETHTransferFailed();\n\n /// @dev The ERC20 `transferFrom` has failed.\n error TransferFromFailed();\n\n /// @dev The ERC20 `transfer` has failed.\n error TransferFailed();\n\n /// @dev The ERC20 `approve` has failed.\n error ApproveFailed();\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* CONSTANTS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Suggested gas stipend for contract receiving ETH\n /// that disallows any storage writes.\n uint256 internal constant _GAS_STIPEND_NO_STORAGE_WRITES = 2300;\n\n /// @dev Suggested gas stipend for contract receiving ETH to perform a few\n /// storage reads and writes, but low enough to prevent griefing.\n /// Multiply by a small constant (e.g. 2), if needed.\n uint256 internal constant _GAS_STIPEND_NO_GRIEF = 100000;\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* ETH OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Sends `amount` (in wei) ETH to `to`.\n /// Reverts upon failure.\n function safeTransferETH(address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n // Transfer the ETH and check if it succeeded or not.\n if iszero(call(gas(), to, amount, 0, 0, 0, 0)) {\n // Store the function selector of `ETHTransferFailed()`.\n mstore(0x00, 0xb12d13eb)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n }\n }\n\n /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.\n /// The `gasStipend` can be set to a low enough value to prevent\n /// storage writes or gas griefing.\n ///\n /// If sending via the normal procedure fails, force sends the ETH by\n /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH.\n ///\n /// Reverts if the current contract has insufficient balance.\n function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {\n /// @solidity memory-safe-assembly\n assembly {\n // If insufficient balance, revert.\n if lt(selfbalance(), amount) {\n // Store the function selector of `ETHTransferFailed()`.\n mstore(0x00, 0xb12d13eb)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Transfer the ETH and check if it succeeded or not.\n if iszero(call(gasStipend, to, amount, 0, 0, 0, 0)) {\n mstore(0x00, to) // Store the address in scratch space.\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n // We can directly use `SELFDESTRUCT` in the contract creation.\n // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758\n pop(create(amount, 0x0b, 0x16))\n }\n }\n }\n\n /// @dev Force sends `amount` (in wei) ETH to `to`, with a gas stipend\n /// equal to `_GAS_STIPEND_NO_GRIEF`. This gas stipend is a reasonable default\n /// for 99% of cases and can be overriden with the three-argument version of this\n /// function if necessary.\n ///\n /// If sending via the normal procedure fails, force sends the ETH by\n /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH.\n ///\n /// Reverts if the current contract has insufficient balance.\n function forceSafeTransferETH(address to, uint256 amount) internal {\n // Manually inlined because the compiler doesn't inline functions with branches.\n /// @solidity memory-safe-assembly\n assembly {\n // If insufficient balance, revert.\n if lt(selfbalance(), amount) {\n // Store the function selector of `ETHTransferFailed()`.\n mstore(0x00, 0xb12d13eb)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Transfer the ETH and check if it succeeded or not.\n if iszero(call(_GAS_STIPEND_NO_GRIEF, to, amount, 0, 0, 0, 0)) {\n mstore(0x00, to) // Store the address in scratch space.\n mstore8(0x0b, 0x73) // Opcode `PUSH20`.\n mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.\n // We can directly use `SELFDESTRUCT` in the contract creation.\n // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758\n pop(create(amount, 0x0b, 0x16))\n }\n }\n }\n\n /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.\n /// The `gasStipend` can be set to a low enough value to prevent\n /// storage writes or gas griefing.\n ///\n /// Simply use `gasleft()` for `gasStipend` if you don't need a gas stipend.\n ///\n /// Note: Does NOT revert upon failure.\n /// Returns whether the transfer of ETH is successful instead.\n function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)\n internal\n returns (bool success)\n {\n /// @solidity memory-safe-assembly\n assembly {\n // Transfer the ETH and check if it succeeded or not.\n success := call(gasStipend, to, amount, 0, 0, 0, 0)\n }\n }\n\n /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/\n /* ERC20 OPERATIONS */\n /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/\n\n /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.\n /// Reverts upon failure.\n ///\n /// The `from` account must have at least `amount` approved for\n /// the current contract to manage.\n function safeTransferFrom(address token, address from, address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n\n // Store the function selector of `transferFrom(address,address,uint256)`.\n mstore(0x00, 0x23b872dd)\n mstore(0x20, from) // Store the `from` argument.\n mstore(0x40, to) // Store the `to` argument.\n mstore(0x60, amount) // Store the `amount` argument.\n\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(eq(mload(0x00), 1), iszero(returndatasize())),\n call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\n )\n ) {\n // Store the function selector of `TransferFromFailed()`.\n mstore(0x00, 0x7939f424)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n\n mstore(0x60, 0) // Restore the zero slot to zero.\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /// @dev Sends all of ERC20 `token` from `from` to `to`.\n /// Reverts upon failure.\n ///\n /// The `from` account must have at least `amount` approved for\n /// the current contract to manage.\n function safeTransferAllFrom(address token, address from, address to)\n internal\n returns (uint256 amount)\n {\n /// @solidity memory-safe-assembly\n assembly {\n let m := mload(0x40) // Cache the free memory pointer.\n\n mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.\n mstore(0x20, from) // Store the `from` argument.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n gt(returndatasize(), 0x1f), // At least 32 bytes returned.\n staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)\n )\n ) {\n // Store the function selector of `TransferFromFailed()`.\n mstore(0x00, 0x7939f424)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n\n // Store the function selector of `transferFrom(address,address,uint256)`.\n mstore(0x00, 0x23b872dd)\n mstore(0x40, to) // Store the `to` argument.\n // The `amount` argument is already written to the memory word at 0x6a.\n amount := mload(0x60)\n\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(eq(mload(0x00), 1), iszero(returndatasize())),\n call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)\n )\n ) {\n // Store the function selector of `TransferFromFailed()`.\n mstore(0x00, 0x7939f424)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n\n mstore(0x60, 0) // Restore the zero slot to zero.\n mstore(0x40, m) // Restore the free memory pointer.\n }\n }\n\n /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.\n /// Reverts upon failure.\n function safeTransfer(address token, address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x1a, to) // Store the `to` argument.\n mstore(0x3a, amount) // Store the `amount` argument.\n // Store the function selector of `transfer(address,uint256)`,\n // left by 6 bytes (enough for 8tb of memory represented by the free memory pointer).\n // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL).\n mstore(0x00, 0xa9059cbb000000000000)\n\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(eq(mload(0x00), 1), iszero(returndatasize())),\n call(gas(), token, 0, 0x16, 0x44, 0x00, 0x20)\n )\n ) {\n // Store the function selector of `TransferFailed()`.\n mstore(0x00, 0x90b8ec18)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Restore the part of the free memory pointer that was overwritten,\n // which is guaranteed to be zero, if less than 8tb of memory is used.\n mstore(0x3a, 0)\n }\n }\n\n /// @dev Sends all of ERC20 `token` from the current contract to `to`.\n /// Reverts upon failure.\n function safeTransferAll(address token, address to) internal returns (uint256 amount) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.\n mstore(0x20, address()) // Store the address of the current contract.\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n gt(returndatasize(), 0x1f), // At least 32 bytes returned.\n staticcall(gas(), token, 0x1c, 0x24, 0x3a, 0x20)\n )\n ) {\n // Store the function selector of `TransferFailed()`.\n mstore(0x00, 0x90b8ec18)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n\n mstore(0x1a, to) // Store the `to` argument.\n // The `amount` argument is already written to the memory word at 0x3a.\n amount := mload(0x3a)\n // Store the function selector of `transfer(address,uint256)`,\n // left by 6 bytes (enough for 8tb of memory represented by the free memory pointer).\n // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL).\n mstore(0x00, 0xa9059cbb000000000000)\n\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(eq(mload(0x00), 1), iszero(returndatasize())),\n call(gas(), token, 0, 0x16, 0x44, 0x00, 0x20)\n )\n ) {\n // Store the function selector of `TransferFailed()`.\n mstore(0x00, 0x90b8ec18)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Restore the part of the free memory pointer that was overwritten,\n // which is guaranteed to be zero, if less than 8tb of memory is used.\n mstore(0x3a, 0)\n }\n }\n\n /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.\n /// Reverts upon failure.\n function safeApprove(address token, address to, uint256 amount) internal {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x1a, to) // Store the `to` argument.\n mstore(0x3a, amount) // Store the `amount` argument.\n // Store the function selector of `approve(address,uint256)`,\n // left by 6 bytes (enough for 8tb of memory represented by the free memory pointer).\n // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL).\n mstore(0x00, 0x095ea7b3000000000000)\n\n if iszero(\n and( // The arguments of `and` are evaluated from right to left.\n // Set success to whether the call reverted, if not we check it either\n // returned exactly 1 (can't just be non-zero data), or had no return data.\n or(eq(mload(0x00), 1), iszero(returndatasize())),\n call(gas(), token, 0, 0x16, 0x44, 0x00, 0x20)\n )\n ) {\n // Store the function selector of `ApproveFailed()`.\n mstore(0x00, 0x3e3f8f73)\n // Revert with (offset, size).\n revert(0x1c, 0x04)\n }\n // Restore the part of the free memory pointer that was overwritten,\n // which is guaranteed to be zero, if less than 8tb of memory is used.\n mstore(0x3a, 0)\n }\n }\n\n /// @dev Returns the amount of ERC20 `token` owned by `account`.\n /// Returns zero if the `token` does not exist.\n function balanceOf(address token, address account) internal view returns (uint256 amount) {\n /// @solidity memory-safe-assembly\n assembly {\n mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.\n mstore(0x20, account) // Store the `account` argument.\n amount :=\n mul(\n mload(0x20),\n and( // The arguments of `and` are evaluated from right to left.\n gt(returndatasize(), 0x1f), // At least 32 bytes returned.\n staticcall(gas(), token, 0x1c, 0x24, 0x20, 0x20)\n )\n )\n }\n }\n}\n"}},"settings":{"remappings":["@core/=contracts/core/","@modules/=contracts/modules/","ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/","chiru-labs/ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/","closedsea/=lib/closedsea/src/","ds-test/=lib/forge-std/lib/ds-test/src/","erc4626-tests/=lib/closedsea/lib/openzeppelin-contracts/lib/erc4626-tests/","erc721a-upgradeable/=lib/multicaller/lib/erc721a-upgradeable/contracts/","erc721a/=lib/multicaller/lib/erc721a/contracts/","forge-std/=lib/forge-std/src/","multicaller/=lib/multicaller/src/","murky/=lib/murky/src/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/openzeppelin-contracts/","openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","openzeppelin/=lib/openzeppelin-contracts/contracts/","operator-filter-registry/=lib/closedsea/lib/operator-filter-registry/","preapprove/=lib/preapprove/src/","solady/=lib/solady/src/","solmate/=lib/solady/lib/solmate/src/"],"optimizer":{"enabled":true,"runs":1000},"metadata":{"bytecodeHash":"ipfs","appendCBOR":true},"outputSelection":{"*":{"":["ast"],"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"]}},"evmVersion":"london","libraries":{}}}