Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
18883312 | 383 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
SoundEditionV2_1
Compiler Version
v0.8.19+commit.7dd6d404
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import { IERC721AUpgradeable } from "chiru-labs/ERC721A-Upgradeable/IERC721AUpgradeable.sol"; import { ERC721AUpgradeable, ERC721AStorage } from "chiru-labs/ERC721A-Upgradeable/ERC721AUpgradeable.sol"; import { ERC721AQueryableUpgradeable } from "chiru-labs/ERC721A-Upgradeable/extensions/ERC721AQueryableUpgradeable.sol"; import { ERC721ABurnableUpgradeable } from "chiru-labs/ERC721A-Upgradeable/extensions/ERC721ABurnableUpgradeable.sol"; import { IERC2981Upgradeable } from "openzeppelin-upgradeable/interfaces/IERC2981Upgradeable.sol"; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { OwnableRoles } from "solady/auth/OwnableRoles.sol"; import { LibString } from "solady/utils/LibString.sol"; import { LibMap } from "solady/utils/LibMap.sol"; import { LibMulticaller } from "multicaller/LibMulticaller.sol"; import { ISoundEditionV2_1 } from "./interfaces/ISoundEditionV2_1.sol"; import { IMetadataModule } from "./interfaces/IMetadataModule.sol"; import { LibOps } from "./utils/LibOps.sol"; import { ArweaveURILib } from "./utils/ArweaveURILib.sol"; import { MintRandomnessLib } from "./utils/MintRandomnessLib.sol"; /** * @title SoundEditionV2_1 * @notice The Sound Edition contract - a creator-owned, modifiable implementation of ERC721A. */ contract SoundEditionV2_1 is ISoundEditionV2_1, ERC721AQueryableUpgradeable, ERC721ABurnableUpgradeable, OwnableRoles { using ArweaveURILib for ArweaveURILib.URI; using LibMap for *; // ============================================================= // STRUCTS // ============================================================= /** * @dev A struct containing the tier data in storage. */ struct TierData { // The current mint randomness state. uint64 mintRandomness; // The lower bound of the maximum number of tokens that can be minted for the tier. uint32 maxMintableLower; // The upper bound of the maximum number of tokens that can be minted for the tier. uint32 maxMintableUpper; // The timestamp (in seconds since unix epoch) after which the // max amount of tokens mintable for the tier will drop from // `maxMintableUpper` to `maxMintableLower`. uint32 cutoffTime; // The total number of tokens minted for the tier. uint32 minted; // The offset to the next tier data in the linked list. uint8 next; // Packed boolean flags. uint8 flags; } // ============================================================= // CONSTANTS // ============================================================= /** * @dev The GA tier. Which is 0. */ uint8 public constant GA_TIER = 0; /** * @dev A role every minter module must have in order to mint new tokens. * Note: this constant will always be 2 for past and future sound protocol contracts. */ uint256 public constant MINTER_ROLE = LibOps.MINTER_ROLE; /** * @dev A role the owner can grant for performing admin actions. * Note: this constant will always be 1 for past and future sound protocol contracts. */ uint256 public constant ADMIN_ROLE = LibOps.ADMIN_ROLE; /** * @dev Basis points denominator used in fee calculations. */ uint16 public constant BPS_DENOMINATOR = LibOps.BPS_DENOMINATOR; /** * @dev For making the the interface ID different. */ bool public constant V2_1 = true; /** * @dev The interface ID for EIP-2981 (royaltyInfo) */ bytes4 private constant _INTERFACE_ID_ERC2981 = 0x2a55205a; /** * @dev The interface ID for SoundEditionV2. */ bytes4 private constant _INTERFACE_ID_SOUND_EDITION_V2 = 0x7888cfe1; /** * @dev The boolean flag on whether the metadata is frozen. */ uint8 private constant _METADATA_IS_FROZEN_FLAG = 1 << 0; /** * @dev The boolean flag on whether the ability to create a new tier is frozen. */ uint8 private constant _CREATE_TIER_IS_FROZEN_FLAG = 1 << 1; /** * @dev The boolean flag on whether the tier has been created. */ uint8 private constant _TIER_CREATED_FLAG = 1 << 0; /** * @dev The boolean flag on whether the tier has mint randomness enabled. */ uint8 private constant _TIER_MINT_RANDOMNESS_ENABLED_FLAG = 1 << 1; /** * @dev The boolean flag on whether the tier is frozen. */ uint8 private constant _TIER_IS_FROZEN_FLAG = 1 << 2; // ============================================================= // STORAGE // ============================================================= /** * @dev The value for `name` and `symbol` if their combined * length is (32 - 2) bytes. We need 2 bytes for their lengths. */ bytes32 private _shortNameAndSymbol; /** * @dev The metadata's base URI. */ ArweaveURILib.URI private _baseURIStorage; /** * @dev The contract base URI. */ ArweaveURILib.URI private _contractURIStorage; /** * @dev The destination for ETH withdrawals. */ address public fundingRecipient; /** * @dev The royalty fee in basis points. */ uint16 public royaltyBPS; /** * @dev Packed boolean flags. */ uint8 private _flags; /** * @dev Metadata module used for `tokenURI` and `contractURI` if it is set. */ address public metadataModule; /** * @dev The total number of tiers. */ uint16 private _numTiers; /** * @dev The head of the tier data linked list. */ uint8 private _tierDataHead; /** * @dev A mapping of `tier` => `tierData`. */ mapping(uint256 => TierData) private _tierData; /** * @dev A packed mapping `tokenId` => `tier`. */ LibMap.Uint8Map private _tokenTiers; /** * @dev A packed mapping of `tier` => `index` => `tokenId`. */ mapping(uint256 => LibMap.Uint32Map) private _tierTokenIds; // ============================================================= // PUBLIC / EXTERNAL WRITE FUNCTIONS // ============================================================= /** * @inheritdoc ISoundEditionV2_1 */ function initialize(EditionInitialization memory init) public { // Will revert upon double initialization. _initializeERC721A(init.name, init.symbol); _initializeOwner(LibMulticaller.senderOrSigner()); _validateRoyaltyBPS(init.royaltyBPS); _validateFundingRecipient(init.fundingRecipient); _baseURIStorage.initialize(init.baseURI); _contractURIStorage.initialize(init.contractURI); fundingRecipient = init.fundingRecipient; unchecked { uint256 n = init.tierCreations.length; if (n == 0) revert ZeroTiersProvided(); for (uint256 i; i != n; ++i) { _createTier(init.tierCreations[i]); } } metadataModule = init.metadataModule; royaltyBPS = init.royaltyBPS; _flags = LibOps.toFlag(init.isMetadataFrozen, _METADATA_IS_FROZEN_FLAG) | LibOps.toFlag(init.isCreateTierFrozen, _CREATE_TIER_IS_FROZEN_FLAG); emit SoundEditionInitialized(init); } /** * @inheritdoc ISoundEditionV2_1 */ function mint( uint8 tier, address to, uint256 quantity ) external payable onlyRolesOrOwner(ADMIN_ROLE | MINTER_ROLE) returns (uint256 fromTokenId) { (fromTokenId, ) = _beforeTieredMint(tier, quantity); _batchMint(to, quantity); emit Minted(tier, to, quantity, fromTokenId); } /** * @inheritdoc ISoundEditionV2_1 */ function airdrop( uint8 tier, address[] calldata to, uint256 quantity ) external payable onlyRolesOrOwner(ADMIN_ROLE | MINTER_ROLE) returns (uint256 fromTokenId) { unchecked { // Multiplication overflow is not possible due to the max block gas limit. // If `quantity` is too big (e.g. 2**64), the loop in `_batchMint` will run out of gas. // If `to.length` is too big (e.g. 2**64), the airdrop mint loop will run out of gas. (fromTokenId, ) = _beforeTieredMint(tier, to.length * quantity); for (uint256 i; i != to.length; ++i) { _batchMint(to[i], quantity); } } emit Airdropped(tier, to, quantity, fromTokenId); } /** * @inheritdoc ISoundEditionV2_1 */ function withdrawETH() external { uint256 amount = address(this).balance; address recipient = fundingRecipient; SafeTransferLib.forceSafeTransferETH(recipient, amount); emit ETHWithdrawn(recipient, amount, msg.sender); } /** * @inheritdoc ISoundEditionV2_1 */ function withdrawERC20(address[] calldata tokens) external { unchecked { uint256[] memory amounts = new uint256[](tokens.length); address recipient = fundingRecipient; for (uint256 i; i != tokens.length; ++i) { amounts[i] = SafeTransferLib.safeTransferAll(tokens[i], recipient); } emit ERC20Withdrawn(recipient, tokens, amounts, msg.sender); } } /** * @inheritdoc ISoundEditionV2_1 */ function setMetadataModule(address module) external onlyRolesOrOwner(ADMIN_ROLE) { _requireMetadataNotFrozen(); metadataModule = module; emit MetadataModuleSet(module); emitAllMetadataUpdate(); } /** * @inheritdoc ISoundEditionV2_1 */ function setBaseURI(string memory uri) external onlyRolesOrOwner(ADMIN_ROLE) { _requireMetadataNotFrozen(); _baseURIStorage.update(uri); emit BaseURISet(uri); emitAllMetadataUpdate(); } /** * @inheritdoc ISoundEditionV2_1 */ function setContractURI(string memory uri) public onlyRolesOrOwner(ADMIN_ROLE) { _requireMetadataNotFrozen(); _contractURIStorage.update(uri); emit ContractURISet(uri); } /** * @inheritdoc ISoundEditionV2_1 */ function freezeMetadata() public onlyRolesOrOwner(ADMIN_ROLE) { _requireMetadataNotFrozen(); _flags |= _METADATA_IS_FROZEN_FLAG; emit MetadataFrozen(metadataModule, baseURI(), contractURI()); } /** * @inheritdoc ISoundEditionV2_1 */ function freezeCreateTier() public onlyRolesOrOwner(ADMIN_ROLE) { _requireCreateTierNotFrozen(); _flags |= _CREATE_TIER_IS_FROZEN_FLAG; emit CreateTierFrozen(); } /** * @inheritdoc ISoundEditionV2_1 */ function setFundingRecipient(address recipient) public onlyRolesOrOwner(ADMIN_ROLE) { _setFundingRecipient(recipient); } /** * @inheritdoc ISoundEditionV2_1 */ function createSplit(address splitMain, bytes calldata splitData) public onlyRolesOrOwner(ADMIN_ROLE) returns (address split) { assembly { // Grab the free memory pointer. let m := mload(0x40) // Copy the `splitData` into the free memory. calldatacopy(m, splitData.offset, splitData.length) // Zeroize 0x00, so that if the call doesn't return anything, `split` will be the zero address. mstore(0x00, 0) // Call the `splitMain`, reverting if the call fails. if iszero( call( gas(), // Gas remaining. splitMain, // Address of the SplitMain. 0, // Send 0 ETH. m, // Start of the `splitData` in memory. splitData.length, // Length of `splitData`. 0x00, // Start of returndata. 0x20 // Length of returndata. ) ) { // Bubble up the revert if the call reverts. returndatacopy(0x00, 0x00, returndatasize()) revert(0x00, returndatasize()) } split := mload(0x00) } _setFundingRecipient(split); } /** * @inheritdoc ISoundEditionV2_1 */ function setRoyalty(uint16 bps) public onlyRolesOrOwner(ADMIN_ROLE) { _validateRoyaltyBPS(bps); royaltyBPS = bps; emit RoyaltySet(bps); } /** * @inheritdoc ISoundEditionV2_1 */ function setMaxMintableRange( uint8 tier, uint32 lower, uint32 upper ) public onlyRolesOrOwner(ADMIN_ROLE) { TierData storage d = _getTierData(tier); _requireNotFrozen(d); _requireBeforeMintConcluded(d); uint256 minted = d.minted; if (minted != 0) { // Disallow increasing either lower or upper. if (LibOps.or(lower > d.maxMintableLower, upper > d.maxMintableUpper)) revert InvalidMaxMintableRange(); // If either is below `minted`, set to `minted`. lower = uint32(LibOps.max(lower, minted)); upper = uint32(LibOps.max(upper, minted)); } if (lower > upper) revert InvalidMaxMintableRange(); d.maxMintableLower = lower; d.maxMintableUpper = upper; emit MaxMintableRangeSet(tier, lower, upper); } /** * @inheritdoc ISoundEditionV2_1 */ function freezeTier(uint8 tier) public onlyRolesOrOwner(ADMIN_ROLE) { TierData storage d = _getTierData(tier); _requireNotFrozen(d); d.flags |= _TIER_IS_FROZEN_FLAG; emit TierFrozen(tier); } /** * @inheritdoc ISoundEditionV2_1 */ function setCutoffTime(uint8 tier, uint32 cutoff) public onlyRolesOrOwner(ADMIN_ROLE) { TierData storage d = _getTierData(tier); _requireNotFrozen(d); _requireBeforeMintConcluded(d); d.cutoffTime = cutoff; emit CutoffTimeSet(tier, cutoff); } /** * @inheritdoc ISoundEditionV2_1 */ function createTier(TierCreation memory creation) public onlyRolesOrOwner(ADMIN_ROLE) { _requireCreateTierNotFrozen(); _createTier(creation); emit TierCreated(creation); } /** * @inheritdoc ISoundEditionV2_1 */ function setMintRandomnessEnabled(uint8 tier, bool enabled) public onlyRolesOrOwner(ADMIN_ROLE) { TierData storage d = _getTierData(tier); _requireNotFrozen(d); _requireNoTierMints(d); d.flags = LibOps.setFlagTo(d.flags, _TIER_MINT_RANDOMNESS_ENABLED_FLAG, enabled); emit MintRandomnessEnabledSet(tier, enabled); } /** * @inheritdoc ISoundEditionV2_1 */ function emitAllMetadataUpdate() public { emit BatchMetadataUpdate(_startTokenId(), _nextTokenId() - 1); } // ============================================================= // PUBLIC / EXTERNAL VIEW FUNCTIONS // ============================================================= /** * @inheritdoc ISoundEditionV2_1 */ function editionInfo() public view returns (EditionInfo memory info) { info.baseURI = baseURI(); info.contractURI = contractURI(); (info.name, info.symbol) = _loadNameAndSymbol(); info.fundingRecipient = fundingRecipient; info.metadataModule = metadataModule; info.isMetadataFrozen = isMetadataFrozen(); info.isCreateTierFrozen = isCreateTierFrozen(); info.royaltyBPS = royaltyBPS; info.nextTokenId = nextTokenId(); info.totalMinted = totalMinted(); info.totalBurned = totalBurned(); info.totalSupply = totalSupply(); unchecked { uint256 n = _numTiers; // Linked-list length. uint8 p = _tierDataHead; // Current linked-list pointer. info.tierInfo = new TierInfo[](n); // Traverse the linked-list and fill the array in reverse. // Front: earliest added tier. Back: latest added tier. while (n != 0) { TierData storage d = _getTierData(p); info.tierInfo[--n] = tierInfo(p); p = d.next; } } } /** * @inheritdoc ISoundEditionV2_1 */ function tierInfo(uint8 tier) public view returns (TierInfo memory info) { TierData storage d = _getTierData(tier); info.tier = tier; info.maxMintable = _maxMintable(d); info.maxMintableLower = d.maxMintableLower; info.maxMintableUpper = d.maxMintableUpper; info.cutoffTime = d.cutoffTime; info.minted = d.minted; info.mintRandomness = _mintRandomness(d); info.mintRandomnessEnabled = _mintRandomnessEnabled(d); info.mintConcluded = _mintConcluded(d); info.isFrozen = _isFrozen(d); } /** * @inheritdoc ISoundEditionV2_1 */ function isFrozen(uint8 tier) public view returns (bool) { return _isFrozen(_getTierData(tier)); } /** * @inheritdoc ISoundEditionV2_1 */ function isMetadataFrozen() public view returns (bool) { return _flags & _METADATA_IS_FROZEN_FLAG != 0; } /** * @inheritdoc ISoundEditionV2_1 */ function isCreateTierFrozen() public view returns (bool) { return _flags & _CREATE_TIER_IS_FROZEN_FLAG != 0; } /** * @inheritdoc ISoundEditionV2_1 */ function nextTokenId() public view returns (uint256) { return _nextTokenId(); } /** * @inheritdoc ISoundEditionV2_1 */ function numberMinted(address owner) public view returns (uint256) { return _numberMinted(owner); } /** * @inheritdoc ISoundEditionV2_1 */ function numberBurned(address owner) public view returns (uint256) { return _numberBurned(owner); } /** * @inheritdoc ISoundEditionV2_1 */ function totalMinted() public view returns (uint256) { return _totalMinted(); } /** * @inheritdoc ISoundEditionV2_1 */ function totalBurned() public view returns (uint256) { return _totalBurned(); } /** * @inheritdoc ISoundEditionV2_1 */ function tokenTier(uint256 tokenId) public view returns (uint8) { if (!_exists(tokenId)) revert TierQueryForNonexistentToken(); return _tokenTiers.get(tokenId); } /** * @inheritdoc ISoundEditionV2_1 */ function explicitTokenTier(uint256 tokenId) public view returns (uint8) { return _tokenTiers.get(tokenId); } /** * @inheritdoc ISoundEditionV2_1 */ function tokenTiers(uint256[] calldata tokenIds) public view returns (uint8[] memory tiers) { unchecked { tiers = new uint8[](tokenIds.length); for (uint256 i; i != tokenIds.length; ++i) { tiers[i] = _tokenTiers.get(tokenIds[i]); } } } /** * @inheritdoc ISoundEditionV2_1 */ function tierMinted(uint8 tier) public view returns (uint32) { return _getTierData(tier).minted; } /** * @inheritdoc ISoundEditionV2_1 */ function tierTokenIds(uint8 tier) public view returns (uint256[] memory tokenIds) { tokenIds = tierTokenIdsIn(tier, 0, tierMinted(tier)); } /** * @inheritdoc ISoundEditionV2_1 */ function tierTokenIdsIn( uint8 tier, uint256 start, uint256 stop ) public view returns (uint256[] memory tokenIds) { unchecked { uint256 l = stop - start; uint256 n = tierMinted(tier); if (LibOps.or(start > stop, stop > n)) revert InvalidQueryRange(); tokenIds = new uint256[](l); LibMap.Uint32Map storage m = _tierTokenIds[tier]; for (uint256 i; i != l; ++i) { tokenIds[i] = m.get(start + i); } } } /** * @inheritdoc ISoundEditionV2_1 */ function tierTokenIdIndex(uint256 tokenId) public view returns (uint256) { uint8 tier = tokenTier(tokenId); (bool found, uint256 index) = _tierTokenIds[tier].searchSorted(uint32(tokenId), 0, tierMinted(tier)); return LibOps.and(tokenId < 1 << 32, found) ? index : type(uint256).max; } /** * @inheritdoc ISoundEditionV2_1 */ function mintRandomness(uint8 tier) public view returns (uint256 result) { return _mintRandomness(_getTierData(tier)); } /** * @inheritdoc ISoundEditionV2_1 */ function mintConcluded(uint8 tier) public view returns (bool) { return _mintConcluded(_getTierData(tier)); } /** * @inheritdoc ISoundEditionV2_1 */ function maxMintable(uint8 tier) public view returns (uint32) { return _maxMintable(_getTierData(tier)); } /** * @inheritdoc ISoundEditionV2_1 */ function maxMintableUpper(uint8 tier) public view returns (uint32) { return _getTierData(tier).maxMintableUpper; } /** * @inheritdoc ISoundEditionV2_1 */ function maxMintableLower(uint8 tier) public view returns (uint32) { return _getTierData(tier).maxMintableLower; } /** * @inheritdoc ISoundEditionV2_1 */ function cutoffTime(uint8 tier) public view returns (uint32) { return _getTierData(tier).cutoffTime; } /** * @inheritdoc ISoundEditionV2_1 */ function mintRandomnessEnabled(uint8 tier) public view returns (bool) { return _mintRandomnessEnabled(_getTierData(tier)); } /** * @inheritdoc ISoundEditionV2_1 */ function mintRandomnessOneOfOne(uint8 tier) public view returns (uint32) { TierData storage d = _getTierData(tier); uint256 r = _mintRandomness(d); uint256 n = _maxMintable(d); return LibOps.or(r == 0, n == 0) ? 0 : _tierTokenIds[tier].get(LibOps.rawMod(r, n)); } /** * @inheritdoc IERC721AUpgradeable */ function tokenURI(uint256 tokenId) public view override(ERC721AUpgradeable, IERC721AUpgradeable) returns (string memory) { if (!_exists(tokenId)) revert URIQueryForNonexistentToken(); return explicitTokenURI(tokenId); } /** * @inheritdoc ISoundEditionV2_1 */ function explicitTokenURI(uint256 tokenId) public view returns (string memory) { if (metadataModule != address(0)) return IMetadataModule(metadataModule).tokenURI(tokenId); string memory baseURI_ = baseURI(); return bytes(baseURI_).length != 0 ? string.concat(baseURI_, _toString(tokenId)) : ""; } /** * @inheritdoc ISoundEditionV2_1 */ function supportsInterface(bytes4 interfaceId) public view override(ISoundEditionV2_1, ERC721AUpgradeable, IERC721AUpgradeable) returns (bool) { return LibOps.or( interfaceId == type(ISoundEditionV2_1).interfaceId, ERC721AUpgradeable.supportsInterface(interfaceId), interfaceId == _INTERFACE_ID_SOUND_EDITION_V2, interfaceId == _INTERFACE_ID_ERC2981 ); } /** * @inheritdoc IERC2981Upgradeable */ function royaltyInfo( uint256, // tokenId uint256 salePrice ) public view override(IERC2981Upgradeable) returns (address recipient, uint256 royaltyAmount) { recipient = fundingRecipient; if (salePrice >= 1 << 240) LibOps.revertOverflow(); // `royaltyBPS` is uint16. `256 - 16 = 240`. royaltyAmount = LibOps.rawMulDiv(salePrice, royaltyBPS, BPS_DENOMINATOR); } /** * @inheritdoc IERC721AUpgradeable */ function name() public view override(ERC721AUpgradeable, IERC721AUpgradeable) returns (string memory name_) { (name_, ) = _loadNameAndSymbol(); } /** * @inheritdoc IERC721AUpgradeable */ function symbol() public view override(ERC721AUpgradeable, IERC721AUpgradeable) returns (string memory symbol_) { (, symbol_) = _loadNameAndSymbol(); } /** * @inheritdoc ISoundEditionV2_1 */ function baseURI() public view returns (string memory) { return _baseURIStorage.load(); } /** * @inheritdoc ISoundEditionV2_1 */ function contractURI() public view returns (string memory) { return _contractURIStorage.load(); } // ============================================================= // INTERNAL / PRIVATE HELPERS // ============================================================= /** * @dev Override the `onlyRolesOrOwner` modifier on `OwnableRoles` * to support multicaller sender forwarding. */ modifier onlyRolesOrOwner(uint256 roles) virtual override { _requireOnlyRolesOrOwner(roles); _; } /** * @dev Require that the caller has any of the `roles`, or is the owner of the contract. * @param roles A roles bitmap. */ function _requireOnlyRolesOrOwner(uint256 roles) internal view { address sender = LibMulticaller.senderOrSigner(); if (!hasAnyRole(sender, roles)) if (sender != owner()) LibOps.revertUnauthorized(); } /** * @inheritdoc ERC721AUpgradeable */ function _startTokenId() internal pure override returns (uint256) { return 1; } /** * @dev Ensures the royalty basis points is a valid value. * @param bps The royalty BPS. */ function _validateRoyaltyBPS(uint16 bps) internal pure { if (bps > BPS_DENOMINATOR) revert InvalidRoyaltyBPS(); } /** * @dev Ensures the funding recipient is not the zero address. * @param recipient The funding recipient. */ function _validateFundingRecipient(address recipient) internal pure { if (recipient == address(0)) revert InvalidFundingRecipient(); } /** * @dev Reverts if the metadata is frozen. */ function _requireMetadataNotFrozen() internal view { if (isMetadataFrozen()) revert MetadataIsFrozen(); } /** * @dev Reverts if the max tier is frozen. */ function _requireCreateTierNotFrozen() internal view { if (isCreateTierFrozen()) revert CreateTierIsFrozen(); } /** * @dev Reverts if there are any mints. */ function _requireNoMints() internal view { if (_totalMinted() != 0) revert MintsAlreadyExist(); } /** * @dev Reverts if there are any mints for the tier. * @param d The tier data. */ function _requireNoTierMints(TierData storage d) internal view { if (d.minted != 0) revert TierMintsAlreadyExist(); } /** * @dev Create a new tier. * @param c The tier creation struct. */ function _createTier(TierCreation memory c) internal { uint8 tier = c.tier; TierData storage d = _tierData[tier]; if (d.flags & _TIER_CREATED_FLAG != 0) revert TierAlreadyExists(); // If GA, overwrite any immutable variables as required. if (tier == GA_TIER) { c.maxMintableLower = type(uint32).max; c.maxMintableUpper = type(uint32).max; c.cutoffTime = type(uint32).max; c.mintRandomnessEnabled = false; c.isFrozen = true; } else { if (c.maxMintableLower > c.maxMintableUpper) revert InvalidMaxMintableRange(); } d.maxMintableLower = c.maxMintableLower; d.maxMintableUpper = c.maxMintableUpper; d.cutoffTime = c.cutoffTime; d.flags = _TIER_CREATED_FLAG | LibOps.toFlag(c.mintRandomnessEnabled, _TIER_MINT_RANDOMNESS_ENABLED_FLAG) | LibOps.toFlag(c.isFrozen, _TIER_IS_FROZEN_FLAG); unchecked { uint16 n = uint16(uint256(_numTiers) + 1); // `_numTiers` is uint16. `tier` is uint8. d.next = _tierDataHead; _numTiers = n; _tierDataHead = tier; } } /** * @dev Sets the funding recipient address. * @param recipient Address to be set as the new funding recipient. */ function _setFundingRecipient(address recipient) internal { _validateFundingRecipient(recipient); fundingRecipient = recipient; emit FundingRecipientSet(recipient); } /** * @dev Ensures that the tier is not frozen. * @param d The tier data. */ function _requireNotFrozen(TierData storage d) internal view { if (_isFrozen(d)) revert TierIsFrozen(); } /** * @dev Ensures that the mint has not been concluded. * @param d The tier data. */ function _requireBeforeMintConcluded(TierData storage d) internal view { if (_mintConcluded(d)) revert MintHasConcluded(); } /** * @dev Ensures that the mint has been concluded. * @param d The tier data. */ function _requireAfterMintConcluded(TierData storage d) internal view { if (!_mintConcluded(d)) revert MintNotConcluded(); } /** * @dev Append to the tier token IDs and the token tiers arrays. * Reverts if there is insufficient supply. * @param tier The tier. * @param quantity The total number of tokens to mint. * @return fromTokenId The first token ID minted. * @return fromTierTokenIdIndex The first token index in the tier. */ function _beforeTieredMint(uint8 tier, uint256 quantity) internal returns (uint256 fromTokenId, uint32 fromTierTokenIdIndex) { unchecked { if (quantity == 0) revert MintZeroQuantity(); fromTokenId = _nextTokenId(); // To ensure that we won't store a token ID above 2**31 - 1 in `_tierTokenIds`. if (fromTokenId + quantity - 1 >= 1 << 32) LibOps.revertOverflow(); TierData storage d = _getTierData(tier); uint256 minted = d.minted; // uint32. uint256 limit = _maxMintable(d); // uint32. // Check that the mints will not exceed the available supply. uint256 finalMinted = minted + quantity; if (finalMinted > limit) revert ExceedsAvailableSupply(); d.minted = uint32(finalMinted); // Update the mint randomness state if required. if (_mintRandomnessEnabled(d)) d.mintRandomness = uint64( MintRandomnessLib.nextMintRandomness(d.mintRandomness, minted, quantity, limit) ); LibMap.Uint32Map storage m = _tierTokenIds[tier]; for (uint256 i; i != quantity; ++i) { m.set(minted + i, uint32(fromTokenId + i)); // Set the token IDs for the tier. if (tier != 0) _tokenTiers.set(fromTokenId + i, tier); // Set the tier for the token ID. } fromTierTokenIdIndex = uint32(minted); } } /** * @dev Returns the full mint randomness for the tier. * @param d The tier data. * @return result The full mint randomness. */ function _mintRandomness(TierData storage d) internal view returns (uint256 result) { if (_mintRandomnessEnabled(d) && _mintConcluded(d)) { result = d.mintRandomness; assembly { mstore(0x00, result) mstore(0x20, address()) result := keccak256(0x00, 0x40) result := add(iszero(result), result) } } } /** * @dev Returns whether the mint has concluded for the tier. * @param d The tier data. * @return Whether the mint has concluded. */ function _mintConcluded(TierData storage d) internal view returns (bool) { return d.minted >= _maxMintable(d); } /** * @dev Returns whether the mint has mint randomness enabled. * @param d The tier data. * @return Whether mint randomness is enabled. */ function _mintRandomnessEnabled(TierData storage d) internal view returns (bool) { return d.flags & _TIER_MINT_RANDOMNESS_ENABLED_FLAG != 0; } /** * @dev Returns the current max mintable supply for the tier. * @param d The tier data. * @return The current max mintable supply. */ function _maxMintable(TierData storage d) internal view returns (uint32) { if (block.timestamp < d.cutoffTime) return d.maxMintableUpper; return uint32(LibOps.max(d.maxMintableLower, d.minted)); } /** * @dev Returns whether the tier is frozen. * @param d The tier data. * @return Whether the tier is frozen. */ function _isFrozen(TierData storage d) internal view returns (bool) { return d.flags & _TIER_IS_FROZEN_FLAG != 0; } /** * @dev Returns a storage pointer to the tier data, reverting if the tier does not exist. * @param tier The tier. * @return d A storage pointer to the tier data. */ function _getTierData(uint8 tier) internal view returns (TierData storage d) { d = _tierData[tier]; if (d.flags & _TIER_CREATED_FLAG == 0) revert TierDoesNotExist(); } /** * @dev Helper function for initializing the ERC721A class. * @param name_ Name of the collection. * @param symbol_ Symbol of the collection. */ function _initializeERC721A(string memory name_, string memory symbol_) internal { ERC721AStorage.Layout storage layout = ERC721AStorage.layout(); // Prevent double initialization. // We can "cheat" here and avoid the initializer modifier to save a SSTORE, // since the `_nextTokenId()` is defined to always return 1. if (layout._currentIndex != 0) LibOps.revertUnauthorized(); layout._currentIndex = _startTokenId(); // Returns `bytes32(0)` if the strings are too long to be packed into a single word. bytes32 packed = LibString.packTwo(name_, symbol_); // If we cannot pack both strings into a single 32-byte word, store separately. // We need 2 bytes to store their lengths. if (packed == bytes32(0)) { layout._name = name_; layout._symbol = symbol_; } else { // Otherwise, pack them and store them into a single word. _shortNameAndSymbol = packed; } } /** * @dev Helper function for retrieving the name and symbol, * unpacking them from a single word in storage if previously packed. * @return name_ Name of the collection. * @return symbol_ Symbol of the collection. */ function _loadNameAndSymbol() internal view returns (string memory name_, string memory symbol_) { bytes32 packed = _shortNameAndSymbol; // If the strings have been previously packed. if (packed != bytes32(0)) { (name_, symbol_) = LibString.unpackTwo(packed); } else { // Otherwise, load them from their separate variables. ERC721AStorage.Layout storage layout = ERC721AStorage.layout(); name_ = layout._name; symbol_ = layout._symbol; } } /** * @dev Mints a big batch in mini batches to prevent expensive * first-time transfer gas costs. * @param to The address to mint to. * @param quantity The number of NFTs to mint. */ function _batchMint(address to, uint256 quantity) internal { unchecked { // Mint in mini batches of 32. uint256 i = quantity % 32; if (i != 0) _mint(to, i); while (i != quantity) { _mint(to, 32); i += 32; } } } }
// 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 // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721AUpgradeable.sol'; import {ERC721AStorage} from './ERC721AStorage.sol'; import './ERC721A__Initializable.sol'; /** * @dev Interface of ERC721 token receiver. */ interface ERC721A__IERC721ReceiverUpgradeable { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } /** * @title ERC721A * * @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721) * Non-Fungible Token Standard, including the Metadata extension. * Optimized for lower gas during batch mints. * * Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...) * starting from `_startTokenId()`. * * Assumptions: * * - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply. * - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256). */ contract ERC721AUpgradeable is ERC721A__Initializable, IERC721AUpgradeable { using ERC721AStorage for ERC721AStorage.Layout; // ============================================================= // CONSTANTS // ============================================================= // Mask of an entry in packed address data. uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1; // The bit position of `numberMinted` in packed address data. uint256 private constant _BITPOS_NUMBER_MINTED = 64; // The bit position of `numberBurned` in packed address data. uint256 private constant _BITPOS_NUMBER_BURNED = 128; // The bit position of `aux` in packed address data. uint256 private constant _BITPOS_AUX = 192; // Mask of all 256 bits in packed address data except the 64 bits for `aux`. uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1; // The bit position of `startTimestamp` in packed ownership. uint256 private constant _BITPOS_START_TIMESTAMP = 160; // The bit mask of the `burned` bit in packed ownership. uint256 private constant _BITMASK_BURNED = 1 << 224; // The bit position of the `nextInitialized` bit in packed ownership. uint256 private constant _BITPOS_NEXT_INITIALIZED = 225; // The bit mask of the `nextInitialized` bit in packed ownership. uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225; // The bit position of `extraData` in packed ownership. uint256 private constant _BITPOS_EXTRA_DATA = 232; // Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`. uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1; // The mask of the lower 160 bits for addresses. uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1; // The maximum `quantity` that can be minted with {_mintERC2309}. // This limit is to prevent overflows on the address data entries. // For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309} // is required to cause an overflow, which is unrealistic. uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000; // The `Transfer` event signature is given by: // `keccak256(bytes("Transfer(address,address,uint256)"))`. bytes32 private constant _TRANSFER_EVENT_SIGNATURE = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef; // ============================================================= // CONSTRUCTOR // ============================================================= function __ERC721A_init(string memory name_, string memory symbol_) internal onlyInitializingERC721A { __ERC721A_init_unchained(name_, symbol_); } function __ERC721A_init_unchained(string memory name_, string memory symbol_) internal onlyInitializingERC721A { ERC721AStorage.layout()._name = name_; ERC721AStorage.layout()._symbol = symbol_; ERC721AStorage.layout()._currentIndex = _startTokenId(); } // ============================================================= // TOKEN COUNTING OPERATIONS // ============================================================= /** * @dev Returns the starting token ID. * To change the starting token ID, please override this function. */ function _startTokenId() internal view virtual returns (uint256) { return 0; } /** * @dev Returns the next token ID to be minted. */ function _nextTokenId() internal view virtual returns (uint256) { return ERC721AStorage.layout()._currentIndex; } /** * @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() public view virtual override returns (uint256) { // Counter underflow is impossible as _burnCounter cannot be incremented // more than `_currentIndex - _startTokenId()` times. unchecked { return ERC721AStorage.layout()._currentIndex - ERC721AStorage.layout()._burnCounter - _startTokenId(); } } /** * @dev Returns the total amount of tokens minted in the contract. */ function _totalMinted() internal view virtual returns (uint256) { // Counter underflow is impossible as `_currentIndex` does not decrement, // and it is initialized to `_startTokenId()`. unchecked { return ERC721AStorage.layout()._currentIndex - _startTokenId(); } } /** * @dev Returns the total number of tokens burned. */ function _totalBurned() internal view virtual returns (uint256) { return ERC721AStorage.layout()._burnCounter; } // ============================================================= // ADDRESS DATA OPERATIONS // ============================================================= /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) public view virtual override returns (uint256) { if (owner == address(0)) _revert(BalanceQueryForZeroAddress.selector); return ERC721AStorage.layout()._packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens minted by `owner`. */ function _numberMinted(address owner) internal view returns (uint256) { return (ERC721AStorage.layout()._packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens burned by or on behalf of `owner`. */ function _numberBurned(address owner) internal view returns (uint256) { return (ERC721AStorage.layout()._packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). */ function _getAux(address owner) internal view returns (uint64) { return uint64(ERC721AStorage.layout()._packedAddressData[owner] >> _BITPOS_AUX); } /** * Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). * If there are multiple variables, please pack them into a uint64. */ function _setAux(address owner, uint64 aux) internal virtual { uint256 packed = ERC721AStorage.layout()._packedAddressData[owner]; uint256 auxCasted; // Cast `aux` with assembly to avoid redundant masking. assembly { auxCasted := aux } packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX); ERC721AStorage.layout()._packedAddressData[owner] = packed; } // ============================================================= // 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) public view virtual override returns (bool) { // The interface IDs are constants representing the first 4 bytes // of the XOR of all function selectors in the interface. // See: [ERC165](https://eips.ethereum.org/EIPS/eip-165) // (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`) return interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165. interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721. interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata. } // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() public view virtual override returns (string memory) { return ERC721AStorage.layout()._name; } /** * @dev Returns the token collection symbol. */ function symbol() public view virtual override returns (string memory) { return ERC721AStorage.layout()._symbol; } /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { if (!_exists(tokenId)) _revert(URIQueryForNonexistentToken.selector); string memory baseURI = _baseURI(); return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : ''; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, it can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ''; } // ============================================================= // OWNERSHIPS OPERATIONS // ============================================================= /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { return address(uint160(_packedOwnershipOf(tokenId))); } /** * @dev Gas spent here starts off proportional to the maximum mint batch size. * It gradually moves to O(1) as tokens get transferred around over time. */ function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnershipOf(tokenId)); } /** * @dev Returns the unpacked `TokenOwnership` struct at `index`. */ function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(ERC721AStorage.layout()._packedOwnerships[index]); } /** * @dev Returns whether the ownership slot at `index` is initialized. * An uninitialized slot does not necessarily mean that the slot has no owner. */ function _ownershipIsInitialized(uint256 index) internal view virtual returns (bool) { return ERC721AStorage.layout()._packedOwnerships[index] != 0; } /** * @dev Initializes the ownership slot minted at `index` for efficiency purposes. */ function _initializeOwnershipAt(uint256 index) internal virtual { if (ERC721AStorage.layout()._packedOwnerships[index] == 0) { ERC721AStorage.layout()._packedOwnerships[index] = _packedOwnershipOf(index); } } /** * Returns the packed ownership data of `tokenId`. */ function _packedOwnershipOf(uint256 tokenId) private view returns (uint256 packed) { if (_startTokenId() <= tokenId) { packed = ERC721AStorage.layout()._packedOwnerships[tokenId]; // If the data at the starting slot does not exist, start the scan. if (packed == 0) { if (tokenId >= ERC721AStorage.layout()._currentIndex) _revert(OwnerQueryForNonexistentToken.selector); // Invariant: // There will always be an initialized ownership slot // (i.e. `ownership.addr != address(0) && ownership.burned == false`) // before an unintialized ownership slot // (i.e. `ownership.addr == address(0) && ownership.burned == false`) // Hence, `tokenId` will not underflow. // // We can directly compare the packed value. // If the address is zero, packed will be zero. for (;;) { unchecked { packed = ERC721AStorage.layout()._packedOwnerships[--tokenId]; } if (packed == 0) continue; if (packed & _BITMASK_BURNED == 0) return packed; // Otherwise, the token is burned, and we must revert. // This handles the case of batch burned tokens, where only the burned bit // of the starting slot is set, and remaining slots are left uninitialized. _revert(OwnerQueryForNonexistentToken.selector); } } // Otherwise, the data exists and we can skip the scan. // This is possible because we have already achieved the target condition. // This saves 2143 gas on transfers of initialized tokens. // If the token is not burned, return `packed`. Otherwise, revert. if (packed & _BITMASK_BURNED == 0) return packed; } _revert(OwnerQueryForNonexistentToken.selector); } /** * @dev Returns the unpacked `TokenOwnership` struct from `packed`. */ function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) { ownership.addr = address(uint160(packed)); ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP); ownership.burned = packed & _BITMASK_BURNED != 0; ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA); } /** * @dev Packs ownership data into a single uint256. */ function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`. result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags)) } } /** * @dev Returns the `nextInitialized` flag set if `quantity` equals 1. */ function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) { // For branchless setting of the `nextInitialized` flag. assembly { // `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`. result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1)) } } // ============================================================= // APPROVAL OPERATIONS // ============================================================= /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. See {ERC721A-_approve}. * * Requirements: * * - The caller must own the token or be an approved operator. */ function approve(address to, uint256 tokenId) public payable virtual override { _approve(to, tokenId, true); } /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { if (!_exists(tokenId)) _revert(ApprovalQueryForNonexistentToken.selector); return ERC721AStorage.layout()._tokenApprovals[tokenId].value; } /** * @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) public virtual override { ERC721AStorage.layout()._operatorApprovals[_msgSenderERC721A()][operator] = approved; emit ApprovalForAll(_msgSenderERC721A(), operator, approved); } /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return ERC721AStorage.layout()._operatorApprovals[owner][operator]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted. See {_mint}. */ function _exists(uint256 tokenId) internal view virtual returns (bool result) { if (_startTokenId() <= tokenId) { if (tokenId < ERC721AStorage.layout()._currentIndex) { uint256 packed; while ((packed = ERC721AStorage.layout()._packedOwnerships[tokenId]) == 0) --tokenId; result = packed & _BITMASK_BURNED == 0; } } } /** * @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`. */ function _isSenderApprovedOrOwner( address approvedAddress, address owner, address msgSender ) private pure returns (bool result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean. msgSender := and(msgSender, _BITMASK_ADDRESS) // `msgSender == owner || msgSender == approvedAddress`. result := or(eq(msgSender, owner), eq(msgSender, approvedAddress)) } } /** * @dev Returns the storage slot and value for the approved address of `tokenId`. */ function _getApprovedSlotAndAddress(uint256 tokenId) private view returns (uint256 approvedAddressSlot, address approvedAddress) { ERC721AStorage.TokenApprovalRef storage tokenApproval = ERC721AStorage.layout()._tokenApprovals[tokenId]; // The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`. assembly { approvedAddressSlot := tokenApproval.slot approvedAddress := sload(approvedAddressSlot) } } // ============================================================= // TRANSFER OPERATIONS // ============================================================= /** * @dev Transfers `tokenId` from `from` to `to`. * * 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 ) public payable virtual override { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); // Mask `from` to the lower 160 bits, in case the upper bits somehow aren't clean. from = address(uint160(uint256(uint160(from)) & _BITMASK_ADDRESS)); if (address(uint160(prevOwnershipPacked)) != from) _revert(TransferFromIncorrectOwner.selector); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector); _beforeTokenTransfers(from, to, tokenId, 1); // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // We can directly increment and decrement the balances. --ERC721AStorage.layout()._packedAddressData[from]; // Updates: `balance -= 1`. ++ERC721AStorage.layout()._packedAddressData[to]; // Updates: `balance += 1`. // Updates: // - `address` to the next owner. // - `startTimestamp` to the timestamp of transfering. // - `burned` to `false`. // - `nextInitialized` to `true`. ERC721AStorage.layout()._packedOwnerships[tokenId] = _packOwnershipData( to, _BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (ERC721AStorage.layout()._packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != ERC721AStorage.layout()._currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. ERC721AStorage.layout()._packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS; assembly { // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. from, // `from`. toMasked, // `to`. tokenId // `tokenId`. ) } if (toMasked == 0) _revert(TransferToZeroAddress.selector); _afterTokenTransfers(from, to, tokenId, 1); } /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public payable virtual override { safeTransferFrom(from, to, tokenId, ''); } /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * 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 approved 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 memory _data ) public payable virtual override { transferFrom(from, to, tokenId); if (to.code.length != 0) if (!_checkContractOnERC721Received(from, to, tokenId, _data)) { _revert(TransferToNonERC721ReceiverImplementer.selector); } } /** * @dev Hook that is called before a set of serially-ordered token IDs * are about to be transferred. This includes minting. * And also called before burning one token. * * `startTokenId` - the first token ID to be transferred. * `quantity` - the amount to be transferred. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _beforeTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Hook that is called after a set of serially-ordered token IDs * have been transferred. This includes minting. * And also called after one token has been burned. * * `startTokenId` - the first token ID to be transferred. * `quantity` - the amount to be transferred. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been * transferred to `to`. * - When `from` is zero, `tokenId` has been minted for `to`. * - When `to` is zero, `tokenId` has been burned by `from`. * - `from` and `to` are never both zero. */ function _afterTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract. * * `from` - Previous owner of the given token ID. * `to` - Target address that will receive the token. * `tokenId` - Token ID to be transferred. * `_data` - Optional data to send along with the call. * * Returns whether the call correctly returned the expected magic value. */ function _checkContractOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) private returns (bool) { try ERC721A__IERC721ReceiverUpgradeable(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns (bytes4 retval) { return retval == ERC721A__IERC721ReceiverUpgradeable(to).onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { _revert(TransferToNonERC721ReceiverImplementer.selector); } assembly { revert(add(32, reason), mload(reason)) } } } // ============================================================= // MINT OPERATIONS // ============================================================= /** * @dev Mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {Transfer} event for each mint. */ function _mint(address to, uint256 quantity) internal virtual { uint256 startTokenId = ERC721AStorage.layout()._currentIndex; if (quantity == 0) _revert(MintZeroQuantity.selector); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are incredibly unrealistic. // `balance` and `numberMinted` have a maximum limit of 2**64. // `tokenId` has a maximum limit of 2**256. unchecked { // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. ERC721AStorage.layout()._packedOwnerships[startTokenId] = _packOwnershipData( to, _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0) ); // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the `balance` and `numberMinted`. ERC721AStorage.layout()._packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1); // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. uint256 toMasked = uint256(uint160(to)) & _BITMASK_ADDRESS; if (toMasked == 0) _revert(MintToZeroAddress.selector); uint256 end = startTokenId + quantity; uint256 tokenId = startTokenId; do { assembly { // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. 0, // `address(0)`. toMasked, // `to`. tokenId // `tokenId`. ) } // The `!=` check ensures that large values of `quantity` // that overflows uint256 will make the loop run out of gas. } while (++tokenId != end); ERC721AStorage.layout()._currentIndex = end; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Mints `quantity` tokens and transfers them to `to`. * * This function is intended for efficient minting only during contract creation. * * It emits only one {ConsecutiveTransfer} as defined in * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309), * instead of a sequence of {Transfer} event(s). * * Calling this function outside of contract creation WILL make your contract * non-compliant with the ERC721 standard. * For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309 * {ConsecutiveTransfer} event is only permissible during contract creation. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {ConsecutiveTransfer} event. */ function _mintERC2309(address to, uint256 quantity) internal virtual { uint256 startTokenId = ERC721AStorage.layout()._currentIndex; if (to == address(0)) _revert(MintToZeroAddress.selector); if (quantity == 0) _revert(MintZeroQuantity.selector); if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) _revert(MintERC2309QuantityExceedsLimit.selector); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are unrealistic due to the above check for `quantity` to be below the limit. unchecked { // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the `balance` and `numberMinted`. ERC721AStorage.layout()._packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1); // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. ERC721AStorage.layout()._packedOwnerships[startTokenId] = _packOwnershipData( to, _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0) ); emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to); ERC721AStorage.layout()._currentIndex = startTokenId + quantity; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Safely mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called for each safe transfer. * - `quantity` must be greater than 0. * * See {_mint}. * * Emits a {Transfer} event for each mint. */ function _safeMint( address to, uint256 quantity, bytes memory _data ) internal virtual { _mint(to, quantity); unchecked { if (to.code.length != 0) { uint256 end = ERC721AStorage.layout()._currentIndex; uint256 index = end - quantity; do { if (!_checkContractOnERC721Received(address(0), to, index++, _data)) { _revert(TransferToNonERC721ReceiverImplementer.selector); } } while (index < end); // Reentrancy protection. if (ERC721AStorage.layout()._currentIndex != end) _revert(bytes4(0)); } } } /** * @dev Equivalent to `_safeMint(to, quantity, '')`. */ function _safeMint(address to, uint256 quantity) internal virtual { _safeMint(to, quantity, ''); } // ============================================================= // APPROVAL OPERATIONS // ============================================================= /** * @dev Equivalent to `_approve(to, tokenId, false)`. */ function _approve(address to, uint256 tokenId) internal virtual { _approve(to, tokenId, false); } /** * @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: * * - `tokenId` must exist. * * Emits an {Approval} event. */ function _approve( address to, uint256 tokenId, bool approvalCheck ) internal virtual { address owner = ownerOf(tokenId); if (approvalCheck && _msgSenderERC721A() != owner) if (!isApprovedForAll(owner, _msgSenderERC721A())) { _revert(ApprovalCallerNotOwnerNorApproved.selector); } ERC721AStorage.layout()._tokenApprovals[tokenId].value = to; emit Approval(owner, to, tokenId); } // ============================================================= // BURN OPERATIONS // ============================================================= /** * @dev Equivalent to `_burn(tokenId, false)`. */ function _burn(uint256 tokenId) internal virtual { _burn(tokenId, false); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId, bool approvalCheck) internal virtual { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); address from = address(uint160(prevOwnershipPacked)); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); if (approvalCheck) { // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector); } _beforeTokenTransfers(from, address(0), tokenId, 1); // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // Updates: // - `balance -= 1`. // - `numberBurned += 1`. // // We can directly decrement the balance, and increment the number burned. // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`. ERC721AStorage.layout()._packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1; // Updates: // - `address` to the last owner. // - `startTimestamp` to the timestamp of burning. // - `burned` to `true`. // - `nextInitialized` to `true`. ERC721AStorage.layout()._packedOwnerships[tokenId] = _packOwnershipData( from, (_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (ERC721AStorage.layout()._packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != ERC721AStorage.layout()._currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. ERC721AStorage.layout()._packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } emit Transfer(from, address(0), tokenId); _afterTokenTransfers(from, address(0), tokenId, 1); // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times. unchecked { ERC721AStorage.layout()._burnCounter++; } } // ============================================================= // EXTRA DATA OPERATIONS // ============================================================= /** * @dev Directly sets the extra data for the ownership data `index`. */ function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual { uint256 packed = ERC721AStorage.layout()._packedOwnerships[index]; if (packed == 0) _revert(OwnershipNotInitializedForExtraData.selector); uint256 extraDataCasted; // Cast `extraData` with assembly to avoid redundant masking. assembly { extraDataCasted := extraData } packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA); ERC721AStorage.layout()._packedOwnerships[index] = packed; } /** * @dev Called during each token transfer to set the 24bit `extraData` field. * Intended to be overridden by the cosumer contract. * * `previousExtraData` - the value of `extraData` before transfer. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _extraData( address from, address to, uint24 previousExtraData ) internal view virtual returns (uint24) {} /** * @dev Returns the next extra data for the packed ownership data. * The returned result is shifted into position. */ function _nextExtraData( address from, address to, uint256 prevOwnershipPacked ) private view returns (uint256) { uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA); return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA; } // ============================================================= // OTHER OPERATIONS // ============================================================= /** * @dev Returns the message sender (defaults to `msg.sender`). * * If you are writing GSN compatible contracts, you need to override this function. */ function _msgSenderERC721A() internal view virtual returns (address) { return msg.sender; } /** * @dev Converts a uint256 to its ASCII string decimal representation. */ function _toString(uint256 value) internal pure virtual returns (string memory str) { assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned. // We will need 1 word for the trailing zeros padding, 1 word for the length, // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0. let m := add(mload(0x40), 0xa0) // Update the free memory pointer to allocate. mstore(0x40, m) // Assign the `str` to the end. str := sub(m, 0x20) // Zeroize the slot after the string. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // prettier-ignore for { let temp := value } 1 {} { str := sub(str, 1) // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing `temp` until zero. temp := div(temp, 10) // prettier-ignore if iszero(temp) { break } } let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 0x20) // Store the length. mstore(str, length) } } /** * @dev For more efficient reverts. */ function _revert(bytes4 errorSelector) internal pure { assembly { mstore(0x00, errorSelector) revert(0x00, 0x04) } } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721AQueryableUpgradeable.sol'; import '../ERC721AUpgradeable.sol'; import '../ERC721A__Initializable.sol'; /** * @title ERC721AQueryable. * * @dev ERC721A subclass with convenience query functions. */ abstract contract ERC721AQueryableUpgradeable is ERC721A__Initializable, ERC721AUpgradeable, IERC721AQueryableUpgradeable { function __ERC721AQueryable_init() internal onlyInitializingERC721A { __ERC721AQueryable_init_unchained(); } function __ERC721AQueryable_init_unchained() internal onlyInitializingERC721A {} /** * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting. * * If the `tokenId` is out of bounds: * * - `addr = address(0)` * - `startTimestamp = 0` * - `burned = false` * - `extraData = 0` * * If the `tokenId` is burned: * * - `addr = <Address of owner before token was burned>` * - `startTimestamp = <Timestamp when token was burned>` * - `burned = true` * - `extraData = <Extra data when token was burned>` * * Otherwise: * * - `addr = <Address of owner>` * - `startTimestamp = <Timestamp of start of ownership>` * - `burned = false` * - `extraData = <Extra data at start of ownership>` */ function explicitOwnershipOf(uint256 tokenId) public view virtual override returns (TokenOwnership memory ownership) { unchecked { if (tokenId >= _startTokenId()) { if (tokenId < _nextTokenId()) { // If the `tokenId` is within bounds, // scan backwards for the initialized ownership slot. while (!_ownershipIsInitialized(tokenId)) --tokenId; return _ownershipAt(tokenId); } } } } /** * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order. * See {ERC721AQueryable-explicitOwnershipOf} */ function explicitOwnershipsOf(uint256[] calldata tokenIds) external view virtual override returns (TokenOwnership[] memory) { TokenOwnership[] memory ownerships; uint256 i = tokenIds.length; assembly { // Grab the free memory pointer. ownerships := mload(0x40) // Store the length. mstore(ownerships, i) // Allocate one word for the length, // `tokenIds.length` words for the pointers. i := shl(5, i) // Multiply `i` by 32. mstore(0x40, add(add(ownerships, 0x20), i)) } while (i != 0) { uint256 tokenId; assembly { i := sub(i, 0x20) tokenId := calldataload(add(tokenIds.offset, i)) } TokenOwnership memory ownership = explicitOwnershipOf(tokenId); assembly { // Store the pointer of `ownership` in the `ownerships` array. mstore(add(add(ownerships, 0x20), i), ownership) } } return ownerships; } /** * @dev Returns an array of token IDs owned by `owner`, * in the range [`start`, `stop`) * (i.e. `start <= tokenId < stop`). * * This function allows for tokens to be queried if the collection * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}. * * Requirements: * * - `start < stop` */ function tokensOfOwnerIn( address owner, uint256 start, uint256 stop ) external view virtual override returns (uint256[] memory) { return _tokensOfOwnerIn(owner, start, stop); } /** * @dev Returns an array of token IDs owned by `owner`. * * This function scans the ownership mapping and is O(`totalSupply`) in complexity. * It is meant to be called off-chain. * * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into * multiple smaller scans if the collection is large enough to cause * an out-of-gas error (10K collections should be fine). */ function tokensOfOwner(address owner) external view virtual override returns (uint256[] memory) { uint256 start = _startTokenId(); uint256 stop = _nextTokenId(); uint256[] memory tokenIds; if (start != stop) tokenIds = _tokensOfOwnerIn(owner, start, stop); return tokenIds; } /** * @dev Helper function for returning an array of token IDs owned by `owner`. * * Note that this function is optimized for smaller bytecode size over runtime gas, * since it is meant to be called off-chain. */ function _tokensOfOwnerIn( address owner, uint256 start, uint256 stop ) private view returns (uint256[] memory) { unchecked { if (start >= stop) _revert(InvalidQueryRange.selector); // Set `start = max(start, _startTokenId())`. if (start < _startTokenId()) { start = _startTokenId(); } uint256 stopLimit = _nextTokenId(); // Set `stop = min(stop, stopLimit)`. if (stop >= stopLimit) { stop = stopLimit; } uint256[] memory tokenIds; uint256 tokenIdsMaxLength = balanceOf(owner); bool startLtStop = start < stop; assembly { // Set `tokenIdsMaxLength` to zero if `start` is less than `stop`. tokenIdsMaxLength := mul(tokenIdsMaxLength, startLtStop) } if (tokenIdsMaxLength != 0) { // Set `tokenIdsMaxLength = min(balanceOf(owner), stop - start)`, // to cater for cases where `balanceOf(owner)` is too big. if (stop - start <= tokenIdsMaxLength) { tokenIdsMaxLength = stop - start; } assembly { // Grab the free memory pointer. tokenIds := mload(0x40) // Allocate one word for the length, and `tokenIdsMaxLength` words // for the data. `shl(5, x)` is equivalent to `mul(32, x)`. mstore(0x40, add(tokenIds, shl(5, add(tokenIdsMaxLength, 1)))) } // We need to call `explicitOwnershipOf(start)`, // because the slot at `start` may not be initialized. TokenOwnership memory ownership = explicitOwnershipOf(start); address currOwnershipAddr; // If the starting slot exists (i.e. not burned), // initialize `currOwnershipAddr`. // `ownership.address` will not be zero, // as `start` is clamped to the valid token ID range. if (!ownership.burned) { currOwnershipAddr = ownership.addr; } uint256 tokenIdsIdx; // Use a do-while, which is slightly more efficient for this case, // as the array will at least contain one element. do { ownership = _ownershipAt(start); assembly { switch mload(add(ownership, 0x40)) // if `ownership.burned == false`. case 0 { // if `ownership.addr != address(0)`. // The `addr` already has it's upper 96 bits clearned, // since it is written to memory with regular Solidity. if mload(ownership) { currOwnershipAddr := mload(ownership) } // if `currOwnershipAddr == owner`. // The `shl(96, x)` is to make the comparison agnostic to any // dirty upper 96 bits in `owner`. if iszero(shl(96, xor(currOwnershipAddr, owner))) { tokenIdsIdx := add(tokenIdsIdx, 1) mstore(add(tokenIds, shl(5, tokenIdsIdx)), start) } } // Otherwise, reset `currOwnershipAddr`. // This handles the case of batch burned tokens // (burned bit of first slot set, remaining slots left uninitialized). default { currOwnershipAddr := 0 } start := add(start, 1) } } while (!(start == stop || tokenIdsIdx == tokenIdsMaxLength)); // Store the length of the array. assembly { mstore(tokenIds, tokenIdsIdx) } } return tokenIds; } } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721ABurnableUpgradeable.sol'; import '../ERC721AUpgradeable.sol'; import '../ERC721A__Initializable.sol'; /** * @title ERC721ABurnable. * * @dev ERC721A token that can be irreversibly burned (destroyed). */ abstract contract ERC721ABurnableUpgradeable is ERC721A__Initializable, ERC721AUpgradeable, IERC721ABurnableUpgradeable { function __ERC721ABurnable_init() internal onlyInitializingERC721A { __ERC721ABurnable_init_unchained(); } function __ERC721ABurnable_init_unchained() internal onlyInitializingERC721A {} /** * @dev Burns `tokenId`. See {ERC721A-_burn}. * * Requirements: * * - The caller must own `tokenId` or be an approved operator. */ function burn(uint256 tokenId) public virtual override { _burn(tokenId, true); } }
// 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 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 Note: /// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection. /// - For ERC20s, this implementation 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. uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000; /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* ETH OPERATIONS */ /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/ // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants. // // The regular variants: // - Forwards all remaining gas to the target. // - Reverts if the target reverts. // - Reverts if the current contract has insufficient balance. // // The force variants: // - Forwards with an optional gas stipend // (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases). // - If the target reverts, or if the gas stipend is exhausted, // creates a temporary contract to force send the ETH via `SELFDESTRUCT`. // Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758. // - Reverts if the current contract has insufficient balance. // // The try variants: // - Forwards with a mandatory gas stipend. // - Instead of reverting, returns whether the transfer succeeded. /// @dev Sends `amount` (in wei) ETH to `to`. function safeTransferETH(address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } } } /// @dev Sends all the ETH in the current contract to `to`. function safeTransferAllETH(address to) internal { /// @solidity memory-safe-assembly assembly { // Transfer all the ETH and check if it succeeded or not. if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`. function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal { /// @solidity memory-safe-assembly assembly { if lt(selfbalance(), amount) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`. function forceSafeTransferAllETH(address to, uint256 gasStipend) internal { /// @solidity memory-safe-assembly assembly { if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`. function forceSafeTransferETH(address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { if lt(selfbalance(), amount) { mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`. revert(0x1c, 0x04) } if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`. function forceSafeTransferAllETH(address to) internal { /// @solidity memory-safe-assembly assembly { // forgefmt: disable-next-item if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) { mstore(0x00, to) // Store the address in scratch space. mstore8(0x0b, 0x73) // Opcode `PUSH20`. mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`. if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation. } } } /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`. function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00) } } /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`. function trySafeTransferAllETH(address to, uint256 gasStipend) internal returns (bool success) { /// @solidity memory-safe-assembly assembly { success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00) } } /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* 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. mstore(0x60, amount) // Store the `amount` argument. mstore(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. 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 their entire balance 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(0x40, to) // Store the `to` argument. mstore(0x2c, shl(96, from)) // Store the `from` argument. mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`. // Read the balance, reverting upon failure. 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) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. revert(0x1c, 0x04) } mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`. amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20) ) ) { mstore(0x00, 0x7939f424) // `TransferFromFailed()`. 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(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @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. // Read the balance, reverting upon failure. 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, 0x34, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x14, to) // Store the `to` argument. amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it. mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`. // Perform the transfer, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x90b8ec18) // `TransferFailed()`. revert(0x1c, 0x04) } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @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(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. // Perform the approval, reverting upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`. revert(0x1c, 0x04) } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. /// If the initial attempt to approve fails, attempts to reset the approved amount to zero, /// then retries the approval again (some tokens, e.g. USDT, requires this). /// Reverts upon failure. function safeApproveWithRetry(address token, address to, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { mstore(0x14, to) // Store the `to` argument. mstore(0x34, amount) // Store the `amount` argument. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. // Perform the approval, retrying upon failure. if iszero( and( // The arguments of `and` are evaluated from right to left. or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x34, 0) // Store 0 for the `amount`. mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`. pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval. mstore(0x34, amount) // Store back the original `amount`. // Retry the approval, reverting upon failure. if iszero( and( or(eq(mload(0x00), 1), iszero(returndatasize())), // Returned 1 or nothing. call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20) ) ) { mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`. revert(0x1c, 0x04) } } mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten. } } /// @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(0x14, account) // Store the `account` argument. mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`. 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, 0x10, 0x24, 0x20, 0x20) ) ) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {Ownable} from "./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 { /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* 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 equivalent to `uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))`. uint256 private constant _ROLE_SLOT_SEED = 0x8b78c6d8; /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* INTERNAL FUNCTIONS */ /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/ /// @dev Overwrite the roles directly without authorization guard. function _setRoles(address user, uint256 roles) internal virtual { /// @solidity memory-safe-assembly assembly { mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) // Store the new value. sstore(keccak256(0x0c, 0x20), roles) // Emit the {RolesUpdated} event. log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles) } } /// @dev Updates the roles directly without authorization guard. /// If `on` is true, each set bit of `roles` will be turned on, /// otherwise, each set bit of `roles` will be turned off. function _updateRoles(address user, uint256 roles, bool on) internal virtual { /// @solidity memory-safe-assembly assembly { mstore(0x0c, _ROLE_SLOT_SEED) mstore(0x00, user) let roleSlot := keccak256(0x0c, 0x20) // Load the current value. let current := sload(roleSlot) // Compute the updated roles if `on` is true. let updated := or(current, roles) // Compute the updated roles if `on` is false. // Use `and` to compute the intersection of `current` and `roles`, // `xor` it with `current` to flip the bits in the intersection. if iszero(on) { updated := xor(current, and(current, roles)) } // Then, store the new value. sstore(roleSlot, updated) // Emit the {RolesUpdated} event. log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), updated) } } /// @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 { _updateRoles(user, roles, true); } /// @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 { _updateRoles(user, roles, false); } /// @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, 0x82b42900) // `Unauthorized()`. 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, 0x82b42900) // `Unauthorized()`. 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, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } } /// @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. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _rolesFromOrdinals(uint8[] memory ordinals) internal 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. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _ordinalsFromRoles(uint256 roles) internal 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) } } /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* 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 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 Returns whether `user` has any of `roles`. function hasAnyRole(address user, uint256 roles) public view virtual returns (bool) { return rolesOf(user) & roles != 0; } /// @dev Returns whether `user` has all of `roles`. function hasAllRoles(address user, uint256 roles) public view virtual returns (bool) { return rolesOf(user) & roles == roles; } /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* 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.4; /// @notice Library for converting numbers into strings and other string operations. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol) library LibString { /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/ /// @dev The `length` of the output is too small to contain all the hex digits. error HexLengthInsufficient(); /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/ /// @dev The constant returned when the `search` is not found in the string. uint256 internal constant NOT_FOUND = type(uint256).max; /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* DECIMAL OPERATIONS */ /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/ /// @dev Returns the base 10 decimal representation of `value`. function toString(uint256 value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned. // We will need 1 word for the trailing zeros padding, 1 word for the length, // and 3 words for a maximum of 78 digits. str := add(mload(0x40), 0x80) // Update the free memory pointer to allocate. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str let w := not(0) // Tsk. // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let temp := value } 1 {} { str := add(str, w) // `sub(str, 1)`. // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing `temp` until zero. temp := div(temp, 10) if iszero(temp) { break } } let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 0x20) // Store the length. mstore(str, length) } } /// @dev Returns the base 10 decimal representation of `value`. function toString(int256 value) internal pure returns (string memory str) { if (value >= 0) { return toString(uint256(value)); } unchecked { str = toString(uint256(-value)); } /// @solidity memory-safe-assembly assembly { // We still have some spare memory space on the left, // as we have allocated 3 words (96 bytes) for up to 78 digits. let length := mload(str) // Load the string length. mstore(str, 0x2d) // Store the '-' character. str := sub(str, 1) // Move back the string pointer by a byte. mstore(str, add(length, 1)) // Update the string length. } } /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* HEXADECIMAL OPERATIONS */ /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/ /// @dev Returns the hexadecimal representation of `value`, /// left-padded to an input length of `length` bytes. /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte, /// giving a total length of `length * 2 + 2` bytes. /// Reverts if `length` is too small for the output to contain all the digits. function toHexString(uint256 value, uint256 length) internal pure returns (string memory str) { str = toHexStringNoPrefix(value, length); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hexadecimal representation of `value`, /// left-padded to an input length of `length` bytes. /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte, /// giving a total length of `length * 2` bytes. /// Reverts if `length` is too small for the output to contain all the digits. function toHexStringNoPrefix(uint256 value, uint256 length) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // We need 0x20 bytes for the trailing zeros padding, `length * 2` bytes // for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length. // We add 0x20 to the total and round down to a multiple of 0x20. // (0x20 + 0x20 + 0x02 + 0x20) = 0x62. str := add(mload(0x40), and(add(shl(1, length), 0x42), not(0x1f))) // Allocate the memory. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end to calculate the length later. let end := str // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let start := sub(str, add(length, length)) let w := not(1) // Tsk. let temp := value // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for {} 1 {} { str := add(str, w) // `sub(str, 2)`. mstore8(add(str, 1), mload(and(temp, 15))) mstore8(str, mload(and(shr(4, temp), 15))) temp := shr(8, temp) if iszero(xor(str, start)) { break } } if temp { // Store the function selector of `HexLengthInsufficient()`. mstore(0x00, 0x2194895a) // Revert with (offset, size). revert(0x1c, 0x04) } // Compute the string's length. let strLength := sub(end, str) // Move the pointer and write the length. str := sub(str, 0x20) mstore(str, strLength) } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. /// As address are 20 bytes long, the output will left-padded to have /// a length of `20 * 2 + 2` bytes. function toHexString(uint256 value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x". /// The output excludes leading "0" from the `toHexString` output. /// `0x00: "0x0", 0x01: "0x1", 0x12: "0x12", 0x123: "0x123"`. function toMinimalHexString(uint256 value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present. let strLength := add(mload(str), 2) // Compute the length. mstore(add(str, o), 0x3078) // Write the "0x" prefix, accounting for leading zero. str := sub(add(str, o), 2) // Move the pointer, accounting for leading zero. mstore(str, sub(strLength, o)) // Write the length, accounting for leading zero. } } /// @dev Returns the hexadecimal representation of `value`. /// The output excludes leading "0" from the `toHexStringNoPrefix` output. /// `0x00: "0", 0x01: "1", 0x12: "12", 0x123: "123"`. function toMinimalHexStringNoPrefix(uint256 value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let o := eq(byte(0, mload(add(str, 0x20))), 0x30) // Whether leading zero is present. let strLength := mload(str) // Get the length. str := add(str, o) // Move the pointer, accounting for leading zero. mstore(str, sub(strLength, o)) // Write the length, accounting for leading zero. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is encoded using 2 hexadecimal digits per byte. /// As address are 20 bytes long, the output will left-padded to have /// a length of `20 * 2` bytes. function toHexStringNoPrefix(uint256 value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length, // 0x02 bytes for the prefix, and 0x40 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0. str := add(mload(0x40), 0x80) // Allocate the memory. mstore(0x40, add(str, 0x20)) // Zeroize the slot after the string. mstore(str, 0) // Cache the end to calculate the length later. let end := str // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let w := not(1) // Tsk. // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let temp := value } 1 {} { str := add(str, w) // `sub(str, 2)`. mstore8(add(str, 1), mload(and(temp, 15))) mstore8(str, mload(and(shr(4, temp), 15))) temp := shr(8, temp) if iszero(temp) { break } } // Compute the string's length. let strLength := sub(end, str) // Move the pointer and write the length. str := sub(str, 0x20) mstore(str, strLength) } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte, /// and the alphabets are capitalized conditionally according to /// https://eips.ethereum.org/EIPS/eip-55 function toHexStringChecksummed(address value) internal pure returns (string memory str) { str = toHexString(value); /// @solidity memory-safe-assembly assembly { let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...` let o := add(str, 0x22) let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... ` let t := shl(240, 136) // `0b10001000 << 240` for { let i := 0 } 1 {} { mstore(add(i, i), mul(t, byte(i, hashed))) i := add(i, 1) if eq(i, 20) { break } } mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask))))) o := add(o, 0x20) mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask))))) } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. function toHexString(address value) internal pure returns (string memory str) { str = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is encoded using 2 hexadecimal digits per byte. function toHexStringNoPrefix(address value) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { str := mload(0x40) // Allocate the memory. // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length, // 0x02 bytes for the prefix, and 0x28 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80. mstore(0x40, add(str, 0x80)) // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) str := add(str, 2) mstore(str, 40) let o := add(str, 0x20) mstore(add(o, 40), 0) value := shl(96, value) // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let i := 0 } 1 {} { let p := add(o, add(i, i)) let temp := byte(i, value) mstore8(add(p, 1), mload(and(temp, 15))) mstore8(p, mload(shr(4, temp))) i := add(i, 1) if eq(i, 20) { break } } } } /// @dev Returns the hex encoded string from the raw bytes. /// The output is encoded using 2 hexadecimal digits per byte. function toHexString(bytes memory raw) internal pure returns (string memory str) { str = toHexStringNoPrefix(raw); /// @solidity memory-safe-assembly assembly { let strLength := add(mload(str), 2) // Compute the length. mstore(str, 0x3078) // Write the "0x" prefix. str := sub(str, 2) // Move the pointer. mstore(str, strLength) // Write the length. } } /// @dev Returns the hex encoded string from the raw bytes. /// The output is encoded using 2 hexadecimal digits per byte. function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory str) { /// @solidity memory-safe-assembly assembly { let length := mload(raw) str := add(mload(0x40), 2) // Skip 2 bytes for the optional prefix. mstore(str, add(length, length)) // Store the length of the output. // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let o := add(str, 0x20) let end := add(raw, length) for {} iszero(eq(raw, end)) {} { raw := add(raw, 1) mstore8(add(o, 1), mload(and(mload(raw), 15))) mstore8(o, mload(and(shr(4, mload(raw)), 15))) o := add(o, 2) } mstore(o, 0) // Zeroize the slot after the string. mstore(0x40, add(o, 0x20)) // Allocate the memory. } } /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* RUNE STRING OPERATIONS */ /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/ /// @dev Returns the number of UTF characters in the string. function runeCount(string memory s) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { if mload(s) { mstore(0x00, div(not(0), 255)) mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506) let o := add(s, 0x20) let end := add(o, mload(s)) for { result := 1 } 1 { result := add(result, 1) } { o := add(o, byte(0, mload(shr(250, mload(o))))) if iszero(lt(o, end)) { break } } } } } /// @dev Returns if this string is a 7-bit ASCII string. /// (i.e. all characters codes are in [0..127]) function is7BitASCII(string memory s) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let mask := shl(7, div(not(0), 255)) result := 1 let n := mload(s) if n { let o := add(s, 0x20) let end := add(o, n) let last := mload(end) mstore(end, 0) for {} 1 {} { if and(mask, mload(o)) { result := 0 break } o := add(o, 0x20) if iszero(lt(o, end)) { break } } mstore(end, last) } } } /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* BYTE STRING OPERATIONS */ /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/ // For performance and bytecode compactness, all indices of the following operations // are byte (ASCII) offsets, not UTF character offsets. /// @dev Returns `subject` all occurrences of `search` replaced with `replacement`. function replace(string memory subject, string memory search, string memory replacement) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) let searchLength := mload(search) let replacementLength := mload(replacement) subject := add(subject, 0x20) search := add(search, 0x20) replacement := add(replacement, 0x20) result := add(mload(0x40), 0x20) let subjectEnd := add(subject, subjectLength) if iszero(gt(searchLength, subjectLength)) { let subjectSearchEnd := add(sub(subjectEnd, searchLength), 1) let h := 0 if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) } let m := shl(3, sub(0x20, and(searchLength, 0x1f))) let s := mload(search) for {} 1 {} { let t := mload(subject) // Whether the first `searchLength % 32` bytes of // `subject` and `search` matches. if iszero(shr(m, xor(t, s))) { if h { if iszero(eq(keccak256(subject, searchLength), h)) { mstore(result, t) result := add(result, 1) subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } continue } } // Copy the `replacement` one word at a time. for { let o := 0 } 1 {} { mstore(add(result, o), mload(add(replacement, o))) o := add(o, 0x20) if iszero(lt(o, replacementLength)) { break } } result := add(result, replacementLength) subject := add(subject, searchLength) if searchLength { if iszero(lt(subject, subjectSearchEnd)) { break } continue } } mstore(result, t) result := add(result, 1) subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } } } let resultRemainder := result result := add(mload(0x40), 0x20) let k := add(sub(resultRemainder, result), sub(subjectEnd, subject)) // Copy the rest of the string one word at a time. for {} lt(subject, subjectEnd) {} { mstore(resultRemainder, mload(subject)) resultRemainder := add(resultRemainder, 0x20) subject := add(subject, 0x20) } result := sub(result, 0x20) let last := add(add(result, 0x20), k) // Zeroize the slot after the string. mstore(last, 0) mstore(0x40, add(last, 0x20)) // Allocate the memory. mstore(result, k) // Store the length. } } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from left to right, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function indexOf(string memory subject, string memory search, uint256 from) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { for { let subjectLength := mload(subject) } 1 {} { if iszero(mload(search)) { if iszero(gt(from, subjectLength)) { result := from break } result := subjectLength break } let searchLength := mload(search) let subjectStart := add(subject, 0x20) result := not(0) // Initialize to `NOT_FOUND`. subject := add(subjectStart, from) let end := add(sub(add(subjectStart, subjectLength), searchLength), 1) let m := shl(3, sub(0x20, and(searchLength, 0x1f))) let s := mload(add(search, 0x20)) if iszero(and(lt(subject, end), lt(from, subjectLength))) { break } if iszero(lt(searchLength, 0x20)) { for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} { if iszero(shr(m, xor(mload(subject), s))) { if eq(keccak256(subject, searchLength), h) { result := sub(subject, subjectStart) break } } subject := add(subject, 1) if iszero(lt(subject, end)) { break } } break } for {} 1 {} { if iszero(shr(m, xor(mload(subject), s))) { result := sub(subject, subjectStart) break } subject := add(subject, 1) if iszero(lt(subject, end)) { break } } break } } } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from left to right. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function indexOf(string memory subject, string memory search) internal pure returns (uint256 result) { result = indexOf(subject, search, 0); } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from right to left, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function lastIndexOf(string memory subject, string memory search, uint256 from) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { for {} 1 {} { result := not(0) // Initialize to `NOT_FOUND`. let searchLength := mload(search) if gt(searchLength, mload(subject)) { break } let w := result let fromMax := sub(mload(subject), searchLength) if iszero(gt(fromMax, from)) { from := fromMax } let end := add(add(subject, 0x20), w) subject := add(add(subject, 0x20), from) if iszero(gt(subject, end)) { break } // As this function is not too often used, // we shall simply use keccak256 for smaller bytecode size. for { let h := keccak256(add(search, 0x20), searchLength) } 1 {} { if eq(keccak256(subject, searchLength), h) { result := sub(subject, add(end, 1)) break } subject := add(subject, w) // `sub(subject, 1)`. if iszero(gt(subject, end)) { break } } break } } } /// @dev Returns the byte index of the first location of `search` in `subject`, /// searching from right to left. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `search` is not found. function lastIndexOf(string memory subject, string memory search) internal pure returns (uint256 result) { result = lastIndexOf(subject, search, uint256(int256(-1))); } /// @dev Returns whether `subject` starts with `search`. function startsWith(string memory subject, string memory search) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let searchLength := mload(search) // Just using keccak256 directly is actually cheaper. // forgefmt: disable-next-item result := and( iszero(gt(searchLength, mload(subject))), eq( keccak256(add(subject, 0x20), searchLength), keccak256(add(search, 0x20), searchLength) ) ) } } /// @dev Returns whether `subject` ends with `search`. function endsWith(string memory subject, string memory search) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let searchLength := mload(search) let subjectLength := mload(subject) // Whether `search` is not longer than `subject`. let withinRange := iszero(gt(searchLength, subjectLength)) // Just using keccak256 directly is actually cheaper. // forgefmt: disable-next-item result := and( withinRange, eq( keccak256( // `subject + 0x20 + max(subjectLength - searchLength, 0)`. add(add(subject, 0x20), mul(withinRange, sub(subjectLength, searchLength))), searchLength ), keccak256(add(search, 0x20), searchLength) ) ) } } /// @dev Returns `subject` repeated `times`. function repeat(string memory subject, uint256 times) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) if iszero(or(iszero(times), iszero(subjectLength))) { subject := add(subject, 0x20) result := mload(0x40) let output := add(result, 0x20) for {} 1 {} { // Copy the `subject` one word at a time. for { let o := 0 } 1 {} { mstore(add(output, o), mload(add(subject, o))) o := add(o, 0x20) if iszero(lt(o, subjectLength)) { break } } output := add(output, subjectLength) times := sub(times, 1) if iszero(times) { break } } mstore(output, 0) // Zeroize the slot after the string. let resultLength := sub(output, add(result, 0x20)) mstore(result, resultLength) // Store the length. // Allocate the memory. mstore(0x40, add(result, add(resultLength, 0x20))) } } } /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive). /// `start` and `end` are byte offsets. function slice(string memory subject, uint256 start, uint256 end) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) if iszero(gt(subjectLength, end)) { end := subjectLength } if iszero(gt(subjectLength, start)) { start := subjectLength } if lt(start, end) { result := mload(0x40) let resultLength := sub(end, start) mstore(result, resultLength) subject := add(subject, start) let w := not(0x1f) // Copy the `subject` one word at a time, backwards. for { let o := and(add(resultLength, 0x1f), w) } 1 {} { mstore(add(result, o), mload(add(subject, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } // Zeroize the slot after the string. mstore(add(add(result, 0x20), resultLength), 0) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, add(result, and(add(resultLength, 0x3f), w))) } } } /// @dev Returns a copy of `subject` sliced from `start` to the end of the string. /// `start` is a byte offset. function slice(string memory subject, uint256 start) internal pure returns (string memory result) { result = slice(subject, start, uint256(int256(-1))); } /// @dev Returns all the indices of `search` in `subject`. /// The indices are byte offsets. function indicesOf(string memory subject, string memory search) internal pure returns (uint256[] memory result) { /// @solidity memory-safe-assembly assembly { let subjectLength := mload(subject) let searchLength := mload(search) if iszero(gt(searchLength, subjectLength)) { subject := add(subject, 0x20) search := add(search, 0x20) result := add(mload(0x40), 0x20) let subjectStart := subject let subjectSearchEnd := add(sub(add(subject, subjectLength), searchLength), 1) let h := 0 if iszero(lt(searchLength, 0x20)) { h := keccak256(search, searchLength) } let m := shl(3, sub(0x20, and(searchLength, 0x1f))) let s := mload(search) for {} 1 {} { let t := mload(subject) // Whether the first `searchLength % 32` bytes of // `subject` and `search` matches. if iszero(shr(m, xor(t, s))) { if h { if iszero(eq(keccak256(subject, searchLength), h)) { subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } continue } } // Append to `result`. mstore(result, sub(subject, subjectStart)) result := add(result, 0x20) // Advance `subject` by `searchLength`. subject := add(subject, searchLength) if searchLength { if iszero(lt(subject, subjectSearchEnd)) { break } continue } } subject := add(subject, 1) if iszero(lt(subject, subjectSearchEnd)) { break } } let resultEnd := result // Assign `result` to the free memory pointer. result := mload(0x40) // Store the length of `result`. mstore(result, shr(5, sub(resultEnd, add(result, 0x20)))) // Allocate memory for result. // We allocate one more word, so this array can be recycled for {split}. mstore(0x40, add(resultEnd, 0x20)) } } } /// @dev Returns a arrays of strings based on the `delimiter` inside of the `subject` string. function split(string memory subject, string memory delimiter) internal pure returns (string[] memory result) { uint256[] memory indices = indicesOf(subject, delimiter); /// @solidity memory-safe-assembly assembly { let w := not(0x1f) let indexPtr := add(indices, 0x20) let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1))) mstore(add(indicesEnd, w), mload(subject)) mstore(indices, add(mload(indices), 1)) let prevIndex := 0 for {} 1 {} { let index := mload(indexPtr) mstore(indexPtr, 0x60) if iszero(eq(index, prevIndex)) { let element := mload(0x40) let elementLength := sub(index, prevIndex) mstore(element, elementLength) // Copy the `subject` one word at a time, backwards. for { let o := and(add(elementLength, 0x1f), w) } 1 {} { mstore(add(element, o), mload(add(add(subject, prevIndex), o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } // Zeroize the slot after the string. mstore(add(add(element, 0x20), elementLength), 0) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, add(element, and(add(elementLength, 0x3f), w))) // Store the `element` into the array. mstore(indexPtr, element) } prevIndex := add(index, mload(delimiter)) indexPtr := add(indexPtr, 0x20) if iszero(lt(indexPtr, indicesEnd)) { break } } result := indices if iszero(mload(delimiter)) { result := add(indices, 0x20) mstore(result, sub(mload(indices), 2)) } } } /// @dev Returns a concatenated string of `a` and `b`. /// Cheaper than `string.concat()` and does not de-align the free memory pointer. function concat(string memory a, string memory b) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let w := not(0x1f) result := mload(0x40) let aLength := mload(a) // Copy `a` one word at a time, backwards. for { let o := and(add(aLength, 0x20), w) } 1 {} { mstore(add(result, o), mload(add(a, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } let bLength := mload(b) let output := add(result, aLength) // Copy `b` one word at a time, backwards. for { let o := and(add(bLength, 0x20), w) } 1 {} { mstore(add(output, o), mload(add(b, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } let totalLength := add(aLength, bLength) let last := add(add(result, 0x20), totalLength) // Zeroize the slot after the string. mstore(last, 0) // Stores the length. mstore(result, totalLength) // Allocate memory for the length and the bytes, // rounded up to a multiple of 32. mstore(0x40, and(add(last, 0x1f), w)) } } /// @dev Returns a copy of the string in either lowercase or UPPERCASE. /// WARNING! This function is only compatible with 7-bit ASCII strings. function toCase(string memory subject, bool toUpper) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let length := mload(subject) if length { result := add(mload(0x40), 0x20) subject := add(subject, 1) let flags := shl(add(70, shl(5, toUpper)), 0x3ffffff) let w := not(0) for { let o := length } 1 {} { o := add(o, w) let b := and(0xff, mload(add(subject, o))) mstore8(add(result, o), xor(b, and(shr(b, flags), 0x20))) if iszero(o) { break } } result := mload(0x40) mstore(result, length) // Store the length. let last := add(add(result, 0x20), length) mstore(last, 0) // Zeroize the slot after the string. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } } /// @dev Returns a string from a small bytes32 string. /// `smallString` must be null terminated, or behavior will be undefined. function fromSmallString(bytes32 smallString) internal pure returns (string memory result) { if (smallString == bytes32(0)) return result; /// @solidity memory-safe-assembly assembly { result := mload(0x40) let n := 0 for {} 1 {} { n := add(n, 1) if iszero(byte(n, smallString)) { break } // Scan for '\0'. } mstore(result, n) let o := add(result, 0x20) mstore(o, smallString) mstore(add(o, n), 0) mstore(0x40, add(result, 0x40)) } } /// @dev Returns a lowercased copy of the string. /// WARNING! This function is only compatible with 7-bit ASCII strings. function lower(string memory subject) internal pure returns (string memory result) { result = toCase(subject, false); } /// @dev Returns an UPPERCASED copy of the string. /// WARNING! This function is only compatible with 7-bit ASCII strings. function upper(string memory subject) internal pure returns (string memory result) { result = toCase(subject, true); } /// @dev Escapes the string to be used within HTML tags. function escapeHTML(string memory s) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let end := add(s, mload(s)) result := add(mload(0x40), 0x20) // Store the bytes of the packed offsets and strides into the scratch space. // `packed = (stride << 5) | offset`. Max offset is 20. Max stride is 6. mstore(0x1f, 0x900094) mstore(0x08, 0xc0000000a6ab) // Store ""&'<>" into the scratch space. mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b)) for {} iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) // Not in `["\"","'","&","<",">"]`. if iszero(and(shl(c, 1), 0x500000c400000000)) { mstore8(result, c) result := add(result, 1) continue } let t := shr(248, mload(c)) mstore(result, mload(and(t, 0x1f))) result := add(result, shr(5, t)) } let last := result mstore(last, 0) // Zeroize the slot after the string. result := mload(0x40) mstore(result, sub(last, add(result, 0x20))) // Store the length. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } /// @dev Escapes the string to be used within double-quotes in a JSON. /// If `addDoubleQuotes` is true, the result will be enclosed in double-quotes. function escapeJSON(string memory s, bool addDoubleQuotes) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let end := add(s, mload(s)) result := add(mload(0x40), 0x20) if addDoubleQuotes { mstore8(result, 34) result := add(1, result) } // Store "\\u0000" in scratch space. // Store "0123456789abcdef" in scratch space. // Also, store `{0x08:"b", 0x09:"t", 0x0a:"n", 0x0c:"f", 0x0d:"r"}`. // into the scratch space. mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672) // Bitmask for detecting `["\"","\\"]`. let e := or(shl(0x22, 1), shl(0x5c, 1)) for {} iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) if iszero(lt(c, 0x20)) { if iszero(and(shl(c, 1), e)) { // Not in `["\"","\\"]`. mstore8(result, c) result := add(result, 1) continue } mstore8(result, 0x5c) // "\\". mstore8(add(result, 1), c) result := add(result, 2) continue } if iszero(and(shl(c, 1), 0x3700)) { // Not in `["\b","\t","\n","\f","\d"]`. mstore8(0x1d, mload(shr(4, c))) // Hex value. mstore8(0x1e, mload(and(c, 15))) // Hex value. mstore(result, mload(0x19)) // "\\u00XX". result := add(result, 6) continue } mstore8(result, 0x5c) // "\\". mstore8(add(result, 1), mload(add(c, 8))) result := add(result, 2) } if addDoubleQuotes { mstore8(result, 34) result := add(1, result) } let last := result mstore(last, 0) // Zeroize the slot after the string. result := mload(0x40) mstore(result, sub(last, add(result, 0x20))) // Store the length. mstore(0x40, add(last, 0x20)) // Allocate the memory. } } /// @dev Escapes the string to be used within double-quotes in a JSON. function escapeJSON(string memory s) internal pure returns (string memory result) { result = escapeJSON(s, false); } /// @dev Returns whether `a` equals `b`. function eq(string memory a, string memory b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b))) } } /// @dev Returns whether `a` equals `b`. For small strings up to 32 bytes. /// `b` must be null terminated, or behavior will be undefined. function eqs(string memory a, bytes32 b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { // These should be evaluated on compile time, as far as possible. let x := and(b, add(not(b), 1)) let r := or(shl(8, iszero(b)), shl(7, iszero(iszero(shr(128, x))))) r := or(r, shl(6, iszero(iszero(shr(64, 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)))) result := gt(eq(mload(a), sub(32, shr(3, r))), shr(r, xor(b, mload(add(a, 0x20))))) } } /// @dev Packs a single string with its length into a single word. /// Returns `bytes32(0)` if the length is zero or greater than 31. function packOne(string memory a) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { // We don't need to zero right pad the string, // since this is our own custom non-standard packing scheme. result := mul( // Load the length and the bytes. mload(add(a, 0x1f)), // `length != 0 && length < 32`. Abuses underflow. // Assumes that the length is valid and within the block gas limit. lt(sub(mload(a), 1), 0x1f) ) } } /// @dev Unpacks a string packed using {packOne}. /// Returns the empty string if `packed` is `bytes32(0)`. /// If `packed` is not an output of {packOne}, the output behavior is undefined. function unpackOne(bytes32 packed) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { // Grab the free memory pointer. result := mload(0x40) // Allocate 2 words (1 for the length, 1 for the bytes). mstore(0x40, add(result, 0x40)) // Zeroize the length slot. mstore(result, 0) // Store the length and bytes. mstore(add(result, 0x1f), packed) // Right pad with zeroes. mstore(add(add(result, 0x20), mload(result)), 0) } } /// @dev Packs two strings with their lengths into a single word. /// Returns `bytes32(0)` if combined length is zero or greater than 30. function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { let aLength := mload(a) // We don't need to zero right pad the strings, // since this is our own custom non-standard packing scheme. result := mul( // Load the length and the bytes of `a` and `b`. or( shl(shl(3, sub(0x1f, aLength)), mload(add(a, aLength))), mload(sub(add(b, 0x1e), aLength)) ), // `totalLength != 0 && totalLength < 31`. Abuses underflow. // Assumes that the lengths are valid and within the block gas limit. lt(sub(add(aLength, mload(b)), 1), 0x1e) ) } } /// @dev Unpacks strings packed using {packTwo}. /// Returns the empty strings if `packed` is `bytes32(0)`. /// If `packed` is not an output of {packTwo}, the output behavior is undefined. function unpackTwo(bytes32 packed) internal pure returns (string memory resultA, string memory resultB) { /// @solidity memory-safe-assembly assembly { // Grab the free memory pointer. resultA := mload(0x40) resultB := add(resultA, 0x40) // Allocate 2 words for each string (1 for the length, 1 for the byte). Total 4 words. mstore(0x40, add(resultB, 0x40)) // Zeroize the length slots. mstore(resultA, 0) mstore(resultB, 0) // Store the lengths and bytes. mstore(add(resultA, 0x1f), packed) mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA)))) // Right pad with zeroes. mstore(add(add(resultA, 0x20), mload(resultA)), 0) mstore(add(add(resultB, 0x20), mload(resultB)), 0) } } /// @dev Directly returns `a` without copying. function directReturn(string memory a) internal pure { assembly { // Assumes that the string does not start from the scratch space. let retStart := sub(a, 0x20) let retSize := add(mload(a), 0x40) // Right pad with zeroes. Just in case the string is produced // by a method that doesn't zero right pad. mstore(add(retStart, retSize), 0) // Store the return offset. mstore(retStart, 0x20) // End the transaction, returning the string. return(retStart, retSize) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library for storage of packed unsigned integers. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibMap.sol) library LibMap { /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* STRUCTS */ /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/ /// @dev A uint8 map in storage. struct Uint8Map { mapping(uint256 => uint256) map; } /// @dev A uint16 map in storage. struct Uint16Map { mapping(uint256 => uint256) map; } /// @dev A uint32 map in storage. struct Uint32Map { mapping(uint256 => uint256) map; } /// @dev A uint40 map in storage. Useful for storing timestamps up to 34841 A.D. struct Uint40Map { mapping(uint256 => uint256) map; } /// @dev A uint64 map in storage. struct Uint64Map { mapping(uint256 => uint256) map; } /// @dev A uint128 map in storage. struct Uint128Map { mapping(uint256 => uint256) map; } /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* GETTERS / SETTERS */ /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/ /// @dev Returns the uint8 value at `index` in `map`. function get(Uint8Map storage map, uint256 index) internal view returns (uint8 result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(5, index)) result := byte(and(31, not(index)), sload(keccak256(0x00, 0x40))) } } /// @dev Updates the uint8 value at `index` in `map`. function set(Uint8Map storage map, uint256 index, uint8 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(5, index)) let s := keccak256(0x00, 0x40) // Storage slot. mstore(0x00, sload(s)) mstore8(and(31, not(index)), value) sstore(s, mload(0x00)) } } /// @dev Returns the uint16 value at `index` in `map`. function get(Uint16Map storage map, uint256 index) internal view returns (uint16 result) { result = uint16(map.map[index >> 4] >> ((index & 15) << 4)); } /// @dev Updates the uint16 value at `index` in `map`. function set(Uint16Map storage map, uint256 index, uint16 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(4, index)) let s := keccak256(0x00, 0x40) // Storage slot. let o := shl(4, and(index, 15)) // Storage slot offset (bits). let v := sload(s) // Storage slot value. let m := 0xffff // Value mask. sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value))))) } } /// @dev Returns the uint32 value at `index` in `map`. function get(Uint32Map storage map, uint256 index) internal view returns (uint32 result) { result = uint32(map.map[index >> 3] >> ((index & 7) << 5)); } /// @dev Updates the uint32 value at `index` in `map`. function set(Uint32Map storage map, uint256 index, uint32 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(3, index)) let s := keccak256(0x00, 0x40) // Storage slot. let o := shl(5, and(index, 7)) // Storage slot offset (bits). let v := sload(s) // Storage slot value. let m := 0xffffffff // Value mask. sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value))))) } } /// @dev Returns the uint40 value at `index` in `map`. function get(Uint40Map storage map, uint256 index) internal view returns (uint40 result) { unchecked { result = uint40(map.map[index / 6] >> ((index % 6) * 40)); } } /// @dev Updates the uint40 value at `index` in `map`. function set(Uint40Map storage map, uint256 index, uint40 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, div(index, 6)) let s := keccak256(0x00, 0x40) // Storage slot. let o := mul(40, mod(index, 6)) // Storage slot offset (bits). let v := sload(s) // Storage slot value. let m := 0xffffffffff // Value mask. sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value))))) } } /// @dev Returns the uint64 value at `index` in `map`. function get(Uint64Map storage map, uint256 index) internal view returns (uint64 result) { result = uint64(map.map[index >> 2] >> ((index & 3) << 6)); } /// @dev Updates the uint64 value at `index` in `map`. function set(Uint64Map storage map, uint256 index, uint64 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(2, index)) let s := keccak256(0x00, 0x40) // Storage slot. let o := shl(6, and(index, 3)) // Storage slot offset (bits). let v := sload(s) // Storage slot value. let m := 0xffffffffffffffff // Value mask. sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value))))) } } /// @dev Returns the uint128 value at `index` in `map`. function get(Uint128Map storage map, uint256 index) internal view returns (uint128 result) { result = uint128(map.map[index >> 1] >> ((index & 1) << 7)); } /// @dev Updates the uint128 value at `index` in `map`. function set(Uint128Map storage map, uint256 index, uint128 value) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, map.slot) mstore(0x00, shr(1, index)) let s := keccak256(0x00, 0x40) // Storage slot. let o := shl(7, and(index, 1)) // Storage slot offset (bits). let v := sload(s) // Storage slot value. let m := 0xffffffffffffffffffffffffffffffff // Value mask. sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value))))) } } /// @dev Returns the value at `index` in `map`. function get(mapping(uint256 => uint256) storage map, uint256 index, uint256 bitWidth) internal view returns (uint256 result) { unchecked { uint256 d = _rawDiv(256, bitWidth); // Bucket size. uint256 m = (1 << bitWidth) - 1; // Value mask. result = (map[_rawDiv(index, d)] >> (_rawMod(index, d) * bitWidth)) & m; } } /// @dev Updates the value at `index` in `map`. function set( mapping(uint256 => uint256) storage map, uint256 index, uint256 value, uint256 bitWidth ) internal { unchecked { uint256 d = _rawDiv(256, bitWidth); // Bucket size. uint256 m = (1 << bitWidth) - 1; // Value mask. uint256 o = _rawMod(index, d) * bitWidth; // Storage slot offset (bits). map[_rawDiv(index, d)] ^= (((map[_rawDiv(index, d)] >> o) ^ value) & m) << o; } } /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* BINARY SEARCH */ /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/ // The following functions search in the range of [`start`, `end`) // (i.e. `start <= index < end`). // The range must be sorted in ascending order. // `index` precedence: equal to > nearest before > nearest after. // An invalid search range will simply return `(found = false, index = start)`. /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint8Map storage map, uint8 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 8); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint16Map storage map, uint16 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 16); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint32Map storage map, uint32 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 32); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint40Map storage map, uint40 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 40); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint64Map storage map, uint64 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 64); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted(Uint128Map storage map, uint128 needle, uint256 start, uint256 end) internal view returns (bool found, uint256 index) { return searchSorted(map.map, needle, start, end, 128); } /// @dev Returns whether `map` contains `needle`, and the index of `needle`. function searchSorted( mapping(uint256 => uint256) storage map, uint256 needle, uint256 start, uint256 end, uint256 bitWidth ) internal view returns (bool found, uint256 index) { unchecked { if (start >= end) end = start; uint256 t; uint256 o = start - 1; // Offset to derive the actual index. uint256 l = 1; // Low. uint256 d = _rawDiv(256, bitWidth); // Bucket size. uint256 m = (1 << bitWidth) - 1; // Value mask. uint256 h = end - start; // High. while (true) { index = (l & h) + ((l ^ h) >> 1); if (l > h) break; t = (map[_rawDiv(index + o, d)] >> (_rawMod(index + o, d) * bitWidth)) & m; if (t == needle) break; if (needle <= t) h = index - 1; else l = index + 1; } /// @solidity memory-safe-assembly assembly { m := or(iszero(index), iszero(bitWidth)) found := iszero(or(xor(t, needle), m)) index := add(o, xor(index, mul(xor(index, 1), m))) } } } /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* PRIVATE HELPERS */ /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/ /// @dev Returns `x / y`, returning 0 if `y` is zero. function _rawDiv(uint256 x, uint256 y) private pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := div(x, y) } } /// @dev Returns `x % y`, returning 0 if `y` is zero. function _rawMod(uint256 x, uint256 y) private pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mod(x, y) } } }
// 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. * * @dev Note: * The functions in this library do NOT guard against reentrancy. * A single transaction can recurse through different Multicallers * (e.g. `MulticallerWithSender -> contract -> MulticallerWithSigner -> contract`). * * Think of these functions like `msg.sender`. * * If your contract `C` can handle reentrancy safely with plain old `msg.sender` * for any `A -> C -> B -> C`, you should be fine substituting `msg.sender` with these functions. */ library LibMulticaller { /** * @dev The address of the multicaller contract. */ address internal constant MULTICALLER = 0x0000000000002Bdbf1Bf3279983603Ec279CC6dF; /** * @dev The address of the multicaller with sender contract. */ address internal constant MULTICALLER_WITH_SENDER = 0x00000000002Fd5Aeb385D324B580FCa7c83823A0; /** * @dev The address of the multicaller with signer contract. */ address internal constant MULTICALLER_WITH_SIGNER = 0x000000000000D9ECebf3C23529de49815Dac1c4c; /** * @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`. */ function multicallerSender() internal view returns (address result) { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x00) if iszero(staticcall(gas(), MULTICALLER_WITH_SENDER, codesize(), 0x00, 0x00, 0x20)) { revert(codesize(), codesize()) // For better gas estimation. } result := mload(0x00) } } /** * @dev Returns the signer of `aggregateWithSigner` on `MULTICALLER_WITH_SIGNER`. */ function multicallerSigner() internal view returns (address result) { /// @solidity memory-safe-assembly assembly { mstore(0x00, 0x00) if iszero(staticcall(gas(), MULTICALLER_WITH_SIGNER, codesize(), 0x00, 0x00, 0x20)) { revert(codesize(), codesize()) // For better gas estimation. } result := mload(0x00) } } /** * @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 { mstore(0x00, caller()) let withSender := MULTICALLER_WITH_SENDER if eq(caller(), withSender) { if iszero(staticcall(gas(), withSender, codesize(), 0x00, 0x00, 0x20)) { revert(codesize(), codesize()) // For better gas estimation. } } result := mload(0x00) } } /** * @dev Returns the caller of `aggregateWithSigner` on `MULTICALLER_WITH_SIGNER`, * if the current context's `msg.sender` is `MULTICALLER_WITH_SIGNER`. * Otherwise, returns `msg.sender`. */ function signer() internal view returns (address result) { /// @solidity memory-safe-assembly assembly { mstore(0x00, caller()) let withSigner := MULTICALLER_WITH_SIGNER if eq(caller(), withSigner) { if iszero(staticcall(gas(), withSigner, codesize(), 0x00, 0x00, 0x20)) { revert(codesize(), codesize()) // For better gas estimation. } } result := mload(0x00) } } /** * @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`, * if the current context's `msg.sender` is `MULTICALLER_WITH_SENDER`. * Returns the signer of `aggregateWithSigner` on `MULTICALLER_WITH_SIGNER`, * if the current context's `msg.sender` is `MULTICALLER_WITH_SIGNER`. * Otherwise, returns `msg.sender`. */ function senderOrSigner() internal view returns (address result) { /// @solidity memory-safe-assembly assembly { mstore(0x00, caller()) let withSender := MULTICALLER_WITH_SENDER if eq(caller(), withSender) { if iszero(staticcall(gas(), withSender, codesize(), 0x00, 0x00, 0x20)) { revert(codesize(), codesize()) // For better gas estimation. } } let withSigner := MULTICALLER_WITH_SIGNER if eq(caller(), withSigner) { if iszero(staticcall(gas(), withSigner, codesize(), 0x00, 0x00, 0x20)) { revert(codesize(), codesize()) // For better gas estimation. } } result := mload(0x00) } } }
// 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"; /** * @title ISoundEditionV2_1 * @notice The interface for Sound edition contracts. */ interface ISoundEditionV2_1 is IERC721AUpgradeable, IERC2981Upgradeable { // ============================================================= // STRUCTS // ============================================================= /** * @dev The information pertaining to a tier. */ struct TierInfo { // The tier. uint8 tier; // The current max mintable amount. uint32 maxMintable; // The lower bound of the maximum number of tokens that can be minted for the tier. uint32 maxMintableLower; // The upper bound of the maximum number of tokens that can be minted for the tier. uint32 maxMintableUpper; // The timestamp (in seconds since unix epoch) after which the // max amount of tokens mintable for the tier will drop from // `maxMintableUpper` to `maxMintableLower`. uint32 cutoffTime; // The total number of tokens minted for the tier. uint32 minted; // The mint randomness for the tier. uint256 mintRandomness; // Whether the tier mints have concluded. bool mintConcluded; // Whether the tier has mint randomness enabled. bool mintRandomnessEnabled; // Whether the tier is frozen. bool isFrozen; } /** * @dev A struct containing the arguments for creating a tier. */ struct TierCreation { // The tier. uint8 tier; // The lower bound of the maximum number of tokens that can be minted for the tier. uint32 maxMintableLower; // The upper bound of the maximum number of tokens that can be minted for the tier. uint32 maxMintableUpper; // The timestamp (in seconds since unix epoch) after which the // max amount of tokens mintable for the tier will drop from // `maxMintableUpper` to `maxMintableLower`. uint32 cutoffTime; // Whether the tier has mint randomness enabled. bool mintRandomnessEnabled; // Whether the tier is frozen. bool isFrozen; } /** * @dev The information pertaining to this edition. */ struct EditionInfo { // Base URI for the metadata. 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; // Address of the metadata module. Optional. address metadataModule; // Whether the metadata is frozen. bool isMetadataFrozen; // Whether the ability to create tiers is frozen. bool isCreateTierFrozen; // The royalty BPS (basis points). uint16 royaltyBPS; // 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; // An array of tier info. From lowest (0-indexed) to highest. TierInfo[] tierInfo; } /** * @dev A struct containing the arguments for initialization. */ struct EditionInitialization { // Name of the collection. string name; // Symbol of the collection. string symbol; // Address of the metadata module. Optional. address metadataModule; // Base URI for the metadata. string baseURI; // Contract URI for OpenSea storefront. string contractURI; // Address that receives primary and secondary royalties. address fundingRecipient; // The royalty BPS (basis points). uint16 royaltyBPS; // Whether the metadata is frozen. bool isMetadataFrozen; // Whether the ability to create tiers is frozen. bool isCreateTierFrozen; // An array of tier creation structs. From lowest (0-indexed) to highest. TierCreation[] tierCreations; } // ============================================================= // 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 ability to create tier is removed. */ event CreateTierFrozen(); /** * @dev Emitted when the `fundingRecipient` is set. * @param recipient The address of the funding recipient. */ event FundingRecipientSet(address recipient); /** * @dev Emitted when the `royaltyBPS` is set. * @param bps The new royalty, measured in basis points. */ event RoyaltySet(uint16 bps); /** * @dev Emitted when the tier's maximum mintable token quantity range is set. * @param tier The tier. * @param lower The lower limit of the maximum number of tokens that can be minted. * @param upper The upper limit of the maximum number of tokens that can be minted. */ event MaxMintableRangeSet(uint8 tier, uint32 lower, uint32 upper); /** * @dev Emitted when the tier's cutoff time set. * @param tier The tier. * @param cutoff The timestamp. */ event CutoffTimeSet(uint8 tier, uint32 cutoff); /** * @dev Emitted when the `mintRandomnessEnabled` for the tier is set. * @param tier The tier. * @param enabled The boolean value. */ event MintRandomnessEnabledSet(uint8 tier, bool enabled); /** * @dev Emitted upon initialization. * @param init The initialization data. */ event SoundEditionInitialized(EditionInitialization init); /** * @dev Emitted when a tier is created. * @param creation The tier creation data. */ event TierCreated(TierCreation creation); /** * @dev Emitted when a tier is frozen. * @param tier The tier. */ event TierFrozen(uint8 tier); /** * @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 tier The tier. * @param to The address to mint to. * @param quantity The number of minted. * @param fromTokenId The first token ID minted. */ event Minted(uint8 tier, address to, uint256 quantity, uint256 fromTokenId); /** * @dev Emitted upon an airdrop. * @param tier The tier. * @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(uint8 tier, 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); // ============================================================= // ERRORS // ============================================================= /** * @dev The edition's metadata is frozen (e.g.: `baseURI` can no longer be changed). */ error MetadataIsFrozen(); /** * @dev The ability to create tiers is frozen. */ error CreateTierIsFrozen(); /** * @dev The given `royaltyBPS` is invalid. */ error InvalidRoyaltyBPS(); /** * @dev A minimum of one tier must be provided to initialize a Sound Edition. */ error ZeroTiersProvided(); /** * @dev The requested quantity exceeds the edition's remaining mintable token quantity. */ error ExceedsAvailableSupply(); /** * @dev The given `fundingRecipient` address is invalid. */ error InvalidFundingRecipient(); /** * @dev The `maxMintableLower` must not be greater than `maxMintableUpper`. */ error InvalidMaxMintableRange(); /** * @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 Cannot perform the operation after a token has been minted in the tier. */ error TierMintsAlreadyExist(); /** * @dev The token IDs must be in strictly ascending order. */ error TokenIdsNotStrictlyAscending(); /** * @dev The tier does not exist. */ error TierDoesNotExist(); /** * @dev The tier already exists. */ error TierAlreadyExists(); /** * @dev The tier is frozen. */ error TierIsFrozen(); /** * @dev One of more of the tokens do not have the correct token tier. */ error InvalidTokenTier(); /** * @dev Please wait for a while before you burn. */ error CannotBurnImmediately(); /** * @dev The token for the tier query doesn't exist. */ error TierQueryForNonexistentToken(); // ============================================================= // PUBLIC / EXTERNAL WRITE FUNCTIONS // ============================================================= /** * @dev Initializes the contract. * @param init The initialization struct. */ function initialize(EditionInitialization calldata init) 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 tier The tier. * @param to Address to mint to. * @param quantity Number of tokens to mint. * @return fromTokenId The first token ID minted. */ function mint( uint8 tier, 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 tier The tier. * @param to Address to mint to. * @param quantity Number of tokens to mint. * @return fromTokenId The first token ID minted. */ function airdrop( uint8 tier, address[] calldata to, uint256 quantity ) external payable 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 Freezes the max tier by preventing any more tiers from being added, * * Calling conditions: * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`. */ function freezeCreateTier() 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 Creates a new split wallet via the SplitMain contract, then sets it as the `fundingRecipient`. * * Calling conditions: * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`. * * @param splitMain The address of the SplitMain contract. * @param splitData The calldata to forward to the SplitMain contract to create a split. * @return split The address of the new split contract. */ function createSplit(address splitMain, bytes calldata splitData) external returns (address split); /** * @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 Freezes the tier. * * Calling conditions: * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`. * * @param tier The tier. */ function freezeTier(uint8 tier) 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 tier The tier. * @param lower The lower limit of the maximum number of tokens that can be minted. * @param upper The upper limit of the maximum number of tokens that can be minted. */ function setMaxMintableRange( uint8 tier, uint32 lower, uint32 upper ) 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 tier The tier. * @param cutoffTime The timestamp. */ function setCutoffTime(uint8 tier, uint32 cutoffTime) 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 tier The tier. * @param enabled The boolean value. */ function setMintRandomnessEnabled(uint8 tier, bool enabled) external; /** * @dev Adds a new tier. * * Calling conditions: * - The caller must be the owner of the contract, or have the `ADMIN_ROLE`. * * @param creation The tier creation data. */ function createTier(TierCreation calldata creation) external; /** * @dev Emits an event to signal to marketplaces to refresh all the metadata. */ function emitAllMetadataUpdate() external; // ============================================================= // PUBLIC / EXTERNAL VIEW FUNCTIONS // ============================================================= /** * @dev Returns the edition info. * @return info The latest value. */ function editionInfo() external view returns (EditionInfo memory info); /** * @dev Returns the tier info. * @param tier The tier. * @return info The latest value. */ function tierInfo(uint8 tier) external view returns (TierInfo memory info); /** * @dev Returns the GA tier, which is 0. * @return The constant value. */ function GA_TIER() external pure returns (uint8); /** * @dev Basis points denominator used in fee calculations. * @return The constant value. */ function BPS_DENOMINATOR() external pure returns (uint16); /** * @dev Returns the minter role flag. * Note: This constant will always be 2 for past and future sound protocol contracts. * @return The constant value. */ function MINTER_ROLE() external view returns (uint256); /** * @dev Returns the admin role flag. * Note: This constant will always be 1 for past and future sound protocol contracts. * @return The constant value. */ function ADMIN_ROLE() external view returns (uint256); /** * @dev Returns the tier of the `tokenId`. * @param tokenId The token ID. * @return The latest value. */ function tokenTier(uint256 tokenId) external view returns (uint8); /** * @dev Returns the tier of the `tokenId`. * Note: Will NOT revert if any `tokenId` does not exist. * If the token has not been minted, the tier will be zero. * If the token is burned, the tier will be the tier before it was burned. * @param tokenId The token ID. * @return The latest value. */ function explicitTokenTier(uint256 tokenId) external view returns (uint8); /** * @dev Returns the tiers of the `tokenIds`. * Note: Will NOT revert if any `tokenId` does not exist. * If the token has not been minted, the tier will be zero. * If the token is burned, the tier will be the tier before it was burned. * @param tokenIds The token IDs. * @return The latest values. */ function tokenTiers(uint256[] calldata tokenIds) external view returns (uint8[] memory); /** * @dev Returns an array of all the token IDs in the tier. * @param tier The tier. * @return tokenIds The array of token IDs in the tier. */ function tierTokenIds(uint8 tier) external view returns (uint256[] memory tokenIds); /** * @dev Returns an array of all the token IDs in the tier, within the range [start, stop). * @param tier The tier. * @param start The start of the range. Inclusive. * @param stop The end of the range. Exclusive. * @return tokenIds The array of token IDs in the tier. */ function tierTokenIdsIn( uint8 tier, uint256 start, uint256 stop ) external view returns (uint256[] memory tokenIds); /** * @dev Returns the index of `tokenId` in it's tier token ID array. * @param tokenId The token ID to find. * @return The index of `tokenId`. If not found, returns `type(uint256).max`. */ function tierTokenIdIndex(uint256 tokenId) external view returns (uint256); /** * @dev Returns the maximum amount of tokens mintable for the tier. * @param tier The tier. * @return The configured value. */ function maxMintable(uint8 tier) external view returns (uint32); /** * @dev Returns the upper bound for the maximum tokens that can be minted for the tier. * @param tier The tier. * @return The configured value. */ function maxMintableUpper(uint8 tier) external view returns (uint32); /** * @dev Returns the lower bound for the maximum tokens that can be minted for the tier. * @param tier The tier. * @return The configured value. */ function maxMintableLower(uint8 tier) external view returns (uint32); /** * @dev Returns the timestamp after which `maxMintable` drops from * `maxMintableUpper` to `maxMintableLower`. * @param tier The tier. * @return The configured value. */ function cutoffTime(uint8 tier) external view returns (uint32); /** * @dev Returns the number of tokens minted for the tier. * @param tier The tier. * @return The latest value. */ function tierMinted(uint8 tier) external view returns (uint32); /** * @dev Returns the mint randomness for the tier. * @param tier The tier. * @return The latest value. */ function mintRandomness(uint8 tier) external view returns (uint256); /** * @dev Returns the one-of-one token ID for the tier. * @param tier The tier. * @return The latest value. */ function mintRandomnessOneOfOne(uint8 tier) external view returns (uint32); /** * @dev Returns whether the `mintRandomness` has been enabled. * @return The configured value. */ function mintRandomnessEnabled(uint8 tier) external view returns (bool); /** * @dev Returns whether the mint has been concluded for the tier. * @param tier The tier. * @return The latest value. */ function mintConcluded(uint8 tier) external view returns (bool); /** * @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 address of the metadata module. * @return The configured value. */ function metadataModule() external view returns (address); /** * @dev Returns the royalty basis points. * @return The configured value. */ function royaltyBPS() external view returns (uint16); /** * @dev Returns whether the tier is frozen. * @return The configured value. */ function isFrozen(uint8 tier) external view returns (bool); /** * @dev Returns whether the metadata module is frozen. * @return The configured value. */ function isMetadataFrozen() external view returns (bool); /** * @dev Returns whether the ability to create tiers is frozen. * @return The configured value. */ function isCreateTierFrozen() 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 Returns the token URI of `tokenId`, but without reverting if * the token does not exist. * @return The latest value. */ function explicitTokenURI(uint256 tokenId) external view returns (string memory); /** * @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); /** * @dev Filler function to make the interface ID different. * @return True. */ function V2_1() 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.16; /** * @title LibOps * @dev Shared utilities. */ library LibOps { // ============================================================= // ERRORS // ============================================================= /** * @dev Error for overflows. */ error Overflow(); /** * @dev Error for unauthorized access. */ error Unauthorized(); // ============================================================= // CONSTANTS // ============================================================= /** * @dev A role every minter module must have in order to mint new tokens. * IMPORTANT: This constant must NEVER be changed! * It will always be 2 across all past and future sound protocol contracts. */ uint256 internal constant MINTER_ROLE = 1 << 1; /** * @dev A role the owner can grant for performing admin actions. * IMPORTANT: This constant must NEVER be changed! * It will always be 1 across all past and future sound protocol contracts. */ uint256 internal constant ADMIN_ROLE = 1 << 0; /** * @dev Basis points denominator used in fee calculations. * IMPORTANT: This constant must NEVER be changed! * It will always be 10000 across all past and future sound protocol contracts. */ uint16 internal constant BPS_DENOMINATOR = 10000; // ============================================================= // FUNCTIONS // ============================================================= /** * @dev `isOn ? flag : 0`. */ function toFlag(bool isOn, uint8 flag) internal pure returns (uint8 result) { assembly { result := mul(iszero(iszero(isOn)), flag) } } /** * @dev `(flags & flag != 0) != isOn ? flags ^ flag : flags`. * Sets `flag` in `flags` to 1 if `isOn` is true. * Sets `flag` in `flags` to 0 if `isOn` is false. */ function setFlagTo( uint8 flags, uint8 flag, bool isOn ) internal pure returns (uint8 result) { assembly { result := xor(flags, mul(xor(iszero(and(0xff, and(flags, flag))), iszero(isOn)), flag)) } } /** * @dev `x > y ? x : y`. */ function max(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { z := xor(x, mul(xor(x, y), gt(y, x))) } } /** * @dev `x < y ? x : y`. */ function min(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly { z := xor(x, mul(xor(x, y), lt(y, x))) } } /** * @dev `(a * b) / d`. Returns 0 if `d` is zero. */ function rawMulDiv( uint256 a, uint256 b, uint256 d ) internal pure returns (uint256 z) { assembly { z := div(mul(a, b), d) } } /** * @dev `a / d`. Returns 0 if `d` is zero. */ function rawMod(uint256 a, uint256 d) internal pure returns (uint256 z) { assembly { z := mod(a, d) } } /** * @dev `a | b`. */ function or(bool a, bool b) internal pure returns (bool z) { assembly { z := or(iszero(iszero(a)), iszero(iszero(b))) } } /** * @dev `a | b | c`. */ function or( bool a, bool b, bool c ) internal pure returns (bool z) { z = or(a, or(b, c)); } /** * @dev `a | b | c | d`. */ function or( bool a, bool b, bool c, bool d ) internal pure returns (bool z) { z = or(a, or(b, or(c, d))); } /** * @dev `a & b`. */ function and(bool a, bool b) internal pure returns (bool z) { assembly { z := and(iszero(iszero(a)), iszero(iszero(b))) } } /** * @dev `x == 0 ? type(uint256).max : x` */ function maxIfZero(uint256 x) internal pure returns (uint256 z) { assembly { z := sub(x, iszero(x)) } } /** * @dev Packs an address and an index to create an unique identifier. * @param a The address. * @param i The index. * @return result The packed result. */ function packId(address a, uint96 i) internal pure returns (uint256 result) { assembly { result := or(shl(96, a), shr(160, shl(160, i))) } } /** * @dev Packs `edition`, `tier`, `scheduleNum` to create an unique identifier. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @return result The packed result. */ function packId( address edition, uint8 tier, uint8 scheduleNum ) internal pure returns (uint256 result) { assembly { mstore(0x00, shl(96, edition)) mstore8(0x1e, tier) mstore8(0x1f, scheduleNum) result := mload(0x00) } } /** * @dev `revert Overflow()`. */ function revertOverflow() internal pure { assembly { mstore(0x00, 0x35278d12) // `Overflow()`. revert(0x1c, 0x04) } } /** * @dev `revert Unauthorized()`. */ function revertUnauthorized() internal pure { assembly { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; /* ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒███████████████████████████████████████████████████████████ ▒███████████████████████████████████████████████████████████ ▒▓▓▓▓▓▓▓▓▓▓▓▓▓████████████████▓▓▓▓▓▓▓▓▓▓▓▓▓▓██████████████████████████████▓▒▒▒▒▒▒▒▒▒▒▒▒▒ █████████████████████████████▓ ████████████████████████████████████████████ █████████████████████████████▓ ████████████████████████████████████████████ █████████████████████████████▓ ▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████████████████████ █████████████████████████████▓ ▒█████████████████████████████ █████████████████████████████▓ ▒████████████████████████████ █████████████████████████████████████████████████████████▓ ███████████████████████████████████████████████████████████ ███████████████████████████████████████████████████████████▒ ███████████████████████████████████████████████████████████▒ ▓██████████████████████████████████████████████████████████▒ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓███████████████████████████████▒ █████████████████████████████ ▒█████████████████████████████▒ ██████████████████████████████ ▒█████████████████████████████▒ ██████████████████████████████▓▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒█████████████████████████████▒ ████████████████████████████████████████████▒ ▒█████████████████████████████▒ ████████████████████████████████████████████▒ ▒█████████████████████████████▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒███████████████████████████████▓▓▓▓▓▓▓▓▓▓▓▓▓███████████████▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▓██████████████████████████████████████████████████████████▒ ▓██████████████████████████████████████████████████████████ */ import { Base64 } from "solady/utils/Base64.sol"; library ArweaveURILib { // ============================================================= // STRUCTS // ============================================================= struct URI { bytes32 arweave; string regular; } // ============================================================= // INTERNAL / PRIVATE HELPERS // ============================================================= /** * @dev Helper function for storing a URI that may be an Arweave URI. * Efficiently stores Arweave CIDs by converting them into a single bytes32 word. * The Arweave CID is a base64 encoded sha-256 output (32 bytes when decoded). * See: https://docs.arweave.org/developers/server/http-api * @param uri The URI storage reference. * @param value The string representation of the URI. * @param isUpdate Whether this is called in an update. */ function store( URI storage uri, string memory value, bool isUpdate ) internal { uint256 valueLength; bool isArweave; assembly { // Example: "ar://Hjtz2YLeVyXQkGxKTNcIYfWkKnHioDvfICulzQIAt3E" valueLength := mload(value) // If the URI is length 48 or 49 (due to a trailing slash). if or(eq(valueLength, 48), eq(valueLength, 49)) { // If starts with "ar://". if eq(and(mload(add(value, 5)), 0xffffffffff), 0x61723a2f2f) { isArweave := 1 value := add(value, 5) // Sets the length of the `value` to 43, // such that it only contains the CID. mstore(value, 43) } } } if (isArweave) { bytes memory decodedCIDBytes = Base64.decode(value); bytes32 arweaveCID; assembly { arweaveCID := mload(add(decodedCIDBytes, 0x20)) // Restore the "ar://". mstore(value, 0x61723a2f2f) // Restore the original position of the `value` pointer. value := sub(value, 5) // Restore the original length. mstore(value, valueLength) } uri.arweave = arweaveCID; } else { uri.regular = value; if (isUpdate) delete uri.arweave; } } /** * @dev Equivalent to `store(uri, value, false)`. * @param uri The URI storage reference. * @param value The string representation of the URI. */ function initialize(URI storage uri, string memory value) internal { if (bytes(value).length == 0) return; store(uri, value, false); } /** * @dev Equivalent to `store(uri, value, true)`. * @param uri The URI storage reference. * @param value The string representation of the URI. */ function update(URI storage uri, string memory value) internal { store(uri, value, true); } /** * @dev Helper function for retrieving a URI stored with {_setURI}. * @param uri The URI storage reference. */ function load(URI storage uri) internal view returns (string memory) { bytes32 arweaveCID = uri.arweave; if (arweaveCID == bytes32(0)) { return uri.regular; } bytes memory decoded; assembly { // Copy `arweaveCID`. // First, grab the free memory pointer. decoded := mload(0x40) // Allocate 2 slots. // 1 slot for the length, 1 slot for the bytes. mstore(0x40, add(decoded, 0x40)) mstore(decoded, 0x20) // Set the length (32 bytes). mstore(add(decoded, 0x20), arweaveCID) // Set the bytes. } return string.concat("ar://", Base64.encode(decoded, true, true), "/"); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; /* ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒███████████████████████████████████████████████████████████ ▒███████████████████████████████████████████████████████████ ▒▓▓▓▓▓▓▓▓▓▓▓▓▓████████████████▓▓▓▓▓▓▓▓▓▓▓▓▓▓██████████████████████████████▓▒▒▒▒▒▒▒▒▒▒▒▒▒ █████████████████████████████▓ ████████████████████████████████████████████ █████████████████████████████▓ ████████████████████████████████████████████ █████████████████████████████▓ ▒▒▒▒▒▒▒▒▒▒▒▒▒██████████████████████████████ █████████████████████████████▓ ▒█████████████████████████████ █████████████████████████████▓ ▒████████████████████████████ █████████████████████████████████████████████████████████▓ ███████████████████████████████████████████████████████████ ███████████████████████████████████████████████████████████▒ ███████████████████████████████████████████████████████████▒ ▓██████████████████████████████████████████████████████████▒ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓███████████████████████████████▒ █████████████████████████████ ▒█████████████████████████████▒ ██████████████████████████████ ▒█████████████████████████████▒ ██████████████████████████████▓▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒█████████████████████████████▒ ████████████████████████████████████████████▒ ▒█████████████████████████████▒ ████████████████████████████████████████████▒ ▒█████████████████████████████▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒███████████████████████████████▓▓▓▓▓▓▓▓▓▓▓▓▓███████████████▓▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▓██████████████████████████████████████████████████████████▒ ▓██████████████████████████████████████████████████████████ */ library MintRandomnessLib { /** * @dev Returns the next mint randomness. * @param randomness The current mint randomness. * @param totalMinted The total number of tokens minted. * @param quantity The number of tokens to mint. * @param maxMintable The maximum number of tokens that can be minted. * @return newRandomness The next mint randomness. */ function nextMintRandomness( uint256 randomness, uint256 totalMinted, uint256 quantity, uint256 maxMintable ) internal view returns (uint256 newRandomness) { assembly { newRandomness := randomness // If neither `maxMintable` nor `quantity` is zero. if mul(maxMintable, quantity) { let end := add(totalMinted, quantity) // prettier-ignore for {} 1 {} { // Pick any of the last 256 blocks pseudorandomly for the blockhash. mstore(0x00, blockhash(sub(number(), add(1, and(0xff, randomness))))) // After the merge, if [EIP-4399](https://eips.ethereum.org/EIPS/eip-4399) // is implemented, the `difficulty()` will be determined by the beacon chain, // and renamed to `prevrandao()`. // We also need to xor with the `totalMinted` to prevent the randomness // from being stucked. mstore(0x20, xor(xor(randomness, prevrandao()), totalMinted)) let r := keccak256(0x00, 0x40) switch randomness case 0 { // If `randomness` is uninitialized, // initialize all bits pseudorandomly. newRandomness := r } default { // Decay the chance to update as more are minted. if gt(add(mod(r, maxMintable), 1), totalMinted) { // If `randomness` has already been initialized, // each update can only contribute 1 bit of pseudorandomness. mstore(0x00, or(shl(1, randomness), shr(255, r))) newRandomness := keccak256(0x00, 0x20) } } randomness := newRandomness totalMinted := add(totalMinted, 1) // prettier-ignore if eq(totalMinted, end) { break } } } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library ERC721AStorage { // Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364). struct TokenApprovalRef { address value; } struct Layout { // ============================================================= // STORAGE // ============================================================= // The next token ID to be minted. uint256 _currentIndex; // The number of tokens burned. uint256 _burnCounter; // Token name string _name; // Token symbol string _symbol; // Mapping from token ID to ownership details // An empty struct value does not necessarily mean the token is unowned. // See {_packedOwnershipOf} implementation for details. // // Bits Layout: // - [0..159] `addr` // - [160..223] `startTimestamp` // - [224] `burned` // - [225] `nextInitialized` // - [232..255] `extraData` mapping(uint256 => uint256) _packedOwnerships; // Mapping owner address to address data. // // Bits Layout: // - [0..63] `balance` // - [64..127] `numberMinted` // - [128..191] `numberBurned` // - [192..255] `aux` mapping(address => uint256) _packedAddressData; // Mapping from token ID to approved address. mapping(uint256 => ERC721AStorage.TokenApprovalRef) _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) _operatorApprovals; } bytes32 internal constant STORAGE_SLOT = keccak256('ERC721A.contracts.storage.ERC721A'); function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev This is a base contract to aid in writing upgradeable diamond facet contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. */ import {ERC721A__InitializableStorage} from './ERC721A__InitializableStorage.sol'; abstract contract ERC721A__Initializable { using ERC721A__InitializableStorage for ERC721A__InitializableStorage.Layout; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializerERC721A() { // If the contract is initializing we ignore whether _initialized is set in order to support multiple // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the // contract may have been reentered. require( ERC721A__InitializableStorage.layout()._initializing ? _isConstructor() : !ERC721A__InitializableStorage.layout()._initialized, 'ERC721A__Initializable: contract is already initialized' ); bool isTopLevelCall = !ERC721A__InitializableStorage.layout()._initializing; if (isTopLevelCall) { ERC721A__InitializableStorage.layout()._initializing = true; ERC721A__InitializableStorage.layout()._initialized = true; } _; if (isTopLevelCall) { ERC721A__InitializableStorage.layout()._initializing = false; } } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} modifier, directly or indirectly. */ modifier onlyInitializingERC721A() { require( ERC721A__InitializableStorage.layout()._initializing, 'ERC721A__Initializable: contract is not initializing' ); _; } /// @dev Returns true if and only if the function is running in the constructor function _isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. address self = address(this); uint256 cs; assembly { cs := extcodesize(self) } return cs == 0; } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; import '../IERC721AUpgradeable.sol'; /** * @dev Interface of ERC721AQueryable. */ interface IERC721AQueryableUpgradeable is IERC721AUpgradeable { /** * Invalid query range (`start` >= `stop`). */ error InvalidQueryRange(); /** * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting. * * If the `tokenId` is out of bounds: * * - `addr = address(0)` * - `startTimestamp = 0` * - `burned = false` * - `extraData = 0` * * If the `tokenId` is burned: * * - `addr = <Address of owner before token was burned>` * - `startTimestamp = <Timestamp when token was burned>` * - `burned = true` * - `extraData = <Extra data when token was burned>` * * Otherwise: * * - `addr = <Address of owner>` * - `startTimestamp = <Timestamp of start of ownership>` * - `burned = false` * - `extraData = <Extra data at start of ownership>` */ function explicitOwnershipOf(uint256 tokenId) external view returns (TokenOwnership memory); /** * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order. * See {ERC721AQueryable-explicitOwnershipOf} */ function explicitOwnershipsOf(uint256[] memory tokenIds) external view returns (TokenOwnership[] memory); /** * @dev Returns an array of token IDs owned by `owner`, * in the range [`start`, `stop`) * (i.e. `start <= tokenId < stop`). * * This function allows for tokens to be queried if the collection * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}. * * Requirements: * * - `start < stop` */ function tokensOfOwnerIn( address owner, uint256 start, uint256 stop ) external view returns (uint256[] memory); /** * @dev Returns an array of token IDs owned by `owner`. * * This function scans the ownership mapping and is O(`totalSupply`) in complexity. * It is meant to be called off-chain. * * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into * multiple smaller scans if the collection is large enough to cause * an out-of-gas error (10K collections should be fine). */ function tokensOfOwner(address owner) external view returns (uint256[] memory); }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; import '../IERC721AUpgradeable.sol'; /** * @dev Interface of ERC721ABurnable. */ interface IERC721ABurnableUpgradeable is IERC721AUpgradeable { /** * @dev Burns `tokenId`. See {ERC721A-_burn}. * * Requirements: * * - The caller must own `tokenId` or be an approved operator. */ function burn(uint256 tokenId) external; }
// 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.4; /// @notice Simple single owner authorization mixin. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol) /// /// @dev Note: /// This implementation does NOT auto-initialize the owner to `msg.sender`. /// You MUST call the `_initializeOwner` in the constructor / initializer. /// /// 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 Cannot double-initialize. error AlreadyInitialized(); /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* 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: /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`. /// It is intentionally chosen 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. bytes32 internal constant _OWNER_SLOT = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927; /// 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 Override to return true to make `_initializeOwner` prevent double-initialization. function _guardInitializeOwner() internal pure virtual returns (bool guard) {} /// @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 { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT if sload(ownerSlot) { mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`. revert(0x1c, 0x04) } // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner)))) // Emit the {OwnershipTransferred} event. log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner) } } else { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits. newOwner := shr(96, shl(96, newOwner)) // Store the new value. sstore(_OWNER_SLOT, 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 { if (_guardInitializeOwner()) { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // 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, or(newOwner, shl(255, iszero(newOwner)))) } } else { /// @solidity memory-safe-assembly assembly { let ownerSlot := _OWNER_SLOT // 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(_OWNER_SLOT))) { mstore(0x00, 0x82b42900) // `Unauthorized()`. revert(0x1c, 0x04) } } } /// @dev Returns how long a two-step ownership handover is valid for in seconds. /// Override to return a different value if needed. /// Made internal to conserve bytecode. Wrap it in a public function if needed. function _ownershipHandoverValidFor() internal view virtual returns (uint64) { return 48 * 3600; } /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* 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, 0x7448fbae) // `NewOwnerIsZeroAddress()`. 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 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, 0x6f5e8818) // `NoHandoverRequest()`. 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(_OWNER_SLOT) } } /// @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)) } } /*´:°â€¢.°+.*•´.*:Ëš.°*.˚•´.°:°â€¢.°â€¢.*•´.*:Ëš.°*.˚•´.°:°â€¢.°+.*•´.*:*/ /* MODIFIERS */ /*.•°:°.´+Ëš.*°.Ëš:*.´â€¢*.+°.•°:´*.´â€¢*.•°.•°:°.´:•˚°.*°.Ëš:*.´+°.•*/ /// @dev Marks a function as only callable by the owner. modifier onlyOwner() virtual { _checkOwner(); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library to encode strings in Base64. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Base64.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Base64.sol) /// @author Modified from (https://github.com/Brechtpd/base64/blob/main/base64.sol) by Brecht Devos - <[email protected]>. library Base64 { /// @dev Encodes `data` using the base64 encoding described in RFC 4648. /// See: https://datatracker.ietf.org/doc/html/rfc4648 /// @param fileSafe Whether to replace '+' with '-' and '/' with '_'. /// @param noPadding Whether to strip away the padding. function encode(bytes memory data, bool fileSafe, bool noPadding) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let dataLength := mload(data) if dataLength { // Multiply by 4/3 rounded up. // The `shl(2, ...)` is equivalent to multiplying by 4. let encodedLength := shl(2, div(add(dataLength, 2), 3)) // Set `result` to point to the start of the free memory. result := mload(0x40) // Store the table into the scratch space. // Offsetted by -1 byte so that the `mload` will load the character. // We will rewrite the free memory pointer at `0x40` later with // the allocated size. // The magic constant 0x0670 will turn "-_" into "+/". mstore(0x1f, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef") mstore(0x3f, xor("ghijklmnopqrstuvwxyz0123456789-_", mul(iszero(fileSafe), 0x0670))) // Skip the first slot, which stores the length. let ptr := add(result, 0x20) let end := add(ptr, encodedLength) // Run over the input, 3 bytes at a time. for {} 1 {} { data := add(data, 3) // Advance 3 bytes. let input := mload(data) // Write 4 bytes. Optimized for fewer stack operations. mstore8(0, mload(and(shr(18, input), 0x3F))) mstore8(1, mload(and(shr(12, input), 0x3F))) mstore8(2, mload(and(shr(6, input), 0x3F))) mstore8(3, mload(and(input, 0x3F))) mstore(ptr, mload(0x00)) ptr := add(ptr, 4) // Advance 4 bytes. if iszero(lt(ptr, end)) { break } } mstore(0x40, add(end, 0x20)) // Allocate the memory. // Equivalent to `o = [0, 2, 1][dataLength % 3]`. let o := div(2, mod(dataLength, 3)) // Offset `ptr` and pad with '='. We can simply write over the end. mstore(sub(ptr, o), shl(240, 0x3d3d)) // Set `o` to zero if there is padding. o := mul(iszero(iszero(noPadding)), o) mstore(sub(ptr, o), 0) // Zeroize the slot after the string. mstore(result, sub(encodedLength, o)) // Store the length. } } } /// @dev Encodes `data` using the base64 encoding described in RFC 4648. /// Equivalent to `encode(data, false, false)`. function encode(bytes memory data) internal pure returns (string memory result) { result = encode(data, false, false); } /// @dev Encodes `data` using the base64 encoding described in RFC 4648. /// Equivalent to `encode(data, fileSafe, false)`. function encode(bytes memory data, bool fileSafe) internal pure returns (string memory result) { result = encode(data, fileSafe, false); } /// @dev Decodes base64 encoded `data`. /// /// Supports: /// - RFC 4648 (both standard and file-safe mode). /// - RFC 3501 (63: ','). /// /// Does not support: /// - Line breaks. /// /// Note: For performance reasons, /// this function will NOT revert on invalid `data` inputs. /// Outputs for invalid inputs will simply be undefined behaviour. /// It is the user's responsibility to ensure that the `data` /// is a valid base64 encoded string. function decode(string memory data) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { let dataLength := mload(data) if dataLength { let decodedLength := mul(shr(2, dataLength), 3) for {} 1 {} { // If padded. if iszero(and(dataLength, 3)) { let t := xor(mload(add(data, dataLength)), 0x3d3d) // forgefmt: disable-next-item decodedLength := sub( decodedLength, add(iszero(byte(30, t)), iszero(byte(31, t))) ) break } // If non-padded. decodedLength := add(decodedLength, sub(and(dataLength, 3), 1)) break } result := mload(0x40) // Write the length of the bytes. mstore(result, decodedLength) // Skip the first slot, which stores the length. let ptr := add(result, 0x20) let end := add(ptr, decodedLength) // Load the table into the scratch space. // Constants are optimized for smaller bytecode with zero gas overhead. // `m` also doubles as the mask of the upper 6 bits. let m := 0xfc000000fc00686c7074787c8084888c9094989ca0a4a8acb0b4b8bcc0c4c8cc mstore(0x5b, m) mstore(0x3b, 0x04080c1014181c2024282c3034383c4044484c5054585c6064) mstore(0x1a, 0xf8fcf800fcd0d4d8dce0e4e8ecf0f4) for {} 1 {} { // Read 4 bytes. data := add(data, 4) let input := mload(data) // Write 3 bytes. // forgefmt: disable-next-item mstore(ptr, or( and(m, mload(byte(28, input))), shr(6, or( and(m, mload(byte(29, input))), shr(6, or( and(m, mload(byte(30, input))), shr(6, mload(byte(31, input))) )) )) )) ptr := add(ptr, 3) if iszero(lt(ptr, end)) { break } } mstore(0x40, add(end, 0x20)) // Allocate the memory. mstore(end, 0) // Zeroize the slot after the bytes. mstore(0x60, 0) // Restore the zero slot. } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev This is a base storage for the initialization function for upgradeable diamond facet contracts **/ library ERC721A__InitializableStorage { struct Layout { /* * Indicates that the contract has been initialized. */ bool _initialized; /* * Indicates that the contract is in the process of being initialized. */ bool _initializing; } bytes32 internal constant STORAGE_SLOT = keccak256('ERC721A.contracts.storage.initializable.facet'); function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } }
{ "remappings": [ "openzeppelin/=lib/openzeppelin-contracts/contracts/", "openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "chiru-labs/ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/", "solady/=lib/solady/src/", "closedsea/=lib/closedsea/src/", "preapprove/=lib/preapprove/src/", "multicaller/=lib/multicaller/src/", "@core/=contracts/core/", "@modules/=contracts/modules/", "forge-std/=lib/forge-std/src/", "ERC721A-Upgradeable/=lib/ERC721A-Upgradeable/contracts/", "ds-test/=lib/solady/lib/ds-test/src/", "erc4626-tests/=lib/closedsea/lib/openzeppelin-contracts/lib/erc4626-tests/", "erc721a-upgradeable/=lib/multicaller/lib/erc721a-upgradeable/contracts/", "erc721a/=lib/multicaller/lib/erc721a/contracts/", "murky/=lib/murky/src/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "operator-filter-registry/=lib/closedsea/lib/operator-filter-registry/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"CannotBurnImmediately","type":"error"},{"inputs":[],"name":"CreateTierIsFrozen","type":"error"},{"inputs":[],"name":"ExceedsAvailableSupply","type":"error"},{"inputs":[],"name":"InvalidFundingRecipient","type":"error"},{"inputs":[],"name":"InvalidMaxMintableRange","type":"error"},{"inputs":[],"name":"InvalidQueryRange","type":"error"},{"inputs":[],"name":"InvalidRoyaltyBPS","type":"error"},{"inputs":[],"name":"InvalidTokenTier","type":"error"},{"inputs":[],"name":"MetadataIsFrozen","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintHasConcluded","type":"error"},{"inputs":[],"name":"MintNotConcluded","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"MintsAlreadyExist","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"TierAlreadyExists","type":"error"},{"inputs":[],"name":"TierDoesNotExist","type":"error"},{"inputs":[],"name":"TierIsFrozen","type":"error"},{"inputs":[],"name":"TierMintsAlreadyExist","type":"error"},{"inputs":[],"name":"TierQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"TokenIdsNotStrictlyAscending","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"ZeroTiersProvided","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"address[]","name":"to","type":"address[]"},{"indexed":false,"internalType":"uint256","name":"quantity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fromTokenId","type":"uint256"}],"name":"Airdropped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"baseURI","type":"string"}],"name":"BaseURISet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"}],"name":"BatchMetadataUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"contractURI","type":"string"}],"name":"ContractURISet","type":"event"},{"anonymous":false,"inputs":[],"name":"CreateTierFrozen","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint32","name":"cutoff","type":"uint32"}],"name":"CutoffTimeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"ERC20Withdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"ETHWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"recipient","type":"address"}],"name":"FundingRecipientSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint32","name":"lower","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"upper","type":"uint32"}],"name":"MaxMintableRangeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"metadataModule","type":"address"},{"indexed":false,"internalType":"string","name":"baseURI","type":"string"},{"indexed":false,"internalType":"string","name":"contractURI","type":"string"}],"name":"MetadataFrozen","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"metadataModule","type":"address"}],"name":"MetadataModuleSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"MintRandomnessEnabledSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"quantity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fromTokenId","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":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"roles","type":"uint256"}],"name":"RolesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"bps","type":"uint16"}],"name":"RoyaltySet","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"metadataModule","type":"address"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"string","name":"contractURI","type":"string"},{"internalType":"address","name":"fundingRecipient","type":"address"},{"internalType":"uint16","name":"royaltyBPS","type":"uint16"},{"internalType":"bool","name":"isMetadataFrozen","type":"bool"},{"internalType":"bool","name":"isCreateTierFrozen","type":"bool"},{"components":[{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint32","name":"maxMintableLower","type":"uint32"},{"internalType":"uint32","name":"maxMintableUpper","type":"uint32"},{"internalType":"uint32","name":"cutoffTime","type":"uint32"},{"internalType":"bool","name":"mintRandomnessEnabled","type":"bool"},{"internalType":"bool","name":"isFrozen","type":"bool"}],"internalType":"struct ISoundEditionV2_1.TierCreation[]","name":"tierCreations","type":"tuple[]"}],"indexed":false,"internalType":"struct ISoundEditionV2_1.EditionInitialization","name":"init","type":"tuple"}],"name":"SoundEditionInitialized","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint32","name":"maxMintableLower","type":"uint32"},{"internalType":"uint32","name":"maxMintableUpper","type":"uint32"},{"internalType":"uint32","name":"cutoffTime","type":"uint32"},{"internalType":"bool","name":"mintRandomnessEnabled","type":"bool"},{"internalType":"bool","name":"isFrozen","type":"bool"}],"indexed":false,"internalType":"struct ISoundEditionV2_1.TierCreation","name":"creation","type":"tuple"}],"name":"TierCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"}],"name":"TierFrozen","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"ADMIN_ROLE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BPS_DENOMINATOR","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GA_TIER","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"V2_1","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"address[]","name":"to","type":"address[]"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"airdrop","outputs":[{"internalType":"uint256","name":"fromTokenId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","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":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"splitMain","type":"address"},{"internalType":"bytes","name":"splitData","type":"bytes"}],"name":"createSplit","outputs":[{"internalType":"address","name":"split","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint32","name":"maxMintableLower","type":"uint32"},{"internalType":"uint32","name":"maxMintableUpper","type":"uint32"},{"internalType":"uint32","name":"cutoffTime","type":"uint32"},{"internalType":"bool","name":"mintRandomnessEnabled","type":"bool"},{"internalType":"bool","name":"isFrozen","type":"bool"}],"internalType":"struct ISoundEditionV2_1.TierCreation","name":"creation","type":"tuple"}],"name":"createTier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"cutoffTime","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"editionInfo","outputs":[{"components":[{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"string","name":"contractURI","type":"string"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"fundingRecipient","type":"address"},{"internalType":"address","name":"metadataModule","type":"address"},{"internalType":"bool","name":"isMetadataFrozen","type":"bool"},{"internalType":"bool","name":"isCreateTierFrozen","type":"bool"},{"internalType":"uint16","name":"royaltyBPS","type":"uint16"},{"internalType":"uint256","name":"nextTokenId","type":"uint256"},{"internalType":"uint256","name":"totalBurned","type":"uint256"},{"internalType":"uint256","name":"totalMinted","type":"uint256"},{"internalType":"uint256","name":"totalSupply","type":"uint256"},{"components":[{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint32","name":"maxMintable","type":"uint32"},{"internalType":"uint32","name":"maxMintableLower","type":"uint32"},{"internalType":"uint32","name":"maxMintableUpper","type":"uint32"},{"internalType":"uint32","name":"cutoffTime","type":"uint32"},{"internalType":"uint32","name":"minted","type":"uint32"},{"internalType":"uint256","name":"mintRandomness","type":"uint256"},{"internalType":"bool","name":"mintConcluded","type":"bool"},{"internalType":"bool","name":"mintRandomnessEnabled","type":"bool"},{"internalType":"bool","name":"isFrozen","type":"bool"}],"internalType":"struct ISoundEditionV2_1.TierInfo[]","name":"tierInfo","type":"tuple[]"}],"internalType":"struct ISoundEditionV2_1.EditionInfo","name":"info","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"emitAllMetadataUpdate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"explicitOwnershipOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721AUpgradeable.TokenOwnership","name":"ownership","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"explicitOwnershipsOf","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"uint64","name":"startTimestamp","type":"uint64"},{"internalType":"bool","name":"burned","type":"bool"},{"internalType":"uint24","name":"extraData","type":"uint24"}],"internalType":"struct IERC721AUpgradeable.TokenOwnership[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"explicitTokenTier","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"explicitTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"freezeCreateTier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"freezeMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"freezeTier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fundingRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"grantRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAllRoles","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAnyRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"metadataModule","type":"address"},{"internalType":"string","name":"baseURI","type":"string"},{"internalType":"string","name":"contractURI","type":"string"},{"internalType":"address","name":"fundingRecipient","type":"address"},{"internalType":"uint16","name":"royaltyBPS","type":"uint16"},{"internalType":"bool","name":"isMetadataFrozen","type":"bool"},{"internalType":"bool","name":"isCreateTierFrozen","type":"bool"},{"components":[{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint32","name":"maxMintableLower","type":"uint32"},{"internalType":"uint32","name":"maxMintableUpper","type":"uint32"},{"internalType":"uint32","name":"cutoffTime","type":"uint32"},{"internalType":"bool","name":"mintRandomnessEnabled","type":"bool"},{"internalType":"bool","name":"isFrozen","type":"bool"}],"internalType":"struct ISoundEditionV2_1.TierCreation[]","name":"tierCreations","type":"tuple[]"}],"internalType":"struct ISoundEditionV2_1.EditionInitialization","name":"init","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isCreateTierFrozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"isFrozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isMetadataFrozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"maxMintable","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"maxMintableLower","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"maxMintableUpper","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadataModule","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"quantity","type":"uint256"}],"name":"mint","outputs":[{"internalType":"uint256","name":"fromTokenId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"mintConcluded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"mintRandomness","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"mintRandomnessEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"mintRandomnessOneOfOne","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"name_","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"numberBurned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"numberMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","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":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"renounceRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"revokeRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rolesOf","outputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"royaltyBPS","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"royaltyAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"uri","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint32","name":"cutoff","type":"uint32"}],"name":"setCutoffTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"setFundingRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint32","name":"lower","type":"uint32"},{"internalType":"uint32","name":"upper","type":"uint32"}],"name":"setMaxMintableRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"module","type":"address"}],"name":"setMetadataModule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setMintRandomnessEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"bps","type":"uint16"}],"name":"setRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"symbol_","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"tierInfo","outputs":[{"components":[{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint32","name":"maxMintable","type":"uint32"},{"internalType":"uint32","name":"maxMintableLower","type":"uint32"},{"internalType":"uint32","name":"maxMintableUpper","type":"uint32"},{"internalType":"uint32","name":"cutoffTime","type":"uint32"},{"internalType":"uint32","name":"minted","type":"uint32"},{"internalType":"uint256","name":"mintRandomness","type":"uint256"},{"internalType":"bool","name":"mintConcluded","type":"bool"},{"internalType":"bool","name":"mintRandomnessEnabled","type":"bool"},{"internalType":"bool","name":"isFrozen","type":"bool"}],"internalType":"struct ISoundEditionV2_1.TierInfo","name":"info","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"tierMinted","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tierTokenIdIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"tierTokenIds","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"stop","type":"uint256"}],"name":"tierTokenIdsIn","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenTier","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"tokenTiers","outputs":[{"internalType":"uint8[]","name":"tiers","type":"uint8[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"stop","type":"uint256"}],"name":"tokensOfOwnerIn","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBurned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061526d806100206000396000f3fe6080604052600436106104ca5760003560e01c80637793818111610276578063b9c9d93a1161014f578063e1a45218116100c1578063eebab8ef11610085578063eebab8ef14610ed6578063f04e283e14610ee9578063f2fde38b14610efc578063faf37bc414610f0f578063fcff385214610f2f578063fee81cf414610f4457600080fd5b8063e1a4521814610e49578063e7a6020d14610e5f578063e8a3d48514610e81578063e985e9c514610e96578063eb78a07614610eb657600080fd5b8063d111515d11610113578063d111515d14610db5578063d539139314610dca578063d89135cd14610ddf578063db0ea80514610df4578063dc33e68114610e14578063e086e5ec14610e3457600080fd5b8063b9c9d93a14610cf3578063c0ede3cf14610d28578063c23dc68f14610d48578063c5bc5a4c14610d75578063c87b56dd14610d9557600080fd5b806399a2557a116101e8578063a8f5473e116101ac578063a8f5473e14610c3e578063aec9b83c14610c60578063b0fbdc8b14610c80578063b393cf7a14610ca0578063b7c858fb14610cc0578063b88d4fde14610ce057600080fd5b806399a2557a14610ba9578063a22cb46514610bc9578063a2309ff814610be9578063a4198fa214610bfe578063a468f04314610c1e57600080fd5b806390e89bb81161023a57806390e89bb814610aff57806390ecf29c14610b1f578063938e3d7b14610b3f57806393e8bcf914610b5f57806395d89b4114610b74578063998ad69114610b8957600080fd5b80637793818114610a665780637ab51f9e14610a865780637f84110f14610aa65780638462151c14610ac65780638da5cb5b14610ae657600080fd5b80632f01b56e116103a85780635bbb21771161031a5780636c0360eb116102de5780636c0360eb146109df57806370a08231146109f4578063715018a614610a1457806375794a3c14610a1c57806375b238fc14610a31578063774de39614610a4657600080fd5b80635bbb2177146109205780635f08f8761461094d5780636352211e1461096d578063649e705f1461098d5780636a3d27c6146109bf57600080fd5b806342842e0e1161036c57806342842e0e1461087b57806342966c681461088e5780634a4ee7b1146108ae578063514e62fc146108c157806354d1f13d146108f857806355f804b31461090057600080fd5b80632f01b56e146107c157806335766f4b146107ee5780633684d1001461081b57806336e79a5a1461083b5780633e1a5b851461085b57600080fd5b80631c10893f11610441578063241d965111610405578063241d9651146106e75780632478d6391461070757806325692962146107275780632a036a4d1461072f5780632a55205a1461074f5780632de948071461078e57600080fd5b80631c10893f146106485780631c519ba41461065b5780631cd64df4146106705780631cdb1765146106a757806323b872dd146106d457600080fd5b8063095ea7b311610493578063095ea7b3146105b45780630e24495e146105c9578063110db80e146105eb57806318160ddd14610600578063183a4f6e146106155780631bb534ba1461062857600080fd5b80624dad56146104cf578063010fe62c1461050957806301ffc9a71461052a57806306fdde031461055a578063081812fc1461057c575b600080fd5b3480156104db57600080fd5b506104ef6104ea3660046140cd565b610f77565b60405163ffffffff90911681526020015b60405180910390f35b61051c610517366004614133565b610f96565b604051908152602001610500565b34801561053657600080fd5b5061054a6105453660046141a2565b61103d565b6040519015158152602001610500565b34801561056657600080fd5b5061056f611089565b604051610500919061420f565b34801561058857600080fd5b5061059c610597366004614222565b611099565b6040516001600160a01b039091168152602001610500565b6105c76105c2366004614252565b6110dd565b005b3480156105d557600080fd5b5061054a600554600160b01b9004600116151590565b3480156105f757600080fd5b506105c76110ed565b34801561060c57600080fd5b5061051c61114d565b6105c7610623366004614222565b61116d565b34801561063457600080fd5b5060055461059c906001600160a01b031681565b6105c7610656366004614252565b61117a565b34801561066757600080fd5b506105c761118c565b34801561067c57600080fd5b5061054a61068b366004614252565b638b78c6d8600c90815260009290925260209091205481161490565b3480156106b357600080fd5b506106c76106c236600461427c565b6111dc565b60405161050091906142bd565b6105c76106e23660046142f8565b61128b565b3480156106f357600080fd5b506105c7610702366004614334565b61144e565b34801561071357600080fd5b5061051c610722366004614334565b611462565b6105c761146d565b34801561073b57600080fd5b5061054a61074a3660046140cd565b6114bc565b34801561075b57600080fd5b5061076f61076a36600461434f565b6114da565b604080516001600160a01b039093168352602083019190915201610500565b34801561079a57600080fd5b5061051c6107a9366004614334565b638b78c6d8600c908152600091909152602090205490565b3480156107cd57600080fd5b506107e16107dc3660046140cd565b61151a565b60405161050091906143ac565b3480156107fa57600080fd5b5061080e6108093660046140cd565b611536565b604051610500919061447c565b34801561082757600080fd5b5060065461059c906001600160a01b031681565b34801561084757600080fd5b506105c761085636600461449d565b6115fc565b34801561086757600080fd5b5061056f610876366004614222565b611668565b6105c76108893660046142f8565b611749565b34801561089a57600080fd5b506105c76108a9366004614222565b611769565b6105c76108bc366004614252565b611774565b3480156108cd57600080fd5b5061054a6108dc366004614252565b638b78c6d8600c90815260009290925260209091205416151590565b6105c7611786565b34801561090c57600080fd5b506105c761091b3660046145ac565b6117c2565b34801561092c57600080fd5b5061094061093b36600461427c565b61181f565b604051610500919061461c565b34801561095957600080fd5b5061059c61096836600461465e565b61186b565b34801561097957600080fd5b5061059c610988366004614222565b6118ab565b34801561099957600080fd5b506109ad6109a8366004614222565b6118b6565b60405160ff9091168152602001610500565b3480156109cb57600080fd5b506105c76109da3660046140cd565b6118fd565b3480156109eb57600080fd5b5061056f611979565b348015610a0057600080fd5b5061051c610a0f366004614334565b61198a565b6105c76119e9565b348015610a2857600080fd5b5061051c6119fd565b348015610a3d57600080fd5b5061051c600181565b348015610a5257600080fd5b506105c7610a613660046147a5565b611a07565b348015610a7257600080fd5b5061051c610a81366004614222565b611a52565b348015610a9257600080fd5b506105c7610aa13660046147c1565b611abe565b348015610ab257600080fd5b506105c7610ac1366004614874565b611b4d565b348015610ad257600080fd5b506107e1610ae1366004614334565b611ce4565b348015610af257600080fd5b50638b78c6d8195461059c565b348015610b0b57600080fd5b506105c7610b1a36600461427c565b611d08565b348015610b2b57600080fd5b506105c7610b3a3660046149cb565b611df2565b348015610b4b57600080fd5b506105c7610b5a3660046145ac565b611f4c565b348015610b6b57600080fd5b506109ad600081565b348015610b8057600080fd5b5061056f611f99565b348015610b9557600080fd5b506105c7610ba4366004614a0e565b611fa3565b348015610bb557600080fd5b506107e1610bc4366004614a38565b612040565b348015610bd557600080fd5b506105c7610be4366004614a6b565b612055565b348015610bf557600080fd5b5061051c6120d2565b348015610c0a57600080fd5b506105c7610c19366004614334565b6120dc565b348015610c2a57600080fd5b506104ef610c393660046140cd565b61213d565b348015610c4a57600080fd5b5061054a600554600160b01b9004600216151590565b348015610c6c57600080fd5b5061054a610c7b3660046140cd565b6121b3565b348015610c8c57600080fd5b506104ef610c9b3660046140cd565b6121d1565b348015610cac57600080fd5b5061051c610cbb3660046140cd565b6121f0565b348015610ccc57600080fd5b506104ef610cdb3660046140cd565b612203565b6105c7610cee366004614a87565b612222565b348015610cff57600080fd5b50600554610d1590600160a01b900461ffff1681565b60405161ffff9091168152602001610500565b348015610d3457600080fd5b506107e1610d43366004614b02565b612263565b348015610d5457600080fd5b50610d68610d63366004614222565b612356565b6040516105009190614b20565b348015610d8157600080fd5b506104ef610d903660046140cd565b6123b9565b348015610da157600080fd5b5061056f610db0366004614222565b6123cc565b348015610dc157600080fd5b506105c76123fd565b348015610dd657600080fd5b5061051c600281565b348015610deb57600080fd5b5061051c61247e565b348015610e0057600080fd5b5061054a610e0f3660046140cd565b612488565b348015610e2057600080fd5b5061051c610e2f366004614334565b61249b565b348015610e4057600080fd5b506105c76124a6565b348015610e5557600080fd5b50610d1561271081565b348015610e6b57600080fd5b50610e74612507565b6040516105009190614b69565b348015610e8d57600080fd5b5061056f61270b565b348015610ea257600080fd5b5061054a610eb1366004614ca8565b612717565b348015610ec257600080fd5b506104ef610ed13660046140cd565b612754565b61051c610ee4366004614cd2565b612773565b6105c7610ef7366004614334565b6127f2565b6105c7610f0a366004614334565b61282f565b348015610f1b57600080fd5b506109ad610f2a366004614222565b612856565b348015610f3b57600080fd5b5061054a600181565b348015610f5057600080fd5b5061051c610f5f366004614334565b63389a75e1600c908152600091909152602090205490565b6000610f8282612875565b54600160601b900463ffffffff1692915050565b60006003610fa3816128b5565b610faf86858502612903565b50915060005b808514610ff457610fec868683818110610fd157610fd1614cf0565b9050602002016020810190610fe69190614334565b85612a87565b600101610fb5565b507f0b411e173d03042c3eb682fe6cf8f1d64b549c283a9ed7e0f83a9711ee0841e8868686868660405161102c959493929190614d42565b60405180910390a150949350505050565b60006110836001600160e01b03198316638477f7b360e01b1461105f84612ab5565b6001600160e01b03198516637888cfe160e01b81149063152a902d60e11b14612b03565b92915050565b6060611093612b20565b50919050565b60006110a482612ca8565b6110b8576110b86333d1c03960e21b612d06565b6110c0612d10565b60009283526006016020525060409020546001600160a01b031690565b6110e982826001612d34565b5050565b60016110f8816128b5565b611100612de5565b6005805460ff60b01b1981166002600160b01b9283900460ff16179091021790556040517f36c5c1f433b3c0800132549fa10c9deefbeafdd7b70aba4bbc6a987ca2fef54790600090a150565b60006001611159612d10565b60010154611165612d10565b540303919050565b6111773382612e18565b50565b611182612e24565b6110e98282612e3f565b7f6bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c6001806111b8612e4b565b6111c29190614d89565b6040805192835260208301919091520160405180910390a1565b6060816001600160401b038111156111f6576111f66144b8565b60405190808252806020026020018201604052801561121f578160200160208202803683370190505b50905060005b8083146112845761125884848381811061124157611241614cf0565b905060200201356008612e5b90919063ffffffff16565b82828151811061126a5761126a614cf0565b60ff90921660209283029190910190910152600101611225565b5092915050565b600061129682612e7c565b6001600160a01b0394851694909150811684146112bc576112bc62a1148160e81b612d06565b6000806112c884612f3e565b915091506112ed81876112d83390565b6001600160a01b039081169116811491141790565b61130f576112fb8633612717565b61130f5761130f632ce44b5f60e11b612d06565b801561131a57600082555b611322612d10565b6001600160a01b038716600090815260059190910160205260409020805460001901905561134e612d10565b6001600160a01b03861660008181526005929092016020526040909120805460010190554260a01b17600160e11b17611385612d10565b60008681526004919091016020526040812091909155600160e11b841690036113fb57600184016113b4612d10565b6000828152600491909101602052604081205490036113f9576113d5612d10565b5481146113f957836113e5612d10565b600083815260049190910160205260409020555b505b6001600160a01b0385168481887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a48060000361144557611445633a954ecd60e21b612d06565b50505050505050565b6001611459816128b5565b6110e982612f66565b600061108382612fbd565b60006202a3006001600160401b03164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b60006110836114ca83612875565b54600160c81b9004600216151590565b6005546001600160a01b03166000600160f01b83106114fb576114fb613002565b600554612710600160a01b90910461ffff168402045b90509250929050565b606061108382600061152b85612203565b63ffffffff16612263565b61153e614068565b600061154983612875565b60ff84168352905061155a81613010565b63ffffffff90811660208401528154600160401b810482166040850152600160601b810482166060850152600160801b810482166080850152600160a01b90041660a08301526115a981613063565b60c08301526115c28154600160c81b9004600216151590565b15156101008301526115d3816130ac565b151560e08301526115ee8154600160c81b9004600416151590565b151561012083015250919050565b6001611607816128b5565b611610826130d6565b6005805461ffff60a01b1916600160a01b61ffff8516908102919091179091556040519081527f092d0aa94dc2b378c7fd77faaaf4cb3fd8336ae247cd486fb593726705772ac0906020015b60405180910390a15050565b6006546060906001600160a01b0316156116ed5760065460405163c87b56dd60e01b8152600481018490526001600160a01b039091169063c87b56dd90602401600060405180830381865afa1580156116c5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110839190810190614d9c565b60006116f7611979565b905080516000036117175760405180602001604052806000815250611742565b80611721846130fd565b604051602001611732929190614e09565b6040516020818303038152906040525b9392505050565b61176483838360405180602001604052806000815250612222565b505050565b611177816001613141565b61177c612e24565b6110e98282612e18565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b60016117cd816128b5565b6117d56132b9565b6117e06001836132ec565b7ff9c7803e94e0d3c02900d8a90893a6d5e90dd04d32a4cfe825520f82bf9f32f68260405161180f919061420f565b60405180910390a16110e961118c565b60408051828152600583901b8082016020019092526060915b801561186357601f198082019186010135600061185482612356565b84840160200152506118389050565b509392505050565b60006001611878816128b5565b604051838582376000805260206000858360008a5af161189c573d6000803e3d6000fd5b50600051915061186382612f66565b600061108382612e7c565b60006118c182612ca8565b6118de5760405163163ceb7760e11b815260040160405180910390fd5b6008602052600582901c60009081526040902054601f8319161a611083565b6001611908816128b5565b600061191383612875565b905061191e816132f8565b805460ff600160c81b80830482166004170260ff60c81b1990921691909117825560405190841681527f5455468b416476a27220f0fc8daad92345a6c408a0356acd2560b63bf0e51d949060200160405180910390a1505050565b6060611985600161332a565b905090565b60006001600160a01b0382166119aa576119aa6323d3ad8160e21b612d06565b6001600160401b036119ba612d10565b6005016000846001600160a01b03166001600160a01b0316815260200190815260200160002054169050919050565b6119f1612e24565b6119fb6000613415565b565b6000611985612e4b565b6001611a12816128b5565b611a1a612de5565b611a2382613453565b7fc14f5a12ed3f072ab9522493ce2b476e950ee5a3f3abf2324961c6ac66b00e948260405161165c9190614e87565b600080611a5e836118b6565b9050600080611a96856000611a7286612203565b60ff8716600090815260096020526040902092919063ffffffff9081169061360316565b9092509050811515640100000000861016611ab357600019611ab5565b805b95945050505050565b6001611ac9816128b5565b6000611ad484612875565b9050611adf816132f8565b611ae881613627565b805463ffffffff60801b1916600160801b63ffffffff85169081029190911782556040805160ff8716815260208101929092527fbfb64051edb1b4f08e14520b9ed4d2609e52d66c0c83cfb1ac125ab41734fceb91015b60405180910390a150505050565b611b5f8160000151826020015161364e565b611b6f611b6a6136d3565b613731565b611b7c8160c001516130d6565b611b898160a0015161376d565b6060810151611b9a90600190613794565b6080810151611bab90600390613794565b60a0810151600580546001600160a01b0319166001600160a01b03909216919091179055610120810151516000819003611bf8576040516392ce813760e01b815260040160405180910390fd5b60005b818114611c3157611c298361012001518281518110611c1c57611c1c614cf0565b6020026020010151613453565b600101611bfb565b50506040810151600680546001600160a01b0319166001600160a01b0390921691909117905560c08101516005805461ffff60a01b1916600160a01b61ffff90931692909202919091179055610100810151151560020260e0820151151517600560166101000a81548160ff021916908360ff1602179055507f4f32c97826173bff1ee9613d86862d161dfbc943f1f5960528f88c42a79fb56881604051611cd99190614ecf565b60405180910390a150565b606060016000611cf2612e4b565b90506060818314611ab357611ab58584846137ad565b6000816001600160401b03811115611d2257611d226144b8565b604051908082528060200260200182016040528015611d4b578160200160208202803683370190505b506005549091506001600160a01b031660005b808414611dba57611d95858583818110611d7a57611d7a614cf0565b9050602002016020810190611d8f9190614334565b836138b5565b838281518110611da757611da7614cf0565b6020908102919091010152600101611d5e565b507fcadee7ff7164fffa7c9c81726bbc520c1fb0bc36d7ac763997ea74aee0e387e48185858533604051611b3f959493929190614fd6565b6001611dfd816128b5565b6000611e0885612875565b9050611e13816132f8565b611e1c81613627565b8054600160a01b900463ffffffff168015611e96578154600160601b810463ffffffff90811686821611600160401b9092048116908716111715611e7357604051633a964d4760e01b815260040160405180910390fd5b63ffffffff85168181108282180218945063ffffffff8416818110828218021893505b8363ffffffff168563ffffffff161115611ec357604051633a964d4760e01b815260040160405180910390fd5b815467ffffffffffffffff60401b1916600160401b63ffffffff87811691820263ffffffff60601b191692909217600160601b9287169283021784556040805160ff8a16815260208101929092528101919091527faabbe826f21f31d8508fe47762ab61162f999f0c296e1a88ce50d1ef0ea6da849060600160405180910390a1505050505050565b6001611f57816128b5565b611f5f6132b9565b611f6a6003836132ec565b7faf497693a87db12ca89131a31edbb3db4bb5702dfb284e8ae7427d185f09112d8260405161165c919061420f565b6060611083612b20565b6001611fae816128b5565b6000611fb984612875565b9050611fc4816132f8565b611fcd8161392d565b8054611ff09060ff600160c81b9091041660028560ff8383161615901518021890565b815460ff60c81b1916600160c81b60ff9283160217825560408051918616825284151560208301527f9213f35ab455184cb0b8872ec8a16bd1fb69d2f0e909f4174a93470cd5e225009101611b3f565b606061204d8484846137ad565b949350505050565b8061205e612d10565b336000818152600792909201602090815260408084206001600160a01b03881680865290835293819020805460ff19169515159590951790945592518415158152919290917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b600061198561395a565b60016120e7816128b5565b6120ef6132b9565b600680546001600160a01b0319166001600160a01b0384169081179091556040519081527ff3fdd6d3ba37d1479142dbb6aef216c352108f558ce922646b4b0d86454d11389060200161180f565b60008061214983612875565b9050600061215682613063565b9050600061216383613010565b63ffffffff16905080158215176121a85760ff85166000908152600960209081526040808320848606600381901c855292529091205460059190911b60e0161c611ab5565b600095945050505050565b60006110836121c183612875565b54600160c81b9004600416151590565b60006121dc82612875565b54600160801b900463ffffffff1692915050565b60006110836121fe83612875565b613063565b600061220e82612875565b54600160a01b900463ffffffff1692915050565b61222d84848461128b565b6001600160a01b0383163b1561225d576122498484848461396d565b61225d5761225d6368d2bf6b60e11b612d06565b50505050565b6060828203600061227386612203565b63ffffffff16905080841184861117156122a057604051631960ccad60e11b815260040160405180910390fd5b816001600160401b038111156122b8576122b86144b8565b6040519080825280602002602001820160405280156122e1578160200160208202803683370190505b5060ff871660009081526009602052604081209194505b83811461234b57868101600381901c60009081526020849052604090205460059190911b60e0161c63ffffffff1685828151811061233857612338614cf0565b60209081029190910101526001016122f8565b505050509392505050565b604080516080810182526000808252602082018190529181018290526060810191909152600182106123b45761238a612e4b565b8210156123b4575b61239b82613a4f565b6123ab5760001990910190612392565b61108382613a6f565b919050565b60006110836123c783612875565b613010565b60606123d782612ca8565b6123f457604051630a14c4b560e41b815260040160405180910390fd5b61108382611668565b6001612408816128b5565b6124106132b9565b6005805460ff60b01b1981166001600160b01b9283900460ff16179091021790556006547f7028d29d7b13876d9de031ac95eb6acef3e844e1d010820781406e6cd5fc70f9906001600160a01b0316612467611979565b61246f61270b565b604051611cd993929190615021565b6000611985613af8565b600061108361249683612875565b6130ac565b600061108382613b0b565b60055447906001600160a01b03166124be8183613b1f565b604080516001600160a01b03831681526020810184905233918101919091527f134d6e96840903022b8e4b57aa0644e9eb6ca6fe65a25205b0857fe918c2bcc69060600161165c565b612593604051806101c001604052806060815260200160608152602001606081526020016060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600015158152602001600015158152602001600061ffff16815260200160008152602001600081526020016000815260200160008152602001606081525090565b61259b611979565b81526125a561270b565b60208201526125b2612b20565b606083015260408201526005546001600160a01b0380821660808401526006541660a0830152600160b01b810460018116151560c0840152600216151560e0830152600160a01b900461ffff1661010082015261260d6119fd565b61012082015261261b6120d2565b61016082015261262961247e565b61014082015261263761114d565b610180820152600654600160a01b810461ffff1690600160b01b900460ff16816001600160401b0381111561266e5761266e6144b8565b6040519080825280602002602001820160405280156126a757816020015b612694614068565b81526020019060019003908161268c5790505b506101a08401525b81156127065760006126c082612875565b90506126cb82611536565b846101a001518460019003945084815181106126e9576126e9614cf0565b602090810291909101015254600160c01b900460ff1690506126af565b505090565b6060611985600361332a565b6000612721612d10565b6001600160a01b039384166000908152600791909101602090815260408083209490951682529290925250205460ff1690565b600061275f82612875565b54600160401b900463ffffffff1692915050565b60006003612780816128b5565b61278a8584612903565b5091506127978484612a87565b6040805160ff871681526001600160a01b0386166020820152908101849052606081018390527f7ac572687bf4e66a8514fc2ec464fc2644c78bcb1d80a225fc51a33e0ee38bfa9060800160405180910390a1509392505050565b6127fa612e24565b63389a75e1600c52806000526020600c20805442111561282257636f5e88186000526004601cfd5b6000905561117781613415565b612837612e24565b8060601b61284d57637448fbae6000526004601cfd5b61117781613415565b6008602052600581901c60009081526040812054601f8319161a611083565b60ff8116600090815260076020526040812080549091600160c81b90910460011690036123b457604051630bec67bf60e31b815260040160405180910390fd5b60006128bf6136d3565b638b78c6d8600c9081526000829052602090205490915082166110e957638b78c6d819546001600160a01b0316816001600160a01b0316146110e9576110e9613b62565b600080826000036129275760405163b562e8dd60e01b815260040160405180910390fd5b61292f612e4b565b91506401000000006001848401031061294a5761294a613002565b600061295585612875565b8054909150600160a01b900463ffffffff16600061297283613010565b63ffffffff1690508186018181111561299e576040516316b9b18560e01b815260040160405180910390fd5b835463ffffffff60a01b1916600160a01b63ffffffff831602178085556002600160c81b90910416156129ff5783546129e2906001600160401b0316848985613b70565b845467ffffffffffffffff19166001600160401b03919091161784555b60ff88166000908152600960205260408120905b888114612a7757612a58828683018a8401826020528160031c60005260406000206007831660051b815463ffffffff8482841c188116831b8218845550505050505050565b60ff8a1615612a6f57612a6f60088983018c613be5565b600101612a13565b5083955050505050509250929050565b601f81168015612a9b57612a9b8382613c0b565b81811461176457612aad836020613c0b565b602001612a9b565b60006301ffc9a760e01b6001600160e01b031983161480612ae657506380ac58cd60e01b6001600160e01b03198316145b806110835750506001600160e01b031916635b5e139f60e01b1490565b6000611ab585612b17868515158715151782565b15159015151790565b60005460609081908015612b7857612b6e81604080516080810182526000808252918101828152601f820193909352805181016020018051605f830152829052825181016060019190915291565b9093509150509091565b6000612b82612d10565b9050806002018054612b9390615057565b80601f0160208091040260200160405190810160405280929190818152602001828054612bbf90615057565b8015612c0c5780601f10612be157610100808354040283529160200191612c0c565b820191906000526020600020905b815481529060010190602001808311612bef57829003601f168201915b50505050509350806003018054612c2290615057565b80601f0160208091040260200160405190810160405280929190818152602001828054612c4e90615057565b8015612c9b5780601f10612c7057610100808354040283529160200191612c9b565b820191906000526020600020905b815481529060010190602001808311612c7e57829003601f168201915b5050505050925050509091565b6000816001116123b457612cba612d10565b548210156123b45760005b612ccd612d10565b600084815260049190910160205260408120549150819003612cf957612cf28361508b565b9250612cc5565b600160e01b161592915050565b8060005260046000fd5b7f2569078dfb4b0305704d3008e7403993ae9601b85f7ae5e742de3de8f8011c4090565b6000612d3f836118ab565b9050818015612d575750336001600160a01b03821614155b15612d7a57612d668133612717565b612d7a57612d7a6367d9dca160e11b612d06565b83612d83612d10565b6000858152600691909101602052604080822080546001600160a01b0319166001600160a01b0394851617905551859287811692908516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a450505050565b612dfa600554600160b01b9004600216151590565b156119fb57604051635dc9af4560e11b815260040160405180910390fd5b6110e982826000613cff565b638b78c6d8195433146119fb576382b429006000526004601cfd5b6110e982826001613cff565b6000612e55612d10565b54919050565b6000826020528160051c6000526040600020548219601f161a905092915050565b600081600111612f2e57612e8e612d10565b600083815260049190910160205260408120549150819003612f1b57612eb2612d10565b548210612ec957612ec9636f96cda160e11b612d06565b612ed1612d10565b600019909201600081815260049390930160205260409092205490508015612ec957600160e01b8116600003612f0657919050565b612f16636f96cda160e11b612d06565b612ec9565b600160e01b8116600003612f2e57919050565b6123b4636f96cda160e11b612d06565b6000806000612f4b612d10565b60009485526006016020525050604090912080549092909150565b612f6f8161376d565b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527f94c4ad53e91574d56aff9aef0726376e9154e071a602000edf9208f28d649be190602001611cd9565b60006001600160401b036080612fd1612d10565b6005016000856001600160a01b03166001600160a01b0316815260200190815260200160002054901c169050919050565b6335278d126000526004601cfd5b8054600090600160801b900463ffffffff1642101561303b575054600160601b900463ffffffff1690565b81546110839063ffffffff600160401b8204811691600160a01b900416808218908210021890565b60006130798254600160c81b9004600216151590565b80156130895750613089826130ac565b156123b45750546001600160401b03166000908152306020526040902080150190565b60006130b782613010565b915463ffffffff928316600160a01b9091049092169190911015919050565b61271061ffff82161115611177576040516319510c8760e31b815260040160405180910390fd5b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a9004806131175750819003601f19909101908152919050565b600061314c83612e7c565b90508060008061315b86612f3e565b915091508415613192576131708184336112d8565b6131925761317e8333612717565b61319257613192632ce44b5f60e11b612d06565b801561319d57600082555b6fffffffffffffffffffffffffffffffff6131b6612d10565b6001600160a01b038516600081815260059290920160205260409091208054929092019091554260a01b17600360e01b176131ef612d10565b60008881526004919091016020526040812091909155600160e11b85169003613265576001860161321e612d10565b6000828152600491909101602052604081205490036132635761323f612d10565b548114613263578461324f612d10565b600083815260049190910160205260409020555b505b60405186906000906001600160a01b038616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a46132a5612d10565b600190810180549091019055505050505050565b6132ce600554600160b01b9004600116151590565b156119fb5760405163b087bbf360e01b815260040160405180910390fd5b6110e982826001613d58565b61330c8154600160c81b9004600416151590565b1561117757604051633fa1be4f60e01b815260040160405180910390fd5b8054606090806133c95782600101805461334390615057565b80601f016020809104026020016040519081016040528092919081815260200182805461336f90615057565b80156133bc5780601f10613391576101008083540402835291602001916133bc565b820191906000526020600020905b81548152906001019060200180831161339f57829003601f168201915b5050505050915050919050565b6060604051905060408101604052602081528160208201526133ed81600180613de0565b6040516020016133fd91906150a2565b60405160208183030381529060405292505050919050565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b805160ff811660009081526007602052604090208054600160c81b90046001161561349157604051632520e1bd60e11b815260040160405180910390fd5b60ff82166134c45763ffffffff6020840181905260408401819052606084015260006080840152600160a08401526134f9565b826040015163ffffffff16836020015163ffffffff1611156134f957604051633a964d4760e01b815260040160405180910390fd5b602083015181546040850151606086015167ffffffffffffffff60401b19909216600160401b63ffffffff9485160263ffffffff60601b191617600160601b918416919091021763ffffffff60801b1916600160801b929091169190910217815560a0830151151560040260808401511515600202825460ff9290911760019081178316600160c81b0260ff60c81b1983168117855560068054600160c01b600160b01b80830488169190910260ff60c01b1990941661ffff60c01b19909616959095179290921790955584549590931690910260ff60b01b1961ffff600160a01b9485900481169093019092169092021662ffffff60a01b199093169290921791909117905550565b60008061361a8663ffffffff871686866020613ec7565b9150915094509492505050565b613630816130ac565b15611177576040516337149c8160e21b815260040160405180910390fd5b6000613658612d10565b80549091501561366a5761366a613b62565b6001815560006136a1848460008251601e600184518301031081601e850103518286015183601f0360031b1b170291505092915050565b9050806136cb57600282016136b68582615128565b50600382016136c58482615128565b5061225d565b600055505050565b6000336000526e2fd5aeb385d324b580fca7c83823a080330361370157602060008038845afa613701573838fd5b506dd9ecebf3c23529de49815dac1c4c80330361372957602060008038845afa613729573838fd5b505060005190565b6001600160a01b0316638b78c6d8198190558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b6001600160a01b03811661117757604051630797cc5760e31b815260040160405180910390fd5b80516000036137a1575050565b6110e982826000613d58565b60608183106137c6576137c6631960ccad60e11b612d06565b60018310156137d457600192505b60006137de612e4b565b90508083106137eb578092505b606060006137f88761198a565b858710908102915081156138a95781878703116138155786860391505b60405192506001820160051b8301604052600061383188612356565b905060008160400151613842575080515b60005b61384e8a613a6f565b9250604083015160008114613866576000925061388b565b83511561387257835192505b8b831860601b61388b576001820191508a8260051b8801525b5060018a019950888a148061389f57508481145b1561384557855250505b50909695505050505050565b60006370a0823160005230602052602060346024601c865afa601f3d11166138e5576390b8ec186000526004601cfd5b81601452603451905063a9059cbb60601b60005260206000604460106000875af13d156001600051141716613922576390b8ec186000526004601cfd5b600060345292915050565b8054600160a01b900463ffffffff1615611177576040516330b33cff60e01b815260040160405180910390fd5b60006001613966612d10565b5403919050565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a02906139a29033908990889088906004016151e7565b6020604051808303816000875af19250505080156139dd575060408051601f3d908101601f191682019092526139da9181019061521a565b60015b613a32573d808015613a0b576040519150601f19603f3d011682016040523d82523d6000602084013e613a10565b606091505b508051600003613a2a57613a2a6368d2bf6b60e11b612d06565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050949350505050565b6000613a59612d10565b6000928352600401602052506040902054151590565b604080516080810182526000808252602082018190529181018290526060810191909152611083613a9e612d10565b60008481526004919091016020526040902054604080516080810182526001600160a01b038316815260a083901c6001600160401b03166020820152600160e01b831615159181019190915260e89190911c606082015290565b6000613b02612d10565b60010154905090565b60006001600160401b036040612fd1612d10565b80471015613b355763b12d13eb6000526004601cfd5b6000386000388486620186a0f16110e957816000526073600b5360ff6020536016600b82f06110e9573838fd5b6382b429006000526004601cfd5b838183021561204d578284015b8560ff16600101430340600052844487181860205260406000208660008114613bc657866001868406011115613bc1578160ff1c8860011b17600052602060002093505b613bca565b8193505b5050819550600185019450808503613b7d5750949350505050565b826020528160051c60005260406000208054600052818319601f16536000519055505050565b6000613c15612d10565b5490506000829003613c3157613c3163b562e8dd60e01b612d06565b6001600160a01b0383164260a01b6001841460e11b1717613c50612d10565b60008381526004919091016020526040902055680100000000000000018202613c77612d10565b6001600160a01b0385166000818152600592909201602052604082208054909301909255819003613cb157613cb1622e076360e81b612d06565b818301825b808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4818160010191508103613cb65781613cf5612d10565b5550611764915050565b638b78c6d8600c52826000526020600c20805483811783613d21575080841681185b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3505050505050565b8151600060308214603183141715613d90576461723a2f2f64ffffffffff60058601511603613d905760019050600584019350602b84525b8015613dbf576000613da185613f6b565b602001516461723a2f2f865260041990950183815294865550613dd9565b60018501613dcd8582615128565b508215613dd957600085555b5050505050565b606083518015611863576003600282010460021b60405192507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f526106708515027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f18603f52602083018181015b6003880197508751603f8160121c1651600053603f81600c1c1651600153603f8160061c1651600253603f811651600353506000518252600482019150808210613e5057602001604052613d3d60f01b60038406600204808303919091526000861515909102918290035290038252509392505050565b600080838510613ed5578493505b6000600019860160018261010087900490506000196001881b018989035b83811684821860011c019650808411613f4a57848701838104600090815260208f90526040902054908490068a021c821695508b8614613f4a57858c11613f3f57506000198601613ef3565b866001019350613ef3565b50505050931582151796188617159760018218909602189091019450505050565b6060815180156110935760038160021c0260038216613fa05783820151613d3d18601e81901a1560ff90911615019003613faa565b6003821601600019015b60405192508083526020830181810191507ffc000000fc00686c7074787c8084888c9094989ca0a4a8acb0b4b8bcc0c4c8cc80605b527804080c1014181c2024282c3034383c4044484c5054585c6064603b526ef8fcf800fcd0d4d8dce0e4e8ecf0f4601a525b600486019550855180601f1a5160061c81601e1a5183161760061c81601d1a5183161760061c81601c1a51831617835250600382019150828210614011575050602081016040526000815250600060605250919050565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b803560ff811681146123b457600080fd5b6000602082840312156140df57600080fd5b611742826140bc565b60008083601f8401126140fa57600080fd5b5081356001600160401b0381111561411157600080fd5b6020830191508360208260051b850101111561412c57600080fd5b9250929050565b6000806000806060858703121561414957600080fd5b614152856140bc565b935060208501356001600160401b0381111561416d57600080fd5b614179878288016140e8565b9598909750949560400135949350505050565b6001600160e01b03198116811461117757600080fd5b6000602082840312156141b457600080fd5b81356117428161418c565b60005b838110156141da5781810151838201526020016141c2565b50506000910152565b600081518084526141fb8160208601602086016141bf565b601f01601f19169290920160200192915050565b60208152600061174260208301846141e3565b60006020828403121561423457600080fd5b5035919050565b80356001600160a01b03811681146123b457600080fd5b6000806040838503121561426557600080fd5b61426e8361423b565b946020939093013593505050565b6000806020838503121561428f57600080fd5b82356001600160401b038111156142a557600080fd5b6142b1858286016140e8565b90969095509350505050565b6020808252825182820181905260009190848201906040850190845b818110156138a957835160ff16835292840192918401916001016142d9565b60008060006060848603121561430d57600080fd5b6143168461423b565b92506143246020850161423b565b9150604084013590509250925092565b60006020828403121561434657600080fd5b6117428261423b565b6000806040838503121561436257600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b838110156143a157815187529582019590820190600101614385565b509495945050505050565b6020815260006117426020830184614371565b805160ff16825260208101516143dd602084018263ffffffff169052565b5060408101516143f5604084018263ffffffff169052565b50606081015161440d606084018263ffffffff169052565b506080810151614425608084018263ffffffff169052565b5060a081015161443d60a084018263ffffffff169052565b5060c081015160c083015260e081015161445b60e084018215159052565b5061010081810151151590830152610120808201518015158285015261225d565b610140810161108382846143bf565b803561ffff811681146123b457600080fd5b6000602082840312156144af57600080fd5b6117428261448b565b634e487b7160e01b600052604160045260246000fd5b60405161014081016001600160401b03811182821017156144f1576144f16144b8565b60405290565b604051601f8201601f191681016001600160401b038111828210171561451f5761451f6144b8565b604052919050565b60006001600160401b03821115614540576145406144b8565b50601f01601f191660200190565b600061456161455c84614527565b6144f7565b905082815283838301111561457557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261459d57600080fd5b6117428383356020850161454e565b6000602082840312156145be57600080fd5b81356001600160401b038111156145d457600080fd5b61204d8482850161458c565b80516001600160a01b031682526020808201516001600160401b03169083015260408082015115159083015260609081015162ffffff16910152565b6020808252825182820181905260009190848201906040850190845b818110156138a95761464b8385516145e0565b9284019260809290920191600101614638565b60008060006040848603121561467357600080fd5b61467c8461423b565b925060208401356001600160401b038082111561469857600080fd5b818601915086601f8301126146ac57600080fd5b8135818111156146bb57600080fd5b8760208285010111156146cd57600080fd5b6020830194508093505050509250925092565b803563ffffffff811681146123b457600080fd5b803580151581146123b457600080fd5b600060c0828403121561471657600080fd5b60405160c081018181106001600160401b0382111715614738576147386144b8565b604052905080614747836140bc565b8152614755602084016146e0565b6020820152614766604084016146e0565b6040820152614777606084016146e0565b6060820152614788608084016146f4565b608082015261479960a084016146f4565b60a08201525092915050565b600060c082840312156147b757600080fd5b6117428383614704565b600080604083850312156147d457600080fd5b6147dd836140bc565b9150611511602084016146e0565b600082601f8301126147fc57600080fd5b813560206001600160401b03821115614817576148176144b8565b614825818360051b016144f7565b82815260c0928302850182019282820191908785111561484457600080fd5b8387015b858110156148675761485a8982614704565b8452928401928101614848565b5090979650505050505050565b60006020828403121561488657600080fd5b81356001600160401b038082111561489d57600080fd5b9083019061014082860312156148b257600080fd5b6148ba6144ce565b8235828111156148c957600080fd5b6148d58782860161458c565b8252506020830135828111156148ea57600080fd5b6148f68782860161458c565b6020830152506149086040840161423b565b604082015260608301358281111561491f57600080fd5b61492b8782860161458c565b60608301525060808301358281111561494357600080fd5b61494f8782860161458c565b60808301525061496160a0840161423b565b60a082015261497260c0840161448b565b60c082015261498360e084016146f4565b60e08201526101006149968185016146f4565b9082015261012083810135838111156149ae57600080fd5b6149ba888287016147eb565b918301919091525095945050505050565b6000806000606084860312156149e057600080fd5b6149e9846140bc565b92506149f7602085016146e0565b9150614a05604085016146e0565b90509250925092565b60008060408385031215614a2157600080fd5b614a2a836140bc565b9150611511602084016146f4565b600080600060608486031215614a4d57600080fd5b614a568461423b565b95602085013595506040909401359392505050565b60008060408385031215614a7e57600080fd5b614a2a8361423b565b60008060008060808587031215614a9d57600080fd5b614aa68561423b565b9350614ab46020860161423b565b92506040850135915060608501356001600160401b03811115614ad657600080fd5b8501601f81018713614ae757600080fd5b614af68782356020840161454e565b91505092959194509250565b600080600060608486031215614b1757600080fd5b614a56846140bc565b6080810161108382846145e0565b600081518084526020808501945080840160005b838110156143a157614b558783516143bf565b610140969096019590820190600101614b42565b60208152600082516101c0806020850152614b886101e08501836141e3565b91506020850151601f1980868503016040870152614ba684836141e3565b93506040870151915080868503016060870152614bc384836141e3565b93506060870151915080868503016080870152614be084836141e3565b935060808701519150614bfe60a08701836001600160a01b03169052565b60a08701516001600160a01b03811660c0880152915060c087015180151560e0880152915060e08701519150610100614c3a8188018415159052565b8701519150610120614c518782018461ffff169052565b8701516101408781019190915287015161016080880191909152870151610180808801919091528701516101a080880191909152870151868503909101838701529050614c9e8382614b2e565b9695505050505050565b60008060408385031215614cbb57600080fd5b614cc48361423b565b91506115116020840161423b565b600080600060608486031215614ce757600080fd5b614316846140bc565b634e487b7160e01b600052603260045260246000fd5b8183526000602080850194508260005b858110156143a1576001600160a01b03614d2f8361423b565b1687529582019590820190600101614d16565b60ff86168152608060208201526000614d5f608083018688614d06565b604083019490945250606001529392505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561108357611083614d73565b600060208284031215614dae57600080fd5b81516001600160401b03811115614dc457600080fd5b8201601f81018413614dd557600080fd5b8051614de361455c82614527565b818152856020838501011115614df857600080fd5b611ab58260208301602086016141bf565b60008351614e1b8184602088016141bf565b835190830190614e2f8183602088016141bf565b01949350505050565b60ff8151168252602081015163ffffffff8082166020850152806040840151166040850152806060840151166060850152505060808101511515608083015260a0810151151560a08301525050565b60c081016110838284614e38565b600081518084526020808501945080840160005b838110156143a157614ebc878351614e38565b60c0969096019590820190600101614ea9565b6020815260008251610140806020850152614eee6101608501836141e3565b91506020850151601f1980868503016040870152614f0c84836141e3565b935060408701519150614f2a60608701836001600160a01b03169052565b6060870151915080868503016080870152614f4584836141e3565b935060808701519150808685030160a0870152614f6284836141e3565b935060a08701519150614f8060c08701836001600160a01b03169052565b60c087015161ffff811660e0880152915060e08701519150610100614fa88188018415159052565b8701519150610120614fbd8782018415159052565b870151868503909101838701529050614c9e8382614e95565b600060018060a01b03808816835260806020840152614ff9608084018789614d06565b838103604085015261500b8187614371565b9250508084166060840152509695505050505050565b6001600160a01b0384168152606060208201819052600090615045908301856141e3565b8281036040840152614c9e81856141e3565b600181811c9082168061506b57607f821691505b60208210810361109357634e487b7160e01b600052602260045260246000fd5b60008161509a5761509a614d73565b506000190190565b6461723a2f2f60d81b8152600082516150c28160058501602087016141bf565b602f60f81b6005939091019283015250600601919050565b601f82111561176457600081815260208120601f850160051c810160208610156151015750805b601f850160051c820191505b818110156151205782815560010161510d565b505050505050565b81516001600160401b03811115615141576151416144b8565b6151558161514f8454615057565b846150da565b602080601f83116001811461518a57600084156151725750858301515b600019600386901b1c1916600185901b178555615120565b600085815260208120601f198616915b828110156151b95788860151825594840194600190910190840161519a565b50858210156151d75787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090614c9e908301846141e3565b60006020828403121561522c57600080fd5b81516117428161418c56fea264697066735822122049e6d1cd0280f13035da064d43e0d0c04baabf189e47190a2588815ba6a8c9fa64736f6c63430008130033
Deployed Bytecode
0x6080604052600436106104ca5760003560e01c80637793818111610276578063b9c9d93a1161014f578063e1a45218116100c1578063eebab8ef11610085578063eebab8ef14610ed6578063f04e283e14610ee9578063f2fde38b14610efc578063faf37bc414610f0f578063fcff385214610f2f578063fee81cf414610f4457600080fd5b8063e1a4521814610e49578063e7a6020d14610e5f578063e8a3d48514610e81578063e985e9c514610e96578063eb78a07614610eb657600080fd5b8063d111515d11610113578063d111515d14610db5578063d539139314610dca578063d89135cd14610ddf578063db0ea80514610df4578063dc33e68114610e14578063e086e5ec14610e3457600080fd5b8063b9c9d93a14610cf3578063c0ede3cf14610d28578063c23dc68f14610d48578063c5bc5a4c14610d75578063c87b56dd14610d9557600080fd5b806399a2557a116101e8578063a8f5473e116101ac578063a8f5473e14610c3e578063aec9b83c14610c60578063b0fbdc8b14610c80578063b393cf7a14610ca0578063b7c858fb14610cc0578063b88d4fde14610ce057600080fd5b806399a2557a14610ba9578063a22cb46514610bc9578063a2309ff814610be9578063a4198fa214610bfe578063a468f04314610c1e57600080fd5b806390e89bb81161023a57806390e89bb814610aff57806390ecf29c14610b1f578063938e3d7b14610b3f57806393e8bcf914610b5f57806395d89b4114610b74578063998ad69114610b8957600080fd5b80637793818114610a665780637ab51f9e14610a865780637f84110f14610aa65780638462151c14610ac65780638da5cb5b14610ae657600080fd5b80632f01b56e116103a85780635bbb21771161031a5780636c0360eb116102de5780636c0360eb146109df57806370a08231146109f4578063715018a614610a1457806375794a3c14610a1c57806375b238fc14610a31578063774de39614610a4657600080fd5b80635bbb2177146109205780635f08f8761461094d5780636352211e1461096d578063649e705f1461098d5780636a3d27c6146109bf57600080fd5b806342842e0e1161036c57806342842e0e1461087b57806342966c681461088e5780634a4ee7b1146108ae578063514e62fc146108c157806354d1f13d146108f857806355f804b31461090057600080fd5b80632f01b56e146107c157806335766f4b146107ee5780633684d1001461081b57806336e79a5a1461083b5780633e1a5b851461085b57600080fd5b80631c10893f11610441578063241d965111610405578063241d9651146106e75780632478d6391461070757806325692962146107275780632a036a4d1461072f5780632a55205a1461074f5780632de948071461078e57600080fd5b80631c10893f146106485780631c519ba41461065b5780631cd64df4146106705780631cdb1765146106a757806323b872dd146106d457600080fd5b8063095ea7b311610493578063095ea7b3146105b45780630e24495e146105c9578063110db80e146105eb57806318160ddd14610600578063183a4f6e146106155780631bb534ba1461062857600080fd5b80624dad56146104cf578063010fe62c1461050957806301ffc9a71461052a57806306fdde031461055a578063081812fc1461057c575b600080fd5b3480156104db57600080fd5b506104ef6104ea3660046140cd565b610f77565b60405163ffffffff90911681526020015b60405180910390f35b61051c610517366004614133565b610f96565b604051908152602001610500565b34801561053657600080fd5b5061054a6105453660046141a2565b61103d565b6040519015158152602001610500565b34801561056657600080fd5b5061056f611089565b604051610500919061420f565b34801561058857600080fd5b5061059c610597366004614222565b611099565b6040516001600160a01b039091168152602001610500565b6105c76105c2366004614252565b6110dd565b005b3480156105d557600080fd5b5061054a600554600160b01b9004600116151590565b3480156105f757600080fd5b506105c76110ed565b34801561060c57600080fd5b5061051c61114d565b6105c7610623366004614222565b61116d565b34801561063457600080fd5b5060055461059c906001600160a01b031681565b6105c7610656366004614252565b61117a565b34801561066757600080fd5b506105c761118c565b34801561067c57600080fd5b5061054a61068b366004614252565b638b78c6d8600c90815260009290925260209091205481161490565b3480156106b357600080fd5b506106c76106c236600461427c565b6111dc565b60405161050091906142bd565b6105c76106e23660046142f8565b61128b565b3480156106f357600080fd5b506105c7610702366004614334565b61144e565b34801561071357600080fd5b5061051c610722366004614334565b611462565b6105c761146d565b34801561073b57600080fd5b5061054a61074a3660046140cd565b6114bc565b34801561075b57600080fd5b5061076f61076a36600461434f565b6114da565b604080516001600160a01b039093168352602083019190915201610500565b34801561079a57600080fd5b5061051c6107a9366004614334565b638b78c6d8600c908152600091909152602090205490565b3480156107cd57600080fd5b506107e16107dc3660046140cd565b61151a565b60405161050091906143ac565b3480156107fa57600080fd5b5061080e6108093660046140cd565b611536565b604051610500919061447c565b34801561082757600080fd5b5060065461059c906001600160a01b031681565b34801561084757600080fd5b506105c761085636600461449d565b6115fc565b34801561086757600080fd5b5061056f610876366004614222565b611668565b6105c76108893660046142f8565b611749565b34801561089a57600080fd5b506105c76108a9366004614222565b611769565b6105c76108bc366004614252565b611774565b3480156108cd57600080fd5b5061054a6108dc366004614252565b638b78c6d8600c90815260009290925260209091205416151590565b6105c7611786565b34801561090c57600080fd5b506105c761091b3660046145ac565b6117c2565b34801561092c57600080fd5b5061094061093b36600461427c565b61181f565b604051610500919061461c565b34801561095957600080fd5b5061059c61096836600461465e565b61186b565b34801561097957600080fd5b5061059c610988366004614222565b6118ab565b34801561099957600080fd5b506109ad6109a8366004614222565b6118b6565b60405160ff9091168152602001610500565b3480156109cb57600080fd5b506105c76109da3660046140cd565b6118fd565b3480156109eb57600080fd5b5061056f611979565b348015610a0057600080fd5b5061051c610a0f366004614334565b61198a565b6105c76119e9565b348015610a2857600080fd5b5061051c6119fd565b348015610a3d57600080fd5b5061051c600181565b348015610a5257600080fd5b506105c7610a613660046147a5565b611a07565b348015610a7257600080fd5b5061051c610a81366004614222565b611a52565b348015610a9257600080fd5b506105c7610aa13660046147c1565b611abe565b348015610ab257600080fd5b506105c7610ac1366004614874565b611b4d565b348015610ad257600080fd5b506107e1610ae1366004614334565b611ce4565b348015610af257600080fd5b50638b78c6d8195461059c565b348015610b0b57600080fd5b506105c7610b1a36600461427c565b611d08565b348015610b2b57600080fd5b506105c7610b3a3660046149cb565b611df2565b348015610b4b57600080fd5b506105c7610b5a3660046145ac565b611f4c565b348015610b6b57600080fd5b506109ad600081565b348015610b8057600080fd5b5061056f611f99565b348015610b9557600080fd5b506105c7610ba4366004614a0e565b611fa3565b348015610bb557600080fd5b506107e1610bc4366004614a38565b612040565b348015610bd557600080fd5b506105c7610be4366004614a6b565b612055565b348015610bf557600080fd5b5061051c6120d2565b348015610c0a57600080fd5b506105c7610c19366004614334565b6120dc565b348015610c2a57600080fd5b506104ef610c393660046140cd565b61213d565b348015610c4a57600080fd5b5061054a600554600160b01b9004600216151590565b348015610c6c57600080fd5b5061054a610c7b3660046140cd565b6121b3565b348015610c8c57600080fd5b506104ef610c9b3660046140cd565b6121d1565b348015610cac57600080fd5b5061051c610cbb3660046140cd565b6121f0565b348015610ccc57600080fd5b506104ef610cdb3660046140cd565b612203565b6105c7610cee366004614a87565b612222565b348015610cff57600080fd5b50600554610d1590600160a01b900461ffff1681565b60405161ffff9091168152602001610500565b348015610d3457600080fd5b506107e1610d43366004614b02565b612263565b348015610d5457600080fd5b50610d68610d63366004614222565b612356565b6040516105009190614b20565b348015610d8157600080fd5b506104ef610d903660046140cd565b6123b9565b348015610da157600080fd5b5061056f610db0366004614222565b6123cc565b348015610dc157600080fd5b506105c76123fd565b348015610dd657600080fd5b5061051c600281565b348015610deb57600080fd5b5061051c61247e565b348015610e0057600080fd5b5061054a610e0f3660046140cd565b612488565b348015610e2057600080fd5b5061051c610e2f366004614334565b61249b565b348015610e4057600080fd5b506105c76124a6565b348015610e5557600080fd5b50610d1561271081565b348015610e6b57600080fd5b50610e74612507565b6040516105009190614b69565b348015610e8d57600080fd5b5061056f61270b565b348015610ea257600080fd5b5061054a610eb1366004614ca8565b612717565b348015610ec257600080fd5b506104ef610ed13660046140cd565b612754565b61051c610ee4366004614cd2565b612773565b6105c7610ef7366004614334565b6127f2565b6105c7610f0a366004614334565b61282f565b348015610f1b57600080fd5b506109ad610f2a366004614222565b612856565b348015610f3b57600080fd5b5061054a600181565b348015610f5057600080fd5b5061051c610f5f366004614334565b63389a75e1600c908152600091909152602090205490565b6000610f8282612875565b54600160601b900463ffffffff1692915050565b60006003610fa3816128b5565b610faf86858502612903565b50915060005b808514610ff457610fec868683818110610fd157610fd1614cf0565b9050602002016020810190610fe69190614334565b85612a87565b600101610fb5565b507f0b411e173d03042c3eb682fe6cf8f1d64b549c283a9ed7e0f83a9711ee0841e8868686868660405161102c959493929190614d42565b60405180910390a150949350505050565b60006110836001600160e01b03198316638477f7b360e01b1461105f84612ab5565b6001600160e01b03198516637888cfe160e01b81149063152a902d60e11b14612b03565b92915050565b6060611093612b20565b50919050565b60006110a482612ca8565b6110b8576110b86333d1c03960e21b612d06565b6110c0612d10565b60009283526006016020525060409020546001600160a01b031690565b6110e982826001612d34565b5050565b60016110f8816128b5565b611100612de5565b6005805460ff60b01b1981166002600160b01b9283900460ff16179091021790556040517f36c5c1f433b3c0800132549fa10c9deefbeafdd7b70aba4bbc6a987ca2fef54790600090a150565b60006001611159612d10565b60010154611165612d10565b540303919050565b6111773382612e18565b50565b611182612e24565b6110e98282612e3f565b7f6bd5c950a8d8df17f772f5af37cb3655737899cbf903264b9795592da439661c6001806111b8612e4b565b6111c29190614d89565b6040805192835260208301919091520160405180910390a1565b6060816001600160401b038111156111f6576111f66144b8565b60405190808252806020026020018201604052801561121f578160200160208202803683370190505b50905060005b8083146112845761125884848381811061124157611241614cf0565b905060200201356008612e5b90919063ffffffff16565b82828151811061126a5761126a614cf0565b60ff90921660209283029190910190910152600101611225565b5092915050565b600061129682612e7c565b6001600160a01b0394851694909150811684146112bc576112bc62a1148160e81b612d06565b6000806112c884612f3e565b915091506112ed81876112d83390565b6001600160a01b039081169116811491141790565b61130f576112fb8633612717565b61130f5761130f632ce44b5f60e11b612d06565b801561131a57600082555b611322612d10565b6001600160a01b038716600090815260059190910160205260409020805460001901905561134e612d10565b6001600160a01b03861660008181526005929092016020526040909120805460010190554260a01b17600160e11b17611385612d10565b60008681526004919091016020526040812091909155600160e11b841690036113fb57600184016113b4612d10565b6000828152600491909101602052604081205490036113f9576113d5612d10565b5481146113f957836113e5612d10565b600083815260049190910160205260409020555b505b6001600160a01b0385168481887fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a48060000361144557611445633a954ecd60e21b612d06565b50505050505050565b6001611459816128b5565b6110e982612f66565b600061108382612fbd565b60006202a3006001600160401b03164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b60006110836114ca83612875565b54600160c81b9004600216151590565b6005546001600160a01b03166000600160f01b83106114fb576114fb613002565b600554612710600160a01b90910461ffff168402045b90509250929050565b606061108382600061152b85612203565b63ffffffff16612263565b61153e614068565b600061154983612875565b60ff84168352905061155a81613010565b63ffffffff90811660208401528154600160401b810482166040850152600160601b810482166060850152600160801b810482166080850152600160a01b90041660a08301526115a981613063565b60c08301526115c28154600160c81b9004600216151590565b15156101008301526115d3816130ac565b151560e08301526115ee8154600160c81b9004600416151590565b151561012083015250919050565b6001611607816128b5565b611610826130d6565b6005805461ffff60a01b1916600160a01b61ffff8516908102919091179091556040519081527f092d0aa94dc2b378c7fd77faaaf4cb3fd8336ae247cd486fb593726705772ac0906020015b60405180910390a15050565b6006546060906001600160a01b0316156116ed5760065460405163c87b56dd60e01b8152600481018490526001600160a01b039091169063c87b56dd90602401600060405180830381865afa1580156116c5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526110839190810190614d9c565b60006116f7611979565b905080516000036117175760405180602001604052806000815250611742565b80611721846130fd565b604051602001611732929190614e09565b6040516020818303038152906040525b9392505050565b61176483838360405180602001604052806000815250612222565b505050565b611177816001613141565b61177c612e24565b6110e98282612e18565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b60016117cd816128b5565b6117d56132b9565b6117e06001836132ec565b7ff9c7803e94e0d3c02900d8a90893a6d5e90dd04d32a4cfe825520f82bf9f32f68260405161180f919061420f565b60405180910390a16110e961118c565b60408051828152600583901b8082016020019092526060915b801561186357601f198082019186010135600061185482612356565b84840160200152506118389050565b509392505050565b60006001611878816128b5565b604051838582376000805260206000858360008a5af161189c573d6000803e3d6000fd5b50600051915061186382612f66565b600061108382612e7c565b60006118c182612ca8565b6118de5760405163163ceb7760e11b815260040160405180910390fd5b6008602052600582901c60009081526040902054601f8319161a611083565b6001611908816128b5565b600061191383612875565b905061191e816132f8565b805460ff600160c81b80830482166004170260ff60c81b1990921691909117825560405190841681527f5455468b416476a27220f0fc8daad92345a6c408a0356acd2560b63bf0e51d949060200160405180910390a1505050565b6060611985600161332a565b905090565b60006001600160a01b0382166119aa576119aa6323d3ad8160e21b612d06565b6001600160401b036119ba612d10565b6005016000846001600160a01b03166001600160a01b0316815260200190815260200160002054169050919050565b6119f1612e24565b6119fb6000613415565b565b6000611985612e4b565b6001611a12816128b5565b611a1a612de5565b611a2382613453565b7fc14f5a12ed3f072ab9522493ce2b476e950ee5a3f3abf2324961c6ac66b00e948260405161165c9190614e87565b600080611a5e836118b6565b9050600080611a96856000611a7286612203565b60ff8716600090815260096020526040902092919063ffffffff9081169061360316565b9092509050811515640100000000861016611ab357600019611ab5565b805b95945050505050565b6001611ac9816128b5565b6000611ad484612875565b9050611adf816132f8565b611ae881613627565b805463ffffffff60801b1916600160801b63ffffffff85169081029190911782556040805160ff8716815260208101929092527fbfb64051edb1b4f08e14520b9ed4d2609e52d66c0c83cfb1ac125ab41734fceb91015b60405180910390a150505050565b611b5f8160000151826020015161364e565b611b6f611b6a6136d3565b613731565b611b7c8160c001516130d6565b611b898160a0015161376d565b6060810151611b9a90600190613794565b6080810151611bab90600390613794565b60a0810151600580546001600160a01b0319166001600160a01b03909216919091179055610120810151516000819003611bf8576040516392ce813760e01b815260040160405180910390fd5b60005b818114611c3157611c298361012001518281518110611c1c57611c1c614cf0565b6020026020010151613453565b600101611bfb565b50506040810151600680546001600160a01b0319166001600160a01b0390921691909117905560c08101516005805461ffff60a01b1916600160a01b61ffff90931692909202919091179055610100810151151560020260e0820151151517600560166101000a81548160ff021916908360ff1602179055507f4f32c97826173bff1ee9613d86862d161dfbc943f1f5960528f88c42a79fb56881604051611cd99190614ecf565b60405180910390a150565b606060016000611cf2612e4b565b90506060818314611ab357611ab58584846137ad565b6000816001600160401b03811115611d2257611d226144b8565b604051908082528060200260200182016040528015611d4b578160200160208202803683370190505b506005549091506001600160a01b031660005b808414611dba57611d95858583818110611d7a57611d7a614cf0565b9050602002016020810190611d8f9190614334565b836138b5565b838281518110611da757611da7614cf0565b6020908102919091010152600101611d5e565b507fcadee7ff7164fffa7c9c81726bbc520c1fb0bc36d7ac763997ea74aee0e387e48185858533604051611b3f959493929190614fd6565b6001611dfd816128b5565b6000611e0885612875565b9050611e13816132f8565b611e1c81613627565b8054600160a01b900463ffffffff168015611e96578154600160601b810463ffffffff90811686821611600160401b9092048116908716111715611e7357604051633a964d4760e01b815260040160405180910390fd5b63ffffffff85168181108282180218945063ffffffff8416818110828218021893505b8363ffffffff168563ffffffff161115611ec357604051633a964d4760e01b815260040160405180910390fd5b815467ffffffffffffffff60401b1916600160401b63ffffffff87811691820263ffffffff60601b191692909217600160601b9287169283021784556040805160ff8a16815260208101929092528101919091527faabbe826f21f31d8508fe47762ab61162f999f0c296e1a88ce50d1ef0ea6da849060600160405180910390a1505050505050565b6001611f57816128b5565b611f5f6132b9565b611f6a6003836132ec565b7faf497693a87db12ca89131a31edbb3db4bb5702dfb284e8ae7427d185f09112d8260405161165c919061420f565b6060611083612b20565b6001611fae816128b5565b6000611fb984612875565b9050611fc4816132f8565b611fcd8161392d565b8054611ff09060ff600160c81b9091041660028560ff8383161615901518021890565b815460ff60c81b1916600160c81b60ff9283160217825560408051918616825284151560208301527f9213f35ab455184cb0b8872ec8a16bd1fb69d2f0e909f4174a93470cd5e225009101611b3f565b606061204d8484846137ad565b949350505050565b8061205e612d10565b336000818152600792909201602090815260408084206001600160a01b03881680865290835293819020805460ff19169515159590951790945592518415158152919290917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b600061198561395a565b60016120e7816128b5565b6120ef6132b9565b600680546001600160a01b0319166001600160a01b0384169081179091556040519081527ff3fdd6d3ba37d1479142dbb6aef216c352108f558ce922646b4b0d86454d11389060200161180f565b60008061214983612875565b9050600061215682613063565b9050600061216383613010565b63ffffffff16905080158215176121a85760ff85166000908152600960209081526040808320848606600381901c855292529091205460059190911b60e0161c611ab5565b600095945050505050565b60006110836121c183612875565b54600160c81b9004600416151590565b60006121dc82612875565b54600160801b900463ffffffff1692915050565b60006110836121fe83612875565b613063565b600061220e82612875565b54600160a01b900463ffffffff1692915050565b61222d84848461128b565b6001600160a01b0383163b1561225d576122498484848461396d565b61225d5761225d6368d2bf6b60e11b612d06565b50505050565b6060828203600061227386612203565b63ffffffff16905080841184861117156122a057604051631960ccad60e11b815260040160405180910390fd5b816001600160401b038111156122b8576122b86144b8565b6040519080825280602002602001820160405280156122e1578160200160208202803683370190505b5060ff871660009081526009602052604081209194505b83811461234b57868101600381901c60009081526020849052604090205460059190911b60e0161c63ffffffff1685828151811061233857612338614cf0565b60209081029190910101526001016122f8565b505050509392505050565b604080516080810182526000808252602082018190529181018290526060810191909152600182106123b45761238a612e4b565b8210156123b4575b61239b82613a4f565b6123ab5760001990910190612392565b61108382613a6f565b919050565b60006110836123c783612875565b613010565b60606123d782612ca8565b6123f457604051630a14c4b560e41b815260040160405180910390fd5b61108382611668565b6001612408816128b5565b6124106132b9565b6005805460ff60b01b1981166001600160b01b9283900460ff16179091021790556006547f7028d29d7b13876d9de031ac95eb6acef3e844e1d010820781406e6cd5fc70f9906001600160a01b0316612467611979565b61246f61270b565b604051611cd993929190615021565b6000611985613af8565b600061108361249683612875565b6130ac565b600061108382613b0b565b60055447906001600160a01b03166124be8183613b1f565b604080516001600160a01b03831681526020810184905233918101919091527f134d6e96840903022b8e4b57aa0644e9eb6ca6fe65a25205b0857fe918c2bcc69060600161165c565b612593604051806101c001604052806060815260200160608152602001606081526020016060815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600015158152602001600015158152602001600061ffff16815260200160008152602001600081526020016000815260200160008152602001606081525090565b61259b611979565b81526125a561270b565b60208201526125b2612b20565b606083015260408201526005546001600160a01b0380821660808401526006541660a0830152600160b01b810460018116151560c0840152600216151560e0830152600160a01b900461ffff1661010082015261260d6119fd565b61012082015261261b6120d2565b61016082015261262961247e565b61014082015261263761114d565b610180820152600654600160a01b810461ffff1690600160b01b900460ff16816001600160401b0381111561266e5761266e6144b8565b6040519080825280602002602001820160405280156126a757816020015b612694614068565b81526020019060019003908161268c5790505b506101a08401525b81156127065760006126c082612875565b90506126cb82611536565b846101a001518460019003945084815181106126e9576126e9614cf0565b602090810291909101015254600160c01b900460ff1690506126af565b505090565b6060611985600361332a565b6000612721612d10565b6001600160a01b039384166000908152600791909101602090815260408083209490951682529290925250205460ff1690565b600061275f82612875565b54600160401b900463ffffffff1692915050565b60006003612780816128b5565b61278a8584612903565b5091506127978484612a87565b6040805160ff871681526001600160a01b0386166020820152908101849052606081018390527f7ac572687bf4e66a8514fc2ec464fc2644c78bcb1d80a225fc51a33e0ee38bfa9060800160405180910390a1509392505050565b6127fa612e24565b63389a75e1600c52806000526020600c20805442111561282257636f5e88186000526004601cfd5b6000905561117781613415565b612837612e24565b8060601b61284d57637448fbae6000526004601cfd5b61117781613415565b6008602052600581901c60009081526040812054601f8319161a611083565b60ff8116600090815260076020526040812080549091600160c81b90910460011690036123b457604051630bec67bf60e31b815260040160405180910390fd5b60006128bf6136d3565b638b78c6d8600c9081526000829052602090205490915082166110e957638b78c6d819546001600160a01b0316816001600160a01b0316146110e9576110e9613b62565b600080826000036129275760405163b562e8dd60e01b815260040160405180910390fd5b61292f612e4b565b91506401000000006001848401031061294a5761294a613002565b600061295585612875565b8054909150600160a01b900463ffffffff16600061297283613010565b63ffffffff1690508186018181111561299e576040516316b9b18560e01b815260040160405180910390fd5b835463ffffffff60a01b1916600160a01b63ffffffff831602178085556002600160c81b90910416156129ff5783546129e2906001600160401b0316848985613b70565b845467ffffffffffffffff19166001600160401b03919091161784555b60ff88166000908152600960205260408120905b888114612a7757612a58828683018a8401826020528160031c60005260406000206007831660051b815463ffffffff8482841c188116831b8218845550505050505050565b60ff8a1615612a6f57612a6f60088983018c613be5565b600101612a13565b5083955050505050509250929050565b601f81168015612a9b57612a9b8382613c0b565b81811461176457612aad836020613c0b565b602001612a9b565b60006301ffc9a760e01b6001600160e01b031983161480612ae657506380ac58cd60e01b6001600160e01b03198316145b806110835750506001600160e01b031916635b5e139f60e01b1490565b6000611ab585612b17868515158715151782565b15159015151790565b60005460609081908015612b7857612b6e81604080516080810182526000808252918101828152601f820193909352805181016020018051605f830152829052825181016060019190915291565b9093509150509091565b6000612b82612d10565b9050806002018054612b9390615057565b80601f0160208091040260200160405190810160405280929190818152602001828054612bbf90615057565b8015612c0c5780601f10612be157610100808354040283529160200191612c0c565b820191906000526020600020905b815481529060010190602001808311612bef57829003601f168201915b50505050509350806003018054612c2290615057565b80601f0160208091040260200160405190810160405280929190818152602001828054612c4e90615057565b8015612c9b5780601f10612c7057610100808354040283529160200191612c9b565b820191906000526020600020905b815481529060010190602001808311612c7e57829003601f168201915b5050505050925050509091565b6000816001116123b457612cba612d10565b548210156123b45760005b612ccd612d10565b600084815260049190910160205260408120549150819003612cf957612cf28361508b565b9250612cc5565b600160e01b161592915050565b8060005260046000fd5b7f2569078dfb4b0305704d3008e7403993ae9601b85f7ae5e742de3de8f8011c4090565b6000612d3f836118ab565b9050818015612d575750336001600160a01b03821614155b15612d7a57612d668133612717565b612d7a57612d7a6367d9dca160e11b612d06565b83612d83612d10565b6000858152600691909101602052604080822080546001600160a01b0319166001600160a01b0394851617905551859287811692908516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a450505050565b612dfa600554600160b01b9004600216151590565b156119fb57604051635dc9af4560e11b815260040160405180910390fd5b6110e982826000613cff565b638b78c6d8195433146119fb576382b429006000526004601cfd5b6110e982826001613cff565b6000612e55612d10565b54919050565b6000826020528160051c6000526040600020548219601f161a905092915050565b600081600111612f2e57612e8e612d10565b600083815260049190910160205260408120549150819003612f1b57612eb2612d10565b548210612ec957612ec9636f96cda160e11b612d06565b612ed1612d10565b600019909201600081815260049390930160205260409092205490508015612ec957600160e01b8116600003612f0657919050565b612f16636f96cda160e11b612d06565b612ec9565b600160e01b8116600003612f2e57919050565b6123b4636f96cda160e11b612d06565b6000806000612f4b612d10565b60009485526006016020525050604090912080549092909150565b612f6f8161376d565b600580546001600160a01b0319166001600160a01b0383169081179091556040519081527f94c4ad53e91574d56aff9aef0726376e9154e071a602000edf9208f28d649be190602001611cd9565b60006001600160401b036080612fd1612d10565b6005016000856001600160a01b03166001600160a01b0316815260200190815260200160002054901c169050919050565b6335278d126000526004601cfd5b8054600090600160801b900463ffffffff1642101561303b575054600160601b900463ffffffff1690565b81546110839063ffffffff600160401b8204811691600160a01b900416808218908210021890565b60006130798254600160c81b9004600216151590565b80156130895750613089826130ac565b156123b45750546001600160401b03166000908152306020526040902080150190565b60006130b782613010565b915463ffffffff928316600160a01b9091049092169190911015919050565b61271061ffff82161115611177576040516319510c8760e31b815260040160405180910390fd5b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a9004806131175750819003601f19909101908152919050565b600061314c83612e7c565b90508060008061315b86612f3e565b915091508415613192576131708184336112d8565b6131925761317e8333612717565b61319257613192632ce44b5f60e11b612d06565b801561319d57600082555b6fffffffffffffffffffffffffffffffff6131b6612d10565b6001600160a01b038516600081815260059290920160205260409091208054929092019091554260a01b17600360e01b176131ef612d10565b60008881526004919091016020526040812091909155600160e11b85169003613265576001860161321e612d10565b6000828152600491909101602052604081205490036132635761323f612d10565b548114613263578461324f612d10565b600083815260049190910160205260409020555b505b60405186906000906001600160a01b038616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a46132a5612d10565b600190810180549091019055505050505050565b6132ce600554600160b01b9004600116151590565b156119fb5760405163b087bbf360e01b815260040160405180910390fd5b6110e982826001613d58565b61330c8154600160c81b9004600416151590565b1561117757604051633fa1be4f60e01b815260040160405180910390fd5b8054606090806133c95782600101805461334390615057565b80601f016020809104026020016040519081016040528092919081815260200182805461336f90615057565b80156133bc5780601f10613391576101008083540402835291602001916133bc565b820191906000526020600020905b81548152906001019060200180831161339f57829003601f168201915b5050505050915050919050565b6060604051905060408101604052602081528160208201526133ed81600180613de0565b6040516020016133fd91906150a2565b60405160208183030381529060405292505050919050565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b805160ff811660009081526007602052604090208054600160c81b90046001161561349157604051632520e1bd60e11b815260040160405180910390fd5b60ff82166134c45763ffffffff6020840181905260408401819052606084015260006080840152600160a08401526134f9565b826040015163ffffffff16836020015163ffffffff1611156134f957604051633a964d4760e01b815260040160405180910390fd5b602083015181546040850151606086015167ffffffffffffffff60401b19909216600160401b63ffffffff9485160263ffffffff60601b191617600160601b918416919091021763ffffffff60801b1916600160801b929091169190910217815560a0830151151560040260808401511515600202825460ff9290911760019081178316600160c81b0260ff60c81b1983168117855560068054600160c01b600160b01b80830488169190910260ff60c01b1990941661ffff60c01b19909616959095179290921790955584549590931690910260ff60b01b1961ffff600160a01b9485900481169093019092169092021662ffffff60a01b199093169290921791909117905550565b60008061361a8663ffffffff871686866020613ec7565b9150915094509492505050565b613630816130ac565b15611177576040516337149c8160e21b815260040160405180910390fd5b6000613658612d10565b80549091501561366a5761366a613b62565b6001815560006136a1848460008251601e600184518301031081601e850103518286015183601f0360031b1b170291505092915050565b9050806136cb57600282016136b68582615128565b50600382016136c58482615128565b5061225d565b600055505050565b6000336000526e2fd5aeb385d324b580fca7c83823a080330361370157602060008038845afa613701573838fd5b506dd9ecebf3c23529de49815dac1c4c80330361372957602060008038845afa613729573838fd5b505060005190565b6001600160a01b0316638b78c6d8198190558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b6001600160a01b03811661117757604051630797cc5760e31b815260040160405180910390fd5b80516000036137a1575050565b6110e982826000613d58565b60608183106137c6576137c6631960ccad60e11b612d06565b60018310156137d457600192505b60006137de612e4b565b90508083106137eb578092505b606060006137f88761198a565b858710908102915081156138a95781878703116138155786860391505b60405192506001820160051b8301604052600061383188612356565b905060008160400151613842575080515b60005b61384e8a613a6f565b9250604083015160008114613866576000925061388b565b83511561387257835192505b8b831860601b61388b576001820191508a8260051b8801525b5060018a019950888a148061389f57508481145b1561384557855250505b50909695505050505050565b60006370a0823160005230602052602060346024601c865afa601f3d11166138e5576390b8ec186000526004601cfd5b81601452603451905063a9059cbb60601b60005260206000604460106000875af13d156001600051141716613922576390b8ec186000526004601cfd5b600060345292915050565b8054600160a01b900463ffffffff1615611177576040516330b33cff60e01b815260040160405180910390fd5b60006001613966612d10565b5403919050565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a02906139a29033908990889088906004016151e7565b6020604051808303816000875af19250505080156139dd575060408051601f3d908101601f191682019092526139da9181019061521a565b60015b613a32573d808015613a0b576040519150601f19603f3d011682016040523d82523d6000602084013e613a10565b606091505b508051600003613a2a57613a2a6368d2bf6b60e11b612d06565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050949350505050565b6000613a59612d10565b6000928352600401602052506040902054151590565b604080516080810182526000808252602082018190529181018290526060810191909152611083613a9e612d10565b60008481526004919091016020526040902054604080516080810182526001600160a01b038316815260a083901c6001600160401b03166020820152600160e01b831615159181019190915260e89190911c606082015290565b6000613b02612d10565b60010154905090565b60006001600160401b036040612fd1612d10565b80471015613b355763b12d13eb6000526004601cfd5b6000386000388486620186a0f16110e957816000526073600b5360ff6020536016600b82f06110e9573838fd5b6382b429006000526004601cfd5b838183021561204d578284015b8560ff16600101430340600052844487181860205260406000208660008114613bc657866001868406011115613bc1578160ff1c8860011b17600052602060002093505b613bca565b8193505b5050819550600185019450808503613b7d5750949350505050565b826020528160051c60005260406000208054600052818319601f16536000519055505050565b6000613c15612d10565b5490506000829003613c3157613c3163b562e8dd60e01b612d06565b6001600160a01b0383164260a01b6001841460e11b1717613c50612d10565b60008381526004919091016020526040902055680100000000000000018202613c77612d10565b6001600160a01b0385166000818152600592909201602052604082208054909301909255819003613cb157613cb1622e076360e81b612d06565b818301825b808360007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a4818160010191508103613cb65781613cf5612d10565b5550611764915050565b638b78c6d8600c52826000526020600c20805483811783613d21575080841681185b80835580600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3505050505050565b8151600060308214603183141715613d90576461723a2f2f64ffffffffff60058601511603613d905760019050600584019350602b84525b8015613dbf576000613da185613f6b565b602001516461723a2f2f865260041990950183815294865550613dd9565b60018501613dcd8582615128565b508215613dd957600085555b5050505050565b606083518015611863576003600282010460021b60405192507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f526106708515027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f18603f52602083018181015b6003880197508751603f8160121c1651600053603f81600c1c1651600153603f8160061c1651600253603f811651600353506000518252600482019150808210613e5057602001604052613d3d60f01b60038406600204808303919091526000861515909102918290035290038252509392505050565b600080838510613ed5578493505b6000600019860160018261010087900490506000196001881b018989035b83811684821860011c019650808411613f4a57848701838104600090815260208f90526040902054908490068a021c821695508b8614613f4a57858c11613f3f57506000198601613ef3565b866001019350613ef3565b50505050931582151796188617159760018218909602189091019450505050565b6060815180156110935760038160021c0260038216613fa05783820151613d3d18601e81901a1560ff90911615019003613faa565b6003821601600019015b60405192508083526020830181810191507ffc000000fc00686c7074787c8084888c9094989ca0a4a8acb0b4b8bcc0c4c8cc80605b527804080c1014181c2024282c3034383c4044484c5054585c6064603b526ef8fcf800fcd0d4d8dce0e4e8ecf0f4601a525b600486019550855180601f1a5160061c81601e1a5183161760061c81601d1a5183161760061c81601c1a51831617835250600382019150828210614011575050602081016040526000815250600060605250919050565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b803560ff811681146123b457600080fd5b6000602082840312156140df57600080fd5b611742826140bc565b60008083601f8401126140fa57600080fd5b5081356001600160401b0381111561411157600080fd5b6020830191508360208260051b850101111561412c57600080fd5b9250929050565b6000806000806060858703121561414957600080fd5b614152856140bc565b935060208501356001600160401b0381111561416d57600080fd5b614179878288016140e8565b9598909750949560400135949350505050565b6001600160e01b03198116811461117757600080fd5b6000602082840312156141b457600080fd5b81356117428161418c565b60005b838110156141da5781810151838201526020016141c2565b50506000910152565b600081518084526141fb8160208601602086016141bf565b601f01601f19169290920160200192915050565b60208152600061174260208301846141e3565b60006020828403121561423457600080fd5b5035919050565b80356001600160a01b03811681146123b457600080fd5b6000806040838503121561426557600080fd5b61426e8361423b565b946020939093013593505050565b6000806020838503121561428f57600080fd5b82356001600160401b038111156142a557600080fd5b6142b1858286016140e8565b90969095509350505050565b6020808252825182820181905260009190848201906040850190845b818110156138a957835160ff16835292840192918401916001016142d9565b60008060006060848603121561430d57600080fd5b6143168461423b565b92506143246020850161423b565b9150604084013590509250925092565b60006020828403121561434657600080fd5b6117428261423b565b6000806040838503121561436257600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b838110156143a157815187529582019590820190600101614385565b509495945050505050565b6020815260006117426020830184614371565b805160ff16825260208101516143dd602084018263ffffffff169052565b5060408101516143f5604084018263ffffffff169052565b50606081015161440d606084018263ffffffff169052565b506080810151614425608084018263ffffffff169052565b5060a081015161443d60a084018263ffffffff169052565b5060c081015160c083015260e081015161445b60e084018215159052565b5061010081810151151590830152610120808201518015158285015261225d565b610140810161108382846143bf565b803561ffff811681146123b457600080fd5b6000602082840312156144af57600080fd5b6117428261448b565b634e487b7160e01b600052604160045260246000fd5b60405161014081016001600160401b03811182821017156144f1576144f16144b8565b60405290565b604051601f8201601f191681016001600160401b038111828210171561451f5761451f6144b8565b604052919050565b60006001600160401b03821115614540576145406144b8565b50601f01601f191660200190565b600061456161455c84614527565b6144f7565b905082815283838301111561457557600080fd5b828260208301376000602084830101529392505050565b600082601f83011261459d57600080fd5b6117428383356020850161454e565b6000602082840312156145be57600080fd5b81356001600160401b038111156145d457600080fd5b61204d8482850161458c565b80516001600160a01b031682526020808201516001600160401b03169083015260408082015115159083015260609081015162ffffff16910152565b6020808252825182820181905260009190848201906040850190845b818110156138a95761464b8385516145e0565b9284019260809290920191600101614638565b60008060006040848603121561467357600080fd5b61467c8461423b565b925060208401356001600160401b038082111561469857600080fd5b818601915086601f8301126146ac57600080fd5b8135818111156146bb57600080fd5b8760208285010111156146cd57600080fd5b6020830194508093505050509250925092565b803563ffffffff811681146123b457600080fd5b803580151581146123b457600080fd5b600060c0828403121561471657600080fd5b60405160c081018181106001600160401b0382111715614738576147386144b8565b604052905080614747836140bc565b8152614755602084016146e0565b6020820152614766604084016146e0565b6040820152614777606084016146e0565b6060820152614788608084016146f4565b608082015261479960a084016146f4565b60a08201525092915050565b600060c082840312156147b757600080fd5b6117428383614704565b600080604083850312156147d457600080fd5b6147dd836140bc565b9150611511602084016146e0565b600082601f8301126147fc57600080fd5b813560206001600160401b03821115614817576148176144b8565b614825818360051b016144f7565b82815260c0928302850182019282820191908785111561484457600080fd5b8387015b858110156148675761485a8982614704565b8452928401928101614848565b5090979650505050505050565b60006020828403121561488657600080fd5b81356001600160401b038082111561489d57600080fd5b9083019061014082860312156148b257600080fd5b6148ba6144ce565b8235828111156148c957600080fd5b6148d58782860161458c565b8252506020830135828111156148ea57600080fd5b6148f68782860161458c565b6020830152506149086040840161423b565b604082015260608301358281111561491f57600080fd5b61492b8782860161458c565b60608301525060808301358281111561494357600080fd5b61494f8782860161458c565b60808301525061496160a0840161423b565b60a082015261497260c0840161448b565b60c082015261498360e084016146f4565b60e08201526101006149968185016146f4565b9082015261012083810135838111156149ae57600080fd5b6149ba888287016147eb565b918301919091525095945050505050565b6000806000606084860312156149e057600080fd5b6149e9846140bc565b92506149f7602085016146e0565b9150614a05604085016146e0565b90509250925092565b60008060408385031215614a2157600080fd5b614a2a836140bc565b9150611511602084016146f4565b600080600060608486031215614a4d57600080fd5b614a568461423b565b95602085013595506040909401359392505050565b60008060408385031215614a7e57600080fd5b614a2a8361423b565b60008060008060808587031215614a9d57600080fd5b614aa68561423b565b9350614ab46020860161423b565b92506040850135915060608501356001600160401b03811115614ad657600080fd5b8501601f81018713614ae757600080fd5b614af68782356020840161454e565b91505092959194509250565b600080600060608486031215614b1757600080fd5b614a56846140bc565b6080810161108382846145e0565b600081518084526020808501945080840160005b838110156143a157614b558783516143bf565b610140969096019590820190600101614b42565b60208152600082516101c0806020850152614b886101e08501836141e3565b91506020850151601f1980868503016040870152614ba684836141e3565b93506040870151915080868503016060870152614bc384836141e3565b93506060870151915080868503016080870152614be084836141e3565b935060808701519150614bfe60a08701836001600160a01b03169052565b60a08701516001600160a01b03811660c0880152915060c087015180151560e0880152915060e08701519150610100614c3a8188018415159052565b8701519150610120614c518782018461ffff169052565b8701516101408781019190915287015161016080880191909152870151610180808801919091528701516101a080880191909152870151868503909101838701529050614c9e8382614b2e565b9695505050505050565b60008060408385031215614cbb57600080fd5b614cc48361423b565b91506115116020840161423b565b600080600060608486031215614ce757600080fd5b614316846140bc565b634e487b7160e01b600052603260045260246000fd5b8183526000602080850194508260005b858110156143a1576001600160a01b03614d2f8361423b565b1687529582019590820190600101614d16565b60ff86168152608060208201526000614d5f608083018688614d06565b604083019490945250606001529392505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561108357611083614d73565b600060208284031215614dae57600080fd5b81516001600160401b03811115614dc457600080fd5b8201601f81018413614dd557600080fd5b8051614de361455c82614527565b818152856020838501011115614df857600080fd5b611ab58260208301602086016141bf565b60008351614e1b8184602088016141bf565b835190830190614e2f8183602088016141bf565b01949350505050565b60ff8151168252602081015163ffffffff8082166020850152806040840151166040850152806060840151166060850152505060808101511515608083015260a0810151151560a08301525050565b60c081016110838284614e38565b600081518084526020808501945080840160005b838110156143a157614ebc878351614e38565b60c0969096019590820190600101614ea9565b6020815260008251610140806020850152614eee6101608501836141e3565b91506020850151601f1980868503016040870152614f0c84836141e3565b935060408701519150614f2a60608701836001600160a01b03169052565b6060870151915080868503016080870152614f4584836141e3565b935060808701519150808685030160a0870152614f6284836141e3565b935060a08701519150614f8060c08701836001600160a01b03169052565b60c087015161ffff811660e0880152915060e08701519150610100614fa88188018415159052565b8701519150610120614fbd8782018415159052565b870151868503909101838701529050614c9e8382614e95565b600060018060a01b03808816835260806020840152614ff9608084018789614d06565b838103604085015261500b8187614371565b9250508084166060840152509695505050505050565b6001600160a01b0384168152606060208201819052600090615045908301856141e3565b8281036040840152614c9e81856141e3565b600181811c9082168061506b57607f821691505b60208210810361109357634e487b7160e01b600052602260045260246000fd5b60008161509a5761509a614d73565b506000190190565b6461723a2f2f60d81b8152600082516150c28160058501602087016141bf565b602f60f81b6005939091019283015250600601919050565b601f82111561176457600081815260208120601f850160051c810160208610156151015750805b601f850160051c820191505b818110156151205782815560010161510d565b505050505050565b81516001600160401b03811115615141576151416144b8565b6151558161514f8454615057565b846150da565b602080601f83116001811461518a57600084156151725750858301515b600019600386901b1c1916600185901b178555615120565b600085815260208120601f198616915b828110156151b95788860151825594840194600190910190840161519a565b50858210156151d75787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090614c9e908301846141e3565b60006020828403121561522c57600080fd5b81516117428161418c56fea264697066735822122049e6d1cd0280f13035da064d43e0d0c04baabf189e47190a2588815ba6a8c9fa64736f6c63430008130033
Deployed Bytecode Sourcemap
1342:34628:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21118:126;;;;;;;;;;-1:-1:-1;21118:126:0;;;;;:::i;:::-;;:::i;:::-;;;635:10:24;623:23;;;605:42;;593:2;578:18;21118:126:0;;;;;;;;7925:757;;;;;;:::i;:::-;;:::i;:::-;;;1756:25:24;;;1744:2;1729:18;7925:757:0;1610:177:24;22934:490:0;;;;;;;;;;-1:-1:-1;22934:490:0;;;;;:::i;:::-;;:::i;:::-;;;2439:14:24;;2432:22;2414:41;;2402:2;2387:18;22934:490:0;2274:187:24;23953:157:0;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;16413:247:7:-;;;;;;;;;;-1:-1:-1;16413:247:7;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;3680:32:24;;;3662:51;;3650:2;3635:18;16413:247:7;3516:203:24;16141:122:7;;;;;;:::i;:::-;;:::i;:::-;;17282:117:0;;;;;;;;;;;;17354:6;;-1:-1:-1;;;17354:6:0;;4022;17354:33;:38;;;17282:117;10663:190;;;;;;;;;;;;;:::i;4916:365:7:-;;;;;;;;;;;;;:::i;10127:109:19:-;;;;;;:::i;:::-;;:::i;5288:31:0:-;;;;;;;;;;-1:-1:-1;5288:31:0;;;;-1:-1:-1;;;;;5288:31:0;;;9588:123:19;;;;;;:::i;:::-;;:::i;14912:118:0:-;;;;;;;;;;;;;:::i;11178:139:19:-;;;;;;;;;;-1:-1:-1;11178:139:19;;;;;:::i;:::-;10769:15;10763:4;10756:29;;;11257:4;10798:18;;;;10898:4;10882:21;;;10876:28;11280:21;;:30;;11178:139;18849:307:0;;;;;;;;;;-1:-1:-1;18849:307:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;20207:3591:7:-;;;;;;:::i;:::-;;:::i;10912:132:0:-;;;;;;;;;;-1:-1:-1;10912:132:0;;;;;:::i;:::-;;:::i;17959:111::-;;;;;;;;;;-1:-1:-1;17959:111:0;;;;;:::i;:::-;;:::i;9021:617:18:-;;;:::i;21661:136:0:-;;;;;;;;;;-1:-1:-1;21661:136:0;;;;;:::i;:::-;;:::i;23485:407::-;;;;;;;;;;-1:-1:-1;23485:407:0;;;;;:::i;:::-;;:::i;:::-;;;;-1:-1:-1;;;;;6296:32:24;;;6278:51;;6360:2;6345:18;;6338:34;;;;6251:18;23485:407:0;6104:274:24;10567:353:19;;;;;;;;;;-1:-1:-1;10567:353:19;;;;;:::i;:::-;10769:15;10763:4;10756:29;;;10627:13;10798:18;;;;10898:4;10882:21;;10876:28;;10567:353;19384:151:0;;;;;;;;;;-1:-1:-1;19384:151:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;16479:575::-;;;;;;;;;;-1:-1:-1;16479:575:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;5591:29::-;;;;;;;;;;-1:-1:-1;5591:29:0;;;;-1:-1:-1;;;;;5591:29:0;;;12455:165;;;;;;;;;;-1:-1:-1;12455:165:0;;;;;:::i;:::-;;:::i;22550:325::-;;;;;;;;;;-1:-1:-1;22550:325:0;;;;;:::i;:::-;;:::i;23889:187:7:-;;;;;;:::i;:::-;;:::i;850:92:11:-;;;;;;;;;;-1:-1:-1;850:92:11;;;;;:::i;:::-;;:::i;9856:125:19:-;;;;;;:::i;:::-;;:::i;10982:134::-;;;;;;;;;;-1:-1:-1;10982:134:19;;;;;:::i;:::-;10769:15;10763:4;10756:29;;;11060:4;10798:18;;;;10898:4;10882:21;;;10876:28;11083:21;:26;;;10982:134;9720:456:18;;;:::i;9846:221:0:-;;;;;;;;;;-1:-1:-1;9846:221:0;;;;;:::i;:::-;;:::i;2145:1131:12:-;;;;;;;;;;-1:-1:-1;2145:1131:12;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;11103:1293:0:-;;;;;;;;;;-1:-1:-1;11103:1293:0;;;;;:::i;:::-;;:::i;10743:150:7:-;;;;;;;;;;-1:-1:-1;10743:150:7;;;;;:::i;:::-;;:::i;18429:182:0:-;;;;;;;;;;-1:-1:-1;18429:182:0;;;;;:::i;:::-;;:::i;:::-;;;12475:4:24;12463:17;;;12445:36;;12433:2;12418:18;18429:182:0;12303:184:24;13608:226:0;;;;;;;;;;-1:-1:-1;13608:226:0;;;;;:::i;:::-;;:::i;24393:101::-;;;;;;;;;;;;;:::i;6163:263:7:-;;;;;;;;;;-1:-1:-1;6163:263:7;;;;;:::i;:::-;;:::i;8762:100:18:-;;;:::i;17639:91:0:-;;;;;;;;;;;;;:::i;3296:54::-;;;;;;;;;;;;1211:6:4;3296:54:0;;14237:199;;;;;;;;;;-1:-1:-1;14237:199:0;;;;;:::i;:::-;;:::i;20200:312::-;;;;;;;;;;-1:-1:-1;20200:312:0;;;;;:::i;:::-;;:::i;13893:285::-;;;;;;;;;;-1:-1:-1;13893:285:0;;;;;:::i;:::-;;:::i;6430:1045::-;;;;;;;;;;-1:-1:-1;6430:1045:0;;;;;:::i;:::-;;:::i;4302:319:12:-;;;;;;;;;;-1:-1:-1;4302:319:12;;;;;:::i;:::-;;:::i;11408:182:18:-;;;;;;;;;;-1:-1:-1;;;11556:18:18;11408:182;;9056:441:0;;;;;;;;;;-1:-1:-1;9056:441:0;;;;;:::i;:::-;;:::i;12679:870::-;;;;;;;;;;-1:-1:-1;12679:870:0;;;;;:::i;:::-;;:::i;10126:198::-;;;;;;;;;;-1:-1:-1;10126:198:0;;;;;:::i;:::-;;:::i;2824:33::-;;;;;;;;;;;;2856:1;2824:33;;24171:163;;;;;;;;;;;;;:::i;14495:358::-;;;;;;;;;;-1:-1:-1;14495:358:0;;;;;:::i;:::-;;:::i;3650:217:12:-;;;;;;;;;;-1:-1:-1;3650:217:12;;;;;:::i;:::-;;:::i;16987:255:7:-;;;;;;;;;;-1:-1:-1;16987:255:7;;;;;:::i;:::-;;:::i;18129:91:0:-;;;;;;;;;;;;;:::i;9556:231::-;;;;;;;;;;-1:-1:-1;9556:231:0;;;;;:::i;:::-;;:::i;21856:299::-;;;;;;;;;;-1:-1:-1;21856:299:0;;;;;:::i;:::-;;:::i;17458:122::-;;;;;;;;;;;;17532:6;;-1:-1:-1;;;17532:6:0;;4188;17532:36;:41;;;17458:122;17113:110;;;;;;;;;;-1:-1:-1;17113:110:0;;;;;:::i;:::-;;:::i;21488:114::-;;;;;;;;;;-1:-1:-1;21488:114:0;;;;;:::i;:::-;;:::i;20571:132::-;;;;;;;;;;-1:-1:-1;20571:132:0;;;;;:::i;:::-;;:::i;19215:110::-;;;;;;;;;;-1:-1:-1;19215:110:0;;;;;:::i;:::-;;:::i;24657:405:7:-;;;;;;:::i;:::-;;:::i;5387:24:0:-;;;;;;;;;;-1:-1:-1;5387:24:0;;;;-1:-1:-1;;;5387:24:0;;;;;;;;;19130:6:24;19118:19;;;19100:38;;19088:2;19073:18;5387:24:0;18956:188:24;19594:547:0;;;;;;;;;;-1:-1:-1;19594:547:0;;;;;:::i;:::-;;:::i;1413:579:12:-;;;;;;;;;;-1:-1:-1;1413:579:12;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;20941:118:0:-;;;;;;;;;;-1:-1:-1;20941:118:0;;;;;:::i;:::-;;:::i;22216:275::-;;;;;;;;;;-1:-1:-1;22216:275:0;;;;;:::i;:::-;;:::i;10383:221::-;;;;;;;;;;;;;:::i;3053:56::-;;;;;;;;;;;;929:6:4;3053:56:0;;18279:91;;;;;;;;;;;;;:::i;20762:120::-;;;;;;;;;;-1:-1:-1;20762:120:0;;;;;:::i;:::-;;:::i;17789:111::-;;;;;;;;;;-1:-1:-1;17789:111:0;;;;;:::i;:::-;;:::i;8741:256::-;;;;;;;;;;;;;:::i;3436:63::-;;;;;;;;;;;;1495:5:4;3436:63:0;;15282:1138;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;24553:109::-;;;;;;;;;;;;;:::i;17392:186:7:-;;;;;;;;;;-1:-1:-1;17392:186:7;;;;;:::i;:::-;;:::i;21303:126:0:-;;;;;;;;;;-1:-1:-1;21303:126:0;;;;;:::i;:::-;;:::i;7534:332::-;;;;;;:::i;:::-;;:::i;10363:708:18:-;;;;;;:::i;:::-;;:::i;8348:349::-;;;;;;:::i;:::-;;:::i;18670:120:0:-;;;;;;;;;;-1:-1:-1;18670:120:0;;;;;:::i;:::-;;:::i;3577:32::-;;;;;;;;;;;;3605:4;3577:32;;11693:435:18;;;;;;;;;;-1:-1:-1;11693:435:18;;;;;:::i;:::-;11963:19;11957:4;11950:33;;;11812:14;11996:26;;;;12106:4;12090:21;;12084:28;;11693:435;21118:126:0;21177:6;21202:18;21215:4;21202:12;:18::i;:::-;:35;-1:-1:-1;;;21202:35:0;;;;;;-1:-1:-1;;21118:126:0:o;7925:757::-;8094:19;8059:24;25067:31;8059:24;25067;:31::i;:::-;8452:45:::1;8470:4:::0;8476:20;;::::1;8452:17;:45::i;:::-;-1:-1:-1::0;8434:63:0;-1:-1:-1;8516:9:0::1;8511:97;8527:14:::0;;::::1;8511:97;;8566:27;8577:2;;8580:1;8577:5;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;8584:8;8566:10;:27::i;:::-;8543:3;;8511:97;;;;8632:43;8643:4;8649:2;;8653:8;8663:11;8632:43;;;;;;;;;;:::i;:::-;;;;;;;;7925:757:::0;;;;;;;:::o;22934:490::-;23103:4;23142:275;-1:-1:-1;;;;;;23169:50:0;;-1:-1:-1;;;23169:50:0;23237:49;23169:11;23237:36;:49::i;:::-;-1:-1:-1;;;;;;23304:45:0;;-1:-1:-1;;;23304:45:0;;;-1:-1:-1;;;23367:36:0;23142:9;:275::i;:::-;23123:294;22934:490;-1:-1:-1;;22934:490:0:o;23953:157::-;24040:19;24083:20;:18;:20::i;:::-;-1:-1:-1;24071:32:0;23953:157;-1:-1:-1;23953:157:0:o;16413:247:7:-;16489:7;16513:16;16521:7;16513;:16::i;:::-;16508:73;;16531:50;-1:-1:-1;;;16531:7:7;:50::i;:::-;16599:23;:21;:23::i;:::-;:48;;;;:39;;:48;;-1:-1:-1;16599:48:7;;;:54;-1:-1:-1;;;;;16599:54:7;;16413:247::o;16141:122::-;16229:27;16238:2;16242:7;16251:4;16229:8;:27::i;:::-;16141:122;;:::o;10663:190:0:-;1211:6:4;25067:31:0;25092:5;25067:24;:31::i;:::-;10737:29:::1;:27;:29::i;:::-;10776:6;:37:::0;;-1:-1:-1;;;;10776:37:0;::::1;4188:6;-1:-1:-1::0;;;10776:37:0;;;::::1;;;;::::0;;::::1;;::::0;;10828:18:::1;::::0;::::1;::::0;-1:-1:-1;;10828:18:0::1;10663:190:::0;:::o;4916:365:7:-;4977:7;25642:1:0;5210:23:7;:21;:23::i;:::-;:36;;;5170:23;:21;:23::i;:::-;:37;:76;:94;;4916:365;-1:-1:-1;4916:365:7:o;10127:109:19:-;10198:31;10211:10;10223:5;10198:12;:31::i;:::-;10127:109;:::o;9588:123::-;12517:13:18;:11;:13::i;:::-;9680:24:19::1;9692:4;9698:5;9680:11;:24::i;14912:118:0:-:0;14967:56;25642:1;15021;15004:14;:12;:14::i;:::-;:18;;;;:::i;:::-;14967:56;;;24551:25:24;;;24607:2;24592:18;;24585:34;;;;24524:18;14967:56:0;;;;;;;14912:118::o;18849:307::-;18919:20;18995:8;-1:-1:-1;;;;;18983:28:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;18983:28:0;;18975:36;;19030:9;19025:115;19041:20;;;19025:115;;19097:28;19113:8;;19122:1;19113:11;;;;;;;:::i;:::-;;;;;;;19097;:15;;:28;;;;:::i;:::-;19086:5;19092:1;19086:8;;;;;;;;:::i;:::-;:39;;;;:8;;;;;;;;;;;:39;19063:3;;19025:115;;;;18849:307;;;;:::o;20207:3591:7:-;20344:27;20374;20393:7;20374:18;:27::i;:::-;-1:-1:-1;;;;;20526:22:7;;;;20344:57;;-1:-1:-1;20584:45:7;;;;20580:95;;20631:44;-1:-1:-1;;;20631:7:7;:44::i;:::-;20687:27;20716:23;20743:35;20770:7;20743:26;:35::i;:::-;20686:92;;;;20875:68;20900:15;20917:4;20923:19;41768:10;;41682:103;20923:19;-1:-1:-1;;;;;18789:32:7;;;18635:28;;18916:20;;18938:30;;18913:56;;18339:646;20875:68;20870:188;;20962:43;20979:4;41768:10;17392:186;:::i;20962:43::-;20957:101;;21007:51;-1:-1:-1;;;21007:7:7;:51::i;:::-;21201:15;21198:157;;;21339:1;21318:19;21311:30;21198:157;21727:23;:21;:23::i;:::-;-1:-1:-1;;;;;21727:48:7;;;;;;:42;;;;;:48;;;;;21725:50;;-1:-1:-1;;21725:50:7;;;21819:23;:21;:23::i;:::-;-1:-1:-1;;;;;21819:46:7;;;;;;:42;;;;;:46;;;;;;21817:48;;;;;;15269:11;15244:23;15240:41;15227:63;-1:-1:-1;;;15227:63:7;22129:23;:21;:23::i;:::-;:50;;;;:41;;;;;:50;;;;;:196;;;;-1:-1:-1;;;22442:47:7;;:52;;22438:689;;22546:1;22536:11;;22667:23;:21;:23::i;:::-;:54;;;;:41;;;;;:54;;;;;;:59;;22663:450;;22827:23;:21;:23::i;:::-;:37;22812:52;;22808:287;;23053:19;22996:23;:21;:23::i;:::-;:54;;;;:41;;;;;:54;;;;;:76;22808:287;22496:631;22438:689;-1:-1:-1;;;;;23255:20:7;;23626:7;23255:20;23558:4;23501:25;23236:16;;23369:292;23684:8;23696:1;23684:13;23680:58;;23699:39;-1:-1:-1;;;23699:7:7;:39::i;:::-;20334:3464;;;;20207:3591;;;:::o;10912:132:0:-;1211:6:4;25067:31:0;25092:5;25067:24;:31::i;:::-;11006::::1;11027:9;11006:20;:31::i;17959:111::-:0;18017:7;18043:20;18057:5;18043:13;:20::i;9021:617:18:-;9114:15;7972:9;-1:-1:-1;;;;;9132:46:18;:15;:46;9114:64;;9346:19;9340:4;9333:33;9396:8;9390:4;9383:22;9452:7;9445:4;9439;9429:21;9422:38;9599:8;9552:45;9549:1;9546;9541:67;9248:374;9021:617::o;21661:136:0:-;21725:4;21748:42;21771:18;21784:4;21771:12;:18::i;:::-;32324:7;-1:-1:-1;;;32324:7:0;;4495:6;32324:44;:49;;;32226:154;23485:407;23682:16;;-1:-1:-1;;;;;23682:16:0;23618:17;-1:-1:-1;;;23712:21:0;;23708:50;;23735:23;:21;:23::i;:::-;23857:10;;1495:5:4;-1:-1:-1;;;23857:10:0;;;;;3012:9:4;;3008:17;23829:56:0;23813:72;;23485:407;;;;;:::o;19384:151::-;19439:25;19487:41;19502:4;19508:1;19511:16;19522:4;19511:10;:16::i;:::-;19487:41;;:14;:41::i;16479:575::-;16530:20;;:::i;:::-;16562:18;16583;16596:4;16583:12;:18::i;:::-;16611:16;;;;;16562:39;-1:-1:-1;16656:15:0;16562:39;16656:12;:15::i;:::-;16637:34;;;;:16;;;:34;16705:18;;-1:-1:-1;;;16705:18:0;;;;16681:21;;;:42;-1:-1:-1;;;16757:18:0;;;;16733:21;;;:42;-1:-1:-1;;;16803:12:0;;;;16785:15;;;:30;-1:-1:-1;;;16839:8:0;;;16825:11;;;:22;16879:18;16705:1;16879:15;:18::i;:::-;16857:19;;;:40;16936:25;16959:1;32324:7;-1:-1:-1;;;32324:7:0;;4495:6;32324:44;:49;;;32226:154;16936:25;16907:54;;:26;;;:54;16992:17;17007:1;16992:14;:17::i;:::-;16971:38;;:18;;;:38;17035:12;17045:1;32992:7;-1:-1:-1;;;32992:7:0;;4630:6;32992:30;:35;;;32907:127;17035:12;17019:28;;:13;;;:28;-1:-1:-1;17019:4:0;16479:575;-1:-1:-1;16479:575:0:o;12455:165::-;1211:6:4;25067:31:0;25092:5;25067:24;:31::i;:::-;12533:24:::1;12553:3;12533:19;:24::i;:::-;12567:10;:16:::0;;-1:-1:-1;;;;12567:16:0::1;-1:-1:-1::0;;;12567:16:0::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;12598:15:::1;::::0;19100:38:24;;;12598:15:0::1;::::0;19088:2:24;19073:18;12598:15:0::1;;;;;;;;12455:165:::0;;:::o;22550:325::-;22643:14;;22614:13;;-1:-1:-1;;;;;22643:14:0;:28;22639:90;;22696:14;;22680:49;;-1:-1:-1;;;22680:49:0;;;;;1756:25:24;;;-1:-1:-1;;;;;22696:14:0;;;;22680:40;;1729:18:24;;22680:49:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;22680:49:0;;;;;;;;;;;;:::i;22639:90::-;22739:22;22764:9;:7;:9::i;:::-;22739:34;;22796:8;22790:22;22816:1;22790:27;:78;;;;;;;;;;;;;;;;;22834:8;22844:18;22854:7;22844:9;:18::i;:::-;22820:43;;;;;;;;;:::i;:::-;;;;;;;;;;;;;22790:78;22783:85;22550:325;-1:-1:-1;;;22550:325:0:o;23889:187:7:-;24030:39;24047:4;24053:2;24057:7;24030:39;;;;;;;;;;;;:16;:39::i;:::-;23889:187;;;:::o;850:92:11:-;915:20;921:7;930:4;915:5;:20::i;9856:125:19:-;12517:13:18;:11;:13::i;:::-;9949:25:19::1;9962:4;9968:5;9949:12;:25::i;9720:456:18:-:0;9922:19;9916:4;9909:33;9968:8;9962:4;9955:22;10020:1;10013:4;10007;9997:21;9990:32;10151:8;10105:44;10102:1;10099;10094:66;9720:456::o;9846:221:0:-;1211:6:4;25067:31:0;25092:5;25067:24;:31::i;:::-;9933:27:::1;:25;:27::i;:::-;9970;:15;9993:3:::0;9970:22:::1;:27::i;:::-;10012:15;10023:3;10012:15;;;;;;:::i;:::-;;;;;;;;10037:23;:21;:23::i;2145:1131:12:-:0;2492:4;2486:11;;2543:21;;;2692:1;2688:9;;;2746:29;;;2766:4;2746:29;2733:43;;;2284:23;;2795:448;2802:6;;2795:448;;-1:-1:-1;;2885:12:12;;;;2938:23;;;2925:37;2824:15;3023:28;2925:37;3023:19;:28::i;:::-;3178:29;;;3198:4;3178:29;3171:48;-1:-1:-1;2795:448:12;;-1:-1:-1;2795:448:12;;-1:-1:-1;3259:10:12;2145:1131;-1:-1:-1;;;2145:1131:12:o;11103:1293:0:-;11238:13;1211:6:4;25067:31:0;25092:5;25067:24;:31::i;:::-;11350:4:::1;11344:11;11460:16;11442;11439:1;11426:51;11611:1;11605:4:::0;11598:15:::1;12064:4;12014;11950:16;11888:1;11850;11790:9;11745:5;11719:392;11692:618;;12232:16;12226:4;12220::::0;12205:44:::1;12279:16;12273:4;12266:30;11692:618;;12338:4;12332:11;12323:20;;12362:27;12383:5;12362:20;:27::i;10743:150:7:-:0;10815:7;10857:27;10876:7;10857:18;:27::i;18429:182:0:-;18486:5;18508:16;18516:7;18508;:16::i;:::-;18503:60;;18533:30;;-1:-1:-1;;;18533:30:0;;;;;;;;;;;18503:60;18580:11;1723:4:21;1716:22;1768:1;1764:13;;;1626:12;1751:27;;;1849:4;1833:21;;1827:28;1810:2;1814:10;;1806:19;1801:55;18580:24:0;1553:319:21;13608:226:0;1211:6:4;25067:31:0;25092:5;25067:24;:31::i;:::-;13686:18:::1;13707;13720:4;13707:12;:18::i;:::-;13686:39;;13735:20;13753:1;13735:17;:20::i;:::-;13765:31:::0;;::::1;-1:-1:-1::0;;;13765:31:0;;::::1;::::0;::::1;4630:6;13765:31;;-1:-1:-1::0;;;;13765:31:0;;::::1;::::0;;;::::1;::::0;;13811:16:::1;::::0;12463:17:24;;;12445:36;;13811:16:0::1;::::0;12433:2:24;12418:18;13811:16:0::1;;;;;;;13676:158;13608:226:::0;;:::o;24393:101::-;24433:13;24465:22;:15;:20;:22::i;:::-;24458:29;;24393:101;:::o;6163:263:7:-;6235:7;-1:-1:-1;;;;;6258:19:7;;6254:69;;6279:44;-1:-1:-1;;;6279:7:7;:44::i;:::-;-1:-1:-1;;;;;6340:23:7;:21;:23::i;:::-;:42;;:49;6383:5;-1:-1:-1;;;;;6340:49:7;-1:-1:-1;;;;;6340:49:7;;;;;;;;;;;;;:79;6333:86;;6163:263;;;:::o;8762:100:18:-;12517:13;:11;:13::i;:::-;8834:21:::1;8852:1;8834:9;:21::i;:::-;8762:100::o:0;17639:91:0:-;17683:7;17709:14;:12;:14::i;14237:199::-;1211:6:4;25067:31:0;25092:5;25067:24;:31::i;:::-;14333:29:::1;:27;:29::i;:::-;14372:21;14384:8;14372:11;:21::i;:::-;14408;14420:8;14408:21;;;;;;:::i;20200:312::-:0;20264:7;20283:10;20296:18;20306:7;20296:9;:18::i;:::-;20283:31;;20325:10;20337:13;20354:70;20394:7;20404:1;20407:16;20418:4;20407:10;:16::i;:::-;20354:19;;;;;;;:13;:19;;;;;;:70;;;;;;;:32;:70;:::i;:::-;20324:100;;-1:-1:-1;20324:100:0;-1:-1:-1;3999:9:4;;3992:17;20462:7:0;20452:17;;3969:41:4;20441:64:0;;-1:-1:-1;;20441:64:0;;;20480:5;20441:64;20434:71;20200:312;-1:-1:-1;;;;;20200:312:0:o;13893:285::-;1211:6:4;25067:31:0;25092:5;25067:24;:31::i;:::-;13989:18:::1;14010;14023:4;14010:12;:18::i;:::-;13989:39;;14038:20;14056:1;14038:17;:20::i;:::-;14068:30;14096:1;14068:27;:30::i;:::-;14108:21:::0;;-1:-1:-1;;;;14108:21:0::1;-1:-1:-1::0;;;14108:21:0::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;::::0;;14144:27:::1;::::0;;26772:4:24;26760:17;;26742:36;;26809:2;26794:18;;26787:51;;;;14144:27:0::1;::::0;26715:18:24;14144:27:0::1;;;;;;;;13979:199;13893:285:::0;;;:::o;6430:1045::-;6553:42;6572:4;:9;;;6583:4;:11;;;6553:18;:42::i;:::-;6605:49;6622:31;:29;:31::i;:::-;6605:16;:49::i;:::-;6665:36;6685:4;:15;;;6665:19;:36::i;:::-;6711:48;6737:4;:21;;;6711:25;:48::i;:::-;6797:12;;;;6770:40;;:15;;:26;:40::i;:::-;6851:16;;;;6820:48;;:19;;:30;:48::i;:::-;6898:21;;;;6879:16;:40;;-1:-1:-1;;;;;;6879:40:0;-1:-1:-1;;;;;6879:40:0;;;;;;;;;6966:18;;;;:25;-1:-1:-1;7009:6:0;;;7005:38;;7024:19;;-1:-1:-1;;;7024:19:0;;;;;;;;;;;7005:38;7062:9;7057:96;7078:1;7073;:6;7057:96;;7104:34;7116:4;:18;;;7135:1;7116:21;;;;;;;;:::i;:::-;;;;;;;7104:11;:34::i;:::-;7081:3;;7057:96;;;-1:-1:-1;;7190:19:0;;;;7173:14;:36;;-1:-1:-1;;;;;;7173:36:0;-1:-1:-1;;;;;7173:36:0;;;;;;;;;7232:15;;;;7219:10;:28;;-1:-1:-1;;;;7219:28:0;-1:-1:-1;;;7219:28:0;;;;;;;;;;;;;;7173:36;7370:23;;;1866:12:4;1859:20;4188:6:0;1855:31:4;7293:21:0;;;;1866:12:4;1859:20;7279:144:0;7258:6;;:165;;;;;;;;;;;;;;;;;;7439:29;7463:4;7439:29;;;;;;:::i;:::-;;;;;;;;6430:1045;:::o;4302:319:12:-;4380:16;25642:1:0;4408:13:12;4464:14;:12;:14::i;:::-;4449:29;;4488:25;4536:4;4527:5;:13;4523:66;;4553:36;4570:5;4577;4584:4;4553:16;:36::i;9056:441:0:-;9149:24;9190:6;-1:-1:-1;;;;;9176:28:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9176:28:0;-1:-1:-1;9238:16:0;;9149:55;;-1:-1:-1;;;;;;9238:16:0;9218:17;9268:140;9284:18;;;9268:140;;9340:53;9372:6;;9379:1;9372:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;9383;9340:31;:53::i;:::-;9327:7;9335:1;9327:10;;;;;;;;:::i;:::-;;;;;;;;;;:66;9304:3;;9268:140;;;;9426:54;9441:9;9452:6;;9460:7;9469:10;9426:54;;;;;;;;;;:::i;12679:870::-;1211:6:4;25067:31:0;25092:5;25067:24;:31::i;:::-;12824:18:::1;12845;12858:4;12845:12;:18::i;:::-;12824:39;;12873:20;12891:1;12873:17;:20::i;:::-;12903:30;12931:1;12903:27;:30::i;:::-;12960:8:::0;;-1:-1:-1;;;12960:8:0;::::1;;;12983:11:::0;;12979:374:::1;;13090:18:::0;;-1:-1:-1;;;13118:18:0;::::1;13090;13118::::0;;::::1;13110:26:::0;;::::1;;-1:-1:-1::0;;;13090:18:0;;::::1;::::0;::::1;13082:26:::0;;::::1;;3385:40:4::0;13068:103:0::1;;;13146:25;;-1:-1:-1::0;;;13146:25:0::1;;;;;;;;;;;13068:103;13261:25;::::0;::::1;-1:-1:-1::0;;;2536:9:4;;;2532:24;2525:32;13246:41:0;-1:-1:-1;13316:25:0::1;::::0;::::1;-1:-1:-1::0;;;2536:9:4;;;2532:24;2525:32;13301:41:0::1;;12979:374;13375:5;13367:13;;:5;:13;;;13363:51;;;13389:25;;-1:-1:-1::0;;;13389:25:0::1;;;;;;;;;;;13363:51;13425:26:::0;;-1:-1:-1;;;;13461:26:0;-1:-1:-1;;;13425:26:0::1;::::0;;::::1;::::0;;::::1;-1:-1:-1::0;;;;13461:26:0;;;;;-1:-1:-1;;;13461:26:0;;::::1;::::0;;::::1;;::::0;;13503:39:::1;::::0;;30058:4:24;30046:17;;30028:36;;30124:2;30109:18;;30102:43;;;;30161:18;;30154:43;;;;13503:39:0::1;::::0;30016:2:24;30001:18;13503:39:0::1;;;;;;;12814:735;;12679:870:::0;;;;:::o;10126:198::-;1211:6:4;25067:31:0;25092:5;25067:24;:31::i;:::-;10215:27:::1;:25;:27::i;:::-;10252:31;:19;10279:3:::0;10252:26:::1;:31::i;:::-;10298:19;10313:3;10298:19;;;;;;:::i;24171:163::-:0;24260:21;24307:20;:18;:20::i;14495:358::-;1211:6:4;25067:31:0;25092:5;25067:24;:31::i;:::-;14601:18:::1;14622;14635:4;14622:12;:18::i;:::-;14601:39;;14650:20;14668:1;14650:17;:20::i;:::-;14680:22;14700:1;14680:19;:22::i;:::-;14739:7:::0;;14722:70:::1;::::0;14739:7:::1;-1:-1:-1::0;;;14739:7:0;;::::1;;4495:6;14784:7:::0;2304:4:4;2310:16;;;2300:27;2293:35;2330:12;;2289:54;2285:65;2274:77;;2109:258;14722:70:0::1;14712:80:::0;;-1:-1:-1;;;;14712:80:0::1;-1:-1:-1::0;;;14712:80:0::1;::::0;;::::1;;;::::0;;14807:39:::1;::::0;;30390:17:24;;;30372:36;;30451:14;;30444:22;30439:2;30424:18;;30417:50;14807:39:0::1;::::0;30345:18:24;14807:39:0::1;30208:265:24::0;3650:217:12;3789:16;3824:36;3841:5;3848;3855:4;3824:16;:36::i;:::-;3817:43;3650:217;-1:-1:-1;;;;3650:217:12:o;16987:255:7:-;17157:8;17081:23;:21;:23::i;:::-;41768:10;17081:63;;;;:42;;;;;:63;;;;;;;;-1:-1:-1;;;;;17081:73:7;;;;;;;;;;;;:84;;-1:-1:-1;;17081:84:7;;;;;;;;;;;17180:55;;2439:14:24;;2432:22;2414:41;;17081:73:7;;41768:10;;17180:55;;2387:18:24;17180:55:7;;;;;;;16987:255;;:::o;18129:91:0:-;18173:7;18199:14;:12;:14::i;9556:231::-;1211:6:4;25067:31:0;25092:5;25067:24;:31::i;:::-;9647:27:::1;:25;:27::i;:::-;9684:14;:23:::0;;-1:-1:-1;;;;;;9684:23:0::1;-1:-1:-1::0;;;;;9684:23:0;::::1;::::0;;::::1;::::0;;;9722:25:::1;::::0;3662:51:24;;;9722:25:0::1;::::0;3650:2:24;3635:18;9722:25:0::1;3516:203:24::0;21856:299:0;21921:6;21939:18;21960;21973:4;21960:12;:18::i;:::-;21939:39;;21988:9;22000:18;22016:1;22000:15;:18::i;:::-;21988:30;;22028:9;22040:15;22053:1;22040:12;:15::i;:::-;22028:27;;;-1:-1:-1;22090:6:0;;22082;;3385:40:4;22072:76:0;;22104:19;;;;;;;:13;:19;;;;;;;;3220:9:4;;;3360:1:21;3351:10;;;3343:19;;;;;;;;3382:1;3367:16;;;;;;3343:41;22072:76:0;;;22100:1;22065:83;21856:299;-1:-1:-1;;;;;21856:299:0:o;17113:110::-;17164:4;17187:29;17197:18;17210:4;17197:12;:18::i;:::-;32992:7;-1:-1:-1;;;32992:7:0;;4630:6;32992:30;:35;;;32907:127;21488:114;21541:6;21566:18;21579:4;21566:12;:18::i;:::-;:29;-1:-1:-1;;;21566:29:0;;;;;;-1:-1:-1;;21488:114:0:o;20571:132::-;20628:14;20661:35;20677:18;20690:4;20677:12;:18::i;:::-;20661:15;:35::i;19215:110::-;19268:6;19293:18;19306:4;19293:12;:18::i;:::-;:25;-1:-1:-1;;;19293:25:0;;;;;;-1:-1:-1;;19215:110:0:o;24657:405:7:-;24826:31;24839:4;24845:2;24849:7;24826:12;:31::i;:::-;-1:-1:-1;;;;;24871:14:7;;;:19;24867:189;;24909:56;24940:4;24946:2;24950:7;24959:5;24909:30;:56::i;:::-;24904:152;;24985:56;-1:-1:-1;;;24985:7:7;:56::i;:::-;24657:405;;;;:::o;19594:547:0:-;19710:25;19783:12;;;19771:9;19821:16;19832:4;19821:10;:16::i;:::-;19809:28;;;-1:-1:-1;19879:8:0;;;19865:12;;;3385:40:4;19851:65:0;;;19897:19;;-1:-1:-1;;;19897:19:0;;;;;;;;;;;19851:65;19955:1;-1:-1:-1;;;;;19941:16:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;19941:16:0;-1:-1:-1;20000:19:0;;;19971:26;20000:19;;;:13;:19;;;;;19930:27;;-1:-1:-1;20033:92:0;20054:1;20049;:6;20033:92;;20100:9;;;3360:1:21;3351:10;;;3302:13;3343:19;;;;;;;;;;;3382:1;3367:16;;;;;;3343:41;20080:30:0;;:8;20089:1;20080:11;;;;;;;;:::i;:::-;;;;;;;;;;:30;20057:3;;20033:92;;;;19747:388;;;19594:547;;;;;:::o;1413:579:12:-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25642:1:0;1612:7:12;:26;1608:368;;1672:14;:12;:14::i;:::-;1662:7;:24;1658:304;;;1842:51;1850:32;1874:7;1850:23;:32::i;:::-;1842:51;;-1:-1:-1;;1884:9:12;;;;1842:51;;;1922:21;1935:7;1922:12;:21::i;1658:304::-;1413:579;;;:::o;20941:118:0:-;20995:6;21020:32;21033:18;21046:4;21033:12;:18::i;:::-;21020:12;:32::i;22216:275::-;22354:13;22388:16;22396:7;22388;:16::i;:::-;22383:59;;22413:29;;-1:-1:-1;;;22413:29:0;;;;;;;;;;;22383:59;22459:25;22476:7;22459:16;:25::i;10383:221::-;1211:6:4;25067:31:0;25092:5;25067:24;:31::i;:::-;10455:27:::1;:25;:27::i;:::-;10492:6;:34:::0;;-1:-1:-1;;;;10492:34:0;::::1;4022:6;-1:-1:-1::0;;;10492:34:0;;;::::1;;;;::::0;;::::1;;::::0;;10556:14:::1;::::0;10541:56:::1;::::0;-1:-1:-1;;;;;10556:14:0::1;10572:9;:7;:9::i;:::-;10583:13;:11;:13::i;:::-;10541:56;;;;;;;;:::i;18279:91::-:0;18323:7;18349:14;:12;:14::i;20762:120::-;20818:4;20841:34;20856:18;20869:4;20856:12;:18::i;:::-;20841:14;:34::i;17789:111::-;17847:7;17873:20;17887:5;17873:13;:20::i;8741:256::-;8851:16;;8800:21;;-1:-1:-1;;;;;8851:16:0;8877:55;8851:16;8800:21;8877:36;:55::i;:::-;8947:43;;;-1:-1:-1;;;;;31221:15:24;;31203:34;;31268:2;31253:18;;31246:34;;;8979:10:0;31296:18:24;;;31289:43;;;;8947::0;;31153:2:24;31138:18;8947:43:0;30963:375:24;15282:1138:0;15326:23;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15326:23:0;15376:9;:7;:9::i;:::-;15361:24;;15414:13;:11;:13::i;:::-;15395:16;;;:32;15464:20;:18;:20::i;:::-;15449:11;;;15437:47;15438:9;;;15437:47;15518:16;;-1:-1:-1;;;;;15518:16:0;;;15494:21;;;:40;15566:14;;;15544:19;;;:36;-1:-1:-1;;;17354:6:0;;4022;17354:33;;:38;;15590:21;;;:42;4188:6;17532:36;:41;;15642:23;;;:46;-1:-1:-1;;;15716:10:0;;;;;15698:15;;:28;15755:13;:11;:13::i;:::-;15736:16;;;:32;15797:13;:11;:13::i;:::-;15778:16;;;:32;15839:13;:11;:13::i;:::-;15820:16;;;:32;15881:13;:11;:13::i;:::-;15862:16;;;:32;15941:9;;-1:-1:-1;;;15941:9:0;;;;;-1:-1:-1;;;15997:13:0;;;;15941:9;-1:-1:-1;;;;;16072:17:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;16056:13:0;;;:33;16242:162;16249:6;;16242:162;;16275:18;16296:15;16309:1;16296:12;:15::i;:::-;16275:36;;16350:11;16359:1;16350:8;:11::i;:::-;16329:4;:13;;;16343:3;;;;;;;16329:18;;;;;;;;:::i;:::-;;;;;;;;;;:32;16383:6;-1:-1:-1;;;16383:6:0;;;;;-1:-1:-1;16242:162:0;;;15905:509;;15282:1138;:::o;24553:109::-;24597:13;24629:26;:19;:24;:26::i;17392:186:7:-;17489:4;17512:23;:21;:23::i;:::-;-1:-1:-1;;;;;17512:49:7;;;;;;;:42;;;;;:49;;;;;;;;:59;;;;;;;;;;-1:-1:-1;17512:59:7;;;;;17392:186::o;21303:126:0:-;21362:6;21387:18;21400:4;21387:12;:18::i;:::-;:35;-1:-1:-1;;;21387:35:0;;;;;;-1:-1:-1;;21303:126:0:o;7534:332::-;7689:19;7654:24;25067:31;7654:24;25067;:31::i;:::-;7738:33:::1;7756:4;7762:8;7738:17;:33::i;:::-;-1:-1:-1::0;7720:51:0;-1:-1:-1;7781:24:0::1;7792:2:::0;7796:8;7781:10:::1;:24::i;:::-;7820:39;::::0;;31600:4:24;31588:17;;31570:36;;-1:-1:-1;;;;;31642:32:24;;31637:2;31622:18;;31615:60;31691:18;;;31684:34;;;31749:2;31734:18;;31727:34;;;7820:39:0::1;::::0;31557:3:24;31542:19;7820:39:0::1;;;;;;;7534:332:::0;;;;;;:::o;10363:708:18:-;12517:13;:11;:13::i;:::-;10597:19:::1;10591:4;10584:33;10643:12;10637:4;10630:26;10705:4;10699;10689:21;10811:12;10805:19;10792:11;10789:36;10786:157;;;10857:10;10851:4;10844:24;10924:4;10918;10911:18;10786:157;11020:1;10999:23:::0;;11041::::1;11051:12:::0;11041:9:::1;:23::i;8348:349::-:0;12517:13;:11;:13::i;:::-;8520:8:::1;8516:2;8512:17;8502:150;;8562:10;8556:4;8549:24;8633:4;8627;8620:18;8502:150;8671:19;8681:8;8671:9;:19::i;18670:120:0:-:0;18759:11;1723:4:21;1716:22;1768:1;1764:13;;;18735:5:0;1751:27:21;;;1849:4;1833:21;;1827:28;1810:2;1814:10;;1806:19;1801:55;18759:24:0;1553:319:21;33232:187:0;33323:15;;;33289:18;33323:15;;;:9;:15;;;;;33352:7;;33323:15;;-1:-1:-1;;;33352:7:0;;;4328:6;33352:28;:33;;33348:64;;33394:18;;-1:-1:-1;;;33394:18:0;;;;;;;;;;;25267:232;25340:14;25357:31;:29;:31::i;:::-;10769:15:19;10763:4;10756:29;;;11060:4;10798:18;;;10898:4;10882:21;;10876:28;25340:48:0;;-1:-1:-1;11083:21:19;;25398:94:0;;-1:-1:-1;;11556:18:18;-1:-1:-1;;;;;25446:17:0;:6;-1:-1:-1;;;;;25446:17:0;;25442:50;;25465:27;:25;:27::i;29685:1504::-;29776:19;29797:27;29868:8;29880:1;29868:13;29864:44;;29890:18;;-1:-1:-1;;;29890:18:0;;;;;;;;;;;29864:44;29936:14;:12;:14::i;:::-;29922:28;;30091:7;30086:1;30075:8;30061:11;:22;:26;:37;30057:66;;30100:23;:21;:23::i;:::-;30138:18;30159;30172:4;30159:12;:18::i;:::-;30209:8;;;;-1:-1:-1;;;;30209:8:0;;;;30192:14;30258:15;30209:8;30258:12;:15::i;:::-;30242:31;;;-1:-1:-1;30395:17:0;;;30430:19;;;30426:56;;;30458:24;;-1:-1:-1;;;30458:24:0;;;;;;;;;;;30426:56;30497:30;;-1:-1:-1;;;;30497:30:0;-1:-1:-1;;;30497:30:0;;;;;;;;4495:6;-1:-1:-1;;;32324:7:0;;;:44;:49;30603:191;;30734:16;;30697:79;;-1:-1:-1;;;;;30734:16:0;30752:6;30760:8;30770:5;30697:36;:79::i;:::-;30650:144;;-1:-1:-1;;30650:144:0;-1:-1:-1;;;;;30650:144:0;;;;;;;30603:191;30838:19;;;30809:26;30838:19;;;:13;:19;;;;;;30871:251;30892:8;30887:1;:13;30871:251;;30925:42;:1;30931:10;;;30950:15;;;3620:8:21;3614:4;3607:22;3662:5;3659:1;3655:13;3649:4;3642:27;3707:4;3701;3691:21;3769:1;3762:5;3758:13;3755:1;3751:21;3831:1;3825:8;3878:10;3962:5;3958:1;3955;3951:9;3947:21;3944:1;3940:29;3937:1;3933:37;3930:1;3926:45;3923:1;3916:56;;;;;3457:531;;;;30925:42:0;31024:9;;;;31020:53;;31035:38;:11;31051:15;;;31068:4;31035:15;:38::i;:::-;30902:3;;30871:251;;;;31165:6;31135:37;;29840:1343;;;;;29685:1504;;;;;:::o;35646:322::-;35794:13;;;35825:6;;35821:24;;35833:12;35839:2;35843:1;35833:5;:12::i;:::-;35871:8;35866:1;:13;35859:93;;35899:13;35905:2;35909;35899:5;:13::i;:::-;35935:2;35930:7;35859:93;;8450:630:7;8535:4;-1:-1:-1;;;;;;;;;8853:25:7;;;;:101;;-1:-1:-1;;;;;;;;;;8929:25:7;;;8853:101;:177;;;-1:-1:-1;;;;;;;;9005:25:7;-1:-1:-1;;;9005:25:7;;8450:630::o;3672:156:4:-;3777:6;3799:22;3802:1;3805:15;3808:1;3414:9;;3407:17;3395:9;;3388:17;3385:40;3805:15;3288:153;3811:8;3414:9;3407:17;3395:9;;3388:17;3385:40;;3288:153;34873:543:0;34980:14;34997:19;34926;;;;35085:20;;35081:329;;35140:27;35160:6;49041:4:22;49035:11;;49213:18;;;49200:32;;-1:-1:-1;49286:18:22;;;49070;;;49317;;;49412:4;49399:18;;49392:34;;;;49496:14;;49472:39;;49489:4;49472:39;49466:46;;49446:18;;;49439:74;49564:50;;;49658:14;;49634:39;;48853:21;49634:39;49627:50;;;;49035:11;48771:922;35140:27:0;35121:46;;-1:-1:-1;35121:46:0;-1:-1:-1;34970:446:0;34873:543;;:::o;35081:329::-;35265:36;35304:23;:21;:23::i;:::-;35265:62;;35349:6;:12;;35341:20;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35385:6;:14;;35375:24;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35184:226;34970:446;34873:543;;:::o;17827:408:7:-;17892:11;17938:7;25642:1:0;17919:26:7;17915:314;;17975:23;:21;:23::i;:::-;:37;17965:47;;17961:258;;;18032:14;18064:84;18081:23;:21;:23::i;:::-;:50;;;;:41;;;;;:50;;;;;;;-1:-1:-1;18071:66:7;;;18064:84;;18139:9;;;:::i;:::-;;;18064:84;;;-1:-1:-1;;;18175:24:7;:29;;17827:408;-1:-1:-1;;17827:408:7:o;43652:160::-;43751:13;43745:4;43738:27;43791:4;43785;43778:18;1793:159:6;1740:46;;1793:159::o;35084:484:7:-;35208:13;35224:16;35232:7;35224;:16::i;:::-;35208:32;;35255:13;:45;;;;-1:-1:-1;41768:10:7;-1:-1:-1;;;;;35272:28:7;;;;35255:45;35251:198;;;35319:44;35336:5;41768:10;17392:186;:::i;35319:44::-;35314:135;;35383:51;-1:-1:-1;;;35383:7:7;:51::i;:::-;35516:2;35459:23;:21;:23::i;:::-;:48;;;;:39;;;;;:48;;;;;;:59;;-1:-1:-1;;;;;;35459:59:7;-1:-1:-1;;;;;35459:59:7;;;;;;35533:28;35459:48;;35533:28;;;;;;;;;;35459:48;35533:28;35198:370;35084:484;;;:::o;26432:123:0:-;26499:20;17532:6;;-1:-1:-1;;;17532:6:0;;4188;17532:36;:41;;;17458:122;26499:20;26495:53;;;26528:20;;-1:-1:-1;;;26528:20:0;;;;;;;;;;;4304:117:19;4382:32;4395:4;4401:5;4408;4382:12;:32::i;7292:355:18:-;-1:-1:-1;;7498:18:18;7488:8;7485:32;7475:156;;7550:10;7544:4;7537:24;7612:4;7606;7599:18;4053:115:19;4130:31;4143:4;4149:5;4156:4;4130:12;:31::i;4588:125:7:-;4643:7;4669:23;:21;:23::i;:::-;:37;;4588:125;-1:-1:-1;4588:125:7:o;1553:319:21:-;1626:12;1729:8;1723:4;1716:22;1771:5;1768:1;1764:13;1758:4;1751:27;1849:4;1843;1833:21;1827:28;1818:5;1814:10;1810:2;1806:19;1801:55;1791:65;;1553:319;;;;:::o;12280:2050:7:-;12347:14;12396:7;25642:1:0;12377:26:7;12373:1894;;12428:23;:21;:23::i;:::-;:50;;;;:41;;;;;:50;;;;;;;-1:-1:-1;12576:11:7;;;12572:1318;;12622:23;:21;:23::i;:::-;:37;12611:48;;12607:101;;12661:47;-1:-1:-1;;;12661:7:7;:47::i;:::-;13331:23;:21;:23::i;:::-;-1:-1:-1;;13373:9:7;;;13331:52;;;;:41;;;;;:52;;;;;;;;-1:-1:-1;13427:25:7;;13255:621;13427:25;-1:-1:-1;;;13478:6:7;:24;13506:1;13478:29;13474:48;;12280:2050;;;:::o;13474:48::-;13810:47;-1:-1:-1;;;13810:7:7;:47::i;:::-;13255:621;;12572:1318;-1:-1:-1;;;14212:6:7;:24;14240:1;14212:29;14208:48;;12280:2050;;;:::o;14208:48::-;14276:47;-1:-1:-1;;;14276:7:7;:47::i;19093:513::-;19192:27;19221:23;19260:53;19316:23;:21;:23::i;:::-;:48;;;;:39;;:48;;-1:-1:-1;;19316:48:7;;;;19564:26;;19316:48;;19564:26;;-1:-1:-1;19093:513:7:o;28417:194:0:-;28485:36;28511:9;28485:25;:36::i;:::-;28531:16;:28;;-1:-1:-1;;;;;;28531:28:0;-1:-1:-1;;;;;28531:28:0;;;;;;;;28574:30;;3662:51:24;;;28574:30:0;;3650:2:24;3635:18;28574:30:0;3516:203:24;6808:212:7;6869:7;-1:-1:-1;;;;;1687:3:7;6908:23;:21;:23::i;:::-;:42;;:49;6951:5;-1:-1:-1;;;;;6908:49:7;-1:-1:-1;;;;;6908:49:7;;;;;;;;;;;;;:74;;6907:106;6888:125;;6808:212;;;:::o;5267:161:4:-;5353:10;5347:4;5340:24;5407:4;5401;5394:18;32547:216:0;32652:12;;32612:6;;-1:-1:-1;;;32652:12:0;;;;32634:15;:30;32630:61;;;-1:-1:-1;32673:18:0;-1:-1:-1;;;32673:18:0;;;;;32547:216::o;32630:61::-;32726:18;;32715:40;;32726:18;-1:-1:-1;;;32726:18:0;;;;;-1:-1:-1;;;32746:8:0;;;2536:9:4;;;2547:8;;-1:-1:-1;2532:24:4;2525:32;;2418:155;31349:418:0;31417:14;31447:25;31470:1;32324:7;-1:-1:-1;;;32324:7:0;;4495:6;32324:44;:49;;;32226:154;31447:25;:46;;;;;31476:17;31491:1;31476:14;:17::i;:::-;31443:318;;;-1:-1:-1;31518:16:0;-1:-1:-1;;;;;31518:16:0;;31575:20;;;31625:9;31619:4;31612:23;31678:4;31662:21;;31714:14;;31710:27;;31349:418::o;31932:124::-;31999:4;32034:15;32047:1;32034:12;:15::i;:::-;32022:8;;:27;;;;-1:-1:-1;;;32022:8:0;;;;;;:27;;;;;;31932:124;-1:-1:-1;31932:124:0:o;25770:125::-;1495:5:4;25839:21:0;;;;25835:53;;;25869:19;;-1:-1:-1;;;25869:19:0;;;;;;;;;;;41882:1708:7;41947:17;42375:4;42368;42362:11;42358:22;42465:1;42459:4;42452:15;42538:4;42535:1;42531:12;42524:19;;;42618:1;42613:3;42606:14;42719:3;42953:5;42935:419;43000:1;42995:3;42991:11;42984:18;;43168:2;43162:4;43158:13;43154:2;43150:22;43145:3;43137:36;43260:2;43250:13;;43315:25;42935:419;43315:25;-1:-1:-1;43382:13:7;;;-1:-1:-1;;43495:14:7;;;43555:19;;;43495:14;41882:1708;-1:-1:-1;41882:1708:7:o;36130:3168::-;36209:27;36239;36258:7;36239:18;:27::i;:::-;36209:57;-1:-1:-1;36209:57:7;36277:12;;36397:35;36424:7;36397:26;:35::i;:::-;36340:92;;;;36447:13;36443:321;;;36566:68;36591:15;36608:4;41768:10;36614:19;41682:103;36566:68;36561:192;;36657:43;36674:4;41768:10;17392:186;:::i;36657:43::-;36652:101;;36702:51;-1:-1:-1;;;36702:7:7;:51::i;:::-;36914:15;36911:157;;;37052:1;37031:19;37024:30;36911:157;37709:32;37657:23;:21;:23::i;:::-;-1:-1:-1;;;;;37657:48:7;;;;;;:42;;;;;:48;;;;;;:84;;;;;;;;;15269:11;15244:23;15240:41;15227:63;-1:-1:-1;;;15227:63:7;37972:23;:21;:23::i;:::-;:50;;;;:41;;;;;:50;;;;;:226;;;;-1:-1:-1;;;38315:47:7;;:52;;38311:689;;38419:1;38409:11;;38540:23;:21;:23::i;:::-;:54;;;;:41;;;;;:54;;;;;;:59;;38536:450;;38700:23;:21;:23::i;:::-;:37;38685:52;;38681:287;;38926:19;38869:23;:21;:23::i;:::-;:54;;;;:41;;;;;:54;;;;;:76;38681:287;38369:631;38311:689;39025:35;;39052:7;;39048:1;;-1:-1:-1;;;;;39025:35:7;;;;;39048:1;;39025:35;39243:23;:21;:23::i;:::-;:36;;;;:38;;;;;;;-1:-1:-1;;;;;;36130:3168:7:o;26246:117:0:-;26311:18;17354:6;;-1:-1:-1;;;17354:6:0;;4022;17354:33;:38;;;17282:117;26311:18;26307:49;;;26338:18;;-1:-1:-1;;;26338:18:0;;;;;;;;;;;8064:103:3;8137:23;8143:3;8148:5;8155:4;8137:5;:23::i;28713:117:0:-;28788:12;28798:1;32992:7;-1:-1:-1;;;32992:7:0;;4630:6;32992:30;:35;;;32907:127;28788:12;28784:39;;;28809:14;;-1:-1:-1;;;28809:14:0;;;;;;;;;;;8306:731:3;8406:11;;8360:13;;8406:11;8427:73;;8478:3;:11;;8471:18;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8306:731;;;:::o;8427:73::-;8509:20;8665:4;8659:11;8648:22;;8802:4;8793:7;8789:18;8783:4;8776:32;8837:4;8828:7;8821:21;8912:10;8905:4;8896:7;8892:18;8885:38;8990:34;9004:7;9013:4;9019;8990:13;:34::i;:::-;8967:63;;;;;;;;:::i;:::-;;;;;;;;;;;;;8960:70;;;;8306:731;;;:::o;6145:1089:18:-;-1:-1:-1;;7093:16:18;;-1:-1:-1;;;;;6941:26:18;;;;;;7053:38;7050:1;;7042:78;7177:27;6145:1089::o;27064:1211:0:-;27140:6;;27177:15;;;27127:10;27177:15;;;:9;:15;;;;;27206:7;;-1:-1:-1;;;27206:7:0;;4328:6;27206:28;:33;27202:65;;27248:19;;-1:-1:-1;;;27248:19:0;;;;;;;;;;;27202:65;27347:15;;;27343:363;;27399:16;27378:18;;;:37;;;27429:18;;;:37;;;27480:12;;;:31;-1:-1:-1;27525:23:0;;;:31;;27570:10;;;:17;27343:363;;;27643:1;:18;;;27622:39;;:1;:18;;;:39;;;27618:77;;;27670:25;;-1:-1:-1;;;27670:25:0;;;;;;;;;;;27618:77;27737:18;;;;27716:39;;27786:18;;;;27829:12;;;;-1:-1:-1;;;;27765:39:0;;;-1:-1:-1;;;27716:39:0;;;;;-1:-1:-1;;;;27765:39:0;;-1:-1:-1;;;27765:39:0;;;;;;;;-1:-1:-1;;;;27814:27:0;-1:-1:-1;;;27814:27:0;;;;;;;;;;;28009:10;;;;1866:12:4;1859:20;4630:6:0;1855:31:4;27920:23:0;;;;1866:12:4;1859:20;4495:6:0;1855:31:4;27851:191:0;;;27873:169;;;;4328:6;27873:169;;;27851:191;;-1:-1:-1;;;27851:191:0;-1:-1:-1;;;;27851:191:0;;;;;;28103:9;;;-1:-1:-1;;;;;;28184:13:0;;;;;28175:22;;;;-1:-1:-1;;;;28175:22:0;;;-1:-1:-1;;;;28175:22:0;;;;;;;;;;;;;;28211:13;;28238:20;;;;;;;-1:-1:-1;;;;28103:9:0;-1:-1:-1;;;28103:9:0;;;;;;28095:22;;;28211:13;;;;;;28238:20;-1:-1:-1;;;;28238:20:0;;;;;;;;;;;;;-1:-1:-1;27064:1211:0:o;8866:235:21:-;9001:10;;9049:45;9062:3;9049:45;;;9079:5;9086:3;9091:2;9049:12;:45::i;:::-;9042:52;;;;8866:235;;;;;;;:::o;28941:136:0:-;29026:17;29041:1;29026:14;:17::i;:::-;29022:48;;;29052:18;;-1:-1:-1;;;29052:18:0;;;;;;;;;;;33599:1013;33690:36;33729:23;:21;:23::i;:::-;33962:20;;33690:62;;-1:-1:-1;33962:25:0;33958:58;;33989:27;:25;:27::i;:::-;25642:1;34026:38;;:20;34185:33;34203:5;34210:7;47752:14:22;47865:1;47859:8;48525:4;48521:1;48516;48510:8;48501:7;48497:22;48493:30;48490:40;48266:7;48259:4;48256:1;48252:12;48248:26;48242:33;48206:7;48203:1;48199:15;48193:22;48182:7;48176:4;48172:18;48169:1;48165:26;48161:55;48133:164;48039:509;48013:535;;;47678:886;;;;;34185:33:0;34168:50;-1:-1:-1;34168:50:0;34367:239;;34407:12;;;:20;34422:5;34407:12;:20;:::i;:::-;-1:-1:-1;34441:14:0;;;:24;34458:7;34441:14;:24;:::i;:::-;;34367:239;;;34567:19;:28;-1:-1:-1;;;33599:1013:0:o;4101:809:15:-;4150:14;4255:8;4249:4;4242:22;4295:23;4347:10;4337:8;4334:24;4331:231;;4441:4;4435;4429;4417:10;4405;4398:5;4387:59;4377:171;;4489:10;4477;4470:30;4377:171;4331:231;4593:23;4645:10;4635:8;4632:24;4629:231;;4739:4;4733;4727;4715:10;4703;4696:5;4685:59;4675:171;;4787:10;4775;4768:30;4675:171;-1:-1:-1;;4889:4:15;4883:11;;4101:809::o;4883:1190:18:-;-1:-1:-1;;;;;5793:26:18;-1:-1:-1;;5876:29:18;;;5793:26;6031:1;5991:38;6031:1;;5980:63;4883:1190;:::o;26031:146:0:-;-1:-1:-1;;;;;26113:23:0;;26109:61;;26145:25;;-1:-1:-1;;;26145:25:0;;;;;;;;;;;7724:154:3;7811:5;7805:19;7828:1;7805:24;7801:37;;7724:154;;:::o;7801:37::-;7847:24;7853:3;7858:5;7865;7847;:24::i;4869:4263:12:-;4991:16;5056:4;5047:5;:13;5043:54;;5062:35;-1:-1:-1;;;5062:7:12;:35::i;:::-;25642:1:0;5173:5:12;:23;5169:85;;;25642:1:0;5216:23:12;;5169:85;5267:17;5287:14;:12;:14::i;:::-;5267:34;;5377:9;5369:4;:17;5365:72;;5413:9;5406:16;;5365:72;5450:25;5489;5517:16;5527:5;5517:9;:16::i;:::-;5566:12;;;5723:35;;;;-1:-1:-1;5789:22:12;;5785:3302;;6008:17;5999:5;5992:4;:12;:33;5988:112;;6076:5;6069:4;:12;6049:32;;5988:112;6219:4;6213:11;6201:23;;6469:1;6450:17;6446:25;6443:1;6439:33;6429:8;6425:48;6419:4;6412:62;6645:31;6679:26;6699:5;6679:19;:26::i;:::-;6645:60;;6723:25;7015:9;:16;;;7010:98;;-1:-1:-1;7075:14:12;;7010:98;7125:19;7312:1616;7349:19;7362:5;7349:12;:19::i;:::-;7337:31;;7453:4;7442:9;7438:20;7432:27;7548:1;7543:893;;;;8752:1;8731:22;;7425:1354;;7543:893;7822:9;7816:16;7813:121;;;7894:9;7888:16;7867:37;;7813:121;8221:5;8202:17;8198:29;8194:2;8190:38;8180:230;;8296:1;8283:11;8279:19;8264:34;;8374:5;8359:11;8356:1;8352:19;8342:8;8338:34;8331:49;8180:230;7425:1354;8824:1;8817:5;8813:13;8804:22;;8885:4;8876:5;:13;:49;;;;8908:17;8893:11;:32;8876:49;8874:52;7312:1616;;9026:29;;-1:-1:-1;;5785:3302:12;-1:-1:-1;9107:8:12;;4869:4263;-1:-1:-1;;;;;;4869:4263:12:o;12425:1612:23:-;12495:14;12600:10;12594:4;12587:24;12693:9;12687:4;12680:23;13053:4;13047;13041;13035;13028:5;13021;13010:48;12952:4;12934:16;12931:26;12846:230;12819:386;;13122:10;13116:4;13109:24;13186:4;13180;13173:18;12819:386;13231:2;13225:4;13218:16;13291:4;13285:11;13275:21;;-1:-1:-1;;;13377:4:23;13370:48;13772:4;13766;13760;13754;13751:1;13744:5;13737;13732:45;13666:16;13659:24;13655:1;13648:4;13642:11;13639:18;13636:48;13551:244;13524:400;;13841:10;13835:4;13828:24;13905:4;13899;13892:18;13524:400;13950:1;13944:4;13937:15;12425:1612;;;;:::o;26840:129:0:-;26917:8;;-1:-1:-1;;;26917:8:0;;;;:13;26913:49;;26939:23;;-1:-1:-1;;;26939:23:0;;;;;;;;;;;5374:314:7;5429:7;25642:1:0;5616:23:7;:21;:23::i;:::-;:37;:55;;5374:314;-1:-1:-1;5374:314:7:o;27088:693::-;27278:99;;-1:-1:-1;;;27278:99:7;;27246:4;;-1:-1:-1;;;;;27278:56:7;;;;;:99;;41768:10;;27356:4;;27362:7;;27371:5;;27278:99;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;27278:99:7;;;;;;;;-1:-1:-1;;27278:99:7;;;;;;;;;;;;:::i;:::-;;;27262:513;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27564:6;:13;27581:1;27564:18;27560:113;;27602:56;-1:-1:-1;;;27602:7:7;:56::i;:::-;27743:6;27737:13;27728:6;27724:2;27720:15;27713:38;27262:513;-1:-1:-1;;;;;;27431:75:7;-1:-1:-1;;;27431:75:7;;-1:-1:-1;27088:693:7;;;;;;:::o;11693:162::-;11772:4;11795:23;:21;:23::i;:::-;:48;;;;:41;;:48;;-1:-1:-1;11795:48:7;;;;:53;;;11693:162::o;11331:183::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11439:68:7;11458:23;:21;:23::i;:::-;:48;;;;:41;;;;;:48;;;;;;-1:-1:-1;;;;;;;;;;;;;14533:41:7;;;;2072:3;14618:33;;;-1:-1:-1;;;;;14584:68:7;-1:-1:-1;;;14584:68:7;-1:-1:-1;;;14681:24:7;;:29;;-1:-1:-1;;;14662:48:7;;;;2581:3;14749:28;;;;-1:-1:-1;;;14720:58:7;-1:-1:-1;14424:361:7;5765:124;5820:7;5846:23;:21;:23::i;:::-;:36;;;5839:43;;5765:124;:::o;6503:212::-;6564:7;-1:-1:-1;;;;;1563:2:7;6603:23;:21;:23::i;5496:721:23:-;5660:6;5645:13;5642:25;5639:146;;;5699:10;5693:4;5686:24;5766:4;5760;5753:18;5639:146;5877:4;5865:10;5859:4;5847:10;5839:6;5835:2;5813:20;5808:74;5798:403;;5915:2;5909:4;5902:16;5988:4;5982;5974:19;6044:4;6038;6030:19;6123:4;6117;6109:6;6102:26;6092:72;;6151:10;6139;6132:30;5487:169:4;5577:10;5571:4;5564:24;5635:4;5629;5622:18;5412:2213:5;5654:10;5744:26;;;5741:1868;;;5817:8;5804:11;5800:26;5878:1717;6055:10;6049:4;6045:21;6042:1;6038:29;6028:8;6024:44;6014:55;6008:4;6001:69;6521:11;6506:12;6494:10;6490:29;6486:47;6480:4;6473:61;6581:4;6575;6565:21;6615:10;6651:1;6646:197;;;;7007:11;7003:1;6989:11;6986:1;6982:19;6978:27;6975:44;6972:387;;;7262:1;7257:3;7253:11;7240:10;7237:1;7233:18;7230:35;7224:4;7217:49;7328:4;7322;7312:21;7295:38;;6972:387;6608:773;;6646:197;6820:1;6803:18;;6608:773;;;7416:13;7402:27;;7482:1;7469:11;7465:19;7450:34;;7563:3;7550:11;7547:20;5878:1717;7544:33;5882:2;5412:2213;;;;;;:::o;1936:404:21:-;2097:8;2091:4;2084:22;2139:5;2136:1;2132:13;2126:4;2119:27;2184:4;2178;2168:21;2238:1;2232:8;2226:4;2219:22;2283:5;2274;2270:10;2266:2;2262:19;2254:35;2318:4;2312:11;2302:22;;-1:-1:-1;;;1936:404:21:o;28227:2347:7:-;28299:20;28322:23;:21;:23::i;:::-;:37;;-1:-1:-1;28322:37:7;28373:13;;;28369:53;;28388:34;-1:-1:-1;;;28388:7:7;:34::i;:::-;-1:-1:-1;;;;;15097:28:7;;15269:11;15244:23;15240:41;15702:1;15689:15;;15663:24;15659:46;15237:52;15227:63;28922:23;:21;:23::i;:::-;:55;;;;:41;;;;;:55;;;;;:194;29389:32;29377:45;;29327:23;:21;:23::i;:::-;-1:-1:-1;;;;;29327:46:7;;;;;;:42;;;;;:46;;;;;:95;;;;;;;;29607:13;;;29603:54;;29622:35;-1:-1:-1;;;29622:7:7;:35::i;:::-;29686:23;;;:12;29768:662;30178:7;30135:8;30091:1;30026:25;29964:1;29900;29870:351;30425:3;30412:9;;;;;;:16;29768:662;;30484:3;30444:23;:21;:23::i;:::-;:43;-1:-1:-1;30507:60:7;;-1:-1:-1;;24657:405:7;2952:967:19;3118:15;3112:4;3105:29;3160:4;3154;3147:18;3210:4;3204;3194:21;3288:8;3282:15;3395:5;3386:7;3383:18;3639:2;3629:62;;-1:-1:-1;3669:19:19;;;3656:33;;3629:62;3763:7;3753:8;3746:25;3895:7;3887:4;3881:11;3877:2;3873:20;3841:30;3838:1;3835;3830:73;;;;2952:967;;;:::o;6048:1489:3:-;6331:12;;6165:19;6450:2;6434:19;;6471:2;6455:19;;6431:44;6428:439;;;6584:12;6569;6564:1;6557:5;6553:13;6547:20;6543:39;6540:57;6537:316;;6633:1;6620:14;;6675:1;6668:5;6664:13;6655:22;;6832:2;6825:5;6818:17;6537:316;6890:9;6886:645;;;6915:28;6946:20;6960:5;6946:13;:20::i;:::-;7080:4;7059:26;7053:33;7157:12;7143:27;;-1:-1:-1;;7269:13:3;;;7347:26;;;7400:24;;;-1:-1:-1;6886:645:3;;;7455:11;;;:19;7469:5;7455:11;:19;:::i;:::-;;7492:8;7488:32;;;7509:11;7502:18;;7488:32;6155:1382;;6048:1489;;;:::o;722:2557:20:-;835:20;961:4;955:11;983:10;980:2283;;;1183:1;1179;1167:10;1163:18;1159:26;1156:1;1152:34;1294:4;1288:11;1278:21;;1664:34;1658:4;1651:48;1791:6;1780:8;1773:16;1769:29;1733:34;1729:70;1723:4;1716:84;1906:4;1898:6;1894:17;1948:13;1943:3;1939:23;2038:623;2090:1;2084:4;2080:12;2072:20;;2152:4;2146:11;2292:4;2284:5;2280:2;2276:14;2272:25;2266:32;2263:1;2255:44;2357:4;2349:5;2345:2;2341:14;2337:25;2331:32;2328:1;2320:44;2421:4;2413:5;2410:1;2406:13;2402:24;2396:31;2393:1;2385:43;2477:4;2470:5;2466:16;2460:23;2457:1;2449:35;;2523:4;2517:11;2512:3;2505:24;2567:1;2562:3;2558:11;2551:18;;2628:3;2623;2620:12;2038:623;2610:33;2700:4;2691:14;2685:4;2678:28;-1:-1:-1;;;2845:1:20;2829:18;;2826:1;2822:26;2956:11;;;2949:37;;;;3134:1;3075:17;;3068:25;3064:33;;;3121:11;;;;3114:22;3206:21;;3191:37;;980:2283;722:2557;;;;;:::o;10157:1206:21:-;10351:10;10363:13;10425:3;10416:5;:12;10412:29;;10436:5;10430:11;;10412:29;10455:9;-1:-1:-1;;10490:9:21;;10498:1;10455:9;10606:3;11863:9;;;10586:34;-1:-1:-1;;;10680:1:21;10663:13;;10662:19;10722:11;;;10756:328;10796:5;;;10807;;;10817:1;10806:12;10795:24;;-1:-1:-1;10841:5:21;;;10848;10837:16;10915:9;;;11863;;;10876:26;;;;;;;;;;;;3220:9:4;;;;10907:32:21;;10876:64;10875:70;;;-1:-1:-1;10963:22:21;;;10980:5;10963:22;11017:1;11007:6;:11;11003:66;;-1:-1:-1;;;11024:9:21;;10756:328;;11003:66;11060:5;11068:1;11060:9;11056:13;;10756:328;;;-1:-1:-1;;;;11194:16:21;;11179:13;;11176:35;11247:14;;11244:21;;11237:29;;11325:1;11314:13;;11310:21;;;11299:33;11292:41;;;;-1:-1:-1;;;;10157:1206:21:o;4370:2729:20:-;4429:19;4550:4;4544:11;4572:10;4569:2514;;;4646:1;4633:10;4630:1;4626:18;4622:26;4760:1;4748:10;4744:18;4734:402;;4809:21;;;4803:28;4833:6;4799:41;5029:2;5024:11;;;5017:19;5045:11;;;;5038:19;5013:45;4937:147;;5109:5;;4734:402;5251:1;5235:18;;5212:46;-1:-1:-1;;5212:46:20;4666:636;5335:4;5329:11;5319:21;;5423:13;5415:6;5408:29;5543:4;5535:6;5531:17;5585:13;5580:3;5576:23;5565:34;;5841:66;5937:1;5931:4;5924:15;5969:52;5963:4;5956:66;6052:32;6046:4;6039:46;6103:771;6192:1;6186:4;6182:12;6174:20;;6234:4;6228:11;6674:5;6670:2;6665:15;6659:22;6656:1;6652:30;6610:5;6606:2;6601:15;6595:22;6592:1;6588:30;6552:160;6549:1;6545:168;6507:5;6503:2;6498:15;6492:22;6489:1;6485:30;6453:286;6450:1;6446:294;6412:5;6408:2;6403:15;6397:22;6394:1;6390:30;6362:400;6357:3;6350:413;;6800:1;6795:3;6791:11;6784:18;;6841:3;6836;6833:12;6103:771;6823:33;6107:2;;6913:4;6908:3;6904:14;6898:4;6891:28;6972:1;6967:3;6960:14;;7041:1;7035:4;7028:15;4569:2514;4370:2729;;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:156:24:-;80:20;;140:4;129:16;;119:27;;109:55;;160:1;157;150:12;175:182;232:6;285:2;273:9;264:7;260:23;256:32;253:52;;;301:1;298;291:12;253:52;324:27;341:9;324:27;:::i;658:367::-;721:8;731:6;785:3;778:4;770:6;766:17;762:27;752:55;;803:1;800;793:12;752:55;-1:-1:-1;826:20:24;;-1:-1:-1;;;;;858:30:24;;855:50;;;901:1;898;891:12;855:50;938:4;930:6;926:17;914:29;;998:3;991:4;981:6;978:1;974:14;966:6;962:27;958:38;955:47;952:67;;;1015:1;1012;1005:12;952:67;658:367;;;;;:::o;1030:575::-;1132:6;1140;1148;1156;1209:2;1197:9;1188:7;1184:23;1180:32;1177:52;;;1225:1;1222;1215:12;1177:52;1248:27;1265:9;1248:27;:::i;:::-;1238:37;;1326:2;1315:9;1311:18;1298:32;-1:-1:-1;;;;;1345:6:24;1342:30;1339:50;;;1385:1;1382;1375:12;1339:50;1424:70;1486:7;1477:6;1466:9;1462:22;1424:70;:::i;:::-;1030:575;;1513:8;;-1:-1:-1;1398:96:24;;1595:2;1580:18;1567:32;;1030:575;-1:-1:-1;;;;1030:575:24:o;1792:131::-;-1:-1:-1;;;;;;1866:32:24;;1856:43;;1846:71;;1913:1;1910;1903:12;1928:245;1986:6;2039:2;2027:9;2018:7;2014:23;2010:32;2007:52;;;2055:1;2052;2045:12;2007:52;2094:9;2081:23;2113:30;2137:5;2113:30;:::i;2466:250::-;2551:1;2561:113;2575:6;2572:1;2569:13;2561:113;;;2651:11;;;2645:18;2632:11;;;2625:39;2597:2;2590:10;2561:113;;;-1:-1:-1;;2708:1:24;2690:16;;2683:27;2466:250::o;2721:271::-;2763:3;2801:5;2795:12;2828:6;2823:3;2816:19;2844:76;2913:6;2906:4;2901:3;2897:14;2890:4;2883:5;2879:16;2844:76;:::i;:::-;2974:2;2953:15;-1:-1:-1;;2949:29:24;2940:39;;;;2981:4;2936:50;;2721:271;-1:-1:-1;;2721:271:24:o;2997:220::-;3146:2;3135:9;3128:21;3109:4;3166:45;3207:2;3196:9;3192:18;3184:6;3166:45;:::i;3222:180::-;3281:6;3334:2;3322:9;3313:7;3309:23;3305:32;3302:52;;;3350:1;3347;3340:12;3302:52;-1:-1:-1;3373:23:24;;3222:180;-1:-1:-1;3222:180:24:o;3724:173::-;3792:20;;-1:-1:-1;;;;;3841:31:24;;3831:42;;3821:70;;3887:1;3884;3877:12;3902:254;3970:6;3978;4031:2;4019:9;4010:7;4006:23;4002:32;3999:52;;;4047:1;4044;4037:12;3999:52;4070:29;4089:9;4070:29;:::i;:::-;4060:39;4146:2;4131:18;;;;4118:32;;-1:-1:-1;;;3902:254:24:o;4161:437::-;4247:6;4255;4308:2;4296:9;4287:7;4283:23;4279:32;4276:52;;;4324:1;4321;4314:12;4276:52;4364:9;4351:23;-1:-1:-1;;;;;4389:6:24;4386:30;4383:50;;;4429:1;4426;4419:12;4383:50;4468:70;4530:7;4521:6;4510:9;4506:22;4468:70;:::i;:::-;4557:8;;4442:96;;-1:-1:-1;4161:437:24;-1:-1:-1;;;;4161:437:24:o;4683:639::-;4850:2;4902:21;;;4972:13;;4875:18;;;4994:22;;;4821:4;;4850:2;5073:15;;;;5047:2;5032:18;;;4821:4;5116:180;5130:6;5127:1;5124:13;5116:180;;;5195:13;;5210:4;5191:24;5179:37;;5271:15;;;;5236:12;;;;5152:1;5145:9;5116:180;;5327:328;5404:6;5412;5420;5473:2;5461:9;5452:7;5448:23;5444:32;5441:52;;;5489:1;5486;5479:12;5441:52;5512:29;5531:9;5512:29;:::i;:::-;5502:39;;5560:38;5594:2;5583:9;5579:18;5560:38;:::i;:::-;5550:48;;5645:2;5634:9;5630:18;5617:32;5607:42;;5327:328;;;;;:::o;5660:186::-;5719:6;5772:2;5760:9;5751:7;5747:23;5743:32;5740:52;;;5788:1;5785;5778:12;5740:52;5811:29;5830:9;5811:29;:::i;5851:248::-;5919:6;5927;5980:2;5968:9;5959:7;5955:23;5951:32;5948:52;;;5996:1;5993;5986:12;5948:52;-1:-1:-1;;6019:23:24;;;6089:2;6074:18;;;6061:32;;-1:-1:-1;5851:248:24:o;6383:435::-;6436:3;6474:5;6468:12;6501:6;6496:3;6489:19;6527:4;6556:2;6551:3;6547:12;6540:19;;6593:2;6586:5;6582:14;6614:1;6624:169;6638:6;6635:1;6632:13;6624:169;;;6699:13;;6687:26;;6733:12;;;;6768:15;;;;6660:1;6653:9;6624:169;;;-1:-1:-1;6809:3:24;;6383:435;-1:-1:-1;;;;;6383:435:24:o;6823:261::-;7002:2;6991:9;6984:21;6965:4;7022:56;7074:2;7063:9;7059:18;7051:6;7022:56;:::i;7089:1087::-;7168:12;;4670:4;4659:16;4647:29;;7232:4;7225:5;7221:16;7215:23;7247:47;7288:4;7283:3;7279:14;7265:12;438:10;427:22;415:35;;362:94;7247:47;;7342:4;7335:5;7331:16;7325:23;7357:49;7400:4;7395:3;7391:14;7375;438:10;427:22;415:35;;362:94;7357:49;;7454:4;7447:5;7443:16;7437:23;7469:49;7512:4;7507:3;7503:14;7487;438:10;427:22;415:35;;362:94;7469:49;;7566:4;7559:5;7555:16;7549:23;7581:49;7624:4;7619:3;7615:14;7599;438:10;427:22;415:35;;362:94;7581:49;;7678:4;7671:5;7667:16;7661:23;7693:49;7736:4;7731:3;7727:14;7711;438:10;427:22;415:35;;362:94;7693:49;;7791:4;7784:5;7780:16;7774:23;7767:4;7762:3;7758:14;7751:47;7846:4;7839:5;7835:16;7829:23;7861:47;7902:4;7897:3;7893:14;7877;2248:13;2241:21;2229:34;;2178:91;7861:47;-1:-1:-1;7927:6:24;7970:14;;;7964:21;2248:13;2241:21;8026:12;;;2229:34;8058:6;8101:14;;;8095:21;2248:13;;2241:21;8157:12;;;2229:34;8125:45;2178:91;8181:250;8367:3;8352:19;;8380:45;8356:9;8407:6;8380:45;:::i;8436:159::-;8503:20;;8563:6;8552:18;;8542:29;;8532:57;;8585:1;8582;8575:12;8600:184;8658:6;8711:2;8699:9;8690:7;8686:23;8682:32;8679:52;;;8727:1;8724;8717:12;8679:52;8750:28;8768:9;8750:28;:::i;8789:127::-;8850:10;8845:3;8841:20;8838:1;8831:31;8881:4;8878:1;8871:15;8905:4;8902:1;8895:15;8921:255;8993:2;8987:9;9035:6;9023:19;;-1:-1:-1;;;;;9057:34:24;;9093:22;;;9054:62;9051:88;;;9119:18;;:::i;:::-;9155:2;9148:22;8921:255;:::o;9181:275::-;9252:2;9246:9;9317:2;9298:13;;-1:-1:-1;;9294:27:24;9282:40;;-1:-1:-1;;;;;9337:34:24;;9373:22;;;9334:62;9331:88;;;9399:18;;:::i;:::-;9435:2;9428:22;9181:275;;-1:-1:-1;9181:275:24:o;9461:187::-;9510:4;-1:-1:-1;;;;;9535:6:24;9532:30;9529:56;;;9565:18;;:::i;:::-;-1:-1:-1;9631:2:24;9610:15;-1:-1:-1;;9606:29:24;9637:4;9602:40;;9461:187::o;9653:338::-;9718:5;9747:53;9763:36;9792:6;9763:36;:::i;:::-;9747:53;:::i;:::-;9738:62;;9823:6;9816:5;9809:21;9863:3;9854:6;9849:3;9845:16;9842:25;9839:45;;;9880:1;9877;9870:12;9839:45;9929:6;9924:3;9917:4;9910:5;9906:16;9893:43;9983:1;9976:4;9967:6;9960:5;9956:18;9952:29;9945:40;9653:338;;;;;:::o;9996:222::-;10039:5;10092:3;10085:4;10077:6;10073:17;10069:27;10059:55;;10110:1;10107;10100:12;10059:55;10132:80;10208:3;10199:6;10186:20;10179:4;10171:6;10167:17;10132:80;:::i;10223:322::-;10292:6;10345:2;10333:9;10324:7;10320:23;10316:32;10313:52;;;10361:1;10358;10351:12;10313:52;10401:9;10388:23;-1:-1:-1;;;;;10426:6:24;10423:30;10420:50;;;10466:1;10463;10456:12;10420:50;10489;10531:7;10522:6;10511:9;10507:22;10489:50;:::i;10550:349::-;10634:12;;-1:-1:-1;;;;;10630:38:24;10618:51;;10722:4;10711:16;;;10705:23;-1:-1:-1;;;;;10701:48:24;10685:14;;;10678:72;10813:4;10802:16;;;10796:23;10789:31;10782:39;10766:14;;;10759:63;10875:4;10864:16;;;10858:23;10883:8;10854:38;10838:14;;10831:62;10550:349::o;10904:724::-;11139:2;11191:21;;;11261:13;;11164:18;;;11283:22;;;11110:4;;11139:2;11362:15;;;;11336:2;11321:18;;;11110:4;11405:197;11419:6;11416:1;11413:13;11405:197;;;11468:52;11516:3;11507:6;11501:13;11468:52;:::i;:::-;11577:15;;;;11549:4;11540:14;;;;;11441:1;11434:9;11405:197;;11633:665;11712:6;11720;11728;11781:2;11769:9;11760:7;11756:23;11752:32;11749:52;;;11797:1;11794;11787:12;11749:52;11820:29;11839:9;11820:29;:::i;:::-;11810:39;;11900:2;11889:9;11885:18;11872:32;-1:-1:-1;;;;;11964:2:24;11956:6;11953:14;11950:34;;;11980:1;11977;11970:12;11950:34;12018:6;12007:9;12003:22;11993:32;;12063:7;12056:4;12052:2;12048:13;12044:27;12034:55;;12085:1;12082;12075:12;12034:55;12125:2;12112:16;12151:2;12143:6;12140:14;12137:34;;;12167:1;12164;12157:12;12137:34;12212:7;12207:2;12198:6;12194:2;12190:15;12186:24;12183:37;12180:57;;;12233:1;12230;12223:12;12180:57;12264:2;12260;12256:11;12246:21;;12286:6;12276:16;;;;;11633:665;;;;;:::o;12492:163::-;12559:20;;12619:10;12608:22;;12598:33;;12588:61;;12645:1;12642;12635:12;12660:160;12725:20;;12781:13;;12774:21;12764:32;;12754:60;;12810:1;12807;12800:12;12825:770;12884:5;12932:4;12920:9;12915:3;12911:19;12907:30;12904:50;;;12950:1;12947;12940:12;12904:50;12983:2;12977:9;13025:4;13017:6;13013:17;13096:6;13084:10;13081:22;-1:-1:-1;;;;;13048:10:24;13045:34;13042:62;13039:88;;;13107:18;;:::i;:::-;13143:2;13136:22;13176:6;-1:-1:-1;13176:6:24;13206:27;13223:9;13206:27;:::i;:::-;13198:6;13191:43;13267:37;13300:2;13289:9;13285:18;13267:37;:::i;:::-;13262:2;13254:6;13250:15;13243:62;13338:37;13371:2;13360:9;13356:18;13338:37;:::i;:::-;13333:2;13325:6;13321:15;13314:62;13409:37;13442:2;13431:9;13427:18;13409:37;:::i;:::-;13404:2;13396:6;13392:15;13385:62;13481:36;13512:3;13501:9;13497:19;13481:36;:::i;:::-;13475:3;13467:6;13463:16;13456:62;13552:36;13583:3;13572:9;13568:19;13552:36;:::i;:::-;13546:3;13538:6;13534:16;13527:62;;12825:770;;;;:::o;13600:238::-;13689:6;13742:3;13730:9;13721:7;13717:23;13713:33;13710:53;;;13759:1;13756;13749:12;13710:53;13782:50;13824:7;13813:9;13782:50;:::i;13843:254::-;13908:6;13916;13969:2;13957:9;13948:7;13944:23;13940:32;13937:52;;;13985:1;13982;13975:12;13937:52;14008:27;14025:9;14008:27;:::i;:::-;13998:37;;14054;14087:2;14076:9;14072:18;14054:37;:::i;14102:758::-;14168:5;14221:3;14214:4;14206:6;14202:17;14198:27;14188:55;;14239:1;14236;14229:12;14188:55;14275:6;14262:20;14301:4;-1:-1:-1;;;;;14320:2:24;14317:26;14314:52;;;14346:18;;:::i;:::-;14386:36;14418:2;14413;14410:1;14406:10;14402:19;14386:36;:::i;:::-;14456:15;;;14518:4;14561:11;;;14549:24;;14545:33;;;14487:12;;;;14444:3;14590:15;;;14587:35;;;14618:1;14615;14608:12;14587:35;14654:2;14646:6;14642:15;14666:165;14682:6;14677:3;14674:15;14666:165;;;14748:40;14784:3;14779;14748:40;:::i;:::-;14736:53;;14809:12;;;;14699;;14666:165;;;-1:-1:-1;14849:5:24;;14102:758;-1:-1:-1;;;;;;;14102:758:24:o;14865:1705::-;14963:6;15016:2;15004:9;14995:7;14991:23;14987:32;14984:52;;;15032:1;15029;15022:12;14984:52;15072:9;15059:23;-1:-1:-1;;;;;15142:2:24;15134:6;15131:14;15128:34;;;15158:1;15155;15148:12;15128:34;15181:22;;;;15237:6;15219:16;;;15215:29;15212:49;;;15257:1;15254;15247:12;15212:49;15283:22;;:::i;:::-;15343:2;15330:16;15371:2;15361:8;15358:16;15355:36;;;15387:1;15384;15377:12;15355:36;15414:45;15451:7;15440:8;15436:2;15432:17;15414:45;:::i;:::-;15407:5;15400:60;;15506:2;15502;15498:11;15485:25;15535:2;15525:8;15522:16;15519:36;;;15551:1;15548;15541:12;15519:36;15587:45;15624:7;15613:8;15609:2;15605:17;15587:45;:::i;:::-;15582:2;15575:5;15571:14;15564:69;;15665:31;15692:2;15688;15684:11;15665:31;:::i;:::-;15660:2;15653:5;15649:14;15642:55;15743:2;15739;15735:11;15722:25;15772:2;15762:8;15759:16;15756:36;;;15788:1;15785;15778:12;15756:36;15824:45;15861:7;15850:8;15846:2;15842:17;15824:45;:::i;:::-;15819:2;15812:5;15808:14;15801:69;;15916:3;15912:2;15908:12;15895:26;15946:2;15936:8;15933:16;15930:36;;;15962:1;15959;15952:12;15930:36;15999:45;16036:7;16025:8;16021:2;16017:17;15999:45;:::i;:::-;15993:3;15986:5;15982:15;15975:70;;16078:32;16105:3;16101:2;16097:12;16078:32;:::i;:::-;16072:3;16065:5;16061:15;16054:57;16144:31;16170:3;16166:2;16162:12;16144:31;:::i;:::-;16138:3;16131:5;16127:15;16120:56;16209:29;16233:3;16229:2;16225:12;16209:29;:::i;:::-;16203:3;16196:5;16192:15;16185:54;16258:3;16293:28;16317:2;16313;16309:11;16293:28;:::i;:::-;16277:14;;;16270:52;16341:3;16382:11;;;16369:25;16406:16;;;16403:36;;;16435:1;16432;16425:12;16403:36;16471:68;16531:7;16520:8;16516:2;16512:17;16471:68;:::i;:::-;16455:14;;;16448:92;;;;-1:-1:-1;16459:5:24;14865:1705;-1:-1:-1;;;;;14865:1705:24:o;17017:326::-;17090:6;17098;17106;17159:2;17147:9;17138:7;17134:23;17130:32;17127:52;;;17175:1;17172;17165:12;17127:52;17198:27;17215:9;17198:27;:::i;:::-;17188:37;;17244;17277:2;17266:9;17262:18;17244:37;:::i;:::-;17234:47;;17300:37;17333:2;17322:9;17318:18;17300:37;:::i;:::-;17290:47;;17017:326;;;;;:::o;17348:250::-;17411:6;17419;17472:2;17460:9;17451:7;17447:23;17443:32;17440:52;;;17488:1;17485;17478:12;17440:52;17511:27;17528:9;17511:27;:::i;:::-;17501:37;;17557:35;17588:2;17577:9;17573:18;17557:35;:::i;17603:322::-;17680:6;17688;17696;17749:2;17737:9;17728:7;17724:23;17720:32;17717:52;;;17765:1;17762;17755:12;17717:52;17788:29;17807:9;17788:29;:::i;:::-;17778:39;17864:2;17849:18;;17836:32;;-1:-1:-1;17915:2:24;17900:18;;;17887:32;;17603:322;-1:-1:-1;;;17603:322:24:o;17930:254::-;17995:6;18003;18056:2;18044:9;18035:7;18031:23;18027:32;18024:52;;;18072:1;18069;18062:12;18024:52;18095:29;18114:9;18095:29;:::i;18189:667::-;18284:6;18292;18300;18308;18361:3;18349:9;18340:7;18336:23;18332:33;18329:53;;;18378:1;18375;18368:12;18329:53;18401:29;18420:9;18401:29;:::i;:::-;18391:39;;18449:38;18483:2;18472:9;18468:18;18449:38;:::i;:::-;18439:48;;18534:2;18523:9;18519:18;18506:32;18496:42;;18589:2;18578:9;18574:18;18561:32;-1:-1:-1;;;;;18608:6:24;18605:30;18602:50;;;18648:1;18645;18638:12;18602:50;18671:22;;18724:4;18716:13;;18712:27;-1:-1:-1;18702:55:24;;18753:1;18750;18743:12;18702:55;18776:74;18842:7;18837:2;18824:16;18819:2;18815;18811:11;18776:74;:::i;:::-;18766:84;;;18189:667;;;;;;;:::o;19149:318::-;19224:6;19232;19240;19293:2;19281:9;19272:7;19268:23;19264:32;19261:52;;;19309:1;19306;19299:12;19261:52;19332:27;19349:9;19332:27;:::i;19472:268::-;19670:3;19655:19;;19683:51;19659:9;19716:6;19683:51;:::i;19745:467::-;19806:3;19844:5;19838:12;19871:6;19866:3;19859:19;19897:4;19926:2;19921:3;19917:12;19910:19;;19963:2;19956:5;19952:14;19984:1;19994:193;20008:6;20005:1;20002:13;19994:193;;;20057:46;20099:3;20090:6;20084:13;20057:46;:::i;:::-;20132:6;20123:16;;;;;20162:15;;;;20030:1;20023:9;19994:193;;20217:2197;20404:2;20393:9;20386:21;20367:4;20442:6;20436:13;20468:6;20510:2;20505;20494:9;20490:18;20483:30;20536:52;20583:3;20572:9;20568:19;20554:12;20536:52;:::i;:::-;20522:66;;20637:2;20629:6;20625:15;20619:22;20664:2;20660:7;20731:2;20719:9;20711:6;20707:22;20703:31;20698:2;20687:9;20683:18;20676:59;20758:41;20792:6;20776:14;20758:41;:::i;:::-;20744:55;;20848:2;20840:6;20836:15;20830:22;20808:44;;20916:2;20904:9;20896:6;20892:22;20888:31;20883:2;20872:9;20868:18;20861:59;20943:41;20977:6;20961:14;20943:41;:::i;:::-;20929:55;;21033:2;21025:6;21021:15;21015:22;20993:44;;21102:2;21090:9;21082:6;21078:22;21074:31;21068:3;21057:9;21053:19;21046:60;21129:41;21163:6;21147:14;21129:41;:::i;:::-;21115:55;;21219:3;21211:6;21207:16;21201:23;21179:45;;21233:55;21283:3;21272:9;21268:19;21252:14;-1:-1:-1;;;;;3473:31:24;3461:44;;3407:104;21233:55;21337:3;21325:16;;21319:23;-1:-1:-1;;;;;3473:31:24;;21401:3;21386:19;;3461:44;21319:23;-1:-1:-1;21455:3:24;21443:16;;21437:23;2248:13;;2241:21;21516:3;21501:19;;2229:34;21437:23;-1:-1:-1;21570:3:24;21562:6;21558:16;21552:23;21530:45;;21594:3;21606:51;21653:2;21642:9;21638:18;21622:14;2248:13;2241:21;2229:34;;2178:91;21606:51;21694:15;;21688:22;;-1:-1:-1;21729:3:24;21741:53;21775:18;;;21688:22;18937:6;18926:18;18914:31;;18861:90;21741:53;21819:15;;21813:22;21854:3;21873:18;;;21866:30;;;;21921:15;;21915:22;21956:3;21975:18;;;21968:30;;;;22023:15;;22017:22;22059:3;22078:19;;;22071:31;;;;22128:16;;22122:23;22165:3;22184:19;;;22177:32;;;;22246:16;;22240:23;22303:22;;;22299:31;;;22279:18;;;22272:59;22240:23;-1:-1:-1;22348:60:24;22307:6;22240:23;22348:60;:::i;:::-;22340:68;20217:2197;-1:-1:-1;;;;;;20217:2197:24:o;22419:260::-;22487:6;22495;22548:2;22536:9;22527:7;22523:23;22519:32;22516:52;;;22564:1;22561;22554:12;22516:52;22587:29;22606:9;22587:29;:::i;:::-;22577:39;;22635:38;22669:2;22658:9;22654:18;22635:38;:::i;22684:324::-;22759:6;22767;22775;22828:2;22816:9;22807:7;22803:23;22799:32;22796:52;;;22844:1;22841;22834:12;22796:52;22867:27;22884:9;22867:27;:::i;23013:127::-;23074:10;23069:3;23065:20;23062:1;23055:31;23105:4;23102:1;23095:15;23129:4;23126:1;23119:15;23145:447;23245:6;23240:3;23233:19;23215:3;23271:4;23300:2;23295:3;23291:12;23284:19;;23326:5;23349:1;23359:208;23373:6;23370:1;23367:13;23359:208;;;-1:-1:-1;;;;;23438:26:24;23457:6;23438:26;:::i;:::-;23434:52;23422:65;;23507:12;;;;23542:15;;;;23395:1;23388:9;23359:208;;23597:510;23878:4;23870:6;23866:17;23855:9;23848:36;23920:3;23915:2;23904:9;23900:18;23893:31;23829:4;23941:74;24010:3;23999:9;23995:19;23987:6;23979;23941:74;:::i;:::-;24046:2;24031:18;;24024:34;;;;-1:-1:-1;24089:2:24;24074:18;24067:34;23933:82;23597:510;-1:-1:-1;;;23597:510:24:o;24112:127::-;24173:10;24168:3;24164:20;24161:1;24154:31;24204:4;24201:1;24194:15;24228:4;24225:1;24218:15;24244:128;24311:9;;;24332:11;;;24329:37;;;24346:18;;:::i;24630:649::-;24710:6;24763:2;24751:9;24742:7;24738:23;24734:32;24731:52;;;24779:1;24776;24769:12;24731:52;24812:9;24806:16;-1:-1:-1;;;;;24837:6:24;24834:30;24831:50;;;24877:1;24874;24867:12;24831:50;24900:22;;24953:4;24945:13;;24941:27;-1:-1:-1;24931:55:24;;24982:1;24979;24972:12;24931:55;25011:2;25005:9;25036:49;25052:32;25081:2;25052:32;:::i;25036:49::-;25108:2;25101:5;25094:17;25148:7;25143:2;25138;25134;25130:11;25126:20;25123:33;25120:53;;;25169:1;25166;25159:12;25120:53;25182:67;25246:2;25241;25234:5;25230:14;25225:2;25221;25217:11;25182:67;:::i;25284:496::-;25463:3;25501:6;25495:13;25517:66;25576:6;25571:3;25564:4;25556:6;25552:17;25517:66;:::i;:::-;25646:13;;25605:16;;;;25668:70;25646:13;25605:16;25715:4;25703:17;;25668:70;:::i;:::-;25754:20;;25284:496;-1:-1:-1;;;;25284:496:24:o;25785:517::-;25881:4;25873:5;25867:12;25863:23;25858:3;25851:36;25933:4;25926:5;25922:16;25916:23;25958:10;26018:2;26004:12;26000:21;25993:4;25988:3;25984:14;25977:45;26083:2;26075:4;26068:5;26064:16;26058:23;26054:32;26047:4;26042:3;26038:14;26031:56;26148:2;26140:4;26133:5;26129:16;26123:23;26119:32;26112:4;26107:3;26103:14;26096:56;;;26215:4;26208:5;26204:16;26198:23;26191:31;26184:39;26177:4;26172:3;26168:14;26161:63;26287:4;26280:5;26276:16;26270:23;26263:31;26256:39;26249:4;26244:3;26240:14;26233:63;25785:517;;:::o;26307:262::-;26501:3;26486:19;;26514:49;26490:9;26545:6;26514:49;:::i;26849:473::-;26914:3;26952:5;26946:12;26979:6;26974:3;26967:19;27005:4;27034:2;27029:3;27025:12;27018:19;;27071:2;27064:5;27060:14;27092:1;27102:195;27116:6;27113:1;27110:13;27102:195;;;27165:50;27211:3;27202:6;27196:13;27165:50;:::i;:::-;27244:4;27235:14;;;;;27272:15;;;;27138:1;27131:9;27102:195;;27327:1805;27534:2;27523:9;27516:21;27497:4;27572:6;27566:13;27598:6;27640:2;27635;27624:9;27620:18;27613:30;27666:52;27713:3;27702:9;27698:19;27684:12;27666:52;:::i;:::-;27652:66;;27767:2;27759:6;27755:15;27749:22;27794:2;27790:7;27861:2;27849:9;27841:6;27837:22;27833:31;27828:2;27817:9;27813:18;27806:59;27888:41;27922:6;27906:14;27888:41;:::i;:::-;27874:55;;27978:2;27970:6;27966:15;27960:22;27938:44;;27991:54;28041:2;28030:9;28026:18;28010:14;-1:-1:-1;;;;;3473:31:24;3461:44;;3407:104;27991:54;28094:2;28086:6;28082:15;28076:22;28054:44;;28163:2;28151:9;28143:6;28139:22;28135:31;28129:3;28118:9;28114:19;28107:60;28190:41;28224:6;28208:14;28190:41;:::i;:::-;28176:55;;28280:3;28272:6;28268:16;28262:23;28240:45;;28350:2;28338:9;28330:6;28326:22;28322:31;28316:3;28305:9;28301:19;28294:60;28377:41;28411:6;28395:14;28377:41;:::i;:::-;28363:55;;28467:3;28459:6;28455:16;28449:23;28427:45;;28481:55;28531:3;28520:9;28516:19;28500:14;-1:-1:-1;;;;;3473:31:24;3461:44;;3407:104;28481:55;28585:3;28573:16;;28567:23;18937:6;18926:18;;28648:3;28633:19;;18914:31;28567:23;-1:-1:-1;28702:3:24;28694:6;28690:16;28684:23;28662:45;;28726:3;28738:51;28785:2;28774:9;28770:18;28754:14;2248:13;2241:21;2229:34;;2178:91;28738:51;28826:15;;28820:22;;-1:-1:-1;28861:3:24;28873:51;28905:18;;;28820:22;2248:13;2241:21;2229:34;;2178:91;28873:51;28961:15;;28955:22;29017;;;29013:31;;;28993:18;;;28986:59;28955:22;-1:-1:-1;29062:64:24;29021:6;28955:22;29062:64;:::i;29137:692::-;29423:4;29469:1;29465;29460:3;29456:11;29452:19;29510:2;29502:6;29498:15;29487:9;29480:34;29550:3;29545:2;29534:9;29530:18;29523:31;29577:74;29646:3;29635:9;29631:19;29623:6;29615;29577:74;:::i;:::-;29699:9;29691:6;29687:22;29682:2;29671:9;29667:18;29660:50;29727:44;29764:6;29756;29727:44;:::i;:::-;29719:52;;;29819:2;29811:6;29807:15;29802:2;29791:9;29787:18;29780:43;;29137:692;;;;;;;;:::o;30478:480::-;-1:-1:-1;;;;;30703:32:24;;30685:51;;30772:2;30767;30752:18;;30745:30;;;-1:-1:-1;;30798:45:24;;30824:18;;30816:6;30798:45;:::i;:::-;30891:9;30883:6;30879:22;30874:2;30863:9;30859:18;30852:50;30919:33;30945:6;30937;30919:33;:::i;31904:380::-;31983:1;31979:12;;;;32026;;;32047:61;;32101:4;32093:6;32089:17;32079:27;;32047:61;32154:2;32146:6;32143:14;32123:18;32120:38;32117:161;;32200:10;32195:3;32191:20;32188:1;32181:31;32235:4;32232:1;32225:15;32263:4;32260:1;32253:15;32289:136;32328:3;32356:5;32346:39;;32365:18;;:::i;:::-;-1:-1:-1;;;32401:18:24;;32289:136::o;32430:567::-;-1:-1:-1;;;32766:3:24;32759:20;32741:3;32808:6;32802:13;32824:74;32891:6;32887:1;32882:3;32878:11;32871:4;32863:6;32859:17;32824:74;:::i;:::-;-1:-1:-1;;;32957:1:24;32917:16;;;;32949:10;;;32942:23;-1:-1:-1;32989:1:24;32981:10;;32430:567;-1:-1:-1;32430:567:24:o;33128:545::-;33230:2;33225:3;33222:11;33219:448;;;33266:1;33291:5;33287:2;33280:17;33336:4;33332:2;33322:19;33406:2;33394:10;33390:19;33387:1;33383:27;33377:4;33373:38;33442:4;33430:10;33427:20;33424:47;;;-1:-1:-1;33465:4:24;33424:47;33520:2;33515:3;33511:12;33508:1;33504:20;33498:4;33494:31;33484:41;;33575:82;33593:2;33586:5;33583:13;33575:82;;;33638:17;;;33619:1;33608:13;33575:82;;;33579:3;;;33128:545;;;:::o;33849:1352::-;33975:3;33969:10;-1:-1:-1;;;;;33994:6:24;33991:30;33988:56;;;34024:18;;:::i;:::-;34053:97;34143:6;34103:38;34135:4;34129:11;34103:38;:::i;:::-;34097:4;34053:97;:::i;:::-;34205:4;;34269:2;34258:14;;34286:1;34281:663;;;;34988:1;35005:6;35002:89;;;-1:-1:-1;35057:19:24;;;35051:26;35002:89;-1:-1:-1;;33806:1:24;33802:11;;;33798:24;33794:29;33784:40;33830:1;33826:11;;;33781:57;35104:81;;34251:944;;34281:663;33075:1;33068:14;;;33112:4;33099:18;;-1:-1:-1;;34317:20:24;;;34435:236;34449:7;34446:1;34443:14;34435:236;;;34538:19;;;34532:26;34517:42;;34630:27;;;;34598:1;34586:14;;;;34465:19;;34435:236;;;34439:3;34699:6;34690:7;34687:19;34684:201;;;34760:19;;;34754:26;-1:-1:-1;;34843:1:24;34839:14;;;34855:3;34835:24;34831:37;34827:42;34812:58;34797:74;;34684:201;-1:-1:-1;;;;;34931:1:24;34915:14;;;34911:22;34898:36;;-1:-1:-1;33849:1352:24:o;35206:489::-;-1:-1:-1;;;;;35475:15:24;;;35457:34;;35527:15;;35522:2;35507:18;;35500:43;35574:2;35559:18;;35552:34;;;35622:3;35617:2;35602:18;;35595:31;;;35400:4;;35643:46;;35669:19;;35661:6;35643:46;:::i;35700:249::-;35769:6;35822:2;35810:9;35801:7;35797:23;35793:32;35790:52;;;35838:1;35835;35828:12;35790:52;35870:9;35864:16;35889:30;35913:5;35889:30;:::i
Swarm Source
ipfs://49e6d1cd0280f13035da064d43e0d0c04baabf189e47190a2588815ba6a8c9fa
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ 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.