Overview
ETH Balance
0.1015 ETH
Eth Value
$340.28 (@ $3,352.49/ETH)More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 157 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Mint | 18405240 | 281 days ago | IN | 0 ETH | 0.00079981 | ||||
Mint | 18218271 | 307 days ago | IN | 0 ETH | 0.00092484 | ||||
Mint | 18218123 | 307 days ago | IN | 0 ETH | 0.00084711 | ||||
Mint | 18180725 | 312 days ago | IN | 0 ETH | 0.00109696 | ||||
Mint | 18180492 | 312 days ago | IN | 0 ETH | 0.00028637 | ||||
Mint | 18180492 | 312 days ago | IN | 0 ETH | 0.00091569 | ||||
Mint | 18176665 | 313 days ago | IN | 0 ETH | 0.00118111 | ||||
Mint | 18176520 | 313 days ago | IN | 0 ETH | 0.00018563 | ||||
Mint | 18175872 | 313 days ago | IN | 0 ETH | 0.00111445 | ||||
Mint | 18175820 | 313 days ago | IN | 0 ETH | 0.00114491 | ||||
Mint | 18175768 | 313 days ago | IN | 0 ETH | 0.00106076 | ||||
Mint | 18175673 | 313 days ago | IN | 0 ETH | 0.00107823 | ||||
Mint | 18175491 | 313 days ago | IN | 0 ETH | 0.00117191 | ||||
Mint | 18175442 | 313 days ago | IN | 0 ETH | 0.0002106 | ||||
Mint | 18175353 | 313 days ago | IN | 0 ETH | 0.00121995 | ||||
Mint | 18175224 | 313 days ago | IN | 0 ETH | 0.00099994 | ||||
Mint | 18175209 | 313 days ago | IN | 0 ETH | 0.00104718 | ||||
Mint | 18174796 | 313 days ago | IN | 0 ETH | 0.00106892 | ||||
Mint | 18174768 | 313 days ago | IN | 0 ETH | 0.00123209 | ||||
Mint | 18174405 | 313 days ago | IN | 0 ETH | 0.00113392 | ||||
Mint | 18173987 | 313 days ago | IN | 0 ETH | 0.00201103 | ||||
Mint | 18173978 | 313 days ago | IN | 0 ETH | 0.00115435 | ||||
Mint | 18173960 | 313 days ago | IN | 0 ETH | 0.00106644 | ||||
Mint | 18173957 | 313 days ago | IN | 0 ETH | 0.00107631 | ||||
Mint | 18173919 | 313 days ago | IN | 0 ETH | 0.00118839 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
17486218 | 409 days ago | 0.01 ETH | ||||
17485614 | 410 days ago | 0.02 ETH | ||||
17340315 | 430 days ago | 0.1 ETH | ||||
17306270 | 435 days ago | 0.1 ETH | ||||
17304879 | 435 days ago | 0.01 ETH | ||||
17303953 | 435 days ago | 0.1 ETH | ||||
17300187 | 436 days ago | 0.1 ETH | ||||
17152494 | 456 days ago | 0.0042 ETH | ||||
17142782 | 458 days ago | 0.02 ETH | ||||
17123799 | 460 days ago | 0.06 ETH | ||||
17121910 | 461 days ago | 0.02 ETH | ||||
17119310 | 461 days ago | 0.0126 ETH | ||||
17115962 | 462 days ago | 0.0084 ETH | ||||
17115961 | 462 days ago | 0.0084 ETH | ||||
17115957 | 462 days ago | 0.0084 ETH | ||||
17106195 | 463 days ago | 0.0126 ETH | ||||
17106161 | 463 days ago | 0.0126 ETH | ||||
17106134 | 463 days ago | 0.0126 ETH | ||||
17106035 | 463 days ago | 0.0084 ETH | ||||
17104480 | 463 days ago | 0.01 ETH | ||||
17101282 | 464 days ago | 0.02 ETH | ||||
17080907 | 467 days ago | 0.05 ETH | ||||
17080888 | 467 days ago | 0.03 ETH | ||||
17077641 | 467 days ago | 0.01 ETH | ||||
17019542 | 475 days ago | 0.02 ETH |
Loading...
Loading
Contract Name:
RangeEditionMinter
Compiler Version
v0.8.16+commit.07a7930e
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import { IERC165 } from "./IERC165.sol"; import { IMinterModule } from "./IMinterModule.sol"; import { ISoundFeeRegistry } from "./ISoundFeeRegistry.sol"; import { IRangeEditionMinter, EditionMintData, MintInfo } from "./IRangeEditionMinter.sol"; import { BaseMinter } from "./BaseMinter.sol"; import { ISoundEditionV1 } from "./ISoundEditionV1.sol"; /* * @title RangeEditionMinter * @notice Module for range edition mints of Sound editions. * @author Sound.xyz */ contract RangeEditionMinter is IRangeEditionMinter, BaseMinter { // ============================================================= // STORAGE // ============================================================= /** * @dev Edition mint data * edition => mintId => EditionMintData */ mapping(address => mapping(uint128 => EditionMintData)) internal _editionMintData; // ============================================================= // CONSTRUCTOR // ============================================================= constructor(ISoundFeeRegistry feeRegistry_) BaseMinter(feeRegistry_) {} // ============================================================= // PUBLIC / EXTERNAL WRITE FUNCTIONS // ============================================================= /** * @inheritdoc IRangeEditionMinter */ function createEditionMint( address edition, uint96 price, uint32 startTime, uint32 cutoffTime, uint32 endTime, uint16 affiliateFeeBPS, uint32 maxMintableLower, uint32 maxMintableUpper, uint32 maxMintablePerAccount ) public onlyValidCombinedTimeRange(startTime, cutoffTime, endTime) returns (uint128 mintId) { if (maxMintableLower > maxMintableUpper) revert InvalidMaxMintableRange(); if (maxMintablePerAccount == 0) revert MaxMintablePerAccountIsZero(); mintId = _createEditionMint(edition, startTime, endTime, affiliateFeeBPS); EditionMintData storage data = _editionMintData[edition][mintId]; data.price = price; data.cutoffTime = cutoffTime; data.maxMintableLower = maxMintableLower; data.maxMintableUpper = maxMintableUpper; data.maxMintablePerAccount = maxMintablePerAccount; // prettier-ignore emit RangeEditionMintCreated( edition, mintId, price, startTime, cutoffTime, endTime, affiliateFeeBPS, maxMintableLower, maxMintableUpper, maxMintablePerAccount ); } /** * @inheritdoc IRangeEditionMinter */ function mint( address edition, uint128 mintId, uint32 quantity, address affiliate ) public payable { EditionMintData storage data = _editionMintData[edition][mintId]; uint32 _maxMintable = _getMaxMintable(data); // Increase `totalMinted` by `quantity`. // Require that the increased value does not exceed `maxMintable`. data.totalMinted = _incrementTotalMinted(data.totalMinted, quantity, _maxMintable); unchecked { // Check the additional `requestedQuantity` does not exceed the maximum mintable per account. uint256 numberMinted = ISoundEditionV1(edition).numberMinted(msg.sender); // Won't overflow. The total number of tokens minted in `edition` won't exceed `type(uint32).max`, // and `quantity` has 32 bits. if (numberMinted + quantity > data.maxMintablePerAccount) revert ExceedsMaxPerAccount(); } _mint(edition, mintId, quantity, affiliate); } /** * @inheritdoc IRangeEditionMinter */ function setTimeRange( address edition, uint128 mintId, uint32 startTime, uint32 cutoffTime, uint32 endTime ) public onlyEditionOwnerOrAdmin(edition) onlyValidCombinedTimeRange(startTime, cutoffTime, endTime) { // Set cutoffTime first, as its stored value gets validated later in the execution. EditionMintData storage data = _editionMintData[edition][mintId]; data.cutoffTime = cutoffTime; // This calls the overriden `setTimeRange`, which will check that // `startTime < cutoffTime < endTime`. RangeEditionMinter.setTimeRange(edition, mintId, startTime, endTime); emit CutoffTimeSet(edition, mintId, cutoffTime); } /** * @inheritdoc BaseMinter */ function setTimeRange( address edition, uint128 mintId, uint32 startTime, uint32 endTime ) public override(BaseMinter, IMinterModule) onlyEditionOwnerOrAdmin(edition) { EditionMintData storage data = _editionMintData[edition][mintId]; if (!(startTime < data.cutoffTime && data.cutoffTime < endTime)) revert InvalidTimeRange(); BaseMinter.setTimeRange(edition, mintId, startTime, endTime); } /** * @inheritdoc IRangeEditionMinter */ function setMaxMintableRange( address edition, uint128 mintId, uint32 maxMintableLower, uint32 maxMintableUpper ) public onlyEditionOwnerOrAdmin(edition) { if (maxMintableLower > maxMintableUpper) revert InvalidMaxMintableRange(); EditionMintData storage data = _editionMintData[edition][mintId]; data.maxMintableLower = maxMintableLower; data.maxMintableUpper = maxMintableUpper; emit MaxMintableRangeSet(edition, mintId, maxMintableLower, maxMintableUpper); } /** * @inheritdoc IRangeEditionMinter */ function setPrice( address edition, uint128 mintId, uint96 price ) public onlyEditionOwnerOrAdmin(edition) { _editionMintData[edition][mintId].price = price; emit PriceSet(edition, mintId, price); } /** * @inheritdoc IRangeEditionMinter */ function setMaxMintablePerAccount( address edition, uint128 mintId, uint32 maxMintablePerAccount ) public onlyEditionOwnerOrAdmin(edition) { if (maxMintablePerAccount == 0) revert MaxMintablePerAccountIsZero(); _editionMintData[edition][mintId].maxMintablePerAccount = maxMintablePerAccount; emit MaxMintablePerAccountSet(edition, mintId, maxMintablePerAccount); } // ============================================================= // PUBLIC / EXTERNAL VIEW FUNCTIONS // ============================================================= /** * @inheritdoc IMinterModule */ function totalPrice( address edition, uint128 mintId, address, /* minter */ uint32 quantity ) public view virtual override(BaseMinter, IMinterModule) returns (uint128) { unchecked { // Will not overflow, as `price` is 96 bits, and `quantity` is 32 bits. 96 + 32 = 128. return uint128(uint256(_editionMintData[edition][mintId].price) * uint256(quantity)); } } /** * @inheritdoc IRangeEditionMinter */ function mintInfo(address edition, uint128 mintId) external view returns (MintInfo memory) { BaseData memory baseData = _baseData[edition][mintId]; EditionMintData storage mintData = _editionMintData[edition][mintId]; MintInfo memory combinedMintData = MintInfo( baseData.startTime, baseData.endTime, baseData.affiliateFeeBPS, baseData.mintPaused, mintData.price, mintData.maxMintableUpper, mintData.maxMintableLower, mintData.maxMintablePerAccount, mintData.totalMinted, mintData.cutoffTime ); return combinedMintData; } /** * @inheritdoc IERC165 */ function supportsInterface(bytes4 interfaceId) public view override(IERC165, BaseMinter) returns (bool) { return BaseMinter.supportsInterface(interfaceId) || interfaceId == type(IRangeEditionMinter).interfaceId; } /** * @inheritdoc IMinterModule */ function moduleInterfaceId() public pure returns (bytes4) { return type(IRangeEditionMinter).interfaceId; } // ============================================================= // INTERNAL / PRIVATE HELPERS // ============================================================= /** * @dev Restricts the `startTime` to be less than `cutoffTime`, * and `cutoffTime` to be less than `endTime`. * @param startTime The start unix timestamp of the mint. * @param cutoffTime The cutoff unix timestamp of the mint. * @param endTime The end unix timestamp of the mint. */ modifier onlyValidCombinedTimeRange( uint32 startTime, uint32 cutoffTime, uint32 endTime ) { if (!(startTime < cutoffTime && cutoffTime < endTime)) revert InvalidTimeRange(); _; } /** * @dev Gets the current maximum mintable quantity. * @param data The edition mint data. * @return The computed value. */ function _getMaxMintable(EditionMintData storage data) internal view returns (uint32) { uint32 _maxMintable; if (block.timestamp < data.cutoffTime) { _maxMintable = data.maxMintableUpper; } else { _maxMintable = data.maxMintableLower; } return _maxMintable; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import { IERC721AUpgradeable } from "./IERC721AUpgradeable.sol"; import { IERC2981Upgradeable } from "./IERC2981Upgradeable.sol"; import { IERC165Upgradeable } from "./IERC165Upgradeable.sol"; import { IMetadataModule } from "./IMetadataModule.sol"; /** * @dev The information pertaining to this edition. */ struct EditionInfo { // Base URI for the tokenId. string baseURI; // Contract URI for OpenSea storefront. string contractURI; // Name of the collection. string name; // Symbol of the collection. string symbol; // Address that receives primary and secondary royalties. address fundingRecipient; // The current max mintable amount; uint32 editionMaxMintable; // The lower limit of the maximum number of tokens that can be minted. uint32 editionMaxMintableUpper; // The upper limit of the maximum number of tokens that can be minted. uint32 editionMaxMintableLower; // The timestamp (in seconds since unix epoch) after which the // max amount of tokens mintable will drop from // `maxMintableUpper` to `maxMintableLower`. uint32 editionCutoffTime; // Address of metadata module, address(0x00) if not used. address metadataModule; // The current mint randomness value. uint256 mintRandomness; // The royalty BPS (basis points). uint16 royaltyBPS; // Whether the mint randomness is enabled. bool mintRandomnessEnabled; // Whether the mint has concluded. bool mintConcluded; // Whether the metadata has been frozen. bool isMetadataFrozen; // Next token ID to be minted. uint256 nextTokenId; // Total number of tokens burned. uint256 totalBurned; // Total number of tokens minted. uint256 totalMinted; // Total number of tokens currently in existence. uint256 totalSupply; } /** * @title ISoundEditionV1 * @notice The interface for Sound edition contracts. */ interface ISoundEditionV1 is IERC721AUpgradeable, IERC2981Upgradeable { // ============================================================= // EVENTS // ============================================================= /** * @dev Emitted when the metadata module is set. * @param metadataModule the address of the metadata module. */ event MetadataModuleSet(address metadataModule); /** * @dev Emitted when the `baseURI` is set. * @param baseURI the base URI of the edition. */ event BaseURISet(string baseURI); /** * @dev Emitted when the `contractURI` is set. * @param contractURI The contract URI of the edition. */ event ContractURISet(string contractURI); /** * @dev Emitted when the metadata is frozen (e.g.: `baseURI` can no longer be changed). * @param metadataModule The address of the metadata module. * @param baseURI The base URI of the edition. * @param contractURI The contract URI of the edition. */ event MetadataFrozen(address metadataModule, string baseURI, string contractURI); /** * @dev Emitted when the `fundingRecipient` is set. * @param fundingRecipient The address of the funding recipient. */ event FundingRecipientSet(address fundingRecipient); /** * @dev Emitted when the `royaltyBPS` is set. * @param bps The new royalty, measured in basis points. */ event RoyaltySet(uint16 bps); /** * @dev Emitted when the edition's maximum mintable token quantity range is set. * @param editionMaxMintableLower_ The lower limit of the maximum number of tokens that can be minted. * @param editionMaxMintableUpper_ The upper limit of the maximum number of tokens that can be minted. */ event EditionMaxMintableRangeSet(uint32 editionMaxMintableLower_, uint32 editionMaxMintableUpper_); /** * @dev Emitted when the edition's cutoff time set. * @param editionCutoffTime_ The timestamp. */ event EditionCutoffTimeSet(uint32 editionCutoffTime_); /** * @dev Emitted when the `mintRandomnessEnabled` is set. * @param mintRandomnessEnabled_ The boolean value. */ event MintRandomnessEnabledSet(bool mintRandomnessEnabled_); /** * @dev Emitted upon initialization. * @param edition_ The address of the edition. * @param name_ Name of the collection. * @param symbol_ Symbol of the collection. * @param metadataModule_ Address of metadata module, address(0x00) if not used. * @param baseURI_ Base URI. * @param contractURI_ Contract URI for OpenSea storefront. * @param fundingRecipient_ Address that receives primary and secondary royalties. * @param royaltyBPS_ Royalty amount in bps (basis points). * @param editionMaxMintableLower_ The lower bound of the max mintable quantity for the edition. * @param editionMaxMintableUpper_ The upper bound of the max mintable quantity for the edition. * @param editionCutoffTime_ The timestamp after which `editionMaxMintable` drops from * `editionMaxMintableUpper` to * `max(_totalMinted(), editionMaxMintableLower)`. * @param flags_ The bitwise OR result of the initialization flags. * See: {METADATA_IS_FROZEN_FLAG} * See: {MINT_RANDOMNESS_ENABLED_FLAG} */ event SoundEditionInitialized( address indexed edition_, string name_, string symbol_, address metadataModule_, string baseURI_, string contractURI_, address fundingRecipient_, uint16 royaltyBPS_, uint32 editionMaxMintableLower_, uint32 editionMaxMintableUpper_, uint32 editionCutoffTime_, uint8 flags_ ); /** * @dev Emitted upon ETH withdrawal. * @param recipient The recipient of the withdrawal. * @param amount The amount withdrawn. * @param caller The account that initiated the withdrawal. */ event ETHWithdrawn(address recipient, uint256 amount, address caller); /** * @dev Emitted upon ERC20 withdrawal. * @param recipient The recipient of the withdrawal. * @param tokens The addresses of the ERC20 tokens. * @param amounts The amount of each token withdrawn. * @param caller The account that initiated the withdrawal. */ event ERC20Withdrawn(address recipient, address[] tokens, uint256[] amounts, address caller); /** * @dev Emitted upon a mint. * @param to The address to mint to. * @param quantity The number of minted. * @param fromTokenId The first token ID minted. */ event Minted(address to, uint256 quantity, uint256 fromTokenId); /** * @dev Emitted upon an airdrop. * @param to The recipients of the airdrop. * @param quantity The number of tokens airdropped to each address in `to`. * @param fromTokenId The first token ID minted to the first address in `to`. */ event Airdropped(address[] to, uint256 quantity, uint256 fromTokenId); // ============================================================= // ERRORS // ============================================================= /** * @dev The edition's metadata is frozen (e.g.: `baseURI` can no longer be changed). */ error MetadataIsFrozen(); /** * @dev The given `royaltyBPS` is invalid. */ error InvalidRoyaltyBPS(); /** * @dev The given `randomnessLockedAfterMinted` value is invalid. */ error InvalidRandomnessLock(); /** * @dev The requested quantity exceeds the edition's remaining mintable token quantity. * @param available The number of tokens remaining available for mint. */ error ExceedsEditionAvailableSupply(uint32 available); /** * @dev The given amount is invalid. */ error InvalidAmount(); /** * @dev The given `fundingRecipient` address is invalid. */ error InvalidFundingRecipient(); /** * @dev The `editionMaxMintableLower` must not be greater than `editionMaxMintableUpper`. */ error InvalidEditionMaxMintableRange(); /** * @dev The `editionMaxMintable` has already been reached. */ error MaximumHasAlreadyBeenReached(); /** * @dev The mint `quantity` cannot exceed `ADDRESS_BATCH_MINT_LIMIT` tokens. */ error ExceedsAddressBatchMintLimit(); /** * @dev The mint randomness has already been revealed. */ error MintRandomnessAlreadyRevealed(); /** * @dev No addresses to airdrop. */ error NoAddressesToAirdrop(); /** * @dev The mint has already concluded. */ error MintHasConcluded(); /** * @dev Cannot perform the operation after a token has been minted. */ error MintsAlreadyExist(); // ============================================================= // PUBLIC / EXTERNAL WRITE FUNCTIONS // ============================================================= /** * @dev Initializes the contract. * @param name_ Name of the collection. * @param symbol_ Symbol of the collection. * @param metadataModule_ Address of metadata module, address(0x00) if not used. * @param baseURI_ Base URI. * @param contractURI_ Contract URI for OpenSea storefront. * @param fundingRecipient_ Address that receives primary and secondary royalties. * @param royaltyBPS_ Royalty amount in bps (basis points). * @param editionMaxMintableLower_ The lower bound of the max mintable quantity for the edition. * @param editionMaxMintableUpper_ The upper bound of the max mintable quantity for the edition. * @param editionCutoffTime_ The timestamp after which `editionMaxMintable` drops from * `editionMaxMintableUpper` to * `max(_totalMinted(), editionMaxMintableLower)`. * @param flags_ The bitwise OR result of the initialization flags. * See: {METADATA_IS_FROZEN_FLAG} * See: {MINT_RANDOMNESS_ENABLED_FLAG} */ function initialize( string memory name_, string memory symbol_, address metadataModule_, string memory baseURI_, string memory contractURI_, address fundingRecipient_, uint16 royaltyBPS_, uint32 editionMaxMintableLower_, uint32 editionMaxMintableUpper_, uint32 editionCutoffTime_, uint8 flags_ ) external; /** * @dev Mints `quantity` tokens to addrress `to` * Each token will be assigned a token ID that is consecutively increasing. * * Calling conditions: * - The caller must be the owner of the contract, or have either the * `ADMIN_ROLE`, `MINTER_ROLE`, which can be granted via {grantRole}. * Multiple minters, such as different minter contracts, * can be authorized simultaneously. * * @param to Address to mint to. * @param quantity Number of tokens to mint. * @return fromTokenId The first token ID minted. */ function mint(address to, uint256 quantity) external payable returns (uint256 fromTokenId); /** * @dev Mints `quantity` tokens to each of the addresses in `to`. * * Calling conditions: * - The caller must be the owner of the contract, or have the * `ADMIN_ROLE`, which can be granted via {grantRole}. * * @param to Address to mint to. * @param quantity Number of tokens to mint. * @return fromTokenId The first token ID minted. */ function airdrop(address[] calldata to, uint256 quantity) external returns (uint256 fromTokenId); /** * @dev Withdraws collected ETH royalties to the fundingRecipient. */ function withdrawETH() external; /** * @dev Withdraws collected ERC20 royalties to the fundingRecipient. * @param tokens array of ERC20 tokens to withdraw */ function withdrawERC20(address[] calldata tokens) external; /** * @dev Sets metadata module. * * Calling conditions: * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`. * * @param metadataModule Address of metadata module. */ function setMetadataModule(address metadataModule) external; /** * @dev Sets global base URI. * * Calling conditions: * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`. * * @param baseURI The base URI to be set. */ function setBaseURI(string memory baseURI) external; /** * @dev Sets contract URI. * * Calling conditions: * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`. * * @param contractURI The contract URI to be set. */ function setContractURI(string memory contractURI) external; /** * @dev Freezes metadata by preventing any more changes to base URI. * * Calling conditions: * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`. */ function freezeMetadata() external; /** * @dev Sets funding recipient address. * * Calling conditions: * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`. * * @param fundingRecipient Address to be set as the new funding recipient. */ function setFundingRecipient(address fundingRecipient) external; /** * @dev Sets royalty amount in bps (basis points). * * Calling conditions: * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`. * * @param bps The new royalty basis points to be set. */ function setRoyalty(uint16 bps) external; /** * @dev Sets the edition max mintable range. * * Calling conditions: * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`. * * @param editionMaxMintableLower_ The lower limit of the maximum number of tokens that can be minted. * @param editionMaxMintableUpper_ The upper limit of the maximum number of tokens that can be minted. */ function setEditionMaxMintableRange(uint32 editionMaxMintableLower_, uint32 editionMaxMintableUpper_) external; /** * @dev Sets the timestamp after which, the `editionMaxMintable` drops * from `editionMaxMintableUpper` to `editionMaxMintableLower. * * Calling conditions: * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`. * * @param editionCutoffTime_ The timestamp. */ function setEditionCutoffTime(uint32 editionCutoffTime_) external; /** * @dev Sets whether the `mintRandomness` is enabled. * * Calling conditions: * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`. * * @param mintRandomnessEnabled_ The boolean value. */ function setMintRandomnessEnabled(bool mintRandomnessEnabled_) external; // ============================================================= // PUBLIC / EXTERNAL VIEW FUNCTIONS // ============================================================= /** * @dev Returns the edition info. * @return editionInfo The latest value. */ function editionInfo() external view returns (EditionInfo memory editionInfo); /** * @dev Returns the minter role flag. * @return The constant value. */ function MINTER_ROLE() external view returns (uint256); /** * @dev Returns the admin role flag. * @return The constant value. */ function ADMIN_ROLE() external view returns (uint256); /** * @dev Returns the maximum limit for the mint or airdrop `quantity`. * Prevents the first-time transfer costs for tokens near the end of large mint batches * via ERC721A from becoming too expensive due to the need to scan many storage slots. * See: https://chiru-labs.github.io/ERC721A/#/tips?id=batch-size * @return The constant value. */ function ADDRESS_BATCH_MINT_LIMIT() external pure returns (uint256); /** * @dev Returns the bit flag to freeze the metadata on initialization. * @return The constant value. */ function METADATA_IS_FROZEN_FLAG() external pure returns (uint8); /** * @dev Returns the bit flag to enable the mint randomness feature on initialization. * @return The constant value. */ function MINT_RANDOMNESS_ENABLED_FLAG() external pure returns (uint8); /** * @dev Returns the base token URI for the collection. * @return The configured value. */ function baseURI() external view returns (string memory); /** * @dev Returns the contract URI to be used by Opensea. * See: https://docs.opensea.io/docs/contract-level-metadata * @return The configured value. */ function contractURI() external view returns (string memory); /** * @dev Returns the address of the funding recipient. * @return The configured value. */ function fundingRecipient() external view returns (address); /** * @dev Returns the maximum amount of tokens mintable for this edition. * @return The configured value. */ function editionMaxMintable() external view returns (uint32); /** * @dev Returns the upper bound for the maximum tokens that can be minted for this edition. * @return The configured value. */ function editionMaxMintableUpper() external view returns (uint32); /** * @dev Returns the lower bound for the maximum tokens that can be minted for this edition. * @return The configured value. */ function editionMaxMintableLower() external view returns (uint32); /** * @dev Returns the timestamp after which `editionMaxMintable` drops from * `editionMaxMintableUpper` to `editionMaxMintableLower`. * @return The configured value. */ function editionCutoffTime() external view returns (uint32); /** * @dev Returns the address of the metadata module. * @return The configured value. */ function metadataModule() external view returns (address); /** * @dev Returns the randomness based on latest block hash, which is stored upon each mint. * unless {mintConcluded} is true. * Used for game mechanics like the Sound Golden Egg. * Returns 0 before revealed. * WARNING: This value should NOT be used for any reward of significant monetary * value, due to it being computed via a purely on-chain psuedorandom mechanism. * @return The latest value. */ function mintRandomness() external view returns (uint256); /** * @dev Returns whether the `mintRandomness` has been enabled. * @return The configured value. */ function mintRandomnessEnabled() external view returns (bool); /** * @dev Returns whether the mint has been concluded. * @return The latest value. */ function mintConcluded() external view returns (bool); /** * @dev Returns the royalty basis points. * @return The configured value. */ function royaltyBPS() external view returns (uint16); /** * @dev Returns whether the metadata module is frozen. * @return The configured value. */ function isMetadataFrozen() external view returns (bool); /** * @dev Returns the next token ID to be minted. * @return The latest value. */ function nextTokenId() external view returns (uint256); /** * @dev Returns the number of tokens minted by `owner`. * @param owner Address to query for number minted. * @return The latest value. */ function numberMinted(address owner) external view returns (uint256); /** * @dev Returns the number of tokens burned by `owner`. * @param owner Address to query for number burned. * @return The latest value. */ function numberBurned(address owner) external view returns (uint256); /** * @dev Returns the total amount of tokens minted. * @return The latest value. */ function totalMinted() external view returns (uint256); /** * @dev Returns the total amount of tokens burned. * @return The latest value. */ function totalBurned() external view returns (uint256); /** * @dev Informs other contracts which interfaces this contract supports. * Required by https://eips.ethereum.org/EIPS/eip-165 * @param interfaceId The interface id to check. * @return Whether the `interfaceId` is supported. */ function supportsInterface(bytes4 interfaceId) external view override(IERC721AUpgradeable, IERC165Upgradeable) returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import { OwnableRoles } from "./OwnableRoles.sol"; import { ISoundEditionV1 } from "./ISoundEditionV1.sol"; import { IMinterModule } from "./IMinterModule.sol"; import { ISoundFeeRegistry } from "./ISoundFeeRegistry.sol"; import { IERC165 } from "./IERC165.sol"; import { SafeTransferLib } from "./SafeTransferLib.sol"; import { FixedPointMathLib } from "./FixedPointMathLib.sol"; /** * @title Minter Base * @dev The `BaseMinter` class maintains a central storage record of edition mint instances. */ abstract contract BaseMinter is IMinterModule { // ============================================================= // CONSTANTS // ============================================================= /** * @dev This is the denominator, in basis points (BPS), for: * - platform fees * - affiliate fees */ uint16 private constant _MAX_BPS = 10_000; // ============================================================= // STORAGE // ============================================================= /** * @dev The next mint ID. Shared amongst all editions connected. */ uint128 private _nextMintId; /** * @dev How much platform fees have been accrued. */ uint128 private _platformFeesAccrued; /** * @dev Maps an edition and the mint ID to a mint instance. */ mapping(address => mapping(uint256 => BaseData)) internal _baseData; /** * @dev Maps an address to how much affiliate fees have they accrued. */ mapping(address => uint128) private _affiliateFeesAccrued; /** * @dev The fee registry. Used for handling platform fees. */ ISoundFeeRegistry public immutable feeRegistry; // ============================================================= // CONSTRUCTOR // ============================================================= constructor(ISoundFeeRegistry feeRegistry_) { if (address(feeRegistry_) == address(0)) revert FeeRegistryIsZeroAddress(); feeRegistry = feeRegistry_; } // ============================================================= // PUBLIC / EXTERNAL WRITE FUNCTIONS // ============================================================= /** * @inheritdoc IMinterModule */ function setEditionMintPaused( address edition, uint128 mintId, bool paused ) public virtual onlyEditionOwnerOrAdmin(edition) { _baseData[edition][mintId].mintPaused = paused; emit MintPausedSet(edition, mintId, paused); } /** * @inheritdoc IMinterModule */ function setTimeRange( address edition, uint128 mintId, uint32 startTime, uint32 endTime ) public virtual onlyEditionOwnerOrAdmin(edition) onlyValidTimeRange(startTime, endTime) { _baseData[edition][mintId].startTime = startTime; _baseData[edition][mintId].endTime = endTime; emit TimeRangeSet(edition, mintId, startTime, endTime); } /** * @inheritdoc IMinterModule */ function setAffiliateFee( address edition, uint128 mintId, uint16 feeBPS ) public virtual override onlyEditionOwnerOrAdmin(edition) onlyValidAffiliateFeeBPS(feeBPS) { _baseData[edition][mintId].affiliateFeeBPS = feeBPS; emit AffiliateFeeSet(edition, mintId, feeBPS); } /** * @inheritdoc IMinterModule */ function withdrawForAffiliate(address affiliate) public override { uint256 accrued = _affiliateFeesAccrued[affiliate]; if (accrued != 0) { _affiliateFeesAccrued[affiliate] = 0; SafeTransferLib.safeTransferETH(affiliate, accrued); } } /** * @inheritdoc IMinterModule */ function withdrawForPlatform() public override { uint256 accrued = _platformFeesAccrued; if (accrued != 0) { _platformFeesAccrued = 0; SafeTransferLib.safeTransferETH(feeRegistry.soundFeeAddress(), accrued); } } // ============================================================= // PUBLIC / EXTERNAL VIEW FUNCTIONS // ============================================================= /** * @dev Getter for the max basis points. */ function MAX_BPS() external pure returns (uint16) { return _MAX_BPS; } /** * @inheritdoc IMinterModule */ function affiliateFeesAccrued(address affiliate) external view returns (uint128) { return _affiliateFeesAccrued[affiliate]; } /** * @inheritdoc IMinterModule */ function platformFeesAccrued() external view returns (uint128) { return _platformFeesAccrued; } /** * @inheritdoc IMinterModule */ function isAffiliated( address, /* edition */ uint128, /* mintId */ address affiliate ) public view virtual override returns (bool) { return affiliate != address(0); } /** * @inheritdoc IMinterModule */ function nextMintId() public view returns (uint128) { return _nextMintId; } /** * @inheritdoc IERC165 */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IMinterModule).interfaceId || interfaceId == this.supportsInterface.selector; } /** * @inheritdoc IMinterModule */ function totalPrice( address edition, uint128 mintId, address minter, uint32 quantity ) public view virtual override returns (uint128); // ============================================================= // INTERNAL / PRIVATE HELPERS // ============================================================= /** * @dev Restricts the function to be only callable by the owner or admin of `edition`. * @param edition The edition address. */ modifier onlyEditionOwnerOrAdmin(address edition) virtual { if ( msg.sender != OwnableRoles(edition).owner() && !OwnableRoles(edition).hasAnyRole(msg.sender, ISoundEditionV1(edition).ADMIN_ROLE()) ) revert Unauthorized(); _; } /** * @dev Restricts the start time to be less than the end time. * @param startTime The start time of the mint. * @param endTime The end time of the mint. */ modifier onlyValidTimeRange(uint32 startTime, uint32 endTime) virtual { if (startTime >= endTime) revert InvalidTimeRange(); _; } /** * @dev Restricts the affiliate fee numerator to not exceed the `MAX_BPS`. */ modifier onlyValidAffiliateFeeBPS(uint16 affiliateFeeBPS) virtual { if (affiliateFeeBPS > _MAX_BPS) revert InvalidAffiliateFeeBPS(); _; } /** * @dev Creates an edition mint instance. * @param edition The edition address. * @param startTime The start time of the mint. * @param endTime The end time of the mint. * @param affiliateFeeBPS The affiliate fee in basis points. * @return mintId The ID for the mint instance. * Calling conditions: * - Must be owner or admin of the edition. */ function _createEditionMint( address edition, uint32 startTime, uint32 endTime, uint16 affiliateFeeBPS ) internal onlyEditionOwnerOrAdmin(edition) onlyValidTimeRange(startTime, endTime) onlyValidAffiliateFeeBPS(affiliateFeeBPS) returns (uint128 mintId) { mintId = _nextMintId; BaseData storage data = _baseData[edition][mintId]; data.startTime = startTime; data.endTime = endTime; data.affiliateFeeBPS = affiliateFeeBPS; _nextMintId = mintId + 1; emit MintConfigCreated(edition, msg.sender, mintId, startTime, endTime, affiliateFeeBPS); } /** * @dev Mints `quantity` of `edition` to `to` with a required payment of `requiredEtherValue`. * Note: this function should be called at the end of a function due to it refunding any * excess ether paid, to adhere to the checks-effects-interactions pattern. * Otherwise, a reentrancy guard must be used. * @param edition The edition address. * @param mintId The ID for the mint instance. * @param quantity The quantity of tokens to mint. * @param affiliate The affiliate (referral) address. */ function _mint( address edition, uint128 mintId, uint32 quantity, address affiliate ) internal { BaseData storage baseData = _baseData[edition][mintId]; /* --------------------- GENERAL CHECKS --------------------- */ { uint32 startTime = baseData.startTime; uint32 endTime = baseData.endTime; if (block.timestamp < startTime) revert MintNotOpen(block.timestamp, startTime, endTime); if (block.timestamp > endTime) revert MintNotOpen(block.timestamp, startTime, endTime); if (baseData.mintPaused) revert MintPaused(); } /* ----------- AFFILIATE AND PLATFORM FEES LOGIC ------------ */ uint128 requiredEtherValue = totalPrice(edition, mintId, msg.sender, quantity); // Reverts if the payment is not exact. if (msg.value < requiredEtherValue) revert Underpaid(msg.value, requiredEtherValue); (uint128 remainingPayment, uint128 platformFee) = _deductPlatformFee(requiredEtherValue); // Check if the mint is an affiliated mint. bool affiliated = isAffiliated(edition, mintId, affiliate); uint128 affiliateFee; unchecked { if (affiliated) { // Compute the affiliate fee. // Won't overflow, as `remainingPayment` is 128 bits, and `affiliateFeeBPS` is 16 bits. affiliateFee = uint128( (uint256(remainingPayment) * uint256(baseData.affiliateFeeBPS)) / uint256(_MAX_BPS) ); // Deduct the affiliate fee from the remaining payment. // Won't underflow as `affiliateFee <= remainingPayment`. remainingPayment -= affiliateFee; // Increment the affiliate fees accrued. // Overflow is incredibly unrealistic. _affiliateFeesAccrued[affiliate] += affiliateFee; } } /* ------------------------- MINT --------------------------- */ // Emit the event. emit Minted( edition, mintId, msg.sender, // Need to put this call here to avoid stack-too-deep error (it returns fromTokenId) uint32(ISoundEditionV1(edition).mint{ value: remainingPayment }(msg.sender, quantity)), quantity, requiredEtherValue, platformFee, affiliateFee, affiliate, affiliated ); /* ------------------------- REFUND ------------------------- */ unchecked { // Note: We do this at the end to avoid creating a reentrancy vector. // Refund the user any ETH they spent over the current total price of the NFTs. if (msg.value > requiredEtherValue) { SafeTransferLib.safeTransferETH(msg.sender, msg.value - requiredEtherValue); } } } /** * @dev Deducts the platform fee from `requiredEtherValue`. * @param requiredEtherValue The amount of Ether required. * @return remainingPayment The remaining payment Ether amount. * @return platformFee The platform fee. */ function _deductPlatformFee(uint128 requiredEtherValue) internal returns (uint128 remainingPayment, uint128 platformFee) { unchecked { // Compute the platform fee. platformFee = feeRegistry.platformFee(requiredEtherValue); // Increment the platform fees accrued. // Overflow is incredibly unrealistic. _platformFeesAccrued += platformFee; // Deduct the platform fee. // Won't underflow as `platformFee <= requiredEtherValue`; remainingPayment = requiredEtherValue - platformFee; } } /** * @dev Increments `totalMinted` with `quantity`, reverting if `totalMinted + quantity > maxMintable`. * @param totalMinted The current total number of minted tokens. * @param maxMintable The maximum number of mintable tokens. * @return `totalMinted` + `quantity`. */ function _incrementTotalMinted( uint32 totalMinted, uint32 quantity, uint32 maxMintable ) internal pure returns (uint32) { unchecked { // Won't overflow as both are 32 bits. uint256 sum = uint256(totalMinted) + uint256(quantity); if (sum > maxMintable) { // Note that the `maxMintable` may vary and drop over time // and cause `totalMinted` to be greater than `maxMintable`. // The `zeroFloorSub` is equivalent to `max(0, x - y)`. uint32 available = uint32(FixedPointMathLib.zeroFloorSub(maxMintable, totalMinted)); revert ExceedsAvailableSupply(available); } return uint32(sum); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import { IMinterModule } from "./IMinterModule.sol"; /** * @dev Data unique to a range edition mint. */ struct EditionMintData { // The price at which each token will be sold, in ETH. uint96 price; // The timestamp (in seconds since unix epoch) after which the // max amount of tokens mintable will drop from // `maxMintableUpper` to `maxMintableLower`. uint32 cutoffTime; // The total number of tokens minted. Includes permissioned mints. uint32 totalMinted; // The lower limit of the maximum number of tokens that can be minted. uint32 maxMintableLower; // The upper limit of the maximum number of tokens that can be minted. uint32 maxMintableUpper; // The maximum number of tokens that a wallet can mint. uint32 maxMintablePerAccount; } /** * @dev All the information about a range edition mint (combines EditionMintData with BaseData). */ struct MintInfo { uint32 startTime; uint32 endTime; uint16 affiliateFeeBPS; bool mintPaused; uint96 price; uint32 maxMintableUpper; uint32 maxMintableLower; uint32 maxMintablePerAccount; uint32 totalMinted; uint32 cutoffTime; } /** * @title IRangeEditionMinter * @dev Interface for the `RangeEditionMinter` module. * @author Sound.xyz */ interface IRangeEditionMinter is IMinterModule { // ============================================================= // EVENTS // ============================================================= /** * @dev Emitted when a range edition is created. * @param edition Address of the song edition contract we are minting for. * @param mintId The mint ID. * @param price Sale price in ETH for minting a single token in `edition`. * @param startTime Start timestamp of sale (in seconds since unix epoch). * @param cutoffTime The timestamp (in seconds since unix epoch) after which the * max amount of tokens mintable will drop from * `maxMintableUpper` to `maxMintableLower`. * @param endTime End timestamp of sale (in seconds since unix epoch). * @param affiliateFeeBPS The affiliate fee in basis points. * @param maxMintableLower The lower limit of the maximum number of tokens that can be minted. * @param maxMintableUpper The upper limit of the maximum number of tokens that can be minted. */ event RangeEditionMintCreated( address indexed edition, uint128 indexed mintId, uint96 price, uint32 startTime, uint32 cutoffTime, uint32 endTime, uint16 affiliateFeeBPS, uint32 maxMintableLower, uint32 maxMintableUpper, uint32 maxMintablePerAccount ); event CutoffTimeSet(address indexed edition, uint128 indexed mintId, uint32 cutoffTime); /** * @dev Emitted when the max mintable range is updated. * @param edition Address of the song edition contract we are minting for. * @param mintId The mint ID. * @param maxMintableLower The lower limit of the maximum number of tokens that can be minted. * @param maxMintableUpper The upper limit of the maximum number of tokens that can be minted. */ event MaxMintableRangeSet( address indexed edition, uint128 indexed mintId, uint32 maxMintableLower, uint32 maxMintableUpper ); /** * @dev Emitted when the `price` is changed for (`edition`, `mintId`). * @param edition Address of the song edition contract we are minting for. * @param mintId The mint ID. * @param price Sale price in ETH for minting a single token in `edition`. */ event PriceSet(address indexed edition, uint128 indexed mintId, uint96 price); /** * @dev Emitted when the `maxMintablePerAccount` is changed for (`edition`, `mintId`). * @param edition Address of the song edition contract we are minting for. * @param mintId The mint ID. * @param maxMintablePerAccount The maximum number of tokens that can be minted per account. */ event MaxMintablePerAccountSet(address indexed edition, uint128 indexed mintId, uint32 maxMintablePerAccount); // ============================================================= // ERRORS // ============================================================= /** * @dev The `maxMintableLower` must not be greater than `maxMintableUpper`. */ error InvalidMaxMintableRange(); /** * @dev The number of tokens minted has exceeded the number allowed for each account. */ error ExceedsMaxPerAccount(); /** * @dev The max mintable per account cannot be zero. */ error MaxMintablePerAccountIsZero(); // ============================================================= // PUBLIC / EXTERNAL WRITE FUNCTIONS // ============================================================= /* * @dev Initializes a range mint instance * @param edition Address of the song edition contract we are minting for. * @param price Sale price in ETH for minting a single token in `edition`. * @param startTime Start timestamp of sale (in seconds since unix epoch). * @param cutoffTime The timestamp (in seconds since unix epoch) after which the * max amount of tokens mintable will drop from * `maxMintableUpper` to `maxMintableLower`. * @param endTime End timestamp of sale (in seconds since unix epoch). * @param affiliateFeeBPS The affiliate fee in basis points. * @param maxMintableLower The lower limit of the maximum number of tokens that can be minted. * @param maxMintableUpper The upper limit of the maximum number of tokens that can be minted. * @param maxMintablePerAccount_ The maximum number of tokens that can be minted by an account. * @return mintId The ID for the new mint instance. */ function createEditionMint( address edition, uint96 price, uint32 startTime, uint32 cutoffTime, uint32 endTime, uint16 affiliateFeeBPS, uint32 maxMintableLower, uint32 maxMintableUpper, uint32 maxMintablePerAccount_ ) external returns (uint128 mintId); /* * @dev Sets the time range. * @param edition Address of the song edition contract we are minting for. * @param startTime Start timestamp of sale (in seconds since unix epoch). * @param cutoffTime The timestamp (in seconds since unix epoch) after which the * max amount of tokens mintable will drop from * `maxMintableUpper` to `maxMintableLower`. * @param endTime End timestamp of sale (in seconds since unix epoch). */ function setTimeRange( address edition, uint128 mintId, uint32 startTime, uint32 cutoffTime, uint32 endTime ) external; /* * @dev Sets the max mintable range. * @param edition Address of the song edition contract we are minting for. * @param maxMintableLower The lower limit of the maximum number of tokens that can be minted. * @param maxMintableUpper The upper limit of the maximum number of tokens that can be minted. */ function setMaxMintableRange( address edition, uint128 mintId, uint32 maxMintableLower, uint32 maxMintableUpper ) external; /* * @dev Mints tokens for a given edition. * @param edition Address of the song edition contract we are minting for. * @param quantity Token quantity to mint in song `edition`. */ function mint( address edition, uint128 mintId, uint32 quantity, address affiliate ) external payable; /* * @dev Sets the `price` for (`edition`, `mintId`). * @param edition Address of the song edition contract we are minting for. * @param mintId The mint ID. * @param price Sale price in ETH for minting a single token in `edition`. */ function setPrice( address edition, uint128 mintId, uint96 price ) external; /* * @dev Sets the `maxMintablePerAccount` for (`edition`, `mintId`). * @param edition Address of the song edition contract we are minting for. * @param mintId The mint ID. * @param maxMintablePerAccount The maximum number of tokens that can be minted by an account. */ function setMaxMintablePerAccount( address edition, uint128 mintId, uint32 maxMintablePerAccount ) external; // ============================================================= // PUBLIC / EXTERNAL VIEW FUNCTIONS // ============================================================= /** * @dev Returns {IRangeEditionMinter.MintInfo} instance containing the full minter parameter set. * @param edition The edition to get the mint instance for. * @param mintId The ID of the mint instance. * @return mintInfo Information about this mint. */ function mintInfo(address edition, uint128 mintId) external view returns (MintInfo memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; /** * @title ISoundFeeRegistry * @author Sound.xyz */ interface ISoundFeeRegistry { // ============================================================= // EVENTS // ============================================================= /** * @dev Emitted when the `soundFeeAddress` is changed. */ event SoundFeeAddressSet(address soundFeeAddress); /** * @dev Emitted when the `platformFeeBPS` is changed. */ event PlatformFeeSet(uint16 platformFeeBPS); // ============================================================= // ERRORS // ============================================================= /** * @dev The new `soundFeeAddress` must not be address(0). */ error InvalidSoundFeeAddress(); /** * @dev The platform fee numerator must not exceed `_MAX_BPS`. */ error InvalidPlatformFeeBPS(); // ============================================================= // PUBLIC / EXTERNAL WRITE FUNCTIONS // ============================================================= /** * @dev Sets the `soundFeeAddress`. * * Calling conditions: * - The caller must be the owner of the contract. * * @param soundFeeAddress_ The sound fee address. */ function setSoundFeeAddress(address soundFeeAddress_) external; /** * @dev Sets the `platformFeePBS`. * * Calling conditions: * - The caller must be the owner of the contract. * * @param platformFeeBPS_ Platform fee amount in bps (basis points). */ function setPlatformFeeBPS(uint16 platformFeeBPS_) external; // ============================================================= // PUBLIC / EXTERNAL VIEW FUNCTIONS // ============================================================= /** * @dev The sound protocol's address that receives platform fees. * @return The configured value. */ function soundFeeAddress() external view returns (address); /** * @dev The numerator of the platform fee. * @return The configured value. */ function platformFeeBPS() external view returns (uint16); /** * @dev The platform fee for `requiredEtherValue`. * @param requiredEtherValue The required Ether value for payment. * @return fee The computed value. */ function platformFee(uint128 requiredEtherValue) external view returns (uint128 fee); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import { IERC165 } from "./IERC165.sol"; import { ISoundFeeRegistry } from "./ISoundFeeRegistry.sol"; /** * @title IMinterModule * @notice The interface for Sound protocol minter modules. */ interface IMinterModule is IERC165 { // ============================================================= // STRUCTS // ============================================================= struct BaseData { // The start unix timestamp of the mint. uint32 startTime; // The end unix timestamp of the mint. uint32 endTime; // The affiliate fee in basis points. uint16 affiliateFeeBPS; // Whether the mint is paused. bool mintPaused; } // ============================================================= // EVENTS // ============================================================= /** * @dev Emitted when the mint instance for an `edition` is created. * @param edition The edition address. * @param mintId The mint ID, a global incrementing identifier used within the minter * @param startTime The start time of the mint. * @param endTime The end time of the mint. * @param affiliateFeeBPS The affiliate fee in basis points. */ event MintConfigCreated( address indexed edition, address indexed creator, uint128 mintId, uint32 startTime, uint32 endTime, uint16 affiliateFeeBPS ); /** * @dev Emitted when the `paused` status of `edition` is updated. * @param edition The edition address. * @param mintId The mint ID, to distinguish between multiple mints for the same edition. * @param paused The new paused status. */ event MintPausedSet(address indexed edition, uint128 mintId, bool paused); /** * @dev Emitted when the `paused` status of `edition` is updated. * @param edition The edition address. * @param mintId The mint ID, to distinguish between multiple mints for the same edition. * @param startTime The start time of the mint. * @param endTime The end time of the mint. */ event TimeRangeSet(address indexed edition, uint128 indexed mintId, uint32 startTime, uint32 endTime); /** * @notice Emitted when the `affiliateFeeBPS` is updated. * @param edition The edition address. * @param mintId The mint ID, to distinguish between multiple mints for the same edition. * @param bps The affiliate fee basis points. */ event AffiliateFeeSet(address indexed edition, uint128 indexed mintId, uint16 bps); /** * @notice Emitted when a mint happens. * @param edition The edition address. * @param mintId The mint ID, to distinguish between multiple mints for * the same edition. * @param buyer The buyer address. * @param fromTokenId The first token ID of the batch. * @param quantity The size of the batch. * @param requiredEtherValue Total amount of Ether required for payment. * @param platformFee The cut paid to the platform. * @param affiliateFee The cut paid to the affiliate. * @param affiliate The affiliate's address. * @param affiliated Whether the affiliate is affiliated. */ event Minted( address indexed edition, uint128 indexed mintId, address indexed buyer, uint32 fromTokenId, uint32 quantity, uint128 requiredEtherValue, uint128 platformFee, uint128 affiliateFee, address affiliate, bool affiliated ); // ============================================================= // ERRORS // ============================================================= /** * @dev The Ether value paid is below the value required. * @param paid The amount sent to the contract. * @param required The amount required to mint. */ error Underpaid(uint256 paid, uint256 required); /** * @dev The number minted has exceeded the max mintable amount. * @param available The number of tokens remaining available for mint. */ error ExceedsAvailableSupply(uint32 available); /** * @dev The mint is not opened. * @param blockTimestamp The current block timestamp. * @param startTime The start time of the mint. * @param endTime The end time of the mint. */ error MintNotOpen(uint256 blockTimestamp, uint32 startTime, uint32 endTime); /** * @dev The mint is paused. */ error MintPaused(); /** * @dev The `startTime` is not less than the `endTime`. */ error InvalidTimeRange(); /** * @dev Unauthorized caller */ error Unauthorized(); /** * @dev The affiliate fee numerator must not exceed `MAX_BPS`. */ error InvalidAffiliateFeeBPS(); /** * @dev Fee registry cannot be the zero address. */ error FeeRegistryIsZeroAddress(); // ============================================================= // PUBLIC / EXTERNAL WRITE FUNCTIONS // ============================================================= /** * @dev Sets the paused status for (`edition`, `mintId`). * * Calling conditions: * - The caller must be the edition's owner or admin. */ function setEditionMintPaused( address edition, uint128 mintId, bool paused ) external; /** * @dev Sets the time range for an edition mint. * * Calling conditions: * - The caller must be the edition's owner or admin. * * @param edition The edition address. * @param mintId The mint ID, a global incrementing identifier used within the minter * @param startTime The start time of the mint. * @param endTime The end time of the mint. */ function setTimeRange( address edition, uint128 mintId, uint32 startTime, uint32 endTime ) external; /** * @dev Sets the affiliate fee for (`edition`, `mintId`). * * Calling conditions: * - The caller must be the edition's owner or admin. */ function setAffiliateFee( address edition, uint128 mintId, uint16 affiliateFeeBPS ) external; /** * @dev Withdraws all the accrued fees for `affiliate`. */ function withdrawForAffiliate(address affiliate) external; /** * @dev Withdraws all the accrued fees for the platform. */ function withdrawForPlatform() external; // ============================================================= // PUBLIC / EXTERNAL VIEW FUNCTIONS // ============================================================= /** * @dev The total fees accrued for `affiliate`. * @param affiliate The affiliate's address. * @return The latest value. */ function affiliateFeesAccrued(address affiliate) external view returns (uint128); /** * @dev The total fees accrued for the platform. * @return The latest value. */ function platformFeesAccrued() external view returns (uint128); /** * @dev Whether `affiliate` is affiliated for (`edition`, `mintId`). * @param edition The edition's address. * @param mintId The mint ID. * @param affiliate The affiliate's address. * @return The computed value. */ function isAffiliated( address edition, uint128 mintId, address affiliate ) external view returns (bool); /** * @dev The total price for `quantity` tokens for (`edition`, `mintId`). * @param edition The edition's address. * @param mintId The mint ID. * @param mintId The minter's address. * @param quantity The number of tokens to mint. * @return The computed value. */ function totalPrice( address edition, uint128 mintId, address minter, uint32 quantity ) external view returns (uint128); /** * @dev The next mint ID. * A mint ID is assigned sequentially starting from (0, 1, 2, ...), * and is shared amongst all editions connected to the minter contract. * @return The latest value. */ function nextMintId() external view returns (uint128); /** * @dev The interface ID of the minter. * @return The constant value. */ function moduleInterfaceId() external view returns (bytes4); /** * @dev The fee registry. Used for handling platform fees. * @return The immutable value. */ function feeRegistry() external view returns (ISoundFeeRegistry); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.16; /** * @title IMetadataModule * @notice The interface for custom metadata modules. */ interface IMetadataModule { /** * @dev When implemented, SoundEdition's `tokenURI` redirects execution to this `tokenURI`. * @param tokenId The token ID to retrieve the token URI for. * @return The token URI string. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "./IERC165Upgradeable.sol"; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. * * _Available since v4.5._ */ interface IERC2981Upgradeable is IERC165Upgradeable { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.2 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev Interface of ERC721A. */ interface IERC721AUpgradeable { /** * The caller must own the token or be an approved operator. */ error ApprovalCallerNotOwnerNorApproved(); /** * The token does not exist. */ error ApprovalQueryForNonexistentToken(); /** * Cannot query the balance for the zero address. */ error BalanceQueryForZeroAddress(); /** * Cannot mint to the zero address. */ error MintToZeroAddress(); /** * The quantity of tokens minted must be more than zero. */ error MintZeroQuantity(); /** * The token does not exist. */ error OwnerQueryForNonexistentToken(); /** * The caller must own the token or be an approved operator. */ error TransferCallerNotOwnerNorApproved(); /** * The token must be owned by `from`. */ error TransferFromIncorrectOwner(); /** * Cannot safely transfer to a contract that does not implement the * ERC721Receiver interface. */ error TransferToNonERC721ReceiverImplementer(); /** * Cannot transfer to the zero address. */ error TransferToZeroAddress(); /** * The token does not exist. */ error URIQueryForNonexistentToken(); /** * The `quantity` minted with ERC2309 exceeds the safety limit. */ error MintERC2309QuantityExceedsLimit(); /** * The `extraData` cannot be set on an unintialized ownership slot. */ error OwnershipNotInitializedForExtraData(); // ============================================================= // STRUCTS // ============================================================= struct TokenOwnership { // The address of the owner. address addr; // Stores the start time of ownership with minimal overhead for tokenomics. uint64 startTimestamp; // Whether the token has been burned. bool burned; // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}. uint24 extraData; } // ============================================================= // TOKEN COUNTERS // ============================================================= /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() external view returns (uint256); // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); // ============================================================= // IERC721 // ============================================================= /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables * (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, * checking first that contract recipients are aware of the ERC721 protocol * to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move * this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} * whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the * zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} * for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) external view returns (bool); // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); // ============================================================= // IERC2309 // ============================================================= /** * @dev Emitted when tokens in `fromTokenId` to `toTokenId` * (inclusive) is transferred from `from` to `to`, as defined in the * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard. * * See {_mintERC2309} for more details. */ event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/FixedPointMathLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol) library FixedPointMathLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The operation failed, as the output exceeds the maximum value of uint256. error ExpOverflow(); /// @dev The operation failed, as the output exceeds the maximum value of uint256. error FactorialOverflow(); /// @dev The operation failed, due to an multiplication overflow. error MulWadFailed(); /// @dev The operation failed, either due to a /// multiplication overflow, or a division by a zero. error DivWadFailed(); /// @dev The multiply-divide operation failed, either due to a /// multiplication overflow, or a division by a zero. error MulDivFailed(); /// @dev The division failed, as the denominator is zero. error DivFailed(); /// @dev The output is undefined, as the input is less-than-or-equal to zero. error LnWadUndefined(); /// @dev The output is undefined, as the input is zero. error Log2Undefined(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The scalar of ETH and most ERC20s. uint256 internal constant WAD = 1e18; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* SIMPLIFIED FIXED POINT OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Equivalent to `(x * y) / WAD` rounded down. function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`. if mul(y, gt(x, div(not(0), y))) { // Store the function selector of `MulWadFailed()`. mstore(0x00, 0xbac65e5b) // Revert with (offset, size). revert(0x1c, 0x04) } z := div(mul(x, y), WAD) } } /// @dev Equivalent to `(x * y) / WAD` rounded up. function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`. if mul(y, gt(x, div(not(0), y))) { // Store the function selector of `MulWadFailed()`. mstore(0x00, 0xbac65e5b) // Revert with (offset, size). revert(0x1c, 0x04) } z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD)) } } /// @dev Equivalent to `(x * WAD) / y` rounded down. function divWadDown(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { // Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`. if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) { // Store the function selector of `DivWadFailed()`. mstore(0x00, 0x7c5f487d) // Revert with (offset, size). revert(0x1c, 0x04) } z := div(mul(x, WAD), y) } } /// @dev Equivalent to `(x * WAD) / y` rounded up. function divWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { // Equivalent to `require(y != 0 && (WAD == 0 || x <= type(uint256).max / WAD))`. if iszero(mul(y, iszero(mul(WAD, gt(x, div(not(0), WAD)))))) { // Store the function selector of `DivWadFailed()`. mstore(0x00, 0x7c5f487d) // Revert with (offset, size). revert(0x1c, 0x04) } z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y)) } } /// @dev Equivalent to `x` to the power of `y`. /// because `x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)`. function powWad(int256 x, int256 y) internal pure returns (int256) { // Using `ln(x)` means `x` must be greater than 0. return expWad((lnWad(x) * y) / int256(WAD)); } /// @dev Returns `exp(x)`, denominated in `WAD`. function expWad(int256 x) internal pure returns (int256 r) { unchecked { // When the result is < 0.5 we return zero. This happens when // x <= floor(log(0.5e18) * 1e18) ~ -42e18 if (x <= -42139678854452767551) return 0; // When the result is > (2**255 - 1) / 1e18 we can not represent it as an // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135. if (x >= 135305999368893231589) revert ExpOverflow(); // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96 // for more intermediate precision and a binary basis. This base conversion // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78. x = (x << 78) / 5**18; // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers // of two such that exp(x) = exp(x') * 2**k, where k is an integer. // Solving this gives k = round(x / log(2)) and x' = x - k * log(2). int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96; x = x - k * 54916777467707473351141471128; // k is in the range [-61, 195]. // Evaluate using a (6, 7)-term rational approximation. // p is made monic, we'll multiply by a scale factor later. int256 y = x + 1346386616545796478920950773328; y = ((y * x) >> 96) + 57155421227552351082224309758442; int256 p = y + x - 94201549194550492254356042504812; p = ((p * y) >> 96) + 28719021644029726153956944680412240; p = p * x + (4385272521454847904659076985693276 << 96); // We leave p in 2**192 basis so we don't need to scale it back up for the division. int256 q = x - 2855989394907223263936484059900; q = ((q * x) >> 96) + 50020603652535783019961831881945; q = ((q * x) >> 96) - 533845033583426703283633433725380; q = ((q * x) >> 96) + 3604857256930695427073651918091429; q = ((q * x) >> 96) - 14423608567350463180887372962807573; q = ((q * x) >> 96) + 26449188498355588339934803723976023; assembly { // Div in assembly because solidity adds a zero check despite the unchecked. // The q polynomial won't have zeros in the domain as all its roots are complex. // No scaling is necessary because p is already 2**96 too large. r := sdiv(p, q) } // r should be in the range (0.09, 0.25) * 2**96. // We now need to multiply r by: // * the scale factor s = ~6.031367120. // * the 2**k factor from the range reduction. // * the 1e18 / 2**96 factor for base conversion. // We do this all at once, with an intermediate result in 2**213 // basis, so the final right shift is always by a positive amount. r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k)); } } /// @dev Returns `ln(x)`, denominated in `WAD`. function lnWad(int256 x) internal pure returns (int256 r) { unchecked { if (x <= 0) revert LnWadUndefined(); // We want to convert x from 10**18 fixed point to 2**96 fixed point. // We do this by multiplying by 2**96 / 10**18. But since // ln(x * C) = ln(x) + ln(C), we can simply do nothing here // and add ln(2**96 / 10**18) at the end. // Compute k = log2(x) - 96. int256 k; assembly { let v := x k := shl(7, lt(0xffffffffffffffffffffffffffffffff, v)) k := or(k, shl(6, lt(0xffffffffffffffff, shr(k, v)))) k := or(k, shl(5, lt(0xffffffff, shr(k, v)))) // For the remaining 32 bits, use a De Bruijn lookup. // See: https://graphics.stanford.edu/~seander/bithacks.html v := shr(k, v) v := or(v, shr(1, v)) v := or(v, shr(2, v)) v := or(v, shr(4, v)) v := or(v, shr(8, v)) v := or(v, shr(16, v)) // prettier-ignore k := sub(or(k, byte(shr(251, mul(v, shl(224, 0x07c4acdd))), 0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f)), 96) } // Reduce range of x to (1, 2) * 2**96 // ln(2^k * x) = k * ln(2) + ln(x) x <<= uint256(159 - k); x = int256(uint256(x) >> 159); // Evaluate using a (8, 8)-term rational approximation. // p is made monic, we will multiply by a scale factor later. int256 p = x + 3273285459638523848632254066296; p = ((p * x) >> 96) + 24828157081833163892658089445524; p = ((p * x) >> 96) + 43456485725739037958740375743393; p = ((p * x) >> 96) - 11111509109440967052023855526967; p = ((p * x) >> 96) - 45023709667254063763336534515857; p = ((p * x) >> 96) - 14706773417378608786704636184526; p = p * x - (795164235651350426258249787498 << 96); // We leave p in 2**192 basis so we don't need to scale it back up for the division. // q is monic by convention. int256 q = x + 5573035233440673466300451813936; q = ((q * x) >> 96) + 71694874799317883764090561454958; q = ((q * x) >> 96) + 283447036172924575727196451306956; q = ((q * x) >> 96) + 401686690394027663651624208769553; q = ((q * x) >> 96) + 204048457590392012362485061816622; q = ((q * x) >> 96) + 31853899698501571402653359427138; q = ((q * x) >> 96) + 909429971244387300277376558375; assembly { // Div in assembly because solidity adds a zero check despite the unchecked. // The q polynomial is known not to have zeros in the domain. // No scaling required because p is already 2**96 too large. r := sdiv(p, q) } // r is in the range (0, 0.125) * 2**96 // Finalization, we need to: // * multiply by the scale factor s = 5.549… // * add ln(2**96 / 10**18) // * add k * ln(2) // * multiply by 10**18 / 2**96 = 5**18 >> 78 // mul s * 5e18 * 2**96, base is now 5**18 * 2**192 r *= 1677202110996718588342820967067443963516166; // add ln(2) * k * 5e18 * 2**192 r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k; // add ln(2**96 / 10**18) * 5e18 * 2**192 r += 600920179829731861736702779321621459595472258049074101567377883020018308; // base conversion: mul 2**18 / 2**192 r >>= 174; } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* GENERAL NUMBER UTILITIES */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns `floor(x * y / denominator)`. /// Reverts if `x * y` overflows, or `denominator` is zero. function mulDivDown( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(denominator, iszero(mul(y, gt(x, div(not(0), y)))))) { // Store the function selector of `MulDivFailed()`. mstore(0x00, 0xad251c27) // Revert with (offset, size). revert(0x1c, 0x04) } z := div(mul(x, y), denominator) } } /// @dev Returns `ceil(x * y / denominator)`. /// Reverts if `x * y` overflows, or `denominator` is zero. function mulDivUp( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(denominator, iszero(mul(y, gt(x, div(not(0), y)))))) { // Store the function selector of `MulDivFailed()`. mstore(0x00, 0xad251c27) // Revert with (offset, size). revert(0x1c, 0x04) } z := add(iszero(iszero(mod(mul(x, y), denominator))), div(mul(x, y), denominator)) } } /// @dev Returns `ceil(x / denominator)`. /// Reverts if `denominator` is zero. function divUp(uint256 x, uint256 denominator) internal pure returns (uint256 z) { assembly { if iszero(denominator) { // Store the function selector of `DivFailed()`. mstore(0x00, 0x65244e4e) // Revert with (offset, size). revert(0x1c, 0x04) } z := add(iszero(iszero(mod(x, denominator))), div(x, denominator)) } } /// @dev Returns `max(0, x - y)`. function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { z := mul(gt(x, y), sub(x, y)) } } /// @dev Returns the square root of `x`. function sqrt(uint256 x) internal pure returns (uint256 z) { assembly { // `floor(sqrt(2**15)) = 181`. `sqrt(2**15) - 181 = 2.84`. z := 181 // The "correct" value is 1, but this saves a multiplication later. // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. // Let `y = x / 2**r`. // We check `y >= 2**(k + 8)` but shift right by `k` bits // each branch to ensure that if `x >= 256`, then `y >= 256`. let r := shl(7, gt(x, 0xffffffffffffffffffffffffffffffffff)) r := or(r, shl(6, gt(shr(r, x), 0xffffffffffffffffff))) r := or(r, shl(5, gt(shr(r, x), 0xffffffffff))) r := or(r, shl(4, gt(shr(r, x), 0xffffff))) z := shl(shr(1, r), z) // Goal was to get `z*z*y` within a small factor of `x`. More iterations could // get y in a tighter range. Currently, we will have y in `[256, 256*(2**16))`. // We ensured `y >= 256` so that the relative difference between `y` and `y+1` is small. // That's not possible if `x < 256` but we can just verify those cases exhaustively. // Now, `z*z*y <= x < z*z*(y+1)`, and `y <= 2**(16+8)`, and either `y >= 256`, or `x < 256`. // Correctness can be checked exhaustively for `x < 256`, so we assume `y >= 256`. // Then `z*sqrt(y)` is within `sqrt(257)/sqrt(256)` of `sqrt(x)`, or about 20bps. // For `s` in the range `[1/256, 256]`, the estimate `f(s) = (181/1024) * (s+1)` // is in the range `(1/2.84 * sqrt(s), 2.84 * sqrt(s))`, // with largest error when `s = 1` and when `s = 256` or `1/256`. // Since `y` is in `[256, 256*(2**16))`, let `a = y/65536`, so that `a` is in `[1/256, 256)`. // Then we can estimate `sqrt(y)` using // `sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2**18`. // There is no overflow risk here since `y < 2**136` after the first branch above. z := shr(18, mul(z, add(shr(r, x), 65536))) // A `mul()` is saved from starting `z` at 181. // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // If `x+1` is a perfect square, the Babylonian method cycles between // `floor(sqrt(x))` and `ceil(sqrt(x))`. This statement ensures we return floor. // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case. // If you don't care whether the floor or ceil square root is returned, you can remove this statement. z := sub(z, lt(div(x, z), z)) } } /// @dev Returns the factorial of `x`. function factorial(uint256 x) public pure returns (uint256 result) { unchecked { if (x < 11) { // prettier-ignore result = (0x375f0016260009d80004ec0002d00001e0000180000180000200000400001 >> (x * 22)) & 0x3fffff; } else if (x < 32) { result = 3628800; do { result = result * x; x = x - 1; } while (x != 10); } else if (x < 58) { // Just cheat lol. result = 8222838654177922817725562880000000; do { result = result * x; x = x - 1; } while (x != 31); } else { revert FactorialOverflow(); } } } /// @dev Returns the log2 of `x`. /// Equivalent to computing the index of the most significant bit (MSB) of `x`. function log2(uint256 x) internal pure returns (uint256 r) { assembly { if iszero(x) { // Store the function selector of `Log2Undefined()`. mstore(0x00, 0x5be3aa5c) // Revert with (offset, size). revert(0x1c, 0x04) } r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) // For the remaining 32 bits, use a De Bruijn lookup. // See: https://graphics.stanford.edu/~seander/bithacks.html x := shr(r, x) x := or(x, shr(1, x)) x := or(x, shr(2, x)) x := or(x, shr(4, x)) x := or(x, shr(8, x)) x := or(x, shr(16, x)) // prettier-ignore r := or(r, byte(shr(251, mul(x, shl(224, 0x07c4acdd))), 0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f)) } } /// @dev Returns the averege of `x` and `y`. function avg(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { z := add(and(x, y), shr(1, xor(x, y))) } } /// @dev Returns the absolute value of `x`. function abs(int256 x) internal pure returns (uint256 z) { assembly { let mask := mul(shr(255, x), not(0)) z := xor(mask, add(mask, x)) } } /// @dev Returns the absolute distance between `x` and `y`. function dist(int256 x, int256 y) internal pure returns (uint256 z) { assembly { let a := sub(y, x) z := xor(a, mul(xor(a, sub(x, y)), sgt(x, y))) } } /// @dev Returns the minimum of `x` and `y`. function min(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { z := xor(x, mul(xor(x, y), lt(y, x))) } } /// @dev Returns the maximum of `x` and `y`. function max(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { z := xor(x, mul(xor(x, y), gt(y, x))) } } /// @dev Returns gcd of `x` and `y`. function gcd(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { // prettier-ignore for { z := x } y {} { let t := y y := mod(z, y) z := t } } } /// @dev Returns `x`, bounded to `minValue` and `maxValue`. function clamp( uint256 x, uint256 minValue, uint256 maxValue ) internal pure returns (uint256 z) { return min(max(x, minValue), maxValue); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Caution! This library won't check that a token has code, responsibility is delegated to the caller. library SafeTransferLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ error ETHTransferFailed(); error TransferFromFailed(); error TransferFailed(); error ApproveFailed(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ETH OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function safeTransferETH(address to, uint256 amount) internal { assembly { // Transfer the ETH and check if it succeeded or not. if iszero(call(gas(), to, amount, 0, 0, 0, 0)) { // Store the function selector of `ETHTransferFailed()`. mstore(0x00, 0xb12d13eb) // Revert with (offset, size). revert(0x1c, 0x04) } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function safeTransferFrom( address token, address from, address to, uint256 amount ) internal { assembly { // We'll write our calldata to this slot below, but restore it later. let memPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(0x00, 0x23b872dd) mstore(0x20, from) // Append the "from" argument. mstore(0x40, to) // Append the "to" argument. mstore(0x60, amount) // Append the "amount" argument. if iszero( and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), // We use 0x64 because that's the total length of our calldata (0x04 + 0x20 * 3) // Counterintuitively, this call() must be positioned after the or() in the // surrounding and() because and() evaluates its arguments from right to left. call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { // Store the function selector of `TransferFromFailed()`. mstore(0x00, 0x7939f424) // Revert with (offset, size). revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot to zero. mstore(0x40, memPointer) // Restore the memPointer. } } function safeTransfer( address token, address to, uint256 amount ) internal { assembly { // We'll write our calldata to this slot below, but restore it later. let memPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(0x00, 0xa9059cbb) mstore(0x20, to) // Append the "to" argument. mstore(0x40, amount) // Append the "amount" argument. if iszero( and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), // We use 0x44 because that's the total length of our calldata (0x04 + 0x20 * 2) // Counterintuitively, this call() must be positioned after the or() in the // surrounding and() because and() evaluates its arguments from right to left. call(gas(), token, 0, 0x1c, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `TransferFailed()`. mstore(0x00, 0x90b8ec18) // Revert with (offset, size). revert(0x1c, 0x04) } mstore(0x40, memPointer) // Restore the memPointer. } } function safeApprove( address token, address to, uint256 amount ) internal { assembly { // We'll write our calldata to this slot below, but restore it later. let memPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(0x00, 0x095ea7b3) mstore(0x20, to) // Append the "to" argument. mstore(0x40, amount) // Append the "amount" argument. if iszero( and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(eq(mload(0x00), 1), iszero(returndatasize())), // We use 0x44 because that's the total length of our calldata (0x04 + 0x20 * 2) // Counterintuitively, this call() must be positioned after the or() in the // surrounding and() because and() evaluates its arguments from right to left. call(gas(), token, 0, 0x1c, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `ApproveFailed()`. mstore(0x00, 0x3e3f8f73) // Revert with (offset, size). revert(0x1c, 0x04) } mstore(0x40, memPointer) // Restore the memPointer. } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Simple single owner and multiroles authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/OwnableRoles.sol) /// @dev While the ownable portion follows [EIP-173](https://eips.ethereum.org/EIPS/eip-173) /// for compatibility, the nomenclature for the 2-step ownership handover and roles /// may be unique to this codebase. abstract contract OwnableRoles { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The caller is not authorized to call the function. error Unauthorized(); /// @dev The `newOwner` cannot be the zero address. error NewOwnerIsZeroAddress(); /// @dev The `pendingOwner` does not have a valid handover request. error NoHandoverRequest(); /// @dev `bytes4(keccak256(bytes("Unauthorized()")))`. uint256 private constant _UNAUTHORIZED_ERROR_SELECTOR = 0x82b42900; /// @dev `bytes4(keccak256(bytes("NewOwnerIsZeroAddress()")))`. uint256 private constant _NEW_OWNER_IS_ZERO_ADDRESS_ERROR_SELECTOR = 0x7448fbae; /// @dev `bytes4(keccak256(bytes("NoHandoverRequest()")))`. uint256 private constant _NO_HANDOVER_REQUEST_ERROR_SELECTOR = 0x6f5e8818; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ownership is transferred from `oldOwner` to `newOwner`. /// This event is intentionally kept the same as OpenZeppelin's Ownable to be /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173), /// despite it not being as lightweight as a single argument event. event OwnershipTransferred(address indexed oldOwner, address indexed newOwner); /// @dev An ownership handover to `pendingOwner` has been requested. event OwnershipHandoverRequested(address indexed pendingOwner); /// @dev The ownership handover to `pendingOwner` has been cancelled. event OwnershipHandoverCanceled(address indexed pendingOwner); /// @dev The `user`'s roles is updated to `roles`. /// Each bit of `roles` represents whether the role is set. event RolesUpdated(address indexed user, uint256 indexed roles); /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`. uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE = 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0; /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE = 0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d; /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`. uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE = 0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92; /// @dev `keccak256(bytes("RolesUpdated(address,uint256)"))`. uint256 private constant _ROLES_UPDATED_EVENT_SIGNATURE = 0x715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The owner slot is given by: `not(_OWNER_SLOT_NOT)`. /// It is intentionally choosen to be a high value /// to avoid collision with lower slots. /// The choice of manual storage layout is to enable compatibility /// with both regular and upgradeable contracts. /// /// The role slot of `user` is given by: /// ``` /// mstore(0x00, or(shl(96, user), _OWNER_SLOT_NOT)) /// let roleSlot := keccak256(0x00, 0x20) /// ``` /// This automatically ignores the upper bits of the `user` in case /// they are not clean, as well as keep the `keccak256` under 32-bytes. uint256 private constant _OWNER_SLOT_NOT = 0x8b78c6d8; /// The ownership handover slot of `newOwner` is given by: /// ``` /// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED)) /// let handoverSlot := keccak256(0x00, 0x20) /// ``` /// It stores the expiry timestamp of the two-step ownership handover. uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Initializes the owner directly without authorization guard. /// This function must be called upon initialization, /// regardless of whether the contract is upgradeable or not. /// This is to enable generalization to both regular and upgradeable contracts, /// and to save gas in case the initial owner is not the caller. /// For performance reasons, this function will not check if there /// is an existing owner. function _initializeOwner(address newOwner) internal virtual { assembly { // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(not(_OWNER_SLOT_NOT), newOwner) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } /// @dev Sets the owner directly without authorization guard. function _setOwner(address newOwner) internal virtual { assembly { let ownerSlot := not(_OWNER_SLOT_NOT) // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner) // Store the new value. sstore(ownerSlot, newOwner) } } /// @dev Grants the roles directly without authorization guard. /// Each bit of `roles` represents the role to turn on. function _grantRoles(address user, uint256 roles) internal virtual { assembly { // Compute the role slot. mstore(0x00, or(shl(96, user), _OWNER_SLOT_NOT)) let roleSlot := keccak256(0x00, 0x20) // Load the current value and `or` it with `roles`. let newRoles := or(sload(roleSlot), roles) // Store the new value. sstore(roleSlot, newRoles) // Emit the {RolesUpdated} event. log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, shl(96, user)), newRoles) } } /// @dev Removes the roles directly without authorization guard. /// Each bit of `roles` represents the role to turn off. function _removeRoles(address user, uint256 roles) internal virtual { assembly { // Compute the role slot. mstore(0x00, or(shl(96, user), _OWNER_SLOT_NOT)) let roleSlot := keccak256(0x00, 0x20) // Load the current value. let currentRoles := sload(roleSlot) // Use `and` to compute the intersection of `currentRoles` and `roles`, // `xor` it with `currentRoles` to flip the bits in the intersection. let newRoles := xor(currentRoles, and(currentRoles, roles)) // Then, store the new value. sstore(roleSlot, newRoles) // Emit the {RolesUpdated} event. log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, shl(96, user)), newRoles) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Allows the owner to transfer the ownership to `newOwner`. function transferOwnership(address newOwner) public virtual onlyOwner { assembly { // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Reverts if the `newOwner` is the zero address. if iszero(newOwner) { mstore(0x00, _NEW_OWNER_IS_ZERO_ADDRESS_ERROR_SELECTOR) revert(0x1c, 0x04) } // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, caller(), newOwner) // Store the new value. sstore(not(_OWNER_SLOT_NOT), newOwner) } } /// @dev Allows the owner to renounce their ownership. function renounceOwnership() public virtual onlyOwner { assembly { // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, caller(), 0) // Store the new value. sstore(not(_OWNER_SLOT_NOT), 0) } } /// @dev Request a two-step ownership handover to the caller. /// The request will be automatically expire in 48 hours (172800 seconds) by default. function requestOwnershipHandover() public virtual { unchecked { uint256 expires = block.timestamp + ownershipHandoverValidFor(); assembly { // Compute and set the handover slot to 1. mstore(0x00, or(shl(96, caller()), _HANDOVER_SLOT_SEED)) sstore(keccak256(0x00, 0x20), expires) // Emit the {OwnershipHandoverRequested} event. log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller()) } } } /// @dev Cancels the two-step ownership handover to the caller, if any. function cancelOwnershipHandover() public virtual { assembly { // Compute and set the handover slot to 0. mstore(0x00, or(shl(96, caller()), _HANDOVER_SLOT_SEED)) sstore(keccak256(0x00, 0x20), 0) // Emit the {OwnershipHandoverCanceled} event. log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller()) } } /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`. /// Reverts if there is no existing ownership handover requested by `pendingOwner`. function completeOwnershipHandover(address pendingOwner) public virtual onlyOwner { assembly { // Clean the upper 96 bits. pendingOwner := shr(96, shl(96, pendingOwner)) // Compute and set the handover slot to 0. mstore(0x00, or(shl(96, pendingOwner), _HANDOVER_SLOT_SEED)) let handoverSlot := keccak256(0x00, 0x20) // If the handover does not exist, or has expired. if gt(timestamp(), sload(handoverSlot)) { mstore(0x00, _NO_HANDOVER_REQUEST_ERROR_SELECTOR) revert(0x1c, 0x04) } // Set the handover slot to 0. sstore(handoverSlot, 0) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, caller(), pendingOwner) // Store the new value. sstore(not(_OWNER_SLOT_NOT), pendingOwner) } } /// @dev Allows the owner to grant `user` `roles`. /// If the `user` already has a role, then it will be an no-op for the role. function grantRoles(address user, uint256 roles) public virtual onlyOwner { _grantRoles(user, roles); } /// @dev Allows the owner to remove `user` `roles`. /// If the `user` does not have a role, then it will be an no-op for the role. function revokeRoles(address user, uint256 roles) public virtual onlyOwner { _removeRoles(user, roles); } /// @dev Allow the caller to remove their own roles. /// If the caller does not have a role, then it will be an no-op for the role. function renounceRoles(uint256 roles) public virtual { _removeRoles(msg.sender, roles); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the owner of the contract. function owner() public view virtual returns (address result) { assembly { result := sload(not(_OWNER_SLOT_NOT)) } } /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`. function ownershipHandoverExpiresAt(address pendingOwner) public view virtual returns (uint256 result) { assembly { // Compute the handover slot. mstore(0x00, or(shl(96, pendingOwner), _HANDOVER_SLOT_SEED)) // Load the handover slot. result := sload(keccak256(0x00, 0x20)) } } /// @dev Returns how long a two-step ownership handover is valid for in seconds. function ownershipHandoverValidFor() public view virtual returns (uint64) { return 48 * 3600; } /// @dev Returns whether `user` has any of `roles`. function hasAnyRole(address user, uint256 roles) public view virtual returns (bool result) { assembly { // Compute the role slot. mstore(0x00, or(shl(96, user), _OWNER_SLOT_NOT)) // Load the stored value, and set the result to whether the // `and` intersection of the value and `roles` is not zero. result := iszero(iszero(and(sload(keccak256(0x00, 0x20)), roles))) } } /// @dev Returns whether `user` has all of `roles`. function hasAllRoles(address user, uint256 roles) public view virtual returns (bool result) { assembly { // Compute the role slot. mstore(0x00, or(shl(96, user), _OWNER_SLOT_NOT)) // Whether the stored value is contains all the set bits in `roles`. result := eq(and(sload(keccak256(0x00, 0x20)), roles), roles) } } /// @dev Returns the roles of `user`. function rolesOf(address user) public view virtual returns (uint256 roles) { assembly { // Compute the role slot. mstore(0x00, or(shl(96, user), _OWNER_SLOT_NOT)) // Load the stored value. roles := sload(keccak256(0x00, 0x20)) } } /// @dev Convenience function to return a `roles` bitmap from the `ordinals`. /// This is meant for frontends like Etherscan, and is therefore not fully optimized. /// Not recommended to be called on-chain. function rolesFromOrdinals(uint8[] memory ordinals) public pure returns (uint256 roles) { assembly { // Skip the length slot. let o := add(ordinals, 0x20) // `shl` 5 is equivalent to multiplying by 0x20. let end := add(o, shl(5, mload(ordinals))) // prettier-ignore for {} iszero(eq(o, end)) { o := add(o, 0x20) } { roles := or(roles, shl(and(mload(o), 0xff), 1)) } } } /// @dev Convenience function to return a `roles` bitmap from the `ordinals`. /// This is meant for frontends like Etherscan, and is therefore not fully optimized. /// Not recommended to be called on-chain. function ordinalsFromRoles(uint256 roles) public pure returns (uint8[] memory ordinals) { assembly { // Grab the pointer to the free memory. let ptr := add(mload(0x40), 0x20) // The absence of lookup tables, De Bruijn, etc., here is intentional for // smaller bytecode, as this function is not meant to be called on-chain. // prettier-ignore for { let i := 0 } 1 { i := add(i, 1) } { mstore(ptr, i) // `shr` 5 is equivalent to multiplying by 0x20. // Push back into the ordinals array if the bit is set. ptr := add(ptr, shl(5, and(roles, 1))) roles := shr(1, roles) // prettier-ignore if iszero(roles) { break } } // Set `ordinals` to the start of the free memory. ordinals := mload(0x40) // Allocate the memory. mstore(0x40, ptr) // Store the length of `ordinals`. mstore(ordinals, shr(5, sub(ptr, add(ordinals, 0x20)))) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by the owner. modifier onlyOwner() virtual { assembly { // If the caller is not the stored owner, revert. if iszero(eq(caller(), sload(not(_OWNER_SLOT_NOT)))) { mstore(0x00, _UNAUTHORIZED_ERROR_SELECTOR) revert(0x1c, 0x04) } } _; } /// @dev Marks a function as only callable by an account with `roles`. modifier onlyRoles(uint256 roles) virtual { assembly { // Compute the role slot. mstore(0x00, or(shl(96, caller()), _OWNER_SLOT_NOT)) // Load the stored value, and if the `and` intersection // of the value and `roles` is zero, revert. if iszero(and(sload(keccak256(0x00, 0x20)), roles)) { mstore(0x00, _UNAUTHORIZED_ERROR_SELECTOR) revert(0x1c, 0x04) } } _; } /// @dev Marks a function as only callable by the owner or by an account /// with `roles`. Checks for ownership first, then lazily checks for roles. modifier onlyOwnerOrRoles(uint256 roles) virtual { assembly { // If the caller is not the stored owner. if iszero(eq(caller(), sload(not(_OWNER_SLOT_NOT)))) { // Compute the role slot. mstore(0x00, or(shl(96, caller()), _OWNER_SLOT_NOT)) // Load the stored value, and if the `and` intersection // of the value and `roles` is zero, revert. if iszero(and(sload(keccak256(0x00, 0x20)), roles)) { mstore(0x00, _UNAUTHORIZED_ERROR_SELECTOR) revert(0x1c, 0x04) } } } _; } /// @dev Marks a function as only callable by an account with `roles` /// or the owner. Checks for roles first, then lazily checks for ownership. modifier onlyRolesOrOwner(uint256 roles) virtual { assembly { // Compute the role slot. mstore(0x00, or(shl(96, caller()), _OWNER_SLOT_NOT)) // Load the stored value, and if the `and` intersection // of the value and `roles` is zero, revert. if iszero(and(sload(keccak256(0x00, 0x20)), roles)) { // If the caller is not the stored owner. if iszero(eq(caller(), sload(not(_OWNER_SLOT_NOT)))) { mstore(0x00, _UNAUTHORIZED_ERROR_SELECTOR) revert(0x1c, 0x04) } } } _; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ROLE CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // IYKYK uint256 internal constant _ROLE_0 = 1 << 0; uint256 internal constant _ROLE_1 = 1 << 1; uint256 internal constant _ROLE_2 = 1 << 2; uint256 internal constant _ROLE_3 = 1 << 3; uint256 internal constant _ROLE_4 = 1 << 4; uint256 internal constant _ROLE_5 = 1 << 5; uint256 internal constant _ROLE_6 = 1 << 6; uint256 internal constant _ROLE_7 = 1 << 7; uint256 internal constant _ROLE_8 = 1 << 8; uint256 internal constant _ROLE_9 = 1 << 9; uint256 internal constant _ROLE_10 = 1 << 10; uint256 internal constant _ROLE_11 = 1 << 11; uint256 internal constant _ROLE_12 = 1 << 12; uint256 internal constant _ROLE_13 = 1 << 13; uint256 internal constant _ROLE_14 = 1 << 14; uint256 internal constant _ROLE_15 = 1 << 15; uint256 internal constant _ROLE_16 = 1 << 16; uint256 internal constant _ROLE_17 = 1 << 17; uint256 internal constant _ROLE_18 = 1 << 18; uint256 internal constant _ROLE_19 = 1 << 19; uint256 internal constant _ROLE_20 = 1 << 20; uint256 internal constant _ROLE_21 = 1 << 21; uint256 internal constant _ROLE_22 = 1 << 22; uint256 internal constant _ROLE_23 = 1 << 23; uint256 internal constant _ROLE_24 = 1 << 24; uint256 internal constant _ROLE_25 = 1 << 25; uint256 internal constant _ROLE_26 = 1 << 26; uint256 internal constant _ROLE_27 = 1 << 27; uint256 internal constant _ROLE_28 = 1 << 28; uint256 internal constant _ROLE_29 = 1 << 29; uint256 internal constant _ROLE_30 = 1 << 30; uint256 internal constant _ROLE_31 = 1 << 31; uint256 internal constant _ROLE_32 = 1 << 32; uint256 internal constant _ROLE_33 = 1 << 33; uint256 internal constant _ROLE_34 = 1 << 34; uint256 internal constant _ROLE_35 = 1 << 35; uint256 internal constant _ROLE_36 = 1 << 36; uint256 internal constant _ROLE_37 = 1 << 37; uint256 internal constant _ROLE_38 = 1 << 38; uint256 internal constant _ROLE_39 = 1 << 39; uint256 internal constant _ROLE_40 = 1 << 40; uint256 internal constant _ROLE_41 = 1 << 41; uint256 internal constant _ROLE_42 = 1 << 42; uint256 internal constant _ROLE_43 = 1 << 43; uint256 internal constant _ROLE_44 = 1 << 44; uint256 internal constant _ROLE_45 = 1 << 45; uint256 internal constant _ROLE_46 = 1 << 46; uint256 internal constant _ROLE_47 = 1 << 47; uint256 internal constant _ROLE_48 = 1 << 48; uint256 internal constant _ROLE_49 = 1 << 49; uint256 internal constant _ROLE_50 = 1 << 50; uint256 internal constant _ROLE_51 = 1 << 51; uint256 internal constant _ROLE_52 = 1 << 52; uint256 internal constant _ROLE_53 = 1 << 53; uint256 internal constant _ROLE_54 = 1 << 54; uint256 internal constant _ROLE_55 = 1 << 55; uint256 internal constant _ROLE_56 = 1 << 56; uint256 internal constant _ROLE_57 = 1 << 57; uint256 internal constant _ROLE_58 = 1 << 58; uint256 internal constant _ROLE_59 = 1 << 59; uint256 internal constant _ROLE_60 = 1 << 60; uint256 internal constant _ROLE_61 = 1 << 61; uint256 internal constant _ROLE_62 = 1 << 62; uint256 internal constant _ROLE_63 = 1 << 63; uint256 internal constant _ROLE_64 = 1 << 64; uint256 internal constant _ROLE_65 = 1 << 65; uint256 internal constant _ROLE_66 = 1 << 66; uint256 internal constant _ROLE_67 = 1 << 67; uint256 internal constant _ROLE_68 = 1 << 68; uint256 internal constant _ROLE_69 = 1 << 69; uint256 internal constant _ROLE_70 = 1 << 70; uint256 internal constant _ROLE_71 = 1 << 71; uint256 internal constant _ROLE_72 = 1 << 72; uint256 internal constant _ROLE_73 = 1 << 73; uint256 internal constant _ROLE_74 = 1 << 74; uint256 internal constant _ROLE_75 = 1 << 75; uint256 internal constant _ROLE_76 = 1 << 76; uint256 internal constant _ROLE_77 = 1 << 77; uint256 internal constant _ROLE_78 = 1 << 78; uint256 internal constant _ROLE_79 = 1 << 79; uint256 internal constant _ROLE_80 = 1 << 80; uint256 internal constant _ROLE_81 = 1 << 81; uint256 internal constant _ROLE_82 = 1 << 82; uint256 internal constant _ROLE_83 = 1 << 83; uint256 internal constant _ROLE_84 = 1 << 84; uint256 internal constant _ROLE_85 = 1 << 85; uint256 internal constant _ROLE_86 = 1 << 86; uint256 internal constant _ROLE_87 = 1 << 87; uint256 internal constant _ROLE_88 = 1 << 88; uint256 internal constant _ROLE_89 = 1 << 89; uint256 internal constant _ROLE_90 = 1 << 90; uint256 internal constant _ROLE_91 = 1 << 91; uint256 internal constant _ROLE_92 = 1 << 92; uint256 internal constant _ROLE_93 = 1 << 93; uint256 internal constant _ROLE_94 = 1 << 94; uint256 internal constant _ROLE_95 = 1 << 95; uint256 internal constant _ROLE_96 = 1 << 96; uint256 internal constant _ROLE_97 = 1 << 97; uint256 internal constant _ROLE_98 = 1 << 98; uint256 internal constant _ROLE_99 = 1 << 99; uint256 internal constant _ROLE_100 = 1 << 100; uint256 internal constant _ROLE_101 = 1 << 101; uint256 internal constant _ROLE_102 = 1 << 102; uint256 internal constant _ROLE_103 = 1 << 103; uint256 internal constant _ROLE_104 = 1 << 104; uint256 internal constant _ROLE_105 = 1 << 105; uint256 internal constant _ROLE_106 = 1 << 106; uint256 internal constant _ROLE_107 = 1 << 107; uint256 internal constant _ROLE_108 = 1 << 108; uint256 internal constant _ROLE_109 = 1 << 109; uint256 internal constant _ROLE_110 = 1 << 110; uint256 internal constant _ROLE_111 = 1 << 111; uint256 internal constant _ROLE_112 = 1 << 112; uint256 internal constant _ROLE_113 = 1 << 113; uint256 internal constant _ROLE_114 = 1 << 114; uint256 internal constant _ROLE_115 = 1 << 115; uint256 internal constant _ROLE_116 = 1 << 116; uint256 internal constant _ROLE_117 = 1 << 117; uint256 internal constant _ROLE_118 = 1 << 118; uint256 internal constant _ROLE_119 = 1 << 119; uint256 internal constant _ROLE_120 = 1 << 120; uint256 internal constant _ROLE_121 = 1 << 121; uint256 internal constant _ROLE_122 = 1 << 122; uint256 internal constant _ROLE_123 = 1 << 123; uint256 internal constant _ROLE_124 = 1 << 124; uint256 internal constant _ROLE_125 = 1 << 125; uint256 internal constant _ROLE_126 = 1 << 126; uint256 internal constant _ROLE_127 = 1 << 127; uint256 internal constant _ROLE_128 = 1 << 128; uint256 internal constant _ROLE_129 = 1 << 129; uint256 internal constant _ROLE_130 = 1 << 130; uint256 internal constant _ROLE_131 = 1 << 131; uint256 internal constant _ROLE_132 = 1 << 132; uint256 internal constant _ROLE_133 = 1 << 133; uint256 internal constant _ROLE_134 = 1 << 134; uint256 internal constant _ROLE_135 = 1 << 135; uint256 internal constant _ROLE_136 = 1 << 136; uint256 internal constant _ROLE_137 = 1 << 137; uint256 internal constant _ROLE_138 = 1 << 138; uint256 internal constant _ROLE_139 = 1 << 139; uint256 internal constant _ROLE_140 = 1 << 140; uint256 internal constant _ROLE_141 = 1 << 141; uint256 internal constant _ROLE_142 = 1 << 142; uint256 internal constant _ROLE_143 = 1 << 143; uint256 internal constant _ROLE_144 = 1 << 144; uint256 internal constant _ROLE_145 = 1 << 145; uint256 internal constant _ROLE_146 = 1 << 146; uint256 internal constant _ROLE_147 = 1 << 147; uint256 internal constant _ROLE_148 = 1 << 148; uint256 internal constant _ROLE_149 = 1 << 149; uint256 internal constant _ROLE_150 = 1 << 150; uint256 internal constant _ROLE_151 = 1 << 151; uint256 internal constant _ROLE_152 = 1 << 152; uint256 internal constant _ROLE_153 = 1 << 153; uint256 internal constant _ROLE_154 = 1 << 154; uint256 internal constant _ROLE_155 = 1 << 155; uint256 internal constant _ROLE_156 = 1 << 156; uint256 internal constant _ROLE_157 = 1 << 157; uint256 internal constant _ROLE_158 = 1 << 158; uint256 internal constant _ROLE_159 = 1 << 159; uint256 internal constant _ROLE_160 = 1 << 160; uint256 internal constant _ROLE_161 = 1 << 161; uint256 internal constant _ROLE_162 = 1 << 162; uint256 internal constant _ROLE_163 = 1 << 163; uint256 internal constant _ROLE_164 = 1 << 164; uint256 internal constant _ROLE_165 = 1 << 165; uint256 internal constant _ROLE_166 = 1 << 166; uint256 internal constant _ROLE_167 = 1 << 167; uint256 internal constant _ROLE_168 = 1 << 168; uint256 internal constant _ROLE_169 = 1 << 169; uint256 internal constant _ROLE_170 = 1 << 170; uint256 internal constant _ROLE_171 = 1 << 171; uint256 internal constant _ROLE_172 = 1 << 172; uint256 internal constant _ROLE_173 = 1 << 173; uint256 internal constant _ROLE_174 = 1 << 174; uint256 internal constant _ROLE_175 = 1 << 175; uint256 internal constant _ROLE_176 = 1 << 176; uint256 internal constant _ROLE_177 = 1 << 177; uint256 internal constant _ROLE_178 = 1 << 178; uint256 internal constant _ROLE_179 = 1 << 179; uint256 internal constant _ROLE_180 = 1 << 180; uint256 internal constant _ROLE_181 = 1 << 181; uint256 internal constant _ROLE_182 = 1 << 182; uint256 internal constant _ROLE_183 = 1 << 183; uint256 internal constant _ROLE_184 = 1 << 184; uint256 internal constant _ROLE_185 = 1 << 185; uint256 internal constant _ROLE_186 = 1 << 186; uint256 internal constant _ROLE_187 = 1 << 187; uint256 internal constant _ROLE_188 = 1 << 188; uint256 internal constant _ROLE_189 = 1 << 189; uint256 internal constant _ROLE_190 = 1 << 190; uint256 internal constant _ROLE_191 = 1 << 191; uint256 internal constant _ROLE_192 = 1 << 192; uint256 internal constant _ROLE_193 = 1 << 193; uint256 internal constant _ROLE_194 = 1 << 194; uint256 internal constant _ROLE_195 = 1 << 195; uint256 internal constant _ROLE_196 = 1 << 196; uint256 internal constant _ROLE_197 = 1 << 197; uint256 internal constant _ROLE_198 = 1 << 198; uint256 internal constant _ROLE_199 = 1 << 199; uint256 internal constant _ROLE_200 = 1 << 200; uint256 internal constant _ROLE_201 = 1 << 201; uint256 internal constant _ROLE_202 = 1 << 202; uint256 internal constant _ROLE_203 = 1 << 203; uint256 internal constant _ROLE_204 = 1 << 204; uint256 internal constant _ROLE_205 = 1 << 205; uint256 internal constant _ROLE_206 = 1 << 206; uint256 internal constant _ROLE_207 = 1 << 207; uint256 internal constant _ROLE_208 = 1 << 208; uint256 internal constant _ROLE_209 = 1 << 209; uint256 internal constant _ROLE_210 = 1 << 210; uint256 internal constant _ROLE_211 = 1 << 211; uint256 internal constant _ROLE_212 = 1 << 212; uint256 internal constant _ROLE_213 = 1 << 213; uint256 internal constant _ROLE_214 = 1 << 214; uint256 internal constant _ROLE_215 = 1 << 215; uint256 internal constant _ROLE_216 = 1 << 216; uint256 internal constant _ROLE_217 = 1 << 217; uint256 internal constant _ROLE_218 = 1 << 218; uint256 internal constant _ROLE_219 = 1 << 219; uint256 internal constant _ROLE_220 = 1 << 220; uint256 internal constant _ROLE_221 = 1 << 221; uint256 internal constant _ROLE_222 = 1 << 222; uint256 internal constant _ROLE_223 = 1 << 223; uint256 internal constant _ROLE_224 = 1 << 224; uint256 internal constant _ROLE_225 = 1 << 225; uint256 internal constant _ROLE_226 = 1 << 226; uint256 internal constant _ROLE_227 = 1 << 227; uint256 internal constant _ROLE_228 = 1 << 228; uint256 internal constant _ROLE_229 = 1 << 229; uint256 internal constant _ROLE_230 = 1 << 230; uint256 internal constant _ROLE_231 = 1 << 231; uint256 internal constant _ROLE_232 = 1 << 232; uint256 internal constant _ROLE_233 = 1 << 233; uint256 internal constant _ROLE_234 = 1 << 234; uint256 internal constant _ROLE_235 = 1 << 235; uint256 internal constant _ROLE_236 = 1 << 236; uint256 internal constant _ROLE_237 = 1 << 237; uint256 internal constant _ROLE_238 = 1 << 238; uint256 internal constant _ROLE_239 = 1 << 239; uint256 internal constant _ROLE_240 = 1 << 240; uint256 internal constant _ROLE_241 = 1 << 241; uint256 internal constant _ROLE_242 = 1 << 242; uint256 internal constant _ROLE_243 = 1 << 243; uint256 internal constant _ROLE_244 = 1 << 244; uint256 internal constant _ROLE_245 = 1 << 245; uint256 internal constant _ROLE_246 = 1 << 246; uint256 internal constant _ROLE_247 = 1 << 247; uint256 internal constant _ROLE_248 = 1 << 248; uint256 internal constant _ROLE_249 = 1 << 249; uint256 internal constant _ROLE_250 = 1 << 250; uint256 internal constant _ROLE_251 = 1 << 251; uint256 internal constant _ROLE_252 = 1 << 252; uint256 internal constant _ROLE_253 = 1 << 253; uint256 internal constant _ROLE_254 = 1 << 254; uint256 internal constant _ROLE_255 = 1 << 255; }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract ISoundFeeRegistry","name":"feeRegistry_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint32","name":"available","type":"uint32"}],"name":"ExceedsAvailableSupply","type":"error"},{"inputs":[],"name":"ExceedsMaxPerAccount","type":"error"},{"inputs":[],"name":"FeeRegistryIsZeroAddress","type":"error"},{"inputs":[],"name":"InvalidAffiliateFeeBPS","type":"error"},{"inputs":[],"name":"InvalidMaxMintableRange","type":"error"},{"inputs":[],"name":"InvalidTimeRange","type":"error"},{"inputs":[],"name":"MaxMintablePerAccountIsZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"blockTimestamp","type":"uint256"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"}],"name":"MintNotOpen","type":"error"},{"inputs":[],"name":"MintPaused","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[{"internalType":"uint256","name":"paid","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"Underpaid","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":true,"internalType":"uint128","name":"mintId","type":"uint128"},{"indexed":false,"internalType":"uint16","name":"bps","type":"uint16"}],"name":"AffiliateFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":true,"internalType":"uint128","name":"mintId","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"cutoffTime","type":"uint32"}],"name":"CutoffTimeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":true,"internalType":"uint128","name":"mintId","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"}],"name":"MaxMintablePerAccountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":true,"internalType":"uint128","name":"mintId","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"maxMintableLower","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"maxMintableUpper","type":"uint32"}],"name":"MaxMintableRangeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":true,"internalType":"address","name":"creator","type":"address"},{"indexed":false,"internalType":"uint128","name":"mintId","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"startTime","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"endTime","type":"uint32"},{"indexed":false,"internalType":"uint16","name":"affiliateFeeBPS","type":"uint16"}],"name":"MintConfigCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint128","name":"mintId","type":"uint128"},{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"MintPausedSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":true,"internalType":"uint128","name":"mintId","type":"uint128"},{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint32","name":"fromTokenId","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"quantity","type":"uint32"},{"indexed":false,"internalType":"uint128","name":"requiredEtherValue","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"platformFee","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"affiliateFee","type":"uint128"},{"indexed":false,"internalType":"address","name":"affiliate","type":"address"},{"indexed":false,"internalType":"bool","name":"affiliated","type":"bool"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":true,"internalType":"uint128","name":"mintId","type":"uint128"},{"indexed":false,"internalType":"uint96","name":"price","type":"uint96"}],"name":"PriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":true,"internalType":"uint128","name":"mintId","type":"uint128"},{"indexed":false,"internalType":"uint96","name":"price","type":"uint96"},{"indexed":false,"internalType":"uint32","name":"startTime","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"cutoffTime","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"endTime","type":"uint32"},{"indexed":false,"internalType":"uint16","name":"affiliateFeeBPS","type":"uint16"},{"indexed":false,"internalType":"uint32","name":"maxMintableLower","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"maxMintableUpper","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"}],"name":"RangeEditionMintCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":true,"internalType":"uint128","name":"mintId","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"startTime","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"endTime","type":"uint32"}],"name":"TimeRangeSet","type":"event"},{"inputs":[],"name":"MAX_BPS","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"affiliate","type":"address"}],"name":"affiliateFeesAccrued","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint96","name":"price","type":"uint96"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"cutoffTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint16","name":"affiliateFeeBPS","type":"uint16"},{"internalType":"uint32","name":"maxMintableLower","type":"uint32"},{"internalType":"uint32","name":"maxMintableUpper","type":"uint32"},{"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"}],"name":"createEditionMint","outputs":[{"internalType":"uint128","name":"mintId","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeRegistry","outputs":[{"internalType":"contract ISoundFeeRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"address","name":"affiliate","type":"address"}],"name":"isAffiliated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","type":"uint128"},{"internalType":"uint32","name":"quantity","type":"uint32"},{"internalType":"address","name":"affiliate","type":"address"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","type":"uint128"}],"name":"mintInfo","outputs":[{"components":[{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint16","name":"affiliateFeeBPS","type":"uint16"},{"internalType":"bool","name":"mintPaused","type":"bool"},{"internalType":"uint96","name":"price","type":"uint96"},{"internalType":"uint32","name":"maxMintableUpper","type":"uint32"},{"internalType":"uint32","name":"maxMintableLower","type":"uint32"},{"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"},{"internalType":"uint32","name":"totalMinted","type":"uint32"},{"internalType":"uint32","name":"cutoffTime","type":"uint32"}],"internalType":"struct MintInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"moduleInterfaceId","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"nextMintId","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformFeesAccrued","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","type":"uint128"},{"internalType":"uint16","name":"feeBPS","type":"uint16"}],"name":"setAffiliateFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","type":"uint128"},{"internalType":"bool","name":"paused","type":"bool"}],"name":"setEditionMintPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","type":"uint128"},{"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"}],"name":"setMaxMintablePerAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","type":"uint128"},{"internalType":"uint32","name":"maxMintableLower","type":"uint32"},{"internalType":"uint32","name":"maxMintableUpper","type":"uint32"}],"name":"setMaxMintableRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","type":"uint128"},{"internalType":"uint96","name":"price","type":"uint96"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","type":"uint128"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"}],"name":"setTimeRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","type":"uint128"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"cutoffTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"}],"name":"setTimeRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","type":"uint128"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"quantity","type":"uint32"}],"name":"totalPrice","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"affiliate","type":"address"}],"name":"withdrawForAffiliate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawForPlatform","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a06040523480156200001157600080fd5b506040516200441c3803806200441c833981810160405281019062000037919062000159565b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036200009f576040517fd9b8066e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff168152505050506200018b565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200010d82620000e0565b9050919050565b6000620001218262000100565b9050919050565b620001338162000114565b81146200013f57600080fd5b50565b600081519050620001538162000128565b92915050565b600060208284031215620001725762000171620000db565b5b6000620001828482850162000142565b91505092915050565b608051614267620001b56000396000818161087f015281816114ee01526132c401526142676000f3fe60806040526004361061012a5760003560e01c8063b3a408b8116100ab578063c7dd32281161006f578063c7dd3228146103e1578063c94dcf8f1461040c578063d73f3aab14610449578063f574029614610472578063fc63e69e1461049b578063fd967f47146104c45761012a565b8063b3a408b81461030b578063b3b34f9914610336578063b40bf08e14610352578063b84158a41461037b578063bf9c0e56146103b85761012a565b80636aa99da3116100f25780636aa99da3146102145780637614a7511461023f5780637cbf126b14610268578063ac1fc22c146102a5578063aec96b6e146102e25761012a565b806301ffc9a71461012f57806303a6ccd01461016c57806308bfa2bf146101a957806322163b86146101c0578063522f7386146101eb575b600080fd5b34801561013b57600080fd5b50610156600480360381019061015191906134b0565b6104ef565b60405161016391906134f8565b60405180910390f35b34801561017857600080fd5b50610193600480360381019061018e91906135b9565b610569565b6040516101a09190613737565b60405180910390f35b3480156101b557600080fd5b506101be610805565b005b3480156101cc57600080fd5b506101d5610916565b6040516101e29190613762565b60405180910390f35b3480156101f757600080fd5b50610212600480360381019061020d91906137a9565b61093b565b005b34801561022057600080fd5b50610229610bd7565b6040516102369190613762565b60405180910390f35b34801561024b57600080fd5b5061026660048036038101906102619190613828565b610bfc565b005b34801561027457600080fd5b5061028f600480360381019061028a91906138d3565b610f02565b60405161029c9190613762565b60405180910390f35b3480156102b157600080fd5b506102cc60048036038101906102c7919061399d565b6111ae565b6040516102d99190613762565b60405180910390f35b3480156102ee57600080fd5b50610309600480360381019061030491906139ca565b611213565b005b34801561031757600080fd5b506103206114ec565b60405161032d9190613a90565b60405180910390f35b610350600480360381019061034b9190613aab565b611510565b005b34801561035e57600080fd5b50610379600480360381019061037491906139ca565b6116c5565b005b34801561038757600080fd5b506103a2600480360381019061039d9190613b12565b6119fd565b6040516103af9190613762565b60405180910390f35b3480156103c457600080fd5b506103df60048036038101906103da9190613b79565b611aaf565b005b3480156103ed57600080fd5b506103f6611deb565b6040516104039190613c03565b60405180910390f35b34801561041857600080fd5b50610433600480360381019061042e9190613c1e565b611e13565b60405161044091906134f8565b60405180910390f35b34801561045557600080fd5b50610470600480360381019061046b9190613c71565b611e4e565b005b34801561047e57600080fd5b506104996004803603810190610494919061399d565b612144565b005b3480156104a757600080fd5b506104c260048036038101906104bd9190613cc4565b612244565b005b3480156104d057600080fd5b506104d961251a565b6040516104e69190613d26565b60405180910390f35b60006104fa82612524565b8061056257507f4d4a2e35000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b6105716133c2565b6000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000846fffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060800160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900461ffff1661ffff1661ffff16815260200160008201600a9054906101000a900460ff16151515158152505090506000600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000856fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200190815260200160002090506000604051806101400160405280846000015163ffffffff168152602001846020015163ffffffff168152602001846040015161ffff1681526020018460600151151581526020018360000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff1681526020018360000160189054906101000a900463ffffffff1663ffffffff1681526020018360000160149054906101000a900463ffffffff1663ffffffff16815260200183600001601c9054906101000a900463ffffffff1663ffffffff1681526020018360000160109054906101000a900463ffffffff1663ffffffff16815260200183600001600c9054906101000a900463ffffffff1663ffffffff16815250905080935050505092915050565b60008060109054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff169050600081146109135760008060106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506109127f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663946f7c9e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061090c9190613d56565b826125dd565b5b50565b60008060109054906101000a90046fffffffffffffffffffffffffffffffff16905090565b828073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ab9190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610acd57508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6d9190613db9565b6040518363ffffffff1660e01b8152600401610a8a929190613e04565b602060405180830381865afa158015610aa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610acb9190613e42565b155b15610b04576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000856fffffffffffffffffffffffffffffffff168152602001908152602001600020600001600a6101000a81548160ff0219169083151502179055508373ffffffffffffffffffffffffffffffffffffffff167fe430910c8e4bfa8180b70a0b2aa923b82d6712a1d165e223053ef439a3f861478484604051610bc9929190613e6f565b60405180910390a250505050565b60008060009054906101000a90046fffffffffffffffffffffffffffffffff16905090565b828073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6c9190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610d8e57508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2e9190613db9565b6040518363ffffffff1660e01b8152600401610d4b929190613e04565b602060405180830381865afa158015610d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8c9190613e42565b155b15610dc5576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008263ffffffff1603610e05576040517fa017714500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000856fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c6101000a81548163ffffffff021916908363ffffffff160217905550826fffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f021f3ca4d64a14574ed4fc7115d2c667604e54efb94b6187ed8117d49c6e475584604051610ef49190613ea7565b60405180910390a350505050565b60008787878163ffffffff168363ffffffff16108015610f2d57508063ffffffff168263ffffffff16105b610f63576040517f536a71af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8563ffffffff168763ffffffff161115610fa9576040517f3a964d4700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008563ffffffff1603610fe9576040517fa017714500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ff58d8c8b8b6125fd565b93506000600360008f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000866fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200190815260200160002090508c8160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508a81600001600c6101000a81548163ffffffff021916908363ffffffff160217905550878160000160146101000a81548163ffffffff021916908363ffffffff160217905550868160000160186101000a81548163ffffffff021916908363ffffffff1602179055508581600001601c6101000a81548163ffffffff021916908363ffffffff160217905550846fffffffffffffffffffffffffffffffff168e73ffffffffffffffffffffffffffffffffffffffff167f9a9e0edce33a498fe7d57bfc9e7b46f9a2cd45507d8853c0c18c4c7bd860798c8f8f8f8f8f8f8f8f604051611195989796959493929190613ed1565b60405180910390a3505050509998505050505050505050565b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a90046fffffffffffffffffffffffffffffffff169050919050565b838073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561125f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112839190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156113a557508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611321573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113459190613db9565b6040518363ffffffff1660e01b8152600401611362929190613e04565b602060405180830381865afa15801561137f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a39190613e42565b155b156113dc576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000866fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152602001908152602001600020905080600001600c9054906101000a900463ffffffff1663ffffffff168463ffffffff161080156114a257508263ffffffff1681600001600c9054906101000a900463ffffffff1663ffffffff16105b6114d8576040517f536a71af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114e4868686866129fa565b505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000856fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020019081526020016000209050600061159382612d7e565b90506115b48260000160109054906101000a900463ffffffff168583612de0565b8260000160106101000a81548163ffffffff021916908363ffffffff16021790555060008673ffffffffffffffffffffffffffffffffffffffff1663dc33e681336040518263ffffffff1660e01b81526004016116119190613f4f565b602060405180830381865afa15801561162e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116529190613db9565b905082600001601c9054906101000a900463ffffffff1663ffffffff168563ffffffff16820111156116b0576040517f1b75136500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506116bd86868686612e64565b505050505050565b838073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611711573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117359190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415801561185757508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f79190613db9565b6040518363ffffffff1660e01b8152600401611814929190613e04565b602060405180830381865afa158015611831573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118559190613e42565b155b1561188e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8163ffffffff168363ffffffff1611156118d4576040517f3a964d4700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000866fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020019081526020016000209050838160000160146101000a81548163ffffffff021916908363ffffffff160217905550828160000160186101000a81548163ffffffff021916908363ffffffff160217905550846fffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f6d809c5e613207ec6ca68c0d872f18cf6e493a727c39e150f185b4b6d13be97786866040516119ed929190613f6a565b60405180910390a3505050505050565b60008163ffffffff16600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000866fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff16029050949350505050565b848073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611afb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b1f9190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015611c4157508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be19190613db9565b6040518363ffffffff1660e01b8152600401611bfe929190613e04565b602060405180830381865afa158015611c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3f9190613e42565b155b15611c78576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8383838163ffffffff168363ffffffff16108015611ca157508063ffffffff168263ffffffff16105b611cd7576040517f536a71af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600360008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a6fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200190815260200160002090508681600001600c6101000a81548163ffffffff021916908363ffffffff160217905550611d7e8a8a8a89611213565b886fffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167f33bbd71c3e2f573cc929e30067dcf5801791814427f844484fa25dee910d135289604051611dd79190613ea7565b60405180910390a350505050505050505050565b60007f4d4a2e3500000000000000000000000000000000000000000000000000000000905090565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141590509392505050565b828073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ebe9190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015611fe057508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f809190613db9565b6040518363ffffffff1660e01b8152600401611f9d929190613e04565b602060405180830381865afa158015611fba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fde9190613e42565b155b15612017576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8161271061ffff168161ffff16111561205c576040517f1a52ce6f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000866fffffffffffffffffffffffffffffffff16815260200190815260200160002060000160086101000a81548161ffff021916908361ffff160217905550836fffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fae6d744348a49699fcb91e6a563f2224c0fb27c21053a9218ee827f9d6e698c7856040516121359190613d26565b60405180910390a35050505050565b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16905060008114612240576000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555061223f82826125dd565b5b5050565b828073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612290573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b49190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156123d657508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612352573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123769190613db9565b6040518363ffffffff1660e01b8152600401612393929190613e04565b602060405180830381865afa1580156123b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d49190613e42565b155b1561240d576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000856fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550826fffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f7c77af090cbae157811da55b6d8ae1e307a85f5aa1dd2f7a13183279a8c2b4b28460405161250c9190613f93565b60405180910390a350505050565b6000612710905090565b60007f37c74bd8000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806125d657506301ffc9a760e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60008060008084865af16125f95763b12d13eb6000526004601cfd5b5050565b6000848073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561264b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061266f9190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415801561279157508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561270d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127319190613db9565b6040518363ffffffff1660e01b815260040161274e929190613e04565b602060405180830381865afa15801561276b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278f9190613e42565b155b156127c8576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84848063ffffffff168263ffffffff161061280f576040517f536a71af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8461271061ffff168161ffff161115612854576040517f1a52ce6f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054906101000a90046fffffffffffffffffffffffffffffffff1694506000600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000876fffffffffffffffffffffffffffffffff1681526020019081526020016000209050888160000160006101000a81548163ffffffff021916908363ffffffff160217905550878160000160046101000a81548163ffffffff021916908363ffffffff160217905550868160000160086101000a81548161ffff021916908361ffff16021790555060018661294b9190613fdd565b6000806101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167feeb5941fb79bbfe40edd76c2e086e8ccdb0b463fc8ac07416266100b4dfddccf888c8c8c6040516129e59493929190614021565b60405180910390a35050505050949350505050565b838073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6a9190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015612b8c57508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2c9190613db9565b6040518363ffffffff1660e01b8152600401612b49929190613e04565b602060405180830381865afa158015612b66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b8a9190613e42565b155b15612bc3576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82828063ffffffff168263ffffffff1610612c0a576040517f536a71af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84600160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000886fffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548163ffffffff021916908363ffffffff16021790555083600160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000886fffffffffffffffffffffffffffffffff16815260200190815260200160002060000160046101000a81548163ffffffff021916908363ffffffff160217905550856fffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f13bc03d97cc4e2accb3b8290af069c19619d32a4e9c5219f8580108766fb18fd8787604051612d6d929190613f6a565b60405180910390a350505050505050565b60008082600001600c9054906101000a900463ffffffff1663ffffffff16421015612dbf578260000160189054906101000a900463ffffffff169050612dd7565b8260000160149054906101000a900463ffffffff1690505b80915050919050565b6000808363ffffffff168563ffffffff160190508263ffffffff16811115612e59576000612e1a8463ffffffff168763ffffffff166132ae565b9050806040517fbdc0f4ce000000000000000000000000000000000000000000000000000000008152600401612e509190613ea7565b60405180910390fd5b809150509392505050565b6000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000856fffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000160009054906101000a900463ffffffff16905060008260000160049054906101000a900463ffffffff1690508163ffffffff16421015612f4b574282826040517f296f4f69000000000000000000000000000000000000000000000000000000008152600401612f4293929190614066565b60405180910390fd5b8063ffffffff16421115612f9a574282826040517f296f4f69000000000000000000000000000000000000000000000000000000008152600401612f9193929190614066565b60405180910390fd5b82600001600a9054906101000a900460ff1615612fe3576040517fd7d248ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50506000612ff3868633876119fd565b9050806fffffffffffffffffffffffffffffffff1634101561304e5734816040517ff3ebc3840000000000000000000000000000000000000000000000000000000081526004016130459291906140ce565b60405180910390fd5b60008061305a836132bf565b91509150600061306b898988611e13565b9050600081156131555761271061ffff168660000160089054906101000a900461ffff1661ffff16856fffffffffffffffffffffffffffffffff1602816130b5576130b46140f7565b5b049050808403935080600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a90046fffffffffffffffffffffffffffffffff160192506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505b3373ffffffffffffffffffffffffffffffffffffffff16896fffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff167f3d73a0206d94d61b7038abcd0eb766a5de22f9844b38a78449054d19a4f1b58a8d73ffffffffffffffffffffffffffffffffffffffff166340c10f19896fffffffffffffffffffffffffffffffff16338f6040518463ffffffff1660e01b8152600401613205929190614157565b60206040518083038185885af1158015613223573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906132489190613db9565b8c8a89888f8b6040516132619796959493929190614180565b60405180910390a4846fffffffffffffffffffffffffffffffff163411156132a2576132a133866fffffffffffffffffffffffffffffffff1634036125dd565b5b50505050505050505050565b600081830382841102905092915050565b6000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16630d411b21846040518263ffffffff1660e01b815260040161331b9190613762565b602060405180830381865afa158015613338573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061335c9190614204565b905080600060108282829054906101000a90046fffffffffffffffffffffffffffffffff160192506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055508083039150915091565b604051806101400160405280600063ffffffff168152602001600063ffffffff168152602001600061ffff16815260200160001515815260200160006bffffffffffffffffffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff1681525090565b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61348d81613458565b811461349857600080fd5b50565b6000813590506134aa81613484565b92915050565b6000602082840312156134c6576134c5613453565b5b60006134d48482850161349b565b91505092915050565b60008115159050919050565b6134f2816134dd565b82525050565b600060208201905061350d60008301846134e9565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061353e82613513565b9050919050565b61354e81613533565b811461355957600080fd5b50565b60008135905061356b81613545565b92915050565b60006fffffffffffffffffffffffffffffffff82169050919050565b61359681613571565b81146135a157600080fd5b50565b6000813590506135b38161358d565b92915050565b600080604083850312156135d0576135cf613453565b5b60006135de8582860161355c565b92505060206135ef858286016135a4565b9150509250929050565b600063ffffffff82169050919050565b613612816135f9565b82525050565b600061ffff82169050919050565b61362f81613618565b82525050565b61363e816134dd565b82525050565b60006bffffffffffffffffffffffff82169050919050565b61366581613644565b82525050565b610140820160008201516136826000850182613609565b5060208201516136956020850182613609565b5060408201516136a86040850182613626565b5060608201516136bb6060850182613635565b5060808201516136ce608085018261365c565b5060a08201516136e160a0850182613609565b5060c08201516136f460c0850182613609565b5060e082015161370760e0850182613609565b5061010082015161371c610100850182613609565b50610120820151613731610120850182613609565b50505050565b60006101408201905061374d600083018461366b565b92915050565b61375c81613571565b82525050565b60006020820190506137776000830184613753565b92915050565b613786816134dd565b811461379157600080fd5b50565b6000813590506137a38161377d565b92915050565b6000806000606084860312156137c2576137c1613453565b5b60006137d08682870161355c565b93505060206137e1868287016135a4565b92505060406137f286828701613794565b9150509250925092565b613805816135f9565b811461381057600080fd5b50565b600081359050613822816137fc565b92915050565b60008060006060848603121561384157613840613453565b5b600061384f8682870161355c565b9350506020613860868287016135a4565b925050604061387186828701613813565b9150509250925092565b61388481613644565b811461388f57600080fd5b50565b6000813590506138a18161387b565b92915050565b6138b081613618565b81146138bb57600080fd5b50565b6000813590506138cd816138a7565b92915050565b60008060008060008060008060006101208a8c0312156138f6576138f5613453565b5b60006139048c828d0161355c565b99505060206139158c828d01613892565b98505060406139268c828d01613813565b97505060606139378c828d01613813565b96505060806139488c828d01613813565b95505060a06139598c828d016138be565b94505060c061396a8c828d01613813565b93505060e061397b8c828d01613813565b92505061010061398d8c828d01613813565b9150509295985092959850929598565b6000602082840312156139b3576139b2613453565b5b60006139c18482850161355c565b91505092915050565b600080600080608085870312156139e4576139e3613453565b5b60006139f28782880161355c565b9450506020613a03878288016135a4565b9350506040613a1487828801613813565b9250506060613a2587828801613813565b91505092959194509250565b6000819050919050565b6000613a56613a51613a4c84613513565b613a31565b613513565b9050919050565b6000613a6882613a3b565b9050919050565b6000613a7a82613a5d565b9050919050565b613a8a81613a6f565b82525050565b6000602082019050613aa56000830184613a81565b92915050565b60008060008060808587031215613ac557613ac4613453565b5b6000613ad38782880161355c565b9450506020613ae4878288016135a4565b9350506040613af587828801613813565b9250506060613b068782880161355c565b91505092959194509250565b60008060008060808587031215613b2c57613b2b613453565b5b6000613b3a8782880161355c565b9450506020613b4b878288016135a4565b9350506040613b5c8782880161355c565b9250506060613b6d87828801613813565b91505092959194509250565b600080600080600060a08688031215613b9557613b94613453565b5b6000613ba38882890161355c565b9550506020613bb4888289016135a4565b9450506040613bc588828901613813565b9350506060613bd688828901613813565b9250506080613be788828901613813565b9150509295509295909350565b613bfd81613458565b82525050565b6000602082019050613c186000830184613bf4565b92915050565b600080600060608486031215613c3757613c36613453565b5b6000613c458682870161355c565b9350506020613c56868287016135a4565b9250506040613c678682870161355c565b9150509250925092565b600080600060608486031215613c8a57613c89613453565b5b6000613c988682870161355c565b9350506020613ca9868287016135a4565b9250506040613cba868287016138be565b9150509250925092565b600080600060608486031215613cdd57613cdc613453565b5b6000613ceb8682870161355c565b9350506020613cfc868287016135a4565b9250506040613d0d86828701613892565b9150509250925092565b613d2081613618565b82525050565b6000602082019050613d3b6000830184613d17565b92915050565b600081519050613d5081613545565b92915050565b600060208284031215613d6c57613d6b613453565b5b6000613d7a84828501613d41565b91505092915050565b6000819050919050565b613d9681613d83565b8114613da157600080fd5b50565b600081519050613db381613d8d565b92915050565b600060208284031215613dcf57613dce613453565b5b6000613ddd84828501613da4565b91505092915050565b613def81613533565b82525050565b613dfe81613d83565b82525050565b6000604082019050613e196000830185613de6565b613e266020830184613df5565b9392505050565b600081519050613e3c8161377d565b92915050565b600060208284031215613e5857613e57613453565b5b6000613e6684828501613e2d565b91505092915050565b6000604082019050613e846000830185613753565b613e9160208301846134e9565b9392505050565b613ea1816135f9565b82525050565b6000602082019050613ebc6000830184613e98565b92915050565b613ecb81613644565b82525050565b600061010082019050613ee7600083018b613ec2565b613ef4602083018a613e98565b613f016040830189613e98565b613f0e6060830188613e98565b613f1b6080830187613d17565b613f2860a0830186613e98565b613f3560c0830185613e98565b613f4260e0830184613e98565b9998505050505050505050565b6000602082019050613f646000830184613de6565b92915050565b6000604082019050613f7f6000830185613e98565b613f8c6020830184613e98565b9392505050565b6000602082019050613fa86000830184613ec2565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613fe882613571565b9150613ff383613571565b925082820190506fffffffffffffffffffffffffffffffff81111561401b5761401a613fae565b5b92915050565b60006080820190506140366000830187613753565b6140436020830186613e98565b6140506040830185613e98565b61405d6060830184613d17565b95945050505050565b600060608201905061407b6000830186613df5565b6140886020830185613e98565b6140956040830184613e98565b949350505050565b60006140b86140b36140ae84613571565b613a31565b613d83565b9050919050565b6140c88161409d565b82525050565b60006040820190506140e36000830185613df5565b6140f060208301846140bf565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061414161413c614137846135f9565b613a31565b613d83565b9050919050565b61415181614126565b82525050565b600060408201905061416c6000830185613de6565b6141796020830184614148565b9392505050565b600060e082019050614195600083018a613e98565b6141a26020830189613e98565b6141af6040830188613753565b6141bc6060830187613753565b6141c96080830186613753565b6141d660a0830185613de6565b6141e360c08301846134e9565b98975050505050505050565b6000815190506141fe8161358d565b92915050565b60006020828403121561421a57614219613453565b5b6000614228848285016141ef565b9150509291505056fea26469706673582212206ba34ec2e256e307651dbe13b6a5e8cf875ce6555110ffd965b3f5662f3e6bdc64736f6c634300081000330000000000000000000000000ba0b5a6a5d707156541d360d9d8e2002110c4d1
Deployed Bytecode
0x60806040526004361061012a5760003560e01c8063b3a408b8116100ab578063c7dd32281161006f578063c7dd3228146103e1578063c94dcf8f1461040c578063d73f3aab14610449578063f574029614610472578063fc63e69e1461049b578063fd967f47146104c45761012a565b8063b3a408b81461030b578063b3b34f9914610336578063b40bf08e14610352578063b84158a41461037b578063bf9c0e56146103b85761012a565b80636aa99da3116100f25780636aa99da3146102145780637614a7511461023f5780637cbf126b14610268578063ac1fc22c146102a5578063aec96b6e146102e25761012a565b806301ffc9a71461012f57806303a6ccd01461016c57806308bfa2bf146101a957806322163b86146101c0578063522f7386146101eb575b600080fd5b34801561013b57600080fd5b50610156600480360381019061015191906134b0565b6104ef565b60405161016391906134f8565b60405180910390f35b34801561017857600080fd5b50610193600480360381019061018e91906135b9565b610569565b6040516101a09190613737565b60405180910390f35b3480156101b557600080fd5b506101be610805565b005b3480156101cc57600080fd5b506101d5610916565b6040516101e29190613762565b60405180910390f35b3480156101f757600080fd5b50610212600480360381019061020d91906137a9565b61093b565b005b34801561022057600080fd5b50610229610bd7565b6040516102369190613762565b60405180910390f35b34801561024b57600080fd5b5061026660048036038101906102619190613828565b610bfc565b005b34801561027457600080fd5b5061028f600480360381019061028a91906138d3565b610f02565b60405161029c9190613762565b60405180910390f35b3480156102b157600080fd5b506102cc60048036038101906102c7919061399d565b6111ae565b6040516102d99190613762565b60405180910390f35b3480156102ee57600080fd5b50610309600480360381019061030491906139ca565b611213565b005b34801561031757600080fd5b506103206114ec565b60405161032d9190613a90565b60405180910390f35b610350600480360381019061034b9190613aab565b611510565b005b34801561035e57600080fd5b50610379600480360381019061037491906139ca565b6116c5565b005b34801561038757600080fd5b506103a2600480360381019061039d9190613b12565b6119fd565b6040516103af9190613762565b60405180910390f35b3480156103c457600080fd5b506103df60048036038101906103da9190613b79565b611aaf565b005b3480156103ed57600080fd5b506103f6611deb565b6040516104039190613c03565b60405180910390f35b34801561041857600080fd5b50610433600480360381019061042e9190613c1e565b611e13565b60405161044091906134f8565b60405180910390f35b34801561045557600080fd5b50610470600480360381019061046b9190613c71565b611e4e565b005b34801561047e57600080fd5b506104996004803603810190610494919061399d565b612144565b005b3480156104a757600080fd5b506104c260048036038101906104bd9190613cc4565b612244565b005b3480156104d057600080fd5b506104d961251a565b6040516104e69190613d26565b60405180910390f35b60006104fa82612524565b8061056257507f4d4a2e35000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b6105716133c2565b6000600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000846fffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060800160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160089054906101000a900461ffff1661ffff1661ffff16815260200160008201600a9054906101000a900460ff16151515158152505090506000600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000856fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200190815260200160002090506000604051806101400160405280846000015163ffffffff168152602001846020015163ffffffff168152602001846040015161ffff1681526020018460600151151581526020018360000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff1681526020018360000160189054906101000a900463ffffffff1663ffffffff1681526020018360000160149054906101000a900463ffffffff1663ffffffff16815260200183600001601c9054906101000a900463ffffffff1663ffffffff1681526020018360000160109054906101000a900463ffffffff1663ffffffff16815260200183600001600c9054906101000a900463ffffffff1663ffffffff16815250905080935050505092915050565b60008060109054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff169050600081146109135760008060106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055506109127f0000000000000000000000000ba0b5a6a5d707156541d360d9d8e2002110c4d173ffffffffffffffffffffffffffffffffffffffff1663946f7c9e6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061090c9190613d56565b826125dd565b5b50565b60008060109054906101000a90046fffffffffffffffffffffffffffffffff16905090565b828073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610987573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ab9190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610acd57508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6d9190613db9565b6040518363ffffffff1660e01b8152600401610a8a929190613e04565b602060405180830381865afa158015610aa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610acb9190613e42565b155b15610b04576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000856fffffffffffffffffffffffffffffffff168152602001908152602001600020600001600a6101000a81548160ff0219169083151502179055508373ffffffffffffffffffffffffffffffffffffffff167fe430910c8e4bfa8180b70a0b2aa923b82d6712a1d165e223053ef439a3f861478484604051610bc9929190613e6f565b60405180910390a250505050565b60008060009054906101000a90046fffffffffffffffffffffffffffffffff16905090565b828073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c6c9190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610d8e57508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d2e9190613db9565b6040518363ffffffff1660e01b8152600401610d4b929190613e04565b602060405180830381865afa158015610d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8c9190613e42565b155b15610dc5576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008263ffffffff1603610e05576040517fa017714500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000856fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152602001908152602001600020600001601c6101000a81548163ffffffff021916908363ffffffff160217905550826fffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f021f3ca4d64a14574ed4fc7115d2c667604e54efb94b6187ed8117d49c6e475584604051610ef49190613ea7565b60405180910390a350505050565b60008787878163ffffffff168363ffffffff16108015610f2d57508063ffffffff168263ffffffff16105b610f63576040517f536a71af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8563ffffffff168763ffffffff161115610fa9576040517f3a964d4700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008563ffffffff1603610fe9576040517fa017714500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ff58d8c8b8b6125fd565b93506000600360008f73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000866fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200190815260200160002090508c8160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508a81600001600c6101000a81548163ffffffff021916908363ffffffff160217905550878160000160146101000a81548163ffffffff021916908363ffffffff160217905550868160000160186101000a81548163ffffffff021916908363ffffffff1602179055508581600001601c6101000a81548163ffffffff021916908363ffffffff160217905550846fffffffffffffffffffffffffffffffff168e73ffffffffffffffffffffffffffffffffffffffff167f9a9e0edce33a498fe7d57bfc9e7b46f9a2cd45507d8853c0c18c4c7bd860798c8f8f8f8f8f8f8f8f604051611195989796959493929190613ed1565b60405180910390a3505050509998505050505050505050565b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a90046fffffffffffffffffffffffffffffffff169050919050565b838073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561125f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112839190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156113a557508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611321573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113459190613db9565b6040518363ffffffff1660e01b8152600401611362929190613e04565b602060405180830381865afa15801561137f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a39190613e42565b155b156113dc576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000866fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152602001908152602001600020905080600001600c9054906101000a900463ffffffff1663ffffffff168463ffffffff161080156114a257508263ffffffff1681600001600c9054906101000a900463ffffffff1663ffffffff16105b6114d8576040517f536a71af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114e4868686866129fa565b505050505050565b7f0000000000000000000000000ba0b5a6a5d707156541d360d9d8e2002110c4d181565b6000600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000856fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020019081526020016000209050600061159382612d7e565b90506115b48260000160109054906101000a900463ffffffff168583612de0565b8260000160106101000a81548163ffffffff021916908363ffffffff16021790555060008673ffffffffffffffffffffffffffffffffffffffff1663dc33e681336040518263ffffffff1660e01b81526004016116119190613f4f565b602060405180830381865afa15801561162e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116529190613db9565b905082600001601c9054906101000a900463ffffffff1663ffffffff168563ffffffff16820111156116b0576040517f1b75136500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506116bd86868686612e64565b505050505050565b838073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611711573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117359190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415801561185757508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f79190613db9565b6040518363ffffffff1660e01b8152600401611814929190613e04565b602060405180830381865afa158015611831573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118559190613e42565b155b1561188e576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8163ffffffff168363ffffffff1611156118d4576040517f3a964d4700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000866fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020019081526020016000209050838160000160146101000a81548163ffffffff021916908363ffffffff160217905550828160000160186101000a81548163ffffffff021916908363ffffffff160217905550846fffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff167f6d809c5e613207ec6ca68c0d872f18cf6e493a727c39e150f185b4b6d13be97786866040516119ed929190613f6a565b60405180910390a3505050505050565b60008163ffffffff16600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000866fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200190815260200160002060000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff16029050949350505050565b848073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611afb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b1f9190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015611c4157508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611be19190613db9565b6040518363ffffffff1660e01b8152600401611bfe929190613e04565b602060405180830381865afa158015611c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c3f9190613e42565b155b15611c78576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8383838163ffffffff168363ffffffff16108015611ca157508063ffffffff168263ffffffff16105b611cd7576040517f536a71af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600360008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a6fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200190815260200160002090508681600001600c6101000a81548163ffffffff021916908363ffffffff160217905550611d7e8a8a8a89611213565b886fffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167f33bbd71c3e2f573cc929e30067dcf5801791814427f844484fa25dee910d135289604051611dd79190613ea7565b60405180910390a350505050505050505050565b60007f4d4a2e3500000000000000000000000000000000000000000000000000000000905090565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141590509392505050565b828073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ebe9190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015611fe057508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f809190613db9565b6040518363ffffffff1660e01b8152600401611f9d929190613e04565b602060405180830381865afa158015611fba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fde9190613e42565b155b15612017576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8161271061ffff168161ffff16111561205c576040517f1a52ce6f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000866fffffffffffffffffffffffffffffffff16815260200190815260200160002060000160086101000a81548161ffff021916908361ffff160217905550836fffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fae6d744348a49699fcb91e6a563f2224c0fb27c21053a9218ee827f9d6e698c7856040516121359190613d26565b60405180910390a35050505050565b6000600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16905060008114612240576000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555061223f82826125dd565b5b5050565b828073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612290573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b49190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156123d657508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612352573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123769190613db9565b6040518363ffffffff1660e01b8152600401612393929190613e04565b602060405180830381865afa1580156123b0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123d49190613e42565b155b1561240d576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000856fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550826fffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f7c77af090cbae157811da55b6d8ae1e307a85f5aa1dd2f7a13183279a8c2b4b28460405161250c9190613f93565b60405180910390a350505050565b6000612710905090565b60007f37c74bd8000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806125d657506301ffc9a760e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b60008060008084865af16125f95763b12d13eb6000526004601cfd5b5050565b6000848073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561264b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061266f9190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415801561279157508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561270d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127319190613db9565b6040518363ffffffff1660e01b815260040161274e929190613e04565b602060405180830381865afa15801561276b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278f9190613e42565b155b156127c8576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84848063ffffffff168263ffffffff161061280f576040517f536a71af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8461271061ffff168161ffff161115612854576040517f1a52ce6f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008054906101000a90046fffffffffffffffffffffffffffffffff1694506000600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000876fffffffffffffffffffffffffffffffff1681526020019081526020016000209050888160000160006101000a81548163ffffffff021916908363ffffffff160217905550878160000160046101000a81548163ffffffff021916908363ffffffff160217905550868160000160086101000a81548161ffff021916908361ffff16021790555060018661294b9190613fdd565b6000806101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff167feeb5941fb79bbfe40edd76c2e086e8ccdb0b463fc8ac07416266100b4dfddccf888c8c8c6040516129e59493929190614021565b60405180910390a35050505050949350505050565b838073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a6a9190613d56565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015612b8c57508073ffffffffffffffffffffffffffffffffffffffff1663514e62fc338373ffffffffffffffffffffffffffffffffffffffff166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2c9190613db9565b6040518363ffffffff1660e01b8152600401612b49929190613e04565b602060405180830381865afa158015612b66573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b8a9190613e42565b155b15612bc3576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82828063ffffffff168263ffffffff1610612c0a576040517f536a71af00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84600160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000886fffffffffffffffffffffffffffffffff16815260200190815260200160002060000160006101000a81548163ffffffff021916908363ffffffff16021790555083600160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000886fffffffffffffffffffffffffffffffff16815260200190815260200160002060000160046101000a81548163ffffffff021916908363ffffffff160217905550856fffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff167f13bc03d97cc4e2accb3b8290af069c19619d32a4e9c5219f8580108766fb18fd8787604051612d6d929190613f6a565b60405180910390a350505050505050565b60008082600001600c9054906101000a900463ffffffff1663ffffffff16421015612dbf578260000160189054906101000a900463ffffffff169050612dd7565b8260000160149054906101000a900463ffffffff1690505b80915050919050565b6000808363ffffffff168563ffffffff160190508263ffffffff16811115612e59576000612e1a8463ffffffff168763ffffffff166132ae565b9050806040517fbdc0f4ce000000000000000000000000000000000000000000000000000000008152600401612e509190613ea7565b60405180910390fd5b809150509392505050565b6000600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000856fffffffffffffffffffffffffffffffff168152602001908152602001600020905060008160000160009054906101000a900463ffffffff16905060008260000160049054906101000a900463ffffffff1690508163ffffffff16421015612f4b574282826040517f296f4f69000000000000000000000000000000000000000000000000000000008152600401612f4293929190614066565b60405180910390fd5b8063ffffffff16421115612f9a574282826040517f296f4f69000000000000000000000000000000000000000000000000000000008152600401612f9193929190614066565b60405180910390fd5b82600001600a9054906101000a900460ff1615612fe3576040517fd7d248ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50506000612ff3868633876119fd565b9050806fffffffffffffffffffffffffffffffff1634101561304e5734816040517ff3ebc3840000000000000000000000000000000000000000000000000000000081526004016130459291906140ce565b60405180910390fd5b60008061305a836132bf565b91509150600061306b898988611e13565b9050600081156131555761271061ffff168660000160089054906101000a900461ffff1661ffff16856fffffffffffffffffffffffffffffffff1602816130b5576130b46140f7565b5b049050808403935080600260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282829054906101000a90046fffffffffffffffffffffffffffffffff160192506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505b3373ffffffffffffffffffffffffffffffffffffffff16896fffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff167f3d73a0206d94d61b7038abcd0eb766a5de22f9844b38a78449054d19a4f1b58a8d73ffffffffffffffffffffffffffffffffffffffff166340c10f19896fffffffffffffffffffffffffffffffff16338f6040518463ffffffff1660e01b8152600401613205929190614157565b60206040518083038185885af1158015613223573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906132489190613db9565b8c8a89888f8b6040516132619796959493929190614180565b60405180910390a4846fffffffffffffffffffffffffffffffff163411156132a2576132a133866fffffffffffffffffffffffffffffffff1634036125dd565b5b50505050505050505050565b600081830382841102905092915050565b6000807f0000000000000000000000000ba0b5a6a5d707156541d360d9d8e2002110c4d173ffffffffffffffffffffffffffffffffffffffff16630d411b21846040518263ffffffff1660e01b815260040161331b9190613762565b602060405180830381865afa158015613338573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061335c9190614204565b905080600060108282829054906101000a90046fffffffffffffffffffffffffffffffff160192506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055508083039150915091565b604051806101400160405280600063ffffffff168152602001600063ffffffff168152602001600061ffff16815260200160001515815260200160006bffffffffffffffffffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff168152602001600063ffffffff1681525090565b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61348d81613458565b811461349857600080fd5b50565b6000813590506134aa81613484565b92915050565b6000602082840312156134c6576134c5613453565b5b60006134d48482850161349b565b91505092915050565b60008115159050919050565b6134f2816134dd565b82525050565b600060208201905061350d60008301846134e9565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061353e82613513565b9050919050565b61354e81613533565b811461355957600080fd5b50565b60008135905061356b81613545565b92915050565b60006fffffffffffffffffffffffffffffffff82169050919050565b61359681613571565b81146135a157600080fd5b50565b6000813590506135b38161358d565b92915050565b600080604083850312156135d0576135cf613453565b5b60006135de8582860161355c565b92505060206135ef858286016135a4565b9150509250929050565b600063ffffffff82169050919050565b613612816135f9565b82525050565b600061ffff82169050919050565b61362f81613618565b82525050565b61363e816134dd565b82525050565b60006bffffffffffffffffffffffff82169050919050565b61366581613644565b82525050565b610140820160008201516136826000850182613609565b5060208201516136956020850182613609565b5060408201516136a86040850182613626565b5060608201516136bb6060850182613635565b5060808201516136ce608085018261365c565b5060a08201516136e160a0850182613609565b5060c08201516136f460c0850182613609565b5060e082015161370760e0850182613609565b5061010082015161371c610100850182613609565b50610120820151613731610120850182613609565b50505050565b60006101408201905061374d600083018461366b565b92915050565b61375c81613571565b82525050565b60006020820190506137776000830184613753565b92915050565b613786816134dd565b811461379157600080fd5b50565b6000813590506137a38161377d565b92915050565b6000806000606084860312156137c2576137c1613453565b5b60006137d08682870161355c565b93505060206137e1868287016135a4565b92505060406137f286828701613794565b9150509250925092565b613805816135f9565b811461381057600080fd5b50565b600081359050613822816137fc565b92915050565b60008060006060848603121561384157613840613453565b5b600061384f8682870161355c565b9350506020613860868287016135a4565b925050604061387186828701613813565b9150509250925092565b61388481613644565b811461388f57600080fd5b50565b6000813590506138a18161387b565b92915050565b6138b081613618565b81146138bb57600080fd5b50565b6000813590506138cd816138a7565b92915050565b60008060008060008060008060006101208a8c0312156138f6576138f5613453565b5b60006139048c828d0161355c565b99505060206139158c828d01613892565b98505060406139268c828d01613813565b97505060606139378c828d01613813565b96505060806139488c828d01613813565b95505060a06139598c828d016138be565b94505060c061396a8c828d01613813565b93505060e061397b8c828d01613813565b92505061010061398d8c828d01613813565b9150509295985092959850929598565b6000602082840312156139b3576139b2613453565b5b60006139c18482850161355c565b91505092915050565b600080600080608085870312156139e4576139e3613453565b5b60006139f28782880161355c565b9450506020613a03878288016135a4565b9350506040613a1487828801613813565b9250506060613a2587828801613813565b91505092959194509250565b6000819050919050565b6000613a56613a51613a4c84613513565b613a31565b613513565b9050919050565b6000613a6882613a3b565b9050919050565b6000613a7a82613a5d565b9050919050565b613a8a81613a6f565b82525050565b6000602082019050613aa56000830184613a81565b92915050565b60008060008060808587031215613ac557613ac4613453565b5b6000613ad38782880161355c565b9450506020613ae4878288016135a4565b9350506040613af587828801613813565b9250506060613b068782880161355c565b91505092959194509250565b60008060008060808587031215613b2c57613b2b613453565b5b6000613b3a8782880161355c565b9450506020613b4b878288016135a4565b9350506040613b5c8782880161355c565b9250506060613b6d87828801613813565b91505092959194509250565b600080600080600060a08688031215613b9557613b94613453565b5b6000613ba38882890161355c565b9550506020613bb4888289016135a4565b9450506040613bc588828901613813565b9350506060613bd688828901613813565b9250506080613be788828901613813565b9150509295509295909350565b613bfd81613458565b82525050565b6000602082019050613c186000830184613bf4565b92915050565b600080600060608486031215613c3757613c36613453565b5b6000613c458682870161355c565b9350506020613c56868287016135a4565b9250506040613c678682870161355c565b9150509250925092565b600080600060608486031215613c8a57613c89613453565b5b6000613c988682870161355c565b9350506020613ca9868287016135a4565b9250506040613cba868287016138be565b9150509250925092565b600080600060608486031215613cdd57613cdc613453565b5b6000613ceb8682870161355c565b9350506020613cfc868287016135a4565b9250506040613d0d86828701613892565b9150509250925092565b613d2081613618565b82525050565b6000602082019050613d3b6000830184613d17565b92915050565b600081519050613d5081613545565b92915050565b600060208284031215613d6c57613d6b613453565b5b6000613d7a84828501613d41565b91505092915050565b6000819050919050565b613d9681613d83565b8114613da157600080fd5b50565b600081519050613db381613d8d565b92915050565b600060208284031215613dcf57613dce613453565b5b6000613ddd84828501613da4565b91505092915050565b613def81613533565b82525050565b613dfe81613d83565b82525050565b6000604082019050613e196000830185613de6565b613e266020830184613df5565b9392505050565b600081519050613e3c8161377d565b92915050565b600060208284031215613e5857613e57613453565b5b6000613e6684828501613e2d565b91505092915050565b6000604082019050613e846000830185613753565b613e9160208301846134e9565b9392505050565b613ea1816135f9565b82525050565b6000602082019050613ebc6000830184613e98565b92915050565b613ecb81613644565b82525050565b600061010082019050613ee7600083018b613ec2565b613ef4602083018a613e98565b613f016040830189613e98565b613f0e6060830188613e98565b613f1b6080830187613d17565b613f2860a0830186613e98565b613f3560c0830185613e98565b613f4260e0830184613e98565b9998505050505050505050565b6000602082019050613f646000830184613de6565b92915050565b6000604082019050613f7f6000830185613e98565b613f8c6020830184613e98565b9392505050565b6000602082019050613fa86000830184613ec2565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000613fe882613571565b9150613ff383613571565b925082820190506fffffffffffffffffffffffffffffffff81111561401b5761401a613fae565b5b92915050565b60006080820190506140366000830187613753565b6140436020830186613e98565b6140506040830185613e98565b61405d6060830184613d17565b95945050505050565b600060608201905061407b6000830186613df5565b6140886020830185613e98565b6140956040830184613e98565b949350505050565b60006140b86140b36140ae84613571565b613a31565b613d83565b9050919050565b6140c88161409d565b82525050565b60006040820190506140e36000830185613df5565b6140f060208301846140bf565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061414161413c614137846135f9565b613a31565b613d83565b9050919050565b61415181614126565b82525050565b600060408201905061416c6000830185613de6565b6141796020830184614148565b9392505050565b600060e082019050614195600083018a613e98565b6141a26020830189613e98565b6141af6040830188613753565b6141bc6060830187613753565b6141c96080830186613753565b6141d660a0830185613de6565b6141e360c08301846134e9565b98975050505050505050565b6000815190506141fe8161358d565b92915050565b60006020828403121561421a57614219613453565b5b6000614228848285016141ef565b9150509291505056fea26469706673582212206ba34ec2e256e307651dbe13b6a5e8cf875ce6555110ffd965b3f5662f3e6bdc64736f6c63430008100033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000ba0b5a6a5d707156541d360d9d8e2002110c4d1
-----Decoded View---------------
Arg [0] : feeRegistry_ (address): 0x0BA0B5a6A5D707156541D360d9d8E2002110C4D1
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000000ba0b5a6a5d707156541d360d9d8e2002110c4d1
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $3,350.54 | 0.1015 | $340.08 |
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.