Feature Tip: Add private address tag to any address under My Name Tag !
ERC-721
Overview
Max Total Supply
25 ONCHAINOPEPEN
Holders
15
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
2 ONCHAINOPEPENLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
OnchainOpepen
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT /** * OnchainOpepens * * Burn OnchainRocks to get an OnchainOpepen * * Why? For the culture * * CC0. No owner, no royalties, no roadmap. * * Art fully on-chain * */ pragma solidity ^0.8.0; import {ERC721A} from "erc721a/ERC721A.sol"; import {IERC721A} from "erc721a/interfaces/IERC721A.sol"; import {ERC721ABurnable} from "erc721a/extensions/ERC721ABurnable.sol"; import {Base64} from "solady/utils/Base64.sol"; import {SSTORE2} from "solady/utils/SSTORE2.sol"; import {console2} from "forge-std/console2.sol"; import "./lib/DynamicBuffer.sol"; import "./lib/HelperLib.sol"; import {OnchainOpepenArt} from "./OnchainOpepenArt.sol"; struct TraitDTO { string name; string mimetype; uint256 occurrence; bytes data; bool hide; bool useExistingData; uint256 existingDataIndex; } struct Trait { string name; string mimetype; uint256 occurrence; address dataPointer; bool hide; } struct Layer { string name; uint256 primeNumber; uint256 numberOfTraits; } error InvalidInput(); error NotAvailable(); interface OnchainRocks { function transferFrom(address from, address to, uint256 tokenId) external; function tokenIdToHash(uint256 tokenId) external returns (string memory); function setApprovalForAll(address operator, bool approved) external; function balanceOf(address owner) external view returns (uint256); function hashToMetadata(string memory _hash) external view returns (string memory); function hashToSVG(string memory _hash) external view returns (string memory); function tokenURI(uint256 tokenId) external view returns (string memory); } contract OnchainOpepen is ERC721ABurnable { using HelperLib for string; using DynamicBuffer for bytes; mapping(uint256 => Layer) private layers; mapping(uint256 => mapping(uint256 => Trait)) private traits; mapping(uint256 => string) private hashOverride; OnchainRocks rocks; uint256 private numberOfLayers; uint256 public maxSupply; constructor(OnchainRocks _rocks) ERC721A("OnchainOpepen", "ONCHAINOPEPEN") { maxSupply = 250; rocks = _rocks; addArt(); } function addArt() public { // Background { TraitDTO[] memory _traits = new TraitDTO[](1); _traits[0] = TraitDTO("Bg", "image/png", 250, OnchainOpepenArt.bg, false, false, 0); addLayer(0, "Background", 263743197985470588204349265269345001644610514897601719492623, _traits, 2); } // Images { TraitDTO[] memory _traits = new TraitDTO[](11); _traits[0] = TraitDTO("Rock", "image/png", 250, OnchainOpepenArt.Rock, false, false, 0); _traits[1] = TraitDTO("Brown", "image/png", 250, OnchainOpepenArt.Brown, false, false, 0); _traits[2] = TraitDTO("Bleu", "image/png", 250, OnchainOpepenArt.Bleu, false, false, 0); _traits[3] = TraitDTO("Rouge", "image/png", 250, OnchainOpepenArt.Rouge, false, false, 0); _traits[4] = TraitDTO("Orange", "image/png", 250, OnchainOpepenArt.Orange, false, false, 0); _traits[5] = TraitDTO("Navy", "image/png", 250, OnchainOpepenArt.Navy, false, false, 0); _traits[6] = TraitDTO("Gold", "image/png", 250, OnchainOpepenArt.Gold, false, false, 0); _traits[7] = TraitDTO("Hell", "image/png", 250, OnchainOpepenArt.Hell, false, false, 0); _traits[8] = TraitDTO("Zombie", "image/png", 250, OnchainOpepenArt.Zombie, false, false, 0); _traits[9] = TraitDTO("Rip", "image/png", 250, OnchainOpepenArt.Rip, false, false, 0); _traits[10] = TraitDTO("Squi", "image/png", 250, OnchainOpepenArt.Squi, false, false, 0); addLayer(1, "Type", 773144458924271516429415765228637679419660582975860746246683, _traits, 2); } } function tokenIdToHash(uint256 tokenId) public view returns (string memory) { if (!_exists(tokenId)) { revert NotAvailable(); } return hashOverride[tokenId]; } function mint(uint256 tokenId1, uint256 tokenId2) external { rocks.transferFrom(msg.sender, address(0x000000000000000000000000000000000000dEaD), tokenId1); rocks.transferFrom(msg.sender, address(0x000000000000000000000000000000000000dEaD), tokenId2); _mint(msg.sender, 1); hashOverride[_nextTokenId() - 1] = rocks.tokenIdToHash(tokenId1); } // function mint__(string memory hash) public { // require(_nextTokenId() < 11, "Maximum limit reached"); // _mint(msg.sender, 1); // hashOverride[_nextTokenId() - 1] = hash; // } function hashToSVG(string memory _hash) public view returns (string memory) { uint256 thisTraitIndex; bytes memory svgBytes = DynamicBuffer.allocate(1024 * 128); svgBytes.appendSafe( '<svg width="1200" height="1200" viewBox="0 0 1200 1200" version="1.2" xmlns="http://www.w3.org/2000/svg" style="background-image:url(' ); for (uint256 i = 0; i < numberOfLayers - 1;) { thisTraitIndex = _hash.subStr((i * 3), (i * 3) + 3).parseInt(); svgBytes.appendSafe( abi.encodePacked( "data:", traits[i][thisTraitIndex].mimetype, ";base64,", Base64.encode(SSTORE2.read(traits[i][thisTraitIndex].dataPointer)), "),url(" ) ); unchecked { ++i; } } thisTraitIndex = _hash.subStr((numberOfLayers * 3) - 3, numberOfLayers * 3).parseInt(); svgBytes.appendSafe( abi.encodePacked( "data:", traits[numberOfLayers - 1][thisTraitIndex].mimetype, ";base64,", Base64.encode(SSTORE2.read(traits[numberOfLayers - 1][thisTraitIndex].dataPointer)), ');background-repeat:no-repeat;background-size:contain;background-position:center;image-rendering:-webkit-optimize-contrast;-ms-interpolation-mode:nearest-neighbor;image-rendering:-moz-crisp-edges;image-rendering:pixelated;"></svg>' ) ); return string(abi.encodePacked("data:image/svg+xml;base64,", Base64.encode(svgBytes))); } function hashToMetadata(string memory _hash) public view returns (string memory) { bytes memory metadataBytes = DynamicBuffer.allocate(1024 * 128); metadataBytes.appendSafe("["); bool afterFirstTrait; for (uint256 i = 0; i < numberOfLayers;) { uint256 thisTraitIndex = _hash.subStr((i * 3), (i * 3) + 3).parseInt(); if (traits[i][thisTraitIndex].hide == false) { if (afterFirstTrait) { metadataBytes.appendSafe(","); } metadataBytes.appendSafe( abi.encodePacked( '{"trait_type":"', layers[i].name, '","value":"', traits[i][thisTraitIndex].name, '"}' ) ); if (afterFirstTrait == false) { afterFirstTrait = true; } } if (i == numberOfLayers - 1) { metadataBytes.appendSafe("]"); } unchecked { ++i; } } return string(metadataBytes); } function tokenURI(uint256 tokenId) public view override(ERC721A, IERC721A) returns (string memory) { if (!_exists(tokenId)) { revert InvalidInput(); } bytes memory jsonBytes = DynamicBuffer.allocate(1024 * 128); jsonBytes.appendSafe( abi.encodePacked('{"name":"', name(), " #", _toString(tokenId), '","description":"OnchainOpepen",') ); string memory tokenHash = tokenIdToHash(tokenId); string memory svgCode = ""; string memory svgString = hashToSVG(tokenHash); svgCode = string( abi.encodePacked( "data:image/svg+xml;base64,", Base64.encode( abi.encodePacked( '<svg width="100%" height="100%" viewBox="0 0 1200 1200" version="1.2" xmlns="http://www.w3.org/2000/svg"><image width="1200" height="1200" href="', svgString, '"></image></svg>' ) ) ) ); jsonBytes.appendSafe(abi.encodePacked('"image_data":"', svgCode, '",')); jsonBytes.appendSafe(abi.encodePacked('"attributes":', hashToMetadata(tokenHash), "}")); return string(abi.encodePacked("data:application/json;base64,", Base64.encode(jsonBytes))); } function addLayer( uint256 index, string memory name, uint256 primeNumber, TraitDTO[] memory _traits, // change this from calldata to memory uint256 _numberOfLayers ) internal { layers[index] = Layer(name, primeNumber, _traits.length); numberOfLayers = _numberOfLayers; for (uint256 i = 0; i < _traits.length;) { address dataPointer; if (_traits[i].useExistingData) { dataPointer = traits[index][_traits[i].existingDataIndex].dataPointer; } else { dataPointer = SSTORE2.write(_traits[i].data); } traits[index][i] = Trait(_traits[i].name, _traits[i].mimetype, _traits[i].occurrence, dataPointer, _traits[i].hide); unchecked { ++i; } } return; } function numberMinted(address owner) public view returns (uint256) { return _numberMinted(owner); } function totalMinted() public view returns (uint256) { return _totalMinted(); } function totalBurned() public view returns (uint256) { return _totalBurned(); } function exists(uint256 tokenId) public view returns (bool) { return _exists(tokenId); } function burn(uint256 tokenId) public override { _burn(tokenId); } function burn(uint256 tokenId, bool approvalCheck) public { _burn(tokenId, approvalCheck); } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721A.sol'; /** * @dev Interface of ERC721 token receiver. */ interface ERC721A__IERC721Receiver { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } /** * @title ERC721A * * @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721) * Non-Fungible Token Standard, including the Metadata extension. * Optimized for lower gas during batch mints. * * Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...) * starting from `_startTokenId()`. * * Assumptions: * * - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply. * - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256). */ contract ERC721A is IERC721A { // Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364). struct TokenApprovalRef { address value; } // ============================================================= // CONSTANTS // ============================================================= // Mask of an entry in packed address data. uint256 private constant _BITMASK_ADDRESS_DATA_ENTRY = (1 << 64) - 1; // The bit position of `numberMinted` in packed address data. uint256 private constant _BITPOS_NUMBER_MINTED = 64; // The bit position of `numberBurned` in packed address data. uint256 private constant _BITPOS_NUMBER_BURNED = 128; // The bit position of `aux` in packed address data. uint256 private constant _BITPOS_AUX = 192; // Mask of all 256 bits in packed address data except the 64 bits for `aux`. uint256 private constant _BITMASK_AUX_COMPLEMENT = (1 << 192) - 1; // The bit position of `startTimestamp` in packed ownership. uint256 private constant _BITPOS_START_TIMESTAMP = 160; // The bit mask of the `burned` bit in packed ownership. uint256 private constant _BITMASK_BURNED = 1 << 224; // The bit position of the `nextInitialized` bit in packed ownership. uint256 private constant _BITPOS_NEXT_INITIALIZED = 225; // The bit mask of the `nextInitialized` bit in packed ownership. uint256 private constant _BITMASK_NEXT_INITIALIZED = 1 << 225; // The bit position of `extraData` in packed ownership. uint256 private constant _BITPOS_EXTRA_DATA = 232; // Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`. uint256 private constant _BITMASK_EXTRA_DATA_COMPLEMENT = (1 << 232) - 1; // The mask of the lower 160 bits for addresses. uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1; // The maximum `quantity` that can be minted with {_mintERC2309}. // This limit is to prevent overflows on the address data entries. // For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309} // is required to cause an overflow, which is unrealistic. uint256 private constant _MAX_MINT_ERC2309_QUANTITY_LIMIT = 5000; // The `Transfer` event signature is given by: // `keccak256(bytes("Transfer(address,address,uint256)"))`. bytes32 private constant _TRANSFER_EVENT_SIGNATURE = 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef; // ============================================================= // STORAGE // ============================================================= // The next token ID to be minted. uint256 private _currentIndex; // The number of tokens burned. uint256 private _burnCounter; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to ownership details // An empty struct value does not necessarily mean the token is unowned. // See {_packedOwnershipOf} implementation for details. // // Bits Layout: // - [0..159] `addr` // - [160..223] `startTimestamp` // - [224] `burned` // - [225] `nextInitialized` // - [232..255] `extraData` mapping(uint256 => uint256) private _packedOwnerships; // Mapping owner address to address data. // // Bits Layout: // - [0..63] `balance` // - [64..127] `numberMinted` // - [128..191] `numberBurned` // - [192..255] `aux` mapping(address => uint256) private _packedAddressData; // Mapping from token ID to approved address. mapping(uint256 => TokenApprovalRef) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; // ============================================================= // CONSTRUCTOR // ============================================================= constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; _currentIndex = _startTokenId(); } // ============================================================= // TOKEN COUNTING OPERATIONS // ============================================================= /** * @dev Returns the starting token ID. * To change the starting token ID, please override this function. */ function _startTokenId() internal view virtual returns (uint256) { return 0; } /** * @dev Returns the next token ID to be minted. */ function _nextTokenId() internal view virtual returns (uint256) { return _currentIndex; } /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() public view virtual override returns (uint256) { // Counter underflow is impossible as _burnCounter cannot be incremented // more than `_currentIndex - _startTokenId()` times. unchecked { return _currentIndex - _burnCounter - _startTokenId(); } } /** * @dev Returns the total amount of tokens minted in the contract. */ function _totalMinted() internal view virtual returns (uint256) { // Counter underflow is impossible as `_currentIndex` does not decrement, // and it is initialized to `_startTokenId()`. unchecked { return _currentIndex - _startTokenId(); } } /** * @dev Returns the total number of tokens burned. */ function _totalBurned() internal view virtual returns (uint256) { return _burnCounter; } // ============================================================= // ADDRESS DATA OPERATIONS // ============================================================= /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) public view virtual override returns (uint256) { if (owner == address(0)) revert BalanceQueryForZeroAddress(); return _packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens minted by `owner`. */ function _numberMinted(address owner) internal view returns (uint256) { return (_packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the number of tokens burned by or on behalf of `owner`. */ function _numberBurned(address owner) internal view returns (uint256) { return (_packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY; } /** * Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). */ function _getAux(address owner) internal view returns (uint64) { return uint64(_packedAddressData[owner] >> _BITPOS_AUX); } /** * Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used). * If there are multiple variables, please pack them into a uint64. */ function _setAux(address owner, uint64 aux) internal virtual { uint256 packed = _packedAddressData[owner]; uint256 auxCasted; // Cast `aux` with assembly to avoid redundant masking. assembly { auxCasted := aux } packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX); _packedAddressData[owner] = packed; } // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { // The interface IDs are constants representing the first 4 bytes // of the XOR of all function selectors in the interface. // See: [ERC165](https://eips.ethereum.org/EIPS/eip-165) // (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`) return interfaceId == 0x01ffc9a7 || // ERC165 interface ID for ERC165. interfaceId == 0x80ac58cd || // ERC165 interface ID for ERC721. interfaceId == 0x5b5e139f; // ERC165 interface ID for ERC721Metadata. } // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the token collection symbol. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { if (!_exists(tokenId)) revert URIQueryForNonexistentToken(); string memory baseURI = _baseURI(); return bytes(baseURI).length != 0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : ''; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, it can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ''; } // ============================================================= // OWNERSHIPS OPERATIONS // ============================================================= /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { return address(uint160(_packedOwnershipOf(tokenId))); } /** * @dev Gas spent here starts off proportional to the maximum mint batch size. * It gradually moves to O(1) as tokens get transferred around over time. */ function _ownershipOf(uint256 tokenId) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnershipOf(tokenId)); } /** * @dev Returns the unpacked `TokenOwnership` struct at `index`. */ function _ownershipAt(uint256 index) internal view virtual returns (TokenOwnership memory) { return _unpackedOwnership(_packedOwnerships[index]); } /** * @dev Initializes the ownership slot minted at `index` for efficiency purposes. */ function _initializeOwnershipAt(uint256 index) internal virtual { if (_packedOwnerships[index] == 0) { _packedOwnerships[index] = _packedOwnershipOf(index); } } /** * Returns the packed ownership data of `tokenId`. */ function _packedOwnershipOf(uint256 tokenId) private view returns (uint256) { uint256 curr = tokenId; unchecked { if (_startTokenId() <= curr) if (curr < _currentIndex) { uint256 packed = _packedOwnerships[curr]; // If not burned. if (packed & _BITMASK_BURNED == 0) { // Invariant: // There will always be an initialized ownership slot // (i.e. `ownership.addr != address(0) && ownership.burned == false`) // before an unintialized ownership slot // (i.e. `ownership.addr == address(0) && ownership.burned == false`) // Hence, `curr` will not underflow. // // We can directly compare the packed value. // If the address is zero, packed will be zero. while (packed == 0) { packed = _packedOwnerships[--curr]; } return packed; } } } revert OwnerQueryForNonexistentToken(); } /** * @dev Returns the unpacked `TokenOwnership` struct from `packed`. */ function _unpackedOwnership(uint256 packed) private pure returns (TokenOwnership memory ownership) { ownership.addr = address(uint160(packed)); ownership.startTimestamp = uint64(packed >> _BITPOS_START_TIMESTAMP); ownership.burned = packed & _BITMASK_BURNED != 0; ownership.extraData = uint24(packed >> _BITPOS_EXTRA_DATA); } /** * @dev Packs ownership data into a single uint256. */ function _packOwnershipData(address owner, uint256 flags) private view returns (uint256 result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`. result := or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags)) } } /** * @dev Returns the `nextInitialized` flag set if `quantity` equals 1. */ function _nextInitializedFlag(uint256 quantity) private pure returns (uint256 result) { // For branchless setting of the `nextInitialized` flag. assembly { // `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`. result := shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1)) } } // ============================================================= // APPROVAL OPERATIONS // ============================================================= /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the * zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) public payable virtual override { address owner = ownerOf(tokenId); if (_msgSenderERC721A() != owner) if (!isApprovedForAll(owner, _msgSenderERC721A())) { revert ApprovalCallerNotOwnerNorApproved(); } _tokenApprovals[tokenId].value = to; emit Approval(owner, to, tokenId); } /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { if (!_exists(tokenId)) revert ApprovalQueryForNonexistentToken(); return _tokenApprovals[tokenId].value; } /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} * for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) public virtual override { _operatorApprovals[_msgSenderERC721A()][operator] = approved; emit ApprovalForAll(_msgSenderERC721A(), operator, approved); } /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted. See {_mint}. */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _startTokenId() <= tokenId && tokenId < _currentIndex && // If within bounds, _packedOwnerships[tokenId] & _BITMASK_BURNED == 0; // and not burned. } /** * @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`. */ function _isSenderApprovedOrOwner( address approvedAddress, address owner, address msgSender ) private pure returns (bool result) { assembly { // Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean. owner := and(owner, _BITMASK_ADDRESS) // Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean. msgSender := and(msgSender, _BITMASK_ADDRESS) // `msgSender == owner || msgSender == approvedAddress`. result := or(eq(msgSender, owner), eq(msgSender, approvedAddress)) } } /** * @dev Returns the storage slot and value for the approved address of `tokenId`. */ function _getApprovedSlotAndAddress(uint256 tokenId) private view returns (uint256 approvedAddressSlot, address approvedAddress) { TokenApprovalRef storage tokenApproval = _tokenApprovals[tokenId]; // The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`. assembly { approvedAddressSlot := tokenApproval.slot approvedAddress := sload(approvedAddressSlot) } } // ============================================================= // TRANSFER OPERATIONS // ============================================================= /** * @dev Transfers `tokenId` from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) public payable virtual override { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); if (address(uint160(prevOwnershipPacked)) != from) revert TransferFromIncorrectOwner(); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved(); if (to == address(0)) revert TransferToZeroAddress(); _beforeTokenTransfers(from, to, tokenId, 1); // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // We can directly increment and decrement the balances. --_packedAddressData[from]; // Updates: `balance -= 1`. ++_packedAddressData[to]; // Updates: `balance += 1`. // Updates: // - `address` to the next owner. // - `startTimestamp` to the timestamp of transfering. // - `burned` to `false`. // - `nextInitialized` to `true`. _packedOwnerships[tokenId] = _packOwnershipData( to, _BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (_packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != _currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. _packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } emit Transfer(from, to, tokenId); _afterTokenTransfers(from, to, tokenId, 1); } /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public payable virtual override { safeTransferFrom(from, to, tokenId, ''); } /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory _data ) public payable virtual override { transferFrom(from, to, tokenId); if (to.code.length != 0) if (!_checkContractOnERC721Received(from, to, tokenId, _data)) { revert TransferToNonERC721ReceiverImplementer(); } } /** * @dev Hook that is called before a set of serially-ordered token IDs * are about to be transferred. This includes minting. * And also called before burning one token. * * `startTokenId` - the first token ID to be transferred. * `quantity` - the amount to be transferred. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _beforeTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Hook that is called after a set of serially-ordered token IDs * have been transferred. This includes minting. * And also called after one token has been burned. * * `startTokenId` - the first token ID to be transferred. * `quantity` - the amount to be transferred. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` has been * transferred to `to`. * - When `from` is zero, `tokenId` has been minted for `to`. * - When `to` is zero, `tokenId` has been burned by `from`. * - `from` and `to` are never both zero. */ function _afterTokenTransfers( address from, address to, uint256 startTokenId, uint256 quantity ) internal virtual {} /** * @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract. * * `from` - Previous owner of the given token ID. * `to` - Target address that will receive the token. * `tokenId` - Token ID to be transferred. * `_data` - Optional data to send along with the call. * * Returns whether the call correctly returned the expected magic value. */ function _checkContractOnERC721Received( address from, address to, uint256 tokenId, bytes memory _data ) private returns (bool) { try ERC721A__IERC721Receiver(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns ( bytes4 retval ) { return retval == ERC721A__IERC721Receiver(to).onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert TransferToNonERC721ReceiverImplementer(); } else { assembly { revert(add(32, reason), mload(reason)) } } } } // ============================================================= // MINT OPERATIONS // ============================================================= /** * @dev Mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {Transfer} event for each mint. */ function _mint(address to, uint256 quantity) internal virtual { uint256 startTokenId = _currentIndex; if (quantity == 0) revert MintZeroQuantity(); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are incredibly unrealistic. // `balance` and `numberMinted` have a maximum limit of 2**64. // `tokenId` has a maximum limit of 2**256. unchecked { // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the `balance` and `numberMinted`. _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1); // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. _packedOwnerships[startTokenId] = _packOwnershipData( to, _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0) ); uint256 toMasked; uint256 end = startTokenId + quantity; // Use assembly to loop and emit the `Transfer` event for gas savings. // The duplicated `log4` removes an extra check and reduces stack juggling. // The assembly, together with the surrounding Solidity code, have been // delicately arranged to nudge the compiler into producing optimized opcodes. assembly { // Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean. toMasked := and(to, _BITMASK_ADDRESS) // Emit the `Transfer` event. log4( 0, // Start of data (0, since no data). 0, // End of data (0, since no data). _TRANSFER_EVENT_SIGNATURE, // Signature. 0, // `address(0)`. toMasked, // `to`. startTokenId // `tokenId`. ) // The `iszero(eq(,))` check ensures that large values of `quantity` // that overflows uint256 will make the loop run out of gas. // The compiler will optimize the `iszero` away for performance. for { let tokenId := add(startTokenId, 1) } iszero(eq(tokenId, end)) { tokenId := add(tokenId, 1) } { // Emit the `Transfer` event. Similar to above. log4(0, 0, _TRANSFER_EVENT_SIGNATURE, 0, toMasked, tokenId) } } if (toMasked == 0) revert MintToZeroAddress(); _currentIndex = end; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Mints `quantity` tokens and transfers them to `to`. * * This function is intended for efficient minting only during contract creation. * * It emits only one {ConsecutiveTransfer} as defined in * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309), * instead of a sequence of {Transfer} event(s). * * Calling this function outside of contract creation WILL make your contract * non-compliant with the ERC721 standard. * For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309 * {ConsecutiveTransfer} event is only permissible during contract creation. * * Requirements: * * - `to` cannot be the zero address. * - `quantity` must be greater than 0. * * Emits a {ConsecutiveTransfer} event. */ function _mintERC2309(address to, uint256 quantity) internal virtual { uint256 startTokenId = _currentIndex; if (to == address(0)) revert MintToZeroAddress(); if (quantity == 0) revert MintZeroQuantity(); if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) revert MintERC2309QuantityExceedsLimit(); _beforeTokenTransfers(address(0), to, startTokenId, quantity); // Overflows are unrealistic due to the above check for `quantity` to be below the limit. unchecked { // Updates: // - `balance += quantity`. // - `numberMinted += quantity`. // // We can directly add to the `balance` and `numberMinted`. _packedAddressData[to] += quantity * ((1 << _BITPOS_NUMBER_MINTED) | 1); // Updates: // - `address` to the owner. // - `startTimestamp` to the timestamp of minting. // - `burned` to `false`. // - `nextInitialized` to `quantity == 1`. _packedOwnerships[startTokenId] = _packOwnershipData( to, _nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0) ); emit ConsecutiveTransfer(startTokenId, startTokenId + quantity - 1, address(0), to); _currentIndex = startTokenId + quantity; } _afterTokenTransfers(address(0), to, startTokenId, quantity); } /** * @dev Safely mints `quantity` tokens and transfers them to `to`. * * Requirements: * * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called for each safe transfer. * - `quantity` must be greater than 0. * * See {_mint}. * * Emits a {Transfer} event for each mint. */ function _safeMint( address to, uint256 quantity, bytes memory _data ) internal virtual { _mint(to, quantity); unchecked { if (to.code.length != 0) { uint256 end = _currentIndex; uint256 index = end - quantity; do { if (!_checkContractOnERC721Received(address(0), to, index++, _data)) { revert TransferToNonERC721ReceiverImplementer(); } } while (index < end); // Reentrancy protection. if (_currentIndex != end) revert(); } } } /** * @dev Equivalent to `_safeMint(to, quantity, '')`. */ function _safeMint(address to, uint256 quantity) internal virtual { _safeMint(to, quantity, ''); } // ============================================================= // BURN OPERATIONS // ============================================================= /** * @dev Equivalent to `_burn(tokenId, false)`. */ function _burn(uint256 tokenId) internal virtual { _burn(tokenId, false); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId, bool approvalCheck) internal virtual { uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId); address from = address(uint160(prevOwnershipPacked)); (uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId); if (approvalCheck) { // The nested ifs save around 20+ gas over a compound boolean condition. if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A())) if (!isApprovedForAll(from, _msgSenderERC721A())) revert TransferCallerNotOwnerNorApproved(); } _beforeTokenTransfers(from, address(0), tokenId, 1); // Clear approvals from the previous owner. assembly { if approvedAddress { // This is equivalent to `delete _tokenApprovals[tokenId]`. sstore(approvedAddressSlot, 0) } } // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. // Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256. unchecked { // Updates: // - `balance -= 1`. // - `numberBurned += 1`. // // We can directly decrement the balance, and increment the number burned. // This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`. _packedAddressData[from] += (1 << _BITPOS_NUMBER_BURNED) - 1; // Updates: // - `address` to the last owner. // - `startTimestamp` to the timestamp of burning. // - `burned` to `true`. // - `nextInitialized` to `true`. _packedOwnerships[tokenId] = _packOwnershipData( from, (_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked) ); // If the next slot may not have been initialized (i.e. `nextInitialized == false`) . if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED == 0) { uint256 nextTokenId = tokenId + 1; // If the next slot's address is zero and not burned (i.e. packed value is zero). if (_packedOwnerships[nextTokenId] == 0) { // If the next slot is within bounds. if (nextTokenId != _currentIndex) { // Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`. _packedOwnerships[nextTokenId] = prevOwnershipPacked; } } } } emit Transfer(from, address(0), tokenId); _afterTokenTransfers(from, address(0), tokenId, 1); // Overflow not possible, as _burnCounter cannot be exceed _currentIndex times. unchecked { _burnCounter++; } } // ============================================================= // EXTRA DATA OPERATIONS // ============================================================= /** * @dev Directly sets the extra data for the ownership data `index`. */ function _setExtraDataAt(uint256 index, uint24 extraData) internal virtual { uint256 packed = _packedOwnerships[index]; if (packed == 0) revert OwnershipNotInitializedForExtraData(); uint256 extraDataCasted; // Cast `extraData` with assembly to avoid redundant masking. assembly { extraDataCasted := extraData } packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA); _packedOwnerships[index] = packed; } /** * @dev Called during each token transfer to set the 24bit `extraData` field. * Intended to be overridden by the cosumer contract. * * `previousExtraData` - the value of `extraData` before transfer. * * Calling conditions: * * - When `from` and `to` are both non-zero, `from`'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, `tokenId` will be burned by `from`. * - `from` and `to` are never both zero. */ function _extraData( address from, address to, uint24 previousExtraData ) internal view virtual returns (uint24) {} /** * @dev Returns the next extra data for the packed ownership data. * The returned result is shifted into position. */ function _nextExtraData( address from, address to, uint256 prevOwnershipPacked ) private view returns (uint256) { uint24 extraData = uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA); return uint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA; } // ============================================================= // OTHER OPERATIONS // ============================================================= /** * @dev Returns the message sender (defaults to `msg.sender`). * * If you are writing GSN compatible contracts, you need to override this function. */ function _msgSenderERC721A() internal view virtual returns (address) { return msg.sender; } /** * @dev Converts a uint256 to its ASCII string decimal representation. */ function _toString(uint256 value) internal pure virtual returns (string memory str) { assembly { // The maximum value of a uint256 contains 78 digits (1 byte per digit), but // we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned. // We will need 1 word for the trailing zeros padding, 1 word for the length, // and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0. let m := add(mload(0x40), 0xa0) // Update the free memory pointer to allocate. mstore(0x40, m) // Assign the `str` to the end. str := sub(m, 0x20) // Zeroize the slot after the string. mstore(str, 0) // Cache the end of the memory to calculate the length later. let end := str // We write the string from rightmost digit to leftmost digit. // The following is essentially a do-while loop that also handles the zero case. // prettier-ignore for { let temp := value } 1 {} { str := sub(str, 1) // Write the character to the pointer. // The ASCII index of the '0' character is 48. mstore8(str, add(48, mod(temp, 10))) // Keep dividing `temp` until zero. temp := div(temp, 10) // prettier-ignore if iszero(temp) { break } } let length := sub(end, str) // Move the pointer 32 bytes leftwards to make room for the length. str := sub(str, 0x20) // Store the length. mstore(str, length) } } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; import '../IERC721A.sol';
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; import './IERC721ABurnable.sol'; import '../ERC721A.sol'; /** * @title ERC721ABurnable. * * @dev ERC721A token that can be irreversibly burned (destroyed). */ abstract contract ERC721ABurnable is ERC721A, IERC721ABurnable { /** * @dev Burns `tokenId`. See {ERC721A-_burn}. * * Requirements: * * - The caller must own `tokenId` or be an approved operator. */ function burn(uint256 tokenId) public virtual override { _burn(tokenId, true); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Library to encode strings in Base64. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Base64.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/Base64.sol) /// @author Modified from (https://github.com/Brechtpd/base64/blob/main/base64.sol) by Brecht Devos - <[email protected]>. library Base64 { /// @dev Encodes `data` using the base64 encoding described in RFC 4648. /// See: https://datatracker.ietf.org/doc/html/rfc4648 /// @param fileSafe Whether to replace '+' with '-' and '/' with '_'. /// @param noPadding Whether to strip away the padding. function encode(bytes memory data, bool fileSafe, bool noPadding) internal pure returns (string memory result) { /// @solidity memory-safe-assembly assembly { let dataLength := mload(data) if dataLength { // Multiply by 4/3 rounded up. // The `shl(2, ...)` is equivalent to multiplying by 4. let encodedLength := shl(2, div(add(dataLength, 2), 3)) // Set `result` to point to the start of the free memory. result := mload(0x40) // Store the table into the scratch space. // Offsetted by -1 byte so that the `mload` will load the character. // We will rewrite the free memory pointer at `0x40` later with // the allocated size. // The magic constant 0x0670 will turn "-_" into "+/". mstore(0x1f, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef") mstore(0x3f, xor("ghijklmnopqrstuvwxyz0123456789-_", mul(iszero(fileSafe), 0x0670))) // Skip the first slot, which stores the length. let ptr := add(result, 0x20) let end := add(ptr, encodedLength) // Run over the input, 3 bytes at a time. for {} 1 {} { data := add(data, 3) // Advance 3 bytes. let input := mload(data) // Write 4 bytes. Optimized for fewer stack operations. mstore8(0, mload(and(shr(18, input), 0x3F))) mstore8(1, mload(and(shr(12, input), 0x3F))) mstore8(2, mload(and(shr(6, input), 0x3F))) mstore8(3, mload(and(input, 0x3F))) mstore(ptr, mload(0x00)) ptr := add(ptr, 4) // Advance 4 bytes. if iszero(lt(ptr, end)) { break } } mstore(0x40, add(end, 0x20)) // Allocate the memory. // Equivalent to `o = [0, 2, 1][dataLength % 3]`. let o := div(2, mod(dataLength, 3)) // Offset `ptr` and pad with '='. We can simply write over the end. mstore(sub(ptr, o), shl(240, 0x3d3d)) // Set `o` to zero if there is padding. o := mul(iszero(iszero(noPadding)), o) mstore(sub(ptr, o), 0) // Zeroize the slot after the string. mstore(result, sub(encodedLength, o)) // Store the length. } } } /// @dev Encodes `data` using the base64 encoding described in RFC 4648. /// Equivalent to `encode(data, false, false)`. function encode(bytes memory data) internal pure returns (string memory result) { result = encode(data, false, false); } /// @dev Encodes `data` using the base64 encoding described in RFC 4648. /// Equivalent to `encode(data, fileSafe, false)`. function encode(bytes memory data, bool fileSafe) internal pure returns (string memory result) { result = encode(data, fileSafe, false); } /// @dev Decodes base64 encoded `data`. /// /// Supports: /// - RFC 4648 (both standard and file-safe mode). /// - RFC 3501 (63: ','). /// /// Does not support: /// - Line breaks. /// /// Note: For performance reasons, /// this function will NOT revert on invalid `data` inputs. /// Outputs for invalid inputs will simply be undefined behaviour. /// It is the user's responsibility to ensure that the `data` /// is a valid base64 encoded string. function decode(string memory data) internal pure returns (bytes memory result) { /// @solidity memory-safe-assembly assembly { let dataLength := mload(data) if dataLength { let decodedLength := mul(shr(2, dataLength), 3) for {} 1 {} { // If padded. if iszero(and(dataLength, 3)) { let t := xor(mload(add(data, dataLength)), 0x3d3d) // forgefmt: disable-next-item decodedLength := sub( decodedLength, add(iszero(byte(30, t)), iszero(byte(31, t))) ) break } // If non-padded. decodedLength := add(decodedLength, sub(and(dataLength, 3), 1)) break } result := mload(0x40) // Write the length of the bytes. mstore(result, decodedLength) // Skip the first slot, which stores the length. let ptr := add(result, 0x20) let end := add(ptr, decodedLength) // Load the table into the scratch space. // Constants are optimized for smaller bytecode with zero gas overhead. // `m` also doubles as the mask of the upper 6 bits. let m := 0xfc000000fc00686c7074787c8084888c9094989ca0a4a8acb0b4b8bcc0c4c8cc mstore(0x5b, m) mstore(0x3b, 0x04080c1014181c2024282c3034383c4044484c5054585c6064) mstore(0x1a, 0xf8fcf800fcd0d4d8dce0e4e8ecf0f4) for {} 1 {} { // Read 4 bytes. data := add(data, 4) let input := mload(data) // Write 3 bytes. // forgefmt: disable-next-item mstore(ptr, or( and(m, mload(byte(28, input))), shr(6, or( and(m, mload(byte(29, input))), shr(6, or( and(m, mload(byte(30, input))), shr(6, mload(byte(31, input))) )) )) )) ptr := add(ptr, 3) if iszero(lt(ptr, end)) { break } } mstore(0x40, add(end, 0x20)) // Allocate the memory. mstore(end, 0) // Zeroize the slot after the bytes. mstore(0x60, 0) // Restore the zero slot. } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Read and write to persistent storage at a fraction of the cost. /// @author Solady (https://github.com/vectorized/solmady/blob/main/src/utils/SSTORE2.sol) /// @author Saw-mon-and-Natalie (https://github.com/Saw-mon-and-Natalie) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SSTORE2.sol) /// @author Modified from 0xSequence (https://github.com/0xSequence/sstore2/blob/master/contracts/SSTORE2.sol) library SSTORE2 { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev We skip the first byte as it's a STOP opcode, /// which ensures the contract can't be called. uint256 internal constant DATA_OFFSET = 1; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Unable to deploy the storage contract. error DeploymentFailed(); /// @dev The storage contract address is invalid. error InvalidPointer(); /// @dev Attempt to read outside of the storage contract's bytecode bounds. error ReadOutOfBounds(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* WRITE LOGIC */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Writes `data` into the bytecode of a storage contract and returns its address. function write(bytes memory data) internal returns (address pointer) { /// @solidity memory-safe-assembly assembly { let originalDataLength := mload(data) // Add 1 to data size since we are prefixing it with a STOP opcode. let dataSize := add(originalDataLength, DATA_OFFSET) /** * ------------------------------------------------------------------------------+ * Opcode | Mnemonic | Stack | Memory | * ------------------------------------------------------------------------------| * 61 dataSize | PUSH2 dataSize | dataSize | | * 80 | DUP1 | dataSize dataSize | | * 60 0xa | PUSH1 0xa | 0xa dataSize dataSize | | * 3D | RETURNDATASIZE | 0 0xa dataSize dataSize | | * 39 | CODECOPY | dataSize | [0..dataSize): code | * 3D | RETURNDATASIZE | 0 dataSize | [0..dataSize): code | * F3 | RETURN | | [0..dataSize): code | * 00 | STOP | | | * ------------------------------------------------------------------------------+ * @dev Prefix the bytecode with a STOP opcode to ensure it cannot be called. * Also PUSH2 is used since max contract size cap is 24,576 bytes which is less than 2 ** 16. */ mstore( // Do a out-of-gas revert if `dataSize` is more than 2 bytes. // The actual EVM limit may be smaller and may change over time. add(data, gt(dataSize, 0xffff)), // Left shift `dataSize` by 64 so that it lines up with the 0000 after PUSH2. or(0xfd61000080600a3d393df300, shl(0x40, dataSize)) ) // Deploy a new contract with the generated creation code. pointer := create(0, add(data, 0x15), add(dataSize, 0xa)) // If `pointer` is zero, revert. if iszero(pointer) { // Store the function selector of `DeploymentFailed()`. mstore(0x00, 0x30116425) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore original length of the variable size `data`. mstore(data, originalDataLength) } } /// @dev Writes `data` into the bytecode of a storage contract with `salt` /// and returns its deterministic address. function writeDeterministic(bytes memory data, bytes32 salt) internal returns (address pointer) { /// @solidity memory-safe-assembly assembly { let originalDataLength := mload(data) let dataSize := add(originalDataLength, DATA_OFFSET) mstore( // Do a out-of-gas revert if `dataSize` is more than 2 bytes. // The actual EVM limit may be smaller and may change over time. add(data, gt(dataSize, 0xffff)), // Left shift `dataSize` by 64 so that it lines up with the 0000 after PUSH2. or(0xfd61000080600a3d393df300, shl(0x40, dataSize)) ) // Deploy a new contract with the generated creation code. pointer := create2(0, add(data, 0x15), add(dataSize, 0xa), salt) // If `pointer` is zero, revert. if iszero(pointer) { // Store the function selector of `DeploymentFailed()`. mstore(0x00, 0x30116425) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore original length of the variable size `data`. mstore(data, originalDataLength) } } /// @dev Returns the initialization code hash of the storage contract for `data`. /// Used for mining vanity addresses with create2crunch. function initCodeHash(bytes memory data) internal pure returns (bytes32 hash) { /// @solidity memory-safe-assembly assembly { let originalDataLength := mload(data) let dataSize := add(originalDataLength, DATA_OFFSET) // Do a out-of-gas revert if `dataSize` is more than 2 bytes. // The actual EVM limit may be smaller and may change over time. returndatacopy(returndatasize(), returndatasize(), shr(16, dataSize)) mstore(data, or(0x61000080600a3d393df300, shl(0x40, dataSize))) hash := keccak256(add(data, 0x15), add(dataSize, 0xa)) // Restore original length of the variable size `data`. mstore(data, originalDataLength) } } /// @dev Returns the address of the storage contract for `data` /// deployed with `salt` by `deployer`. /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. function predictDeterministicAddress(bytes memory data, bytes32 salt, address deployer) internal pure returns (address predicted) { bytes32 hash = initCodeHash(data); /// @solidity memory-safe-assembly assembly { // Compute and store the bytecode hash. mstore8(0x00, 0xff) // Write the prefix. mstore(0x35, hash) mstore(0x01, shl(96, deployer)) mstore(0x15, salt) predicted := keccak256(0x00, 0x55) // Restore the part of the free memory pointer that has been overwritten. mstore(0x35, 0) } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* READ LOGIC */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns all the `data` from the bytecode of the storage contract at `pointer`. function read(address pointer) internal view returns (bytes memory data) { /// @solidity memory-safe-assembly assembly { let pointerCodesize := extcodesize(pointer) if iszero(pointerCodesize) { // Store the function selector of `InvalidPointer()`. mstore(0x00, 0x11052bb4) // Revert with (offset, size). revert(0x1c, 0x04) } // Offset all indices by 1 to skip the STOP opcode. let size := sub(pointerCodesize, DATA_OFFSET) // Get the pointer to the free memory and allocate // enough 32-byte words for the data and the length of the data, // then copy the code to the allocated memory. // Masking with 0xffe0 will suffice, since contract size is less than 16 bits. data := mload(0x40) mstore(0x40, add(data, and(add(size, 0x3f), 0xffe0))) mstore(data, size) mstore(add(add(data, 0x20), size), 0) // Zeroize the last slot. extcodecopy(pointer, add(data, 0x20), DATA_OFFSET, size) } } /// @dev Returns the `data` from the bytecode of the storage contract at `pointer`, /// from the byte at `start`, to the end of the data stored. function read(address pointer, uint256 start) internal view returns (bytes memory data) { /// @solidity memory-safe-assembly assembly { let pointerCodesize := extcodesize(pointer) if iszero(pointerCodesize) { // Store the function selector of `InvalidPointer()`. mstore(0x00, 0x11052bb4) // Revert with (offset, size). revert(0x1c, 0x04) } // If `!(pointer.code.size > start)`, reverts. // This also handles the case where `start + DATA_OFFSET` overflows. if iszero(gt(pointerCodesize, start)) { // Store the function selector of `ReadOutOfBounds()`. mstore(0x00, 0x84eb0dd1) // Revert with (offset, size). revert(0x1c, 0x04) } let size := sub(pointerCodesize, add(start, DATA_OFFSET)) // Get the pointer to the free memory and allocate // enough 32-byte words for the data and the length of the data, // then copy the code to the allocated memory. // Masking with 0xffe0 will suffice, since contract size is less than 16 bits. data := mload(0x40) mstore(0x40, add(data, and(add(size, 0x3f), 0xffe0))) mstore(data, size) mstore(add(add(data, 0x20), size), 0) // Zeroize the last slot. extcodecopy(pointer, add(data, 0x20), add(start, DATA_OFFSET), size) } } /// @dev Returns the `data` from the bytecode of the storage contract at `pointer`, /// from the byte at `start`, to the byte at `end` (exclusive) of the data stored. function read(address pointer, uint256 start, uint256 end) internal view returns (bytes memory data) { /// @solidity memory-safe-assembly assembly { let pointerCodesize := extcodesize(pointer) if iszero(pointerCodesize) { // Store the function selector of `InvalidPointer()`. mstore(0x00, 0x11052bb4) // Revert with (offset, size). revert(0x1c, 0x04) } // If `!(pointer.code.size > end) || (start > end)`, revert. // This also handles the cases where // `end + DATA_OFFSET` or `start + DATA_OFFSET` overflows. if iszero( and( gt(pointerCodesize, end), // Within bounds. iszero(gt(start, end)) // Valid range. ) ) { // Store the function selector of `ReadOutOfBounds()`. mstore(0x00, 0x84eb0dd1) // Revert with (offset, size). revert(0x1c, 0x04) } let size := sub(end, start) // Get the pointer to the free memory and allocate // enough 32-byte words for the data and the length of the data, // then copy the code to the allocated memory. // Masking with 0xffe0 will suffice, since contract size is less than 16 bits. data := mload(0x40) mstore(0x40, add(data, and(add(size, 0x3f), 0xffe0))) mstore(data, size) mstore(add(add(data, 0x20), size), 0) // Zeroize the last slot. extcodecopy(pointer, add(data, 0x20), add(start, DATA_OFFSET), size) } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.22 <0.9.0; /// @dev The original console.sol uses `int` and `uint` for computing function selectors, but it should /// use `int256` and `uint256`. This modified version fixes that. This version is recommended /// over `console.sol` if you don't need compatibility with Hardhat as the logs will show up in /// forge stack traces. If you do need compatibility with Hardhat, you must use `console.sol`. /// Reference: https://github.com/NomicFoundation/hardhat/issues/2178 library console2 { address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67); function _castLogPayloadViewToPure( function(bytes memory) internal view fnIn ) internal pure returns (function(bytes memory) internal pure fnOut) { assembly { fnOut := fnIn } } function _sendLogPayload(bytes memory payload) internal pure { _castLogPayloadViewToPure(_sendLogPayloadView)(payload); } function _sendLogPayloadView(bytes memory payload) private view { uint256 payloadLength = payload.length; address consoleAddress = CONSOLE_ADDRESS; /// @solidity memory-safe-assembly assembly { let payloadStart := add(payload, 32) let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0) } } function log() internal pure { _sendLogPayload(abi.encodeWithSignature("log()")); } function logInt(int256 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); } function logUint(uint256 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); } function logString(string memory p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } function logBool(bool p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } function logAddress(address p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } function logBytes(bytes memory p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes)", p0)); } function logBytes1(bytes1 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0)); } function logBytes2(bytes2 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0)); } function logBytes3(bytes3 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0)); } function logBytes4(bytes4 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0)); } function logBytes5(bytes5 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0)); } function logBytes6(bytes6 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0)); } function logBytes7(bytes7 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0)); } function logBytes8(bytes8 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0)); } function logBytes9(bytes9 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0)); } function logBytes10(bytes10 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0)); } function logBytes11(bytes11 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0)); } function logBytes12(bytes12 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0)); } function logBytes13(bytes13 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0)); } function logBytes14(bytes14 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0)); } function logBytes15(bytes15 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0)); } function logBytes16(bytes16 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0)); } function logBytes17(bytes17 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0)); } function logBytes18(bytes18 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0)); } function logBytes19(bytes19 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0)); } function logBytes20(bytes20 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0)); } function logBytes21(bytes21 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0)); } function logBytes22(bytes22 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0)); } function logBytes23(bytes23 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0)); } function logBytes24(bytes24 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0)); } function logBytes25(bytes25 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0)); } function logBytes26(bytes26 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0)); } function logBytes27(bytes27 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0)); } function logBytes28(bytes28 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0)); } function logBytes29(bytes29 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0)); } function logBytes30(bytes30 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0)); } function logBytes31(bytes31 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0)); } function logBytes32(bytes32 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0)); } function log(uint256 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256)", p0)); } function log(int256 p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(int256)", p0)); } function log(string memory p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string)", p0)); } function log(bool p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool)", p0)); } function log(address p0) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address)", p0)); } function log(uint256 p0, uint256 p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1)); } function log(uint256 p0, string memory p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1)); } function log(uint256 p0, bool p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1)); } function log(uint256 p0, address p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1)); } function log(string memory p0, uint256 p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1)); } function log(string memory p0, int256 p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,int256)", p0, p1)); } function log(string memory p0, string memory p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1)); } function log(string memory p0, bool p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1)); } function log(string memory p0, address p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1)); } function log(bool p0, uint256 p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1)); } function log(bool p0, string memory p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1)); } function log(bool p0, bool p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1)); } function log(bool p0, address p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1)); } function log(address p0, uint256 p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1)); } function log(address p0, string memory p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1)); } function log(address p0, bool p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1)); } function log(address p0, address p1) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1)); } function log(uint256 p0, uint256 p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2)); } function log(uint256 p0, uint256 p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2)); } function log(uint256 p0, uint256 p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2)); } function log(uint256 p0, uint256 p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2)); } function log(uint256 p0, string memory p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2)); } function log(uint256 p0, string memory p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2)); } function log(uint256 p0, string memory p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2)); } function log(uint256 p0, string memory p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2)); } function log(uint256 p0, bool p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2)); } function log(uint256 p0, bool p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2)); } function log(uint256 p0, bool p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2)); } function log(uint256 p0, bool p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2)); } function log(uint256 p0, address p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2)); } function log(uint256 p0, address p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2)); } function log(uint256 p0, address p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2)); } function log(uint256 p0, address p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2)); } function log(string memory p0, uint256 p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2)); } function log(string memory p0, uint256 p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2)); } function log(string memory p0, uint256 p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2)); } function log(string memory p0, uint256 p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2)); } function log(string memory p0, string memory p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2)); } function log(string memory p0, string memory p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2)); } function log(string memory p0, string memory p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2)); } function log(string memory p0, string memory p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2)); } function log(string memory p0, bool p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2)); } function log(string memory p0, bool p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2)); } function log(string memory p0, bool p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2)); } function log(string memory p0, bool p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2)); } function log(string memory p0, address p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2)); } function log(string memory p0, address p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2)); } function log(string memory p0, address p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2)); } function log(string memory p0, address p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2)); } function log(bool p0, uint256 p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2)); } function log(bool p0, uint256 p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2)); } function log(bool p0, uint256 p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2)); } function log(bool p0, uint256 p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2)); } function log(bool p0, string memory p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2)); } function log(bool p0, string memory p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2)); } function log(bool p0, string memory p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2)); } function log(bool p0, string memory p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2)); } function log(bool p0, bool p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2)); } function log(bool p0, bool p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2)); } function log(bool p0, bool p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2)); } function log(bool p0, bool p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2)); } function log(bool p0, address p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2)); } function log(bool p0, address p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2)); } function log(bool p0, address p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2)); } function log(bool p0, address p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2)); } function log(address p0, uint256 p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2)); } function log(address p0, uint256 p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2)); } function log(address p0, uint256 p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2)); } function log(address p0, uint256 p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2)); } function log(address p0, string memory p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2)); } function log(address p0, string memory p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2)); } function log(address p0, string memory p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2)); } function log(address p0, string memory p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2)); } function log(address p0, bool p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2)); } function log(address p0, bool p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2)); } function log(address p0, bool p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2)); } function log(address p0, bool p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2)); } function log(address p0, address p1, uint256 p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2)); } function log(address p0, address p1, string memory p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2)); } function log(address p0, address p1, bool p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2)); } function log(address p0, address p1, address p2) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2)); } function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3)); } function log(uint256 p0, uint256 p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3)); } function log(uint256 p0, string memory p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3)); } function log(uint256 p0, bool p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3)); } function log(uint256 p0, address p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, uint256 p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, string memory p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, bool p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3)); } function log(string memory p0, address p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3)); } function log(bool p0, uint256 p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3)); } function log(bool p0, string memory p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3)); } function log(bool p0, bool p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3)); } function log(bool p0, address p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3)); } function log(address p0, uint256 p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3)); } function log(address p0, string memory p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3)); } function log(address p0, bool p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3)); } function log(address p0, address p1, uint256 p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3)); } function log(address p0, address p1, uint256 p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3)); } function log(address p0, address p1, uint256 p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, uint256 p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, string memory p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, bool p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, uint256 p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, string memory p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, bool p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3)); } function log(address p0, address p1, address p2, address p3) internal pure { _sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3)); } }
// SPDX-License-Identifier: MIT // Copyright (c) 2021 the ethier authors (github.com/divergencetech/ethier) pragma solidity >=0.8.0; /// @title DynamicBuffer /// @author David Huber (@cxkoda) and Simon Fremaux (@dievardump). See also /// https://raw.githubusercontent.com/dievardump/solidity-dynamic-buffer /// @notice This library is used to allocate a big amount of container memory // which will be subsequently filled without needing to reallocate /// memory. /// @dev First, allocate memory. /// Then use `buffer.appendUnchecked(theBytes)` or `appendSafe()` if /// bounds checking is required. library DynamicBuffer { /// @notice Allocates container space for the DynamicBuffer /// @param capacity The intended max amount of bytes in the buffer /// @return buffer The memory location of the buffer /// @dev Allocates `capacity + 0x60` bytes of space /// The buffer array starts at the first container data position, /// (i.e. `buffer = container + 0x20`) function allocate(uint256 capacity) internal pure returns (bytes memory buffer) { assembly { // Get next-free memory address let container := mload(0x40) // Allocate memory by setting a new next-free address { // Add 2 x 32 bytes in size for the two length fields // Add 32 bytes safety space for 32B chunked copy let size := add(capacity, 0x60) let newNextFree := add(container, size) mstore(0x40, newNextFree) } // Set the correct container length { let length := add(capacity, 0x40) mstore(container, length) } // The buffer starts at idx 1 in the container (0 is length) buffer := add(container, 0x20) // Init content with length 0 mstore(buffer, 0) } return buffer; } /// @notice Appends data to buffer, and update buffer length /// @param buffer the buffer to append the data to /// @param data the data to append /// @dev Does not perform out-of-bound checks (container capacity) /// for efficiency. function appendUnchecked(bytes memory buffer, bytes memory data) internal pure { assembly { let length := mload(data) for { data := add(data, 0x20) let dataEnd := add(data, length) let copyTo := add(buffer, add(mload(buffer), 0x20)) } lt(data, dataEnd) { data := add(data, 0x20) copyTo := add(copyTo, 0x20) } { // Copy 32B chunks from data to buffer. // This may read over data array boundaries and copy invalid // bytes, which doesn't matter in the end since we will // later set the correct buffer length, and have allocated an // additional word to avoid buffer overflow. mstore(copyTo, mload(data)) } // Update buffer length mstore(buffer, add(mload(buffer), length)) } } /// @notice Appends data to buffer, and update buffer length /// @param buffer the buffer to append the data to /// @param data the data to append /// @dev Performs out-of-bound checks and calls `appendUnchecked`. function appendSafe(bytes memory buffer, bytes memory data) internal pure { uint256 capacity; uint256 length; assembly { capacity := sub(mload(sub(buffer, 0x20)), 0x40) length := mload(buffer) } require( length + data.length <= capacity, "DynamicBuffer: Appending out of bounds." ); appendUnchecked(buffer, data); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library HelperLib { function parseInt(string memory self) internal pure returns (uint8) { bytes memory bresult = bytes(self); uint8 mint = 0; for (uint8 i = 0; i < bresult.length; i++) { if ( (uint8(uint8(bresult[i])) >= 48) && (uint8(uint8(bresult[i])) <= 57) ) { mint *= 10; mint += uint8(bresult[i]) - 48; } } return mint; } function subStr( string memory self, uint256 startIndex, uint256 endIndex ) internal pure returns (string memory) { bytes memory strBytes = bytes(self); bytes memory result = new bytes(endIndex - startIndex); for (uint256 i = startIndex; i < endIndex; i++) { result[i - startIndex] = strBytes[i]; } return string(result); } }
pragma solidity ^0.8.0; library OnchainOpepenArt { bytes constant Bleu = hex"89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000037349444154789ced9a314feb3010c7ff7d7a136bc25eb1d08905988ad41921f533f4495d18112b232beac8c2c067a8843a23d109de82de5096aa7bed95b56fe03938c1766cdfa5ed13fe49959ae47cf65d2e76ee622091482412894422914824be21add886799eaf42e48510de7dd97487e8f0e527a5f1c5dd43e978b65816ff3bedddd2b5d1f06c05b88d50869f5edd47eb08851401a757f7a541ba1ca0180dcf8c06287d3aa13a62f84155305b2c8b9f0f17770f5f42dc647ca88e58c80eb0e172886e80cb785f1d141a7300006b64d4454ba7bd5b847fac0e5fc8730085c9f500261dbaf13e3a28f301691500ec1395ce6cb10c324ac974dabba5b626269ee3b441728090124f527ac9dae484a3bd6ae3db470c8dce01ff03a408c8b3ac74ac87ead3ef5921630a6515e6ba8eaa9caea329c873808eedf956e7eb9e7f5f394ea21f0121446b723d703ec32ed4ec3db91e7ce80bd023a4849092bc02004c11a006ef0a559781ea9a90b236dc631d6e8334090a215acfb7979fc79e33fdf3ed6571e74c3a74f9f9745c9cd3cfeb3a28b02414799eafb2831e0060afdb07f03170d3b17c7db42643d941af9037e950e76c3a62e079048468e1f571951df4309f8e4b0306ea8dd775a8e3bd6e1fef6f2fd8d93f2adad7e98881b520a2a20000dedf5e8aff3bfb47003e065f8749475d7b8a4358eb018ad962599a18ab32faf593c38ef175b74e8792a1ae041b7f135ce79a6f62e30e50f8be2471c3ea009fca90eb7a88915c0e617340489abb8ebe7c61cd053858f79c4076c026ef3cc76bf1d64c82a170e504e48a5068aeae065ebcdd75fbd13a38203f02ba13aa490c00e4fd5f25f93ccbbe18a01faf3b1b644d873975991c51ed47cf116221cd01b103f009792125e6d371291de6e8bb4ae3cb2077c8027ed9a52fe45580eb4e6caabfe808a8d60014d55a00274dd405c80af46a904e35970fbdee92d9aa8a905ec9313982135510d98a8a9009ae6ff6369ad8229348241289efccb75f06d9be0d02e59da36a73c3c961c7d8a6eeba4966343c03b0652f42b6dd62d5bcbeba49ca94f7577790d86a031cfb0214a46c3064ab9ceb9b41d5f0ba22eae9d5fde6778ae679be3a3ebf09caf7f50d903a315b63b89cc052156ea2e8e1d3e7f1f90dd9096c15219fc226e5fb40534e2639c0b48303f8ace701882a7b9b74b8faa74072802a58fcf9b793c3560d32ddbd3ae3ea984fc7a54d18b1fc05991b7a930373ad800000000049454e44ae426082"; bytes constant Brown = hex"89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000036f49444154789ced9abd6ae3401080c7e61e4195cb1030e4c8a5b807b8268d8d1b839bab53ea090ed7214fe0f2ea348134216eaec903a4389b180c42a52b3d8375cd8d6eb4da3fed8c6c1fde0f0c96b43bbb33dabf190d40241289442291482412899c21bdd08a4992946dca1745e1dd9649761b19be7ce2547e7d7eaa5def77dbea7f7f30ac3d1b4f6725805d0954fc65711f2ca32d2c03ec77db46274da0b1c6d359a95320499212150f9511429f2b60bfdb563f1f5e9f9f1a43dc4779978c50d8063061330855c0a6bcaf0c0e9d1900008c23c3355afa836135b54265f8c2da05da0c5b1d93740e3a1954791f199cf580b5080234576a1d74b1f4510acbf407c3560b6d082c03ac3739c026f72b6c28b7b6d5c767be6d04d0e91af03fc01a01d75717b56b3a547fff5a5665744319873995a196a332ba82bd06504cf31befbbe6bf6f394982a7405114bd493ab7cf610bb87a4fd2390038d60285f52687f52667ef00004223003b6f1baa3605f1d97a933b877ba8c14db0cfd34992940fe95d758d0a50a3a89dfeb1f8597b73aa0c5a6f9567f0e5e2b2d1ae2a23141187224992f2fbe81b0040d5d9559e69af1f976fda8ea30caaac2a03ef99648420b20d1645d17b5cbe01c0bf4e535cca5319ab3cabcabf7f64557dfc492a0fc058036c8ec82acfaacebf7f64f0f5f3a5573d55865a1f8daccae01884ed0be88ea9fbddb6b606a865e8f39bdb91f6b8eb928165b83bc1d14f8287dcf3751cdd0088ef21491a5103f844866ccfdb282965103103b471730fd1962fa2be8004875e13d80638e69b9738169fcc22d816299f801d116aebab63c7e98931548604ec29408d403b860aaacae99c237a7d686f50d41d9694a53384da8eceef680bcb002657d5c5f5d585b3f3e80adbda96a0f36d507ac802f87997beb07701a93771acf65831411a03a07e7c5750f9527101d614f86b842a1a04008d608609d7735b19c9a0087b0d40230000504374018e38c9889068ca89d4377b135da4c844229148e49c39fb6d50ecdb20403d7314931b6e6e47da3aaee7ba32e3e90c004e285314a09e2d664b6733254999d26be97dfc8fed4cd2f969648ab64995b37d3350157705515f16f7c7cf14c56ffa6dfc7d9a004909498d9132824854b88ba0874f9b0fe91ddb086211219fc026e7fb40574666c70401a0111754e37921696eae98206d9f03cb006a12842940aa7b7bdcced3240c0e7f00f6308154847ee1430000000049454e44ae426082"; bytes constant Gold = hex"89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000037f49444154789ced9abd6e223110c7ff9caea520da12290969a08894fe4a404a1e8014291329e5b5d7e731228532053c402205daab235d411a0227a55c918207d82b90375e63afbd9e59e0847f1212bb9e1d7b66fd35b30602814020100804028140600fa9f83e18455152443e8e63e7ba4cba8be870e53be5e18ff787ccf5723a4eff574fda99b27ae32601f28d10864f5eaebc751485e480e574bcd64813c259f5c64da233208aa24418eeabc3876f5405cbe938fdb9f0f1feb0d6c55d8cb7e9f085ec0013790e910dc833de550785d21c00c0d8336cbda57ad24e8796af0e5748ab40916eaba3d57d844e876cbc8b0eca7c409a0481f5995a873c59ba182564aa276d8789f6d1a99d26480e98cf16c06ce8266c909bcf16f6675cebf0a0d439e07f80d4038e8e0f32d77257fd331aa632baae2cbab9ac439593759405790e90318d6f71df36fe5de538f11e02711c575addc7fc319c8398bd5bddd5245644cf7cb6c07cb620af0000530f108dcfebaa79068ab2f96c61edeebe0e37419a04e338ae5cdc3ea7d7a6c6a9f72f6e9fd337a7d321cbf70793f49e7c5fd6418125a088a228e9750e0100d7972d00ab86ebae87a3bfda860b1d425ea743dc33e9f0816508c4715c198e90f43a87e80f2699060376e3651de2fafab285d7b74f9c356be9f3361d3eb02644442f0080d7b7cff4ff59b30660d5781b3a1db6e7290e21c702ba6dea723ace4c8caa8c5c7edae969b7bb361d4286ba126c7d27b8c9355fc7d61d2070dd2471c3ea0097cc505e791123b91cc2e6802261ee26ea72853516e060d37302d901db7cf31cdbe29d99048bc21513901ce0d308b1a7ef0f26e93e7f13f59a200f01398253831800b8fbf523237f747cb066807cbde96890351ce6d4a573845a8f1c23f8421a02be0d704971a9c3a40ce3810d2c83dc5d16708b2e5d21af025c6f625bf579f7003507205073019c949117202b90b341326a2c5fb43c4f66a73242722647e7084e4442642732423ab8bed99b28e3884c20100804f699bd5f06d9be0d02d993a3e270c369a7a77dc656ae93a9376e00ecd846c8745a4c8debd54352bab85f3d4162ca0d709c0b1090a2c12247e5f2be19a886db92a89397abed9f148da22879ba3f2f14efcb0720657c8ec6703981252b5c46d2c3a5cea7fb73b213d832422e894dcaf781b29c4c7280ee0407f095cf13653ec7dc541d79f553203940242c7edefdc659b3666ca8eeedd98cb3d11f4c3287307cf9072e827783447ec0ce0000000049454e44ae426082"; bytes constant Hell = hex"89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000037049444154789ced9a5f6ae33010c6bf6c12ba0da4e4411b0a2185bce40e0b3d498fd053e4143d422fb05758c81dfcd2875228410f2106ef1627641f12796547ffac911343f483426d8f3f69c6926c4d0688442291482412894422912ba4e37b23636c5fc79e73eedc964ebb8e862b3dcacd2f0fb3d2f16ab72dfe1f77cbd2cfc01e303b211c5f4ca6de1a75210560b5db9e74528708d633b05739c018db0bc77d357cf8461558edb6c59f0b2f0fb39321eee2bc4dc3177200749802223b6072de558342630100a01d19b6d132eef68aa9e5abe14aa30110c8d344747c3199d61afa260d4adf488b2070ba52ab90174b9727276cc6dd5ead85d607927292e64890bbd96aec92547fbfb8c7b50d1fce3205da0c6904cc87fdd2b13c547fafff1436aaa1bcda6d814d59a36a276b68d9503c08b006c8e8e6b7386f9bffae7621f19e029cf3cee2e3dd38874d2c3ede0b0dc0bc165449d21c499a171a5e1d3812640488ce9b86aa71b13b5e4bd2dc3cdc2d3a3e901641ce79e775f3591ceb3a573dffbaf92c9e9c4a43b65f66ebe29c7c5ed6a0106443c118dbcf7adf01003f072300878eab8edfb67f951d171ac25ea521cee9347c08320538e71d1c1d5866eb528701bbf3b20624a7f95706763328eeb769f810342122460100f0afecbfedcd00c0a1f336541ab6fb2901218d80c564aafc4c5dedb6a585b16a235f7f1cdd2a3f776d1ac246bc457cb9f897e039dff92a2e1e0081eb4752688206c0253364ba5ec7c9d6e503ea6c73cfd1962bcd6db43d39f79a400ec0259f7c88cfe2d62c827509b5272067846c9b17d53d00a4afbb91b74608c853400e4275130300f3e18f92fd7cd83f71403e3ef76e30e87638a4962a10d576e43d822fa400a8363e2ecc877d2c33b34d92e6a569a26a3b048dbf06430f59c06d77e90af92d10ea495caa3def1150cd01087ca6842b4de405c802723648a6ba97af7bdd64d3aa8c5091c9413999d1042221d28a8c908a50bfd9eb68a2442612894422d7ccd5bf06836c8684e372e5a8286e781cdd2aefb15d57d9b4ae521428d7f999cad9744552baf25af9bc5c1506008bb6548afa94b9a9a83a6e4ba286288f1378078031b67fbabbafb5df970b20657c4a634205214856b889a4874b9b4f77f7972f94943b24d0253629bf0f341564724e10384d8254f37975d3de2a0d53fb14480110098b5fc74a0e5d3648f5f46cced95866eb43fb5dda2cfe07f2bf7fac7f79917b0000000049454e44ae426082"; bytes constant Navy = hex"89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000035749444154789ced9acd6ee2301080876a5b4a0e54489638e4d256ea8563dfa14fdd77e891cb1e762f9116c91282432020357b68ed3a8eff670254f5272111e28c672613c7330c402693c96432994c2693c9fc4046a91732c6da98f19cf3e0b96cb2636484f20b73f1e3f34be798af2af99dcdcbeee0b7d716c06d84307c5a2e9265c48272005f557d252d4867bdbdb626031863ad303c55460a5758017c55c94f088fcf2fbd100f31de272315b4036cb81ca21ae0323e540686c11c0000d6c8f0450b9b97f2d14a95110a6a0d08c5a4ecc75d5f0687be4b06663d403b2064115417cb903b27c6b079e95d68b7d532505333a87dc078768f9abc59ff050a19980818740df80ea01e817151748ed550adfefc96634ca1cc571534ebae0c7d9c2ac346b3c65840bc08da9e6ff1bbeff90f1d4749f223c0391f6dab2534759d74fdb65a4a19001025a7a96b68ea5aca4852e013920810ca3b43d561a038d7d4b553864f4e0ab85c80f31103906f039b01bad2eaca6d9201f0e5cce37e639c1bbbfa0bd011200cb89acc3abfeb8a8be3f7ddbaa7b82ae3faf60e003e1c6132feb8df1865a442965632c6a413ae6fefa4f2ea779fe2ba8cc3f61f8c6e269d3194c603101744d428680fbbaf493e8d78dff9df592619beebcfb6159e960be33695afaaceb3ac8f51cf970f4fc6edae4f861883dd0a9f7d2778ca77be89b33b4010ba49a286d401219521d7f91823a91c42e6809834f7147385729282480ca75e13f01ba133de798a6df1c52c82b150e504a80808495e4cd70074b7caa93228403f02aa1354c58481ba71e3a2e82747caf1b7ca0605944ab9526b7d1e5ba61803ca01c7fd46666f318c8bc2abbc2d1b54e7a660f0d72075c802b853eb58d06f01aa3b71aef9503541919e1ef71bf91912553e555d002d402d62a8e8b97cec79d718caa2084d498c410bd02d660c8188b88ba80899a0facfdec6102d32994c2693f9c9fcf8d7204932240c573b47457343f9f064bcc677de3866804e5192adb0a9d34bcfebf5262953dedfeb20b1d40628fa0204a80888e9f0741546456b8c6f9c80a23d4e909c0d8a2eb1987c5f6d805449698d99968bcbe9141da2e81132e778768f7602594528a4b089f97f602827a36b8200d0ab0beaf5bcd8b2b749866b7e0c28078882c5e1b083d1cdc45a2035dd3dacf2c7fda6d38491ca7f0bac6cab77088dfc0000000049454e44ae426082"; bytes constant Orange = hex"89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000035f49444154789ced9abd6a1b41108047219d444070e060ecd2e801e4d218b9481a57e9f40a7a041726850b3f825ec12fa0462a2c8c3b5b0f6052da04051604e6542b8533e7b9cbeeedcfcc4a32da0f04badbbdd99db9b9b99db90548241289442291482412891da4117a6196652b9ffe4a29e7b14cb27d64b8f29973f1d3cd79e9385f2c8bffad76b3d4d6e98f5600f54aa0e2b3612f58862f2c0f980d7ba549d61900e9f4475a05501ec55746089fb802f2c5b2f8b9f07473fe9f8beb94f795110adb0026ea0c4215a853de55068768060000a367d8bca5d56e16ee1f2ac315760ce0d01d4c4127832aef2283130f586f010073a0a2e48ba59752d8a7d56e96ae8d01cb00af2a8757953bf7f5394fdb5cc708216a0cf808b03ce04bd62a1d5357fdfdeb4fd147e7cae8e65446b51f95110b760ca0989e6f3c6f7bfe5dfb4912fc0828a51addc134f8f9c4e8dd1d4c01c0ef39c7d8c37d03000879004ebece555d839dcddda503222b082aa51a67978fc5b16ba43fbb7c2cee9c4e06ed3f9ecc8b73f43c95c14124a1c8b26c75717a000000dfbf7d0580b789eb8eafef5e8cc9d0c5e941d15f2703cf996484209656568d40276f53de24e3c7cf07189c1c96fa482a0f205c10c1c903000cef9f8bffa8c4f5dd8b55ae4e86ed7a8e4144eb0148be58960263b50f6ddf3fdad32e776d32b00ff74db0f195e03adff93a366e00c47591248da8015c2a4375ed3e4a4a1944cc003e69ee3ac6724534179060dd31816d804dde798965f1d604415fa4720296014226816bfaf1645eacf3d731ae09b607d0c9d0a40515aca2cbf674c98ecb781288a6c392b24c86a2e80cec0bcb034227e052e2aa3e2631940758c36b304645d735bb74811d03a4eec4a6c663d504313d45578d6d0c2a5faa2ec07a04de8c002b9ac3e324693d4087adbdae8f6451841d03d00800e562460cd0e3b6a222a443ea9bbd89185b6412894422b1cbecfc6b50ecdb204079e7286e6ed83fdad35e636bd7f5e9f44700b0650b21d36eb16a5e5fdd24a5cbfbab3b484cb501897d01082b1bf4d92a57f7cda0aab8ad883a1bf636bf5334cbb2d5edd5b157be4f37405242b6c6481941a42a1c731b5bdd98b757c76c23885584a8114c252fcef7815846661940b78303e0bd9e876d21dbdcaa32eac6e7c03200162c86f7cf303839344e5477f76ccad9184fe6ffc6e7bd0cfe02ec318fd9344a0a090000000049454e44ae426082"; bytes constant Rip = hex"89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000027749444154789ced9ab18ec2300c40cd89b92ccc5dda9105f1ff9f8058186161ee427f809baccbe59cc44e9c36a7fa2d080826761cdb7103601886611886611886b14176b93f3c1e8f1fc9f8699ad8ff15922d91c1655ff2e3e7ebc11e3bf4e30720ae042a1e92cb9121a5c803240640867e241590c80bc9c8e14b438884ae3bfc7171a9319faf87780b8658d400e7d3056ef7eb2f23e478d2f974210d99c3a206b8ddaf703e5d54e468b1f816c0c9e30a4a561f8d87af1a5eb0f8162841cb835c8ab240d71d8afe7c9edfa021a324232cbe055aa3a8100a052374537459779cefc2b180e6caa13ed7a0ba07f893cf8de07e00d422db00d334ed867e8c8ea1268b9fe1de45191cc5fc31a5fb1fa0b207e06aa7560fb749ca089af91f29aea7a95c4ec50057397fe5a88c923288c6ea032878406c2b70944719f3fc0600de2a6b290fa0e00108a72e484d5c438694ec34985b829694aee825be8c128354698884f2778d31a94c9462f395a01960ed09ac8d1960ed094871ab4a8d73c1bf32805b586995c5cd192076800a95d6252c6e007fe29cfe807ba8d26e8badd61475df734e8b359407503440eec47cc5a8e0e61fab355133406e50f2831a25a786e248b101527bda776feef71ca59be808a57a7eeeca52e9cb5ff91a5d9f186a3dc15800c3572a8851318083565fa07a4b0cdfc75ae3529aeb08b9171b5ce5b4d31636449ab82041a1f5cc3e448d2b32866118c696d97c1a542f8490d4438d9c0723587a37f1680cc9bd319a03fecfd08f9f266e8a2ea93cc08f473471531495d76e56c4e4b987ab266e8a4afa74b131fe018a2b43c30855ee09fa4689b5b9a823b3c4ab56bf27487574a8a607c703b49ef64858f5a6a806a51ef00d0127c02237dfbafc0000000049454e44ae426082"; bytes constant Rock = hex"89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000036449444154789ced9abd6ee240108087d33d81b574c4af80a868d2a108d14442a9d2a54a9707b9ea8a4857a44a478522d144164a972615ca2b001d2bbf82af88c6599b5defcf8c8188fd24246caf6777c6b3e3ddf10044229148241289442291c819d209bd510851f8b497523af76592ed23c395df949b571fef95e33cdf95ff93a45bb936185e1600cd4aa0e26faf2fc1327c211920cf777b833481c61a0c2f0b9d02428802150f9511c22faa803cdf953f17561fef7b2eeea2bc4d4628640398683288aa4093f2ae3228b4660000307a86cd5b92a45b4ead5019ae90de023e6eab633499824e86aabc8b0c4a3c20054180fd48ad430d962e4a619b24e97a05da104806d86cb6b0d96c9ddbfa9c57afb9f61142ab31e02740f2808b8b5ee55875d5cfcf55d946e7cae8e6aa8c7a3b55465b9063808a697ee379dbfc776dc749f014905276469369f0fcc4e83d9a4c01c06f9e63eca1be0100983c0007dfe4aaaec1cee6eedc01911404a5949dbbfb87f2d835d2dfdd3f944f4e27436d3f9b2fca73ea79550605960d8510a2188faf0000e0f6e61a00be06ae3bceb2a576e02803dbeb64e039938c1058a68094b29365cb623cbe82d97c511930805d7955061edfde5cc37abd8534ed95f7db6484c09a10412f000058afbfdd354dbfe675962dad7275326cf7530c42de0be896a979beab04c67a1bf57abf3fd02e776d32b00df54d70f495e021dff93a8e6e00c47591c40dab015c32434dd77d94e432089b017cb6b987e8cb15d6bd0007878e0964031cf3c9732c8b4f2608fac2b5272019206410b8a69fcd17e53aff10fd9a207b803a1875d3820ad6d1edf6749b1d97fe3860dd0e73ca32194a4567605f481e103a009714577d9ab4a13cc0015e836d64745d7697ae906300d79338567fc11e50cf0120f55c00276de405c802d46c904a7d2fef7bbda9cd496584d44c8ece109c6042e42432423ab8bed99b68a3442612894422e7ccd9bf06d9be0d02542b47b1b8a1df1f68efb15dd7b5190c2f01e0842a4501aad5624de56ca622295379ad7a1eff633fa3c9f4342a457d4ae59abe19d415b72551df5e5f8e5f292a84289e9f1ebdf6fb6a01a44a48690c971158b2c26d96b135f5f9fcf44836025b4648358229e545f93ed096914906d05570007ce7f3f05a48995b5d4653ff144806c084c59fbfff204d7bc681ea9e9e4d391bb3f9a2528411ca7f3f789142ac22e3ce0000000049454e44ae426082"; bytes constant Rouge = hex"89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000034d49444154789ced9ab18ee230108687d349275d419596faa4d0b05dd817d86a4b1e01695b6aeaad69917804caabee05201d6912696b5a57142b6dc515bb8e26c6766ccf84b0c29f844412e7b767327132130344229148241289442291c81d32083d314992b34f7b2184735f266d1f0d577e524eae56af8ded5355d4ff87e9a4712c5d2ccf007623a4e1f97c16ace10b2902f2f9ac31489b0324e962a93540ea617c3542f84115385545fd73a15abd5e84b8ce785f8d50c80e3061730836c066bcab0685ce1c0000c6c8688b96613aa9c33f54c315f21c4021db6c41a7818d77d1a0cc07a4a7008079a2c29caac2cb28d966984e1ae7ead93a8dd304c901fbf208501edd1a1bdaed6de7cb63ae7d04d0e91cf01d2045c0743c6a6ce350fdb7fd5bb7d185f2a92a00767943436d87358cec728a09f4390063babfe5feb6fbdfb51d27c1b7801062906db6f67bd8829cbdb3cde724e6a3b32f8fb02f8fe42700005304c8c1db42d566a03cb62f8ff6706fd1098134090a21060b740f9a06a7ee5fecf2facae93470fb7571a8f7e1fd5883023902be0c38fff9fdabb17f5d1cb4db6fef1f1703c71a2f930700f87484aa2175741aa1b0a5954992d44e78993cd483c7ffdb066ed2c0701a0fc05c1051a340e5edfda355d7a6613abfb75761b51e20395545636254dbe0e34fb367edeb6e9b866c239f22a1f4fe2678cd67be8ede1d20717d49e286d5012e9521db711f23b91cc2e6009f34f71a7db9c29a0b7070ed3981ec803eaf3cc76bf1cd4c82be70e504e48a505bf2a23b07a0f9aa1caac101f916c04e509318804be3a6e3d1850178fbdad9206b3acca9a57384da8f2e57f085e4807571a8b3371fa6e351ebe04dd920ee9b83ce1f83dc210b604fad7d213f05b8ae445ffd0547801062005ff93b1e54c82de10aee87ab2e4016c0458c6b71731521591ce9da11b220721315211d5cdfec4d74b1442612894422f7ccdd3f06595f84f0ca51b9b8e169f6ac3da7edb8ae4dba580200af23c8d9205e2d665bce665a24655a5d8af7cbffb29f6cb33ddfc44a519fa572b66f06aae16d45d47c3eeb7fa5689224e7d563e695efe305909890a5315c4e60a90a7751f470e973f598919dc0561172296c52be0f74e564724d10e0b208a2d6f37ccbde3a0d5bff145822c0e40889eeea5107cf551afb0fe1da4dd508c862c60000000049454e44ae426082"; bytes constant Squi = hex"89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000040449444154789ced9abd6adc4010c7ffe71c290226c5ad316a7270b83c84895db8f313b8cb0bdc4b5c9147307e877b8134264fe0ce86a4092e83e1d288035d11420c0621a55056da5bed87a4193901efaff159ba5bcd7ff66b66b44020100804028140201008bc40467d7f288428ba7c3f4dd3d6cfb2b5dda58db68c293f4e92f3eaf3473c2977ae77be77f5fa37849815805b8414feeddd5be3fd18f0b6d1159203243ef100b0dd3e000084981526014288c224fce0eeb8fa9cfcfd1b4537c636fa4076804f7c9eef57ff6f4e1f01ac31c77447802e5e155d193afe547d5e24175845b72c4e20ad018be44cb9528b97bdae8a976c4e1f911731e21f3f91a6e948156f120eec8a972cb30baca25bf27460990226f136f2226e5c33095747d6a5f599872dedb3b3476ec1223e79ffcaf9ab24398710a2501752a014be3badec2c924de7dd48873802dce237a78f38fcf2a6be7e72e4ed6dc9e5f833006099e55866392ec7755f2db39c66b602cb1450c5cb792fe77a72525e3fb83b6e21feba715fb67f6579f664d2c7e21ab2036cc35e9debba70f310df15bfcc72ef7ac201c901260365cf03fec5adc41c37487c6bc97cddc250074cbb4069a8abd701d3702f57f12e8b2737a43d540851dc4feb2ec88bb8f53c5f4587551cb0dd3e78859bb64f194bf4b3be846d04f8c5efee18eae265126f123c04e450524672f685aeb9554e2633e8a1f0fd74ed15ad3e238a6e5892229684420d686cdb9a4dbcda862d0b0486110f303900a89dd0a5e74d6df8f2024ef1007341a44e8e4af1faea3e5f4fbdedeaa1b1e4239eb08a6e8df7280e2139a039ecfd7941db6468b75d49335294bb494bb31b30d6039ae2f5d5dd152798525e731658b2b7f70bc03f0e8575f1ae80c617247525cff72b275018341b043ae404d985b34d1553a1a52fecd9a04afb84a839b7db84c7e5c2dac150036c91a0441a6b13df25197a8ebc6090747828f1b25d5963e0802d1da6886f2b5c127dfd5e7ef7e4a8bbd11a0c35c1e1c4e745dc10afb6cbb19b90a7c090e255d436b3ec436f7b7568afc60cc3d5dd2bddc5bb9d49876517b0a5b1becc10b08b1f5ab884751bb41bdd2f60f2154fa97900c0e0007fe5864bbcb9644ea5b703d2341dcd313516314c09928a4b7c5be11cbd0f1047409aa6a3183096c4744c19a23b41b287c7bec24a17c853403a01d10d7c15211bee395fb73199ccaa67d2acae613d72427d51e9638823328140201078c9bcf86d90251992c217c9c61bef37839ef6ef13fecb93a2e579c10d007fb2e30a977d95e583bbe3414e8a924a6236f12aa66cd1952cb5719c3c62d7c7669dde0e7089ef5e296a62132fcf112e92331627b01445557c2f424de873df5615d293250e273cfb31b93ee52d778d80765c96fdcd900e47e9baa6f92285fa76986d0af419fa14b80e51fe015b82798ed508dde10000000049454e44ae426082"; bytes constant Zombie = hex"89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000035a49444154789ced9abd6a1b411080c721459cca82c38582f01bd87e06b706f74206bf82e00a831f409042a0573058b837a4f53324695d092115e6e05cf9dc294de632b7dadddbdd999514b41f187cbabdd99db9d99f991b8044229148241289442291d8430e421fccb26ce5d3be280ae7be4cb27d64b8f299f3f0f8f1ae713d5fceeaff7bdd93c6bdbc3f5a01d89540c587e341b00c5f581e301c0f1a83b41900c9fb23ad02288fe22b23844f5c01f3e5acfe7361fc78b7e6e23ae57d6584c23680099b41a80236e55d657088660000307a469bb7f4ba27b5fb87ca7085bd067098e453d0c9a0cabbc8e0ac07ac5d00c0bc5051e6cb999752d8a6d73d693c1b039601cad737285fdf9cdbfafc4eefb9f61142d435e07f80e5019de3a3c63575d5df3f7fd56d74ae8c6e4e65a8eda88c58b0d7008a697ee3ef6df3dfb59d24c153a0288a83493e0d9e9fb87a4ff22900f8cd735c7bb83b00809007e0e06daeeabad8b5b9bbf482c83e4f6759b6bab9bdacaf51016a1475d0f7df7f34de9c2a833e572e2ae87c3b5ceb5795118a48409165d9eaeafa0200a01e6cb9a8b4d74f0fcfc660e8eafaa2a1ac2a037f33c908412cac548d4007dfa6bc49c6f2a584c3af5f1a6d24950760ac01b640a45c5450bd7f000040f5f2d150c2358041a355efff9e7f7a78d6cae01844341f80cc97b3c61aa0b6a1f74fcfcfb4c7dd3619d886bb136cfd24b8c93d5fc7d60d80b81e92a41135804b66c876df474929838819c027ccdd445fae88c602126c7a4d601b609b6f5ee258bc338ba02f5231013b23e41babd781cfdf830e807fbc2f1910b1a70035021d587d145694d30547f47ad3d1a068382c294b678835c3112f0a8537050ca16a1b9de3a3d6c163286ceb5b82e8db608c8cae6b74e9027b17907a13dbea8f9513c4f0b45c54f55f4ca87ca9bc80484a0c931814cc07a8090dd7fbb6363b9711c2040535440c03a0c7ed4481840ea96ff6266294c824128944629fd9fb6d50f420442b47b1b8e1f4fc4cfb4cdb7d5d9bbc3f02801d3b0899aac5d4b85e2d92d2c5fd6a0589293720511780b0a2419f5239db370355f1b624ea703cd87ea5287ed3f789f769012425a43446ca082259e198656cb63e6f6e2fd94610cb08b9243639df076219999d130480b5bca09acf0b29736bcb09d2fe39b00ca016419812a4bab7c71d3c2dc2e0f0077d3871dcf62e9aae0000000049454e44ae426082"; bytes constant bg = hex"89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000018249444154789ced9a416ec5200c4427558f00f73f20dcc15d54a852d4f4077b7e4614bf75620d0f1448e2c3cc0c1bf3a10ea02605a803a84901ea006a52803a809a14a00ea02605a803a8d95ec0a7f7c65aebd4f5adb570ed991a77710b0080defb71f7da5aab017f0f620cfcaaee9d1ad39893528aeb35ba9412ae7755c3c3e3cf80defb715ee2b5d6a9d5f45b0d375e73de153018b318a9c35809dbef02b215007ccf20a346ae800029401d404d0a50079013798232f6f03c07a8891af4cce079e61835bc840598715e64542f43140166f706f02a38a3c62c8f7d1089de07fc1c9dcf3542df07bce618e77806f92e102405a803a84901ea006a52803a809a14a00ea02605a803a8595a4029c5a23f4a9716c0c02da0b546f9b3e38531fb407005a824b0060f008759bc5dfe5563038b219bd920411130a0fdb3bfe01d2d3254012b92bb803a809a14a00ea0667b01a146c9332b6e8314014f1d84ded1291a3e07cc363932601e8543cf00c5e0817fd229ca60fb0e11c64a585a008314a00ea0e60bf0425f8751926ab40000000049454e44ae426082"; }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev Interface of ERC721A. */ interface IERC721A { /** * The caller must own the token or be an approved operator. */ error ApprovalCallerNotOwnerNorApproved(); /** * The token does not exist. */ error ApprovalQueryForNonexistentToken(); /** * Cannot query the balance for the zero address. */ error BalanceQueryForZeroAddress(); /** * Cannot mint to the zero address. */ error MintToZeroAddress(); /** * The quantity of tokens minted must be more than zero. */ error MintZeroQuantity(); /** * The token does not exist. */ error OwnerQueryForNonexistentToken(); /** * The caller must own the token or be an approved operator. */ error TransferCallerNotOwnerNorApproved(); /** * The token must be owned by `from`. */ error TransferFromIncorrectOwner(); /** * Cannot safely transfer to a contract that does not implement the * ERC721Receiver interface. */ error TransferToNonERC721ReceiverImplementer(); /** * Cannot transfer to the zero address. */ error TransferToZeroAddress(); /** * The token does not exist. */ error URIQueryForNonexistentToken(); /** * The `quantity` minted with ERC2309 exceeds the safety limit. */ error MintERC2309QuantityExceedsLimit(); /** * The `extraData` cannot be set on an unintialized ownership slot. */ error OwnershipNotInitializedForExtraData(); // ============================================================= // STRUCTS // ============================================================= struct TokenOwnership { // The address of the owner. address addr; // Stores the start time of ownership with minimal overhead for tokenomics. uint64 startTimestamp; // Whether the token has been burned. bool burned; // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}. uint24 extraData; } // ============================================================= // TOKEN COUNTERS // ============================================================= /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() external view returns (uint256); // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); // ============================================================= // IERC721 // ============================================================= /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables * (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, * checking first that contract recipients are aware of the ERC721 protocol * to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move * this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external payable; /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external payable; /** * @dev Transfers `tokenId` from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} * whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external payable; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the * zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external payable; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} * for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) external view returns (bool); // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); // ============================================================= // IERC2309 // ============================================================= /** * @dev Emitted when tokens in `fromTokenId` to `toTokenId` * (inclusive) is transferred from `from` to `to`, as defined in the * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard. * * See {_mintERC2309} for more details. */ event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to); }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; import '../IERC721A.sol'; /** * @dev Interface of ERC721ABurnable. */ interface IERC721ABurnable is IERC721A { /** * @dev Burns `tokenId`. See {ERC721A-_burn}. * * Requirements: * * - The caller must own `tokenId` or be an approved operator. */ function burn(uint256 tokenId) external; }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "solmate/=lib/solmate/src/", "@openzeppelin/=lib/openzeppelin-contracts/", "erc721a/=lib/ERC721A/contracts/", "solady/=lib/solady/src/", "ERC721A/=lib/ERC721A/contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract OnchainRocks","name":"_rocks","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApprovalCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"ApprovalQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"BalanceQueryForZeroAddress","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"MintERC2309QuantityExceedsLimit","type":"error"},{"inputs":[],"name":"MintToZeroAddress","type":"error"},{"inputs":[],"name":"MintZeroQuantity","type":"error"},{"inputs":[],"name":"NotAvailable","type":"error"},{"inputs":[],"name":"OwnerQueryForNonexistentToken","type":"error"},{"inputs":[],"name":"OwnershipNotInitializedForExtraData","type":"error"},{"inputs":[],"name":"TransferCallerNotOwnerNorApproved","type":"error"},{"inputs":[],"name":"TransferFromIncorrectOwner","type":"error"},{"inputs":[],"name":"TransferToNonERC721ReceiverImplementer","type":"error"},{"inputs":[],"name":"TransferToZeroAddress","type":"error"},{"inputs":[],"name":"URIQueryForNonexistentToken","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromTokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"toTokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"ConsecutiveTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"addArt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bool","name":"approvalCheck","type":"bool"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_hash","type":"string"}],"name":"hashToMetadata","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_hash","type":"string"}],"name":"hashToSVG","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId1","type":"uint256"},{"internalType":"uint256","name":"tokenId2","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"numberMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"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":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenIdToHash","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBurned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b50604051620093e9380380620093e9833981016040819052620000349162000d8f565b6040518060400160405280600d81526020016c27b731b430b4b727b832b832b760991b8152506040518060400160405280600d81526020016c27a721a420a4a727a822a822a760991b815250816002908162000091919062000e62565b506003620000a0828262000e62565b5060008055505060fa600d55600b80546001600160a01b0319166001600160a01b038316179055620000d1620000d8565b5062000f44565b604080516001808252818301909252600091816020015b620001346040518060e0016040528060608152602001606081526020016000815260200160608152602001600015158152602001600015158152602001600081525090565b815260200190600190039081620000ef5790505090506040518060e0016040528060405180604001604052806002815260200161426760f01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa81526020016040518061020001604052806101c8815260200162008ad26101c891398152602001600015158152602001600015158152602001600081525081600081518110620001f257620001f262000f2e565b60200260200101819052506200024f60006040518060400160405280600a815260200169109858dad9dc9bdd5b9960b21b815250782a0447781a3883ec736ad2be7913092a92e405d8ce75f8e00f84600262000adf60201b60201c565b5060408051600b8082526101808201909252600091816020015b620002ae6040518060e0016040528060608152602001606081526020016000815260200160608152602001600015158152602001600015158152602001600081525090565b815260200190600190039081620002695790505090506040518060e0016040528060405180604001604052806004815260200163526f636b60e01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103e001604052806103aa81526020016200903f6103aa913981526020016000151581526020016000151581526020016000815250816000815181106200036e576200036e62000f2e565b60200260200101819052506040518060e0016040528060405180604001604052806005815260200164213937bbb760d91b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103e001604052806103b581526020016200795e6103b59139815260200160001515815260200160001515815260200160008152508160018151811062000424576200042462000f2e565b60200260200101819052506040518060e0016040528060405180604001604052806004815260200163426c657560e01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103e001604052806103b9815260200162006a126103b991398152602001600015158152602001600015158152602001600081525081600281518110620004d957620004d962000f2e565b60200260200101819052506040518060e0016040528060405180604001604052806005815260200164526f75676560d81b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103c00160405280610393815260200162007181610393913981526020016000151581526020016000151581526020016000815250816003815181106200058f576200058f62000f2e565b60200260200101819052506040518060e00160405280604051806040016040528060068152602001654f72616e676560d01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103e001604052806103a5815260200162008c9a6103a59139815260200160001515815260200160001515815260200160008152508160048151811062000646576200064662000f2e565b60200260200101819052506040518060e00160405280604051806040016040528060048152602001634e61767960e01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103c0016040528061039d815260200162007d1361039d91398152602001600015158152602001600015158152602001600081525081600581518110620006fb57620006fb62000f2e565b60200260200101819052506040518060e001604052806040518060400160405280600481526020016311dbdb1960e21b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa81526020016040518061040001604052806103c581526020016200870d6103c591398152602001600015158152602001600015158152602001600081525081600681518110620007b057620007b062000f2e565b60200260200101819052506040518060e001604052806040518060400160405280600481526020016312195b1b60e21b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103e001604052806103b6815260200162006dcb6103b69139815260200160001515815260200160001515815260200160008152508160078151811062000865576200086562000f2e565b60200260200101819052506040518060e00160405280604051806040016040528060068152602001655a6f6d62696560d01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103c001604052806103a08152602001620080b06103a0913981526020016000151581526020016000151581526020016000815250816008815181106200091c576200091c62000f2e565b60200260200101819052506040518060e001604052806040518060400160405280600381526020016205269760ec1b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806102e001604052806102bd8152602001620084506102bd91398152602001600015158152602001600015158152602001600081525081600981518110620009d057620009d062000f2e565b60200260200101819052506040518060e00160405280604051806040016040528060048152602001635371756960e01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa815260200160405180610480016040528061044a81526020016200751461044a91398152602001600015158152602001600015158152602001600081525081600a8151811062000a855762000a8562000f2e565b602002602001018190525062000adc6001604051806040016040528060048152602001635479706560e01b815250787b2b44c99db9e92dcb7790634e8caf295764b2ea4221185a1b84600262000adf60201b60201c565b50565b60408051606081018252858152602080820186905284518284015260008881526008909152919091208151819062000b18908262000e62565b5060208201516001820155604090910151600290910155600c81905560005b825181101562000d3d57600083828151811062000b585762000b5862000f2e565b602002602001015160a001511562000bc75760096000888152602001908152602001600020600085848151811062000b945762000b9462000f2e565b60209081029190910181015160c001518252810191909152604001600020600301546001600160a01b0316905062000bfb565b62000bf884838151811062000be05762000be062000f2e565b60200260200101516060015162000d4560201b60201c565b90505b6040518060a0016040528085848151811062000c1b5762000c1b62000f2e565b602002602001015160000151815260200185848151811062000c415762000c4162000f2e565b602002602001015160200151815260200185848151811062000c675762000c6762000f2e565b6020026020010151604001518152602001826001600160a01b0316815260200185848151811062000c9c5762000c9c62000f2e565b6020908102919091018101516080015115159091526000898152600982526040808220868352909252208151819062000cd6908262000e62565b506020820151600182019062000ced908262000e62565b50604082015160028201556060820151600390910180546080909301511515600160a01b026001600160a81b03199093166001600160a01b03909216919091179190911790555060010162000b37565b505050505050565b60008151600181018060401b6bfd61000080600a3d393df3001761ffff8211850152600a8101601585016000f09250508162000d895763301164256000526004601cfd5b90915290565b60006020828403121562000da257600080fd5b81516001600160a01b038116811462000dba57600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c9082168062000dec57607f821691505b60208210810362000e0d57634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111562000e5d57600081815260208120601f850160051c8101602086101562000e3c5750805b601f850160051c820191505b8181101562000d3d5782815560010162000e48565b505050565b81516001600160401b0381111562000e7e5762000e7e62000dc1565b62000e968162000e8f845462000dd7565b8462000e13565b602080601f83116001811462000ece576000841562000eb55750858301515b600019600386901b1c1916600185901b17855562000d3d565b600085815260208120601f198616915b8281101562000eff5788860151825594840194600190910190840162000ede565b508582101562000f1e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b600052603260045260246000fd5b615abe8062000f546000396000f3fe6080604052600436106101815760003560e01c806366e33870116100d1578063a2309ff81161008a578063d5abeb0111610064578063d5abeb0114610425578063d89135cd1461043b578063dc33e68114610450578063e985e9c51461047057600080fd5b8063a2309ff8146103dd578063b88d4fde146103f2578063c87b56dd1461040557600080fd5b806366e338701461032857806370a082311461034857806389ce30741461036857806395d89b41146103885780639fac68cb1461039d578063a22cb465146103bd57600080fd5b80631b2ef1ca1161013e57806342966c681161011857806342966c68146102a85780634f558e79146102c8578063621a1f74146102e85780636352211e1461030857600080fd5b80631b2ef1ca1461026257806323b872dd1461028257806342842e0e1461029557600080fd5b806301ffc9a71461018657806306fdde03146101bb578063081812fc146101dd578063095ea7b3146102155780630b1eb64a1461022a57806318160ddd1461023f575b600080fd5b34801561019257600080fd5b506101a66101a13660046124ae565b610490565b60405190151581526020015b60405180910390f35b3480156101c757600080fd5b506101d06104e2565b6040516101b2919061251b565b3480156101e957600080fd5b506101fd6101f836600461252e565b610574565b6040516001600160a01b0390911681526020016101b2565b610228610223366004612563565b6105b8565b005b34801561023657600080fd5b50610228610658565b34801561024b57600080fd5b50600154600054035b6040519081526020016101b2565b34801561026e57600080fd5b5061022861027d36600461258d565b61101b565b6102286102903660046125af565b6111a9565b6102286102a33660046125af565b61133a565b3480156102b457600080fd5b506102286102c336600461252e565b611355565b3480156102d457600080fd5b506101a66102e336600461252e565b61135e565b3480156102f457600080fd5b506101d061030336600461252e565b611369565b34801561031457600080fd5b506101fd61032336600461252e565b61142f565b34801561033457600080fd5b506101d0610343366004612698565b61143a565b34801561035457600080fd5b506102546103633660046126e1565b6115c3565b34801561037457600080fd5b506101d0610383366004612698565b611612565b34801561039457600080fd5b506101d0611831565b3480156103a957600080fd5b506102286103b836600461270c565b611840565b3480156103c957600080fd5b506102286103d8366004612738565b61184e565b3480156103e957600080fd5b50600054610254565b610228610400366004612762565b6118bf565b34801561041157600080fd5b506101d061042036600461252e565b611909565b34801561043157600080fd5b50610254600d5481565b34801561044757600080fd5b50610254611a49565b34801561045c57600080fd5b5061025461046b3660046126e1565b611a54565b34801561047c57600080fd5b506101a661048b3660046127de565b611a7f565b60006301ffc9a760e01b6001600160e01b0319831614806104c157506380ac58cd60e01b6001600160e01b03198316145b806104dc5750635b5e139f60e01b6001600160e01b03198316145b92915050565b6060600280546104f190612808565b80601f016020809104026020016040519081016040528092919081815260200182805461051d90612808565b801561056a5780601f1061053f5761010080835404028352916020019161056a565b820191906000526020600020905b81548152906001019060200180831161054d57829003601f168201915b5050505050905090565b600061057f82611aad565b61059c576040516333d1c03960e21b815260040160405180910390fd5b506000908152600660205260409020546001600160a01b031690565b60006105c38261142f565b9050336001600160a01b038216146105fc576105df8133611a7f565b6105fc576040516367d9dca160e11b815260040160405180910390fd5b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b604080516001808252818301909252600091816020015b6106b36040518060e0016040528060608152602001606081526020016000815260200160608152602001600015158152602001600015158152602001600081525090565b81526020019060019003908161066f5790505090506040518060e0016040528060405180604001604052806002815260200161426760f01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa81526020016040518061020001604052806101c881526020016151726101c89139815260200160001515815260200160001515815260200160008152508160008151811061076c5761076c612842565b60200260200101819052506107c160006040518060400160405280600a815260200169109858dad9dc9bdd5b9960b21b815250782a0447781a3883ec736ad2be7913092a92e405d8ce75f8e00f846002611ad4565b5060408051600b8082526101808201909252600091816020015b61081f6040518060e0016040528060608152602001606081526020016000815260200160608152602001600015158152602001600015158152602001600081525090565b8152602001906001900390816107db5790505090506040518060e0016040528060405180604001604052806004815260200163526f636b60e01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103e001604052806103aa81526020016156df6103aa913981526020016000151581526020016000151581526020016000815250816000815181106108da576108da612842565b60200260200101819052506040518060e0016040528060405180604001604052806005815260200164213937bbb760d91b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103e001604052806103b58152602001613f596103b59139815260200160001515815260200160001515815260200160008152508160018151811061098c5761098c612842565b60200260200101819052506040518060e0016040528060405180604001604052806004815260200163426c657560e01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103e001604052806103b9815260200161300d6103b991398152602001600015158152602001600015158152602001600081525081600281518110610a3d57610a3d612842565b60200260200101819052506040518060e0016040528060405180604001604052806005815260200164526f75676560d81b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103c00160405280610393815260200161377c61039391398152602001600015158152602001600015158152602001600081525081600381518110610aef57610aef612842565b60200260200101819052506040518060e00160405280604051806040016040528060068152602001654f72616e676560d01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103e001604052806103a5815260200161533a6103a591398152602001600015158152602001600015158152602001600081525081600481518110610ba257610ba2612842565b60200260200101819052506040518060e00160405280604051806040016040528060048152602001634e61767960e01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103c0016040528061039d815260200161430e61039d91398152602001600015158152602001600015158152602001600081525081600581518110610c5357610c53612842565b60200260200101819052506040518060e001604052806040518060400160405280600481526020016311dbdb1960e21b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa81526020016040518061040001604052806103c58152602001614dad6103c591398152602001600015158152602001600015158152602001600081525081600681518110610d0457610d04612842565b60200260200101819052506040518060e001604052806040518060400160405280600481526020016312195b1b60e21b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103e001604052806103b681526020016133c66103b691398152602001600015158152602001600015158152602001600081525081600781518110610db557610db5612842565b60200260200101819052506040518060e00160405280604051806040016040528060068152602001655a6f6d62696560d01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103c001604052806103a081526020016147506103a091398152602001600015158152602001600015158152602001600081525081600881518110610e6857610e68612842565b60200260200101819052506040518060e001604052806040518060400160405280600381526020016205269760ec1b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806102e001604052806102bd8152602001614af06102bd91398152602001600015158152602001600015158152602001600081525081600981518110610f1857610f18612842565b60200260200101819052506040518060e00160405280604051806040016040528060048152602001635371756960e01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa815260200160405180610480016040528061044a8152602001613b0f61044a91398152602001600015158152602001600015158152602001600081525081600a81518110610fc957610fc9612842565b60200260200101819052506110186001604051806040016040528060048152602001635479706560e01b815250787b2b44c99db9e92dcb7790634e8caf295764b2ea4221185a1b846002611ad4565b50565b600b546040516323b872dd60e01b815233600482015261dead6024820152604481018490526001600160a01b03909116906323b872dd90606401600060405180830381600087803b15801561106f57600080fd5b505af1158015611083573d6000803e3d6000fd5b5050600b546040516323b872dd60e01b815233600482015261dead6024820152604481018590526001600160a01b0390911692506323b872dd9150606401600060405180830381600087803b1580156110db57600080fd5b505af11580156110ef573d6000803e3d6000fd5b505050506110fe336001611d0b565b600b5460405163188687dd60e21b8152600481018490526001600160a01b039091169063621a1f74906024016000604051808303816000875af1158015611149573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111719190810190612858565b600a6000600161118060005490565b61118a91906128e5565b815260200190815260200160002090816111a4919061293e565b505050565b60006111b482611de5565b9050836001600160a01b0316816001600160a01b0316146111e75760405162a1148160e81b815260040160405180910390fd5b600082815260066020526040902080546112138187335b6001600160a01b039081169116811491141790565b61123e576112218633611a7f565b61123e57604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b03851661126557604051633a954ecd60e21b815260040160405180910390fd5b801561127057600082555b6001600160a01b038681166000908152600560205260408082208054600019019055918716808252919020805460010190554260a01b17600160e11b17600085815260046020526040812091909155600160e11b84169003611302576001840160008181526004602052604081205490036113005760005481146113005760008181526004602052604090208490555b505b83856001600160a01b0316876001600160a01b031660008051602061473083398151915260405160405180910390a45b505050505050565b6111a4838383604051806020016040528060008152506118bf565b61101881611e53565b60006104dc82611aad565b606061137482611aad565b6113915760405163d9b9141960e01b815260040160405180910390fd5b6000828152600a6020526040902080546113aa90612808565b80601f01602080910402602001604051908101604052809291908181526020018280546113d690612808565b80156114235780601f106113f857610100808354040283529160200191611423565b820191906000526020600020905b81548152906001019060200180831161140657829003601f168201915b50505050509050919050565b60006104dc82611de5565b60408051620200608101825262020040815260006020918201908152825180840190935260018352605b60f81b9183019190915260609161147c908290611e5e565b6000805b600c548110156115ba5760006114c06114bb61149d8460036129fe565b6114a88560036129fe565b6114b3906003612a15565b899190611ee7565b611fb4565b600083815260096020908152604080832060ff9485168085529252822060030154909350600160a01b90049091161515900361157957821561151f576040805180820190915260018152600b60fa1b602082015261151f908590611e5e565b600082815260086020908152604080832060098352818420858552835292819020905161156a936115539390929101612a9b565b60408051601f198184030181529190528590611e5e565b82151560000361157957600192505b6001600c5461158891906128e5565b82036115b1576040805180820190915260018152605d60f81b60208201526115b1908590611e5e565b50600101611480565b50909392505050565b60006001600160a01b0382166115ec576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b031660009081526005602052604090205467ffffffffffffffff1690565b6040805162020060810190915262020040815260006020909101818152606091906116566040518060c00160405280608581526020016146ab608591398290611e5e565b60005b6001600c5461166891906128e5565b81101561171b5761169e6114bb6116808360036129fe565b61168b8460036129fe565b611696906003612a15565b889190611ee7565b600082815260096020908152604080832060ff949094168084529390915290206003810154919450611713916001909101906116eb906116e6906001600160a01b0316612072565b6120bc565b6040516020016116fc929190612af1565b60408051601f198184030181529190528390611e5e565b600101611659565b506117536114bb6003600c54600361173391906129fe565b61173d91906128e5565b600c5461174b9060036129fe565b879190611ee7565b60ff169150611800600960006001600c5461176e91906128e5565b815260200190815260200160002060008481526020019081526020016000206001016117d86116e6600960006001600c546117a991906128e5565b8152602080820192909252604090810160009081208982529092529020600301546001600160a01b0316612072565b6040516020016117e9929190612b4b565b60408051601f198184030181529190528290611e5e565b611809816120bc565b6040516020016118199190612caf565b60405160208183030381529060405292505050919050565b6060600380546104f190612808565b61184a82826120ca565b5050565b3360008181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b905090565b6118ca8484846111a9565b6001600160a01b0383163b15611903576118e684848484612202565b611903576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b606061191482611aad565b6119315760405163b4fa3fb360e01b815260040160405180910390fd5b60408051620200608101909152620200408152600060209091019081526119736119596104e2565b611962856122ee565b6040516020016117e9929190612cf4565b600061197e84611369565b604080516020810190915260008082529192509061199b83611612565b90506119c5816040516020016119b19190612d71565b6040516020818303038152906040526120bc565b6040516020016119d59190612caf565b60405160208183030381529060405291506119fa826040516020016115539190612e5c565b611a16611a068461143a565b6040516020016115539190612e9f565b611a1f846120bc565b604051602001611a2f9190612ee0565b604051602081830303815290604052945050505050919050565b60006118ba60015490565b6001600160a01b0381166000908152600560205260408082205467ffffffffffffffff911c166104dc565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b60008054821080156104dc575050600090815260046020526040902054600160e01b161590565b604080516060810182528581526020808201869052845182840152600088815260089091529190912081518190611b0b908261293e565b5060208201516001820155604090910151600290910155600c81905560005b8251811015611332576000838281518110611b4757611b47612842565b602002602001015160a0015115611bb157600960008881526020019081526020016000206000858481518110611b7f57611b7f612842565b60209081029190910181015160c001518252810191909152604001600020600301546001600160a01b03169050611bda565b611bd7848381518110611bc657611bc6612842565b602002602001015160600151612332565b90505b6040518060a00160405280858481518110611bf757611bf7612842565b6020026020010151600001518152602001858481518110611c1a57611c1a612842565b6020026020010151602001518152602001858481518110611c3d57611c3d612842565b6020026020010151604001518152602001826001600160a01b03168152602001858481518110611c6f57611c6f612842565b60209081029190910181015160800151151590915260008981526009825260408082208683529092522081518190611ca7908261293e565b5060208201516001820190611cbc908261293e565b50604082015160028201556060820151600390910180546080909301511515600160a01b026001600160a81b03199093166001600160a01b039092169190911791909117905550600101611b2a565b6000805490829003611d305760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b03831660008181526005602090815260408083208054680100000000000000018802019055848352600490915281206001851460e11b4260a01b178317905582840190839083906000805160206147308339815191528180a4600183015b818114611dbb5780836000600080516020614730833981519152600080a4600101611d95565b5081600003611ddc57604051622e076360e81b815260040160405180910390fd5b60005550505050565b600081600054811015611e3a5760008181526004602052604081205490600160e01b82169003611e38575b80600003611e31575060001901600081815260046020526040902054611e10565b9392505050565b505b604051636f96cda160e11b815260040160405180910390fd5b6110188160006120ca565b601f1982015182518251603f19909201918290611e7b9083612a15565b1115611edd5760405162461bcd60e51b815260206004820152602760248201527f44796e616d69634275666665723a20417070656e64696e67206f7574206f66206044820152663137bab732399760c91b606482015260840160405180910390fd5b611903848461237b565b6060836000611ef685856128e5565b67ffffffffffffffff811115611f0e57611f0e6125eb565b6040519080825280601f01601f191660200182016040528015611f38576020820181803683370190505b509050845b84811015611faa57828181518110611f5757611f57612842565b01602001516001600160f81b03191682611f7188846128e5565b81518110611f8157611f81612842565b60200101906001600160f81b031916908160001a90535080611fa281612f25565b915050611f3d565b5095945050505050565b60008181805b82518160ff16101561206a576030838260ff1681518110611fdd57611fdd612842565b016020015160f81c1080159061201057506039838260ff168151811061200557612005612842565b016020015160f81c11155b1561205857612020600a83612f3e565b91506030838260ff168151811061203957612039612842565b016020015161204b919060f81c612f61565b6120559083612f7a565b91505b8061206281612f93565b915050611fba565b509392505050565b6060813b80612089576311052bb46000526004601cfd5b600181039050604051915061ffe0603f820116820160405280825260008160208401015280600160208401853c50919050565b60606104dc826000806123b1565b60006120d583611de5565b9050806000806120f386600090815260066020526040902080549091565b915091508415612133576121088184336111fe565b612133576121168333611a7f565b61213357604051632ce44b5f60e11b815260040160405180910390fd5b801561213e57600082555b6001600160a01b038316600081815260056020526040902080546fffffffffffffffffffffffffffffffff0190554260a01b17600360e01b17600087815260046020526040812091909155600160e11b851690036121cc576001860160008181526004602052604081205490036121ca5760005481146121ca5760008181526004602052604090208590555b505b60405186906000906001600160a01b03861690600080516020614730833981519152908390a45050600180548101905550505050565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290612237903390899088908890600401612fb2565b6020604051808303816000875af1925050508015612272575060408051601f3d908101601f1916820190925261226f91810190612fef565b60015b6122d0573d8080156122a0576040519150601f19603f3d011682016040523d82523d6000602084013e6122a5565b606091505b5080516000036122c8576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a9004806123085750819003601f19909101908152919050565b60008151600181018060401b6bfd61000080600a3d393df3001761ffff8211850152600a8101601585016000f0925050816123755763301164256000526004601cfd5b90915290565b8051602082019150808201602084510184015b818410156123a657835181526020938401930161238e565b505082510190915250565b60608351801561206a576003600282010460021b60405192507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f526106708515027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f18603f52602083018181015b6003880197508751603f8160121c1651600053603f81600c1c1651600153603f8160061c1651600253603f81165160035350600051825260048201915080821061242157602001604052613d3d60f01b60038406600204808303919091526000861515909102918290035290038252509392505050565b6001600160e01b03198116811461101857600080fd5b6000602082840312156124c057600080fd5b8135611e3181612498565b60005b838110156124e65781810151838201526020016124ce565b50506000910152565b600081518084526125078160208601602086016124cb565b601f01601f19169290920160200192915050565b602081526000611e3160208301846124ef565b60006020828403121561254057600080fd5b5035919050565b80356001600160a01b038116811461255e57600080fd5b919050565b6000806040838503121561257657600080fd5b61257f83612547565b946020939093013593505050565b600080604083850312156125a057600080fd5b50508035926020909101359150565b6000806000606084860312156125c457600080fd5b6125cd84612547565b92506125db60208501612547565b9150604084013590509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561262a5761262a6125eb565b604052919050565b600067ffffffffffffffff82111561264c5761264c6125eb565b50601f01601f191660200190565b600061266d61266884612632565b612601565b905082815283838301111561268157600080fd5b828260208301376000602084830101529392505050565b6000602082840312156126aa57600080fd5b813567ffffffffffffffff8111156126c157600080fd5b8201601f810184136126d257600080fd5b6122e68482356020840161265a565b6000602082840312156126f357600080fd5b611e3182612547565b8035801515811461255e57600080fd5b6000806040838503121561271f57600080fd5b8235915061272f602084016126fc565b90509250929050565b6000806040838503121561274b57600080fd5b61275483612547565b915061272f602084016126fc565b6000806000806080858703121561277857600080fd5b61278185612547565b935061278f60208601612547565b925060408501359150606085013567ffffffffffffffff8111156127b257600080fd5b8501601f810187136127c357600080fd5b6127d28782356020840161265a565b91505092959194509250565b600080604083850312156127f157600080fd5b6127fa83612547565b915061272f60208401612547565b600181811c9082168061281c57607f821691505b60208210810361283c57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561286a57600080fd5b815167ffffffffffffffff81111561288157600080fd5b8201601f8101841361289257600080fd5b80516128a061266882612632565b8181528560208385010111156128b557600080fd5b6128c68260208301602086016124cb565b95945050505050565b634e487b7160e01b600052601160045260246000fd5b818103818111156104dc576104dc6128cf565b601f8211156111a457600081815260208120601f850160051c8101602086101561291f5750805b601f850160051c820191505b818110156113325782815560010161292b565b815167ffffffffffffffff811115612958576129586125eb565b61296c816129668454612808565b846128f8565b602080601f8311600181146129a157600084156129895750858301515b600019600386901b1c1916600185901b178555611332565b600085815260208120601f198616915b828110156129d0578886015182559484019460019091019084016129b1565b50858210156129ee5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80820281158282048414176104dc576104dc6128cf565b808201808211156104dc576104dc6128cf565b60008154612a3581612808565b60018281168015612a4d5760018114612a6257612a91565b60ff1984168752821515830287019450612a91565b8560005260208060002060005b85811015612a885781548a820152908401908201612a6f565b50505082870194505b5050505092915050565b6e3d913a3930b4ba2fba3cb832911d1160891b81526000612abf600f830185612a28565b6a1116113b30b63ab2911d1160a91b8152612add600b820185612a28565b61227d60f01b815260020195945050505050565b643230ba309d60d91b81526000612b0b6005830185612a28565b670ed8985cd94d8d0b60c21b81528351612b2c8160088401602088016124cb565b6505258eae4d8560d31b60089290910191820152600e01949350505050565b643230ba309d60d91b81526000612b656005830185612a28565b670ed8985cd94d8d0b60c21b81528351612b868160088401602088016124cb565b7f293b6261636b67726f756e642d7265706561743a6e6f2d7265706561743b6261600892909101918201527f636b67726f756e642d73697a653a636f6e7461696e3b6261636b67726f756e6460288201527f2d706f736974696f6e3a63656e7465723b696d6167652d72656e646572696e6760488201527f3a2d7765626b69742d6f7074696d697a652d636f6e74726173743b2d6d732d6960688201527f6e746572706f6c6174696f6e2d6d6f64653a6e6561726573742d6e656967686260888201527f6f723b696d6167652d72656e646572696e673a2d6d6f7a2d63726973702d656460a88201527f6765733b696d6167652d72656e646572696e673a706978656c617465643b223e60c8820152651e17b9bb339f60d11b60e882015260ee01949350505050565b7f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000815260008251612ce781601a8501602087016124cb565b91909101601a0192915050565b683d913730b6b2911d1160b91b81528251600090612d198160098501602088016124cb565b61202360f01b6009918401918201528351612d3b81600b8401602088016124cb565b7f222c226465736372697074696f6e223a224f6e636861696e4f706570656e222c600b9290910191820152602b01949350505050565b7f3c7376672077696474683d223130302522206865696768743d2231303025222081527f76696577426f783d2230203020313230302031323030222076657273696f6e3d60208201527f22312e322220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f3260408201527f3030302f737667223e3c696d6167652077696474683d2231323030222068656960608201527033b43a1e91189918181110343932b31e9160791b608082015260008251612e358160918501602087016124cb565b6f111f1e17b4b6b0b3b29f1e17b9bb339f60811b609193909101928301525060a101919050565b6d1134b6b0b3b2afb230ba30911d1160911b81528151600090612e8681600e8501602087016124cb565b61088b60f21b600e939091019283015250601001919050565b6c1130ba3a3934b13aba32b9911d60991b81528151600090612ec881600d8501602087016124cb565b607d60f81b600d939091019283015250600e01919050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000815260008251612f1881601d8501602087016124cb565b91909101601d0192915050565b600060018201612f3757612f376128cf565b5060010190565b60ff8181168382160290811690818114612f5a57612f5a6128cf565b5092915050565b60ff82811682821603908111156104dc576104dc6128cf565b60ff81811683821601908111156104dc576104dc6128cf565b600060ff821660ff8103612fa957612fa96128cf565b60010192915050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612fe5908301846124ef565b9695505050505050565b60006020828403121561300157600080fd5b8151611e318161249856fe89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000037349444154789ced9a314feb3010c7ff7d7a136bc25eb1d08905988ad41921f533f4495d18112b232beac8c2c067a8843a23d109de82de5096aa7bed95b56fe03938c1766cdfa5ed13fe49959ae47cf65d2e76ee622091482412894422914824be21add886799eaf42e48510de7dd97487e8f0e527a5f1c5dd43e978b65816ff3bedddd2b5d1f06c05b88d50869f5edd47eb08851401a757f7a541ba1ca0180dcf8c06287d3aa13a62f84155305b2c8b9f0f17770f5f42dc647ca88e58c80eb0e172886e80cb785f1d141a7300006b64d4454ba7bd5b847fac0e5fc8730085c9f500261dbaf13e3a28f301691500ec1395ce6cb10c324ac974dabba5b626269ee3b441728090124f527ac9dae484a3bd6ae3db470c8dce01ff03a408c8b3ac74ac87ead3ef5921630a6515e6ba8eaa9caea329c873808eedf956e7eb9e7f5f394ea21f0121446b723d703ec32ed4ec3db91e7ce80bd023a4849092bc02004c11a006ef0a559781ea9a90b236dc631d6e8334090a215acfb7979fc79e33fdf3ed6571e74c3a74f9f9745c9cd3cfeb3a28b02414799eafb2831e0060afdb07f03170d3b17c7db42643d941af9037e950e76c3a62e079048468e1f571951df4309f8e4b0306ea8dd775a8e3bd6e1fef6f2fd8d93f2adad7e98881b520a2a20000dedf5e8aff3bfb47003e065f8749475d7b8a4358eb018ad962599a18ab32faf593c38ef175b74e8792a1ae041b7f135ce79a6f62e30e50f8be2471c3ea009fca90eb7a88915c0e617340489abb8ebe7c61cd053858f79c4076c026ef3cc76bf1d64c82a170e504e48a5068aeae065ebcdd75fbd13a38203f02ba13aa490c00e4fd5f25f93ccbbe18a01faf3b1b644d873975991c51ed47cf116221cd01b103f009792125e6d371291de6e8bb4ae3cb2077c8027ed9a52fe45580eb4e6caabfe808a8d60014d55a00274dd405c80af46a904e35970fbdee92d9aa8a905ec9313982135510d98a8a9009ae6ff6369ad8229348241289efccb75f06d9be0d02e59da36a73c3c961c7d8a6eeba4966343c03b0652f42b6dd62d5bcbeba49ca94f7577790d86a031cfb0214a46c3064ab9ceb9b41d5f0ba22eae9d5fde6778ae679be3a3ebf09caf7f50d903a315b63b89cc052156ea2e8e1d3e7f1f90dd9096c15219fc226e5fb40534e2639c0b48303f8ace701882a7b9b74b8faa74072802a58fcf9b793c3560d32ddbd3ae3ea984fc7a54d18b1fc05991b7a930373ad800000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000037049444154789ced9a5f6ae33010c6bf6c12ba0da4e4411b0a2185bce40e0b3d498fd053e4143d422fb05758c81dfcd2875228410f2106ef1627641f12796547ffac911343f483426d8f3f69c6926c4d0688442291482412894422912ba4e37b23636c5fc79e73eedc964ebb8e862b3dcacd2f0fb3d2f16ab72dfe1f77cbd2cfc01e303b211c5f4ca6de1a75210560b5db9e74528708d633b05739c018db0bc77d357cf8461558edb6c59f0b2f0fb39321eee2bc4dc3177200749802223b6072de558342630100a01d19b6d132eef68aa9e5abe14aa30110c8d344747c3199d61afa260d4adf488b2070ba52ab90174b9727276cc6dd5ead85d607927292e64890bbd96aec92547fbfb8c7b50d1fce3205da0c6904cc87fdd2b13c547fafff1436aaa1bcda6d814d59a36a276b68d9503c08b006c8e8e6b7386f9bffae7621f19e029cf3cee2e3dd38874d2c3ede0b0dc0bc165449d21c499a171a5e1d3812640488ce9b86aa71b13b5e4bd2dc3cdc2d3a3e901641ce79e775f3591ceb3a573dffbaf92c9e9c4a43b65f66ebe29c7c5ed6a0106443c118dbcf7adf01003f072300878eab8edfb67f951d171ac25ea521cee9347c08320538e71d1c1d5866eb528701bbf3b20624a7f95706763328eeb769f810342122460100f0afecbfedcd00c0a1f336541ab6fb2901218d80c564aafc4c5dedb6a585b16a235f7f1cdd2a3f776d1ac246bc457cb9f897e039dff92a2e1e0081eb4752688206c0253364ba5ec7c9d6e503ea6c73cfd1962bcd6db43d39f79a400ec0259f7c88cfe2d62c827509b5272067846c9b17d53d00a4afbb91b74608c853400e4275130300f3e18f92fd7cd83f71403e3ef76e30e87638a4962a10d576e43d822fa400a8363e2ecc877d2c33b34d92e6a569a26a3b048dbf06430f59c06d77e90af92d10ea495caa3def1150cd01087ca6842b4de405c802723648a6ba97af7bdd64d3aa8c5091c9413999d1042221d28a8c908a50bfd9eb68a2442612894422d7ccd5bf06836c8684e372e5a8286e781cdd2aefb15d57d9b4ae521428d7f999cad9744552baf25af9bc5c1506008bb6548afa94b9a9a83a6e4ba286288f1378078031b67fbabbafb5df970b20657c4a634205214856b889a4874b9b4f77f7972f94943b24d0253629bf0f341564724e10384d8254f37975d3de2a0d53fb14480110098b5fc74a0e5d3648f5f46cced95866eb43fb5dda2cfe07f2bf7fac7f79917b0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000034d49444154789ced9ab18ee230108687d349275d419596faa4d0b05dd817d86a4b1e01695b6aeaad69917804caabee05201d6912696b5a57142b6dc515bb8e26c6766ccf84b0c29f844412e7b767327132130344229148241289442291c81d32083d314992b34f7b2184735f266d1f0d577e524eae56af8ded5355d4ff87e9a4712c5d2ccf007623a4e1f97c16ace10b2902f2f9ac31489b0324e962a93540ea617c3542f84115385545fd73a15abd5e84b8ce785f8d50c80e3061730836c066bcab0685ce1c0000c6c8688b96613aa9c33f54c315f21c4021db6c41a7818d77d1a0cc07a4a7008079a2c29caac2cb28d966984e1ae7ead93a8dd304c901fbf208501edd1a1bdaed6de7cb63ae7d04d0e91cf01d2045c0743c6a6ce350fdb7fd5bb7d185f2a92a00767943436d87358cec728a09f4390063babfe5feb6fbdfb51d27c1b7801062906db6f67bd8829cbdb3cde724e6a3b32f8fb02f8fe42700005304c8c1db42d566a03cb62f8ff6706fd1098134090a21060b740f9a06a7ee5fecf2facae93470fb7571a8f7e1fd5883023902be0c38fff9fdabb17f5d1cb4db6fef1f1703c71a2f930700f87484aa2175741aa1b0a5954992d44e78993cd483c7ffdb066ed2c0701a0fc05c1051a340e5edfda355d7a6613abfb75761b51e20395545636254dbe0e34fb367edeb6e9b866c239f22a1f4fe2678cd67be8ede1d20717d49e286d5012e9521db711f23b91cc2e6009f34f71a7db9c29a0b7070ed3981ec803eaf3cc76bf1cd4c82be70e504e48a505bf2a23b07a0f9aa1caac101f916c04e509318804be3a6e3d1850178fbdad9206b3acca9a57384da8f2e57f085e4807571a8b3371fa6e351ebe04dd920ee9b83ce1f83dc210b604fad7d213f05b8ae445ffd0547801062005ff93b1e54c82de10aee87ab2e4016c0458c6b71731521591ce9da11b220721315211d5cdfec4d74b1442612894422f7ccdd3f06595f84f0ca51b9b8e169f6ac3da7edb8ae4dba580200af23c8d9205e2d665bce665a24655a5d8af7cbffb29f6cb33ddfc44a519fa572b66f06aae16d45d47c3eeb7fa5689224e7d563e695efe305909890a5315c4e60a90a7751f470e973f598919dc0561172296c52be0f74e564724d10e0b208a2d6f37ccbde3a0d5bff145822c0e40889eeea5107cf551afb0fe1da4dd508c862c60000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000040449444154789ced9abd6adc4010c7ffe71c290226c5ad316a7270b83c84895db8f313b8cb0bdc4b5c9147307e877b8134264fe0ce86a4092e83e1d288035d11420c0621a55056da5bed87a4193901efaff159ba5bcd7ff66b66b44020100804028140201008bc40467d7f288428ba7c3f4dd3d6cfb2b5dda58db68c293f4e92f3eaf3473c2977ae77be77f5fa37849815805b8414feeddd5be3fd18f0b6d1159203243ef100b0dd3e000084981526014288c224fce0eeb8fa9cfcfd1b4537c636fa4076804f7c9eef57ff6f4e1f01ac31c77447802e5e155d193afe547d5e24175845b72c4e20ad018be44cb9528b97bdae8a976c4e1f911731e21f3f91a6e948156f120eec8a972cb30baca25bf27460990226f136f2226e5c33095747d6a5f599872dedb3b3476ec1223e79ffcaf9ab24398710a2501752a014be3badec2c924de7dd48873802dce237a78f38fcf2a6be7e72e4ed6dc9e5f833006099e55866392ec7755f2db39c66b602cb1450c5cb792fe77a72525e3fb83b6e21feba715fb67f6579f664d2c7e21ab2036cc35e9debba70f310df15bfcc72ef7ac201c901260365cf03fec5adc41c37487c6bc97cddc250074cbb4069a8abd701d3702f57f12e8b2737a43d540851dc4feb2ec88bb8f53c5f4587551cb0dd3e78859bb64f194bf4b3be846d04f8c5efee18eae265126f123c04e450524672f685aeb9554e2633e8a1f0fd74ed15ad3e238a6e5892229684420d686cdb9a4dbcda862d0b0486110f303900a89dd0a5e74d6df8f2024ef1007341a44e8e4af1faea3e5f4fbdedeaa1b1e4239eb08a6e8df7280e2139a039ecfd7941db6468b75d49335294bb494bb31b30d6039ae2f5d5dd152798525e731658b2b7f70bc03f0e8575f1ae80c617247525cff72b275018341b043ae404d985b34d1553a1a52fecd9a04afb84a839b7db84c7e5c2dac150036c91a0441a6b13df25197a8ebc6090747828f1b25d5963e0802d1da6886f2b5c127dfd5e7ef7e4a8bbd11a0c35c1e1c4e745dc10afb6cbb19b90a7c090e255d436b3ec436f7b7568afc60cc3d5dd2bddc5bb9d49876517b0a5b1becc10b08b1f5ab884751bb41bdd2f60f2154fa97900c0e0007fe5864bbcb9644ea5b703d2341dcd313516314c09928a4b7c5be11cbd0f1047409aa6a3183096c4744c19a23b41b287c7bec24a17c853403a01d10d7c15211bee395fb73199ccaa67d2acae613d72427d51e9638823328140201078c9bcf86d90251992c217c9c61bef37839ef6ef13fecb93a2e579c10d007fb2e30a977d95e583bbe3414e8a924a6236f12aa66cd1952cb5719c3c62d7c7669dde0e7089ef5e296a62132fcf112e92331627b01445557c2f424de873df5615d293250e273cfb31b93ee52d778d80765c96fdcd900e47e9baa6f92285fa76986d0af419fa14b80e51fe015b82798ed508dde10000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000036f49444154789ced9abd6ae3401080c7e61e4195cb1030e4c8a5b807b8268d8d1b839bab53ea090ed7214fe0f2ea348134216eaec903a4389b180c42a52b3d8375cd8d6eb4da3fed8c6c1fde0f0c96b43bbb33dabf190d40241289442291482412899c21bdd08a4992946dca1745e1dd9649761b19be7ce2547e7d7eaa5def77dbea7f7f30ac3d1b4f6725805d0954fc65711f2ca32d2c03ec77db46274da0b1c6d359a95320499212150f9511429f2b60bfdb563f1f5e9f9f1a43dc4779978c50d8063061330855c0a6bcaf0c0e9d1900008c23c3355afa836135b54265f8c2da05da0c5b1d93740e3a1954791f199cf580b5080234576a1d74b1f4510acbf407c3560b6d082c03ac3739c026f72b6c28b7b6d5c767be6d04d0e91af03fc01a01d75717b56b3a547fff5a5665744319873995a196a332ba82bd06504cf31befbbe6bf6f394982a7405114bd493ab7cf610bb87a4fd2390038d60285f52687f52667ef00004223003b6f1baa3605f1d97a933b877ba8c14db0cfd34992940fe95d758d0a50a3a89dfeb1f8597b73aa0c5a6f9567f0e5e2b2d1ae2a23141187224992f2fbe81b0040d5d9559e69af1f976fda8ea30caaac2a03ef99648420b20d1645d17b5cbe01c0bf4e535cca5319ab3cabcabf7f64557dfc492a0fc058036c8ec82acfaacebf7f64f0f5f3a5573d55865a1f8daccae01884ed0be88ea9fbddb6b606a865e8f39bdb91f6b8eb928165b83bc1d14f8287dcf3751cdd0088ef21491a5103f844866ccfdb282965103103b471730fd1962fa2be8004875e13d80638e69b9738169fcc22d816299f801d116aebab63c7e98931548604ec29408d403b860aaacae99c237a7d686f50d41d9694a53384da8eceef680bcb002657d5c5f5d585b3f3e80adbda96a0f36d507ac802f87997beb07701a93771acf65831411a03a07e7c5750f9527101d614f86b842a1a04008d608609d7735b19c9a0087b0d40230000504374018e38c9889068ca89d4377b135da4c844229148e49c39fb6d50ecdb20403d7314931b6e6e47da3aaee7ba32e3e90c004e285314a09e2d664b6733254999d26be97dfc8fed4cd2f969648ab64995b37d3350157705515f16f7c7cf14c56ffa6dfc7d9a004909498d9132824854b88ba0874f9b0fe91ddb086211219fc026e7fb40574666c70401a0111754e37921696eae98206d9f03cb006a12842940aa7b7bdcced3240c0e7f00f6308154847ee1430000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000035749444154789ced9acd6ee2301080876a5b4a0e54489638e4d256ea8563dfa14fdd77e891cb1e762f9116c91282432020357b68ed3a8eff670254f5272111e28c672613c7330c402693c96432994c2693c9fc4046a91732c6da98f19cf3e0b96cb2636484f20b73f1e3f34be798af2af99dcdcbeee0b7d716c06d84307c5a2e9265c48272005f557d252d4867bdbdb626031863ad303c55460a5758017c55c94f088fcf2fbd100f31de272315b4036cb81ca21ae0323e540686c11c0000d6c8f0450b9b97f2d14a95110a6a0d08c5a4ecc75d5f0687be4b06663d403b2064115417cb903b27c6b079e95d68b7d532505333a87dc078768f9abc59ff050a19980818740df80ea01e817151748ed550adfefc96634ca1cc571534ebae0c7d9c2ac346b3c65840bc08da9e6ff1bbeff90f1d4749f223c0391f6dab2534759d74fdb65a4a19001025a7a96b68ea5aca4852e013920810ca3b43d561a038d7d4b553864f4e0ab85c80f31103906f039b01bad2eaca6d9201f0e5cce37e639c1bbbfa0bd011200cb89acc3abfeb8a8be3f7ddbaa7b82ae3faf60e003e1c6132feb8df1865a442965632c6a413ae6fefa4f2ea779fe2ba8cc3f61f8c6e269d3194c603101744d428680fbbaf493e8d78dff9df592619beebcfb6159e960be33695afaaceb3ac8f51cf970f4fc6edae4f861883dd0a9f7d2778ca77be89b33b4010ba49a286d401219521d7f91823a91c42e6809834f7147385729282480ca75e13f01ba133de798a6df1c52c82b150e504a80808495e4cd70074b7caa93228403f02aa1354c58481ba71e3a2e82747caf1b7ca0605944ab9526b7d1e5ba61803ca01c7fd46666f318c8bc2abbc2d1b54e7a660f0d72075c802b853eb58d06f01aa3b71aef9503541919e1ef71bf91912553e555d002d402d62a8e8b97cec79d718caa2084d498c410bd02d660c8188b88ba80899a0facfdec6102d32994c2693f9c9fcf8d7204932240c573b47457343f9f064bcc677de3866804e5192adb0a9d34bcfebf5262953dedfeb20b1d40628fa0204a80888e9f0741546456b8c6f9c80a23d4e909c0d8a2eb1987c5f6d805449698d99968bcbe9141da2e81132e778768f7602594528a4b089f97f602827a36b8200d0ab0beaf5bcd8b2b749866b7e0c28078882c5e1b083d1cdc45a2035dd3dacf2c7fda6d38491ca7f0bac6cab77088dfc0000000049454e44ae4260823c7376672077696474683d223132303022206865696768743d2231323030222076696577426f783d2230203020313230302031323030222076657273696f6e3d22312e322220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207374796c653d226261636b67726f756e642d696d6167653a75726c28ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000035a49444154789ced9abd6a1b411080c721459cca82c38582f01bd87e06b706f74206bf82e00a831f409042a0573058b837a4f53324695d092115e6e05cf9dc294de632b7dadddbdd999514b41f187cbabdd99db9d99f991b8044229148241289442291d8430e421fccb26ce5d3be280ae7be4cb27d64b8f299f3f0f8f1ae713d5fceeaff7bdd93c6bdbc3f5a01d89540c587e341b00c5f581e301c0f1a83b41900c9fb23ad02288fe22b23844f5c01f3e5acfe7361fc78b7e6e23ae57d6584c23680099b41a80236e55d657088660000307a469bb7f4ba27b5fb87ca7085bd067098e453d0c9a0cabbc8e0ac07ac5d00c0bc5051e6cb999752d8a6d73d693c1b039601cad737285fdf9cdbfafc4eefb9f61142d435e07f80e5019de3a3c63575d5df3f7fd56d74ae8c6e4e65a8eda88c58b0d7008a697ee3ef6df3dfb59d24c153a0288a83493e0d9e9fb87a4ff22900f8cd735c7bb83b00809007e0e06daeeabad8b5b9bbf482c83e4f6759b6bab9bdacaf51016a1475d0f7df7f34de9c2a833e572e2ae87c3b5ceb5795118a48409165d9eaeafa0200a01e6cb9a8b4d74f0fcfc660e8eafaa2a1ac2a037f33c908412cac548d4007dfa6bc49c6f2a584c3af5f1a6d24950760ac01b640a45c5450bd7f000040f5f2d150c2358041a355efff9e7f7a78d6cae01844341f80cc97b3c61aa0b6a1f74fcfcfb4c7dd3619d886bb136cfd24b8c93d5fc7d60d80b81e92a41135804b66c876df474929838819c027ccdd445fae88c602126c7a4d601b609b6f5ee258bc338ba02f5231013b23e41babd781cfdf830e807fbc2f1910b1a70035021d587d145694d30547f47ad3d1a068382c294b678835c3112f0a8537050ca16a1b9de3a3d6c163286ceb5b82e8db608c8cae6b74e9027b17907a13dbea8f9513c4f0b45c54f55f4ca87ca9bc80484a0c931814cc07a8090dd7fbb6363b9711c2040535440c03a0c7ed4481840ea96ff6266294c824128944629fd9fb6d50f420442b47b1b8e1f4fc4cfb4cdb7d5d9bbc3f02801d3b0899aac5d4b85e2d92d2c5fd6a0589293720511780b0a2419f5239db370355f1b624ea703cd87ea5287ed3f789f769012425a43446ca082259e198656cb63e6f6e2fd94610cb08b9243639df076219999d130480b5bca09acf0b29736bcb09d2fe39b00ca016419812a4bab7c71d3c2dc2e0f0077d3871dcf62e9aae0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000027749444154789ced9ab18ec2300c40cd89b92ccc5dda9105f1ff9f8058186161ee427f809baccbe59cc44e9c36a7fa2d080826761cdb7103601886611886611886b14176b93f3c1e8f1fc9f8699ad8ff15922d91c1655ff2e3e7ebc11e3bf4e30720ae042a1e92cb9121a5c803240640867e241590c80bc9c8e14b438884ae3bfc7171a9319faf87780b8658d400e7d3056ef7eb2f23e478d2f974210d99c3a206b8ddaf703e5d54e468b1f816c0c9e30a4a561f8d87af1a5eb0f8162841cb835c8ab240d71d8afe7c9edfa021a324232cbe055aa3a8100a052374537459779cefc2b180e6caa13ed7a0ba07f893cf8de07e00d422db00d334ed867e8c8ea1268b9fe1de45191cc5fc31a5fb1fa0b207e06aa7560fb749ca089af91f29aea7a95c4ec50057397fe5a88c923288c6ea032878406c2b70944719f3fc0600de2a6b290fa0e00108a72e484d5c438694ec34985b829694aee825be8c128354698884f2778d31a94c9462f395a01960ed09ac8d1960ed094871ab4a8d73c1bf32805b586995c5cd192076800a95d6252c6e007fe29cfe807ba8d26e8badd61475df734e8b359407503440eec47cc5a8e0e61fab355133406e50f2831a25a786e248b101527bda776feef71ca59be808a57a7eeeca52e9cb5ff91a5d9f186a3dc15800c3572a8851318083565fa07a4b0cdfc75ae3529aeb08b9171b5ce5b4d31636449ab82041a1f5cc3e448d2b32866118c696d97c1a542f8490d4438d9c0723587a37f1680cc9bd319a03fecfd08f9f266e8a2ea93cc08f473471531495d76e56c4e4b987ab266e8a4afa74b131fe018a2b43c30855ee09fa4689b5b9a823b3c4ab56bf27487574a8a607c703b49ef64858f5a6a806a51ef00d0127c02237dfbafc0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000037f49444154789ced9abd6e223110c7ff9caea520da12290969a08894fe4a404a1e8014291329e5b5d7e731228532053c402205daab235d411a0227a55c918207d82b90375e63afbd9e59e0847f1212bb9e1d7b66fd35b30602814020100804028140600fa9f83e18455152443e8e63e7ba4cba8be870e53be5e18ff787ccf5723a4eff574fda99b27ae32601f28d10864f5eaebc751485e480e574bcd64813c259f5c64da233208aa24418eeabc3876f5405cbe938fdb9f0f1feb0d6c55d8cb7e9f085ec0013790e910dc833de550785d21c00c0d8336cbda57ad24e8796af0e5748ab40916eaba3d57d844e876cbc8b0eca7c409a0481f5995a873c59ba182564aa276d8789f6d1a99d26480e98cf16c06ce8266c909bcf16f6675cebf0a0d439e07f80d4038e8e0f32d77257fd331aa632baae2cbab9ac439593759405790e90318d6f71df36fe5de538f11e02711c575addc7fc319c8398bd5bddd5245644cf7cb6c07cb620af0000530f108dcfebaa79068ab2f96c61edeebe0e37419a04e338ae5cdc3ea7d7a6c6a9f72f6e9fd337a7d321cbf70793f49e7c5fd6418125a088a228e9750e0100d7972d00ab86ebae87a3bfda860b1d425ea743dc33e9f0816508c4715c198e90f43a87e80f2699060376e3651de2fafab285d7b74f9c356be9f3361d3eb02644442f0080d7b7cff4ff59b30660d5781b3a1db6e7290e21c702ba6dea723ace4c8caa8c5c7edae969b7bb361d4286ba126c7d27b8c9355fc7d61d2070dd2471c3ea0097cc505e791123b91cc2e6802261ee26ea72853516e060d37302d901db7cf31cdbe29d99048bc21513901ce0d308b1a7ef0f26e93e7f13f59a200f01398253831800b8fbf523237f747cb066807cbde96890351ce6d4a573845a8f1c23f8421a02be0d704971a9c3a40ce3810d2c83dc5d16708b2e5d21af025c6f625bf579f7003507205073019c949117202b90b341326a2c5fb43c4f66a73242722647e7084e4442642732423ab8bed99b28e3884c20100804f699bd5f06d9be0d02d993a3e270c369a7a77dc656ae93a9376e00ecd846c8745a4c8debd54352bab85f3d4162ca0d709c0b1090a2c12247e5f2be19a886db92a89397abed9f148da22879ba3f2f14efcb0720657c8ec6703981252b5c46d2c3a5cea7fb73b213d832422e894dcaf781b29c4c7280ee0407f095cf13653ec7dc541d79f553203940242c7edefdc659b3666ca8eeedd98cb3d11f4c3287307cf9072e827783447ec0ce0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000018249444154789ced9a416ec5200c4427558f00f73f20dcc15d54a852d4f4077b7e4614bf75620d0f1448e2c3cc0c1bf3a10ea02605a803a84901ea006a52803a809a14a00ea02605a803a8d95ec0a7f7c65aebd4f5adb570ed991a77710b0080defb71f7da5aab017f0f620cfcaaee9d1ad39893528aeb35ba9412ae7755c3c3e3cf80defb715ee2b5d6a9d5f45b0d375e73de153018b318a9c35809dbef02b215007ccf20a346ae800029401d404d0a50079013798232f6f03c07a8891af4cce079e61835bc840598715e64542f43140166f706f02a38a3c62c8f7d1089de07fc1c9dcf3542df07bce618e77806f92e102405a803a84901ea006a52803a809a14a00ea02605a803a8595a4029c5a23f4a9716c0c02da0b546f9b3e38531fb407005a824b0060f008759bc5dfe5563038b219bd920411130a0fdb3bfe01d2d3254012b92bb803a809a14a00ea0667b01a146c9332b6e8314014f1d84ded1291a3e07cc363932601e8543cf00c5e0817fd229ca60fb0e11c64a585a008314a00ea0e60bf0425f8751926ab40000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000035f49444154789ced9abd6a1b41108047219d444070e060ecd2e801e4d218b9481a57e9f40a7a041726850b3f825ec12fa0462a2c8c3b5b0f6052da04051604e6542b8533e7b9cbeeedcfcc4a32da0f04badbbdd99db9b9b99db90548241289442291482412891da4117a6196652b9ffe4a29e7b14cb27d64b8f29973f1d3cd79e9385f2c8bffad76b3d4d6e98f5600f54aa0e2b3612f58862f2c0f980d7ba549d61900e9f4475a05501ec55746089fb802f2c5b2f8b9f07473fe9f8beb94f795110adb0026ea0c4215a853de55068768060000a367d8bca5d56e16ee1f2ac315760ce0d01d4c4127832aef2283130f586f010073a0a2e48ba59752d8a7d56e96ae8d01cb00af2a8757953bf7f5394fdb5cc708216a0cf808b03ce04bd62a1d5357fdfdeb4fd147e7cae8e65446b51f95110b760ca0989e6f3c6f7bfe5dfb4912fc0828a51addc134f8f9c4e8dd1d4c01c0ef39c7d8c37d03000879004ebece555d839dcddda503222b082aa51a67978fc5b16ba43fbb7c2cee9c4e06ed3f9ecc8b73f43c95c14124a1c8b26c75717a000000dfbf7d0580b789eb8eafef5e8cc9d0c5e941d15f2703cf996484209656568d40276f53de24e3c7cf07189c1c96fa482a0f205c10c1c903000cef9f8bffa8c4f5dd8b55ae4e86ed7a8e4144eb0148be58960263b50f6ddf3fdad32e776d32b00ff74db0f195e03adff93a366e00c47591248da8015c2a4375ed3e4a4a1944cc003e69ee3ac6724534179060dd31816d804dde798965f1d604415fa4720296014226816bfaf1645eacf3d731ae09b607d0c9d0a40515aca2cbf674c98ecb781288a6c392b24c86a2e80cec0bcb034227e052e2aa3e2631940758c36b304645d735bb74811d03a4eec4a6c663d504313d45578d6d0c2a5faa2ec07a04de8c002b9ac3e324693d4087adbdae8f6451841d03d00800e562460cd0e3b6a222a443ea9bbd89185b6412894422b1cbecfc6b50ecdb204079e7286e6ed83fdad35e636bd7f5e9f44700b0650b21d36eb16a5e5fdd24a5cbfbab3b484cb501897d01082b1bf4d92a57f7cda0aab8ad883a1bf636bf5334cbb2d5edd5b157be4f37405242b6c6481941a42a1c731b5bdd98b757c76c23885584a8114c252fcef7815846661940b78303e0bd9e876d21dbdcaa32eac6e7c03200162c86f7cf303839344e5477f76ccad9184fe6ffc6e7bd0cfe02ec318fd9344a0a090000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000036449444154789ced9abd6ee240108087d33d81b574c4af80a868d2a108d14442a9d2a54a9707b9ea8a4857a44a478522d144164a972615ca2b001d2bbf82af88c6599b5defcf8c8188fd24246caf6777c6b3e3ddf10044229148241289442291c819d209bd510851f8b497523af76592ed23c395df949b571fef95e33cdf95ff93a45bb936185e1600cd4aa0e26faf2fc1327c211920cf777b833481c61a0c2f0b9d02428802150f9511c22faa803cdf953f17561fef7b2eeea2bc4d4628640398683288aa4093f2ae3228b4660000307a86cd5b92a45b4ead5019ae90de023e6eab633499824e86aabc8b0c4a3c20054180fd48ad430d962e4a619b24e97a05da104806d86cb6b0d96c9ddbfa9c57afb9f61142ab31e02740f2808b8b5ee55875d5cfcf55d946e7cae8e6aa8c7a3b55465b9063808a697ee379dbfc776dc749f014905276469369f0fcc4e83d9a4c01c06f9e63eca1be0100983c0007dfe4aaaec1cee6eedc01911404a5949dbbfb87f2d835d2dfdd3f944f4e27436d3f9b2fca73ea79550605960d8510a2188faf0000e0f6e61a00be06ae3bceb2a576e02803dbeb64e039938c1058a68094b29365cb623cbe82d97c511930805d7955061edfde5cc37abd8534ed95f7db6484c09a10412f000058afbfdd354dbfe675962dad7275326cf7530c42de0be896a979beab04c67a1bf57abf3fd02e776d32b00df54d70f495e021dff93a8e6e00c47591c40dab015c32434dd77d94e432089b017cb6b987e8cb15d6bd0007878e0964031cf3c9732c8b4f2608fac2b5272019206410b8a69fcd17e53aff10fd9a207b803a1875d3820ad6d1edf6749b1d97fe3860dd0e73ca32194a4567605f481e103a009714577d9ab4a13cc0015e836d64745d7697ae906300d79338567fc11e50cf0120f55c00276de405c802d46c904a7d2fef7bbda9cd496584d44c8ece109c6042e42432423ab8bed99b68a3442612894422e7ccd9bf06d9be0d02542b47b1b8a1df1f68efb15dd7b5190c2f01e0842a4501aad5624de56ca622295379ad7a1eff633fa3c9f4342a457d4ae59abe19d415b72551df5e5f8e5f292a84289e9f1ebdf6fb6a01a44a48690c971158b2c26d96b135f5f9fcf44836025b4648358229e545f93ed096914906d05570007ce7f3f05a48995b5d4653ff144806c084c59fbfff204d7bc681ea9e9e4d391bb3f9a2528411ca7f3f789142ac22e3ce0000000049454e44ae426082a2646970667358221220d06f88ec1fc88ebef149af151d56ef1ff9ae0348dc4bbffe1daf1b4c77285d4064736f6c6343000815003389504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000037349444154789ced9a314feb3010c7ff7d7a136bc25eb1d08905988ad41921f533f4495d18112b232beac8c2c067a8843a23d109de82de5096aa7bed95b56fe03938c1766cdfa5ed13fe49959ae47cf65d2e76ee622091482412894422914824be21add886799eaf42e48510de7dd97487e8f0e527a5f1c5dd43e978b65816ff3bedddd2b5d1f06c05b88d50869f5edd47eb08851401a757f7a541ba1ca0180dcf8c06287d3aa13a62f84155305b2c8b9f0f17770f5f42dc647ca88e58c80eb0e172886e80cb785f1d141a7300006b64d4454ba7bd5b847fac0e5fc8730085c9f500261dbaf13e3a28f301691500ec1395ce6cb10c324ac974dabba5b626269ee3b441728090124f527ac9dae484a3bd6ae3db470c8dce01ff03a408c8b3ac74ac87ead3ef5921630a6515e6ba8eaa9caea329c873808eedf956e7eb9e7f5f394ea21f0121446b723d703ec32ed4ec3db91e7ce80bd023a4849092bc02004c11a006ef0a559781ea9a90b236dc631d6e8334090a215acfb7979fc79e33fdf3ed6571e74c3a74f9f9745c9cd3cfeb3a28b02414799eafb2831e0060afdb07f03170d3b17c7db42643d941af9037e950e76c3a62e079048468e1f571951df4309f8e4b0306ea8dd775a8e3bd6e1fef6f2fd8d93f2adad7e98881b520a2a20000dedf5e8aff3bfb47003e065f8749475d7b8a4358eb018ad962599a18ab32faf593c38ef175b74e8792a1ae041b7f135ce79a6f62e30e50f8be2471c3ea009fca90eb7a88915c0e617340489abb8ebe7c61cd053858f79c4076c026ef3cc76bf1d64c82a170e504e48a5068aeae065ebcdd75fbd13a38203f02ba13aa490c00e4fd5f25f93ccbbe18a01faf3b1b644d873975991c51ed47cf116221cd01b103f009792125e6d371291de6e8bb4ae3cb2077c8027ed9a52fe45580eb4e6caabfe808a8d60014d55a00274dd405c80af46a904e35970fbdee92d9aa8a905ec9313982135510d98a8a9009ae6ff6369ad8229348241289efccb75f06d9be0d02e59da36a73c3c961c7d8a6eeba4966343c03b0652f42b6dd62d5bcbeba49ca94f7577790d86a031cfb0214a46c3064ab9ceb9b41d5f0ba22eae9d5fde6778ae679be3a3ebf09caf7f50d903a315b63b89cc052156ea2e8e1d3e7f1f90dd9096c15219fc226e5fb40534e2639c0b48303f8ace701882a7b9b74b8faa74072802a58fcf9b793c3560d32ddbd3ae3ea984fc7a54d18b1fc05991b7a930373ad800000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000037049444154789ced9a5f6ae33010c6bf6c12ba0da4e4411b0a2185bce40e0b3d498fd053e4143d422fb05758c81dfcd2875228410f2106ef1627641f12796547ffac911343f483426d8f3f69c6926c4d0688442291482412894422912ba4e37b23636c5fc79e73eedc964ebb8e862b3dcacd2f0fb3d2f16ab72dfe1f77cbd2cfc01e303b211c5f4ca6de1a75210560b5db9e74528708d633b05739c018db0bc77d357cf8461558edb6c59f0b2f0fb39321eee2bc4dc3177200749802223b6072de558342630100a01d19b6d132eef68aa9e5abe14aa30110c8d344747c3199d61afa260d4adf488b2070ba52ab90174b9727276cc6dd5ead85d607927292e64890bbd96aec92547fbfb8c7b50d1fce3205da0c6904cc87fdd2b13c547fafff1436aaa1bcda6d814d59a36a276b68d9503c08b006c8e8e6b7386f9bffae7621f19e029cf3cee2e3dd38874d2c3ede0b0dc0bc165449d21c499a171a5e1d3812640488ce9b86aa71b13b5e4bd2dc3cdc2d3a3e901641ce79e775f3591ceb3a573dffbaf92c9e9c4a43b65f66ebe29c7c5ed6a0106443c118dbcf7adf01003f072300878eab8edfb67f951d171ac25ea521cee9347c08320538e71d1c1d5866eb528701bbf3b20624a7f95706763328eeb769f810342122460100f0afecbfedcd00c0a1f336541ab6fb2901218d80c564aafc4c5dedb6a585b16a235f7f1cdd2a3f776d1ac246bc457cb9f897e039dff92a2e1e0081eb4752688206c0253364ba5ec7c9d6e503ea6c73cfd1962bcd6db43d39f79a400ec0259f7c88cfe2d62c827509b5272067846c9b17d53d00a4afbb91b74608c853400e4275130300f3e18f92fd7cd83f71403e3ef76e30e87638a4962a10d576e43d822fa400a8363e2ecc877d2c33b34d92e6a569a26a3b048dbf06430f59c06d77e90af92d10ea495caa3def1150cd01087ca6842b4de405c802723648a6ba97af7bdd64d3aa8c5091c9413999d1042221d28a8c908a50bfd9eb68a2442612894422d7ccd5bf06836c8684e372e5a8286e781cdd2aefb15d57d9b4ae521428d7f999cad9744552baf25af9bc5c1506008bb6548afa94b9a9a83a6e4ba286288f1378078031b67fbabbafb5df970b20657c4a634205214856b889a4874b9b4f77f7972f94943b24d0253629bf0f341564724e10384d8254f37975d3de2a0d53fb14480110098b5fc74a0e5d3648f5f46cced95866eb43fb5dda2cfe07f2bf7fac7f79917b0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000034d49444154789ced9ab18ee230108687d349275d419596faa4d0b05dd817d86a4b1e01695b6aeaad69917804caabee05201d6912696b5a57142b6dc515bb8e26c6766ccf84b0c29f844412e7b767327132130344229148241289442291c81d32083d314992b34f7b2184735f266d1f0d577e524eae56af8ded5355d4ff87e9a4712c5d2ccf007623a4e1f97c16ace10b2902f2f9ac31489b0324e962a93540ea617c3542f84115385545fd73a15abd5e84b8ce785f8d50c80e3061730836c066bcab0685ce1c0000c6c8688b96613aa9c33f54c315f21c4021db6c41a7818d77d1a0cc07a4a7008079a2c29caac2cb28d966984e1ae7ead93a8dd304c901fbf208501edd1a1bdaed6de7cb63ae7d04d0e91cf01d2045c0743c6a6ce350fdb7fd5bb7d185f2a92a00767943436d87358cec728a09f4390063babfe5feb6fbdfb51d27c1b7801062906db6f67bd8829cbdb3cde724e6a3b32f8fb02f8fe42700005304c8c1db42d566a03cb62f8ff6706fd1098134090a21060b740f9a06a7ee5fecf2facae93470fb7571a8f7e1fd5883023902be0c38fff9fdabb17f5d1cb4db6fef1f1703c71a2f930700f87484aa2175741aa1b0a5954992d44e78993cd483c7ffdb066ed2c0701a0fc05c1051a340e5edfda355d7a6613abfb75761b51e20395545636254dbe0e34fb367edeb6e9b866c239f22a1f4fe2678cd67be8ede1d20717d49e286d5012e9521db711f23b91cc2e6009f34f71a7db9c29a0b7070ed3981ec803eaf3cc76bf1cd4c82be70e504e48a505bf2a23b07a0f9aa1caac101f916c04e509318804be3a6e3d1850178fbdad9206b3acca9a57384da8f2e57f085e4807571a8b3371fa6e351ebe04dd920ee9b83ce1f83dc210b604fad7d213f05b8ae445ffd0547801062005ff93b1e54c82de10aee87ab2e4016c0458c6b71731521591ce9da11b220721315211d5cdfec4d74b1442612894422f7ccdd3f06595f84f0ca51b9b8e169f6ac3da7edb8ae4dba580200af23c8d9205e2d665bce665a24655a5d8af7cbffb29f6cb33ddfc44a519fa572b66f06aae16d45d47c3eeb7fa5689224e7d563e695efe305909890a5315c4e60a90a7751f470e973f598919dc0561172296c52be0f74e564724d10e0b208a2d6f37ccbde3a0d5bff145822c0e40889eeea5107cf551afb0fe1da4dd508c862c60000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000040449444154789ced9abd6adc4010c7ffe71c290226c5ad316a7270b83c84895db8f313b8cb0bdc4b5c9147307e877b8134264fe0ce86a4092e83e1d288035d11420c0621a55056da5bed87a4193901efaff159ba5bcd7ff66b66b44020100804028140201008bc40467d7f288428ba7c3f4dd3d6cfb2b5dda58db68c293f4e92f3eaf3473c2977ae77be77f5fa37849815805b8414feeddd5be3fd18f0b6d1159203243ef100b0dd3e000084981526014288c224fce0eeb8fa9cfcfd1b4537c636fa4076804f7c9eef57ff6f4e1f01ac31c77447802e5e155d193afe547d5e24175845b72c4e20ad018be44cb9528b97bdae8a976c4e1f911731e21f3f91a6e948156f120eec8a972cb30baca25bf27460990226f136f2226e5c33095747d6a5f599872dedb3b3476ec1223e79ffcaf9ab24398710a2501752a014be3badec2c924de7dd48873802dce237a78f38fcf2a6be7e72e4ed6dc9e5f833006099e55866392ec7755f2db39c66b602cb1450c5cb792fe77a72525e3fb83b6e21feba715fb67f6579f664d2c7e21ab2036cc35e9debba70f310df15bfcc72ef7ac201c901260365cf03fec5adc41c37487c6bc97cddc250074cbb4069a8abd701d3702f57f12e8b2737a43d540851dc4feb2ec88bb8f53c5f4587551cb0dd3e78859bb64f194bf4b3be846d04f8c5efee18eae265126f123c04e450524672f685aeb9554e2633e8a1f0fd74ed15ad3e238a6e5892229684420d686cdb9a4dbcda862d0b0486110f303900a89dd0a5e74d6df8f2024ef1007341a44e8e4af1faea3e5f4fbdedeaa1b1e4239eb08a6e8df7280e2139a039ecfd7941db6468b75d49335294bb494bb31b30d6039ae2f5d5dd152798525e731658b2b7f70bc03f0e8575f1ae80c617247525cff72b275018341b043ae404d985b34d1553a1a52fecd9a04afb84a839b7db84c7e5c2dac150036c91a0441a6b13df25197a8ebc6090747828f1b25d5963e0802d1da6886f2b5c127dfd5e7ef7e4a8bbd11a0c35c1e1c4e745dc10afb6cbb19b90a7c090e255d436b3ec436f7b7568afc60cc3d5dd2bddc5bb9d49876517b0a5b1becc10b08b1f5ab884751bb41bdd2f60f2154fa97900c0e0007fe5864bbcb9644ea5b703d2341dcd313516314c09928a4b7c5be11cbd0f1047409aa6a3183096c4744c19a23b41b287c7bec24a17c853403a01d10d7c15211bee395fb73199ccaa67d2acae613d72427d51e9638823328140201078c9bcf86d90251992c217c9c61bef37839ef6ef13fecb93a2e579c10d007fb2e30a977d95e583bbe3414e8a924a6236f12aa66cd1952cb5719c3c62d7c7669dde0e7089ef5e296a62132fcf112e92331627b01445557c2f424de873df5615d293250e273cfb31b93ee52d778d80765c96fdcd900e47e9baa6f92285fa76986d0af419fa14b80e51fe015b82798ed508dde10000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000036f49444154789ced9abd6ae3401080c7e61e4195cb1030e4c8a5b807b8268d8d1b839bab53ea090ed7214fe0f2ea348134216eaec903a4389b180c42a52b3d8375cd8d6eb4da3fed8c6c1fde0f0c96b43bbb33dabf190d40241289442291482412899c21bdd08a4992946dca1745e1dd9649761b19be7ce2547e7d7eaa5def77dbea7f7f30ac3d1b4f6725805d0954fc65711f2ca32d2c03ec77db46274da0b1c6d359a95320499212150f9511429f2b60bfdb563f1f5e9f9f1a43dc4779978c50d8063061330855c0a6bcaf0c0e9d1900008c23c3355afa836135b54265f8c2da05da0c5b1d93740e3a1954791f199cf580b5080234576a1d74b1f4510acbf407c3560b6d082c03ac3739c026f72b6c28b7b6d5c767be6d04d0e91af03fc01a01d75717b56b3a547fff5a5665744319873995a196a332ba82bd06504cf31befbbe6bf6f394982a7405114bd493ab7cf610bb87a4fd2390038d60285f52687f52667ef00004223003b6f1baa3605f1d97a933b877ba8c14db0cfd34992940fe95d758d0a50a3a89dfeb1f8597b73aa0c5a6f9567f0e5e2b2d1ae2a23141187224992f2fbe81b0040d5d9559e69af1f976fda8ea30caaac2a03ef99648420b20d1645d17b5cbe01c0bf4e535cca5319ab3cabcabf7f64557dfc492a0fc058036c8ec82acfaacebf7f64f0f5f3a5573d55865a1f8daccae01884ed0be88ea9fbddb6b606a865e8f39bdb91f6b8eb928165b83bc1d14f8287dcf3751cdd0088ef21491a5103f844866ccfdb282965103103b471730fd1962fa2be8004875e13d80638e69b9738169fcc22d816299f801d116aebab63c7e98931548604ec29408d403b860aaacae99c237a7d686f50d41d9694a53384da8eceef680bcb002657d5c5f5d585b3f3e80adbda96a0f36d507ac802f87997beb07701a93771acf65831411a03a07e7c5750f9527101d614f86b842a1a04008d608609d7735b19c9a0087b0d40230000504374018e38c9889068ca89d4377b135da4c844229148e49c39fb6d50ecdb20403d7314931b6e6e47da3aaee7ba32e3e90c004e285314a09e2d664b6733254999d26be97dfc8fed4cd2f969648ab64995b37d3350157705515f16f7c7cf14c56ffa6dfc7d9a004909498d9132824854b88ba0874f9b0fe91ddb086211219fc026e7fb40574666c70401a0111754e37921696eae98206d9f03cb006a12842940aa7b7bdcced3240c0e7f00f6308154847ee1430000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000035749444154789ced9acd6ee2301080876a5b4a0e54489638e4d256ea8563dfa14fdd77e891cb1e762f9116c91282432020357b68ed3a8eff670254f5272111e28c672613c7330c402693c96432994c2693c9fc4046a91732c6da98f19cf3e0b96cb2636484f20b73f1e3f34be798af2af99dcdcbeee0b7d716c06d84307c5a2e9265c48272005f557d252d4867bdbdb626031863ad303c55460a5758017c55c94f088fcf2fbd100f31de272315b4036cb81ca21ae0323e540686c11c0000d6c8f0450b9b97f2d14a95110a6a0d08c5a4ecc75d5f0687be4b06663d403b2064115417cb903b27c6b079e95d68b7d532505333a87dc078768f9abc59ff050a19980818740df80ea01e817151748ed550adfefc96634ca1cc571534ebae0c7d9c2ac346b3c65840bc08da9e6ff1bbeff90f1d4749f223c0391f6dab2534759d74fdb65a4a19001025a7a96b68ea5aca4852e013920810ca3b43d561a038d7d4b553864f4e0ab85c80f31103906f039b01bad2eaca6d9201f0e5cce37e639c1bbbfa0bd011200cb89acc3abfeb8a8be3f7ddbaa7b82ae3faf60e003e1c6132feb8df1865a442965632c6a413ae6fefa4f2ea779fe2ba8cc3f61f8c6e269d3194c603101744d428680fbbaf493e8d78dff9df592619beebcfb6159e960be33695afaaceb3ac8f51cf970f4fc6edae4f861883dd0a9f7d2778ca77be89b33b4010ba49a286d401219521d7f91823a91c42e6809834f7147385729282480ca75e13f01ba133de798a6df1c52c82b150e504a80808495e4cd70074b7caa93228403f02aa1354c58481ba71e3a2e82747caf1b7ca0605944ab9526b7d1e5ba61803ca01c7fd46666f318c8bc2abbc2d1b54e7a660f0d72075c802b853eb58d06f01aa3b71aef9503541919e1ef71bf91912553e555d002d402d62a8e8b97cec79d718caa2084d498c410bd02d660c8188b88ba80899a0facfdec6102d32994c2693f9c9fcf8d7204932240c573b47457343f9f064bcc677de3866804e5192adb0a9d34bcfebf5262953dedfeb20b1d40628fa0204a80888e9f0741546456b8c6f9c80a23d4e909c0d8a2eb1987c5f6d805449698d99968bcbe9141da2e81132e778768f7602594528a4b089f97f602827a36b8200d0ab0beaf5bcd8b2b749866b7e0c28078882c5e1b083d1cdc45a2035dd3dacf2c7fda6d38491ca7f0bac6cab77088dfc0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000035a49444154789ced9abd6a1b411080c721459cca82c38582f01bd87e06b706f74206bf82e00a831f409042a0573058b837a4f53324695d092115e6e05cf9dc294de632b7dadddbdd999514b41f187cbabdd99db9d99f991b8044229148241289442291d8430e421fccb26ce5d3be280ae7be4cb27d64b8f299f3f0f8f1ae713d5fceeaff7bdd93c6bdbc3f5a01d89540c587e341b00c5f581e301c0f1a83b41900c9fb23ad02288fe22b23844f5c01f3e5acfe7361fc78b7e6e23ae57d6584c23680099b41a80236e55d657088660000307a469bb7f4ba27b5fb87ca7085bd067098e453d0c9a0cabbc8e0ac07ac5d00c0bc5051e6cb999752d8a6d73d693c1b039601cad737285fdf9cdbfafc4eefb9f61142d435e07f80e5019de3a3c63575d5df3f7fd56d74ae8c6e4e65a8eda88c58b0d7008a697ee3ef6df3dfb59d24c153a0288a83493e0d9e9fb87a4ff22900f8cd735c7bb83b00809007e0e06daeeabad8b5b9bbf482c83e4f6759b6bab9bdacaf51016a1475d0f7df7f34de9c2a833e572e2ae87c3b5ceb5795118a48409165d9eaeafa0200a01e6cb9a8b4d74f0fcfc660e8eafaa2a1ac2a037f33c908412cac548d4007dfa6bc49c6f2a584c3af5f1a6d24950760ac01b640a45c5450bd7f000040f5f2d150c2358041a355efff9e7f7a78d6cae01844341f80cc97b3c61aa0b6a1f74fcfcfb4c7dd3619d886bb136cfd24b8c93d5fc7d60d80b81e92a41135804b66c876df474929838819c027ccdd445fae88c602126c7a4d601b609b6f5ee258bc338ba02f5231013b23e41babd781cfdf830e807fbc2f1910b1a70035021d587d145694d30547f47ad3d1a068382c294b678835c3112f0a8537050ca16a1b9de3a3d6c163286ceb5b82e8db608c8cae6b74e9027b17907a13dbea8f9513c4f0b45c54f55f4ca87ca9bc80484a0c931814cc07a8090dd7fbb6363b9711c2040535440c03a0c7ed4481840ea96ff6266294c824128944629fd9fb6d50f420442b47b1b8e1f4fc4cfb4cdb7d5d9bbc3f02801d3b0899aac5d4b85e2d92d2c5fd6a0589293720511780b0a2419f5239db370355f1b624ea703cd87ea5287ed3f789f769012425a43446ca082259e198656cb63e6f6e2fd94610cb08b9243639df076219999d130480b5bca09acf0b29736bcb09d2fe39b00ca016419812a4bab7c71d3c2dc2e0f0077d3871dcf62e9aae0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000027749444154789ced9ab18ec2300c40cd89b92ccc5dda9105f1ff9f8058186161ee427f809baccbe59cc44e9c36a7fa2d080826761cdb7103601886611886611886b14176b93f3c1e8f1fc9f8699ad8ff15922d91c1655ff2e3e7ebc11e3bf4e30720ae042a1e92cb9121a5c803240640867e241590c80bc9c8e14b438884ae3bfc7171a9319faf87780b8658d400e7d3056ef7eb2f23e478d2f974210d99c3a206b8ddaf703e5d54e468b1f816c0c9e30a4a561f8d87af1a5eb0f8162841cb835c8ab240d71d8afe7c9edfa021a324232cbe055aa3a8100a052374537459779cefc2b180e6caa13ed7a0ba07f893cf8de07e00d422db00d334ed867e8c8ea1268b9fe1de45191cc5fc31a5fb1fa0b207e06aa7560fb749ca089af91f29aea7a95c4ec50057397fe5a88c923288c6ea032878406c2b70944719f3fc0600de2a6b290fa0e00108a72e484d5c438694ec34985b829694aee825be8c128354698884f2778d31a94c9462f395a01960ed09ac8d1960ed094871ab4a8d73c1bf32805b586995c5cd192076800a95d6252c6e007fe29cfe807ba8d26e8badd61475df734e8b359407503440eec47cc5a8e0e61fab355133406e50f2831a25a786e248b101527bda776feef71ca59be808a57a7eeeca52e9cb5ff91a5d9f186a3dc15800c3572a8851318083565fa07a4b0cdfc75ae3529aeb08b9171b5ce5b4d31636449ab82041a1f5cc3e448d2b32866118c696d97c1a542f8490d4438d9c0723587a37f1680cc9bd319a03fecfd08f9f266e8a2ea93cc08f473471531495d76e56c4e4b987ab266e8a4afa74b131fe018a2b43c30855ee09fa4689b5b9a823b3c4ab56bf27487574a8a607c703b49ef64858f5a6a806a51ef00d0127c02237dfbafc0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000037f49444154789ced9abd6e223110c7ff9caea520da12290969a08894fe4a404a1e8014291329e5b5d7e731228532053c402205daab235d411a0227a55c918207d82b90375e63afbd9e59e0847f1212bb9e1d7b66fd35b30602814020100804028140600fa9f83e18455152443e8e63e7ba4cba8be870e53be5e18ff787ccf5723a4eff574fda99b27ae32601f28d10864f5eaebc751485e480e574bcd64813c259f5c64da233208aa24418eeabc3876f5405cbe938fdb9f0f1feb0d6c55d8cb7e9f085ec0013790e910dc833de550785d21c00c0d8336cbda57ad24e8796af0e5748ab40916eaba3d57d844e876cbc8b0eca7c409a0481f5995a873c59ba182564aa276d8789f6d1a99d26480e98cf16c06ce8266c909bcf16f6675cebf0a0d439e07f80d4038e8e0f32d77257fd331aa632baae2cbab9ac439593759405790e90318d6f71df36fe5de538f11e02711c575addc7fc319c8398bd5bddd5245644cf7cb6c07cb620af0000530f108dcfebaa79068ab2f96c61edeebe0e37419a04e338ae5cdc3ea7d7a6c6a9f72f6e9fd337a7d321cbf70793f49e7c5fd6418125a088a228e9750e0100d7972d00ab86ebae87a3bfda860b1d425ea743dc33e9f0816508c4715c198e90f43a87e80f2699060376e3651de2fafab285d7b74f9c356be9f3361d3eb02644442f0080d7b7cff4ff59b30660d5781b3a1db6e7290e21c702ba6dea723ace4c8caa8c5c7edae969b7bb361d4286ba126c7d27b8c9355fc7d61d2070dd2471c3ea0097cc505e791123b91cc2e6802261ee26ea72853516e060d37302d901db7cf31cdbe29d99048bc21513901ce0d308b1a7ef0f26e93e7f13f59a200f01398253831800b8fbf523237f747cb066807cbde96890351ce6d4a573845a8f1c23f8421a02be0d704971a9c3a40ce3810d2c83dc5d16708b2e5d21af025c6f625bf579f7003507205073019c949117202b90b341326a2c5fb43c4f66a73242722647e7084e4442642732423ab8bed99b28e3884c20100804f699bd5f06d9be0d02d993a3e270c369a7a77dc656ae93a9376e00ecd846c8745a4c8debd54352bab85f3d4162ca0d709c0b1090a2c12247e5f2be19a886db92a89397abed9f148da22879ba3f2f14efcb0720657c8ec6703981252b5c46d2c3a5cea7fb73b213d832422e894dcaf781b29c4c7280ee0407f095cf13653ec7dc541d79f553203940242c7edefdc659b3666ca8eeedd98cb3d11f4c3287307cf9072e827783447ec0ce0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000018249444154789ced9a416ec5200c4427558f00f73f20dcc15d54a852d4f4077b7e4614bf75620d0f1448e2c3cc0c1bf3a10ea02605a803a84901ea006a52803a809a14a00ea02605a803a8d95ec0a7f7c65aebd4f5adb570ed991a77710b0080defb71f7da5aab017f0f620cfcaaee9d1ad39893528aeb35ba9412ae7755c3c3e3cf80defb715ee2b5d6a9d5f45b0d375e73de153018b318a9c35809dbef02b215007ccf20a346ae800029401d404d0a50079013798232f6f03c07a8891af4cce079e61835bc840598715e64542f43140166f706f02a38a3c62c8f7d1089de07fc1c9dcf3542df07bce618e77806f92e102405a803a84901ea006a52803a809a14a00ea02605a803a8595a4029c5a23f4a9716c0c02da0b546f9b3e38531fb407005a824b0060f008759bc5dfe5563038b219bd920411130a0fdb3bfe01d2d3254012b92bb803a809a14a00ea0667b01a146c9332b6e8314014f1d84ded1291a3e07cc363932601e8543cf00c5e0817fd229ca60fb0e11c64a585a008314a00ea0e60bf0425f8751926ab40000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000035f49444154789ced9abd6a1b41108047219d444070e060ecd2e801e4d218b9481a57e9f40a7a041726850b3f825ec12fa0462a2c8c3b5b0f6052da04051604e6542b8533e7b9cbeeedcfcc4a32da0f04badbbdd99db9b9b99db90548241289442291482412891da4117a6196652b9ffe4a29e7b14cb27d64b8f29973f1d3cd79e9385f2c8bffad76b3d4d6e98f5600f54aa0e2b3612f58862f2c0f980d7ba549d61900e9f4475a05501ec55746089fb802f2c5b2f8b9f07473fe9f8beb94f795110adb0026ea0c4215a853de55068768060000a367d8bca5d56e16ee1f2ac315760ce0d01d4c4127832aef2283130f586f010073a0a2e48ba59752d8a7d56e96ae8d01cb00af2a8757953bf7f5394fdb5cc708216a0cf808b03ce04bd62a1d5357fdfdeb4fd147e7cae8e65446b51f95110b760ca0989e6f3c6f7bfe5dfb4912fc0828a51addc134f8f9c4e8dd1d4c01c0ef39c7d8c37d03000879004ebece555d839dcddda503222b082aa51a67978fc5b16ba43fbb7c2cee9c4e06ed3f9ecc8b73f43c95c14124a1c8b26c75717a000000dfbf7d0580b789eb8eafef5e8cc9d0c5e941d15f2703cf996484209656568d40276f53de24e3c7cf07189c1c96fa482a0f205c10c1c903000cef9f8bffa8c4f5dd8b55ae4e86ed7a8e4144eb0148be58960263b50f6ddf3fdad32e776d32b00ff74db0f195e03adff93a366e00c47591248da8015c2a4375ed3e4a4a1944cc003e69ee3ac6724534179060dd31816d804dde798965f1d604415fa4720296014226816bfaf1645eacf3d731ae09b607d0c9d0a40515aca2cbf674c98ecb781288a6c392b24c86a2e80cec0bcb034227e052e2aa3e2631940758c36b304645d735bb74811d03a4eec4a6c663d504313d45578d6d0c2a5faa2ec07a04de8c002b9ac3e324693d4087adbdae8f6451841d03d00800e562460cd0e3b6a222a443ea9bbd89185b6412894422b1cbecfc6b50ecdb204079e7286e6ed83fdad35e636bd7f5e9f44700b0650b21d36eb16a5e5fdd24a5cbfbab3b484cb501897d01082b1bf4d92a57f7cda0aab8ad883a1bf636bf5334cbb2d5edd5b157be4f37405242b6c6481941a42a1c731b5bdd98b757c76c23885584a8114c252fcef7815846661940b78303e0bd9e876d21dbdcaa32eac6e7c03200162c86f7cf303839344e5477f76ccad9184fe6ffc6e7bd0cfe02ec318fd9344a0a090000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000036449444154789ced9abd6ee240108087d33d81b574c4af80a868d2a108d14442a9d2a54a9707b9ea8a4857a44a478522d144164a972615ca2b001d2bbf82af88c6599b5defcf8c8188fd24246caf6777c6b3e3ddf10044229148241289442291c819d209bd510851f8b497523af76592ed23c395df949b571fef95e33cdf95ff93a45bb936185e1600cd4aa0e26faf2fc1327c211920cf777b833481c61a0c2f0b9d02428802150f9511c22faa803cdf953f17561fef7b2eeea2bc4d4628640398683288aa4093f2ae3228b4660000307a86cd5b92a45b4ead5019ae90de023e6eab633499824e86aabc8b0c4a3c20054180fd48ad430d962e4a619b24e97a05da104806d86cb6b0d96c9ddbfa9c57afb9f61142ab31e02740f2808b8b5ee55875d5cfcf55d946e7cae8e6aa8c7a3b55465b9063808a697ee379dbfc776dc749f014905276469369f0fcc4e83d9a4c01c06f9e63eca1be0100983c0007dfe4aaaec1cee6eedc01911404a5949dbbfb87f2d835d2dfdd3f944f4e27436d3f9b2fca73ea79550605960d8510a2188faf0000e0f6e61a00be06ae3bceb2a576e02803dbeb64e039938c1058a68094b29365cb623cbe82d97c511930805d7955061edfde5cc37abd8534ed95f7db6484c09a10412f000058afbfdd354dbfe675962dad7275326cf7530c42de0be896a979beab04c67a1bf57abf3fd02e776d32b00df54d70f495e021dff93a8e6e00c47591c40dab015c32434dd77d94e432089b017cb6b987e8cb15d6bd0007878e0964031cf3c9732c8b4f2608fac2b5272019206410b8a69fcd17e53aff10fd9a207b803a1875d3820ad6d1edf6749b1d97fe3860dd0e73ca32194a4567605f481e103a009714577d9ab4a13cc0015e836d64745d7697ae906300d79338567fc11e50cf0120f55c00276de405c802d46c904a7d2fef7bbda9cd496584d44c8ece109c6042e42432423ab8bed99b68a3442612894422e7ccd9bf06d9be0d02542b47b1b8a1df1f68efb15dd7b5190c2f01e0842a4501aad5624de56ca622295379ad7a1eff633fa3c9f4342a457d4ae59abe19d415b72551df5e5f8e5f292a84289e9f1ebdf6fb6a01a44a48690c971158b2c26d96b135f5f9fcf44836025b4648358229e545f93ed096914906d05570007ce7f3f05a48995b5d4653ff144806c084c59fbfff204d7bc681ea9e9e4d391bb3f9a2528411ca7f3f789142ac22e3ce0000000049454e44ae426082000000000000000000000000c51d4269d159beb8a91ef9f0a8da9c40443d6bd4
Deployed Bytecode
0x6080604052600436106101815760003560e01c806366e33870116100d1578063a2309ff81161008a578063d5abeb0111610064578063d5abeb0114610425578063d89135cd1461043b578063dc33e68114610450578063e985e9c51461047057600080fd5b8063a2309ff8146103dd578063b88d4fde146103f2578063c87b56dd1461040557600080fd5b806366e338701461032857806370a082311461034857806389ce30741461036857806395d89b41146103885780639fac68cb1461039d578063a22cb465146103bd57600080fd5b80631b2ef1ca1161013e57806342966c681161011857806342966c68146102a85780634f558e79146102c8578063621a1f74146102e85780636352211e1461030857600080fd5b80631b2ef1ca1461026257806323b872dd1461028257806342842e0e1461029557600080fd5b806301ffc9a71461018657806306fdde03146101bb578063081812fc146101dd578063095ea7b3146102155780630b1eb64a1461022a57806318160ddd1461023f575b600080fd5b34801561019257600080fd5b506101a66101a13660046124ae565b610490565b60405190151581526020015b60405180910390f35b3480156101c757600080fd5b506101d06104e2565b6040516101b2919061251b565b3480156101e957600080fd5b506101fd6101f836600461252e565b610574565b6040516001600160a01b0390911681526020016101b2565b610228610223366004612563565b6105b8565b005b34801561023657600080fd5b50610228610658565b34801561024b57600080fd5b50600154600054035b6040519081526020016101b2565b34801561026e57600080fd5b5061022861027d36600461258d565b61101b565b6102286102903660046125af565b6111a9565b6102286102a33660046125af565b61133a565b3480156102b457600080fd5b506102286102c336600461252e565b611355565b3480156102d457600080fd5b506101a66102e336600461252e565b61135e565b3480156102f457600080fd5b506101d061030336600461252e565b611369565b34801561031457600080fd5b506101fd61032336600461252e565b61142f565b34801561033457600080fd5b506101d0610343366004612698565b61143a565b34801561035457600080fd5b506102546103633660046126e1565b6115c3565b34801561037457600080fd5b506101d0610383366004612698565b611612565b34801561039457600080fd5b506101d0611831565b3480156103a957600080fd5b506102286103b836600461270c565b611840565b3480156103c957600080fd5b506102286103d8366004612738565b61184e565b3480156103e957600080fd5b50600054610254565b610228610400366004612762565b6118bf565b34801561041157600080fd5b506101d061042036600461252e565b611909565b34801561043157600080fd5b50610254600d5481565b34801561044757600080fd5b50610254611a49565b34801561045c57600080fd5b5061025461046b3660046126e1565b611a54565b34801561047c57600080fd5b506101a661048b3660046127de565b611a7f565b60006301ffc9a760e01b6001600160e01b0319831614806104c157506380ac58cd60e01b6001600160e01b03198316145b806104dc5750635b5e139f60e01b6001600160e01b03198316145b92915050565b6060600280546104f190612808565b80601f016020809104026020016040519081016040528092919081815260200182805461051d90612808565b801561056a5780601f1061053f5761010080835404028352916020019161056a565b820191906000526020600020905b81548152906001019060200180831161054d57829003601f168201915b5050505050905090565b600061057f82611aad565b61059c576040516333d1c03960e21b815260040160405180910390fd5b506000908152600660205260409020546001600160a01b031690565b60006105c38261142f565b9050336001600160a01b038216146105fc576105df8133611a7f565b6105fc576040516367d9dca160e11b815260040160405180910390fd5b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b604080516001808252818301909252600091816020015b6106b36040518060e0016040528060608152602001606081526020016000815260200160608152602001600015158152602001600015158152602001600081525090565b81526020019060019003908161066f5790505090506040518060e0016040528060405180604001604052806002815260200161426760f01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa81526020016040518061020001604052806101c881526020016151726101c89139815260200160001515815260200160001515815260200160008152508160008151811061076c5761076c612842565b60200260200101819052506107c160006040518060400160405280600a815260200169109858dad9dc9bdd5b9960b21b815250782a0447781a3883ec736ad2be7913092a92e405d8ce75f8e00f846002611ad4565b5060408051600b8082526101808201909252600091816020015b61081f6040518060e0016040528060608152602001606081526020016000815260200160608152602001600015158152602001600015158152602001600081525090565b8152602001906001900390816107db5790505090506040518060e0016040528060405180604001604052806004815260200163526f636b60e01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103e001604052806103aa81526020016156df6103aa913981526020016000151581526020016000151581526020016000815250816000815181106108da576108da612842565b60200260200101819052506040518060e0016040528060405180604001604052806005815260200164213937bbb760d91b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103e001604052806103b58152602001613f596103b59139815260200160001515815260200160001515815260200160008152508160018151811061098c5761098c612842565b60200260200101819052506040518060e0016040528060405180604001604052806004815260200163426c657560e01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103e001604052806103b9815260200161300d6103b991398152602001600015158152602001600015158152602001600081525081600281518110610a3d57610a3d612842565b60200260200101819052506040518060e0016040528060405180604001604052806005815260200164526f75676560d81b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103c00160405280610393815260200161377c61039391398152602001600015158152602001600015158152602001600081525081600381518110610aef57610aef612842565b60200260200101819052506040518060e00160405280604051806040016040528060068152602001654f72616e676560d01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103e001604052806103a5815260200161533a6103a591398152602001600015158152602001600015158152602001600081525081600481518110610ba257610ba2612842565b60200260200101819052506040518060e00160405280604051806040016040528060048152602001634e61767960e01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103c0016040528061039d815260200161430e61039d91398152602001600015158152602001600015158152602001600081525081600581518110610c5357610c53612842565b60200260200101819052506040518060e001604052806040518060400160405280600481526020016311dbdb1960e21b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa81526020016040518061040001604052806103c58152602001614dad6103c591398152602001600015158152602001600015158152602001600081525081600681518110610d0457610d04612842565b60200260200101819052506040518060e001604052806040518060400160405280600481526020016312195b1b60e21b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103e001604052806103b681526020016133c66103b691398152602001600015158152602001600015158152602001600081525081600781518110610db557610db5612842565b60200260200101819052506040518060e00160405280604051806040016040528060068152602001655a6f6d62696560d01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806103c001604052806103a081526020016147506103a091398152602001600015158152602001600015158152602001600081525081600881518110610e6857610e68612842565b60200260200101819052506040518060e001604052806040518060400160405280600381526020016205269760ec1b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa8152602001604051806102e001604052806102bd8152602001614af06102bd91398152602001600015158152602001600015158152602001600081525081600981518110610f1857610f18612842565b60200260200101819052506040518060e00160405280604051806040016040528060048152602001635371756960e01b815250815260200160405180604001604052806009815260200168696d6167652f706e6760b81b815250815260200160fa815260200160405180610480016040528061044a8152602001613b0f61044a91398152602001600015158152602001600015158152602001600081525081600a81518110610fc957610fc9612842565b60200260200101819052506110186001604051806040016040528060048152602001635479706560e01b815250787b2b44c99db9e92dcb7790634e8caf295764b2ea4221185a1b846002611ad4565b50565b600b546040516323b872dd60e01b815233600482015261dead6024820152604481018490526001600160a01b03909116906323b872dd90606401600060405180830381600087803b15801561106f57600080fd5b505af1158015611083573d6000803e3d6000fd5b5050600b546040516323b872dd60e01b815233600482015261dead6024820152604481018590526001600160a01b0390911692506323b872dd9150606401600060405180830381600087803b1580156110db57600080fd5b505af11580156110ef573d6000803e3d6000fd5b505050506110fe336001611d0b565b600b5460405163188687dd60e21b8152600481018490526001600160a01b039091169063621a1f74906024016000604051808303816000875af1158015611149573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526111719190810190612858565b600a6000600161118060005490565b61118a91906128e5565b815260200190815260200160002090816111a4919061293e565b505050565b60006111b482611de5565b9050836001600160a01b0316816001600160a01b0316146111e75760405162a1148160e81b815260040160405180910390fd5b600082815260066020526040902080546112138187335b6001600160a01b039081169116811491141790565b61123e576112218633611a7f565b61123e57604051632ce44b5f60e11b815260040160405180910390fd5b6001600160a01b03851661126557604051633a954ecd60e21b815260040160405180910390fd5b801561127057600082555b6001600160a01b038681166000908152600560205260408082208054600019019055918716808252919020805460010190554260a01b17600160e11b17600085815260046020526040812091909155600160e11b84169003611302576001840160008181526004602052604081205490036113005760005481146113005760008181526004602052604090208490555b505b83856001600160a01b0316876001600160a01b031660008051602061473083398151915260405160405180910390a45b505050505050565b6111a4838383604051806020016040528060008152506118bf565b61101881611e53565b60006104dc82611aad565b606061137482611aad565b6113915760405163d9b9141960e01b815260040160405180910390fd5b6000828152600a6020526040902080546113aa90612808565b80601f01602080910402602001604051908101604052809291908181526020018280546113d690612808565b80156114235780601f106113f857610100808354040283529160200191611423565b820191906000526020600020905b81548152906001019060200180831161140657829003601f168201915b50505050509050919050565b60006104dc82611de5565b60408051620200608101825262020040815260006020918201908152825180840190935260018352605b60f81b9183019190915260609161147c908290611e5e565b6000805b600c548110156115ba5760006114c06114bb61149d8460036129fe565b6114a88560036129fe565b6114b3906003612a15565b899190611ee7565b611fb4565b600083815260096020908152604080832060ff9485168085529252822060030154909350600160a01b90049091161515900361157957821561151f576040805180820190915260018152600b60fa1b602082015261151f908590611e5e565b600082815260086020908152604080832060098352818420858552835292819020905161156a936115539390929101612a9b565b60408051601f198184030181529190528590611e5e565b82151560000361157957600192505b6001600c5461158891906128e5565b82036115b1576040805180820190915260018152605d60f81b60208201526115b1908590611e5e565b50600101611480565b50909392505050565b60006001600160a01b0382166115ec576040516323d3ad8160e21b815260040160405180910390fd5b506001600160a01b031660009081526005602052604090205467ffffffffffffffff1690565b6040805162020060810190915262020040815260006020909101818152606091906116566040518060c00160405280608581526020016146ab608591398290611e5e565b60005b6001600c5461166891906128e5565b81101561171b5761169e6114bb6116808360036129fe565b61168b8460036129fe565b611696906003612a15565b889190611ee7565b600082815260096020908152604080832060ff949094168084529390915290206003810154919450611713916001909101906116eb906116e6906001600160a01b0316612072565b6120bc565b6040516020016116fc929190612af1565b60408051601f198184030181529190528390611e5e565b600101611659565b506117536114bb6003600c54600361173391906129fe565b61173d91906128e5565b600c5461174b9060036129fe565b879190611ee7565b60ff169150611800600960006001600c5461176e91906128e5565b815260200190815260200160002060008481526020019081526020016000206001016117d86116e6600960006001600c546117a991906128e5565b8152602080820192909252604090810160009081208982529092529020600301546001600160a01b0316612072565b6040516020016117e9929190612b4b565b60408051601f198184030181529190528290611e5e565b611809816120bc565b6040516020016118199190612caf565b60405160208183030381529060405292505050919050565b6060600380546104f190612808565b61184a82826120ca565b5050565b3360008181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b905090565b6118ca8484846111a9565b6001600160a01b0383163b15611903576118e684848484612202565b611903576040516368d2bf6b60e11b815260040160405180910390fd5b50505050565b606061191482611aad565b6119315760405163b4fa3fb360e01b815260040160405180910390fd5b60408051620200608101909152620200408152600060209091019081526119736119596104e2565b611962856122ee565b6040516020016117e9929190612cf4565b600061197e84611369565b604080516020810190915260008082529192509061199b83611612565b90506119c5816040516020016119b19190612d71565b6040516020818303038152906040526120bc565b6040516020016119d59190612caf565b60405160208183030381529060405291506119fa826040516020016115539190612e5c565b611a16611a068461143a565b6040516020016115539190612e9f565b611a1f846120bc565b604051602001611a2f9190612ee0565b604051602081830303815290604052945050505050919050565b60006118ba60015490565b6001600160a01b0381166000908152600560205260408082205467ffffffffffffffff911c166104dc565b6001600160a01b03918216600090815260076020908152604080832093909416825291909152205460ff1690565b60008054821080156104dc575050600090815260046020526040902054600160e01b161590565b604080516060810182528581526020808201869052845182840152600088815260089091529190912081518190611b0b908261293e565b5060208201516001820155604090910151600290910155600c81905560005b8251811015611332576000838281518110611b4757611b47612842565b602002602001015160a0015115611bb157600960008881526020019081526020016000206000858481518110611b7f57611b7f612842565b60209081029190910181015160c001518252810191909152604001600020600301546001600160a01b03169050611bda565b611bd7848381518110611bc657611bc6612842565b602002602001015160600151612332565b90505b6040518060a00160405280858481518110611bf757611bf7612842565b6020026020010151600001518152602001858481518110611c1a57611c1a612842565b6020026020010151602001518152602001858481518110611c3d57611c3d612842565b6020026020010151604001518152602001826001600160a01b03168152602001858481518110611c6f57611c6f612842565b60209081029190910181015160800151151590915260008981526009825260408082208683529092522081518190611ca7908261293e565b5060208201516001820190611cbc908261293e565b50604082015160028201556060820151600390910180546080909301511515600160a01b026001600160a81b03199093166001600160a01b039092169190911791909117905550600101611b2a565b6000805490829003611d305760405163b562e8dd60e01b815260040160405180910390fd5b6001600160a01b03831660008181526005602090815260408083208054680100000000000000018802019055848352600490915281206001851460e11b4260a01b178317905582840190839083906000805160206147308339815191528180a4600183015b818114611dbb5780836000600080516020614730833981519152600080a4600101611d95565b5081600003611ddc57604051622e076360e81b815260040160405180910390fd5b60005550505050565b600081600054811015611e3a5760008181526004602052604081205490600160e01b82169003611e38575b80600003611e31575060001901600081815260046020526040902054611e10565b9392505050565b505b604051636f96cda160e11b815260040160405180910390fd5b6110188160006120ca565b601f1982015182518251603f19909201918290611e7b9083612a15565b1115611edd5760405162461bcd60e51b815260206004820152602760248201527f44796e616d69634275666665723a20417070656e64696e67206f7574206f66206044820152663137bab732399760c91b606482015260840160405180910390fd5b611903848461237b565b6060836000611ef685856128e5565b67ffffffffffffffff811115611f0e57611f0e6125eb565b6040519080825280601f01601f191660200182016040528015611f38576020820181803683370190505b509050845b84811015611faa57828181518110611f5757611f57612842565b01602001516001600160f81b03191682611f7188846128e5565b81518110611f8157611f81612842565b60200101906001600160f81b031916908160001a90535080611fa281612f25565b915050611f3d565b5095945050505050565b60008181805b82518160ff16101561206a576030838260ff1681518110611fdd57611fdd612842565b016020015160f81c1080159061201057506039838260ff168151811061200557612005612842565b016020015160f81c11155b1561205857612020600a83612f3e565b91506030838260ff168151811061203957612039612842565b016020015161204b919060f81c612f61565b6120559083612f7a565b91505b8061206281612f93565b915050611fba565b509392505050565b6060813b80612089576311052bb46000526004601cfd5b600181039050604051915061ffe0603f820116820160405280825260008160208401015280600160208401853c50919050565b60606104dc826000806123b1565b60006120d583611de5565b9050806000806120f386600090815260066020526040902080549091565b915091508415612133576121088184336111fe565b612133576121168333611a7f565b61213357604051632ce44b5f60e11b815260040160405180910390fd5b801561213e57600082555b6001600160a01b038316600081815260056020526040902080546fffffffffffffffffffffffffffffffff0190554260a01b17600360e01b17600087815260046020526040812091909155600160e11b851690036121cc576001860160008181526004602052604081205490036121ca5760005481146121ca5760008181526004602052604090208590555b505b60405186906000906001600160a01b03861690600080516020614730833981519152908390a45050600180548101905550505050565b604051630a85bd0160e11b81526000906001600160a01b0385169063150b7a0290612237903390899088908890600401612fb2565b6020604051808303816000875af1925050508015612272575060408051601f3d908101601f1916820190925261226f91810190612fef565b60015b6122d0573d8080156122a0576040519150601f19603f3d011682016040523d82523d6000602084013e6122a5565b606091505b5080516000036122c8576040516368d2bf6b60e11b815260040160405180910390fd5b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490505b949350505050565b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a9004806123085750819003601f19909101908152919050565b60008151600181018060401b6bfd61000080600a3d393df3001761ffff8211850152600a8101601585016000f0925050816123755763301164256000526004601cfd5b90915290565b8051602082019150808201602084510184015b818410156123a657835181526020938401930161238e565b505082510190915250565b60608351801561206a576003600282010460021b60405192507f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f526106708515027f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f18603f52602083018181015b6003880197508751603f8160121c1651600053603f81600c1c1651600153603f8160061c1651600253603f81165160035350600051825260048201915080821061242157602001604052613d3d60f01b60038406600204808303919091526000861515909102918290035290038252509392505050565b6001600160e01b03198116811461101857600080fd5b6000602082840312156124c057600080fd5b8135611e3181612498565b60005b838110156124e65781810151838201526020016124ce565b50506000910152565b600081518084526125078160208601602086016124cb565b601f01601f19169290920160200192915050565b602081526000611e3160208301846124ef565b60006020828403121561254057600080fd5b5035919050565b80356001600160a01b038116811461255e57600080fd5b919050565b6000806040838503121561257657600080fd5b61257f83612547565b946020939093013593505050565b600080604083850312156125a057600080fd5b50508035926020909101359150565b6000806000606084860312156125c457600080fd5b6125cd84612547565b92506125db60208501612547565b9150604084013590509250925092565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561262a5761262a6125eb565b604052919050565b600067ffffffffffffffff82111561264c5761264c6125eb565b50601f01601f191660200190565b600061266d61266884612632565b612601565b905082815283838301111561268157600080fd5b828260208301376000602084830101529392505050565b6000602082840312156126aa57600080fd5b813567ffffffffffffffff8111156126c157600080fd5b8201601f810184136126d257600080fd5b6122e68482356020840161265a565b6000602082840312156126f357600080fd5b611e3182612547565b8035801515811461255e57600080fd5b6000806040838503121561271f57600080fd5b8235915061272f602084016126fc565b90509250929050565b6000806040838503121561274b57600080fd5b61275483612547565b915061272f602084016126fc565b6000806000806080858703121561277857600080fd5b61278185612547565b935061278f60208601612547565b925060408501359150606085013567ffffffffffffffff8111156127b257600080fd5b8501601f810187136127c357600080fd5b6127d28782356020840161265a565b91505092959194509250565b600080604083850312156127f157600080fd5b6127fa83612547565b915061272f60208401612547565b600181811c9082168061281c57607f821691505b60208210810361283c57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561286a57600080fd5b815167ffffffffffffffff81111561288157600080fd5b8201601f8101841361289257600080fd5b80516128a061266882612632565b8181528560208385010111156128b557600080fd5b6128c68260208301602086016124cb565b95945050505050565b634e487b7160e01b600052601160045260246000fd5b818103818111156104dc576104dc6128cf565b601f8211156111a457600081815260208120601f850160051c8101602086101561291f5750805b601f850160051c820191505b818110156113325782815560010161292b565b815167ffffffffffffffff811115612958576129586125eb565b61296c816129668454612808565b846128f8565b602080601f8311600181146129a157600084156129895750858301515b600019600386901b1c1916600185901b178555611332565b600085815260208120601f198616915b828110156129d0578886015182559484019460019091019084016129b1565b50858210156129ee5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b80820281158282048414176104dc576104dc6128cf565b808201808211156104dc576104dc6128cf565b60008154612a3581612808565b60018281168015612a4d5760018114612a6257612a91565b60ff1984168752821515830287019450612a91565b8560005260208060002060005b85811015612a885781548a820152908401908201612a6f565b50505082870194505b5050505092915050565b6e3d913a3930b4ba2fba3cb832911d1160891b81526000612abf600f830185612a28565b6a1116113b30b63ab2911d1160a91b8152612add600b820185612a28565b61227d60f01b815260020195945050505050565b643230ba309d60d91b81526000612b0b6005830185612a28565b670ed8985cd94d8d0b60c21b81528351612b2c8160088401602088016124cb565b6505258eae4d8560d31b60089290910191820152600e01949350505050565b643230ba309d60d91b81526000612b656005830185612a28565b670ed8985cd94d8d0b60c21b81528351612b868160088401602088016124cb565b7f293b6261636b67726f756e642d7265706561743a6e6f2d7265706561743b6261600892909101918201527f636b67726f756e642d73697a653a636f6e7461696e3b6261636b67726f756e6460288201527f2d706f736974696f6e3a63656e7465723b696d6167652d72656e646572696e6760488201527f3a2d7765626b69742d6f7074696d697a652d636f6e74726173743b2d6d732d6960688201527f6e746572706f6c6174696f6e2d6d6f64653a6e6561726573742d6e656967686260888201527f6f723b696d6167652d72656e646572696e673a2d6d6f7a2d63726973702d656460a88201527f6765733b696d6167652d72656e646572696e673a706978656c617465643b223e60c8820152651e17b9bb339f60d11b60e882015260ee01949350505050565b7f646174613a696d6167652f7376672b786d6c3b6261736536342c000000000000815260008251612ce781601a8501602087016124cb565b91909101601a0192915050565b683d913730b6b2911d1160b91b81528251600090612d198160098501602088016124cb565b61202360f01b6009918401918201528351612d3b81600b8401602088016124cb565b7f222c226465736372697074696f6e223a224f6e636861696e4f706570656e222c600b9290910191820152602b01949350505050565b7f3c7376672077696474683d223130302522206865696768743d2231303025222081527f76696577426f783d2230203020313230302031323030222076657273696f6e3d60208201527f22312e322220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f3260408201527f3030302f737667223e3c696d6167652077696474683d2231323030222068656960608201527033b43a1e91189918181110343932b31e9160791b608082015260008251612e358160918501602087016124cb565b6f111f1e17b4b6b0b3b29f1e17b9bb339f60811b609193909101928301525060a101919050565b6d1134b6b0b3b2afb230ba30911d1160911b81528151600090612e8681600e8501602087016124cb565b61088b60f21b600e939091019283015250601001919050565b6c1130ba3a3934b13aba32b9911d60991b81528151600090612ec881600d8501602087016124cb565b607d60f81b600d939091019283015250600e01919050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000815260008251612f1881601d8501602087016124cb565b91909101601d0192915050565b600060018201612f3757612f376128cf565b5060010190565b60ff8181168382160290811690818114612f5a57612f5a6128cf565b5092915050565b60ff82811682821603908111156104dc576104dc6128cf565b60ff81811683821601908111156104dc576104dc6128cf565b600060ff821660ff8103612fa957612fa96128cf565b60010192915050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090612fe5908301846124ef565b9695505050505050565b60006020828403121561300157600080fd5b8151611e318161249856fe89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000037349444154789ced9a314feb3010c7ff7d7a136bc25eb1d08905988ad41921f533f4495d18112b232beac8c2c067a8843a23d109de82de5096aa7bed95b56fe03938c1766cdfa5ed13fe49959ae47cf65d2e76ee622091482412894422914824be21add886799eaf42e48510de7dd97487e8f0e527a5f1c5dd43e978b65816ff3bedddd2b5d1f06c05b88d50869f5edd47eb08851401a757f7a541ba1ca0180dcf8c06287d3aa13a62f84155305b2c8b9f0f17770f5f42dc647ca88e58c80eb0e172886e80cb785f1d141a7300006b64d4454ba7bd5b847fac0e5fc8730085c9f500261dbaf13e3a28f301691500ec1395ce6cb10c324ac974dabba5b626269ee3b441728090124f527ac9dae484a3bd6ae3db470c8dce01ff03a408c8b3ac74ac87ead3ef5921630a6515e6ba8eaa9caea329c873808eedf956e7eb9e7f5f394ea21f0121446b723d703ec32ed4ec3db91e7ce80bd023a4849092bc02004c11a006ef0a559781ea9a90b236dc631d6e8334090a215acfb7979fc79e33fdf3ed6571e74c3a74f9f9745c9cd3cfeb3a28b02414799eafb2831e0060afdb07f03170d3b17c7db42643d941af9037e950e76c3a62e079048468e1f571951df4309f8e4b0306ea8dd775a8e3bd6e1fef6f2fd8d93f2adad7e98881b520a2a20000dedf5e8aff3bfb47003e065f8749475d7b8a4358eb018ad962599a18ab32faf593c38ef175b74e8792a1ae041b7f135ce79a6f62e30e50f8be2471c3ea009fca90eb7a88915c0e617340489abb8ebe7c61cd053858f79c4076c026ef3cc76bf1d64c82a170e504e48a5068aeae065ebcdd75fbd13a38203f02ba13aa490c00e4fd5f25f93ccbbe18a01faf3b1b644d873975991c51ed47cf116221cd01b103f009792125e6d371291de6e8bb4ae3cb2077c8027ed9a52fe45580eb4e6caabfe808a8d60014d55a00274dd405c80af46a904e35970fbdee92d9aa8a905ec9313982135510d98a8a9009ae6ff6369ad8229348241289efccb75f06d9be0d02e59da36a73c3c961c7d8a6eeba4966343c03b0652f42b6dd62d5bcbeba49ca94f7577790d86a031cfb0214a46c3064ab9ceb9b41d5f0ba22eae9d5fde6778ae679be3a3ebf09caf7f50d903a315b63b89cc052156ea2e8e1d3e7f1f90dd9096c15219fc226e5fb40534e2639c0b48303f8ace701882a7b9b74b8faa74072802a58fcf9b793c3560d32ddbd3ae3ea984fc7a54d18b1fc05991b7a930373ad800000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000037049444154789ced9a5f6ae33010c6bf6c12ba0da4e4411b0a2185bce40e0b3d498fd053e4143d422fb05758c81dfcd2875228410f2106ef1627641f12796547ffac911343f483426d8f3f69c6926c4d0688442291482412894422912ba4e37b23636c5fc79e73eedc964ebb8e862b3dcacd2f0fb3d2f16ab72dfe1f77cbd2cfc01e303b211c5f4ca6de1a75210560b5db9e74528708d633b05739c018db0bc77d357cf8461558edb6c59f0b2f0fb39321eee2bc4dc3177200749802223b6072de558342630100a01d19b6d132eef68aa9e5abe14aa30110c8d344747c3199d61afa260d4adf488b2070ba52ab90174b9727276cc6dd5ead85d607927292e64890bbd96aec92547fbfb8c7b50d1fce3205da0c6904cc87fdd2b13c547fafff1436aaa1bcda6d814d59a36a276b68d9503c08b006c8e8e6b7386f9bffae7621f19e029cf3cee2e3dd38874d2c3ede0b0dc0bc165449d21c499a171a5e1d3812640488ce9b86aa71b13b5e4bd2dc3cdc2d3a3e901641ce79e775f3591ceb3a573dffbaf92c9e9c4a43b65f66ebe29c7c5ed6a0106443c118dbcf7adf01003f072300878eab8edfb67f951d171ac25ea521cee9347c08320538e71d1c1d5866eb528701bbf3b20624a7f95706763328eeb769f810342122460100f0afecbfedcd00c0a1f336541ab6fb2901218d80c564aafc4c5dedb6a585b16a235f7f1cdd2a3f776d1ac246bc457cb9f897e039dff92a2e1e0081eb4752688206c0253364ba5ec7c9d6e503ea6c73cfd1962bcd6db43d39f79a400ec0259f7c88cfe2d62c827509b5272067846c9b17d53d00a4afbb91b74608c853400e4275130300f3e18f92fd7cd83f71403e3ef76e30e87638a4962a10d576e43d822fa400a8363e2ecc877d2c33b34d92e6a569a26a3b048dbf06430f59c06d77e90af92d10ea495caa3def1150cd01087ca6842b4de405c802723648a6ba97af7bdd64d3aa8c5091c9413999d1042221d28a8c908a50bfd9eb68a2442612894422d7ccd5bf06836c8684e372e5a8286e781cdd2aefb15d57d9b4ae521428d7f999cad9744552baf25af9bc5c1506008bb6548afa94b9a9a83a6e4ba286288f1378078031b67fbabbafb5df970b20657c4a634205214856b889a4874b9b4f77f7972f94943b24d0253629bf0f341564724e10384d8254f37975d3de2a0d53fb14480110098b5fc74a0e5d3648f5f46cced95866eb43fb5dda2cfe07f2bf7fac7f79917b0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000034d49444154789ced9ab18ee230108687d349275d419596faa4d0b05dd817d86a4b1e01695b6aeaad69917804caabee05201d6912696b5a57142b6dc515bb8e26c6766ccf84b0c29f844412e7b767327132130344229148241289442291c81d32083d314992b34f7b2184735f266d1f0d577e524eae56af8ded5355d4ff87e9a4712c5d2ccf007623a4e1f97c16ace10b2902f2f9ac31489b0324e962a93540ea617c3542f84115385545fd73a15abd5e84b8ce785f8d50c80e3061730836c066bcab0685ce1c0000c6c8688b96613aa9c33f54c315f21c4021db6c41a7818d77d1a0cc07a4a7008079a2c29caac2cb28d966984e1ae7ead93a8dd304c901fbf208501edd1a1bdaed6de7cb63ae7d04d0e91cf01d2045c0743c6a6ce350fdb7fd5bb7d185f2a92a00767943436d87358cec728a09f4390063babfe5feb6fbdfb51d27c1b7801062906db6f67bd8829cbdb3cde724e6a3b32f8fb02f8fe42700005304c8c1db42d566a03cb62f8ff6706fd1098134090a21060b740f9a06a7ee5fecf2facae93470fb7571a8f7e1fd5883023902be0c38fff9fdabb17f5d1cb4db6fef1f1703c71a2f930700f87484aa2175741aa1b0a5954992d44e78993cd483c7ffdb066ed2c0701a0fc05c1051a340e5edfda355d7a6613abfb75761b51e20395545636254dbe0e34fb367edeb6e9b866c239f22a1f4fe2678cd67be8ede1d20717d49e286d5012e9521db711f23b91cc2e6009f34f71a7db9c29a0b7070ed3981ec803eaf3cc76bf1cd4c82be70e504e48a505bf2a23b07a0f9aa1caac101f916c04e509318804be3a6e3d1850178fbdad9206b3acca9a57384da8f2e57f085e4807571a8b3371fa6e351ebe04dd920ee9b83ce1f83dc210b604fad7d213f05b8ae445ffd0547801062005ff93b1e54c82de10aee87ab2e4016c0458c6b71731521591ce9da11b220721315211d5cdfec4d74b1442612894422f7ccdd3f06595f84f0ca51b9b8e169f6ac3da7edb8ae4dba580200af23c8d9205e2d665bce665a24655a5d8af7cbffb29f6cb33ddfc44a519fa572b66f06aae16d45d47c3eeb7fa5689224e7d563e695efe305909890a5315c4e60a90a7751f470e973f598919dc0561172296c52be0f74e564724d10e0b208a2d6f37ccbde3a0d5bff145822c0e40889eeea5107cf551afb0fe1da4dd508c862c60000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000040449444154789ced9abd6adc4010c7ffe71c290226c5ad316a7270b83c84895db8f313b8cb0bdc4b5c9147307e877b8134264fe0ce86a4092e83e1d288035d11420c0621a55056da5bed87a4193901efaff159ba5bcd7ff66b66b44020100804028140201008bc40467d7f288428ba7c3f4dd3d6cfb2b5dda58db68c293f4e92f3eaf3473c2977ae77be77f5fa37849815805b8414feeddd5be3fd18f0b6d1159203243ef100b0dd3e000084981526014288c224fce0eeb8fa9cfcfd1b4537c636fa4076804f7c9eef57ff6f4e1f01ac31c77447802e5e155d193afe547d5e24175845b72c4e20ad018be44cb9528b97bdae8a976c4e1f911731e21f3f91a6e948156f120eec8a972cb30baca25bf27460990226f136f2226e5c33095747d6a5f599872dedb3b3476ec1223e79ffcaf9ab24398710a2501752a014be3badec2c924de7dd48873802dce237a78f38fcf2a6be7e72e4ed6dc9e5f833006099e55866392ec7755f2db39c66b602cb1450c5cb792fe77a72525e3fb83b6e21feba715fb67f6579f664d2c7e21ab2036cc35e9debba70f310df15bfcc72ef7ac201c901260365cf03fec5adc41c37487c6bc97cddc250074cbb4069a8abd701d3702f57f12e8b2737a43d540851dc4feb2ec88bb8f53c5f4587551cb0dd3e78859bb64f194bf4b3be846d04f8c5efee18eae265126f123c04e450524672f685aeb9554e2633e8a1f0fd74ed15ad3e238a6e5892229684420d686cdb9a4dbcda862d0b0486110f303900a89dd0a5e74d6df8f2024ef1007341a44e8e4af1faea3e5f4fbdedeaa1b1e4239eb08a6e8df7280e2139a039ecfd7941db6468b75d49335294bb494bb31b30d6039ae2f5d5dd152798525e731658b2b7f70bc03f0e8575f1ae80c617247525cff72b275018341b043ae404d985b34d1553a1a52fecd9a04afb84a839b7db84c7e5c2dac150036c91a0441a6b13df25197a8ebc6090747828f1b25d5963e0802d1da6886f2b5c127dfd5e7ef7e4a8bbd11a0c35c1e1c4e745dc10afb6cbb19b90a7c090e255d436b3ec436f7b7568afc60cc3d5dd2bddc5bb9d49876517b0a5b1becc10b08b1f5ab884751bb41bdd2f60f2154fa97900c0e0007fe5864bbcb9644ea5b703d2341dcd313516314c09928a4b7c5be11cbd0f1047409aa6a3183096c4744c19a23b41b287c7bec24a17c853403a01d10d7c15211bee395fb73199ccaa67d2acae613d72427d51e9638823328140201078c9bcf86d90251992c217c9c61bef37839ef6ef13fecb93a2e579c10d007fb2e30a977d95e583bbe3414e8a924a6236f12aa66cd1952cb5719c3c62d7c7669dde0e7089ef5e296a62132fcf112e92331627b01445557c2f424de873df5615d293250e273cfb31b93ee52d778d80765c96fdcd900e47e9baa6f92285fa76986d0af419fa14b80e51fe015b82798ed508dde10000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000036f49444154789ced9abd6ae3401080c7e61e4195cb1030e4c8a5b807b8268d8d1b839bab53ea090ed7214fe0f2ea348134216eaec903a4389b180c42a52b3d8375cd8d6eb4da3fed8c6c1fde0f0c96b43bbb33dabf190d40241289442291482412899c21bdd08a4992946dca1745e1dd9649761b19be7ce2547e7d7eaa5def77dbea7f7f30ac3d1b4f6725805d0954fc65711f2ca32d2c03ec77db46274da0b1c6d359a95320499212150f9511429f2b60bfdb563f1f5e9f9f1a43dc4779978c50d8063061330855c0a6bcaf0c0e9d1900008c23c3355afa836135b54265f8c2da05da0c5b1d93740e3a1954791f199cf580b5080234576a1d74b1f4510acbf407c3560b6d082c03ac3739c026f72b6c28b7b6d5c767be6d04d0e91af03fc01a01d75717b56b3a547fff5a5665744319873995a196a332ba82bd06504cf31befbbe6bf6f394982a7405114bd493ab7cf610bb87a4fd2390038d60285f52687f52667ef00004223003b6f1baa3605f1d97a933b877ba8c14db0cfd34992940fe95d758d0a50a3a89dfeb1f8597b73aa0c5a6f9567f0e5e2b2d1ae2a23141187224992f2fbe81b0040d5d9559e69af1f976fda8ea30caaac2a03ef99648420b20d1645d17b5cbe01c0bf4e535cca5319ab3cabcabf7f64557dfc492a0fc058036c8ec82acfaacebf7f64f0f5f3a5573d55865a1f8daccae01884ed0be88ea9fbddb6b606a865e8f39bdb91f6b8eb928165b83bc1d14f8287dcf3751cdd0088ef21491a5103f844866ccfdb282965103103b471730fd1962fa2be8004875e13d80638e69b9738169fcc22d816299f801d116aebab63c7e98931548604ec29408d403b860aaacae99c237a7d686f50d41d9694a53384da8eceef680bcb002657d5c5f5d585b3f3e80adbda96a0f36d507ac802f87997beb07701a93771acf65831411a03a07e7c5750f9527101d614f86b842a1a04008d608609d7735b19c9a0087b0d40230000504374018e38c9889068ca89d4377b135da4c844229148e49c39fb6d50ecdb20403d7314931b6e6e47da3aaee7ba32e3e90c004e285314a09e2d664b6733254999d26be97dfc8fed4cd2f969648ab64995b37d3350157705515f16f7c7cf14c56ffa6dfc7d9a004909498d9132824854b88ba0874f9b0fe91ddb086211219fc026e7fb40574666c70401a0111754e37921696eae98206d9f03cb006a12842940aa7b7bdcced3240c0e7f00f6308154847ee1430000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000035749444154789ced9acd6ee2301080876a5b4a0e54489638e4d256ea8563dfa14fdd77e891cb1e762f9116c91282432020357b68ed3a8eff670254f5272111e28c672613c7330c402693c96432994c2693c9fc4046a91732c6da98f19cf3e0b96cb2636484f20b73f1e3f34be798af2af99dcdcbeee0b7d716c06d84307c5a2e9265c48272005f557d252d4867bdbdb626031863ad303c55460a5758017c55c94f088fcf2fbd100f31de272315b4036cb81ca21ae0323e540686c11c0000d6c8f0450b9b97f2d14a95110a6a0d08c5a4ecc75d5f0687be4b06663d403b2064115417cb903b27c6b079e95d68b7d532505333a87dc078768f9abc59ff050a19980818740df80ea01e817151748ed550adfefc96634ca1cc571534ebae0c7d9c2ac346b3c65840bc08da9e6ff1bbeff90f1d4749f223c0391f6dab2534759d74fdb65a4a19001025a7a96b68ea5aca4852e013920810ca3b43d561a038d7d4b553864f4e0ab85c80f31103906f039b01bad2eaca6d9201f0e5cce37e639c1bbbfa0bd011200cb89acc3abfeb8a8be3f7ddbaa7b82ae3faf60e003e1c6132feb8df1865a442965632c6a413ae6fefa4f2ea779fe2ba8cc3f61f8c6e269d3194c603101744d428680fbbaf493e8d78dff9df592619beebcfb6159e960be33695afaaceb3ac8f51cf970f4fc6edae4f861883dd0a9f7d2778ca77be89b33b4010ba49a286d401219521d7f91823a91c42e6809834f7147385729282480ca75e13f01ba133de798a6df1c52c82b150e504a80808495e4cd70074b7caa93228403f02aa1354c58481ba71e3a2e82747caf1b7ca0605944ab9526b7d1e5ba61803ca01c7fd46666f318c8bc2abbc2d1b54e7a660f0d72075c802b853eb58d06f01aa3b71aef9503541919e1ef71bf91912553e555d002d402d62a8e8b97cec79d718caa2084d498c410bd02d660c8188b88ba80899a0facfdec6102d32994c2693f9c9fcf8d7204932240c573b47457343f9f064bcc677de3866804e5192adb0a9d34bcfebf5262953dedfeb20b1d40628fa0204a80888e9f0741546456b8c6f9c80a23d4e909c0d8a2eb1987c5f6d805449698d99968bcbe9141da2e81132e778768f7602594528a4b089f97f602827a36b8200d0ab0beaf5bcd8b2b749866b7e0c28078882c5e1b083d1cdc45a2035dd3dacf2c7fda6d38491ca7f0bac6cab77088dfc0000000049454e44ae4260823c7376672077696474683d223132303022206865696768743d2231323030222076696577426f783d2230203020313230302031323030222076657273696f6e3d22312e322220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f73766722207374796c653d226261636b67726f756e642d696d6167653a75726c28ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef89504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000035a49444154789ced9abd6a1b411080c721459cca82c38582f01bd87e06b706f74206bf82e00a831f409042a0573058b837a4f53324695d092115e6e05cf9dc294de632b7dadddbdd999514b41f187cbabdd99db9d99f991b8044229148241289442291d8430e421fccb26ce5d3be280ae7be4cb27d64b8f299f3f0f8f1ae713d5fceeaff7bdd93c6bdbc3f5a01d89540c587e341b00c5f581e301c0f1a83b41900c9fb23ad02288fe22b23844f5c01f3e5acfe7361fc78b7e6e23ae57d6584c23680099b41a80236e55d657088660000307a469bb7f4ba27b5fb87ca7085bd067098e453d0c9a0cabbc8e0ac07ac5d00c0bc5051e6cb999752d8a6d73d693c1b039601cad737285fdf9cdbfafc4eefb9f61142d435e07f80e5019de3a3c63575d5df3f7fd56d74ae8c6e4e65a8eda88c58b0d7008a697ee3ef6df3dfb59d24c153a0288a83493e0d9e9fb87a4ff22900f8cd735c7bb83b00809007e0e06daeeabad8b5b9bbf482c83e4f6759b6bab9bdacaf51016a1475d0f7df7f34de9c2a833e572e2ae87c3b5ceb5795118a48409165d9eaeafa0200a01e6cb9a8b4d74f0fcfc660e8eafaa2a1ac2a037f33c908412cac548d4007dfa6bc49c6f2a584c3af5f1a6d24950760ac01b640a45c5450bd7f000040f5f2d150c2358041a355efff9e7f7a78d6cae01844341f80cc97b3c61aa0b6a1f74fcfcfb4c7dd3619d886bb136cfd24b8c93d5fc7d60d80b81e92a41135804b66c876df474929838819c027ccdd445fae88c602126c7a4d601b609b6f5ee258bc338ba02f5231013b23e41babd781cfdf830e807fbc2f1910b1a70035021d587d145694d30547f47ad3d1a068382c294b678835c3112f0a8537050ca16a1b9de3a3d6c163286ceb5b82e8db608c8cae6b74e9027b17907a13dbea8f9513c4f0b45c54f55f4ca87ca9bc80484a0c931814cc07a8090dd7fbb6363b9711c2040535440c03a0c7ed4481840ea96ff6266294c824128944629fd9fb6d50f420442b47b1b8e1f4fc4cfb4cdb7d5d9bbc3f02801d3b0899aac5d4b85e2d92d2c5fd6a0589293720511780b0a2419f5239db370355f1b624ea703cd87ea5287ed3f789f769012425a43446ca082259e198656cb63e6f6e2fd94610cb08b9243639df076219999d130480b5bca09acf0b29736bcb09d2fe39b00ca016419812a4bab7c71d3c2dc2e0f0077d3871dcf62e9aae0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000027749444154789ced9ab18ec2300c40cd89b92ccc5dda9105f1ff9f8058186161ee427f809baccbe59cc44e9c36a7fa2d080826761cdb7103601886611886611886b14176b93f3c1e8f1fc9f8699ad8ff15922d91c1655ff2e3e7ebc11e3bf4e30720ae042a1e92cb9121a5c803240640867e241590c80bc9c8e14b438884ae3bfc7171a9319faf87780b8658d400e7d3056ef7eb2f23e478d2f974210d99c3a206b8ddaf703e5d54e468b1f816c0c9e30a4a561f8d87af1a5eb0f8162841cb835c8ab240d71d8afe7c9edfa021a324232cbe055aa3a8100a052374537459779cefc2b180e6caa13ed7a0ba07f893cf8de07e00d422db00d334ed867e8c8ea1268b9fe1de45191cc5fc31a5fb1fa0b207e06aa7560fb749ca089af91f29aea7a95c4ec50057397fe5a88c923288c6ea032878406c2b70944719f3fc0600de2a6b290fa0e00108a72e484d5c438694ec34985b829694aee825be8c128354698884f2778d31a94c9462f395a01960ed09ac8d1960ed094871ab4a8d73c1bf32805b586995c5cd192076800a95d6252c6e007fe29cfe807ba8d26e8badd61475df734e8b359407503440eec47cc5a8e0e61fab355133406e50f2831a25a786e248b101527bda776feef71ca59be808a57a7eeeca52e9cb5ff91a5d9f186a3dc15800c3572a8851318083565fa07a4b0cdfc75ae3529aeb08b9171b5ce5b4d31636449ab82041a1f5cc3e448d2b32866118c696d97c1a542f8490d4438d9c0723587a37f1680cc9bd319a03fecfd08f9f266e8a2ea93cc08f473471531495d76e56c4e4b987ab266e8a4afa74b131fe018a2b43c30855ee09fa4689b5b9a823b3c4ab56bf27487574a8a607c703b49ef64858f5a6a806a51ef00d0127c02237dfbafc0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000037f49444154789ced9abd6e223110c7ff9caea520da12290969a08894fe4a404a1e8014291329e5b5d7e731228532053c402205daab235d411a0227a55c918207d82b90375e63afbd9e59e0847f1212bb9e1d7b66fd35b30602814020100804028140600fa9f83e18455152443e8e63e7ba4cba8be870e53be5e18ff787ccf5723a4eff574fda99b27ae32601f28d10864f5eaebc751485e480e574bcd64813c259f5c64da233208aa24418eeabc3876f5405cbe938fdb9f0f1feb0d6c55d8cb7e9f085ec0013790e910dc833de550785d21c00c0d8336cbda57ad24e8796af0e5748ab40916eaba3d57d844e876cbc8b0eca7c409a0481f5995a873c59ba182564aa276d8789f6d1a99d26480e98cf16c06ce8266c909bcf16f6675cebf0a0d439e07f80d4038e8e0f32d77257fd331aa632baae2cbab9ac439593759405790e90318d6f71df36fe5de538f11e02711c575addc7fc319c8398bd5bddd5245644cf7cb6c07cb620af0000530f108dcfebaa79068ab2f96c61edeebe0e37419a04e338ae5cdc3ea7d7a6c6a9f72f6e9fd337a7d321cbf70793f49e7c5fd6418125a088a228e9750e0100d7972d00ab86ebae87a3bfda860b1d425ea743dc33e9f0816508c4715c198e90f43a87e80f2699060376e3651de2fafab285d7b74f9c356be9f3361d3eb02644442f0080d7b7cff4ff59b30660d5781b3a1db6e7290e21c702ba6dea723ace4c8caa8c5c7edae969b7bb361d4286ba126c7d27b8c9355fc7d61d2070dd2471c3ea0097cc505e791123b91cc2e6802261ee26ea72853516e060d37302d901db7cf31cdbe29d99048bc21513901ce0d308b1a7ef0f26e93e7f13f59a200f01398253831800b8fbf523237f747cb066807cbde96890351ce6d4a573845a8f1c23f8421a02be0d704971a9c3a40ce3810d2c83dc5d16708b2e5d21af025c6f625bf579f7003507205073019c949117202b90b341326a2c5fb43c4f66a73242722647e7084e4442642732423ab8bed99b28e3884c20100804f699bd5f06d9be0d02d993a3e270c369a7a77dc656ae93a9376e00ecd846c8745a4c8debd54352bab85f3d4162ca0d709c0b1090a2c12247e5f2be19a886db92a89397abed9f148da22879ba3f2f14efcb0720657c8ec6703981252b5c46d2c3a5cea7fb73b213d832422e894dcaf781b29c4c7280ee0407f095cf13653ec7dc541d79f553203940242c7edefdc659b3666ca8eeedd98cb3d11f4c3287307cf9072e827783447ec0ce0000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000018249444154789ced9a416ec5200c4427558f00f73f20dcc15d54a852d4f4077b7e4614bf75620d0f1448e2c3cc0c1bf3a10ea02605a803a84901ea006a52803a809a14a00ea02605a803a8d95ec0a7f7c65aebd4f5adb570ed991a77710b0080defb71f7da5aab017f0f620cfcaaee9d1ad39893528aeb35ba9412ae7755c3c3e3cf80defb715ee2b5d6a9d5f45b0d375e73de153018b318a9c35809dbef02b215007ccf20a346ae800029401d404d0a50079013798232f6f03c07a8891af4cce079e61835bc840598715e64542f43140166f706f02a38a3c62c8f7d1089de07fc1c9dcf3542df07bce618e77806f92e102405a803a84901ea006a52803a809a14a00ea02605a803a8595a4029c5a23f4a9716c0c02da0b546f9b3e38531fb407005a824b0060f008759bc5dfe5563038b219bd920411130a0fdb3bfe01d2d3254012b92bb803a809a14a00ea0667b01a146c9332b6e8314014f1d84ded1291a3e07cc363932601e8543cf00c5e0817fd229ca60fb0e11c64a585a008314a00ea0e60bf0425f8751926ab40000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000035f49444154789ced9abd6a1b41108047219d444070e060ecd2e801e4d218b9481a57e9f40a7a041726850b3f825ec12fa0462a2c8c3b5b0f6052da04051604e6542b8533e7b9cbeeedcfcc4a32da0f04badbbdd99db9b9b99db90548241289442291482412891da4117a6196652b9ffe4a29e7b14cb27d64b8f29973f1d3cd79e9385f2c8bffad76b3d4d6e98f5600f54aa0e2b3612f58862f2c0f980d7ba549d61900e9f4475a05501ec55746089fb802f2c5b2f8b9f07473fe9f8beb94f795110adb0026ea0c4215a853de55068768060000a367d8bca5d56e16ee1f2ac315760ce0d01d4c4127832aef2283130f586f010073a0a2e48ba59752d8a7d56e96ae8d01cb00af2a8757953bf7f5394fdb5cc708216a0cf808b03ce04bd62a1d5357fdfdeb4fd147e7cae8e65446b51f95110b760ca0989e6f3c6f7bfe5dfb4912fc0828a51addc134f8f9c4e8dd1d4c01c0ef39c7d8c37d03000879004ebece555d839dcddda503222b082aa51a67978fc5b16ba43fbb7c2cee9c4e06ed3f9ecc8b73f43c95c14124a1c8b26c75717a000000dfbf7d0580b789eb8eafef5e8cc9d0c5e941d15f2703cf996484209656568d40276f53de24e3c7cf07189c1c96fa482a0f205c10c1c903000cef9f8bffa8c4f5dd8b55ae4e86ed7a8e4144eb0148be58960263b50f6ddf3fdad32e776d32b00ff74db0f195e03adff93a366e00c47591248da8015c2a4375ed3e4a4a1944cc003e69ee3ac6724534179060dd31816d804dde798965f1d604415fa4720296014226816bfaf1645eacf3d731ae09b607d0c9d0a40515aca2cbf674c98ecb781288a6c392b24c86a2e80cec0bcb034227e052e2aa3e2631940758c36b304645d735bb74811d03a4eec4a6c663d504313d45578d6d0c2a5faa2ec07a04de8c002b9ac3e324693d4087adbdae8f6451841d03d00800e562460cd0e3b6a222a443ea9bbd89185b6412894422b1cbecfc6b50ecdb204079e7286e6ed83fdad35e636bd7f5e9f44700b0650b21d36eb16a5e5fdd24a5cbfbab3b484cb501897d01082b1bf4d92a57f7cda0aab8ad883a1bf636bf5334cbb2d5edd5b157be4f37405242b6c6481941a42a1c731b5bdd98b757c76c23885584a8114c252fcef7815846661940b78303e0bd9e876d21dbdcaa32eac6e7c03200162c86f7cf303839344e5477f76ccad9184fe6ffc6e7bd0cfe02ec318fd9344a0a090000000049454e44ae42608289504e470d0a1a0a0000000d4948445200000040000000400806000000aa6971de000000017352474200aece1ce90000036449444154789ced9abd6ee240108087d33d81b574c4af80a868d2a108d14442a9d2a54a9707b9ea8a4857a44a478522d144164a972615ca2b001d2bbf82af88c6599b5defcf8c8188fd24246caf6777c6b3e3ddf10044229148241289442291c819d209bd510851f8b497523af76592ed23c395df949b571fef95e33cdf95ff93a45bb936185e1600cd4aa0e26faf2fc1327c211920cf777b833481c61a0c2f0b9d02428802150f9511c22faa803cdf953f17561fef7b2eeea2bc4d4628640398683288aa4093f2ae3228b4660000307a86cd5b92a45b4ead5019ae90de023e6eab633499824e86aabc8b0c4a3c20054180fd48ad430d962e4a619b24e97a05da104806d86cb6b0d96c9ddbfa9c57afb9f61142ab31e02740f2808b8b5ee55875d5cfcf55d946e7cae8e6aa8c7a3b55465b9063808a697ee379dbfc776dc749f014905276469369f0fcc4e83d9a4c01c06f9e63eca1be0100983c0007dfe4aaaec1cee6eedc01911404a5949dbbfb87f2d835d2dfdd3f944f4e27436d3f9b2fca73ea79550605960d8510a2188faf0000e0f6e61a00be06ae3bceb2a576e02803dbeb64e039938c1058a68094b29365cb623cbe82d97c511930805d7955061edfde5cc37abd8534ed95f7db6484c09a10412f000058afbfdd354dbfe675962dad7275326cf7530c42de0be896a979beab04c67a1bf57abf3fd02e776d32b00df54d70f495e021dff93a8e6e00c47591c40dab015c32434dd77d94e432089b017cb6b987e8cb15d6bd0007878e0964031cf3c9732c8b4f2608fac2b5272019206410b8a69fcd17e53aff10fd9a207b803a1875d3820ad6d1edf6749b1d97fe3860dd0e73ca32194a4567605f481e103a009714577d9ab4a13cc0015e836d64745d7697ae906300d79338567fc11e50cf0120f55c00276de405c802d46c904a7d2fef7bbda9cd496584d44c8ece109c6042e42432423ab8bed99b68a3442612894422e7ccd9bf06d9be0d02542b47b1b8a1df1f68efb15dd7b5190c2f01e0842a4501aad5624de56ca622295379ad7a1eff633fa3c9f4342a457d4ae59abe19d415b72551df5e5f8e5f292a84289e9f1ebdf6fb6a01a44a48690c971158b2c26d96b135f5f9fcf44836025b4648358229e545f93ed096914906d05570007ce7f3f05a48995b5d4653ff144806c084c59fbfff204d7bc681ea9e9e4d391bb3f9a2528411ca7f3f789142ac22e3ce0000000049454e44ae426082a2646970667358221220d06f88ec1fc88ebef149af151d56ef1ff9ae0348dc4bbffe1daf1b4c77285d4064736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c51d4269d159beb8a91ef9f0a8da9c40443d6bd4
-----Decoded View---------------
Arg [0] : _rocks (address): 0xC51D4269D159bEb8A91ef9f0A8dA9C40443D6bd4
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000c51d4269d159beb8a91ef9f0a8da9c40443d6bd4
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.