This nametag was submitted by Kleros Curate.
Overview
ETH Balance
4.53187195 ETH
ETH Value
$16,873.22 (@ $3,723.23/ETH)Token Holdings
More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 56,771 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x4a04a1c9 | 129088626 | 6 hrs ago | IN | 0.000777 ETH | 0.000000434706 | ||||
0x4a04a1c9 | 129083445 | 8 hrs ago | IN | 0.000777 ETH | 0.000000524389 | ||||
0x4a04a1c9 | 129081015 | 10 hrs ago | IN | 0.000777 ETH | 0.000001131417 | ||||
0x4a04a1c9 | 129076151 | 12 hrs ago | IN | 0.000777 ETH | 0.00000073467 | ||||
0x4a04a1c9 | 129076032 | 13 hrs ago | IN | 0.000777 ETH | 0.000000686582 | ||||
0x4a04a1c9 | 129065998 | 18 hrs ago | IN | 0.000777 ETH | 0.000000921862 | ||||
0x4a04a1c9 | 129060308 | 21 hrs ago | IN | 0.000777 ETH | 0.000001892621 | ||||
0x4a04a1c9 | 129059771 | 22 hrs ago | IN | 0.000777 ETH | 0.000001599218 | ||||
0x4a04a1c9 | 129059105 | 22 hrs ago | IN | 0.000777 ETH | 0.00000242371 | ||||
0x4a04a1c9 | 129059049 | 22 hrs ago | IN | 0.000777 ETH | 0.000002165588 | ||||
0x4a04a1c9 | 129057648 | 23 hrs ago | IN | 0.000777 ETH | 0.000002861766 | ||||
0x4a04a1c9 | 129053483 | 25 hrs ago | IN | 0.000777 ETH | 0.00000028141 | ||||
0x4a04a1c9 | 129051337 | 26 hrs ago | IN | 0.000777 ETH | 0.000000144718 | ||||
0x4a04a1c9 | 129050880 | 27 hrs ago | IN | 0.000777 ETH | 0.000000330097 | ||||
0x4a04a1c9 | 129049888 | 27 hrs ago | IN | 0.000777 ETH | 0.000000147183 | ||||
0x4a04a1c9 | 129049881 | 27 hrs ago | IN | 0.000777 ETH | 0.00000014384 | ||||
0x4a04a1c9 | 129048264 | 28 hrs ago | IN | 0.000777 ETH | 0.000000165819 | ||||
0x4a04a1c9 | 129043571 | 31 hrs ago | IN | 0.000777 ETH | 0.00000019624 | ||||
0x4a04a1c9 | 129043507 | 31 hrs ago | IN | 0.000777 ETH | 0.000000209155 | ||||
0x4a04a1c9 | 129041414 | 32 hrs ago | IN | 0.000777 ETH | 0.00000042699 | ||||
0x4a04a1c9 | 129040235 | 32 hrs ago | IN | 0.000777 ETH | 0.000000471099 | ||||
0x4a04a1c9 | 129038720 | 33 hrs ago | IN | 0.000777 ETH | 0.000000758808 | ||||
0x4a04a1c9 | 129035065 | 35 hrs ago | IN | 0.000777 ETH | 0.000001217201 | ||||
0x4a04a1c9 | 129033649 | 36 hrs ago | IN | 0.000777 ETH | 0.000000607963 | ||||
0x4a04a1c9 | 129033565 | 36 hrs ago | IN | 0.000777 ETH | 0.000000513735 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
129088626 | 6 hrs ago | 0.000555 ETH | ||||
129083445 | 8 hrs ago | 0.000555 ETH | ||||
129081015 | 10 hrs ago | 0.000555 ETH | ||||
129076151 | 12 hrs ago | 0.000555 ETH | ||||
129076032 | 13 hrs ago | 0.000555 ETH | ||||
129065998 | 18 hrs ago | 0.000555 ETH | ||||
129060308 | 21 hrs ago | 0.000555 ETH | ||||
129059771 | 22 hrs ago | 0.000555 ETH | ||||
129059105 | 22 hrs ago | 0.000555 ETH | ||||
129059049 | 22 hrs ago | 0.000555 ETH | ||||
129057648 | 23 hrs ago | 0.000555 ETH | ||||
129053483 | 25 hrs ago | 0.000555 ETH | ||||
129051337 | 26 hrs ago | 0.000555 ETH | ||||
129050880 | 27 hrs ago | 0.000555 ETH | ||||
129049888 | 27 hrs ago | 0.000555 ETH | ||||
129049881 | 27 hrs ago | 0.000555 ETH | ||||
129048264 | 28 hrs ago | 0.000555 ETH | ||||
129043571 | 31 hrs ago | 0.000555 ETH | ||||
129043507 | 31 hrs ago | 0.000555 ETH | ||||
129041414 | 32 hrs ago | 0.000555 ETH | ||||
129040235 | 32 hrs ago | 0.000555 ETH | ||||
129038720 | 33 hrs ago | 0.000555 ETH | ||||
129035065 | 35 hrs ago | 0.000555 ETH | ||||
129033649 | 36 hrs ago | 0.000555 ETH | ||||
129033565 | 36 hrs ago | 0.000555 ETH |
Loading...
Loading
Contract Name:
SuperMinterV2
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 { Ownable, OwnableRoles } from "solady/auth/OwnableRoles.sol"; import { ISoundEditionV2_1 } from "@core/interfaces/ISoundEditionV2_1.sol"; import { ISuperMinterV2 } from "@modules/interfaces/ISuperMinterV2.sol"; import { IERC165 } from "openzeppelin/utils/introspection/IERC165.sol"; import { SafeTransferLib } from "solady/utils/SafeTransferLib.sol"; import { EIP712 } from "solady/utils/EIP712.sol"; import { MerkleProofLib } from "solady/utils/MerkleProofLib.sol"; import { LibBitmap } from "solady/utils/LibBitmap.sol"; import { SignatureCheckerLib } from "solady/utils/SignatureCheckerLib.sol"; import { LibZip } from "solady/utils/LibZip.sol"; import { LibMap } from "solady/utils/LibMap.sol"; import { DelegateCashLib } from "@modules/utils/DelegateCashLib.sol"; import { LibOps } from "@core/utils/LibOps.sol"; import { LibMulticaller } from "multicaller/LibMulticaller.sol"; /** * @title SuperMinterV2 * @dev The `SuperMinterV2` class is a generalized minter. */ contract SuperMinterV2 is ISuperMinterV2, EIP712 { using LibBitmap for *; using MerkleProofLib for *; using LibMap for *; // ============================================================= // STRUCTS // ============================================================= /** * @dev A struct to hold the mint data in storage. */ struct MintData { // The platform address. address platform; // The price per token. uint96 price; // The start time of the mint. uint32 startTime; // The end time of the mint. uint32 endTime; // The maximum number of tokens an account can mint in this mint. uint32 maxMintablePerAccount; // The maximum tokens mintable. uint32 maxMintable; // The total number of tokens minted. uint32 minted; // The affiliate fee BPS. uint16 affiliateFeeBPS; // The offset to the next mint data in the linked list. uint16 next; // The head of the mint data linked list. // Only stored in the 0-th mint data per edition. uint16 head; // The total number of mint data. // Only stored in the 0-th mint data per edition. uint16 numMintData; // The total number of mints for the edition-tier. // Only stored in the 0-th mint data per edition-tier. uint8 nextScheduleNum; // The mode of the mint. uint8 mode; // The packed boolean flags. uint8 flags; // The affiliate Merkle root, if any. bytes32 affiliateMerkleRoot; // The Merkle root hash, required if `mode` is `VERIFY_MERKLE`. bytes32 merkleRoot; } // ============================================================= // CONSTANTS // ============================================================= /** * @dev The GA tier. Which is 0. */ uint8 public constant GA_TIER = 0; /** * @dev For EIP-712 signature digest calculation. */ bytes32 public constant MINT_TO_TYPEHASH = // prettier-ignore keccak256( "MintTo(" "address edition," "uint8 tier," "uint8 scheduleNum," "address to," "uint32 signedQuantity," "uint32 signedClaimTicket," "uint96 signedPrice," "uint32 signedDeadline," "address affiliate" ")" ); /** * @dev For EIP-712 platform airdrop signature digest calculation. */ bytes32 public constant PLATFORM_AIRDROP_TYPEHASH = // prettier-ignore keccak256( "PlatformAirdrop(" "address edition," "uint8 tier," "uint8 scheduleNum," "address[] to," "uint32 signedQuantity," "uint32 signedClaimTicket," "uint32 signedDeadline" ")" ); /** * @dev For EIP-712 signature digest calculation. */ bytes32 public constant DOMAIN_TYPEHASH = _DOMAIN_TYPEHASH; /** * @dev The default value for options. */ uint8 public constant DEFAULT = 0; /** * @dev The Merkle drop mint mode. */ uint8 public constant VERIFY_MERKLE = 1; /** * @dev The Signature mint mint mode. */ uint8 public constant VERIFY_SIGNATURE = 2; /** * @dev The platform airdrop mint mode. */ uint8 public constant PLATFORM_AIRDROP = 3; /** * @dev The denominator of all BPS calculations. */ uint16 public constant BPS_DENOMINATOR = LibOps.BPS_DENOMINATOR; /** * @dev The maximum affiliate fee BPS. */ uint16 public constant MAX_AFFILIATE_FEE_BPS = 1000; /** * @dev The maximum platform per-mint fee BPS. */ uint16 public constant MAX_PLATFORM_PER_MINT_FEE_BPS = 1000; /** * @dev The maximum per-mint reward. Applies to artists, affiliates, platform. */ uint96 public constant MAX_PER_MINT_REWARD = 0.1 ether; /** * @dev The maximum platform per-transaction flat fee. */ uint96 public constant MAX_PLATFORM_PER_TX_FLAT_FEE = 0.1 ether; /** * @dev The boolean flag on whether the mint has been created. */ uint8 internal constant _MINT_CREATED_FLAG = 1 << 0; /** * @dev The boolean flag on whether the mint is paused. */ uint8 internal constant _MINT_PAUSED_FLAG = 1 << 1; /** * @dev The boolean flag on whether the signer is the platform's signer. */ uint8 internal constant _USE_PLATFORM_SIGNER_FLAG = 1 << 2; /** * @dev The index for the per-platform default fee config. * We use 256, as the tier is uint8, which ranges from 0 to 255. */ uint16 internal constant _DEFAULT_FEE_CONFIG_INDEX = 256; // ============================================================= // STORAGE // ============================================================= /** * @dev A mapping of `platform` => `feesAccrued`. */ mapping(address => uint256) public platformFeesAccrued; /** * @dev A mapping of `platform` => `feeRecipient`. */ mapping(address => address) public platformFeeAddress; /** * @dev A mapping of `affiliate` => `feesAccrued`. */ mapping(address => uint256) public affiliateFeesAccrued; /** * @dev A mapping of `platform` => `price`. */ mapping(address => uint96) public gaPrice; /** * @dev A mapping of `platform` => `platformSigner`. */ mapping(address => address) public platformSigner; /** * @dev A mapping of `mintId` => `mintData`. */ mapping(uint256 => MintData) internal _mintData; /** * @dev A mapping of `platformTierId` => `platformFeeConfig`. */ mapping(uint256 => PlatformFeeConfig) internal _platformFeeConfigs; /** * @dev A mapping of `to` => `mintId` => `numberMinted`. */ mapping(address => LibMap.Uint32Map) internal _numberMinted; /** * @dev A mapping of `mintId` => `signedClaimedTicket` => `claimed`. */ mapping(uint256 => LibBitmap.Bitmap) internal _claimsBitmaps; // ============================================================= // PUBLIC / EXTERNAL WRITE FUNCTIONS // ============================================================= /** * @inheritdoc ISuperMinterV2 */ function createEditionMint(MintCreation memory c) public returns (uint8 scheduleNum) { _requireOnlyEditionOwnerOrAdmin(c.edition); _validateAffiliateFeeBPS(c.affiliateFeeBPS); uint8 mode = c.mode; if (mode == DEFAULT) { c.merkleRoot = bytes32(0); } else if (mode == VERIFY_MERKLE) { _validateMerkleRoot(c.merkleRoot); } else if (mode == VERIFY_SIGNATURE) { c.merkleRoot = bytes32(0); c.maxMintablePerAccount = type(uint32).max; } else if (mode == PLATFORM_AIRDROP) { c.merkleRoot = bytes32(0); c.maxMintablePerAccount = type(uint32).max; c.price = 0; // Platform airdrop mode doesn't have a price. } else { revert InvalidMode(); } // If GA, overwrite any immutable variables as required. if (c.tier == GA_TIER) { c.endTime = type(uint32).max; c.maxMintablePerAccount = type(uint32).max; // We allow the `price` to be the minimum price if the `mode` is `VERIFY_SIGNATURE`. // Otherwise, the actual default price is the live value of `gaPrice[platform]`, // and we'll simply set it to zero to avoid a SLOAD. if (mode != VERIFY_SIGNATURE) c.price = 0; // Set `maxMintable` to the maximum only if `mode` is `DEFAULT`. if (mode == DEFAULT) c.maxMintable = type(uint32).max; } _validateTimeRange(c.startTime, c.endTime); _validateMaxMintablePerAccount(c.maxMintablePerAccount); _validateMaxMintable(c.maxMintable); unchecked { MintData storage tierHead = _mintData[LibOps.packId(c.edition, c.tier, 0)]; MintData storage editionHead = _mintData[LibOps.packId(c.edition, 0)]; scheduleNum = tierHead.nextScheduleNum; uint256 n = scheduleNum; if (++n >= 1 << 8) LibOps.revertOverflow(); tierHead.nextScheduleNum = uint8(n); n = editionHead.numMintData; if (++n >= 1 << 16) LibOps.revertOverflow(); editionHead.numMintData = uint16(n); uint256 mintId = LibOps.packId(c.edition, c.tier, scheduleNum); MintData storage d = _mintData[mintId]; d.platform = c.platform; d.price = c.price; d.startTime = c.startTime; d.endTime = c.endTime; d.maxMintablePerAccount = c.maxMintablePerAccount; d.maxMintable = c.maxMintable; d.affiliateFeeBPS = c.affiliateFeeBPS; d.mode = c.mode; d.flags = _MINT_CREATED_FLAG; d.next = editionHead.head; editionHead.head = uint16((uint256(c.tier) << 8) | uint256(scheduleNum)); // Skip writing zeros, to avoid cold SSTOREs. if (c.affiliateMerkleRoot != bytes32(0)) d.affiliateMerkleRoot = c.affiliateMerkleRoot; if (c.merkleRoot != bytes32(0)) d.merkleRoot = c.merkleRoot; emit MintCreated(c.edition, c.tier, scheduleNum, c); } } /** * @inheritdoc ISuperMinterV2 */ function mintTo(MintTo calldata p) public payable returns (uint256 fromTokenId) { MintData storage d = _getMintData(LibOps.packId(p.edition, p.tier, p.scheduleNum)); /* ------------------- CHECKS AND UPDATES ------------------- */ _requireMintOpen(d); // Perform the sub workflows depending on the mint mode. uint8 mode = d.mode; if (mode == VERIFY_MERKLE) _verifyMerkle(d, p); else if (mode == VERIFY_SIGNATURE) _verifyAndClaimSignature(d, p); else if (mode == PLATFORM_AIRDROP) revert InvalidMode(); _incrementMinted(mode, d, p); /* ----------------- COMPUTE AND ACCRUE FEES ---------------- */ MintedLogData memory l; // Blocking same address self referral is left curved, but we do anyway. l.affiliate = p.to == p.affiliate ? address(0) : p.affiliate; // Affiliate check. l.affiliated = _isAffiliatedWithProof(d, l.affiliate, p.affiliateProof); TotalPriceAndFees memory f = _totalPriceAndFees(p.tier, d, p.quantity, p.signedPrice, l.affiliated); if (msg.value != f.total) revert WrongPayment(msg.value, f.total); // Require exact payment. l.finalArtistFee = f.finalArtistFee; l.finalPlatformFee = f.finalPlatformFee; l.finalAffiliateFee = f.finalAffiliateFee; // Platform and affilaite fees are accrued mappings. // Artist earnings are directly forwarded to the nft contract in mint call below. // Overflow not possible since all fees are uint96s. unchecked { if (l.finalAffiliateFee != 0) { affiliateFeesAccrued[p.affiliate] += l.finalAffiliateFee; } if (l.finalPlatformFee != 0) { platformFeesAccrued[d.platform] += l.finalPlatformFee; } } /* ------------------------- MINT --------------------------- */ ISoundEditionV2_1 edition = ISoundEditionV2_1(p.edition); l.quantity = p.quantity; l.fromTokenId = edition.mint{ value: l.finalArtistFee }(p.tier, p.to, p.quantity); l.allowlisted = p.allowlisted; l.allowlistedQuantity = p.allowlistedQuantity; l.signedClaimTicket = p.signedClaimTicket; l.requiredEtherValue = f.total; l.unitPrice = f.unitPrice; emit Minted(p.edition, p.tier, p.scheduleNum, p.to, l, p.attributionId); return l.fromTokenId; } /** * @inheritdoc ISuperMinterV2 */ function platformAirdrop(PlatformAirdrop calldata p) public returns (uint256 fromTokenId) { MintData storage d = _getMintData(LibOps.packId(p.edition, p.tier, p.scheduleNum)); /* ------------------- CHECKS AND UPDATES ------------------- */ _requireMintOpen(d); if (d.mode != PLATFORM_AIRDROP) revert InvalidMode(); _verifyAndClaimPlatfromAidropSignature(d, p); _incrementPlatformAirdropMinted(d, p); /* ------------------------- MINT --------------------------- */ ISoundEditionV2_1 edition = ISoundEditionV2_1(p.edition); fromTokenId = edition.airdrop(p.tier, p.to, p.signedQuantity); emit PlatformAirdropped(p.edition, p.tier, p.scheduleNum, p.to, p.signedQuantity, fromTokenId); } // Per edition mint parameter setters: // ----------------------------------- // These functions can only be called by the owner or admin of the edition. /** * @inheritdoc ISuperMinterV2 */ function setPrice( address edition, uint8 tier, uint8 scheduleNum, uint96 price ) public onlyEditionOwnerOrAdmin(edition) { uint256 mintId = LibOps.packId(edition, tier, scheduleNum); MintData storage d = _getMintData(mintId); // If the tier is GA and the `mode` is `VERIFY_SIGNATURE`, we'll use `gaPrice[platform]`. if (tier == GA_TIER && d.mode != VERIFY_SIGNATURE) revert NotConfigurable(); // Platform airdropped mints will not have a price. if (d.mode == PLATFORM_AIRDROP) revert NotConfigurable(); d.price = price; emit PriceSet(edition, tier, scheduleNum, price); } /** * @inheritdoc ISuperMinterV2 */ function setPaused( address edition, uint8 tier, uint8 scheduleNum, bool paused ) public onlyEditionOwnerOrAdmin(edition) { uint256 mintId = LibOps.packId(edition, tier, scheduleNum); MintData storage d = _getMintData(mintId); d.flags = LibOps.setFlagTo(d.flags, _MINT_PAUSED_FLAG, paused); emit PausedSet(edition, tier, scheduleNum, paused); } /** * @inheritdoc ISuperMinterV2 */ function setTimeRange( address edition, uint8 tier, uint8 scheduleNum, uint32 startTime, uint32 endTime ) public onlyEditionOwnerOrAdmin(edition) { uint256 mintId = LibOps.packId(edition, tier, scheduleNum); MintData storage d = _getMintData(mintId); // For GA tier, `endTime` will always be `type(uint32).max`. if (tier == GA_TIER && endTime != type(uint32).max) revert NotConfigurable(); _validateTimeRange(startTime, endTime); d.startTime = startTime; d.endTime = endTime; emit TimeRangeSet(edition, tier, scheduleNum, startTime, endTime); } /** * @inheritdoc ISuperMinterV2 */ function setStartTime( address edition, uint8 tier, uint8 scheduleNum, uint32 startTime ) public { uint256 mintId = LibOps.packId(edition, tier, scheduleNum); setTimeRange(edition, tier, scheduleNum, startTime, _mintData[mintId].endTime); } /** * @inheritdoc ISuperMinterV2 */ function setAffiliateFee( address edition, uint8 tier, uint8 scheduleNum, uint16 bps ) public onlyEditionOwnerOrAdmin(edition) { uint256 mintId = LibOps.packId(edition, tier, scheduleNum); MintData storage d = _getMintData(mintId); _validateAffiliateFeeBPS(bps); d.affiliateFeeBPS = bps; emit AffiliateFeeSet(edition, tier, scheduleNum, bps); } /** * @inheritdoc ISuperMinterV2 */ function setAffiliateMerkleRoot( address edition, uint8 tier, uint8 scheduleNum, bytes32 root ) public onlyEditionOwnerOrAdmin(edition) { uint256 mintId = LibOps.packId(edition, tier, scheduleNum); MintData storage d = _getMintData(mintId); d.affiliateMerkleRoot = root; emit AffiliateMerkleRootSet(edition, tier, scheduleNum, root); } /** * @inheritdoc ISuperMinterV2 */ function setMaxMintablePerAccount( address edition, uint8 tier, uint8 scheduleNum, uint32 value ) public onlyEditionOwnerOrAdmin(edition) { uint256 mintId = LibOps.packId(edition, tier, scheduleNum); MintData storage d = _getMintData(mintId); // GA tier will have `type(uint32).max`. if (tier == GA_TIER) revert NotConfigurable(); // Signature mints will have `type(uint32).max`. if (d.mode == VERIFY_SIGNATURE) revert NotConfigurable(); // Platform airdrops will have `type(uint32).max`. if (d.mode == PLATFORM_AIRDROP) revert NotConfigurable(); _validateMaxMintablePerAccount(value); d.maxMintablePerAccount = value; emit MaxMintablePerAccountSet(edition, tier, scheduleNum, value); } /** * @inheritdoc ISuperMinterV2 */ function setMaxMintable( address edition, uint8 tier, uint8 scheduleNum, uint32 value ) public onlyEditionOwnerOrAdmin(edition) { uint256 mintId = LibOps.packId(edition, tier, scheduleNum); MintData storage d = _getMintData(mintId); // We allow edits for GA tier, if the `mode` is not `DEFAULT`. if (tier == GA_TIER && d.mode == DEFAULT) revert NotConfigurable(); _validateMaxMintable(value); d.maxMintable = value; emit MaxMintableSet(edition, tier, scheduleNum, value); } /** * @inheritdoc ISuperMinterV2 */ function setMerkleRoot( address edition, uint8 tier, uint8 scheduleNum, bytes32 merkleRoot ) public onlyEditionOwnerOrAdmin(edition) { uint256 mintId = LibOps.packId(edition, tier, scheduleNum); MintData storage d = _getMintData(mintId); if (d.mode != VERIFY_MERKLE) revert NotConfigurable(); _validateMerkleRoot(merkleRoot); d.merkleRoot = merkleRoot; emit MerkleRootSet(edition, tier, scheduleNum, merkleRoot); } // Withdrawal functions: // --------------------- // These functions can be called by anyone. /** * @inheritdoc ISuperMinterV2 */ function withdrawForAffiliate(address affiliate) public { uint256 accrued = affiliateFeesAccrued[affiliate]; if (accrued != 0) { affiliateFeesAccrued[affiliate] = 0; SafeTransferLib.forceSafeTransferETH(affiliate, accrued); emit AffiliateFeesWithdrawn(affiliate, accrued); } } /** * @inheritdoc ISuperMinterV2 */ function withdrawForPlatform(address platform) public { address recipient = platformFeeAddress[platform]; _validatePlatformFeeAddress(recipient); uint256 accrued = platformFeesAccrued[platform]; if (accrued != 0) { platformFeesAccrued[platform] = 0; SafeTransferLib.forceSafeTransferETH(recipient, accrued); emit PlatformFeesWithdrawn(platform, accrued); } } // Platform fee functions: // ----------------------- // These functions enable any caller to set their own platform fees. /** * @inheritdoc ISuperMinterV2 */ function setPlatformFeeAddress(address recipient) public { address sender = LibMulticaller.senderOrSigner(); _validatePlatformFeeAddress(recipient); platformFeeAddress[sender] = recipient; emit PlatformFeeAddressSet(sender, recipient); } /** * @inheritdoc ISuperMinterV2 */ function setPlatformFeeConfig(uint8 tier, PlatformFeeConfig memory c) public { address sender = LibMulticaller.senderOrSigner(); _validatePlatformFeeConfig(c); _platformFeeConfigs[LibOps.packId(sender, tier)] = c; emit PlatformFeeConfigSet(sender, tier, c); } /** * @inheritdoc ISuperMinterV2 */ function setDefaultPlatformFeeConfig(PlatformFeeConfig memory c) public { address sender = LibMulticaller.senderOrSigner(); _validatePlatformFeeConfig(c); _platformFeeConfigs[LibOps.packId(sender, _DEFAULT_FEE_CONFIG_INDEX)] = c; emit DefaultPlatformFeeConfigSet(sender, c); } /** * @inheritdoc ISuperMinterV2 */ function setGAPrice(uint96 price) public { address sender = LibMulticaller.senderOrSigner(); gaPrice[sender] = price; emit GAPriceSet(sender, price); } /** * @inheritdoc ISuperMinterV2 */ function setPlatformSigner(address signer) public { address sender = LibMulticaller.senderOrSigner(); platformSigner[sender] = signer; emit PlatformSignerSet(sender, signer); } // Misc functions: // --------------- /** * @dev For calldata compression. */ fallback() external payable { LibZip.cdFallback(); } /** * @dev For calldata compression. */ receive() external payable { LibZip.cdFallback(); } // ============================================================= // PUBLIC / EXTERNAL VIEW FUNCTIONS // ============================================================= /** * @inheritdoc ISuperMinterV2 */ function computeMintToDigest(MintTo calldata p) public view returns (bytes32) { // prettier-ignore return _hashTypedData(keccak256(abi.encode( MINT_TO_TYPEHASH, p.edition, p.tier, p.scheduleNum, p.to, p.signedQuantity, p.signedClaimTicket, p.signedPrice, p.signedDeadline, p.affiliate ))); } /** * @inheritdoc ISuperMinterV2 */ function computePlatformAirdropDigest(PlatformAirdrop calldata p) public view returns (bytes32) { // prettier-ignore return _hashTypedData(keccak256(abi.encode( PLATFORM_AIRDROP_TYPEHASH, p.edition, p.tier, p.scheduleNum, keccak256(abi.encodePacked(p.to)), p.signedQuantity, p.signedClaimTicket, p.signedDeadline ))); } /** * @inheritdoc ISuperMinterV2 */ function totalPriceAndFees( address edition, uint8 tier, uint8 scheduleNum, uint32 quantity, bool hasValidAffiliate ) public view returns (TotalPriceAndFees memory) { return totalPriceAndFeesWithSignedPrice(edition, tier, scheduleNum, quantity, 0, hasValidAffiliate); } /** * @inheritdoc ISuperMinterV2 */ function totalPriceAndFeesWithSignedPrice( address edition, uint8 tier, uint8 scheduleNum, uint32 quantity, uint96 signedPrice, bool hasValidAffiliate ) public view returns (TotalPriceAndFees memory) { uint256 mintId = LibOps.packId(edition, tier, scheduleNum); return _totalPriceAndFees(tier, _getMintData(mintId), quantity, signedPrice, hasValidAffiliate); } /** * @inheritdoc ISuperMinterV2 */ function nextScheduleNum(address edition, uint8 tier) public view returns (uint8) { return _mintData[LibOps.packId(edition, tier, 0)].nextScheduleNum; } /** * @inheritdoc ISuperMinterV2 */ function numberMinted( address edition, uint8 tier, uint8 scheduleNum, address collector ) external view returns (uint32) { uint256 mintId = LibOps.packId(edition, tier, scheduleNum); return _numberMinted[collector].get(mintId); } /** * @inheritdoc ISuperMinterV2 */ function isAffiliatedWithProof( address edition, uint8 tier, uint8 scheduleNum, address affiliate, bytes32[] calldata affiliateProof ) public view virtual returns (bool) { uint256 mintId = LibOps.packId(edition, tier, scheduleNum); return _isAffiliatedWithProof(_getMintData(mintId), affiliate, affiliateProof); } /** * @inheritdoc ISuperMinterV2 */ function isAffiliated( address edition, uint8 tier, uint8 scheduleNum, address affiliate ) public view virtual returns (bool) { return isAffiliatedWithProof(edition, tier, scheduleNum, affiliate, MerkleProofLib.emptyProof()); } /** * @inheritdoc ISuperMinterV2 */ function checkClaimTickets( address edition, uint8 tier, uint8 scheduleNum, uint32[] calldata claimTickets ) public view returns (bool[] memory claimed) { uint256 mintId = LibOps.packId(edition, tier, scheduleNum); LibBitmap.Bitmap storage bitmap = _claimsBitmaps[mintId]; claimed = new bool[](claimTickets.length); unchecked { for (uint256 i; i != claimTickets.length; i++) { claimed[i] = bitmap.get(claimTickets[i]); } } } /** * @inheritdoc ISuperMinterV2 */ function platformFeeConfig(address platform, uint8 tier) public view returns (PlatformFeeConfig memory) { return _platformFeeConfigs[LibOps.packId(platform, tier)]; } /** * @inheritdoc ISuperMinterV2 */ function defaultPlatformFeeConfig(address platform) public view returns (PlatformFeeConfig memory) { return _platformFeeConfigs[LibOps.packId(platform, _DEFAULT_FEE_CONFIG_INDEX)]; } /** * @inheritdoc ISuperMinterV2 */ function effectivePlatformFeeConfig(address platform, uint8 tier) public view returns (PlatformFeeConfig memory) { PlatformFeeConfig memory c = _platformFeeConfigs[LibOps.packId(platform, tier)]; if (!c.active) c = _platformFeeConfigs[LibOps.packId(platform, _DEFAULT_FEE_CONFIG_INDEX)]; if (!c.active) delete c; // Set all values to zero. return c; } /** * @inheritdoc ISuperMinterV2 */ function mintInfoList(address edition) public view returns (MintInfo[] memory a) { unchecked { MintData storage editionHead = _mintData[LibOps.packId(edition, 0)]; uint256 n = editionHead.numMintData; // Linked-list length. uint16 p = editionHead.head; // Current linked-list pointer. a = new MintInfo[](n); // Traverse the linked-list and fill the array in reverse. // Front: earliest added mint schedule. Back: latest added mint schedule. while (n != 0) { MintData storage d = _mintData[LibOps.packId(edition, p)]; a[--n] = mintInfo(edition, uint8(p >> 8), uint8(p)); p = d.next; } } } /** * @inheritdoc ISuperMinterV2 */ function mintInfo( address edition, uint8 tier, uint8 scheduleNum ) public view returns (MintInfo memory info) { uint256 mintId = LibOps.packId(edition, tier, scheduleNum); MintData storage d = _getMintData(mintId); info.edition = edition; info.tier = tier; info.scheduleNum = scheduleNum; info.platform = d.platform; info.price = tier == GA_TIER && d.mode != VERIFY_SIGNATURE ? gaPrice[d.platform] : d.price; info.startTime = d.startTime; info.endTime = d.endTime; info.maxMintablePerAccount = d.maxMintablePerAccount; info.maxMintable = d.maxMintable; info.minted = d.minted; info.affiliateFeeBPS = d.affiliateFeeBPS; info.mode = d.mode; info.paused = _isPaused(d); info.affiliateMerkleRoot = d.affiliateMerkleRoot; info.merkleRoot = d.merkleRoot; info.signer = platformSigner[d.platform]; } /** * @inheritdoc ISuperMinterV2 */ function name() external pure returns (string memory name_) { (name_, ) = _domainNameAndVersion(); } /** * @inheritdoc ISuperMinterV2 */ function version() external pure returns (string memory version_) { (, version_) = _domainNameAndVersion(); } /** * @inheritdoc IERC165 */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return LibOps.or(interfaceId == type(ISuperMinterV2).interfaceId, interfaceId == this.supportsInterface.selector); } // ============================================================= // INTERNAL / PRIVATE HELPERS // ============================================================= // Validations: // ------------ /** * @dev Guards a function to make it callable only by the edition's owner or admin. * @param edition The edition address. */ modifier onlyEditionOwnerOrAdmin(address edition) { _requireOnlyEditionOwnerOrAdmin(edition); _; } /** * @dev Requires that the caller is the owner or admin of `edition`. * @param edition The edition address. */ function _requireOnlyEditionOwnerOrAdmin(address edition) internal view { address sender = LibMulticaller.senderOrSigner(); if (sender != OwnableRoles(edition).owner()) if (!OwnableRoles(edition).hasAnyRole(sender, LibOps.ADMIN_ROLE)) LibOps.revertUnauthorized(); } /** * @dev Validates that `startTime <= endTime`. * @param startTime The start time of the mint. * @param endTime The end time of the mint. */ function _validateTimeRange(uint32 startTime, uint32 endTime) internal pure { if (startTime > endTime) revert InvalidTimeRange(); } /** * @dev Validates that the max mintable amount per account is not zero. * @param value The max mintable amount. */ function _validateMaxMintablePerAccount(uint32 value) internal pure { if (value == 0) revert MaxMintablePerAccountIsZero(); } /** * @dev Validates that the max mintable per schedule. * @param value The max mintable amount. */ function _validateMaxMintable(uint32 value) internal pure { if (value == 0) revert MaxMintableIsZero(); } /** * @dev Validates that the Merkle root is not empty. * @param merkleRoot The Merkle root. */ function _validateMerkleRoot(bytes32 merkleRoot) internal pure { if (merkleRoot == bytes32(0)) revert MerkleRootIsEmpty(); } /** * @dev Validates that the affiliate fee BPS does not exceed the max threshold. * @param bps The affiliate fee BPS. */ function _validateAffiliateFeeBPS(uint16 bps) internal pure { if (bps > MAX_AFFILIATE_FEE_BPS) revert InvalidAffiliateFeeBPS(); } /** * @dev Validates the platform fee configuration. * @param c The platform fee configuration. */ function _validatePlatformFeeConfig(PlatformFeeConfig memory c) internal pure { if ( LibOps.or( LibOps.or( c.platformTxFlatFee > MAX_PLATFORM_PER_TX_FLAT_FEE, c.platformMintFeeBPS > MAX_PLATFORM_PER_MINT_FEE_BPS ), LibOps.or( c.artistMintReward > MAX_PER_MINT_REWARD, c.affiliateMintReward > MAX_PER_MINT_REWARD, c.platformMintReward > MAX_PER_MINT_REWARD ), LibOps.or( c.thresholdArtistMintReward > MAX_PER_MINT_REWARD, c.thresholdAffiliateMintReward > MAX_PER_MINT_REWARD, c.thresholdPlatformMintReward > MAX_PER_MINT_REWARD ) ) ) revert InvalidPlatformFeeConfig(); } /** * @dev Validates that the platform fee address is not the zero address. * @param a The platform fee address. */ function _validatePlatformFeeAddress(address a) internal pure { if (a == address(0)) revert PlatformFeeAddressIsZero(); } // EIP-712: // -------- /** * @dev Override for EIP-712. * @return name_ The EIP-712 name. * @return version_ The EIP-712 version. */ function _domainNameAndVersion() internal pure virtual override returns (string memory name_, string memory version_) { name_ = "SuperMinter"; version_ = "1_1"; } // Minting: // -------- /** * @dev Increments the number minted in the mint and the number minted by the collector. * @param mode The mint mode. * @param d The mint data storage pointer. * @param p The mint-to parameters. */ function _incrementMinted( uint8 mode, MintData storage d, MintTo calldata p ) internal { unchecked { // Increment the number minted in the mint. uint256 n = uint256(d.minted) + uint256(p.quantity); // The next `minted`. if (n > d.maxMintable) revert ExceedsMintSupply(); d.minted = uint32(n); // Increment the number minted by the collector. uint256 mintId = LibOps.packId(p.edition, p.tier, p.scheduleNum); if (mode == VERIFY_MERKLE) { LibMap.Uint32Map storage m = _numberMinted[p.allowlisted]; n = uint256(m.get(mintId)) + uint256(p.quantity); // Check that `n` does not exceed either the default limit, // or the limit in the Merkle leaf if a non-zero value is provided. if (LibOps.or(n > d.maxMintablePerAccount, n > p.allowlistedQuantity)) revert ExceedsMaxPerAccount(); m.set(mintId, uint32(n)); } else { LibMap.Uint32Map storage m = _numberMinted[p.to]; n = uint256(m.get(mintId)) + uint256(p.quantity); if (n > d.maxMintablePerAccount) revert ExceedsMaxPerAccount(); m.set(mintId, uint32(n)); } } } /** * @dev Increments the number minted in the mint and the number minted by the collector. * @param d The mint data storage pointer. * @param p The platform airdrop parameters. */ function _incrementPlatformAirdropMinted(MintData storage d, PlatformAirdrop calldata p) internal { unchecked { uint256 mintId = LibOps.packId(p.edition, p.tier, p.scheduleNum); uint256 toLength = p.to.length; // Increment the number minted in the mint. uint256 n = uint256(d.minted) + toLength * uint256(p.signedQuantity); // The next `minted`. if (n > d.maxMintable) revert ExceedsMintSupply(); d.minted = uint32(n); // Increment the number minted by the collectors. for (uint256 i; i != toLength; ++i) { LibMap.Uint32Map storage m = _numberMinted[p.to[i]]; m.set(mintId, uint32(uint256(m.get(mintId)) + uint256(p.signedQuantity))); } } } /** * @dev Requires that the mint is open and not paused. * @param d The mint data storage pointer. */ function _requireMintOpen(MintData storage d) internal view { if (LibOps.or(block.timestamp < d.startTime, block.timestamp > d.endTime)) revert MintNotOpen(block.timestamp, d.startTime, d.endTime); if (_isPaused(d)) revert MintPaused(); // Check if the mint is not paused. } /** * @dev Verify the signature, and mark the signed claim ticket as claimed. * @param d The mint data storage pointer. * @param p The mint-to parameters. */ function _verifyAndClaimSignature(MintData storage d, MintTo calldata p) internal { if (p.quantity > p.signedQuantity) revert ExceedsSignedQuantity(); address signer = platformSigner[d.platform]; if (!SignatureCheckerLib.isValidSignatureNowCalldata(signer, computeMintToDigest(p), p.signature)) revert InvalidSignature(); if (block.timestamp > p.signedDeadline) revert SignatureExpired(); uint256 mintId = LibOps.packId(p.edition, p.tier, p.scheduleNum); if (!_claimsBitmaps[mintId].toggle(p.signedClaimTicket)) revert SignatureAlreadyUsed(); } /** * @dev Verify the platform airdrop signature, and mark the signed claim ticket as claimed. * @param d The mint data storage pointer. * @param p The platform airdrop parameters. */ function _verifyAndClaimPlatfromAidropSignature(MintData storage d, PlatformAirdrop calldata p) internal { // Unlike regular signature mints, platform airdrops only use `signedQuantity`. address signer = platformSigner[d.platform]; if (!SignatureCheckerLib.isValidSignatureNowCalldata(signer, computePlatformAirdropDigest(p), p.signature)) revert InvalidSignature(); if (block.timestamp > p.signedDeadline) revert SignatureExpired(); uint256 mintId = LibOps.packId(p.edition, p.tier, p.scheduleNum); if (!_claimsBitmaps[mintId].toggle(p.signedClaimTicket)) revert SignatureAlreadyUsed(); } /** * @dev Verify the Merkle proof. * @param d The mint data storage pointer. * @param p The mint-to parameters. */ function _verifyMerkle(MintData storage d, MintTo calldata p) internal view { uint32 allowlistedQuantity = p.allowlistedQuantity; address allowlisted = p.allowlisted; // Revert if `allowlisted` is the zero address to prevent libraries // that fill up partial Merkle trees with empty leafs from screwing things up. if (allowlisted == address(0)) revert InvalidMerkleProof(); // If `allowlistedQuantity` is the max limit, we've got to check two cases for backwards compatibility. if (allowlistedQuantity == type(uint32).max) { // Revert if neither `keccak256(abi.encodePacked(allowlisted))` nor // `keccak256(abi.encodePacked(allowlisted, uint32(0)))` are in the Merkle tree. if ( !p.allowlistProof.verifyCalldata(d.merkleRoot, _leaf(allowlisted)) && !p.allowlistProof.verifyCalldata(d.merkleRoot, _leaf(allowlisted, type(uint32).max)) ) revert InvalidMerkleProof(); } else { // Revert if `keccak256(abi.encodePacked(allowlisted, uint32(allowlistedQuantity)))` // is not in the Merkle tree. if (!p.allowlistProof.verifyCalldata(d.merkleRoot, _leaf(allowlisted, allowlistedQuantity))) revert InvalidMerkleProof(); } // To mint, either the sender or `to` must be equal to `allowlisted`, address sender = LibMulticaller.senderOrSigner(); if (!LibOps.or(sender == allowlisted, p.to == allowlisted)) { // or the sender must be a delegate of `allowlisted`. if (!DelegateCashLib.checkDelegateForAll(sender, allowlisted)) revert CallerNotDelegated(); } } /** * @dev Returns the total price and fees for the mint. * @param tier The tier. * @param d The mint data storage pointer. * @param quantity How many tokens to mint. * @param signedPrice The signed price. Only for `VERIFY_SIGNATURE`. * @return f A struct containing the total price and fees. */ function _totalPriceAndFees( uint8 tier, MintData storage d, uint32 quantity, uint96 signedPrice, bool hasValidAffiliate ) internal view returns (TotalPriceAndFees memory f) { // All flat prices are stored as uint96s in storage. // The quantity is a uint32. Multiplications between a uint96 and uint32 won't overflow. unchecked { PlatformFeeConfig memory c = effectivePlatformFeeConfig(d.platform, tier); // For signature mints, even if it is GA tier, we will use the signed price. if (d.mode == VERIFY_SIGNATURE) { if (signedPrice < d.price) revert SignedPriceTooLow(); // Enforce the price floor. f.unitPrice = signedPrice; } else if (tier == GA_TIER) { f.unitPrice = gaPrice[d.platform]; // Else if GA tier, use `gaPrice[platform]`. } else { f.unitPrice = d.price; // Else, use the `price`. } // The total price before any additive fees. f.subTotal = f.unitPrice * uint256(quantity); // Artist earns `subTotal` minus any basis points (BPS) split with affiliates and platform f.finalArtistFee = f.subTotal; // `affiliateBPSFee` is deducted from the `finalArtistFee`. if (d.affiliateFeeBPS != 0 && hasValidAffiliate) { uint256 affiliateBPSFee = LibOps.rawMulDiv(f.subTotal, d.affiliateFeeBPS, BPS_DENOMINATOR); f.finalArtistFee -= affiliateBPSFee; f.finalAffiliateFee = affiliateBPSFee; } // `platformBPSFee` is deducted from the `finalArtistFee`. if (c.platformMintFeeBPS != 0) { uint256 platformBPSFee = LibOps.rawMulDiv(f.subTotal, c.platformMintFeeBPS, BPS_DENOMINATOR); f.finalArtistFee -= platformBPSFee; f.finalPlatformFee = platformBPSFee; } // Protocol rewards are additive to `unitPrice` and paid by the buyer. // There are 2 sets of rewards, one for prices below `thresholdPrice` and one for prices above. if (f.unitPrice <= c.thresholdPrice) { f.finalArtistFee += c.artistMintReward * uint256(quantity); f.finalPlatformFee += c.platformMintReward * uint256(quantity); // The platform is the affiliate if no affiliate is provided. if (hasValidAffiliate) { f.finalAffiliateFee += c.affiliateMintReward * uint256(quantity); } else { f.finalPlatformFee += c.affiliateMintReward * uint256(quantity); } } else { f.finalArtistFee += c.thresholdArtistMintReward * uint256(quantity); f.finalPlatformFee += c.thresholdPlatformMintReward * uint256(quantity); // The platform is the affiliate if no affiliate is provided if (hasValidAffiliate) { f.finalAffiliateFee += c.thresholdAffiliateMintReward * uint256(quantity); } else { f.finalPlatformFee += c.thresholdAffiliateMintReward * uint256(quantity); } } // Per-transaction flat fee. f.finalPlatformFee += c.platformTxFlatFee; // The total is the final value which the minter has to pay. It includes all fees. f.total = f.finalArtistFee + f.finalAffiliateFee + f.finalPlatformFee; } } /** * @dev Returns whether the affiliate is affiliated for the mint * @param d The mint data storage pointer. * @param affiliate The affiliate address. * @param affiliateProof The Merkle proof for the affiliate. * @return The result. */ function _isAffiliatedWithProof( MintData storage d, address affiliate, bytes32[] calldata affiliateProof ) internal view virtual returns (bool) { bytes32 root = d.affiliateMerkleRoot; // If the root is empty, then use the default logic. if (root == bytes32(0)) return affiliate != address(0); // Otherwise, check if the affiliate is in the Merkle tree. // The check that that affiliate is not a zero address is to prevent libraries // that fill up partial Merkle trees with empty leafs from screwing things up. return LibOps.and(affiliate != address(0), affiliateProof.verifyCalldata(root, _leaf(affiliate))); } // Utilities: // ---------- /** * @dev Equivalent to `keccak256(abi.encodePacked(allowlisted))`. * @param allowlisted The allowlisted address. * @return result The leaf in the Merkle tree. */ function _leaf(address allowlisted) internal pure returns (bytes32 result) { assembly { mstore(0x00, allowlisted) result := keccak256(0x0c, 0x14) } } /** * @dev Equivalent to `keccak256(abi.encodePacked(allowlisted, allowlistedQuantity))`. * @param allowlisted The allowlisted address. * @param allowlistedQuantity Number of mints allowlisted. * @return result The leaf in the Merkle tree. */ function _leaf(address allowlisted, uint32 allowlistedQuantity) internal pure returns (bytes32 result) { assembly { mstore(0x04, allowlistedQuantity) mstore(0x00, allowlisted) result := keccak256(0x0c, 0x18) } } /** * @dev Retrieves the mint data from storage, reverting if the mint does not exist. * @param mintId The mint ID. * @return d The storage pointer to the mint data. */ function _getMintData(uint256 mintId) internal view returns (MintData storage d) { d = _mintData[mintId]; if (d.flags & _MINT_CREATED_FLAG == 0) revert MintDoesNotExist(); } /** * @dev Returns whether the mint is paused. * @param d The storage pointer to the mint data. * @return Whether the mint is paused. */ function _isPaused(MintData storage d) internal view returns (bool) { return d.flags & _MINT_PAUSED_FLAG != 0; } }
// 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.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. * @param fromTierTokenIdIndex The first token index in the tier. */ event Minted(uint8 tier, address to, uint256 quantity, uint256 fromTokenId, uint32 fromTierTokenIdIndex); /** * @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`. * @param fromTierTokenIdIndex The first token index in the tier. */ event Airdropped(uint8 tier, address[] to, uint256 quantity, uint256 fromTokenId, uint32 fromTierTokenIdIndex); /** * @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); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; import { IERC165 } from "openzeppelin/utils/introspection/IERC165.sol"; /** * @title ISuperMinterV2 * @notice The interface for the generalized minter. */ interface ISuperMinterV2 is IERC165 { // ============================================================= // STRUCTS // ============================================================= /** * @dev A struct containing the arguments to create a mint. */ struct MintCreation { // The edition address. address edition; // The base price per token. // For `VERIFY_SIGNATURE`, this will be the minimum limit of the signed price. // Will be 0 if the `tier` is `GA_TIER`. uint96 price; // The start time of the mint. uint32 startTime; // The end time of the mint. uint32 endTime; // The maximum number of tokens an account can mint in this mint. uint32 maxMintablePerAccount; // The maximum number of tokens mintable. uint32 maxMintable; // The affiliate fee BPS. uint16 affiliateFeeBPS; // The affiliate Merkle root, if any. bytes32 affiliateMerkleRoot; // The tier of the mint. uint8 tier; // The address of the platform. address platform; // The mode of the mint. Options: `DEFAULT`, `VERIFY_MERKLE`, `VERIFY_SIGNATURE`. uint8 mode; // The Merkle root hash, required if `mode` is `VERIFY_MERKLE`. bytes32 merkleRoot; } /** * @dev A struct containing the arguments for mint-to. */ struct MintTo { // The mint ID. address edition; // The tier of the mint. uint8 tier; // The edition-tier schedule number. uint8 scheduleNum; // The address to mint to. address to; // The number of tokens to mint. uint32 quantity; // The allowlisted address. Used if `mode` is `VERIFY_MERKLE`. address allowlisted; // The allowlisted quantity. Used if `mode` is `VERIFY_MERKLE`. // A default zero value means no limit. uint32 allowlistedQuantity; // The allowlist Merkle proof. bytes32[] allowlistProof; // The signed price. Used if `mode` is `VERIFY_SIGNATURE`. uint96 signedPrice; // The signed quantity. Used if `mode` is `VERIFY_SIGNATURE`. uint32 signedQuantity; // The signed claimed ticket. Used if `mode` is `VERIFY_SIGNATURE`. uint32 signedClaimTicket; // The expiry timestamp for the signature. Used if `mode` is `VERIFY_SIGNATURE`. uint32 signedDeadline; // The signature by the signer. Used if `mode` is `VERIFY_SIGNATURE`. bytes signature; // The affiliate address. Optional. address affiliate; // The Merkle proof for the affiliate. bytes32[] affiliateProof; // The attribution ID, optional. uint256 attributionId; } /** * @dev A struct containing the arguments for platformAirdrop. */ struct PlatformAirdrop { // The mint ID. address edition; // The tier of the mint. uint8 tier; // The edition-tier schedule number. uint8 scheduleNum; // The addresses to mint to. address[] to; // The signed quantity. uint32 signedQuantity; // The signed claimed ticket. Used if `mode` is `VERIFY_SIGNATURE`. uint32 signedClaimTicket; // The expiry timestamp for the signature. Used if `mode` is `VERIFY_SIGNATURE`. uint32 signedDeadline; // The signature by the signer. Used if `mode` is `VERIFY_SIGNATURE`. bytes signature; } /** * @dev A struct containing the total prices and fees. */ struct TotalPriceAndFees { // The required Ether value. // (`subTotal + platformTxFlatFee + artistReward + affiliateReward + platformReward`). uint256 total; // The total price before any additive fees. uint256 subTotal; // The price per token. uint256 unitPrice; // The final artist fee (inclusive of `finalArtistReward`). uint256 finalArtistFee; // The total affiliate fee (inclusive of `finalAffiliateReward`). uint256 finalAffiliateFee; // The final platform fee // (inclusive of `finalPlatformReward`, `perTxFlat`, sum of `perMintBPS`). uint256 finalPlatformFee; } /** * @dev A struct containing the log data for the `Minted` event. */ struct MintedLogData { // The number of tokens minted. uint32 quantity; // The starting token ID minted. uint256 fromTokenId; // The allowlisted address. address allowlisted; // The allowlisted quantity. uint32 allowlistedQuantity; // The signed quantity. uint32 signedQuantity; // The signed claim ticket. uint32 signedClaimTicket; // The affiliate address. address affiliate; // Whether the affiliate address is affiliated. bool affiliated; // The total price paid, inclusive of all fees. uint256 requiredEtherValue; // The price per token. uint256 unitPrice; // The final artist fee (inclusive of `finalArtistReward`). uint256 finalArtistFee; // The total affiliate fee (inclusive of `finalAffiliateReward`). uint256 finalAffiliateFee; // The final platform fee // (inclusive of `finalPlatformReward`, `perTxFlat`, sum of `perMintBPS`). uint256 finalPlatformFee; } /** * @dev A struct to hold the fee configuration for a platform and a tier. */ struct PlatformFeeConfig { // The amount of reward to give to the artist per mint. uint96 artistMintReward; // The amount of reward to give to the affiliate per mint. uint96 affiliateMintReward; // The amount of reward to give to the platform per mint. uint96 platformMintReward; // If the price is greater than this, the rewards will become the threshold variants. uint96 thresholdPrice; // The amount of reward to give to the artist (`unitPrice >= thresholdPrice`). uint96 thresholdArtistMintReward; // The amount of reward to give to the affiliate (`unitPrice >= thresholdPrice`). uint96 thresholdAffiliateMintReward; // The amount of reward to give to the platform (`unitPrice >= thresholdPrice`). uint96 thresholdPlatformMintReward; // The per-transaction flat fee. uint96 platformTxFlatFee; // The per-token fee BPS. uint16 platformMintFeeBPS; // Whether the fees are active. bool active; } /** * @dev A struct containing the mint information. */ struct MintInfo { // The mint ID. address edition; // The tier of the mint. uint8 tier; // The edition-tier schedule number. uint8 scheduleNum; // The platform address. address platform; // The base price per token. // For `VERIFY_SIGNATURE` this will be the minimum limit of the signed price. // If the `tier` is `GA_TIER`, and the `mode` is NOT `VERIFY_SIGNATURE`, // this value will be the GA price instead. uint96 price; // The start time of the mint. uint32 startTime; // The end time of the mint. uint32 endTime; // The maximum number of tokens an account can mint in this mint. uint32 maxMintablePerAccount; // The maximum number of tokens mintable. uint32 maxMintable; // The total number of tokens minted. uint32 minted; // The affiliate fee BPS. uint16 affiliateFeeBPS; // The mode of the mint. uint8 mode; // Whether the mint is paused. bool paused; // Whether the mint already has mints. bool hasMints; // The affiliate Merkle root, if any. bytes32 affiliateMerkleRoot; // The Merkle root hash, required if `mode` is `VERIFY_MERKLE`. bytes32 merkleRoot; // The signer address, used if `mode` is `VERIFY_SIGNATURE` or `PLATFORM_AIRDROP`. address signer; } // ============================================================= // EVENTS // ============================================================= /** * @dev Emitted when a new mint is created. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param creation The mint creation struct. */ event MintCreated(address indexed edition, uint8 tier, uint8 scheduleNum, MintCreation creation); /** * @dev Emitted when a mint is paused or un-paused. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param paused Whether the mint is paused. */ event PausedSet(address indexed edition, uint8 tier, uint8 scheduleNum, bool paused); /** * @dev Emitted when the time range of a mint is updated. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param startTime The start time. * @param endTime The end time. */ event TimeRangeSet(address indexed edition, uint8 tier, uint8 scheduleNum, uint32 startTime, uint32 endTime); /** * @dev Emitted when the base per-token price of a mint is updated. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param price The base per-token price. */ event PriceSet(address indexed edition, uint8 tier, uint8 scheduleNum, uint96 price); /** * @dev Emitted when the max mintable per account for a mint is updated. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param value The max mintable per account. */ event MaxMintablePerAccountSet(address indexed edition, uint8 tier, uint8 scheduleNum, uint32 value); /** * @dev Emitted when the max mintable for a mint is updated. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param value The max mintable for the mint. */ event MaxMintableSet(address indexed edition, uint8 tier, uint8 scheduleNum, uint32 value); /** * @dev Emitted when the Merkle root of a mint is updated. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param merkleRoot The Merkle root of the mint. */ event MerkleRootSet(address indexed edition, uint8 tier, uint8 scheduleNum, bytes32 merkleRoot); /** * @dev Emitted when the affiliate fee BPS for a mint is updated. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param bps The affiliate fee BPS. */ event AffiliateFeeSet(address indexed edition, uint8 tier, uint8 scheduleNum, uint16 bps); /** * @dev Emitted when the affiliate Merkle root for a mint is updated. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param root The affiliate Merkle root hash. */ event AffiliateMerkleRootSet(address indexed edition, uint8 tier, uint8 scheduleNum, bytes32 root); /** * @dev Emitted when tokens are minted. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param to The recipient of the tokens minted. * @param data The mint-to log data. * @param attributionId The optional attribution ID. */ event Minted( address indexed edition, uint8 tier, uint8 scheduleNum, address indexed to, MintedLogData data, uint256 indexed attributionId ); /** * @dev Emitted when tokens are platform airdropped. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param to The recipients of the tokens minted. * @param signedQuantity The amount of tokens per address. * @param fromTokenId The first token ID minted. */ event PlatformAirdropped( address indexed edition, uint8 tier, uint8 scheduleNum, address[] to, uint32 signedQuantity, uint256 fromTokenId ); /** * @dev Emitted when the platform fee configuration for `tier` is updated. * @param platform The platform address. * @param tier The tier of the mint. * @param config The platform fee configuration. */ event PlatformFeeConfigSet(address indexed platform, uint8 tier, PlatformFeeConfig config); /** * @dev Emitted when the default platform fee configuration is updated. * @param platform The platform address. * @param config The platform fee configuration. */ event DefaultPlatformFeeConfigSet(address indexed platform, PlatformFeeConfig config); /** * @dev Emitted when affiliate fees are withdrawn. * @param affiliate The recipient of the fees. * @param accrued The amount of Ether accrued and withdrawn. */ event AffiliateFeesWithdrawn(address indexed affiliate, uint256 accrued); /** * @dev Emitted when platform fees are withdrawn. * @param platform The platform address. * @param accrued The amount of Ether accrued and withdrawn. */ event PlatformFeesWithdrawn(address indexed platform, uint256 accrued); /** * @dev Emitted when the platform fee recipient address is updated. * @param platform The platform address. * @param recipient The platform fee recipient address. */ event PlatformFeeAddressSet(address indexed platform, address recipient); /** * @dev Emitted when the per-token price for the GA tier is set. * @param platform The platform address. * @param price The price per token for the GA tier. */ event GAPriceSet(address indexed platform, uint96 price); /** * @dev Emitted when the signer for a platform is set. * @param platform The platform address. * @param signer The signer for the platform. */ event PlatformSignerSet(address indexed platform, address signer); // ============================================================= // ERRORS // ============================================================= /** * @dev Exact payment required. * @param paid The amount of Ether paid. * @param required The amount of Ether required. */ error WrongPayment(uint256 paid, uint256 required); /** * @dev The mint is not opened. * @param blockTimestamp The current block timestamp. * @param startTime The opening time of the mint. * @param endTime The closing time of the mint. */ error MintNotOpen(uint256 blockTimestamp, uint32 startTime, uint32 endTime); /** * @dev The mint is paused. */ error MintPaused(); /** * @dev Cannot perform the operation when any mints exist. */ error MintsAlreadyExist(); /** * @dev The time range is invalid. */ error InvalidTimeRange(); /** * @dev The max mintable range is invalid. */ error InvalidMaxMintableRange(); /** * @dev The affiliate fee BPS cannot exceed the limit. */ error InvalidAffiliateFeeBPS(); /** * @dev The affiliate fee BPS cannot exceed the limit. */ error InvalidPlatformFeeBPS(); /** * @dev The affiliate fee BPS cannot exceed the limit. */ error InvalidPlatformFlatFee(); /** * @dev Cannot mint more than the maximum limit per account. */ error ExceedsMaxPerAccount(); /** * @dev Cannot mint more than the maximum supply. */ error ExceedsMintSupply(); /** * @dev Cannot mint more than the signed quantity. */ error ExceedsSignedQuantity(); /** * @dev The signature is invalid. */ error InvalidSignature(); /** * @dev The signature has expired. */ error SignatureExpired(); /** * @dev The signature claim ticket has already been used. */ error SignatureAlreadyUsed(); /** * @dev The Merkle root cannot be empty. */ error MerkleRootIsEmpty(); /** * @dev The Merkle proof is invalid. */ error InvalidMerkleProof(); /** * @dev The caller has not been delegated via delegate cash. */ error CallerNotDelegated(); /** * @dev The max mintable amount per account cannot be zero. */ error MaxMintablePerAccountIsZero(); /** * @dev The max mintable value cannot be zero. */ error MaxMintableIsZero(); /** * @dev The plaform fee address cannot be the zero address. */ error PlatformFeeAddressIsZero(); /** * @dev The mint does not exist. */ error MintDoesNotExist(); /** * @dev The affiliate provided is invalid. */ error InvalidAffiliate(); /** * @dev The mint mode provided is invalid. */ error InvalidMode(); /** * @dev The signed price is too low. */ error SignedPriceTooLow(); /** * @dev The platform fee configuration provided is invalid. */ error InvalidPlatformFeeConfig(); /** * @dev The parameter cannot be configured. */ error NotConfigurable(); // ============================================================= // PUBLIC / EXTERNAL WRITE FUNCTIONS // ============================================================= /** * @dev Creates a mint. * @param c The mint creation struct. * @return scheduleNum The mint ID. */ function createEditionMint(MintCreation calldata c) external returns (uint8 scheduleNum); /** * @dev Performs a mint. * @param p The mint-to parameters. * @return fromTokenId The first token ID minted. */ function mintTo(MintTo calldata p) external payable returns (uint256 fromTokenId); /** * @dev Performs a platform airdrop. * @param p The platform airdrop parameters. * @return fromTokenId The first token ID minted. */ function platformAirdrop(PlatformAirdrop calldata p) external returns (uint256 fromTokenId); /** * @dev Sets the price of the mint. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param price The price per token. */ function setPrice( address edition, uint8 tier, uint8 scheduleNum, uint96 price ) external; /** * @dev Pause or unpase the the mint. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param paused Whether to pause the mint. */ function setPaused( address edition, uint8 tier, uint8 scheduleNum, bool paused ) external; /** * @dev Sets the time range for the the mint. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param startTime The mint start time. * @param endTime The mint end time. */ function setTimeRange( address edition, uint8 tier, uint8 scheduleNum, uint32 startTime, uint32 endTime ) external; /** * @dev Sets the start time for the the mint. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param startTime The mint start time. */ function setStartTime( address edition, uint8 tier, uint8 scheduleNum, uint32 startTime ) external; /** * @dev Sets the affiliate fee BPS for the mint. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param bps The fee BPS. */ function setAffiliateFee( address edition, uint8 tier, uint8 scheduleNum, uint16 bps ) external; /** * @dev Sets the affiliate Merkle root for the mint. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param root The affiliate Merkle root. */ function setAffiliateMerkleRoot( address edition, uint8 tier, uint8 scheduleNum, bytes32 root ) external; /** * @dev Sets the max mintable per account. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param value The max mintable per account. */ function setMaxMintablePerAccount( address edition, uint8 tier, uint8 scheduleNum, uint32 value ) external; /** * @dev Sets the max mintable for the mint. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param value The max mintable for the mint. */ function setMaxMintable( address edition, uint8 tier, uint8 scheduleNum, uint32 value ) external; /** * @dev Sets the mode for the mint. The mint mode must be `VERIFY_MERKLE`. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param merkleRoot The Merkle root of the mint. */ function setMerkleRoot( address edition, uint8 tier, uint8 scheduleNum, bytes32 merkleRoot ) external; /** * @dev Withdraws all accrued fees of the affiliate, to the affiliate. * @param affiliate The affiliate address. */ function withdrawForAffiliate(address affiliate) external; /** * @dev Withdraws all accrued fees of the platform, to the their fee address. * @param platform The platform address. */ function withdrawForPlatform(address platform) external; /** * @dev Allows the caller, as a platform, to set their fee address * @param recipient The platform fee address of the caller. */ function setPlatformFeeAddress(address recipient) external; /** * @dev Allows the caller, as a platform, to set their per-tier fee configuration. * @param tier The tier of the mint. * @param c The platform fee configuration struct. */ function setPlatformFeeConfig(uint8 tier, PlatformFeeConfig memory c) external; /** * @dev Allows the caller, as a platform, to set their default fee configuration. * @param c The platform fee configuration struct. */ function setDefaultPlatformFeeConfig(PlatformFeeConfig memory c) external; /** * @dev Allows the platform to set the price for the GA tier. * @param price The price per token for the GA tier. */ function setGAPrice(uint96 price) external; /** * @dev Allows the platform to set their signer. * @param signer The signer for the platform. */ function setPlatformSigner(address signer) external; // ============================================================= // PUBLIC / EXTERNAL VIEW FUNCTIONS // ============================================================= /** * @dev Returns the GA tier. Which is 0. * @return The constant value. */ function GA_TIER() external pure returns (uint8); /** * @dev The EIP-712 typehash for signed mints. * @return The constant value. */ function MINT_TO_TYPEHASH() external pure returns (bytes32); /** * @dev The EIP-712 typehash for platform airdrop mints. * @return The constant value. */ function PLATFORM_AIRDROP_TYPEHASH() external pure returns (bytes32); /** * @dev The default mint mode. * @return The constant value. */ function DEFAULT() external pure returns (uint8); /** * @dev The mint mode for Merkle drops. * @return The constant value. */ function VERIFY_MERKLE() external pure returns (uint8); /** * @dev The mint mode for Merkle drops. * @return The constant value. */ function VERIFY_SIGNATURE() external pure returns (uint8); /** * @dev The mint mode for platform airdrop. * @return The constant value. */ function PLATFORM_AIRDROP() external pure returns (uint8); /** * @dev The denominator used in BPS fee calculations. * @return The constant value. */ function BPS_DENOMINATOR() external pure returns (uint16); /** * @dev The maximum affiliate fee BPS. * @return The constant value. */ function MAX_AFFILIATE_FEE_BPS() external pure returns (uint16); /** * @dev The maximum per-mint platform fee BPS. * @return The constant value. */ function MAX_PLATFORM_PER_MINT_FEE_BPS() external pure returns (uint16); /** * @dev The maximum per-mint reward. Applies to artists, affiliates, platform. * @return The constant value. */ function MAX_PER_MINT_REWARD() external pure returns (uint96); /** * @dev The maximum platform per-transaction flat fee. * @return The constant value. */ function MAX_PLATFORM_PER_TX_FLAT_FEE() external pure returns (uint96); /** * @dev Returns the amount of fees accrued by the platform. * @param platform The platform address. * @return The latest value. */ function platformFeesAccrued(address platform) external view returns (uint256); /** * @dev Returns the fee recipient for the platform. * @param platform The platform address. * @return The configured value. */ function platformFeeAddress(address platform) external view returns (address); /** * @dev Returns the amount of fees accrued by the affiliate. * @param affiliate The affiliate address. * @return The latest value. */ function affiliateFeesAccrued(address affiliate) external view returns (uint256); /** * @dev Returns the EIP-712 digest of the mint-to data for signature mints. * @param p The mint-to parameters. * @return The computed value. */ function computeMintToDigest(MintTo calldata p) external view returns (bytes32); /** * @dev Returns the EIP-712 digest of the mint-to data for platform airdrops. * @param p The platform airdrop parameters. * @return The computed value. */ function computePlatformAirdropDigest(PlatformAirdrop calldata p) external view returns (bytes32); /** * @dev Returns the total price and fees for the mint. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param quantity How many tokens to mint. * @param hasValidAffiliate Whether there is a valid affiliate for the mint. * @return A struct containing the total price and fees. */ function totalPriceAndFees( address edition, uint8 tier, uint8 scheduleNum, uint32 quantity, bool hasValidAffiliate ) external view returns (TotalPriceAndFees memory); /** * @dev Returns the total price and fees for the mint. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param quantity How many tokens to mint. * @param signedPrice The signed price. * @param hasValidAffiliate Whether there is a valid affiliate for the mint. * @return A struct containing the total price and fees. */ function totalPriceAndFeesWithSignedPrice( address edition, uint8 tier, uint8 scheduleNum, uint32 quantity, uint96 signedPrice, bool hasValidAffiliate ) external view returns (TotalPriceAndFees memory); /** * @dev Returns the GA price for the platform. * @param platform The platform address. * @return The configured value. */ function gaPrice(address platform) external view returns (uint96); /** * @dev Returns the signer for the platform. * @param platform The platform address. * @return The configured value. */ function platformSigner(address platform) external view returns (address); /** * @dev Returns the next mint schedule number for the edition-tier. * @param edition The Sound Edition address. * @param tier The tier. * @return The next schedule number for the edition-tier. */ function nextScheduleNum(address edition, uint8 tier) external view returns (uint8); /** * @dev Returns the number of tokens minted by `collector` for the mint. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param collector The address which tokens are minted to, * or in the case of `VERIFY_MERKLE`, is the allowlisted address. * @return The number of tokens minted. */ function numberMinted( address edition, uint8 tier, uint8 scheduleNum, address collector ) external view returns (uint32); /** * @dev Returns whether the affiliate is affiliated for the mint * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param affiliate The affiliate address. * @param affiliateProof The Merkle proof for the affiliate. * @return The result. */ function isAffiliatedWithProof( address edition, uint8 tier, uint8 scheduleNum, address affiliate, bytes32[] calldata affiliateProof ) external view returns (bool); /** * @dev Returns whether the affiliate is affiliated for the mint. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param affiliate The affiliate address. * @return A boolean on whether the affiliate is affiliated for the mint. */ function isAffiliated( address edition, uint8 tier, uint8 scheduleNum, address affiliate ) external view returns (bool); /** * @dev Returns whether the claim tickets have been used. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @param claimTickets An array of claim tickets. * @return An array of bools, where true means that a ticket has been used. */ function checkClaimTickets( address edition, uint8 tier, uint8 scheduleNum, uint32[] calldata claimTickets ) external view returns (bool[] memory); /** * @dev Returns the platform fee configuration for the tier. * @param platform The platform address. * @param tier The tier of the mint. * @return The platform fee configuration struct. */ function platformFeeConfig(address platform, uint8 tier) external view returns (PlatformFeeConfig memory); /** * @dev Returns the default platform fee configuration. * @param platform The platform address. * @return The platform fee configuration struct. */ function defaultPlatformFeeConfig(address platform) external view returns (PlatformFeeConfig memory); /** * @dev Returns the effective platform fee configuration. * @param platform The platform address. * @param tier The tier of the mint. * @return The platform fee configuration struct. */ function effectivePlatformFeeConfig(address platform, uint8 tier) external view returns (PlatformFeeConfig memory); /** * @dev Returns an array of mint information structs pertaining to the mint. * @param edition The Sound Edition address. * @return An array of mint information structs. */ function mintInfoList(address edition) external view returns (MintInfo[] memory); /** * @dev Returns information pertaining to the mint. * @param edition The address of the Sound Edition. * @param tier The tier. * @param scheduleNum The edition-tier schedule number. * @return The mint info struct. */ function mintInfo( address edition, uint8 tier, uint8 scheduleNum ) external view returns (MintInfo memory); /** * @dev Retuns the EIP-712 name for the contract. * @return The constant value. */ function name() external pure returns (string memory); /** * @dev Retuns the EIP-712 version for the contract. * @return The constant value. */ function version() external pure returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.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; /// @notice Contract for EIP-712 typed structured data hashing and signing. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EIP712.sol) /// @author Modified from Solbase (https://github.com/Sol-DAO/solbase/blob/main/src/utils/EIP712.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/EIP712.sol) /// /// @dev Note, this implementation: /// - Uses `address(this)` for the `verifyingContract` field. /// - Does NOT use the optional EIP-712 salt. /// - Does NOT use any EIP-712 extensions. /// This is for simplicity and to save gas. /// If you need to customize, please fork / modify accordingly. abstract contract EIP712 { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS AND IMMUTABLES */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev `keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`. bytes32 internal constant _DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f; uint256 private immutable _cachedThis; uint256 private immutable _cachedChainId; bytes32 private immutable _cachedNameHash; bytes32 private immutable _cachedVersionHash; bytes32 private immutable _cachedDomainSeparator; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTRUCTOR */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Cache the hashes for cheaper runtime gas costs. /// In the case of upgradeable contracts (i.e. proxies), /// or if the chain id changes due to a hard fork, /// the domain separator will be seamlessly calculated on-the-fly. constructor() { _cachedThis = uint256(uint160(address(this))); _cachedChainId = block.chainid; string memory name; string memory version; if (!_domainNameAndVersionMayChange()) (name, version) = _domainNameAndVersion(); bytes32 nameHash = _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(name)); bytes32 versionHash = _domainNameAndVersionMayChange() ? bytes32(0) : keccak256(bytes(version)); _cachedNameHash = nameHash; _cachedVersionHash = versionHash; bytes32 separator; if (!_domainNameAndVersionMayChange()) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Load the free memory pointer. mstore(m, _DOMAIN_TYPEHASH) mstore(add(m, 0x20), nameHash) mstore(add(m, 0x40), versionHash) mstore(add(m, 0x60), chainid()) mstore(add(m, 0x80), address()) separator := keccak256(m, 0xa0) } } _cachedDomainSeparator = separator; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* FUNCTIONS TO OVERRIDE */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Please override this function to return the domain name and version. /// ``` /// function _domainNameAndVersion() /// internal /// pure /// virtual /// returns (string memory name, string memory version) /// { /// name = "Solady"; /// version = "1"; /// } /// ``` /// /// Note: If the returned result may change after the contract has been deployed, /// you must override `_domainNameAndVersionMayChange()` to return true. function _domainNameAndVersion() internal view virtual returns (string memory name, string memory version); /// @dev Returns if `_domainNameAndVersion()` may change /// after the contract has been deployed (i.e. after the constructor). /// Default: false. function _domainNameAndVersionMayChange() internal pure virtual returns (bool result) {} /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HASHING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the EIP-712 domain separator. function _domainSeparator() internal view virtual returns (bytes32 separator) { if (_domainNameAndVersionMayChange()) { separator = _buildDomainSeparator(); } else { separator = _cachedDomainSeparator; if (_cachedDomainSeparatorInvalidated()) separator = _buildDomainSeparator(); } } /// @dev Returns the hash of the fully encoded EIP-712 message for this domain, /// given `structHash`, as defined in /// https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct. /// /// The hash can be used together with {ECDSA-recover} to obtain the signer of a message: /// ``` /// bytes32 digest = _hashTypedData(keccak256(abi.encode( /// keccak256("Mail(address to,string contents)"), /// mailTo, /// keccak256(bytes(mailContents)) /// ))); /// address signer = ECDSA.recover(digest, signature); /// ``` function _hashTypedData(bytes32 structHash) internal view virtual returns (bytes32 digest) { // We will use `digest` to store the domain separator to save a bit of gas. if (_domainNameAndVersionMayChange()) { digest = _buildDomainSeparator(); } else { digest = _cachedDomainSeparator; if (_cachedDomainSeparatorInvalidated()) digest = _buildDomainSeparator(); } /// @solidity memory-safe-assembly assembly { // Compute the digest. mstore(0x00, 0x1901000000000000) // Store "\x19\x01". mstore(0x1a, digest) // Store the domain separator. mstore(0x3a, structHash) // Store the struct hash. digest := keccak256(0x18, 0x42) // Restore the part of the free memory slot that was overwritten. mstore(0x3a, 0) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EIP-5267 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev See: https://eips.ethereum.org/EIPS/eip-5267 function eip712Domain() public view virtual returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { fields = hex"0f"; // `0b01111`. (name, version) = _domainNameAndVersion(); chainId = block.chainid; verifyingContract = address(this); salt = salt; // `bytes32(0)`. extensions = extensions; // `new uint256[](0)`. } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* PRIVATE HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the EIP-712 domain separator. function _buildDomainSeparator() private view returns (bytes32 separator) { // We will use `separator` to store the name hash to save a bit of gas. bytes32 versionHash; if (_domainNameAndVersionMayChange()) { (string memory name, string memory version) = _domainNameAndVersion(); separator = keccak256(bytes(name)); versionHash = keccak256(bytes(version)); } else { separator = _cachedNameHash; versionHash = _cachedVersionHash; } /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Load the free memory pointer. mstore(m, _DOMAIN_TYPEHASH) mstore(add(m, 0x20), separator) // Name hash. mstore(add(m, 0x40), versionHash) mstore(add(m, 0x60), chainid()) mstore(add(m, 0x80), address()) separator := keccak256(m, 0xa0) } } /// @dev Returns if the cached domain separator has been invalidated. function _cachedDomainSeparatorInvalidated() private view returns (bool result) { uint256 cachedChainId = _cachedChainId; uint256 cachedThis = _cachedThis; /// @solidity memory-safe-assembly assembly { result := iszero(and(eq(chainid(), cachedChainId), eq(address(), cachedThis))) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/MerkleProofLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol) library MerkleProofLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* MERKLE PROOF VERIFICATION OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`. function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool isValid) { /// @solidity memory-safe-assembly assembly { if mload(proof) { // Initialize `offset` to the offset of `proof` elements in memory. let offset := add(proof, 0x20) // Left shift by 5 is equivalent to multiplying by 0x20. let end := add(offset, shl(5, mload(proof))) // Iterate over proof elements to compute root hash. for {} 1 {} { // Slot of `leaf` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(leaf, mload(offset))) // Store elements to hash contiguously in scratch space. // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. mstore(scratch, leaf) mstore(xor(scratch, 0x20), mload(offset)) // Reuse `leaf` to store the hash to reduce stack operations. leaf := keccak256(0x00, 0x40) offset := add(offset, 0x20) if iszero(lt(offset, end)) { break } } } isValid := eq(leaf, root) } } /// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`. function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool isValid) { /// @solidity memory-safe-assembly assembly { if proof.length { // Left shift by 5 is equivalent to multiplying by 0x20. let end := add(proof.offset, shl(5, proof.length)) // Initialize `offset` to the offset of `proof` in the calldata. let offset := proof.offset // Iterate over proof elements to compute root hash. for {} 1 {} { // Slot of `leaf` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(leaf, calldataload(offset))) // Store elements to hash contiguously in scratch space. // Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes. mstore(scratch, leaf) mstore(xor(scratch, 0x20), calldataload(offset)) // Reuse `leaf` to store the hash to reduce stack operations. leaf := keccak256(0x00, 0x40) offset := add(offset, 0x20) if iszero(lt(offset, end)) { break } } } isValid := eq(leaf, root) } } /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`, /// given `proof` and `flags`. /// /// Note: /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length` /// will always return false. /// - The sum of the lengths of `proof` and `leaves` must never overflow. /// - Any non-zero word in the `flags` array is treated as true. /// - The memory offset of `proof` must be non-zero /// (i.e. `proof` is not pointing to the scratch space). function verifyMultiProof( bytes32[] memory proof, bytes32 root, bytes32[] memory leaves, bool[] memory flags ) internal pure returns (bool isValid) { // Rebuilds the root by consuming and producing values on a queue. // The queue starts with the `leaves` array, and goes into a `hashes` array. // After the process, the last element on the queue is verified // to be equal to the `root`. // // The `flags` array denotes whether the sibling // should be popped from the queue (`flag == true`), or // should be popped from the `proof` (`flag == false`). /// @solidity memory-safe-assembly assembly { // Cache the lengths of the arrays. let leavesLength := mload(leaves) let proofLength := mload(proof) let flagsLength := mload(flags) // Advance the pointers of the arrays to point to the data. leaves := add(0x20, leaves) proof := add(0x20, proof) flags := add(0x20, flags) // If the number of flags is correct. for {} eq(add(leavesLength, proofLength), add(flagsLength, 1)) {} { // For the case where `proof.length + leaves.length == 1`. if iszero(flagsLength) { // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`. isValid := eq(mload(xor(leaves, mul(xor(proof, leaves), proofLength))), root) break } // The required final proof offset if `flagsLength` is not zero, otherwise zero. let proofEnd := add(proof, shl(5, proofLength)) // We can use the free memory space for the queue. // We don't need to allocate, since the queue is temporary. let hashesFront := mload(0x40) // Copy the leaves into the hashes. // Sometimes, a little memory expansion costs less than branching. // Should cost less, even with a high free memory offset of 0x7d00. leavesLength := shl(5, leavesLength) for { let i := 0 } iszero(eq(i, leavesLength)) { i := add(i, 0x20) } { mstore(add(hashesFront, i), mload(add(leaves, i))) } // Compute the back of the hashes. let hashesBack := add(hashesFront, leavesLength) // This is the end of the memory for the queue. // We recycle `flagsLength` to save on stack variables (sometimes save gas). flagsLength := add(hashesBack, shl(5, flagsLength)) for {} 1 {} { // Pop from `hashes`. let a := mload(hashesFront) // Pop from `hashes`. let b := mload(add(hashesFront, 0x20)) hashesFront := add(hashesFront, 0x40) // If the flag is false, load the next proof, // else, pops from the queue. if iszero(mload(flags)) { // Loads the next proof. b := mload(proof) proof := add(proof, 0x20) // Unpop from `hashes`. hashesFront := sub(hashesFront, 0x20) } // Advance to the next flag. flags := add(flags, 0x20) // Slot of `a` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(a, b)) // Hash the scratch space and push the result onto the queue. mstore(scratch, a) mstore(xor(scratch, 0x20), b) mstore(hashesBack, keccak256(0x00, 0x40)) hashesBack := add(hashesBack, 0x20) if iszero(lt(hashesBack, flagsLength)) { break } } isValid := and( // Checks if the last value in the queue is same as the root. eq(mload(sub(hashesBack, 0x20)), root), // And whether all the proofs are used, if required. eq(proofEnd, proof) ) break } } } /// @dev Returns whether all `leaves` exist in the Merkle tree with `root`, /// given `proof` and `flags`. /// /// Note: /// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length` /// will always return false. /// - Any non-zero word in the `flags` array is treated as true. /// - The calldata offset of `proof` must be non-zero /// (i.e. `proof` is from a regular Solidity function with a 4-byte selector). function verifyMultiProofCalldata( bytes32[] calldata proof, bytes32 root, bytes32[] calldata leaves, bool[] calldata flags ) internal pure returns (bool isValid) { // Rebuilds the root by consuming and producing values on a queue. // The queue starts with the `leaves` array, and goes into a `hashes` array. // After the process, the last element on the queue is verified // to be equal to the `root`. // // The `flags` array denotes whether the sibling // should be popped from the queue (`flag == true`), or // should be popped from the `proof` (`flag == false`). /// @solidity memory-safe-assembly assembly { // If the number of flags is correct. for {} eq(add(leaves.length, proof.length), add(flags.length, 1)) {} { // For the case where `proof.length + leaves.length == 1`. if iszero(flags.length) { // `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`. // forgefmt: disable-next-item isValid := eq( calldataload( xor(leaves.offset, mul(xor(proof.offset, leaves.offset), proof.length)) ), root ) break } // The required final proof offset if `flagsLength` is not zero, otherwise zero. let proofEnd := add(proof.offset, shl(5, proof.length)) // We can use the free memory space for the queue. // We don't need to allocate, since the queue is temporary. let hashesFront := mload(0x40) // Copy the leaves into the hashes. // Sometimes, a little memory expansion costs less than branching. // Should cost less, even with a high free memory offset of 0x7d00. calldatacopy(hashesFront, leaves.offset, shl(5, leaves.length)) // Compute the back of the hashes. let hashesBack := add(hashesFront, shl(5, leaves.length)) // This is the end of the memory for the queue. // We recycle `flagsLength` to save on stack variables (sometimes save gas). flags.length := add(hashesBack, shl(5, flags.length)) // We don't need to make a copy of `proof.offset` or `flags.offset`, // as they are pass-by-value (this trick may not always save gas). for {} 1 {} { // Pop from `hashes`. let a := mload(hashesFront) // Pop from `hashes`. let b := mload(add(hashesFront, 0x20)) hashesFront := add(hashesFront, 0x40) // If the flag is false, load the next proof, // else, pops from the queue. if iszero(calldataload(flags.offset)) { // Loads the next proof. b := calldataload(proof.offset) proof.offset := add(proof.offset, 0x20) // Unpop from `hashes`. hashesFront := sub(hashesFront, 0x20) } // Advance to the next flag offset. flags.offset := add(flags.offset, 0x20) // Slot of `a` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(a, b)) // Hash the scratch space and push the result onto the queue. mstore(scratch, a) mstore(xor(scratch, 0x20), b) mstore(hashesBack, keccak256(0x00, 0x40)) hashesBack := add(hashesBack, 0x20) if iszero(lt(hashesBack, flags.length)) { break } } isValid := and( // Checks if the last value in the queue is same as the root. eq(mload(sub(hashesBack, 0x20)), root), // And whether all the proofs are used, if required. eq(proofEnd, proof.offset) ) break } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EMPTY CALLDATA HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an empty calldata bytes32 array. function emptyProof() internal pure returns (bytes32[] calldata proof) { /// @solidity memory-safe-assembly assembly { proof.length := 0 } } /// @dev Returns an empty calldata bytes32 array. function emptyLeaves() internal pure returns (bytes32[] calldata leaves) { /// @solidity memory-safe-assembly assembly { leaves.length := 0 } } /// @dev Returns an empty calldata bool array. function emptyFlags() internal pure returns (bool[] calldata flags) { /// @solidity memory-safe-assembly assembly { flags.length := 0 } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {LibBit} from "./LibBit.sol"; /// @notice Library for storage of packed unsigned booleans. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBitmap.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibBitmap.sol) /// @author Modified from Solidity-Bits (https://github.com/estarriolvetch/solidity-bits/blob/main/contracts/BitMaps.sol) library LibBitmap { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The constant returned when a bitmap scan does not find a result. uint256 internal constant NOT_FOUND = type(uint256).max; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STRUCTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev A bitmap in storage. struct Bitmap { mapping(uint256 => uint256) map; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the boolean value of the bit at `index` in `bitmap`. function get(Bitmap storage bitmap, uint256 index) internal view returns (bool isSet) { // It is better to set `isSet` to either 0 or 1, than zero vs non-zero. // Both cost the same amount of gas, but the former allows the returned value // to be reused without cleaning the upper bits. uint256 b = (bitmap.map[index >> 8] >> (index & 0xff)) & 1; /// @solidity memory-safe-assembly assembly { isSet := b } } /// @dev Updates the bit at `index` in `bitmap` to true. function set(Bitmap storage bitmap, uint256 index) internal { bitmap.map[index >> 8] |= (1 << (index & 0xff)); } /// @dev Updates the bit at `index` in `bitmap` to false. function unset(Bitmap storage bitmap, uint256 index) internal { bitmap.map[index >> 8] &= ~(1 << (index & 0xff)); } /// @dev Flips the bit at `index` in `bitmap`. /// Returns the boolean result of the flipped bit. function toggle(Bitmap storage bitmap, uint256 index) internal returns (bool newIsSet) { /// @solidity memory-safe-assembly assembly { mstore(0x20, bitmap.slot) mstore(0x00, shr(8, index)) let storageSlot := keccak256(0x00, 0x40) let shift := and(index, 0xff) let storageValue := xor(sload(storageSlot), shl(shift, 1)) // It makes sense to return the `newIsSet`, // as it allow us to skip an additional warm `sload`, // and it costs minimal gas (about 15), // which may be optimized away if the returned value is unused. newIsSet := and(1, shr(shift, storageValue)) sstore(storageSlot, storageValue) } } /// @dev Updates the bit at `index` in `bitmap` to `shouldSet`. function setTo(Bitmap storage bitmap, uint256 index, bool shouldSet) internal { /// @solidity memory-safe-assembly assembly { mstore(0x20, bitmap.slot) mstore(0x00, shr(8, index)) let storageSlot := keccak256(0x00, 0x40) let storageValue := sload(storageSlot) let shift := and(index, 0xff) sstore( storageSlot, // Unsets the bit at `shift` via `and`, then sets its new value via `or`. or(and(storageValue, not(shl(shift, 1))), shl(shift, iszero(iszero(shouldSet)))) ) } } /// @dev Consecutively sets `amount` of bits starting from the bit at `start`. function setBatch(Bitmap storage bitmap, uint256 start, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { let max := not(0) let shift := and(start, 0xff) mstore(0x20, bitmap.slot) mstore(0x00, shr(8, start)) if iszero(lt(add(shift, amount), 257)) { let storageSlot := keccak256(0x00, 0x40) sstore(storageSlot, or(sload(storageSlot), shl(shift, max))) let bucket := add(mload(0x00), 1) let bucketEnd := add(mload(0x00), shr(8, add(amount, shift))) amount := and(add(amount, shift), 0xff) shift := 0 for {} iszero(eq(bucket, bucketEnd)) { bucket := add(bucket, 1) } { mstore(0x00, bucket) sstore(keccak256(0x00, 0x40), max) } mstore(0x00, bucket) } let storageSlot := keccak256(0x00, 0x40) sstore(storageSlot, or(sload(storageSlot), shl(shift, shr(sub(256, amount), max)))) } } /// @dev Consecutively unsets `amount` of bits starting from the bit at `start`. function unsetBatch(Bitmap storage bitmap, uint256 start, uint256 amount) internal { /// @solidity memory-safe-assembly assembly { let shift := and(start, 0xff) mstore(0x20, bitmap.slot) mstore(0x00, shr(8, start)) if iszero(lt(add(shift, amount), 257)) { let storageSlot := keccak256(0x00, 0x40) sstore(storageSlot, and(sload(storageSlot), not(shl(shift, not(0))))) let bucket := add(mload(0x00), 1) let bucketEnd := add(mload(0x00), shr(8, add(amount, shift))) amount := and(add(amount, shift), 0xff) shift := 0 for {} iszero(eq(bucket, bucketEnd)) { bucket := add(bucket, 1) } { mstore(0x00, bucket) sstore(keccak256(0x00, 0x40), 0) } mstore(0x00, bucket) } let storageSlot := keccak256(0x00, 0x40) sstore( storageSlot, and(sload(storageSlot), not(shl(shift, shr(sub(256, amount), not(0))))) ) } } /// @dev Returns number of set bits within a range by /// scanning `amount` of bits starting from the bit at `start`. function popCount(Bitmap storage bitmap, uint256 start, uint256 amount) internal view returns (uint256 count) { unchecked { uint256 bucket = start >> 8; uint256 shift = start & 0xff; if (!(amount + shift < 257)) { count = LibBit.popCount(bitmap.map[bucket] >> shift); uint256 bucketEnd = bucket + ((amount + shift) >> 8); amount = (amount + shift) & 0xff; shift = 0; for (++bucket; bucket != bucketEnd; ++bucket) { count += LibBit.popCount(bitmap.map[bucket]); } } count += LibBit.popCount((bitmap.map[bucket] >> shift) << (256 - amount)); } } /// @dev Returns the index of the most significant set bit before the bit at `before`. /// If no set bit is found, returns `NOT_FOUND`. function findLastSet(Bitmap storage bitmap, uint256 before) internal view returns (uint256 setBitIndex) { uint256 bucket; uint256 bucketBits; /// @solidity memory-safe-assembly assembly { setBitIndex := not(0) bucket := shr(8, before) mstore(0x00, bucket) mstore(0x20, bitmap.slot) let offset := and(0xff, not(before)) // `256 - (255 & before) - 1`. bucketBits := shr(offset, shl(offset, sload(keccak256(0x00, 0x40)))) if iszero(or(bucketBits, iszero(bucket))) { for {} 1 {} { bucket := add(bucket, setBitIndex) // `sub(bucket, 1)`. mstore(0x00, bucket) bucketBits := sload(keccak256(0x00, 0x40)) if or(bucketBits, iszero(bucket)) { break } } } } if (bucketBits != 0) { setBitIndex = (bucket << 8) | LibBit.fls(bucketBits); /// @solidity memory-safe-assembly assembly { setBitIndex := or(setBitIndex, sub(0, gt(setBitIndex, before))) } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Signature verification helper that supports both ECDSA signatures from EOAs /// and ERC1271 signatures from smart contract wallets like Argent and Gnosis safe. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SignatureCheckerLib.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/SignatureChecker.sol) /// /// @dev Note: /// - The signature checking functions use the ecrecover precompile (0x1). /// - The `bytes memory signature` variants use the identity precompile (0x4) /// to copy memory internally. /// - Unlike ECDSA signatures, contract signatures are revocable. /// - As of Solady version 0.0.134, all `bytes signature` variants accept both /// regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures. /// See: https://eips.ethereum.org/EIPS/eip-2098 /// This is for calldata efficiency on smart accounts prevalent on L2s. /// /// WARNING! Do NOT use signatures as unique identifiers: /// - Use a nonce in the digest to prevent replay attacks on the same contract. /// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts. /// EIP-712 also enables readable signing of typed data for better user safety. /// This implementation does NOT check if a signature is non-malleable. library SignatureCheckerLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* SIGNATURE CHECKING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `signature` is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits of `signer` in case they are dirty. for { signer := shr(96, shl(96, signer)) } signer {} { let m := mload(0x40) mstore(0x00, hash) mstore(0x40, mload(add(signature, 0x20))) // `r`. if eq(mload(signature), 64) { let vs := mload(add(signature, 0x40)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x60, shr(1, shl(1, vs))) // `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } if eq(mload(signature), 65) { mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x60, mload(add(signature, 0x40))) // `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. // Copy the `signature` over. let n := add(0x20, mload(signature)) pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n)) // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(returndatasize(), 0x44), // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) break } } } /// @dev Returns whether `signature` is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNowCalldata(address signer, bytes32 hash, bytes calldata signature) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits of `signer` in case they are dirty. for { signer := shr(96, shl(96, signer)) } signer {} { let m := mload(0x40) mstore(0x00, hash) if eq(signature.length, 64) { let vs := calldataload(add(signature.offset, 0x20)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, calldataload(signature.offset)) // `r`. mstore(0x60, shr(1, shl(1, vs))) // `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } if eq(signature.length, 65) { mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`. calldatacopy(0x40, signature.offset, 0x40) // `r`, `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), signature.length) // Copy the `signature` over. calldatacopy(add(m, 0x64), signature.offset, signature.length) // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(signature.length, 0x64), // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) break } } } /// @dev Returns whether the signature (`r`, `vs`) is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits of `signer` in case they are dirty. for { signer := shr(96, shl(96, signer)) } signer {} { let m := mload(0x40) mstore(0x00, hash) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, r) // `r`. mstore(0x60, shr(1, shl(1, vs))) // `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), mload(0x60)) // `s`. mstore8(add(m, 0xa4), mload(0x20)) // `v`. // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. 0xa5, // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } } /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `signer` and `hash`. /// If `signer` is a smart contract, the signature is validated with ERC1271. /// Otherwise, the signature is validated with `ECDSA.recover`. function isValidSignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { // Clean the upper 96 bits of `signer` in case they are dirty. for { signer := shr(96, shl(96, signer)) } signer {} { let m := mload(0x40) mstore(0x00, hash) mstore(0x20, and(v, 0xff)) // `v`. mstore(0x40, r) // `r`. mstore(0x60, s) // `s`. let t := staticcall( gas(), // Amount of gas left for the transaction. 1, // Address of `ecrecover`. 0x00, // Start of input. 0x80, // Size of input. 0x01, // Start of output. 0x20 // Size of output. ) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(or(iszero(returndatasize()), xor(signer, mload(t)))) { isValid := 1 mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), s) // `s`. mstore8(add(m, 0xa4), v) // `v`. // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. 0xa5, // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. break } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* ERC1271 OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract. function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. // Copy the `signature` over. let n := add(0x20, mload(signature)) pop(staticcall(gas(), 4, signature, n, add(m, 0x44), n)) // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(returndatasize(), 0x44), // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) } } /// @dev Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract. function isValidERC1271SignatureNowCalldata( address signer, bytes32 hash, bytes calldata signature ) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), signature.length) // Copy the `signature` over. calldatacopy(add(m, 0x64), signature.offset, signature.length) // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. add(signature.length, 0x64), // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) } } /// @dev Returns whether the signature (`r`, `vs`) is valid for `hash` /// for an ERC1271 `signer` contract. function isValidERC1271SignatureNow(address signer, bytes32 hash, bytes32 r, bytes32 vs) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), shr(1, shl(1, vs))) // `s`. mstore8(add(m, 0xa4), add(shr(255, vs), 27)) // `v`. // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. 0xa5, // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) } } /// @dev Returns whether the signature (`v`, `r`, `s`) is valid for `hash` /// for an ERC1271 `signer` contract. function isValidERC1271SignatureNow(address signer, bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (bool isValid) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) let f := shl(224, 0x1626ba7e) mstore(m, f) // `bytes4(keccak256("isValidSignature(bytes32,bytes)"))`. mstore(add(m, 0x04), hash) let d := add(m, 0x24) mstore(d, 0x40) // The offset of the `signature` in the calldata. mstore(add(m, 0x44), 65) // Length of the signature. mstore(add(m, 0x64), r) // `r`. mstore(add(m, 0x84), s) // `s`. mstore8(add(m, 0xa4), v) // `v`. // forgefmt: disable-next-item isValid := and( // Whether the returndata is the magic value `0x1626ba7e` (left-aligned). eq(mload(d), f), // Whether the staticcall does not revert. // This must be placed at the end of the `and` clause, // as the arguments are evaluated from right to left. staticcall( gas(), // Remaining gas. signer, // The `signer` address. m, // Offset of calldata in memory. 0xa5, // Length of calldata in memory. d, // Offset of returndata. 0x20 // Length of returndata to write. ) ) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HASHING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an Ethereum Signed Message, created from a `hash`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { mstore(0x20, hash) // Store into scratch space for keccak256. mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes. result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`. } } /// @dev Returns an Ethereum Signed Message, created from `s`. /// This produces a hash corresponding to the one signed with the /// [`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) /// JSON-RPC method as part of EIP-191. /// Note: Supports lengths of `s` up to 999999 bytes. function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { let sLength := mload(s) let o := 0x20 mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded. mstore(0x00, 0x00) // Convert the `s.length` to ASCII decimal representation: `base10(s.length)`. for { let temp := sLength } 1 {} { o := sub(o, 1) mstore8(o, add(48, mod(temp, 10))) temp := div(temp, 10) if iszero(temp) { break } } let n := sub(0x3a, o) // Header length: `26 + 32 - o`. // Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes. returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20)) mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header. result := keccak256(add(s, sub(0x20, n)), add(n, sLength)) mstore(s, sLength) // Restore the length. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* EMPTY CALLDATA HELPERS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns an empty calldata bytes. function emptySignature() internal pure returns (bytes calldata signature) { /// @solidity memory-safe-assembly assembly { signature.length := 0 } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library for compressing and decompressing bytes. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibZip.sol) /// @author Calldata compression by clabby (https://github.com/clabby/op-kompressor) /// @author FastLZ by ariya (https://github.com/ariya/FastLZ) /// /// @dev Note: /// The accompanying solady.js library includes implementations of /// FastLZ and calldata operations for convenience. library LibZip { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* FAST LZ OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // LZ77 implementation based on FastLZ. // Equivalent to level 1 compression and decompression at the following commit: // https://github.com/ariya/FastLZ/commit/344eb4025f9ae866ebf7a2ec48850f7113a97a42 // Decompression is backwards compatible. /// @dev Returns the compressed `data`. function flzCompress(bytes memory data) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { function ms8(d_, v_) -> _d { mstore8(d_, v_) _d := add(d_, 1) } function u24(p_) -> _u { let w := mload(p_) _u := or(shl(16, byte(2, w)), or(shl(8, byte(1, w)), byte(0, w))) } function cmp(p_, q_, e_) -> _l { for { e_ := sub(e_, q_) } lt(_l, e_) { _l := add(_l, 1) } { e_ := mul(iszero(byte(0, xor(mload(add(p_, _l)), mload(add(q_, _l))))), e_) } } function literals(runs_, src_, dest_) -> _o { for { _o := dest_ } iszero(lt(runs_, 0x20)) { runs_ := sub(runs_, 0x20) } { mstore(ms8(_o, 31), mload(src_)) _o := add(_o, 0x21) src_ := add(src_, 0x20) } if iszero(runs_) { leave } mstore(ms8(_o, sub(runs_, 1)), mload(src_)) _o := add(1, add(_o, runs_)) } function match(l_, d_, o_) -> _o { for { d_ := sub(d_, 1) } iszero(lt(l_, 263)) { l_ := sub(l_, 262) } { o_ := ms8(ms8(ms8(o_, add(224, shr(8, d_))), 253), and(0xff, d_)) } if iszero(lt(l_, 7)) { _o := ms8(ms8(ms8(o_, add(224, shr(8, d_))), sub(l_, 7)), and(0xff, d_)) leave } _o := ms8(ms8(o_, add(shl(5, l_), shr(8, d_))), and(0xff, d_)) } function setHash(i_, v_) { let p := add(mload(0x40), shl(2, i_)) mstore(p, xor(mload(p), shl(224, xor(shr(224, mload(p)), v_)))) } function getHash(i_) -> _h { _h := shr(224, mload(add(mload(0x40), shl(2, i_)))) } function hash(v_) -> _r { _r := and(shr(19, mul(2654435769, v_)), 0x1fff) } function setNextHash(ip_, ipStart_) -> _ip { setHash(hash(u24(ip_)), sub(ip_, ipStart_)) _ip := add(ip_, 1) } codecopy(mload(0x40), codesize(), 0x8000) // Zeroize the hashmap. let op := add(mload(0x40), 0x8000) let a := add(data, 0x20) let ipStart := a let ipLimit := sub(add(ipStart, mload(data)), 13) for { let ip := add(2, a) } lt(ip, ipLimit) {} { let r := 0 let d := 0 for {} 1 {} { let s := u24(ip) let h := hash(s) r := add(ipStart, getHash(h)) setHash(h, sub(ip, ipStart)) d := sub(ip, r) if iszero(lt(ip, ipLimit)) { break } ip := add(ip, 1) if iszero(gt(d, 0x1fff)) { if eq(s, u24(r)) { break } } } if iszero(lt(ip, ipLimit)) { break } ip := sub(ip, 1) if gt(ip, a) { op := literals(sub(ip, a), a, op) } let l := cmp(add(r, 3), add(ip, 3), add(ipLimit, 9)) op := match(l, d, op) ip := setNextHash(setNextHash(add(ip, l), ipStart), ipStart) a := ip } op := literals(sub(add(ipStart, mload(data)), a), a, op) result := mload(0x40) let t := add(result, 0x8000) let n := sub(op, t) mstore(result, n) // Store the length. // Copy the result to compact the memory, overwriting the hashmap. let o := add(result, 0x20) for { let i } lt(i, n) { i := add(i, 0x20) } { mstore(add(o, i), mload(add(t, i))) } mstore(add(o, n), 0) // Zeroize the slot after the string. mstore(0x40, add(add(o, n), 0x20)) // Allocate the memory. } } /// @dev Returns the decompressed `data`. function flzDecompress(bytes memory data) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { let n := 0 let end := add(add(data, 0x20), mload(data)) result := mload(0x40) let op := add(result, 0x20) for { data := add(data, 0x20) } lt(data, end) {} { let w := mload(data) let c := byte(0, w) let t := shr(5, c) if iszero(t) { mstore(add(op, n), mload(add(data, 1))) data := add(data, add(2, c)) n := add(n, add(1, c)) continue } let g := eq(t, 7) let l := add(2, xor(t, mul(g, xor(t, add(7, byte(1, w)))))) for { let s := add(add(shl(8, and(0x1f, c)), byte(add(1, g), w)), 1) let r := add(op, sub(n, s)) let o := add(op, n) let f := xor(s, mul(gt(s, 0x20), xor(s, 0x20))) let j := 0 } 1 {} { mstore(add(o, j), mload(add(r, j))) j := add(j, f) if iszero(lt(j, l)) { break } } data := add(data, add(2, g)) n := add(n, l) } mstore(result, n) // Store the length. let o := add(add(result, 0x20), n) mstore(o, 0) // Zeroize the slot after the string. mstore(0x40, add(o, 0x20)) // Allocate the memory. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CALLDATA OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // Calldata compression and decompression using selective run length encoding: // - Sequences of 0x00 (up to 128 consecutive). // - Sequences of 0xff (up to 32 consecutive). // // A run length encoded block consists of two bytes: // (0) 0x00 // (1) A control byte with the following bit layout: // - [7] `0: 0x00, 1: 0xff`. // - [0..6] `runLength - 1`. // // The first 4 bytes are bitwise negated so that the compressed calldata // can be dispatched into the `fallback` and `receive` functions. /// @dev Returns the compressed `data`. function cdCompress(bytes memory data) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { function rle(v_, o_, d_) -> _o, _d { mstore(o_, shl(240, or(and(0xff, add(d_, 0xff)), and(0x80, v_)))) _o := add(o_, 2) } result := mload(0x40) let o := add(result, 0x20) let z := 0 // Number of consecutive 0x00. let y := 0 // Number of consecutive 0xff. for { let end := add(data, mload(data)) } iszero(eq(data, end)) {} { data := add(data, 1) let c := byte(31, mload(data)) if iszero(c) { if y { o, y := rle(0xff, o, y) } z := add(z, 1) if eq(z, 0x80) { o, z := rle(0x00, o, 0x80) } continue } if eq(c, 0xff) { if z { o, z := rle(0x00, o, z) } y := add(y, 1) if eq(y, 0x20) { o, y := rle(0xff, o, 0x20) } continue } if y { o, y := rle(0xff, o, y) } if z { o, z := rle(0x00, o, z) } mstore8(o, c) o := add(o, 1) } if y { o, y := rle(0xff, o, y) } if z { o, z := rle(0x00, o, z) } // Bitwise negate the first 4 bytes. mstore(add(result, 4), not(mload(add(result, 4)))) mstore(result, sub(o, add(result, 0x20))) // Store the length. mstore(o, 0) // Zeroize the slot after the string. mstore(0x40, add(o, 0x20)) // Allocate the memory. } } /// @dev Returns the decompressed `data`. function cdDecompress(bytes memory data) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { if mload(data) { result := mload(0x40) let o := add(result, 0x20) let s := add(data, 4) let v := mload(s) let end := add(data, mload(data)) mstore(s, not(v)) // Bitwise negate the first 4 bytes. for {} lt(data, end) {} { data := add(data, 1) let c := byte(31, mload(data)) if iszero(c) { data := add(data, 1) let d := byte(31, mload(data)) // Fill with either 0xff or 0x00. mstore(o, not(0)) if iszero(gt(d, 0x7f)) { codecopy(o, codesize(), add(d, 1)) } o := add(o, add(and(d, 0x7f), 1)) continue } mstore8(o, c) o := add(o, 1) } mstore(s, v) // Restore the first 4 bytes. mstore(result, sub(o, add(result, 0x20))) // Store the length. mstore(o, 0) // Zeroize the slot after the string. mstore(0x40, add(o, 0x20)) // Allocate the memory. } } } /// @dev To be called in the `receive` and `fallback` functions. /// ``` /// receive() external payable { LibZip.cdFallback(); } /// fallback() external payable { LibZip.cdFallback(); } /// ``` /// For efficiency, this function will directly return the results, terminating the context. /// If called internally, it must be called at the end of the function. function cdFallback() internal { assembly { if iszero(calldatasize()) { return(calldatasize(), calldatasize()) } let o := 0 let f := not(3) // For negating the first 4 bytes. for { let i := 0 } lt(i, calldatasize()) {} { let c := byte(0, xor(add(i, f), calldataload(i))) i := add(i, 1) if iszero(c) { let d := byte(0, xor(add(i, f), calldataload(i))) i := add(i, 1) // Fill with either 0xff or 0x00. mstore(o, not(0)) if iszero(gt(d, 0x7f)) { codecopy(o, codesize(), add(d, 1)) } o := add(o, add(and(d, 0x7f), 1)) continue } mstore8(o, c) o := add(o, 1) } let success := delegatecall(gas(), address(), 0x00, o, codesize(), 0x00) returndatacopy(0x00, 0x00, returndatasize()) if iszero(success) { revert(0x00, returndatasize()) } return(0x00, returndatasize()) } } }
// 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; library DelegateCashLib { address internal constant REGISTRY_V2 = 0x00000000000000447e69651d841bD8D104Bed493; function checkDelegateForAll(address delegate, address vault) internal view returns (bool result) { assembly { // Cache the free memory pointer. let m := mload(0x40) // Store the function selector of `checkDelegateForAll(address,address,bytes32)`. mstore(0x00, 0xe839bd53) // Store the `delegate`. mstore(0x20, delegate) // Store the `vault`. mstore(0x40, vault) // The `bytes32 right` argument points to 0x60, which is zero. // Arguments are evaulated last to first. result := and( // The returndata is 1, which represents a bool true. eq(mload(0x00), 1), // The staticcall is successful. staticcall(gas(), REGISTRY_V2, 0x1c, 0x64, 0x00, 0x20) ) // Restore the free memory pointer. mstore(0x40, m) } } }
// 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.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.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 // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev Interface of ERC721A. */ interface IERC721AUpgradeable { /** * The caller must own the token or be an approved operator. */ error ApprovalCallerNotOwnerNorApproved(); /** * The token does not exist. */ error ApprovalQueryForNonexistentToken(); /** * Cannot query the balance for the zero address. */ error BalanceQueryForZeroAddress(); /** * Cannot mint to the zero address. */ error MintToZeroAddress(); /** * The quantity of tokens minted must be more than zero. */ error MintZeroQuantity(); /** * The token does not exist. */ error OwnerQueryForNonexistentToken(); /** * The caller must own the token or be an approved operator. */ error TransferCallerNotOwnerNorApproved(); /** * The token must be owned by `from`. */ error TransferFromIncorrectOwner(); /** * Cannot safely transfer to a contract that does not implement the * ERC721Receiver interface. */ error TransferToNonERC721ReceiverImplementer(); /** * Cannot transfer to the zero address. */ error TransferToZeroAddress(); /** * The token does not exist. */ error URIQueryForNonexistentToken(); /** * The `quantity` minted with ERC2309 exceeds the safety limit. */ error MintERC2309QuantityExceedsLimit(); /** * The `extraData` cannot be set on an unintialized ownership slot. */ error OwnershipNotInitializedForExtraData(); // ============================================================= // STRUCTS // ============================================================= struct TokenOwnership { // The address of the owner. address addr; // Stores the start time of ownership with minimal overhead for tokenomics. uint64 startTimestamp; // Whether the token has been burned. bool burned; // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}. uint24 extraData; } // ============================================================= // TOKEN COUNTERS // ============================================================= /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() external view returns (uint256); // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); // ============================================================= // IERC721 // ============================================================= /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables * (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, * checking first that contract recipients are aware of the ERC721 protocol * to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move * this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external payable; /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external payable; /** * @dev Transfers `tokenId` from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} * whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external payable; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the * zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external payable; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} * for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) external view returns (bool); // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); // ============================================================= // IERC2309 // ============================================================= /** * @dev Emitted when tokens in `fromTokenId` to `toTokenId` * (inclusive) is transferred from `from` to `to`, as defined in the * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard. * * See {_mintERC2309} for more details. */ event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165Upgradeable.sol"; /** * @dev Interface for the NFT Royalty Standard. * * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal * support for royalty payments across all NFT marketplaces and ecosystem participants. * * _Available since v4.5._ */ interface IERC2981Upgradeable is IERC165Upgradeable { /** * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of * exchange. The royalty amount is denominated and should be paid in that same unit of exchange. */ function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165Upgradeable { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.16; /** * @title IMetadataModule * @notice The interface for custom metadata modules. */ interface IMetadataModule { /** * @dev When implemented, SoundEdition's `tokenURI` redirects execution to this `tokenURI`. * @param tokenId The token ID to retrieve the token URI for. * @return The token URI string. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library for bit twiddling and boolean operations. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBit.sol) /// @author Inspired by (https://graphics.stanford.edu/~seander/bithacks.html) library LibBit { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BIT TWIDDLING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Find last set. /// Returns the index of the most significant bit of `x`, /// counting from the least significant bit position. /// If `x` is zero, returns 256. function fls(uint256 x) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, x))) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // forgefmt: disable-next-item r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)), 0x0706060506020504060203020504030106050205030304010505030400000000)) } } /// @dev Count leading zeros. /// Returns the number of zeros preceding the most significant one bit. /// If `x` is zero, returns 256. function clz(uint256 x) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // forgefmt: disable-next-item r := add(xor(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)), 0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff)), iszero(x)) } } /// @dev Find first set. /// Returns the index of the least significant bit of `x`, /// counting from the least significant bit position. /// If `x` is zero, returns 256. /// Equivalent to `ctz` (count trailing zeros), which gives /// the number of zeros following the least significant one bit. function ffs(uint256 x) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { // Isolate the least significant bit. let b := and(x, add(not(x), 1)) r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, b))) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, b)))) r := or(r, shl(5, lt(0xffffffff, shr(r, b)))) // For the remaining 32 bits, use a De Bruijn lookup. // forgefmt: disable-next-item r := or(r, byte(and(div(0xd76453e0, shr(r, b)), 0x1f), 0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405)) } } /// @dev Returns the number of set bits in `x`. function popCount(uint256 x) internal pure returns (uint256 c) { /// @solidity memory-safe-assembly assembly { let max := not(0) let isMax := eq(x, max) x := sub(x, and(shr(1, x), div(max, 3))) x := add(and(x, div(max, 5)), and(shr(2, x), div(max, 5))) x := and(add(x, shr(4, x)), div(max, 17)) c := or(shl(8, isMax), shr(248, mul(x, div(max, 255)))) } } /// @dev Returns whether `x` is a power of 2. function isPo2(uint256 x) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { // Equivalent to `x && !(x & (x - 1))`. result := iszero(add(and(x, sub(x, 1)), iszero(x))) } } /// @dev Returns `x` reversed at the bit level. function reverseBits(uint256 x) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { // Computing masks on-the-fly reduces bytecode size by about 500 bytes. let m := not(0) r := x for { let s := 128 } 1 {} { m := xor(m, shl(s, m)) r := or(and(shr(s, r), m), and(shl(s, r), not(m))) s := shr(1, s) if iszero(s) { break } } } } /// @dev Returns `x` reversed at the byte level. function reverseBytes(uint256 x) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { // Computing masks on-the-fly reduces bytecode size by about 200 bytes. let m := not(0) r := x for { let s := 128 } 1 {} { m := xor(m, shl(s, m)) r := or(and(shr(s, r), m), and(shl(s, r), not(m))) s := shr(1, s) if eq(s, 4) { break } } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BOOLEAN OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // A Solidity bool on the stack or memory is represented as a 256-bit word. // Non-zero values are true, zero is false. // A clean bool is either 0 (false) or 1 (true) under the hood. // Usually, if not always, the bool result of a regular Solidity expression, // or the argument of a public/external function will be a clean bool. // You can usually use the raw variants for more performance. // If uncertain, test (best with exact compiler settings). // Or use the non-raw variants (compiler can sometimes optimize out the double `iszero`s). /// @dev Returns `x & y`. Inputs must be clean. function rawAnd(bool x, bool y) internal pure returns (bool z) { /// @solidity memory-safe-assembly assembly { z := and(x, y) } } /// @dev Returns `x & y`. function and(bool x, bool y) internal pure returns (bool z) { /// @solidity memory-safe-assembly assembly { z := and(iszero(iszero(x)), iszero(iszero(y))) } } /// @dev Returns `x | y`. Inputs must be clean. function rawOr(bool x, bool y) internal pure returns (bool z) { /// @solidity memory-safe-assembly assembly { z := or(x, y) } } /// @dev Returns `x | y`. function or(bool x, bool y) internal pure returns (bool z) { /// @solidity memory-safe-assembly assembly { z := or(iszero(iszero(x)), iszero(iszero(y))) } } /// @dev Returns 1 if `b` is true, else 0. Input must be clean. function rawToUint(bool b) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := b } } /// @dev Returns 1 if `b` is true, else 0. function toUint(bool b) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := iszero(iszero(b)) } } }
{ "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":"CallerNotDelegated","type":"error"},{"inputs":[],"name":"ExceedsMaxPerAccount","type":"error"},{"inputs":[],"name":"ExceedsMintSupply","type":"error"},{"inputs":[],"name":"ExceedsSignedQuantity","type":"error"},{"inputs":[],"name":"InvalidAffiliate","type":"error"},{"inputs":[],"name":"InvalidAffiliateFeeBPS","type":"error"},{"inputs":[],"name":"InvalidMaxMintableRange","type":"error"},{"inputs":[],"name":"InvalidMerkleProof","type":"error"},{"inputs":[],"name":"InvalidMode","type":"error"},{"inputs":[],"name":"InvalidPlatformFeeBPS","type":"error"},{"inputs":[],"name":"InvalidPlatformFeeConfig","type":"error"},{"inputs":[],"name":"InvalidPlatformFlatFee","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidTimeRange","type":"error"},{"inputs":[],"name":"MaxMintableIsZero","type":"error"},{"inputs":[],"name":"MaxMintablePerAccountIsZero","type":"error"},{"inputs":[],"name":"MerkleRootIsEmpty","type":"error"},{"inputs":[],"name":"MintDoesNotExist","type":"error"},{"inputs":[{"internalType":"uint256","name":"blockTimestamp","type":"uint256"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"}],"name":"MintNotOpen","type":"error"},{"inputs":[],"name":"MintPaused","type":"error"},{"inputs":[],"name":"MintsAlreadyExist","type":"error"},{"inputs":[],"name":"NotConfigurable","type":"error"},{"inputs":[],"name":"PlatformFeeAddressIsZero","type":"error"},{"inputs":[],"name":"SignatureAlreadyUsed","type":"error"},{"inputs":[],"name":"SignatureExpired","type":"error"},{"inputs":[],"name":"SignedPriceTooLow","type":"error"},{"inputs":[{"internalType":"uint256","name":"paid","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"WrongPayment","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"uint16","name":"bps","type":"uint16"}],"name":"AffiliateFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"affiliate","type":"address"},{"indexed":false,"internalType":"uint256","name":"accrued","type":"uint256"}],"name":"AffiliateFeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"AffiliateMerkleRootSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"platform","type":"address"},{"components":[{"internalType":"uint96","name":"artistMintReward","type":"uint96"},{"internalType":"uint96","name":"affiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"platformMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPrice","type":"uint96"},{"internalType":"uint96","name":"thresholdArtistMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdAffiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPlatformMintReward","type":"uint96"},{"internalType":"uint96","name":"platformTxFlatFee","type":"uint96"},{"internalType":"uint16","name":"platformMintFeeBPS","type":"uint16"},{"internalType":"bool","name":"active","type":"bool"}],"indexed":false,"internalType":"struct ISuperMinterV2.PlatformFeeConfig","name":"config","type":"tuple"}],"name":"DefaultPlatformFeeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"platform","type":"address"},{"indexed":false,"internalType":"uint96","name":"price","type":"uint96"}],"name":"GAPriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"uint32","name":"value","type":"uint32"}],"name":"MaxMintablePerAccountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"uint32","name":"value","type":"uint32"}],"name":"MaxMintableSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"name":"MerkleRootSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint96","name":"price","type":"uint96"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"},{"internalType":"uint32","name":"maxMintable","type":"uint32"},{"internalType":"uint16","name":"affiliateFeeBPS","type":"uint16"},{"internalType":"bytes32","name":"affiliateMerkleRoot","type":"bytes32"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"address","name":"platform","type":"address"},{"internalType":"uint8","name":"mode","type":"uint8"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"indexed":false,"internalType":"struct ISuperMinterV2.MintCreation","name":"creation","type":"tuple"}],"name":"MintCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"components":[{"internalType":"uint32","name":"quantity","type":"uint32"},{"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"internalType":"address","name":"allowlisted","type":"address"},{"internalType":"uint32","name":"allowlistedQuantity","type":"uint32"},{"internalType":"uint32","name":"signedQuantity","type":"uint32"},{"internalType":"uint32","name":"signedClaimTicket","type":"uint32"},{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"bool","name":"affiliated","type":"bool"},{"internalType":"uint256","name":"requiredEtherValue","type":"uint256"},{"internalType":"uint256","name":"unitPrice","type":"uint256"},{"internalType":"uint256","name":"finalArtistFee","type":"uint256"},{"internalType":"uint256","name":"finalAffiliateFee","type":"uint256"},{"internalType":"uint256","name":"finalPlatformFee","type":"uint256"}],"indexed":false,"internalType":"struct ISuperMinterV2.MintedLogData","name":"data","type":"tuple"},{"indexed":true,"internalType":"uint256","name":"attributionId","type":"uint256"}],"name":"Minted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"PausedSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"address[]","name":"to","type":"address[]"},{"indexed":false,"internalType":"uint32","name":"signedQuantity","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"fromTokenId","type":"uint256"}],"name":"PlatformAirdropped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"platform","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"}],"name":"PlatformFeeAddressSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"platform","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"components":[{"internalType":"uint96","name":"artistMintReward","type":"uint96"},{"internalType":"uint96","name":"affiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"platformMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPrice","type":"uint96"},{"internalType":"uint96","name":"thresholdArtistMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdAffiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPlatformMintReward","type":"uint96"},{"internalType":"uint96","name":"platformTxFlatFee","type":"uint96"},{"internalType":"uint16","name":"platformMintFeeBPS","type":"uint16"},{"internalType":"bool","name":"active","type":"bool"}],"indexed":false,"internalType":"struct ISuperMinterV2.PlatformFeeConfig","name":"config","type":"tuple"}],"name":"PlatformFeeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"platform","type":"address"},{"indexed":false,"internalType":"uint256","name":"accrued","type":"uint256"}],"name":"PlatformFeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"platform","type":"address"},{"indexed":false,"internalType":"address","name":"signer","type":"address"}],"name":"PlatformSignerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"uint96","name":"price","type":"uint96"}],"name":"PriceSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"edition","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"indexed":false,"internalType":"uint32","name":"startTime","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"endTime","type":"uint32"}],"name":"TimeRangeSet","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"BPS_DENOMINATOR","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GA_TIER","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_AFFILIATE_FEE_BPS","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PER_MINT_REWARD","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PLATFORM_PER_MINT_FEE_BPS","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PLATFORM_PER_TX_FLAT_FEE","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINT_TO_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PLATFORM_AIRDROP","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PLATFORM_AIRDROP_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERIFY_MERKLE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERIFY_SIGNATURE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"affiliateFeesAccrued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint32[]","name":"claimTickets","type":"uint32[]"}],"name":"checkClaimTickets","outputs":[{"internalType":"bool[]","name":"claimed","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint32","name":"quantity","type":"uint32"},{"internalType":"address","name":"allowlisted","type":"address"},{"internalType":"uint32","name":"allowlistedQuantity","type":"uint32"},{"internalType":"bytes32[]","name":"allowlistProof","type":"bytes32[]"},{"internalType":"uint96","name":"signedPrice","type":"uint96"},{"internalType":"uint32","name":"signedQuantity","type":"uint32"},{"internalType":"uint32","name":"signedClaimTicket","type":"uint32"},{"internalType":"uint32","name":"signedDeadline","type":"uint32"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"bytes32[]","name":"affiliateProof","type":"bytes32[]"},{"internalType":"uint256","name":"attributionId","type":"uint256"}],"internalType":"struct ISuperMinterV2.MintTo","name":"p","type":"tuple"}],"name":"computeMintToDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address[]","name":"to","type":"address[]"},{"internalType":"uint32","name":"signedQuantity","type":"uint32"},{"internalType":"uint32","name":"signedClaimTicket","type":"uint32"},{"internalType":"uint32","name":"signedDeadline","type":"uint32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct ISuperMinterV2.PlatformAirdrop","name":"p","type":"tuple"}],"name":"computePlatformAirdropDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint96","name":"price","type":"uint96"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"},{"internalType":"uint32","name":"maxMintable","type":"uint32"},{"internalType":"uint16","name":"affiliateFeeBPS","type":"uint16"},{"internalType":"bytes32","name":"affiliateMerkleRoot","type":"bytes32"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"address","name":"platform","type":"address"},{"internalType":"uint8","name":"mode","type":"uint8"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"internalType":"struct ISuperMinterV2.MintCreation","name":"c","type":"tuple"}],"name":"createEditionMint","outputs":[{"internalType":"uint8","name":"scheduleNum","type":"uint8"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"platform","type":"address"}],"name":"defaultPlatformFeeConfig","outputs":[{"components":[{"internalType":"uint96","name":"artistMintReward","type":"uint96"},{"internalType":"uint96","name":"affiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"platformMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPrice","type":"uint96"},{"internalType":"uint96","name":"thresholdArtistMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdAffiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPlatformMintReward","type":"uint96"},{"internalType":"uint96","name":"platformTxFlatFee","type":"uint96"},{"internalType":"uint16","name":"platformMintFeeBPS","type":"uint16"},{"internalType":"bool","name":"active","type":"bool"}],"internalType":"struct ISuperMinterV2.PlatformFeeConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"platform","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"effectivePlatformFeeConfig","outputs":[{"components":[{"internalType":"uint96","name":"artistMintReward","type":"uint96"},{"internalType":"uint96","name":"affiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"platformMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPrice","type":"uint96"},{"internalType":"uint96","name":"thresholdArtistMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdAffiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPlatformMintReward","type":"uint96"},{"internalType":"uint96","name":"platformTxFlatFee","type":"uint96"},{"internalType":"uint16","name":"platformMintFeeBPS","type":"uint16"},{"internalType":"bool","name":"active","type":"bool"}],"internalType":"struct ISuperMinterV2.PlatformFeeConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eip712Domain","outputs":[{"internalType":"bytes1","name":"fields","type":"bytes1"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"},{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"verifyingContract","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256[]","name":"extensions","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gaPrice","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address","name":"affiliate","type":"address"}],"name":"isAffiliated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"bytes32[]","name":"affiliateProof","type":"bytes32[]"}],"name":"isAffiliatedWithProof","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"}],"name":"mintInfo","outputs":[{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address","name":"platform","type":"address"},{"internalType":"uint96","name":"price","type":"uint96"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"},{"internalType":"uint32","name":"maxMintable","type":"uint32"},{"internalType":"uint32","name":"minted","type":"uint32"},{"internalType":"uint16","name":"affiliateFeeBPS","type":"uint16"},{"internalType":"uint8","name":"mode","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"hasMints","type":"bool"},{"internalType":"bytes32","name":"affiliateMerkleRoot","type":"bytes32"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct ISuperMinterV2.MintInfo","name":"info","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"}],"name":"mintInfoList","outputs":[{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address","name":"platform","type":"address"},{"internalType":"uint96","name":"price","type":"uint96"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"},{"internalType":"uint32","name":"maxMintablePerAccount","type":"uint32"},{"internalType":"uint32","name":"maxMintable","type":"uint32"},{"internalType":"uint32","name":"minted","type":"uint32"},{"internalType":"uint16","name":"affiliateFeeBPS","type":"uint16"},{"internalType":"uint8","name":"mode","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"hasMints","type":"bool"},{"internalType":"bytes32","name":"affiliateMerkleRoot","type":"bytes32"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct ISuperMinterV2.MintInfo[]","name":"a","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint32","name":"quantity","type":"uint32"},{"internalType":"address","name":"allowlisted","type":"address"},{"internalType":"uint32","name":"allowlistedQuantity","type":"uint32"},{"internalType":"bytes32[]","name":"allowlistProof","type":"bytes32[]"},{"internalType":"uint96","name":"signedPrice","type":"uint96"},{"internalType":"uint32","name":"signedQuantity","type":"uint32"},{"internalType":"uint32","name":"signedClaimTicket","type":"uint32"},{"internalType":"uint32","name":"signedDeadline","type":"uint32"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"affiliate","type":"address"},{"internalType":"bytes32[]","name":"affiliateProof","type":"bytes32[]"},{"internalType":"uint256","name":"attributionId","type":"uint256"}],"internalType":"struct ISuperMinterV2.MintTo","name":"p","type":"tuple"}],"name":"mintTo","outputs":[{"internalType":"uint256","name":"fromTokenId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"name_","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"nextScheduleNum","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address","name":"collector","type":"address"}],"name":"numberMinted","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"address[]","name":"to","type":"address[]"},{"internalType":"uint32","name":"signedQuantity","type":"uint32"},{"internalType":"uint32","name":"signedClaimTicket","type":"uint32"},{"internalType":"uint32","name":"signedDeadline","type":"uint32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct ISuperMinterV2.PlatformAirdrop","name":"p","type":"tuple"}],"name":"platformAirdrop","outputs":[{"internalType":"uint256","name":"fromTokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"platformFeeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"platform","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"}],"name":"platformFeeConfig","outputs":[{"components":[{"internalType":"uint96","name":"artistMintReward","type":"uint96"},{"internalType":"uint96","name":"affiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"platformMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPrice","type":"uint96"},{"internalType":"uint96","name":"thresholdArtistMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdAffiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPlatformMintReward","type":"uint96"},{"internalType":"uint96","name":"platformTxFlatFee","type":"uint96"},{"internalType":"uint16","name":"platformMintFeeBPS","type":"uint16"},{"internalType":"bool","name":"active","type":"bool"}],"internalType":"struct ISuperMinterV2.PlatformFeeConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"platformFeesAccrued","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"platformSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint16","name":"bps","type":"uint16"}],"name":"setAffiliateFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"setAffiliateMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint96","name":"artistMintReward","type":"uint96"},{"internalType":"uint96","name":"affiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"platformMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPrice","type":"uint96"},{"internalType":"uint96","name":"thresholdArtistMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdAffiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPlatformMintReward","type":"uint96"},{"internalType":"uint96","name":"platformTxFlatFee","type":"uint96"},{"internalType":"uint16","name":"platformMintFeeBPS","type":"uint16"},{"internalType":"bool","name":"active","type":"bool"}],"internalType":"struct ISuperMinterV2.PlatformFeeConfig","name":"c","type":"tuple"}],"name":"setDefaultPlatformFeeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"price","type":"uint96"}],"name":"setGAPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint32","name":"value","type":"uint32"}],"name":"setMaxMintable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint32","name":"value","type":"uint32"}],"name":"setMaxMintablePerAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"}],"name":"setMerkleRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"setPlatformFeeAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"tier","type":"uint8"},{"components":[{"internalType":"uint96","name":"artistMintReward","type":"uint96"},{"internalType":"uint96","name":"affiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"platformMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPrice","type":"uint96"},{"internalType":"uint96","name":"thresholdArtistMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdAffiliateMintReward","type":"uint96"},{"internalType":"uint96","name":"thresholdPlatformMintReward","type":"uint96"},{"internalType":"uint96","name":"platformTxFlatFee","type":"uint96"},{"internalType":"uint16","name":"platformMintFeeBPS","type":"uint16"},{"internalType":"bool","name":"active","type":"bool"}],"internalType":"struct ISuperMinterV2.PlatformFeeConfig","name":"c","type":"tuple"}],"name":"setPlatformFeeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"setPlatformSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint96","name":"price","type":"uint96"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint32","name":"startTime","type":"uint32"}],"name":"setStartTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint32","name":"startTime","type":"uint32"},{"internalType":"uint32","name":"endTime","type":"uint32"}],"name":"setTimeRange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint32","name":"quantity","type":"uint32"},{"internalType":"bool","name":"hasValidAffiliate","type":"bool"}],"name":"totalPriceAndFees","outputs":[{"components":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"subTotal","type":"uint256"},{"internalType":"uint256","name":"unitPrice","type":"uint256"},{"internalType":"uint256","name":"finalArtistFee","type":"uint256"},{"internalType":"uint256","name":"finalAffiliateFee","type":"uint256"},{"internalType":"uint256","name":"finalPlatformFee","type":"uint256"}],"internalType":"struct ISuperMinterV2.TotalPriceAndFees","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"edition","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"uint8","name":"scheduleNum","type":"uint8"},{"internalType":"uint32","name":"quantity","type":"uint32"},{"internalType":"uint96","name":"signedPrice","type":"uint96"},{"internalType":"bool","name":"hasValidAffiliate","type":"bool"}],"name":"totalPriceAndFeesWithSignedPrice","outputs":[{"components":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"subTotal","type":"uint256"},{"internalType":"uint256","name":"unitPrice","type":"uint256"},{"internalType":"uint256","name":"finalArtistFee","type":"uint256"},{"internalType":"uint256","name":"finalAffiliateFee","type":"uint256"},{"internalType":"uint256","name":"finalPlatformFee","type":"uint256"}],"internalType":"struct ISuperMinterV2.TotalPriceAndFees","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"version_","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"affiliate","type":"address"}],"name":"withdrawForAffiliate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"platform","type":"address"}],"name":"withdrawForPlatform","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6101206040523480156200001257600080fd5b50306080524660a05260608062000061604080518082018252600b81526a29bab832b926b4b73a32b960a91b60208083019190915282518084019093526003835262315f3160e81b9083015291565b815160209283012081519183019190912060c082905260e0819052604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8152938401929092529082015246606082015230608082015260a090206101005250620000cb9050565b60805160a05160c05160e051610100516151676200011060003960006139fa01526000613ab401526000613a8e01526000613a3e01526000613a1b01526151676000f3fe6080604052600436106103545760003560e01c8063a01efa34116101c6578063d3ec6f59116100f7578063ea25045411610095578063f57402961161006f578063f574029614610ae9578063f7b2f1bf14610b09578063fb128c83146103a0578063fe1c0c4b14610b1e57610363565b8063ea25045414610a89578063edb3a0a314610aa9578063ef8e19b814610ac957610363565b8063e3d47d5c116100d1578063e3d47d5c146109fc578063e544144314610a29578063e62a61a714610a49578063e7cb88f114610a6957610363565b8063d3ec6f591461097b578063e1a45218146109b0578063e1f3e17d146109c657610363565b8063b276be3511610164578063c4f0c1c21161013e578063c4f0c1c2146108d7578063cbd8aff214610925578063d03206a414610674578063d379ab5f1461095b57610363565b8063b276be3514610863578063b9ee495414610883578063bd3e8fc9146108a357610363565b8063ab986897116101a0578063ab986897146107c9578063ac1fc22c146107f6578063ae85945714610823578063b05786881461084357610363565b8063a01efa3414610774578063a0aefa2a14610794578063a167fd5f146107b457610363565b8063532cf596116102a057806370304e2f1161023e57806384b0196e1161021857806384b0196e146106ff57806387d4d28c146107275780639375da5a1461075457806393e8bcf9146103f657610363565b806370304e2f1461069d578063752d8e91146106ca578063843f92aa146106ea57610363565b80635e7876821161027a5780635e7876821461061457806361b26ea4146106345780636a7319cf146106545780636c5f55f71461067457610363565b8063532cf5961461056657806354fd4d501461059357806359b9370a146105a857610363565b80631b98e5101161030d57806344a8246f116102e757806344a8246f146104f35780634618d76214610513578063498120a0146105335780634a04a1c91461055357610363565b80631b98e5101461047f57806320606b701461049f5780633b79c44f146104d357610363565b806301ffc9a71461036b5780630597fa30146103a057806306fdde03146103d45780630a25dea9146103f657806310bc37791461041d5780631542b7fc1461045f57610363565b3661036357610361610b3e565b005b610361610b3e565b34801561037757600080fd5b5061038b610386366004614075565b610bd6565b60405190151581526020015b60405180910390f35b3480156103ac57600080fd5b506103bc67016345785d8a000081565b6040516001600160601b039091168152602001610397565b3480156103e057600080fd5b506103e9610c01565b60405161039791906140e5565b34801561040257600080fd5b5061040b600081565b60405160ff9091168152602001610397565b34801561042957600080fd5b506104517fbeeccead3be397d17079af6fbbbb014209a75062141befe787822f16816d9da581565b604051908152602001610397565b34801561046b57600080fd5b5061036161047a366004614129565b610c11565b34801561048b57600080fd5b5061040b61049a366004614176565b610c99565b3480156104ab57600080fd5b506104517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b3480156104df57600080fd5b506103616104ee3660046141ab565b610cd1565b3480156104ff57600080fd5b5061036161050e3660046141dc565b610d45565b34801561051f57600080fd5b5061036161052e366004614243565b610e3a565b34801561053f57600080fd5b5061036161054e3660046142b0565b610f18565b6104516105613660046142fb565b611015565b34801561057257600080fd5b50610586610581366004614176565b6114c0565b6040516103979190614423565b34801561059f57600080fd5b506103e9611657565b3480156105b457600080fd5b506105c86105c336600461444b565b611661565b6040516103979190600060c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b34801561062057600080fd5b5061058661062f3660046141ab565b611699565b34801561064057600080fd5b5061036161064f3660046144c5565b611758565b34801561066057600080fd5b5061038b61066f36600461452c565b6117d1565b34801561068057600080fd5b5061068a6103e881565b60405161ffff9091168152602001610397565b3480156106a957600080fd5b506106bd6106b83660046145b6565b6117f5565b604051610397919061462e565b3480156106d657600080fd5b506105866106e5366004614176565b6118d9565b3480156106f657600080fd5b5061040b600381565b34801561070b57600080fd5b50610714611995565b6040516103979796959493929190614674565b34801561073357600080fd5b506104516107423660046141ab565b60006020819052908152604090205481565b34801561076057600080fd5b5061036161076f3660046141ab565b6119bc565b34801561078057600080fd5b5061036161078f366004614129565b611a31565b3480156107a057600080fd5b506103616107af366004614865565b611ae4565b3480156107c057600080fd5b5061040b600281565b3480156107d557600080fd5b506107e96107e43660046141ab565b611c27565b60405161039791906149c2565b34801561080257600080fd5b506104516108113660046141ab565b60026020526000908152604090205481565b34801561082f57600080fd5b5061040b61083e366004614a05565b611d1d565b34801561084f57600080fd5b5061036161085e366004614243565b612182565b34801561086f57600080fd5b5061036161087e366004614243565b6122ad565b34801561088f57600080fd5b506105c861089e366004614ae5565b6122f5565b3480156108af57600080fd5b506104517fc03e2545e609fd0b7813d6074f00235b048ae7580a8e57070eed03901dd951ae81565b3480156108e357600080fd5b5061090d6108f23660046141ab565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610397565b34801561093157600080fd5b506103bc6109403660046141ab565b6003602052600090815260409020546001600160601b031681565b34801561096757600080fd5b50610361610976366004614b50565b612316565b34801561098757600080fd5b5061099b610996366004614b9b565b6123b5565b60405163ffffffff9091168152602001610397565b3480156109bc57600080fd5b5061068a61271081565b3480156109d257600080fd5b5061090d6109e13660046141ab565b6001602052600090815260409020546001600160a01b031681565b348015610a0857600080fd5b50610a1c610a17366004614bf3565b612404565b6040516103979190614c38565b348015610a3557600080fd5b50610361610a44366004614c47565b61257c565b348015610a5557600080fd5b50610451610a643660046142fb565b612631565b348015610a7557600080fd5b50610451610a84366004614c94565b612777565b348015610a9557600080fd5b50610361610aa4366004614cd0565b612922565b348015610ab557600080fd5b50610361610ac43660046141ab565b612a75565b348015610ad557600080fd5b50610451610ae4366004614c94565b612b1b565b348015610af557600080fd5b50610361610b043660046141ab565b612c2f565b348015610b1557600080fd5b5061040b600181565b348015610b2a57600080fd5b5061038b610b39366004614b9b565b612cb0565b36610b47573636f35b6000805b80368210610b595750610bb5565b600180830192600319810190351860001a9081610ba557600019855260028301933560021984011860001a607f808211610b94578282013888395b16949094019093019250610b4b9050565b8185538085019450505050610b4b565b50600038826000305af490503d6000803e80610bd0573d6000fd5b503d6000f35b60006301ffc9a760e01b6001600160e01b0319831690811463075dd78560e41b909114175b92915050565b6060610c0b612cc9565b50919050565b83610c1b81612d08565b6000610c28868686612e0b565b90506000610c3582612e27565b600281018590556040805160ff808a168252881660208201529081018690529091506001600160a01b038816907fe08051cfd6c9341327f7f5550f77e02e815f59c1ecba22a4ac006ddca62dec20906060015b60405180910390a250505050505050565b600060056000610cab85856000612e0b565b8152602081019190915260400160002060010154600160e01b900460ff16905092915050565b6000610cdb612e6a565b6001600160a01b0381811660008181526004602090815260409182902080546001600160a01b03191694881694851790559051928352929350917fb9aba67a9619eecb4b3e9fe6ded4a35c9bcdbfb1040f5122f91716de616a799391015b60405180910390a25050565b84610d4f81612d08565b6000610d5c878787612e0b565b90506000610d6982612e27565b905060ff8716158015610d82575063ffffffff84811614155b15610da05760405163d25a973560e01b815260040160405180910390fd5b610daa8585612ec8565b60018101805463ffffffff87811667ffffffffffffffff199092168217640100000000918816918202179092556040805160ff808c1682528a1660208201529081019190915260608101919091526001600160a01b038916907f41ad9ed088bad8a3ad3052c7360f6919b647b45d4b527e478d463edbb8f9a4359060800160405180910390a25050505050505050565b83610e4481612d08565b6000610e51868686612e0b565b90506000610e5e82612e27565b905060ff8616158015610e7d57506001810154600160e81b900460ff16155b15610e9b5760405163d25a973560e01b815260040160405180910390fd5b610ea484612ef5565b60018101805463ffffffff60601b1916600160601b63ffffffff8716908102919091179091556040805160ff808a16825288166020820152908101919091526001600160a01b038816907f5da54689220406b0ee18edb07d2007345f96968da27c7fd0f405f649d26040a890606001610c88565b83610f2281612d08565b6000610f2f868686612e0b565b90506000610f3c82612e27565b905060ff8616158015610f5e57506001810154600160e81b900460ff16600214155b15610f7c5760405163d25a973560e01b815260040160405180910390fd5b6001810154600219600160e81b90910460ff1601610fad5760405163d25a973560e01b815260040160405180910390fd5b80546001600160601b038516600160a01b81026001600160a01b039283161783556040805160ff8a811682528916602082015290810191909152908816907f3b082de0ef84f822f97496af03a3df5a8d5f0c271ea658b5b210819f1310494f90606001610c88565b60008061105561105061102b60208601866141ab565b61103b6040870160208801614cfc565b61104b6060880160408901614cfc565b612e0b565b612e27565b905061106081612f1f565b6001810154600160e81b900460ff166000198101611087576110828285612fb3565b6110c2565b60011960ff82160161109d576110828285613134565b60021960ff8216016110c25760405163a0042b1760e01b815260040160405180910390fd5b6110cd81838661329d565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081018290526101808101919091526111486101c086016101a087016141ab565b6001600160a01b031661116160808701606088016141ab565b6001600160a01b031614611186576111816101c086016101a087016141ab565b611189565b60005b6001600160a01b031660c082018190526111b29084906111ad6101c0890189614d17565b6134a3565b151560e082015260006111fb6111ce6040880160208901614cfc565b856111df60a08a0160808b01614d61565b6111f16101208b016101008c016144c5565b8660e001516134f7565b80519091503414611230578051604051630374cb4760e21b815234600482015260248101919091526044015b60405180910390fd5b606081015161014083015260a0810151610180830152608081015161016083018190521561129557610160820151600260006112746101c08a016101a08b016141ab565b6001600160a01b031681526020810191909152604001600020805490910190555b610180820151156112c75761018082015184546001600160a01b03166000908152602081905260409020805490910190555b60006112d660208801886141ab565b90506112e860a0880160808901614d61565b63ffffffff1683526101408301516001600160a01b0382169063eebab8ef9061131760408b0160208c01614cfc565b61132760808c0160608d016141ab565b61133760a08d0160808e01614d61565b6040516001600160e01b031960e087901b16815260ff90931660048401526001600160a01b03909116602483015263ffffffff16604482015260640160206040518083038185885af1158015611391573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906113b69190614d7c565b60208401526113cb60c0880160a089016141ab565b6001600160a01b031660408401526113e960e0880160c08901614d61565b63ffffffff16606084015261140661016088016101408901614d61565b63ffffffff1660a0840152815161010084015260408201516101208401526101e087013561143a6080890160608a016141ab565b6001600160a01b031661145060208a018a6141ab565b6001600160a01b03167f2a29f7402bd32f0e4bbe17d44be064f7f64d96ee174ed7cb27936d869bf9a88861148a60408c0160208d01614cfc565b61149a60608d0160408e01614cfc565b886040516114aa93929190614d95565b60405180910390a4505060200151949350505050565b6114c8613f5f565b606083811b60ff8481169190911760009081526006602090815260409182902082516101408101845281546001600160601b038082168352600160601b918290048116948301949094526001830154808516958301959095529384900483169581019590955260028101548083166080870152839004821660a08601526003015480821660c08601529182041660e0840152600160c01b810461ffff16610100840152600160d01b9004161515610120820181905261163b5760066000606086901b610100178152602080820192909252604090810160002081516101408101835281546001600160601b038082168352600160601b91829004811695830195909552600183015480861694830194909452928390048416606082015260028201548085166080830152839004841660a082015260039091015480841660c083015291820490921660e0830152600160c01b810461ffff16610100830152600160d01b900460ff16151561012082015290505b8061012001516116505761164d613f5f565b90505b9392505050565b6060610bfb612cc9565b611669613fb3565b6000611676888888612e0b565b905061168d8761168583612e27565b8787876134f7565b98975050505050505050565b6116a1613f5f565b50610100606091821b811760009081526006602090815260409182902082516101408101845281546001600160601b038082168352600160601b918290048116948301949094526001830154808516958301959095529384900483169581019590955260028101548083166080870152839004821660a08601526003015480821660c08601529182041660e084015261ffff600160c01b8204169183019190915260ff600160d01b90910416151561012082015290565b6000611762612e6a565b6001600160a01b03811660008181526003602090815260409182902080546bffffffffffffffffffffffff19166001600160601b038816908117909155915191825292935090917fed3d3f99e57c78ce76ac9a1704a72bb912e8f231cc25c6379fdf5354dbb6481b9101610d39565b6000806117df888888612e0b565b905061168d6117ed82612e27565b8686866134a3565b60606000611804878787612e0b565b60008181526008602052604090209091508367ffffffffffffffff81111561182e5761182e61470a565b604051908082528060200260200182016040528015611857578160200160208202803683370190505b50925060005b8085146118cd576118a386868381811061187957611879614e86565b905060200201602081019061188e9190614d61565b63ffffffff16836137d690919063ffffffff16565b8482815181106118b5576118b5614e86565b9115156020928302919091019091015260010161185d565b50505095945050505050565b6118e1613f5f565b5060ff908116606092831b1760009081526006602090815260409182902082516101408101845281546001600160601b038082168352600160601b918290048116948301949094526001830154808516958301959095529384900483169581019590955260028101548083166080870152839004821660a08601526003015480821660c08601529182041660e084015261ffff600160c01b820416610100840152600160d01b900416151561012082015290565b600f60f81b60608060008080836119aa612cc9565b97989097965046955030945091925090565b60006119c6612e6a565b90506119d1826137f8565b6001600160a01b0381811660008181526001602090815260409182902080546001600160a01b0319169487169485179055905192835290917f3a9b87574e9f01aaafa6d829c77645fe96010be0b3093259c7873f4a93de28e99101610d39565b83611a3b81612d08565b6000611a48868686612e0b565b90506000611a5582612e27565b600180820154919250600160e81b90910460ff1614611a875760405163d25a973560e01b815260040160405180910390fd5b611a908461381f565b600381018490556040805160ff8089168252871660208201529081018590526001600160a01b038816907f0b0a6fe894fe7695ac067d44d6e0de766337e9c3b5f0ee0a61be727383aac5a790606001610c88565b6000611aee612e6a565b9050611af98261383d565b8160066000606084901b610100178152602080820192909252604090810160002083518154938501516001600160601b039182166001600160c01b031995861617600160601b9183168202178355858401516001840180546060890151928516908816179184168302919091179055608086015160028401805460a089015192851690881617918416830291909117905560c08601516003909301805460e088015161010089015161012090990151958516919097161795909216029390931762ffffff60c01b1916600160c01b61ffff9095169490940260ff60d01b191693909317600160d01b93151593909302929092179055516001600160a01b038216907fe6bb0d56f1c8a28e8a4fa4c725b521b129a2d80fa461d8365016d98c4775ab0f90610d39908590614423565b606081811b6000908152600560205260409020600181015461ffff600160d01b8204811691600160c01b9004168167ffffffffffffffff811115611c6d57611c6d61470a565b604051908082528060200260200182016040528015611ca657816020015b611c93613fe9565b815260200190600190039081611c8b5790505b5093505b8115611d155761ffff8116606086901b176000908152600560205260409020611cdb8660ff600885901c1684612404565b85846001900394508481518110611cf457611cf4614e86565b602090810291909101015260010154600160b01b900461ffff169050611caa565b505050919050565b6000611d2c8260000151612d08565b611d398260c00151613979565b61014082015160ff8116611d54576000610160840152611dd9565b60001960ff821601611d7357611d6e83610160015161381f565b611dd9565b60011960ff821601611d9657600061016084015263ffffffff6080840152611dd9565b60021960ff821601611dc0576000610160840181905263ffffffff60808501526020840152611dd9565b60405163a0042b1760e01b815260040160405180910390fd5b61010083015160ff16611e1d5763ffffffff60608401819052608084015260ff8116600214611e0a57600060208401525b60ff8116611e1d5763ffffffff60a08401525b611e2f83604001518460600151612ec8565b611e3c83608001516139a0565b611e498360a00151612ef5565b600060056000611e6486600001518761010001516000612e0b565b815260208082019290925260409081016000908120875160601b8252600590935220600180830154600160e01b900460ff1695509192509084016101008110611eaf57611eaf6139c7565b6001808401805460ff909316600160e01b0260ff60e01b19909316929092179091558181015461ffff600160d01b9091041601620100008110611ef457611ef46139c7565b60018201805461ffff60d01b1916600160d01b61ffff8416021790558551610100870151600091611f259188612e0b565b905060006005600083815260200190815260200160002090508761012001518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555087602001518160000160146101000a8154816001600160601b0302191690836001600160601b0316021790555087604001518160010160006101000a81548163ffffffff021916908363ffffffff16021790555087606001518160010160046101000a81548163ffffffff021916908363ffffffff16021790555087608001518160010160086101000a81548163ffffffff021916908363ffffffff1602179055508760a0015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055508760c001518160010160146101000a81548161ffff021916908361ffff16021790555087610140015181600101601d6101000a81548160ff021916908360ff160217905550600181600101601e6101000a81548160ff021916908360ff1602179055508360010160189054906101000a900461ffff168160010160166101000a81548161ffff021916908361ffff1602179055508660ff16600889610100015160ff16901b178460010160186101000a81548161ffff021916908361ffff1602179055506000801b8860e00151146121125760e088015160028201555b610160880151156121295761016088015160038201555b87600001516001600160a01b03167f71e782e300c458b9de1211d63df057e6f372a85a3b394606ac3335907b14f097896101000151898b60405161216f93929190614e9c565b60405180910390a2505050505050919050565b8361218c81612d08565b6000612199868686612e0b565b905060006121a682612e27565b905060ff86166121c95760405163d25a973560e01b815260040160405180910390fd5b6001810154600119600160e81b90910460ff16016121fa5760405163d25a973560e01b815260040160405180910390fd5b6001810154600219600160e81b90910460ff160161222b5760405163d25a973560e01b815260040160405180910390fd5b612234846139a0565b6001810180546bffffffff00000000000000001916600160401b63ffffffff8716908102919091179091556040805160ff808a16825288166020820152908101919091526001600160a01b038816907f674233c20daf715ad9e94f9e5818adc53482b77e9556564e5fe3766678246e8e90606001610c88565b60006122ba858585612e0b565b6000818152600560205260409020600101549091506122ee908690869086908690640100000000900463ffffffff16610d45565b5050505050565b6122fd613fb3565b61230c86868686600087611661565b9695505050505050565b8361232081612d08565b600061232d868686612e0b565b9050600061233a82612e27565b905061234584613979565b60018101805461ffff60a01b1916600160a01b61ffff8716908102919091179091556040805160ff808a16825288166020820152908101919091526001600160a01b038816907fcdff4ec2999e249a9a848accff5e46b43263f82c4076334cd70300e07326472d90606001610c88565b6000806123c3868686612e0b565b6001600160a01b0384166000908152600760209081526040808320600385901c845290915290205490915060e0600583901b161c5b9150505b949350505050565b61240c613fe9565b6000612419858585612e0b565b9050600061242682612e27565b6001600160a01b03808816855260ff8088166020870181905290871660408701528254909116606086015290915015801561247057506001810154600160e81b900460ff16600214155b61248b578054600160a01b90046001600160601b03166124af565b80546001600160a01b03166000908152600360205260409020546001600160601b03165b6001600160601b03166080840152600181015463ffffffff80821660a08601526401000000008204811660c0860152600160401b8204811660e0860152600160601b82048116610100860152600160801b820416610120850152600160a01b810461ffff16610140850152600160e81b810460ff166101608501526002600160f01b909104811615156101808501528101546101c084015260038101546101e0840152546001600160a01b0390811660009081526004602052604090205416610200830152509392505050565b8361258681612d08565b6000612593868686612e0b565b905060006125a082612e27565b60018101549091506125c99060ff600160f01b9091041660028660ff8383161615901518021890565b60018201805460ff60f01b1916600160f01b60ff938416021790556040805188831681529187166020830152851515908201526001600160a01b038816907f81bd379475659273b35365d353d46c7de87aa468a01efc54544fcee90ae0d3b690606001610c88565b6000610bfb7fc03e2545e609fd0b7813d6074f00235b048ae7580a8e57070eed03901dd951ae61266460208501856141ab565b6126746040860160208701614cfc565b6126846060870160408801614cfc565b61269460808801606089016141ab565b6126a661014089016101208a01614d61565b6126b86101608a016101408b01614d61565b6126ca6101208b016101008c016144c5565b6126dc6101808c016101608d01614d61565b6126ee6101c08d016101a08e016141ab565b60408051602081019b909b526001600160a01b03998a16908b015260ff97881660608b015296909516608089015292861660a088015263ffffffff91821660c0880152811660e08701526001600160601b039091166101008601521661012084015216610140820152610160015b604051602081830303815290604052805190602001206139f8565b60008061278d61105061102b60208601866141ab565b905061279881612f1f565b6001810154600160e81b900460ff166003146127c75760405163a0042b1760e01b815260040160405180910390fd5b6127d18184613b10565b6127db8184613bc1565b60006127ea60208501856141ab565b90506001600160a01b03811663010fe62c61280b6040870160208801614cfc565b6128186060880188614d17565b61282860a08a0160808b01614d61565b6040518563ffffffff1660e01b81526004016128479493929190614fe1565b6020604051808303816000875af1158015612866573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061288a9190614d7c565b925061289960208501856141ab565b6001600160a01b03167f0b4410e982ad454e02d2fb1663c16f53389d5126913f7223d14d8a8b311c33246128d36040870160208801614cfc565b6128e36060880160408901614cfc565b6128f06060890189614d17565b61290060a08b0160808c01614d61565b8960405161291396959493929190615015565b60405180910390a25050919050565b600061292c612e6a565b90506129378261383d565b8160066000606084901b60ff8716178152602080820192909252604090810160002083518154938501516001600160601b039182166001600160c01b031995861617600160601b9183168202178355858401516001840180546060890151928516908816179184168302919091179055608086015160028401805460a089015192851690881617918416830291909117905560c08601516003909301805460e088015161010089015161012090990151958516919097161795909216029390931762ffffff60c01b1916600160c01b61ffff9095169490940260ff60d01b191693909317600160d01b93151593909302929092179055516001600160a01b038216907f7fcaf05e0d01e61bfcf3c7d5035259d2bbdb13b68a9c0f183b52d074a3f1110490612a689086908690615056565b60405180910390a2505050565b6001600160a01b0380821660009081526001602052604090205416612a99816137f8565b6001600160a01b0382166000908152602081905260409020548015612b16576001600160a01b038316600090815260208190526040812055612adb8282613d26565b826001600160a01b03167ffc7ad544ff6a06d6499925723d25b6fe70457a42939995b1d3d6f560fe33633382604051612a6891815260200190565b505050565b6000610bfb7fbeeccead3be397d17079af6fbbbb014209a75062141befe787822f16816d9da5612b4e60208501856141ab565b612b5e6040860160208701614cfc565b612b6e6060870160408801614cfc565b612b7b6060880188614d17565b604051602001612b8c92919061506e565b60408051601f198184030181529190528051602090910120612bb460a0890160808a01614d61565b612bc460c08a0160a08b01614d61565b612bd460e08b0160c08c01614d61565b6040805160208101999099526001600160a01b039097169688019690965260ff948516606088015293909216608086015260a085015263ffffffff90811660c085015290811660e0840152166101008201526101200161275c565b6001600160a01b0381166000908152600260205260409020548015612cac576001600160a01b038216600090815260026020526040812055612c718282613d26565b816001600160a01b03167f0a1adaaf9d9caba9cf65528900e946b718d511ebd66ae81d5eb71e7fd0122c4a82604051610d3991815260200190565b5050565b6000612cc08585858536866117d1565b95945050505050565b604080518082018252600b81526a29bab832b926b4b73a32b960a91b60208083019190915282518084019093526003835262315f3160e81b9083015291565b6000612d12612e6a565b9050816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d7691906150b0565b6001600160a01b0316816001600160a01b031614612cac5760405163145398bf60e21b81526001600160a01b0382811660048301526001602483015283169063514e62fc90604401602060405180830381865afa158015612ddb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dff91906150cd565b612cac57612cac613d69565b60008360601b60005282601e5381601f53505060005192915050565b60008181526005602052604081206001808201549192600160f01b909204169003612e655760405163947dbacd60e01b815260040160405180910390fd5b919050565b6000336000526e2fd5aeb385d324b580fca7c83823a0803303612e9857602060008038845afa612e98573838fd5b506dd9ecebf3c23529de49815dac1c4c803303612ec057602060008038845afa612ec0573838fd5b505060005190565b8063ffffffff168263ffffffff161115612cac5760405163536a71af60e01b815260040160405180910390fd5b8063ffffffff16600003612f1c57604051630ccae60160e31b815260040160405180910390fd5b50565b600181015442640100000000820463ffffffff90811682119216111715612f7e57600181015460405163296f4f6960e01b815242600482015263ffffffff80831660248301526401000000009092049091166044820152606401611227565b612f958160010154600160f01b9004600216151590565b15612f1c57604051636be9245d60e11b815260040160405180910390fd5b6000612fc560e0830160c08401614d61565b90506000612fd960c0840160a085016141ab565b90506001600160a01b0381166130025760405163582f497d60e11b815260040160405180910390fd5b63fffffffe1963ffffffff83160161308d57613041846003015461302b836000526014600c2090565b61303860e0870187614d17565b90929091613d77565b15801561306a5750613068846003015461302b8363ffffffff6004526000526018600c2090565b155b156130885760405163582f497d60e11b815260040160405180910390fd5b6130c5565b6130a8846003015461302b83856004526000526018600c2090565b6130c55760405163582f497d60e11b815260040160405180910390fd5b60006130cf612e6a565b90506131096001600160a01b038381169083168114906130f560808801606089016141ab565b6001600160a01b0316149015159015151790565b6122ee576131178183613db1565b6122ee5760405163fe736e0160e01b815260040160405180910390fd5b61314661014082016101208301614d61565b63ffffffff1661315c60a0830160808401614d61565b63ffffffff161115613181576040516352ad28c360e11b815260040160405180910390fd5b81546001600160a01b03908116600090815260046020526040902054166131be816131ab84612631565b6131b96101808601866150ea565b613df2565b6131db57604051638baa579f60e01b815260040160405180910390fd5b6131ed61018083016101608401614d61565b63ffffffff1642111561321357604051630819bdcd60e01b815260040160405180910390fd5b600061324561322560208501856141ab565b6132356040860160208701614cfc565b61104b6060870160408801614cfc565b905061327a61325c61016085016101408601614d61565b60008381526008602052604090209063ffffffff90811690613eeb16565b6132975760405163900bb2c960e01b815260040160405180910390fd5b50505050565b60006132af60a0830160808401614d61565b600184015463ffffffff918216600160801b82048316019250600160601b9004168111156132f057604051637f70f90b60e01b815260040160405180910390fd5b60018301805463ffffffff60801b1916600160801b63ffffffff841602179055600061332261322560208501856141ab565b905060001960ff8616016133fb57600060078161334560c0870160a088016141ab565b6001600160a01b031681526020810191909152604001600020905061337060a0850160808601614d61565b63ffffffff1661338983836139d590919063ffffffff16565b600187015463ffffffff9182169290920194506133cc91600160401b90041684116133ba60e0870160c08801614d61565b63ffffffff1685119015159015151790565b156133ea57604051631b75136560e01b815260040160405180910390fd5b6133f5818385613f17565b506122ee565b600060078161341060808701606088016141ab565b6001600160a01b031681526020810191909152604001600020905061343b60a0850160808601614d61565b63ffffffff1661345483836139d590919063ffffffff16565b600187015463ffffffff918216929092019450600160401b9091041683111561349057604051631b75136560e01b815260040160405180910390fd5b61349b818385613f17565b505050505050565b6002840154600090806134c35750506001600160a01b03831615156123fc565b6123f86001600160a01b03861615156134ee836134e5896000526014600c2090565b88918891613d77565b15159015151690565b6134ff613fb3565b8454600090613517906001600160a01b0316886114c0565b6001870154909150600119600160e81b90910460ff160161357c5785546001600160601b03600160a01b909104811690851610156135685760405163dcdc2f1560e01b815260040160405180910390fd5b6001600160601b03841660408301526135ca565b60ff87166135b25785546001600160a01b031660009081526003602052604090819020546001600160601b0316908301526135ca565b8554600160a01b90046001600160601b031660408301525b604082015163ffffffff8616026020830181905260608301526001860154600160a01b900461ffff16158015906135fe5750825b156136335760208201516001870154600091612710600160a01b90920461ffff16020460608401805182900390526080840152505b61010081015161ffff161561366d57602082015161010082015160009161271061ffff9092160204606084018051829003905260a0840152505b80606001516001600160601b031682604001511161371457805160608301805163ffffffff88166001600160601b039384168102909101909152604083015160a0850180519190931690910201905282156136eb5760208101516080830180516001600160601b0390921663ffffffff8816029190910190526137a3565b602081015160a0830180516001600160601b0390921663ffffffff8816029190910190526137a3565b608081015160608301805163ffffffff88166001600160601b03938416810290910190915260c083015160a08501805191909316909102019052821561377d5760a08101516080830180516001600160601b0390921663ffffffff8816029190910190526137a3565b8463ffffffff168160a001516001600160601b0316028260a00181815101915081815250505b60e0015160a0820180516001600160601b0390921690910190819052608082015160608301510101815295945050505050565b600881901c6000908152602092909252604090912054600160ff9092161c1690565b6001600160a01b038116612f1c576040516362ccef3360e01b815260040160405180910390fd5b80612f1c5760405163caa2867f60e01b815260040160405180910390fd5b61395b61388067016345785d8a00006001600160601b03168360e001516001600160601b0316116103e861ffff1684610100015161ffff16119015159015151790565b6138eb67016345785d8a00006001600160601b031684600001516001600160601b03161167016345785d8a00006001600160601b031685602001516001600160601b03161167016345785d8a00006001600160601b031686604001516001600160601b031611613f4b565b61395667016345785d8a00006001600160601b031685608001516001600160601b03161167016345785d8a00006001600160601b03168660a001516001600160601b03161167016345785d8a00006001600160601b03168760c001516001600160601b031611613f4b565b613f4b565b15612f1c5760405163b17424c360e01b815260040160405180910390fd5b6103e861ffff82161115612f1c57604051631a52ce6f60e01b815260040160405180910390fd5b8063ffffffff16600003612f1c5760405163a017714560e01b815260040160405180910390fd5b6335278d126000526004601cfd5b600381901c600090815260209290925260409091205460059190911b60e0161c90565b7f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000030147f0000000000000000000000000000000000000000000000000000000000000000461416613aeb5750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527f000000000000000000000000000000000000000000000000000000000000000060208201527f00000000000000000000000000000000000000000000000000000000000000009181019190915246606082015230608082015260a090205b67190100000000000060005280601a5281603a52604260182090506000603a52919050565b81546001600160a01b0390811660009081526004602052604090205416613b4781613b3a84612b1b565b6131b960e08601866150ea565b613b6457604051638baa579f60e01b815260040160405180910390fd5b613b7460e0830160c08401614d61565b63ffffffff16421115613b9a57604051630819bdcd60e01b815260040160405180910390fd5b6000613bac61322560208501856141ab565b905061327a61325c60c0850160a08601614d61565b6000613bf3613bd360208401846141ab565b613be36040850160208601614cfc565b61104b6060860160408701614cfc565b90506000613c046060840184614d17565b915060009050613c1a60a0850160808601614d61565b600186015463ffffffff9182168402600160801b82048316019250600160601b900416811115613c5d57604051637f70f90b60e01b815260040160405180910390fd5b60018501805463ffffffff60801b1916600160801b63ffffffff84160217905560005b82811461349b576000600781613c996060890189614d17565b85818110613ca957613ca9614e86565b9050602002016020810190613cbe91906141ab565b6001600160a01b0316815260208101919091526040016000209050613d1d85613ced60a0890160808a01614d61565b63ffffffff16613d0688856139d590919063ffffffff16565b63ffffffff160183613f179092919063ffffffff16565b50600101613c80565b80471015613d3c5763b12d13eb6000526004601cfd5b6000386000388486620186a0f1612cac57816000526073600b5360ff6020536016600b82f0612cac573838fd5b6382b429006000526004601cfd5b60008315613da9578360051b8501855b803580851160051b94855260209485185260406000209301818110613d875750505b501492915050565b600060405163e839bd536000528360205282604052602060006064601c6c447e69651d841bd8d104bed4935afa600160005114169150806040525092915050565b6001600160a01b0390931692600084156123fc576040518460005260408303613e5d5760208481013560ff81901c601b01825285356040526001600160ff1b0316606052600160806000825afa805187183d1517613e5b575060006060526040525060016123fc565b505b60418303613ea057604084013560001a602052604084604037602060016080600060015afa805187183d1517613e9e575060006060526040525060016123fc565b505b600060605280604052631626ba7e60e01b80825285600483015260248201604081528460448401528486606485013760208160648701858b5afa905190911416915050949350505050565b602091909152600881901c6000908152604090208054600160ff90931683811b909118918290551c1690565b826020528160031c60005260406000206007831660051b815463ffffffff8482841c188116831b8218845550505050505050565b6000831515831515831515171515176123fc565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805161022081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e0810182905261020081019190915290565b60006020828403121561408757600080fd5b81356001600160e01b03198116811461165057600080fd5b6000815180845260005b818110156140c5576020818501810151868301820152016140a9565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000611650602083018461409f565b6001600160a01b0381168114612f1c57600080fd5b8035612e65816140f8565b803560ff81168114612e6557600080fd5b6000806000806080858703121561413f57600080fd5b843561414a816140f8565b935061415860208601614118565b925061416660408601614118565b9396929550929360600135925050565b6000806040838503121561418957600080fd5b8235614194816140f8565b91506141a260208401614118565b90509250929050565b6000602082840312156141bd57600080fd5b8135611650816140f8565b803563ffffffff81168114612e6557600080fd5b600080600080600060a086880312156141f457600080fd5b85356141ff816140f8565b945061420d60208701614118565b935061421b60408701614118565b9250614229606087016141c8565b9150614237608087016141c8565b90509295509295909350565b6000806000806080858703121561425957600080fd5b8435614264816140f8565b935061427260208601614118565b925061428060408601614118565b915061428e606086016141c8565b905092959194509250565b80356001600160601b0381168114612e6557600080fd5b600080600080608085870312156142c657600080fd5b84356142d1816140f8565b93506142df60208601614118565b92506142ed60408601614118565b915061428e60608601614299565b60006020828403121561430d57600080fd5b813567ffffffffffffffff81111561432457600080fd5b8201610200818503121561165057600080fd5b80516001600160601b03168252602081015161435e60208401826001600160601b03169052565b50604081015161437960408401826001600160601b03169052565b50606081015161439460608401826001600160601b03169052565b5060808101516143af60808401826001600160601b03169052565b5060a08101516143ca60a08401826001600160601b03169052565b5060c08101516143e560c08401826001600160601b03169052565b5060e081015161440060e08401826001600160601b03169052565b506101008181015161ffff16908301526101208082015180151582850152613297565b6101408101610bfb8284614337565b8015158114612f1c57600080fd5b8035612e6581614432565b60008060008060008060c0878903121561446457600080fd5b863561446f816140f8565b955061447d60208801614118565b945061448b60408801614118565b9350614499606088016141c8565b92506144a760808801614299565b915060a08701356144b781614432565b809150509295509295509295565b6000602082840312156144d757600080fd5b61165082614299565b60008083601f8401126144f257600080fd5b50813567ffffffffffffffff81111561450a57600080fd5b6020830191508360208260051b850101111561452557600080fd5b9250929050565b60008060008060008060a0878903121561454557600080fd5b8635614550816140f8565b955061455e60208801614118565b945061456c60408801614118565b9350606087013561457c816140f8565b9250608087013567ffffffffffffffff81111561459857600080fd5b6145a489828a016144e0565b979a9699509497509295939492505050565b6000806000806000608086880312156145ce57600080fd5b85356145d9816140f8565b94506145e760208701614118565b93506145f560408701614118565b9250606086013567ffffffffffffffff81111561461157600080fd5b61461d888289016144e0565b969995985093965092949392505050565b6020808252825182820181905260009190848201906040850190845b8181101561466857835115158352928401929184019160010161464a565b50909695505050505050565b60ff60f81b881681526000602060e08184015261469460e084018a61409f565b83810360408501526146a6818a61409f565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156146f8578351835292840192918401916001016146dc565b50909c9b505050505050505050505050565b634e487b7160e01b600052604160045260246000fd5b604051610140810167ffffffffffffffff8111828210171561475257634e487b7160e01b600052604160045260246000fd5b60405290565b604051610180810167ffffffffffffffff8111828210171561475257634e487b7160e01b600052604160045260246000fd5b803561ffff81168114612e6557600080fd5b600061014082840312156147af57600080fd5b6147b7614720565b90506147c282614299565b81526147d060208301614299565b60208201526147e160408301614299565b60408201526147f260608301614299565b606082015261480360808301614299565b608082015261481460a08301614299565b60a082015261482560c08301614299565b60c082015261483660e08301614299565b60e082015261010061484981840161478a565b9082015261012061485b838201614440565b9082015292915050565b6000610140828403121561487857600080fd5b611650838361479c565b80516001600160a01b0316825260208101516148a3602084018260ff169052565b5060408101516148b8604084018260ff169052565b5060608101516148d360608401826001600160a01b03169052565b5060808101516148ee60808401826001600160601b03169052565b5060a081015161490660a084018263ffffffff169052565b5060c081015161491e60c084018263ffffffff169052565b5060e081015161493660e084018263ffffffff169052565b506101008181015163ffffffff9081169184019190915261012080830151909116908301526101408082015161ffff16908301526101608082015160ff1690830152610180808201511515908301526101a0808201511515908301526101c080820151908301526101e08082015190830152610200808201516001600160a01b03811682850152613297565b6020808252825182820181905260009190848201906040850190845b81811015614668576149f1838551614882565b9284019261022092909201916001016149de565b60006101808284031215614a1857600080fd5b614a20614758565b614a298361410d565b8152614a3760208401614299565b6020820152614a48604084016141c8565b6040820152614a59606084016141c8565b6060820152614a6a608084016141c8565b6080820152614a7b60a084016141c8565b60a0820152614a8c60c0840161478a565b60c082015260e083013560e0820152610100614aa9818501614118565b90820152610120614abb84820161410d565b90820152610140614acd848201614118565b90820152610160928301359281019290925250919050565b600080600080600060a08688031215614afd57600080fd5b8535614b08816140f8565b9450614b1660208701614118565b9350614b2460408701614118565b9250614b32606087016141c8565b91506080860135614b4281614432565b809150509295509295909350565b60008060008060808587031215614b6657600080fd5b8435614b71816140f8565b9350614b7f60208601614118565b9250614b8d60408601614118565b915061428e6060860161478a565b60008060008060808587031215614bb157600080fd5b8435614bbc816140f8565b9350614bca60208601614118565b9250614bd860408601614118565b91506060850135614be8816140f8565b939692955090935050565b600080600060608486031215614c0857600080fd5b8335614c13816140f8565b9250614c2160208501614118565b9150614c2f60408501614118565b90509250925092565b6102208101610bfb8284614882565b60008060008060808587031215614c5d57600080fd5b8435614c68816140f8565b9350614c7660208601614118565b9250614c8460408601614118565b91506060850135614be881614432565b600060208284031215614ca657600080fd5b813567ffffffffffffffff811115614cbd57600080fd5b8201610100818503121561165057600080fd5b6000806101608385031215614ce457600080fd5b614ced83614118565b91506141a2846020850161479c565b600060208284031215614d0e57600080fd5b61165082614118565b6000808335601e19843603018112614d2e57600080fd5b83018035915067ffffffffffffffff821115614d4957600080fd5b6020019150600581901b360382131561452557600080fd5b600060208284031215614d7357600080fd5b611650826141c8565b600060208284031215614d8e57600080fd5b5051919050565b60ff848116825283166020820152815163ffffffff1660408201526101e081016020830151606083015260408301516001600160a01b038116608084015250606083015163ffffffff811660a084015250608083015163ffffffff811660c08401525060a083015163ffffffff811660e08401525060c0830151610100614e26818501836001600160a01b03169052565b60e08501519150610120614e3d8186018415159052565b908501516101408581019190915290850151610160808601919091529085015161018080860191909152908501516101a0850152909301516101c0909201919091529392505050565b634e487b7160e01b600052603260045260246000fd5b60ff84811682528316602082015281516001600160a01b031660408201526101c0810160208301516001600160601b038116606084015250604083015163ffffffff8116608084015250606083015163ffffffff811660a084015250608083015163ffffffff811660c08401525060a083015163ffffffff811660e08401525060c0830151610100614f338185018361ffff169052565b60e08501516101208581019190915290850151915061014090614f5a8286018460ff169052565b8501519150610160614f76858201846001600160a01b03169052565b9085015160ff16610180850152909301516101a0909201919091529392505050565b8183526000602080850194508260005b85811015614fd6578135614fbb816140f8565b6001600160a01b031687529582019590820190600101614fa8565b509495945050505050565b60ff85168152606060208201526000614ffe606083018587614f98565b905063ffffffff8316604083015295945050505050565b60ff8716815260ff8616602082015260a06040820152600061503b60a083018688614f98565b63ffffffff9490941660608301525060800152949350505050565b60ff8316815261016081016116506020830184614337565b60008184825b858110156150a5578135615087816140f8565b6001600160a01b031683526020928301929190910190600101615074565b509095945050505050565b6000602082840312156150c257600080fd5b8151611650816140f8565b6000602082840312156150df57600080fd5b815161165081614432565b6000808335601e1984360301811261510157600080fd5b83018035915067ffffffffffffffff82111561511c57600080fd5b60200191503681900382131561452557600080fdfea26469706673582212207ebafb7b76188b79b0bde174d599a0d340478ed83ec0a06d25b34aede972729964736f6c63430008130033
Deployed Bytecode
0x6080604052600436106103545760003560e01c8063a01efa34116101c6578063d3ec6f59116100f7578063ea25045411610095578063f57402961161006f578063f574029614610ae9578063f7b2f1bf14610b09578063fb128c83146103a0578063fe1c0c4b14610b1e57610363565b8063ea25045414610a89578063edb3a0a314610aa9578063ef8e19b814610ac957610363565b8063e3d47d5c116100d1578063e3d47d5c146109fc578063e544144314610a29578063e62a61a714610a49578063e7cb88f114610a6957610363565b8063d3ec6f591461097b578063e1a45218146109b0578063e1f3e17d146109c657610363565b8063b276be3511610164578063c4f0c1c21161013e578063c4f0c1c2146108d7578063cbd8aff214610925578063d03206a414610674578063d379ab5f1461095b57610363565b8063b276be3514610863578063b9ee495414610883578063bd3e8fc9146108a357610363565b8063ab986897116101a0578063ab986897146107c9578063ac1fc22c146107f6578063ae85945714610823578063b05786881461084357610363565b8063a01efa3414610774578063a0aefa2a14610794578063a167fd5f146107b457610363565b8063532cf596116102a057806370304e2f1161023e57806384b0196e1161021857806384b0196e146106ff57806387d4d28c146107275780639375da5a1461075457806393e8bcf9146103f657610363565b806370304e2f1461069d578063752d8e91146106ca578063843f92aa146106ea57610363565b80635e7876821161027a5780635e7876821461061457806361b26ea4146106345780636a7319cf146106545780636c5f55f71461067457610363565b8063532cf5961461056657806354fd4d501461059357806359b9370a146105a857610363565b80631b98e5101161030d57806344a8246f116102e757806344a8246f146104f35780634618d76214610513578063498120a0146105335780634a04a1c91461055357610363565b80631b98e5101461047f57806320606b701461049f5780633b79c44f146104d357610363565b806301ffc9a71461036b5780630597fa30146103a057806306fdde03146103d45780630a25dea9146103f657806310bc37791461041d5780631542b7fc1461045f57610363565b3661036357610361610b3e565b005b610361610b3e565b34801561037757600080fd5b5061038b610386366004614075565b610bd6565b60405190151581526020015b60405180910390f35b3480156103ac57600080fd5b506103bc67016345785d8a000081565b6040516001600160601b039091168152602001610397565b3480156103e057600080fd5b506103e9610c01565b60405161039791906140e5565b34801561040257600080fd5b5061040b600081565b60405160ff9091168152602001610397565b34801561042957600080fd5b506104517fbeeccead3be397d17079af6fbbbb014209a75062141befe787822f16816d9da581565b604051908152602001610397565b34801561046b57600080fd5b5061036161047a366004614129565b610c11565b34801561048b57600080fd5b5061040b61049a366004614176565b610c99565b3480156104ab57600080fd5b506104517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b3480156104df57600080fd5b506103616104ee3660046141ab565b610cd1565b3480156104ff57600080fd5b5061036161050e3660046141dc565b610d45565b34801561051f57600080fd5b5061036161052e366004614243565b610e3a565b34801561053f57600080fd5b5061036161054e3660046142b0565b610f18565b6104516105613660046142fb565b611015565b34801561057257600080fd5b50610586610581366004614176565b6114c0565b6040516103979190614423565b34801561059f57600080fd5b506103e9611657565b3480156105b457600080fd5b506105c86105c336600461444b565b611661565b6040516103979190600060c082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015292915050565b34801561062057600080fd5b5061058661062f3660046141ab565b611699565b34801561064057600080fd5b5061036161064f3660046144c5565b611758565b34801561066057600080fd5b5061038b61066f36600461452c565b6117d1565b34801561068057600080fd5b5061068a6103e881565b60405161ffff9091168152602001610397565b3480156106a957600080fd5b506106bd6106b83660046145b6565b6117f5565b604051610397919061462e565b3480156106d657600080fd5b506105866106e5366004614176565b6118d9565b3480156106f657600080fd5b5061040b600381565b34801561070b57600080fd5b50610714611995565b6040516103979796959493929190614674565b34801561073357600080fd5b506104516107423660046141ab565b60006020819052908152604090205481565b34801561076057600080fd5b5061036161076f3660046141ab565b6119bc565b34801561078057600080fd5b5061036161078f366004614129565b611a31565b3480156107a057600080fd5b506103616107af366004614865565b611ae4565b3480156107c057600080fd5b5061040b600281565b3480156107d557600080fd5b506107e96107e43660046141ab565b611c27565b60405161039791906149c2565b34801561080257600080fd5b506104516108113660046141ab565b60026020526000908152604090205481565b34801561082f57600080fd5b5061040b61083e366004614a05565b611d1d565b34801561084f57600080fd5b5061036161085e366004614243565b612182565b34801561086f57600080fd5b5061036161087e366004614243565b6122ad565b34801561088f57600080fd5b506105c861089e366004614ae5565b6122f5565b3480156108af57600080fd5b506104517fc03e2545e609fd0b7813d6074f00235b048ae7580a8e57070eed03901dd951ae81565b3480156108e357600080fd5b5061090d6108f23660046141ab565b6004602052600090815260409020546001600160a01b031681565b6040516001600160a01b039091168152602001610397565b34801561093157600080fd5b506103bc6109403660046141ab565b6003602052600090815260409020546001600160601b031681565b34801561096757600080fd5b50610361610976366004614b50565b612316565b34801561098757600080fd5b5061099b610996366004614b9b565b6123b5565b60405163ffffffff9091168152602001610397565b3480156109bc57600080fd5b5061068a61271081565b3480156109d257600080fd5b5061090d6109e13660046141ab565b6001602052600090815260409020546001600160a01b031681565b348015610a0857600080fd5b50610a1c610a17366004614bf3565b612404565b6040516103979190614c38565b348015610a3557600080fd5b50610361610a44366004614c47565b61257c565b348015610a5557600080fd5b50610451610a643660046142fb565b612631565b348015610a7557600080fd5b50610451610a84366004614c94565b612777565b348015610a9557600080fd5b50610361610aa4366004614cd0565b612922565b348015610ab557600080fd5b50610361610ac43660046141ab565b612a75565b348015610ad557600080fd5b50610451610ae4366004614c94565b612b1b565b348015610af557600080fd5b50610361610b043660046141ab565b612c2f565b348015610b1557600080fd5b5061040b600181565b348015610b2a57600080fd5b5061038b610b39366004614b9b565b612cb0565b36610b47573636f35b6000805b80368210610b595750610bb5565b600180830192600319810190351860001a9081610ba557600019855260028301933560021984011860001a607f808211610b94578282013888395b16949094019093019250610b4b9050565b8185538085019450505050610b4b565b50600038826000305af490503d6000803e80610bd0573d6000fd5b503d6000f35b60006301ffc9a760e01b6001600160e01b0319831690811463075dd78560e41b909114175b92915050565b6060610c0b612cc9565b50919050565b83610c1b81612d08565b6000610c28868686612e0b565b90506000610c3582612e27565b600281018590556040805160ff808a168252881660208201529081018690529091506001600160a01b038816907fe08051cfd6c9341327f7f5550f77e02e815f59c1ecba22a4ac006ddca62dec20906060015b60405180910390a250505050505050565b600060056000610cab85856000612e0b565b8152602081019190915260400160002060010154600160e01b900460ff16905092915050565b6000610cdb612e6a565b6001600160a01b0381811660008181526004602090815260409182902080546001600160a01b03191694881694851790559051928352929350917fb9aba67a9619eecb4b3e9fe6ded4a35c9bcdbfb1040f5122f91716de616a799391015b60405180910390a25050565b84610d4f81612d08565b6000610d5c878787612e0b565b90506000610d6982612e27565b905060ff8716158015610d82575063ffffffff84811614155b15610da05760405163d25a973560e01b815260040160405180910390fd5b610daa8585612ec8565b60018101805463ffffffff87811667ffffffffffffffff199092168217640100000000918816918202179092556040805160ff808c1682528a1660208201529081019190915260608101919091526001600160a01b038916907f41ad9ed088bad8a3ad3052c7360f6919b647b45d4b527e478d463edbb8f9a4359060800160405180910390a25050505050505050565b83610e4481612d08565b6000610e51868686612e0b565b90506000610e5e82612e27565b905060ff8616158015610e7d57506001810154600160e81b900460ff16155b15610e9b5760405163d25a973560e01b815260040160405180910390fd5b610ea484612ef5565b60018101805463ffffffff60601b1916600160601b63ffffffff8716908102919091179091556040805160ff808a16825288166020820152908101919091526001600160a01b038816907f5da54689220406b0ee18edb07d2007345f96968da27c7fd0f405f649d26040a890606001610c88565b83610f2281612d08565b6000610f2f868686612e0b565b90506000610f3c82612e27565b905060ff8616158015610f5e57506001810154600160e81b900460ff16600214155b15610f7c5760405163d25a973560e01b815260040160405180910390fd5b6001810154600219600160e81b90910460ff1601610fad5760405163d25a973560e01b815260040160405180910390fd5b80546001600160601b038516600160a01b81026001600160a01b039283161783556040805160ff8a811682528916602082015290810191909152908816907f3b082de0ef84f822f97496af03a3df5a8d5f0c271ea658b5b210819f1310494f90606001610c88565b60008061105561105061102b60208601866141ab565b61103b6040870160208801614cfc565b61104b6060880160408901614cfc565b612e0b565b612e27565b905061106081612f1f565b6001810154600160e81b900460ff166000198101611087576110828285612fb3565b6110c2565b60011960ff82160161109d576110828285613134565b60021960ff8216016110c25760405163a0042b1760e01b815260040160405180910390fd5b6110cd81838661329d565b604080516101a081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290526101208101829052610140810182905261016081018290526101808101919091526111486101c086016101a087016141ab565b6001600160a01b031661116160808701606088016141ab565b6001600160a01b031614611186576111816101c086016101a087016141ab565b611189565b60005b6001600160a01b031660c082018190526111b29084906111ad6101c0890189614d17565b6134a3565b151560e082015260006111fb6111ce6040880160208901614cfc565b856111df60a08a0160808b01614d61565b6111f16101208b016101008c016144c5565b8660e001516134f7565b80519091503414611230578051604051630374cb4760e21b815234600482015260248101919091526044015b60405180910390fd5b606081015161014083015260a0810151610180830152608081015161016083018190521561129557610160820151600260006112746101c08a016101a08b016141ab565b6001600160a01b031681526020810191909152604001600020805490910190555b610180820151156112c75761018082015184546001600160a01b03166000908152602081905260409020805490910190555b60006112d660208801886141ab565b90506112e860a0880160808901614d61565b63ffffffff1683526101408301516001600160a01b0382169063eebab8ef9061131760408b0160208c01614cfc565b61132760808c0160608d016141ab565b61133760a08d0160808e01614d61565b6040516001600160e01b031960e087901b16815260ff90931660048401526001600160a01b03909116602483015263ffffffff16604482015260640160206040518083038185885af1158015611391573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906113b69190614d7c565b60208401526113cb60c0880160a089016141ab565b6001600160a01b031660408401526113e960e0880160c08901614d61565b63ffffffff16606084015261140661016088016101408901614d61565b63ffffffff1660a0840152815161010084015260408201516101208401526101e087013561143a6080890160608a016141ab565b6001600160a01b031661145060208a018a6141ab565b6001600160a01b03167f2a29f7402bd32f0e4bbe17d44be064f7f64d96ee174ed7cb27936d869bf9a88861148a60408c0160208d01614cfc565b61149a60608d0160408e01614cfc565b886040516114aa93929190614d95565b60405180910390a4505060200151949350505050565b6114c8613f5f565b606083811b60ff8481169190911760009081526006602090815260409182902082516101408101845281546001600160601b038082168352600160601b918290048116948301949094526001830154808516958301959095529384900483169581019590955260028101548083166080870152839004821660a08601526003015480821660c08601529182041660e0840152600160c01b810461ffff16610100840152600160d01b9004161515610120820181905261163b5760066000606086901b610100178152602080820192909252604090810160002081516101408101835281546001600160601b038082168352600160601b91829004811695830195909552600183015480861694830194909452928390048416606082015260028201548085166080830152839004841660a082015260039091015480841660c083015291820490921660e0830152600160c01b810461ffff16610100830152600160d01b900460ff16151561012082015290505b8061012001516116505761164d613f5f565b90505b9392505050565b6060610bfb612cc9565b611669613fb3565b6000611676888888612e0b565b905061168d8761168583612e27565b8787876134f7565b98975050505050505050565b6116a1613f5f565b50610100606091821b811760009081526006602090815260409182902082516101408101845281546001600160601b038082168352600160601b918290048116948301949094526001830154808516958301959095529384900483169581019590955260028101548083166080870152839004821660a08601526003015480821660c08601529182041660e084015261ffff600160c01b8204169183019190915260ff600160d01b90910416151561012082015290565b6000611762612e6a565b6001600160a01b03811660008181526003602090815260409182902080546bffffffffffffffffffffffff19166001600160601b038816908117909155915191825292935090917fed3d3f99e57c78ce76ac9a1704a72bb912e8f231cc25c6379fdf5354dbb6481b9101610d39565b6000806117df888888612e0b565b905061168d6117ed82612e27565b8686866134a3565b60606000611804878787612e0b565b60008181526008602052604090209091508367ffffffffffffffff81111561182e5761182e61470a565b604051908082528060200260200182016040528015611857578160200160208202803683370190505b50925060005b8085146118cd576118a386868381811061187957611879614e86565b905060200201602081019061188e9190614d61565b63ffffffff16836137d690919063ffffffff16565b8482815181106118b5576118b5614e86565b9115156020928302919091019091015260010161185d565b50505095945050505050565b6118e1613f5f565b5060ff908116606092831b1760009081526006602090815260409182902082516101408101845281546001600160601b038082168352600160601b918290048116948301949094526001830154808516958301959095529384900483169581019590955260028101548083166080870152839004821660a08601526003015480821660c08601529182041660e084015261ffff600160c01b820416610100840152600160d01b900416151561012082015290565b600f60f81b60608060008080836119aa612cc9565b97989097965046955030945091925090565b60006119c6612e6a565b90506119d1826137f8565b6001600160a01b0381811660008181526001602090815260409182902080546001600160a01b0319169487169485179055905192835290917f3a9b87574e9f01aaafa6d829c77645fe96010be0b3093259c7873f4a93de28e99101610d39565b83611a3b81612d08565b6000611a48868686612e0b565b90506000611a5582612e27565b600180820154919250600160e81b90910460ff1614611a875760405163d25a973560e01b815260040160405180910390fd5b611a908461381f565b600381018490556040805160ff8089168252871660208201529081018590526001600160a01b038816907f0b0a6fe894fe7695ac067d44d6e0de766337e9c3b5f0ee0a61be727383aac5a790606001610c88565b6000611aee612e6a565b9050611af98261383d565b8160066000606084901b610100178152602080820192909252604090810160002083518154938501516001600160601b039182166001600160c01b031995861617600160601b9183168202178355858401516001840180546060890151928516908816179184168302919091179055608086015160028401805460a089015192851690881617918416830291909117905560c08601516003909301805460e088015161010089015161012090990151958516919097161795909216029390931762ffffff60c01b1916600160c01b61ffff9095169490940260ff60d01b191693909317600160d01b93151593909302929092179055516001600160a01b038216907fe6bb0d56f1c8a28e8a4fa4c725b521b129a2d80fa461d8365016d98c4775ab0f90610d39908590614423565b606081811b6000908152600560205260409020600181015461ffff600160d01b8204811691600160c01b9004168167ffffffffffffffff811115611c6d57611c6d61470a565b604051908082528060200260200182016040528015611ca657816020015b611c93613fe9565b815260200190600190039081611c8b5790505b5093505b8115611d155761ffff8116606086901b176000908152600560205260409020611cdb8660ff600885901c1684612404565b85846001900394508481518110611cf457611cf4614e86565b602090810291909101015260010154600160b01b900461ffff169050611caa565b505050919050565b6000611d2c8260000151612d08565b611d398260c00151613979565b61014082015160ff8116611d54576000610160840152611dd9565b60001960ff821601611d7357611d6e83610160015161381f565b611dd9565b60011960ff821601611d9657600061016084015263ffffffff6080840152611dd9565b60021960ff821601611dc0576000610160840181905263ffffffff60808501526020840152611dd9565b60405163a0042b1760e01b815260040160405180910390fd5b61010083015160ff16611e1d5763ffffffff60608401819052608084015260ff8116600214611e0a57600060208401525b60ff8116611e1d5763ffffffff60a08401525b611e2f83604001518460600151612ec8565b611e3c83608001516139a0565b611e498360a00151612ef5565b600060056000611e6486600001518761010001516000612e0b565b815260208082019290925260409081016000908120875160601b8252600590935220600180830154600160e01b900460ff1695509192509084016101008110611eaf57611eaf6139c7565b6001808401805460ff909316600160e01b0260ff60e01b19909316929092179091558181015461ffff600160d01b9091041601620100008110611ef457611ef46139c7565b60018201805461ffff60d01b1916600160d01b61ffff8416021790558551610100870151600091611f259188612e0b565b905060006005600083815260200190815260200160002090508761012001518160000160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555087602001518160000160146101000a8154816001600160601b0302191690836001600160601b0316021790555087604001518160010160006101000a81548163ffffffff021916908363ffffffff16021790555087606001518160010160046101000a81548163ffffffff021916908363ffffffff16021790555087608001518160010160086101000a81548163ffffffff021916908363ffffffff1602179055508760a0015181600101600c6101000a81548163ffffffff021916908363ffffffff1602179055508760c001518160010160146101000a81548161ffff021916908361ffff16021790555087610140015181600101601d6101000a81548160ff021916908360ff160217905550600181600101601e6101000a81548160ff021916908360ff1602179055508360010160189054906101000a900461ffff168160010160166101000a81548161ffff021916908361ffff1602179055508660ff16600889610100015160ff16901b178460010160186101000a81548161ffff021916908361ffff1602179055506000801b8860e00151146121125760e088015160028201555b610160880151156121295761016088015160038201555b87600001516001600160a01b03167f71e782e300c458b9de1211d63df057e6f372a85a3b394606ac3335907b14f097896101000151898b60405161216f93929190614e9c565b60405180910390a2505050505050919050565b8361218c81612d08565b6000612199868686612e0b565b905060006121a682612e27565b905060ff86166121c95760405163d25a973560e01b815260040160405180910390fd5b6001810154600119600160e81b90910460ff16016121fa5760405163d25a973560e01b815260040160405180910390fd5b6001810154600219600160e81b90910460ff160161222b5760405163d25a973560e01b815260040160405180910390fd5b612234846139a0565b6001810180546bffffffff00000000000000001916600160401b63ffffffff8716908102919091179091556040805160ff808a16825288166020820152908101919091526001600160a01b038816907f674233c20daf715ad9e94f9e5818adc53482b77e9556564e5fe3766678246e8e90606001610c88565b60006122ba858585612e0b565b6000818152600560205260409020600101549091506122ee908690869086908690640100000000900463ffffffff16610d45565b5050505050565b6122fd613fb3565b61230c86868686600087611661565b9695505050505050565b8361232081612d08565b600061232d868686612e0b565b9050600061233a82612e27565b905061234584613979565b60018101805461ffff60a01b1916600160a01b61ffff8716908102919091179091556040805160ff808a16825288166020820152908101919091526001600160a01b038816907fcdff4ec2999e249a9a848accff5e46b43263f82c4076334cd70300e07326472d90606001610c88565b6000806123c3868686612e0b565b6001600160a01b0384166000908152600760209081526040808320600385901c845290915290205490915060e0600583901b161c5b9150505b949350505050565b61240c613fe9565b6000612419858585612e0b565b9050600061242682612e27565b6001600160a01b03808816855260ff8088166020870181905290871660408701528254909116606086015290915015801561247057506001810154600160e81b900460ff16600214155b61248b578054600160a01b90046001600160601b03166124af565b80546001600160a01b03166000908152600360205260409020546001600160601b03165b6001600160601b03166080840152600181015463ffffffff80821660a08601526401000000008204811660c0860152600160401b8204811660e0860152600160601b82048116610100860152600160801b820416610120850152600160a01b810461ffff16610140850152600160e81b810460ff166101608501526002600160f01b909104811615156101808501528101546101c084015260038101546101e0840152546001600160a01b0390811660009081526004602052604090205416610200830152509392505050565b8361258681612d08565b6000612593868686612e0b565b905060006125a082612e27565b60018101549091506125c99060ff600160f01b9091041660028660ff8383161615901518021890565b60018201805460ff60f01b1916600160f01b60ff938416021790556040805188831681529187166020830152851515908201526001600160a01b038816907f81bd379475659273b35365d353d46c7de87aa468a01efc54544fcee90ae0d3b690606001610c88565b6000610bfb7fc03e2545e609fd0b7813d6074f00235b048ae7580a8e57070eed03901dd951ae61266460208501856141ab565b6126746040860160208701614cfc565b6126846060870160408801614cfc565b61269460808801606089016141ab565b6126a661014089016101208a01614d61565b6126b86101608a016101408b01614d61565b6126ca6101208b016101008c016144c5565b6126dc6101808c016101608d01614d61565b6126ee6101c08d016101a08e016141ab565b60408051602081019b909b526001600160a01b03998a16908b015260ff97881660608b015296909516608089015292861660a088015263ffffffff91821660c0880152811660e08701526001600160601b039091166101008601521661012084015216610140820152610160015b604051602081830303815290604052805190602001206139f8565b60008061278d61105061102b60208601866141ab565b905061279881612f1f565b6001810154600160e81b900460ff166003146127c75760405163a0042b1760e01b815260040160405180910390fd5b6127d18184613b10565b6127db8184613bc1565b60006127ea60208501856141ab565b90506001600160a01b03811663010fe62c61280b6040870160208801614cfc565b6128186060880188614d17565b61282860a08a0160808b01614d61565b6040518563ffffffff1660e01b81526004016128479493929190614fe1565b6020604051808303816000875af1158015612866573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061288a9190614d7c565b925061289960208501856141ab565b6001600160a01b03167f0b4410e982ad454e02d2fb1663c16f53389d5126913f7223d14d8a8b311c33246128d36040870160208801614cfc565b6128e36060880160408901614cfc565b6128f06060890189614d17565b61290060a08b0160808c01614d61565b8960405161291396959493929190615015565b60405180910390a25050919050565b600061292c612e6a565b90506129378261383d565b8160066000606084901b60ff8716178152602080820192909252604090810160002083518154938501516001600160601b039182166001600160c01b031995861617600160601b9183168202178355858401516001840180546060890151928516908816179184168302919091179055608086015160028401805460a089015192851690881617918416830291909117905560c08601516003909301805460e088015161010089015161012090990151958516919097161795909216029390931762ffffff60c01b1916600160c01b61ffff9095169490940260ff60d01b191693909317600160d01b93151593909302929092179055516001600160a01b038216907f7fcaf05e0d01e61bfcf3c7d5035259d2bbdb13b68a9c0f183b52d074a3f1110490612a689086908690615056565b60405180910390a2505050565b6001600160a01b0380821660009081526001602052604090205416612a99816137f8565b6001600160a01b0382166000908152602081905260409020548015612b16576001600160a01b038316600090815260208190526040812055612adb8282613d26565b826001600160a01b03167ffc7ad544ff6a06d6499925723d25b6fe70457a42939995b1d3d6f560fe33633382604051612a6891815260200190565b505050565b6000610bfb7fbeeccead3be397d17079af6fbbbb014209a75062141befe787822f16816d9da5612b4e60208501856141ab565b612b5e6040860160208701614cfc565b612b6e6060870160408801614cfc565b612b7b6060880188614d17565b604051602001612b8c92919061506e565b60408051601f198184030181529190528051602090910120612bb460a0890160808a01614d61565b612bc460c08a0160a08b01614d61565b612bd460e08b0160c08c01614d61565b6040805160208101999099526001600160a01b039097169688019690965260ff948516606088015293909216608086015260a085015263ffffffff90811660c085015290811660e0840152166101008201526101200161275c565b6001600160a01b0381166000908152600260205260409020548015612cac576001600160a01b038216600090815260026020526040812055612c718282613d26565b816001600160a01b03167f0a1adaaf9d9caba9cf65528900e946b718d511ebd66ae81d5eb71e7fd0122c4a82604051610d3991815260200190565b5050565b6000612cc08585858536866117d1565b95945050505050565b604080518082018252600b81526a29bab832b926b4b73a32b960a91b60208083019190915282518084019093526003835262315f3160e81b9083015291565b6000612d12612e6a565b9050816001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d7691906150b0565b6001600160a01b0316816001600160a01b031614612cac5760405163145398bf60e21b81526001600160a01b0382811660048301526001602483015283169063514e62fc90604401602060405180830381865afa158015612ddb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612dff91906150cd565b612cac57612cac613d69565b60008360601b60005282601e5381601f53505060005192915050565b60008181526005602052604081206001808201549192600160f01b909204169003612e655760405163947dbacd60e01b815260040160405180910390fd5b919050565b6000336000526e2fd5aeb385d324b580fca7c83823a0803303612e9857602060008038845afa612e98573838fd5b506dd9ecebf3c23529de49815dac1c4c803303612ec057602060008038845afa612ec0573838fd5b505060005190565b8063ffffffff168263ffffffff161115612cac5760405163536a71af60e01b815260040160405180910390fd5b8063ffffffff16600003612f1c57604051630ccae60160e31b815260040160405180910390fd5b50565b600181015442640100000000820463ffffffff90811682119216111715612f7e57600181015460405163296f4f6960e01b815242600482015263ffffffff80831660248301526401000000009092049091166044820152606401611227565b612f958160010154600160f01b9004600216151590565b15612f1c57604051636be9245d60e11b815260040160405180910390fd5b6000612fc560e0830160c08401614d61565b90506000612fd960c0840160a085016141ab565b90506001600160a01b0381166130025760405163582f497d60e11b815260040160405180910390fd5b63fffffffe1963ffffffff83160161308d57613041846003015461302b836000526014600c2090565b61303860e0870187614d17565b90929091613d77565b15801561306a5750613068846003015461302b8363ffffffff6004526000526018600c2090565b155b156130885760405163582f497d60e11b815260040160405180910390fd5b6130c5565b6130a8846003015461302b83856004526000526018600c2090565b6130c55760405163582f497d60e11b815260040160405180910390fd5b60006130cf612e6a565b90506131096001600160a01b038381169083168114906130f560808801606089016141ab565b6001600160a01b0316149015159015151790565b6122ee576131178183613db1565b6122ee5760405163fe736e0160e01b815260040160405180910390fd5b61314661014082016101208301614d61565b63ffffffff1661315c60a0830160808401614d61565b63ffffffff161115613181576040516352ad28c360e11b815260040160405180910390fd5b81546001600160a01b03908116600090815260046020526040902054166131be816131ab84612631565b6131b96101808601866150ea565b613df2565b6131db57604051638baa579f60e01b815260040160405180910390fd5b6131ed61018083016101608401614d61565b63ffffffff1642111561321357604051630819bdcd60e01b815260040160405180910390fd5b600061324561322560208501856141ab565b6132356040860160208701614cfc565b61104b6060870160408801614cfc565b905061327a61325c61016085016101408601614d61565b60008381526008602052604090209063ffffffff90811690613eeb16565b6132975760405163900bb2c960e01b815260040160405180910390fd5b50505050565b60006132af60a0830160808401614d61565b600184015463ffffffff918216600160801b82048316019250600160601b9004168111156132f057604051637f70f90b60e01b815260040160405180910390fd5b60018301805463ffffffff60801b1916600160801b63ffffffff841602179055600061332261322560208501856141ab565b905060001960ff8616016133fb57600060078161334560c0870160a088016141ab565b6001600160a01b031681526020810191909152604001600020905061337060a0850160808601614d61565b63ffffffff1661338983836139d590919063ffffffff16565b600187015463ffffffff9182169290920194506133cc91600160401b90041684116133ba60e0870160c08801614d61565b63ffffffff1685119015159015151790565b156133ea57604051631b75136560e01b815260040160405180910390fd5b6133f5818385613f17565b506122ee565b600060078161341060808701606088016141ab565b6001600160a01b031681526020810191909152604001600020905061343b60a0850160808601614d61565b63ffffffff1661345483836139d590919063ffffffff16565b600187015463ffffffff918216929092019450600160401b9091041683111561349057604051631b75136560e01b815260040160405180910390fd5b61349b818385613f17565b505050505050565b6002840154600090806134c35750506001600160a01b03831615156123fc565b6123f86001600160a01b03861615156134ee836134e5896000526014600c2090565b88918891613d77565b15159015151690565b6134ff613fb3565b8454600090613517906001600160a01b0316886114c0565b6001870154909150600119600160e81b90910460ff160161357c5785546001600160601b03600160a01b909104811690851610156135685760405163dcdc2f1560e01b815260040160405180910390fd5b6001600160601b03841660408301526135ca565b60ff87166135b25785546001600160a01b031660009081526003602052604090819020546001600160601b0316908301526135ca565b8554600160a01b90046001600160601b031660408301525b604082015163ffffffff8616026020830181905260608301526001860154600160a01b900461ffff16158015906135fe5750825b156136335760208201516001870154600091612710600160a01b90920461ffff16020460608401805182900390526080840152505b61010081015161ffff161561366d57602082015161010082015160009161271061ffff9092160204606084018051829003905260a0840152505b80606001516001600160601b031682604001511161371457805160608301805163ffffffff88166001600160601b039384168102909101909152604083015160a0850180519190931690910201905282156136eb5760208101516080830180516001600160601b0390921663ffffffff8816029190910190526137a3565b602081015160a0830180516001600160601b0390921663ffffffff8816029190910190526137a3565b608081015160608301805163ffffffff88166001600160601b03938416810290910190915260c083015160a08501805191909316909102019052821561377d5760a08101516080830180516001600160601b0390921663ffffffff8816029190910190526137a3565b8463ffffffff168160a001516001600160601b0316028260a00181815101915081815250505b60e0015160a0820180516001600160601b0390921690910190819052608082015160608301510101815295945050505050565b600881901c6000908152602092909252604090912054600160ff9092161c1690565b6001600160a01b038116612f1c576040516362ccef3360e01b815260040160405180910390fd5b80612f1c5760405163caa2867f60e01b815260040160405180910390fd5b61395b61388067016345785d8a00006001600160601b03168360e001516001600160601b0316116103e861ffff1684610100015161ffff16119015159015151790565b6138eb67016345785d8a00006001600160601b031684600001516001600160601b03161167016345785d8a00006001600160601b031685602001516001600160601b03161167016345785d8a00006001600160601b031686604001516001600160601b031611613f4b565b61395667016345785d8a00006001600160601b031685608001516001600160601b03161167016345785d8a00006001600160601b03168660a001516001600160601b03161167016345785d8a00006001600160601b03168760c001516001600160601b031611613f4b565b613f4b565b15612f1c5760405163b17424c360e01b815260040160405180910390fd5b6103e861ffff82161115612f1c57604051631a52ce6f60e01b815260040160405180910390fd5b8063ffffffff16600003612f1c5760405163a017714560e01b815260040160405180910390fd5b6335278d126000526004601cfd5b600381901c600090815260209290925260409091205460059190911b60e0161c90565b7f26482c2ccfd6bc416cd1fb0622c316b8698f986bbeb1dca3edfb52fdd46d85487f000000000000000000000000000000000001a36777f9930aaeff623771b13e7030147f000000000000000000000000000000000000000000000000000000000000000a461416613aeb5750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81527fa6cb2587267be99efde5eb570922efe1ef200501c220db4e8df4187255e6c05060208201527f7bc1c9889e0858302721aa6da0318e4e6eb7eab947465105c4873f8c5c6ee34c9181019190915246606082015230608082015260a090205b67190100000000000060005280601a5281603a52604260182090506000603a52919050565b81546001600160a01b0390811660009081526004602052604090205416613b4781613b3a84612b1b565b6131b960e08601866150ea565b613b6457604051638baa579f60e01b815260040160405180910390fd5b613b7460e0830160c08401614d61565b63ffffffff16421115613b9a57604051630819bdcd60e01b815260040160405180910390fd5b6000613bac61322560208501856141ab565b905061327a61325c60c0850160a08601614d61565b6000613bf3613bd360208401846141ab565b613be36040850160208601614cfc565b61104b6060860160408701614cfc565b90506000613c046060840184614d17565b915060009050613c1a60a0850160808601614d61565b600186015463ffffffff9182168402600160801b82048316019250600160601b900416811115613c5d57604051637f70f90b60e01b815260040160405180910390fd5b60018501805463ffffffff60801b1916600160801b63ffffffff84160217905560005b82811461349b576000600781613c996060890189614d17565b85818110613ca957613ca9614e86565b9050602002016020810190613cbe91906141ab565b6001600160a01b0316815260208101919091526040016000209050613d1d85613ced60a0890160808a01614d61565b63ffffffff16613d0688856139d590919063ffffffff16565b63ffffffff160183613f179092919063ffffffff16565b50600101613c80565b80471015613d3c5763b12d13eb6000526004601cfd5b6000386000388486620186a0f1612cac57816000526073600b5360ff6020536016600b82f0612cac573838fd5b6382b429006000526004601cfd5b60008315613da9578360051b8501855b803580851160051b94855260209485185260406000209301818110613d875750505b501492915050565b600060405163e839bd536000528360205282604052602060006064601c6c447e69651d841bd8d104bed4935afa600160005114169150806040525092915050565b6001600160a01b0390931692600084156123fc576040518460005260408303613e5d5760208481013560ff81901c601b01825285356040526001600160ff1b0316606052600160806000825afa805187183d1517613e5b575060006060526040525060016123fc565b505b60418303613ea057604084013560001a602052604084604037602060016080600060015afa805187183d1517613e9e575060006060526040525060016123fc565b505b600060605280604052631626ba7e60e01b80825285600483015260248201604081528460448401528486606485013760208160648701858b5afa905190911416915050949350505050565b602091909152600881901c6000908152604090208054600160ff90931683811b909118918290551c1690565b826020528160031c60005260406000206007831660051b815463ffffffff8482841c188116831b8218845550505050505050565b6000831515831515831515171515176123fc565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b6040518060c001604052806000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040805161022081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810182905261018081018290526101a081018290526101c081018290526101e0810182905261020081019190915290565b60006020828403121561408757600080fd5b81356001600160e01b03198116811461165057600080fd5b6000815180845260005b818110156140c5576020818501810151868301820152016140a9565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000611650602083018461409f565b6001600160a01b0381168114612f1c57600080fd5b8035612e65816140f8565b803560ff81168114612e6557600080fd5b6000806000806080858703121561413f57600080fd5b843561414a816140f8565b935061415860208601614118565b925061416660408601614118565b9396929550929360600135925050565b6000806040838503121561418957600080fd5b8235614194816140f8565b91506141a260208401614118565b90509250929050565b6000602082840312156141bd57600080fd5b8135611650816140f8565b803563ffffffff81168114612e6557600080fd5b600080600080600060a086880312156141f457600080fd5b85356141ff816140f8565b945061420d60208701614118565b935061421b60408701614118565b9250614229606087016141c8565b9150614237608087016141c8565b90509295509295909350565b6000806000806080858703121561425957600080fd5b8435614264816140f8565b935061427260208601614118565b925061428060408601614118565b915061428e606086016141c8565b905092959194509250565b80356001600160601b0381168114612e6557600080fd5b600080600080608085870312156142c657600080fd5b84356142d1816140f8565b93506142df60208601614118565b92506142ed60408601614118565b915061428e60608601614299565b60006020828403121561430d57600080fd5b813567ffffffffffffffff81111561432457600080fd5b8201610200818503121561165057600080fd5b80516001600160601b03168252602081015161435e60208401826001600160601b03169052565b50604081015161437960408401826001600160601b03169052565b50606081015161439460608401826001600160601b03169052565b5060808101516143af60808401826001600160601b03169052565b5060a08101516143ca60a08401826001600160601b03169052565b5060c08101516143e560c08401826001600160601b03169052565b5060e081015161440060e08401826001600160601b03169052565b506101008181015161ffff16908301526101208082015180151582850152613297565b6101408101610bfb8284614337565b8015158114612f1c57600080fd5b8035612e6581614432565b60008060008060008060c0878903121561446457600080fd5b863561446f816140f8565b955061447d60208801614118565b945061448b60408801614118565b9350614499606088016141c8565b92506144a760808801614299565b915060a08701356144b781614432565b809150509295509295509295565b6000602082840312156144d757600080fd5b61165082614299565b60008083601f8401126144f257600080fd5b50813567ffffffffffffffff81111561450a57600080fd5b6020830191508360208260051b850101111561452557600080fd5b9250929050565b60008060008060008060a0878903121561454557600080fd5b8635614550816140f8565b955061455e60208801614118565b945061456c60408801614118565b9350606087013561457c816140f8565b9250608087013567ffffffffffffffff81111561459857600080fd5b6145a489828a016144e0565b979a9699509497509295939492505050565b6000806000806000608086880312156145ce57600080fd5b85356145d9816140f8565b94506145e760208701614118565b93506145f560408701614118565b9250606086013567ffffffffffffffff81111561461157600080fd5b61461d888289016144e0565b969995985093965092949392505050565b6020808252825182820181905260009190848201906040850190845b8181101561466857835115158352928401929184019160010161464a565b50909695505050505050565b60ff60f81b881681526000602060e08184015261469460e084018a61409f565b83810360408501526146a6818a61409f565b606085018990526001600160a01b038816608086015260a0850187905284810360c0860152855180825283870192509083019060005b818110156146f8578351835292840192918401916001016146dc565b50909c9b505050505050505050505050565b634e487b7160e01b600052604160045260246000fd5b604051610140810167ffffffffffffffff8111828210171561475257634e487b7160e01b600052604160045260246000fd5b60405290565b604051610180810167ffffffffffffffff8111828210171561475257634e487b7160e01b600052604160045260246000fd5b803561ffff81168114612e6557600080fd5b600061014082840312156147af57600080fd5b6147b7614720565b90506147c282614299565b81526147d060208301614299565b60208201526147e160408301614299565b60408201526147f260608301614299565b606082015261480360808301614299565b608082015261481460a08301614299565b60a082015261482560c08301614299565b60c082015261483660e08301614299565b60e082015261010061484981840161478a565b9082015261012061485b838201614440565b9082015292915050565b6000610140828403121561487857600080fd5b611650838361479c565b80516001600160a01b0316825260208101516148a3602084018260ff169052565b5060408101516148b8604084018260ff169052565b5060608101516148d360608401826001600160a01b03169052565b5060808101516148ee60808401826001600160601b03169052565b5060a081015161490660a084018263ffffffff169052565b5060c081015161491e60c084018263ffffffff169052565b5060e081015161493660e084018263ffffffff169052565b506101008181015163ffffffff9081169184019190915261012080830151909116908301526101408082015161ffff16908301526101608082015160ff1690830152610180808201511515908301526101a0808201511515908301526101c080820151908301526101e08082015190830152610200808201516001600160a01b03811682850152613297565b6020808252825182820181905260009190848201906040850190845b81811015614668576149f1838551614882565b9284019261022092909201916001016149de565b60006101808284031215614a1857600080fd5b614a20614758565b614a298361410d565b8152614a3760208401614299565b6020820152614a48604084016141c8565b6040820152614a59606084016141c8565b6060820152614a6a608084016141c8565b6080820152614a7b60a084016141c8565b60a0820152614a8c60c0840161478a565b60c082015260e083013560e0820152610100614aa9818501614118565b90820152610120614abb84820161410d565b90820152610140614acd848201614118565b90820152610160928301359281019290925250919050565b600080600080600060a08688031215614afd57600080fd5b8535614b08816140f8565b9450614b1660208701614118565b9350614b2460408701614118565b9250614b32606087016141c8565b91506080860135614b4281614432565b809150509295509295909350565b60008060008060808587031215614b6657600080fd5b8435614b71816140f8565b9350614b7f60208601614118565b9250614b8d60408601614118565b915061428e6060860161478a565b60008060008060808587031215614bb157600080fd5b8435614bbc816140f8565b9350614bca60208601614118565b9250614bd860408601614118565b91506060850135614be8816140f8565b939692955090935050565b600080600060608486031215614c0857600080fd5b8335614c13816140f8565b9250614c2160208501614118565b9150614c2f60408501614118565b90509250925092565b6102208101610bfb8284614882565b60008060008060808587031215614c5d57600080fd5b8435614c68816140f8565b9350614c7660208601614118565b9250614c8460408601614118565b91506060850135614be881614432565b600060208284031215614ca657600080fd5b813567ffffffffffffffff811115614cbd57600080fd5b8201610100818503121561165057600080fd5b6000806101608385031215614ce457600080fd5b614ced83614118565b91506141a2846020850161479c565b600060208284031215614d0e57600080fd5b61165082614118565b6000808335601e19843603018112614d2e57600080fd5b83018035915067ffffffffffffffff821115614d4957600080fd5b6020019150600581901b360382131561452557600080fd5b600060208284031215614d7357600080fd5b611650826141c8565b600060208284031215614d8e57600080fd5b5051919050565b60ff848116825283166020820152815163ffffffff1660408201526101e081016020830151606083015260408301516001600160a01b038116608084015250606083015163ffffffff811660a084015250608083015163ffffffff811660c08401525060a083015163ffffffff811660e08401525060c0830151610100614e26818501836001600160a01b03169052565b60e08501519150610120614e3d8186018415159052565b908501516101408581019190915290850151610160808601919091529085015161018080860191909152908501516101a0850152909301516101c0909201919091529392505050565b634e487b7160e01b600052603260045260246000fd5b60ff84811682528316602082015281516001600160a01b031660408201526101c0810160208301516001600160601b038116606084015250604083015163ffffffff8116608084015250606083015163ffffffff811660a084015250608083015163ffffffff811660c08401525060a083015163ffffffff811660e08401525060c0830151610100614f338185018361ffff169052565b60e08501516101208581019190915290850151915061014090614f5a8286018460ff169052565b8501519150610160614f76858201846001600160a01b03169052565b9085015160ff16610180850152909301516101a0909201919091529392505050565b8183526000602080850194508260005b85811015614fd6578135614fbb816140f8565b6001600160a01b031687529582019590820190600101614fa8565b509495945050505050565b60ff85168152606060208201526000614ffe606083018587614f98565b905063ffffffff8316604083015295945050505050565b60ff8716815260ff8616602082015260a06040820152600061503b60a083018688614f98565b63ffffffff9490941660608301525060800152949350505050565b60ff8316815261016081016116506020830184614337565b60008184825b858110156150a5578135615087816140f8565b6001600160a01b031683526020928301929190910190600101615074565b509095945050505050565b6000602082840312156150c257600080fd5b8151611650816140f8565b6000602082840312156150df57600080fd5b815161165081614432565b6000808335601e1984360301811261510157600080fd5b83018035915067ffffffffffffffff82111561511c57600080fd5b60200191503681900382131561452557600080fdfea26469706673582212207ebafb7b76188b79b0bde174d599a0d340478ed83ec0a06d25b34aede972729964736f6c63430008130033
Deployed Bytecode Sourcemap
1041:46050:3:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;22458:19;:17;:19::i;:::-;1041:46050;;22335:19;:17;:19::i;29725:224::-;;;;;;;;;;-1:-1:-1;29725:224:3;;;;;:::i;:::-;;:::i;:::-;;;566:14:21;;559:22;541:41;;529:2;514:18;29725:224:3;;;;;;;;5170:54;;;;;;;;;;;;5215:9;5170:54;;;;;-1:-1:-1;;;;;870:39:21;;;852:58;;840:2;825:18;5170:54:3;708:208:21;29387:112:3;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;4325:33::-;;;;;;;;;;;;4357:1;4325:33;;;;;1826:4:21;1814:17;;;1796:36;;1784:2;1769:18;4325:33:3;1654:184:21;3711:413:3;;;;;;;;;;;;3798:326;3711:413;;;;;1989:25:21;;;1977:2;1962:18;3711:413:3;1843:177:21;17054:407:3;;;;;;;;;;-1:-1:-1;17054:407:3;;;;;:::i;:::-;;:::i;24702:164::-;;;;;;;;;;-1:-1:-1;24702:164:3;;;;;:::i;:::-;;:::i;4201:58::-;;;;;;;;;;-1:-1:-1;4201:58:3;1250:66:13;4201:58:3;;21986:204;;;;;;;;;;-1:-1:-1;21986:204:3;;;;;:::i;:::-;;:::i;15510:656::-;;;;;;;;;;-1:-1:-1;15510:656:3;;;;;:::i;:::-;;:::i;18387:569::-;;;;;;;;;;-1:-1:-1;18387:569:3;;;;;:::i;:::-;;:::i;14306:676::-;;;;;;;;;;-1:-1:-1;14306:676:3;;;;;:::i;:::-;;:::i;10813:2439::-;;;;;;:::i;:::-;;:::i;27112:387::-;;;;;;;;;;-1:-1:-1;27112:387:3;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;29555:121::-;;;;;;;;;;;;;:::i;24214:432::-;;;;;;;;;;-1:-1:-1;24214:432:3;;;;;:::i;:::-;;:::i;:::-;;;;;;8520:4:21;8562:3;8551:9;8547:19;8539:27;;8599:6;8593:13;8582:9;8575:32;8663:4;8655:6;8651:17;8645:24;8638:4;8627:9;8623:20;8616:54;8726:4;8718:6;8714:17;8708:24;8701:4;8690:9;8686:20;8679:54;8789:4;8781:6;8777:17;8771:24;8764:4;8753:9;8749:20;8742:54;8852:4;8844:6;8840:17;8834:24;8827:4;8816:9;8812:20;8805:54;8915:4;8907:6;8903:17;8897:24;8890:4;8879:9;8875:20;8868:54;8358:570;;;;;26862:194:3;;;;;;;;;;-1:-1:-1;26862:194:3;;;;;:::i;:::-;;:::i;21751:179::-;;;;;;;;;;-1:-1:-1;21751:179:3;;;;;:::i;:::-;;:::i;25264:377::-;;;;;;;;;;-1:-1:-1;25264:377:3;;;;;:::i;:::-;;:::i;4880:51::-;;;;;;;;;;;;4927:4;4880:51;;;;;10528:6:21;10516:19;;;10498:38;;10486:2;10471:18;4880:51:3;10354:188:21;26028:544:3;;;;;;;;;;-1:-1:-1;26028:544:3;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;26628:178::-;;;;;;;;;;-1:-1:-1;26628:178:3;;;;;:::i;:::-;;:::i;4633:42::-;;;;;;;;;;;;4674:1;4633:42;;6989:596:13;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;:::i;6275:54:3:-;;;;;;;;;;-1:-1:-1;6275:54:3;;;;;:::i;:::-;;;;;;;;;;;;;;;20703:273;;;;;;;;;;-1:-1:-1;20703:273:3;;;;;:::i;:::-;;:::i;19012:502::-;;;;;;;;;;-1:-1:-1;19012:502:3;;;;;:::i;:::-;;:::i;21383:312::-;;;;;;;;;;-1:-1:-1;21383:312:3;;;;;:::i;:::-;;:::i;4524:42::-;;;;;;;;;;;;4565:1;4524:42;;27555:751;;;;;;;;;;-1:-1:-1;27555:751:3;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;6538:55::-;;;;;;;;;;-1:-1:-1;6538:55:3;;;;;:::i;:::-;;;;;;;;;;;;;;7658:3099;;;;;;;;;;-1:-1:-1;7658:3099:3;;;;;:::i;:::-;;:::i;17517:814::-;;;;;;;;;;-1:-1:-1;17517:814:3;;;;;:::i;:::-;;:::i;16222:296::-;;;;;;;;;;-1:-1:-1;16222:296:3;;;;;:::i;:::-;;:::i;23833:325::-;;;;;;;;;;-1:-1:-1;23833:325:3;;;;;:::i;:::-;;:::i;3149:468::-;;;;;;;;;;;;3227:390;3149:468;;6785:49;;;;;;;;;;-1:-1:-1;6785:49:3;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;6785:49:3;;;;;;-1:-1:-1;;;;;20158:32:21;;;20140:51;;20128:2;20113:18;6785:49:3;19994:203:21;6664:41:3;;;;;;;;;;-1:-1:-1;6664:41:3;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;6664:41:3;;;16574:424;;;;;;;;;;-1:-1:-1;16574:424:3;;;;;:::i;:::-;;:::i;24922:286::-;;;;;;;;;;-1:-1:-1;24922:286:3;;;;;:::i;:::-;;:::i;:::-;;;21375:10:21;21363:23;;;21345:42;;21333:2;21318:18;24922:286:3;21201:192:21;4751:63:3;;;;;;;;;;;;1495:5:2;4751:63:3;;6407:53;;;;;;;;;;-1:-1:-1;6407:53:3;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;6407:53:3;;;28362:969;;;;;;;;;;-1:-1:-1;28362:969:3;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;15038:416::-;;;;;;;;;;-1:-1:-1;15038:416:3;;;;;:::i;:::-;;:::i;22733:496::-;;;;;;;;;;-1:-1:-1;22733:496:3;;;;;:::i;:::-;;:::i;13308:775::-;;;;;;;;;;-1:-1:-1;13308:775:3;;;;;:::i;:::-;;:::i;21032:295::-;;;;;;;;;;-1:-1:-1;21032:295:3;;;;;:::i;:::-;;:::i;20073:438::-;;;;;;;;;;-1:-1:-1;20073:438:3;;;;;:::i;:::-;;:::i;23285:492::-;;;;;;;;;;-1:-1:-1;23285:492:3;;;;;:::i;:::-;;:::i;19677:340::-;;;;;;;;;;-1:-1:-1;19677:340:3;;;;;:::i;:::-;;:::i;4420:39::-;;;;;;;;;;;;4458:1;4420:39;;25697:275;;;;;;;;;;-1:-1:-1;25697:275:3;;;;;:::i;:::-;;:::i;11272:1126:17:-;11346:14;11336:68;;11346:14;;11364:38;11336:68;11426:1;;11503:628;11522:21;11346:14;11525:1;11522:21;;;-1:-1:-1;;;11522:21:17;11643:1;11636:9;;;;-1:-1:-1;;11586:9:17;;11597:15;;11582:31;11426:1;11574:40;;;11662:394;;-1:-1:-1;;11856:17:17;;11718:9;11772;;;11729:15;-1:-1:-1;;11718:9:17;;11714:31;11426:1;11706:40;11910:4;11904:11;;;11894:61;;11643:1;11947;11943:9;11931:10;11928:1;11919:34;11894:61;11992:12;11981:28;;;;;;;;-1:-1:-1;11503:628:17;;-1:-1:-1;11503:628:17;11662:394;12084:1;12081;12073:13;11643:1;12112;12108:9;12103:14;;;;;11503:628;;;11507:14;11426:1;12199:10;12196:1;11426;12179:9;12172:5;12159:57;12144:72;;12256:16;11426:1;;12229:44;12296:7;12286:53;;12320:16;11426:1;12307:30;12286:53;;12365:16;11426:1;12352:30;29725:224:3;29801:4;-1:-1:-1;;;;;;;;;29846:47:3;;29895:46;;;-1:-1:-1;;;29846:47:3;;;3385:40:2;29836:106:3;29817:125;29725:224;-1:-1:-1;;29725:224:3:o;29387:112::-;29426:19;29469:23;:21;:23::i;:::-;-1:-1:-1;29457:35:3;29387:112;-1:-1:-1;29387:112:3:o;17054:407::-;17217:7;30393:40;30425:7;30393:31;:40::i;:::-;17236:14:::1;17253:41;17267:7;17276:4;17282:11;17253:13;:41::i;:::-;17236:58;;17304:18;17325:20;17338:6;17325:12;:20::i;:::-;17355:21;::::0;::::1;:28:::0;;;17398:56:::1;::::0;;23520:4:21;23508:17;;;23490:36;;23562:17;;23557:2;23542:18;;23535:45;23596:18;;;23589:34;;;17304:41:3;;-1:-1:-1;;;;;;17398:56:3;::::1;::::0;::::1;::::0;23478:2:21;23463:18;17398:56:3::1;;;;;;;;17226:235;;17054:407:::0;;;;;:::o;24702:164::-;24777:5;24801:9;:42;24811:31;24825:7;24834:4;24840:1;24811:13;:31::i;:::-;24801:42;;;;;;;;;;;-1:-1:-1;24801:42:3;:58;;;-1:-1:-1;;;24801:58:3;;;;;-1:-1:-1;24702:164:3;;;;:::o;21986:204::-;22046:14;22063:31;:29;:31::i;:::-;-1:-1:-1;;;;;22104:22:3;;;;;;;:14;:22;;;;;;;;;:31;;-1:-1:-1;;;;;;22104:31:3;;;;;;;;;22150:33;;20140:51:21;;;22104:22:3;;-1:-1:-1;22104:22:3;22150:33;;20113:18:21;22150:33:3;;;;;;;;22036:154;21986:204;:::o;15510:656::-;15691:7;30393:40;30425:7;30393:31;:40::i;:::-;15710:14:::1;15727:41;15741:7;15750:4;15756:11;15727:13;:41::i;:::-;15710:58;;15778:18;15799:20;15812:6;15799:12;:20::i;:::-;15778:41:::0;-1:-1:-1;15902:15:3::1;::::0;::::1;::::0;:46;::::1;;;-1:-1:-1::0;15932:16:3::1;15921:27:::0;;::::1;;;15902:46;15898:76;;;15957:17;;-1:-1:-1::0;;;15957:17:3::1;;;;;;;;;;;15898:76;15984:38;16003:9;16014:7;15984:18;:38::i;:::-;16032:11;::::0;::::1;:23:::0;;::::1;::::0;;::::1;-1:-1:-1::0;;16065:19:3;;;;;;;;::::1;::::0;;::::1;;::::0;;;16099:60:::1;::::0;;23883:4:21;23871:17;;;23853:36;;23925:17;;23920:2;23905:18;;23898:45;23988:18;;;23981:43;;;;24055:2;24040:18;;24033:43;;;;-1:-1:-1;;;;;16099:60:3;::::1;::::0;::::1;::::0;23840:3:21;23825:19;16099:60:3::1;;;;;;;15700:466;;15510:656:::0;;;;;;:::o;18387:569::-;18542:7;30393:40;30425:7;30393:31;:40::i;:::-;18561:14:::1;18578:41;18592:7;18601:4;18607:11;18578:13;:41::i;:::-;18561:58;;18629:18;18650:20;18663:6;18650:12;:20::i;:::-;18629:41:::0;-1:-1:-1;18755:15:3::1;::::0;::::1;::::0;:36;::::1;;;-1:-1:-1::0;18774:6:3::1;::::0;::::1;::::0;-1:-1:-1;;;18774:6:3;::::1;:17;:6;:17:::0;18755:36:::1;18751:66;;;18800:17;;-1:-1:-1::0;;;18800:17:3::1;;;;;;;;;;;18751:66;18827:27;18848:5;18827:20;:27::i;:::-;18864:13;::::0;::::1;:21:::0;;-1:-1:-1;;;;18864:21:3::1;-1:-1:-1::0;;;18864:21:3::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;18900:49:::1;::::0;;24309:4:21;24297:17;;;24279:36;;24351:17;;24346:2;24331:18;;24324:45;24385:18;;;24378:51;;;;-1:-1:-1;;;;;18900:49:3;::::1;::::0;::::1;::::0;24267:2:21;24252:18;18900:49:3::1;24087:348:21::0;14306:676:3;14455:7;30393:40;30425:7;30393:31;:40::i;:::-;14474:14:::1;14491:41;14505:7;14514:4;14520:11;14491:13;:41::i;:::-;14474:58;;14542:18;14563:20;14576:6;14563:12;:20::i;:::-;14542:41:::0;-1:-1:-1;14695:15:3::1;::::0;::::1;::::0;:45;::::1;;;-1:-1:-1::0;14714:6:3::1;::::0;::::1;::::0;-1:-1:-1;;;14714:6:3;::::1;:26;:6;4565:1;14714:26;;14695:45;14691:75;;;14749:17;;-1:-1:-1::0;;;14749:17:3::1;;;;;;;;;;;14691:75;14840:6;::::0;::::1;::::0;-1:-1:-1;;;;;14840:6:3;;::::1;:26;:6;:26:::0;14836:56:::1;;14875:17;;-1:-1:-1::0;;;14875:17:3::1;;;;;;;;;;;14836:56;14902:15:::0;;-1:-1:-1;;;;;14902:15:3;::::1;-1:-1:-1::0;;;14902:15:3;::::1;-1:-1:-1::0;;;;;14902:15:3;;::::1;;::::0;;14932:43:::1;::::0;;24662:4:21;24650:17;;;24632:36;;24704:17;;24699:2;24684:18;;24677:45;24738:18;;;24731:67;;;;14932:43:3;;::::1;::::0;::::1;::::0;24620:2:21;24605:18;14932:43:3::1;24440:364:21::0;10813:2439:3;10872:19;;10924:61;10937:47;10951:9;;;;:1;:9;:::i;:::-;10962:6;;;;;;;;:::i;:::-;10970:13;;;;;;;;:::i;:::-;10937;:47::i;:::-;10924:12;:61::i;:::-;10903:82;;11070:19;11087:1;11070:16;:19::i;:::-;11178:6;;;;-1:-1:-1;;;11178:6:3;;;;-1:-1:-1;;11198:21:3;;11194:186;;11221:19;11235:1;11238;11221:13;:19::i;:::-;11194:186;;;-1:-1:-1;;11259:24:3;;;;11255:125;;11285:30;11310:1;11313;11285:24;:30::i;11255:125::-;-1:-1:-1;;11334:24:3;;;;11330:50;;11367:13;;-1:-1:-1;;;11367:13:3;;;;;;;;;;;11330:50;11391:28;11408:4;11414:1;11417;11391:16;:28::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11639:11:3;;;;;;;;:::i;:::-;-1:-1:-1;;;;;11631:19:3;:4;;;;;;;;:::i;:::-;-1:-1:-1;;;;;11631:19:3;;:46;;11666:11;;;;;;;;:::i;:::-;11631:46;;;11661:1;11631:46;-1:-1:-1;;;;;11617:60:3;:11;;;:60;;;11730:56;;11753:1;;11769:16;;;;:1;:16;:::i;:::-;11730:22;:56::i;:::-;11715:71;;:12;;;:71;11797:26;11826:70;11845:6;;;;;;;;:::i;:::-;11853:1;11856:10;;;;;;;;:::i;:::-;11868:13;;;;;;;;:::i;:::-;11883:1;:12;;;11826:18;:70::i;:::-;11924:7;;11797:99;;-1:-1:-1;11911:9:3;:20;11907:65;;11964:7;;11940:32;;-1:-1:-1;;;11940:32:3;;11953:9;11940:32;;;25909:25:21;25950:18;;;25943:34;;;;25882:18;;11940:32:3;;;;;;;;11907:65;12028:16;;;;12009;;;:35;12075:18;;;;12054;;;:39;12125:19;;;;12103;;;:41;;;12395:24;12391:119;;12476:19;;;;12439:20;:33;12460:11;;;;;;;;:::i;:::-;-1:-1:-1;;;;;12439:33:3;;;;;;;;;;;;-1:-1:-1;12439:33:3;:56;;;;;;;12391:119;12527:18;;;;:23;12523:115;;12605:18;;;;12590:10;;-1:-1:-1;;;;;12590:10:3;12570:19;:31;;;;;;;;;;:53;;;;;;;12523:115;12732:25;12778:9;;;;:1;:9;:::i;:::-;12732:56;-1:-1:-1;12811:10:3;;;;;;;;:::i;:::-;12798:23;;;;12868:16;;;;-1:-1:-1;;;;;12847:12:3;;;;;12887:6;;;;;;;;:::i;:::-;12895:4;;;;;;;;:::i;:::-;12901:10;;;;;;;;:::i;:::-;12847:65;;-1:-1:-1;;;;;;12847:65:3;;;;;;;26215:4:21;26203:17;;;12847:65:3;;;26185:36:21;-1:-1:-1;;;;;26257:32:21;;;26237:18;;;26230:60;12847:65:3;26326:23:21;26306:18;;;26299:51;26158:18;;12847:65:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;12831:13;;;:81;12938:13;;;;;;;;:::i;:::-;-1:-1:-1;;;;;12922:29:3;:13;;;:29;12985:21;;;;;;;;:::i;:::-;12961:45;;:21;;;:45;13038:19;;;;;;;;:::i;:::-;13016:41;;:19;;;:41;13090:7;;13067:20;;;:30;13121:11;;;;13107;;;:25;13198:15;;;;13189:4;;;;;;;;:::i;:::-;-1:-1:-1;;;;;13148:66:3;13155:9;;;;:1;:9;:::i;:::-;-1:-1:-1;;;;;13148:66:3;;13166:6;;;;;;;;:::i;:::-;13174:13;;;;;;;;:::i;:::-;13195:1;13148:66;;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;13232:13:3;;;;10813:2439;-1:-1:-1;;;;10813:2439:3:o;27112:387::-;27199:24;;:::i;:::-;4547:2:2;4543:10;;;27284:29:3;;;;4540:37:2;;;;27235:26:3;27264:50;;;:19;:50;;;;;;;;;27235:79;;;;;;;;;-1:-1:-1;;;;;27235:79:3;;;;;-1:-1:-1;;;27235:79:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;27235:79:3;;;;;;;;-1:-1:-1;;;27235:79:3;;;;;;;;;;;27324:90;;27343:19;:71;4547:2:2;4543:10;;;6014:3:3;4540:37:2;27343:71:3;;;;;;;;;;;;;;-1:-1:-1;27343:71:3;27339:75;;;;;;;;;-1:-1:-1;;;;;27339:75:3;;;;;-1:-1:-1;;;27339:75:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;27339:75:3;;;;;;;;-1:-1:-1;;;27339:75:3;;;;;;;;;;;-1:-1:-1;27324:90:3;27429:1;:8;;;27424:23;;27439:8;;:::i;:::-;;;27424:23;27491:1;27112:387;-1:-1:-1;;;27112:387:3:o;29555:121::-;29597:22;29646:23;:21;:23::i;24214:432::-;24440:24;;:::i;:::-;24476:14;24493:41;24507:7;24516:4;24522:11;24493:13;:41::i;:::-;24476:58;;24551:88;24570:4;24576:20;24589:6;24576:12;:20::i;:::-;24598:8;24608:11;24621:17;24551:18;:88::i;:::-;24544:95;24214:432;-1:-1:-1;;;;;;;;24214:432:3:o;26862:194::-;26935:24;;:::i;:::-;-1:-1:-1;6014:3:3;4547:2:2;4543:10;;;4540:37;;26978:71:3;;;;:19;:71;;;;;;;;;26971:78;;;;;;;;;-1:-1:-1;;;;;26971:78:3;;;;;-1:-1:-1;;;26971:78:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;26971:78:3;;;;;;;;;;;-1:-1:-1;;;26971:78:3;;;;;;;;;;;26862:194::o;21751:179::-;21802:14;21819:31;:29;:31::i;:::-;-1:-1:-1;;;;;21860:15:3;;;;;;:7;:15;;;;;;;;;:23;;-1:-1:-1;;21860:23:3;-1:-1:-1;;;;;21860:23:3;;;;;;;;21898:25;;852:58:21;;;21860:15:3;;-1:-1:-1;21860:15:3;;21898:25;;825:18:21;21898:25:3;708:208:21;25264:377:3;25472:4;25488:14;25505:41;25519:7;25528:4;25534:11;25505:13;:41::i;:::-;25488:58;;25563:71;25586:20;25599:6;25586:12;:20::i;:::-;25608:9;25619:14;;25563:22;:71::i;26028:544::-;26194:21;26227:14;26244:41;26258:7;26267:4;26273:11;26244:13;:41::i;:::-;26295:31;26329:22;;;:14;:22;;;;;26227:58;;-1:-1:-1;26382:12:3;26371:31;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;26371:31:3;;26361:41;;26441:9;26436:120;26452:24;;;26436:120;;26514:27;26525:12;;26538:1;26525:15;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;26514:27;;:6;:10;;:27;;;;:::i;:::-;26501:7;26509:1;26501:10;;;;;;;;:::i;:::-;:40;;;:10;;;;;;;;;;;:40;26478:3;;26436:120;;;;26217:355;;26028:544;;;;;;;:::o;26628:178::-;26706:24;;:::i;:::-;-1:-1:-1;26769:29:3;;;;4547:2:2;4543:10;;;4540:37;26749:50:3;;;;:19;:50;;;;;;;;;26742:57;;;;;;;;;-1:-1:-1;;;;;26742:57:3;;;;;-1:-1:-1;;;26742:57:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;26742:57:3;;;;;;;-1:-1:-1;;;26742:57:3;;;;;;;;;;26628:178::o;6989:596:13:-;-1:-1:-1;;;7114:18:13;;7087:13;;;7114:18;7385:23;:21;:23::i;:::-;6989:596;;7367:41;;;-1:-1:-1;7428:13:13;;-1:-1:-1;7479:4:13;;-1:-1:-1;6989:596:13;;-1:-1:-1;6989:596:13;:::o;20703:273:3:-;20770:14;20787:31;:29;:31::i;:::-;20770:48;;20828:38;20856:9;20828:27;:38::i;:::-;-1:-1:-1;;;;;20876:26:3;;;;;;;:18;:26;;;;;;;;;:38;;-1:-1:-1;;;;;;20876:38:3;;;;;;;;;20929:40;;20140:51:21;;;20876:26:3;;20929:40;;20113:18:21;20929:40:3;19994:203:21;19012:502:3;19172:7;30393:40;30425:7;30393:31;:40::i;:::-;19191:14:::1;19208:41;19222:7;19231:4;19237:11;19208:13;:41::i;:::-;19191:58;;19259:18;19280:20;19293:6;19280:12;:20::i;:::-;4458:1;19314:6:::0;;::::1;::::0;19259:41;;-1:-1:-1;;;;19314:6:3;;::::1;:23;:6;:23;19310:53;;19346:17;;-1:-1:-1::0;;;19346:17:3::1;;;;;;;;;;;19310:53;19373:31;19393:10;19373:19;:31::i;:::-;19414:12;::::0;::::1;:25:::0;;;19454:53:::1;::::0;;23520:4:21;23508:17;;;23490:36;;23562:17;;23557:2;23542:18;;23535:45;23596:18;;;23589:34;;;-1:-1:-1;;;;;19454:53:3;::::1;::::0;::::1;::::0;23478:2:21;23463:18;19454:53:3::1;23296:333:21::0;21383:312:3;21465:14;21482:31;:29;:31::i;:::-;21465:48;;21523:29;21550:1;21523:26;:29::i;:::-;21634:1;21562:19;:69;4547:2:2;4543:10;;;6014:3:3;4540:37:2;21562:69:3;;;;;;;;;;;;;;-1:-1:-1;21562:69:3;:73;;;;;;;;-1:-1:-1;;;;;21562:73:3;;;-1:-1:-1;;;;;;21562:73:3;;;;-1:-1:-1;;;21562:73:3;;;;;;;;;;;;-1:-1:-1;21562:73:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;21562:73:3;-1:-1:-1;;;21562:73:3;;;;;;;;-1:-1:-1;;;;21562:73:3;;;;;-1:-1:-1;;;21562:73:3;;;;;;;;;;;;;21650:38;-1:-1:-1;;;;;21650:38:3;;;;;;;21686:1;;21650:38;:::i;27555:751::-;27615:19;4543:10:2;;;27670:28:3;27701:36;;;:9;:36;;;;;27763:23;;;;;-1:-1:-1;;;27763:23:3;;;;;-1:-1:-1;;;27834:16:3;;;27763:23;27900:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;27896:21;;28088:202;28095:6;;28088:202;;28152:25;;;4547:2:2;4543:10;;;4540:37;28121:18:3;28142:36;;;:9;:36;;;;;28205:42;4543:10:2;28229:6:3;28234:1;28229:6;;;;28152:25;28205:8;:42::i;:::-;28196:1;28198:3;;;;;;;28196:6;;;;;;;;:::i;:::-;;;;;;;;;;:51;28269:6;;;-1:-1:-1;;;28269:6:3;;;;;-1:-1:-1;28088:202:3;;;27646:654;;;27555:751;;;:::o;7658:3099::-;7724:17;7753:42;7785:1;:9;;;7753:31;:42::i;:::-;7806:43;7831:1;:17;;;7806:24;:43::i;:::-;7873:6;;;;7894:15;;;7890:569;;7948:1;7925:12;;;:25;7890:569;;;-1:-1:-1;;7971:21:3;;;;7967:492;;8008:33;8028:1;:12;;;8008:19;:33::i;:::-;7967:492;;;-1:-1:-1;;8062:24:3;;;;8058:401;;8125:1;8102:12;;;:25;8167:16;8141:23;;;:42;8058:401;;;-1:-1:-1;;8204:24:3;;;;8200:259;;8267:1;8244:12;;;:25;;;8309:16;8283:23;;;:42;8339:7;;;:11;8200:259;;;8435:13;;-1:-1:-1;;;8435:13:3;;;;;;;;;;;8200:259;8538:6;;;;:17;;8534:586;;8583:16;8571:9;;;:28;;;8613:23;;;:42;8928:24;;;4565:1;8928:24;8924:41;;8964:1;8954:7;;;:11;8924:41;9060:15;;;9056:53;;9093:16;9077:13;;;:32;9056:53;9130:42;9149:1;:11;;;9162:1;:9;;;9130:18;:42::i;:::-;9182:55;9213:1;:23;;;9182:30;:55::i;:::-;9247:35;9268:1;:13;;;9247:20;:35::i;:::-;9317:25;9345:9;:46;9355:35;9369:1;:9;;;9380:1;:6;;;9388:1;9355:13;:35::i;:::-;9345:46;;;;;;;;;;;;;;-1:-1:-1;9345:46:3;;;9460:9;;4547:2:2;4543:10;9436:38:3;;:9;:38;;;;9503:24;;;;;-1:-1:-1;;;9503:24:3;;;;;-1:-1:-1;9345:46:3;;-1:-1:-1;9436:38:3;9582:3;;9503:24;9582:13;;9578:42;;9597:23;:21;:23::i;:::-;9634:24;;;;:35;;;;;;-1:-1:-1;;;9634:35:3;-1:-1:-1;;;;9634:35:3;;;;;;;;;;9688:23;;;;;-1:-1:-1;;;9688:23:3;;;;9729:3;9736:7;9729:14;;9725:43;;9745:23;:21;:23::i;:::-;9782;;;:35;;-1:-1:-1;;;;9782:35:3;-1:-1:-1;;;9782:35:3;;;;;;;9863:9;;9782:35;9874:6;;;-1:-1:-1;;9849:45:3;;9882:11;9849:13;:45::i;:::-;9832:62;;9909:18;9930:9;:17;9940:6;9930:17;;;;;;;;;;;9909:38;;9974:1;:10;;;9961:1;:10;;;:23;;;;;-1:-1:-1;;;;;9961:23:3;;;;;-1:-1:-1;;;;;9961:23:3;;;;;;10008:1;:7;;;9998:1;:7;;;:17;;;;;-1:-1:-1;;;;;9998:17:3;;;;;-1:-1:-1;;;;;9998:17:3;;;;;;10043:1;:11;;;10029:1;:11;;;:25;;;;;;;;;;;;;;;;;;10080:1;:9;;;10068:1;:9;;;:21;;;;;;;;;;;;;;;;;;10129:1;:23;;;10103:1;:23;;;:49;;;;;;;;;;;;;;;;;;10182:1;:13;;;10166:1;:13;;;:29;;;;;;;;;;;;;;;;;;10229:1;:17;;;10209:1;:17;;;:37;;;;;;;;;;;;;;;;;;10269:1;:6;;;10260:1;:6;;;:15;;;;;;;;;;;;;;;;;;5504:6;10289:1;:7;;;:28;;;;;;;;;;;;;;;;;;10340:11;:16;;;;;;;;;;;;10331:1;:6;;;:25;;;;;;;;;;;;;;;;;;10429:11;10421:20;;10416:1;10405;:6;;;10397:15;;:20;;10396:45;10370:11;:16;;;:72;;;;;;;;;;;;;;;;;;10552:1;10544:10;;10519:1;:21;;;:35;10515:86;;10580:21;;;;10556;;;:45;10515:86;10619:12;;;;:26;10615:59;;10662:12;;;;10647;;;:27;10615:59;10706:1;:9;;;-1:-1:-1;;;;;10694:46:3;;10717:1;:6;;;10725:11;10738:1;10694:46;;;;;;;;:::i;:::-;;;;;;;;9293:1458;;;;;7743:3014;7658:3099;;;:::o;17517:814::-;17682:7;30393:40;30425:7;30393:31;:40::i;:::-;17701:14:::1;17718:41;17732:7;17741:4;17747:11;17718:13;:41::i;:::-;17701:58;;17769:18;17790:20;17803:6;17790:12;:20::i;:::-;17769:41:::0;-1:-1:-1;17873:15:3::1;::::0;::::1;17869:45;;17897:17;;-1:-1:-1::0;;;17897:17:3::1;;;;;;;;;;;17869:45;17985:6;::::0;::::1;::::0;-1:-1:-1;;;;;17985:6:3;;::::1;:26;:6;:26:::0;17981:56:::1;;18020:17;;-1:-1:-1::0;;;18020:17:3::1;;;;;;;;;;;17981:56;18110:6;::::0;::::1;::::0;-1:-1:-1;;;;;18110:6:3;;::::1;:26;:6;:26:::0;18106:56:::1;;18145:17;;-1:-1:-1::0;;;18145:17:3::1;;;;;;;;;;;18106:56;18172:37;18203:5;18172:30;:37::i;:::-;18219:23;::::0;::::1;:31:::0;;-1:-1:-1;;18219:31:3::1;-1:-1:-1::0;;;18219:31:3::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;18265:59:::1;::::0;;24309:4:21;24297:17;;;24279:36;;24351:17;;24346:2;24331:18;;24324:45;24385:18;;;24378:51;;;;-1:-1:-1;;;;;18265:59:3;::::1;::::0;::::1;::::0;24267:2:21;24252:18;18265:59:3::1;24087:348:21::0;16222:296:3;16365:14;16382:41;16396:7;16405:4;16411:11;16382:13;:41::i;:::-;16485:17;;;;:9;:17;;;;;:25;;;:17;;-1:-1:-1;16433:78:3;;16446:7;;16455:4;;16461:11;;16474:9;;16485:25;;;;;16433:12;:78::i;:::-;16355:163;16222:296;;;;:::o;23833:325::-;24016:24;;:::i;:::-;24059:92;24092:7;24101:4;24107:11;24120:8;24130:1;24133:17;24059:32;:92::i;:::-;24052:99;23833:325;-1:-1:-1;;;;;;23833:325:3:o;16574:424::-;16728:7;30393:40;30425:7;30393:31;:40::i;:::-;16747:14:::1;16764:41;16778:7;16787:4;16793:11;16764:13;:41::i;:::-;16747:58;;16815:18;16836:20;16849:6;16836:12;:20::i;:::-;16815:41;;16866:29;16891:3;16866:24;:29::i;:::-;16905:17;::::0;::::1;:23:::0;;-1:-1:-1;;;;16905:23:3::1;-1:-1:-1::0;;;16905:23:3::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;16943:48:::1;::::0;;30231:4:21;30219:17;;;30201:36;;30273:17;;30268:2;30253:18;;30246:45;30307:18;;;30300:47;;;;-1:-1:-1;;;;;16943:48:3;::::1;::::0;::::1;::::0;30189:2:21;30174:18;16943:48:3::1;30009:344:21::0;24922:286:3;25072:6;25090:14;25107:41;25121:7;25130:4;25136:11;25107:13;:41::i;:::-;-1:-1:-1;;;;;25165:24:3;;;;;;:13;:24;;;;;;;;3360:1:16;3351:10;;;3343:19;;;;;;;;25090:58:3;;-1:-1:-1;3367:16:16;3382:1;3367:16;;;;3343:41;25165:36:3;25158:43;;;24922:286;;;;;;;:::o;28362:969::-;28479:20;;:::i;:::-;28511:14;28528:41;28542:7;28551:4;28557:11;28528:13;:41::i;:::-;28511:58;;28579:18;28600:20;28613:6;28600:12;:20::i;:::-;-1:-1:-1;;;;;28630:22:3;;;;;28662:16;;;;:9;;;:16;;;28688:30;;;:16;;;:30;28744:10;;;;;28728:13;;;:26;28579:41;;-1:-1:-1;28777:15:3;:45;;;;-1:-1:-1;28796:6:3;;;;-1:-1:-1;;;28796:6:3;;:26;:6;4565:1;28796:26;;28777:45;:77;;28847:7;;-1:-1:-1;;;28847:7:3;;-1:-1:-1;;;;;28847:7:3;28777:77;;;28833:10;;-1:-1:-1;;;;;28833:10:3;28825:19;;;;:7;:19;;;;;;-1:-1:-1;;;;;28825:19:3;28777:77;-1:-1:-1;;;;;28764:90:3;:10;;;:90;28881:11;;;;;;;;28864:14;;;:28;28917:9;;;;;28902:12;;;:24;-1:-1:-1;;;28965:23:3;;;;28936:26;;;:52;-1:-1:-1;;;29017:13:3;;;;28881:11;28998:16;;:32;-1:-1:-1;;;29054:8:3;;;29040:11;;;:22;-1:-1:-1;;;29095:17:3;;;;29072:20;;;:40;-1:-1:-1;;;29134:6:3;;;;29122:9;;;:18;5637:6;-1:-1:-1;;;47050:7:3;;;:27;;:32;;29150:11;;;:26;29213:21;;;29186:24;;;:48;29262:12;;;;29244:15;;;:30;29313:10;-1:-1:-1;;;;;29313:10:3;;;-1:-1:-1;29298:26:3;;;:14;:26;;;;;;;29284:11;;;:40;-1:-1:-1;28764:10:3;29150:4;-1:-1:-1;;;28362:969:3:o;15038:416::-;15187:7;30393:40;30425:7;30393:31;:40::i;:::-;15206:14:::1;15223:41;15237:7;15246:4;15252:11;15223:13;:41::i;:::-;15206:58;;15274:18;15295:20;15308:6;15295:12;:20::i;:::-;15352:7;::::0;::::1;::::0;15274:41;;-1:-1:-1;15335:52:3::1;::::0;15352:7:::1;-1:-1:-1::0;;;15352:7:3;;::::1;;5637:6;15380::::0;2304:4:2;2310:16;;;2300:27;2293:35;2330:12;;2289:54;2285:65;2274:77;;2109:258;15335:52:3::1;15325:7;::::0;::::1;:62:::0;;-1:-1:-1;;;;15325:62:3::1;-1:-1:-1::0;;;15325:62:3::1;::::0;;::::1;;;::::0;;15402:45:::1;::::0;;30564:17:21;;;30546:36;;30618:17;;;30613:2;30598:18;;30591:45;30679:14;;30672:22;30652:18;;;30645:50;-1:-1:-1;;;;;15402:45:3;::::1;::::0;::::1;::::0;30534:2:21;30519:18;15402:45:3::1;30358:343:21::0;22733:496:3;22802:7;22867:355;3227:390;22954:9;;;;:1;:9;:::i;:::-;22981:6;;;;;;;;:::i;:::-;23006:13;;;;;;;;:::i;:::-;23037:4;;;;;;;;:::i;:::-;23059:16;;;;;;;;:::i;:::-;23093:19;;;;;;;;:::i;:::-;23130:13;;;;;;;;:::i;:::-;23161:16;;;;;;;;:::i;:::-;23195:11;;;;;;;;:::i;:::-;22892:328;;;;;;31089:25:21;;;;-1:-1:-1;;;;;31188:15:21;;;31168:18;;;31161:43;31252:4;31240:17;;;31220:18;;;31213:45;31294:17;;;;31274:18;;;31267:45;31349:15;;;31328:19;;;31321:44;31384:10;31431:15;;;31410:19;;;31403:44;31484:15;;31463:19;;;31456:44;-1:-1:-1;;;;;31537:39:21;;;31516:19;;;31509:68;31614:15;31593:19;;;31586:44;31667:15;31646:19;;;31639:44;31061:19;;22892:328:3;;;;;;;;;;;;;22882:339;;;;;;22867:14;:355::i;13308:775::-;13377:19;;13429:61;13442:47;13456:9;;;;:1;:9;:::i;13429:61::-;13408:82;;13575:19;13592:1;13575:16;:19::i;:::-;13609:6;;;;-1:-1:-1;;;13609:6:3;;:26;:6;4674:1;13609:26;13605:52;;13644:13;;-1:-1:-1;;;13644:13:3;;;;;;;;;;;13605:52;13667:44;13706:1;13709;13667:38;:44::i;:::-;13722:37;13754:1;13757;13722:31;:37::i;:::-;13844:25;13890:9;;;;:1;:9;:::i;:::-;13844:56;-1:-1:-1;;;;;;13924:15:3;;;13940:6;;;;;;;;:::i;:::-;13948:4;;;;:1;:4;:::i;:::-;13954:16;;;;;;;;:::i;:::-;13924:47;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13910:61;-1:-1:-1;14006:9:3;;;;:1;:9;:::i;:::-;-1:-1:-1;;;;;13987:89:3;;14017:6;;;;;;;;:::i;:::-;14025:13;;;;;;;;:::i;:::-;14040:4;;;;:1;:4;:::i;:::-;14046:16;;;;;;;;:::i;:::-;14064:11;13987:89;;;;;;;;;;;:::i;:::-;;;;;;;;13398:685;;13308:775;;;:::o;21032:295::-;21119:14;21136:31;:29;:31::i;:::-;21119:48;;21177:29;21204:1;21177:26;:29::i;:::-;21267:1;21216:19;:48;4547:2:2;4543:10;;;21236:27:3;;;4540:37:2;21216:48:3;;;;;;;;;;;;;;-1:-1:-1;21216:48:3;:52;;;;;;;;-1:-1:-1;;;;;21216:52:3;;;-1:-1:-1;;;;;;21216:52:3;;;;-1:-1:-1;;;21216:52:3;;;;;;;;;;;;-1:-1:-1;21216:52:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;21216:52:3;-1:-1:-1;;;21216:52:3;;;;;;;;-1:-1:-1;;;;21216:52:3;;;;;-1:-1:-1;;;21216:52:3;;;;;;;;;;;;;21283:37;-1:-1:-1;;;;;21283:37:3;;;;;;;21312:4;;21318:1;;21283:37;:::i;:::-;;;;;;;;21109:218;21032:295;;:::o;20073:438::-;-1:-1:-1;;;;;20157:28:3;;;20137:17;20157:28;;;:18;:28;;;;;;;20195:38;20157:28;20195:27;:38::i;:::-;-1:-1:-1;;;;;20261:29:3;;20243:15;20261:29;;;;;;;;;;;20304:12;;20300:205;;-1:-1:-1;;;;;20332:29:3;;20364:1;20332:29;;;;;;;;;;:33;20379:56;20416:9;20427:7;20379:36;:56::i;:::-;20476:8;-1:-1:-1;;;;;20454:40:3;;20486:7;20454:40;;;;1989:25:21;;1977:2;1962:18;;1843:177;20300:205:3;20127:384;;20073:438;:::o;23285:492::-;23372:7;23437:333;3798:326;23533:9;;;;:1;:9;:::i;:::-;23560:6;;;;;;;;:::i;:::-;23585:13;;;;;;;;:::i;:::-;23643:4;;;;:1;:4;:::i;:::-;23626:22;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;23626:22:3;;;;;;;;;23616:33;;23626:22;23616:33;;;;23667:16;;;;;;;;:::i;:::-;23701:19;;;;;;;;:::i;:::-;23738:16;;;;;;;;:::i;:::-;23462:306;;;;;;35152:25:21;;;;-1:-1:-1;;;;;35213:32:21;;;35193:18;;;35186:60;;;;35294:4;35282:17;;;35262:18;;;35255:45;35336:17;;;;35316:18;;;35309:45;35370:19;;;35363:35;35417:10;35464:15;;;35443:19;;;35436:44;35517:15;;;35496:19;;;35489:44;35570:15;35549:19;;;35542:44;35124:19;;23462:306:3;34823:769:21;19677:340:3;-1:-1:-1;;;;;19761:31:3;;19743:15;19761:31;;;:20;:31;;;;;;19806:12;;19802:209;;-1:-1:-1;;;;;19834:31:3;;19868:1;19834:31;;;:20;:31;;;;;:35;19883:56;19855:9;19931:7;19883:36;:56::i;:::-;19981:9;-1:-1:-1;;;;;19958:42:3;;19992:7;19958:42;;;;1989:25:21;;1977:2;1962:18;;1843:177;19802:209:3;19733:284;19677:340;:::o;25697:275::-;25853:4;25876:89;25898:7;25907:4;25913:11;25926:9;14090:24:18;25853:4:3;25264:377;:::i;25876:89::-;25869:96;25697:275;-1:-1:-1;;;;;25697:275:3:o;33716:226::-;33888:21;;;;;;;;;;;-1:-1:-1;;;33888:21:3;;;;;;;;33919:16;;;;;;;;;;;-1:-1:-1;;;33919:16:3;;;;33888:21;33716:226::o;30589:297::-;30671:14;30688:31;:29;:31::i;:::-;30671:48;;30756:7;-1:-1:-1;;;;;30743:27:3;;:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;30733:39:3;:6;-1:-1:-1;;;;;30733:39:3;;30729:150;;30791:59;;-1:-1:-1;;;30791:59:3;;-1:-1:-1;;;;;36045:32:21;;;30791:59:3;;;36027:51:21;1211:6:2;36094:18:21;;;36087:34;30791:32:3;;;;;36000:18:21;;30791:59:3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;30786:93;;30852:27;:25;:27::i;4895:317:2:-;5012:14;5082:7;5078:2;5074:16;5068:4;5061:30;5118:4;5112;5104:19;5150:11;5144:4;5136:26;-1:-1:-1;;5191:4:2;5185:11;;4895:317;-1:-1:-1;;4895:317:2:o;46605:193:3:-;46666:18;46700:17;;;:9;:17;;;;;5504:6;46731:7;;;;46700:17;;-1:-1:-1;;;46731:7:3;;;:28;:33;;46727:64;;46773:18;;-1:-1:-1;;;46773:18:3;;;;;;;;;;;46727:64;46605:193;;;:::o;4101:809:7:-;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:7;4883:11;;4101:809::o;31063:143:3:-;31165:7;31153:19;;:9;:19;;;31149:50;;;31181:18;;-1:-1:-1;;;31181:18:3;;;;;;;;;;;31611:117;31683:5;:10;;31692:1;31683:10;31679:42;;31702:19;;-1:-1:-1;;;31702:19:3;;;;;;;;;;;31679:42;31611:117;:::o;36691:306::-;36793:11;;;;36775:15;36824:9;;;36793:11;36824:9;;;-1:-1:-1;;36793:11:3;;-1:-1:-1;3385:40:2;36761:146:3;;;36884:11;;;;36855:52;;-1:-1:-1;;;36855:52:3;;36867:15;36897:9;36855:52;;36580:25:21;36884:11:3;;;;36650:18:21;;;36643:43;36897:9:3;;;;;;;36702:18:21;;;36695:43;36553:18;;36855:52:3;36382:362:21;36761:146:3;36921:12;36931:1;47050:7;;;-1:-1:-1;;;47050:7:3;;5637:6;47050:27;:32;;;46965:124;36921:12;36917:37;;;36942:12;;-1:-1:-1;;;36942:12:3;;;;;;;;;;;38806:1708;38892:26;38921:21;;;;;;;;:::i;:::-;38892:50;-1:-1:-1;38952:19:3;38974:13;;;;;;;;:::i;:::-;38952:35;-1:-1:-1;;;;;;39164:25:3;;39160:58;;39198:20;;-1:-1:-1;;;39198:20:3;;;;;;;;;;;39160:58;-1:-1:-1;;39367:16:3;39344:39;;;39340:782;;39594:65;39626:1;:12;;;39640:18;39646:11;45719:14;45768:25;45832:4;45826;45816:21;;45660:193;39640:18;39594:16;;;;:1;:16;:::i;:::-;:31;;;;;:65::i;:::-;39593:66;:170;;;;;39680:83;39712:1;:12;;;39726:36;39732:11;39745:16;46282:4;46275:33;46226:14;46321:25;46385:4;46379;46369:21;;46139:267;39680:83;39679:84;39593:170;39572:233;;;39785:20;;-1:-1:-1;;;39785:20:3;;;;;;;;;;;39572:233;39340:782;;;39980:86;40012:1;:12;;;40026:39;40032:11;40045:19;46282:4;46275:33;46226:14;46321:25;46385:4;46379;46369:21;;46139:267;39980:86;39975:136;;40091:20;;-1:-1:-1;;;40091:20:3;;;;;;;;;;;39975:136;40209:14;40226:31;:29;:31::i;:::-;40209:48;-1:-1:-1;40272:53:3;-1:-1:-1;;;;;40282:21:3;;;;;;;;;40305:4;;;;;;;;:::i;:::-;-1:-1:-1;;;;;40305:19:3;;3395:9:2;;3388:17;3414:9;;3407:17;3385:40;;3288:153;40272:53:3;40267:241;;40412:56;40448:6;40456:11;40412:35;:56::i;:::-;40407:90;;40477:20;;-1:-1:-1;;;40477:20:3;;;;;;;;;;;37185:608;37294:16;;;;;;;;:::i;:::-;37281:29;;:10;;;;;;;;:::i;:::-;:29;;;37277:65;;;37319:23;;-1:-1:-1;;;37319:23:3;;;;;;;;;;;37277:65;37384:10;;-1:-1:-1;;;;;37384:10:3;;;37352:14;37369:26;;;:14;:26;;;;;;;37410:92;37369:26;37466:22;37486:1;37466:19;:22::i;:::-;37490:11;;;;:1;:11;:::i;:::-;37410:47;:92::i;:::-;37405:136;;37523:18;;-1:-1:-1;;;37523:18:3;;;;;;;;;;;37405:136;37573:16;;;;;;;;:::i;:::-;37555:34;;:15;:34;37551:65;;;37598:18;;-1:-1:-1;;;37598:18:3;;;;;;;;;;;37551:65;37626:14;37643:47;37657:9;;;;:1;:9;:::i;:::-;37668:6;;;;;;;;:::i;:::-;37676:13;;;;;;;;:::i;37643:47::-;37626:64;-1:-1:-1;37705:50:3;37735:19;;;;;;;;:::i;:::-;37705:22;;;;:14;:22;;;;;;:50;;;;;:29;:50;:::i;:::-;37700:86;;37764:22;;-1:-1:-1;;;37764:22:3;;;;;;;;;;;37700:86;37267:526;;37185:608;;:::o;34217:1324::-;34423:9;34463:10;;;;;;;;:::i;:::-;34443:8;;;;34455:19;;;;-1:-1:-1;;;34443:8:3;;;;34435:39;;-1:-1:-1;;;;34518:13:3;;;34514:17;;34510:49;;;34540:19;;-1:-1:-1;;;34540:19:3;;;;;;;;;;;34510:49;34573:8;;;:20;;-1:-1:-1;;;;34573:20:3;-1:-1:-1;;;34573:20:3;;;;;;;-1:-1:-1;34686:47:3;34700:9;;;;;;:::i;34686:47::-;34669:64;-1:-1:-1;;;34751:21:3;;;;34747:778;;34792:26;34821:13;34792:26;34835:13;;;;;;;;:::i;:::-;-1:-1:-1;;;;;34821:28:3;;;;;;;;;;;;-1:-1:-1;34821:28:3;;-1:-1:-1;34904:10:3;;;;;;;;:::i;:::-;34896:19;;34879:13;34885:6;34879:1;:5;;:13;;;;:::i;:::-;35111:23;;;;34871:22;;;;:44;;;;;-1:-1:-1;35097:65:3;;-1:-1:-1;;;35111:23:3;;;35107:27;;35140:21;;;;;;;;:::i;:::-;35136:25;;:1;:25;3395:9:2;;3388:17;3414:9;;3407:17;3385:40;;3288:153;35097:65:3;35093:100;;;35171:22;;-1:-1:-1;;;35171:22:3;;;;;;;;;;;35093:100;35211:24;:1;35217:6;35232:1;35211:5;:24::i;:::-;34774:476;34747:778;;;35274:26;35303:13;35274:26;35317:4;;;;;;;;:::i;:::-;-1:-1:-1;;;;;35303:19:3;;;;;;;;;;;;-1:-1:-1;35303:19:3;;-1:-1:-1;35377:10:3;;;;;;;;:::i;:::-;35369:19;;35352:13;35358:6;35352:1;:5;;:13;;;;:::i;:::-;35414:23;;;;35344:22;;;;:44;;;;;-1:-1:-1;;;;35414:23:3;;;;35410:27;;35406:62;;;35446:22;;-1:-1:-1;;;35446:22:3;;;;;;;;;;;35406:62;35486:24;:1;35492:6;35507:1;35486:5;:24::i;:::-;35256:269;34343:1192;;34217:1324;;;:::o;44729:700::-;44927:21;;;;44896:4;;44927:21;45019:54;;-1:-1:-1;;;;;;;45050:23:3;;;;45043:30;;45019:54;45332:90;-1:-1:-1;;;;;45343:23:3;;;;45368:53;45398:4;45404:16;45343:9;45719:14;45768:25;45832:4;45826;45816:21;;45660:193;45404:16;45368:14;;;;:29;:53::i;:::-;3999:9:2;3992:17;3980:9;;3973:17;3969:41;;3871:155;40875:3559:3;41065:26;;:::i;:::-;41341:10;;41285:26;;41314:44;;-1:-1:-1;;;;;41341:10:3;41353:4;41314:26;:44::i;:::-;41466:6;;;;41285:73;;-1:-1:-1;;;;;;41466:6:3;;;:26;:6;:26;41462:413;;41530:7;;-1:-1:-1;;;;;;;;41530:7:3;;;;;41516:21;;;;41512:53;;;41546:19;;-1:-1:-1;;;41546:19:3;;;;;;;;;;;41512:53;-1:-1:-1;;;;;41611:25:3;;:11;;;:25;41462:413;;;41661:15;;;41657:218;;41718:10;;-1:-1:-1;;;;;41718:10:3;41710:19;;;;:7;:19;;;;;;;;-1:-1:-1;;;;;41710:19:3;41696:11;;;:33;41657:218;;;41827:7;;-1:-1:-1;;;41827:7:3;;-1:-1:-1;;;;;41827:7:3;41813:11;;;:21;41657:218;41959:11;;;;41973:17;;;41959:31;41946:10;;;:44;;;42108:16;;;:29;42228:17;;;;-1:-1:-1;;;42228:17:3;;;;:22;;;;:43;;;42254:17;42228:43;42224:280;;;42334:10;;;;42346:17;;;;42291:23;;1495:5:2;-1:-1:-1;;;42346:17:3;;;;;3012:9:2;3008:17;42399:16:3;;;:35;;;;;;;42452:19;;;:37;-1:-1:-1;42224:280:3;42592:20;;;;:25;;;42588:261;;42679:10;;;;42691:20;;;;42637:22;;1495:5:2;42662:67:3;;;;3012:9:2;3008:17;42747:16:3;;;:34;;;;;;;42799:18;;;:35;-1:-1:-1;42588:261:3;43073:1;:16;;;-1:-1:-1;;;;;43058:31:3;:1;:11;;;:31;43054:1088;;43129:18;;43109:16;;;:58;;43150:17;;;-1:-1:-1;;;;;43129:38:3;;;;;43109:58;;;;;;43207:20;;;;43185:18;;;:62;;43207:40;;;;;;;43185:62;;;43344:238;;;;43412:21;;;;43389:19;;;:64;;-1:-1:-1;;;;;43412:41:3;;;43436:17;;;43412:41;43389:64;;;;;;43054:1088;;43344:238;43522:21;;;;43500:18;;;:63;;-1:-1:-1;;;;;43522:41:3;;;43546:17;;;43522:41;43500:63;;;;;;43054:1088;;;43640:27;;;;43620:16;;;:67;;43670:17;;;-1:-1:-1;;;;;43640:47:3;;;;;43620:67;;;;;;43727:29;;;;43705:18;;;:71;;43727:49;;;;;;;43705:71;;;43872:256;;;;43940:30;;;;43917:19;;;:73;;-1:-1:-1;;;;;43940:50:3;;;43973:17;;;43940:50;43917:73;;;;;;43872:256;;;44100:8;44092:17;;44059:1;:30;;;-1:-1:-1;;;;;44059:50:3;;44037:1;:18;;:72;;;;;;;;;;;43872:256;44219:19;;;44197:18;;;:41;;-1:-1:-1;;;;;44197:41:3;;;;;;;;;;44377:19;;;;44358:16;;;;:38;:59;44348:69;;44197:18;:1;-1:-1:-1;;;;;40875:3559:3:o;1672:479:15:-;2024:1;2015:10;;;1746;2004:22;;;;;;;;;;;;;2048:1;2039:4;2031:12;;;2004:40;2003:46;;1672:479::o;33407:133:3:-;-1:-1:-1;;;;;33483:15:3;;33479:54;;33507:26;;-1:-1:-1;;;33507:26:3;;;;;;;;;;;31849:136;31926:10;31922:56;;31959:19;;-1:-1:-1;;;31959:19:3;;;;;;;;;;;32397:869;32502:713;32529:173;5360:9;-1:-1:-1;;;;;32560:50:3;:1;:19;;;-1:-1:-1;;;;;32560:50:3;;5060:4;32632:52;;:1;:20;;;:52;;;3395:9:2;;3388:17;3414:9;;3407:17;3385:40;;3288:153;32529:173:3;32720:218;5215:9;-1:-1:-1;;;;;32751:40:3;:1;:18;;;-1:-1:-1;;;;;32751:40:3;;5215:9;-1:-1:-1;;;;;32813:43:3;:1;:21;;;-1:-1:-1;;;;;32813:43:3;;5215:9;-1:-1:-1;;;;;32878:42:3;:1;:20;;;-1:-1:-1;;;;;32878:42:3;;32720:9;:218::i;:::-;32956:245;5215:9;-1:-1:-1;;;;;32987:49:3;:1;:27;;;-1:-1:-1;;;;;32987:49:3;;5215:9;-1:-1:-1;;;;;33058:52:3;:1;:30;;;-1:-1:-1;;;;;33058:52:3;;5215:9;-1:-1:-1;;;;;33132:51:3;:1;:29;;;-1:-1:-1;;;;;33132:51:3;;32956:9;:245::i;:::-;32502:9;:713::i;:::-;32485:774;;;33233:26;;-1:-1:-1;;;33233:26:3;;;;;;;;;;;32132:141;4927:4;32206:27;;;;32202:64;;;32242:24;;-1:-1:-1;;;32242:24:3;;;;;;;;;;;31349:137;31431:5;:10;;31440:1;31431:10;31427:52;;31450:29;;-1:-1:-1;;;31450:29:3;;;;;;;;;;;5267:161:2;5353:10;5347:4;5340:24;5407:4;5401;5394:18;3228:164:16;3360:1;3351:10;;;3302:13;3343:19;;;;;;;;;;;;;3382:1;3367:16;;;;;;3343:41;;3228:164::o;5757:885:13:-;6066:22;9114:11;9255:9;9252:25;9069:14;9225:9;9222:28;9218:60;6102:73;;-1:-1:-1;8545:4:13;8539:11;;8606:16;8596:27;;8383:15;8650:4;8643:12;;8636:31;8426:18;8701:12;;;8694:33;;;;8761:9;8754:4;8747:12;;8740:31;8805:9;8798:4;8791:12;;8784:31;8854:4;8841:18;;6102:73;6309:18;6303:4;6296:32;6375:6;6369:4;6362:20;6439:10;6433:4;6426:24;6515:4;6509;6499:21;6489:31;;6624:1;6618:4;6611:15;5757:885;;;:::o;38007:653:3:-;38242:10;;-1:-1:-1;;;;;38242:10:3;;;38210:14;38227:26;;;:14;:26;;;;;;;38268:101;38227:26;38324:31;38353:1;38324:28;:31::i;:::-;38357:11;;;;:1;:11;:::i;38268:101::-;38263:145;;38390:18;;-1:-1:-1;;;38390:18:3;;;;;;;;;;;38263:145;38440:16;;;;;;;;:::i;:::-;38422:34;;:15;:34;38418:65;;;38465:18;;-1:-1:-1;;;38465:18:3;;;;;;;;;;;38418:65;38493:14;38510:47;38524:9;;;;:1;:9;:::i;38510:47::-;38493:64;-1:-1:-1;38572:50:3;38602:19;;;;;;;;:::i;35758:802::-;35890:14;35907:47;35921:9;;;;:1;:9;:::i;:::-;35932:6;;;;;;;;:::i;:::-;35940:13;;;;;;;;:::i;35907:47::-;35890:64;-1:-1:-1;35968:16:3;35987:4;;;;:1;:4;:::i;:::-;:11;-1:-1:-1;36069:9:3;;-1:-1:-1;36120:16:3;;;;;;;;:::i;:::-;36089:8;;;;36112:25;;;;36101:36;;-1:-1:-1;;;36089:8:3;;;;36081:56;;-1:-1:-1;;;;36181:13:3;;;36177:17;;36173:49;;;36203:19;;-1:-1:-1;;;36203:19:3;;;;;;;;;;;36173:49;36236:8;;;:20;;-1:-1:-1;;;;36236:20:3;-1:-1:-1;;;36236:20:3;;;;;;;-1:-1:-1;36333:211:3;36354:8;36349:1;:13;36333:211;;36387:26;36416:13;36387:26;36430:4;;;;:1;:4;:::i;:::-;36435:1;36430:7;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;36416:22:3;;;;;;;;;;;;-1:-1:-1;36416:22:3;;-1:-1:-1;36456:73:3;36462:6;36510:16;;;;;;;;:::i;:::-;36502:25;;36485:13;36491:6;36485:1;:5;;:13;;;;:::i;:::-;36477:22;;:50;36456:1;:5;;:73;;;;;:::i;:::-;-1:-1:-1;36364:3:3;;36333:211;;5496:721:19;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:2;5577:10;5571:4;5564:24;5635:4;5629;5622:18;2397:1407:18;2522:12;2619;2616:1134;;;2759:12;2756:1;2752:20;2738:12;2734:39;2885:12;2983:753;3176:20;;3167:30;;;3164:1;3160:38;3391:21;;;3453:4;3440:18;;;3433:48;3608:4;3602;3592:21;;3644:17;3692:15;;;2983:753;3682:36;2987:2;;2616:1134;-1:-1:-1;3774:14:18;;2397:1407;-1:-1:-1;;2397:1407:18:o;176:956:5:-;261:11;368:4;362:11;493:10;487:4;480:24;567:8;561:4;554:22;636:5;630:4;623:19;1020:4;1014;1008;1002;989:11;982:5;971:54;902:1;895:4;889:11;886:18;795:244;785:254;;1114:1;1108:4;1101:15;;176:956;;;;:::o;6365:4213:20:-;-1:-1:-1;;;;;6690:24:20;;;;6505:12;6717:6;6674:3888;;;6760:4;6754:11;6795:4;6789;6782:18;6841:2;6823:16;6820:24;6817:1164;;6912:4;6890:27;;;6877:41;6960:3;6956:12;;;6970:2;6952:21;6939:35;;7016:30;;7010:4;7003:44;-1:-1:-1;;;;;7089:18:20;7083:4;7076:32;7100:1;7399:4;7346;7100:1;7210:5;7170:384;7725:1;7719:8;7711:6;7707:21;7688:16;7681:24;7678:51;7668:295;;-1:-1:-1;7807:1:20;7801:4;7794:15;7867:4;7860:15;-1:-1:-1;7768:1:20;7936:5;;7668:295;;6817:1164;8022:2;8004:16;8001:24;7998:1063;;8104:4;8086:16;8082:27;8069:41;8066:1;8061:50;8055:4;8048:64;8178:4;8160:16;8154:4;8141:42;8585:4;8531;8479;8426;8368:1;8290:5;8250:384;8805:1;8799:8;8791:6;8787:21;8768:16;8761:24;8758:51;8748:295;;-1:-1:-1;8887:1:20;8881:4;8874:15;8947:4;8940:15;-1:-1:-1;8848:1:20;9016:5;;8748:295;;7998:1063;9091:1;9085:4;9078:15;9149:1;9143:4;9136:15;9223:10;9218:3;9214:20;9261:1;9258;9251:12;9360:4;9353;9350:1;9346:12;9339:26;9398:4;9395:1;9391:12;9430:4;9427:1;9420:15;9523:16;9516:4;9513:1;9509:12;9502:38;9648:16;9630;9623:4;9620:1;9616:12;9603:62;10448:4;10396:1;10332:4;10314:16;10310:27;10250:1;10193:6;10144:5;10108:400;9862:8;;9859:15;;;9740:786;;-1:-1:-1;;6365:4213:20;;;;;;:::o;2649:763:15:-;2819:4;2812:25;;;;2867:1;2863:13;;;2721;2850:27;;;2925:4;2909:21;;3009:18;;3040:1;2967:4;2956:16;;;3029:13;;;3005:38;;;3363:33;;;;3325:24;3318:32;;2649:763::o;3457:531:16:-;3620:8;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;;;:::o;3488:133:2:-;3577:6;3395:9;;3388:17;3395:9;;3388:17;3414:9;;3407:17;3385:40;3414:9;3407:17;3385:40;3599:15;3288:153;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:286:21:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:21;;209:43;;199:71;;266:1;263;256:12;921:423;963:3;1001:5;995:12;1028:6;1023:3;1016:19;1053:1;1063:162;1077:6;1074:1;1071:13;1063:162;;;1139:4;1195:13;;;1191:22;;1185:29;1167:11;;;1163:20;;1156:59;1092:12;1063:162;;;1067:3;1270:1;1263:4;1254:6;1249:3;1245:16;1241:27;1234:38;1333:4;1326:2;1322:7;1317:2;1309:6;1305:15;1301:29;1296:3;1292:39;1288:50;1281:57;;;921:423;;;;:::o;1349:220::-;1498:2;1487:9;1480:21;1461:4;1518:45;1559:2;1548:9;1544:18;1536:6;1518:45;:::i;2025:131::-;-1:-1:-1;;;;;2100:31:21;;2090:42;;2080:70;;2146:1;2143;2136:12;2161:134;2229:20;;2258:31;2229:20;2258:31;:::i;2300:156::-;2366:20;;2426:4;2415:16;;2405:27;;2395:55;;2446:1;2443;2436:12;2461:456;2543:6;2551;2559;2567;2620:3;2608:9;2599:7;2595:23;2591:33;2588:53;;;2637:1;2634;2627:12;2588:53;2676:9;2663:23;2695:31;2720:5;2695:31;:::i;:::-;2745:5;-1:-1:-1;2769:36:21;2801:2;2786:18;;2769:36;:::i;:::-;2759:46;;2824:36;2856:2;2845:9;2841:18;2824:36;:::i;:::-;2461:456;;;;-1:-1:-1;2814:46:21;;2907:2;2892:18;2879:32;;-1:-1:-1;;2461:456:21:o;2922:317::-;2988:6;2996;3049:2;3037:9;3028:7;3024:23;3020:32;3017:52;;;3065:1;3062;3055:12;3017:52;3104:9;3091:23;3123:31;3148:5;3123:31;:::i;:::-;3173:5;-1:-1:-1;3197:36:21;3229:2;3214:18;;3197:36;:::i;:::-;3187:46;;2922:317;;;;;:::o;3244:247::-;3303:6;3356:2;3344:9;3335:7;3331:23;3327:32;3324:52;;;3372:1;3369;3362:12;3324:52;3411:9;3398:23;3430:31;3455:5;3430:31;:::i;3496:163::-;3563:20;;3623:10;3612:22;;3602:33;;3592:61;;3649:1;3646;3639:12;3664:533;3753:6;3761;3769;3777;3785;3838:3;3826:9;3817:7;3813:23;3809:33;3806:53;;;3855:1;3852;3845:12;3806:53;3894:9;3881:23;3913:31;3938:5;3913:31;:::i;:::-;3963:5;-1:-1:-1;3987:36:21;4019:2;4004:18;;3987:36;:::i;:::-;3977:46;;4042:36;4074:2;4063:9;4059:18;4042:36;:::i;:::-;4032:46;;4097:37;4130:2;4119:9;4115:18;4097:37;:::i;:::-;4087:47;;4153:38;4186:3;4175:9;4171:19;4153:38;:::i;:::-;4143:48;;3664:533;;;;;;;;:::o;4202:460::-;4283:6;4291;4299;4307;4360:3;4348:9;4339:7;4335:23;4331:33;4328:53;;;4377:1;4374;4367:12;4328:53;4416:9;4403:23;4435:31;4460:5;4435:31;:::i;:::-;4485:5;-1:-1:-1;4509:36:21;4541:2;4526:18;;4509:36;:::i;:::-;4499:46;;4564:36;4596:2;4585:9;4581:18;4564:36;:::i;:::-;4554:46;;4619:37;4652:2;4641:9;4637:18;4619:37;:::i;:::-;4609:47;;4202:460;;;;;;;:::o;4667:179::-;4734:20;;-1:-1:-1;;;;;4783:38:21;;4773:49;;4763:77;;4836:1;4833;4826:12;4851:460;4932:6;4940;4948;4956;5009:3;4997:9;4988:7;4984:23;4980:33;4977:53;;;5026:1;5023;5016:12;4977:53;5065:9;5052:23;5084:31;5109:5;5084:31;:::i;:::-;5134:5;-1:-1:-1;5158:36:21;5190:2;5175:18;;5158:36;:::i;:::-;5148:46;;5213:36;5245:2;5234:9;5230:18;5213:36;:::i;:::-;5203:46;;5268:37;5301:2;5290:9;5286:18;5268:37;:::i;5316:386::-;5401:6;5454:2;5442:9;5433:7;5429:23;5425:32;5422:52;;;5470:1;5467;5460:12;5422:52;5510:9;5497:23;5543:18;5535:6;5532:30;5529:50;;;5575:1;5572;5565:12;5529:50;5598:22;;5654:3;5636:16;;;5632:26;5629:46;;;5671:1;5668;5661:12;5984:1157;6073:12;;-1:-1:-1;;;;;658:38:21;646:51;;6137:4;6130:5;6126:16;6120:23;6152:47;6193:4;6188:3;6184:14;6170:12;-1:-1:-1;;;;;658:38:21;646:51;;593:110;6152:47;;6247:4;6240:5;6236:16;6230:23;6262:49;6305:4;6300:3;6296:14;6280;-1:-1:-1;;;;;658:38:21;646:51;;593:110;6262:49;;6359:4;6352:5;6348:16;6342:23;6374:49;6417:4;6412:3;6408:14;6392;-1:-1:-1;;;;;658:38:21;646:51;;593:110;6374:49;;6471:4;6464:5;6460:16;6454:23;6486:49;6529:4;6524:3;6520:14;6504;-1:-1:-1;;;;;658:38:21;646:51;;593:110;6486:49;;6583:4;6576:5;6572:16;6566:23;6598:49;6641:4;6636:3;6632:14;6616;-1:-1:-1;;;;;658:38:21;646:51;;593:110;6598:49;;6695:4;6688:5;6684:16;6678:23;6710:49;6753:4;6748:3;6744:14;6728;-1:-1:-1;;;;;658:38:21;646:51;;593:110;6710:49;;6807:4;6800:5;6796:16;6790:23;6822:49;6865:4;6860:3;6856:14;6840;-1:-1:-1;;;;;658:38:21;646:51;;593:110;6822:49;-1:-1:-1;6890:6:21;6933:14;;;6927:21;5965:6;5954:18;6991:12;;;5942:31;7023:6;7066:14;;;7060:21;375:13;;368:21;7122:12;;;356:34;7090:45;305:91;7146:277;7350:3;7335:19;;7363:54;7339:9;7399:6;7363:54;:::i;7428:118::-;7514:5;7507:13;7500:21;7493:5;7490:32;7480:60;;7536:1;7533;7526:12;7551:128;7616:20;;7645:28;7616:20;7645:28;:::i;7684:669::-;7779:6;7787;7795;7803;7811;7819;7872:3;7860:9;7851:7;7847:23;7843:33;7840:53;;;7889:1;7886;7879:12;7840:53;7928:9;7915:23;7947:31;7972:5;7947:31;:::i;:::-;7997:5;-1:-1:-1;8021:36:21;8053:2;8038:18;;8021:36;:::i;:::-;8011:46;;8076:36;8108:2;8097:9;8093:18;8076:36;:::i;:::-;8066:46;;8131:37;8164:2;8153:9;8149:18;8131:37;:::i;:::-;8121:47;;8187:38;8220:3;8209:9;8205:19;8187:38;:::i;:::-;8177:48;;8277:3;8266:9;8262:19;8249:33;8291:30;8313:7;8291:30;:::i;:::-;8340:7;8330:17;;;7684:669;;;;;;;;:::o;8933:184::-;8991:6;9044:2;9032:9;9023:7;9019:23;9015:32;9012:52;;;9060:1;9057;9050:12;9012:52;9083:28;9101:9;9083:28;:::i;9122:367::-;9185:8;9195:6;9249:3;9242:4;9234:6;9230:17;9226:27;9216:55;;9267:1;9264;9257:12;9216:55;-1:-1:-1;9290:20:21;;9333:18;9322:30;;9319:50;;;9365:1;9362;9355:12;9319:50;9402:4;9394:6;9390:17;9378:29;;9462:3;9455:4;9445:6;9442:1;9438:14;9430:6;9426:27;9422:38;9419:47;9416:67;;;9479:1;9476;9469:12;9416:67;9122:367;;;;;:::o;9494:855::-;9612:6;9620;9628;9636;9644;9652;9705:3;9693:9;9684:7;9680:23;9676:33;9673:53;;;9722:1;9719;9712:12;9673:53;9761:9;9748:23;9780:31;9805:5;9780:31;:::i;:::-;9830:5;-1:-1:-1;9854:36:21;9886:2;9871:18;;9854:36;:::i;:::-;9844:46;;9909:36;9941:2;9930:9;9926:18;9909:36;:::i;:::-;9899:46;;9997:2;9986:9;9982:18;9969:32;10010:33;10035:7;10010:33;:::i;:::-;10062:7;-1:-1:-1;10120:3:21;10105:19;;10092:33;10148:18;10137:30;;10134:50;;;10180:1;10177;10170:12;10134:50;10219:70;10281:7;10272:6;10261:9;10257:22;10219:70;:::i;:::-;9494:855;;;;-1:-1:-1;9494:855:21;;-1:-1:-1;9494:855:21;;10308:8;;9494:855;-1:-1:-1;;;9494:855:21:o;10547:712::-;10655:6;10663;10671;10679;10687;10740:3;10728:9;10719:7;10715:23;10711:33;10708:53;;;10757:1;10754;10747:12;10708:53;10796:9;10783:23;10815:31;10840:5;10815:31;:::i;:::-;10865:5;-1:-1:-1;10889:36:21;10921:2;10906:18;;10889:36;:::i;:::-;10879:46;;10944:36;10976:2;10965:9;10961:18;10944:36;:::i;:::-;10934:46;;11031:2;11020:9;11016:18;11003:32;11058:18;11050:6;11047:30;11044:50;;;11090:1;11087;11080:12;11044:50;11129:70;11191:7;11182:6;11171:9;11167:22;11129:70;:::i;:::-;10547:712;;;;-1:-1:-1;10547:712:21;;-1:-1:-1;11218:8:21;;11103:96;10547:712;-1:-1:-1;;;10547:712:21:o;11264:642::-;11429:2;11481:21;;;11551:13;;11454:18;;;11573:22;;;11400:4;;11429:2;11652:15;;;;11626:2;11611:18;;;11400:4;11695:185;11709:6;11706:1;11703:13;11695:185;;;11784:13;;11777:21;11770:29;11758:42;;11855:15;;;;11820:12;;;;11731:1;11724:9;11695:185;;;-1:-1:-1;11897:3:21;;11264:642;-1:-1:-1;;;;;;11264:642:21:o;12020:1259::-;12426:3;12421;12417:13;12409:6;12405:26;12394:9;12387:45;12368:4;12451:2;12489:3;12484:2;12473:9;12469:18;12462:31;12516:46;12557:3;12546:9;12542:19;12534:6;12516:46;:::i;:::-;12610:9;12602:6;12598:22;12593:2;12582:9;12578:18;12571:50;12644:33;12670:6;12662;12644:33;:::i;:::-;12708:2;12693:18;;12686:34;;;-1:-1:-1;;;;;12757:32:21;;12751:3;12736:19;;12729:61;12777:3;12806:19;;12799:35;;;12871:22;;;12865:3;12850:19;;12843:51;12943:13;;12965:22;;;13041:15;;;;-1:-1:-1;13003:15:21;;;;-1:-1:-1;13084:169:21;13098:6;13095:1;13092:13;13084:169;;;13159:13;;13147:26;;13228:15;;;;13193:12;;;;13120:1;13113:9;13084:169;;;-1:-1:-1;13270:3:21;;12020:1259;-1:-1:-1;;;;;;;;;;;;12020:1259:21:o;13284:127::-;13345:10;13340:3;13336:20;13333:1;13326:31;13376:4;13373:1;13366:15;13400:4;13397:1;13390:15;13416:352;13488:2;13482:9;13530:6;13518:19;;13567:18;13552:34;;13588:22;;;13549:62;13546:185;;;13653:10;13648:3;13644:20;13641:1;13634:31;13688:4;13685:1;13678:15;13716:4;13713:1;13706:15;13546:185;13747:2;13740:22;13416:352;:::o;13773:344::-;13840:2;13834:9;13882:3;13870:16;;13916:18;13901:34;;13937:22;;;13898:62;13895:185;;;14002:10;13997:3;13993:20;13990:1;13983:31;14037:4;14034:1;14027:15;14065:4;14062:1;14055:15;14122:159;14189:20;;14249:6;14238:18;;14228:29;;14218:57;;14271:1;14268;14261:12;14286:914;14350:5;14398:6;14386:9;14381:3;14377:19;14373:32;14370:52;;;14418:1;14415;14408:12;14370:52;14440:22;;:::i;:::-;14431:31;;14485:28;14503:9;14485:28;:::i;:::-;14478:5;14471:43;14546:37;14579:2;14568:9;14564:18;14546:37;:::i;:::-;14541:2;14534:5;14530:14;14523:61;14616:37;14649:2;14638:9;14634:18;14616:37;:::i;:::-;14611:2;14604:5;14600:14;14593:61;14686:37;14719:2;14708:9;14704:18;14686:37;:::i;:::-;14681:2;14674:5;14670:14;14663:61;14757:38;14790:3;14779:9;14775:19;14757:38;:::i;:::-;14751:3;14744:5;14740:15;14733:63;14829:38;14862:3;14851:9;14847:19;14829:38;:::i;:::-;14823:3;14816:5;14812:15;14805:63;14901:38;14934:3;14923:9;14919:19;14901:38;:::i;:::-;14895:3;14888:5;14884:15;14877:63;14973:38;15006:3;14995:9;14991:19;14973:38;:::i;:::-;14967:3;14960:5;14956:15;14949:63;15031:3;15066:37;15099:2;15088:9;15084:18;15066:37;:::i;:::-;15050:14;;;15043:61;15123:3;15158:35;15174:18;;;15158:35;:::i;:::-;15142:14;;;15135:59;15146:5;14286:914;-1:-1:-1;;14286:914:21:o;15205:248::-;15299:6;15352:3;15340:9;15331:7;15327:23;15323:33;15320:53;;;15369:1;15366;15359:12;15320:53;15392:55;15439:7;15428:9;15392:55;:::i;15557:1973::-;15638:12;;-1:-1:-1;;;;;11977:31:21;11965:44;;15702:4;15695:5;15691:16;15685:23;15717:46;15757:4;15752:3;15748:14;15734:12;1641:4;1630:16;1618:29;;1574:75;15717:46;;15811:4;15804:5;15800:16;15794:23;15826:48;15868:4;15863:3;15859:14;15843;1641:4;1630:16;1618:29;;1574:75;15826:48;;15922:4;15915:5;15911:16;15905:23;15937:50;15981:4;15976:3;15972:14;15956;-1:-1:-1;;;;;11977:31:21;11965:44;;11911:104;15937:50;;16035:4;16028:5;16024:16;16018:23;16050:49;16093:4;16088:3;16084:14;16068;-1:-1:-1;;;;;658:38:21;646:51;;593:110;16050:49;;16147:4;16140:5;16136:16;16130:23;16162:49;16205:4;16200:3;16196:14;16180;15534:10;15523:22;15511:35;;15458:94;16162:49;;16259:4;16252:5;16248:16;16242:23;16274:49;16317:4;16312:3;16308:14;16292;15534:10;15523:22;15511:35;;15458:94;16274:49;;16371:4;16364:5;16360:16;16354:23;16386:49;16429:4;16424:3;16420:14;16404;15534:10;15523:22;15511:35;;15458:94;16386:49;-1:-1:-1;16454:6:21;16497:14;;;16491:21;15534:10;15523:22;;;16555:12;;;15511:35;;;;16587:6;16630:14;;;16624:21;15523:22;;;16688:12;;;15511:35;16720:6;16763:14;;;16757:21;5965:6;5954:18;16821:12;;;5942:31;16853:6;16897:14;;;16891:21;1641:4;1630:16;16955:12;;;1618:29;16987:6;17031:14;;;17025:21;375:13;368:21;17088:12;;;356:34;17120:6;17164:14;;;17158:21;375:13;368:21;17221:12;;;356:34;17253:6;17295:14;;;17289:21;17275:12;;;17268:43;17330:6;17372:14;;;17366:21;17352:12;;;17345:43;17407:6;17451:14;;;17445:21;-1:-1:-1;;;;;11977:31:21;;17511:12;;;11965:44;17475:49;11911:104;17535:708;17758:2;17810:21;;;17880:13;;17783:18;;;17902:22;;;17729:4;;17758:2;17981:15;;;;17955:2;17940:18;;;17729:4;18024:193;18038:6;18035:1;18032:13;18024:193;;;18087:46;18129:3;18120:6;18114:13;18087:46;:::i;:::-;18192:15;;;;18162:6;18153:16;;;;;18060:1;18053:9;18024:193;;18248:1140;18337:6;18390:3;18378:9;18369:7;18365:23;18361:33;18358:53;;;18407:1;18404;18397:12;18358:53;18433:17;;:::i;:::-;18473:29;18492:9;18473:29;:::i;:::-;18466:5;18459:44;18535:37;18568:2;18557:9;18553:18;18535:37;:::i;:::-;18530:2;18523:5;18519:14;18512:61;18605:37;18638:2;18627:9;18623:18;18605:37;:::i;:::-;18600:2;18593:5;18589:14;18582:61;18675:37;18708:2;18697:9;18693:18;18675:37;:::i;:::-;18670:2;18663:5;18659:14;18652:61;18746:38;18779:3;18768:9;18764:19;18746:38;:::i;:::-;18740:3;18733:5;18729:15;18722:63;18818:38;18851:3;18840:9;18836:19;18818:38;:::i;:::-;18812:3;18805:5;18801:15;18794:63;18890:38;18923:3;18912:9;18908:19;18890:38;:::i;:::-;18884:3;18877:5;18873:15;18866:63;18990:3;18979:9;18975:19;18962:33;18956:3;18949:5;18945:15;18938:58;19015:3;19050:36;19082:2;19071:9;19067:18;19050:36;:::i;:::-;19034:14;;;19027:60;19106:3;19141:38;19160:18;;;19141:38;:::i;:::-;19125:14;;;19118:62;19199:3;19234:36;19251:18;;;19234:36;:::i;:::-;19218:14;;;19211:60;19290:3;19338:18;;;19325:32;19309:14;;;19302:56;;;;-1:-1:-1;19222:5:21;18248:1140;-1:-1:-1;18248:1140:21:o;19393:596::-;19480:6;19488;19496;19504;19512;19565:3;19553:9;19544:7;19540:23;19536:33;19533:53;;;19582:1;19579;19572:12;19533:53;19621:9;19608:23;19640:31;19665:5;19640:31;:::i;:::-;19690:5;-1:-1:-1;19714:36:21;19746:2;19731:18;;19714:36;:::i;:::-;19704:46;;19769:36;19801:2;19790:9;19786:18;19769:36;:::i;:::-;19759:46;;19824:37;19857:2;19846:9;19842:18;19824:37;:::i;:::-;19814:47;;19913:3;19902:9;19898:19;19885:33;19927:30;19949:7;19927:30;:::i;:::-;19976:7;19966:17;;;19393:596;;;;;;;;:::o;20202:460::-;20283:6;20291;20299;20307;20360:3;20348:9;20339:7;20335:23;20331:33;20328:53;;;20377:1;20374;20367:12;20328:53;20416:9;20403:23;20435:31;20460:5;20435:31;:::i;:::-;20485:5;-1:-1:-1;20509:36:21;20541:2;20526:18;;20509:36;:::i;:::-;20499:46;;20564:36;20596:2;20585:9;20581:18;20564:36;:::i;:::-;20554:46;;20619:37;20652:2;20641:9;20637:18;20619:37;:::i;20667:529::-;20749:6;20757;20765;20773;20826:3;20814:9;20805:7;20801:23;20797:33;20794:53;;;20843:1;20840;20833:12;20794:53;20882:9;20869:23;20901:31;20926:5;20901:31;:::i;:::-;20951:5;-1:-1:-1;20975:36:21;21007:2;20992:18;;20975:36;:::i;:::-;20965:46;;21030:36;21062:2;21051:9;21047:18;21030:36;:::i;:::-;21020:46;;21118:2;21107:9;21103:18;21090:32;21131:33;21156:7;21131:33;:::i;:::-;20667:529;;;;-1:-1:-1;20667:529:21;;-1:-1:-1;;20667:529:21:o;21398:387::-;21471:6;21479;21487;21540:2;21528:9;21519:7;21515:23;21511:32;21508:52;;;21556:1;21553;21546:12;21508:52;21595:9;21582:23;21614:31;21639:5;21614:31;:::i;:::-;21664:5;-1:-1:-1;21688:36:21;21720:2;21705:18;;21688:36;:::i;:::-;21678:46;;21743:36;21775:2;21764:9;21760:18;21743:36;:::i;:::-;21733:46;;21398:387;;;;;:::o;21790:250::-;21976:3;21961:19;;21989:45;21965:9;22016:6;21989:45;:::i;22045:523::-;22124:6;22132;22140;22148;22201:3;22189:9;22180:7;22176:23;22172:33;22169:53;;;22218:1;22215;22208:12;22169:53;22257:9;22244:23;22276:31;22301:5;22276:31;:::i;:::-;22326:5;-1:-1:-1;22350:36:21;22382:2;22367:18;;22350:36;:::i;:::-;22340:46;;22405:36;22437:2;22426:9;22422:18;22405:36;:::i;:::-;22395:46;;22493:2;22482:9;22478:18;22465:32;22506:30;22528:7;22506:30;:::i;22573:395::-;22667:6;22720:2;22708:9;22699:7;22695:23;22691:32;22688:52;;;22736:1;22733;22726:12;22688:52;22776:9;22763:23;22809:18;22801:6;22798:30;22795:50;;;22841:1;22838;22831:12;22795:50;22864:22;;22920:3;22902:16;;;22898:26;22895:46;;;22937:1;22934;22927:12;22973:318;23074:6;23082;23135:3;23123:9;23114:7;23110:23;23106:33;23103:53;;;23152:1;23149;23142:12;23103:53;23175:27;23192:9;23175:27;:::i;:::-;23165:37;;23221:64;23277:7;23272:2;23261:9;23257:18;23221:64;:::i;24809:182::-;24866:6;24919:2;24907:9;24898:7;24894:23;24890:32;24887:52;;;24935:1;24932;24925:12;24887:52;24958:27;24975:9;24958:27;:::i;24996:545::-;25089:4;25095:6;25155:11;25142:25;25249:2;25245:7;25234:8;25218:14;25214:29;25210:43;25190:18;25186:68;25176:96;;25268:1;25265;25258:12;25176:96;25295:33;;25347:20;;;-1:-1:-1;25390:18:21;25379:30;;25376:50;;;25422:1;25419;25412:12;25376:50;25455:4;25443:17;;-1:-1:-1;25506:1:21;25502:14;;;25486;25482:35;25472:46;;25469:66;;;25531:1;25528;25521:12;25546:184;25604:6;25657:2;25645:9;25636:7;25632:23;25628:32;25625:52;;;25673:1;25670;25663:12;25625:52;25696:28;25714:9;25696:28;:::i;26361:184::-;26431:6;26484:2;26472:9;26463:7;26459:23;26455:32;26452:52;;;26500:1;26497;26490:12;26452:52;-1:-1:-1;26523:16:21;;26361:184;-1:-1:-1;26361:184:21:o;26550:1637::-;26837:4;26825:17;;;26807:36;;26879:17;;26874:2;26859:18;;26852:45;26924:13;;15534:10;15523:22;26954:2;26939:18;;15511:35;26794:3;26779:19;;27012:2;27000:15;;26994:22;26989:2;26974:18;;26967:50;27064:2;27052:15;;27046:22;-1:-1:-1;;;;;11977:31:21;;27125:3;27110:19;;11965:44;-1:-1:-1;27179:2:21;27167:15;;27161:22;15534:10;15523:22;;27241:3;27226:19;;15511:35;-1:-1:-1;27295:3:21;27283:16;;27277:23;15534:10;15523:22;;27358:3;27343:19;;15511:35;-1:-1:-1;27412:3:21;27400:16;;27394:23;15534:10;15523:22;;27475:3;27460:19;;15511:35;27426:54;27529:3;27521:6;27517:16;27511:23;27553:3;27565:54;27615:2;27604:9;27600:18;27584:14;-1:-1:-1;;;;;11977:31:21;11965:44;;11911:104;27565:54;27668:3;27660:6;27656:16;27650:23;27628:45;;27692:3;27704:51;27751:2;27740:9;27736:18;27720:14;375:13;368:21;356:34;;305:91;27704:51;27780:15;;;27774:22;27815:3;27834:18;;;27827:30;;;;27882:15;;;27876:22;27917:3;27936:18;;;27929:30;;;;27984:15;;;27978:22;28019:3;28038:18;;;28031:30;;;;28104:15;;;28098:22;28092:3;28077:19;;28070:51;28164:15;;;28158:22;28152:3;28137:19;;;28130:51;;;;26550:1637;;-1:-1:-1;;;26550:1637:21:o;28192:127::-;28253:10;28248:3;28244:20;28241:1;28234:31;28284:4;28281:1;28274:15;28308:4;28305:1;28298:15;28324:1680;28609:4;28597:17;;;28579:36;;28651:17;;28646:2;28631:18;;28624:45;28697:13;;-1:-1:-1;;;;;11977:31:21;28727:2;28712:18;;11965:44;28566:3;28551:19;;28778:2;28766:15;;28760:22;-1:-1:-1;;;;;658:38:21;;28838:2;28823:18;;646:51;-1:-1:-1;28891:2:21;28879:15;;28873:22;15534:10;15523:22;;28953:3;28938:19;;15511:35;-1:-1:-1;29007:2:21;28995:15;;28989:22;15534:10;15523:22;;29069:3;29054:19;;15511:35;-1:-1:-1;29123:3:21;29111:16;;29105:23;15534:10;15523:22;;29186:3;29171:19;;15511:35;-1:-1:-1;29240:3:21;29228:16;;29222:23;15534:10;15523:22;;29303:3;29288:19;;15511:35;29254:54;29357:3;29349:6;29345:16;29339:23;29381:3;29393:53;29442:2;29431:9;29427:18;29411:14;5965:6;5954:18;5942:31;;5889:90;29393:53;29483:3;29471:16;;29465:23;29507:3;29526:18;;;29519:30;;;;29586:15;;;29580:22;;-1:-1:-1;29621:3:21;;29633:52;29666:18;;;29580:22;1641:4;1630:16;1618:29;;1574:75;29633:52;29722:15;;29716:22;;-1:-1:-1;29757:3:21;29769:54;29804:18;;;29716:22;-1:-1:-1;;;;;11977:31:21;11965:44;;11911:104;29769:54;29860:15;;;29854:22;1641:4;1630:16;29933:3;29918:19;;1618:29;29981:15;;;29975:22;29969:3;29954:19;;;29947:51;;;;28324:1680;;-1:-1:-1;;;28324:1680:21:o;32244:522::-;32344:6;32339:3;32332:19;32314:3;32370:4;32399:2;32394:3;32390:12;32383:19;;32425:5;32448:1;32458:283;32472:6;32469:1;32466:13;32458:283;;;32549:6;32536:20;32569:33;32594:7;32569:33;:::i;:::-;-1:-1:-1;;;;;32627:33:21;32615:46;;32681:12;;;;32716:15;;;;32657:1;32487:9;32458:283;;;-1:-1:-1;32757:3:21;;32244:522;-1:-1:-1;;;;;32244:522:21:o;32771:453::-;33023:4;33015:6;33011:17;33000:9;32993:36;33065:2;33060;33049:9;33045:18;33038:30;32974:4;33085:73;33154:2;33143:9;33139:18;33131:6;33123;33085:73;:::i;:::-;33077:81;;33206:10;33198:6;33194:23;33189:2;33178:9;33174:18;33167:51;32771:453;;;;;;;:::o;33229:604::-;33532:4;33524:6;33520:17;33509:9;33502:36;33586:4;33578:6;33574:17;33569:2;33558:9;33554:18;33547:45;33628:3;33623:2;33612:9;33608:18;33601:31;33483:4;33649:74;33718:3;33707:9;33703:19;33695:6;33687;33649:74;:::i;:::-;33771:10;33759:23;;;;33754:2;33739:18;;33732:51;-1:-1:-1;33814:3:21;33799:19;33792:35;33641:82;33229:604;-1:-1:-1;;;;33229:604:21:o;33838:355::-;34109:4;34097:17;;34079:36;;34066:3;34051:19;;34124:63;34183:2;34168:18;;34160:6;34124:63;:::i;34198:620::-;34369:3;34400;34447:6;34369:3;34481:310;34495:6;34492:1;34489:13;34481:310;;;34570:6;34557:20;34590:31;34615:5;34590:31;:::i;:::-;-1:-1:-1;;;;;34648:31:21;34634:46;;34703:4;34729:14;;;;34766:15;;;;;34676:1;34510:9;34481:310;;;-1:-1:-1;34807:5:21;;34198:620;-1:-1:-1;;;;;34198:620:21:o;35597:251::-;35667:6;35720:2;35708:9;35699:7;35695:23;35691:32;35688:52;;;35736:1;35733;35726:12;35688:52;35768:9;35762:16;35787:31;35812:5;35787:31;:::i;36132:245::-;36199:6;36252:2;36240:9;36231:7;36227:23;36223:32;36220:52;;;36268:1;36265;36258:12;36220:52;36300:9;36294:16;36319:28;36341:5;36319:28;:::i;36749:521::-;36826:4;36832:6;36892:11;36879:25;36986:2;36982:7;36971:8;36955:14;36951:29;36947:43;36927:18;36923:68;36913:96;;37005:1;37002;36995:12;36913:96;37032:33;;37084:20;;;-1:-1:-1;37127:18:21;37116:30;;37113:50;;;37159:1;37156;37149:12;37113:50;37192:4;37180:17;;-1:-1:-1;37223:14:21;37219:27;;;37209:38;;37206:58;;;37260:1;37257;37250:12
Swarm Source
ipfs://7ebafb7b76188b79b0bde174d599a0d340478ed83ec0a06d25b34aede9727299
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
BASE | 90.23% | $3,728.94 | 43.9567 | $163,911.77 | |
OP | Ether (ETH) | 9.29% | $3,725.45 | 4.5319 | $16,883.24 |
POL | 0.19% | $0.57152 | 590.8069 | $337.66 | |
ETH | 0.10% | $3,726.49 | 0.0494 | $184.07 | |
ARB | 0.07% | $3,726.56 | 0.0326 | $121.61 | |
SCROLL | 0.06% | $3,726.49 | 0.0311 | $115.82 | |
TAIKO | 0.02% | $3,726.49 | 0.00777 | $28.95 | |
LINEA | 0.01% | $3,719.12 | 0.006993 | $26.01 | |
BLAST | <0.01% | $3,725.32 | 0.00471908 | $17.58 | |
FRAXTAL | <0.01% | $3,737.01 | 0.003108 | $11.61 | |
ZKSYNC | <0.01% | $3,726.49 | 0.003108 | $11.58 | |
ARBNOVA | <0.01% | $3,729 | 0.000777 | $2.9 | |
OPBNB | <0.01% | $685.88 | 0.002331 | $1.6 | |
BSC | <0.01% | $685.57 | 0.002331 | $1.6 | |
CELO | <0.01% | $0.828017 | 0.00777 | $0.006434 | |
MANTLE | <0.01% | $1.1 | 0.001554 | $0.001705 |
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.