Overview
ETH Balance
0.18257 ETH
Eth Value
$539.19 (@ $2,953.35/ETH)More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 265 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Mint | 18344013 | 265 days ago | IN | 0.0007 ETH | 0.00069421 | ||||
Mint | 18343845 | 265 days ago | IN | 0.0007 ETH | 0.00133607 | ||||
Mint | 18342958 | 265 days ago | IN | 0.0007 ETH | 0.00312125 | ||||
Mint To | 18342927 | 265 days ago | IN | 0.0007 ETH | 0.00408932 | ||||
Mint | 18342150 | 265 days ago | IN | 0.0007 ETH | 0.00132995 | ||||
Mint | 18342027 | 265 days ago | IN | 0.0007 ETH | 0.00257865 | ||||
Mint To | 18341610 | 265 days ago | IN | 0.0007 ETH | 0.00146915 | ||||
Mint | 18340335 | 266 days ago | IN | 0.0007 ETH | 0.00082479 | ||||
Mint | 18340129 | 266 days ago | IN | 0.0007 ETH | 0.00093638 | ||||
Mint | 18339197 | 266 days ago | IN | 0.0007 ETH | 0.00095886 | ||||
Mint | 18339008 | 266 days ago | IN | 0.0007 ETH | 0.00083197 | ||||
Mint | 18339001 | 266 days ago | IN | 0.0007 ETH | 0.0008119 | ||||
Mint | 18338952 | 266 days ago | IN | 0.0007 ETH | 0.00098967 | ||||
Mint | 18338887 | 266 days ago | IN | 0.0007 ETH | 0.00088437 | ||||
Mint | 18338765 | 266 days ago | IN | 0.0007 ETH | 0.00089553 | ||||
Mint | 18338645 | 266 days ago | IN | 0.0007 ETH | 0.00077772 | ||||
Mint | 18338637 | 266 days ago | IN | 0.0007 ETH | 0.00082007 | ||||
Mint | 18338563 | 266 days ago | IN | 0.0007 ETH | 0.00084653 | ||||
Mint | 18338469 | 266 days ago | IN | 0.0007 ETH | 0.00096041 | ||||
Mint | 18338453 | 266 days ago | IN | 0.0007 ETH | 0.0010971 | ||||
Mint | 18338325 | 266 days ago | IN | 0.0007 ETH | 0.00079661 | ||||
Mint | 18338291 | 266 days ago | IN | 0.0007 ETH | 0.00086677 | ||||
Mint | 18338273 | 266 days ago | IN | 0.0007 ETH | 0.00117384 | ||||
Mint | 18338257 | 266 days ago | IN | 0.0007 ETH | 0.00091656 | ||||
Mint | 18338201 | 266 days ago | IN | 0.0007 ETH | 0.00082748 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
18232832 | 281 days ago | 0.009 ETH | ||||
18179052 | 288 days ago | 0.009 ETH | ||||
18136731 | 294 days ago | 0.0138 ETH | ||||
18136629 | 294 days ago | 0.0138 ETH | ||||
18136594 | 294 days ago | 0.0138 ETH | ||||
18136551 | 294 days ago | 0.0138 ETH | ||||
18136538 | 294 days ago | 0.0069 ETH | ||||
18136528 | 294 days ago | 0.0138 ETH | ||||
18136516 | 294 days ago | 0.0138 ETH | ||||
18136505 | 294 days ago | 0.0069 ETH | ||||
18136500 | 294 days ago | 0.0138 ETH | ||||
18136498 | 294 days ago | 0.0069 ETH | ||||
18136494 | 294 days ago | 0.0069 ETH | ||||
18136480 | 294 days ago | 0.0138 ETH | ||||
18136472 | 294 days ago | 0.0138 ETH | ||||
18136455 | 294 days ago | 0.0069 ETH | ||||
18136455 | 294 days ago | 0.0138 ETH | ||||
18136451 | 294 days ago | 0.0138 ETH | ||||
18136449 | 294 days ago | 0.0138 ETH | ||||
18136445 | 294 days ago | 0.0138 ETH | ||||
18131292 | 295 days ago | 0.009 ETH | ||||
18131028 | 295 days ago | 0.009 ETH | ||||
18129800 | 295 days ago | 0.009 ETH | ||||
18119122 | 297 days ago | 0.009 ETH | ||||
18115699 | 297 days ago | 0.009 ETH |
Loading...
Loading
Contract Name:
MerkleDropMinterV2_1
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import { MerkleProofLib } from "solady/utils/MerkleProofLib.sol"; import { IERC165 } from "openzeppelin/utils/introspection/IERC165.sol"; import { BaseMinterV2_1 } from "@modules/BaseMinterV2_1.sol"; import { DelegateCashLib } from "@modules/utils/DelegateCashLib.sol"; import { IMerkleDropMinterV2_1, EditionMintData, MintInfo } from "./interfaces/IMerkleDropMinterV2_1.sol"; import { IMinterModuleV2_1 } from "@core/interfaces/IMinterModuleV2_1.sol"; import { ISoundEditionV1 } from "@core/interfaces/ISoundEditionV1.sol"; /** * @title MerkleDropMinterV2_1 * @dev Module for minting Sound editions using a merkle tree of approved accounts. * @author Sound.xyz */ contract MerkleDropMinterV2_1 is IMerkleDropMinterV2_1, BaseMinterV2_1 { // ============================================================= // STORAGE // ============================================================= /** * @dev Edition mint data. * `_baseDataSlot(_getBaseData(edition, mintId))` => value. */ mapping(bytes32 => EditionMintData) internal _editionMintData; /** * @dev The number of mints for each account. * `_baseDataSlot(_getBaseData(edition, mintId))` => `address` => value. * We will simply store a uint256 for every account, to keep the Merkle tree * simple, so that it is compatible with 3rd party allowlist services like Lanyard. */ mapping(bytes32 => mapping(address => uint256)) internal _mintCounts; // ============================================================= // PUBLIC / EXTERNAL WRITE FUNCTIONS // ============================================================= /** * @inheritdoc IMerkleDropMinterV2_1 */ function createEditionMint( address edition, bytes32 merkleRootHash, uint96 price, uint32 startTime, uint32 endTime, uint16 affiliateFeeBPS, uint32 maxMintable, uint32 maxMintablePerAccount ) public returns (uint128 mintId) { if (merkleRootHash == bytes32(0)) revert MerkleRootHashIsEmpty(); if (maxMintablePerAccount == 0) revert MaxMintablePerAccountIsZero(); mintId = _createEditionMint(edition, startTime, endTime, affiliateFeeBPS); BaseData storage baseData = _getBaseDataUnchecked(edition, mintId); baseData.price = price; baseData.maxMintablePerAccount = maxMintablePerAccount; EditionMintData storage data = _editionMintData[_baseDataSlot(baseData)]; data.merkleRootHash = merkleRootHash; data.maxMintable = maxMintable; // prettier-ignore emit MerkleDropMintCreated( edition, mintId, merkleRootHash, price, startTime, endTime, affiliateFeeBPS, maxMintable, maxMintablePerAccount ); } /** * @inheritdoc IMerkleDropMinterV2_1 */ function mintTo( address edition, uint128 mintId, address to, uint32 quantity, address allowlisted, bytes32[] calldata proof, address affiliate, bytes32[] calldata affiliateProof, uint256 attributionId ) public payable { BaseData storage baseData = _getBaseData(edition, mintId); EditionMintData storage data = _editionMintData[_baseDataSlot(baseData)]; // Increase `totalMinted` by `quantity`. // Require that the increased value does not exceed `maxMintable`. data.totalMinted = _incrementTotalMinted(data.totalMinted, quantity, data.maxMintable); // Verify that `allowlisted` is in the Merkle tree with the `proof`. // We also revert if `allowlisted` is the zero address to prevent libraries // that fill up partial Merkle trees with empty leafs from screwing things up. if ( allowlisted == address(0) || !MerkleProofLib.verifyCalldata(proof, data.merkleRootHash, _keccak256EncodePacked(allowlisted)) ) revert InvalidMerkleProof(); // To mint, either `msg.sender` or `to` must be equal to `allowlisted`, // or `msg.sender` must be a delegate of `allowlisted`. if (msg.sender != allowlisted && to != allowlisted) if (!DelegateCashLib.checkDelegateForAll(msg.sender, allowlisted)) revert CallerNotDelegated(); unchecked { // Check that the additional `quantity` does not exceed the maximum mintable per account. // Won't overflow, as `maxMintablePerAccount` and `quantity` are 32 bits. if ((_mintCounts[_baseDataSlot(baseData)][allowlisted] += quantity) > baseData.maxMintablePerAccount) revert ExceedsMaxPerAccount(); } _mintTo(edition, mintId, to, quantity, affiliate, affiliateProof, attributionId); emit DropClaimed(allowlisted, quantity); } /** * @inheritdoc IMerkleDropMinterV2_1 */ function mint( address edition, uint128 mintId, uint32 quantity, bytes32[] calldata proof, address affiliate ) public payable { mintTo(edition, mintId, msg.sender, quantity, msg.sender, proof, affiliate, MerkleProofLib.emptyProof(), 0); } /** * @inheritdoc IMerkleDropMinterV2_1 */ function setPrice( address edition, uint128 mintId, uint96 price ) public onlyEditionOwnerOrAdmin(edition) { _getBaseData(edition, mintId).price = price; emit PriceSet(edition, mintId, price); } /** * @inheritdoc IMerkleDropMinterV2_1 */ function setMaxMintablePerAccount( address edition, uint128 mintId, uint32 maxMintablePerAccount ) public onlyEditionOwnerOrAdmin(edition) { if (maxMintablePerAccount == 0) revert MaxMintablePerAccountIsZero(); _getBaseData(edition, mintId).maxMintablePerAccount = maxMintablePerAccount; emit MaxMintablePerAccountSet(edition, mintId, maxMintablePerAccount); } /** * @inheritdoc IMerkleDropMinterV2_1 */ function setMaxMintable( address edition, uint128 mintId, uint32 maxMintable ) public onlyEditionOwnerOrAdmin(edition) { _editionMintData[_baseDataSlot(_getBaseData(edition, mintId))].maxMintable = maxMintable; emit MaxMintableSet(edition, mintId, maxMintable); } /* * @inheritdoc IMerkleDropMinterV2_1 */ function setMerkleRootHash( address edition, uint128 mintId, bytes32 merkleRootHash ) public onlyEditionOwnerOrAdmin(edition) { if (merkleRootHash == bytes32(0)) revert MerkleRootHashIsEmpty(); _editionMintData[_baseDataSlot(_getBaseData(edition, mintId))].merkleRootHash = merkleRootHash; emit MerkleRootHashSet(edition, mintId, merkleRootHash); } // ============================================================= // PUBLIC / EXTERNAL VIEW FUNCTIONS // ============================================================= /** * @inheritdoc IMerkleDropMinterV2_1 */ function mintCount( address edition, uint128 mintId, address to ) public view virtual returns (uint256) { return _mintCounts[_baseDataSlot(_getBaseData(edition, mintId))][to]; } /** * @inheritdoc IMerkleDropMinterV2_1 */ function mintInfo(address edition, uint128 mintId) external view returns (MintInfo memory info) { BaseData storage baseData = _getBaseData(edition, mintId); EditionMintData storage mintData = _editionMintData[_baseDataSlot(baseData)]; info.startTime = baseData.startTime; info.endTime = baseData.endTime; info.affiliateFeeBPS = baseData.affiliateFeeBPS; info.mintPaused = baseData.mintPaused; info.price = baseData.price; info.maxMintable = mintData.maxMintable; info.maxMintablePerAccount = baseData.maxMintablePerAccount; info.totalMinted = mintData.totalMinted; info.merkleRootHash = mintData.merkleRootHash; info.affiliateMerkleRoot = baseData.affiliateMerkleRoot; info.platformFeeBPS = platformFeeBPS; info.platformFlatFee = platformFlatFee; info.platformPerTxFlatFee = platformPerTxFlatFee; } /** * @inheritdoc IERC165 */ function supportsInterface(bytes4 interfaceId) public view override(IERC165, BaseMinterV2_1) returns (bool) { return BaseMinterV2_1.supportsInterface(interfaceId) || interfaceId == type(IMerkleDropMinterV2_1).interfaceId; } /** * @inheritdoc IMinterModuleV2_1 */ function moduleInterfaceId() public pure returns (bytes4) { return type(IMerkleDropMinterV2_1).interfaceId; } /** * @inheritdoc IMerkleDropMinterV2_1 */ function isV2_1() external pure override returns (bool) { return true; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/MerkleProofLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol) library MerkleProofLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MERKLE PROOF VERIFICATION OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`. function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool isValid) { /// @solidity memory-safe-assembly assembly { if mload(proof) { // Initialize `offset` to the offset of `proof` elements in memory. let offset := add(proof, 0x20) // Left shift by 5 is equivalent to multiplying by 0x20. let end := add(offset, shl(5, mload(proof))) // Iterate over proof elements to compute root hash. for {} 1 {} { // Slot of `leaf` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(leaf, mload(offset))) // Store elements to hash contiguously in scratch space. // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. mstore(scratch, leaf) mstore(xor(scratch, 0x20), mload(offset)) // Reuse `leaf` to store the hash to reduce stack operations. leaf := keccak256(0x00, 0x40) offset := add(offset, 0x20) if iszero(lt(offset, end)) { break } } } isValid := eq(leaf, root) } } /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`. function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool isValid) { /// @solidity memory-safe-assembly assembly { if proof.length { // Left shift by 5 is equivalent to multiplying by 0x20. let end := add(proof.offset, shl(5, proof.length)) // Initialize `offset` to the offset of `proof` in the calldata. let offset := proof.offset // Iterate over proof elements to compute root hash. for {} 1 {} { // Slot of `leaf` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(leaf, calldataload(offset))) // Store elements to hash contiguously in scratch space. // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. mstore(scratch, leaf) mstore(xor(scratch, 0x20), calldataload(offset)) // Reuse `leaf` to store the hash to reduce stack operations. leaf := keccak256(0x00, 0x40) offset := add(offset, 0x20) if iszero(lt(offset, end)) { break } } } isValid := eq(leaf, root) } } /// @dev Returns whether all `leafs` exist in the Merkle tree with `root`, /// given `proof` and `flags`. function verifyMultiProof( bytes32[] memory proof, bytes32 root, bytes32[] memory leafs, bool[] memory flags ) internal pure returns (bool isValid) { // Rebuilds the root by consuming and producing values on a queue. // The queue starts with the `leafs` array, and goes into a `hashes` array. // After the process, the last element on the queue is verified // to be equal to the `root`. // // The `flags` array denotes whether the sibling // should be popped from the queue (`flag == true`), or // should be popped from the `proof` (`flag == false`). /// @solidity memory-safe-assembly assembly { // Cache the lengths of the arrays. let leafsLength := mload(leafs) let proofLength := mload(proof) let flagsLength := mload(flags) // Advance the pointers of the arrays to point to the data. leafs := add(0x20, leafs) proof := add(0x20, proof) flags := add(0x20, flags) // If the number of flags is correct. for {} eq(add(leafsLength, proofLength), add(flagsLength, 1)) {} { // For the case where `proof.length + leafs.length == 1`. if iszero(flagsLength) { // `isValid = (proof.length == 1 ? proof[0] : leafs[0]) == root`. isValid := eq(mload(xor(leafs, mul(xor(proof, leafs), proofLength))), root) break } // We can use the free memory space for the queue. // We don't need to allocate, since the queue is temporary. let hashesFront := mload(0x40) // Copy the leafs into the hashes. // Sometimes, a little memory expansion costs less than branching. // Should cost less, even with a high free memory offset of 0x7d00. // Left shift by 5 is equivalent to multiplying by 0x20. leafsLength := shl(5, leafsLength) for { let i := 0 } iszero(eq(i, leafsLength)) { i := add(i, 0x20) } { mstore(add(hashesFront, i), mload(add(leafs, i))) } // Compute the back of the hashes. let hashesBack := add(hashesFront, leafsLength) // This is the end of the memory for the queue. // We recycle `flagsLength` to save on stack variables // (this trick may not always save gas). flagsLength := add(hashesBack, shl(5, flagsLength)) for {} 1 {} { // Pop from `hashes`. let a := mload(hashesFront) // Pop from `hashes`. let b := mload(add(hashesFront, 0x20)) hashesFront := add(hashesFront, 0x40) // If the flag is false, load the next proof, // else, pops from the queue. if iszero(mload(flags)) { // Loads the next proof. b := mload(proof) proof := add(proof, 0x20) // Unpop from `hashes`. hashesFront := sub(hashesFront, 0x20) } // Advance to the next flag. flags := add(flags, 0x20) // Slot of `a` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(a, b)) // Hash the scratch space and push the result onto the queue. mstore(scratch, a) mstore(xor(scratch, 0x20), b) mstore(hashesBack, keccak256(0x00, 0x40)) hashesBack := add(hashesBack, 0x20) if iszero(lt(hashesBack, flagsLength)) { break } } // Checks if the last value in the queue is same as the root. isValid := eq(mload(sub(hashesBack, 0x20)), root) break } } } /// @dev Returns whether all `leafs` exist in the Merkle tree with `root`, /// given `proof` and `flags`. function verifyMultiProofCalldata( bytes32[] calldata proof, bytes32 root, bytes32[] calldata leafs, bool[] calldata flags ) internal pure returns (bool isValid) { // Rebuilds the root by consuming and producing values on a queue. // The queue starts with the `leafs` array, and goes into a `hashes` array. // After the process, the last element on the queue is verified // to be equal to the `root`. // // The `flags` array denotes whether the sibling // should be popped from the queue (`flag == true`), or // should be popped from the `proof` (`flag == false`). /// @solidity memory-safe-assembly assembly { // If the number of flags is correct. for {} eq(add(leafs.length, proof.length), add(flags.length, 1)) {} { // For the case where `proof.length + leafs.length == 1`. if iszero(flags.length) { // `isValid = (proof.length == 1 ? proof[0] : leafs[0]) == root`. // forgefmt: disable-next-item isValid := eq( calldataload( xor(leafs.offset, mul(xor(proof.offset, leafs.offset), proof.length)) ), root ) break } // We can use the free memory space for the queue. // We don't need to allocate, since the queue is temporary. let hashesFront := mload(0x40) // Copy the leafs into the hashes. // Sometimes, a little memory expansion costs less than branching. // Should cost less, even with a high free memory offset of 0x7d00. // Left shift by 5 is equivalent to multiplying by 0x20. calldatacopy(hashesFront, leafs.offset, shl(5, leafs.length)) // Compute the back of the hashes. let hashesBack := add(hashesFront, shl(5, leafs.length)) // This is the end of the memory for the queue. // We recycle `flags.length` to save on stack variables // (this trick may not always save gas). flags.length := add(hashesBack, shl(5, flags.length)) // We don't need to make a copy of `proof.offset` or `flags.offset`, // as they are pass-by-value (this trick may not always save gas). for {} 1 {} { // Pop from `hashes`. let a := mload(hashesFront) // Pop from `hashes`. let b := mload(add(hashesFront, 0x20)) hashesFront := add(hashesFront, 0x40) // If the flag is false, load the next proof, // else, pops from the queue. if iszero(calldataload(flags.offset)) { // Loads the next proof. b := calldataload(proof.offset) proof.offset := add(proof.offset, 0x20) // Unpop from `hashes`. hashesFront := sub(hashesFront, 0x20) } // Advance to the next flag offset. flags.offset := add(flags.offset, 0x20) // Slot of `a` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(a, b)) // Hash the scratch space and push the result onto the queue. mstore(scratch, a) mstore(xor(scratch, 0x20), b) mstore(hashesBack, keccak256(0x00, 0x40)) hashesBack := add(hashesBack, 0x20) if iszero(lt(hashesBack, flags.length)) { break } } // Checks if the last value in the queue is same as the root. isValid := eq(mload(sub(hashesBack, 0x20)), root) break } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EMPTY CALLDATA HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an empty calldata bytes32 array. function emptyProof() internal pure returns (bytes32[] calldata proof) { /// @solidity memory-safe-assembly assembly { proof.length := 0 } } /// @dev Returns an empty calldata bytes32 array. function emptyLeafs() internal pure returns (bytes32[] calldata leafs) { /// @solidity memory-safe-assembly assembly { leafs.length := 0 } } /// @dev Returns an empty calldata bool array. function emptyFlags() internal pure returns (bool[] calldata flags) { /// @solidity memory-safe-assembly assembly { flags.length := 0 } } }
// 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: MIT pragma solidity ^0.8.16; import { Ownable, OwnableRoles } from "solady/auth/OwnableRoles.sol"; import { ISoundEditionV1_2 } from "@core/interfaces/ISoundEditionV1_2.sol"; import { IMinterModuleV2_1 } from "@core/interfaces/IMinterModuleV2_1.sol"; import { IERC165 } from "openzeppelin/utils/introspection/IERC165.sol"; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { FixedPointMathLib } from "solady/utils/FixedPointMathLib.sol"; import { SafeCastLib } from "solady/utils/SafeCastLib.sol"; import { MerkleProofLib } from "solady/utils/MerkleProofLib.sol"; import { LibMulticaller } from "multicaller/LibMulticaller.sol"; /** * @title Minter Base * @dev The `BaseMinterV2_1` class maintains a central storage record of edition mint instances. */ abstract contract BaseMinterV2_1 is IMinterModuleV2_1, Ownable { // ============================================================= // CONSTANTS // ============================================================= /** * @dev This is the denominator, in basis points (BPS), for any of the fees. */ uint16 public constant BPS_DENOMINATOR = 10_000; /** * @dev The maximum basis points (BPS) limit allowed for the affiliate fees. */ uint16 public constant MAX_AFFILIATE_FEE_BPS = 1000; /** * @dev The maximum basis points (BPS) limit allowed for the platform fees. */ uint16 public constant MAX_PLATFORM_FEE_BPS = 1000; /** * @dev The maximum platform flat fee per transaction NFT. */ uint96 public constant MAX_PLATFORM_PER_TX_FLAT_FEE = 0.1 ether; /** * @dev The maximum platform flat fee per NFT. */ uint96 public constant MAX_PLATFORM_FLAT_FEE = 0.1 ether; /** * @dev The interface id for IMinterModuleV2. */ bytes4 internal constant _INTERFACE_ID_MINTER_MODULE_V2 = 0xf8ccd08e; // ============================================================= // STORAGE // ============================================================= /** * @dev The platform fee address. */ address public platformFeeAddress; /** * @dev The next mint ID. Shared amongst all editions connected. */ uint96 private _nextMintId; /** * @dev How much platform fees have been accrued. */ uint128 public platformFeesAccrued; /** * @dev The amount of platform flat fees per token. */ uint96 public platformFlatFee; /** * @dev The platform fee in basis points. */ uint16 public platformFeeBPS; /** * @dev The amount of platform flat fees per transaction. */ uint96 public platformPerTxFlatFee; /** * @dev Maps an edition and the mint ID to a mint instance. */ mapping(address => mapping(uint256 => BaseData)) private _baseData; /** * @dev Maps an address to how much affiliate fees have they accrued. */ mapping(address => uint128) public affiliateFeesAccrued; // ============================================================= // CONSTRUCTOR // ============================================================= constructor() payable { _initializeOwner(msg.sender); } // ============================================================= // PUBLIC / EXTERNAL WRITE FUNCTIONS // ============================================================= // Per edition mint parameter setters: // ----------------------------------- // These functions can only be called by the owner or admin of the edition. /** * @inheritdoc IMinterModuleV2_1 */ function setEditionMintPaused( address edition, uint128 mintId, bool paused ) public virtual onlyEditionOwnerOrAdmin(edition) { _getBaseData(edition, mintId).mintPaused = paused; emit MintPausedSet(edition, mintId, paused); } /** * @inheritdoc IMinterModuleV2_1 */ function setTimeRange( address edition, uint128 mintId, uint32 startTime, uint32 endTime ) public virtual onlyEditionOwnerOrAdmin(edition) { if (startTime >= endTime) revert InvalidTimeRange(); BaseData storage baseData = _getBaseData(edition, mintId); baseData.startTime = startTime; baseData.endTime = endTime; emit TimeRangeSet(edition, mintId, startTime, endTime); } /** * @inheritdoc IMinterModuleV2_1 */ function setAffiliateFee( address edition, uint128 mintId, uint16 bps ) public virtual override onlyEditionOwnerOrAdmin(edition) { if (bps > MAX_AFFILIATE_FEE_BPS) revert InvalidAffiliateFeeBPS(); _getBaseData(edition, mintId).affiliateFeeBPS = bps; emit AffiliateFeeSet(edition, mintId, bps); } /** * @inheritdoc IMinterModuleV2_1 */ function setAffiliateMerkleRoot( address edition, uint128 mintId, bytes32 root ) public virtual override onlyEditionOwnerOrAdmin(edition) { _getBaseData(edition, mintId).affiliateMerkleRoot = root; emit AffiliateMerkleRootSet(edition, mintId, root); } // Withdrawal functions: // --------------------- // These functions can be called by anyone. /** * @inheritdoc IMinterModuleV2_1 */ function withdrawForAffiliate(address affiliate) public override { uint128 accrued = affiliateFeesAccrued[affiliate]; if (accrued != 0) { affiliateFeesAccrued[affiliate] = 0; SafeTransferLib.forceSafeTransferETH(affiliate, accrued); emit AffiliateFeesWithdrawn(affiliate, accrued); } } /** * @inheritdoc IMinterModuleV2_1 */ function withdrawForPlatform() public override { address to = platformFeeAddress; if (to == address(0)) revert PlatformFeeAddressIsZero(); uint128 accrued = platformFeesAccrued; if (accrued != 0) { platformFeesAccrued = 0; SafeTransferLib.forceSafeTransferETH(to, accrued); emit PlatformFeesWithdrawn(accrued); } } // Only owner setters: // ------------------- // These functions can only be called by the owner of the minter contract. /** * @inheritdoc IMinterModuleV2_1 */ function setPlatformFee(uint16 bps) public onlyOwner { if (bps > MAX_PLATFORM_FEE_BPS) revert InvalidPlatformFeeBPS(); platformFeeBPS = bps; emit PlatformFeeSet(bps); } /** * @inheritdoc IMinterModuleV2_1 */ function setPlatformFlatFee(uint96 flatFee) public onlyOwner { if (flatFee > MAX_PLATFORM_FLAT_FEE) revert InvalidPlatformFlatFee(); platformFlatFee = flatFee; emit PlatformFlatFeeSet(flatFee); } /** * @inheritdoc IMinterModuleV2_1 */ function setPlatformPerTxFlatFee(uint96 perTxFlatFee) public onlyOwner { if (perTxFlatFee > MAX_PLATFORM_PER_TX_FLAT_FEE) revert InvalidPlatformPerTxFlatFee(); platformPerTxFlatFee = perTxFlatFee; emit PlatformPerTxFlatFeeSet(perTxFlatFee); } /** * @inheritdoc IMinterModuleV2_1 */ function setPlatformFeeAddress(address addr) public onlyOwner { if (addr == address(0)) revert PlatformFeeAddressIsZero(); platformFeeAddress = addr; emit PlatformFeeAddressSet(addr); } // ============================================================= // PUBLIC / EXTERNAL VIEW FUNCTIONS // ============================================================= /** * @inheritdoc IMinterModuleV2_1 */ function nextMintId() external view returns (uint128) { return _nextMintId; } /** * @inheritdoc IMinterModuleV2_1 */ function isAffiliatedWithProof( address edition, uint128 mintId, address affiliate, bytes32[] calldata affiliateProof ) public view virtual override returns (bool) { bytes32 root = _getBaseData(edition, mintId).affiliateMerkleRoot; // If the root is empty, then use the default logic. if (root == bytes32(0)) { return affiliate != address(0); } // Otherwise, check if the affiliate is in the Merkle tree. // The check that that affiliate is not a zero address is to prevent libraries // that fill up partial Merkle trees with empty leafs from screwing things up. return affiliate != address(0) && MerkleProofLib.verifyCalldata(affiliateProof, root, _keccak256EncodePacked(affiliate)); } /** * @inheritdoc IMinterModuleV2_1 */ function isAffiliated( address edition, uint128 mintId, address affiliate ) public view virtual override returns (bool) { return isAffiliatedWithProof(edition, mintId, affiliate, MerkleProofLib.emptyProof()); } /** * @inheritdoc IMinterModuleV2_1 */ function affiliateMerkleRoot(address edition, uint128 mintId) external view returns (bytes32) { return _getBaseData(edition, mintId).affiliateMerkleRoot; } /** * @inheritdoc IERC165 */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == _INTERFACE_ID_MINTER_MODULE_V2 || interfaceId == type(IMinterModuleV2_1).interfaceId || interfaceId == this.supportsInterface.selector; } /** * @inheritdoc IMinterModuleV2_1 */ function totalPriceAndFees( address edition, uint128 mintId, uint32 quantity ) public view virtual override returns ( uint256 total, uint256 subTotal, uint256 platformFlatFeeTotal, uint256 platformFee, uint256 affiliateFee ) { BaseData storage baseData = _getBaseData(edition, mintId); unchecked { subTotal = uint256(quantity) * uint256(baseData.price); // Before additional fees. platformFlatFeeTotal = uint256(quantity) * uint256(platformFlatFee) + uint256(platformPerTxFlatFee); total = subTotal + platformFlatFeeTotal; platformFee = (subTotal * uint256(platformFeeBPS)) / uint256(BPS_DENOMINATOR) + platformFlatFeeTotal; affiliateFee = (subTotal * uint256(baseData.affiliateFeeBPS)) / uint256(BPS_DENOMINATOR); } } // ============================================================= // INTERNAL / PRIVATE HELPERS // ============================================================= /** * @dev Requires that the caller is the owner or admin of `edition`. * @param edition The edition address. */ modifier onlyEditionOwnerOrAdmin(address edition) { _requireOnlyEditionOwnerOrAdmin(edition); _; } /** * @dev Requires that the caller is the owner or admin of `edition`. * @param edition The edition address. */ function _requireOnlyEditionOwnerOrAdmin(address edition) internal view { address sender = LibMulticaller.sender(); if (sender != OwnableRoles(edition).owner()) if (!OwnableRoles(edition).hasAnyRole(sender, ISoundEditionV1_2(edition).ADMIN_ROLE())) revert Unauthorized(); } /** * @dev If overriden to return true, the amount of ETH paid must be exact. * @return The constant value. */ function _useExactPayment() internal view virtual returns (bool) { return true; } /** * @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) returns (uint128 mintId) { if (startTime >= endTime) revert InvalidTimeRange(); if (affiliateFeeBPS > MAX_AFFILIATE_FEE_BPS) revert InvalidAffiliateFeeBPS(); mintId = _nextMintId; BaseData storage data = _getBaseDataUnchecked(edition, mintId); data.startTime = startTime; data.endTime = endTime; data.affiliateFeeBPS = affiliateFeeBPS; data.created = true; unchecked { _nextMintId = SafeCastLib.toUint96(mintId + 1); } emit MintConfigCreated(edition, msg.sender, mintId, startTime, endTime, affiliateFeeBPS); } /** * For avoiding stack too deep. */ struct _MintTemps { bool affiliated; uint256 affiliateFee; uint256 remainingPayment; uint256 platformFee; uint256 requiredEtherValue; } /** * @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 to The address to mint to. * @param quantity The quantity of tokens to mint. * @param affiliate The affiliate (referral) address. * @param affiliateProof The Merkle proof needed for verifying the affiliate, if any. * @param attributionId The attribution ID. */ function _mintTo( address edition, uint128 mintId, address to, uint32 quantity, address affiliate, bytes32[] calldata affiliateProof, uint256 attributionId ) internal { BaseData storage baseData = _getBaseData(edition, mintId); _MintTemps memory t; /* --------------------- 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 ------------ */ unchecked { // `requiredEtherValue = platformFee + affiliateFee + artistFee`. (t.requiredEtherValue, , , t.platformFee, t.affiliateFee) = totalPriceAndFees(edition, mintId, quantity); // Reverts if the payment is not exact, or not enough. if (_useExactPayment()) { if (msg.value != t.requiredEtherValue) revert WrongPayment(msg.value, t.requiredEtherValue); } else { if (msg.value < t.requiredEtherValue) revert Underpaid(msg.value, t.requiredEtherValue); } // Increment the platform fees accrued. platformFeesAccrued = SafeCastLib.toUint128(uint256(platformFeesAccrued) + t.platformFee); // Deduct the platform BPS fee, and the platform flat fees. // Won't underflow as `platformFee <= requiredEtherValue`; t.remainingPayment = t.requiredEtherValue - t.platformFee; } // Check if the mint is an affiliated mint. t.affiliated = isAffiliatedWithProof(edition, mintId, affiliate, affiliateProof); unchecked { if (t.affiliated) { // Deduct the affiliate fee from the remaining payment. // Won't underflow as `affiliateFee <= remainingPayment`. t.remainingPayment -= t.affiliateFee; // Increment the affiliate fees accrued. affiliateFeesAccrued[affiliate] = SafeCastLib.toUint128( uint256(affiliateFeesAccrued[affiliate]) + t.affiliateFee ); } else { t.affiliateFee = 0; // If the affiliate is not the zero address despite not being // affiliated, it might be due to an invalid affiliate proof. // Revert to prevent unintended skipping of affiliate payment. if (affiliate != address(0)) { revert InvalidAffiliate(); } } } /* ------------------------- MINT --------------------------- */ // Emit the event. emit Minted( edition, mintId, to, // Need to put this call here to avoid stack-too-deep error (it returns `fromTokenId`). uint32(ISoundEditionV1_2(edition).mint{ value: t.remainingPayment }(to, quantity)), quantity, uint128(t.requiredEtherValue), uint128(t.platformFee), uint128(t.affiliateFee), affiliate, t.affiliated, attributionId ); /* ------------------------- REFUND ------------------------- */ unchecked { if (!_useExactPayment()) { // 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 > t.requiredEtherValue) { SafeTransferLib.forceSafeTransferETH(msg.sender, msg.value - t.requiredEtherValue); } } } } /** * @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); } } /** * @dev Returns the storage pointer to the BaseData for (`edition`, `mintId`). * @param edition The edition address. * @param mintId The mint ID. * @return data Storage pointer to a BaseData. */ function _getBaseDataUnchecked(address edition, uint128 mintId) internal view returns (BaseData storage data) { data = _baseData[edition][mintId]; } /** * @dev Returns the storage pointer to the BaseData for (`edition`, `mintId`). * Reverts if the mint does not exist. * @param edition The edition address. * @param mintId The mint ID. * @return data Storage pointer to a BaseData. */ function _getBaseData(address edition, uint128 mintId) internal view returns (BaseData storage data) { data = _getBaseDataUnchecked(edition, mintId); if (!data.created) revert MintDoesNotExist(); } /** * @dev Casts the storage pointer to the BaseData to a bytes32. * @param data Storage pointer to a BaseData. * @return result The casted value of the slot. */ function _baseDataSlot(BaseData storage data) internal pure returns (bytes32 result) { assembly { result := data.slot } } /** * @dev Equivalent to `keccak256(abi.encodePacked(addr))`. * @param addr The address to hash. * @return result The hash of the address. */ function _keccak256EncodePacked(address addr) internal pure returns (bytes32 result) { assembly { mstore(0x00, addr) result := keccak256(0x0c, 0x14) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; library DelegateCashLib { address internal constant REGISTRY = 0x00000000000076A84feF008CDAbe6409d2FE638B; function checkDelegateForAll(address delegate, address vault) internal view returns (bool result) { assembly { // Cache the free memory pointer. let m := mload(0x40) // Store the function selector of `checkDelegateForAll(address,address)`. mstore(0x00, 0x9c395bc2) // Store the `delegate`. mstore(0x20, delegate) // Store the `vault`. mstore(0x40, vault) // Arguments are evaulated last to first. result := and( // The returndata is 1, which represents a bool true. eq(mload(0x00), 1), // The staticcall is successful. staticcall(gas(), REGISTRY, 0x1c, 0x44, 0x00, 0x20) ) // Restore the free memory pointer. mstore(0x40, m) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import { IMinterModuleV2_1 } from "@core/interfaces/IMinterModuleV2_1.sol"; /** * @dev Data unique to a Merkle drop mint. */ struct EditionMintData { // Hash of the root node for the Merkle tree drop bytes32 merkleRootHash; // The maximum number of tokens that can can be minted for this sale. uint32 maxMintable; // The total number of tokens minted so far for this sale. uint32 totalMinted; } /** * @dev All the information about a Merkle drop mint (combines EditionMintData with BaseData). */ struct MintInfo { uint32 startTime; uint32 endTime; uint16 affiliateFeeBPS; bool mintPaused; uint96 price; uint32 maxMintable; uint32 maxMintablePerAccount; uint32 totalMinted; bytes32 merkleRootHash; bytes32 affiliateMerkleRoot; uint16 platformFeeBPS; uint96 platformFlatFee; uint96 platformPerTxFlatFee; } /** * @title IMerkleDropMinterV2_1 * @dev Interface for the `MerkleDropMinterV2_1` module. * @author Sound.xyz */ interface IMerkleDropMinterV2_1 is IMinterModuleV2_1 { // ============================================================= // EVENTS // ============================================================= /** * @dev Emitted when a new Merkle drop mint is created. * @param edition The edition address. * @param mintId The mint ID. * @param merkleRootHash The root of the Merkle tree of the approved addresses. * @param price The price at which each token will be sold, in ETH. * @param startTime The time minting can begin. * @param endTime The time minting will end. * @param affiliateFeeBPS The affiliate fee in basis points. * @param maxMintable The maximum number of tokens that can be minted. * @param maxMintablePerAccount The maximum number of tokens that an account can mint. */ event MerkleDropMintCreated( address indexed edition, uint128 mintId, bytes32 merkleRootHash, uint96 price, uint32 startTime, uint32 endTime, uint16 affiliateFeeBPS, uint32 maxMintable, uint32 maxMintablePerAccount ); /** * @dev Emitted when tokens are claimed by an account. * @param allowlisted The address in the allowlist. * @param quantity The quantity of tokens claimed. */ event DropClaimed(address allowlisted, uint32 quantity); /** * @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 mintId, uint96 price); /** * @dev Emitted when the `maxMintable` is changed for (`edition`, `mintId`). * @param edition Address of the song edition contract we are minting for. * @param mintId The mint ID. * @param maxMintable The maximum number of tokens that can be minted on this schedule. */ event MaxMintableSet(address indexed edition, uint128 mintId, uint32 maxMintable); /** * @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 mintId, uint32 maxMintablePerAccount); /** * @dev Emitted when the `merkleRootHash` is changed for (`edition`, `mintId`). * @param edition Address of the song edition contract we are minting for. * @param mintId The mint ID. * @param merkleRootHash The merkle root hash of the entries. */ event MerkleRootHashSet(address indexed edition, uint128 mintId, bytes32 merkleRootHash); // ============================================================= // ERRORS // ============================================================= /** * @dev The merkle proof is invalid. */ error InvalidMerkleProof(); /** * @dev The caller must be delegated by the allowlisted. */ error CallerNotDelegated(); /** * @dev The number of tokens minted has exceeded the number allowed for each account. */ error ExceedsMaxPerAccount(); /** * @dev The merkle root hash is empty. */ error MerkleRootHashIsEmpty(); /** * @dev The max mintable per account cannot be zero. */ error MaxMintablePerAccountIsZero(); // ============================================================= // PUBLIC / EXTERNAL WRITE FUNCTIONS // ============================================================= /** * @dev Initializes Merkle drop mint instance. * @param edition Address of the song edition contract we are minting for. * @param merkleRootHash bytes32 hash of the Merkle tree representing eligible mints. * @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 endTime End timestamp of sale (in seconds since unix epoch). * @param affiliateFeeBPS The affiliate fee in basis points. * @param maxMintable_ The maximum number of tokens that can can be minted for this sale. * @param maxMintablePerAccount_ The maximum number of tokens that a single account can mint. * @return mintId The ID of the new mint instance. */ function createEditionMint( address edition, bytes32 merkleRootHash, uint96 price, uint32 startTime, uint32 endTime, uint16 affiliateFeeBPS, uint32 maxMintable_, uint32 maxMintablePerAccount_ ) external returns (uint128 mintId); /** * @dev Mints a token for a particular mint instance. * @param edition Address of the song edition contract we are minting for. * @param mintId The mint ID. * @param to The address to mint to. * @param quantity The quantity of tokens to mint. * @param allowlisted The address authorized to mint the tokens. * @param proof The Merkle proof. * @param affiliate The affiliate address. * @param affiliateProof The Merkle proof needed for verifying the affiliate, if any. * @param attributionId The attribution ID. */ function mintTo( address edition, uint128 mintId, address to, uint32 quantity, address allowlisted, bytes32[] calldata proof, address affiliate, bytes32[] calldata affiliateProof, uint256 attributionId ) external payable; /** * @dev Mints a token for a particular mint instance. * @param edition Address of the song edition contract we are minting for. * @param mintId The mint ID.. * @param quantity The quantity of tokens to mint. * @param proof The Merkle proof. * @param affiliate The affiliate address. */ function mint( address edition, uint128 mintId, uint32 quantity, bytes32[] calldata proof, 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; /** * @dev Sets the `maxMintable` for (`edition`, `mintId`). * @param edition Address of the song edition contract we are minting for. * @param mintId The mint ID. * @param maxMintable The maximum number of tokens that can be minted on this schedule. */ function setMaxMintable( address edition, uint128 mintId, uint32 maxMintable ) external; /** * @dev Sets the `merkleRootHash` for (`edition`, `mintId`). * @param edition Address of the song edition contract we are minting for. * @param mintId The mint ID. * @param merkleRootHash The Merkle root hash of the entries. */ function setMerkleRootHash( address edition, uint128 mintId, bytes32 merkleRootHash ) external; // ============================================================= // PUBLIC / EXTERNAL VIEW FUNCTIONS // ============================================================= /** * @dev Returns the number of tokens minted to address `to`, for (`edition`, `mintId`). * @param edition Address of the song edition contract we are minting for. * @param mintId The mint ID. * @param to The address to mint to. * @return count The number of tokens minted. */ function mintCount( address edition, uint128 mintId, address to ) external view returns (uint256 count); /** * @dev Returns IMerkleDropMinterV2_1.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); /** * @dev To prevent ERC165 selector collision. */ function isV2_1() external pure returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import { IERC165 } from "openzeppelin/utils/introspection/IERC165.sol"; /** * @title IMinterModuleV2_1 * @notice The interface for Sound protocol minter modules. */ interface IMinterModuleV2_1 is IERC165 { // ============================================================= // STRUCTS // ============================================================= struct BaseData { // Auxillary variable for storing the price. // May or may not be used. uint96 price; // Auxillary variable for storing the max amount mintable by an account. // May or may not be used. uint32 maxMintablePerAccount; // 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; // Whether the mint has been created. bool created; // The Merkle root of the affiliate allow list, if any. bytes32 affiliateMerkleRoot; } // ============================================================= // 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 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 mintId, uint16 bps); /** * @dev Emitted when the Merkle root for an affiliate allow list is set. * @param edition The edition address. * @param mintId The mint ID, to distinguish between multiple mints for the same edition. * @param root The Merkle root for the affiliate allow list. */ event AffiliateMerkleRootSet(address indexed edition, uint128 mintId, bytes32 root); /** * @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. * @param attributionId The attribution ID. */ event Minted( address indexed edition, uint128 mintId, address indexed buyer, uint32 fromTokenId, uint32 quantity, uint128 requiredEtherValue, uint128 platformFee, uint128 affiliateFee, address affiliate, bool affiliated, uint256 indexed attributionId ); /** * @dev Emitted when the `platformFeeBPS` is updated. * @param bps The platform fee basis points. */ event PlatformFeeSet(uint16 bps); /** * @dev Emitted when the `platformFlatFee` is updated. * @param flatFee The amount of platform flat fee per token. */ event PlatformFlatFeeSet(uint96 flatFee); /** * @dev Emitted when the `platformPerTxFlatFee` is updated. * @param perTxFlatFee The amount of platform flat fee per transaction. */ event PlatformPerTxFlatFeeSet(uint96 perTxFlatFee); /** * @dev Emitted when the `platformFeeAddress` is updated. * @param addr The platform fee address. */ event PlatformFeeAddressSet(address addr); /** * @dev Emitted when the accrued fees for `affiliate` are withdrawn. * @param affiliate The affiliate address. * @param accrued The amount of fees withdrawn. */ event AffiliateFeesWithdrawn(address indexed affiliate, uint256 accrued); /** * @dev Emitted when the accrued fees for the platform are withdrawn. * @param accrued The amount of fees withdrawn. */ event PlatformFeesWithdrawn(uint128 accrued); // ============================================================= // 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 Ether value paid is not exact. * @param paid The amount sent to the contract. * @param required The amount required to mint. */ error WrongPayment(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 The affiliate fee BPS must not exceed `MAX_AFFILIATE_FEE_BPS`. */ error InvalidAffiliateFeeBPS(); /** * @dev The platform fee BPS must not exceed `MAX_PLATFORM_FEE_BPS`. */ error InvalidPlatformFeeBPS(); /** * @dev The platform flat fee must not exceed `MAX_PLATFORM_FLAT_FEE`. */ error InvalidPlatformFlatFee(); /** * @dev The platform per-transaction flat fee must not exceed `MAX_PLATFORM_PER_TX_FLAT_FEE`. */ error InvalidPlatformPerTxFlatFee(); /** * @dev The platform fee address cannot be zero. */ error PlatformFeeAddressIsZero(); /** * @dev The mint does not exist. */ error MintDoesNotExist(); /** * @dev The `affiliate` provided is invalid for the given `affiliateProof`. */ error InvalidAffiliate(); // ============================================================= // 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. * * @param edition The edition address. * @param mintId The mint ID, a global incrementing identifier used within the minter * @param affiliateFeeBPS The affiliate fee in basis points. */ function setAffiliateFee( address edition, uint128 mintId, uint16 affiliateFeeBPS ) external; /** * @dev Sets the affiliate Merkle root for (`edition`, `mintId`). * * 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 root The affiliate Merkle root, if any. */ function setAffiliateMerkleRoot( address edition, uint128 mintId, bytes32 root ) external; /** * @dev Sets the platform fee bps. * * Calling conditions: * - The caller must be the owner of the contract. * * @param bps The platform fee in basis points. */ function setPlatformFee(uint16 bps) external; /** * @dev Sets the platform flat fee. * * Calling conditions: * - The caller must be the owner of the contract. * * @param flatFee The platform flat fee. */ function setPlatformFlatFee(uint96 flatFee) external; /** * @dev Sets the per-transaction platform flat fee. * * Calling conditions: * - The caller must be the owner of the contract. * * @param perTxFlatFee The platform per transaction flat fee. */ function setPlatformPerTxFlatFee(uint96 perTxFlatFee) external; /** * @dev Sets the platform fee address. * * Calling conditions: * - The caller must be the owner of the contract. * * @param addr The platform fee address. */ function setPlatformFeeAddress(address addr) 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 This is the denominator, in basis points (BPS), for any of the fees. * @return The constant value. */ function BPS_DENOMINATOR() external pure returns (uint16); /** * @dev The maximum basis points (BPS) limit allowed for the affiliate fees. * @return The constant value. */ function MAX_AFFILIATE_FEE_BPS() external pure returns (uint16); /** * @dev The maximum basis points (BPS) limit allowed for the platform fees. * @return The constant value. */ function MAX_PLATFORM_FEE_BPS() external pure returns (uint16); /** * @dev The maximum value for platform flat fee per NFT. * @return The constant value. */ function MAX_PLATFORM_FLAT_FEE() external pure returns (uint96); /** * @dev The maximum value for platform flat fee per transaction. * @return The constant value. */ function MAX_PLATFORM_PER_TX_FLAT_FEE() external pure returns (uint96); /** * @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. * @param affiliateProof The Merkle proof needed for verifying the affiliate, if any. * @return The computed value. */ function isAffiliatedWithProof( address edition, uint128 mintId, address affiliate, bytes32[] calldata affiliateProof ) external view returns (bool); /** * @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 Returns the affiliate Merkle root. * @param edition The edition's address. * @param mintId The mint ID. * @return The latest value. */ function affiliateMerkleRoot(address edition, uint128 mintId) external view returns (bytes32); /** * @dev Returns the total price and fees for `quantity` tokens for (`edition`, `mintId`). * @param edition The edition's address. * @param mintId The mint ID. * @param quantity The number of tokens to mint. * @return total The total buy price, inclusive of any additional platform flat fees. * @return subTotal The total buy price, exclusive of any additional platform flat fees. * @return platformFlatFeeTotal The total platform flat fees, which is added onto `subTotal` to give `total`. * @return platformFee The total platform fees. * @return affiliateFee The affiliate fees. */ function totalPriceAndFees( address edition, uint128 mintId, uint32 quantity ) external view returns ( uint256 total, uint256 subTotal, uint256 platformFlatFeeTotal, uint256 platformFee, uint256 affiliateFee ); /** * @dev Returns the platform fee basis points. * @return The configured value. */ function platformFeeBPS() external returns (uint16); /** * @dev Returns the platform flat fee per item. * @return The configured value. */ function platformFlatFee() external returns (uint96); /** * @dev Returns the platform flat fee per transaction. * @return The configured value. */ function platformPerTxFlatFee() external returns (uint96); /** * @dev Returns the platform fee address. * @return The configured value. */ function platformFeeAddress() external returns (address); /** * @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); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import { IERC721AUpgradeable } from "chiru-labs/ERC721A-Upgradeable/IERC721AUpgradeable.sol"; import { IERC2981Upgradeable } from "openzeppelin-upgradeable/interfaces/IERC2981Upgradeable.sol"; import { IERC165Upgradeable } from "openzeppelin-upgradeable/utils/introspection/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.4; import "./Ownable.sol"; /// @notice Simple single owner and multiroles authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.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 is Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev `bytes4(keccak256(bytes("Unauthorized()")))`. uint256 private constant _UNAUTHORIZED_ERROR_SELECTOR = 0x82b42900; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EVENTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @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("RolesUpdated(address,uint256)"))`. uint256 private constant _ROLES_UPDATED_EVENT_SIGNATURE = 0x715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STORAGE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The role slot of `user` is given by: /// ``` /// mstore(0x00, or(shl(96, user), _ROLE_SLOT_SEED)) /// 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. /// /// Note: This is equal to `_OWNER_SLOT_NOT` in for gas efficiency. uint256 private constant _ROLE_SLOT_SEED = 0x8b78c6d8; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @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 { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) let roleSlot := keccak256(0x0c, 0x20) // Load the current value and `or` it with `roles`. roles := or(sload(roleSlot), roles) // Store the new value. sstore(roleSlot, roles) // Emit the {RolesUpdated} event. log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles) } } /// @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 { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) let roleSlot := keccak256(0x0c, 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. roles := xor(currentRoles, and(currentRoles, roles)) // Then, store the new value. sstore(roleSlot, roles) // Emit the {RolesUpdated} event. log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles) } } /// @dev Throws if the sender does not have any of the `roles`. function _checkRoles(uint256 roles) internal view virtual { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, caller()) // Load the stored value, and if the `and` intersection // of the value and `roles` is zero, revert. if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) { mstore(0x00, _UNAUTHORIZED_ERROR_SELECTOR) revert(0x1c, 0x04) } } } /// @dev Throws if the sender is not the owner, /// and does not have any of the `roles`. /// Checks for ownership first, then lazily checks for roles. function _checkOwnerOrRoles(uint256 roles) internal view virtual { /// @solidity memory-safe-assembly assembly { // If the caller is not the stored owner. // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`. if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, caller()) // Load the stored value, and if the `and` intersection // of the value and `roles` is zero, revert. if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) { mstore(0x00, _UNAUTHORIZED_ERROR_SELECTOR) revert(0x1c, 0x04) } } } } /// @dev Throws if the sender does not have any of the `roles`, /// and is not the owner. /// Checks for roles first, then lazily checks for ownership. function _checkRolesOrOwner(uint256 roles) internal view virtual { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, caller()) // Load the stored value, and if the `and` intersection // of the value and `roles` is zero, revert. if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) { // If the caller is not the stored owner. // Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`. if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) { mstore(0x00, _UNAUTHORIZED_ERROR_SELECTOR) revert(0x1c, 0x04) } } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @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 payable 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 payable 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 payable virtual { _removeRoles(msg.sender, roles); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `user` has any of `roles`. function hasAnyRole(address user, uint256 roles) public view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) // 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(0x0c, 0x20)), roles))) } } /// @dev Returns whether `user` has all of `roles`. function hasAllRoles(address user, uint256 roles) public view virtual returns (bool result) { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) // Whether the stored value is contains all the set bits in `roles`. result := eq(and(sload(keccak256(0x0c, 0x20)), roles), roles) } } /// @dev Returns the roles of `user`. function rolesOf(address user) public view virtual returns (uint256 roles) { /// @solidity memory-safe-assembly assembly { // Compute the role slot. mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) // Load the stored value. roles := sload(keccak256(0x0c, 0x20)) } } /// @dev Convenience function to return a `roles` bitmap from an array of `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) { /// @solidity memory-safe-assembly assembly { for { let i := shl(5, mload(ordinals)) } i { i := sub(i, 0x20) } { // We don't need to mask the values of `ordinals`, as Solidity // cleans dirty upper bits when storing variables into memory. roles := or(shl(mload(add(ordinals, i)), 1), roles) } } } /// @dev Convenience function to return an array of `ordinals` from the `roles` bitmap. /// 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) { /// @solidity memory-safe-assembly assembly { // Grab the pointer to the free memory. ordinals := mload(0x40) let ptr := add(ordinals, 0x20) let o := 0 // 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. for { let t := roles } 1 {} { mstore(ptr, o) // `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(t, 1))) o := add(o, 1) t := shr(o, roles) if iszero(t) { break } } // Store the length of `ordinals`. mstore(ordinals, shr(5, sub(ptr, add(ordinals, 0x20)))) // Allocate the memory. mstore(0x40, ptr) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by an account with `roles`. modifier onlyRoles(uint256 roles) virtual { _checkRoles(roles); _; } /// @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 { _checkOwnerOrRoles(roles); _; } /// @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 { _checkRolesOrOwner(roles); _; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* 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; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import { IERC721AUpgradeable } from "chiru-labs/ERC721A-Upgradeable/IERC721AUpgradeable.sol"; import { IERC2981Upgradeable } from "openzeppelin-upgradeable/interfaces/IERC2981Upgradeable.sol"; import { IERC165Upgradeable } from "openzeppelin-upgradeable/utils/introspection/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_2 * @notice The interface for Sound edition contracts. */ interface ISoundEditionV1_2 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 when the `operatorFilteringEnabled` is set. * @param operatorFilteringEnabled_ The boolean value. */ event OperatorFilteringEnablededSet(bool operatorFilteringEnabled_); /** * @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); /** * @dev EIP-4906 event to signal marketplaces to refresh the metadata. * @param fromTokenId The starting token ID. * @param toTokenId The ending token ID. */ event BatchMetadataUpdate(uint256 fromTokenId, uint256 toTokenId); /** * @dev Emiited when the Sound Automated Market (i.e. bonding curve minter) is set. * @param sam_ The Sound Automated Market. */ event SAMSet(address sam_); // ============================================================= // 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 The mint has not concluded. */ error MintNotConcluded(); /** * @dev Cannot perform the operation after a token has been minted. */ error MintsAlreadyExist(); /** * @dev The token IDs must be in strictly ascending order. */ error TokenIdsNotStrictlyAscending(); /** * @dev Please wait for a while before you burn. */ error CannotBurnImmediately(); // ============================================================= // 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 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 bonding curve contract. * * @param to Address to mint to. * @param quantity Number of tokens to mint. * @return fromTokenId The first token ID minted. */ function samMint(address to, uint256 quantity) external payable returns (uint256 fromTokenId); /** * @dev Burns the `tokenIds`. * * Calling conditions: * - The caller must be the bonding curve contract. * * @param burner The initiator of the burn. * @param tokenIds The list of token IDs to burn. */ function samBurn(address burner, uint256[] calldata tokenIds) external; /** * @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; /** * @dev Sets whether OpenSea operator filtering is enabled. * * Calling conditions: * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`. * * @param operatorFilteringEnabled_ The boolean value. */ function setOperatorFilteringEnabled(bool operatorFilteringEnabled_) external; /** * @dev Emits an event to signal to marketplaces to refresh all the metadata. */ function emitAllMetadataUpdate() external; /** * @dev Sets the Sound Automated Market (i.e. bonding curve minter). * * Calling conditions: * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`. * * @param sam_ The Sound Automated Market. */ function setSAM(address sam_) 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 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 bit flag to enable OpenSea operator filtering. * @return The constant value. */ function OPERATOR_FILTERING_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 `operatorFilteringEnabled` has been enabled. * @return The configured value. */ function operatorFilteringEnabled() 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 sound automated market, if any. * @return The configured value. */ function sam() external view returns (address); /** * @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.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 */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The ETH transfer has failed. error ETHTransferFailed(); /// @dev The ERC20 `transferFrom` has failed. error TransferFromFailed(); /// @dev The ERC20 `transfer` has failed. error TransferFailed(); /// @dev The ERC20 `approve` has failed. error ApproveFailed(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Suggested gas stipend for contract receiving ETH /// that disallows any storage writes. uint256 internal constant _GAS_STIPEND_NO_STORAGE_WRITES = 2300; /// @dev Suggested gas stipend for contract receiving ETH to perform a few /// storage reads and writes, but low enough to prevent griefing. /// Multiply by a small constant (e.g. 2), if needed. uint256 internal constant _GAS_STIPEND_NO_GRIEF = 100000; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ETH OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sends `amount` (in wei) ETH to `to`. /// Reverts upon failure. function safeTransferETH(address to, uint256 amount) internal { /// @solidity memory-safe-assembly 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) } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`. /// The `gasStipend` can be set to a low enough value to prevent /// storage writes or gas griefing. /// /// If sending via the normal procedure fails, force sends the ETH by /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH. /// /// Reverts if the current contract has insufficient balance. function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal { /// @solidity memory-safe-assembly assembly { // If insufficient balance, revert. if lt(selfbalance(), amount) { // Store the function selector of `ETHTransferFailed()`. mstore(0x00, 0xb12d13eb) // Revert with (offset, size). revert(0x1c, 0x04) } // Transfer the ETH and check if it succeeded or not. if iszero(call(gasStipend, to, amount, 0, 0, 0, 0)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. // We can directly use `SELFDESTRUCT` in the contract creation. // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758 pop(create(amount, 0x0b, 0x16)) } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with a gas stipend /// equal to `_GAS_STIPEND_NO_GRIEF`. This gas stipend is a reasonable default /// for 99% of cases and can be overriden with the three-argument version of this /// function if necessary. /// /// If sending via the normal procedure fails, force sends the ETH by /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH. /// /// Reverts if the current contract has insufficient balance. function forceSafeTransferETH(address to, uint256 amount) internal { // Manually inlined because the compiler doesn't inline functions with branches. /// @solidity memory-safe-assembly assembly { // If insufficient balance, revert. if lt(selfbalance(), amount) { // Store the function selector of `ETHTransferFailed()`. mstore(0x00, 0xb12d13eb) // Revert with (offset, size). revert(0x1c, 0x04) } // Transfer the ETH and check if it succeeded or not. if iszero(call(_GAS_STIPEND_NO_GRIEF, to, amount, 0, 0, 0, 0)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. // We can directly use `SELFDESTRUCT` in the contract creation. // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758 pop(create(amount, 0x0b, 0x16)) } } } /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`. /// The `gasStipend` can be set to a low enough value to prevent /// storage writes or gas griefing. /// /// Simply use `gasleft()` for `gasStipend` if you don't need a gas stipend. /// /// Note: Does NOT revert upon failure. /// Returns whether the transfer of ETH is successful instead. function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { // Transfer the ETH and check if it succeeded or not. success := call(gasStipend, to, amount, 0, 0, 0, 0) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC20 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sends `amount` of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have at least `amount` approved for /// the current contract to manage. function safeTransferFrom(address token, address from, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. // Store the function selector of `transferFrom(address,address,uint256)`. mstore(0x00, 0x23b872dd) mstore(0x20, from) // Store the `from` argument. mstore(0x40, to) // Store the `to` argument. mstore(0x60, amount) // Store the `amount` argument. if iszero( and( // The arguments of `and` are evaluated from right to left. // 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())), 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, m) // Restore the free memory pointer. } } /// @dev Sends all of ERC20 `token` from `from` to `to`. /// Reverts upon failure. /// /// The `from` account must have at least `amount` approved for /// the current contract to manage. function safeTransferAllFrom(address token, address from, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`. mstore(0x20, from) // Store the `from` argument. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20) ) ) { // Store the function selector of `TransferFromFailed()`. mstore(0x00, 0x7939f424) // Revert with (offset, size). revert(0x1c, 0x04) } // Store the function selector of `transferFrom(address,address,uint256)`. mstore(0x00, 0x23b872dd) mstore(0x40, to) // Store the `to` argument. // The `amount` argument is already written to the memory word at 0x6a. amount := mload(0x60) if iszero( and( // The arguments of `and` are evaluated from right to left. // 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())), 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, m) // Restore the free memory pointer. } } /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransfer(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x1a, to) // Store the `to` argument. mstore(0x3a, amount) // Store the `amount` argument. // Store the function selector of `transfer(address,uint256)`, // left by 6 bytes (enough for 8tb of memory represented by the free memory pointer). // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL). mstore(0x00, 0xa9059cbb000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. // 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())), call(gas(), token, 0, 0x16, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `TransferFailed()`. mstore(0x00, 0x90b8ec18) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the part of the free memory pointer that was overwritten, // which is guaranteed to be zero, if less than 8tb of memory is used. mstore(0x3a, 0) } } /// @dev Sends all of ERC20 `token` from the current contract to `to`. /// Reverts upon failure. function safeTransferAll(address token, address to) internal returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`. mstore(0x20, address()) // Store the address of the current contract. if iszero( and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x3a, 0x20) ) ) { // Store the function selector of `TransferFailed()`. mstore(0x00, 0x90b8ec18) // Revert with (offset, size). revert(0x1c, 0x04) } mstore(0x1a, to) // Store the `to` argument. // The `amount` argument is already written to the memory word at 0x3a. amount := mload(0x3a) // Store the function selector of `transfer(address,uint256)`, // left by 6 bytes (enough for 8tb of memory represented by the free memory pointer). // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL). mstore(0x00, 0xa9059cbb000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. // 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())), call(gas(), token, 0, 0x16, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `TransferFailed()`. mstore(0x00, 0x90b8ec18) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the part of the free memory pointer that was overwritten, // which is guaranteed to be zero, if less than 8tb of memory is used. mstore(0x3a, 0) } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// Reverts upon failure. function safeApprove(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x1a, to) // Store the `to` argument. mstore(0x3a, amount) // Store the `amount` argument. // Store the function selector of `approve(address,uint256)`, // left by 6 bytes (enough for 8tb of memory represented by the free memory pointer). // We waste 6-3 = 3 bytes to save on 6 runtime gas (PUSH1 0x224 SHL). mstore(0x00, 0x095ea7b3000000000000) if iszero( and( // The arguments of `and` are evaluated from right to left. // 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())), call(gas(), token, 0, 0x16, 0x44, 0x00, 0x20) ) ) { // Store the function selector of `ApproveFailed()`. mstore(0x00, 0x3e3f8f73) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the part of the free memory pointer that was overwritten, // which is guaranteed to be zero, if less than 8tb of memory is used. mstore(0x3a, 0) } } /// @dev Returns the amount of ERC20 `token` owned by `account`. /// Returns zero if the `token` does not exist. function balanceOf(address token, address account) internal view returns (uint256 amount) { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`. mstore(0x20, account) // Store the `account` argument. amount := mul( mload(0x20), and( // The arguments of `and` are evaluated from right to left. gt(returndatasize(), 0x1f), // At least 32 bytes returned. staticcall(gas(), token, 0x1c, 0x24, 0x20, 0x20) ) ) } } }
// 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 full precision multiply-divide operation failed, either due /// to the result being larger than 256 bits, or a division by a zero. error FullMulDivFailed(); /// @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 mulWad(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly 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) { /// @solidity memory-safe-assembly 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 divWad(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly 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) { /// @solidity memory-safe-assembly 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 r; /// @solidity memory-safe-assembly assembly { // 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 iszero(slt(x, 135305999368893231589)) { // Store the function selector of `ExpOverflow()`. mstore(0x00, 0xa37bfec9) // Revert with (offset, size). revert(0x1c, 0x04) } } // 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; /// @solidity memory-safe-assembly 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 { /// @solidity memory-safe-assembly assembly { if iszero(sgt(x, 0)) { // Store the function selector of `LnWadUndefined()`. mstore(0x00, 0x1615e638) // Revert with (offset, size). revert(0x1c, 0x04) } } // 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; /// @solidity memory-safe-assembly 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)) // forgefmt: disable-next-item 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; /// @solidity memory-safe-assembly 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 Calculates `floor(a * b / d)` with full precision. /// Throws if result overflows a uint256 or when `d` is zero. /// Credit to Remco Bloemen under MIT license: https://2π.com/21/muldiv function fullMulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { // forgefmt: disable-next-item for {} 1 {} { // 512-bit multiply `[prod1 prod0] = x * y`. // Compute the product mod `2**256` and mod `2**256 - 1` // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that `product = prod1 * 2**256 + prod0`. // Least significant 256 bits of the product. let prod0 := mul(x, y) let mm := mulmod(x, y, not(0)) // Most significant 256 bits of the product. let prod1 := sub(mm, add(prod0, lt(mm, prod0))) // Handle non-overflow cases, 256 by 256 division. if iszero(prod1) { if iszero(d) { // Store the function selector of `FullMulDivFailed()`. mstore(0x00, 0xae47f702) // Revert with (offset, size). revert(0x1c, 0x04) } result := div(prod0, d) break } // Make sure the result is less than `2**256`. // Also prevents `d == 0`. if iszero(gt(d, prod1)) { // Store the function selector of `FullMulDivFailed()`. mstore(0x00, 0xae47f702) // Revert with (offset, size). revert(0x1c, 0x04) } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from `[prod1 prod0]`. // Compute remainder using mulmod. let remainder := mulmod(x, y, d) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) // Factor powers of two out of `d`. // Compute largest power of two divisor of `d`. // Always greater or equal to 1. let twos := and(d, sub(0, d)) // Divide d by power of two. d := div(d, twos) // Divide [prod1 prod0] by the factors of two. prod0 := div(prod0, twos) // Shift in bits from `prod1` into `prod0`. For this we need // to flip `twos` such that it is `2**256 / twos`. // If `twos` is zero, then it becomes one. prod0 := or(prod0, mul(prod1, add(div(sub(0, twos), twos), 1))) // Invert `d mod 2**256` // Now that `d` is an odd number, it has an inverse // modulo `2**256` such that `d * inv = 1 mod 2**256`. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, `d * inv = 1 mod 2**4`. let inv := xor(mul(3, d), 2) // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**8 inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**16 inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**32 inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**64 inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**128 result := mul(prod0, mul(inv, sub(2, mul(d, inv)))) // inverse mod 2**256 break } } } /// @dev Calculates `floor(x * y / d)` with full precision, rounded up. /// Throws if result overflows a uint256 or when `d` is zero. /// Credit to Uniswap-v3-core under MIT license: /// https://github.com/Uniswap/v3-core/blob/contracts/libraries/FullMath.sol function fullMulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 result) { result = fullMulDiv(x, y, d); /// @solidity memory-safe-assembly assembly { if mulmod(x, y, d) { if iszero(add(result, 1)) { // Store the function selector of `FullMulDivFailed()`. mstore(0x00, 0xae47f702) // Revert with (offset, size). revert(0x1c, 0x04) } result := add(result, 1) } } } /// @dev Returns `floor(x * y / d)`. /// Reverts if `x * y` overflows, or `d` is zero. function mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(d, 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), d) } } /// @dev Returns `ceil(x * y / d)`. /// Reverts if `x * y` overflows, or `d` is zero. function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to require(d != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(d, 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), d))), div(mul(x, y), d)) } } /// @dev Returns `ceil(x / d)`. /// Reverts if `d` is zero. function divUp(uint256 x, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { if iszero(d) { // Store the function selector of `DivFailed()`. mstore(0x00, 0x65244e4e) // Revert with (offset, size). revert(0x1c, 0x04) } z := add(iszero(iszero(mod(x, d))), div(x, d)) } } /// @dev Returns `max(0, x - y)`. function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly 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) { /// @solidity memory-safe-assembly 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, lt(0xffffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffffff, shr(r, x)))) 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 cube root of `x`. /// Credit to bout3fiddy and pcaversaccio under AGPLv3 license: /// https://github.com/pcaversaccio/snekmate/blob/main/src/utils/Math.vy function cbrt(uint256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { let 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)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) z := shl(add(div(r, 3), lt(0xf, shr(r, x))), 0xff) z := div(z, byte(mod(r, 3), shl(232, 0x7f624b))) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := sub(z, lt(div(x, mul(z, z)), z)) } } /// @dev Returns the factorial of `x`. function factorial(uint256 x) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { for {} 1 {} { if iszero(lt(10, x)) { // forgefmt: disable-next-item result := and( shr(mul(22, x), 0x375f0016260009d80004ec0002d00001e0000180000180000200000400001), 0x3fffff ) break } if iszero(lt(57, x)) { let end := 31 result := 8222838654177922817725562880000000 if iszero(lt(end, x)) { end := 10 result := 3628800 } for { let w := not(0) } 1 {} { result := mul(result, x) x := add(x, w) if eq(x, end) { break } } break } // Store the function selector of `FactorialOverflow()`. mstore(0x00, 0xaba0f2a2) // Revert with (offset, size). revert(0x1c, 0x04) } } } /// @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) { /// @solidity memory-safe-assembly 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)) // forgefmt: disable-next-item r := or(r, byte(shr(251, mul(x, shl(224, 0x07c4acdd))), 0x0009010a0d15021d0b0e10121619031e080c141c0f111807131b17061a05041f)) } } /// @dev Returns the log2 of `x`, rounded up. function log2Up(uint256 x) internal pure returns (uint256 r) { unchecked { uint256 isNotPo2; assembly { isNotPo2 := iszero(iszero(and(x, sub(x, 1)))) } return log2(x) + isNotPo2; } } /// @dev Returns the average of `x` and `y`. function avg(uint256 x, uint256 y) internal pure returns (uint256 z) { unchecked { z = (x & y) + ((x ^ y) >> 1); } } /// @dev Returns the average of `x` and `y`. function avg(int256 x, int256 y) internal pure returns (int256 z) { unchecked { z = (x >> 1) + (y >> 1) + (((x & 1) + (y & 1)) >> 1); } } /// @dev Returns the absolute value of `x`. function abs(int256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { let mask := sub(0, shr(255, x)) 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) { /// @solidity memory-safe-assembly 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) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), lt(y, x))) } } /// @dev Returns the minimum of `x` and `y`. function min(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), slt(y, x))) } } /// @dev Returns the maximum of `x` and `y`. function max(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), gt(y, x))) } } /// @dev Returns the maximum of `x` and `y`. function max(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), sgt(y, x))) } } /// @dev Returns `x`, bounded to `minValue` and `maxValue`. function clamp(uint256 x, uint256 minValue, uint256 maxValue) internal pure returns (uint256 z) { z = min(max(x, minValue), maxValue); } /// @dev Returns `x`, bounded to `minValue` and `maxValue`. function clamp(int256 x, int256 minValue, int256 maxValue) internal pure returns (int256 z) { z = min(max(x, minValue), maxValue); } /// @dev Returns greatest common divisor of `x` and `y`. function gcd(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // forgefmt: disable-next-item for { z := x } y {} { let t := y y := mod(z, y) z := t } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RAW NUMBER OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns `x + y`, without checking for overflow. function rawAdd(uint256 x, uint256 y) internal pure returns (uint256 z) { unchecked { z = x + y; } } /// @dev Returns `x + y`, without checking for overflow. function rawAdd(int256 x, int256 y) internal pure returns (int256 z) { unchecked { z = x + y; } } /// @dev Returns `x - y`, without checking for underflow. function rawSub(uint256 x, uint256 y) internal pure returns (uint256 z) { unchecked { z = x - y; } } /// @dev Returns `x - y`, without checking for underflow. function rawSub(int256 x, int256 y) internal pure returns (int256 z) { unchecked { z = x - y; } } /// @dev Returns `x * y`, without checking for overflow. function rawMul(uint256 x, uint256 y) internal pure returns (uint256 z) { unchecked { z = x * y; } } /// @dev Returns `x * y`, without checking for overflow. function rawMul(int256 x, int256 y) internal pure returns (int256 z) { unchecked { z = x * y; } } /// @dev Returns `x / y`, returning 0 if `y` is zero. function rawDiv(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := div(x, y) } } /// @dev Returns `x / y`, returning 0 if `y` is zero. function rawSDiv(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := sdiv(x, y) } } /// @dev Returns `x % y`, returning 0 if `y` is zero. function rawMod(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mod(x, y) } } /// @dev Returns `x % y`, returning 0 if `y` is zero. function rawSMod(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := smod(x, y) } } /// @dev Returns `(x + y) % d`, return 0 if `d` if zero. function rawAddMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := addmod(x, y, d) } } /// @dev Returns `(x * y) % d`, return 0 if `d` if zero. function rawMulMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mulmod(x, y, d) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Safe integer casting library that reverts on overflow. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeCastLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol) library SafeCastLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ error Overflow(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* UNSIGNED INTEGER SAFE CASTING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function toUint8(uint256 x) internal pure returns (uint8) { if (x >= 1 << 8) _revertOverflow(); return uint8(x); } function toUint16(uint256 x) internal pure returns (uint16) { if (x >= 1 << 16) _revertOverflow(); return uint16(x); } function toUint24(uint256 x) internal pure returns (uint24) { if (x >= 1 << 24) _revertOverflow(); return uint24(x); } function toUint32(uint256 x) internal pure returns (uint32) { if (x >= 1 << 32) _revertOverflow(); return uint32(x); } function toUint40(uint256 x) internal pure returns (uint40) { if (x >= 1 << 40) _revertOverflow(); return uint40(x); } function toUint48(uint256 x) internal pure returns (uint48) { if (x >= 1 << 48) _revertOverflow(); return uint48(x); } function toUint56(uint256 x) internal pure returns (uint56) { if (x >= 1 << 56) _revertOverflow(); return uint56(x); } function toUint64(uint256 x) internal pure returns (uint64) { if (x >= 1 << 64) _revertOverflow(); return uint64(x); } function toUint72(uint256 x) internal pure returns (uint72) { if (x >= 1 << 72) _revertOverflow(); return uint72(x); } function toUint80(uint256 x) internal pure returns (uint80) { if (x >= 1 << 80) _revertOverflow(); return uint80(x); } function toUint88(uint256 x) internal pure returns (uint88) { if (x >= 1 << 88) _revertOverflow(); return uint88(x); } function toUint96(uint256 x) internal pure returns (uint96) { if (x >= 1 << 96) _revertOverflow(); return uint96(x); } function toUint104(uint256 x) internal pure returns (uint104) { if (x >= 1 << 104) _revertOverflow(); return uint104(x); } function toUint112(uint256 x) internal pure returns (uint112) { if (x >= 1 << 112) _revertOverflow(); return uint112(x); } function toUint120(uint256 x) internal pure returns (uint120) { if (x >= 1 << 120) _revertOverflow(); return uint120(x); } function toUint128(uint256 x) internal pure returns (uint128) { if (x >= 1 << 128) _revertOverflow(); return uint128(x); } function toUint136(uint256 x) internal pure returns (uint136) { if (x >= 1 << 136) _revertOverflow(); return uint136(x); } function toUint144(uint256 x) internal pure returns (uint144) { if (x >= 1 << 144) _revertOverflow(); return uint144(x); } function toUint152(uint256 x) internal pure returns (uint152) { if (x >= 1 << 152) _revertOverflow(); return uint152(x); } function toUint160(uint256 x) internal pure returns (uint160) { if (x >= 1 << 160) _revertOverflow(); return uint160(x); } function toUint168(uint256 x) internal pure returns (uint168) { if (x >= 1 << 168) _revertOverflow(); return uint168(x); } function toUint176(uint256 x) internal pure returns (uint176) { if (x >= 1 << 176) _revertOverflow(); return uint176(x); } function toUint184(uint256 x) internal pure returns (uint184) { if (x >= 1 << 184) _revertOverflow(); return uint184(x); } function toUint192(uint256 x) internal pure returns (uint192) { if (x >= 1 << 192) _revertOverflow(); return uint192(x); } function toUint200(uint256 x) internal pure returns (uint200) { if (x >= 1 << 200) _revertOverflow(); return uint200(x); } function toUint208(uint256 x) internal pure returns (uint208) { if (x >= 1 << 208) _revertOverflow(); return uint208(x); } function toUint216(uint256 x) internal pure returns (uint216) { if (x >= 1 << 216) _revertOverflow(); return uint216(x); } function toUint224(uint256 x) internal pure returns (uint224) { if (x >= 1 << 224) _revertOverflow(); return uint224(x); } function toUint232(uint256 x) internal pure returns (uint232) { if (x >= 1 << 232) _revertOverflow(); return uint232(x); } function toUint240(uint256 x) internal pure returns (uint240) { if (x >= 1 << 240) _revertOverflow(); return uint240(x); } function toUint248(uint256 x) internal pure returns (uint248) { if (x >= 1 << 248) _revertOverflow(); return uint248(x); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* SIGNED INTEGER SAFE CASTING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function toInt8(int256 x) internal pure returns (int8) { int8 y = int8(x); if (x != y) _revertOverflow(); return y; } function toInt16(int256 x) internal pure returns (int16) { int16 y = int16(x); if (x != y) _revertOverflow(); return y; } function toInt24(int256 x) internal pure returns (int24) { int24 y = int24(x); if (x != y) _revertOverflow(); return y; } function toInt32(int256 x) internal pure returns (int32) { int32 y = int32(x); if (x != y) _revertOverflow(); return y; } function toInt40(int256 x) internal pure returns (int40) { int40 y = int40(x); if (x != y) _revertOverflow(); return y; } function toInt48(int256 x) internal pure returns (int48) { int48 y = int48(x); if (x != y) _revertOverflow(); return y; } function toInt56(int256 x) internal pure returns (int56) { int56 y = int56(x); if (x != y) _revertOverflow(); return y; } function toInt64(int256 x) internal pure returns (int64) { int64 y = int64(x); if (x != y) _revertOverflow(); return y; } function toInt72(int256 x) internal pure returns (int72) { int72 y = int72(x); if (x != y) _revertOverflow(); return y; } function toInt80(int256 x) internal pure returns (int80) { int80 y = int80(x); if (x != y) _revertOverflow(); return y; } function toInt88(int256 x) internal pure returns (int88) { int88 y = int88(x); if (x != y) _revertOverflow(); return y; } function toInt96(int256 x) internal pure returns (int96) { int96 y = int96(x); if (x != y) _revertOverflow(); return y; } function toInt104(int256 x) internal pure returns (int104) { int104 y = int104(x); if (x != y) _revertOverflow(); return y; } function toInt112(int256 x) internal pure returns (int112) { int112 y = int112(x); if (x != y) _revertOverflow(); return y; } function toInt120(int256 x) internal pure returns (int120) { int120 y = int120(x); if (x != y) _revertOverflow(); return y; } function toInt128(int256 x) internal pure returns (int128) { int128 y = int128(x); if (x != y) _revertOverflow(); return y; } function toInt136(int256 x) internal pure returns (int136) { int136 y = int136(x); if (x != y) _revertOverflow(); return y; } function toInt144(int256 x) internal pure returns (int144) { int144 y = int144(x); if (x != y) _revertOverflow(); return y; } function toInt152(int256 x) internal pure returns (int152) { int152 y = int152(x); if (x != y) _revertOverflow(); return y; } function toInt160(int256 x) internal pure returns (int160) { int160 y = int160(x); if (x != y) _revertOverflow(); return y; } function toInt168(int256 x) internal pure returns (int168) { int168 y = int168(x); if (x != y) _revertOverflow(); return y; } function toInt176(int256 x) internal pure returns (int176) { int176 y = int176(x); if (x != y) _revertOverflow(); return y; } function toInt184(int256 x) internal pure returns (int184) { int184 y = int184(x); if (x != y) _revertOverflow(); return y; } function toInt192(int256 x) internal pure returns (int192) { int192 y = int192(x); if (x != y) _revertOverflow(); return y; } function toInt200(int256 x) internal pure returns (int200) { int200 y = int200(x); if (x != y) _revertOverflow(); return y; } function toInt208(int256 x) internal pure returns (int208) { int208 y = int208(x); if (x != y) _revertOverflow(); return y; } function toInt216(int256 x) internal pure returns (int216) { int216 y = int216(x); if (x != y) _revertOverflow(); return y; } function toInt224(int256 x) internal pure returns (int224) { int224 y = int224(x); if (x != y) _revertOverflow(); return y; } function toInt232(int256 x) internal pure returns (int232) { int232 y = int232(x); if (x != y) _revertOverflow(); return y; } function toInt240(int256 x) internal pure returns (int240) { int240 y = int240(x); if (x != y) _revertOverflow(); return y; } function toInt248(int256 x) internal pure returns (int248) { int248 y = int248(x); if (x != y) _revertOverflow(); return y; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PRIVATE HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ function _revertOverflow() private pure { /// @solidity memory-safe-assembly assembly { // Store the function selector of `Overflow()`. mstore(0x00, 0x35278d12) // Revert with (offset, size). revert(0x1c, 0x04) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /** * @title LibMulticaller * @author vectorized.eth * @notice Library to read the `msg.sender` of the multicaller with sender contract. */ library LibMulticaller { /** * @dev The address of the multicaller contract. */ address internal constant MULTICALLER = 0x000000000088228fCF7b8af41Faf3955bD0B3A41; /** * @dev The address of the multicaller with sender contract. */ address internal constant MULTICALLER_WITH_SENDER = 0x00000000002Fd5Aeb385D324B580FCa7c83823A0; /** * @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`. */ function multicallerSender() internal view returns (address result) { /// @solidity memory-safe-assembly assembly { if iszero( staticcall( gas(), // Remaining gas. MULTICALLER_WITH_SENDER, // The multicaller. 0x00, // Start of calldata in memory. 0x00, // Length of calldata. 0x00, // Start of returndata in memory. 0x20 // Length of returndata. ) ) { revert(0, 0) } // For better gas estimation. result := mul(mload(0x00), eq(returndatasize(), 0x20)) } } /** * @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`, * if the current context's `msg.sender` is `MULTICALLER_WITH_SENDER`. * Otherwise, returns `msg.sender`. */ function sender() internal view returns (address result) { /// @solidity memory-safe-assembly assembly { result := caller() if eq(result, MULTICALLER_WITH_SENDER) { if iszero( staticcall( gas(), // Remaining gas. MULTICALLER_WITH_SENDER, // The multicaller with sender. 0x00, // Start of calldata in memory. 0x00, // Length of calldata. 0x00, // Start of returndata in memory. 0x20 // Length of returndata. ) ) { revert(0, 0) } // For better gas estimation. result := mul(mload(0x00), eq(returndatasize(), 0x20)) } } } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.3 // 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 payable; /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external payable; /** * @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 payable; /** * @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 payable; /** * @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 // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "../utils/introspection/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 // 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 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 pragma solidity ^0.8.4; /// @notice Simple single owner authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.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 /// may be unique to this codebase. abstract contract Ownable { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* 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 canceled. event OwnershipHandoverCanceled(address indexed pendingOwner); /// @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; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* 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. 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 { /// @solidity memory-safe-assembly 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 { /// @solidity memory-safe-assembly 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 Throws if the sender is not the owner. function _checkOwner() internal view virtual { /// @solidity memory-safe-assembly 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) } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC UPDATE FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Allows the owner to transfer the ownership to `newOwner`. function transferOwnership(address newOwner) public payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { if iszero(shl(96, newOwner)) { mstore(0x00, _NEW_OWNER_IS_ZERO_ADDRESS_ERROR_SELECTOR) revert(0x1c, 0x04) } } _setOwner(newOwner); } /// @dev Allows the owner to renounce their ownership. function renounceOwnership() public payable virtual onlyOwner { _setOwner(address(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 payable virtual { unchecked { uint256 expires = block.timestamp + ownershipHandoverValidFor(); /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to `expires`. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 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 payable virtual { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, caller()) sstore(keccak256(0x0c, 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 payable virtual onlyOwner { /// @solidity memory-safe-assembly assembly { // Compute and set the handover slot to 0. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) let handoverSlot := keccak256(0x0c, 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) } _setOwner(pendingOwner); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PUBLIC READ FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the owner of the contract. function owner() public view virtual returns (address result) { /// @solidity memory-safe-assembly 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) { /// @solidity memory-safe-assembly assembly { // Compute the handover slot. mstore(0x0c, _HANDOVER_SLOT_SEED) mstore(0x00, pendingOwner) // Load the handover slot. result := sload(keccak256(0x0c, 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; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Marks a function as only callable by the owner. modifier onlyOwner() virtual { _checkOwner(); _; } }
{ "remappings": [ "@core/=contracts/core/", "@modules/=contracts/modules/", "ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/", "chiru-labs/ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/", "closedsea/=lib/closedsea/src/", "ds-test/=lib/solady/lib/ds-test/src/", "erc4626-tests/=lib/closedsea/lib/openzeppelin-contracts/lib/erc4626-tests/", "erc721a-upgradeable/=lib/closedsea/lib/erc721a-upgradeable/contracts/", "erc721a/=lib/closedsea/lib/erc721a/contracts/", "forge-std/=lib/forge-std/src/", "multicaller/=lib/multicaller/src/", "murky/=lib/murky/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "openzeppelin/=lib/openzeppelin-contracts/contracts/", "operator-filter-registry/=lib/closedsea/lib/operator-filter-registry/", "preapprove/=lib/preapprove/src/", "solady/=lib/solady/src/", "solmate/=lib/solady/lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 1000 }, "metadata": { "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"CallerNotDelegated","type":"error"},{"inputs":[{"internalType":"uint32","name":"available","type":"uint32"}],"name":"ExceedsAvailableSupply","type":"error"},{"inputs":[],"name":"ExceedsMaxPerAccount","type":"error"},{"inputs":[],"name":"InvalidAffiliate","type":"error"},{"inputs":[],"name":"InvalidAffiliateFeeBPS","type":"error"},{"inputs":[],"name":"InvalidMerkleProof","type":"error"},{"inputs":[],"name":"InvalidPlatformFeeBPS","type":"error"},{"inputs":[],"name":"InvalidPlatformFlatFee","type":"error"},{"inputs":[],"name":"InvalidPlatformPerTxFlatFee","type":"error"},{"inputs":[],"name":"InvalidTimeRange","type":"error"},{"inputs":[],"name":"MaxMintablePerAccountIsZero","type":"error"},{"inputs":[],"name":"MerkleRootHashIsEmpty","type":"error"},{"inputs":[],"name":"MintDoesNotExist","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":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"PlatformFeeAddressIsZero","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[{"internalType":"uint256","name":"paid","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"Underpaid","type":"error"},{"inputs":[{"internalType":"uint256","name":"paid","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"WrongPayment","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"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":"affiliate","type":"address"},{"indexed":false,"internalType":"uint256","name":"accrued","type":"uint256"}],"name":"AffiliateFeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint128","name":"mintId","type":"uint128"},{"indexed":false,"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"AffiliateMerkleRootSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"allowlisted","type":"address"},{"indexed":false,"internalType":"uint32","name":"quantity","type":"uint32"}],"name":"DropClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"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":false,"internalType":"uint128","name":"mintId","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"maxMintable","type":"uint32"}],"name":"MaxMintableSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint128","name":"mintId","type":"uint128"},{"indexed":false,"internalType":"bytes32","name":"merkleRootHash","type":"bytes32"},{"indexed":false,"internalType":"uint96","name":"price","type":"uint96"},{"indexed":false,"internalType":"uint32","name":"startTime","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"endTime","type":"uint32"},{"indexed":false,"internalType":"uint16","name":"affiliateFeeBPS","type":"uint16"},{"indexed":false,"internalType":"uint32","name":"maxMintable","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"}],"name":"MerkleDropMintCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint128","name":"mintId","type":"uint128"},{"indexed":false,"internalType":"bytes32","name":"merkleRootHash","type":"bytes32"}],"name":"MerkleRootHashSet","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":false,"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"},{"indexed":true,"internalType":"uint256","name":"attributionId","type":"uint256"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"PlatformFeeAddressSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"bps","type":"uint16"}],"name":"PlatformFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"accrued","type":"uint128"}],"name":"PlatformFeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint96","name":"flatFee","type":"uint96"}],"name":"PlatformFlatFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint96","name":"perTxFlatFee","type":"uint96"}],"name":"PlatformPerTxFlatFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"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":false,"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":"BPS_DENOMINATOR","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_AFFILIATE_FEE_BPS","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PLATFORM_FEE_BPS","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PLATFORM_FLAT_FEE","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PLATFORM_PER_TX_FLAT_FEE","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"affiliateFeesAccrued","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","type":"uint128"}],"name":"affiliateMerkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"bytes32","name":"merkleRootHash","type":"bytes32"},{"internalType":"uint96","name":"price","type":"uint96"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint16","name":"affiliateFeeBPS","type":"uint16"},{"internalType":"uint32","name":"maxMintable","type":"uint32"},{"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"}],"name":"createEditionMint","outputs":[{"internalType":"uint128","name":"mintId","type":"uint128"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","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":"address","name":"affiliate","type":"address"},{"internalType":"bytes32[]","name":"affiliateProof","type":"bytes32[]"}],"name":"isAffiliatedWithProof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isV2_1","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","type":"uint128"},{"internalType":"uint32","name":"quantity","type":"uint32"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"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"},{"internalType":"address","name":"to","type":"address"}],"name":"mintCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"maxMintable","type":"uint32"},{"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"},{"internalType":"uint32","name":"totalMinted","type":"uint32"},{"internalType":"bytes32","name":"merkleRootHash","type":"bytes32"},{"internalType":"bytes32","name":"affiliateMerkleRoot","type":"bytes32"},{"internalType":"uint16","name":"platformFeeBPS","type":"uint16"},{"internalType":"uint96","name":"platformFlatFee","type":"uint96"},{"internalType":"uint96","name":"platformPerTxFlatFee","type":"uint96"}],"internalType":"struct MintInfo","name":"info","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","type":"uint128"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint32","name":"quantity","type":"uint32"},{"internalType":"address","name":"allowlisted","type":"address"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"bytes32[]","name":"affiliateProof","type":"bytes32[]"},{"internalType":"uint256","name":"attributionId","type":"uint256"}],"name":"mintTo","outputs":[],"stateMutability":"payable","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":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownershipHandoverValidFor","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformFeeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformFeeBPS","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformFeesAccrued","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformFlatFee","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformPerTxFlatFee","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","type":"uint128"},{"internalType":"uint16","name":"bps","type":"uint16"}],"name":"setAffiliateFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint128","name":"mintId","type":"uint128"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"setAffiliateMerkleRoot","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":"maxMintable","type":"uint32"}],"name":"setMaxMintable","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":"bytes32","name":"merkleRootHash","type":"bytes32"}],"name":"setMerkleRootHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"bps","type":"uint16"}],"name":"setPlatformFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"setPlatformFeeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"flatFee","type":"uint96"}],"name":"setPlatformFlatFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"perTxFlatFee","type":"uint96"}],"name":"setPlatformPerTxFlatFee","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":"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":"uint32","name":"quantity","type":"uint32"}],"name":"totalPriceAndFees","outputs":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"subTotal","type":"uint256"},{"internalType":"uint256","name":"platformFlatFeeTotal","type":"uint256"},{"internalType":"uint256","name":"platformFee","type":"uint256"},{"internalType":"uint256","name":"affiliateFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","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
608060405234801561001057600080fd5b5061001a3361001f565b61005b565b6001600160a01b0316638b78c6d8198190558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b612b8e806200006b6000396000f3fe6080604052600436106102fd5760003560e01c8063b0d659381161018f578063d7533f02116100e1578063f04e283e1161008a578063fb128c8311610064578063fb128c83146103ee578063fc63e69e14610865578063fee81cf41461088557600080fd5b8063f04e283e1461081f578063f2fde38b14610832578063f57402961461084557600080fd5b8063e71924f1116100bb578063e71924f1146107b6578063ebaaa3a1146107dd578063ed14834f146107ff57600080fd5b8063d7533f0214610762578063e1a4521814610780578063e37a0cea1461079657600080fd5b8063c3190a2e11610143578063c94dcf8f1161011d578063c94dcf8f146106da578063cbb35c21146106fa578063d73f3aab1461074257600080fd5b8063c3190a2e14610678578063c7dd322814610698578063c9238eae146106ba57600080fd5b8063be0c9b6c11610174578063be0c9b6c14610618578063bf013d7b14610638578063c309c47d1461065857600080fd5b8063b0d65938146105e5578063b24e737e1461060557600080fd5b80635cbc742c116102535780638d01513c116101fc57806398040f46116101d657806398040f461461056f578063ac1fc22c1461058f578063aec96b6e146105c557600080fd5b80638d01513c146104d15780638da5cb5b146105225780639375da5a1461054f57600080fd5b80636c5f55f71161022d5780636c5f55f7146104d1578063715018a6146104fa5780637614a7511461050257600080fd5b80635cbc742c1461045e57806365bd416d1461047e5780636aa99da3146104ac57600080fd5b806322163b86116102b55780633db2c7f21161028f5780633db2c7f214610422578063522f73861461043657806354d1f13d1461045657600080fd5b806322163b86146103ae57806325692962146103e65780632848caef146103ee57600080fd5b806308bfa2bf116102e657806308bfa2bf14610364578063153229bd1461037b578063159a76bd1461039b57600080fd5b806301ffc9a71461030257806303a6ccd014610337575b600080fd5b34801561030e57600080fd5b5061032261031d366004612419565b6108b8565b60405190151581526020015b60405180910390f35b34801561034357600080fd5b50610357610352366004612486565b6108e4565b60405161032e91906124bb565b34801561037057600080fd5b50610379610a2d565b005b34801561038757600080fd5b506103796103963660046125d4565b610ad6565b6103796103a9366004612665565b610b74565b3480156103ba57600080fd5b506001546103ce906001600160801b031681565b6040516001600160801b03909116815260200161032e565b610379610b90565b3480156103fa57600080fd5b5061040a67016345785d8a000081565b6040516001600160601b03909116815260200161032e565b34801561042e57600080fd5b506001610322565b34801561044257600080fd5b506103796104513660046126fd565b610be0565b610379610c75565b34801561046a57600080fd5b50610379610479366004612758565b610cb1565b34801561048a57600080fd5b5061049e610499366004612773565b610d6a565b60405190815260200161032e565b3480156104b857600080fd5b50600054600160a01b90046001600160601b03166103ce565b3480156104dd57600080fd5b506104e76103e881565b60405161ffff909116815260200161032e565b610379610db8565b34801561050e57600080fd5b5061037961051d3660046125d4565b610dcc565b34801561052e57600080fd5b50638b78c6d819545b6040516001600160a01b03909116815260200161032e565b34801561055b57600080fd5b5061037961056a3660046127b1565b610e88565b34801561057b57600080fd5b5061049e61058a366004612486565b610f1d565b34801561059b57600080fd5b506103ce6105aa3660046127b1565b6004602052600090815260409020546001600160801b031681565b3480156105d157600080fd5b506103796105e03660046127ce565b610f34565b3480156105f157600080fd5b5061037961060036600461283b565b611027565b610379610613366004612856565b6110cd565b34801561062457600080fd5b5061037961063336600461283b565b6112eb565b34801561064457600080fd5b50610322610653366004612943565b6113ad565b34801561066457600080fd5b506103ce6106733660046129bd565b61140d565b34801561068457600080fd5b50610379610693366004612a4f565b611593565b3480156106a457600080fd5b50604051636328e9ad60e01b815260200161032e565b3480156106c657600080fd5b5060025461040a906001600160601b031681565b3480156106e657600080fd5b506103226106f5366004612773565b61162b565b34801561070657600080fd5b5061071a6107153660046125d4565b611642565b604080519586526020860194909452928401919091526060830152608082015260a00161032e565b34801561074e57600080fd5b5061037961075d366004612a8d565b6116c4565b34801561076e57600080fd5b506040516202a300815260200161032e565b34801561078c57600080fd5b506104e761271081565b3480156107a257600080fd5b506103796107b1366004612a4f565b61177e565b3480156107c257600080fd5b5060015461040a90600160801b90046001600160601b031681565b3480156107e957600080fd5b506001546104e790600160e01b900461ffff1681565b34801561080b57600080fd5b50600054610537906001600160a01b031681565b61037961082d3660046127b1565b6117e1565b6103796108403660046127b1565b611821565b34801561085157600080fd5b506103796108603660046127b1565b611848565b34801561087157600080fd5b50610379610880366004612ac9565b6118fd565b34801561089157600080fd5b5061049e6108a03660046127b1565b63389a75e1600c908152600091909152602090205490565b60006108c38261197c565b806108de57506001600160e01b03198216636328e9ad60e01b145b92915050565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081018290526101808101829052906109578484611a18565b600081815260056020908152604091829020835463ffffffff600160801b80830482168952600160a01b830482169489019490945261ffff600160c01b830481169589019590955260ff600160d01b830416151560608901526001600160601b0380831660808a015260018085015480841660a08c0152600160601b909404831660c08b015264010000000090930490911660e08901529154610100880152938401546101208701529254600160e01b810490921661014086015290048116610160840152600254166101808301525092915050565b6000546001600160a01b031680610a57576040516362ccef3360e01b815260040160405180910390fd5b6001546001600160801b03168015610ad257600180546fffffffffffffffffffffffffffffffff19169055610a95826001600160801b038316611a86565b6040516001600160801b03821681527fa8a9aa21b43d916fdaf4bdf9975892e984e7dbe00c0befea632d6fe5bbead73a9060200160405180910390a15b5050565b82610ae081611ac6565b8160056000610af5610af28888611a18565b90565b81526020808201929092526040908101600020600101805463ffffffff191663ffffffff94851617905580516001600160801b0387168152928516918301919091526001600160a01b038616917f4c3c29668821111c3ddbcf87e1cd6047dc735ef691d46e09671629cb42cdd94891015b60405180910390a250505050565b610b888686338781888888366000806110cd565b505050505050565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b82610bea81611ac6565b81610bf58585611a18565b8054911515600160d01b027fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055604080516001600160801b038516815283151560208201526001600160a01b038616917fe430910c8e4bfa8180b70a0b2aa923b82d6712a1d165e223053ef439a3f861479101610b66565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b610cb9611c61565b6103e861ffff82161115610cf9576040517f3d1e858400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160e01b61ffff8416908102919091179091556040519081527f1426859b6b96e2e9ae302b23a42f763f4b0ae916a71a093e61c77120458b2e95906020015b60405180910390a150565b600060066000610d7d610af28787611a18565b81526020019081526020016000206000836001600160a01b03166001600160a01b031681526020019081526020016000205490509392505050565b610dc0611c61565b610dca6000611c7c565b565b82610dd681611ac6565b8163ffffffff16600003610dfd5760405163a017714560e01b815260040160405180910390fd5b81610e088585611a18565b80547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16600160601b63ffffffff93841602179055604080516001600160801b038616815291841660208301526001600160a01b038616917f021f3ca4d64a14574ed4fc7115d2c667604e54efb94b6187ed8117d49c6e47559101610b66565b610e90611c61565b6001600160a01b038116610eb7576040516362ccef3360e01b815260040160405180910390fd5b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527fda1940b15ab63ed4db791f1c7ec186c01a546f6ce58fa1dcc0561b8638a1bd1290602001610d5f565b6000610f298383611a18565b600101549392505050565b83610f3e81611ac6565b8163ffffffff168363ffffffff1610610f6a5760405163536a71af60e01b815260040160405180910390fd5b6000610f768686611a18565b80547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b63ffffffff87811691820263ffffffff60a01b191692909217600160a01b928716928302178355604080516001600160801b038a16815260208101929092528101919091529091506001600160a01b038716907f13bc03d97cc4e2accb3b8290af069c19619d32a4e9c5219f8580108766fb18fd9060600160405180910390a2505050505050565b61102f611c61565b67016345785d8a00006001600160601b038216111561107a576040517fe750044700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280546bffffffffffffffffffffffff19166001600160601b0383169081179091556040519081527fd294b805671973af1412f646018eacbaf3cab01934465d9623e12de8dd6acbc190602001610d5f565b60006110d98c8c611a18565b600081815260056020526040902060018101549192509061110c9063ffffffff64010000000082048116918d9116611cba565b60018201805463ffffffff929092166401000000000267ffffffff00000000199092169190911790556001600160a01b038916158061116657506111648888836000015461115f8d6000526014600c2090565b611d30565b155b1561119d576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336001600160a01b038a16148015906111c85750886001600160a01b03168b6001600160a01b031614155b1561120d576111d7338a611d6a565b61120d576040517ffe736e0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815460008381526006602090815260408083206001600160a01b038e1684529091529020805463ffffffff8d811690910191829055600160601b9092049091161015611285576040517f1b75136500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112958d8d8d8d8a8a8a8a611dac565b604080516001600160a01b038b16815263ffffffff8c1660208201527fbbce3c6646076fce6266a06486d114fd6f4fcdce3df843aadf9c56a2d89721a0910160405180910390a150505050505050505050505050565b6112f3611c61565b67016345785d8a00006001600160601b038216111561133e576040517f5d2be82000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff16600160801b6001600160601b038416908102919091179091556040519081527f267d27ed20a4d7ecba313e2039580b03e8c3d8018eeefe72709708735b02116490602001610d5f565b6000806113ba8787611a18565b600101549050806113d85750506001600160a01b0383161515611404565b6001600160a01b03851615801590611400575061140084848361115f896000526014600c2090565b9150505b95945050505050565b60008761142d5760405163b00db6fb60e01b815260040160405180910390fd5b8163ffffffff166000036114545760405163a017714560e01b815260040160405180910390fd5b611460898787876121b2565b6001600160a01b038a1660009081526003602090815260408083206001600160801b038516845290915281209192509080546001600160601b038a166fffffffffffffffffffffffffffffffff1990911617600160601b63ffffffff8616021781559050600060058183815260208082019290925260409081016000208c815560018101805463ffffffff191663ffffffff8a811691821790925583516001600160801b03891681529485018f90526001600160601b038e16938501939093528b811660608501528a8116608085015261ffff8a1660a085015260c084019290925290861660e083015291506001600160a01b038c16907fd9faafd9b789bcd20399f1fafa1c6459996ac840e9177ee687c23cdbe3b7a9cb906101000160405180910390a2505098975050505050505050565b8261159d81611ac6565b816115bb5760405163b00db6fb60e01b815260040160405180910390fd5b81600560006115cd610af28888611a18565b815260208082019290925260409081016000209290925581516001600160801b03861681529081018490526001600160a01b038616917fa863d0ab0f23accb1c42ee00c0587f1c94539e15956a678a54c1e710ba07066e9101610b66565b600061163a84848436856113ad565b949350505050565b6000806000806000806116558989611a18565b54600254600154600160801b81046001600160601b0390811663ffffffff9b909b169a8b0292811692909201918316999099028181019c909b50909950612710600160e01b90990461ffff9081168c028a90048b0199600160c01b909304168b02919091049650945050505050565b826116ce81611ac6565b6103e861ffff831611156116f557604051631a52ce6f60e01b815260040160405180910390fd5b816117008585611a18565b80547fffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b61ffff93841602179055604080516001600160801b038616815291841660208301526001600160a01b038616917fae6d744348a49699fcb91e6a563f2224c0fb27c21053a9218ee827f9d6e698c79101610b66565b8261178881611ac6565b816117938585611a18565b60010155604080516001600160801b0385168152602081018490526001600160a01b038616917f50beeb3db2bdaab85213836eb4be24fe53e830e8ee419c5859ea380e3b7102759101610b66565b6117e9611c61565b63389a75e1600c52806000526020600c20805442111561181157636f5e88186000526004601cfd5b6000905561181e81611c7c565b50565b611829611c61565b8060601b61183f57637448fbae6000526004601cfd5b61181e81611c7c565b6001600160a01b0381166000908152600460205260409020546001600160801b03168015610ad2576001600160a01b038216600090815260046020526040902080546fffffffffffffffffffffffffffffffff191690556118b2826001600160801b038316611a86565b6040516001600160801b03821681526001600160a01b038316907f0a1adaaf9d9caba9cf65528900e946b718d511ebd66ae81d5eb71e7fd0122c4a9060200160405180910390a25050565b8261190781611ac6565b816119128585611a18565b80546bffffffffffffffffffffffff19166001600160601b03928316179055604080516001600160801b038616815291841660208301526001600160a01b038616917f7c77af090cbae157811da55b6d8ae1e307a85f5aa1dd2f7a13183279a8c2b4b29101610b66565b60006001600160e01b031982167ff8ccd08e0000000000000000000000000000000000000000000000000000000014806119df57506001600160e01b031982167f09d98f1e00000000000000000000000000000000000000000000000000000000145b806108de57506001600160e01b031982167f01ffc9a7000000000000000000000000000000000000000000000000000000001492915050565b6001600160a01b03821660009081526003602090815260408083206001600160801b038516845290915290208054600160d81b900460ff166108de576040517f947dbacd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80471015611a9c5763b12d13eb6000526004601cfd5b6000806000808486620186a0f1610ad257816000526073600b5360ff6020536016600b82f0505050565b6000611ad061239b565b9050816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b349190612b05565b6001600160a01b0316816001600160a01b031614610ad257816001600160a01b031663514e62fc82846001600160a01b03166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bbe9190612b22565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa158015611c07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2b9190612b3b565b610ad2576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b638b78c6d819543314610dca576382b429006000526004601cfd5b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b600063ffffffff8481168185160190831681111561163a576000611cee8463ffffffff168763ffffffff1680821191030290565b6040517fbdc0f4ce00000000000000000000000000000000000000000000000000000000815263ffffffff821660048201529091506024015b60405180910390fd5b60008315611d62578360051b8501855b803580851160051b94855260209485185260406000209301818110611d405750505b501492915050565b6000604051639c395bc26000528360205282604052602060006044601c6d76a84fef008cdabe6409d2fe638b5afa600160005114169150806040525092915050565b6000611db88989611a18565b9050611dee6040518060a00160405280600015158152602001600081526020016000815260200160008152602001600081525090565b815463ffffffff600160801b8204811691600160a01b90041642821115611e3e5760405163296f4f6960e01b815242600482015263ffffffff808416602483015282166044820152606401611d27565b8063ffffffff16421115611e7b5760405163296f4f6960e01b815242600482015263ffffffff808416602483015282166044820152606401611d27565b8354600160d01b900460ff1615611ebe576040517fd7d248ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050611ecb8a8a89611642565b602086015260608501525050608082018190523414611f255760808101516040517f0dd32d1c0000000000000000000000000000000000000000000000000000000081523460048201526024810191909152604401611d27565b6060810151600154611f42916001600160801b03909116016123e1565b600180546fffffffffffffffffffffffffffffffff19166001600160801b039290921691909117905560608101516080820151036040820152611f888a8a8888886113ad565b1580158252612014576020808201516040808401805183900390526001600160a01b0389166000908152600490935290912054611fd0916001600160801b03909116016123e1565b6001600160a01b038716600090815260046020526040902080546fffffffffffffffffffffffffffffffff19166001600160801b039290921691909117905561205c565b600060208201526001600160a01b0386161561205c576040517f20d6c38900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408082015190517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b03808b166004830181905263ffffffff8b16602484015286939092918e16917f1c9d0475cac0f75d579d1156e780903d43532d6212c6890ce4f6f278770dc915918e9184916340c10f199160440160206040518083038185885af11580156120fa573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061211f9190612b22565b8c8760800151886060015189602001518f8b6000015160405161219e9897969594939291906001600160801b03988916815263ffffffff97881660208201529590961660408601529286166060850152908516608084015290931660a08201526001600160a01b039290921660c0830152151560e08201526101000190565b60405180910390a450505050505050505050565b6000846121be81611ac6565b8363ffffffff168563ffffffff16106121ea5760405163536a71af60e01b815260040160405180910390fd5b6103e861ffff8416111561221157604051631a52ce6f60e01b815260040160405180910390fd5b600080546001600160a01b0388168252600360209081526040808420600160a01b9093046001600160601b03168085529290915282209093508054600160d81b7fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff909116600160801b63ffffffff8a81169190910263ffffffff60a01b191691909117600160a01b91891691909102177fffffffff00ff0000ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b61ffff8816027fffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffff1617178155905061230b600184016001600160801b03166123fa565b600080546001600160601b0392909216600160a01b026001600160a01b03928316179055604080516001600160801b038616815263ffffffff898116602083015288169181019190915261ffff8616606082015233918916907feeb5941fb79bbfe40edd76c2e086e8ccdb0b463fc8ac07416266100b4dfddccf9060800160405180910390a35050949350505050565b336e2fd5aeb385d324b580fca7c838239f198101610af257602060008060006e2fd5aeb385d324b580fca7c83823a05afa6123d557600080fd5b506000513d6020140290565b6000600160801b82106123f6576123f661240b565b5090565b6000600160601b82106123f6576123f65b6335278d126000526004601cfd5b60006020828403121561242b57600080fd5b81356001600160e01b03198116811461244357600080fd5b9392505050565b6001600160a01b038116811461181e57600080fd5b803561246a8161244a565b919050565b80356001600160801b038116811461246a57600080fd5b6000806040838503121561249957600080fd5b82356124a48161244a565b91506124b26020840161246f565b90509250929050565b815163ffffffff1681526101a0810160208301516124e1602084018263ffffffff169052565b5060408301516124f7604084018261ffff169052565b50606083015161250b606084018215159052565b50608083015161252660808401826001600160601b03169052565b5060a083015161253e60a084018263ffffffff169052565b5060c083015161255660c084018263ffffffff169052565b5060e083015161256e60e084018263ffffffff169052565b50610100838101519083015261012080840151908301526101408084015161ffff1690830152610160808401516001600160601b03908116918401919091526101809384015116929091019190915290565b803563ffffffff8116811461246a57600080fd5b6000806000606084860312156125e957600080fd5b83356125f48161244a565b92506126026020850161246f565b9150612610604085016125c0565b90509250925092565b60008083601f84011261262b57600080fd5b50813567ffffffffffffffff81111561264357600080fd5b6020830191508360208260051b850101111561265e57600080fd5b9250929050565b60008060008060008060a0878903121561267e57600080fd5b86356126898161244a565b95506126976020880161246f565b94506126a5604088016125c0565b9350606087013567ffffffffffffffff8111156126c157600080fd5b6126cd89828a01612619565b90945092505060808701356126e18161244a565b809150509295509295509295565b801515811461181e57600080fd5b60008060006060848603121561271257600080fd5b833561271d8161244a565b925061272b6020850161246f565b9150604084013561273b816126ef565b809150509250925092565b803561ffff8116811461246a57600080fd5b60006020828403121561276a57600080fd5b61244382612746565b60008060006060848603121561278857600080fd5b83356127938161244a565b92506127a16020850161246f565b9150604084013561273b8161244a565b6000602082840312156127c357600080fd5b81356124438161244a565b600080600080608085870312156127e457600080fd5b84356127ef8161244a565b93506127fd6020860161246f565b925061280b604086016125c0565b9150612819606086016125c0565b905092959194509250565b80356001600160601b038116811461246a57600080fd5b60006020828403121561284d57600080fd5b61244382612824565b60008060008060008060008060008060006101208c8e03121561287857600080fd5b6128828c3561244a565b8b359a5061289260208d0161246f565b99506128a160408d013561244a565b60408c013598506128b460608d016125c0565b97506128c260808d0161245f565b965067ffffffffffffffff8060a08e013511156128de57600080fd5b6128ee8e60a08f01358f01612619565b90975095506128ff60c08e0161245f565b94508060e08e0135111561291257600080fd5b506129238d60e08e01358e01612619565b81945080935050506101008c013590509295989b509295989b9093969950565b60008060008060006080868803121561295b57600080fd5b85356129668161244a565b94506129746020870161246f565b935060408601356129848161244a565b9250606086013567ffffffffffffffff8111156129a057600080fd5b6129ac88828901612619565b969995985093965092949392505050565b600080600080600080600080610100898b0312156129da57600080fd5b88356129e58161244a565b9750602089013596506129fa60408a01612824565b9550612a0860608a016125c0565b9450612a1660808a016125c0565b9350612a2460a08a01612746565b9250612a3260c08a016125c0565b9150612a4060e08a016125c0565b90509295985092959890939650565b600080600060608486031215612a6457600080fd5b8335612a6f8161244a565b9250612a7d6020850161246f565b9150604084013590509250925092565b600080600060608486031215612aa257600080fd5b8335612aad8161244a565b9250612abb6020850161246f565b915061261060408501612746565b600080600060608486031215612ade57600080fd5b8335612ae98161244a565b9250612af76020850161246f565b915061261060408501612824565b600060208284031215612b1757600080fd5b81516124438161244a565b600060208284031215612b3457600080fd5b5051919050565b600060208284031215612b4d57600080fd5b8151612443816126ef56fea26469706673582212201617c2ca1f644c161a8d76b39215bf1a1d7b037af4be6758ce9a84dd3b155faf64736f6c63430008130033
Deployed Bytecode
0x6080604052600436106102fd5760003560e01c8063b0d659381161018f578063d7533f02116100e1578063f04e283e1161008a578063fb128c8311610064578063fb128c83146103ee578063fc63e69e14610865578063fee81cf41461088557600080fd5b8063f04e283e1461081f578063f2fde38b14610832578063f57402961461084557600080fd5b8063e71924f1116100bb578063e71924f1146107b6578063ebaaa3a1146107dd578063ed14834f146107ff57600080fd5b8063d7533f0214610762578063e1a4521814610780578063e37a0cea1461079657600080fd5b8063c3190a2e11610143578063c94dcf8f1161011d578063c94dcf8f146106da578063cbb35c21146106fa578063d73f3aab1461074257600080fd5b8063c3190a2e14610678578063c7dd322814610698578063c9238eae146106ba57600080fd5b8063be0c9b6c11610174578063be0c9b6c14610618578063bf013d7b14610638578063c309c47d1461065857600080fd5b8063b0d65938146105e5578063b24e737e1461060557600080fd5b80635cbc742c116102535780638d01513c116101fc57806398040f46116101d657806398040f461461056f578063ac1fc22c1461058f578063aec96b6e146105c557600080fd5b80638d01513c146104d15780638da5cb5b146105225780639375da5a1461054f57600080fd5b80636c5f55f71161022d5780636c5f55f7146104d1578063715018a6146104fa5780637614a7511461050257600080fd5b80635cbc742c1461045e57806365bd416d1461047e5780636aa99da3146104ac57600080fd5b806322163b86116102b55780633db2c7f21161028f5780633db2c7f214610422578063522f73861461043657806354d1f13d1461045657600080fd5b806322163b86146103ae57806325692962146103e65780632848caef146103ee57600080fd5b806308bfa2bf116102e657806308bfa2bf14610364578063153229bd1461037b578063159a76bd1461039b57600080fd5b806301ffc9a71461030257806303a6ccd014610337575b600080fd5b34801561030e57600080fd5b5061032261031d366004612419565b6108b8565b60405190151581526020015b60405180910390f35b34801561034357600080fd5b50610357610352366004612486565b6108e4565b60405161032e91906124bb565b34801561037057600080fd5b50610379610a2d565b005b34801561038757600080fd5b506103796103963660046125d4565b610ad6565b6103796103a9366004612665565b610b74565b3480156103ba57600080fd5b506001546103ce906001600160801b031681565b6040516001600160801b03909116815260200161032e565b610379610b90565b3480156103fa57600080fd5b5061040a67016345785d8a000081565b6040516001600160601b03909116815260200161032e565b34801561042e57600080fd5b506001610322565b34801561044257600080fd5b506103796104513660046126fd565b610be0565b610379610c75565b34801561046a57600080fd5b50610379610479366004612758565b610cb1565b34801561048a57600080fd5b5061049e610499366004612773565b610d6a565b60405190815260200161032e565b3480156104b857600080fd5b50600054600160a01b90046001600160601b03166103ce565b3480156104dd57600080fd5b506104e76103e881565b60405161ffff909116815260200161032e565b610379610db8565b34801561050e57600080fd5b5061037961051d3660046125d4565b610dcc565b34801561052e57600080fd5b50638b78c6d819545b6040516001600160a01b03909116815260200161032e565b34801561055b57600080fd5b5061037961056a3660046127b1565b610e88565b34801561057b57600080fd5b5061049e61058a366004612486565b610f1d565b34801561059b57600080fd5b506103ce6105aa3660046127b1565b6004602052600090815260409020546001600160801b031681565b3480156105d157600080fd5b506103796105e03660046127ce565b610f34565b3480156105f157600080fd5b5061037961060036600461283b565b611027565b610379610613366004612856565b6110cd565b34801561062457600080fd5b5061037961063336600461283b565b6112eb565b34801561064457600080fd5b50610322610653366004612943565b6113ad565b34801561066457600080fd5b506103ce6106733660046129bd565b61140d565b34801561068457600080fd5b50610379610693366004612a4f565b611593565b3480156106a457600080fd5b50604051636328e9ad60e01b815260200161032e565b3480156106c657600080fd5b5060025461040a906001600160601b031681565b3480156106e657600080fd5b506103226106f5366004612773565b61162b565b34801561070657600080fd5b5061071a6107153660046125d4565b611642565b604080519586526020860194909452928401919091526060830152608082015260a00161032e565b34801561074e57600080fd5b5061037961075d366004612a8d565b6116c4565b34801561076e57600080fd5b506040516202a300815260200161032e565b34801561078c57600080fd5b506104e761271081565b3480156107a257600080fd5b506103796107b1366004612a4f565b61177e565b3480156107c257600080fd5b5060015461040a90600160801b90046001600160601b031681565b3480156107e957600080fd5b506001546104e790600160e01b900461ffff1681565b34801561080b57600080fd5b50600054610537906001600160a01b031681565b61037961082d3660046127b1565b6117e1565b6103796108403660046127b1565b611821565b34801561085157600080fd5b506103796108603660046127b1565b611848565b34801561087157600080fd5b50610379610880366004612ac9565b6118fd565b34801561089157600080fd5b5061049e6108a03660046127b1565b63389a75e1600c908152600091909152602090205490565b60006108c38261197c565b806108de57506001600160e01b03198216636328e9ad60e01b145b92915050565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081018290526101808101829052906109578484611a18565b600081815260056020908152604091829020835463ffffffff600160801b80830482168952600160a01b830482169489019490945261ffff600160c01b830481169589019590955260ff600160d01b830416151560608901526001600160601b0380831660808a015260018085015480841660a08c0152600160601b909404831660c08b015264010000000090930490911660e08901529154610100880152938401546101208701529254600160e01b810490921661014086015290048116610160840152600254166101808301525092915050565b6000546001600160a01b031680610a57576040516362ccef3360e01b815260040160405180910390fd5b6001546001600160801b03168015610ad257600180546fffffffffffffffffffffffffffffffff19169055610a95826001600160801b038316611a86565b6040516001600160801b03821681527fa8a9aa21b43d916fdaf4bdf9975892e984e7dbe00c0befea632d6fe5bbead73a9060200160405180910390a15b5050565b82610ae081611ac6565b8160056000610af5610af28888611a18565b90565b81526020808201929092526040908101600020600101805463ffffffff191663ffffffff94851617905580516001600160801b0387168152928516918301919091526001600160a01b038616917f4c3c29668821111c3ddbcf87e1cd6047dc735ef691d46e09671629cb42cdd94891015b60405180910390a250505050565b610b888686338781888888366000806110cd565b505050505050565b60006202a30067ffffffffffffffff164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b82610bea81611ac6565b81610bf58585611a18565b8054911515600160d01b027fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff909216919091179055604080516001600160801b038516815283151560208201526001600160a01b038616917fe430910c8e4bfa8180b70a0b2aa923b82d6712a1d165e223053ef439a3f861479101610b66565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b610cb9611c61565b6103e861ffff82161115610cf9576040517f3d1e858400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffff0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff16600160e01b61ffff8416908102919091179091556040519081527f1426859b6b96e2e9ae302b23a42f763f4b0ae916a71a093e61c77120458b2e95906020015b60405180910390a150565b600060066000610d7d610af28787611a18565b81526020019081526020016000206000836001600160a01b03166001600160a01b031681526020019081526020016000205490509392505050565b610dc0611c61565b610dca6000611c7c565b565b82610dd681611ac6565b8163ffffffff16600003610dfd5760405163a017714560e01b815260040160405180910390fd5b81610e088585611a18565b80547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff16600160601b63ffffffff93841602179055604080516001600160801b038616815291841660208301526001600160a01b038616917f021f3ca4d64a14574ed4fc7115d2c667604e54efb94b6187ed8117d49c6e47559101610b66565b610e90611c61565b6001600160a01b038116610eb7576040516362ccef3360e01b815260040160405180910390fd5b600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383169081179091556040519081527fda1940b15ab63ed4db791f1c7ec186c01a546f6ce58fa1dcc0561b8638a1bd1290602001610d5f565b6000610f298383611a18565b600101549392505050565b83610f3e81611ac6565b8163ffffffff168363ffffffff1610610f6a5760405163536a71af60e01b815260040160405180910390fd5b6000610f768686611a18565b80547fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff16600160801b63ffffffff87811691820263ffffffff60a01b191692909217600160a01b928716928302178355604080516001600160801b038a16815260208101929092528101919091529091506001600160a01b038716907f13bc03d97cc4e2accb3b8290af069c19619d32a4e9c5219f8580108766fb18fd9060600160405180910390a2505050505050565b61102f611c61565b67016345785d8a00006001600160601b038216111561107a576040517fe750044700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280546bffffffffffffffffffffffff19166001600160601b0383169081179091556040519081527fd294b805671973af1412f646018eacbaf3cab01934465d9623e12de8dd6acbc190602001610d5f565b60006110d98c8c611a18565b600081815260056020526040902060018101549192509061110c9063ffffffff64010000000082048116918d9116611cba565b60018201805463ffffffff929092166401000000000267ffffffff00000000199092169190911790556001600160a01b038916158061116657506111648888836000015461115f8d6000526014600c2090565b611d30565b155b1561119d576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336001600160a01b038a16148015906111c85750886001600160a01b03168b6001600160a01b031614155b1561120d576111d7338a611d6a565b61120d576040517ffe736e0100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815460008381526006602090815260408083206001600160a01b038e1684529091529020805463ffffffff8d811690910191829055600160601b9092049091161015611285576040517f1b75136500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6112958d8d8d8d8a8a8a8a611dac565b604080516001600160a01b038b16815263ffffffff8c1660208201527fbbce3c6646076fce6266a06486d114fd6f4fcdce3df843aadf9c56a2d89721a0910160405180910390a150505050505050505050505050565b6112f3611c61565b67016345785d8a00006001600160601b038216111561133e576040517f5d2be82000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff16600160801b6001600160601b038416908102919091179091556040519081527f267d27ed20a4d7ecba313e2039580b03e8c3d8018eeefe72709708735b02116490602001610d5f565b6000806113ba8787611a18565b600101549050806113d85750506001600160a01b0383161515611404565b6001600160a01b03851615801590611400575061140084848361115f896000526014600c2090565b9150505b95945050505050565b60008761142d5760405163b00db6fb60e01b815260040160405180910390fd5b8163ffffffff166000036114545760405163a017714560e01b815260040160405180910390fd5b611460898787876121b2565b6001600160a01b038a1660009081526003602090815260408083206001600160801b038516845290915281209192509080546001600160601b038a166fffffffffffffffffffffffffffffffff1990911617600160601b63ffffffff8616021781559050600060058183815260208082019290925260409081016000208c815560018101805463ffffffff191663ffffffff8a811691821790925583516001600160801b03891681529485018f90526001600160601b038e16938501939093528b811660608501528a8116608085015261ffff8a1660a085015260c084019290925290861660e083015291506001600160a01b038c16907fd9faafd9b789bcd20399f1fafa1c6459996ac840e9177ee687c23cdbe3b7a9cb906101000160405180910390a2505098975050505050505050565b8261159d81611ac6565b816115bb5760405163b00db6fb60e01b815260040160405180910390fd5b81600560006115cd610af28888611a18565b815260208082019290925260409081016000209290925581516001600160801b03861681529081018490526001600160a01b038616917fa863d0ab0f23accb1c42ee00c0587f1c94539e15956a678a54c1e710ba07066e9101610b66565b600061163a84848436856113ad565b949350505050565b6000806000806000806116558989611a18565b54600254600154600160801b81046001600160601b0390811663ffffffff9b909b169a8b0292811692909201918316999099028181019c909b50909950612710600160e01b90990461ffff9081168c028a90048b0199600160c01b909304168b02919091049650945050505050565b826116ce81611ac6565b6103e861ffff831611156116f557604051631a52ce6f60e01b815260040160405180910390fd5b816117008585611a18565b80547fffffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b61ffff93841602179055604080516001600160801b038616815291841660208301526001600160a01b038616917fae6d744348a49699fcb91e6a563f2224c0fb27c21053a9218ee827f9d6e698c79101610b66565b8261178881611ac6565b816117938585611a18565b60010155604080516001600160801b0385168152602081018490526001600160a01b038616917f50beeb3db2bdaab85213836eb4be24fe53e830e8ee419c5859ea380e3b7102759101610b66565b6117e9611c61565b63389a75e1600c52806000526020600c20805442111561181157636f5e88186000526004601cfd5b6000905561181e81611c7c565b50565b611829611c61565b8060601b61183f57637448fbae6000526004601cfd5b61181e81611c7c565b6001600160a01b0381166000908152600460205260409020546001600160801b03168015610ad2576001600160a01b038216600090815260046020526040902080546fffffffffffffffffffffffffffffffff191690556118b2826001600160801b038316611a86565b6040516001600160801b03821681526001600160a01b038316907f0a1adaaf9d9caba9cf65528900e946b718d511ebd66ae81d5eb71e7fd0122c4a9060200160405180910390a25050565b8261190781611ac6565b816119128585611a18565b80546bffffffffffffffffffffffff19166001600160601b03928316179055604080516001600160801b038616815291841660208301526001600160a01b038616917f7c77af090cbae157811da55b6d8ae1e307a85f5aa1dd2f7a13183279a8c2b4b29101610b66565b60006001600160e01b031982167ff8ccd08e0000000000000000000000000000000000000000000000000000000014806119df57506001600160e01b031982167f09d98f1e00000000000000000000000000000000000000000000000000000000145b806108de57506001600160e01b031982167f01ffc9a7000000000000000000000000000000000000000000000000000000001492915050565b6001600160a01b03821660009081526003602090815260408083206001600160801b038516845290915290208054600160d81b900460ff166108de576040517f947dbacd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80471015611a9c5763b12d13eb6000526004601cfd5b6000806000808486620186a0f1610ad257816000526073600b5360ff6020536016600b82f0505050565b6000611ad061239b565b9050816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b349190612b05565b6001600160a01b0316816001600160a01b031614610ad257816001600160a01b031663514e62fc82846001600160a01b03166375b238fc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bbe9190612b22565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401602060405180830381865afa158015611c07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c2b9190612b3b565b610ad2576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b638b78c6d819543314610dca576382b429006000526004601cfd5b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b600063ffffffff8481168185160190831681111561163a576000611cee8463ffffffff168763ffffffff1680821191030290565b6040517fbdc0f4ce00000000000000000000000000000000000000000000000000000000815263ffffffff821660048201529091506024015b60405180910390fd5b60008315611d62578360051b8501855b803580851160051b94855260209485185260406000209301818110611d405750505b501492915050565b6000604051639c395bc26000528360205282604052602060006044601c6d76a84fef008cdabe6409d2fe638b5afa600160005114169150806040525092915050565b6000611db88989611a18565b9050611dee6040518060a00160405280600015158152602001600081526020016000815260200160008152602001600081525090565b815463ffffffff600160801b8204811691600160a01b90041642821115611e3e5760405163296f4f6960e01b815242600482015263ffffffff808416602483015282166044820152606401611d27565b8063ffffffff16421115611e7b5760405163296f4f6960e01b815242600482015263ffffffff808416602483015282166044820152606401611d27565b8354600160d01b900460ff1615611ebe576040517fd7d248ba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050611ecb8a8a89611642565b602086015260608501525050608082018190523414611f255760808101516040517f0dd32d1c0000000000000000000000000000000000000000000000000000000081523460048201526024810191909152604401611d27565b6060810151600154611f42916001600160801b03909116016123e1565b600180546fffffffffffffffffffffffffffffffff19166001600160801b039290921691909117905560608101516080820151036040820152611f888a8a8888886113ad565b1580158252612014576020808201516040808401805183900390526001600160a01b0389166000908152600490935290912054611fd0916001600160801b03909116016123e1565b6001600160a01b038716600090815260046020526040902080546fffffffffffffffffffffffffffffffff19166001600160801b039290921691909117905561205c565b600060208201526001600160a01b0386161561205c576040517f20d6c38900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408082015190517f40c10f190000000000000000000000000000000000000000000000000000000081526001600160a01b03808b166004830181905263ffffffff8b16602484015286939092918e16917f1c9d0475cac0f75d579d1156e780903d43532d6212c6890ce4f6f278770dc915918e9184916340c10f199160440160206040518083038185885af11580156120fa573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019061211f9190612b22565b8c8760800151886060015189602001518f8b6000015160405161219e9897969594939291906001600160801b03988916815263ffffffff97881660208201529590961660408601529286166060850152908516608084015290931660a08201526001600160a01b039290921660c0830152151560e08201526101000190565b60405180910390a450505050505050505050565b6000846121be81611ac6565b8363ffffffff168563ffffffff16106121ea5760405163536a71af60e01b815260040160405180910390fd5b6103e861ffff8416111561221157604051631a52ce6f60e01b815260040160405180910390fd5b600080546001600160a01b0388168252600360209081526040808420600160a01b9093046001600160601b03168085529290915282209093508054600160d81b7fffffffffffffffff0000000000000000ffffffffffffffffffffffffffffffff909116600160801b63ffffffff8a81169190910263ffffffff60a01b191691909117600160a01b91891691909102177fffffffff00ff0000ffffffffffffffffffffffffffffffffffffffffffffffff16600160c01b61ffff8816027fffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffff1617178155905061230b600184016001600160801b03166123fa565b600080546001600160601b0392909216600160a01b026001600160a01b03928316179055604080516001600160801b038616815263ffffffff898116602083015288169181019190915261ffff8616606082015233918916907feeb5941fb79bbfe40edd76c2e086e8ccdb0b463fc8ac07416266100b4dfddccf9060800160405180910390a35050949350505050565b336e2fd5aeb385d324b580fca7c838239f198101610af257602060008060006e2fd5aeb385d324b580fca7c83823a05afa6123d557600080fd5b506000513d6020140290565b6000600160801b82106123f6576123f661240b565b5090565b6000600160601b82106123f6576123f65b6335278d126000526004601cfd5b60006020828403121561242b57600080fd5b81356001600160e01b03198116811461244357600080fd5b9392505050565b6001600160a01b038116811461181e57600080fd5b803561246a8161244a565b919050565b80356001600160801b038116811461246a57600080fd5b6000806040838503121561249957600080fd5b82356124a48161244a565b91506124b26020840161246f565b90509250929050565b815163ffffffff1681526101a0810160208301516124e1602084018263ffffffff169052565b5060408301516124f7604084018261ffff169052565b50606083015161250b606084018215159052565b50608083015161252660808401826001600160601b03169052565b5060a083015161253e60a084018263ffffffff169052565b5060c083015161255660c084018263ffffffff169052565b5060e083015161256e60e084018263ffffffff169052565b50610100838101519083015261012080840151908301526101408084015161ffff1690830152610160808401516001600160601b03908116918401919091526101809384015116929091019190915290565b803563ffffffff8116811461246a57600080fd5b6000806000606084860312156125e957600080fd5b83356125f48161244a565b92506126026020850161246f565b9150612610604085016125c0565b90509250925092565b60008083601f84011261262b57600080fd5b50813567ffffffffffffffff81111561264357600080fd5b6020830191508360208260051b850101111561265e57600080fd5b9250929050565b60008060008060008060a0878903121561267e57600080fd5b86356126898161244a565b95506126976020880161246f565b94506126a5604088016125c0565b9350606087013567ffffffffffffffff8111156126c157600080fd5b6126cd89828a01612619565b90945092505060808701356126e18161244a565b809150509295509295509295565b801515811461181e57600080fd5b60008060006060848603121561271257600080fd5b833561271d8161244a565b925061272b6020850161246f565b9150604084013561273b816126ef565b809150509250925092565b803561ffff8116811461246a57600080fd5b60006020828403121561276a57600080fd5b61244382612746565b60008060006060848603121561278857600080fd5b83356127938161244a565b92506127a16020850161246f565b9150604084013561273b8161244a565b6000602082840312156127c357600080fd5b81356124438161244a565b600080600080608085870312156127e457600080fd5b84356127ef8161244a565b93506127fd6020860161246f565b925061280b604086016125c0565b9150612819606086016125c0565b905092959194509250565b80356001600160601b038116811461246a57600080fd5b60006020828403121561284d57600080fd5b61244382612824565b60008060008060008060008060008060006101208c8e03121561287857600080fd5b6128828c3561244a565b8b359a5061289260208d0161246f565b99506128a160408d013561244a565b60408c013598506128b460608d016125c0565b97506128c260808d0161245f565b965067ffffffffffffffff8060a08e013511156128de57600080fd5b6128ee8e60a08f01358f01612619565b90975095506128ff60c08e0161245f565b94508060e08e0135111561291257600080fd5b506129238d60e08e01358e01612619565b81945080935050506101008c013590509295989b509295989b9093969950565b60008060008060006080868803121561295b57600080fd5b85356129668161244a565b94506129746020870161246f565b935060408601356129848161244a565b9250606086013567ffffffffffffffff8111156129a057600080fd5b6129ac88828901612619565b969995985093965092949392505050565b600080600080600080600080610100898b0312156129da57600080fd5b88356129e58161244a565b9750602089013596506129fa60408a01612824565b9550612a0860608a016125c0565b9450612a1660808a016125c0565b9350612a2460a08a01612746565b9250612a3260c08a016125c0565b9150612a4060e08a016125c0565b90509295985092959890939650565b600080600060608486031215612a6457600080fd5b8335612a6f8161244a565b9250612a7d6020850161246f565b9150604084013590509250925092565b600080600060608486031215612aa257600080fd5b8335612aad8161244a565b9250612abb6020850161246f565b915061261060408501612746565b600080600060608486031215612ade57600080fd5b8335612ae98161244a565b9250612af76020850161246f565b915061261060408501612824565b600060208284031215612b1757600080fd5b81516124438161244a565b600060208284031215612b3457600080fd5b5051919050565b600060208284031215612b4d57600080fd5b8151612443816126ef56fea26469706673582212201617c2ca1f644c161a8d76b39215bf1a1d7b037af4be6758ce9a84dd3b155faf64736f6c63430008130033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $2,950.14 | 0.1826 | $538.61 |
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.