Token
DYLI (DYLI)
ERC-1155
Overview
Max Total Supply
0 DYLI
Holders
3
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
DYLI
Compiler Version
v0.8.24+commit.e11b9ed9
ZkSolc Version
v1.5.7
Optimization Enabled:
Yes with Mode 3
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "solady/src/utils/ECDSA.sol"; import "solady/src/utils/LibBitmap.sol"; import "solady/src/auth/Ownable.sol"; import "solady/src/utils/LibString.sol"; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {ERC1155C, ERC1155OpenZeppelin} from "@limitbreak/creator-token-contracts/contracts/erc1155c/ERC1155C.sol"; import {ERC2981, BasicRoyalties} from "@limitbreak/creator-token-contracts/contracts/programmable-royalties/BasicRoyalties.sol"; /** * @title DYLI * @dev ERC1155C token contract with programmable royalties and fair drop lottery queue system * @author DYLI (https://www.dyli.io/) */ contract DYLI is ERC1155C, Ownable, BasicRoyalties { /// @notice BitMap for refund override status of token IDs using LibBitmap for LibBitmap.Bitmap; /// @notice Error for invalid nonce error InvalidNonce(); /// @notice Error for invalid signature error InvalidSignature(); /// @notice Error when a payment fails error PaymentFailed(); /// @notice Error when the sale has not started error SaleNotStarted(); /// @notice Error when the caller is not the token owner or a marketplace error OnlyTokenOwnerOrMarketplaceCanTransfer(); /// @notice Error when the sale has ended error SaleEnded(); /// @notice Error when exceeding maximum quantity error ExceedsMaxQuantity(); /// @notice Error when token minting is disabled error TokenMintingDisabled(); /// @notice Error when token is not refundable error TokenNotRefundable(); /// @notice Error for refund transfer failure error RefundTransferFailed(); /// @notice Error for blockhash not found error BlockhashNotFound(); /// @notice Error for blockhash expiration error BlockhashExpired(); /// @notice Error for a user not in the queue error NotInQueue(); /// @notice Error when the queue is already processed error QueueAlreadyProcessed(); /// @notice Error when the queue is still open error QueueStillOpen(); /// @notice Error when the queue period has ended error QueuePeriodEnded(); /// @notice Error when the queue is empty error QueueEmpty(); /// @notice Error when a user is already in the queue error AlreadyInQueue(); /// @notice Error when the queue blockhash is not ready error BlockhashNotReady(); /// @notice Error when the queue is already revealed error QueueAlreadyRevealed(); /// @notice Error when a queue has already been committed for processing error QueueAlreadyCommitted(); /// @notice Error for insufficient tokens to refund error InsufficientTokensToRefund(); /// @notice Error for insufficient tokens to redeem error InsufficientTokensToRedeem(); /// @notice Error lose queue refund being more than queue fee error LoseQueueRefundExceedsQueueFee(); /// @notice Mapping of tokenId to queue data mapping(uint256 => Queue) public queue; /// @notice Mapping of tokenId to whether a user has entered the queue mapping(uint256 => mapping(address => bool)) public enteredQueue; /// @notice Mapping of tokenId to token data mapping(uint256 => TokenData) public tokenData; /// @notice Mapping of tokenId to disabled status mapping(uint256 => bool) public tokenDisabled; /// @notice Mapping of tokenId to total minted count mapping(uint256 => uint256) public totalMinted; /// @notice Mapping of tokenId to total refunded count mapping(uint256 => uint256) public totalRefunded; /// @notice Mapping of tokenId to total redeemed count mapping(uint256 => uint256) public totalRedeemed; /// @notice Mapping of user address to nonce mapping(address => uint256) public nonces; /// @notice Mapping of user address and nonce to whether it was used mapping(address => mapping(uint256 => bool)) public nonceUsed; /// @notice Mapping of blacklisted marketplaces mapping(address => bool) public blacklistedMarketplaces; /// @notice USDC token contract IERC20 public immutable USDC; /// @notice Current token ID uint256 public currentTokenId = 20000; /// @notice Address of the signer address public signerAddress; /// @notice Fee amount uint256 public fee; /// @notice Queue fee amount uint256 public queueFee; /// @notice Fee you get back if you lose the queue uint256 public loseQueueRefund; /// @notice Create fee amount uint256 public createFee; /// @notice Base URI for tokens string public baseURI; /// @dev Fee recipient address address private _feeRecipient; /// @notice Bitmap to override the refundable status of token IDs. LibBitmap.Bitmap private isRefundableOverride; /// @notice Emitted when a new drop is created event DropCreated( uint256 indexed tokenId, address indexed creator, uint256 price ); /// @notice Emitted when a token is minted event TokenMinted( uint256 indexed tokenId, address indexed minter, uint256 price, uint256 fee ); /// @notice Emitted when a token is refunded event TokenRefunded( uint256 indexed tokenId, address indexed minter, uint256 amount, uint256 price ); /// @notice Emitted when a token is redeemed event TokenRedeemed(uint256 indexed tokenId, address indexed redeemer); /// @notice Emitted when a user joins a queue event QueueJoined( uint256 indexed tokenId, address indexed user, uint256 amount ); /// @notice Emitted when a user leaves a queue event QueueLeft( uint256 indexed tokenId, address indexed user, uint256 amount ); /** * @dev Modifier to validate and update nonces */ modifier checkNonce(address user, uint256 nonce) { if (nonceUsed[user][nonce]) revert InvalidNonce(); nonceUsed[user][nonce] = true; nonces[user]++; _; } /** * @dev Token data structure */ struct TokenData { uint256 nonReserved; uint256 price; uint256 startTimestamp; uint256 endTimestamp; uint256 minMint; address creator; bool isOE; uint256 reserved; uint256 purchased; } /** * @dev Queue structure */ struct Queue { uint256 reserved; uint256 cost; uint256 blockCommit; uint256 rng; uint256 entries; uint256 claimed; uint256 queueFee; uint256 loseQueueRefund; } /** * @notice Constructor to initialize the contract * @param _baseURI Base URI for token metadata * @param usdc_ Address of the USDC token contract * @param signerAddress_ Address of the signer * @param feeRecipient_ Address to receive fees * @param royaltyFeeNumerator_ Royalty fee numerator * @param initialQueueFee Initial fee for joining the queue * @param initialLoseQueueRefund Initial refund if a user loses the queue * @param initialCreateFee Initial fee for creating a new drop * @param initialFee Initial fee amount for minting */ constructor( string memory _baseURI, address usdc_, address signerAddress_, address feeRecipient_, uint96 royaltyFeeNumerator_, uint256 initialQueueFee, uint256 initialLoseQueueRefund, uint256 initialCreateFee, uint256 initialFee ) ERC1155OpenZeppelin(_baseURI) BasicRoyalties(feeRecipient_, royaltyFeeNumerator_) { _initializeOwner(msg.sender); USDC = IERC20(usdc_); baseURI = _baseURI; signerAddress = signerAddress_; _feeRecipient = feeRecipient_; fee = initialFee; queueFee = initialQueueFee; loseQueueRefund = initialLoseQueueRefund; createFee = initialCreateFee; } /** * @notice Returns the name of the contract * @return The name of the contract */ function name() external pure returns (string memory) { return "DYLI"; } /** * @notice Returns the symbol of the contract * @return The symbol of the contract */ function symbol() external pure returns (string memory) { return "DYLI"; } /** * @notice Updates the base URI for token metadata * @param _URI New base URI */ function setURI(string memory _URI) external onlyOwner { baseURI = _URI; } /** * @notice Updates the fee recipient address * @param newFeeRecipient Address of the new fee recipient */ function setFeeRecipient(address newFeeRecipient) external onlyOwner { _feeRecipient = newFeeRecipient; } /** * @notice Updates the fee amount * @param newFee New fee amount */ function setFee(uint256 newFee) external onlyOwner { fee = newFee; } /** * @notice Updates the queue fee amount and ensures loseQueueRefund is not greater than queueFee * @param newQueueFee New queue fee amount */ function setQueueFee(uint256 newQueueFee) external onlyOwner { queueFee = newQueueFee; if (loseQueueRefund > queueFee) { loseQueueRefund = queueFee; } } /** * @notice Updates the refund you get back if you lose the queue * @param newLoseQueueRefund New refund you get back if you lose the queue */ function setNewLoseQueueRefund(uint256 newLoseQueueRefund) external onlyOwner { if (newLoseQueueRefund > queueFee) { revert LoseQueueRefundExceedsQueueFee(); } loseQueueRefund = newLoseQueueRefund; } /** * @notice Updates the create fee amount * @param newCreateFee New create fee amount */ function setCreateFee(uint256 newCreateFee) external onlyOwner { createFee = newCreateFee; } /** * @notice Updates the signer address * @param newSigner Address of the new signer */ function setSigner(address newSigner) external onlyOwner { signerAddress = newSigner; } /** * @notice Updates the refundable override status for a token ID * @param tokenId Token ID to update * @param refundable New refundable status */ function setRefundableOverride(uint256 tokenId, bool refundable) external onlyOwner { isRefundableOverride.setTo(tokenId, refundable); } /** * @notice Creates a new drop * @param nonReserved Maximum number of tokens available for public minting, excluding reserved tokens. * @param price Price per token * @param _isOE Whether the drop is open edition * @param isStripe Whether the payment is made via Stripe * @param signature Cryptographic signature for verification * @param nonce Nonce for transaction validation * @param startTimestamp Start timestamp of the sale * @param endTimestamp End timestamp of the sale * @param minMint Minimum number of tokens to mint * @param reserved Number of tokens reserved * @return tokenId ID of the newly created drop */ function createDrop( uint256 nonReserved, uint256 price, bool _isOE, bool isStripe, bytes memory signature, uint256 nonce, uint256 startTimestamp, uint256 endTimestamp, uint256 minMint, uint256 reserved ) external checkNonce(msg.sender, nonce) returns (uint256) { if (startTimestamp == 0) startTimestamp = block.timestamp; if (endTimestamp != 0 && endTimestamp <= startTimestamp) revert SaleEnded(); bytes32 hash = ECDSA.toEthSignedMessageHash( keccak256( abi.encode( msg.sender, nonReserved, price, _isOE, isStripe, nonce, startTimestamp, endTimestamp, minMint, reserved ) ) ); if (!_verify(hash, signature)) revert InvalidSignature(); if ( !isStripe && !USDC.transferFrom(msg.sender, _feeRecipient, createFee) ) revert PaymentFailed(); return _createDrop( msg.sender, nonReserved, price, _isOE, startTimestamp, endTimestamp, minMint, reserved ); } /** * @notice Mints a token * @param tokenId ID of the token to mint * @param signature Cryptographic signature for verification * @param nonce Nonce for transaction validation * @param isStripe Whether the payment is made via Stripe * @param tax Additional tax amount */ function mintToken( uint256 tokenId, bytes memory signature, uint256 nonce, bool isStripe, uint256 tax ) external checkNonce(msg.sender, nonce) { TokenData storage data = tokenData[tokenId]; if (data.endTimestamp != 0 && block.timestamp > data.endTimestamp) revert SaleEnded(); bytes32 hash = ECDSA.toEthSignedMessageHash( keccak256(abi.encode(msg.sender, tokenId, nonce, isStripe, tax)) ); if (!_verify(hash, signature)) revert InvalidSignature(); if (!isStripe) { uint256 totalFee = fee + tax; if (!USDC.transferFrom(msg.sender, address(this), data.price)) revert PaymentFailed(); if (!USDC.transferFrom(msg.sender, _feeRecipient, totalFee)) revert PaymentFailed(); } _mintToken(msg.sender, tokenId, data, false); } /** * @notice Allows the creator or contract owner to mint tokens for a recipient before sale starts. * @dev Nonce is checked for replay protection. Payments handled based on the `isStripe` flag. * @param tokenId ID of the token to mint. * @param signature Signature for verifying the transaction. * @param recipient Address of the recipient to receive minted tokens. * @param nonce Unique transaction nonce. * @param isStripe Flag indicating whether the payment was made via Stripe. * @param tax Additional tax amount. */ function mintTokenByCreator( uint256 tokenId, bytes memory signature, address recipient, uint256 nonce, bool isStripe, uint256 tax ) external checkNonce(msg.sender, nonce) { bytes32 hash = ECDSA.toEthSignedMessageHash( keccak256(abi.encode(msg.sender, tokenId, nonce, isStripe, tax)) ); if (!_verify(hash, signature)) revert InvalidSignature(); TokenData storage data = tokenData[tokenId]; if (msg.sender != data.creator && msg.sender != owner()) revert SaleNotStarted(); if (data.endTimestamp != 0 && block.timestamp > data.endTimestamp) { revert SaleEnded(); } if (!isStripe) { uint256 totalFee = fee + tax; if (!USDC.transferFrom(recipient, address(this), data.price)) revert PaymentFailed(); if (!USDC.transferFrom(recipient, _feeRecipient, totalFee)) revert PaymentFailed(); } _mintToken(recipient, tokenId, data, false); } /** * @notice Redeems multiple tokens in a batch. * @dev Uses nonces for replay protection and checks the provided signature. * @param tokenIds Array of token IDs to redeem. * @param nonce Unique transaction nonce. * @param fees Array of additional fees for each token. * @param signature Signature for verifying the transaction. */ function batchRedeem( uint256[] memory tokenIds, uint256 nonce, uint256[] memory fees, bytes memory signature ) external checkNonce(msg.sender, nonce) { bytes32 hash = ECDSA.toEthSignedMessageHash( keccak256(abi.encode(msg.sender, tokenIds, nonce, fees)) ); if (!_verify(hash, signature)) revert InvalidSignature(); for (uint256 i = 0; i < tokenIds.length; i++) { if (fees[i] > 0) { if (!USDC.transferFrom(msg.sender, _feeRecipient, fees[i])) revert PaymentFailed(); } totalRedeemed[tokenIds[i]] += 1; _burn(msg.sender, tokenIds[i], 1); emit TokenRedeemed(tokenIds[i], msg.sender); } } /** * @notice Refunds tokens to the sender. * @dev Requires valid signature and verifies refund eligibility. * @param tokenId ID of the token to refund. * @param amount Number of tokens to refund. * @param nonce Unique transaction nonce. * @param signature Signature for verifying the transaction. */ function refundToken( uint256 tokenId, uint256 amount, uint256 nonce, bytes memory signature ) external checkNonce(msg.sender, nonce) { bytes32 hash = ECDSA.toEthSignedMessageHash( keccak256(abi.encode(msg.sender, tokenId, amount, nonce)) ); if (!_verify(hash, signature)) revert InvalidSignature(); TokenData storage data = tokenData[tokenId]; if (!isRefundableOverride.get(tokenId)) { if ( block.timestamp > data.endTimestamp && totalMinted[tokenId] <= data.minMint ) { revert TokenNotRefundable(); } } uint256 totalRefund; unchecked { totalRefund = data.price * amount; } if (totalRefund == 0) revert RefundTransferFailed(); unchecked { totalRefunded[tokenId] += amount; } _burn(msg.sender, tokenId, amount); if (!USDC.transfer(msg.sender, totalRefund)) revert RefundTransferFailed(); emit TokenRefunded(tokenId, msg.sender, amount, totalRefund); } /** * @notice Allows a user to join a token's queue. * @dev Requires that the queue exists and the user is not already in it. * @param tokenId ID of the token queue to join. */ function joinQueue(uint256 tokenId) external { TokenData storage data = tokenData[tokenId]; if (data.reserved == 0) revert QueueEmpty(); if (block.timestamp > data.startTimestamp) revert QueuePeriodEnded(); if (enteredQueue[tokenId][msg.sender]) revert AlreadyInQueue(); uint256 totalAmount = data.price + queueFee; enteredQueue[tokenId][msg.sender] = true; queue[tokenId].entries++; if (!USDC.transferFrom(msg.sender, address(this), totalAmount)) revert PaymentFailed(); emit QueueJoined(tokenId, msg.sender, totalAmount); } /** * @notice Allows a user to leave a token's queue. * @dev Refunds the user and removes them from the queue. * @param tokenId ID of the token queue to leave. */ function leaveQueue(uint256 tokenId) external { if (!enteredQueue[tokenId][msg.sender]) revert NotInQueue(); if (queue[tokenId].blockCommit != 0) revert QueueAlreadyCommitted(); uint256 amount = queue[tokenId].cost + queue[tokenId].queueFee; enteredQueue[tokenId][msg.sender] = false; queue[tokenId].entries--; if (!USDC.transfer(msg.sender, amount)) revert RefundTransferFailed(); emit QueueLeft(tokenId, msg.sender, amount); } /** * @notice Commits the queue for processing. * @dev Ensures the queue is ready for RNG calculation. * @param tokenId ID of the token queue to commit. */ function commitQueue(uint256 tokenId) external { TokenData storage data = tokenData[tokenId]; Queue storage queueData = queue[tokenId]; if (block.timestamp < data.startTimestamp) revert QueueStillOpen(); if (queueData.reserved == 0) revert QueueEmpty(); if (block.number > queueData.blockCommit + 256 && queueData.rng == 0) { queueData.blockCommit = block.number + 5; return; } if (queueData.blockCommit != 0) revert QueueAlreadyProcessed(); queueData.blockCommit = block.number + 5; } /** * @notice Reveals the RNG for a queue after the block is committed. * @dev Uses the blockhash to determine the RNG. * @param tokenId ID of the token queue to reveal. */ function revealQueue(uint256 tokenId) external { Queue storage queueData = queue[tokenId]; if (queueData.rng != 0) revert QueueAlreadyRevealed(); if (block.number < queueData.blockCommit) revert BlockhashNotReady(); bytes32 blockHash = blockhash(queueData.blockCommit); if (blockHash == 0) revert BlockhashNotFound(); if (block.number >= queueData.blockCommit + 256) revert BlockhashExpired(); queueData.rng = uint256(blockHash); } /** * @notice Claims a token from the queue if the user is a winner. * @dev Refunds the user if they are not a winner. * @param tokenId ID of the token to claim. */ function claimFromQueue(uint256 tokenId) external { if (!enteredQueue[tokenId][msg.sender]) revert NotInQueue(); bool isWinner = checkQueueResult(tokenId, msg.sender); enteredQueue[tokenId][msg.sender] = false; if (!isWinner) { if ( !USDC.transfer( msg.sender, queue[tokenId].cost + queue[tokenId].loseQueueRefund ) ) revert RefundTransferFailed(); return; } TokenData storage data = tokenData[tokenId]; _mintToken(msg.sender, tokenId, data, true); } /** * @notice Blacklists or removes a blacklist for a specific marketplace. * @param marketplace Address of the marketplace. * @param isBlacklisted Boolean indicating whether the marketplace is blacklisted. */ function blacklistMarketplace(address marketplace, bool isBlacklisted) public onlyOwner { blacklistedMarketplaces[marketplace] = isBlacklisted; } /** * @notice Enables or disables minting for a specific token. * @param tokenId ID of the token to enable/disable. * @param disabled Boolean indicating whether minting is disabled. */ function disableToken(uint256 tokenId, bool disabled) public onlyOwner { tokenDisabled[tokenId] = disabled; } /** * @notice Transfers a token from one address to another. * @dev Validates that the caller is either the owner or a non-blacklisted marketplace. * @param from Address of the sender. * @param to Address of the recipient. * @param id ID of the token to transfer. * @param amount Amount of tokens to transfer. * @param data Additional data for the transfer. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public override { if (msg.sender != from && blacklistedMarketplaces[msg.sender]) revert OnlyTokenOwnerOrMarketplaceCanTransfer(); super.safeTransferFrom(from, to, id, amount, data); } /** * @notice Transfers multiple tokens in a batch from one address to another. * @dev Validates that the caller is either the owner or a non-blacklisted marketplace. * @param from Address of the sender. * @param to Address of the recipient. * @param ids Array of token IDs to transfer. * @param amounts Array of token amounts to transfer. * @param data Additional data for the transfer. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public override { if (msg.sender != from && blacklistedMarketplaces[msg.sender]) revert PaymentFailed(); super.safeBatchTransferFrom(from, to, ids, amounts, data); } /** * @notice Withdraws a specified amount of USDC from the contract. * @param amount Amount of USDC to withdraw. */ function withdraw(uint256 amount) public onlyOwner { if (amount == 0) revert PaymentFailed(); USDC.transfer(msg.sender, amount); } /** * @notice Withdraws the full USDC balance from the contract. */ function fullWithdraw() public onlyOwner { USDC.transfer(msg.sender, USDC.balanceOf(address(this))); } /** * @notice Checks whether a user is a winner in a token's queue. * @dev The result of this function is dynamic and can change based on the following factors: * - The state of the `rng` (random number generator) for the queue. * - The number of `claimed` entries in the queue, which can increase over time. * Users should claim their tokens promptly if they are determined to be winners, as the result of this function * is not guaranteed to remain consistent. * @param tokenId ID of the token queue to check. * @param user Address of the user to check. * @return Boolean indicating whether the user is a winner. */ function checkQueueResult(uint256 tokenId, address user) public view returns (bool) { Queue memory queueData = queue[tokenId]; if (!enteredQueue[tokenId][user]) { return false; } uint256 rng = queueData.rng; uint256 entries = queueData.entries; uint256 reserved = queueData.reserved; if (rng == 0 || queueData.claimed >= queueData.reserved) { return false; } if (queueData.entries <= queueData.reserved) return true; uint256 rank = uint256(keccak256(abi.encode(rng, user))); return (rank % entries) < reserved; } /** * @notice Returns the URI for a specific token ID. * @param tokenId ID of the token to retrieve the URI for. * @return The URI of the token. */ function uri(uint256 tokenId) public view override returns (string memory) { return string(abi.encodePacked(baseURI, "/", LibString.toString(tokenId))); } /** * @notice Checks if a given interface is supported. * @param interfaceId ID of the interface to check. * @return Boolean indicating whether the interface is supported. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC1155C, ERC2981) returns (bool) { return super.supportsInterface(interfaceId); } /** * @notice Internal function to create a new drop * @param creator Address of the creator * @param nonReserved Maximum number of tokens available for public minting, excluding reserved tokens. * @param price Price per token * @param _isOE Whether the drop is open edition * @param startTimestamp Start timestamp of the sale * @param endTimestamp End timestamp of the sale * @param minMint Minimum number of tokens to mint * @param reserved Number of tokens reserved * @return tokenId ID of the newly created drop */ function _createDrop( address creator, uint256 nonReserved, uint256 price, bool _isOE, uint256 startTimestamp, uint256 endTimestamp, uint256 minMint, uint256 reserved ) internal returns (uint256) { unchecked { currentTokenId++; } tokenData[currentTokenId] = TokenData( nonReserved, price, startTimestamp, endTimestamp, minMint, creator, _isOE, reserved, 0 ); emit DropCreated(currentTokenId, creator, price); if (reserved > 0) { queue[currentTokenId] = Queue( reserved, price, 0, 0, 0, 0, queueFee, loseQueueRefund ); } return currentTokenId; } /** * @notice Internal function to mint a token to a user. * @dev Handles minting logic, including checks for open edition and maximum supply. * @param user Address of the user to mint the token to. * @param tokenId ID of the token to mint. * @param fromQueue bool to decide if the mint is coming from claiming or regular mint. * @param data Token data structure for the specified tokenId. */ function _mintToken( address user, uint256 tokenId, TokenData storage data, bool fromQueue ) internal { if (tokenDisabled[tokenId]) revert TokenMintingDisabled(); Queue storage queueData = queue[tokenId]; uint256 availableSupply = 0; if (fromQueue) { availableSupply = queueData.reserved - queueData.claimed; queueData.claimed++; } else { uint256 unclaimedFromQueue = queueData.entries < data.reserved ? data.reserved - queueData.entries : 0; uint256 realNonreserved = data.nonReserved + unclaimedFromQueue; availableSupply = realNonreserved - data.purchased; data.purchased++; } if (!data.isOE && availableSupply <= 0) revert ExceedsMaxQuantity(); totalMinted[tokenId] += 1; _mint(user, tokenId, 1, ""); emit TokenMinted(tokenId, user, data.price, fee); } /** * @dev Internal function to enforce that the caller is the contract owner. */ function _requireCallerIsContractOwner() internal view virtual override { if (msg.sender != owner()) revert SaleNotStarted(); } /** * @notice Verifies the validity of a signature. * @dev Recovers the signer address and compares it with the stored signer address. * @param hash Hash of the data being signed. * @param signature Signature to verify. * @return Boolean indicating whether the signature is valid. */ function _verify(bytes32 hash, bytes memory signature) internal view returns (bool) { address recovered = ECDSA.recover(hash, signature); return recovered == signerAddress; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Gas optimized ECDSA wrapper. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol) /// /// @dev Note: /// - The recovery functions use the ecrecover precompile (0x1). /// - As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure. /// This is for more safety by default. /// Use the `tryRecover` variants if you need to get the zero address back /// upon recovery failure instead. /// - 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 directly use signatures as unique identifiers: /// - The recovery operations do NOT check if a signature is non-malleable. /// - 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. /// - If you need a unique hash from a signature, please use the `canonicalHash` functions. library ECDSA { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The order of the secp256k1 elliptic curve. uint256 internal constant N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141; /// @dev `N/2 + 1`. Used for checking the malleability of the signature. uint256 private constant _HALF_N_PLUS_1 = 0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The signature is invalid. error InvalidSignature(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RECOVERY OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function recover(bytes32 hash, bytes memory signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { for { let m := mload(0x40) } 1 { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } { switch mload(signature) case 64 { let vs := mload(add(signature, 0x40)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x60, shr(1, shl(1, vs))) // `s`. } case 65 { mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x60, mload(add(signature, 0x40))) // `s`. } default { continue } mstore(0x00, hash) mstore(0x40, mload(add(signature, 0x20))) // `r`. result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20)) mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if returndatasize() { break } } } } /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function recoverCalldata(bytes32 hash, bytes calldata signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { for { let m := mload(0x40) } 1 { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } { switch signature.length case 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`. } case 65 { mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`. calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`. } default { continue } mstore(0x00, hash) result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20)) mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if returndatasize() { break } } } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the EIP-2098 short form signature defined by `r` and `vs`. function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, r) mstore(0x60, shr(1, shl(1, vs))) // `s`. result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20)) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the signature defined by `v`, `r`, `s`. function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, and(v, 0xff)) mstore(0x40, r) mstore(0x60, s) result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20)) // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. if iszero(returndatasize()) { mstore(0x00, 0x8baa579f) // `InvalidSignature()`. revert(0x1c, 0x04) } mstore(0x60, 0) // Restore the zero slot. mstore(0x40, m) // Restore the free memory pointer. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* TRY-RECOVER OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // WARNING! // These functions will NOT revert upon recovery failure. // Instead, they will return the zero address upon recovery failure. // It is critical that the returned address is NEVER compared against // a zero address (e.g. an uninitialized address variable). /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function tryRecover(bytes32 hash, bytes memory signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { for { let m := mload(0x40) } 1 {} { switch mload(signature) case 64 { let vs := mload(add(signature, 0x40)) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x60, shr(1, shl(1, vs))) // `s`. } case 65 { mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`. mstore(0x60, mload(add(signature, 0x40))) // `s`. } default { break } mstore(0x00, hash) mstore(0x40, mload(add(signature, 0x20))) // `r`. pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20)) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. break } } } /// @dev Recovers the signer's address from a message digest `hash`, and the `signature`. function tryRecoverCalldata(bytes32 hash, bytes calldata signature) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { for { let m := mload(0x40) } 1 {} { switch signature.length case 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`. } case 65 { mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`. calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`. } default { break } mstore(0x00, hash) pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20)) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. break } } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the EIP-2098 short form signature defined by `r` and `vs`. function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, add(shr(255, vs), 27)) // `v`. mstore(0x40, r) mstore(0x60, shr(1, shl(1, vs))) // `s`. pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20)) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /// @dev Recovers the signer's address from a message digest `hash`, /// and the signature defined by `v`, `r`, `s`. function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns (address result) { /// @solidity memory-safe-assembly assembly { let m := mload(0x40) // Cache the free memory pointer. mstore(0x00, hash) mstore(0x20, and(v, 0xff)) mstore(0x40, r) mstore(0x60, s) pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20)) mstore(0x60, 0) // Restore the zero slot. // `returndatasize()` will be `0x20` upon success, and `0x00` otherwise. result := mload(xor(0x60, returndatasize())) mstore(0x40, m) // Restore the free memory pointer. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* 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://ethereum.org/en/developers/docs/apis/json-rpc/#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://ethereum.org/en/developers/docs/apis/json-rpc/#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. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CANONICAL HASH FUNCTIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // The following functions returns the hash of the signature in it's canonicalized format, // which is the 65-byte `abi.encodePacked(r, s, uint8(v))`, where `v` is either 27 or 28. // If `s` is greater than `N / 2` then it will be converted to `N - s` // and the `v` value will be flipped. // If the signature has an invalid length, or if `v` is invalid, // a uniquely corrupt hash will be returned. // These functions are useful for "poor-mans-VRF". /// @dev Returns the canonical hash of `signature`. function canonicalHash(bytes memory signature) internal pure returns (bytes32 result) { // @solidity memory-safe-assembly assembly { let l := mload(signature) for {} 1 {} { mstore(0x00, mload(add(signature, 0x20))) // `r`. let s := mload(add(signature, 0x40)) let v := mload(add(signature, 0x41)) if eq(l, 64) { v := add(shr(255, s), 27) s := shr(1, shl(1, s)) } if iszero(lt(s, _HALF_N_PLUS_1)) { v := xor(v, 7) s := sub(N, s) } mstore(0x21, v) mstore(0x20, s) result := keccak256(0x00, 0x41) mstore(0x21, 0) // Restore the overwritten part of the free memory pointer. break } // If the length is neither 64 nor 65, return a uniquely corrupted hash. if iszero(lt(sub(l, 64), 2)) { // `bytes4(keccak256("InvalidSignatureLength"))`. result := xor(keccak256(add(signature, 0x20), l), 0xd62f1ab2) } } } /// @dev Returns the canonical hash of `signature`. function canonicalHashCalldata(bytes calldata signature) internal pure returns (bytes32 result) { // @solidity memory-safe-assembly assembly { for {} 1 {} { mstore(0x00, calldataload(signature.offset)) // `r`. let s := calldataload(add(signature.offset, 0x20)) let v := calldataload(add(signature.offset, 0x21)) if eq(signature.length, 64) { v := add(shr(255, s), 27) s := shr(1, shl(1, s)) } if iszero(lt(s, _HALF_N_PLUS_1)) { v := xor(v, 7) s := sub(N, s) } mstore(0x21, v) mstore(0x20, s) result := keccak256(0x00, 0x41) mstore(0x21, 0) // Restore the overwritten part of the free memory pointer. break } // If the length is neither 64 nor 65, return a uniquely corrupted hash. if iszero(lt(sub(signature.length, 64), 2)) { calldatacopy(mload(0x40), signature.offset, signature.length) // `bytes4(keccak256("InvalidSignatureLength"))`. result := xor(keccak256(mload(0x40), signature.length), 0xd62f1ab2) } } } /// @dev Returns the canonical hash of `signature`. function canonicalHash(bytes32 r, bytes32 vs) internal pure returns (bytes32 result) { // @solidity memory-safe-assembly assembly { mstore(0x00, r) // `r`. let v := add(shr(255, vs), 27) let s := shr(1, shl(1, vs)) mstore(0x21, v) mstore(0x20, s) result := keccak256(0x00, 0x41) mstore(0x21, 0) // Restore the overwritten part of the free memory pointer. } } /// @dev Returns the canonical hash of `signature`. function canonicalHash(uint8 v, bytes32 r, bytes32 s) internal pure returns (bytes32 result) { // @solidity memory-safe-assembly assembly { mstore(0x00, r) // `r`. if iszero(lt(s, _HALF_N_PLUS_1)) { v := xor(v, 7) s := sub(N, s) } mstore(0x21, v) mstore(0x20, s) result := keccak256(0x00, 0x41) mstore(0x21, 0) // Restore the overwritten part of the free memory pointer. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* 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; 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 in `[0..upTo]`. /// If no set bit is found, returns `NOT_FOUND`. function findLastSet(Bitmap storage bitmap, uint256 upTo) internal view returns (uint256 setBitIndex) { setBitIndex = NOT_FOUND; uint256 bucket = upTo >> 8; uint256 bits; /// @solidity memory-safe-assembly assembly { mstore(0x00, bucket) mstore(0x20, bitmap.slot) let offset := and(0xff, not(upTo)) // `256 - (255 & upTo) - 1`. bits := shr(offset, shl(offset, sload(keccak256(0x00, 0x40)))) if iszero(or(bits, iszero(bucket))) { for {} 1 {} { bucket := add(bucket, setBitIndex) // `sub(bucket, 1)`. mstore(0x00, bucket) bits := sload(keccak256(0x00, 0x40)) if or(bits, iszero(bucket)) { break } } } } if (bits != 0) { setBitIndex = (bucket << 8) | LibBit.fls(bits); /// @solidity memory-safe-assembly assembly { setBitIndex := or(setBitIndex, sub(0, gt(setBitIndex, upTo))) } } } /// @dev Returns the index of the least significant unset bit in `[begin..upTo]`. /// If no unset bit is found, returns `NOT_FOUND`. function findFirstUnset(Bitmap storage bitmap, uint256 begin, uint256 upTo) internal view returns (uint256 unsetBitIndex) { unsetBitIndex = NOT_FOUND; uint256 bucket = begin >> 8; uint256 negBits; /// @solidity memory-safe-assembly assembly { mstore(0x00, bucket) mstore(0x20, bitmap.slot) let offset := and(0xff, begin) negBits := shl(offset, shr(offset, not(sload(keccak256(0x00, 0x40))))) if iszero(negBits) { let lastBucket := shr(8, upTo) for {} 1 {} { bucket := add(bucket, 1) mstore(0x00, bucket) negBits := not(sload(keccak256(0x00, 0x40))) if or(negBits, gt(bucket, lastBucket)) { break } } if gt(bucket, lastBucket) { negBits := shl(and(0xff, not(upTo)), shr(and(0xff, not(upTo)), negBits)) } } } if (negBits != 0) { uint256 r = (bucket << 8) | LibBit.ffs(negBits); /// @solidity memory-safe-assembly assembly { unsetBitIndex := or(r, sub(0, or(gt(r, upTo), lt(r, begin)))) } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(account), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * May emit a {RoleGranted} event. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "../utils/CreatorTokenBase.sol"; import "../token/erc1155/ERC1155OpenZeppelin.sol"; /** * @title ERC1155C * @author Limit Break, Inc. * @notice Extends OpenZeppelin's ERC1155 implementation with Creator Token functionality, which * allows the contract owner to update the transfer validation logic by managing a security policy in * an external transfer validation security policy registry. See {CreatorTokenTransferValidator}. */ abstract contract ERC1155C is ERC1155OpenZeppelin, CreatorTokenBase { function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(ICreatorToken).interfaceId || super.supportsInterface(interfaceId); } /// @dev Ties the open-zeppelin _beforeTokenTransfer hook to more granular transfer validation logic function _beforeTokenTransfer( address /*operator*/, address from, address to, uint256[] memory ids, uint256[] memory /*amounts*/, bytes memory /*data*/ ) internal virtual override { uint256 idsArrayLength = ids.length; for (uint256 i = 0; i < idsArrayLength;) { _validateBeforeTransfer(from, to, ids[i]); unchecked { ++i; } } } /// @dev Ties the open-zeppelin _afterTokenTransfer hook to more granular transfer validation logic function _afterTokenTransfer( address /*operator*/, address from, address to, uint256[] memory ids, uint256[] memory /*amounts*/, bytes memory /*data*/ ) internal virtual override { uint256 idsArrayLength = ids.length; for (uint256 i = 0; i < idsArrayLength;) { _validateAfterTransfer(from, to, ids[i]); unchecked { ++i; } } } } /** * @title ERC1155CInitializable * @author Limit Break, Inc. * @notice Initializable implementation of ERC1155C to allow for EIP-1167 proxy clones. */ abstract contract ERC1155CInitializable is ERC1155OpenZeppelinInitializable, CreatorTokenBase { function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(ICreatorToken).interfaceId || super.supportsInterface(interfaceId); } /// @dev Ties the open-zeppelin _beforeTokenTransfer hook to more granular transfer validation logic function _beforeTokenTransfer( address /*operator*/, address from, address to, uint256[] memory ids, uint256[] memory /*amounts*/, bytes memory /*data*/ ) internal virtual override { uint256 idsArrayLength = ids.length; for (uint256 i = 0; i < idsArrayLength;) { _validateBeforeTransfer(from, to, ids[i]); unchecked { ++i; } } } /// @dev Ties the open-zeppelin _afterTokenTransfer hook to more granular transfer validation logic function _afterTokenTransfer( address /*operator*/, address from, address to, uint256[] memory ids, uint256[] memory /*amounts*/, bytes memory /*data*/ ) internal virtual override { uint256 idsArrayLength = ids.length; for (uint256 i = 0; i < idsArrayLength;) { _validateAfterTransfer(from, to, ids[i]); unchecked { ++i; } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import {LibBytes} from "./LibBytes.sol"; /// @notice Library for converting numbers into strings and other string operations. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibString.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol) /// /// @dev Note: /// For performance and bytecode compactness, most of the string operations are restricted to /// byte strings (7-bit ASCII), except where otherwise specified. /// Usage of byte string operations on charsets with runes spanning two or more bytes /// can lead to undefined behavior. library LibString { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STRUCTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Goated string storage struct that totally MOGs, no cap, fr. /// Uses less gas and bytecode than Solidity's native string storage. It's meta af. /// Packs length with the first 31 bytes if <255 bytes, so it’s mad tight. struct StringStorage { bytes32 _spacer; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The length of the output is too small to contain all the hex digits. error HexLengthInsufficient(); /// @dev The length of the string is more than 32 bytes. error TooBigForSmallString(); /// @dev The input string must be a 7-bit ASCII. error StringNot7BitASCII(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The constant returned when the `search` is not found in the string. uint256 internal constant NOT_FOUND = type(uint256).max; /// @dev Lookup for '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'. uint128 internal constant ALPHANUMERIC_7_BIT_ASCII = 0x7fffffe07fffffe03ff000000000000; /// @dev Lookup for 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'. uint128 internal constant LETTERS_7_BIT_ASCII = 0x7fffffe07fffffe0000000000000000; /// @dev Lookup for 'abcdefghijklmnopqrstuvwxyz'. uint128 internal constant LOWERCASE_7_BIT_ASCII = 0x7fffffe000000000000000000000000; /// @dev Lookup for 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. uint128 internal constant UPPERCASE_7_BIT_ASCII = 0x7fffffe0000000000000000; /// @dev Lookup for '0123456789'. uint128 internal constant DIGITS_7_BIT_ASCII = 0x3ff000000000000; /// @dev Lookup for '0123456789abcdefABCDEF'. uint128 internal constant HEXDIGITS_7_BIT_ASCII = 0x7e0000007e03ff000000000000; /// @dev Lookup for '01234567'. uint128 internal constant OCTDIGITS_7_BIT_ASCII = 0xff000000000000; /// @dev Lookup for '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'. uint128 internal constant PRINTABLE_7_BIT_ASCII = 0x7fffffffffffffffffffffff00003e00; /// @dev Lookup for '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'. uint128 internal constant PUNCTUATION_7_BIT_ASCII = 0x78000001f8000001fc00fffe00000000; /// @dev Lookup for ' \t\n\r\x0b\x0c'. uint128 internal constant WHITESPACE_7_BIT_ASCII = 0x100003e00; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STRING STORAGE OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sets the value of the string storage `$` to `s`. function set(StringStorage storage $, string memory s) internal { LibBytes.set(bytesStorage($), bytes(s)); } /// @dev Sets the value of the string storage `$` to `s`. function setCalldata(StringStorage storage $, string calldata s) internal { LibBytes.setCalldata(bytesStorage($), bytes(s)); } /// @dev Sets the value of the string storage `$` to the empty string. function clear(StringStorage storage $) internal { delete $._spacer; } /// @dev Returns whether the value stored is `$` is the empty string "". function isEmpty(StringStorage storage $) internal view returns (bool) { return uint256($._spacer) & 0xff == uint256(0); } /// @dev Returns the length of the value stored in `$`. function length(StringStorage storage $) internal view returns (uint256) { return LibBytes.length(bytesStorage($)); } /// @dev Returns the value stored in `$`. function get(StringStorage storage $) internal view returns (string memory) { return string(LibBytes.get(bytesStorage($))); } /// @dev Helper to cast `$` to a `BytesStorage`. function bytesStorage(StringStorage storage $) internal pure returns (LibBytes.BytesStorage storage casted) { /// @solidity memory-safe-assembly assembly { casted.slot := $.slot } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* DECIMAL OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the base 10 decimal representation of `value`. function toString(uint256 value) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned. // We will need 1 word for the trailing zeros padding, 1 word for the length, // and 3 words for a maximum of 78 digits. result := add(mload(0x40), 0x80) mstore(0x40, add(result, 0x20)) // Allocate memory. mstore(result, 0) // Zeroize the slot after the string. let end := result // Cache the end of the memory to calculate the length later. let w := not(0) // Tsk. // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let temp := value } 1 {} { result := add(result, w) // `sub(result, 1)`. // Store the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(result, add(48, mod(temp, 10))) temp := div(temp, 10) // Keep dividing `temp` until zero. if iszero(temp) { break } } let n := sub(end, result) result := sub(result, 0x20) // Move the pointer 32 bytes back to make room for the length. mstore(result, n) // Store the length. } } /// @dev Returns the base 10 decimal representation of `value`. function toString(int256 value) internal pure returns (string memory result) { if (value >= 0) return toString(uint256(value)); unchecked { result = toString(~uint256(value) + 1); } /// @solidity memory-safe-assembly assembly { // We still have some spare memory space on the left, // as we have allocated 3 words (96 bytes) for up to 78 digits. let n := mload(result) // Load the string length. mstore(result, 0x2d) // Store the '-' character. result := sub(result, 1) // Move back the string pointer by a byte. mstore(result, add(n, 1)) // Update the string length. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* HEXADECIMAL OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the hexadecimal representation of `value`, /// left-padded to an input length of `byteCount` bytes. /// The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte, /// giving a total length of `byteCount * 2 + 2` bytes. /// Reverts if `byteCount` is too small for the output to contain all the digits. function toHexString(uint256 value, uint256 byteCount) internal pure returns (string memory result) { result = toHexStringNoPrefix(value, byteCount); /// @solidity memory-safe-assembly assembly { let n := add(mload(result), 2) // Compute the length. mstore(result, 0x3078) // Store the "0x" prefix. result := sub(result, 2) // Move the pointer. mstore(result, n) // Store the length. } } /// @dev Returns the hexadecimal representation of `value`, /// left-padded to an input length of `byteCount` bytes. /// The output is not prefixed with "0x" and is encoded using 2 hexadecimal digits per byte, /// giving a total length of `byteCount * 2` bytes. /// Reverts if `byteCount` is too small for the output to contain all the digits. function toHexStringNoPrefix(uint256 value, uint256 byteCount) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { // We need 0x20 bytes for the trailing zeros padding, `byteCount * 2` bytes // for the digits, 0x02 bytes for the prefix, and 0x20 bytes for the length. // We add 0x20 to the total and round down to a multiple of 0x20. // (0x20 + 0x20 + 0x02 + 0x20) = 0x62. result := add(mload(0x40), and(add(shl(1, byteCount), 0x42), not(0x1f))) mstore(0x40, add(result, 0x20)) // Allocate memory. mstore(result, 0) // Zeroize the slot after the string. let end := result // Cache the end to calculate the length later. // Store "0123456789abcdef" in scratch space. mstore(0x0f, 0x30313233343536373839616263646566) let start := sub(result, add(byteCount, byteCount)) let w := not(1) // Tsk. let temp := value // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for {} 1 {} { result := add(result, w) // `sub(result, 2)`. mstore8(add(result, 1), mload(and(temp, 15))) mstore8(result, mload(and(shr(4, temp), 15))) temp := shr(8, temp) if iszero(xor(result, start)) { break } } if temp { mstore(0x00, 0x2194895a) // `HexLengthInsufficient()`. revert(0x1c, 0x04) } let n := sub(end, result) result := sub(result, 0x20) mstore(result, n) // Store the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. /// As address are 20 bytes long, the output will left-padded to have /// a length of `20 * 2 + 2` bytes. function toHexString(uint256 value) internal pure returns (string memory result) { result = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let n := add(mload(result), 2) // Compute the length. mstore(result, 0x3078) // Store the "0x" prefix. result := sub(result, 2) // Move the pointer. mstore(result, n) // Store the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x". /// The output excludes leading "0" from the `toHexString` output. /// `0x00: "0x0", 0x01: "0x1", 0x12: "0x12", 0x123: "0x123"`. function toMinimalHexString(uint256 value) internal pure returns (string memory result) { result = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let o := eq(byte(0, mload(add(result, 0x20))), 0x30) // Whether leading zero is present. let n := add(mload(result), 2) // Compute the length. mstore(add(result, o), 0x3078) // Store the "0x" prefix, accounting for leading zero. result := sub(add(result, o), 2) // Move the pointer, accounting for leading zero. mstore(result, sub(n, o)) // Store the length, accounting for leading zero. } } /// @dev Returns the hexadecimal representation of `value`. /// The output excludes leading "0" from the `toHexStringNoPrefix` output. /// `0x00: "0", 0x01: "1", 0x12: "12", 0x123: "123"`. function toMinimalHexStringNoPrefix(uint256 value) internal pure returns (string memory result) { result = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let o := eq(byte(0, mload(add(result, 0x20))), 0x30) // Whether leading zero is present. let n := mload(result) // Get the length. result := add(result, o) // Move the pointer, accounting for leading zero. mstore(result, sub(n, o)) // Store the length, accounting for leading zero. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is encoded using 2 hexadecimal digits per byte. /// As address are 20 bytes long, the output will left-padded to have /// a length of `20 * 2` bytes. function toHexStringNoPrefix(uint256 value) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length, // 0x02 bytes for the prefix, and 0x40 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x40) is 0xa0. result := add(mload(0x40), 0x80) mstore(0x40, add(result, 0x20)) // Allocate memory. mstore(result, 0) // Zeroize the slot after the string. let end := result // Cache the end to calculate the length later. mstore(0x0f, 0x30313233343536373839616263646566) // Store the "0123456789abcdef" lookup. let w := not(1) // Tsk. // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let temp := value } 1 {} { result := add(result, w) // `sub(result, 2)`. mstore8(add(result, 1), mload(and(temp, 15))) mstore8(result, mload(and(shr(4, temp), 15))) temp := shr(8, temp) if iszero(temp) { break } } let n := sub(end, result) result := sub(result, 0x20) mstore(result, n) // Store the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte, /// and the alphabets are capitalized conditionally according to /// https://eips.ethereum.org/EIPS/eip-55 function toHexStringChecksummed(address value) internal pure returns (string memory result) { result = toHexString(value); /// @solidity memory-safe-assembly assembly { let mask := shl(6, div(not(0), 255)) // `0b010000000100000000 ...` let o := add(result, 0x22) let hashed := and(keccak256(o, 40), mul(34, mask)) // `0b10001000 ... ` let t := shl(240, 136) // `0b10001000 << 240` for { let i := 0 } 1 {} { mstore(add(i, i), mul(t, byte(i, hashed))) i := add(i, 1) if eq(i, 20) { break } } mstore(o, xor(mload(o), shr(1, and(mload(0x00), and(mload(o), mask))))) o := add(o, 0x20) mstore(o, xor(mload(o), shr(1, and(mload(0x20), and(mload(o), mask))))) } } /// @dev Returns the hexadecimal representation of `value`. /// The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. function toHexString(address value) internal pure returns (string memory result) { result = toHexStringNoPrefix(value); /// @solidity memory-safe-assembly assembly { let n := add(mload(result), 2) // Compute the length. mstore(result, 0x3078) // Store the "0x" prefix. result := sub(result, 2) // Move the pointer. mstore(result, n) // Store the length. } } /// @dev Returns the hexadecimal representation of `value`. /// The output is encoded using 2 hexadecimal digits per byte. function toHexStringNoPrefix(address value) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) // Allocate memory. // We need 0x20 bytes for the trailing zeros padding, 0x20 bytes for the length, // 0x02 bytes for the prefix, and 0x28 bytes for the digits. // The next multiple of 0x20 above (0x20 + 0x20 + 0x02 + 0x28) is 0x80. mstore(0x40, add(result, 0x80)) mstore(0x0f, 0x30313233343536373839616263646566) // Store the "0123456789abcdef" lookup. result := add(result, 2) mstore(result, 40) // Store the length. let o := add(result, 0x20) mstore(add(o, 40), 0) // Zeroize the slot after the string. value := shl(96, value) // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. for { let i := 0 } 1 {} { let p := add(o, add(i, i)) let temp := byte(i, value) mstore8(add(p, 1), mload(and(temp, 15))) mstore8(p, mload(shr(4, temp))) i := add(i, 1) if eq(i, 20) { break } } } } /// @dev Returns the hex encoded string from the raw bytes. /// The output is encoded using 2 hexadecimal digits per byte. function toHexString(bytes memory raw) internal pure returns (string memory result) { result = toHexStringNoPrefix(raw); /// @solidity memory-safe-assembly assembly { let n := add(mload(result), 2) // Compute the length. mstore(result, 0x3078) // Store the "0x" prefix. result := sub(result, 2) // Move the pointer. mstore(result, n) // Store the length. } } /// @dev Returns the hex encoded string from the raw bytes. /// The output is encoded using 2 hexadecimal digits per byte. function toHexStringNoPrefix(bytes memory raw) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let n := mload(raw) result := add(mload(0x40), 2) // Skip 2 bytes for the optional prefix. mstore(result, add(n, n)) // Store the length of the output. mstore(0x0f, 0x30313233343536373839616263646566) // Store the "0123456789abcdef" lookup. let o := add(result, 0x20) let end := add(raw, n) for {} iszero(eq(raw, end)) {} { raw := add(raw, 1) mstore8(add(o, 1), mload(and(mload(raw), 15))) mstore8(o, mload(and(shr(4, mload(raw)), 15))) o := add(o, 2) } mstore(o, 0) // Zeroize the slot after the string. mstore(0x40, add(o, 0x20)) // Allocate memory. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RUNE STRING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns the number of UTF characters in the string. function runeCount(string memory s) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { if mload(s) { mstore(0x00, div(not(0), 255)) mstore(0x20, 0x0202020202020202020202020202020202020202020202020303030304040506) let o := add(s, 0x20) let end := add(o, mload(s)) for { result := 1 } 1 { result := add(result, 1) } { o := add(o, byte(0, mload(shr(250, mload(o))))) if iszero(lt(o, end)) { break } } } } } /// @dev Returns if this string is a 7-bit ASCII string. /// (i.e. all characters codes are in [0..127]) function is7BitASCII(string memory s) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { result := 1 let mask := shl(7, div(not(0), 255)) let n := mload(s) if n { let o := add(s, 0x20) let end := add(o, n) let last := mload(end) mstore(end, 0) for {} 1 {} { if and(mask, mload(o)) { result := 0 break } o := add(o, 0x20) if iszero(lt(o, end)) { break } } mstore(end, last) } } } /// @dev Returns if this string is a 7-bit ASCII string, /// AND all characters are in the `allowed` lookup. /// Note: If `s` is empty, returns true regardless of `allowed`. function is7BitASCII(string memory s, uint128 allowed) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { result := 1 if mload(s) { let allowed_ := shr(128, shl(128, allowed)) let o := add(s, 0x20) for { let end := add(o, mload(s)) } 1 {} { result := and(result, shr(byte(0, mload(o)), allowed_)) o := add(o, 1) if iszero(and(result, lt(o, end))) { break } } } } } /// @dev Converts the bytes in the 7-bit ASCII string `s` to /// an allowed lookup for use in `is7BitASCII(s, allowed)`. /// To save runtime gas, you can cache the result in an immutable variable. function to7BitASCIIAllowedLookup(string memory s) internal pure returns (uint128 result) { /// @solidity memory-safe-assembly assembly { if mload(s) { let o := add(s, 0x20) for { let end := add(o, mload(s)) } 1 {} { result := or(result, shl(byte(0, mload(o)), 1)) o := add(o, 1) if iszero(lt(o, end)) { break } } if shr(128, result) { mstore(0x00, 0xc9807e0d) // `StringNot7BitASCII()`. revert(0x1c, 0x04) } } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BYTE STRING OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ // For performance and bytecode compactness, byte string operations are restricted // to 7-bit ASCII strings. All offsets are byte offsets, not UTF character offsets. // Usage of byte string operations on charsets with runes spanning two or more bytes // can lead to undefined behavior. /// @dev Returns `subject` all occurrences of `needle` replaced with `replacement`. function replace(string memory subject, string memory needle, string memory replacement) internal pure returns (string memory) { return string(LibBytes.replace(bytes(subject), bytes(needle), bytes(replacement))); } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from left to right, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function indexOf(string memory subject, string memory needle, uint256 from) internal pure returns (uint256) { return LibBytes.indexOf(bytes(subject), bytes(needle), from); } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from left to right. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function indexOf(string memory subject, string memory needle) internal pure returns (uint256) { return LibBytes.indexOf(bytes(subject), bytes(needle), 0); } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from right to left, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function lastIndexOf(string memory subject, string memory needle, uint256 from) internal pure returns (uint256) { return LibBytes.lastIndexOf(bytes(subject), bytes(needle), from); } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from right to left. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function lastIndexOf(string memory subject, string memory needle) internal pure returns (uint256) { return LibBytes.lastIndexOf(bytes(subject), bytes(needle), type(uint256).max); } /// @dev Returns true if `needle` is found in `subject`, false otherwise. function contains(string memory subject, string memory needle) internal pure returns (bool) { return LibBytes.contains(bytes(subject), bytes(needle)); } /// @dev Returns whether `subject` starts with `needle`. function startsWith(string memory subject, string memory needle) internal pure returns (bool) { return LibBytes.startsWith(bytes(subject), bytes(needle)); } /// @dev Returns whether `subject` ends with `needle`. function endsWith(string memory subject, string memory needle) internal pure returns (bool) { return LibBytes.endsWith(bytes(subject), bytes(needle)); } /// @dev Returns `subject` repeated `times`. function repeat(string memory subject, uint256 times) internal pure returns (string memory) { return string(LibBytes.repeat(bytes(subject), times)); } /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive). /// `start` and `end` are byte offsets. function slice(string memory subject, uint256 start, uint256 end) internal pure returns (string memory) { return string(LibBytes.slice(bytes(subject), start, end)); } /// @dev Returns a copy of `subject` sliced from `start` to the end of the string. /// `start` is a byte offset. function slice(string memory subject, uint256 start) internal pure returns (string memory) { return string(LibBytes.slice(bytes(subject), start, type(uint256).max)); } /// @dev Returns all the indices of `needle` in `subject`. /// The indices are byte offsets. function indicesOf(string memory subject, string memory needle) internal pure returns (uint256[] memory) { return LibBytes.indicesOf(bytes(subject), bytes(needle)); } /// @dev Returns a arrays of strings based on the `delimiter` inside of the `subject` string. function split(string memory subject, string memory delimiter) internal pure returns (string[] memory result) { bytes[] memory a = LibBytes.split(bytes(subject), bytes(delimiter)); /// @solidity memory-safe-assembly assembly { result := a } } /// @dev Returns a concatenated string of `a` and `b`. /// Cheaper than `string.concat()` and does not de-align the free memory pointer. function concat(string memory a, string memory b) internal pure returns (string memory) { return string(LibBytes.concat(bytes(a), bytes(b))); } /// @dev Returns a copy of the string in either lowercase or UPPERCASE. /// WARNING! This function is only compatible with 7-bit ASCII strings. function toCase(string memory subject, bool toUpper) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let n := mload(subject) if n { result := mload(0x40) let o := add(result, 0x20) let d := sub(subject, result) let flags := shl(add(70, shl(5, toUpper)), 0x3ffffff) for { let end := add(o, n) } 1 {} { let b := byte(0, mload(add(d, o))) mstore8(o, xor(and(shr(b, flags), 0x20), b)) o := add(o, 1) if eq(o, end) { break } } mstore(result, n) // Store the length. mstore(o, 0) // Zeroize the slot after the string. mstore(0x40, add(o, 0x20)) // Allocate memory. } } } /// @dev Returns a string from a small bytes32 string. /// `s` must be null-terminated, or behavior will be undefined. function fromSmallString(bytes32 s) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) let n := 0 for {} byte(n, s) { n := add(n, 1) } {} // Scan for '\0'. mstore(result, n) // Store the length. let o := add(result, 0x20) mstore(o, s) // Store the bytes of the string. mstore(add(o, n), 0) // Zeroize the slot after the string. mstore(0x40, add(result, 0x40)) // Allocate memory. } } /// @dev Returns the small string, with all bytes after the first null byte zeroized. function normalizeSmallString(bytes32 s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { for {} byte(result, s) { result := add(result, 1) } {} // Scan for '\0'. mstore(0x00, s) mstore(result, 0x00) result := mload(0x00) } } /// @dev Returns the string as a normalized null-terminated small string. function toSmallString(string memory s) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { result := mload(s) if iszero(lt(result, 33)) { mstore(0x00, 0xec92f9a3) // `TooBigForSmallString()`. revert(0x1c, 0x04) } result := shl(shl(3, sub(32, result)), mload(add(s, result))) } } /// @dev Returns a lowercased copy of the string. /// WARNING! This function is only compatible with 7-bit ASCII strings. function lower(string memory subject) internal pure returns (string memory result) { result = toCase(subject, false); } /// @dev Returns an UPPERCASED copy of the string. /// WARNING! This function is only compatible with 7-bit ASCII strings. function upper(string memory subject) internal pure returns (string memory result) { result = toCase(subject, true); } /// @dev Escapes the string to be used within HTML tags. function escapeHTML(string memory s) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) let end := add(s, mload(s)) let o := add(result, 0x20) // Store the bytes of the packed offsets and strides into the scratch space. // `packed = (stride << 5) | offset`. Max offset is 20. Max stride is 6. mstore(0x1f, 0x900094) mstore(0x08, 0xc0000000a6ab) // Store ""&'<>" into the scratch space. mstore(0x00, shl(64, 0x2671756f743b26616d703b262333393b266c743b2667743b)) for {} iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) // Not in `["\"","'","&","<",">"]`. if iszero(and(shl(c, 1), 0x500000c400000000)) { mstore8(o, c) o := add(o, 1) continue } let t := shr(248, mload(c)) mstore(o, mload(and(t, 0x1f))) o := add(o, shr(5, t)) } mstore(o, 0) // Zeroize the slot after the string. mstore(result, sub(o, add(result, 0x20))) // Store the length. mstore(0x40, add(o, 0x20)) // Allocate memory. } } /// @dev Escapes the string to be used within double-quotes in a JSON. /// If `addDoubleQuotes` is true, the result will be enclosed in double-quotes. function escapeJSON(string memory s, bool addDoubleQuotes) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) let o := add(result, 0x20) if addDoubleQuotes { mstore8(o, 34) o := add(1, o) } // Store "\\u0000" in scratch space. // Store "0123456789abcdef" in scratch space. // Also, store `{0x08:"b", 0x09:"t", 0x0a:"n", 0x0c:"f", 0x0d:"r"}`. // into the scratch space. mstore(0x15, 0x5c75303030303031323334353637383961626364656662746e006672) // Bitmask for detecting `["\"","\\"]`. let e := or(shl(0x22, 1), shl(0x5c, 1)) for { let end := add(s, mload(s)) } iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) if iszero(lt(c, 0x20)) { if iszero(and(shl(c, 1), e)) { // Not in `["\"","\\"]`. mstore8(o, c) o := add(o, 1) continue } mstore8(o, 0x5c) // "\\". mstore8(add(o, 1), c) o := add(o, 2) continue } if iszero(and(shl(c, 1), 0x3700)) { // Not in `["\b","\t","\n","\f","\d"]`. mstore8(0x1d, mload(shr(4, c))) // Hex value. mstore8(0x1e, mload(and(c, 15))) // Hex value. mstore(o, mload(0x19)) // "\\u00XX". o := add(o, 6) continue } mstore8(o, 0x5c) // "\\". mstore8(add(o, 1), mload(add(c, 8))) o := add(o, 2) } if addDoubleQuotes { mstore8(o, 34) o := add(1, o) } mstore(o, 0) // Zeroize the slot after the string. mstore(result, sub(o, add(result, 0x20))) // Store the length. mstore(0x40, add(o, 0x20)) // Allocate memory. } } /// @dev Escapes the string to be used within double-quotes in a JSON. function escapeJSON(string memory s) internal pure returns (string memory result) { result = escapeJSON(s, false); } /// @dev Encodes `s` so that it can be safely used in a URI, /// just like `encodeURIComponent` in JavaScript. /// See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent /// See: https://datatracker.ietf.org/doc/html/rfc2396 /// See: https://datatracker.ietf.org/doc/html/rfc3986 function encodeURIComponent(string memory s) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) // Store "0123456789ABCDEF" in scratch space. // Uppercased to be consistent with JavaScript's implementation. mstore(0x0f, 0x30313233343536373839414243444546) let o := add(result, 0x20) for { let end := add(s, mload(s)) } iszero(eq(s, end)) {} { s := add(s, 1) let c := and(mload(s), 0xff) // If not in `[0-9A-Z-a-z-_.!~*'()]`. if iszero(and(1, shr(c, 0x47fffffe87fffffe03ff678200000000))) { mstore8(o, 0x25) // '%'. mstore8(add(o, 1), mload(and(shr(4, c), 15))) mstore8(add(o, 2), mload(and(c, 15))) o := add(o, 3) continue } mstore8(o, c) o := add(o, 1) } 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 memory. } } /// @dev Returns whether `a` equals `b`. function eq(string memory a, string memory b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b))) } } /// @dev Returns whether `a` equals `b`, where `b` is a null-terminated small string. function eqs(string memory a, bytes32 b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { // These should be evaluated on compile time, as far as possible. let m := not(shl(7, div(not(iszero(b)), 255))) // `0x7f7f ...`. let x := not(or(m, or(b, add(m, and(b, m))))) let r := shl(7, iszero(iszero(shr(128, x)))) r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x)))))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // forgefmt: disable-next-item result := gt(eq(mload(a), add(iszero(x), xor(31, shr(3, r)))), xor(shr(add(8, r), b), shr(add(8, r), mload(add(a, 0x20))))) } } /// @dev Returns 0 if `a == b`, -1 if `a < b`, +1 if `a > b`. /// If `a` == b[:a.length]`, and `a.length < b.length`, returns -1. function cmp(string memory a, string memory b) internal pure returns (int256) { return LibBytes.cmp(bytes(a), bytes(b)); } /// @dev Packs a single string with its length into a single word. /// Returns `bytes32(0)` if the length is zero or greater than 31. function packOne(string memory a) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { // We don't need to zero right pad the string, // since this is our own custom non-standard packing scheme. result := mul( // Load the length and the bytes. mload(add(a, 0x1f)), // `length != 0 && length < 32`. Abuses underflow. // Assumes that the length is valid and within the block gas limit. lt(sub(mload(a), 1), 0x1f) ) } } /// @dev Unpacks a string packed using {packOne}. /// Returns the empty string if `packed` is `bytes32(0)`. /// If `packed` is not an output of {packOne}, the output behavior is undefined. function unpackOne(bytes32 packed) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) // Grab the free memory pointer. mstore(0x40, add(result, 0x40)) // Allocate 2 words (1 for the length, 1 for the bytes). mstore(result, 0) // Zeroize the length slot. mstore(add(result, 0x1f), packed) // Store the length and bytes. mstore(add(add(result, 0x20), mload(result)), 0) // Right pad with zeroes. } } /// @dev Packs two strings with their lengths into a single word. /// Returns `bytes32(0)` if combined length is zero or greater than 30. function packTwo(string memory a, string memory b) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { let aLen := mload(a) // We don't need to zero right pad the strings, // since this is our own custom non-standard packing scheme. result := mul( or( // Load the length and the bytes of `a` and `b`. shl(shl(3, sub(0x1f, aLen)), mload(add(a, aLen))), mload(sub(add(b, 0x1e), aLen))), // `totalLen != 0 && totalLen < 31`. Abuses underflow. // Assumes that the lengths are valid and within the block gas limit. lt(sub(add(aLen, mload(b)), 1), 0x1e) ) } } /// @dev Unpacks strings packed using {packTwo}. /// Returns the empty strings if `packed` is `bytes32(0)`. /// If `packed` is not an output of {packTwo}, the output behavior is undefined. function unpackTwo(bytes32 packed) internal pure returns (string memory resultA, string memory resultB) { /// @solidity memory-safe-assembly assembly { resultA := mload(0x40) // Grab the free memory pointer. resultB := add(resultA, 0x40) // Allocate 2 words for each string (1 for the length, 1 for the byte). Total 4 words. mstore(0x40, add(resultB, 0x40)) // Zeroize the length slots. mstore(resultA, 0) mstore(resultB, 0) // Store the lengths and bytes. mstore(add(resultA, 0x1f), packed) mstore(add(resultB, 0x1f), mload(add(add(resultA, 0x20), mload(resultA)))) // Right pad with zeroes. mstore(add(add(resultA, 0x20), mload(resultA)), 0) mstore(add(add(resultB, 0x20), mload(resultB)), 0) } } /// @dev Directly returns `a` without copying. function directReturn(string memory a) internal pure { assembly { // Assumes that the string does not start from the scratch space. let retStart := sub(a, 0x20) let retUnpaddedSize := add(mload(a), 0x40) // Right pad with zeroes. Just in case the string is produced // by a method that doesn't zero right pad. mstore(add(retStart, retUnpaddedSize), 0) mstore(retStart, 0x20) // Store the return offset. // End the transaction, returning the string. return(retStart, and(not(0x1f), add(0x1f, retUnpaddedSize))) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "@openzeppelin/contracts/token/common/ERC2981.sol"; /** * @title BasicRoyaltiesBase * @author Limit Break, Inc. * @dev Base functionality of an NFT mix-in contract implementing the most basic form of programmable royalties. */ abstract contract BasicRoyaltiesBase is ERC2981 { event DefaultRoyaltySet(address indexed receiver, uint96 feeNumerator); event TokenRoyaltySet(uint256 indexed tokenId, address indexed receiver, uint96 feeNumerator); function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual override { super._setDefaultRoyalty(receiver, feeNumerator); emit DefaultRoyaltySet(receiver, feeNumerator); } function _setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internal virtual override { super._setTokenRoyalty(tokenId, receiver, feeNumerator); emit TokenRoyaltySet(tokenId, receiver, feeNumerator); } } /** * @title BasicRoyalties * @author Limit Break, Inc. * @notice Constructable BasicRoyalties Contract implementation. */ abstract contract BasicRoyalties is BasicRoyaltiesBase { constructor(address receiver, uint96 feeNumerator) { _setDefaultRoyalty(receiver, feeNumerator); } } /** * @title BasicRoyaltiesInitializable * @author Limit Break, Inc. * @notice Initializable BasicRoyalties Contract implementation to allow for EIP-1167 clones. */ abstract contract BasicRoyaltiesInitializable is BasicRoyaltiesBase {}
// 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 // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// 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. x := and(x, add(not(x), 1)) // For the upper 3 bits of the result, use a De Bruijn-like lookup. // Credit to adhusson: https://blog.adhusson.com/cheap-find-first-set-evm/ // forgefmt: disable-next-item r := shl(5, shr(252, shl(shl(2, shr(250, mul(x, 0xb6db6db6ddddddddd34d34d349249249210842108c6318c639ce739cffffffff))), 0x8040405543005266443200005020610674053026020000107506200176117077))) // For the lower 5 bits of the result, use a De Bruijn lookup. // forgefmt: disable-next-item r := or(r, byte(and(div(0xd76453e0, shr(r, x)), 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) { uint256 m0 = 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f; uint256 m1 = m0 ^ (m0 << 2); uint256 m2 = m1 ^ (m1 << 1); r = reverseBytes(x); r = (m2 & (r >> 1)) | ((m2 & r) << 1); r = (m1 & (r >> 2)) | ((m1 & r) << 2); r = (m0 & (r >> 4)) | ((m0 & r) << 4); } /// @dev Returns `x` reversed at the byte level. function reverseBytes(uint256 x) internal pure returns (uint256 r) { unchecked { // Computing masks on-the-fly reduces bytecode size by about 200 bytes. uint256 m0 = 0x100000000000000000000000000000001 * (~toUint(x == uint256(0)) >> 192); uint256 m1 = m0 ^ (m0 << 32); uint256 m2 = m1 ^ (m1 << 16); uint256 m3 = m2 ^ (m2 << 8); r = (m3 & (x >> 8)) | ((m3 & x) << 8); r = (m2 & (r >> 16)) | ((m2 & r) << 16); r = (m1 & (r >> 32)) | ((m1 & r) << 32); r = (m0 & (r >> 64)) | ((m0 & r) << 64); r = (r >> 128) | (r << 128); } } /// @dev Returns the common prefix of `x` and `y` at the bit level. function commonBitPrefix(uint256 x, uint256 y) internal pure returns (uint256) { unchecked { uint256 s = 256 - clz(x ^ y); return (x >> s) << s; } } /// @dev Returns the common prefix of `x` and `y` at the nibble level. function commonNibblePrefix(uint256 x, uint256 y) internal pure returns (uint256) { unchecked { uint256 s = (64 - (clz(x ^ y) >> 2)) << 2; return (x >> s) << s; } } /// @dev Returns the common prefix of `x` and `y` at the byte level. function commonBytePrefix(uint256 x, uint256 y) internal pure returns (uint256) { unchecked { uint256 s = (32 - (clz(x ^ y) >> 3)) << 3; return (x >> s) << s; } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* 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)) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library for byte related operations. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBytes.sol) library LibBytes { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* STRUCTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Goated bytes storage struct that totally MOGs, no cap, fr. /// Uses less gas and bytecode than Solidity's native bytes storage. It's meta af. /// Packs length with the first 31 bytes if <255 bytes, so it’s mad tight. struct BytesStorage { bytes32 _spacer; } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The constant returned when the `search` is not found in the bytes. uint256 internal constant NOT_FOUND = type(uint256).max; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BYTE STORAGE OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Sets the value of the bytes storage `$` to `s`. function set(BytesStorage storage $, bytes memory s) internal { /// @solidity memory-safe-assembly assembly { let n := mload(s) let packed := or(0xff, shl(8, n)) for { let i := 0 } 1 {} { if iszero(gt(n, 0xfe)) { i := 0x1f packed := or(n, shl(8, mload(add(s, i)))) if iszero(gt(n, i)) { break } } let o := add(s, 0x20) mstore(0x00, $.slot) for { let p := keccak256(0x00, 0x20) } 1 {} { sstore(add(p, shr(5, i)), mload(add(o, i))) i := add(i, 0x20) if iszero(lt(i, n)) { break } } break } sstore($.slot, packed) } } /// @dev Sets the value of the bytes storage `$` to `s`. function setCalldata(BytesStorage storage $, bytes calldata s) internal { /// @solidity memory-safe-assembly assembly { let packed := or(0xff, shl(8, s.length)) for { let i := 0 } 1 {} { if iszero(gt(s.length, 0xfe)) { i := 0x1f packed := or(s.length, shl(8, shr(8, calldataload(s.offset)))) if iszero(gt(s.length, i)) { break } } mstore(0x00, $.slot) for { let p := keccak256(0x00, 0x20) } 1 {} { sstore(add(p, shr(5, i)), calldataload(add(s.offset, i))) i := add(i, 0x20) if iszero(lt(i, s.length)) { break } } break } sstore($.slot, packed) } } /// @dev Sets the value of the bytes storage `$` to the empty bytes. function clear(BytesStorage storage $) internal { delete $._spacer; } /// @dev Returns whether the value stored is `$` is the empty bytes "". function isEmpty(BytesStorage storage $) internal view returns (bool) { return uint256($._spacer) & 0xff == uint256(0); } /// @dev Returns the length of the value stored in `$`. function length(BytesStorage storage $) internal view returns (uint256 result) { result = uint256($._spacer); /// @solidity memory-safe-assembly assembly { let n := and(0xff, result) result := or(mul(shr(8, result), eq(0xff, n)), mul(n, iszero(eq(0xff, n)))) } } /// @dev Returns the value stored in `$`. function get(BytesStorage storage $) internal view returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) let o := add(result, 0x20) let packed := sload($.slot) let n := shr(8, packed) for { let i := 0 } 1 {} { if iszero(eq(or(packed, 0xff), packed)) { mstore(o, packed) n := and(0xff, packed) i := 0x1f if iszero(gt(n, i)) { break } } mstore(0x00, $.slot) for { let p := keccak256(0x00, 0x20) } 1 {} { mstore(add(o, i), sload(add(p, shr(5, i)))) i := add(i, 0x20) if iszero(lt(i, n)) { break } } break } mstore(result, n) // Store the length of the memory. mstore(add(o, n), 0) // Zeroize the slot after the bytes. mstore(0x40, add(add(o, n), 0x20)) // Allocate memory. } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* BYTES OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns `subject` all occurrences of `needle` replaced with `replacement`. function replace(bytes memory subject, bytes memory needle, bytes memory replacement) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) let needleLen := mload(needle) let replacementLen := mload(replacement) let d := sub(result, subject) // Memory difference. let i := add(subject, 0x20) // Subject bytes pointer. mstore(0x00, add(i, mload(subject))) // End of subject. if iszero(gt(needleLen, mload(subject))) { let subjectSearchEnd := add(sub(mload(0x00), needleLen), 1) let h := 0 // The hash of `needle`. if iszero(lt(needleLen, 0x20)) { h := keccak256(add(needle, 0x20), needleLen) } let s := mload(add(needle, 0x20)) for { let m := shl(3, sub(0x20, and(needleLen, 0x1f))) } 1 {} { let t := mload(i) // Whether the first `needleLen % 32` bytes of `subject` and `needle` matches. if iszero(shr(m, xor(t, s))) { if h { if iszero(eq(keccak256(i, needleLen), h)) { mstore(add(i, d), t) i := add(i, 1) if iszero(lt(i, subjectSearchEnd)) { break } continue } } // Copy the `replacement` one word at a time. for { let j := 0 } 1 {} { mstore(add(add(i, d), j), mload(add(add(replacement, 0x20), j))) j := add(j, 0x20) if iszero(lt(j, replacementLen)) { break } } d := sub(add(d, replacementLen), needleLen) if needleLen { i := add(i, needleLen) if iszero(lt(i, subjectSearchEnd)) { break } continue } } mstore(add(i, d), t) i := add(i, 1) if iszero(lt(i, subjectSearchEnd)) { break } } } let end := mload(0x00) let n := add(sub(d, add(result, 0x20)), end) // Copy the rest of the bytes one word at a time. for {} lt(i, end) { i := add(i, 0x20) } { mstore(add(i, d), mload(i)) } let o := add(i, d) mstore(o, 0) // Zeroize the slot after the bytes. mstore(0x40, add(o, 0x20)) // Allocate memory. mstore(result, n) // Store the length. } } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from left to right, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function indexOf(bytes memory subject, bytes memory needle, uint256 from) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { result := not(0) // Initialize to `NOT_FOUND`. for { let subjectLen := mload(subject) } 1 {} { if iszero(mload(needle)) { result := from if iszero(gt(from, subjectLen)) { break } result := subjectLen break } let needleLen := mload(needle) let subjectStart := add(subject, 0x20) subject := add(subjectStart, from) let end := add(sub(add(subjectStart, subjectLen), needleLen), 1) let m := shl(3, sub(0x20, and(needleLen, 0x1f))) let s := mload(add(needle, 0x20)) if iszero(and(lt(subject, end), lt(from, subjectLen))) { break } if iszero(lt(needleLen, 0x20)) { for { let h := keccak256(add(needle, 0x20), needleLen) } 1 {} { if iszero(shr(m, xor(mload(subject), s))) { if eq(keccak256(subject, needleLen), h) { result := sub(subject, subjectStart) break } } subject := add(subject, 1) if iszero(lt(subject, end)) { break } } break } for {} 1 {} { if iszero(shr(m, xor(mload(subject), s))) { result := sub(subject, subjectStart) break } subject := add(subject, 1) if iszero(lt(subject, end)) { break } } break } } } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from left to right. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function indexOf(bytes memory subject, bytes memory needle) internal pure returns (uint256) { return indexOf(subject, needle, 0); } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from right to left, starting from `from`. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function lastIndexOf(bytes memory subject, bytes memory needle, uint256 from) internal pure returns (uint256 result) { /// @solidity memory-safe-assembly assembly { for {} 1 {} { result := not(0) // Initialize to `NOT_FOUND`. let needleLen := mload(needle) if gt(needleLen, mload(subject)) { break } let w := result let fromMax := sub(mload(subject), needleLen) if iszero(gt(fromMax, from)) { from := fromMax } let end := add(add(subject, 0x20), w) subject := add(add(subject, 0x20), from) if iszero(gt(subject, end)) { break } // As this function is not too often used, // we shall simply use keccak256 for smaller bytecode size. for { let h := keccak256(add(needle, 0x20), needleLen) } 1 {} { if eq(keccak256(subject, needleLen), h) { result := sub(subject, add(end, 1)) break } subject := add(subject, w) // `sub(subject, 1)`. if iszero(gt(subject, end)) { break } } break } } } /// @dev Returns the byte index of the first location of `needle` in `subject`, /// needleing from right to left. /// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. function lastIndexOf(bytes memory subject, bytes memory needle) internal pure returns (uint256) { return lastIndexOf(subject, needle, type(uint256).max); } /// @dev Returns true if `needle` is found in `subject`, false otherwise. function contains(bytes memory subject, bytes memory needle) internal pure returns (bool) { return indexOf(subject, needle) != NOT_FOUND; } /// @dev Returns whether `subject` starts with `needle`. function startsWith(bytes memory subject, bytes memory needle) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let n := mload(needle) // Just using keccak256 directly is actually cheaper. let t := eq(keccak256(add(subject, 0x20), n), keccak256(add(needle, 0x20), n)) result := lt(gt(n, mload(subject)), t) } } /// @dev Returns whether `subject` ends with `needle`. function endsWith(bytes memory subject, bytes memory needle) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { let n := mload(needle) let notInRange := gt(n, mload(subject)) // `subject + 0x20 + max(subject.length - needle.length, 0)`. let t := add(add(subject, 0x20), mul(iszero(notInRange), sub(mload(subject), n))) // Just using keccak256 directly is actually cheaper. result := gt(eq(keccak256(t, n), keccak256(add(needle, 0x20), n)), notInRange) } } /// @dev Returns `subject` repeated `times`. function repeat(bytes memory subject, uint256 times) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { let l := mload(subject) // Subject length. if iszero(or(iszero(times), iszero(l))) { result := mload(0x40) subject := add(subject, 0x20) let o := add(result, 0x20) for {} 1 {} { // Copy the `subject` one word at a time. for { let j := 0 } 1 {} { mstore(add(o, j), mload(add(subject, j))) j := add(j, 0x20) if iszero(lt(j, l)) { break } } o := add(o, l) times := sub(times, 1) if iszero(times) { break } } mstore(o, 0) // Zeroize the slot after the bytes. mstore(0x40, add(o, 0x20)) // Allocate memory. mstore(result, sub(o, add(result, 0x20))) // Store the length. } } } /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive). /// `start` and `end` are byte offsets. function slice(bytes memory subject, uint256 start, uint256 end) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { let l := mload(subject) // Subject length. if iszero(gt(l, end)) { end := l } if iszero(gt(l, start)) { start := l } if lt(start, end) { result := mload(0x40) let n := sub(end, start) let i := add(subject, start) let w := not(0x1f) // Copy the `subject` one word at a time, backwards. for { let j := and(add(n, 0x1f), w) } 1 {} { mstore(add(result, j), mload(add(i, j))) j := add(j, w) // `sub(j, 0x20)`. if iszero(j) { break } } let o := add(add(result, 0x20), n) mstore(o, 0) // Zeroize the slot after the bytes. mstore(0x40, add(o, 0x20)) // Allocate memory. mstore(result, n) // Store the length. } } } /// @dev Returns a copy of `subject` sliced from `start` to the end of the bytes. /// `start` is a byte offset. function slice(bytes memory subject, uint256 start) internal pure returns (bytes memory result) { result = slice(subject, start, type(uint256).max); } /// @dev Returns a copy of `subject` sliced from `start` to `end` (exclusive). /// `start` and `end` are byte offsets. Faster than Solidity's native slicing. function sliceCalldata(bytes calldata subject, uint256 start, uint256 end) internal pure returns (bytes calldata result) { /// @solidity memory-safe-assembly assembly { end := xor(end, mul(xor(end, subject.length), lt(subject.length, end))) start := xor(start, mul(xor(start, subject.length), lt(subject.length, start))) result.offset := add(subject.offset, start) result.length := mul(lt(start, end), sub(end, start)) } } /// @dev Returns a copy of `subject` sliced from `start` to the end of the bytes. /// `start` is a byte offset. Faster than Solidity's native slicing. function sliceCalldata(bytes calldata subject, uint256 start) internal pure returns (bytes calldata result) { /// @solidity memory-safe-assembly assembly { start := xor(start, mul(xor(start, subject.length), lt(subject.length, start))) result.offset := add(subject.offset, start) result.length := mul(lt(start, subject.length), sub(subject.length, start)) } } /// @dev Reduces the size of `subject` to `n`. /// If `n` is greater than the size of `subject`, this will be a no-op. function truncate(bytes memory subject, uint256 n) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { result := subject mstore(mul(lt(n, mload(result)), result), n) } } /// @dev Returns a copy of `subject`, with the length reduced to `n`. /// If `n` is greater than the size of `subject`, this will be a no-op. function truncatedCalldata(bytes calldata subject, uint256 n) internal pure returns (bytes calldata result) { /// @solidity memory-safe-assembly assembly { result.offset := subject.offset result.length := xor(n, mul(xor(n, subject.length), lt(subject.length, n))) } } /// @dev Returns all the indices of `needle` in `subject`. /// The indices are byte offsets. function indicesOf(bytes memory subject, bytes memory needle) internal pure returns (uint256[] memory result) { /// @solidity memory-safe-assembly assembly { let searchLen := mload(needle) if iszero(gt(searchLen, mload(subject))) { result := mload(0x40) let i := add(subject, 0x20) let o := add(result, 0x20) let subjectSearchEnd := add(sub(add(i, mload(subject)), searchLen), 1) let h := 0 // The hash of `needle`. if iszero(lt(searchLen, 0x20)) { h := keccak256(add(needle, 0x20), searchLen) } let s := mload(add(needle, 0x20)) for { let m := shl(3, sub(0x20, and(searchLen, 0x1f))) } 1 {} { let t := mload(i) // Whether the first `searchLen % 32` bytes of `subject` and `needle` matches. if iszero(shr(m, xor(t, s))) { if h { if iszero(eq(keccak256(i, searchLen), h)) { i := add(i, 1) if iszero(lt(i, subjectSearchEnd)) { break } continue } } mstore(o, sub(i, add(subject, 0x20))) // Append to `result`. o := add(o, 0x20) i := add(i, searchLen) // Advance `i` by `searchLen`. if searchLen { if iszero(lt(i, subjectSearchEnd)) { break } continue } } i := add(i, 1) if iszero(lt(i, subjectSearchEnd)) { break } } mstore(result, shr(5, sub(o, add(result, 0x20)))) // Store the length of `result`. // Allocate memory for result. // We allocate one more word, so this array can be recycled for {split}. mstore(0x40, add(o, 0x20)) } } } /// @dev Returns a arrays of bytess based on the `delimiter` inside of the `subject` bytes. function split(bytes memory subject, bytes memory delimiter) internal pure returns (bytes[] memory result) { uint256[] memory indices = indicesOf(subject, delimiter); /// @solidity memory-safe-assembly assembly { let w := not(0x1f) let indexPtr := add(indices, 0x20) let indicesEnd := add(indexPtr, shl(5, add(mload(indices), 1))) mstore(add(indicesEnd, w), mload(subject)) mstore(indices, add(mload(indices), 1)) for { let prevIndex := 0 } 1 {} { let index := mload(indexPtr) mstore(indexPtr, 0x60) if iszero(eq(index, prevIndex)) { let element := mload(0x40) let l := sub(index, prevIndex) mstore(element, l) // Store the length of the element. // Copy the `subject` one word at a time, backwards. for { let o := and(add(l, 0x1f), w) } 1 {} { mstore(add(element, o), mload(add(add(subject, prevIndex), o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } mstore(add(add(element, 0x20), l), 0) // Zeroize the slot after the bytes. // Allocate memory for the length and the bytes, rounded up to a multiple of 32. mstore(0x40, add(element, and(add(l, 0x3f), w))) mstore(indexPtr, element) // Store the `element` into the array. } prevIndex := add(index, mload(delimiter)) indexPtr := add(indexPtr, 0x20) if iszero(lt(indexPtr, indicesEnd)) { break } } result := indices if iszero(mload(delimiter)) { result := add(indices, 0x20) mstore(result, sub(mload(indices), 2)) } } } /// @dev Returns a concatenated bytes of `a` and `b`. /// Cheaper than `bytes.concat()` and does not de-align the free memory pointer. function concat(bytes memory a, bytes memory b) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { result := mload(0x40) let w := not(0x1f) let aLen := mload(a) // Copy `a` one word at a time, backwards. for { let o := and(add(aLen, 0x20), w) } 1 {} { mstore(add(result, o), mload(add(a, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } let bLen := mload(b) let output := add(result, aLen) // Copy `b` one word at a time, backwards. for { let o := and(add(bLen, 0x20), w) } 1 {} { mstore(add(output, o), mload(add(b, o))) o := add(o, w) // `sub(o, 0x20)`. if iszero(o) { break } } let totalLen := add(aLen, bLen) let last := add(add(result, 0x20), totalLen) mstore(last, 0) // Zeroize the slot after the bytes. mstore(result, totalLen) // Store the length. mstore(0x40, add(last, 0x20)) // Allocate memory. } } /// @dev Returns whether `a` equals `b`. function eq(bytes memory a, bytes memory b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { result := eq(keccak256(add(a, 0x20), mload(a)), keccak256(add(b, 0x20), mload(b))) } } /// @dev Returns whether `a` equals `b`, where `b` is a null-terminated small bytes. function eqs(bytes memory a, bytes32 b) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { // These should be evaluated on compile time, as far as possible. let m := not(shl(7, div(not(iszero(b)), 255))) // `0x7f7f ...`. let x := not(or(m, or(b, add(m, and(b, m))))) let r := shl(7, iszero(iszero(shr(128, x)))) r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x)))))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // forgefmt: disable-next-item result := gt(eq(mload(a), add(iszero(x), xor(31, shr(3, r)))), xor(shr(add(8, r), b), shr(add(8, r), mload(add(a, 0x20))))) } } /// @dev Returns 0 if `a == b`, -1 if `a < b`, +1 if `a > b`. /// If `a` == b[:a.length]`, and `a.length < b.length`, returns -1. function cmp(bytes memory a, bytes memory b) internal pure returns (int256 result) { /// @solidity memory-safe-assembly assembly { let aLen := mload(a) let bLen := mload(b) let n := and(xor(aLen, mul(xor(aLen, bLen), lt(bLen, aLen))), not(0x1f)) if n { for { let i := 0x20 } 1 {} { let x := mload(add(a, i)) let y := mload(add(b, i)) if iszero(or(xor(x, y), eq(i, n))) { i := add(i, 0x20) continue } result := sub(gt(x, y), lt(x, y)) break } } // forgefmt: disable-next-item if iszero(result) { let l := 0x201f1e1d1c1b1a191817161514131211100f0e0d0c0b0a090807060504030201 let x := and(mload(add(add(a, 0x20), n)), shl(shl(3, byte(sub(aLen, n), l)), not(0))) let y := and(mload(add(add(b, 0x20), n)), shl(shl(3, byte(sub(bLen, n), l)), not(0))) result := sub(gt(x, y), lt(x, y)) if iszero(result) { result := sub(gt(aLen, bLen), lt(aLen, bLen)) } } } } /// @dev Directly returns `a` without copying. function directReturn(bytes memory a) internal pure { assembly { // Assumes that the bytes does not start from the scratch space. let retStart := sub(a, 0x20) let retUnpaddedSize := add(mload(a), 0x40) // Right pad with zeroes. Just in case the bytes is produced // by a method that doesn't zero right pad. mstore(add(retStart, retUnpaddedSize), 0) mstore(retStart, 0x20) // Store the return offset. // End the transaction, returning the bytes. return(retStart, and(not(0x1f), add(0x1f, retUnpaddedSize))) } } /// @dev Directly returns `a` with minimal copying. function directReturn(bytes[] memory a) internal pure { assembly { let n := mload(a) // `a.length`. let o := add(a, 0x20) // Start of elements in `a`. let u := a // Highest memory slot. let w := not(0x1f) for { let i := 0 } iszero(eq(i, n)) { i := add(i, 1) } { let c := add(o, shl(5, i)) // Location of pointer to `a[i]`. let s := mload(c) // `a[i]`. let l := mload(s) // `a[i].length`. let r := and(l, 0x1f) // `a[i].length % 32`. let z := add(0x20, and(l, w)) // Offset of last word in `a[i]` from `s`. // If `s` comes before `o`, or `s` is not zero right padded. if iszero(lt(lt(s, o), or(iszero(r), iszero(shl(shl(3, r), mload(add(s, z))))))) { let m := mload(0x40) mstore(m, l) // Copy `a[i].length`. for {} 1 {} { mstore(add(m, z), mload(add(s, z))) // Copy `a[i]`, backwards. z := add(z, w) // `sub(z, 0x20)`. if iszero(z) { break } } let e := add(add(m, 0x20), l) mstore(e, 0) // Zeroize the slot after the copied bytes. mstore(0x40, add(e, 0x20)) // Allocate memory. s := m } mstore(c, sub(s, o)) // Convert to calldata offset. let t := add(l, add(s, 0x20)) if iszero(lt(t, u)) { u := t } } let retStart := add(a, w) // Assumes `a` doesn't start from scratch space. mstore(retStart, 0x20) // Store the return offset. return(retStart, add(0x40, sub(u, retStart))) // End the transaction. } } /// @dev Returns the word at `offset`, without any bounds checks. /// To load an address, you can use `address(bytes20(load(a, offset)))`. function load(bytes memory a, uint256 offset) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { result := mload(add(add(a, 0x20), offset)) } } /// @dev Returns the word at `offset`, without any bounds checks. /// To load an address, you can use `address(bytes20(loadCalldata(a, offset)))`. function loadCalldata(bytes calldata a, uint256 offset) internal pure returns (bytes32 result) { /// @solidity memory-safe-assembly assembly { result := calldataload(add(a.offset, offset)) } } /// @dev Returns empty calldata bytes. For silencing the compiler. function emptyCalldata() internal pure returns (bytes calldata result) { /// @solidity memory-safe-assembly assembly { result.length := 0 } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "../access/OwnablePermissions.sol"; import "../interfaces/ICreatorToken.sol"; import "../interfaces/ICreatorTokenTransferValidator.sol"; import "../utils/TransferValidation.sol"; import "@openzeppelin/contracts/interfaces/IERC165.sol"; /** * @title CreatorTokenBase * @author Limit Break, Inc. * @notice CreatorTokenBase is an abstract contract that provides basic functionality for managing token * transfer policies through an implementation of ICreatorTokenTransferValidator. This contract is intended to be used * as a base for creator-specific token contracts, enabling customizable transfer restrictions and security policies. * * <h4>Features:</h4> * <ul>Ownable: This contract can have an owner who can set and update the transfer validator.</ul> * <ul>TransferValidation: Implements the basic token transfer validation interface.</ul> * <ul>ICreatorToken: Implements the interface for creator tokens, providing view functions for token security policies.</ul> * * <h4>Benefits:</h4> * <ul>Provides a flexible and modular way to implement custom token transfer restrictions and security policies.</ul> * <ul>Allows creators to enforce policies such as whitelisted operators and permitted contract receivers.</ul> * <ul>Can be easily integrated into other token contracts as a base contract.</ul> * * <h4>Intended Usage:</h4> * <ul>Use as a base contract for creator token implementations that require advanced transfer restrictions and * security policies.</ul> * <ul>Set and update the ICreatorTokenTransferValidator implementation contract to enforce desired policies for the * creator token.</ul> */ abstract contract CreatorTokenBase is OwnablePermissions, TransferValidation, ICreatorToken { error CreatorTokenBase__InvalidTransferValidatorContract(); error CreatorTokenBase__SetTransferValidatorFirst(); address public constant DEFAULT_TRANSFER_VALIDATOR = address(0x0000721C310194CcfC01E523fc93C9cCcFa2A0Ac); TransferSecurityLevels public constant DEFAULT_TRANSFER_SECURITY_LEVEL = TransferSecurityLevels.One; uint120 public constant DEFAULT_OPERATOR_WHITELIST_ID = uint120(1); ICreatorTokenTransferValidator private transferValidator; /** * @notice Allows the contract owner to set the transfer validator to the official validator contract * and set the security policy to the recommended default settings. * @dev May be overridden to change the default behavior of an individual collection. */ function setToDefaultSecurityPolicy() public virtual { _requireCallerIsContractOwner(); setTransferValidator(DEFAULT_TRANSFER_VALIDATOR); ICreatorTokenTransferValidator(DEFAULT_TRANSFER_VALIDATOR).setTransferSecurityLevelOfCollection(address(this), DEFAULT_TRANSFER_SECURITY_LEVEL); ICreatorTokenTransferValidator(DEFAULT_TRANSFER_VALIDATOR).setOperatorWhitelistOfCollection(address(this), DEFAULT_OPERATOR_WHITELIST_ID); } /** * @notice Allows the contract owner to set the transfer validator to a custom validator contract * and set the security policy to their own custom settings. */ function setToCustomValidatorAndSecurityPolicy( address validator, TransferSecurityLevels level, uint120 operatorWhitelistId, uint120 permittedContractReceiversAllowlistId) public { _requireCallerIsContractOwner(); setTransferValidator(validator); ICreatorTokenTransferValidator(validator). setTransferSecurityLevelOfCollection(address(this), level); ICreatorTokenTransferValidator(validator). setOperatorWhitelistOfCollection(address(this), operatorWhitelistId); ICreatorTokenTransferValidator(validator). setPermittedContractReceiverAllowlistOfCollection(address(this), permittedContractReceiversAllowlistId); } /** * @notice Allows the contract owner to set the security policy to their own custom settings. * @dev Reverts if the transfer validator has not been set. */ function setToCustomSecurityPolicy( TransferSecurityLevels level, uint120 operatorWhitelistId, uint120 permittedContractReceiversAllowlistId) public { _requireCallerIsContractOwner(); ICreatorTokenTransferValidator validator = getTransferValidator(); if (address(validator) == address(0)) { revert CreatorTokenBase__SetTransferValidatorFirst(); } validator.setTransferSecurityLevelOfCollection(address(this), level); validator.setOperatorWhitelistOfCollection(address(this), operatorWhitelistId); validator.setPermittedContractReceiverAllowlistOfCollection(address(this), permittedContractReceiversAllowlistId); } /** * @notice Sets the transfer validator for the token contract. * * @dev Throws when provided validator contract is not the zero address and doesn't support * the ICreatorTokenTransferValidator interface. * @dev Throws when the caller is not the contract owner. * * @dev <h4>Postconditions:</h4> * 1. The transferValidator address is updated. * 2. The `TransferValidatorUpdated` event is emitted. * * @param transferValidator_ The address of the transfer validator contract. */ function setTransferValidator(address transferValidator_) public { _requireCallerIsContractOwner(); bool isValidTransferValidator = false; if(transferValidator_.code.length > 0) { try IERC165(transferValidator_).supportsInterface(type(ICreatorTokenTransferValidator).interfaceId) returns (bool supportsInterface) { isValidTransferValidator = supportsInterface; } catch {} } if(transferValidator_ != address(0) && !isValidTransferValidator) { revert CreatorTokenBase__InvalidTransferValidatorContract(); } emit TransferValidatorUpdated(address(transferValidator), transferValidator_); transferValidator = ICreatorTokenTransferValidator(transferValidator_); } /** * @notice Returns the transfer validator contract address for this token contract. */ function getTransferValidator() public view override returns (ICreatorTokenTransferValidator) { return transferValidator; } /** * @notice Returns the security policy for this token contract, which includes: * Transfer security level, operator whitelist id, permitted contract receiver allowlist id. */ function getSecurityPolicy() public view override returns (CollectionSecurityPolicy memory) { if (address(transferValidator) != address(0)) { return transferValidator.getCollectionSecurityPolicy(address(this)); } return CollectionSecurityPolicy({ transferSecurityLevel: TransferSecurityLevels.Zero, operatorWhitelistId: 0, permittedContractReceiversId: 0 }); } /** * @notice Returns the list of all whitelisted operators for this token contract. * @dev This can be an expensive call and should only be used in view-only functions. */ function getWhitelistedOperators() public view override returns (address[] memory) { if (address(transferValidator) != address(0)) { return transferValidator.getWhitelistedOperators( transferValidator.getCollectionSecurityPolicy(address(this)).operatorWhitelistId); } return new address[](0); } /** * @notice Returns the list of permitted contract receivers for this token contract. * @dev This can be an expensive call and should only be used in view-only functions. */ function getPermittedContractReceivers() public view override returns (address[] memory) { if (address(transferValidator) != address(0)) { return transferValidator.getPermittedContractReceivers( transferValidator.getCollectionSecurityPolicy(address(this)).permittedContractReceiversId); } return new address[](0); } /** * @notice Checks if an operator is whitelisted for this token contract. * @param operator The address of the operator to check. */ function isOperatorWhitelisted(address operator) public view override returns (bool) { if (address(transferValidator) != address(0)) { return transferValidator.isOperatorWhitelisted( transferValidator.getCollectionSecurityPolicy(address(this)).operatorWhitelistId, operator); } return false; } /** * @notice Checks if a contract receiver is permitted for this token contract. * @param receiver The address of the receiver to check. */ function isContractReceiverPermitted(address receiver) public view override returns (bool) { if (address(transferValidator) != address(0)) { return transferValidator.isContractReceiverPermitted( transferValidator.getCollectionSecurityPolicy(address(this)).permittedContractReceiversId, receiver); } return false; } /** * @notice Determines if a transfer is allowed based on the token contract's security policy. Use this function * to simulate whether or not a transfer made by the specified `caller` from the `from` address to the `to` * address would be allowed by this token's security policy. * * @notice This function only checks the security policy restrictions and does not check whether token ownership * or approvals are in place. * * @param caller The address of the simulated caller. * @param from The address of the sender. * @param to The address of the receiver. * @return True if the transfer is allowed, false otherwise. */ function isTransferAllowed(address caller, address from, address to) public view override returns (bool) { if (address(transferValidator) != address(0)) { try transferValidator.applyCollectionTransferPolicy(caller, from, to) { return true; } catch { return false; } } return true; } /** * @dev Pre-validates a token transfer, reverting if the transfer is not allowed by this token's security policy. * Inheriting contracts are responsible for overriding the _beforeTokenTransfer function, or its equivalent * and calling _validateBeforeTransfer so that checks can be properly applied during token transfers. * * @dev Throws when the transfer doesn't comply with the collection's transfer policy, if the transferValidator is * set to a non-zero address. * * @param caller The address of the caller. * @param from The address of the sender. * @param to The address of the receiver. */ function _preValidateTransfer( address caller, address from, address to, uint256 /*tokenId*/, uint256 /*value*/) internal virtual override { if (address(transferValidator) != address(0)) { transferValidator.applyCollectionTransferPolicy(caller, from, to); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "../../access/OwnablePermissions.sol"; import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; abstract contract ERC1155OpenZeppelinBase is ERC1155 { } abstract contract ERC1155OpenZeppelin is ERC1155OpenZeppelinBase { constructor(string memory uri_) ERC1155(uri_) {} } abstract contract ERC1155OpenZeppelinInitializable is OwnablePermissions, ERC1155OpenZeppelinBase { error ERC1155OpenZeppelinInitializable__AlreadyInitializedERC1155(); bool private _erc1155Initialized; function initializeERC1155(string memory uri_) public { _requireCallerIsContractOwner(); if(_erc1155Initialized) { revert ERC1155OpenZeppelinInitializable__AlreadyInitializedERC1155(); } _erc1155Initialized = true; _setURI(uri_); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol) pragma solidity ^0.8.0; import "../../interfaces/IERC2981.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information. * * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first. * * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the * fee is specified in basis points by default. * * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported. * * _Available since v4.5._ */ abstract contract ERC2981 is IERC2981, ERC165 { struct RoyaltyInfo { address receiver; uint96 royaltyFraction; } RoyaltyInfo private _defaultRoyaltyInfo; mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) { return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId); } /** * @inheritdoc IERC2981 */ function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) { RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId]; if (royalty.receiver == address(0)) { royalty = _defaultRoyaltyInfo; } uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator(); return (royalty.receiver, royaltyAmount); } /** * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an * override. */ function _feeDenominator() internal pure virtual returns (uint96) { return 10000; } /** * @dev Sets the royalty information that all ids in this contract will default to. * * Requirements: * * - `receiver` cannot be the zero address. * - `feeNumerator` cannot be greater than the fee denominator. */ function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual { require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice"); require(receiver != address(0), "ERC2981: invalid receiver"); _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator); } /** * @dev Removes default royalty information. */ function _deleteDefaultRoyalty() internal virtual { delete _defaultRoyaltyInfo; } /** * @dev Sets the royalty information for a specific token id, overriding the global default. * * Requirements: * * - `receiver` cannot be the zero address. * - `feeNumerator` cannot be greater than the fee denominator. */ function _setTokenRoyalty( uint256 tokenId, address receiver, uint96 feeNumerator ) internal virtual { require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice"); require(receiver != address(0), "ERC2981: Invalid parameters"); _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator); } /** * @dev Resets royalty information for the token id back to the global default. */ function _resetTokenRoyalty(uint256 tokenId) internal virtual { delete _tokenRoyaltyInfo[tokenId]; } }
// 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; import "@openzeppelin/contracts/utils/Context.sol"; abstract contract OwnablePermissions is Context { function _requireCallerIsContractOwner() internal view virtual; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "@openzeppelin/contracts/utils/Context.sol"; /** * @title TransferValidation * @author Limit Break, Inc. * @notice A mix-in that can be combined with ERC-721 contracts to provide more granular hooks. * Openzeppelin's ERC721 contract only provides hooks for before and after transfer. This allows * developers to validate or customize transfers within the context of a mint, a burn, or a transfer. */ abstract contract TransferValidation is Context { error ShouldNotMintToBurnAddress(); /// @dev Inheriting contracts should call this function in the _beforeTokenTransfer function to get more granular hooks. function _validateBeforeTransfer(address from, address to, uint256 tokenId) internal virtual { bool fromZeroAddress = from == address(0); bool toZeroAddress = to == address(0); if(fromZeroAddress && toZeroAddress) { revert ShouldNotMintToBurnAddress(); } else if(fromZeroAddress) { _preValidateMint(_msgSender(), to, tokenId, msg.value); } else if(toZeroAddress) { _preValidateBurn(_msgSender(), from, tokenId, msg.value); } else { _preValidateTransfer(_msgSender(), from, to, tokenId, msg.value); } } /// @dev Inheriting contracts should call this function in the _afterTokenTransfer function to get more granular hooks. function _validateAfterTransfer(address from, address to, uint256 tokenId) internal virtual { bool fromZeroAddress = from == address(0); bool toZeroAddress = to == address(0); if(fromZeroAddress && toZeroAddress) { revert ShouldNotMintToBurnAddress(); } else if(fromZeroAddress) { _postValidateMint(_msgSender(), to, tokenId, msg.value); } else if(toZeroAddress) { _postValidateBurn(_msgSender(), from, tokenId, msg.value); } else { _postValidateTransfer(_msgSender(), from, to, tokenId, msg.value); } } /// @dev Optional validation hook that fires before a mint function _preValidateMint(address caller, address to, uint256 tokenId, uint256 value) internal virtual {} /// @dev Optional validation hook that fires after a mint function _postValidateMint(address caller, address to, uint256 tokenId, uint256 value) internal virtual {} /// @dev Optional validation hook that fires before a burn function _preValidateBurn(address caller, address from, uint256 tokenId, uint256 value) internal virtual {} /// @dev Optional validation hook that fires after a burn function _postValidateBurn(address caller, address from, uint256 tokenId, uint256 value) internal virtual {} /// @dev Optional validation hook that fires before a transfer function _preValidateTransfer(address caller, address from, address to, uint256 tokenId, uint256 value) internal virtual {} /// @dev Optional validation hook that fires after a transfer function _postValidateTransfer(address caller, address from, address to, uint256 tokenId, uint256 value) internal virtual {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "../interfaces/ICreatorTokenTransferValidator.sol"; interface ICreatorToken { event TransferValidatorUpdated(address oldValidator, address newValidator); function getTransferValidator() external view returns (ICreatorTokenTransferValidator); function getSecurityPolicy() external view returns (CollectionSecurityPolicy memory); function getWhitelistedOperators() external view returns (address[] memory); function getPermittedContractReceivers() external view returns (address[] memory); function isOperatorWhitelisted(address operator) external view returns (bool); function isContractReceiverPermitted(address receiver) external view returns (bool); function isTransferAllowed(address caller, address from, address to) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "./IEOARegistry.sol"; import "./ITransferSecurityRegistry.sol"; import "./ITransferValidator.sol"; interface ICreatorTokenTransferValidator is ITransferSecurityRegistry, ITransferValidator, IEOARegistry {}
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC1155/ERC1155.sol) pragma solidity ^0.8.0; import "./IERC1155.sol"; import "./IERC1155Receiver.sol"; import "./extensions/IERC1155MetadataURI.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of the basic standard multi-token. * See https://eips.ethereum.org/EIPS/eip-1155 * Originally based on code by Enjin: https://github.com/enjin/erc-1155 * * _Available since v3.1._ */ contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { using Address for address; // Mapping from token ID to account balances mapping(uint256 => mapping(address => uint256)) private _balances; // Mapping from account to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json string private _uri; /** * @dev See {_setURI}. */ constructor(string memory uri_) { _setURI(uri_); } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155).interfaceId || interfaceId == type(IERC1155MetadataURI).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC1155MetadataURI-uri}. * * This implementation returns the same URI for *all* token types. It relies * on the token type ID substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * Clients calling this function must replace the `\{id\}` substring with the * actual token type ID. */ function uri(uint256) public view virtual override returns (string memory) { return _uri; } /** * @dev See {IERC1155-balanceOf}. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) public view virtual override returns (uint256) { require(account != address(0), "ERC1155: address zero is not a valid owner"); return _balances[id][account]; } /** * @dev See {IERC1155-balanceOfBatch}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] memory accounts, uint256[] memory ids) public view virtual override returns (uint256[] memory) { require(accounts.length == ids.length, "ERC1155: accounts and ids length mismatch"); uint256[] memory batchBalances = new uint256[](accounts.length); for (uint256 i = 0; i < accounts.length; ++i) { batchBalances[i] = balanceOf(accounts[i], ids[i]); } return batchBalances; } /** * @dev See {IERC1155-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC1155-isApprovedForAll}. */ function isApprovedForAll(address account, address operator) public view virtual override returns (bool) { return _operatorApprovals[account][operator]; } /** * @dev See {IERC1155-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not token owner or approved" ); _safeTransferFrom(from, to, id, amount, data); } /** * @dev See {IERC1155-safeBatchTransferFrom}. */ function safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) public virtual override { require( from == _msgSender() || isApprovedForAll(from, _msgSender()), "ERC1155: caller is not token owner or approved" ); _safeBatchTransferFrom(from, to, ids, amounts, data); } /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, to, ids, amounts, data); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; emit TransferSingle(operator, from, to, id, amount); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _safeBatchTransferFrom( address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); require(to != address(0), "ERC1155: transfer to the zero address"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, to, ids, amounts, data); for (uint256 i = 0; i < ids.length; ++i) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: insufficient balance for transfer"); unchecked { _balances[id][from] = fromBalance - amount; } _balances[id][to] += amount; } emit TransferBatch(operator, from, to, ids, amounts); _afterTokenTransfer(operator, from, to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data); } /** * @dev Sets a new URI for all token types, by relying on the token type ID * substitution mechanism * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. * * By this mechanism, any occurrence of the `\{id\}` substring in either the * URI or any of the amounts in the JSON file at said URI will be replaced by * clients with the token type ID. * * For example, the `https://token-cdn-domain/\{id\}.json` URI would be * interpreted by clients as * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` * for token type ID 0x4cce0. * * See {uri}. * * Because these URIs cannot be meaningfully represented by the {URI} event, * this function emits no events. */ function _setURI(string memory newuri) internal virtual { _uri = newuri; } /** * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); _balances[id][to] += amount; emit TransferSingle(operator, address(0), to, id, amount); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeTransferAcceptanceCheck(operator, address(0), to, id, amount, data); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function _mintBatch( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { require(to != address(0), "ERC1155: mint to the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); for (uint256 i = 0; i < ids.length; i++) { _balances[ids[i]][to] += amounts[i]; } emit TransferBatch(operator, address(0), to, ids, amounts); _afterTokenTransfer(operator, address(0), to, ids, amounts, data); _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data); } /** * @dev Destroys `amount` tokens of token type `id` from `from` * * Emits a {TransferSingle} event. * * Requirements: * * - `from` cannot be the zero address. * - `from` must have at least `amount` tokens of token type `id`. */ function _burn( address from, uint256 id, uint256 amount ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); address operator = _msgSender(); uint256[] memory ids = _asSingletonArray(id); uint256[] memory amounts = _asSingletonArray(amount); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } emit TransferSingle(operator, from, address(0), id, amount); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. */ function _burnBatch( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { require(from != address(0), "ERC1155: burn from the zero address"); require(ids.length == amounts.length, "ERC1155: ids and amounts length mismatch"); address operator = _msgSender(); _beforeTokenTransfer(operator, from, address(0), ids, amounts, ""); for (uint256 i = 0; i < ids.length; i++) { uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 fromBalance = _balances[id][from]; require(fromBalance >= amount, "ERC1155: burn amount exceeds balance"); unchecked { _balances[id][from] = fromBalance - amount; } } emit TransferBatch(operator, from, address(0), ids, amounts); _afterTokenTransfer(operator, from, address(0), ids, amounts, ""); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC1155: setting approval status for self"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Hook that is called before any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `ids` and `amounts` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} /** * @dev Hook that is called after any token transfer. This includes minting * and burning, as well as batched variants. * * The same hook is called on both single and batched variants. For single * transfers, the length of the `id` and `amount` arrays will be 1. * * Calling conditions (for each `id` and `amount` pair): * * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens * of token type `id` will be transferred to `to`. * - When `from` is zero, `amount` tokens of token type `id` will be minted * for `to`. * - when `to` is zero, `amount` of ``from``'s tokens of token type `id` * will be burned. * - `from` and `to` are never both zero. * - `ids` and `amounts` have the same, non-zero length. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual {} function _doSafeTransferAcceptanceCheck( address operator, address from, address to, uint256 id, uint256 amount, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) { if (response != IERC1155Receiver.onERC1155Received.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non-ERC1155Receiver implementer"); } } } function _doSafeBatchTransferAcceptanceCheck( address operator, address from, address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) private { if (to.isContract()) { try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns ( bytes4 response ) { if (response != IERC1155Receiver.onERC1155BatchReceived.selector) { revert("ERC1155: ERC1155Receiver rejected tokens"); } } catch Error(string memory reason) { revert(reason); } catch { revert("ERC1155: transfer to non-ERC1155Receiver implementer"); } } } function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) { uint256[] memory array = new uint256[](1); array[0] = element; return array; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.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 IERC2981 is IERC165 { /** * @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 (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "../utils/TransferPolicy.sol"; interface ITransferSecurityRegistry { event AddedToAllowlist(AllowlistTypes indexed kind, uint256 indexed id, address indexed account); event CreatedAllowlist(AllowlistTypes indexed kind, uint256 indexed id, string indexed name); event ReassignedAllowlistOwnership(AllowlistTypes indexed kind, uint256 indexed id, address indexed newOwner); event RemovedFromAllowlist(AllowlistTypes indexed kind, uint256 indexed id, address indexed account); event SetAllowlist(AllowlistTypes indexed kind, address indexed collection, uint120 indexed id); event SetTransferSecurityLevel(address indexed collection, TransferSecurityLevels level); function createOperatorWhitelist(string calldata name) external returns (uint120); function createPermittedContractReceiverAllowlist(string calldata name) external returns (uint120); function reassignOwnershipOfOperatorWhitelist(uint120 id, address newOwner) external; function reassignOwnershipOfPermittedContractReceiverAllowlist(uint120 id, address newOwner) external; function renounceOwnershipOfOperatorWhitelist(uint120 id) external; function renounceOwnershipOfPermittedContractReceiverAllowlist(uint120 id) external; function setTransferSecurityLevelOfCollection(address collection, TransferSecurityLevels level) external; function setOperatorWhitelistOfCollection(address collection, uint120 id) external; function setPermittedContractReceiverAllowlistOfCollection(address collection, uint120 id) external; function addOperatorToWhitelist(uint120 id, address operator) external; function addPermittedContractReceiverToAllowlist(uint120 id, address receiver) external; function removeOperatorFromWhitelist(uint120 id, address operator) external; function removePermittedContractReceiverFromAllowlist(uint120 id, address receiver) external; function getCollectionSecurityPolicy(address collection) external view returns (CollectionSecurityPolicy memory); function getWhitelistedOperators(uint120 id) external view returns (address[] memory); function getPermittedContractReceivers(uint120 id) external view returns (address[] memory); function isOperatorWhitelisted(uint120 id, address operator) external view returns (bool); function isContractReceiverPermitted(uint120 id, address receiver) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; interface IEOARegistry is IERC165 { function isVerifiedEOA(address account) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; import "../utils/TransferPolicy.sol"; interface ITransferValidator { function applyCollectionTransferPolicy(address caller, address from, address to) external view; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. * * _Available since v3.1._ */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/extensions/IERC1155MetadataURI.sol) pragma solidity ^0.8.0; import "../IERC1155.sol"; /** * @dev Interface of the optional ERC1155MetadataExtension interface, as defined * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP]. * * _Available since v3.1._ */ interface IERC1155MetadataURI is IERC1155 { /** * @dev Returns the URI for token type `id`. * * If the `\{id\}` substring is present in the URI, it must be replaced by * clients with the actual token type ID. */ function uri(uint256 id) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; enum AllowlistTypes { Operators, PermittedContractReceivers } enum ReceiverConstraints { None, NoCode, EOA } enum CallerConstraints { None, OperatorWhitelistEnableOTC, OperatorWhitelistDisableOTC } enum StakerConstraints { None, CallerIsTxOrigin, EOA } enum TransferSecurityLevels { Zero, One, Two, Three, Four, Five, Six } struct TransferSecurityPolicy { CallerConstraints callerConstraints; ReceiverConstraints receiverConstraints; } struct CollectionSecurityPolicy { TransferSecurityLevels transferSecurityLevel; uint120 operatorWhitelistId; uint120 permittedContractReceiversId; }
{ "evmVersion": "paris", "optimizer": { "enabled": true, "mode": "3" }, "outputSelection": { "*": { "*": [ "abi", "metadata" ], "": [ "ast" ] } }, "detectMissingLibraries": false, "forceEVMLA": false, "enableEraVMExtensions": false, "libraries": {} }
[{"inputs":[{"internalType":"string","name":"_baseURI","type":"string"},{"internalType":"address","name":"usdc_","type":"address"},{"internalType":"address","name":"signerAddress_","type":"address"},{"internalType":"address","name":"feeRecipient_","type":"address"},{"internalType":"uint96","name":"royaltyFeeNumerator_","type":"uint96"},{"internalType":"uint256","name":"initialQueueFee","type":"uint256"},{"internalType":"uint256","name":"initialLoseQueueRefund","type":"uint256"},{"internalType":"uint256","name":"initialCreateFee","type":"uint256"},{"internalType":"uint256","name":"initialFee","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInQueue","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"BlockhashExpired","type":"error"},{"inputs":[],"name":"BlockhashNotFound","type":"error"},{"inputs":[],"name":"BlockhashNotReady","type":"error"},{"inputs":[],"name":"CreatorTokenBase__InvalidTransferValidatorContract","type":"error"},{"inputs":[],"name":"CreatorTokenBase__SetTransferValidatorFirst","type":"error"},{"inputs":[],"name":"ExceedsMaxQuantity","type":"error"},{"inputs":[],"name":"InsufficientTokensToRedeem","type":"error"},{"inputs":[],"name":"InsufficientTokensToRefund","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"LoseQueueRefundExceedsQueueFee","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NotInQueue","type":"error"},{"inputs":[],"name":"OnlyTokenOwnerOrMarketplaceCanTransfer","type":"error"},{"inputs":[],"name":"PaymentFailed","type":"error"},{"inputs":[],"name":"QueueAlreadyCommitted","type":"error"},{"inputs":[],"name":"QueueAlreadyProcessed","type":"error"},{"inputs":[],"name":"QueueAlreadyRevealed","type":"error"},{"inputs":[],"name":"QueueEmpty","type":"error"},{"inputs":[],"name":"QueuePeriodEnded","type":"error"},{"inputs":[],"name":"QueueStillOpen","type":"error"},{"inputs":[],"name":"RefundTransferFailed","type":"error"},{"inputs":[],"name":"SaleEnded","type":"error"},{"inputs":[],"name":"SaleNotStarted","type":"error"},{"inputs":[],"name":"ShouldNotMintToBurnAddress","type":"error"},{"inputs":[],"name":"TokenMintingDisabled","type":"error"},{"inputs":[],"name":"TokenNotRefundable","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"DefaultRoyaltySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"creator","type":"address"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"DropCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"QueueJoined","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"QueueLeft","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"TokenMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"redeemer","type":"address"}],"name":"TokenRedeemed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"TokenRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint96","name":"feeNumerator","type":"uint96"}],"name":"TokenRoyaltySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"TransferBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"TransferSingle","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldValidator","type":"address"},{"indexed":false,"internalType":"address","name":"newValidator","type":"address"}],"name":"TransferValidatorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"value","type":"string"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"URI","type":"event"},{"inputs":[],"name":"DEFAULT_OPERATOR_WHITELIST_ID","outputs":[{"internalType":"uint120","name":"","type":"uint120"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_TRANSFER_SECURITY_LEVEL","outputs":[{"internalType":"enum TransferSecurityLevels","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_TRANSFER_VALIDATOR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"USDC","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"accounts","type":"address[]"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"balanceOfBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256[]","name":"fees","type":"uint256[]"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"batchRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"marketplace","type":"address"},{"internalType":"bool","name":"isBlacklisted","type":"bool"}],"name":"blacklistMarketplace","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"blacklistedMarketplaces","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"user","type":"address"}],"name":"checkQueueResult","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"claimFromQueue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"commitQueue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonReserved","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bool","name":"_isOE","type":"bool"},{"internalType":"bool","name":"isStripe","type":"bool"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"internalType":"uint256","name":"minMint","type":"uint256"},{"internalType":"uint256","name":"reserved","type":"uint256"}],"name":"createDrop","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"createFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentTokenId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"disabled","type":"bool"}],"name":"disableToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"enteredQueue","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fullWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getPermittedContractReceivers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSecurityPolicy","outputs":[{"components":[{"internalType":"enum TransferSecurityLevels","name":"transferSecurityLevel","type":"uint8"},{"internalType":"uint120","name":"operatorWhitelistId","type":"uint120"},{"internalType":"uint120","name":"permittedContractReceiversId","type":"uint120"}],"internalType":"struct CollectionSecurityPolicy","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransferValidator","outputs":[{"internalType":"contract ICreatorTokenTransferValidator","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWhitelistedOperators","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"isContractReceiverPermitted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isOperatorWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"isTransferAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"joinQueue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"leaveQueue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"loseQueueRefund","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bool","name":"isStripe","type":"bool"},{"internalType":"uint256","name":"tax","type":"uint256"}],"name":"mintToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bool","name":"isStripe","type":"bool"},{"internalType":"uint256","name":"tax","type":"uint256"}],"name":"mintTokenByCreator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"nonceUsed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"queue","outputs":[{"internalType":"uint256","name":"reserved","type":"uint256"},{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"uint256","name":"blockCommit","type":"uint256"},{"internalType":"uint256","name":"rng","type":"uint256"},{"internalType":"uint256","name":"entries","type":"uint256"},{"internalType":"uint256","name":"claimed","type":"uint256"},{"internalType":"uint256","name":"queueFee","type":"uint256"},{"internalType":"uint256","name":"loseQueueRefund","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"queueFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"refundToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"revealQueue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeBatchTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newCreateFee","type":"uint256"}],"name":"setCreateFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFeeRecipient","type":"address"}],"name":"setFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newLoseQueueRefund","type":"uint256"}],"name":"setNewLoseQueueRefund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newQueueFee","type":"uint256"}],"name":"setQueueFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"refundable","type":"bool"}],"name":"setRefundableOverride","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSigner","type":"address"}],"name":"setSigner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum TransferSecurityLevels","name":"level","type":"uint8"},{"internalType":"uint120","name":"operatorWhitelistId","type":"uint120"},{"internalType":"uint120","name":"permittedContractReceiversAllowlistId","type":"uint120"}],"name":"setToCustomSecurityPolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"validator","type":"address"},{"internalType":"enum TransferSecurityLevels","name":"level","type":"uint8"},{"internalType":"uint120","name":"operatorWhitelistId","type":"uint120"},{"internalType":"uint120","name":"permittedContractReceiversAllowlistId","type":"uint120"}],"name":"setToCustomValidatorAndSecurityPolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setToDefaultSecurityPolicy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"transferValidator_","type":"address"}],"name":"setTransferValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_URI","type":"string"}],"name":"setURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"signerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenData","outputs":[{"internalType":"uint256","name":"nonReserved","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"startTimestamp","type":"uint256"},{"internalType":"uint256","name":"endTimestamp","type":"uint256"},{"internalType":"uint256","name":"minMint","type":"uint256"},{"internalType":"address","name":"creator","type":"address"},{"internalType":"bool","name":"isOE","type":"bool"},{"internalType":"uint256","name":"reserved","type":"uint256"},{"internalType":"uint256","name":"purchased","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenDisabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalRedeemed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalRefunded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"uri","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
9c4d535b000000000000000000000000000000000000000000000000000000000000000001000bb50e7223cf30924b6141d0d76e379d32aa23503c0bd301dc06071246f100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000012000000000000000000000000075bf8f439d205b8ee0de9d3622342eb05985859b0000000000000000000000002f2a13462f6d4af64954ee84641d265932849b640000000000000000000000002f2a13462f6d4af64954ee84641d265932849b6400000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000001e8480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4b4000000000000000000000000000000000000000000000000000000000001e8480000000000000000000000000000000000000000000000000000000000000002068747470733a2f2f7777772e64796c692e696f2f6170692f6d65746164617461
Deployed Bytecode
0x00020000000000020011000000000002000000000801034f0001000000010355000000600110027000000a9d0310019700000001002001900000004e0000c13d0000008001000039000000400010043f000000040030008c0000006f0000413d000000000138034f000000000208043b000000e00220027000000ab80020009c0000008a0000a13d00000ab90020009c000000cf0000a13d00000aba0020009c000002050000a13d00000abb0020009c000002700000213d00000ac20020009c0000063a0000a13d00000ac30020009c00000e940000613d00000ac40020009c00000ad80000613d00000ac50020009c0000006f0000c13d000000240030008c0000006f0000413d0000000401800370000000000101043b000b00000001001d00000aa20010009c0000006f0000213d00000aaa01000041000000000101041a0000000002000411000000000012004b00000edb0000c13d00000b20010000410000000c0010043f0000000b01000029000000000010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b39011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000900000001001d000000000101041a000a00000001001d00000b3a010000410000000000100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b3b011001c70000800b020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b0000000a0010006c000015b40000a13d00000b3c01000041000000000010043f00000b2f0100004100002a7300010430000000a002000039000000400020043f0000000001000416000000000001004b0000006f0000c13d0000001f0130003900000a9e01100197000000a001100039000000400010043f0000001f0430018f00000a9f05300198000000a001500039000000600000613d000000000608034f000000006706043c0000000002720436000000000012004b0000005c0000c13d000000000004004b0000006d0000613d000000000258034f0000000304400210000000000501043300000000054501cf000000000545022f000000000202043b0000010004400089000000000242022f00000000024201cf000000000252019f0000000000210435000001200030008c000000710000813d000000000100001900002a7300010430000000a00200043d00000aa00020009c0000006f0000213d0000001f01200039000000000031004b000000000400001900000aa10400804100000aa101100197000000000001004b000000000500001900000aa10500404100000aa10010009c000000000504c019000000000005004b0000006f0000c13d000000a001200039000000000101043300000aa00010009c0000019c0000a13d00000b8c01000041000000000010043f0000004101000039000000040010043f00000b2c0100004100002a730001043000000aed0020009c000000e00000213d00000b070020009c000002350000213d00000b140020009c000002dd0000a13d00000b150020009c000006620000a13d00000b160020009c0000029f0000613d00000b170020009c00000d7e0000613d00000b180020009c0000006f0000c13d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000000000010043f0000000801000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000b00000001001d0000000601000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000a00000001001d0000000b010000290000000201100039000000000101041a000b00000001001d00000b3a010000410000000000100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b3b011001c70000800b020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b0000000b0010006c000014ac0000813d000000400100043d00000b9d020000410000117c0000013d00000ad40020009c000001f60000213d00000ae10020009c000002870000a13d00000ae20020009c000005e90000a13d00000ae30020009c00000aaa0000613d00000ae40020009c00000a370000613d00000ae50020009c0000006f0000c13d0000000001000416000000000001004b0000006f0000c13d00000aaa0100004100000d870000013d00000aee0020009c000002510000213d00000afb0020009c000002f00000a13d00000afc0020009c000006720000a13d00000afd0020009c00000edf0000613d00000afe0020009c00000d830000613d00000aff0020009c0000006f0000c13d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000b00000001001d000000000010043f0000000701000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000000ff0010019000000a7c0000613d0000000b01000029000000000010043f0000000601000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000400200043d000a00000002001d00000b4b0020009c000000840000213d000000000101043b0000000a040000290000010002400039000000400020043f000000000201041a00000000022404360000000103100039000000000303041a00000000003204350000000202100039000000000202041a000000400340003900000000002304350000000302100039000000000202041a0000006003400039000900000003001d00000000002304350000000402100039000000000202041a0000008003400039000700000003001d00000000002304350000000502100039000000000202041a000000a003400039000800000003001d00000000002304350000000602100039000000000202041a000000c0034000390000000000230435000000e0024000390000000701100039000000000101041a00000000001204350000000b01000029000000000010043f0000000701000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000200041100000aa202200197000600000002001d000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000000ff00100190000500000000001d000019130000613d00000009010000290000000001010433000000000001004b000500000000001d000019130000613d0000000a02000029000000000302043300000008020000290000000002020433000a00000003001d000000000032004b000500000000001d000019130000813d00000007020000290000000003020433000900000003001d0000000a0030006c000019110000a13d000000400200043d00000040032000390000000604000029000000000043043500000040030000390000000003320436000000000013043500000b710020009c000000840000213d0000006001200039000000400010043f00000a9d0030009c00000a9d030080410000004001300210000000000202043300000a9d0020009c00000a9d020080410000006002200210000000000112019f000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000aab011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b00000009101000fa0000000a0010006c00000000010000390000000101004039000019120000013d0000001f0410003900000ba6044001970000003f0440003900000ba604400197000000400500043d0000000004450019000b00000005001d000000000054004b0000000005000039000000010500403900000aa00040009c000000840000213d0000000100500190000000840000c13d000000a003300039000000400040043f0000000b040000290000000004140436000a00000004001d000000c0022000390000000004210019000000000034004b0000006f0000213d000000000001004b0000000a06000029000001be0000613d000000000300001900000000043600190000000005230019000000000505043300000000005404350000002003300039000000000013004b000001b70000413d0000000b0110002900000020011000390000000000010435000000c00100043d000900000001001d00000aa20010009c0000006f0000213d000000e00100043d000800000001001d00000aa20010009c0000006f0000213d000001000200043d00000aa20020009c0000006f0000213d000001200100043d00000aa30010009c0000006f0000213d0000000b03000029000000000403043300000aa00040009c000000840000213d0000000203000039000000000503041a000000010650019000000001055002700000007f0550618f0000001f0050008c00000000070000390000000107002039000000000076004b00000e8e0000c13d000000200050008c000001ee0000413d000000000030043f0000001f06400039000000050660027000000aa40660009a000000200040008c00000aa5060040410000001f05500039000000050550027000000aa40550009a000000000056004b000001ee0000813d000000000006041b0000000106600039000000000056004b000001ea0000413d0000001f0040008c000015050000a13d000000000030043f00000ba607400198000016090000c13d000000200600003900000aa505000041000016160000013d00000ad50020009c000002990000a13d00000ad60020009c000006020000a13d00000ad70020009c00000ab80000613d00000ad80020009c00000a570000613d00000ad90020009c0000006f0000c13d0000000001000416000000000001004b0000006f0000c13d000000150100003900000dd90000013d00000ac80020009c000002b30000a13d00000ac90020009c000006270000a13d00000aca0020009c00000ddd0000613d00000acb0020009c00000aa50000613d00000acc0020009c0000006f0000c13d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000000000010043f0000000601000039000000200010043f000000400200003900000000010000192a712a340000040f0000000702100039000000000202041a0000000603100039000000000303041a0000000504100039000000000404041a0000000405100039000000000505041a0000000306100039000000000606041a0000000207100039000000000707041a0000000108100039000000000808041a000000000101041a000000800010043f000000a00080043f000000c00070043f000000e00060043f000001000050043f000001200040043f000001400030043f000001600020043f00000b4d0100004100002a720001042e00000b080020009c000004470000a13d00000b090020009c000006d10000a13d00000b0a0020009c00000ef70000613d00000b0b0020009c00000d8c0000613d00000b0c0020009c0000006f0000c13d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b00000aaa02000041000000000302041a0000000002000411000000000032004b00000edb0000c13d000000000001004b000011820000c13d00000b4501000041000000800010043f00000b590100004100002a730001043000000aef0020009c000004570000a13d00000af00020009c000006da0000a13d00000af10020009c00000f230000613d00000af20020009c00000dcc0000613d00000af30020009c0000006f0000c13d00000aaa01000041000000000101041a0000000005000411000000000015004b00000edb0000c13d000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000aab011001c70000800d02000039000000030300003900000aac0400004100000000060000192a712a670000040f00000001002001900000006f0000613d00000aaa01000041000000000001041b000000000100001900002a720001042e00000abc0020009c0000064b0000a13d00000abd0020009c00000eb50000613d00000abe0020009c00000bb90000613d00000abf0020009c0000006f0000c13d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b00000aa20010009c0000006f0000213d00000b20020000410000000c0020043f000000000010043f0000000c01000039000000200200003900000dd80000013d00000ae80020009c0000047f0000213d00000aeb0020009c000006f50000613d00000aec0020009c0000006f0000c13d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b00000aa20010009c0000006f0000213d000000000010043f0000000d0100003900000dd50000013d00000adc0020009c000004980000213d00000adf0020009c000007020000613d00000ae00020009c0000006f0000c13d0000000001000416000000000001004b0000006f0000c13d000000c001000039000000400010043f0000000401000039000000800010043f00000b9e01000041000000a00010043f0000002001000039000000c00010043f0000008001000039000000e0020000392a7126650000040f000000c00110008a00000a9d0010009c00000a9d01008041000000600110021000000b9f011001c700002a720001042e00000acf0020009c000004b70000213d00000ad20020009c000009790000613d00000ad30020009c0000006f0000c13d0000000001000416000000000001004b0000006f0000c13d000000e001000039000000400010043f000000800000043f000000a00000043f000000c00000043f0000000301000039000000000101041a00000aa20210019800000f8a0000c13d0000014001000039000000400010043f000000e001000039000000e00000043f000001000000043f0000000002000019000000000300001900000040041000390000000000340435000000400300043d00000000022304360000002001100039000000000101043300000b22011001970000000000120435000000000104043300000b22011001970000004002300039000000000012043500000a9d0030009c00000a9d03008041000000400130021000000b5b011001c700002a720001042e00000b1b0020009c000004cf0000213d00000b1e0020009c000009ba0000613d00000b1f0020009c0000006f0000c13d000000440030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b00000aa20010009c0000006f0000213d0000002402800370000000000202043b2a71269f0000040f000009b30000013d00000b020020009c000004e60000213d00000b050020009c000009bf0000613d00000b060020009c0000006f0000c13d000000a40030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b00000aa20010009c0000006f0000213d0000002402800370000000000202043b000700000002001d00000aa20020009c0000006f0000213d0000004402800370000000000202043b00000aa00020009c0000006f0000213d0000002304200039000000000034004b0000006f0000813d0000000404200039000000000448034f000000000504043b00000aa00050009c000000840000213d00000005045002100000003f0640003900000b570660019700000b300060009c000000840000213d0000008006600039000000400060043f000000800050043f00000024022000390000000004240019000000000034004b0000006f0000213d000000000908034f000000000708034f000000000005004b000003280000613d0000008005000039000000000627034f000000000606043b000000200550003900000000006504350000002002200039000000000042004b000003210000413d0000006402700370000000000202043b00000aa00020009c0000006f0000213d0000002304200039000000000034004b000000000500001900000aa10500804100000aa104400197000000000004004b000000000600001900000aa10600404100000aa10040009c000000000605c019000000000006004b0000006f0000c13d0000000404200039000000000447034f000000000404043b00000aa00040009c000000840000213d00000005054002100000003f0650003900000b5706600197000000400700043d0000000006670019000400000007001d000000000076004b0000000007000039000000010700403900000aa00060009c000000840000213d0000000100700190000000840000c13d000000400060043f00000004060000290000000006460436000300000006001d00000024022000390000000005250019000000000035004b0000006f0000213d000000000709034f000000000004004b0000035d0000613d0000000404000029000000000627034f000000000606043b000000200440003900000000006404350000002002200039000000000052004b000003560000413d0000008402700370000000000402043b00000aa00040009c0000006f0000213d0000002302400039000000000032004b000000000500001900000aa10500804100000aa102200197000000000002004b000000000600001900000aa10600404100000aa10020009c000000000605c019000000000006004b0000006f0000c13d0000000405400039000000000257034f000000000202043b00000aa00020009c000000840000213d0000001f0620003900000ba6066001970000003f0660003900000ba606600197000000400700043d0000000006670019000200000007001d000000000076004b0000000007000039000000010700403900000aa00060009c000000840000213d0000000100700190000000840000c13d0000002404400039000000400060043f00000002060000290000000006260436000100000006001d0000000004420019000000000034004b0000006f0000213d0000002003500039000000000439034f00000ba6052001980000001f0620018f0000000103500029000003940000613d000000000704034f0000000108000029000000007907043c0000000008980436000000000038004b000003900000c13d000000000006004b000003a10000613d000000000454034f0000000305600210000000000603043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f000000000043043500000001022000290000000000020435000b0aa20010019b00000000010004110000000b0010006c00001c4b0000c13d00000004010000290000000001010433000000800200043d000600000002001d000000000012004b00001d1e0000c13d000000070100002900080aa20010019c00000d740000613d000000060000006b00001ddf0000c13d000000400100043d000000400200003900000000022104360000004003100039000000800400043d00000000004304350000006003100039000000000004004b000003c30000613d000000800500003900000000060000190000002005500039000000000705043300000000037304360000000106600039000000000046004b000003bd0000413d00000000041300490000000000420435000000040200002900000000040204330000000002430436000000000004004b000003d20000613d000000000300001900000004050000290000002005500039000000000605043300000000026204360000000103300039000000000043004b000003cc0000413d000000000212004900000a9d0020009c00000a9d02008041000000600220021000000a9d0010009c00000a9d010080410000004001100210000000000112019f000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000121019f00000aab011001c70000800d02000039000000040300003900000b8f0400004100000000050004110000000b0600002900000008070000292a712a670000040f00000001002001900000006f0000613d00000b2301000041000000000010044300000007010000290000000400100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000000001004b00000f210000613d000000400300043d0000004401300039000000a002000039000000000021043500000024013000390000000b02000029000000000021043500000b90010000410000000000130435000000040130003900000000020004110000000000210435000000a401300039000000800200043d0000000000210435000a00000003001d000000c401300039000000000002004b000004140000613d000000800300003900000000040000190000002003300039000000000503043300000000015104360000000104400039000000000024004b0000040e0000413d0000000a030000290000000002310049000000040220008a00000064033000390000000000230435000000040200002900000000020204330000000001210436000000000002004b000004260000613d000000000300001900000004050000290000002005500039000000000405043300000000014104360000000103300039000000000023004b000004200000413d0000000a030000290000000002310049000000040220008a00000084033000390000000000230435000000020200002900000000020204330000000001210436000000000002004b0000000106000029000004390000613d000000000300001900000000041300190000000005630019000000000505043300000000005404350000002003300039000000000023004b000004320000413d0000000003120019000000000003043500000000030004140000000804000029000000040040008c0000207b0000c13d0000000005000415000000110550008a00000005055002100000000003000031000000200030008c00000020040000390000000004034019000020b00000013d00000b0f0020009c000005b90000213d00000b120020009c000009d50000613d00000b130020009c0000006f0000c13d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000000000010043f0000000b0100003900000dd50000013d00000af60020009c000005d80000213d00000af90020009c000006ee0000613d00000afa0020009c0000006f0000c13d000000640030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000b00000001001d000000060010008c0000006f0000213d0000002401800370000000000101043b000a00000001001d00000b220010009c0000006f0000213d0000004401800370000000000101043b000900000001001d00000b220010009c0000006f0000213d00000aaa01000041000000000101041a00000aa2011001970000000002000411000000000012004b00000f860000c13d0000000301000039000000000101041a00000aa202100198000015140000c13d00000b7001000041000000800010043f00000b590100004100002a730001043000000ae90020009c0000085e0000613d00000aea0020009c0000006f0000c13d000000440030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d2a7126940000040f000b00000001001d2a7128200000040f00000004010000390000000101100367000000000101043b000000000010043f0000000901000039000000200010043f000000400200003900000000010000192a712a340000040f000000000301041a00000ba7023001970000000b0300002900000a960000013d00000add0020009c0000095d0000613d00000ade0020009c0000006f0000c13d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000b00000001001d00000aa20010009c0000006f0000213d0000000301000039000000000101041a00000aa202100198000009cd0000613d00000b5401000041000000800010043f0000000001000410000000840010043f0000000001000414000000040020008c000a00000002001d000011a50000c13d0000000003000031000000600030008c00000060040000390000000004034019000011c90000013d00000ad00020009c000009a40000613d00000ad10020009c0000006f0000c13d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b00000aaa02000041000000000202041a0000000003000411000000000023004b00000edb0000c13d0000001302000039000000000202041a000000000021004b000010220000a13d00000b5801000041000000800010043f00000b590100004100002a730001043000000b1c0020009c00000a0a0000613d00000b1d0020009c0000006f0000c13d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000201043b00000b37002001980000006f0000c13d000000010100003900000ba10020009c0000119e0000a13d00000ba20020009c00000eb20000613d00000ba30020009c00000eb20000613d00000ba40020009c00000eb20000613d000011a20000013d00000b030020009c00000a110000613d00000b040020009c0000006f0000c13d000000840030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000004401800370000000000101043b000b00000001001d0000002401800370000000000101043b000900000001001d0000000401800370000000000101043b000a00000001001d0000006401800370000000000201043b00000aa00020009c0000006f0000213d0000002301200039000000000031004b0000006f0000813d0000000404200039000000000148034f000000000101043b00000aa00010009c000000840000213d0000001f0610003900000ba6066001970000003f0660003900000ba60660019700000b300060009c000000840000213d00000024022000390000008006600039000000400060043f000000800010043f0000000002210019000000000032004b0000006f0000213d0000002002400039000000000328034f00000ba6041001980000001f0510018f000000a0024000390000051d0000613d000000a006000039000000000703034f000000007807043c0000000006860436000000000026004b000005190000c13d000000000005004b0000052a0000613d000000000343034f0000000304500210000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000320435000000a00110003900000000000104350000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000000ff00100190000016c80000c13d0000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a00000ba70220019700000001022001bf000000000021041b0000000001000411000000000010043f0000000d01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a000000010220003a000016cd0000613d000000000021041b000000400100043d00000080021000390000000b03000029000000000032043500000060021000390000000903000029000000000032043500000040021000390000000a030000290000000000320435000000800200003900000000022104360000000003000411000000000032043500000b800010009c000000840000213d000000a003100039000000400030043f00000a9d0020009c00000a9d020080410000004002200210000000000101043300000a9d0010009c00000a9d010080410000006001100210000000000121019f000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000aab011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000200010043f00000b3e01000041000000000010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b3f011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000400200043d000b00000002001d000000000101043b000000800200043d000000400020008c00001c870000613d000000410020008c00001ed20000c13d000000e00200043d000000f802200270000000200020043f000000c00200043d00001c8c0000013d00000b100020009c00000a160000613d00000b110020009c0000006f0000c13d000000640030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000b00000001001d00000aa20010009c0000006f0000213d0000002401800370000000000101043b000a00000001001d00000aa20010009c0000006f0000213d0000004401800370000000000101043b000900000001001d00000aa20010009c0000006f0000213d00000001020000390000000301000039000000000101041a00000aa2031001980000144e0000c13d0000008001000039000009cf0000013d00000af70020009c00000a2a0000613d00000af80020009c0000006f0000c13d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d2a7128200000040f00000004010000390000000101100367000000000101043b0000001202000039000000000012041b000000000100001900002a720001042e00000ae60020009c00000a7f0000613d00000ae70020009c0000006f0000c13d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b00000aaa02000041000000000202041a0000000003000411000000000023004b00000edb0000c13d0000001302000039000000000012041b0000001402000039000000000302041a000000000013004b00000f210000a13d000000000012041b000000000100001900002a720001042e00000ada0020009c00000a9b0000613d00000adb0020009c0000006f0000c13d000000440030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000b00000001001d00000aa20010009c0000006f0000213d0000002401800370000000000201043b000000000002004b0000000001000039000000010100c039000a00000002001d000000000012004b0000006f0000c13d00000000020004110000000b0020006c0000132b0000c13d00000ab301000041000000800010043f0000002001000039000000840010043f0000002901000039000000a40010043f00000b6201000041000000c40010043f00000b6301000041000000e40010043f00000b640100004100002a730001043000000acd0020009c00000ac40000613d00000ace0020009c0000006f0000c13d000000440030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000002401800370000000000101043b000b00000001001d00000aa20010009c0000006f0000213d0000000401800370000000000101043b000000000010043f000000070100003900000ea40000013d00000ac60020009c00000c740000613d00000ac70020009c0000006f0000c13d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000b00000001001d00000aa20010009c0000006f0000213d2a7128200000040f0000001701000039000006ea0000013d00000ac00020009c00000d2c0000613d00000ac10020009c0000006f0000c13d000000240030008c0000006f0000413d0000000401800370000000000101043b000b00000001001d00000aa20010009c0000006f0000213d00000aaa01000041000000000101041a0000000005000411000000000015004b00000edb0000c13d0000000b06000029000000000006004b000013a50000c13d00000b2e01000041000000000010043f00000b2f0100004100002a730001043000000b190020009c00000e0c0000613d00000b1a0020009c0000006f0000c13d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b00000aa20010009c0000006f0000213d000000000010043f0000000f01000039000006fe0000013d00000b000020009c00000e710000613d00000b010020009c0000006f0000c13d000000440030008c0000006f0000413d0000000002000416000000000002004b0000006f0000c13d0000000402800370000000000202043b00000aa00020009c0000006f0000213d0000002304200039000000000034004b0000006f0000813d0000000404200039000000000448034f000000000504043b00000aa00050009c000000840000213d00000005045002100000003f0640003900000b570660019700000b300060009c000000840000213d0000008006600039000000400060043f000000800050043f00000024022000390000000004240019000000000034004b0000006f0000213d000000000908034f000000000708034f000000000005004b000006a00000613d000000a005000039000000000627034f000000000606043b00000aa20060009c0000006f0000213d00000000056504360000002002200039000000000042004b000006980000413d0000002402700370000000000202043b00000aa00020009c0000006f0000213d0000002304200039000000000034004b000000000500001900000aa10500404100000aa104400197000000000004004b000000000600001900000aa10600204100000aa10040009c000000000605c019000000000006004b0000006f0000613d0000000404200039000000000447034f000000000404043b00000aa00040009c000000840000213d00000005054002100000003f0650003900000b5706600197000000400700043d0000000006670019000800000007001d000000000076004b0000000007000039000000010700403900000aa00060009c000000840000213d0000000100700190000000840000c13d000000400060043f00000008060000290000000006460436000700000006001d00000024022000390000000005250019000000000035004b0000006f0000213d000000000004004b000018c90000c13d000000800200043d000000000002004b0000000002000019000018d80000613d000018fd0000013d00000b0d0020009c000006ee0000613d00000b0e0020009c0000006f0000c13d0000000001000416000000000001004b0000006f0000c13d000000130100003900000dd90000013d00000af40020009c00000e800000613d00000af50020009c0000006f0000c13d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000b00000001001d00000aa20010009c0000006f0000213d2a7128200000040f0000001101000039000000000201041a00000ab0022001970000000b0300002900000a530000013d0000000001000416000000000001004b0000006f0000c13d0000000101000039000000800010043f00000b210100004100002a720001042e000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000000000010043f0000000901000039000000200010043f0000004002000039000000000100001900000ead0000013d000000840030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b00000aa00010009c0000006f0000213d0000002302100039000000000032004b0000006f0000813d0000000402100039000000000228034f000000000402043b00000aa00040009c000000840000213d00000005024002100000003f0520003900000b570550019700000b300050009c000000840000213d0000008005500039000000400050043f000000800040043f00000024011000390000000002120019000000000032004b0000006f0000213d000000000708034f000000000608034f000000000004004b0000072b0000613d0000008004000039000000000516034f000000000505043b000000200440003900000000005404350000002001100039000000000021004b000007240000413d0000002401600370000000000101043b000b00000001001d0000004401600370000000000101043b00000aa00010009c0000006f0000213d0000002302100039000000000032004b000000000400001900000aa10400804100000aa102200197000000000002004b000000000500001900000aa10500404100000aa10020009c000000000504c019000000000005004b0000006f0000c13d0000000402100039000000000226034f000000000202043b00000aa00020009c000000840000213d00000005042002100000003f0540003900000b5705500197000000400600043d0000000005560019000a00000006001d000000000065004b0000000006000039000000010600403900000aa00050009c000000840000213d0000000100600190000000840000c13d000000400050043f0000000a050000290000000005250436000900000005001d00000024011000390000000004140019000000000034004b0000006f0000213d000000000607034f000000000002004b000007630000613d0000000a02000029000000000516034f000000000505043b000000200220003900000000005204350000002001100039000000000041004b0000075c0000413d0000006401600370000000000201043b00000aa00020009c0000006f0000213d0000002301200039000000000031004b000000000400001900000aa10400804100000aa101100197000000000001004b000000000500001900000aa10500404100000aa10010009c000000000504c019000000000005004b0000006f0000c13d0000000404200039000000000146034f000000000101043b00000aa00010009c000000840000213d0000001f0510003900000ba6055001970000003f0550003900000ba605500197000000400600043d0000000005560019000800000006001d000000000065004b0000000006000039000000010600403900000aa00050009c000000840000213d0000000100600190000000840000c13d0000002402200039000000400050043f00000008050000290000000005150436000700000005001d0000000002210019000000000032004b0000006f0000213d0000002002400039000000000327034f00000ba6041001980000001f0510018f00000007024000290000079a0000613d000000000603034f0000000707000029000000006806043c0000000007870436000000000027004b000007960000c13d000000000005004b000007a70000613d000000000343034f0000000304500210000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000320435000000070110002900000000000104350000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000000ff00100190000016c80000c13d0000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a00000ba70220019700000001022001bf000000000021041b0000000001000411000000000010043f0000000d01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a000000010220003a000016cd0000613d000000000021041b000000400100043d000000400210003900000080040000390000000000420435000000200210003900000000030004110000000000320435000000a003100039000000800500043d0000000000530435000000c003100039000000000005004b0000080c0000613d00000000060000190000002004400039000000000704043300000000037304360000000106600039000000000056004b000008060000413d00000060041000390000000b0500002900000000005404350000000004130049000000200440008a000000800510003900000000004504350000000a0400002900000000040404330000000003430436000000000004004b000008200000613d00000000050000190000000a060000290000002006600039000000000706043300000000037304360000000105500039000000000045004b0000081a0000413d0000000003130049000000200430008a00000000004104350000001f0330003900000ba6043001970000000003140019000000000043004b0000000004000039000000010400403900000aa00030009c000000840000213d0000000100400190000000840000c13d000000400030043f00000a9d0020009c00000a9d020080410000004002200210000000000101043300000a9d0010009c00000a9d010080410000006001100210000000000121019f000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000aab011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000200010043f00000b3e01000041000000000010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b3f011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000400200043d000b00000002001d000000000101043b00000008020000290000000002020433000000400020008c000022b60000613d000000410020008c00001ed20000c13d000000080300002900000060023000390000000002020433000000f802200270000000200020043f00000040023000390000000002020433000022bd0000013d000000a40030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000b00000001001d0000002401800370000000000201043b00000aa00020009c0000006f0000213d0000002301200039000000000031004b0000006f0000813d0000000404200039000000000148034f000000000101043b00000aa00010009c000000840000213d0000001f0610003900000ba6066001970000003f0660003900000ba60660019700000b300060009c000000840000213d00000024022000390000008006600039000000400060043f000000800010043f0000000002210019000000000032004b0000006f0000213d000000000908034f0000002002400039000000000328034f00000ba6041001980000001f0510018f000000a0024000390000088c0000613d000000a006000039000000000703034f000000007807043c0000000006860436000000000026004b000008880000c13d000000000005004b000008990000613d000000000343034f0000000304500210000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000320435000000a00110003900000000000104350000004401900370000000000101043b000a00000001001d0000006401900370000000000201043b000000000002004b0000000001000039000000010100c039000900000002001d000000000012004b0000006f0000c13d0000008401900370000000000101043b000800000001001d0000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000a02000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000000ff00100190000016c80000c13d0000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000a02000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a00000ba70220019700000001022001bf000000000021041b0000000001000411000000000010043f0000000d01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a000000010220003a000016cd0000613d000000000021041b0000000b01000029000000000010043f0000000801000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000600000001001d0000000301100039000000000101041a000700000001001d000000000001004b0000091a0000613d00000b3a010000410000000000100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b3b011001c70000800b020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000070010006c00000d290000213d000000400100043d000000a0021000390000000803000029000000000032043500000080021000390000000903000029000000000032043500000060021000390000000a03000029000000000032043500000040021000390000000b030000290000000000320435000000a0020000390000000002210436000000000300041100000aa203300197000a00000003001d000000000032043500000b3d0010009c000000840000213d000000c003100039000000400030043f00000a9d0020009c00000a9d020080410000004002200210000000000101043300000a9d0010009c00000a9d010080410000006001100210000000000121019f000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000aab011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000200010043f00000b3e01000041000000000010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b3f011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000400200043d000700000002001d000000000101043b000000800200043d000000400020008c00001e330000613d000000410020008c00001ed20000c13d000000e00200043d000000f802200270000000200020043f000000c00200043d00001e380000013d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000b00000001001d000000000010043f0000000801000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000201043b0000000601200039000000000101041a000000000001004b00000fab0000c13d000000400100043d00000b9c020000410000117c0000013d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000000000010043f0000000801000039000000200010043f000000400200003900000000010000192a712a340000040f0000000702100039000000000202041a0000000603100039000000000303041a0000000504100039000000000404041a0000000405100039000000000505041a0000000306100039000000000606041a0000000207100039000000000707041a0000000108100039000000000808041a000000000101041a000000800010043f000000a00080043f000000c00070043f000000e00060043f000001000050043f00000aa201400197000001200010043f00000b5c004001980000000001000039000000010100c039000001400010043f000001600030043f000001800020043f00000b5d0100004100002a720001042e000000440030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000002401800370000000000201043b00000aa20020009c0000006f0000213d0000000401800370000000000101043b2a71278a0000040f000000000001004b0000000001000039000000010100c039000000400200043d000000000012043500000a9d0020009c00000a9d02008041000000400120021000000b4c011001c700002a720001042e0000000001000416000000000001004b0000006f0000c13d000000100100003900000dd90000013d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000b00000001001d00000aa20010009c0000006f0000213d0000000301000039000000000101041a00000aa20210019800000fc00000c13d0000008001000039000000010200018f000000000021043500000a9d0010009c00000a9d01008041000000400110021000000b4c011001c700002a720001042e000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000012001000039000000400010043f0000010001000039000001000000043f0000000402800370000000000202043b0000000003010019000000090020008c0000000a1220011a000000f804100210000000010130008a000000000501043300000b9805500197000000000445019f00000b99044001c70000000000410435000009e00000213d0000010102300089000000210330008a00000000002304350000001604000039000000000204041a000000010520019000000001092002700000007f0990618f0000001f0090008c00000000060000390000000106002039000000000662013f000000010060019000000e8e0000c13d000000400800043d000000000005004b00000fcd0000613d000000000040043f000000000009004b00000fd00000613d00000aae02000041000000200480003900000000050000190000000006540019000000000702041a000000000076043500000001022000390000002005500039000000000095004b00000a020000413d00000fd00000013d0000000001000416000000000001004b0000006f0000c13d00000b6c01000041000000800010043f00000b210100004100002a720001042e0000000001000416000000000001004b0000006f0000c13d000000140100003900000dd90000013d000000440030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b00000aa20010009c0000006f0000213d000000000010043f0000000e01000039000000200010043f00000040020000390000000001000019000b0000000803532a712a340000040f0000000b0200035f0000002402200370000000000202043b00000ea90000013d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d2a7128200000040f00000004010000390000000101100367000000000101043b0000001502000039000000000012041b000000000100001900002a720001042e000000440030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000b00000001001d2a7126940000040f000a00000001001d2a7128200000040f0000001801000039000000200010043f0000000b010000290000000801100270000000000010043f000000400200003900000000010000192a712a340000040f0000000b02000029000000ff0220018f0000000a0000006b0000000003000039000000010300c03900000000032301cf00000ba8022002df000000000401041a000000000224016f000000000232019f000000000021041b000000000100001900002a720001042e000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000b00000001001d000000000010043f0000000701000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000000ff00100190000012770000c13d000000400100043d00000b77020000410000117c0000013d000000440030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000b00000001001d00000aa20010009c0000006f0000213d2a7126940000040f000a00000001001d2a7128200000040f0000000b01000029000000000010043f0000000f01000039000000200010043f000000400200003900000000010000192a712a340000040f000000000301041a00000ba7023001970000000a03000029000000000003004b000000010220c1bf000000000021041b000000000100001900002a720001042e000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000000000010043f0000000a0100003900000dd50000013d0000000001000416000000000001004b0000006f0000c13d000000120100003900000dd90000013d0000000001000416000000000001004b0000006f0000c13d0000000001000412000f00000001001d000e00000000003d0000800501000039000000440300003900000000040004150000000f0440008a000000050440021000000b29020000412a712a490000040f00000d880000013d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b00000aa20010009c0000006f0000213d2a7126e10000040f000000000100001900002a720001042e0000000002000416000000000002004b0000006f0000c13d0000000302000039000000000202041a00000aa20220019800000e780000613d00000b5403000041000000800030043f0000000003000410000000840030043f0000000003000414000000040020008c000b00000002001d000010260000c13d0000000003000031000000600030008c000000600400003900000000040340190000104a0000013d000000c40030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000b00000001001d0000002401800370000000000201043b00000aa00020009c0000006f0000213d0000002301200039000000000031004b0000006f0000813d0000000404200039000000000148034f000000000101043b00000aa00010009c000000840000213d0000001f0610003900000ba6066001970000003f0660003900000ba60660019700000b300060009c000000840000213d00000024022000390000008006600039000000400060043f000000800010043f0000000002210019000000000032004b0000006f0000213d000000000908034f0000002002400039000000000328034f00000ba6041001980000001f0510018f000000a00240003900000b060000613d000000a006000039000000000703034f000000007807043c0000000006860436000000000026004b00000b020000c13d000000000005004b00000b130000613d000000000343034f0000000304500210000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000320435000000a00110003900000000000104350000004401900370000000000101043b000a00000001001d00000aa20010009c0000006f0000213d0000006401900370000000000101043b000900000001001d0000008401900370000000000201043b000000000002004b0000000001000039000000010100c039000800000002001d000000000012004b0000006f0000c13d000000a401900370000000000101043b000700000001001d0000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000902000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000000ff00100190000016c80000c13d0000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000902000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a00000ba70220019700000001022001bf000000000021041b0000000001000411000000000010043f0000000d01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a000000010220003a000016cd0000613d000000000021041b000000400100043d000000a0021000390000000703000029000000000032043500000080021000390000000803000029000000000032043500000060021000390000000903000029000000000032043500000040021000390000000b030000290000000000320435000000a0020000390000000002210436000000000300041100000aa203300197000000000032043500000b3d0010009c000000840000213d000000c003100039000000400030043f00000a9d0020009c00000a9d020080410000004002200210000000000101043300000a9d0010009c00000a9d010080410000006001100210000000000121019f000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000aab011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000200010043f00000b3e01000041000000000010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b3f011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000400200043d000900000002001d000000000101043b000000800200043d000000400020008c00001d700000613d000000410020008c00001ed20000c13d000000e00200043d000000f802200270000000200020043f000000c00200043d00001d750000013d000000840030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000b00000001001d00000aa20010009c0000006f0000213d0000002401800370000000000101043b000a00000001001d000000060010008c0000006f0000213d0000004401800370000000000101043b000900000001001d00000b220010009c0000006f0000213d0000006401800370000000000101043b000800000001001d00000b220010009c0000006f0000213d00000aaa01000041000000000101041a00000aa2011001970000000002000411000000000012004b00000f860000c13d0000000b010000292a7126e10000040f00000b230100004100000000001004430000000b010000290000000400100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000000001004b0000006f0000613d000000400300043d00000024013000390000000a02000029000000000021043500000b25010000410000000000130435000000000100041000000aa202100197000a00000003001d0000000401300039000700000002001d000000000021043500000000010004140000000b02000029000000040020008c00000c090000613d0000000a0200002900000a9d0020009c00000a9d02008041000000400220021000000a9d0010009c00000a9d01008041000000c001100210000000000121019f00000b26011001c70000000b020000292a712a670000040f000000600310027000000a9d0030019d00000001002001900000187d0000613d0000000a0100002900000aa00010009c000000840000213d0000000a01000029000000400010043f00000b230100004100000000001004430000000b010000290000000400100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000000001004b0000006f0000613d000000400300043d00000024013000390000000902000029000000000021043500000b27010000410000000000130435000a00000003001d00000004013000390000000702000029000000000021043500000000010004140000000b02000029000000040020008c00000c3b0000613d0000000a0200002900000a9d0020009c00000a9d02008041000000400220021000000a9d0010009c00000a9d01008041000000c001100210000000000121019f00000b26011001c70000000b020000292a712a670000040f000000600310027000000a9d0030019d000000010020019000001a600000613d0000000a0100002900000aa00010009c000000840000213d0000000a01000029000000400010043f00000b230100004100000000001004430000000b010000290000000400100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000000001004b0000006f0000613d000000400300043d00000024013000390000000802000029000000000021043500000b28010000410000000000130435000a00000003001d00000004013000390000000702000029000000000021043500000000010004140000000b02000029000000040020008c00000c6d0000613d0000000a0200002900000a9d0020009c00000a9d02008041000000400220021000000a9d0010009c00000a9d01008041000000c001100210000000000121019f00000b26011001c70000000b020000292a712a670000040f000000600310027000000a9d0030019d000000010020019000001d110000613d0000000a0100002900000aa00010009c000000840000213d0000000a01000029000000400010043f000000000100001900002a720001042e000001440030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000004401800370000000000201043b000000000002004b0000000001000039000000010100c039000b00000002001d000000000012004b0000006f0000c13d0000006401800370000000000201043b000000000002004b0000000001000039000000010100c039000a00000002001d000000000012004b0000006f0000c13d0000008401800370000000000201043b00000aa00020009c0000006f0000213d0000002301200039000000000031004b0000006f0000813d0000000404200039000000000148034f000000000101043b00000aa00010009c000000840000213d0000001f0610003900000ba6066001970000003f0660003900000ba60660019700000b300060009c000000840000213d00000024022000390000008006600039000000400060043f000000800010043f0000000002210019000000000032004b0000006f0000213d0000002002400039000000000328034f00000ba6041001980000001f0510018f000000a00240003900000cae0000613d000000a006000039000000000703034f000000007807043c0000000006860436000000000026004b00000caa0000c13d000000000005004b00000cbb0000613d000000000343034f0000000304500210000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000320435000000a00110003900000000000104350000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000a4020000390000000102200367000000000202043b000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000000ff00100190000016c80000c13d0000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000a4020000390000000102200367000000000202043b000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a00000ba70220019700000001022001bf000000000021041b0000000001000411000000000010043f0000000d01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a000000010220003a000016cd0000613d000000000021041b0000000102000367000000c401200370000000000101043b000900000001001d000000000001004b00000d240000c13d00000b3a010000410000000000100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b3b011001c70000800b020000392a712a6c0000040f0000000100200190000025bc0000613d0000000102000367000000000101043b000900000001001d000000e401200370000000000401043b000000010140008a000000090010006c00001bf60000813d000000400100043d00000b6b020000410000117c0000013d000000a40030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000901043b00000aa20090009c0000006f0000213d0000002401800370000000000101043b000800000001001d00000aa20010009c0000006f0000213d0000008401800370000000000201043b00000aa00020009c0000006f0000213d0000002301200039000000000031004b0000006f0000813d0000000404200039000000000148034f000000000101043b00000aa00010009c000000840000213d0000001f0510003900000ba6055001970000003f0550003900000ba60550019700000b300050009c000000840000213d00000024022000390000008005500039000000400050043f000000800010043f0000000002210019000000000032004b0000006f0000213d000900000009001d0000002002400039000000000328034f00000ba6041001980000001f0510018f000000a00240003900000d600000613d000000a006000039000000000703034f000000007807043c0000000006860436000000000026004b00000d5c0000c13d000000000005004b00000d6d0000613d000000000343034f0000000304500210000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000320435000000a00110003900000000000104350000000002000411000000090020006c000016e20000c13d000000080000006b0000177a0000c13d000000400100043d000000640210003900000b91030000410000000000320435000000440210003900000b9203000041000000000032043500000024021000390000002503000039000019060000013d0000000001000416000000000001004b0000006f0000c13d000000030100003900000d870000013d0000000001000416000000000001004b0000006f0000c13d0000001101000039000000000101041a00000aa201100197000000800010043f00000b210100004100002a720001042e000000440030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000002401800370000000000101043b000b00000001001d0000000401800370000000000101043b000000000010043f0000000501000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000400300043d00000aa70030009c000000840000213d000000000101043b0000004002300039000000400020043f000000000101041a0000002004300039000000a002100270000000000024043500000aa201100198000000000013043500000dbb0000c13d000000400300043d00000aa70030009c000000840000213d0000004001300039000000400010043f0000000401000039000000000101041a0000002004300039000000a002100270000000000024043500000aa20110019700000000001304350000000b0400002900000000034200a9000000000004004b00000dc20000613d00000000044300d9000000000042004b000016cd0000c13d000027100230011a000000400300043d00000020043000390000000000240435000000000013043500000a9d0030009c00000a9d03008041000000400130021000000b95011001c700002a720001042e000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000000000010043f0000000c01000039000000200010043f000000400200003900000000010000192a712a340000040f000000000101041a000000800010043f00000b210100004100002a720001042e000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b000000000010043f0000000601000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000303100039000000000203041a000000000002004b0000117a0000c13d000a00000003001d0000000201100039000000000101041a000b00000001001d00000b4f010000410000000000100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b3b011001c70000800b020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000900000001001d0000000b02000029000000000021004b000014910000813d000000400100043d00000b53020000410000117c0000013d000000240030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000201043b00000aa00020009c0000006f0000213d0000002301200039000000000031004b0000006f0000813d0000000405200039000000000158034f000000000101043b00000aa00010009c000000840000213d0000001f0610003900000ba6066001970000003f0660003900000ba60660019700000b300060009c000000840000213d00000024022000390000008006600039000000400060043f000000800010043f0000000002210019000000000032004b0000006f0000213d0000002002500039000000000328034f00000ba6051001980000001f0610018f000000a00250003900000e360000613d000000a007000039000000000803034f000000008908043c0000000007970436000000000027004b00000e320000c13d000000000006004b00000e430000613d000000000353034f0000000305600210000000000602043300000000065601cf000000000656022f000000000303043b0000010005500089000000000353022f00000000035301cf000000000363019f0000000000320435000000a001100039000000000001043500000aaa01000041000000000101041a0000000002000411000000000012004b00000edb0000c13d000000800200043d00000aa00020009c000000840000213d0000001601000039000000000501041a000000010050019000000001035002700000007f0330618f0000001f0030008c00000000060000390000000106002039000000000565013f000000010050019000000e8e0000c13d000000200030008c00000e690000413d000000000010043f0000001f05200039000000050550027000000aad0550009a000000200020008c00000aae050040410000001f03300039000000050330027000000aad0330009a000000000035004b00000e690000813d000000000005041b0000000105500039000000000035004b00000e650000413d0000001f0020008c000017e80000a13d000000000010043f00000ba604200198000018ac0000c13d000000a00500003900000aae03000041000018ba0000013d0000000002000416000000000002004b0000006f0000c13d0000000302000039000000000202041a00000aa20220019800000f960000c13d000000a001000039000000400010043f0000008002000039000000800000043f000000400100043d000b00000001001d2a7126770000040f000013150000013d0000000001000416000000000001004b0000006f0000c13d0000001603000039000000000203041a000000010420019000000001012002700000007f0110618f0000001f0010008c00000000050000390000000105002039000000000552013f000000010050019000000fa30000613d00000b8c01000041000000000010043f0000002201000039000000040010043f00000b2c0100004100002a7300010430000000440030008c0000006f0000413d0000000001000416000000000001004b0000006f0000c13d0000000401800370000000000101043b00000aa20010009c0000006f0000213d0000002402800370000000000202043b000b00000002001d00000aa20020009c0000006f0000213d000000000010043f0000000101000039000000200010043f000000400200003900000000010000192a712a340000040f0000000b02000029000000000020043f000000200010043f000000000100001900000040020000392a712a340000040f000000000101041a000000ff001001900000000001000039000000010100c039000000800010043f00000b210100004100002a720001042e0000000001000416000000000001004b0000006f0000c13d00000aaa01000041000000000101041a0000000002000411000000000012004b00000edb0000c13d00000b29010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b2a011001c700008005020000392a712a6c0000040f0000000100200190000025bc0000613d000000000201043b000000400b00043d00000b2b0100004100000000001b04350000000401b0003900000000030004100000000000310435000000000100041400000aa202200197000000040020008c000a00000002001d0000135b0000c13d0000000004000031000000200040008c0000002004008039000013860000013d00000ba001000041000000000010043f00000b2f0100004100002a730001043000000b20010000410000000c0010043f0000000001000411000000000010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b39011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000001041b000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000aab011001c70000800d02000039000000020300003900000b780400004100000f1d0000013d00000b20010000410000000c0010043f0000000001000411000000000010043f00000b3a010000410000000000100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b3b011001c70000800b020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000b00000001001d000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b39011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000b0200002900000b960220009a000000000021041b000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000aab011001c70000800d02000039000000020300003900000b970400004100000000050004112a712a670000040f00000001002001900000006f0000613d000000000100001900002a720001042e0000000001000416000000000001004b0000006f0000c13d00000aaa01000041000000000101041a00000aa2011001970000000002000411000000000012004b00000f860000c13d00000b2301000041000000000010044300000b6c010000410000000400100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f0000000100200190000025bc0000613d000000400300043d000000000101043b000000000001004b000014a50000613d00000b6d0100004100000000001304350000000401300039000000000001043500000a9d0030009c00000a9d0100004100000000010340190000004001100210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000b2c011001c700000b6c02000041000b00000003001d2a712a6c0000040f0000000b0b000029000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900000f5e0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00000f5a0000c13d000000000006004b00000f6b0000613d000000000171034f0000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f0000000000150435000000000003001f0000000100200190000014a40000613d0000001f01400039000000600210018f0000000001b20019000000000021004b0000000002000039000000010200403900000aa00010009c000000840000213d0000000100200190000000840000c13d000000400010043f000000200030008c0000006f0000413d0000000b020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b0000006f0000c13d000000000002004b000017f20000c13d0000000003010019000014a50000013d00000b4301000041000000800010043f00000b590100004100002a730001043000000b5401000041000000e00010043f0000000001000410000000e40010043f0000000001000414000000040020008c00000fe90000c13d0000000003000031000000600030008c000000600400003900000000040340190000100d0000013d00000b5403000041000000800030043f0000000003000410000000840030043f0000000003000414000000040020008c000b00000002001d000010cd0000c13d0000000003000031000000600030008c00000060040000390000000004034019000010f10000013d000000800010043f000000000004004b000011740000613d000000000030043f000000000001004b000013010000c13d000000a0010000390000130c0000013d000900000002001d0000000201200039000000000101041a000a00000001001d00000b3a010000410000000000100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b3b011001c70000800b020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b0000000a0010006c000013b50000a13d000000400100043d00000b68020000410000117c0000013d00000b5401000041000000800010043f0000000001000410000000840010043f0000000001000414000000040020008c000a00000002001d000012220000c13d0000000003000031000000600030008c00000060040000390000000004034019000012460000013d00000ba702200197000000200480003900000000002404350000000002890019000000200420003900000b9a05000041000000000054043500000021022000390000000003030433000a00000003001d000b00000008001d000900000009001d2a7126580000040f00000009020000290000000a0320002900000001023000390000000b01000029000000000021043500000021023000392a7126460000040f0000002001000039000000400200043d000a00000002001d00000000021204360000000b010000292a7126650000040f0000000a02000029000013160000013d00000a9d0010009c00000a9d01008041000000c00110021000000b5a011001c72a712a6c0000040f000000e00a000039000000600310027000000a9d03300197000000600030008c000000600400003900000000040340190000001f0640018f0000006007400190000000e00570003900000ffd0000613d000000000801034f000000008908043c000000000a9a043600000000005a004b00000ff90000c13d000000000006004b0000100a0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00000001002001900000126b0000613d0000001f01400039000000e00410018f000000e001400039000000400010043f000000600030008c0000006f0000413d0000014002400039000000400020043f000000e00200043d000000060020008c0000006f0000213d0000000000210435000001000300043d00000b220030009c0000006f0000213d00000100044001bf0000000000340435000001200300043d00000b220030009c000002cc0000a13d0000006f0000013d0000001402000039000000000012041b000000000100001900002a720001042e00000a9d0030009c00000a9d03008041000000c00130021000000b55011001c72a712a6c0000040f000000800a000039000000600310027000000a9d03300197000000600030008c000000600400003900000000040340190000001f0640018f000000600740019000000080057001bf0000103a0000613d000000000801034f000000008908043c000000000a9a043600000000005a004b000010360000c13d000000000006004b000010470000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000012f50000613d0000001f02400039000000e00220018f0000008004200039000000400040043f000000600030008c0000006f0000413d000000e005200039000000400050043f000000800500043d000000060050008c0000006f0000213d0000000000540435000000a00400043d00000b220040009c0000006f0000213d000000a0052000390000000000450435000000c00400043d00000b220040009c0000006f0000213d000000c002200039000000000042043500000b5602000041000000400500043d0000000000250435000a00000005001d0000000402500039000000000042043500000000020004140000000b04000029000000040040008c0000107a0000613d0000000a0100002900000a9d0010009c00000a9d01008041000000400110021000000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000b2c011001c70000000b020000292a712a6c0000040f000000600310027000000a9d0030019d00000a9d033001970000000100200190000017620000613d00000ba6053001980000001f0630018f0000000a04500029000010840000613d000000000701034f0000000a08000029000000007907043c0000000008980436000000000048004b000010800000c13d000000000006004b000010910000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000ba6011001970000000a02100029000000000012004b0000000001000039000000010100403900000aa00020009c000000840000213d0000000100100190000000840000c13d000000400020043f00000b400030009c0000006f0000213d000000200030008c0000006f0000413d0000000a01000029000000000101043300000aa00010009c0000006f0000213d0000000a033000290000000a011000290000001f04100039000000000034004b000000000500001900000aa10500804100000aa10440019700000aa106300197000000000764013f000000000064004b000000000400001900000aa10400404100000aa10070009c000000000405c019000000000004004b0000006f0000c13d000000001401043400000aa00040009c000000840000213d00000005054002100000003f0650003900000b5706600197000000000626001900000aa00060009c000000840000213d000000400060043f00000000004204350000000004150019000000000034004b0000006f0000213d000000000041004b00000e7c0000813d0000000003020019000000001501043400000aa20050009c0000006f0000213d00000020033000390000000000530435000000000041004b000010c50000413d00000e7c0000013d00000a9d0030009c00000a9d03008041000000c00130021000000b55011001c72a712a6c0000040f000000600310027000000a9d03300197000000600030008c000000600400003900000000040340190000001f0640018f000000600740019000000080057001bf000010e10000613d0000008008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000010dd0000c13d000000000006004b000010ee0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00000001002001900000131f0000613d0000001f02400039000000e00220018f0000008004200039000000400040043f000000600030008c0000006f0000413d000000e005200039000000400050043f000000800500043d000000060050008c0000006f0000213d0000000000540435000000a00400043d00000b220040009c0000006f0000213d000000a0052000390000000000450435000000c00500043d00000b220050009c0000006f0000213d000000c002200039000000000052043500000b7e02000041000000400500043d0000000000250435000a00000005001d0000000402500039000000000042043500000000020004140000000b04000029000000040040008c000011210000613d0000000a0100002900000a9d0010009c00000a9d01008041000000400110021000000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000b2c011001c70000000b020000292a712a6c0000040f000000600310027000000a9d0030019d00000a9d0330019700000001002001900000176e0000613d00000ba6053001980000001f0630018f0000000a045000290000112b0000613d000000000701034f0000000a08000029000000007907043c0000000008980436000000000048004b000011270000c13d000000000006004b000011380000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000ba6011001970000000a02100029000000000012004b0000000001000039000000010100403900000aa00020009c000000840000213d0000000100100190000000840000c13d000000400020043f00000b400030009c0000006f0000213d000000200030008c0000006f0000413d0000000a01000029000000000101043300000aa00010009c0000006f0000213d0000000a033000290000000a011000290000001f04100039000000000034004b000000000500001900000aa10500804100000aa10440019700000aa106300197000000000764013f000000000064004b000000000400001900000aa10400404100000aa10070009c000000000405c019000000000004004b0000006f0000c13d000000001401043400000aa00040009c000000840000213d00000005054002100000003f0650003900000b5706600197000000000626001900000aa00060009c000000840000213d000000400060043f00000000004204350000000004150019000000000034004b0000006f0000213d000000000041004b00000e7c0000813d0000000003020019000000001501043400000aa20050009c0000006f0000213d00000020033000390000000000530435000000000041004b0000116c0000413d00000e7c0000013d00000ba702200197000000a00020043f000000000001004b000000c001000039000000a0010060390000130c0000013d000000400100043d00000b4e02000041000000000021043500000a9d0010009c00000a9d01008041000000400110021000000b33011001c700002a730001043000000b2d03000041000000800030043f00000aa202200197000000840020043f000000a40010043f00000b29010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b2a011001c700008005020000392a712a6c0000040f0000000100200190000025bc0000613d000000000201043b000000000100041400000aa202200197000000040020008c000014d60000c13d000000000a0000310000002000a0008c000000200a008039000014fb0000013d00000b6d0020009c00000eb20000613d00000ba50020009c00000eb20000613d000000800000043f00000b210100004100002a720001042e00000a9d0010009c00000a9d01008041000000c00110021000000b55011001c72a712a6c0000040f000000600310027000000a9d03300197000000600030008c000000600400003900000000040340190000001f0640018f000000600740019000000080057001bf000011b90000613d0000008008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000011b50000c13d000000000006004b000011c60000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000014360000613d0000001f01400039000000e00110018f0000008002100039000000400020043f000000600030008c0000006f0000413d000000e004100039000000400040043f000000800400043d000000060040008c0000006f0000213d0000000000420435000000a00200043d00000b220020009c0000006f0000213d000000a0041000390000000000240435000000c00200043d00000b220020009c0000006f0000213d000000c0011000390000000000210435000000400500043d00000024015000390000000b04000029000000000041043500000b65010000410000000000150435000900000005001d0000000401500039000000000021043500000000010004140000000a02000029000000040020008c000012690000613d000000090200002900000a9d0020009c00000a9d02008041000000400220021000000a9d0010009c00000a9d01008041000000c001100210000000000121019f00000b26011001c70000000a020000292a712a6c0000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000905700029000012060000613d000000000801034f0000000909000029000000008a08043c0000000009a90436000000000059004b000012020000c13d000000000006004b000012130000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00000001002001900000174c0000c13d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000121d0000c13d000018960000013d00000a9d0010009c00000a9d01008041000000c00110021000000b55011001c72a712a6c0000040f000000600310027000000a9d03300197000000600030008c000000600400003900000000040340190000001f0640018f000000600740019000000080057001bf000012360000613d0000008008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000012320000c13d000000000006004b000012430000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000014420000613d0000001f01400039000000e00110018f0000008002100039000000400020043f000000600030008c0000006f0000413d000000e004100039000000400040043f000000800400043d000000060040008c0000006f0000213d0000000000420435000000a00200043d00000b220020009c0000006f0000213d000000a0041000390000000000240435000000c00400043d00000b220040009c0000006f0000213d000000c0011000390000000000410435000000400500043d00000024015000390000000b04000029000000000041043500000b93010000410000000000150435000900000005001d0000000401500039000000000021043500000000010004140000000a02000029000000040020008c000017220000c13d00000020040000390000174c0000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000012720000c13d000018960000013d0000000b01000029000000000010043f0000000601000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000201100039000000000101041a000000000001004b000015110000c13d0000000b01000029000000000010043f0000000601000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000102100039000000000202041a0000000601100039000000000101041a000a00000002001d000900000001001d000000000021001a000016cd0000413d0000000b01000029000000000010043f0000000701000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a00000ba702200197000000000021041b0000000b01000029000000000010043f0000000601000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000401100039000000000201041a000000000002004b000016cd0000613d00000009040000290000000a03400029000000010220008a000000000021041b000000400200043d0000002401200039000900000003001d000000000031043500000b2d010000410000000000120435000000000100041100000aa201100197000a00000002001d0000000402200039000000000012043500000b29010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b2a011001c700008005020000392a712a6c0000040f0000000100200190000025bc0000613d000000000201043b000000000100041400000aa202200197000000040020008c00001a050000c13d0000000004000031000000200040008c000000200400803900001a2e0000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000012fc0000c13d000018960000013d00000aae0200004100000000040000190000000003040019000000000402041a000000a005300039000000000045043500000001022000390000002004300039000000000014004b000013030000413d000000c001300039000000800210008a00000080010000392a7126460000040f0000002001000039000000400200043d000b00000002001d000000000212043600000080010000392a7126650000040f0000000b02000029000000000121004900000a9d0010009c00000a9d01008041000000600110021000000a9d0020009c00000a9d020080410000004002200210000000000121019f00002a720001042e0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013260000c13d000018960000013d000000000020043f0000000101000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a00000ba7022001970000000a03000029000000000232019f000000000021041b000000400100043d000000000031043500000a9d0010009c00000a9d010080410000004001100210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000aa8011001c70000800d02000039000000030300003900000b610400004100000000050004110000000b0600002900000f1e0000013d00000a9d00b0009c00000a9d0300004100000000030b4019000000400330021000000a9d0010009c00000a9d01008041000000c001100210000000000131019f00000b2c011001c7000b0000000b001d2a712a6c0000040f0000000b0b000029000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000013760000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000013720000c13d000000000006004b000013830000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000014850000613d0000001f01400039000000600110018f0000000002b10019000000000012004b00000000010000390000000101004039000b00000002001d00000aa00020009c000000840000213d0000000100100190000000840000c13d0000000b01000029000000400010043f000000200040008c0000006f0000413d00000000010b04330000000b030000290000002402300039000000000012043500000b2d010000410000000000130435000000000100041100000aa2011001970000000402300039000000000012043500000000010004140000000a02000029000000040020008c000015d50000c13d000000200a000039000016000000013d000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000aab011001c70000800d02000039000000030300003900000aac040000412a712a670000040f00000001002001900000006f0000613d00000aaa010000410000000b02000029000000000021041b000000000100001900002a720001042e0000000b01000029000000000010043f0000000701000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000000ff00100190000016df0000c13d0000001301000039000000000201041a00000009010000290000000101100039000000000101041a000a00000002001d000900000001001d000000000012001a000016cd0000413d0000000b01000029000000000010043f0000000701000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a00000ba70220019700000001022001bf000000000021041b0000000b01000029000000000010043f0000000601000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000401100039000000000201041a000000010220003a000016cd0000613d00000009040000290000000a03400029000000000021041b000000400400043d0000004401400039000900000003001d0000000000310435000000000100041000000aa2011001970000002402400039000000000012043500000b44010000410000000000140435000000000100041100000aa201100197000a00000004001d0000000402400039000000000012043500000b29010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b2a011001c700008005020000392a712a6c0000040f0000000100200190000025bc0000613d000000000201043b000000000100041400000aa202200197000000040020008c00001aa40000c13d0000000004000031000000200040008c000000200400803900001acd0000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000143d0000c13d000018960000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000014490000c13d000018960000013d00000b23010000410000000000100443000800000003001d0000000400300443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000000001004b0000006f0000613d000000400200043d00000044012000390000000903000029000000000031043500000024012000390000000a03000029000000000031043500000b34010000410000000000120435000a00000002001d00000004012000390000000b02000029000000000021043500000000010004140000000802000029000000040020008c0000147e0000613d0000000a0200002900000a9d0020009c00000a9d02008041000000400220021000000a9d0010009c00000a9d01008041000000c001100210000000000121019f00000ab4011001c700000008020000292a712a6c0000040f000000600110027000000a9d0010019d0000000100200190000017e20000613d0000000a0100002900000aa00010009c000000840000213d0000000a01000029000000400010043f0000000102000039000009cf0000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000148c0000c13d000018960000013d00000b500100004100000000001004430000000400200443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c70000800b020000392a712a6c0000040f0000000100200190000025bc0000613d0000000b03000029000000000101043b000000000001004b000016cb0000c13d000000400100043d00000b52020000410000117c0000013d000000400300043d00000b6f01000041000000000013043500000a9d0030009c00000a9d03008041000000400130021000000b33011001c700002a73000104300000000a02000029000000000102041a000000000001004b000009760000613d0000000201200039000b00000001001d000000000201041a000900000002001d00000ba70020009c000016cd0000813d00000b4f010000410000000000100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b3b011001c70000800b020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b00000009020000290000010002200039000000000021004b000014cb0000a13d0000000a020000290000000302200039000000000202041a000000000002004b000014cf0000613d0000000b02000029000000000202041a000000000002004b0000187a0000c13d00000ba90010009c000016cd0000213d00000005011000390000000b02000029000000000012041b000000000100001900002a720001042e00000a9d0010009c00000a9d01008041000000c00110021000000b94011001c72a712a670000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0540018f000000000a040019000000200640019000000080046001bf000014eb0000613d0000008007000039000000000801034f000000008908043c0000000007970436000000000047004b000014e70000c13d000000000005004b000014f80000613d000000000661034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000000000003001f0000000100200190000015c90000613d000000800100003900000000020a0019000b0000000a001d2a7126460000040f0000000b0100002900000080021001bf00000080010000392a7126d30000040f000000000100001900002a720001042e000000000004004b00000000050000190000150a0000613d0000000a050000290000000005050433000000030640021000000baa0660027f00000baa06600167000000000565016f0000000104400210000000000445019f000016220000013d000000400100043d00000b5e020000410000117c0000013d00000b23010000410000000000100443000800000002001d0000000400200443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000000001004b0000006f0000613d000000400300043d00000024013000390000000b02000029000000000021043500000b25010000410000000000130435000000000100041000000aa202100197000b00000003001d0000000401300039000700000002001d000000000021043500000000010004140000000802000029000000040020008c000015430000613d0000000b0200002900000a9d0020009c00000a9d02008041000000400220021000000a9d0010009c00000a9d01008041000000c001100210000000000121019f00000b26011001c700000008020000292a712a670000040f000000600310027000000a9d0030019d00000001002001900000188a0000613d0000000b0100002900000aa00010009c000000840000213d0000000b01000029000000400010043f00000b2301000041000000000010044300000008010000290000000400100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000000001004b0000006f0000613d000000400300043d00000024013000390000000a02000029000000000021043500000b27010000410000000000130435000b00000003001d00000004013000390000000702000029000000000021043500000000010004140000000802000029000000040020008c000015750000613d0000000b0200002900000a9d0020009c00000a9d02008041000000400220021000000a9d0010009c00000a9d01008041000000c001100210000000000121019f00000b26011001c700000008020000292a712a670000040f000000600310027000000a9d0030019d000000010020019000001a6d0000613d0000000b0100002900000aa00010009c000000840000213d0000000b01000029000000400010043f00000b2301000041000000000010044300000008010000290000000400100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000000001004b0000006f0000613d000000400300043d00000024013000390000000902000029000000000021043500000b28010000410000000000130435000b00000003001d00000004013000390000000702000029000000000021043500000000010004140000000802000029000000040020008c000018670000613d0000000b0200002900000a9d0020009c00000a9d02008041000000400220021000000a9d0010009c00000a9d01008041000000c001100210000000000121019f00000b26011001c700000008020000292a712a670000040f000000600310027000000a9d0030019d0000000100200190000018670000c13d00000a9d033001970000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000015af0000c13d000018960000013d0000000901000029000000000001041b00000aaa01000041000000000501041a000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000aab011001c70000800d02000039000000030300003900000aac040000410000000b060000292a712a670000040f00000001002001900000006f0000613d0000000b0100002900000aaa02000041000000000012041b000000000100001900002a720001042e0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000015d00000c13d000018960000013d0000000b0200002900000a9d0020009c00000a9d02008041000000400220021000000a9d0010009c00000a9d01008041000000c001100210000000000121019f00000b26011001c70000000a020000292a712a670000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0540018f000000000a04001900000020064001900000000b04600029000015f00000613d000000000701034f0000000b08000029000000007907043c0000000008980436000000000048004b000015ec0000c13d000000000005004b000015fd0000613d000000000661034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000000000003001f0000000100200190000016d30000613d0000000b0100002900000000020a0019000a0000000a001d2a7126460000040f0000000b010000290000000a021000292a7126d30000040f000000000100001900002a720001042e00000aa5050000410000002006000039000000010870008a000000050880027000000aa60880009a0000000b0a0000290000000009a600190000000009090433000000000095041b00000020066000390000000105500039000000000085004b0000160f0000c13d000000000047004b000016200000813d0000000307400210000000f80770018f00000baa0770027f00000baa077001670000000b066000290000000006060433000000000676016f000000000065041b000000010440021000000001044001bf000001a00500043d000500000005001d000001800500043d000700000005001d000001600500043d000600000005001d000001400500043d000400000005001d000000000043041b000000400300043d00000aa304100197000027100040008c000016420000a13d000000640130003900000ab5020000410000000000210435000000440130003900000ab602000041000000000021043500000024013000390000002a02000039000000000021043500000ab301000041000000000013043500000004013000390000002002000039000000000021043500000a9d0030009c00000a9d03008041000000400130021000000ab7011001c700002a730001043000030aa20020019c000016540000c13d000000440130003900000ab202000041000000000021043500000024013000390000001902000039000000000021043500000ab301000041000000000013043500000004013000390000002002000039000000000021043500000a9d0030009c00000a9d03008041000000400130021000000ab4011001c700002a730001043000000aa70030009c000000840000213d0000004002300039000000400020043f0000002002300039000000000042043500000003050000290000000000530435000000a001100210000000000151019f0000000402000039000000000012041b000000400100043d000000000041043500000a9d0010009c00000a9d010080410000004001100210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000aa8011001c70000800d02000039000000020300003900000aa9040000412a712a670000040f00000001002001900000006f0000613d00004e20010000390000001002000039000000000012041b000000000600041100000aaa01000041000000000061041b000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000aab011001c70000800d02000039000000030300003900000aac0400004100000000050000192a712a670000040f00000001002001900000006f0000613d000000090100002900000aa201100197000000800010043f0000000b02000029000000000302043300000aa00030009c000000840000213d0000001602000039000000000502041a000000010050019000000001045002700000007f0440618f0000001f0040008c00000000060000390000000106002039000000000565013f000000010050019000000e8e0000c13d000000200040008c000016a60000413d000000000020043f0000001f05300039000000050550027000000aad0550009a000000200030008c00000aae050040410000001f04400039000000050440027000000aad0440009a000000000045004b000016a60000813d000000000005041b0000000105500039000000000045004b000016a20000413d0000001f0030008c00000020040000390000000105000039000019a60000a13d000000000020043f00000ba60830019800000aae0600004100000000070400190000000b0b000029000016bb0000613d0000002007000039000000010980008a000000050990027000000aaf0990009a000000000ab70019000000000a0a04330000000000a6041b00000020077000390000000106600039000000000096004b000016b40000c13d000000000038004b000016c50000813d0000000308300210000000f80880018f00000baa0880027f00000baa088001670000000b077000290000000007070433000000000787016f000000000076041b00000001063002100000000003050019000019b00000013d000000400100043d00000b7f020000410000117c0000013d00000bab0030009c0000171b0000a13d00000b8c01000041000000000010043f0000001101000039000000040010043f00000b2c0100004100002a73000104300000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000016da0000c13d000018960000013d000000400100043d00000b66020000410000117c0000013d0000000001000411000000000010043f0000000f01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000000ff00100190000018a90000c13d0000000901000029000000000010043f0000000101000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000000ff0010019000000d720000c13d000000400100043d000000640210003900000b88030000410000000000320435000000440210003900000b8903000041000000000032043500000024021000390000002e03000039000019060000013d0000010002300039000000090020006b000017e50000813d0000000a02000029000000000012041b000000000100001900002a720001042e000000090200002900000a9d0020009c00000a9d02008041000000400220021000000a9d0010009c00000a9d01008041000000c001100210000000000121019f00000b26011001c70000000a020000292a712a6c0000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000009057000290000173c0000613d000000000801034f0000000909000029000000008a08043c0000000009a90436000000000059004b000017380000c13d000000000006004b000017490000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00000001002001900000186e0000613d0000001f01400039000000600210018f0000000901200029000000000021004b0000000002000039000000010200403900000aa00010009c000000840000213d0000000100200190000000840000c13d000000400010043f000000200030008c0000006f0000413d00000009020000290000000003020433000000000003004b0000000002000039000000010200c039000000000023004b0000006f0000c13d000000010220018f000009cf0000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000017690000c13d000018960000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000017750000c13d000018960000013d000000400100043d000700000001001d00000aa70010009c000000840000213d00000001030003670000004401300370000000000101043b00000007040000290000004002400039000000400020043f000000010200003900000000042404360000000000140435000000400400043d00000aa70040009c000000840000213d0000006403300370000000000303043b0000004005400039000000400050043f00000020054000390000000000350435000000000024043500000007020000290000000002020433000600000002001d000000000002004b00001a7d0000613d000000000100041100050aa20010019b0000000005000019000000090400002900000007020000290000000603000029000017a00000013d0000000105500039000000000035004b00001a7a0000813d0000000001020433000000000051004b0000240f0000a13d000000000004004b0000179d0000613d0000000301000039000000000101041a00000aa2061001980000179d0000613d000a00000005001d00000b23010000410000000000100443000b00000006001d0000000400600443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000000001004b00000009040000290000006f0000613d000000400500043d0000004401500039000000080200002900000000002104350000002401500039000000000041043500000b3401000041000000000015043500000004015000390000000502000029000000000021043500000000010004140000000b02000029000000040020008c000017db0000613d00000a9d0050009c00000a9d030000410000000003054019000000400330021000000a9d0010009c00000a9d01008041000000c001100210000000000131019f00000ab4011001c7000b00000005001d2a712a6c0000040f0000000b050000290000000904000029000000600310027000000a9d0030019d000000010020019000001c7a0000613d00000aa00050009c000000840000213d000000400050043f000000070200002900000006030000290000000a050000290000179d0000013d000000400100043d0000000002000019000009cf0000013d000000400100043d00000b51020000410000117c0000013d000000000002004b0000000003000019000017ec0000613d000000a00300043d000000030420021000000baa0440027f00000baa04400167000000000443016f0000000103200210000018c50000013d0000000302000039000000000402041a000000200210003900000b6c030000410000000000320435000b00000004001d00000aa202400197000000000021043500000a9d0010009c00000a9d010080410000004001100210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000b31011001c70000800d02000039000000010300003900000b6e040000412a712a670000040f00000001002001900000006f0000613d0000000b0100002900000ab00110019700000b6c011001c70000000302000039000000000012041b00000b2301000041000000000010044300000b6c010000410000000400100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000000001004b0000006f0000613d000000400300043d00000024013000390000000102000039000000000021043500000b2501000041000000000013043500000004013000390000000002000410000000000021043500000a9d0030009c000b00000003001d00000a9d0100004100000000010340190000004001100210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000b26011001c700000b6c020000412a712a670000040f000000600310027000000a9d0030019d000000010020019000001a530000613d0000000b0100002900000aa00010009c000000840000213d0000000b01000029000000400010043f00000b2301000041000000000010044300000b6c010000410000000400100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000000001004b0000006f0000613d000000400300043d00000024013000390000000102000039000000000021043500000b2701000041000000000013043500000004013000390000000002000410000000000021043500000a9d0030009c000b00000003001d00000a9d0100004100000000010340190000004001100210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000b26011001c700000b6c020000412a712a670000040f000000600310027000000a9d0030019d000000010020019000001d280000613d0000000b0100002900000aa00010009c000000840000213d0000000b01000029000000400010043f000000000100001900002a720001042e0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000018750000c13d000018960000013d000000400100043d00000b9b020000410000117c0000013d00000a9d033001970000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000018850000c13d000018960000013d00000a9d033001970000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000018920000c13d000000000005004b000018a30000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000a9d0020009c00000a9d020080410000004002200210000000000112019f00002a7300010430000000400100043d00000b32020000410000117c0000013d00000aae030000410000002006000039000000010540008a000000050550027000000aaf0550009a000000000706001900000080066000390000000006060433000000000063041b00000020067000390000000103300039000000000053004b000018b10000c13d000000a005700039000000000024004b000018c30000813d0000000304200210000000f80440018f00000baa0440027f00000baa044001670000000005050433000000000445016f000000000043041b00000001030000390000000104200210000000000234019f000000000021041b000000000100001900002a720001042e0000000803000029000000000429034f000000000404043b000000200330003900000000004304350000002002200039000000000052004b000018ca0000413d00000008020000290000000002020433000000800300043d000000000023004b000018fd0000c13d00000aa00020009c000000840000213d00000005032002100000003f0430003900000b7b05400197000000400400043d000600000004001d0000000004450019000000000054004b0000000005000039000000010500403900000aa00040009c000000840000213d0000000100500190000000840000c13d000000400040043f00000006040000290000000002240436000500000002001d0000001f0230018f000000000003004b000018f20000613d00000005040000290000000003340019000000001501043c0000000004540436000000000034004b000018ee0000c13d000000000002004b000000800100043d000000000001004b000019d00000c13d000000400200043d000b00000002001d0000002001000039000000000212043600000006010000292a7126870000040f000013150000013d000000400100043d000000640210003900000b79030000410000000000320435000000440210003900000b7a03000041000000000032043500000024021000390000002903000039000000000032043500000ab302000041000000000021043500000004021000390000002003000039000000000032043500000a9d0010009c00000a9d01008041000000400110021000000ab7011001c700002a73000104300000000101000039000500000001001d0000000b01000029000000000010043f0000000701000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a00000ba702200197000000000021041b0000000b01000029000000000010043f000000050000006b000019690000c13d0000000601000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000201043b0000000101200039000000000101041a0000000702200039000000000202041a000000000012001a000016cd0000413d0000000001120019000000400300043d0000002402300039000000000012043500000b2d010000410000000000130435000b00000003001d00000004013000390000000602000029000000000021043500000b29010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b2a011001c700008005020000392a712a6c0000040f0000000100200190000025bc0000613d000000000201043b000000000100041400000aa202200197000000040020008c00001af10000c13d0000000003000031000000200030008c0000002004000039000000000403401900001b1a0000013d0000000801000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000a00000001001d0000000901000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000000ff0010019000001b320000c13d0000000b01000029000000000010043f0000000601000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000201043b000000000102041a0000000502200039000000000302041a000000000013004b000016cd0000213d00000baa0030009c000016cd0000613d0000000104300039000000000042041b000000000031004b00001d350000c13d0000000a010000290000000501100039000000000101041a00000b5c0010019800001d350000c13d000000400100043d00000b76020000410000117c0000013d000000000003004b0000000006000019000019ab0000613d0000000a060000290000000006060433000000030730021000000baa0770027f00000baa07700167000000000676016f0000000103300210000000000336019f000000000032041b000000080200002900000aa2022001970000001103000039000000000603041a00000ab006600197000000000226019f000000000023041b0000001702000039000000000302041a00000ab00330019700000003033001af000000000032041b00000012020000390000000503000029000000000032041b00000013020000390000000403000029000000000032041b00000014020000390000000603000029000000000032041b00000015020000390000000703000029000000000032041b000001400000044300000160001004430000010000400443000001200050044300000ab10100004100002a720001042e000000000300001900000008010000290000000001010433000000000031004b0000240f0000a13d000a00000003001d0000000503300210000000a0013000390000000001010433000b0aa20010019c000080100200003900001bec0000613d000900000003001d00000007013000290000000001010433000000000010043f000000200000043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c72a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000060200002900000000020204330000000a03000029000000000032004b0000240f0000a13d00000009040000290000000502400029000000000101043b000000000101041a00000000001204350000000103300039000000800100043d000000000013004b000019d10000413d000018f60000013d0000000a0300002900000a9d0030009c00000a9d03008041000000400330021000000a9d0010009c00000a9d01008041000000c001100210000000000131019f00000b26011001c72a712a670000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000a0570002900001a1e0000613d000000000801034f0000000a09000029000000008a08043c0000000009a90436000000000059004b00001a1a0000c13d000000000006004b00001a2b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000000010020019000001ae50000613d0000001f01400039000000600210018f0000000a01200029000000000021004b0000000002000039000000010200403900000aa00010009c000000840000213d0000000100200190000000840000c13d000000400010043f000000200040008c0000006f0000413d0000000a020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b0000006f0000c13d000000000002004b00001b300000613d0000000902000029000000000021043500000a9d0010009c00000a9d010080410000004001100210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000aa8011001c70000800d02000039000000030300003900000b5f0400004100001d6a0000013d00000a9d033001970000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001a5b0000c13d000018960000013d00000a9d033001970000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001a680000c13d000018960000013d00000a9d033001970000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001a750000c13d000018960000013d00000044010000390000000101100367000000000101043b000000000010043f000000200000043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f000000010020019000000009020000290000006f0000613d000000000101043b000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000301041a00000001010003670000006402100370000000000202043b000b00000003001d000000000023004b00001b350000813d000000400100043d000000640210003900000b8d030000410000000000320435000000440210003900000b8e0300004100001bf20000013d0000000a0300002900000a9d0030009c00000a9d03008041000000400330021000000a9d0010009c00000a9d01008041000000c001100210000000000131019f00000ab4011001c72a712a670000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000a0570002900001abd0000613d000000000801034f0000000a09000029000000008a08043c0000000009a90436000000000059004b00001ab90000c13d000000000006004b00001aca0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000000010020019000001bd40000613d0000001f01400039000000600210018f0000000a01200029000000000021004b0000000002000039000000010200403900000aa00010009c000000840000213d0000000100200190000000840000c13d000000400010043f000000200040008c0000006f0000413d0000000a020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b0000006f0000c13d000000000002004b00001d5c0000c13d00000b45020000410000117c0000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001aec0000c13d000018960000013d0000000b0300002900000a9d0030009c00000a9d03008041000000400330021000000a9d0010009c00000a9d01008041000000c001100210000000000131019f00000b26011001c72a712a670000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000b0570002900001b0a0000613d000000000801034f0000000b09000029000000008a08043c0000000009a90436000000000059004b00001b060000c13d000000000006004b00001b170000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000000010020019000001be00000613d0000001f01400039000000600210018f0000000b01200029000000000021004b0000000002000039000000010200403900000aa00010009c000000840000213d0000000100200190000000840000c13d000000400010043f000000200030008c0000006f0000413d0000000b020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b0000006f0000c13d000000000002004b00000f210000c13d00000b60020000410000117c0000013d000000400100043d00000b72020000410000117c0000013d0000004401100370000000000101043b000000000010043f000000200000043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f000000010020019000000009020000290000006f0000613d000000000101043b000000000020043f000000200010043f00000064010000390000000101100367000000000101043b000a00000001001d000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d0000000a030000290000000b02300069000000000101043b000000000021041b00000044010000390000000101100367000000000101043b000000000010043f000000200000043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000802000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d00000001030003670000006402300370000000000202043b000000000101043b000000000401041a000000000024001a000016cd0000413d0000000004240019000000000041041b0000004401300370000000000101043b000000400300043d00000020043000390000000000240435000000000013043500000a9d0030009c00000a9d030080410000004001300210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000b31011001c70000800d02000039000000040300003900000b35040000410000000005000411000000090600002900000008070000292a712a670000040f00000001002001900000006f0000613d00000b2301000041000000000010044300000008010000290000000400100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000000001004b000000090200002900000f210000613d000000400400043d0000002401400039000000000021043500000b3601000041000000000014043500000004014000390000000002000411000000000021043500000001010003670000004402100370000000000202043b000000440340003900000000002304350000006401100370000000000101043b0000008402400039000000a003000039000000000032043500000064024000390000000000120435000000a402400039000000800100043d0000000000120435000b00000004001d000000c402400039000000000001004b00001bc70000613d00000000030000190000000004230019000000a005300039000000000505043300000000005404350000002003300039000000000013004b00001bc00000413d0000000002210019000000000002043500000000020004140000000803000029000000040030008c00001ffa0000c13d00000000050004150000000d0550008a00000005055002100000000004000031000000200040008c00000020040080390000202d0000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001bdb0000c13d000018960000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001be70000c13d000018960000013d000000400100043d000000640210003900000b7c030000410000000000320435000000440210003900000b7d03000041000000000032043500000024021000390000002a03000039000019060000013d000000400100043d0000002003100039000000000500041100000000005304350000000405200370000000000505043b000000400610003900000000005604350000002405200370000000000505043b000000a0061000390000000a07000029000000000076043500000080061000390000000b07000029000000000076043500000060061000390000000000560435000000a405200370000000000505043b00000100061000390000000000460435000000e00410003900000009060000290000000000640435000000c00410003900000000005404350000010404200370000000000404043b000001200510003900000000004504350000012402200370000000000202043b000001400410003900000000002404350000014002000039000000000021043500000b460010009c000000840000213d0000016002100039000000400020043f00000a9d0030009c00000a9d030080410000004002300210000000000101043300000a9d0010009c00000a9d010080410000006001100210000000000121019f000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000aab011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000200010043f00000b3e01000041000000000010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b3f011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000400200043d000800000002001d000000000101043b000000800200043d000000400020008c00001e9e0000613d000000410020008c00001ed20000c13d000000e00200043d000000f802200270000000200020043f000000c00200043d00001ea30000013d000000000010043f0000000f01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000000ff0010019000001d6d0000c13d0000000b01000029000000000010043f0000000101000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000000ff00100190000003a70000c13d000017110000013d00000a9d033001970000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c820000c13d000018960000013d000000c00200043d000000ff032002700000001b03300039000000200030043f00000b4002200197000000600020043f000000000010043f000000a00100043d000000400010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b41011001c700000001020000392a712a6c0000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0540018f000000200640019000000001046001bf00001ca60000613d000000000701034f0000000108000039000000007907043c0000000008980436000000000048004b00001ca20000c13d000000010220018f000000000005004b00001cb40000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000000003001f0000000001020433000000600000043f0000000b02000029000000400020043f000000000003004b00001ed20000613d0000001102000039000000000202041a000000000112013f00000aa200100198000024150000c13d0000000a01000029000000000010043f0000000801000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000b00000001001d0000000a010000290000000801100270000000000010043f0000001801000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d0000000a02000029000000ff0220018f000000000101043b000000000101041a000000000121022f000000010010019000001d0a0000c13d0000000b010000290000000301100039000000000101041a000800000001001d00000b3a010000410000000000100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b3b011001c70000800b020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000080010006c00001d0a0000a13d0000000a01000029000000000010043f0000000a01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d0000000b020000290000000402200039000000000202041a000000000101043b000000000101041a000000000021004b0000241d0000a13d0000000b010000290000000101100039000000000101041a000b0009001000be00001fdc0000c13d000000400100043d00001b300000013d00000a9d033001970000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d190000c13d000018960000013d000000400100043d000000640210003900000b8a030000410000000000320435000000440210003900000b8b03000041000000000032043500000024021000390000002803000039000019060000013d00000a9d033001970000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d300000c13d000018960000013d0000000b01000029000000000010043f0000000a01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a000000010220003a000016cd0000613d000000000021041b000000400100043d000900000001001d00000b690010009c000000840000213d00000009020000290000002001200039000000400010043f0000000000020435000000400100043d0000000002000411000000000002004b00001f790000c13d000000640210003900000b74030000410000000000320435000000440210003900000b7503000041000000000032043500000024021000390000002103000039000019060000013d0000000902000029000000000021043500000a9d0010009c00000a9d010080410000004001100210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000aa8011001c70000800d02000039000000030300003900000b67040000410000000b05000029000000000600041100000f1e0000013d000000400100043d00000b45020000410000117c0000013d000000c00200043d000000ff032002700000001b03300039000000200030043f00000b4002200197000000600020043f000000000010043f000000a00100043d000000400010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b41011001c700000001020000392a712a6c0000040f0000000109000039000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0540018f000000200640019000000001046001bf00001d8f0000613d000000000701034f000000007807043c0000000009890436000000000049004b00001d8b0000c13d000000010220018f000000000005004b00001d9d0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000000003001f0000000001020433000000600000043f0000000902000029000000400020043f000000000003004b00001ed20000613d0000001102000039000000000202041a000000000112013f00000aa20010019800001e9b0000c13d0000000b01000029000000000010043f0000000801000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000900000001001d0000000501100039000000000101041a00000aa2011001970000000002000411000000000012004b00001dc30000613d00000aaa01000041000000000101041a00000aa201100197000000000012004b0000204b0000c13d00000009010000290000000301100039000000000101041a000600000001001d000000000001004b00001dd70000613d00000b3a010000410000000000100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b3b011001c70000800b020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000060010006c00000d290000213d000000080000006b0000204e0000613d0000000a010000290000000b0200002900000009030000292a71282a0000040f000000000100001900002a720001042e000000000100041100050aa20010019b0000000003000019000000060200002900001dec0000013d00000aa00040009c000000840000213d000000400040043f000000060200002900000009030000290000000103300039000000000023004b00001f080000813d000000800100043d000000000031004b0000240f0000a13d0000000b0000006b00001de90000613d0000000301000039000000000101041a00000aa20410019800001de90000613d000900000003001d00000b23010000410000000000100443000a00000004001d0000000400400443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f0000000100200190000025bc0000613d000000000101043b000000000001004b0000006f0000613d000000400400043d00000044014000390000000802000029000000000021043500000024014000390000000b02000029000000000021043500000b3401000041000000000014043500000004014000390000000502000029000000000021043500000000010004140000000a02000029000000040020008c00001de40000613d00000a9d0040009c00000a9d030000410000000003044019000000400330021000000a9d0010009c00000a9d01008041000000c001100210000000000131019f00000ab4011001c7000a00000004001d2a712a6c0000040f0000000a04000029000000600310027000000a9d0030019d000000010020019000001de40000c13d00000a9d033001970000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e2e0000c13d000018960000013d000000c00200043d000000ff032002700000001b03300039000000200030043f00000b4002200197000000600020043f000000000010043f000000a00100043d000000400010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b41011001c700000001020000392a712a6c0000040f0000000109000039000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0540018f000000200640019000000001046001bf00001e520000613d000000000701034f000000007807043c0000000009890436000000000049004b00001e4e0000c13d000000010220018f000000000005004b00001e600000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000000003001f0000000001020433000000600000043f0000000702000029000000400020043f000000000003004b00001ed20000613d0000001102000039000000000202041a000000000112013f00000aa20010019800001f050000c13d000000090000006b000021700000c13d0000001201000039000000000201041a000700000002001d000000080020002a000016cd0000413d00000b29010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b2a011001c700008005020000392a712a6c0000040f0000000100200190000025bc0000613d000000000201043b00000006010000290000000101100039000000000101041a000000400400043d00000044034000390000000000130435000000000100041000000aa2011001970000002403400039000000000013043500000b44010000410000000000140435000900000004001d00000004014000390000000a030000290000000000310435000000000100041400000aa202200197000500000002001d000000040020008c0000210e0000c13d0000000004000031000000200040008c0000002004008039000021380000013d00000b42010000410000000902000029000024170000013d000000c00200043d000000ff032002700000001b03300039000000200030043f00000b4002200197000000600020043f000000000010043f000000a00100043d000000400010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b41011001c700000001020000392a712a6c0000040f0000000109000039000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0540018f000000200640019000000001046001bf00001ebd0000613d000000000701034f000000007807043c0000000009890436000000000049004b00001eb90000c13d000000010220018f000000000005004b00001ecb0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000000003001f0000000001020433000000600000043f0000000802000029000000400020043f000000000003004b00001ed60000c13d00000b8701000041000000000010043f00000b2f0100004100002a73000104300000001102000039000000000202041a000000000112013f00000aa20010019800001f760000c13d0000000a0000006b000022240000c13d0000001701000039000000000101041a0000001502000039000000000202041a00000008040000290000004403400039000000000023043500000aa2011001970000002402400039000000000012043500000b44010000410000000000140435000000000100041100000aa2011001970000000402400039000000000012043500000b29010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b2a011001c700008005020000392a712a6c0000040f0000000100200190000025bc0000613d000000000201043b000000000100041400000aa202200197000000040020008c000021e40000c13d0000000003000031000000200030008c000000200400003900000000040340190000220d0000013d00000b42010000410000000702000029000024170000013d000000800100043d000000000001004b000003b20000613d000000000200001900000004010000290000000001010433000000000021004b0000240f0000a13d000600000002001d0000000501200210000000a002100039000000000302043300000003011000290000000001010433000900000001001d000a00000003001d000000000030043f000000200000043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000500090010007400001a9d0000413d0000000a01000029000000000010043f000000200000043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000502000029000000000021041b0000000a01000029000000000010043f000000200000043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000802000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a0000000903000029000000000032001a000016cd0000413d0000000002320019000000000021041b00000006020000290000000102200039000000800100043d000000000012004b00001f0c0000413d000003b20000013d00000b42010000410000000802000029000024170000013d00000aa70010009c000000840000213d0000004002100039000000400020043f00000020021000390000000b03000029000000000032043500000001020000390000000000210435000000400100043d00000aa70010009c000000840000213d0000004002100039000000400020043f00000020021000390000000103000039000000000032043500000000003104350000000b01000029000000000010043f000000200000043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a000000010220003a000016cd0000613d000000000021041b000000400100043d0000002002100039000000010300003900000000003204350000000b02000029000000000021043500000a9d0010009c00000a9d010080410000004001100210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000b31011001c70000800d02000039000000040300003900000b35040000410000000005000411000000000600001900000000070500192a712a670000040f00000001002001900000006f0000613d000000000100041100000000020100190000000b0300002900000009040000292a71292f0000040f0000000a010000290000000101100039000000000101041a0000001202000039000000000202041a000000400300043d00000020043000390000000000240435000000000013043500000a9d0030009c00000a9d030080410000004001300210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000b31011001c70000800d02000039000000030300003900000b730400004100001d6a0000013d0000000a01000029000000000010043f0000000b01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a0000000902200029000000000021041b0000000001000411000000000001004b000020cd0000c13d000000400100043d000000640210003900000b85030000410000000000320435000000440210003900000b8603000041000000000032043500000024021000390000002303000039000019060000013d0000001f0110003900000ba601100197000000c40110003900000a9d0010009c00000a9d0100804100000060011002100000000b0300002900000a9d0030009c00000a9d030080410000004003300210000000000131019f00000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000008020000292a712a670000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000b057000290000201a0000613d000000000801034f0000000b09000029000000008a08043c0000000009a90436000000000059004b000020160000c13d000000000006004b000020270000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00000000050004150000000c0550008a00000005055002100000000100200190000021760000613d0000001f01400039000000600110018f0000000b02100029000000000012004b0000000001000039000000010100403900000aa00020009c000000840000213d0000000100100190000000840000c13d0000000003020019000000400020043f000000200040008c0000006f0000413d0000000b01000029000000000101043300000b37001001980000006f0000c13d0000000502500270000000000201001f00000b380110019700000b360010009c00000f210000613d00000ab301000041000a00000003001d000000000013043500000004013000392a7129150000040f0000000a02000029000021db0000013d000000400100043d00000b43020000410000117c0000013d0000001201000039000000000201041a000600000002001d000000070020002a000016cd0000413d00000b29010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b2a011001c700008005020000392a712a6c0000040f0000000100200190000025bc0000613d000000000201043b00000009010000290000000101100039000000000101041a000000400400043d00000044034000390000000000130435000000000100041000000aa2011001970000002403400039000000000013043500000b44010000410000000000140435000800000004001d00000004014000390000000a030000290000000000310435000000000100041400000aa202200197000500000002001d000000040020008c000024200000c13d0000000004000031000000200040008c00000020040080390000244a0000013d0000001f0220003900000ba6022001970000000a040000290000000001410049000000000121001900000a9d0010009c00000a9d01008041000000600110021000000a9d0040009c00000a9d0200004100000000020440190000004002200210000000000121019f00000a9d0030009c00000a9d03008041000000c002300210000000000112019f00000008020000292a712a670000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000a057000290000209d0000613d000000000801034f0000000a09000029000000008a08043c0000000009a90436000000000059004b000020990000c13d000000000006004b000020aa0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000005000415000000100550008a00000005055002100000000100200190000021900000613d0000001f01400039000000600110018f0000000a02100029000000000012004b0000000001000039000000010100403900000aa00020009c000000840000213d0000000100100190000000840000c13d0000000004020019000000400020043f000000200030008c0000006f0000413d0000000a01000029000000000101043300000b37001001980000006f0000c13d0000000502500270000000000201001f00000b380110019700000b900010009c00000f210000613d00000ab301000041000b00000004001d000000000014043500000004014000392a7129150000040f000021da0000013d000000400100043d00000aa70010009c000000840000213d0000004002100039000000400020043f00000020021000390000000a03000029000000000032043500000001020000390000000000210435000000400100043d00000aa70010009c000000840000213d0000004002100039000000400020043f00000020021000390000000903000029000000000032043500000001020000390000000000210435000000400100043d00000b690010009c000000840000213d0000002002100039000000400020043f00000000000104350000000a01000029000000000010043f000000200000043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a0008000900100074000025600000813d000000400100043d000000640210003900000b83030000410000000000320435000000440210003900000b8403000041000000000032043500000024021000390000002403000039000019060000013d000000090200002900000a9d0020009c00000a9d02008041000000400220021000000a9d0010009c00000a9d01008041000000c001100210000000000121019f00000ab4011001c700000005020000292a712a670000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000905700029000021280000613d000000000801034f0000000909000029000000008a08043c0000000009a90436000000000059004b000021240000c13d000000000006004b000021350000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000022aa0000613d0000001f01400039000000600110018f0000000903100029000000000013004b00000000020000390000000102004039000400000003001d00000aa00030009c000000840000213d0000000100200190000000840000c13d0000000402000029000000400020043f000000200040008c0000006f0000413d00000009020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b0000006f0000c13d000000000002004b000024620000613d000000070300002900000008023000290000001703000039000000000303041a00000004050000290000004404500039000000000024043500000aa2023001970000002403500039000000000023043500000b4402000041000000000025043500000004025000390000000a03000029000000000032043500000000020004140000000503000029000000040030008c000024cd0000c13d000000040110002900000aa00010009c000000840000213d000000400010043f00000004020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b0000006f0000c13d000000000002004b00001ae30000613d00000000010004110000000b0200002900000006030000292a71282a0000040f000000000100001900002a720001042e000000040230008c000021d40000413d000000000400043d00000b3704400197000000000501043b00000b3805500197000000000445019f000000000040043f00000b380440019700000ab30040009c000021d40000c13d000000440030008c000021d40000413d000000040510037000000ba6062001980000001f0720018f000000400400043d0000000001640019000021a90000613d000000000805034f0000000009040019000000008a08043c0000000009a90436000000000019004b0000218b0000c13d000021a90000013d000000040230008c000021d40000413d000000000400043d00000b3704400197000000000501043b00000b3805500197000000000445019f000000000040043f000000440030008c000021d40000413d00000b380440019700000ab30040009c000021d40000c13d000000040510037000000ba6062001980000001f0720018f000000400400043d0000000001640019000021a90000613d000000000805034f0000000009040019000000008a08043c0000000009a90436000000000019004b000021a50000c13d000000000007004b000021b60000613d000000000565034f0000000306700210000000000701043300000000076701cf000000000767022f000000000505043b0000010006600089000000000565022f00000000056501cf000000000575019f0000000000510435000000000504043300000aa00050009c000021d40000213d0000002401500039000000000031004b000021d40000213d0000000001450019000000000301043300000aa00030009c000021d40000213d000000000224001900000000063100190000002006600039000000000026004b000021d40000213d00000000023500190000003f0220003900000ba6022001970000000004420019000000000024004b0000000002000039000000010200403900000aa00040009c000000840000213d0000000100200190000000840000c13d0000000003040019000000400040043f000000000001004b000025bd0000c13d000000400200043d000b00000002001d00000ab301000041000000000012043500000004012000392a7129220000040f0000000b02000029000000000121004900000a9d0010009c00000a9d01008041000000600110021000000a9d0020009c00000a9d020080410000004002200210000000000121019f00002a7300010430000000080300002900000a9d0030009c00000a9d03008041000000400330021000000a9d0010009c00000a9d01008041000000c001100210000000000131019f00000ab4011001c72a712a670000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000805700029000021fd0000613d000000000801034f0000000809000029000000008a08043c0000000009a90436000000000059004b000021f90000c13d000000000006004b0000220a0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000024650000613d0000001f01400039000000600210018f0000000801200029000000000021004b0000000002000039000000010200403900000aa00010009c000000840000213d0000000100200190000000840000c13d000000400010043f000000200030008c0000006f0000413d00000008020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b0000006f0000c13d000000000002004b00001ae30000613d000800000001001d0000001002000039000000000102041a0000000101100039000000000012041b000000080200002900000b470020009c000000840000213d00000008050000290000012002500039000000400020043f00000001020003670000000403200370000000000303043b00000000073504360000002403200370000000000303043b00000040065000390000000904000029000700000006001d0000000000460435000600000007001d0000000000370435000000e403200370000000000303043b0000006004500039000500000004001d00000000003404350000010403200370000000000303043b000000c0065000390000000b04000029000a00000006001d0000000000460435000000a0065000390000000004000411000400000006001d00000000004604350000008004500039000300000004001d00000000003404350000012402200370000000000202043b000000e003500039000900000003001d00000000002304350000010002500039000b00000002001d0000000000020435000000000010043f0000000801000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d00000008020000290000000002020433000000000101043b000000000021041b000000060200002900000000020204330000000103100039000000000023041b000000070200002900000000020204330000000203100039000000000023041b000000050200002900000000020204330000000303100039000000000023041b000000030200002900000000020204330000000403100039000000000023041b0000000402000029000000000202043300000aa2022001970000000503100039000000000403041a00000b4804400197000000000224019f0000000a040000290000000004040433000000000004004b00000b49040000410000000004006019000000000242019f000000000023041b000000090200002900000000020204330000000603100039000000000023041b00000007011000390000000b020000290000000002020433000000000021041b0000001001000039000000000501041a00000024010000390000000101100367000000000101043b000000400200043d000000000012043500000a9d0020009c00000a9d020080410000004001200210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000aa8011001c70000800d02000039000000030300003900000b4a04000041000b00000005001d00000000060004112a712a670000040f00000001002001900000006f0000613d00000001010003670000012402100370000000000202043b000000000002004b0000247d0000c13d0000001001000039000000000101041a000009b30000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000022b10000c13d000018960000013d000000080200002900000040022000390000000002020433000000ff032002700000001b03300039000000200030043f00000b4002200197000000600020043f000000000010043f00000007010000290000000001010433000000400010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b41011001c700000001020000392a712a6c0000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0540018f000000200640019000000001046001bf000022d80000613d000000000701034f0000000108000039000000007907043c0000000008980436000000000048004b000022d40000c13d000000010220018f000000000005004b000022e60000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000000003001f0000000001020433000000600000043f0000000b02000029000000400020043f000000000003004b00001ed20000613d0000001102000039000000000202041a000000000112013f00000aa200100198000024150000c13d000000800100043d000000000001004b00000f210000613d000000000200041100050aa20020019b000b00000000001d0000000a0200002900000000020204330000000b0020006c0000240f0000a13d0000000b020000290000000503200210000700000003001d00000009023000290000000002020433000000000002004b000023670000613d0000001701000039000000000101041a000000400400043d0000004403400039000000000023043500000aa2011001970000002402400039000000000012043500000b44010000410000000000140435000800000004001d00000004014000390000000502000029000000000021043500000b29010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b2a011001c700008005020000392a712a6c0000040f0000000100200190000025bc0000613d000000000201043b000000000100041400000aa202200197000000040020008c000023280000c13d0000000004000031000000200040008c0000002004008039000023500000013d000000080300002900000a9d0030009c00000a9d03008041000000400330021000000a9d0010009c00000a9d01008041000000c001100210000000000131019f00000ab4011001c72a712a670000040f000000600310027000000a9d03300197000000200030008c0000002004000039000000000403401900000020064001900000000805600029000023400000613d000000000701034f0000000808000029000000007907043c0000000008980436000000000058004b0000233c0000c13d0000001f074001900000234d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0000000100200190000025dc0000613d0000001f01400039000000600210018f0000000801200029000000000021004b0000000002000039000000010200403900000aa00010009c000000840000213d0000000100200190000000840000c13d000000400010043f000000200040008c0000006f0000413d00000008020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b0000006f0000c13d000000000002004b00001ae30000613d000000800100043d0000000b0010006c0000240f0000a13d0000000701000029000000a001100039000700000001001d0000000001010433000000000010043f0000000c01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000201041a000000010220003a000016cd0000613d000000000021041b000000800100043d0000000b0010006c0000240f0000a13d0000000001000411000000000001004b00001ff00000613d000000400100043d00000aa70010009c000000840000213d000000070200002900000000030204330000004002100039000000400020043f0000002002100039000800000003001d000000000032043500000001020000390000000000210435000000400100043d00000aa70010009c000000840000213d0000004002100039000000400020043f0000002002100039000000010300003900000000003204350000000000310435000000400100043d00000b690010009c000000840000213d0000002002100039000000400020043f00000000000104350000000801000029000000000010043f000000200000043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b000000000101041a000600000001001d000000000001004b000021040000613d0000000801000029000000000010043f000000200000043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000602000029000000010220008a000000000021041b000000400100043d0000002002100039000000010300003900000000003204350000000802000029000000000021043500000a9d0010009c00000a9d010080410000004001100210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000b31011001c70000800d02000039000000040300003900000b35040000410000000005000411000000000605001900000000070000192a712a670000040f00000001002001900000006f0000613d000000400100043d00000b690010009c000000840000213d0000002002100039000000400020043f0000000000010435000000800100043d0000000b0010006c0000240f0000a13d00000007010000290000000005010433000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000aab011001c70000800d02000039000000030300003900000b6a0400004100000000060004112a712a670000040f00000001002001900000006f0000613d0000000b02000029000b00010020003d000000800100043d0000000b0010006b000022f80000413d00000f210000013d00000b8c01000041000000000010043f0000003201000039000000040010043f00000b2c0100004100002a730001043000000b42010000410000000b02000029000000000012043500000a9d0020009c00000a9d02008041000000400120021000000b33011001c700002a7300010430000000400100043d00000b81020000410000117c0000013d000000080200002900000a9d0020009c00000a9d02008041000000400220021000000a9d0010009c00000a9d01008041000000c001100210000000000121019f00000ab4011001c700000005020000292a712a670000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000008057000290000243a0000613d000000000801034f0000000809000029000000008a08043c0000000009a90436000000000059004b000024360000c13d000000000006004b000024470000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000024710000613d0000001f01400039000000600110018f0000000803100029000000000013004b00000000020000390000000102004039000400000003001d00000aa00030009c000000840000213d0000000100200190000000840000c13d0000000402000029000000400020043f000000200040008c0000006f0000413d00000008020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b0000006f0000c13d000000000002004b000025000000c13d00000b45010000410000000402000029000024170000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000246c0000c13d000018960000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000024780000c13d000018960000013d000000400300043d000a00000003001d00000b4b0030009c000000840000213d0000001303000039000000000303041a0000001404000039000000000404041a0000000a060000290000010005600039000000400050043f00000000052604360000002401100370000000000101043b000000e002600039000900000002001d0000000000420435000000c002600039000800000002001d0000000000320435000600000005001d0000000000150435000000a001600039000700000001001d00000000000104350000008001600039000500000001001d00000000000104350000006001600039000400000001001d00000000000104350000004001600039000300000001001d00000000000104350000000b01000029000000000010043f0000000601000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d0000000a020000290000000002020433000000000101043b000000000021041b000000060200002900000000020204330000000103100039000000000023041b000000030200002900000000020204330000000203100039000000000023041b000000040200002900000000020204330000000303100039000000000023041b000000050200002900000000020204330000000403100039000000000023041b000000070200002900000000020204330000000503100039000000000023041b000000080200002900000000020204330000000603100039000000000023041b000000070110003900000009020000290000000002020433000000000021041b000022a70000013d000000040100002900000a9d0010009c00000a9d01008041000000400110021000000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000ab4011001c700000005020000292a712a670000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000405700029000024e70000613d000000000801034f0000000409000029000000008a08043c0000000009a90436000000000059004b000024e30000c13d000000000006004b000024f40000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000025210000613d0000001f01400039000000600110018f000000040110002900000aa00010009c000000840000213d000000400010043f000000200030008c000021670000813d0000006f0000013d000000060300002900000007023000290000001703000039000000000303041a00000004050000290000004404500039000000000024043500000aa2023001970000002403500039000000000023043500000b4402000041000000000025043500000004025000390000000a03000029000000000032043500000000020004140000000503000029000000040030008c0000252d0000c13d000000040110002900000aa00010009c000000840000213d000000400010043f00000004020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b0000006f0000c13d000000000002004b00001ae30000613d00001dd90000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000025280000c13d000018960000013d000000040100002900000a9d0010009c00000a9d01008041000000400110021000000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000ab4011001c700000005020000292a712a670000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000405700029000025470000613d000000000801034f0000000409000029000000008a08043c0000000009a90436000000000059004b000025430000c13d000000000006004b000025540000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000025d00000613d0000001f01400039000000600110018f000000040110002900000aa00010009c000000840000213d000000400010043f000000200030008c000025170000813d0000006f0000013d0000000a01000029000000000010043f000000200000043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f00000001002001900000006f0000613d000000000101043b0000000802000029000000000021041b000000400100043d0000002002100039000000090300002900000000003204350000000a02000029000000000021043500000a9d0010009c00000a9d010080410000004001100210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000b31011001c70000800d02000039000000040300003900000b35040000410000000005000411000000000605001900000000070000192a712a670000040f00000001002001900000006f0000613d000000400100043d00000b690010009c000000840000213d0000002002100039000000400020043f0000000000010435000000400300043d00000024013000390000000b02000029000000000021043500000b2d010000410000000000130435000000000100041100000aa201100197000800000003001d0000000402300039000000000012043500000b29010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b2a011001c700008005020000392a712a6c0000040f0000000100200190000025bc0000613d000000000201043b000000000100041400000aa202200197000000040020008c000025e80000c13d0000000004000031000000200040008c0000002004008039000026110000013d000000000001042f00000ab3020000410000000004030019000b00000003001d000000000023043500000004023000390000002003000039000000000032043500000024024000392a7126650000040f0000000b02000029000000000121004900000a9d0010009c00000a9d0100804100000a9d0020009c00000a9d0200804100000060011002100000004002200210000000000121019f00002a73000104300000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000025d70000c13d000018960000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000025e30000c13d000018960000013d000000080300002900000a9d0030009c00000a9d03008041000000400330021000000a9d0010009c00000a9d01008041000000c001100210000000000131019f00000b26011001c72a712a670000040f000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000805700029000026010000613d000000000801034f0000000809000029000000008a08043c0000000009a90436000000000059004b000025fd0000c13d000000000006004b0000260e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00000001002001900000263a0000613d0000001f01400039000000600210018f0000000801200029000000000021004b0000000002000039000000010200403900000aa00010009c000000840000213d0000000100200190000000840000c13d000000400010043f000000200040008c0000006f0000413d00000008020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b0000006f0000c13d000000000002004b00001b300000613d00000020021000390000000b0300002900000000003204350000000902000029000000000021043500000a9d0010009c00000a9d010080410000004001100210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000b31011001c70000800d02000039000000030300003900000b82040000410000000a0500002900001d6b0000013d0000001f0530018f00000a9f06300198000000400200043d0000000004620019000018960000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000026410000c13d000018960000013d0000001f0220003900000ba6022001970000000001120019000000000021004b0000000002000039000000010200403900000aa00010009c000026520000213d0000000100200190000026520000c13d000000400010043f000000000001042d00000b8c01000041000000000010043f0000004101000039000000040010043f00000b2c0100004100002a7300010430000000000003004b000026620000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000034004b0000265b0000413d00000000012300190000000000010435000000000001042d00000000430104340000000001320436000000000003004b000026710000613d000000000200001900000000051200190000000006240019000000000606043300000000006504350000002002200039000000000032004b0000266a0000413d000000000213001900000000000204350000001f0230003900000ba6022001970000000001210019000000000001042d00000020030000390000000004310436000000000302043300000000003404350000004001100039000000000003004b000026860000613d00000000040000190000002002200039000000000502043300000aa20550019700000000015104360000000104400039000000000034004b0000267f0000413d000000000001042d000000000301001900000000040104330000000001420436000000000004004b000026930000613d00000000020000190000002003300039000000000503043300000000015104360000000102200039000000000042004b0000268d0000413d000000000001042d00000024010000390000000101100367000000000101043b000000000001004b0000000002000039000000010200c039000000000021004b0000269d0000c13d000000000001042d000000000100001900002a7300010430000100000000000200010aa20010019c000026bf0000613d000000000020043f000000200000043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f0000000100200190000026bd0000613d000000000101043b0000000102000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f0000000100200190000026bd0000613d000000000101043b000000000101041a000000000001042d000000000100001900002a7300010430000000400100043d000000640210003900000b7c030000410000000000320435000000440210003900000b7d03000041000000000032043500000024021000390000002a03000039000000000032043500000ab302000041000000000021043500000004021000390000002003000039000000000032043500000a9d0010009c00000a9d01008041000000400110021000000ab7011001c700002a7300010430000000000212004900000b400020009c000026df0000213d0000001f0020008c000026df0000a13d0000000001010433000000000001004b0000000002000039000000010200c039000000000021004b000026df0000c13d000000000001042d000000000100001900002a7300010430000400000000000200000aaa02000041000000000202041a00000aa2032001970000000002000411000000000032004b000027790000c13d00000b23020000410000000000200443000200000001001d0000000400100443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f00000001002001900000277c0000613d0000000102000039000000020300002900000aa205300197000000000101043b000000000001004b000200000005001d000027550000613d000000400b00043d00000b6d0100004100000000001b04350000000401b0003900000000000104350000000001000414000000040050008c0000270c0000c13d0000000001000415000000040110008a00000005011002100000000003000031000000200030008c000000200400003900000000040340190000273d0000013d00000a9d00b0009c00000a9d0200004100000000020b4019000000400220021000000a9d0010009c00000a9d01008041000000c001100210000000000121019f00000b2c011001c7000000000205001900010000000b001d2a712a6c0000040f000000010b000029000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000027280000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000027240000c13d000000000006004b000027350000613d000000000171034f0000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f0000000000150435000000000003001f0000000001000415000000030110008a0000000501100210000000010020019000000002050000290000000102000039000027550000613d0000001f02400039000000600420018f0000000002b40019000000000042004b0000000004000039000000010400403900000aa00020009c000027840000213d0000000100400190000027840000c13d000000400020043f0000001f0030008c000027770000a13d00000000020b0433000000000002004b0000000003000039000000010300c039000000000032004b000027770000c13d0000000501100270000000000102001f000000000002004b00000000020000390000000102006039000000400100043d000000000005004b0000275a0000613d00000001002001900000277d0000c13d0000000302000039000000000302041a00000020021000390000000000520435000100000003001d00000aa202300197000000000021043500000a9d0010009c00000a9d010080410000004001100210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000b31011001c70000800d02000039000000010300003900000b6e040000412a712a670000040f00000002030000290000000100200190000027770000613d000000010100002900000ab001100197000000000131019f0000000302000039000000000012041b000000000001042d000000000100001900002a7300010430000000400100043d00000b43020000410000277e0000013d000000000001042f00000b6f02000041000000000021043500000a9d0010009c00000a9d01008041000000400110021000000b33011001c700002a730001043000000b8c01000041000000000010043f0000004101000039000000040010043f00000b2c0100004100002a73000104300006000000000002000500000002001d000600000001001d000000000010043f0000000601000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f0000000100200190000028180000613d000000400400043d00000bac0040009c0000281a0000813d000000000101043b0000010002400039000000400020043f000000000201041a00000000022404360000000103100039000000000303041a00000000003204350000000202100039000000000202041a000000400340003900000000002304350000000302100039000000000202041a0000006003400039000400000003001d00000000002304350000000402100039000000000202041a0000008003400039000100000003001d00000000002304350000000502100039000000000202041a000000a003400039000200000003001d00000000002304350000000602100039000000000202041a000000c0034000390000000000230435000300000004001d000000e0024000390000000701100039000000000101041a00000000001204350000000601000029000000000010043f0000000701000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f0000000100200190000028180000613d000000000101043b000000050200002900000aa202200197000600000002001d000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f0000000100200190000028180000613d000000000101043b000000000101041a000000ff00100190000028140000613d00000004010000290000000002010433000000000002004b000028140000613d0000000301000029000000000301043300000002010000290000000001010433000000000031004b0000000001000019000028150000813d00000001010000290000000001010433000000000031004b000028160000a13d000400000001001d000500000003001d000000400100043d00000040031000390000000604000029000000000043043500000040030000390000000003310436000000000023043500000b710010009c0000281a0000213d0000006002100039000000400020043f00000a9d0030009c00000a9d030080410000004002300210000000000101043300000a9d0010009c00000a9d010080410000006001100210000000000121019f000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000aab011001c700008010020000392a712a6c0000040f0000000100200190000028180000613d000000000101043b00000004101000fa000000050010006c00000000010000390000000101004039000000000001042d0000000001000019000000000001042d0000000101000039000000000001042d000000000100001900002a730001043000000b8c01000041000000000010043f0000004101000039000000040010043f00000b2c0100004100002a730001043000000aaa01000041000000000101041a0000000002000411000000000012004b000028260000c13d000000000001042d00000ba001000041000000000010043f00000b2f0100004100002a73000104300005000000000002000400000003001d000200000001001d000500000002001d000000000020043f0000000901000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f0000000100200190000028e90000613d000000000101043b000000000101041a000000ff00100190000028f70000c13d0000000601000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f0000000100200190000028e90000613d00000004030000290000000602300039000000000202041a000000000101043b0000000401100039000000000101041a000000000112004b0000000001004019000000000203041a000000000021001a000028eb0000413d000000000121001900000004020000290000000702200039000000000302041a000000000013004b000028eb0000213d00000baa0030009c000028eb0000613d0000000104300039000000000042041b000000000031004b000028650000c13d00000004010000290000000501100039000000000101041a00000b5c00100198000028fa0000613d0000000501000029000000000010043f0000000a01000039000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f0000000100200190000028e90000613d000000000101043b000000000201041a000000010220003a000028eb0000613d000000000021041b000000400400043d00000bad0040009c000028f10000813d0000002001400039000000400010043f0000000000040435000000400100043d000000020200002900030aa20020019c000029020000613d00000aa70010009c000028f10000213d0000004002100039000000400020043f00000020021000390000000503000029000000000032043500000001030000390000000000310435000000400100043d00000aa70010009c000028f10000213d000100000004001d0000004002100039000000400020043f0000002002100039000000000032043500000000003104350000000501000029000000000010043f000000200000043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f0000000100200190000028e90000613d000000000101043b0000000302000029000000000020043f000000200010043f000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b31011001c700008010020000392a712a6c0000040f0000000100200190000028e90000613d000000000101043b000000000201041a000000010220003a000028eb0000613d000000000021041b000000400100043d0000002002100039000000010300003900000000003204350000000502000029000000000021043500000a9d0010009c00000a9d010080410000004001100210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000b31011001c70000800d020000390000000403000039000000000500041100000b3504000041000000000600001900000003070000292a712a670000040f0000000100200190000028e90000613d00000000010004110000000202000029000000050300002900000001040000292a71292f0000040f00000004010000290000000101100039000000000101041a0000001202000039000000000202041a000000400300043d00000020043000390000000000240435000000000013043500000a9d0030009c00000a9d030080410000004001300210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000b31011001c70000800d02000039000000030300003900000b7304000041000000050500002900000003060000292a712a670000040f0000000100200190000028e90000613d000000000001042d000000000100001900002a730001043000000b8c01000041000000000010043f0000001101000039000000040010043f00000b2c0100004100002a730001043000000b8c01000041000000000010043f0000004101000039000000040010043f00000b2c0100004100002a7300010430000000400100043d00000b7202000041000028fc0000013d000000400100043d00000b7602000041000000000021043500000a9d0010009c00000a9d01008041000000400110021000000b33011001c700002a7300010430000000640210003900000b74030000410000000000320435000000440210003900000b7503000041000000000032043500000024021000390000002103000039000000000032043500000ab302000041000000000021043500000004021000390000002003000039000000000032043500000a9d0010009c00000a9d01008041000000400110021000000ab7011001c700002a7300010430000000600210003900000bae030000410000000000320435000000400210003900000baf030000410000000000320435000000200210003900000028030000390000000000320435000000200200003900000000002104350000008001100039000000000001042d000000600210003900000bb0030000410000000000320435000000400210003900000bb1030000410000000000320435000000200210003900000034030000390000000000320435000000200200003900000000002104350000008001100039000000000001042d0006000000000002000300000004001d000100000003001d000200000001001d00000b23010000410000000000100443000400000002001d0000000400200443000000000100041400000a9d0010009c00000a9d01008041000000c00110021000000b24011001c700008002020000392a712a6c0000040f0000000100200190000029bf0000613d000000000101043b000000000001004b000029bc0000613d000000400b00043d0000008401b00039000000a00200003900000000002104350000006401b00039000000010200003900000000002104350000004401b000390000000102000029000000000021043500000b360100004100000000001b0435000000020100002900000aa2011001970000000402b0003900000000001204350000002401b000390000000000010435000000a403b00039000000030100002900000000210104340000000000130435000000c403b00039000000000001004b000029640000613d000000000400001900000000053400190000000006420019000000000606043300000000006504350000002004400039000000000014004b0000295d0000413d000000000231001900000000000204350000000003000414000000040200002900000aa202200197000000040020008c000029730000c13d0000000005000415000000060550008a00000005055002100000000003000031000000200030008c00000020040000390000000004034019000029a70000013d0000001f0110003900000ba601100197000000c40110003900000a9d0010009c00000a9d01008041000000600110021000000a9d00b0009c00000a9d0400004100000000040b40190000004004400210000000000141019f00000a9d0030009c00000a9d03008041000000c003300210000000000113019f00040000000b001d2a712a670000040f000000040b000029000000600310027000000a9d03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000029940000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000029900000c13d000000000006004b000029a10000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000005000415000000050550008a00000005055002100000000100200190000029c60000613d0000001f01400039000000600110018f0000000004b10019000000000014004b0000000001000039000000010100403900000aa00040009c00002a2d0000213d000000010010019000002a2d0000c13d000000400040043f0000001f0030008c000029bd0000a13d00000000010b043300000b3700100198000029bd0000c13d0000000502500270000000000201001f00000b380110019700000b360010009c000029c00000c13d000000000001042d000000000100001900002a7300010430000000000001042f00000ab30100004100000000001404350000000401400039000400000004001d2a7129150000040f00002a010000013d000000040230008c000029fb0000413d000000000400043d00000b3704400197000000000501043b00000b3805500197000000000445019f000000000040043f000000440030008c000029fb0000413d00000b380440019700000ab30040009c000029fb0000c13d000000040510037000000ba6062001980000001f0720018f000000400400043d0000000001640019000029df0000613d000000000805034f0000000009040019000000008a08043c0000000009a90436000000000019004b000029db0000c13d000000000007004b000029ec0000613d000000000565034f0000000306700210000000000701043300000000076701cf000000000767022f000000000505043b0000010006600089000000000565022f00000000056501cf000000000575019f0000000000510435000000000504043300000aa00050009c000029fb0000213d0000002401500039000000000031004b000029fb0000213d0000000001450019000000000301043300000aa00030009c000029fb0000213d000000000224001900000000063100190000002006600039000000000026004b00002a0b0000a13d000000400200043d000400000002001d00000ab301000041000000000012043500000004012000392a7129220000040f0000000402000029000000000121004900000a9d0010009c00000a9d01008041000000600110021000000a9d0020009c00000a9d020080410000004002200210000000000121019f00002a730001043000000000023500190000003f0220003900000ba6022001970000000004420019000000000024004b0000000002000039000000010200403900000aa00040009c00002a2d0000213d000000010020019000002a2d0000c13d0000000003040019000000400040043f000000000001004b000029fb0000613d00000ab3020000410000000004030019000400000003001d000000000023043500000004023000390000002003000039000000000032043500000024024000392a7126650000040f0000000402000029000000000121004900000a9d0010009c00000a9d0100804100000a9d0020009c00000a9d0200804100000060011002100000004002200210000000000121019f00002a730001043000000b8c01000041000000000010043f0000004101000039000000040010043f00000b2c0100004100002a7300010430000000000001042f00000a9d0010009c00000a9d01008041000000400110021000000a9d0020009c00000a9d020080410000006002200210000000000112019f000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000aab011001c700008010020000392a712a6c0000040f000000010020019000002a470000613d000000000101043b000000000001042d000000000100001900002a730001043000000000050100190000000000200443000000050030008c00002a570000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b00002a4f0000413d00000a9d0030009c00000a9d030080410000006001300210000000000200041400000a9d0020009c00000a9d02008041000000c002200210000000000112019f00000bb2011001c700000000020500192a712a6c0000040f000000010020019000002a660000613d000000000101043b000000000001042d000000000001042f00002a6a002104210000000102000039000000000001042d0000000002000019000000000001042d00002a6f002104230000000102000039000000000001042d0000000002000019000000000001042d00002a710000043200002a720001042e00002a730001043000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000000000000000000000000000ffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000ffffffffffffffffffffffffbfa87805ed57dc1f0d489ce33be4c4577d74ccde357eeeee058a32c55c44a532405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acebfa87805ed57dc1f0d489ce33be4c4577d74ccde357eeeee058a32c55c44a531000000000000000000000000000000000000000000000000ffffffffffffffbf02000000000000000000000000000000000000200000000000000000000000008a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76efffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392702000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e027cceb82823caa45ba60387709961a73050623da2232f8fd178296384aedbd77d833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428927cceb82823caa45ba60387709961a73050623da2232f8fd178296384aedbd76ffffffffffffffffffffffff00000000000000000000000000000000000000000000000200000000000000000000000000000080000001000000000000000000455243323938313a20696e76616c69642072656365697665720000000000000008c379a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000640000000000000000000000002073616c65507269636500000000000000000000000000000000000000000000455243323938313a20726f79616c7479206665652077696c6c206578636565640000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000000000000000000000007d5c3ff000000000000000000000000000000000000000000000000000000000b4b5b48e00000000000000000000000000000000000000000000000000000000def25aca00000000000000000000000000000000000000000000000000000000f242432900000000000000000000000000000000000000000000000000000000fa914ed400000000000000000000000000000000000000000000000000000000fa914ed500000000000000000000000000000000000000000000000000000000fd762d9200000000000000000000000000000000000000000000000000000000fee81cf400000000000000000000000000000000000000000000000000000000f242432a00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000e985e9c400000000000000000000000000000000000000000000000000000000e985e9c500000000000000000000000000000000000000000000000000000000eefdc1df00000000000000000000000000000000000000000000000000000000f04e283e00000000000000000000000000000000000000000000000000000000def25acb00000000000000000000000000000000000000000000000000000000e74b981b00000000000000000000000000000000000000000000000000000000d007af5b00000000000000000000000000000000000000000000000000000000d8d07ed900000000000000000000000000000000000000000000000000000000d8d07eda00000000000000000000000000000000000000000000000000000000ddca3f4300000000000000000000000000000000000000000000000000000000ddf0b00900000000000000000000000000000000000000000000000000000000d007af5c00000000000000000000000000000000000000000000000000000000d4f4ddaa00000000000000000000000000000000000000000000000000000000c0bc62f600000000000000000000000000000000000000000000000000000000c0bc62f700000000000000000000000000000000000000000000000000000000c6af66b900000000000000000000000000000000000000000000000000000000b4b5b48f00000000000000000000000000000000000000000000000000000000be537f430000000000000000000000000000000000000000000000000000000091eb290d000000000000000000000000000000000000000000000000000000009d7f4ebe00000000000000000000000000000000000000000000000000000000a9fc664d00000000000000000000000000000000000000000000000000000000a9fc664e00000000000000000000000000000000000000000000000000000000ae796ab300000000000000000000000000000000000000000000000000000000b2db919b000000000000000000000000000000000000000000000000000000009d7f4ebf00000000000000000000000000000000000000000000000000000000a22cb465000000000000000000000000000000000000000000000000000000009694941f0000000000000000000000000000000000000000000000000000000096949420000000000000000000000000000000000000000000000000000000009d645a440000000000000000000000000000000000000000000000000000000091eb290e0000000000000000000000000000000000000000000000000000000095d89b4100000000000000000000000000000000000000000000000000000000809a619d0000000000000000000000000000000000000000000000000000000089a302700000000000000000000000000000000000000000000000000000000089a30271000000000000000000000000000000000000000000000000000000008d1d9520000000000000000000000000000000000000000000000000000000008da5cb5b00000000000000000000000000000000000000000000000000000000809a619e0000000000000000000000000000000000000000000000000000000083e096ce000000000000000000000000000000000000000000000000000000007f58b4be000000000000000000000000000000000000000000000000000000007f58b4bf000000000000000000000000000000000000000000000000000000007f631e47000000000000000000000000000000000000000000000000000000007d5c3ff1000000000000000000000000000000000000000000000000000000007ecebe00000000000000000000000000000000000000000000000000000000002e8da828000000000000000000000000000000000000000000000000000000005d4c1d45000000000000000000000000000000000000000000000000000000006c0360ea000000000000000000000000000000000000000000000000000000006c3b8698000000000000000000000000000000000000000000000000000000006c3b8699000000000000000000000000000000000000000000000000000000006e85a0d900000000000000000000000000000000000000000000000000000000715018a6000000000000000000000000000000000000000000000000000000006c0360eb000000000000000000000000000000000000000000000000000000006c19e783000000000000000000000000000000000000000000000000000000006291484800000000000000000000000000000000000000000000000000000000629148490000000000000000000000000000000000000000000000000000000069fe0e2d000000000000000000000000000000000000000000000000000000005d4c1d46000000000000000000000000000000000000000000000000000000006134716200000000000000000000000000000000000000000000000000000000495c8bf80000000000000000000000000000000000000000000000000000000054d1f13c0000000000000000000000000000000000000000000000000000000054d1f13d000000000000000000000000000000000000000000000000000000005b7633d0000000000000000000000000000000000000000000000000000000005beaa04900000000000000000000000000000000000000000000000000000000495c8bf9000000000000000000000000000000000000000000000000000000004e1273f4000000000000000000000000000000000000000000000000000000002fc47b23000000000000000000000000000000000000000000000000000000002fc47b240000000000000000000000000000000000000000000000000000000042d96dd7000000000000000000000000000000000000000000000000000000002e8da829000000000000000000000000000000000000000000000000000000002eb2c2d6000000000000000000000000000000000000000000000000000000000e89341b000000000000000000000000000000000000000000000000000000001c33b32700000000000000000000000000000000000000000000000000000000256929610000000000000000000000000000000000000000000000000000000025692962000000000000000000000000000000000000000000000000000000002a55205a000000000000000000000000000000000000000000000000000000002e1a7d4d000000000000000000000000000000000000000000000000000000001c33b328000000000000000000000000000000000000000000000000000000001ed74928000000000000000000000000000000000000000000000000000000001647795d000000000000000000000000000000000000000000000000000000001647795e000000000000000000000000000000000000000000000000000000001b25b077000000000000000000000000000000000000000000000000000000000e89341c000000000000000000000000000000000000000000000000000000000fa7b7b30000000000000000000000000000000000000000000000000000000002fe53040000000000000000000000000000000000000000000000000000000006fdde020000000000000000000000000000000000000000000000000000000006fdde0300000000000000000000000000000000000000000000000000000000098144d4000000000000000000000000000000000000000000000000000000000dce83c70000000000000000000000000000000000000000000000000000000002fe53050000000000000000000000000000000000000000000000000000000004845e3e000000000000000000000000000000000000000000000000000000000146354500000000000000000000000000000000000000000000000000000000014635460000000000000000000000000000000000000000000000000000000001ffc9a700000000000000000000000000000000000000000000000000000000009a9b7b0000000000000000000000000000000000000000000000000000000000fdd58e00000000000000000000000000000000000000000000000000000000389a75e100000000000000000000000000000000000000200000008000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffff1806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b830200000200000000000000000000000000000024000000000000000000000000da0194c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000000000000000000000002304aa02000000000000000000000000000000000000000000000000000000008d74431400000000000000000000000000000000000000000000000000000000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e020000020000000000000000000000000000004400000000000000000000000070a08231000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000a9059cbb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007448fbae00000000000000000000000000000000000000040000001c0000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7f02000000000000000000000000000000000000400000000000000000000000008ee600cb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000285fb8c800000000000000000000000000000000000000000000000000000000c3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62f23a6e610000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000c0000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d955391320200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000006f5e8818000000000000000000000000000000000000000000000000ffffffffffffff3f0000000019457468657265756d205369676e6564204d6573736167653a0a3332020000000000000000000000000000000000003c0000000400000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000800000000000000000000000008baa579f000000000000000000000000000000000000000000000000000000002d0a346e0000000000000000000000000000000000000000000000000000000023b872dd00000000000000000000000000000000000000000000000000000000f499da2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffe9f000000000000000000000000000000000000000000000000fffffffffffffedfffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000d8e6d657f706eb987a687ae78b967b4b1cf806551ebeb3a85471d9b8cf6c04a0000000000000000000000000000000000000000000000000fffffffffffffeff0000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000010000000080000000000000000048b6e6df0000000000000000000000000000000000000000000000000000000042cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd180b41246c05cbb406f874e82aa2faf7db11bba9792fe09929e56ef1eee2c2da3c212ef7d00000000000000000000000000000000000000000000000000000000feea0d9900000000000000000000000000000000000000000000000000000000bd8c6ccc00000000000000000000000000000000000000000000000000000000b955455200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000080000000000000000017e94a6c000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02f34bba70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000008000000000000000000000000000000000000000000000000000000024000000e0000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000000000000000000000000000000001200000008000000000000000007820c10a00000000000000000000000000000000000000000000000000000000321aa27e9c5c4ca98453ba7da9a1af4aa7bfed3bab5098e02fee58ce3cafe6b7cbe4e8c30000000000000000000000000000000000000000000000000000000017307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31455243313135353a2073657474696e6720617070726f76616c2073746174757320666f722073656c66000000000000000000000000000000000000000000000000000000000000000000000000000000000000840000008000000000000000009445f53000000000000000000000000000000000000000000000000000000000f91d7f9b00000000000000000000000000000000000000000000000000000000ad3d6587006c45fb2f92060267e172188795374f8f5bdf4187d50c571cce287fc19c461c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdfecb0813fff72f72d5c424535fe69f97316a856e5cd5830226c189a4a8662e2c10bd8a3eb000000000000000000000000000000000000000000000000000000000000000000000000000000000000721c310194ccfc01e523fc93c9cccfa2a0ac01ffc9a700000000000000000000000000000000000000000000000000000000cc5dc080ff977b3c3a211fa63ab74f90f658f5ba9d3236e92c8f59570f442aac32483afb0000000000000000000000000000000000000000000000000000000039ffc7ba00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff9f48c460c80000000000000000000000000000000000000000000000000000000081fd5f457056a8b19e623dc52551a385bfcafd0914d3942446ecab71d19b123b7300000000000000000000000000000000000000000000000000000000000000455243313135353a206d696e7420746f20746865207a65726f20616464726573d76288d70000000000000000000000000000000000000000000000000000000038685a6b00000000000000000000000000000000000000000000000000000000fa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92206d69736d617463680000000000000000000000000000000000000000000000455243313135353a206163636f756e747320616e6420696473206c656e67746800000000000000000000000000000000000000000000003fffffffffffffffe0616c6964206f776e657200000000000000000000000000000000000000000000455243313135353a2061646472657373207a65726f206973206e6f74206120763fe5df9900000000000000000000000000000000000000000000000000000000756688fe00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff5fbf7c9c2f00000000000000000000000000000000000000000000000000000000ed7318a9455ec161085222a6e508a46debace6235bba0202c768d3840f809c85616e636500000000000000000000000000000000000000000000000000000000455243313135353a206275726e20616d6f756e7420657863656564732062616c6573730000000000000000000000000000000000000000000000000000000000455243313135353a206275726e2066726f6d20746865207a65726f2061646472000000000000000000000000000000000000000000000000000000008baa579f6572206f7220617070726f766564000000000000000000000000000000000000455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e6d69736d61746368000000000000000000000000000000000000000000000000455243313135353a2069647320616e6420616d6f756e7473206c656e677468204e487b710000000000000000000000000000000000000000000000000000000072207472616e7366657200000000000000000000000000000000000000000000455243313135353a20696e73756666696369656e742062616c616e636520666f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fbbc197c81000000000000000000000000000000000000000000000000000000006472657373000000000000000000000000000000000000000000000000000000455243313135353a207472616e7366657220746f20746865207a65726f206164d72dde5e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000008000000000000000000000000000000000000000000000000000000040000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d00dbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff30000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002b8acba10000000000000000000000000000000000000000000000000000000075e52f4f000000000000000000000000000000000000000000000000000000004b092bc80000000000000000000000000000000000000000000000000000000044594c49000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000082b429002a552059ffffffffffffffffffffffffffffffffffffffffffffffffffffffff2a55205a00000000000000000000000000000000000000000000000000000000d9b67a260000000000000000000000000000000000000000000000000000000086455d28000000000000000000000000000000000000000000000000000000000e89341c00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffafffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeff000000000000000000000000000000000000000000000000ffffffffffffff00000000000000000000000000000000000000000000000000ffffffffffffffe06420746f6b656e73000000000000000000000000000000000000000000000000455243313135353a204552433131353552656365697665722072656a65637465526563656976657220696d706c656d656e746572000000000000000000000000455243313135353a207472616e7366657220746f206e6f6e2d45524331313535020000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c1ea34ac063c3b51a63ded922d891ac1ec1d9e60e214c8042373480243bb40c
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000012000000000000000000000000075bf8f439d205b8ee0de9d3622342eb05985859b0000000000000000000000002f2a13462f6d4af64954ee84641d265932849b640000000000000000000000002f2a13462f6d4af64954ee84641d265932849b6400000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000001e8480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4b4000000000000000000000000000000000000000000000000000000000001e8480000000000000000000000000000000000000000000000000000000000000002068747470733a2f2f7777772e64796c692e696f2f6170692f6d65746164617461
-----Decoded View---------------
Arg [0] : _baseURI (string): https://www.dyli.io/api/metadata
Arg [1] : usdc_ (address): 0x75Bf8F439d205B8eE0DE9d3622342eb05985859B
Arg [2] : signerAddress_ (address): 0x2f2A13462f6d4aF64954ee84641D265932849b64
Arg [3] : feeRecipient_ (address): 0x2f2A13462f6d4aF64954ee84641D265932849b64
Arg [4] : royaltyFeeNumerator_ (uint96): 500
Arg [5] : initialQueueFee (uint256): 2000000
Arg [6] : initialLoseQueueRefund (uint256): 0
Arg [7] : initialCreateFee (uint256): 5000000
Arg [8] : initialFee (uint256): 2000000
-----Encoded View---------------
11 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000120
Arg [1] : 00000000000000000000000075bf8f439d205b8ee0de9d3622342eb05985859b
Arg [2] : 0000000000000000000000002f2a13462f6d4af64954ee84641d265932849b64
Arg [3] : 0000000000000000000000002f2a13462f6d4af64954ee84641d265932849b64
Arg [4] : 00000000000000000000000000000000000000000000000000000000000001f4
Arg [5] : 00000000000000000000000000000000000000000000000000000000001e8480
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [7] : 00000000000000000000000000000000000000000000000000000000004c4b40
Arg [8] : 00000000000000000000000000000000000000000000000000000000001e8480
Arg [9] : 0000000000000000000000000000000000000000000000000000000000000020
Arg [10] : 68747470733a2f2f7777772e64796c692e696f2f6170692f6d65746164617461
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.