Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
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 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 = 0; /// @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; } /** * @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); } /** * @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); } /** * @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; } queue[tokenId].claimed++; TokenData storage data = tokenData[tokenId]; _mintToken(msg.sender, tokenId, data); } /** * @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 + reserved, price, startTimestamp, endTimestamp, minMint, creator, _isOE, reserved ); 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 data Token data structure for the specified tokenId. */ function _mintToken( address user, uint256 tokenId, TokenData storage data ) internal { if (tokenDisabled[tokenId]) revert TokenMintingDisabled(); if (!data.isOE && totalMinted[tokenId] >= data.nonReserved) { 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; } /** * --------------------------------------------- * TESTNET FUNCTIONS * --------------------------------------------- * @dev These functions are intended for use only * on testnets and will be removed in production. * --------------------------------------------- */ /** * @notice Testnet-only function to create a drop by the owner. * @dev This function will be removed before deployment to mainnet. * @param nonReserved Maximum number of tokens available for public minting, excluding reserved tokens. * @param price Price per token. * @param _isOE Indicates if the drop is open edition. * @param startTimestamp Start time of the sale. * @param endTimestamp End time of the sale. * @param minMint Minimum number of tokens to mint. * @param reserved Number of reserved tokens. * @return Token ID of the created drop. */ function ownerCreateDrop( uint256 nonReserved, uint256 price, bool _isOE, uint256 startTimestamp, uint256 endTimestamp, uint256 minMint, uint256 reserved ) public onlyOwner returns (uint256) { return _createDrop( msg.sender, nonReserved, price, _isOE, startTimestamp, endTimestamp, minMint, reserved ); } /** * @notice Testnet-only function to refund tokens by the owner. * @dev This function will be removed before deployment to mainnet. * @param tokenId ID of the token to refund. * @param recipient Address of the recipient receiving the refund. * @param amount Amount of tokens to refund. */ function ownerRefund( uint256 tokenId, address recipient, uint256 amount ) public onlyOwner { if (balanceOf(recipient, tokenId) < amount) revert InsufficientTokensToRefund(); TokenData memory data = tokenData[tokenId]; uint256 refundAmount = data.price * amount; unchecked { totalRefunded[tokenId] += amount; } _burn(recipient, tokenId, amount); emit TokenRefunded(tokenId, recipient, amount, refundAmount); } /** * @notice Testnet-only function to mint tokens by the owner. * @dev This function will be removed before deployment to mainnet. * @param tokenId ID of the token to mint. * @param recipient Address of the recipient receiving the tokens. * @param amount Amount of tokens to mint. */ function ownerMintToken( uint256 tokenId, address recipient, uint256 amount ) public onlyOwner { TokenData memory data = tokenData[tokenId]; totalMinted[tokenId] += amount; _mint(recipient, tokenId, amount, ""); emit TokenMinted(tokenId, recipient, data.price, fee); } /** * @notice Testnet-only function to redeem tokens by the owner. * @dev This function will be removed before deployment to mainnet. * @param tokenId ID of the token to redeem. * @param recipient Address of the recipient redeeming the tokens. * @param amount Amount of tokens to redeem. */ function ownerRedeem( uint256 tokenId, address recipient, uint256 amount ) public onlyOwner { if (balanceOf(recipient, tokenId) < amount) revert InsufficientTokensToRedeem(); totalRedeemed[tokenId] += amount; _burn(recipient, tokenId, amount); emit TokenRedeemed(tokenId, recipient); } }
// 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 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 (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 {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.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; /// @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 "../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 "@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 // 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/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 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 // 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 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 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 (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 // 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 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 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 // 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.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) (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 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 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 "../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 (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 // 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 // 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; 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":"uint256","name":"nonReserved","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bool","name":"_isOE","type":"bool"},{"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":"ownerCreateDrop","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ownerMintToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ownerRedeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ownerRefund","outputs":[],"stateMutability":"nonpayable","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"}],"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
9c4d535b000000000000000000000000000000000000000000000000000000000000000001000c4521ec41c69734d524e42a20a71c9af92c8b1e9684ed0fc24b89e5209900000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000012000000000000000000000000075bf8f439d205b8ee0de9d3622342eb05985859b0000000000000000000000002f2a13462f6d4af64954ee84641d265932849b640000000000000000000000002f2a13462f6d4af64954ee84641d265932849b6400000000000000000000000000000000000000000000000000000000000001f400000000000000000000000000000000000000000000000000000000001e8480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004c4b4000000000000000000000000000000000000000000000000000000000001e8480000000000000000000000000000000000000000000000000000000000000002068747470733a2f2f7777772e64796c692e696f2f6170692f6d65746164617461
Deployed Bytecode
0x00020000000000020013000000000002000000000801034f0001000000010355000000600110027000000b28031001970000000100200190000000330000c13d0000008001000039000000400010043f000000040030008c000000540000413d000000000138034f000000000208043b000000e00220027000000b430020009c0000006f0000a13d00000b440020009c000000b30000a13d00000b450020009c000000f40000213d00000b530020009c000002a90000213d00000b5a0020009c000006570000a13d00000b5b0020009c00000c860000613d00000b5c0020009c0000080e0000613d00000b5d0020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b00000b3502000041000000000202041a0000000003000411000000000023004b00000ddd0000c13d0000001302000039000000000202041a000000000021004b000010e00000a13d00000be201000041000000800010043f00000be30100004100002c9d00010430000000a002000039000000400020043f0000000001000416000000000001004b000000540000c13d0000001f0130003900000b2901100197000000a001100039000000400010043f0000001f0430018f00000b2a05300198000000a001500039000000450000613d000000000608034f000000006706043c0000000002720436000000000012004b000000410000c13d000000000004004b000000520000613d000000000258034f0000000304400210000000000501043300000000054501cf000000000545022f000000000202043b0000010004400089000000000242022f00000000024201cf000000000252019f0000000000210435000001200030008c000000560000813d000000000100001900002c9d00010430000000a00200043d00000b2b0020009c000000540000213d0000001f01200039000000000031004b000000000400001900000b2c0400804100000b2c01100197000000000001004b000000000500001900000b2c0500404100000b2c0010009c000000000504c019000000000005004b000000540000c13d000000a001200039000000000101043300000b2b0010009c0000012d0000a13d00000c1401000041000000000010043f0000004101000039000000040010043f00000bbb0100004100002c9d0001043000000b7a0020009c000000db0000213d00000b950020009c000001ae0000a13d00000b960020009c000002ee0000213d00000b9d0020009c000006be0000a13d00000b9e0020009c00000d200000613d00000b9f0020009c000009bf0000613d00000ba00020009c000000540000c13d000000640030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000002401800370000000000101043b000b00000001001d00000b2d0010009c000000540000213d0000004401800370000000000401043b0000000401800370000000000301043b00000b3501000041000000000101041a0000000002000411000000000012004b00000ddd0000c13d0000000b0000006b00000d350000613d000a00000004001d000900000003001d000000000030043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a0000000a0010006c000018180000813d000000400100043d00000c2002000041000011f50000013d00000b600020009c000001870000a13d00000b610020009c000001fe0000213d00000b680020009c000004be0000a13d00000b690020009c0000077e0000613d00000b6a0020009c000006f60000613d00000b6b0020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000b00000001001d000000000010043f0000000801000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000201043b0000000601200039000000000101041a000000000001004b000010cb0000c13d000000400100043d00000c2602000041000011f50000013d00000b7b0020009c000001ef0000a13d00000b7c0020009c000003370000213d00000b830020009c000006cc0000a13d00000b840020009c00000d410000613d00000b850020009c000009d30000613d00000b860020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d2c9b28f40000040f00000004010000390000000101100367000000000101043b0000001502000039000000000012041b000000000100001900002c9c0001042e00000b460020009c000002d70000213d00000b4d0020009c000006830000a13d00000b4e0020009c00000caa0000613d00000b4f0020009c0000081e0000613d00000b500020009c000000540000c13d000000240030008c000000540000413d0000000401800370000000000101043b000b00000001001d00000b2d0010009c000000540000213d00000b3501000041000000000101041a0000000002000411000000000012004b00000ddd0000c13d00000baf010000410000000c0010043f0000000b01000029000000000010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc8011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000900000001001d000000000101041a000a00000001001d00000bc9010000410000000000100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bca011001c70000800b020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b0000000a0010006c000016620000a13d00000bcb01000041000000000010043f00000bbe0100004100002c9d000104300000001f0410003900000c30044001970000003f0440003900000c3004400197000000400500043d0000000004450019000b00000005001d000000000054004b0000000005000039000000010500403900000b2b0040009c000000690000213d0000000100500190000000690000c13d000000a003300039000000400040043f0000000b040000290000000004140436000a00000004001d000000c0022000390000000004210019000000000034004b000000540000213d000000000001004b0000000a060000290000014f0000613d000000000300001900000000043600190000000005230019000000000505043300000000005404350000002003300039000000000013004b000001480000413d0000000b0110002900000020011000390000000000010435000000c00100043d000900000001001d00000b2d0010009c000000540000213d000000e00100043d000800000001001d00000b2d0010009c000000540000213d000001000200043d00000b2d0020009c000000540000213d000001200100043d00000b2e0010009c000000540000213d0000000b03000029000000000403043300000b2b0040009c000000690000213d0000000203000039000000000503041a000000010650019000000001055002700000007f0550618f0000001f0050008c00000000070000390000000107002039000000000076004b000010470000c13d000000200050008c0000017f0000413d000000000030043f0000001f06400039000000050660027000000b2f0660009a000000200040008c00000b30060040410000001f05500039000000050550027000000b2f0550009a000000000056004b0000017f0000813d000000000006041b0000000106600039000000000056004b0000017b0000413d0000001f0040008c000016530000a13d000000000030043f00000c3007400198000017570000c13d000000200600003900000b3005000041000017640000013d00000b6e0020009c000003490000a13d00000b6f0020009c000004820000a13d00000b700020009c000007240000613d00000b710020009c0000070a0000613d00000b720020009c000000540000c13d000000440030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000b00000001001d2c9b275a0000040f000a00000001001d2c9b28f40000040f0000001801000039000000200010043f0000000b010000290000000801100270000000000010043f000000400200003900000000010000192c9b2c5e0000040f0000000b02000029000000ff0220018f0000000a0000006b0000000003000039000000010300c03900000000032301cf00000c31022002df000000000401041a000000000224016f00000d740000013d00000ba30020009c000003590000a13d00000ba40020009c0000062c0000a13d00000ba50020009c000006f60000613d00000ba60020009c000007610000613d00000ba70020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000000000010043f0000000801000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000b00000001001d0000000601000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000a00000001001d0000000b010000290000000201100039000000000101041a000b00000001001d00000bc9010000410000000000100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bca011001c70000800b020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b0000000b0010006c000015840000813d000000400100043d00000c2702000041000011f50000013d00000b890020009c0000036c0000a13d00000b8a0020009c0000063f0000a13d00000b8b0020009c00000a9d0000613d00000b8c0020009c000007660000613d00000b8d0020009c000000540000c13d0000000001000416000000000001004b000000540000c13d000000110100003900000c6b0000013d00000b620020009c0000061e0000a13d00000b630020009c000007ed0000613d00000b640020009c000007180000613d00000b650020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000b00000001001d000000000010043f0000000701000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a000000ff00100190000010720000613d0000000b01000029000000000010043f0000000601000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000201100039000000000101041a000000000001004b0000165f0000c13d0000000b01000029000000000010043f0000000601000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000102100039000000000202041a0000000601100039000000000101041a000a00000002001d000900000001001d000000000021001a0000189c0000413d0000000b01000029000000000010043f0000000701000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a00000c3202200197000000000021041b0000000b01000029000000000010043f0000000601000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000401100039000000000201041a000000000002004b0000189c0000613d00000009040000290000000a03400029000000010220008a000000000021041b000000400200043d0000002401200039000900000003001d000000000031043500000bbc010000410000000000120435000000000100041100000b2d01100197000a00000002001d0000000402200039000000000012043500000bb8010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb9011001c700008005020000392c9b2c960000040f0000000100200190000025ba0000613d000000000201043b000000000100041400000b2d02200197000000040020008c00001c2b0000c13d0000000004000031000000200040008c000000200400803900001c540000013d00000b540020009c000006940000a13d00000b550020009c00000ccb0000613d00000b560020009c000008ff0000613d00000b570020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000000000010043f0000000601000039000000200010043f000000400200003900000000010000192c9b2c5e0000040f0000000702100039000000000202041a0000000603100039000000000303041a0000000504100039000000000404041a0000000405100039000000000505041a0000000306100039000000000606041a0000000207100039000000000707041a0000000108100039000000000808041a000000000101041a000000800010043f000000a00080043f000000c00070043f000000e00060043f000001000050043f000001200040043f000001400030043f000001600020043f00000bd70100004100002c9c0001042e00000b470020009c000006a70000a13d00000b480020009c00000cfa0000613d00000b490020009c000009040000613d00000b4a0020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b00000b2d0010009c000000540000213d00000baf020000410000000c0020043f000000000010043f0000000c0100003900000020020000390000075c0000013d00000b970020009c000006d10000a13d00000b980020009c00000d600000613d00000b990020009c000009f50000613d00000b9a0020009c000000540000c13d000000440030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000000000010043f0000000501000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000400200043d000b00000002001d00000b320020009c000000690000213d000000000101043b0000000b040000290000004002400039000000400020043f000000000101041a0000002003400039000000a002100270000000000023043500000b2d011001980000000000140435000003260000c13d000000400100043d000b00000001001d00000b320010009c000000690000213d0000000b040000290000004001400039000000400010043f0000000401000039000000000101041a0000002003400039000000a002100270000000000023043500000b2d01100197000000000014043500000024010000390000000101100367000000000101043b2c9b27990000040f0000000b020000290000000002020433000027100110011a000000400300043d0000002004300039000000000014043500000b2d01200197000000000013043500000b280030009c00000b2803008041000000400130021000000c1d011001c700002c9c0001042e00000b7d0020009c000006dc0000a13d00000b7e0020009c00000d650000613d00000b7f0020009c00000a210000613d00000b800020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000000000010043f0000000c01000039000007590000013d00000b750020009c0000038d0000213d00000b780020009c000007390000613d00000b790020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000000000010043f00000009010000390000063b0000013d00000baa0020009c0000049e0000213d00000bad0020009c00000af80000613d00000bae0020009c000000540000c13d000000440030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b00000b2d0010009c000000540000213d0000002402800370000000000202043b2c9b27650000040f00000d590000013d00000b900020009c000004b50000213d00000b930020009c00000afd0000613d00000b940020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000b00000001001d00000b2d0010009c000000540000213d0000000301000039000000000101041a00000b2d0210019800000c7e0000613d00000bde01000041000000800010043f0000000001000410000000840010043f0000000001000414000000040020008c000a00000002001d000012c50000c13d0000000003000031000000600030008c00000060040000390000000004034019000012e90000013d00000b760020009c0000074e0000613d00000b770020009c000000540000c13d000000a40030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000b00000001001d0000002401800370000000000201043b00000b2b0020009c000000540000213d0000002301200039000000000031004b000000540000813d0000000404200039000000000148034f000000000101043b00000b2b0010009c000000690000213d0000001f0610003900000c30066001970000003f0660003900000c300660019700000bbf0060009c000000690000213d00000024022000390000008006600039000000400060043f000000800010043f0000000002210019000000000032004b000000540000213d000000000908034f0000002002400039000000000328034f00000c30041001980000001f0510018f000000a002400039000003bf0000613d000000a006000039000000000703034f000000007807043c0000000006860436000000000026004b000003bb0000c13d000000000005004b000003cc0000613d000000000343034f0000000304500210000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000320435000000a00110003900000000000104350000004401900370000000000101043b000a00000001001d0000006401900370000000000201043b000000000002004b0000000001000039000000010100c039000900000002001d000000000012004b000000540000c13d0000008401900370000000000101043b000800000001001d0000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000a02000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a000000ff00100190000018150000c13d0000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000a02000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a00000c320220019700000001022001bf000000000021041b0000000001000411000000000010043f0000000d01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a000000010220003a0000189c0000613d000000000021041b0000000b01000029000000000010043f0000000801000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000600000001001d0000000301100039000000000101041a000700000001001d000000000001004b00001df70000c13d000000400100043d000000a0021000390000000803000029000000000032043500000080021000390000000903000029000000000032043500000060021000390000000a03000029000000000032043500000040021000390000000b030000290000000000320435000000a0020000390000000002210436000000000300041100000b2d03300197000a00000003001d000000000032043500000bcc0010009c000000690000213d000000c003100039000000400030043f00000b280020009c00000b28020080410000004002200210000000000101043300000b280010009c00000b28010080410000006001100210000000000121019f000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000b36011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000200010043f00000bcd01000041000000000010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bce011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000400200043d000700000002001d000000000101043b000000800200043d000000400020008c000020a60000613d000000410020008c00001f140000c13d000000e00200043d000000f802200270000000200020043f000000c00200043d000020ab0000013d00000b730020009c00000a840000613d00000b740020009c000000540000c13d000000440030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000b00000001001d00000b2d0010009c000000540000213d2c9b275a0000040f000a00000001001d2c9b28f40000040f0000000b01000029000000000010043f0000000f01000039000000200010043f000000400200003900000000010000192c9b2c5e0000040f000000000301041a00000c32023001970000000a0300002900000a980000013d00000bab0020009c00000b0f0000613d00000bac0020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000201043b00000bc600200198000000540000c13d000000010100003900000c2b0020009c000012be0000a13d00000c2c0020009c00000eb50000613d00000c2d0020009c00000eb50000613d00000c2e0020009c00000eb50000613d000012c20000013d00000b910020009c00000b160000613d00000b920020009c000000540000c13d0000000001000416000000000001004b000000540000c13d00000014010000390000075d0000013d00000b6c0020009c00000c670000613d00000b6d0020009c000000540000c13d000000840030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b00000b2b0010009c000000540000213d0000002302100039000000000032004b000000540000813d0000000402100039000000000228034f000000000402043b00000b2b0040009c000000690000213d00000005024002100000003f0520003900000be10550019700000bbf0050009c000000690000213d0000008005500039000000400050043f000000800040043f00000024011000390000000002120019000000000032004b000000540000213d000000000708034f000000000608034f000000000004004b000004eb0000613d0000008004000039000000000516034f000000000505043b000000200440003900000000005404350000002001100039000000000021004b000004e40000413d0000002401600370000000000101043b000b00000001001d0000004401600370000000000101043b00000b2b0010009c000000540000213d0000002302100039000000000032004b000000000400001900000b2c0400804100000b2c02200197000000000002004b000000000500001900000b2c0500404100000b2c0020009c000000000504c019000000000005004b000000540000c13d0000000402100039000000000226034f000000000202043b00000b2b0020009c000000690000213d00000005042002100000003f0540003900000be105500197000000400600043d0000000005560019000a00000006001d000000000065004b0000000006000039000000010600403900000b2b0050009c000000690000213d0000000100600190000000690000c13d000000400050043f0000000a050000290000000005250436000900000005001d00000024011000390000000004140019000000000034004b000000540000213d000000000607034f000000000002004b000005230000613d0000000a02000029000000000516034f000000000505043b000000200220003900000000005204350000002001100039000000000041004b0000051c0000413d0000006401600370000000000201043b00000b2b0020009c000000540000213d0000002301200039000000000031004b000000000400001900000b2c0400804100000b2c01100197000000000001004b000000000500001900000b2c0500404100000b2c0010009c000000000504c019000000000005004b000000540000c13d0000000404200039000000000146034f000000000101043b00000b2b0010009c000000690000213d0000001f0510003900000c30055001970000003f0550003900000c3005500197000000400600043d0000000005560019000800000006001d000000000065004b0000000006000039000000010600403900000b2b0050009c000000690000213d0000000100600190000000690000c13d0000002402200039000000400050043f00000008050000290000000005150436000700000005001d0000000002210019000000000032004b000000540000213d0000002002400039000000000327034f00000c30041001980000001f0510018f00000007024000290000055a0000613d000000000603034f0000000707000029000000006806043c0000000007870436000000000027004b000005560000c13d000000000005004b000005670000613d000000000343034f0000000304500210000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000320435000000070110002900000000000104350000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a000000ff00100190000018150000c13d0000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a00000c320220019700000001022001bf000000000021041b0000000001000411000000000010043f0000000d01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a000000010220003a0000189c0000613d000000000021041b000000400100043d000000400210003900000080040000390000000000420435000000200210003900000000030004110000000000320435000000a003100039000000800500043d0000000000530435000000c003100039000000000005004b000005cc0000613d00000000060000190000002004400039000000000704043300000000037304360000000106600039000000000056004b000005c60000413d00000060041000390000000b0500002900000000005404350000000004130049000000200440008a000000800510003900000000004504350000000a0400002900000000040404330000000003430436000000000004004b000005e00000613d00000000050000190000000a060000290000002006600039000000000706043300000000037304360000000105500039000000000045004b000005da0000413d0000000003130049000000200430008a00000000004104350000001f0330003900000c30043001970000000003140019000000000043004b0000000004000039000000010400403900000b2b0030009c000000690000213d0000000100400190000000690000c13d000000400030043f00000b280020009c00000b28020080410000004002200210000000000101043300000b280010009c00000b28010080410000006001100210000000000121019f000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000b36011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000200010043f00000bcd01000041000000000010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bce011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000400200043d000b00000002001d000000000101043b00000008020000290000000002020433000000400020008c000024610000613d000000410020008c00001f140000c13d000000080300002900000060023000390000000002020433000000f802200270000000200020043f00000040023000390000000002020433000024680000013d00000b660020009c00000c700000613d00000b670020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000000000010043f0000000a01000039000007590000013d00000ba80020009c00000d780000613d00000ba90020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b00000b2d0010009c000000540000213d000000000010043f0000000f01000039000000200010043f0000004002000039000000000100001900000cc30000013d00000b8e0020009c00000de10000613d00000b8f0020009c000000540000c13d0000000002000416000000000002004b000000540000c13d0000000302000039000000000202041a00000b2d0220019800000fc90000613d00000bde03000041000000800030043f0000000003000410000000840030043f0000000003000414000000040020008c000b00000002001d000010e40000c13d0000000003000031000000600030008c00000060040000390000000004034019000011080000013d00000b5e0020009c00000eb00000613d00000b5f0020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000000000010043f0000000801000039000000200010043f000000400200003900000000010000192c9b2c5e0000040f0000000602100039000000000202041a0000000503100039000000000303041a0000000404100039000000000404041a0000000305100039000000000505041a0000000206100039000000000606041a0000000107100039000000000707041a000000000101041a000000800010043f000000a00070043f000000c00060043f000000e00050043f000001000040043f00000b2d01300197000001200010043f00000be6003001980000000001000039000000010100c039000001400010043f000001600020043f00000bd70100004100002c9c0001042e00000b510020009c00000eb80000613d00000b520020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000b00000001001d00000b2d0010009c000000540000213d2c9b28f40000040f000000170100003900000d710000013d00000b580020009c00000fc20000613d00000b590020009c000000540000c13d000000440030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000002401800370000000000101043b000b00000001001d00000b2d0010009c000000540000213d0000000401800370000000000101043b000000000010043f000000070100003900000cba0000013d00000b4b0020009c00000fd10000613d00000b4c0020009c000000540000c13d000000240030008c000000540000413d0000000401800370000000000101043b000b00000001001d00000b2d0010009c000000540000213d00000b3501000041000000000101041a0000000005000411000000000015004b00000ddd0000c13d0000000b06000029000000000006004b0000137e0000c13d00000bbd01000041000000000010043f00000bbe0100004100002c9d0001043000000ba10020009c000010230000613d00000ba20020009c000000540000c13d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000000000010043f0000000b01000039000007590000013d00000b870020009c0000104d0000613d00000b880020009c000006d50000613d000000540000013d00000b9b0020009c000010750000613d00000b9c0020009c000000540000c13d0000000001000416000000000001004b000000540000c13d0000000101000039000000800010043f00000bb00100004100002c9c0001042e00000b810020009c000010900000613d00000b820020009c000000540000c13d0000000001000416000000000001004b000000540000c13d0000001603000039000000000203041a000000010420019000000001012002700000007f0110618f0000001f0010008c00000000050000390000000105002039000000000552013f0000000100500190000010470000c13d000000800010043f000000000004004b0000118b0000613d000000000030043f000000000001004b0000138e0000c13d000000a001000039000013990000013d0000000001000416000000000001004b000000540000c13d000000c001000039000000400010043f0000000401000039000000800010043f00000c2801000041000000a00010043f0000002001000039000000c00010043f0000008001000039000000e0020000392c9b27200000040f000000c00110008a00000b280010009c00000b2801008041000000600110021000000c29011001c700002c9c0001042e0000000001000416000000000001004b000000540000c13d0000000001000412001100000001001d001000000000003d000080050100003900000044030000390000000004000415000000110440008a000000050440021000000bb8020000412c9b2c730000040f00000c6c0000013d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b00000b2d0010009c000000540000213d2c9b27b50000040f000000000100001900002c9c0001042e000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b00000b3502000041000000000202041a0000000003000411000000000023004b00000ddd0000c13d0000001302000039000000000012041b0000001402000039000000000302041a000000000013004b00000a1f0000a13d000000000012041b000000000100001900002c9c0001042e00000b3501000041000000000101041a0000000005000411000000000015004b00000ddd0000c13d000000000100041400000b280010009c00000b2801008041000000c00110021000000b36011001c70000800d02000039000000030300003900000b370400004100000000060000192c9b2c910000040f0000000100200190000000540000613d00000b3501000041000000000001041b000000000100001900002c9c0001042e000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b00000b2d0010009c000000540000213d000000000010043f0000000d01000039000000200010043f000000400200003900000000010000192c9b2c5e0000040f000000000101041a000000800010043f00000bb00100004100002c9c0001042e0000000001000416000000000001004b000000540000c13d000000030100003900000c6b0000013d00000baf010000410000000c0010043f0000000001000411000000000010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc8011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000001041b000000000100041400000b280010009c00000b2801008041000000c00110021000000b36011001c70000800d02000039000000020300003900000c040400004100000a1b0000013d000000640030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000002401800370000000000101043b000b00000001001d00000b2d0010009c000000540000213d0000004401800370000000000401043b0000000401800370000000000201043b00000b3501000041000000000101041a0000000003000411000000000013004b00000ddd0000c13d000900000004001d000a00000002001d000000000020043f0000000801000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000400200043d00000bf20020009c000000690000213d000000000101043b0000010003200039000000400030043f000000000301041a00000000043204360000000103100039000000000303041a000800000004001d00000000003404350000000203100039000000000303041a000000400420003900000000003404350000000303100039000000000303041a000000600420003900000000003404350000000403100039000000000303041a000000800420003900000000003404350000000503100039000000000303041a000000a00420003900000b2d05300197000000000054043500000be6003001980000000003000039000000010300c039000000c0042000390000000000340435000000e0022000390000000601100039000000000101041a00000000001204350000000a01000029000000000010043f0000000a01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a000000090020002a0000189c0000413d0000000902200029000000000021041b000000400100043d000700000001001d00000bf30010009c000000690000213d00000007020000290000002001200039000600000001001d000000400010043f0000000000020435000000400100043d0000000b0000006b000018b10000c13d000000640210003900000bf5030000410000000000320435000000440210003900000bf60300004100000000003204350000002402100039000000210300003900001b470000013d000000440030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000b00000001001d00000b2d0010009c000000540000213d0000002401800370000000000201043b000000000002004b0000000001000039000000010100c039000a00000002001d000000000012004b000000540000c13d00000000020004110000000b0020006c000013420000c13d00000b3e01000041000000800010043f0000002001000039000000840010043f0000002901000039000000a40010043f00000beb01000041000000c40010043f00000bec01000041000000e40010043f00000bed0100004100002c9d00010430000000440030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000002401800370000000000201043b00000b2d0020009c000000540000213d0000000401800370000000000101043b2c9b285e0000040f000000000001004b0000000001000039000000010100c03900000d590000013d000000c40030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000b00000001001d0000002401800370000000000201043b00000b2b0020009c000000540000213d0000002301200039000000000031004b000000540000813d0000000404200039000000000148034f000000000101043b00000b2b0010009c000000690000213d0000001f0610003900000c30066001970000003f0660003900000c300660019700000bbf0060009c000000690000213d00000024022000390000008006600039000000400060043f000000800010043f0000000002210019000000000032004b000000540000213d000000000908034f0000002002400039000000000328034f00000c30041001980000001f0510018f000000a0024000390000084c0000613d000000a006000039000000000703034f000000007807043c0000000006860436000000000026004b000008480000c13d000000000005004b000008590000613d000000000343034f0000000304500210000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000320435000000a00110003900000000000104350000004401900370000000000101043b000a00000001001d00000b2d0010009c000000540000213d0000006401900370000000000101043b000900000001001d0000008401900370000000000201043b000000000002004b0000000001000039000000010100c039000800000002001d000000000012004b000000540000c13d000000a401900370000000000101043b000700000001001d0000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000902000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a000000ff00100190000018150000c13d0000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000902000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a00000c320220019700000001022001bf000000000021041b0000000001000411000000000010043f0000000d01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a000000010220003a0000189c0000613d000000000021041b000000400100043d000000a0021000390000000703000029000000000032043500000080021000390000000803000029000000000032043500000060021000390000000903000029000000000032043500000040021000390000000b030000290000000000320435000000a0020000390000000002210436000000000300041100000b2d03300197000000000032043500000bcc0010009c000000690000213d000000c003100039000000400030043f00000b280020009c00000b28020080410000004002200210000000000101043300000b280010009c00000b28010080410000006001100210000000000121019f000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000b36011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000200010043f00000bcd01000041000000000010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bce011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000400200043d000900000002001d000000000101043b000000800200043d000000400020008c00001ffd0000613d000000410020008c00001f140000c13d000000e00200043d000000f802200270000000200020043f000000c00200043d000020020000013d0000000001000416000000000001004b000000540000c13d00000012010000390000075d0000013d000000840030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000b00000001001d00000b2d0010009c000000540000213d0000002401800370000000000101043b000a00000001001d000000060010008c000000540000213d0000004401800370000000000101043b000900000001001d00000bb10010009c000000540000213d0000006401800370000000000101043b000800000001001d00000bb10010009c000000540000213d00000b3501000041000000000101041a00000b2d011001970000000002000411000000000012004b0000109d0000c13d0000000b010000292c9b27b50000040f00000bb20100004100000000001004430000000b010000290000000400100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000000001004b000000540000613d000000400300043d00000024013000390000000a02000029000000000021043500000bb4010000410000000000130435000000000100041000000b2d02100197000a00000003001d0000000401300039000700000002001d000000000021043500000000010004140000000b02000029000000040020008c000009540000613d0000000a0200002900000b280020009c00000b2802008041000000400220021000000b280010009c00000b2801008041000000c001100210000000000121019f00000bb5011001c70000000b020000292c9b2c910000040f000000600310027000000b280030019d000000010020019000001abe0000613d0000000a0100002900000b2b0010009c000000690000213d0000000a01000029000000400010043f00000bb20100004100000000001004430000000b010000290000000400100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000000001004b000000540000613d000000400300043d00000024013000390000000902000029000000000021043500000bb6010000410000000000130435000a00000003001d00000004013000390000000702000029000000000021043500000000010004140000000b02000029000000040020008c000009860000613d0000000a0200002900000b280020009c00000b2802008041000000400220021000000b280010009c00000b2801008041000000c001100210000000000121019f00000bb5011001c70000000b020000292c9b2c910000040f000000600310027000000b280030019d000000010020019000001c860000613d0000000a0100002900000b2b0010009c000000690000213d0000000a01000029000000400010043f00000bb20100004100000000001004430000000b010000290000000400100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000000001004b000000540000613d000000400300043d00000024013000390000000802000029000000000021043500000bb7010000410000000000130435000a00000003001d00000004013000390000000702000029000000000021043500000000010004140000000b02000029000000040020008c000009b80000613d0000000a0200002900000b280020009c00000b2802008041000000400220021000000b280010009c00000b2801008041000000c001100210000000000121019f00000bb5011001c70000000b020000292c9b2c910000040f000000600310027000000b280030019d000000010020019000001f6e0000613d0000000a0100002900000b2b0010009c000000690000213d0000000a01000029000000400010043f000000000100001900002c9c0001042e000000440030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b00000b2d0010009c000000540000213d000000000010043f0000000e01000039000000200010043f00000040020000390000000001000019000b0000000803532c9b2c5e0000040f0000000b0200035f0000002402200370000000000202043b00000cbf0000013d000000640030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000b00000001001d000000060010008c000000540000213d0000002401800370000000000101043b000a00000001001d00000bb10010009c000000540000213d0000004401800370000000000101043b000900000001001d00000bb10010009c000000540000213d00000b3501000041000000000101041a00000b2d011001970000000002000411000000000012004b0000109d0000c13d0000000301000039000000000101041a00000b2d02100198000016770000c13d00000c0101000041000000800010043f00000be30100004100002c9d0001043000000baf010000410000000c0010043f0000000001000411000000000010043f00000bc9010000410000000000100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bca011001c70000800b020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000b00000001001d000000000100041400000b280010009c00000b2801008041000000c00110021000000bc8011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000b0200002900000c1e0220009a000000000021041b000000000100041400000b280010009c00000b2801008041000000c00110021000000b36011001c70000800d02000039000000020300003900000c1f0400004100000000050004112c9b2c910000040f0000000100200190000000540000613d000000000100001900002c9c0001042e0000000001000416000000000001004b000000540000c13d00000b3501000041000000000101041a00000b2d011001970000000002000411000000000012004b0000109d0000c13d00000bb201000041000000000010044300000bfd010000410000000400100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000025ba0000613d000000400300043d000000000101043b000000000001004b000015af0000613d00000bfe0100004100000000001304350000000401300039000000000001043500000b280030009c00000b280100004100000000010340190000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000bbb011001c700000bfd02000041000b00000003001d2c9b2c960000040f0000000b0b000029000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900000a5c0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00000a580000c13d000000000006004b00000a690000613d000000000171034f0000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f0000000000150435000000000003001f0000000100200190000015ae0000613d0000001f01400039000000600210018f0000000001b20019000000000021004b0000000002000039000000010200403900000b2b0010009c000000690000213d0000000100200190000000690000c13d000000400010043f000000200030008c000000540000413d0000000b020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b000000540000c13d000000000002004b00001a230000c13d0000000003010019000015af0000013d000000440030008c000000540000413d0000000001000416000000000001004b000000540000c13d2c9b275a0000040f000b00000001001d2c9b28f40000040f00000004010000390000000101100367000000000101043b000000000010043f0000000901000039000000200010043f000000400200003900000000010000192c9b2c5e0000040f000000000301041a00000c32023001970000000b03000029000000000003004b000000010220c1bf000000000021041b000000000100001900002c9c0001042e000000440030008c000000540000413d0000000002000416000000000002004b000000540000c13d0000000402800370000000000202043b00000b2b0020009c000000540000213d0000002304200039000000000034004b000000540000813d0000000404200039000000000448034f000000000504043b00000b2b0050009c000000690000213d00000005045002100000003f0640003900000be10660019700000bbf0060009c000000690000213d0000008006600039000000400060043f000000800050043f00000024022000390000000004240019000000000034004b000000540000213d000000000908034f000000000708034f000000000005004b00000ac70000613d000000a005000039000000000627034f000000000606043b00000b2d0060009c000000540000213d00000000056504360000002002200039000000000042004b00000abf0000413d0000002402700370000000000202043b00000b2b0020009c000000540000213d0000002304200039000000000034004b000000000500001900000b2c0500404100000b2c04400197000000000004004b000000000600001900000b2c0600204100000b2c0040009c000000000605c019000000000006004b000000540000613d0000000404200039000000000447034f000000000404043b00000b2b0040009c000000690000213d00000005054002100000003f0650003900000be106600197000000400700043d0000000006670019000800000007001d000000000076004b0000000007000039000000010700403900000b2b0060009c000000690000213d0000000100700190000000690000c13d000000400060043f00000008060000290000000006460436000700000006001d00000024022000390000000005250019000000000035004b000000540000213d000000000004004b00001b0a0000c13d000000800200043d000000000002004b000000000200001900001b190000613d00001b3e0000013d0000000001000416000000000001004b000000540000c13d00000010010000390000075d0000013d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b00000b3502000041000000000302041a0000000002000411000000000032004b00000ddd0000c13d000000000001004b000011ca0000c13d00000bd401000041000000800010043f00000be30100004100002c9d000104300000000001000416000000000001004b000000540000c13d00000bfd01000041000000800010043f00000bb00100004100002c9c0001042e000000a40030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b00000b2d0010009c000000540000213d0000002402800370000000000202043b000700000002001d00000b2d0020009c000000540000213d0000004402800370000000000202043b00000b2b0020009c000000540000213d0000002304200039000000000034004b000000540000813d0000000404200039000000000448034f000000000504043b00000b2b0050009c000000690000213d00000005045002100000003f0640003900000be10660019700000bbf0060009c000000690000213d0000008006600039000000400060043f000000800050043f00000024022000390000000004240019000000000034004b000000540000213d000000000908034f000000000708034f000000000005004b00000b480000613d0000008005000039000000000627034f000000000606043b000000200550003900000000006504350000002002200039000000000042004b00000b410000413d0000006402700370000000000202043b00000b2b0020009c000000540000213d0000002304200039000000000034004b000000000500001900000b2c0500804100000b2c04400197000000000004004b000000000600001900000b2c0600404100000b2c0040009c000000000605c019000000000006004b000000540000c13d0000000404200039000000000447034f000000000404043b00000b2b0040009c000000690000213d00000005054002100000003f0650003900000be106600197000000400700043d0000000006670019000400000007001d000000000076004b0000000007000039000000010700403900000b2b0060009c000000690000213d0000000100700190000000690000c13d000000400060043f00000004060000290000000006460436000300000006001d00000024022000390000000005250019000000000035004b000000540000213d000000000709034f000000000004004b00000b7d0000613d0000000404000029000000000627034f000000000606043b000000200440003900000000006404350000002002200039000000000052004b00000b760000413d0000008402700370000000000402043b00000b2b0040009c000000540000213d0000002302400039000000000032004b000000000500001900000b2c0500804100000b2c02200197000000000002004b000000000600001900000b2c0600404100000b2c0020009c000000000605c019000000000006004b000000540000c13d0000000405400039000000000257034f000000000202043b00000b2b0020009c000000690000213d0000001f0620003900000c30066001970000003f0660003900000c3006600197000000400700043d0000000006670019000200000007001d000000000076004b0000000007000039000000010700403900000b2b0060009c000000690000213d0000000100700190000000690000c13d0000002404400039000000400060043f00000002060000290000000006260436000100000006001d0000000004420019000000000034004b000000540000213d0000002003500039000000000439034f00000c30052001980000001f0620018f000000010350002900000bb40000613d000000000704034f0000000108000029000000007907043c0000000008980436000000000038004b00000bb00000c13d000000000006004b00000bc10000613d000000000454034f0000000305600210000000000603043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f000000000043043500000001022000290000000000020435000b0b2d0010019b00000000010004110000000b0010006c00001e580000c13d00000004010000290000000001010433000000800200043d000600000002001d000000000012004b00001f7b0000c13d000000070100002900080b2d0010019c000010190000613d000000060000006b0000205e0000c13d000000400100043d000000400200003900000000022104360000004003100039000000800400043d00000000004304350000006003100039000000000004004b00000be30000613d000000800500003900000000060000190000002005500039000000000705043300000000037304360000000106600039000000000046004b00000bdd0000413d00000000041300490000000000420435000000040200002900000000040204330000000002430436000000000004004b00000bf20000613d000000000300001900000004050000290000002005500039000000000605043300000000026204360000000103300039000000000043004b00000bec0000413d000000000212004900000b280020009c00000b2802008041000000600220021000000b280010009c00000b28010080410000004001100210000000000112019f000000000200041400000b280020009c00000b2802008041000000c002200210000000000121019f00000b36011001c70000800d02000039000000040300003900000c170400004100000000050004110000000b0600002900000008070000292c9b2c910000040f0000000100200190000000540000613d00000bb201000041000000000010044300000007010000290000000400100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000000001004b00000a1f0000613d000000400300043d0000004401300039000000a002000039000000000021043500000024013000390000000b02000029000000000021043500000c18010000410000000000130435000000040130003900000000020004110000000000210435000000a401300039000000800200043d0000000000210435000a00000003001d000000c401300039000000000002004b00000c340000613d000000800300003900000000040000190000002003300039000000000503043300000000015104360000000104400039000000000024004b00000c2e0000413d0000000a030000290000000002310049000000040220008a00000064033000390000000000230435000000040200002900000000020204330000000001210436000000000002004b00000c460000613d000000000300001900000004050000290000002005500039000000000405043300000000014104360000000103300039000000000023004b00000c400000413d0000000a030000290000000002310049000000040220008a00000084033000390000000000230435000000020200002900000000020204330000000001210436000000000002004b000000010600002900000c590000613d000000000300001900000000041300190000000005630019000000000505043300000000005404350000002003300039000000000023004b00000c520000413d0000000003120019000000000003043500000000030004140000000804000029000000040040008c000022c50000c13d0000000005000415000000130550008a00000005055002100000000003000031000000200030008c00000020040000390000000004034019000022fa0000013d0000000001000416000000000001004b000000540000c13d00000b3501000041000000000101041a00000b2d01100197000000800010043f00000bb00100004100002c9c0001042e000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000b00000001001d00000b2d0010009c000000540000213d0000000301000039000000000101041a00000b2d02100198000011e60000c13d0000008001000039000000010200018f000000000021043500000b280010009c00000b2801008041000000400110021000000bd6011001c700002c9c0001042e0000000001000416000000000001004b000000540000c13d000000e001000039000000400010043f000000800000043f000000a00000043f000000c00000043f0000000301000039000000000101041a00000b2d02100198000010a10000c13d0000014001000039000000400010043f000000e001000039000000e00000043f000001000000043f0000000002000019000000000300001900000040041000390000000000340435000000400300043d00000000022304360000002001100039000000000101043300000bb1011001970000000000120435000000000104043300000bb1011001970000004002300039000000000012043500000b280030009c00000b2803008041000000400130021000000be5011001c700002c9c0001042e000000440030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b00000b2d0010009c000000540000213d0000002402800370000000000202043b000b00000002001d00000b2d0020009c000000540000213d000000000010043f0000000101000039000000200010043f000000400200003900000000010000192c9b2c5e0000040f0000000b02000029000000000020043f000000200010043f000000000100001900000040020000392c9b2c5e0000040f000000000101041a000000ff001001900000000001000039000000010100c039000000800010043f00000bb00100004100002c9c0001042e000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000000000010043f0000000601000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000303100039000000000203041a000000000002004b000011f30000c13d000a00000003001d0000000201100039000000000101041a000b00000001001d00000bd9010000410000000000100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bca011001c70000800b020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000900000001001d0000000b02000029000000000021004b000015c20000813d000000400100043d00000bdd02000041000011f50000013d0000000001000416000000000001004b000000540000c13d00000b3501000041000000000101041a0000000002000411000000000012004b00000ddd0000c13d00000bb8010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb9011001c700008005020000392c9b2c960000040f0000000100200190000025ba0000613d000000000201043b000000400b00043d00000bba0100004100000000001b04350000000401b0003900000000030004100000000000310435000000000100041400000b2d02200197000000040020008c000a00000002001d000013ac0000c13d0000000004000031000000200040008c0000002004008039000013d70000013d000000640030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000002401800370000000000101043b000b00000001001d00000b2d0010009c000000540000213d0000004401800370000000000401043b0000000401800370000000000301043b00000b3501000041000000000101041a0000000002000411000000000012004b00000ddd0000c13d0000000b0000006b0000144b0000c13d00000b3e01000041000000800010043f0000002001000039000000840010043f0000002a01000039000000a40010043f00000c0901000041000000c40010043f00000c0801000041000000e40010043f00000bed0100004100002c9d00010430000000e40030008c000000540000413d0000000001000416000000000001004b000000540000c13d2c9b274f0000040f000b00000001001d2c9b28f40000040f00000001010003670000000402100370000000000202043b0000002403100370000000000303043b0000006404100370000000000504043b0000008404100370000000000604043b000000a404100370000000000704043b000000c401100370000000000801043b00000000010004110000000b040000292c9b2b6e0000040f000000400200043d000000000012043500000b280020009c00000b2802008041000000400120021000000bd6011001c700002c9c0001042e0000000001000416000000000001004b000000540000c13d00000013010000390000075d0000013d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000b00000001001d00000b2d0010009c000000540000213d2c9b28f40000040f0000001101000039000000000201041a00000b3b022001970000000b03000029000000000232019f000000000021041b000000000100001900002c9c0001042e000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000201043b00000b2b0020009c000000540000213d0000002301200039000000000031004b000000540000813d0000000405200039000000000158034f000000000101043b00000b2b0010009c000000690000213d0000001f0610003900000c30066001970000003f0660003900000c300660019700000bbf0060009c000000690000213d00000024022000390000008006600039000000400060043f000000800010043f0000000002210019000000000032004b000000540000213d0000002002500039000000000328034f00000c30051001980000001f0610018f000000a00250003900000da20000613d000000a007000039000000000803034f000000008908043c0000000007970436000000000027004b00000d9e0000c13d000000000006004b00000daf0000613d000000000353034f0000000305600210000000000602043300000000065601cf000000000656022f000000000303043b0000010005500089000000000353022f00000000035301cf000000000363019f0000000000320435000000a001100039000000000001043500000b3501000041000000000101041a0000000002000411000000000012004b00000ddd0000c13d000000800200043d00000b2b0020009c000000690000213d0000001601000039000000000501041a000000010050019000000001035002700000007f0330618f0000001f0030008c00000000060000390000000106002039000000000565013f0000000100500190000010470000c13d000000200030008c00000dd50000413d000000000010043f0000001f05200039000000050550027000000b380550009a000000200020008c00000b39050040410000001f03300039000000050330027000000b380330009a000000000035004b00000dd50000813d000000000005041b0000000105500039000000000035004b00000dd10000413d0000001f0020008c00001a9f0000a13d000000000010043f00000c300420019800001acb0000c13d000000a00500003900000b390300004100001ad90000013d00000c2a01000041000000000010043f00000bbe0100004100002c9d00010430000000840030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000004401800370000000000101043b000b00000001001d0000002401800370000000000101043b000900000001001d0000000401800370000000000101043b000a00000001001d0000006401800370000000000201043b00000b2b0020009c000000540000213d0000002301200039000000000031004b000000540000813d0000000404200039000000000148034f000000000101043b00000b2b0010009c000000690000213d0000001f0610003900000c30066001970000003f0660003900000c300660019700000bbf0060009c000000690000213d00000024022000390000008006600039000000400060043f000000800010043f0000000002210019000000000032004b000000540000213d0000002002400039000000000328034f00000c30041001980000001f0510018f000000a00240003900000e140000613d000000a006000039000000000703034f000000007807043c0000000006860436000000000026004b00000e100000c13d000000000005004b00000e210000613d000000000343034f0000000304500210000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000320435000000a00110003900000000000104350000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a000000ff00100190000018150000c13d0000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a00000c320220019700000001022001bf000000000021041b0000000001000411000000000010043f0000000d01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a000000010220003a0000189c0000613d000000000021041b000000400100043d00000080021000390000000b03000029000000000032043500000060021000390000000903000029000000000032043500000040021000390000000a030000290000000000320435000000800200003900000000022104360000000003000411000000000032043500000c0c0010009c000000690000213d000000a003100039000000400030043f00000b280020009c00000b28020080410000004002200210000000000101043300000b280010009c00000b28010080410000006001100210000000000121019f000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000b36011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000200010043f00000bcd01000041000000000010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bce011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000400200043d000b00000002001d000000000101043b000000800200043d000000400020008c00001ee00000613d000000410020008c00001f140000c13d000000e00200043d000000f802200270000000200020043f000000c00200043d00001ee50000013d0000000001000416000000000001004b000000540000c13d0000001501000039000000000101041a000000800010043f00000bb00100004100002c9c0001042e000001440030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000004401800370000000000201043b000000000002004b0000000001000039000000010100c039000b00000002001d000000000012004b000000540000c13d0000006401800370000000000201043b000000000002004b0000000001000039000000010100c039000a00000002001d000000000012004b000000540000c13d0000008401800370000000000201043b00000b2b0020009c000000540000213d0000002301200039000000000031004b000000540000813d0000000404200039000000000148034f000000000101043b00000b2b0010009c000000690000213d0000001f0610003900000c30066001970000003f0660003900000c300660019700000bbf0060009c000000690000213d00000024022000390000008006600039000000400060043f000000800010043f0000000002210019000000000032004b000000540000213d0000002002400039000000000328034f00000c30041001980000001f0510018f000000a00240003900000ef20000613d000000a006000039000000000703034f000000007807043c0000000006860436000000000026004b00000eee0000c13d000000000005004b00000eff0000613d000000000343034f0000000304500210000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000320435000000a00110003900000000000104350000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000a4020000390000000102200367000000000202043b000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a000000ff00100190000018150000c13d0000000001000411000000000010043f0000000e01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000a4020000390000000102200367000000000202043b000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a00000c320220019700000001022001bf000000000021041b0000000001000411000000000010043f0000000d01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a000000010220003a0000189c0000613d000000000021041b0000000102000367000000c401200370000000000101043b000900000001001d000000000001004b00000f680000c13d00000bc9010000410000000000100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bca011001c70000800b020000392c9b2c960000040f0000000100200190000025ba0000613d0000000102000367000000000101043b000900000001001d000000e401200370000000000401043b000000010140008a000000090010006c00001e050000413d000000400100043d0000002003100039000000000500041100000000005304350000000405200370000000000505043b000000400610003900000000005604350000002405200370000000000505043b000000a0061000390000000a07000029000000000076043500000080061000390000000b07000029000000000076043500000060061000390000000000560435000000a405200370000000000505043b00000100061000390000000000460435000000e00410003900000009060000290000000000640435000000c00410003900000000005404350000010404200370000000000404043b000001200510003900000000004504350000012402200370000000000202043b000001400410003900000000002404350000014002000039000000000021043500000bd50010009c000000690000213d0000016002100039000000400020043f00000b280030009c00000b28030080410000004002300210000000000101043300000b280010009c00000b28010080410000006001100210000000000121019f000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000b36011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000200010043f00000bcd01000041000000000010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bce011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000400200043d000800000002001d000000000101043b000000800200043d000000400020008c000021180000613d000000410020008c00001f140000c13d000000e00200043d000000f802200270000000200020043f000000c00200043d0000211d0000013d0000000002000416000000000002004b000000540000c13d0000000302000039000000000202041a00000b2d02200198000010ad0000c13d000000a001000039000000400010043f0000008002000039000000800000043f000000400100043d000b00000001001d2c9b27320000040f000013a20000013d000000a40030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000901043b00000b2d0090009c000000540000213d0000002401800370000000000101043b000800000001001d00000b2d0010009c000000540000213d0000008401800370000000000201043b00000b2b0020009c000000540000213d0000002301200039000000000031004b000000540000813d0000000404200039000000000148034f000000000101043b00000b2b0010009c000000690000213d0000001f0510003900000c30055001970000003f0550003900000c300550019700000bbf0050009c000000690000213d00000024022000390000008005500039000000400050043f000000800010043f0000000002210019000000000032004b000000540000213d000900000009001d0000002002400039000000000328034f00000c30041001980000001f0510018f000000a002400039000010050000613d000000a006000039000000000703034f000000007807043c0000000006860436000000000026004b000010010000c13d000000000005004b000010120000613d000000000343034f0000000304500210000000000502043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000320435000000a00110003900000000000104350000000002000411000000090020006c000019230000c13d000000080000006b000019bb0000c13d000000400100043d000000640210003900000c19030000410000000000320435000000440210003900000c1a0300004100000000003204350000002402100039000000250300003900001b470000013d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000012001000039000000400010043f0000010001000039000001000000043f0000000402800370000000000202043b0000000003010019000000090020008c0000000a1220011a000000f804100210000000010130008a000000000501043300000c2205500197000000000445019f00000c23044001c700000000004104350000102e0000213d0000010102300089000000210330008a00000000002304350000001604000039000000000204041a000000010520019000000001092002700000007f0990618f0000001f0090008c00000000060000390000000106002039000000000662013f0000000100600190000010ba0000613d00000c1401000041000000000010043f0000002201000039000000040010043f00000bbb0100004100002c9d00010430000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000b00000001001d000000000010043f0000000701000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a000000ff00100190000014780000c13d000000400100043d00000c0302000041000011f50000013d000000640030008c000000540000413d0000000001000416000000000001004b000000540000c13d0000000401800370000000000101043b000b00000001001d00000b2d0010009c000000540000213d0000002401800370000000000101043b000a00000001001d00000b2d0010009c000000540000213d0000004401800370000000000101043b000900000001001d00000b2d0010009c000000540000213d00000001020000390000000301000039000000000101041a00000b2d031001980000161c0000c13d000000800100003900000c800000013d000000240030008c000000540000413d0000000001000416000000000001004b000000540000c13d2c9b28f40000040f00000004010000390000000101100367000000000101043b0000001202000039000000000012041b000000000100001900002c9c0001042e00000bd201000041000000800010043f00000be30100004100002c9d0001043000000bde01000041000000e00010043f0000000001000410000000e40010043f0000000001000414000000040020008c000011910000c13d0000000003000031000000600030008c00000060040000390000000004034019000011b50000013d00000bde03000041000000800030043f0000000003000410000000840030043f0000000003000414000000040020008c000b00000002001d000011fb0000c13d0000000003000031000000600030008c000000600400003900000000040340190000121f0000013d000000400800043d000000000005004b000012a20000613d000000000040043f000000000009004b000012a50000613d00000b3902000041000000200480003900000000050000190000000006540019000000000702041a000000000076043500000001022000390000002005500039000000000095004b000010c30000413d000012a50000013d000900000002001d0000000201200039000000000101041a000a00000001001d00000bc9010000410000000000100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bca011001c70000800b020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b0000000a0010006c000015030000a13d000000400100043d00000bf102000041000011f50000013d0000001402000039000000000012041b000000000100001900002c9c0001042e00000b280030009c00000b2803008041000000c00130021000000bdf011001c72c9b2c960000040f000000600310027000000b2803300197000000600030008c000000600400003900000000040340190000001f0640018f000000600740019000000080057001bf000010f80000613d0000008008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000010f40000c13d000000000006004b000011050000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000013720000613d0000001f02400039000000e00220018f0000008004200039000000400040043f000000600030008c000000540000413d000000e005200039000000400050043f000000800500043d000000060050008c000000540000213d0000000000540435000000a00400043d00000bb10040009c000000540000213d000000a0052000390000000000450435000000c00500043d00000bb10050009c000000540000213d000000c002200039000000000052043500000c0a02000041000000400500043d0000000000250435000a00000005001d0000000402500039000000000042043500000000020004140000000b04000029000000040040008c000011380000613d0000000a0100002900000b280010009c00000b2801008041000000400110021000000b280020009c00000b2802008041000000c002200210000000000112019f00000bbb011001c70000000b020000292c9b2c960000040f000000600310027000000b280030019d00000b28033001970000000100200190000019630000613d00000c30053001980000001f0630018f0000000a04500029000011420000613d000000000701034f0000000a08000029000000007907043c0000000008980436000000000048004b0000113e0000c13d000000000006004b0000114f0000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000c30011001970000000a02100029000000000012004b0000000001000039000000010100403900000b2b0020009c000000690000213d0000000100100190000000690000c13d000000400020043f00000bcf0030009c000000540000213d000000200030008c000000540000413d0000000a01000029000000000101043300000b2b0010009c000000540000213d0000000a033000290000000a011000290000001f04100039000000000034004b000000000500001900000b2c0500804100000b2c0440019700000b2c06300197000000000764013f000000000064004b000000000400001900000b2c0400404100000b2c0070009c000000000405c019000000000004004b000000540000c13d000000001401043400000b2b0040009c000000690000213d00000005054002100000003f0650003900000be106600197000000000626001900000b2b0060009c000000690000213d000000400060043f00000000004204350000000004150019000000000034004b000000540000213d000000000041004b00000fcd0000813d0000000003020019000000001501043400000b2d0050009c000000540000213d00000020033000390000000000530435000000000041004b000011830000413d00000fcd0000013d00000c3202200197000000a00020043f000000000001004b000000c001000039000000a001006039000013990000013d00000b280010009c00000b2801008041000000c00110021000000be4011001c72c9b2c960000040f000000e00a000039000000600310027000000b2803300197000000600030008c000000600400003900000000040340190000001f0640018f0000006007400190000000e005700039000011a50000613d000000000801034f000000008908043c000000000a9a043600000000005a004b000011a10000c13d000000000006004b000011b20000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000013f60000613d0000001f01400039000000e00410018f000000e001400039000000400010043f000000600030008c000000540000413d0000014002400039000000400020043f000000e00200043d000000060020008c000000540000213d0000000000210435000001000300043d00000bb10030009c000000540000213d00000100044001bf0000000000340435000001200300043d00000bb10030009c00000c990000a13d000000540000013d00000bbc03000041000000800030043f00000b2d02200197000000840020043f000000a40010043f00000bb8010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb9011001c700008005020000392c9b2c960000040f0000000100200190000025ba0000613d000000000201043b000000000100041400000b2d02200197000000040020008c000015d50000c13d000000000a0000310000002000a0008c000000200a008039000015fa0000013d00000bde01000041000000800010043f0000000001000410000000840010043f0000000001000414000000040020008c000a00000002001d000014020000c13d0000000003000031000000600030008c00000060040000390000000004034019000014260000013d000000400100043d00000bd802000041000000000021043500000b280010009c00000b2801008041000000400110021000000bc2011001c700002c9d0001043000000b280030009c00000b2803008041000000c00130021000000bdf011001c72c9b2c960000040f000000800a000039000000600310027000000b2803300197000000600030008c000000600400003900000000040340190000001f0640018f000000600740019000000080057001bf0000120f0000613d000000000801034f000000008908043c000000000a9a043600000000005a004b0000120b0000c13d000000000006004b0000121c0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00000001002001900000146c0000613d0000001f02400039000000e00220018f0000008004200039000000400040043f000000600030008c000000540000413d000000e005200039000000400050043f000000800500043d000000060050008c000000540000213d0000000000540435000000a00400043d00000bb10040009c000000540000213d000000a0052000390000000000450435000000c00400043d00000bb10040009c000000540000213d000000c002200039000000000042043500000be002000041000000400500043d0000000000250435000a00000005001d0000000402500039000000000042043500000000020004140000000b04000029000000040040008c0000124f0000613d0000000a0100002900000b280010009c00000b2801008041000000400110021000000b280020009c00000b2802008041000000c002200210000000000112019f00000bbb011001c70000000b020000292c9b2c960000040f000000600310027000000b280030019d00000b280330019700000001002001900000196f0000613d00000c30053001980000001f0630018f0000000a04500029000012590000613d000000000701034f0000000a08000029000000007907043c0000000008980436000000000048004b000012550000c13d000000000006004b000012660000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000001f0130003900000c30011001970000000a02100029000000000012004b0000000001000039000000010100403900000b2b0020009c000000690000213d0000000100100190000000690000c13d000000400020043f00000bcf0030009c000000540000213d000000200030008c000000540000413d0000000a01000029000000000101043300000b2b0010009c000000540000213d0000000a033000290000000a011000290000001f04100039000000000034004b000000000500001900000b2c0500804100000b2c0440019700000b2c06300197000000000764013f000000000064004b000000000400001900000b2c0400404100000b2c0070009c000000000405c019000000000004004b000000540000c13d000000001401043400000b2b0040009c000000690000213d00000005054002100000003f0650003900000be106600197000000000626001900000b2b0060009c000000690000213d000000400060043f00000000004204350000000004150019000000000034004b000000540000213d000000000041004b00000fcd0000813d0000000003020019000000001501043400000b2d0050009c000000540000213d00000020033000390000000000530435000000000041004b0000129a0000413d00000fcd0000013d00000c3202200197000000200480003900000000002404350000000002890019000000200420003900000c2405000041000000000054043500000021022000390000000003030433000a00000003001d000b00000008001d000900000009001d2c9b27130000040f00000009020000290000000a0320002900000001023000390000000b01000029000000000021043500000021023000392c9b27010000040f0000002001000039000000400200043d000a00000002001d00000000021204360000000b010000292c9b27200000040f0000000a02000029000013a30000013d00000bfe0020009c00000eb50000613d00000c2f0020009c00000eb50000613d000000800000043f00000bb00100004100002c9c0001042e00000b280010009c00000b2801008041000000c00110021000000bdf011001c72c9b2c960000040f000000600310027000000b2803300197000000600030008c000000600400003900000000040340190000001f0640018f000000600740019000000080057001bf000012d90000613d0000008008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000012d50000c13d000000000006004b000012e60000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000015b60000613d0000001f01400039000000e00110018f0000008002100039000000400020043f000000600030008c000000540000413d000000e004100039000000400040043f000000800400043d000000060040008c000000540000213d0000000000420435000000a00200043d00000bb10020009c000000540000213d000000a0041000390000000000240435000000c00400043d00000bb10040009c000000540000213d000000c0011000390000000000410435000000400500043d00000024015000390000000b04000029000000000041043500000c1b010000410000000000150435000900000005001d0000000401500039000000000021043500000000010004140000000a02000029000000040020008c000014490000613d000000090200002900000b280020009c00000b2802008041000000400220021000000b280010009c00000b2801008041000000c001100210000000000121019f00000bb5011001c70000000a020000292c9b2c960000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000905700029000013260000613d000000000801034f0000000909000029000000008a08043c0000000009a90436000000000059004b000013220000c13d000000000006004b000013330000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000019a50000c13d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000133d0000c13d00001af40000013d000000000020043f0000000101000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a00000c32022001970000000a03000029000000000232019f000000000021041b000000400100043d000000000031043500000b280010009c00000b28010080410000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000b33011001c70000800d02000039000000030300003900000bea0400004100000000050004110000000b0600002900000a1c0000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013790000c13d00001af40000013d000000000100041400000b280010009c00000b2801008041000000c00110021000000b36011001c70000800d02000039000000030300003900000b37040000412c9b2c910000040f0000000100200190000000540000613d00000b35010000410000000b02000029000000000021041b000000000100001900002c9c0001042e00000b390200004100000000040000190000000003040019000000000402041a000000a005300039000000000045043500000001022000390000002004300039000000000014004b000013900000413d000000c001300039000000800210008a00000080010000392c9b27010000040f0000002001000039000000400200043d000b00000002001d000000000212043600000080010000392c9b27200000040f0000000b02000029000000000121004900000b280010009c00000b2801008041000000600110021000000b280020009c00000b28020080410000004002200210000000000121019f00002c9c0001042e00000b2800b0009c00000b280300004100000000030b4019000000400330021000000b280010009c00000b2801008041000000c001100210000000000131019f00000bbb011001c7000b0000000b001d2c9b2c960000040f0000000b0b000029000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000013c70000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000013c30000c13d000000000006004b000013d40000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000016040000613d0000001f01400039000000600110018f0000000002b10019000000000012004b00000000010000390000000101004039000b00000002001d00000b2b0020009c000000690000213d0000000100100190000000690000c13d0000000b01000029000000400010043f000000200040008c000000540000413d00000000010b04330000000b030000290000002402300039000000000012043500000bbc010000410000000000130435000000000100041100000b2d011001970000000402300039000000000012043500000000010004140000000a02000029000000040020008c000017230000c13d000000200a0000390000174e0000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013fd0000c13d00001af40000013d00000b280010009c00000b2801008041000000c00110021000000bdf011001c72c9b2c960000040f000000600310027000000b2803300197000000600030008c000000600400003900000000040340190000001f0640018f000000600740019000000080057001bf000014160000613d0000008008000039000000000901034f000000009a09043c0000000008a80436000000000058004b000014120000c13d000000000006004b000014230000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000016100000613d0000001f01400039000000e00110018f0000008002100039000000400020043f000000600030008c000000540000413d000000e004100039000000400040043f000000800400043d000000060040008c000000540000213d0000000000420435000000a00200043d00000bb10020009c000000540000213d000000a0041000390000000000240435000000c00200043d00000bb10020009c000000540000213d000000c0011000390000000000210435000000400500043d00000024015000390000000b04000029000000000041043500000bee010000410000000000150435000900000005001d0000000401500039000000000021043500000000010004140000000a02000029000000040020008c0000197b0000c13d0000002004000039000019a50000013d000a00000004001d000900000003001d000000000030043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a0000000a0010006c000018780000813d000000400100043d00000c2102000041000011f50000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000014730000c13d00001af40000013d0000000b01000029000000000010043f0000000601000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000400200043d000a00000002001d00000bf20020009c000000690000213d000000000101043b0000000a040000290000010002400039000000400020043f000000000201041a00000000022404360000000103100039000000000303041a00000000003204350000000202100039000000000202041a000000400340003900000000002304350000000302100039000000000202041a0000006003400039000900000003001d00000000002304350000000402100039000000000202041a0000008003400039000700000003001d00000000002304350000000502100039000000000202041a000000a003400039000800000003001d00000000002304350000000602100039000000000202041a000000c0034000390000000000230435000000e0024000390000000701100039000000000101041a00000000001204350000000b01000029000000000010043f0000000701000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000200041100000b2d02200197000600000002001d000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a000000ff00100190000500000000001d00001b540000613d00000009010000290000000001010433000000000001004b000500000000001d00001b540000613d0000000a02000029000000000302043300000008020000290000000002020433000a00000003001d000000000032004b000500000000001d00001b540000813d00000007020000290000000003020433000900000003001d0000000a0030006c00001b520000a13d000000400200043d00000040032000390000000604000029000000000043043500000040030000390000000003320436000000000013043500000c020020009c000000690000213d0000006001200039000000400010043f00000b280030009c00000b28030080410000004001300210000000000202043300000b280020009c00000b28020080410000006002200210000000000112019f000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000b36011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b00000009101000fa0000000a0010006c0000000001000039000000010100403900001b530000013d0000000b01000029000000000010043f0000000701000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a000000ff00100190000018ae0000c13d0000001301000039000000000201041a00000009010000290000000101100039000000000101041a000a00000002001d000900000001001d000000000012001a0000189c0000413d0000000b01000029000000000010043f0000000701000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a00000c320220019700000001022001bf000000000021041b0000000b01000029000000000010043f0000000601000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000401100039000000000201041a000000010220003a0000189c0000613d00000009040000290000000a03400029000000000021041b000000400400043d0000004401400039000900000003001d0000000000310435000000000100041000000b2d011001970000002402400039000000000012043500000bd3010000410000000000140435000000000100041100000b2d01100197000a00000004001d0000000402400039000000000012043500000bb8010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb9011001c700008005020000392c9b2c960000040f0000000100200190000025ba0000613d000000000201043b000000000100041400000b2d02200197000000040020008c00001cca0000c13d0000000004000031000000200040008c000000200400803900001cf30000013d0000000a02000029000000000102041a000000000001004b000000d80000613d0000000201200039000b00000001001d000000000201041a000900000002001d00000c320020009c0000189c0000813d00000bd9010000410000000000100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bca011001c70000800b020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b00000009020000290000010002200039000000000021004b000015a30000a13d0000000a020000290000000302200039000000000202041a000000000002004b000015a70000613d0000000b02000029000000000202041a000000000002004b00001aaf0000c13d00000c330010009c0000189c0000213d00000005011000390000000b02000029000000000012041b000000000100001900002c9c0001042e000000400300043d00000c0001000041000000000013043500000b280030009c00000b2803008041000000400130021000000bc2011001c700002c9d000104300000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000015bd0000c13d00001af40000013d00000bda0100004100000000001004430000000400200443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c70000800b020000392c9b2c960000040f0000000100200190000025ba0000613d0000000b03000029000000000101043b000000000001004b0000189a0000c13d000000400100043d00000bdc02000041000011f50000013d00000b280010009c00000b2801008041000000c00110021000000c1c011001c72c9b2c910000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0540018f000000000a040019000000200640019000000080046001bf000015ea0000613d0000008007000039000000000801034f000000008908043c0000000007970436000000000047004b000015e60000c13d000000000005004b000015f70000613d000000000661034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000000000003001f0000000100200190000017170000613d000000800100003900000000020a0019000b0000000a001d2c9b27010000040f0000000b0100002900000080021001bf00000080010000392c9b27a70000040f000000000100001900002c9c0001042e0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000160b0000c13d00001af40000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000016170000c13d00001af40000013d00000bb2010000410000000000100443000800000003001d0000000400300443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000000001004b000000540000613d000000400200043d00000044012000390000000903000029000000000031043500000024012000390000000a03000029000000000031043500000bc3010000410000000000120435000a00000002001d00000004012000390000000b02000029000000000021043500000000010004140000000802000029000000040020008c0000164c0000613d0000000a0200002900000b280020009c00000b2802008041000000400220021000000b280010009c00000b2801008041000000c001100210000000000121019f00000b3f011001c700000008020000292c9b2c960000040f000000600110027000000b280010019d000000010020019000001aa90000613d0000000a0100002900000b2b0010009c000000690000213d0000000a01000029000000400010043f000000010200003900000c800000013d000000000004004b0000000005000019000016580000613d0000000a050000290000000005050433000000030640021000000c340660027f00000c3406600167000000000565016f0000000104400210000000000445019f000017700000013d000000400100043d00000be702000041000011f50000013d0000000901000029000000000001041b00000b3501000041000000000501041a000000000100041400000b280010009c00000b2801008041000000c00110021000000b36011001c70000800d02000039000000030300003900000b37040000410000000b060000292c9b2c910000040f0000000100200190000000540000613d0000000b0100002900000b3502000041000000000012041b000000000100001900002c9c0001042e00000bb2010000410000000000100443000800000002001d0000000400200443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000000001004b000000540000613d000000400300043d00000024013000390000000b02000029000000000021043500000bb4010000410000000000130435000000000100041000000b2d02100197000b00000003001d0000000401300039000700000002001d000000000021043500000000010004140000000802000029000000040020008c000016a60000613d0000000b0200002900000b280020009c00000b2802008041000000400220021000000b280010009c00000b2801008041000000c001100210000000000121019f00000bb5011001c700000008020000292c9b2c910000040f000000600310027000000b280030019d000000010020019000001ae80000613d0000000b0100002900000b2b0010009c000000690000213d0000000b01000029000000400010043f00000bb201000041000000000010044300000008010000290000000400100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000000001004b000000540000613d000000400300043d00000024013000390000000a02000029000000000021043500000bb6010000410000000000130435000b00000003001d00000004013000390000000702000029000000000021043500000000010004140000000802000029000000040020008c000016d80000613d0000000b0200002900000b280020009c00000b2802008041000000400220021000000b280010009c00000b2801008041000000c001100210000000000121019f00000bb5011001c700000008020000292c9b2c910000040f000000600310027000000b280030019d000000010020019000001c930000613d0000000b0100002900000b2b0010009c000000690000213d0000000b01000029000000400010043f00000bb201000041000000000010044300000008010000290000000400100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000000001004b000000540000613d000000400300043d00000024013000390000000902000029000000000021043500000bb7010000410000000000130435000b00000003001d00000004013000390000000702000029000000000021043500000000010004140000000802000029000000040020008c00001a980000613d0000000b0200002900000b280020009c00000b2802008041000000400220021000000b280010009c00000b2801008041000000c001100210000000000121019f00000bb5011001c700000008020000292c9b2c910000040f000000600310027000000b280030019d000000010020019000001a980000c13d00000b28033001970000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000017120000c13d00001af40000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000171e0000c13d00001af40000013d0000000b0200002900000b280020009c00000b2802008041000000400220021000000b280010009c00000b2801008041000000c001100210000000000121019f00000bb5011001c70000000a020000292c9b2c910000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0540018f000000000a04001900000020064001900000000b046000290000173e0000613d000000000701034f0000000b08000029000000007907043c0000000008980436000000000048004b0000173a0000c13d000000000005004b0000174b0000613d000000000661034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000000000003001f0000000100200190000018a20000613d0000000b0100002900000000020a0019000a0000000a001d2c9b27010000040f0000000b010000290000000a021000292c9b27a70000040f000000000100001900002c9c0001042e00000b30050000410000002006000039000000010870008a000000050880027000000b310880009a0000000b0a0000290000000009a600190000000009090433000000000095041b00000020066000390000000105500039000000000085004b0000175d0000c13d000000000047004b0000176e0000813d0000000307400210000000f80770018f00000c340770027f00000c34077001670000000b066000290000000006060433000000000676016f000000000065041b000000010440021000000001044001bf000001a00500043d000500000005001d000001800500043d000700000005001d000001600500043d000600000005001d000001400500043d000400000005001d000000000043041b000000400300043d00000b2e04100197000027100040008c000017900000a13d000000640130003900000b40020000410000000000210435000000440130003900000b4102000041000000000021043500000024013000390000002a02000039000000000021043500000b3e01000041000000000013043500000004013000390000002002000039000000000021043500000b280030009c00000b2803008041000000400130021000000b42011001c700002c9d0001043000030b2d0020019c000017a20000c13d000000440130003900000b3d02000041000000000021043500000024013000390000001902000039000000000021043500000b3e01000041000000000013043500000004013000390000002002000039000000000021043500000b280030009c00000b2803008041000000400130021000000b3f011001c700002c9d0001043000000b320030009c000000690000213d0000004002300039000000400020043f0000002002300039000000000042043500000003050000290000000000530435000000a001100210000000000151019f0000000402000039000000000012041b000000400100043d000000000041043500000b280010009c00000b28010080410000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000b33011001c70000800d02000039000000020300003900000b34040000412c9b2c910000040f0000000100200190000000540000613d0000001001000039000000000001041b000000000600041100000b3501000041000000000061041b000000000100041400000b280010009c00000b2801008041000000c00110021000000b36011001c70000800d02000039000000030300003900000b370400004100000000050000192c9b2c910000040f0000000100200190000000540000613d000000090100002900000b2d01100197000000800010043f0000000b02000029000000000302043300000b2b0030009c000000690000213d0000001602000039000000000502041a000000010050019000000001045002700000007f0440618f0000001f0040008c00000000060000390000000106002039000000000565013f0000000100500190000010470000c13d000000200040008c000017f30000413d000000000020043f0000001f05300039000000050550027000000b380550009a000000200030008c00000b39050040410000001f04400039000000050440027000000b380440009a000000000045004b000017f30000813d000000000005041b0000000105500039000000000045004b000017ef0000413d0000001f0030008c0000002004000039000000010500003900001bcc0000a13d000000000020043f00000c300830019800000b390600004100000000070400190000000b0b000029000018080000613d0000002007000039000000010980008a000000050990027000000b3a0990009a000000000ab70019000000000a0a04330000000000a6041b00000020077000390000000106600039000000000096004b000018010000c13d000000000038004b000018120000813d0000000308300210000000f80880018f00000c340880027f00000c34088001670000000b077000290000000007070433000000000787016f000000000076041b0000000106300210000000000305001900001bd60000013d000000400100043d00000c0b02000041000011f50000013d0000000901000029000000000010043f0000000801000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000400200043d00000bf20020009c000000690000213d000000000301043b0000010001200039000000400010043f000000000103041a00000000041204360000000101300039000000000101041a00000000001404350000000204300039000000000404041a000000400520003900000000004504350000000304300039000000000404041a000000600520003900000000004504350000000404300039000000000404041a000000800520003900000000004504350000000504300039000000000404041a000000a00520003900000b2d06400197000000000065043500000be6004001980000000004000039000000010400c039000000c0052000390000000000450435000000e0022000390000000603300039000000000303041a00000000003204350008000a001000bd000000000001004b000018500000613d00000008011000f90000000a0010006c0000189c0000c13d0000000901000029000000000010043f0000000b01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a0000000a030000290000000002320019000000000021041b0000000b0100002900000009020000292c9b28fe0000040f000000400100043d0000002002100039000000080300002900000000003204350000000a02000029000000000021043500000b280010009c00000b28010080410000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000bc0011001c70000800d02000039000000030300003900000c0e04000041000018970000013d0000000901000029000000000010043f0000000c01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a0000000a0020002a0000189c0000413d0000000a030000290000000002320019000000000021041b0000000b0100002900000009020000292c9b28fe0000040f000000000100041400000b280010009c00000b2801008041000000c00110021000000b36011001c70000800d02000039000000030300003900000bf70400004100000009050000290000000b0600002900000a1c0000013d00000c350030009c0000195c0000a13d00000c1401000041000000000010043f0000001101000039000000040010043f00000bbb0100004100002c9d000104300000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000018a90000c13d00001af40000013d000000400100043d00000bef02000041000011f50000013d00000b320010009c000000690000213d0000004002100039000000400020043f00000020021000390000000a03000029000000000032043500000001020000390000000000210435000000400100043d00000b320010009c000000690000213d0000004003100039000000400030043f00000020031000390000000904000029000000000043043500000000002104350000000a01000029000000000010043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a000000090020002a0000189c0000413d00000009030000290000000002320019000000000021041b000000400100043d000000200210003900000000003204350000000a02000029000000000021043500000b280010009c00000b28010080410000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000bc0011001c70000800d02000039000000040300003900000bc404000041000000000500041100000000060000190000000b070000292c9b2c910000040f0000000100200190000000540000613d00000bb20100004100000000001004430000000b010000290000000400100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000025ba0000613d000000400200043d000500000002001d000000000101043b000000000001004b00001e080000c13d000000080100002900000000010104330000001202000039000000000202041a000000050400002900000020034000390000000000230435000000000014043500000b280040009c00000b28040080410000004001400210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000bc0011001c70000800d02000039000000030300003900000bf4040000410000000a050000290000000b0600002900000a1c0000013d0000000001000411000000000010043f0000000f01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a000000ff0010019000001b070000c13d0000000901000029000000000010043f0000000101000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a000000ff00100190000010170000c13d000000400100043d000000640210003900000c10030000410000000000320435000000440210003900000c1103000041000000000032043500000024021000390000002e0300003900001b470000013d0000010002300039000000090020006b00001aac0000813d0000000a02000029000000000012041b000000000100001900002c9c0001042e0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000196a0000c13d00001af40000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000019760000c13d00001af40000013d000000090200002900000b280020009c00000b2802008041000000400220021000000b280010009c00000b2801008041000000c001100210000000000121019f00000bb5011001c70000000a020000292c9b2c960000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000905700029000019950000613d000000000801034f0000000909000029000000008a08043c0000000009a90436000000000059004b000019910000c13d000000000006004b000019a20000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000000010020019000001ab20000613d0000001f01400039000000600210018f0000000901200029000000000021004b0000000002000039000000010200403900000b2b0010009c000000690000213d0000000100200190000000690000c13d000000400010043f000000200030008c000000540000413d00000009020000290000000003020433000000000003004b0000000002000039000000010200c039000000000023004b000000540000c13d000000010220018f00000c800000013d000000400100043d000700000001001d00000b320010009c000000690000213d00000001030003670000004401300370000000000101043b00000007040000290000004002400039000000400020043f000000010200003900000000042404360000000000140435000000400400043d00000b320040009c000000690000213d0000006403300370000000000303043b0000004005400039000000400050043f00000020054000390000000000350435000000000024043500000007020000290000000002020433000600000002001d000000000002004b00001ca30000613d000000000100041100050b2d0010019b0000000005000019000000090400002900000007020000290000000603000029000019e10000013d0000000105500039000000000035004b00001ca00000813d0000000001020433000000000051004b000025bb0000a13d000000000004004b000019de0000613d0000000301000039000000000101041a00000b2d06100198000019de0000613d000a00000005001d00000bb2010000410000000000100443000b00000006001d0000000400600443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000000001004b0000000904000029000000540000613d000000400500043d0000004401500039000000080200002900000000002104350000002401500039000000000041043500000bc301000041000000000015043500000004015000390000000502000029000000000021043500000000010004140000000b02000029000000040020008c00001a1c0000613d00000b280050009c00000b28030000410000000003054019000000400330021000000b280010009c00000b2801008041000000c001100210000000000131019f00000b3f011001c7000b00000005001d2c9b2c960000040f0000000b050000290000000904000029000000600310027000000b280030019d000000010020019000001ed30000613d00000b2b0050009c000000690000213d000000400050043f000000070200002900000006030000290000000a05000029000019de0000013d0000000302000039000000000402041a000000200210003900000bfd030000410000000000320435000b00000004001d00000b2d02400197000000000021043500000b280010009c00000b28010080410000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000bc0011001c70000800d02000039000000010300003900000bff040000412c9b2c910000040f0000000100200190000000540000613d0000000b0100002900000b3b0110019700000bfd011001c70000000302000039000000000012041b00000bb201000041000000000010044300000bfd010000410000000400100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000000001004b000000540000613d000000400300043d00000024013000390000000102000039000000000021043500000bb401000041000000000013043500000004013000390000000002000410000000000021043500000b280030009c000b00000003001d00000b280100004100000000010340190000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000bb5011001c700000bfd020000412c9b2c910000040f000000600310027000000b280030019d000000010020019000001c790000613d0000000b0100002900000b2b0010009c000000690000213d0000000b01000029000000400010043f00000bb201000041000000000010044300000bfd010000410000000400100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000000001004b000000540000613d000000400300043d00000024013000390000000102000039000000000021043500000bb601000041000000000013043500000004013000390000000002000410000000000021043500000b280030009c000b00000003001d00000b280100004100000000010340190000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000bb5011001c700000bfd020000412c9b2c910000040f000000600310027000000b280030019d000000010020019000001f850000613d0000000b0100002900000b2b0010009c000000690000213d0000000b01000029000000400010043f000000000100001900002c9c0001042e000000000002004b000000000300001900001aa30000613d000000a00300043d000000030420021000000c340440027f00000c3404400167000000000443016f000000010320021000001ae40000013d000000400100043d000000000200001900000c800000013d000000400100043d00000bdb02000041000011f50000013d000000400100043d00000c2502000041000011f50000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001ab90000c13d00001af40000013d00000b28033001970000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001ac60000c13d00001af40000013d00000b39030000410000002006000039000000010540008a000000050550027000000b3a0550009a000000000706001900000080066000390000000006060433000000000063041b00000020067000390000000103300039000000000053004b00001ad00000c13d000000a005700039000000000024004b00001ae20000813d0000000304200210000000f80440018f00000c340440027f00000c34044001670000000005050433000000000445016f000000000043041b00000001030000390000000104200210000000000234019f000000000021041b000000000100001900002c9c0001042e00000b28033001970000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001af00000c13d000000000005004b00001b010000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000000b280020009c00000b28020080410000004002200210000000000112019f00002c9d00010430000000400100043d00000bc102000041000011f50000013d0000000803000029000000000429034f000000000404043b000000200330003900000000004304350000002002200039000000000052004b00001b0b0000413d00000008020000290000000002020433000000800300043d000000000023004b00001b3e0000c13d00000b2b0020009c000000690000213d00000005032002100000003f0430003900000c0705400197000000400400043d000600000004001d0000000004450019000000000054004b0000000005000039000000010500403900000b2b0040009c000000690000213d0000000100500190000000690000c13d000000400040043f00000006040000290000000002240436000500000002001d0000001f0230018f000000000003004b00001b330000613d00000005040000290000000003340019000000001501043c0000000004540436000000000034004b00001b2f0000c13d000000000002004b000000800100043d000000000001004b00001bf60000c13d000000400200043d000b00000002001d0000002001000039000000000212043600000006010000292c9b27420000040f000013a20000013d000000400100043d000000640210003900000c05030000410000000000320435000000440210003900000c0603000041000000000032043500000024021000390000002903000039000000000032043500000b3e02000041000000000021043500000004021000390000002003000039000000000032043500000b280010009c00000b2801008041000000400110021000000b42011001c700002c9d000104300000000101000039000500000001001d0000000b01000029000000000010043f0000000701000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a00000c3202200197000000000021041b0000000b01000029000000000010043f0000000601000039000000200010043f000000050000006b00001baa0000c13d000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000201043b0000000101200039000000000101041a0000000702200039000000000202041a000000000012001a0000189c0000413d0000000001120019000000400300043d0000002402300039000000000012043500000bbc010000410000000000130435000b00000003001d00000004013000390000000602000029000000000021043500000bb8010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb9011001c700008005020000392c9b2c960000040f0000000100200190000025ba0000613d000000000201043b000000000100041400000b2d02200197000000040020008c00001d170000c13d0000000003000031000000200030008c0000002004000039000000000403401900001d400000013d000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000501100039000000000201041a000000010220003a0000189c0000613d000000000021041b0000000b01000029000000000010043f0000000801000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000301043b00000000010004110000000b020000292c9b29a00000040f000000000100001900002c9c0001042e000000000003004b000000000600001900001bd10000613d0000000a060000290000000006060433000000030730021000000c340770027f00000c3407700167000000000676016f0000000103300210000000000336019f000000000032041b000000080200002900000b2d022001970000001103000039000000000603041a00000b3b06600197000000000226019f000000000023041b0000001702000039000000000302041a00000b3b0330019700000003033001af000000000032041b00000012020000390000000503000029000000000032041b00000013020000390000000403000029000000000032041b00000014020000390000000603000029000000000032041b00000015020000390000000703000029000000000032041b000001400000044300000160001004430000010000400443000001200050044300000b3c0100004100002c9c0001042e000000000300001900000008010000290000000001010433000000000031004b000025bb0000a13d000a00000003001d0000000503300210000000a0013000390000000001010433000b0b2d0010019c000080100200003900001e4e0000613d000900000003001d00000007013000290000000001010433000000000010043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c72c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000060200002900000000020204330000000a03000029000000000032004b000025bb0000a13d00000009040000290000000502400029000000000101043b000000000101041a00000000001204350000000103300039000000800100043d000000000013004b00001bf70000413d00001b370000013d0000000a0300002900000b280030009c00000b2803008041000000400330021000000b280010009c00000b2801008041000000c001100210000000000131019f00000bb5011001c72c9b2c910000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000a0570002900001c440000613d000000000801034f0000000a09000029000000008a08043c0000000009a90436000000000059004b00001c400000c13d000000000006004b00001c510000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000000010020019000001d0b0000613d0000001f01400039000000600210018f0000000a01200029000000000021004b0000000002000039000000010200403900000b2b0010009c000000690000213d0000000100200190000000690000c13d000000400010043f000000200040008c000000540000413d0000000a020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b000000540000c13d000000000002004b00001d560000613d0000000902000029000000000021043500000b280010009c00000b28010080410000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000b33011001c70000800d02000039000000030300003900000be80400004100001ff70000013d00000b28033001970000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c810000c13d00001af40000013d00000b28033001970000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c8e0000c13d00001af40000013d00000b28033001970000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001c9b0000c13d00001af40000013d00000044010000390000000101100367000000000101043b000000000010043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f00000001002001900000000902000029000000540000613d000000000101043b000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000301041a00000001010003670000006402100370000000000202043b000b00000003001d000000000023004b00001d580000813d000000400100043d000000640210003900000c15030000410000000000320435000000440210003900000c160300004100001e540000013d0000000a0300002900000b280030009c00000b2803008041000000400330021000000b280010009c00000b2801008041000000c001100210000000000131019f00000b3f011001c72c9b2c910000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000a0570002900001ce30000613d000000000801034f0000000a09000029000000008a08043c0000000009a90436000000000059004b00001cdf0000c13d000000000006004b00001cf00000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000000010020019000001e360000613d0000001f01400039000000600210018f0000000a01200029000000000021004b0000000002000039000000010200403900000b2b0010009c000000690000213d0000000100200190000000690000c13d000000400010043f000000200040008c000000540000413d0000000a020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b000000540000c13d000000000002004b00001fe90000c13d00000bd402000041000011f50000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001d120000c13d00001af40000013d0000000b0300002900000b280030009c00000b2803008041000000400330021000000b280010009c00000b2801008041000000c001100210000000000131019f00000bb5011001c72c9b2c910000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000b0570002900001d300000613d000000000801034f0000000b09000029000000008a08043c0000000009a90436000000000059004b00001d2c0000c13d000000000006004b00001d3d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f000000010020019000001e420000613d0000001f01400039000000600210018f0000000b01200029000000000021004b0000000002000039000000010200403900000b2b0010009c000000690000213d0000000100200190000000690000c13d000000400010043f000000200030008c000000540000413d0000000b020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b000000540000c13d000000000002004b00000a1f0000c13d00000be902000041000011f50000013d0000004401100370000000000101043b000000000010043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f00000001002001900000000902000029000000540000613d000000000101043b000000000020043f000000200010043f00000064010000390000000101100367000000000101043b000a00000001001d000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d0000000a030000290000000b02300069000000000101043b000000000021041b00000044010000390000000101100367000000000101043b000000000010043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000802000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d00000001030003670000006402300370000000000202043b000000000101043b000000000401041a000000000024001a0000189c0000413d0000000004240019000000000041041b0000004401300370000000000101043b000000400300043d00000020043000390000000000240435000000000013043500000b280030009c00000b28030080410000004001300210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000bc0011001c70000800d02000039000000040300003900000bc4040000410000000005000411000000090600002900000008070000292c9b2c910000040f0000000100200190000000540000613d00000bb201000041000000000010044300000008010000290000000400100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000000001004b000000090200002900000a1f0000613d000000400400043d0000002401400039000000000021043500000bc501000041000000000014043500000004014000390000000002000411000000000021043500000001010003670000004402100370000000000202043b000000440340003900000000002304350000006401100370000000000101043b0000008402400039000000a003000039000000000032043500000064024000390000000000120435000000a402400039000000800100043d0000000000120435000b00000004001d000000c402400039000000000001004b00001dea0000613d00000000030000190000000004230019000000a005300039000000000505043300000000005404350000002003300039000000000013004b00001de30000413d0000000002210019000000000002043500000000020004140000000803000029000000040030008c000022440000c13d00000000050004150000000d0550008a00000005055002100000000004000031000000200040008c0000002004008039000022770000013d00000bc9010000410000000000100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bca011001c70000800b020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000070010006c0000043f0000a13d000000400100043d00000bfc02000041000011f50000013d00000005030000290000008401300039000000a002000039000000000021043500000064013000390000000902000029000000000021043500000044013000390000000a02000029000000000021043500000bc50100004100000000001304350000000401300039000000000200041100000000002104350000002401300039000000000001043500000007010000290000000001010433000000a4023000390000000000120435000000c402300039000000000001004b000000060600002900001e290000613d000000000300001900000000042300190000000005630019000000000505043300000000005404350000002003300039000000000013004b00001e220000413d0000000002210019000000000002043500000000020004140000000b03000029000000040030008c00001e870000c13d00000000050004150000000f0550008a00000005055002100000000004000031000000200040008c000000200400803900001eba0000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e3d0000c13d00001af40000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001e490000c13d00001af40000013d000000400100043d000000640210003900000c08030000410000000000320435000000440210003900000c0903000041000000000032043500000024021000390000002a0300003900001b470000013d000000000010043f0000000f01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a000000ff0010019000001ffa0000c13d0000000b01000029000000000010043f0000000101000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a000000ff0010019000000bc70000c13d000019520000013d0000001f0110003900000c3001100197000000c40110003900000b280010009c00000b28010080410000006001100210000000050300002900000b280030009c00000b28030080410000004003300210000000000131019f00000b280020009c00000b2802008041000000c002200210000000000112019f0000000b020000292c9b2c910000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000050570002900001ea70000613d000000000801034f0000000509000029000000008a08043c0000000009a90436000000000059004b00001ea30000c13d000000000006004b00001eb40000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00000000050004150000000e0550008a0000000505500210000000010020019000001f920000613d0000001f01400039000000600110018f0000000502100029000000000012004b0000000001000039000000010100403900000b2b0020009c000000690000213d0000000100100190000000690000c13d0000000003020019000000400020043f000000200040008c000000540000413d0000000501000029000000000101043300000bc600100198000000540000c13d0000000502500270000000000201001f00000bc70110019700000bc50010009c0000210e0000c13d000500000003001d0000190c0000013d00000b28033001970000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001edb0000c13d00001af40000013d000000c00200043d000000ff032002700000001b03300039000000200030043f00000bcf02200197000000600020043f000000000010043f000000a00100043d000000400010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bd0011001c700000001020000392c9b2c960000040f0000000109000039000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0540018f000000200640019000000001046001bf00001eff0000613d000000000701034f000000007807043c0000000009890436000000000049004b00001efb0000c13d000000010220018f000000000005004b00001f0d0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000000003001f0000000001020433000000600000043f0000000b02000029000000400020043f000000000003004b00001f180000c13d00000c0f01000041000000000010043f00000bbe0100004100002c9d000104300000001102000039000000000202041a000000000112013f00000b2d00100198000025c10000c13d0000000a01000029000000000010043f0000000801000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000b00000001001d0000000a010000290000000801100270000000000010043f0000001801000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d0000000a02000029000000ff0220018f000000000101043b000000000101041a000000000121022f000000010010019000001f670000c13d0000000b010000290000000301100039000000000101041a000800000001001d00000bc9010000410000000000100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bca011001c70000800b020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000080010006c00001f670000a13d0000000a01000029000000000010043f0000000a01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d0000000b020000290000000402200039000000000202041a000000000101043b000000000101041a000000000021004b000025c90000a13d0000000b010000290000000101100039000000000101041a000b0009001000be000021d60000c13d000000400100043d00001d560000013d00000b28033001970000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f760000c13d00001af40000013d000000400100043d000000640210003900000c12030000410000000000320435000000440210003900000c130300004100000000003204350000002402100039000000280300003900001b470000013d00000b28033001970000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00001f8d0000c13d00001af40000013d000000040230008c000023b20000413d000000000400043d00000bc604400197000000000501043b00000bc705500197000000000445019f000000000040043f00000bc70440019700000b3e0040009c000023b20000c13d000000440030008c000023b20000413d000000040510037000000c30062001980000001f0720018f000000400400043d000000000164001900001fab0000613d000000000805034f0000000009040019000000008a08043c0000000009a90436000000000019004b00001fa70000c13d000000000007004b00001fb80000613d000000000565034f0000000306700210000000000701043300000000076701cf000000000767022f000000000505043b0000010006600089000000000565022f00000000056501cf000000000575019f0000000000510435000000000504043300000b2b0050009c000023b20000213d0000002401500039000000000031004b000023b20000213d0000000001450019000000000301043300000b2b0030009c000023b20000213d000000000224001900000000063100190000002006600039000000000026004b000023b20000213d00000000023500190000003f0220003900000c30022001970000000004420019000000000024004b0000000002000039000000010200403900000b2b0040009c000000690000213d0000000100200190000000690000c13d0000000003040019000000400040043f000000000001004b000023b20000613d00000b3e020000410000000004030019000b00000003001d000000000023043500000004023000390000002003000039000000000032043500000024024000392c9b27200000040f0000000b02000029000000000121004900000b280010009c00000b280100804100000b280020009c00000b280200804100000060011002100000004002200210000000000121019f00002c9d000104300000000902000029000000000021043500000b280010009c00000b28010080410000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000b33011001c70000800d02000039000000030300003900000bf0040000410000000b05000029000000000600041100000a1c0000013d000000400100043d00000bd402000041000011f50000013d000000c00200043d000000ff032002700000001b03300039000000200030043f00000bcf02200197000000600020043f000000000010043f000000a00100043d000000400010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bd0011001c700000001020000392c9b2c960000040f0000000109000039000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0540018f000000200640019000000001046001bf0000201c0000613d000000000701034f000000007807043c0000000009890436000000000049004b000020180000c13d000000010220018f000000000005004b0000202a0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000000003001f0000000001020433000000600000043f0000000902000029000000400020043f000000000003004b00001f140000613d0000001102000039000000000202041a000000000112013f00000b2d00100198000021150000c13d0000000b01000029000000000010043f0000000801000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000900000001001d0000000501100039000000000101041a00000b2d011001970000000002000411000000000012004b000020500000613d00000b3501000041000000000101041a00000b2d01100197000000000012004b000022950000c13d00000009010000290000000301100039000000000101041a000600000001001d000000000001004b0000220d0000c13d000000080000006b000022980000613d0000000a010000290000000b0200002900000009030000292c9b29a00000040f000000000100001900002c9c0001042e000000000100041100050b2d0010019b00000000030000190000000602000029000020660000013d0000000103300039000000000023004b000021650000813d000000800100043d000000000031004b000025bb0000a13d0000000b0000006b000020630000613d0000000301000039000000000101041a00000b2d04100198000020630000613d000900000003001d00000bb2010000410000000000100443000a00000004001d0000000400400443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000000001004b000000540000613d000000400400043d00000044014000390000000802000029000000000021043500000024014000390000000b02000029000000000021043500000bc301000041000000000014043500000004014000390000000502000029000000000021043500000000010004140000000a02000029000000040020008c000020a00000613d00000b280040009c00000b28030000410000000003044019000000400330021000000b280010009c00000b2801008041000000c001100210000000000131019f00000b3f011001c7000a00000004001d2c9b2c960000040f0000000a04000029000000600310027000000b280030019d0000000100200190000023170000613d00000b2b0040009c000000690000213d000000400040043f00000006020000290000000903000029000020630000013d000000c00200043d000000ff032002700000001b03300039000000200030043f00000bcf02200197000000600020043f000000000010043f000000a00100043d000000400010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bd0011001c700000001020000392c9b2c960000040f0000000109000039000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0540018f000000200640019000000001046001bf000020c50000613d000000000701034f000000007807043c0000000009890436000000000049004b000020c10000c13d000000010220018f000000000005004b000020d30000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000000003001f0000000001020433000000600000043f0000000702000029000000400020043f000000000003004b00001f140000613d0000001102000039000000000202041a000000000112013f00000b2d00100198000021620000c13d000000090000006b000026700000c13d0000001201000039000000000201041a000700000002001d000000080020002a0000189c0000413d00000bb8010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb9011001c700008005020000392c9b2c960000040f0000000100200190000025ba0000613d000000000201043b00000006010000290000000101100039000000000101041a000000400400043d00000044034000390000000000130435000000000100041000000b2d011001970000002403400039000000000013043500000bd3010000410000000000140435000900000004001d00000004014000390000000a030000290000000000310435000000000100041400000b2d02200197000500000002001d000000040020008c000023240000c13d0000000004000031000000200040008c00000020040080390000234e0000013d00000b3e01000041000900000003001d000000000013043500000004013000392c9b2c430000040f0000000902000029000023b90000013d00000bd1010000410000000902000029000025c30000013d000000c00200043d000000ff032002700000001b03300039000000200030043f00000bcf02200197000000600020043f000000000010043f000000a00100043d000000400010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bd0011001c700000001020000392c9b2c960000040f0000000109000039000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0540018f000000200640019000000001046001bf000021370000613d000000000701034f000000007807043c0000000009890436000000000049004b000021330000c13d000000010220018f000000000005004b000021450000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000000003001f0000000001020433000000600000043f0000000802000029000000400020043f000000000003004b00001f140000613d0000001102000039000000000202041a000000000112013f00000b2d00100198000021d30000c13d0000000a0000006b0000221c0000613d00000001010003670000000402100370000000000202043b0000002403100370000000000303043b000000e404100370000000000604043b0000010404100370000000000704043b0000012401100370000000000801043b00000000010004110000000b04000029000000090500002900000d580000013d00000bd1010000410000000702000029000025c30000013d000000800100043d000000000001004b00000bd20000613d000000000200001900000004010000290000000001010433000000000021004b000025bb0000a13d000600000002001d0000000501200210000000a002100039000000000302043300000003011000290000000001010433000900000001001d000a00000003001d000000000030043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a000500090010007400001cc30000413d0000000a01000029000000000010043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000b02000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000502000029000000000021041b0000000a01000029000000000010043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000802000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a0000000903000029000000000032001a0000189c0000413d0000000002320019000000000021041b00000006020000290000000102200039000000800100043d000000000012004b000021690000413d00000bd20000013d00000bd1010000410000000802000029000025c30000013d0000000a01000029000000000010043f0000000b01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a00000009030000290000000002320019000000000021041b00000000010004110000000a020000292c9b28fe0000040f000000400300043d00000024013000390000000b02000029000000000021043500000bbc010000410000000000130435000000000100041100000b2d01100197000800000003001d0000000402300039000000000012043500000bb8010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb9011001c700008005020000392c9b2c960000040f0000000100200190000025ba0000613d000000000201043b000000000100041400000b2d02200197000000040020008c000024020000c13d0000000004000031000000200040008c00000020040080390000242b0000013d00000bc9010000410000000000100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bca011001c70000800b020000392c9b2c960000040f0000000100200190000025ba0000613d000000000101043b000000060010006c00001e050000213d000020560000013d0000001701000039000000000101041a0000001502000039000000000202041a00000008040000290000004403400039000000000023043500000b2d011001970000002402400039000000000012043500000bd3010000410000000000140435000000000100041100000b2d011001970000000402400039000000000012043500000bb8010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb9011001c700008005020000392c9b2c960000040f0000000100200190000025ba0000613d000000000201043b000000000100041400000b2d02200197000000040020008c000023c20000c13d0000000003000031000000200030008c00000020040000390000000004034019000023eb0000013d0000001f0110003900000c3001100197000000c40110003900000b280010009c00000b280100804100000060011002100000000b0300002900000b280030009c00000b28030080410000004003300210000000000131019f00000b280020009c00000b2802008041000000c002200210000000000112019f00000008020000292c9b2c910000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000b05700029000022640000613d000000000801034f0000000b09000029000000008a08043c0000000009a90436000000000059004b000022600000c13d000000000006004b000022710000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00000000050004150000000c0550008a000000050550021000000001002001900000237e0000613d0000001f01400039000000600110018f0000000b02100029000000000012004b0000000001000039000000010100403900000b2b0020009c000000690000213d0000000100100190000000690000c13d0000000003020019000000400020043f000000200040008c000000540000413d0000000b01000029000000000101043300000bc600100198000000540000c13d0000000502500270000000000201001f00000bc70110019700000bc50010009c00000a1f0000613d00000b3e01000041000a00000003001d000000000013043500000004013000392c9b2c430000040f0000000a02000029000023b90000013d000000400100043d00000bd202000041000011f50000013d0000001201000039000000000201041a000600000002001d000000070020002a0000189c0000413d00000bb8010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb9011001c700008005020000392c9b2c960000040f0000000100200190000025ba0000613d000000000201043b00000009010000290000000101100039000000000101041a000000400400043d00000044034000390000000000130435000000000100041000000b2d011001970000002403400039000000000013043500000bd3010000410000000000140435000800000004001d00000004014000390000000a030000290000000000310435000000000100041400000b2d02200197000500000002001d000000040020008c000025cc0000c13d0000000004000031000000200040008c0000002004008039000025f60000013d0000001f0220003900000c30022001970000000a040000290000000001410049000000000121001900000b280010009c00000b2801008041000000600110021000000b280040009c00000b280200004100000000020440190000004002200210000000000121019f00000b280030009c00000b2803008041000000c002300210000000000112019f00000008020000292c9b2c910000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000a05700029000022e70000613d000000000801034f0000000a09000029000000008a08043c0000000009a90436000000000059004b000022e30000c13d000000000006004b000022f40000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000005000415000000120550008a00000005055002100000000100200190000023980000613d0000001f01400039000000600110018f0000000a02100029000000000012004b0000000001000039000000010100403900000b2b0020009c000000690000213d0000000100100190000000690000c13d0000000004020019000000400020043f000000200030008c000000540000413d0000000a01000029000000000101043300000bc600100198000000540000c13d0000000502500270000000000201001f00000bc70110019700000c180010009c00000a1f0000613d00000b3e01000041000b00000004001d000000000014043500000004014000392c9b2c430000040f000023b80000013d00000b28033001970000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000231f0000c13d00001af40000013d000000090200002900000b280020009c00000b2802008041000000400220021000000b280010009c00000b2801008041000000c001100210000000000121019f00000b3f011001c700000005020000292c9b2c910000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000009057000290000233e0000613d000000000801034f0000000909000029000000008a08043c0000000009a90436000000000059004b0000233a0000c13d000000000006004b0000234b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000024550000613d0000001f01400039000000600110018f0000000903100029000000000013004b00000000020000390000000102004039000400000003001d00000b2b0030009c000000690000213d0000000100200190000000690000c13d0000000402000029000000400020043f000000200040008c000000540000413d00000009020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b000000540000c13d000000000002004b0000260e0000613d000000070300002900000008023000290000001703000039000000000303041a00000004050000290000004404500039000000000024043500000b2d023001970000002403500039000000000023043500000bd302000041000000000025043500000004025000390000000a03000029000000000032043500000000020004140000000503000029000000040030008c000026350000c13d000000040110002900000b2b0010009c000000690000213d000000400010043f000026670000013d000000040230008c000023b20000413d000000000400043d00000bc604400197000000000501043b00000bc705500197000000000445019f000000000040043f00000bc70440019700000b3e0040009c000023b20000c13d000000440030008c000023b20000413d000000040510037000000c30062001980000001f0720018f000000400400043d000000000164001900001fab0000613d000000000805034f0000000009040019000000008a08043c0000000009a90436000000000019004b000023930000c13d00001fab0000013d000000040230008c000023b20000413d000000000400043d00000bc604400197000000000501043b00000bc705500197000000000445019f000000000040043f000000440030008c000023b20000413d00000bc70440019700000b3e0040009c000023b20000c13d000000040510037000000c30062001980000001f0720018f000000400400043d000000000164001900001fab0000613d000000000805034f0000000009040019000000008a08043c0000000009a90436000000000019004b000023ad0000c13d00001fab0000013d000000400200043d000b00000002001d00000b3e01000041000000000012043500000004012000392c9b2c500000040f0000000b02000029000000000121004900000b280010009c00000b2801008041000000600110021000000b280020009c00000b28020080410000004002200210000000000121019f00002c9d00010430000000080300002900000b280030009c00000b2803008041000000400330021000000b280010009c00000b2801008041000000c001100210000000000131019f00000b3f011001c72c9b2c910000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000805700029000023db0000613d000000000801034f0000000809000029000000008a08043c0000000009a90436000000000059004b000023d70000c13d000000000006004b000023e80000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000026110000613d0000001f01400039000000600210018f0000000801200029000000000021004b0000000002000039000000010200403900000b2b0010009c000000690000213d0000000100200190000000690000c13d000000400010043f000000200030008c000000540000413d00000008020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b000000540000c13d000000000002004b00001d090000613d000021530000013d000000080300002900000b280030009c00000b2803008041000000400330021000000b280010009c00000b2801008041000000c001100210000000000131019f00000bb5011001c72c9b2c910000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000008057000290000241b0000613d000000000801034f0000000809000029000000008a08043c0000000009a90436000000000059004b000024170000c13d000000000006004b000024280000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f00000001002001900000261d0000613d0000001f01400039000000600210018f0000000801200029000000000021004b0000000002000039000000010200403900000b2b0010009c000000690000213d0000000100200190000000690000c13d000000400010043f000000200040008c000000540000413d00000008020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b000000540000c13d000000000002004b00001d560000613d00000020021000390000000b0300002900000000003204350000000902000029000000000021043500000b280010009c00000b28010080410000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000bc0011001c70000800d02000039000000030300003900000c0e040000410000000a05000029000000000600041100000a1c0000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000245c0000c13d00001af40000013d000000080200002900000040022000390000000002020433000000ff032002700000001b03300039000000200030043f00000bcf02200197000000600020043f000000000010043f00000007010000290000000001010433000000400010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bd0011001c700000001020000392c9b2c960000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0540018f000000200640019000000001046001bf000024830000613d000000000701034f0000000108000039000000007907043c0000000008980436000000000048004b0000247f0000c13d000000010220018f000000000005004b000024910000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000000003001f0000000001020433000000600000043f0000000b02000029000000400020043f000000000003004b00001f140000613d0000001102000039000000000202041a000000000112013f00000b2d00100198000025c10000c13d000000800100043d000000000001004b00000a1f0000613d000000000200041100050b2d0020019b000b00000000001d0000000a0200002900000000020204330000000b0020006c000025bb0000a13d0000000b020000290000000503200210000700000003001d00000009023000290000000002020433000000000002004b000025120000613d0000001701000039000000000101041a000000400400043d0000004403400039000000000023043500000b2d011001970000002402400039000000000012043500000bd3010000410000000000140435000800000004001d00000004014000390000000502000029000000000021043500000bb8010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb9011001c700008005020000392c9b2c960000040f0000000100200190000025ba0000613d000000000201043b000000000100041400000b2d02200197000000040020008c000024d30000c13d0000000004000031000000200040008c0000002004008039000024fb0000013d000000080300002900000b280030009c00000b2803008041000000400330021000000b280010009c00000b2801008041000000c001100210000000000131019f00000b3f011001c72c9b2c910000040f000000600310027000000b2803300197000000200030008c0000002004000039000000000403401900000020064001900000000805600029000024eb0000613d000000000701034f0000000808000029000000007907043c0000000008980436000000000058004b000024e70000c13d0000001f07400190000024f80000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000000000003001f0000000100200190000026f50000613d0000001f01400039000000600210018f0000000801200029000000000021004b0000000002000039000000010200403900000b2b0010009c000000690000213d0000000100200190000000690000c13d000000400010043f000000200040008c000000540000413d00000008020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b000000540000c13d000000000002004b00001d090000613d000000800100043d0000000b0010006c000025bb0000a13d0000000701000029000000a001100039000700000001001d0000000001010433000000000010043f0000000c01000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000201041a000000010220003a0000189c0000613d000000000021041b000000800100043d0000000b0010006c000025bb0000a13d000000400100043d0000000002000411000000000002004b000026e20000613d00000b320010009c000000690000213d000000070200002900000000030204330000004002100039000000400020043f0000002002100039000800000003001d000000000032043500000001020000390000000000210435000000400100043d00000b320010009c000000690000213d0000004002100039000000400020043f0000002002100039000000010300003900000000003204350000000000310435000000400100043d00000bf30010009c000000690000213d0000002002100039000000400020043f00000000000104350000000801000029000000000010043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b000000000101041a000600000001001d000000000001004b000026eb0000613d0000000801000029000000000010043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000002000411000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000000540000613d000000000101043b0000000602000029000000010220008a000000000021041b000000400100043d0000002002100039000000010300003900000000003204350000000802000029000000000021043500000b280010009c00000b28010080410000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000bc0011001c70000800d02000039000000040300003900000bc4040000410000000005000411000000000605001900000000070000192c9b2c910000040f0000000100200190000000540000613d000000400100043d00000bf30010009c000000690000213d0000002002100039000000400020043f0000000000010435000000800100043d0000000b0010006c000025bb0000a13d00000007010000290000000005010433000000000100041400000b280010009c00000b2801008041000000c00110021000000b36011001c70000800d02000039000000030300003900000bf70400004100000000060004112c9b2c910000040f0000000100200190000000540000613d0000000b02000029000b00010020003d000000800100043d0000000b0010006b000024a30000413d00000a1f0000013d000000000001042f00000c1401000041000000000010043f0000003201000039000000040010043f00000bbb0100004100002c9d0001043000000bd1010000410000000b02000029000000000012043500000b280020009c00000b2802008041000000400120021000000bc2011001c700002c9d00010430000000400100043d00000c0d02000041000011f50000013d000000080200002900000b280020009c00000b2802008041000000400220021000000b280010009c00000b2801008041000000c001100210000000000121019f00000b3f011001c700000005020000292c9b2c910000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000805700029000025e60000613d000000000801034f0000000809000029000000008a08043c0000000009a90436000000000059004b000025e20000c13d000000000006004b000025f30000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000026290000613d0000001f01400039000000600110018f0000000803100029000000000013004b00000000020000390000000102004039000400000003001d00000b2b0030009c000000690000213d0000000100200190000000690000c13d0000000402000029000000400020043f000000200040008c000000540000413d00000008020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b000000540000c13d000000000002004b000026760000c13d00000bd4010000410000000402000029000025c30000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000026180000c13d00001af40000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000026240000c13d00001af40000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000026300000c13d00001af40000013d000000040100002900000b280010009c00000b2801008041000000400110021000000b280020009c00000b2802008041000000c002200210000000000112019f00000b3f011001c700000005020000292c9b2c910000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000004057000290000264f0000613d000000000801034f0000000409000029000000008a08043c0000000009a90436000000000059004b0000264b0000c13d000000000006004b0000265c0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000026970000613d0000001f01400039000000600110018f000000040110002900000b2b0010009c000000690000213d000000400010043f000000200030008c000000540000413d00000004020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b000000540000c13d000000000002004b00001d090000613d00000000010004110000000b0200002900000006030000292c9b29a00000040f000000000100001900002c9c0001042e000000060300002900000007023000290000001703000039000000000303041a00000004050000290000004404500039000000000024043500000b2d023001970000002403500039000000000023043500000bd302000041000000000025043500000004025000390000000a03000029000000000032043500000000020004140000000503000029000000040030008c000026a30000c13d000000040110002900000b2b0010009c000000690000213d000000400010043f00000004020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b000000540000c13d000000000002004b00001d090000613d000020580000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000269e0000c13d00001af40000013d000000040100002900000b280010009c00000b2801008041000000400110021000000b280020009c00000b2802008041000000c002200210000000000112019f00000b3f011001c700000005020000292c9b2c910000040f000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000405700029000026bd0000613d000000000801034f0000000409000029000000008a08043c0000000009a90436000000000059004b000026b90000c13d000000000006004b000026ca0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000100200190000026d60000613d0000001f01400039000000600110018f000000040110002900000b2b0010009c000000690000213d000000400010043f000000200030008c0000268d0000813d000000540000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000026dd0000c13d00001af40000013d000000640210003900000bfa030000410000000000320435000000440210003900000bfb0300004100000000003204350000002402100039000000230300003900001b470000013d000000400100043d000000640210003900000bf8030000410000000000320435000000440210003900000bf90300004100000000003204350000002402100039000000240300003900001b470000013d0000001f0530018f00000b2a06300198000000400200043d000000000462001900001af40000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000026fc0000c13d00001af40000013d0000001f0220003900000c30022001970000000001120019000000000021004b0000000002000039000000010200403900000b2b0010009c0000270d0000213d00000001002001900000270d0000c13d000000400010043f000000000001042d00000c1401000041000000000010043f0000004101000039000000040010043f00000bbb0100004100002c9d00010430000000000003004b0000271d0000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000034004b000027160000413d00000000012300190000000000010435000000000001042d00000000430104340000000001320436000000000003004b0000272c0000613d000000000200001900000000051200190000000006240019000000000606043300000000006504350000002002200039000000000032004b000027250000413d000000000213001900000000000204350000001f0230003900000c30022001970000000001210019000000000001042d00000020030000390000000004310436000000000302043300000000003404350000004001100039000000000003004b000027410000613d00000000040000190000002002200039000000000502043300000b2d0550019700000000015104360000000104400039000000000034004b0000273a0000413d000000000001042d000000000301001900000000040104330000000001420436000000000004004b0000274e0000613d00000000020000190000002003300039000000000503043300000000015104360000000102200039000000000042004b000027480000413d000000000001042d00000044010000390000000101100367000000000101043b000000000001004b0000000002000039000000010200c039000000000021004b000027580000c13d000000000001042d000000000100001900002c9d0001043000000024010000390000000101100367000000000101043b000000000001004b0000000002000039000000010200c039000000000021004b000027630000c13d000000000001042d000000000100001900002c9d00010430000100000000000200010b2d0010019c000027850000613d000000000020043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000027830000613d000000000101043b0000000102000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000027830000613d000000000101043b000000000101041a000000000001042d000000000100001900002c9d00010430000000400100043d000000640210003900000c08030000410000000000320435000000440210003900000c0903000041000000000032043500000024021000390000002a03000039000000000032043500000b3e02000041000000000021043500000004021000390000002003000039000000000032043500000b280010009c00000b2801008041000000400110021000000b42011001c700002c9d00010430000000000301001900000000011200a9000000000003004b000027a00000613d00000000033100d9000000000023004b000027a10000c13d000000000001042d00000c1401000041000000000010043f0000001101000039000000040010043f00000bbb0100004100002c9d00010430000000000212004900000bcf0020009c000027b30000213d0000001f0020008c000027b30000a13d0000000001010433000000000001004b0000000002000039000000010200c039000000000021004b000027b30000c13d000000000001042d000000000100001900002c9d00010430000400000000000200000b3502000041000000000202041a00000b2d032001970000000002000411000000000032004b0000284d0000c13d00000bb2020000410000000000200443000200000001001d0000000400100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f0000000100200190000028500000613d0000000102000039000000020300002900000b2d05300197000000000101043b000000000001004b000200000005001d000028290000613d000000400b00043d00000bfe0100004100000000001b04350000000401b0003900000000000104350000000001000414000000040050008c000027e00000c13d0000000001000415000000040110008a00000005011002100000000003000031000000200030008c00000020040000390000000004034019000028110000013d00000b2800b0009c00000b280200004100000000020b4019000000400220021000000b280010009c00000b2801008041000000c001100210000000000121019f00000bbb011001c7000000000205001900010000000b001d2c9b2c960000040f000000010b000029000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000027fc0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000027f80000c13d000000000006004b000028090000613d000000000171034f0000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f0000000000150435000000000003001f0000000001000415000000030110008a0000000501100210000000010020019000000002050000290000000102000039000028290000613d0000001f02400039000000600420018f0000000002b40019000000000042004b0000000004000039000000010400403900000b2b0020009c000028580000213d0000000100400190000028580000c13d000000400020043f0000001f0030008c0000284b0000a13d00000000020b0433000000000002004b0000000003000039000000010300c039000000000032004b0000284b0000c13d0000000501100270000000000102001f000000000002004b00000000020000390000000102006039000000400100043d000000000005004b0000282e0000613d0000000100200190000028510000c13d0000000302000039000000000302041a00000020021000390000000000520435000100000003001d00000b2d02300197000000000021043500000b280010009c00000b28010080410000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000bc0011001c70000800d02000039000000010300003900000bff040000412c9b2c910000040f000000020300002900000001002001900000284b0000613d000000010100002900000b3b01100197000000000131019f0000000302000039000000000012041b000000000001042d000000000100001900002c9d00010430000000400100043d00000bd202000041000028520000013d000000000001042f00000c0002000041000000000021043500000b280010009c00000b2801008041000000400110021000000bc2011001c700002c9d0001043000000c1401000041000000000010043f0000004101000039000000040010043f00000bbb0100004100002c9d000104300006000000000002000500000002001d000600000001001d000000000010043f0000000601000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000028ec0000613d000000400400043d00000c360040009c000028ee0000813d000000000101043b0000010002400039000000400020043f000000000201041a00000000022404360000000103100039000000000303041a00000000003204350000000202100039000000000202041a000000400340003900000000002304350000000302100039000000000202041a0000006003400039000400000003001d00000000002304350000000402100039000000000202041a0000008003400039000100000003001d00000000002304350000000502100039000000000202041a000000a003400039000200000003001d00000000002304350000000602100039000000000202041a000000c0034000390000000000230435000300000004001d000000e0024000390000000701100039000000000101041a00000000001204350000000601000029000000000010043f0000000701000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000028ec0000613d000000000101043b000000050200002900000b2d02200197000600000002001d000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000028ec0000613d000000000101043b000000000101041a000000ff00100190000028e80000613d00000004010000290000000002010433000000000002004b000028e80000613d0000000301000029000000000301043300000002010000290000000001010433000000000031004b0000000001000019000028e90000813d00000001010000290000000001010433000000000031004b000028ea0000a13d000400000001001d000500000003001d000000400100043d00000040031000390000000604000029000000000043043500000040030000390000000003310436000000000023043500000c020010009c000028ee0000213d0000006002100039000000400020043f00000b280030009c00000b28030080410000004002300210000000000101043300000b280010009c00000b28010080410000006001100210000000000121019f000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000b36011001c700008010020000392c9b2c960000040f0000000100200190000028ec0000613d000000000101043b00000004101000fa000000050010006c00000000010000390000000101004039000000000001042d0000000001000019000000000001042d0000000101000039000000000001042d000000000100001900002c9d0001043000000c1401000041000000000010043f0000004101000039000000040010043f00000bbb0100004100002c9d0001043000000b3501000041000000000101041a0000000002000411000000000012004b000028fa0000c13d000000000001042d00000c2a01000041000000000010043f00000bbe0100004100002c9d000104300004000000000002000000400400043d00040b2d0010019c000029790000613d00000c370040009c000029730000813d0000004001400039000000400010043f0000002001400039000000000021043500000001010000390000000000140435000000400400043d00000b320040009c000029730000213d0000004005400039000000400050043f000000200540003900000000003504350000000000140435000000400100043d00000bf30010009c000029730000213d000300000003001d0000002003100039000000400030043f0000000000010435000200000002001d000000000020043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000029710000613d000000000101043b0000000402000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000029710000613d000000000101043b000000000101041a00010003001000740000298c0000413d0000000201000029000000000010043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000029710000613d000000000101043b0000000402000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f0000000100200190000029710000613d000000000101043b0000000102000029000000000021041b000000400100043d0000002002100039000000030300002900000000003204350000000202000029000000000021043500000b280010009c00000b28010080410000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000bc0011001c70000800d020000390000000403000039000000000500041100000bc404000041000000040600002900000000070000192c9b2c910000040f0000000100200190000029710000613d000000400100043d00000bf30010009c000029730000213d0000002002100039000000400020043f0000000000010435000000000001042d000000000100001900002c9d0001043000000c1401000041000000000010043f0000004101000039000000040010043f00000bbb0100004100002c9d00010430000000640140003900000bfa030000410000000000310435000000440140003900000bfb03000041000000000031043500000024014000390000002303000039000000000031043500000b3e01000041000000000014043500000004014000390000002003000039000000000031043500000b280040009c00000b2804008041000000400140021000000b42011001c700002c9d00010430000000400100043d000000640210003900000bf8030000410000000000320435000000440210003900000bf903000041000000000032043500000024021000390000002403000039000000000032043500000b3e02000041000000000021043500000004021000390000002003000039000000000032043500000b280010009c00000b2801008041000000400110021000000b42011001c700002c9d000104300008000000000002000400000003001d000300000001001d000600000002001d000000000020043f0000000901000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f000000010020019000002ad40000613d000000000101043b000000000101041a000000ff0010019000002adc0000c13d00000004010000290000000501100039000000000101041a00000be6001001980000000a02000039000029cd0000c13d0000000601000029000000000010043f000000200020043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f000000010020019000002ad40000613d0000000402000029000000000202041a000000000101043b000000000101041a000000000021004b0000000a0200003900002af90000813d0000000601000029000000000010043f000000200020043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f000000010020019000002ad40000613d000000000101043b000000000201041a000000010220003a00002ad60000613d000000000021041b000000400400043d00000c3a0040009c00002b680000813d0000002003400039000000400030043f0000000000040435000000400100043d000000030200002900050b2d0020019c00002adf0000613d000200000003001d00000b320010009c00002b680000213d0000004002100039000000400020043f00000020021000390000000603000029000000000032043500000001030000390000000000310435000000400100043d00000b320010009c00002b680000213d000100000004001d0000004002100039000000400020043f0000002002100039000000000032043500000000003104350000000601000029000000000010043f000000200000043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f000000010020019000002ad40000613d000000000101043b0000000502000029000000000020043f000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f000000010020019000002ad40000613d000000000101043b000000000201041a000000010220003a00002ad60000613d000000000021041b000000400100043d0000002002100039000000010300003900000000003204350000000602000029000000000021043500000b280010009c00000b28010080410000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000bc0011001c70000800d020000390000000403000039000000000500041100000bc404000041000000000600001900000005070000292c9b2c910000040f000000010020019000002ad40000613d00000bb201000041000000000010044300000003010000290000000400100443000000000100041400000b280010009c00000b2801008041000000c00110021000000bb3011001c700008002020000392c9b2c960000040f000000010020019000002af20000613d000000400b00043d000000000101043b000000000001004b000000020600002900002aba0000613d0000008401b00039000000a00200003900000000002104350000006401b00039000000010200003900000000002104350000004401b000390000000602000029000000000021043500000bc50100004100000000001b04350000000401b00039000000000200041100000000002104350000002401b00039000000000001043500000001010000290000000001010433000000a402b000390000000000120435000000c402b00039000000000001004b00002a620000613d000000000300001900000000042300190000000005630019000000000505043300000000005404350000002003300039000000000013004b00002a5b0000413d0000000002210019000000000002043500000000040004140000000502000029000000040020008c00002a700000c13d0000000005000415000000080550008a00000005055002100000000003000031000000200030008c0000002004000039000000000403401900002aa40000013d0000001f0110003900000c3001100197000000c40110003900000b280010009c00000b2801008041000000600110021000000b2800b0009c00000b280300004100000000030b40190000004003300210000000000131019f00000b280040009c00000b2804008041000000c003400210000000000113019f00030000000b001d2c9b2c910000040f000000030b000029000000600310027000000b2803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900002a910000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00002a8d0000c13d000000000006004b00002a9e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000000003001f0000000005000415000000070550008a0000000505500210000000010020019000002b010000613d0000001f01400039000000600110018f0000000004b10019000000000014004b0000000001000039000000010100403900000b2b0040009c00002b680000213d000000010010019000002b680000c13d000000400040043f000000200030008c00002ad40000413d00000000010b043300000bc60010019800002ad40000c13d0000000502500270000000000201001f00000bc70110019700000bc50010009c00002af30000c13d000000000b04001900000004010000290000000101100039000000000101041a0000001202000039000000000202041a0000002003b00039000000000023043500000000001b043500000b2800b0009c00000b280b0080410000004001b00210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000bc0011001c70000800d02000039000000030300003900000bf404000041000000060500002900000005060000292c9b2c910000040f000000010020019000002ad40000613d000000000001042d000000000100001900002c9d0001043000000c1401000041000000000010043f0000001101000039000000040010043f00000bbb0100004100002c9d00010430000000400100043d00000c380200004100002afb0000013d000000640210003900000bf5030000410000000000320435000000440210003900000bf603000041000000000032043500000024021000390000002103000039000000000032043500000b3e02000041000000000021043500000004021000390000002003000039000000000032043500000b280010009c00000b2801008041000000400110021000000b42011001c700002c9d00010430000000000001042f00000b3e0100004100000000001404350000000401400039000600000004001d2c9b2c430000040f00002b3c0000013d000000400100043d00000c3902000041000000000021043500000b280010009c00000b2801008041000000400110021000000bc2011001c700002c9d00010430000000040230008c00002b360000413d000000000400043d00000bc604400197000000000501043b00000bc705500197000000000445019f000000000040043f000000440030008c00002b360000413d00000bc70440019700000b3e0040009c00002b360000c13d000000040510037000000c30062001980000001f0720018f000000400400043d000000000164001900002b1a0000613d000000000805034f0000000009040019000000008a08043c0000000009a90436000000000019004b00002b160000c13d000000000007004b00002b270000613d000000000565034f0000000306700210000000000701043300000000076701cf000000000767022f000000000505043b0000010006600089000000000565022f00000000056501cf000000000575019f0000000000510435000000000504043300000b2b0050009c00002b360000213d0000002401500039000000000031004b00002b360000213d0000000001450019000000000301043300000b2b0030009c00002b360000213d000000000224001900000000063100190000002006600039000000000026004b00002b460000a13d000000400200043d000600000002001d00000b3e01000041000000000012043500000004012000392c9b2c500000040f0000000602000029000000000121004900000b280010009c00000b2801008041000000600110021000000b280020009c00000b28020080410000004002200210000000000121019f00002c9d0001043000000000023500190000003f0220003900000c30022001970000000004420019000000000024004b0000000002000039000000010200403900000b2b0040009c00002b680000213d000000010020019000002b680000c13d0000000003040019000000400040043f000000000001004b00002b360000613d00000b3e020000410000000004030019000600000003001d000000000023043500000004023000390000002003000039000000000032043500000024024000392c9b27200000040f0000000602000029000000000121004900000b280010009c00000b280100804100000b280020009c00000b280200804100000060011002100000004002200210000000000121019f00002c9d0001043000000c1401000041000000000010043f0000004101000039000000040010043f00000bbb0100004100002c9d00010430000b0000000000020000001009000039000000000a09041a000000010aa000390000000000a9041b000000000028001a00002c3d0000413d000000400b00043d00000bf200b0009c00002c370000213d00000000022800190000010009b00039000000400090043f000000e009b00039000100000008001d000900000009001d0000000000890435000000000004004b0000000004000039000000010400c039000000c008b00039000800000008001d00000000004804350000008004b00039000600000004001d00000000007404350000006004b00039000500000004001d00000000006404350000004004b00039000300000004001d00000000005404350000002004b00039000200000004001d000000000034043500000000002b043500000b2d0110019700070000000b001d000000a002b00039000a00000001001d000400000002001d00000000001204350000000000a0043f0000000801000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c70000801002000039000b00000003001d2c9b2c960000040f000000010020019000002c350000613d00000007020000290000000002020433000000000101043b000000000021041b000000020200002900000000020204330000000103100039000000000023041b000000030200002900000000020204330000000203100039000000000023041b000000050200002900000000020204330000000303100039000000000023041b000000060200002900000000020204330000000403100039000000000023041b0000000402000029000000000202043300000b2d022001970000000503100039000000000403041a00000c3b04400197000000000224019f00000008040000290000000004040433000000000004004b00000c3c040000410000000004006019000000000242019f000000000023041b000000060110003900000009020000290000000002020433000000000021041b0000001001000039000000000501041a000000400100043d0000000b02000029000000000021043500000b280010009c00000b28010080410000004001100210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000b33011001c70000800d02000039000000030300003900000c3d04000041000900000005001d0000000a060000292c9b2c910000040f000000010020019000002c350000613d0000000b050000290000000104000029000000000004004b00002c320000613d000000400600043d00000bf20060009c00002c370000213d0000001301000039000000000101041a0000001402000039000000000202041a0000010003600039000000400030043f000000e003600039000a00000003001d0000000000230435000000c002600039000800000002001d00000000001204350000002001600039000500000001001d00000000005104350000000000460435000000a001600039000700000001001d00000000000104350000008001600039000600000001001d00000000000104350000006001600039000400000001001d0000000000010435000b00000006001d0000004001600039000300000001001d00000000000104350000000901000029000000000010043f0000000601000039000000200010043f000000000100041400000b280010009c00000b2801008041000000c00110021000000bc0011001c700008010020000392c9b2c960000040f000000010020019000002c350000613d0000000b020000290000000002020433000000000101043b000000000021041b000000050200002900000000020204330000000103100039000000000023041b000000030200002900000000020204330000000203100039000000000023041b000000040200002900000000020204330000000303100039000000000023041b000000060200002900000000020204330000000403100039000000000023041b000000070200002900000000020204330000000503100039000000000023041b000000080200002900000000020204330000000603100039000000000023041b00000007011000390000000a020000290000000002020433000000000021041b0000001001000039000000000101041a000000000001042d000000000100001900002c9d0001043000000c1401000041000000000010043f0000004101000039000000040010043f00000bbb0100004100002c9d0001043000000c1401000041000000000010043f0000001101000039000000040010043f00000bbb0100004100002c9d00010430000000600210003900000c3e030000410000000000320435000000400210003900000c3f030000410000000000320435000000200210003900000028030000390000000000320435000000200200003900000000002104350000008001100039000000000001042d000000600210003900000c40030000410000000000320435000000400210003900000c41030000410000000000320435000000200210003900000034030000390000000000320435000000200200003900000000002104350000008001100039000000000001042d000000000001042f00000b280010009c00000b2801008041000000400110021000000b280020009c00000b28020080410000006002200210000000000112019f000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000b36011001c700008010020000392c9b2c960000040f000000010020019000002c710000613d000000000101043b000000000001042d000000000100001900002c9d0001043000000000050100190000000000200443000000050030008c00002c810000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b00002c790000413d00000b280030009c00000b28030080410000006001300210000000000200041400000b280020009c00000b2802008041000000c002200210000000000112019f00000c42011001c700000000020500192c9b2c960000040f000000010020019000002c900000613d000000000101043b000000000001042d000000000001042f00002c94002104210000000102000039000000000001042d0000000002000019000000000001042d00002c99002104230000000102000039000000000001042d0000000002000019000000000001042d00002c9b0000043200002c9c0001042e00002c9d000104300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000000000000000000000000000ffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000ffffffffffffffffffffffffbfa87805ed57dc1f0d489ce33be4c4577d74ccde357eeeee058a32c55c44a532405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5acebfa87805ed57dc1f0d489ce33be4c4577d74ccde357eeeee058a32c55c44a531000000000000000000000000000000000000000000000000ffffffffffffffbf02000000000000000000000000000000000000200000000000000000000000008a8bae378cb731c5c40b632330c6836c2f916f48edb967699c86736f9a6a76efffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392702000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e027cceb82823caa45ba60387709961a73050623da2232f8fd178296384aedbd77d833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b512428927cceb82823caa45ba60387709961a73050623da2232f8fd178296384aedbd76ffffffffffffffffffffffff00000000000000000000000000000000000000000000000200000000000000000000000000000080000001000000000000000000455243323938313a20696e76616c69642072656365697665720000000000000008c379a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000640000000000000000000000002073616c65507269636500000000000000000000000000000000000000000000455243323938313a20726f79616c7479206665652077696c6c20657863656564000000000000000000000000000000000000008400000000000000000000000000000000000000000000000000000000000000000000000000000000715018a500000000000000000000000000000000000000000000000000000000b2db919a00000000000000000000000000000000000000000000000000000000def25aca00000000000000000000000000000000000000000000000000000000f242432900000000000000000000000000000000000000000000000000000000fa914ed400000000000000000000000000000000000000000000000000000000fa914ed500000000000000000000000000000000000000000000000000000000fd762d9200000000000000000000000000000000000000000000000000000000fee81cf400000000000000000000000000000000000000000000000000000000f242432a00000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000e985e9c400000000000000000000000000000000000000000000000000000000e985e9c500000000000000000000000000000000000000000000000000000000eefdc1df00000000000000000000000000000000000000000000000000000000f04e283e00000000000000000000000000000000000000000000000000000000def25acb00000000000000000000000000000000000000000000000000000000e74b981b00000000000000000000000000000000000000000000000000000000d007af5b00000000000000000000000000000000000000000000000000000000d8d07ed900000000000000000000000000000000000000000000000000000000d8d07eda00000000000000000000000000000000000000000000000000000000ddca3f4300000000000000000000000000000000000000000000000000000000ddf0b00900000000000000000000000000000000000000000000000000000000d007af5c00000000000000000000000000000000000000000000000000000000d4f4ddaa00000000000000000000000000000000000000000000000000000000be537f4200000000000000000000000000000000000000000000000000000000be537f4300000000000000000000000000000000000000000000000000000000c0bc62f700000000000000000000000000000000000000000000000000000000c6af66b900000000000000000000000000000000000000000000000000000000b2db919b00000000000000000000000000000000000000000000000000000000b4b5b48f000000000000000000000000000000000000000000000000000000008da5cb5a000000000000000000000000000000000000000000000000000000009d645a4300000000000000000000000000000000000000000000000000000000a22cb46400000000000000000000000000000000000000000000000000000000a22cb46500000000000000000000000000000000000000000000000000000000a9fc664e00000000000000000000000000000000000000000000000000000000ae796ab3000000000000000000000000000000000000000000000000000000009d645a44000000000000000000000000000000000000000000000000000000009d7f4ebf0000000000000000000000000000000000000000000000000000000095be539f0000000000000000000000000000000000000000000000000000000095be53a00000000000000000000000000000000000000000000000000000000095d89b410000000000000000000000000000000000000000000000000000000096949420000000000000000000000000000000000000000000000000000000008da5cb5b0000000000000000000000000000000000000000000000000000000091eb290e000000000000000000000000000000000000000000000000000000007f631e460000000000000000000000000000000000000000000000000000000083e096cd0000000000000000000000000000000000000000000000000000000083e096ce0000000000000000000000000000000000000000000000000000000089a30271000000000000000000000000000000000000000000000000000000008d1d9520000000000000000000000000000000000000000000000000000000007f631e4700000000000000000000000000000000000000000000000000000000809a619e000000000000000000000000000000000000000000000000000000007ecebdff000000000000000000000000000000000000000000000000000000007ecebe00000000000000000000000000000000000000000000000000000000007f58b4bf00000000000000000000000000000000000000000000000000000000715018a6000000000000000000000000000000000000000000000000000000007d5c3ff1000000000000000000000000000000000000000000000000000000002e1a7d4c000000000000000000000000000000000000000000000000000000005beaa0480000000000000000000000000000000000000000000000000000000069fe0e2c000000000000000000000000000000000000000000000000000000006c19e782000000000000000000000000000000000000000000000000000000006c19e783000000000000000000000000000000000000000000000000000000006c3b8699000000000000000000000000000000000000000000000000000000006e85a0d90000000000000000000000000000000000000000000000000000000069fe0e2d000000000000000000000000000000000000000000000000000000006c0360eb00000000000000000000000000000000000000000000000000000000612107da00000000000000000000000000000000000000000000000000000000612107db00000000000000000000000000000000000000000000000000000000613471620000000000000000000000000000000000000000000000000000000062914849000000000000000000000000000000000000000000000000000000005beaa049000000000000000000000000000000000000000000000000000000005d4c1d460000000000000000000000000000000000000000000000000000000042d96dd6000000000000000000000000000000000000000000000000000000004e1273f3000000000000000000000000000000000000000000000000000000004e1273f40000000000000000000000000000000000000000000000000000000054d1f13d000000000000000000000000000000000000000000000000000000005b7633d00000000000000000000000000000000000000000000000000000000042d96dd700000000000000000000000000000000000000000000000000000000495c8bf9000000000000000000000000000000000000000000000000000000002eb2c2d5000000000000000000000000000000000000000000000000000000002eb2c2d6000000000000000000000000000000000000000000000000000000002fc47b24000000000000000000000000000000000000000000000000000000002e1a7d4d000000000000000000000000000000000000000000000000000000002e8da829000000000000000000000000000000000000000000000000000000000e89341b000000000000000000000000000000000000000000000000000000001b25b076000000000000000000000000000000000000000000000000000000001ed74927000000000000000000000000000000000000000000000000000000001ed749280000000000000000000000000000000000000000000000000000000025692962000000000000000000000000000000000000000000000000000000002a55205a000000000000000000000000000000000000000000000000000000001b25b077000000000000000000000000000000000000000000000000000000001c33b32800000000000000000000000000000000000000000000000000000000134954b700000000000000000000000000000000000000000000000000000000134954b8000000000000000000000000000000000000000000000000000000001647795e000000000000000000000000000000000000000000000000000000001b24e9df000000000000000000000000000000000000000000000000000000000e89341c000000000000000000000000000000000000000000000000000000000fa7b7b30000000000000000000000000000000000000000000000000000000002fe53040000000000000000000000000000000000000000000000000000000006fdde020000000000000000000000000000000000000000000000000000000006fdde0300000000000000000000000000000000000000000000000000000000098144d4000000000000000000000000000000000000000000000000000000000dce83c70000000000000000000000000000000000000000000000000000000002fe53050000000000000000000000000000000000000000000000000000000004845e3e000000000000000000000000000000000000000000000000000000000146354500000000000000000000000000000000000000000000000000000000014635460000000000000000000000000000000000000000000000000000000001ffc9a700000000000000000000000000000000000000000000000000000000009a9b7b0000000000000000000000000000000000000000000000000000000000fdd58e00000000000000000000000000000000000000000000000000000000389a75e100000000000000000000000000000000000000200000008000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffff1806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b830200000200000000000000000000000000000024000000000000000000000000da0194c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000000000000000000000002304aa02000000000000000000000000000000000000000000000000000000008d74431400000000000000000000000000000000000000000000000000000000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e020000020000000000000000000000000000004400000000000000000000000070a08231000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000a9059cbb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007448fbae00000000000000000000000000000000000000040000001c0000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7f02000000000000000000000000000000000000400000000000000000000000008ee600cb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000285fb8c800000000000000000000000000000000000000000000000000000000c3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62f23a6e610000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000200000000c0000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d955391320200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000006f5e8818000000000000000000000000000000000000000000000000ffffffffffffff3f0000000019457468657265756d205369676e6564204d6573736167653a0a3332020000000000000000000000000000000000003c0000000400000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000800000000000000000000000008baa579f000000000000000000000000000000000000000000000000000000002d0a346e0000000000000000000000000000000000000000000000000000000023b872dd00000000000000000000000000000000000000000000000000000000f499da2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffe9f0000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000010000000080000000000000000048b6e6df0000000000000000000000000000000000000000000000000000000042cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd180b41246c05cbb406f874e82aa2faf7db11bba9792fe09929e56ef1eee2c2da3c212ef7d00000000000000000000000000000000000000000000000000000000feea0d9900000000000000000000000000000000000000000000000000000000bd8c6ccc00000000000000000000000000000000000000000000000000000000b955455200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000080000000000000000017e94a6c000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe02f34bba70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000008000000000000000000000000000000000000000000000000000000024000000e0000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000ff00000000000000000000000000000000000000007820c10a00000000000000000000000000000000000000000000000000000000321aa27e9c5c4ca98453ba7da9a1af4aa7bfed3bab5098e02fee58ce3cafe6b7cbe4e8c30000000000000000000000000000000000000000000000000000000017307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31455243313135353a2073657474696e6720617070726f76616c2073746174757320666f722073656c66000000000000000000000000000000000000000000000000000000000000000000000000000000000000840000008000000000000000009445f53000000000000000000000000000000000000000000000000000000000f91d7f9b00000000000000000000000000000000000000000000000000000000ad3d6587006c45fb2f92060267e172188795374f8f5bdf4187d50c571cce287fc19c461c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffeff000000000000000000000000000000000000000000000000ffffffffffffffdf81fd5f457056a8b19e623dc52551a385bfcafd0914d3942446ecab71d19b123b7300000000000000000000000000000000000000000000000000000000000000455243313135353a206d696e7420746f20746865207a65726f20616464726573ecb0813fff72f72d5c424535fe69f97316a856e5cd5830226c189a4a8662e2c1616e636500000000000000000000000000000000000000000000000000000000455243313135353a206275726e20616d6f756e7420657863656564732062616c6573730000000000000000000000000000000000000000000000000000000000455243313135353a206275726e2066726f6d20746865207a65726f20616464720bd8a3eb000000000000000000000000000000000000000000000000000000000000000000000000000000000000721c310194ccfc01e523fc93c9cccfa2a0ac01ffc9a700000000000000000000000000000000000000000000000000000000cc5dc080ff977b3c3a211fa63ab74f90f658f5ba9d3236e92c8f59570f442aac32483afb0000000000000000000000000000000000000000000000000000000039ffc7ba00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff9f38685a6b00000000000000000000000000000000000000000000000000000000fa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92206d69736d617463680000000000000000000000000000000000000000000000455243313135353a206163636f756e747320616e6420696473206c656e67746800000000000000000000000000000000000000000000003fffffffffffffffe0616c6964206f776e657200000000000000000000000000000000000000000000455243313135353a2061646472657373207a65726f206973206e6f74206120763fe5df9900000000000000000000000000000000000000000000000000000000756688fe00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff5fbf7c9c2f00000000000000000000000000000000000000000000000000000000ed7318a9455ec161085222a6e508a46debace6235bba0202c768d3840f809c85000000000000000000000000000000000000000000000000000000008baa579f6572206f7220617070726f766564000000000000000000000000000000000000455243313135353a2063616c6c6572206973206e6f7420746f6b656e206f776e6d69736d61746368000000000000000000000000000000000000000000000000455243313135353a2069647320616e6420616d6f756e7473206c656e677468204e487b710000000000000000000000000000000000000000000000000000000072207472616e7366657200000000000000000000000000000000000000000000455243313135353a20696e73756666696369656e742062616c616e636520666f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fbbc197c81000000000000000000000000000000000000000000000000000000006472657373000000000000000000000000000000000000000000000000000000455243313135353a207472616e7366657220746f20746865207a65726f206164d72dde5e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000440000008000000000000000000000000000000000000000000000000000000040000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d00dbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1de6d0175500000000000000000000000000000000000000000000000000000000f342c3d80000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff30000000000000000000000000000000000000000000000000000000000000002f000000000000000000000000000000000000000000000000000000000000002b8acba10000000000000000000000000000000000000000000000000000000075e52f4f000000000000000000000000000000000000000000000000000000004b092bc80000000000000000000000000000000000000000000000000000000044594c49000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000082b429002a552059ffffffffffffffffffffffffffffffffffffffffffffffffffffffff2a55205a00000000000000000000000000000000000000000000000000000000d9b67a260000000000000000000000000000000000000000000000000000000086455d28000000000000000000000000000000000000000000000000000000000e89341c00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffafffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeff000000000000000000000000000000000000000000000000ffffffffffffff00000000000000000000000000000000000000000000000000ffffffffffffffc048c460c800000000000000000000000000000000000000000000000000000000d76288d700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffe0ffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000d8e6d657f706eb987a687ae78b967b4b1cf806551ebeb3a85471d9b8cf6c04a06420746f6b656e73000000000000000000000000000000000000000000000000455243313135353a204552433131353552656365697665722072656a65637465526563656976657220696d706c656d656e746572000000000000000000000000455243313135353a207472616e7366657220746f206e6f6e2d45524331313535020000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b84597c977aa66066946b5810539527a4387e2b35b35080bbe33d30a74cd851
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
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.