Overview
APE Balance
APE Value
$0.00More Info
Private Name Tags
ContractCreator
Multichain Info
No addresses found
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Void
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.28; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/utils/Base64.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract Void is ERC721, Ownable { // Constants uint256 private constant MINT_PRICE = 10 ether; uint256 private constant TOKENS_PER_SECOND = 5; // 5 ACO = 1 second uint256 private constant MAX_TRANSFERS = 10; uint256 private constant TRANSFER_RESET_TIME = 2 hours; uint256 private constant INITIAL_COUNTDOWN = 24 hours; uint256 private constant MAX_BATCH_ELIMINATE = 25; uint256 private constant REVEAL_BATCH_SIZE = 25; uint256 private constant MAX_TOKENS_PER_MINT = 5; IERC20 public immutable acoToken = IERC20(0x982eDdC7CB6Aa589050ACBd3c6042864a91352EE); uint256 private constant BONUS_REQUIREMENT = 100000 ether; uint256 private constant BONUS_WINNERS = 10; uint256 private constant BONUS_PERCENTAGE = 2; address constant DEAD_ADDRESS = 0x000000000000000000000000000000000000dEaD; struct TokenData { uint256 eliminationTime; uint256 transferCount; bool isActive; bool isRevealed; uint256 survivalTime; uint8 voidClass; uint8 eyeType; uint8 symmetryType; uint8 dimensionCount; uint8 distortionType; uint8 glitchIntensity; } // Core trait limits uint256[10] private voidTypeLimits = [uint256(10), uint256(120), uint256(200), uint256(200), uint256(50), uint256(200), uint256(40), uint256(200), uint256(200), uint256(80)]; uint256[3] private eyeTypeLimits = [uint256(940), uint256(10), uint256(50)]; uint256[5] private symmetryLimits = [uint256(900), uint256(800), uint256(700), uint256(600), uint256(500)]; uint256[6] private dimensionLimits = [uint256(900), uint256(800), uint256(700), uint256(600), uint256(500), uint256(400)]; uint256[5] private distortionLimits = [uint256(500), uint256(750), uint256(900), uint256(300), uint256(300)]; uint256[3] private glitchLimits = [uint256(900), uint256(700), uint256(500)]; // Rarity tracking mapping(uint8 => uint256) private voidTypeCount; mapping(uint8 => uint256) private eyeTypeCount; mapping(uint8 => uint256) private symmetryCount; mapping(uint8 => uint256) private dimensionCount; mapping(uint8 => uint256) private distortionCount; mapping(bytes32 => bool) private usedCombinations; mapping(uint8 => bool) private voidTypeCyclopean; mapping(uint8 => uint256) private glitchCount; mapping(uint256 => TokenData) public tokenData; uint256 public totalSupply; uint256 public maxSupply; bool public mintActive; bool public mintingComplete; bool public tournamentComplete; uint256 public poolBalance; // Tournament tracking uint256 public activeTokens; string private unrevealedSVG; string private eliminatedSVG; // SVG Storage mapping(uint256 => string) private tokenSVGs; mapping(uint256 => bool) private svgLocked; mapping(uint256 => bool) public hasClaimed; mapping(uint256 => bool) public hasBonusClaimed; uint256 public tournamentStartTime; uint256 public currentRevealBatch; uint256[] public winningTokenIds; uint256[] public lastThreeEliminatedTokens; uint256[] private sortedTokenIndices; uint256 public lastRevealedIndex; uint256 public maxSurvivalTime; mapping(uint256 => uint256) public totalFeedAmount; uint256[] public bonusWinners; event TokenFed(uint256 indexed tokenId, uint256 amount, uint256 newRevealTime); event TokenEliminated(uint256 indexed tokenId, uint256 survivalTime); event TournamentComplete(uint256[] winners, uint256 finalPool); event FinalReveal(uint256 indexed tokenId, uint8 voidClass, uint8 eyeType, uint8 symmetryType, uint8 dimensionCount, uint8 distortionType, uint8 glitchIntensity); event TokenMinted(uint256 indexed tokenId, address indexed owner, uint256 price); event TournamentStarted(uint256 startTime, uint256 totalParticipants, uint256 initialPool); event TransferCountUpdated(uint256 indexed tokenId, uint256 newCount, uint256 newRevealTime); event BatchRevealStarted(uint256 batchNumber, uint256 startIndex, uint256 endIndex); event BatchRevealCompleted(uint256 batchNumber, uint256 tokensRevealed); event RevealCompleted(uint256 totalTokens, uint256 timestamp); event BonusWinnersSelected(uint256[] winners); event BonusClaimed(uint256 tokenId, uint256 amount); event MintingToggled(bool isActive); constructor( uint256 _maxSupply, string memory _unrevealedSVG, string memory _eliminatedSVG ) ERC721("Void", "VOID") Ownable(msg.sender) { maxSupply = _maxSupply; unrevealedSVG = _unrevealedSVG; eliminatedSVG = _eliminatedSVG; } function toggleMinting() external onlyOwner { require(!mintingComplete, "Minting complete"); mintActive = !mintActive; emit MintingToggled(mintActive); } function mint(uint256 amount) external payable { require(mintActive, "Mint is not active"); require(!mintingComplete, "Minting complete"); require(amount > 0 && amount <= MAX_TOKENS_PER_MINT, "Invalid amount"); require(totalSupply + amount <= maxSupply, "Exceed max supply"); require(msg.value == MINT_PRICE * amount, "Incorrect APE amount"); poolBalance += msg.value; for(uint256 i = 0; i < amount; i++) { uint256 tokenId = totalSupply++; _mint(msg.sender, tokenId); tokenData[tokenId] = TokenData({ eliminationTime: 0, transferCount: 0, isActive: true, isRevealed: false, survivalTime: 0, voidClass: 0, eyeType: 0, symmetryType: 0, dimensionCount: 0, distortionType: 0, glitchIntensity: 0 }); activeTokens++; emit TokenMinted(tokenId, msg.sender, MINT_PRICE); } if (totalSupply == maxSupply) { mintingComplete = true; tournamentStartTime = block.timestamp; for(uint256 i = 0; i < maxSupply; i++) { tokenData[i].eliminationTime = block.timestamp + INITIAL_COUNTDOWN; } emit TournamentStarted(tournamentStartTime, maxSupply, poolBalance); } } function feedToken(uint256 tokenId, uint256 amount) external { TokenData storage data = tokenData[tokenId]; require(data.isActive, "Token not active"); require(mintingComplete, "Minting not complete"); require(block.timestamp < data.eliminationTime, "Token time expired"); require(acoToken.transferFrom(msg.sender, address(this), amount), "Token transfer failed"); acoToken.transfer(DEAD_ADDRESS, amount); uint256 secondsToAdd = (amount / 1e18) / TOKENS_PER_SECOND; uint256 newTime = data.eliminationTime + secondsToAdd; require(newTime >= data.eliminationTime, "Time overflow"); data.eliminationTime = newTime; emit TokenFed(tokenId, amount, data.eliminationTime); totalFeedAmount[tokenId] += amount; } function _update( address to, uint256 tokenId, address auth ) internal virtual override returns (address) { address from = super._update(to, tokenId, auth); if (from != address(0) && to != address(0)) { TokenData storage data = tokenData[tokenId]; if (!data.isRevealed) { data.transferCount++; emit TransferCountUpdated(tokenId, data.transferCount, data.eliminationTime); if (data.transferCount >= MAX_TRANSFERS && data.isActive) { eliminateToken(tokenId); } else if (data.isActive) { data.eliminationTime = block.timestamp + TRANSFER_RESET_TIME; } } } return from; } function eliminateToken(uint256 tokenId) internal { TokenData storage data = tokenData[tokenId]; require(data.isActive, "Token already eliminated"); data.isActive = false; data.survivalTime = block.timestamp - tournamentStartTime; activeTokens--; sortedTokenIndices.push(tokenId); if (activeTokens <= 3) { lastThreeEliminatedTokens.push(tokenId); } emit TokenEliminated(tokenId, data.survivalTime); if (activeTokens == 1) { _completeTournament(); } } function _completeTournament() internal { require(!tournamentComplete, "Tournament already complete"); require(activeTokens == 1, "More than one token active"); uint256 lastSurvivor; for(uint256 i = 0; i < maxSupply; i++) { if (tokenData[i].isActive) { lastSurvivor = i; TokenData storage winnerData = tokenData[lastSurvivor]; winnerData.survivalTime = block.timestamp - tournamentStartTime; maxSurvivalTime = winnerData.survivalTime; break; } } sortedTokenIndices.push(lastSurvivor); winningTokenIds = new uint256[](3); winningTokenIds[0] = lastSurvivor; winningTokenIds[1] = lastThreeEliminatedTokens[lastThreeEliminatedTokens.length - 1]; winningTokenIds[2] = lastThreeEliminatedTokens[lastThreeEliminatedTokens.length - 2]; tournamentComplete = true; emit TournamentComplete(winningTokenIds, poolBalance); } function revealSingle(uint256 index) external onlyOwner { require(tournamentComplete, "Tournament not complete"); require(index < maxSupply, "Invalid index"); uint256 tokenId = sortedTokenIndices[maxSupply - index - 1]; TokenData storage data = tokenData[tokenId]; require(!data.isRevealed, "Token already revealed"); _assignRegularTraits(data, index); data.isRevealed = true; emit FinalReveal(tokenId, data.voidClass, data.eyeType, data.symmetryType, data.dimensionCount, data.distortionType, data.glitchIntensity); } function checkAllRevealed() external view returns (bool allRevealed, uint256[] memory unrevealedTokens) { require(tournamentComplete, "Tournament not complete"); uint256 unrevealedCount = 0; for(uint256 i = 0; i < maxSupply; i++) { if(!tokenData[sortedTokenIndices[i]].isRevealed) { unrevealedCount++; } } if(unrevealedCount == 0) { return (true, new uint256[](0)); } unrevealedTokens = new uint256[](unrevealedCount); uint256 arrayIndex = 0; for(uint256 i = 0; i < maxSupply; i++) { uint256 tokenId = sortedTokenIndices[i]; if(!tokenData[tokenId].isRevealed) { unrevealedTokens[arrayIndex++] = tokenId; } } return (false, unrevealedTokens); } function revealBatch(uint256 batchSize) external onlyOwner { require(tournamentComplete, "Tournament not complete"); require(batchSize > 0 && batchSize <= REVEAL_BATCH_SIZE, "Invalid batch size"); uint256 startIndex = lastRevealedIndex; uint256 endIndex = startIndex + batchSize; if (endIndex > maxSupply) endIndex = maxSupply; emit BatchRevealStarted(currentRevealBatch, startIndex, endIndex); uint256 revealedCount; unchecked { // Safe since we validate batchSize and indices for(uint256 i = maxSupply - startIndex - 1; i >= maxSupply - endIndex && i < maxSupply; i--) { uint256 tokenId = sortedTokenIndices[i]; TokenData storage data = tokenData[tokenId]; _assignRegularTraits(data, maxSupply - i - 1); data.isRevealed = true; ++revealedCount; emit FinalReveal(tokenId, data.voidClass, data.eyeType, data.symmetryType, data.dimensionCount, data.distortionType, data.glitchIntensity); } lastRevealedIndex = endIndex; ++currentRevealBatch; } emit BatchRevealCompleted(currentRevealBatch, revealedCount); if (lastRevealedIndex >= maxSupply) { emit RevealCompleted(maxSupply, block.timestamp); } } function _assignRegularTraits(TokenData storage data, uint256 index) internal { uint256 tokenId = sortedTokenIndices[maxSupply - index - 1]; if (tokenId == winningTokenIds[0]) { _assignWinnerTraits(data, 0); // 1st place return; } else if (tokenId == winningTokenIds[1]) { _assignWinnerTraits(data, 1); // 2nd place return; } else if (tokenId == winningTokenIds[2]) { _assignWinnerTraits(data, 2); // 3rd place return; } uint256 seed = uint256(keccak256(abi.encodePacked(block.prevrandao, tokenId))); _assignRandomTraitsSimplified(data, seed, index); } function _assignWinnerTraits(TokenData storage data, uint8 position) internal { data.voidClass = position == 0 ? 0 : position == 1 ? 7 : 5; data.eyeType = 1; // Cyclopean data.symmetryType = 4; data.dimensionCount = 5; data.distortionType = 3; data.glitchIntensity = 2; voidTypeCyclopean[data.voidClass] = true; voidTypeCount[data.voidClass]++; eyeTypeCount[data.eyeType]++; symmetryCount[data.symmetryType]++; dimensionCount[data.dimensionCount]++; distortionCount[data.distortionType]++; glitchCount[data.glitchIntensity]++; } function _assignRandomTraitsSimplified(TokenData storage data, uint256 seed, uint256 index) internal { uint256 voidRoll = seed % 1000; if (voidRoll < 10 && voidTypeCount[0] < voidTypeLimits[0]) { data.voidClass = 0; } else if (voidRoll < 50 && voidTypeCount[6] < voidTypeLimits[6]) { data.voidClass = 6; } else if (voidRoll < 100 && voidTypeCount[4] < voidTypeLimits[4]) { data.voidClass = 4; } else if (voidRoll < 180 && voidTypeCount[9] < voidTypeLimits[9]) { data.voidClass = 9; } else { uint8[6] memory commonClasses = [1,2,3,5,7,8]; for (uint8 i = 0; i < 6; i++) { uint8 classIndex = commonClasses[uint8(seed >> (i * 8)) % 6]; if (voidTypeCount[classIndex] < voidTypeLimits[classIndex]) { data.voidClass = classIndex; break; } } } uint256 eyeRoll = (seed >> 32) % 1000; if (eyeRoll < 70 && eyeTypeCount[1] < 10 && !voidTypeCyclopean[data.voidClass]) { data.eyeType = 1; voidTypeCyclopean[data.voidClass] = true; } else if (eyeRoll < 120 && eyeTypeCount[2] < eyeTypeLimits[2]) { data.eyeType = 2; } else { data.eyeType = 0; } data.symmetryType = uint8((seed >> 64) % 5); data.dimensionCount = uint8((seed >> 96) % 6); data.distortionType = uint8((seed >> 128) % 5); data.glitchIntensity = uint8((seed >> 160) % 3); voidTypeCount[data.voidClass]++; eyeTypeCount[data.eyeType]++; symmetryCount[data.symmetryType]++; dimensionCount[data.dimensionCount]++; distortionCount[data.distortionType]++; glitchCount[data.glitchIntensity]++; } function checkElimination(uint256 tokenId) public { TokenData storage data = tokenData[tokenId]; require(mintingComplete, "Minting not complete"); require(!tournamentComplete, "Tournament is complete"); if (block.timestamp >= data.eliminationTime) { eliminateToken(tokenId); } } function eliminateExpiredTokens() external { require(mintingComplete, "Minting not complete"); require(!tournamentComplete, "Tournament complete"); uint256 eliminatedCount = 0; uint256 earliestExpiry = type(uint256).max; for(uint256 i = 0; i < maxSupply; i++) { TokenData storage checkData = tokenData[i]; if (checkData.isActive && !checkData.isRevealed && block.timestamp >= checkData.eliminationTime && checkData.eliminationTime < earliestExpiry) { earliestExpiry = checkData.eliminationTime; } } for(uint256 i = 0; i < maxSupply && eliminatedCount < MAX_BATCH_ELIMINATE; i++) { TokenData storage data = tokenData[i]; if (data.isActive && !data.isRevealed && data.eliminationTime == earliestExpiry) { eliminateToken(i); eliminatedCount++; if (tournamentComplete) { break; } } } require(eliminatedCount > 0, "No tokens eliminated"); } function tokenURI(uint256 tokenId) public view override returns (string memory) { require(_ownerOf(tokenId) != address(0), "Token does not exist"); TokenData memory data = tokenData[tokenId]; if (!data.isRevealed) { if (data.isActive) { return _generateActiveURI(tokenId); } else { return _generateEliminatedURI(tokenId); } } return _generateRevealedURI(tokenId); } function _generateActiveURI(uint256 tokenId) internal view returns (string memory) { TokenData memory data = tokenData[tokenId]; string memory json = Base64.encode(bytes(string(abi.encodePacked( '{"name": "Void #', toString(tokenId), '", "description": "A void entity fighting for survival", ', '"attributes": [', '{"trait_type": "Status", "value": "Surviving"}, ', '{"trait_type": "Void Collapse", "value": "', toString(data.eliminationTime), '"}', '], ', '"image": "', unrevealedSVG, '"}' )))); return string(abi.encodePacked("data:application/json;base64,", json)); } function _generateEliminatedURI(uint256 tokenId) internal view returns (string memory) { string memory json = Base64.encode(bytes(string(abi.encodePacked( '{"name": "Void #', toString(tokenId), '", "description": "This void has collapsed", ', '"attributes": [', '{"trait_type": "Status", "value": "Collapsed"}', '], ', '"image": "', eliminatedSVG, '"}' )))); return string(abi.encodePacked("data:application/json;base64,", json)); } function _generateRevealedURI(uint256 tokenId) internal view returns (string memory) { TokenData memory data = tokenData[tokenId]; string memory svg = tokenSVGs[tokenId]; string memory json = Base64.encode(bytes(string(abi.encodePacked( '{"name": "Void #', toString(tokenId), '", "description": "A transcended void entity", ', '"attributes": [', '{"trait_type": "Void Class", "value": "', _getVoidClassName(data.voidClass), '"}, ', '{"trait_type": "Eye Type", "value": "', _getEyeTypeName(data.eyeType), '"}, ', '{"trait_type": "Symmetry", "value": "', _getSymmetryName(data.symmetryType), '"}, ', '{"trait_type": "Dimensions", "value": "', _getDimensionName(data.dimensionCount), '"}, ', '{"trait_type": "Distortion", "value": "', _getDistortionName(data.distortionType), '"}, ', '{"trait_type": "Glitch Intensity", "value": "', _getGlitchName(data.glitchIntensity), '"}', '], ', '"image": "data:image/svg+xml;base64,', Base64.encode(bytes(svg)), '"}' )))); return string(abi.encodePacked("data:application/json;base64,", json)); } // Helper functions for trait names function _getVoidClassName(uint8 voidClass) internal pure returns (string memory) { string[10] memory names = ["Void", "Singularity", "Nexus", "Entropy", "Paradox", "Tesseract", "Labyrinth", "Mandala", "Vortex", "Golden"]; return names[voidClass]; } function _getEyeTypeName(uint8 eyeType) internal pure returns (string memory) { string[3] memory names = ["None", "Cyclopean", "Triclops"]; return names[eyeType]; } function _getSymmetryName(uint8 symmetryType) internal pure returns (string memory) { string[5] memory names = ["Radial", "Bilateral", "Chaotic", "Quantum", "Transcendent"]; return names[symmetryType]; } function _getDimensionName(uint8 dimCount) internal pure returns (string memory) { string[6] memory names = ["3D", "4D", "5D", "6D", "7D", "8D"]; return names[dimCount]; } function _getDistortionName(uint8 distortionType) internal pure returns (string memory) { string[5] memory names = ["Wave", "Fractal", "Quantum", "Void", "Paradox"]; return names[distortionType]; } function _getGlitchName(uint8 glitchIntensity) internal pure returns (string memory) { string[3] memory names = ["Minor", "Moderate", "Severe"]; return names[glitchIntensity]; } function toString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } function setTokenSVG(uint256 tokenId, string calldata svgData) external onlyOwner { require(tokenData[tokenId].isRevealed, "Token not revealed"); require(!svgLocked[tokenId], "SVG already set"); tokenSVGs[tokenId] = svgData; svgLocked[tokenId] = true; } // For withdrawing stuck APE tokens function withdrawAPE() external onlyOwner { uint256 balance = address(this).balance; require(balance > 0, "No APE to withdraw"); (bool success, ) = payable(owner()).call{value: balance}(""); require(success, "Transfer failed"); } // For withdrawing any ERC20 token function withdrawERC20(address tokenAddress) external onlyOwner { IERC20 token = IERC20(tokenAddress); uint256 balance = token.balanceOf(address(this)); require(balance > 0, "No tokens to withdraw"); require(token.transfer(owner(), balance), "Transfer failed"); } function getTournamentInfo() external view returns ( bool isComplete, uint256 remainingTokens, uint256 currentPool, uint256[] memory winners ) { return ( tournamentComplete, activeTokens, poolBalance, winningTokenIds ); } // Claim Price function claimPrize(uint256 tokenId) external { require(tournamentComplete, "Tournament not complete"); require(ownerOf(tokenId) == msg.sender, "Not token owner"); require(!hasClaimed[tokenId], "Prize already claimed"); require( tokenId == winningTokenIds[0] || tokenId == winningTokenIds[1] || tokenId == winningTokenIds[2], "Token not a winner" ); hasClaimed[tokenId] = true; uint256 prize; if (tokenId == winningTokenIds[0]) { prize = (poolBalance * 50) / 100; // 1st place } else if (tokenId == winningTokenIds[1]) { prize = (poolBalance * 20) / 100; // 2nd place } else if (tokenId == winningTokenIds[2]) { prize = (poolBalance * 10) / 100; // 3rd place } require(prize > 0, "No prize to claim"); (bool success,) = payable(msg.sender).call{value: prize}(""); require(success, "Transfer failed"); } function getTokenData(uint256 tokenId) external view returns ( uint256 eliminationTime, uint256 transferCount, bool isActive, bool isRevealed, uint256 survivalTime, uint8 voidClass, uint8 eyeType, uint8 symmetryType, uint8 dimensionCount, uint8 distortionType, uint8 glitchIntensity ) { require(_ownerOf(tokenId) != address(0), "Token does not exist"); TokenData storage data = tokenData[tokenId]; return ( data.eliminationTime, data.transferCount, data.isActive, data.isRevealed, data.survivalTime, data.voidClass, data.eyeType, data.symmetryType, data.dimensionCount, data.distortionType, data.glitchIntensity ); } function getNextTokensToEliminate(uint256 limit) external view returns ( uint256[] memory tokenIds, uint256[] memory eliminationTimes, uint256 currentTimestamp ) { require(mintingComplete && !tournamentComplete, "Tournament not active"); require(limit <= 100, "Limit too high"); tokenIds = new uint256[](limit); eliminationTimes = new uint256[](limit); currentTimestamp = block.timestamp; uint256 count; for(uint256 i = 0; i < maxSupply && count < limit; i++) { TokenData storage data = tokenData[i]; if (data.isActive && !data.isRevealed) { tokenIds[count] = i; eliminationTimes[count] = data.eliminationTime; count++; } } assembly { mstore(tokenIds, count) mstore(eliminationTimes, count) } return (tokenIds, eliminationTimes, currentTimestamp); } function getTokensReadyToEliminate() external view returns (uint256) { require(mintingComplete && !tournamentComplete, "Tournament not active"); uint256 readyCount; for(uint256 i = 0; i < maxSupply; i++) { TokenData storage data = tokenData[i]; if (data.isActive && !data.isRevealed && block.timestamp >= data.eliminationTime) { readyCount++; } } return readyCount; } receive() external payable {} function selectBonusWinners() external onlyOwner { require(tournamentComplete, "Tournament not complete yet"); require(bonusWinners.length == 0, "Bonus winners already selected"); uint256[] memory eligibleTokens = new uint256[](maxSupply); uint256 eligibleCount; for(uint256 i = 0; i < maxSupply; i++) { if(totalFeedAmount[i] >= BONUS_REQUIREMENT) { eligibleTokens[eligibleCount] = i; eligibleCount++; } } // Select winners uint256 seed = uint256(keccak256(abi.encodePacked(block.timestamp, block.prevrandao))); for(uint256 i = 0; i < BONUS_WINNERS; i++) { seed = uint256(keccak256(abi.encodePacked(seed, i))); uint256 j = i + (seed % (eligibleCount - i)); uint256 temp = eligibleTokens[i]; eligibleTokens[i] = eligibleTokens[j]; eligibleTokens[j] = temp; bonusWinners.push(eligibleTokens[i]); } emit BonusWinnersSelected(bonusWinners); } function getBonusWinners() external view returns (uint256[] memory) { return bonusWinners; } function claimBonus(uint256 tokenId) external { require(bonusWinners.length == BONUS_WINNERS, "Bonus winners not selected yet"); require(ownerOf(tokenId) == msg.sender, "Not token owner"); require(!hasBonusClaimed[tokenId], "Already claimed"); bool isWinner = false; for(uint256 i = 0; i < BONUS_WINNERS; i++) { if(bonusWinners[i] == tokenId) { isWinner = true; break; } } require(isWinner, "Token not a bonus winner"); hasBonusClaimed[tokenId] = true; uint256 bonusAmount = (poolBalance * BONUS_PERCENTAGE) / 100; (bool success, ) = payable(msg.sender).call{value: bonusAmount}(""); require(success, "Transfer failed"); emit BonusClaimed(tokenId, bonusAmount); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol) pragma solidity ^0.8.20; /** * @dev Standard ERC-20 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens. */ interface IERC20Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers. * @param spender Address that may be allowed to operate on tokens without being their owner. * @param allowance Amount of tokens a `spender` is allowed to operate with. * @param needed Minimum amount required to perform a transfer. */ error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC20InvalidApprover(address approver); /** * @dev Indicates a failure with the `spender` to be approved. Used in approvals. * @param spender Address that may be allowed to operate on tokens without being their owner. */ error ERC20InvalidSpender(address spender); } /** * @dev Standard ERC-721 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens. */ interface IERC721Errors { /** * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20. * Used in balance queries. * @param owner Address of the current owner of a token. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(uint256 tokenId); /** * @dev Indicates an error related to the ownership over a particular token. Used in transfers. * @param sender Address whose tokens are being transferred. * @param tokenId Identifier number of a token. * @param owner Address of the current owner of a token. */ error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param tokenId Identifier number of a token. */ error ERC721InsufficientApproval(address operator, uint256 tokenId); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC721InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC721InvalidOperator(address operator); } /** * @dev Standard ERC-1155 Errors * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens. */ interface IERC1155Errors { /** * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. * @param balance Current balance for the interacting account. * @param needed Minimum amount required to perform a transfer. * @param tokenId Identifier number of a token. */ error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId); /** * @dev Indicates a failure with the token `sender`. Used in transfers. * @param sender Address whose tokens are being transferred. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(address receiver); /** * @dev Indicates a failure with the `operator`’s approval. Used in transfers. * @param operator Address that may be allowed to operate on tokens without being their owner. * @param owner Address of the current owner of a token. */ error ERC1155MissingApprovalForAll(address operator, address owner); /** * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals. * @param approver Address initiating an approval operation. */ error ERC1155InvalidApprover(address approver); /** * @dev Indicates a failure with the `operator` to be approved. Used in approvals. * @param operator Address that may be allowed to operate on tokens without being their owner. */ error ERC1155InvalidOperator(address operator); /** * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation. * Used in batch transfers. * @param idsLength Length of the array of token identifiers * @param valuesLength Length of the array of token amounts */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.20; import {IERC721} from "./IERC721.sol"; import {IERC721Metadata} from "./extensions/IERC721Metadata.sol"; import {ERC721Utils} from "./utils/ERC721Utils.sol"; import {Context} from "../../utils/Context.sol"; import {Strings} from "../../utils/Strings.sol"; import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol"; import {IERC721Errors} from "../../interfaces/draft-IERC6093.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC-721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ abstract contract ERC721 is Context, ERC165, IERC721, IERC721Metadata, IERC721Errors { using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; mapping(uint256 tokenId => address) private _owners; mapping(address owner => uint256) private _balances; mapping(uint256 tokenId => address) private _tokenApprovals; mapping(address owner => mapping(address operator => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual returns (uint256) { if (owner == address(0)) { revert ERC721InvalidOwner(address(0)); } return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual returns (address) { return _requireOwned(tokenId); } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual returns (string memory) { _requireOwned(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : ""; } /** * @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, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual { _approve(to, tokenId, _msgSender()); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual returns (address) { _requireOwned(tokenId); return _getApproved(tokenId); } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom(address from, address to, uint256 tokenId) public virtual { if (to == address(0)) { revert ERC721InvalidReceiver(address(0)); } // Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here. address previousOwner = _update(to, tokenId, _msgSender()); if (previousOwner != from) { revert ERC721IncorrectOwner(from, tokenId, previousOwner); } } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId) public { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual { transferFrom(from, to, tokenId); ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist * * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the * core ERC-721 logic MUST be matched with the use of {_increaseBalance} to keep balances * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`. */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } /** * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted. */ function _getApproved(uint256 tokenId) internal view virtual returns (address) { return _tokenApprovals[tokenId]; } /** * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in * particular (ignoring whether it is owned by `owner`). * * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this * assumption. */ function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) { return spender != address(0) && (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender); } /** * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner. * Reverts if: * - `spender` does not have approval from `owner` for `tokenId`. * - `spender` does not have approval to manage all of `owner`'s assets. * * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this * assumption. */ function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual { if (!_isAuthorized(owner, spender, tokenId)) { if (owner == address(0)) { revert ERC721NonexistentToken(tokenId); } else { revert ERC721InsufficientApproval(spender, tokenId); } } } /** * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override. * * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that * a uint256 would ever overflow from increments when these increments are bounded to uint128 values. * * WARNING: Increasing an account's balance using this function tends to be paired with an override of the * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership * remain consistent with one another. */ function _increaseBalance(address account, uint128 value) internal virtual { unchecked { _balances[account] += value; } } /** * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update. * * The `auth` argument is optional. If the value passed is non 0, then this function will check that * `auth` is either the owner of the token, or approved to operate on the token (by the owner). * * Emits a {Transfer} event. * * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}. */ function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) { address from = _ownerOf(tokenId); // Perform (optional) operator check if (auth != address(0)) { _checkAuthorized(from, auth, tokenId); } // Execute the update if (from != address(0)) { // Clear approval. No need to re-authorize or emit the Approval event _approve(address(0), tokenId, address(0), false); unchecked { _balances[from] -= 1; } } if (to != address(0)) { unchecked { _balances[to] += 1; } } _owners[tokenId] = to; emit Transfer(from, to, tokenId); return from; } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal { if (to == address(0)) { revert ERC721InvalidReceiver(address(0)); } address previousOwner = _update(to, tokenId, address(0)); if (previousOwner != address(0)) { revert ERC721InvalidSender(address(0)); } } /** * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual { _mint(to, tokenId); ERC721Utils.checkOnERC721Received(_msgSender(), address(0), to, tokenId, data); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * This is an internal function that does not check if the sender is authorized to operate on the token. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal { address previousOwner = _update(address(0), tokenId, address(0)); if (previousOwner == address(0)) { revert ERC721NonexistentToken(tokenId); } } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer(address from, address to, uint256 tokenId) internal { if (to == address(0)) { revert ERC721InvalidReceiver(address(0)); } address previousOwner = _update(to, tokenId, address(0)); if (previousOwner == address(0)) { revert ERC721NonexistentToken(tokenId); } else if (previousOwner != from) { revert ERC721IncorrectOwner(from, tokenId, previousOwner); } } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients * are aware of the ERC-721 standard to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is like {safeTransferFrom} in the sense that it invokes * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `tokenId` token must exist and be owned by `from`. * - `to` cannot be the zero address. * - `from` cannot be the zero address. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer(address from, address to, uint256 tokenId) internal { _safeTransfer(from, to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeTransfer(address from, address to, uint256 tokenId, bytes memory data) internal virtual { _transfer(from, to, tokenId); ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data); } /** * @dev Approve `to` to operate on `tokenId` * * The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is * either the owner of the token, or approved to operate on all tokens held by this owner. * * Emits an {Approval} event. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address to, uint256 tokenId, address auth) internal { _approve(to, tokenId, auth, true); } /** * @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not * emitted in the context of transfers. */ function _approve(address to, uint256 tokenId, address auth, bool emitEvent) internal virtual { // Avoid reading the owner unless necessary if (emitEvent || auth != address(0)) { address owner = _requireOwned(tokenId); // We do not use _isAuthorized because single-token approvals should not be able to call approve if (auth != address(0) && owner != auth && !isApprovedForAll(owner, auth)) { revert ERC721InvalidApprover(auth); } if (emitEvent) { emit Approval(owner, to, tokenId); } } _tokenApprovals[tokenId] = to; } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Requirements: * - operator can't be the address zero. * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll(address owner, address operator, bool approved) internal virtual { if (operator == address(0)) { revert ERC721InvalidOperator(operator); } _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned). * Returns the owner. * * Overrides to ownership logic should be done to {_ownerOf}. */ function _requireOwned(uint256 tokenId) internal view returns (address) { address owner = _ownerOf(tokenId); if (owner == address(0)) { revert ERC721NonexistentToken(tokenId); } return owner; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.20; import {IERC721} from "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC-721 compliant contract. */ interface IERC721 is IERC165 { /** * @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`. * * 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 calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC-721 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 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) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * 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; /** * @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; /** * @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 address zero. * * 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.20; /** * @title ERC-721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC-721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be * reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/utils/ERC721Utils.sol) pragma solidity ^0.8.20; import {IERC721Receiver} from "../IERC721Receiver.sol"; import {IERC721Errors} from "../../../interfaces/draft-IERC6093.sol"; /** * @dev Library that provide common ERC-721 utility functions. * * See https://eips.ethereum.org/EIPS/eip-721[ERC-721]. * * _Available since v5.1._ */ library ERC721Utils { /** * @dev Performs an acceptance check for the provided `operator` by calling {IERC721-onERC721Received} * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`). * * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA). * Otherwise, the recipient must implement {IERC721Receiver-onERC721Received} and return the acceptance magic value to accept * the transfer. */ function checkOnERC721Received( address operator, address from, address to, uint256 tokenId, bytes memory data ) internal { if (to.code.length > 0) { try IERC721Receiver(to).onERC721Received(operator, from, tokenId, data) returns (bytes4 retval) { if (retval != IERC721Receiver.onERC721Received.selector) { // Token rejected revert IERC721Errors.ERC721InvalidReceiver(to); } } catch (bytes memory reason) { if (reason.length == 0) { // non-IERC721Receiver implementer revert IERC721Errors.ERC721InvalidReceiver(to); } else { assembly ("memory-safe") { revert(add(32, reason), mload(reason)) } } } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Base64.sol) pragma solidity ^0.8.20; /** * @dev Provides a set of functions to operate with Base64 strings. */ library Base64 { /** * @dev Base64 Encoding/Decoding Table * See sections 4 and 5 of https://datatracker.ietf.org/doc/html/rfc4648 */ string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; string internal constant _TABLE_URL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; /** * @dev Converts a `bytes` to its Bytes64 `string` representation. */ function encode(bytes memory data) internal pure returns (string memory) { return _encode(data, _TABLE, true); } /** * @dev Converts a `bytes` to its Bytes64Url `string` representation. * Output is not padded with `=` as specified in https://www.rfc-editor.org/rfc/rfc4648[rfc4648]. */ function encodeURL(bytes memory data) internal pure returns (string memory) { return _encode(data, _TABLE_URL, false); } /** * @dev Internal table-agnostic conversion */ function _encode(bytes memory data, string memory table, bool withPadding) private pure returns (string memory) { /** * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol */ if (data.length == 0) return ""; // If padding is enabled, the final length should be `bytes` data length divided by 3 rounded up and then // multiplied by 4 so that it leaves room for padding the last chunk // - `data.length + 2` -> Prepare for division rounding up // - `/ 3` -> Number of 3-bytes chunks (rounded up) // - `4 *` -> 4 characters for each chunk // This is equivalent to: 4 * Math.ceil(data.length / 3) // // If padding is disabled, the final length should be `bytes` data length multiplied by 4/3 rounded up as // opposed to when padding is required to fill the last chunk. // - `4 * data.length` -> 4 characters for each chunk // - ` + 2` -> Prepare for division rounding up // - `/ 3` -> Number of 3-bytes chunks (rounded up) // This is equivalent to: Math.ceil((4 * data.length) / 3) uint256 resultLength = withPadding ? 4 * ((data.length + 2) / 3) : (4 * data.length + 2) / 3; string memory result = new string(resultLength); assembly ("memory-safe") { // Prepare the lookup table (skip the first "length" byte) let tablePtr := add(table, 1) // Prepare result pointer, jump over length let resultPtr := add(result, 0x20) let dataPtr := data let endPtr := add(data, mload(data)) // In some cases, the last iteration will read bytes after the end of the data. We cache the value, and // set it to zero to make sure no dirty bytes are read in that section. let afterPtr := add(endPtr, 0x20) let afterCache := mload(afterPtr) mstore(afterPtr, 0x00) // Run over the input, 3 bytes at a time for { } lt(dataPtr, endPtr) { } { // Advance 3 bytes dataPtr := add(dataPtr, 3) let input := mload(dataPtr) // To write each character, shift the 3 byte (24 bits) chunk // 4 times in blocks of 6 bits for each character (18, 12, 6, 0) // and apply logical AND with 0x3F to bitmask the least significant 6 bits. // Use this as an index into the lookup table, mload an entire word // so the desired character is in the least significant byte, and // mstore8 this least significant byte into the result and continue. mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F)))) resultPtr := add(resultPtr, 1) // Advance } // Reset the value that was cached mstore(afterPtr, afterCache) if withPadding { // When data `bytes` is not exactly 3 bytes long // it is padded with `=` characters at the end switch mod(mload(data), 3) case 1 { mstore8(sub(resultPtr, 1), 0x3d) mstore8(sub(resultPtr, 2), 0x3d) } case 2 { mstore8(sub(resultPtr, 1), 0x3d) } } } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol) pragma solidity ^0.8.20; import {Panic} from "../Panic.sol"; import {SafeCast} from "./SafeCast.sol"; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an success flag (no overflow). */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow). */ function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow). */ function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a success flag (no division by zero). */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero). */ function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * SafeCast.toUint(condition)); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return ternary(a < b, a, b); } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. Panic.panic(Panic.DIVISION_BY_ZERO); } // The following calculation ensures accurate ceiling division without overflow. // Since a is non-zero, (a - 1) / b will not overflow. // The largest possible result occurs when (a - 1) / b is type(uint256).max, // but the largest value we can obtain is type(uint256).max - 1, which happens // when a = type(uint256).max and b = 1. unchecked { return SafeCast.toUint(a > 0) * ((a - 1) / b + 1); } } /** * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2²⁵⁶ + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0. if (denominator <= prod1) { Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW)); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv ≡ 1 mod 2⁴. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2⁸ inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶ inverse *= 2 - denominator * inverse; // inverse mod 2³² inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴ inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸ inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶ // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @dev Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0); } /** * @dev Calculate the modular multiplicative inverse of a number in Z/nZ. * * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0. * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible. * * If the input value is not inversible, 0 is returned. * * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the * inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}. */ function invMod(uint256 a, uint256 n) internal pure returns (uint256) { unchecked { if (n == 0) return 0; // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version) // Used to compute integers x and y such that: ax + ny = gcd(a, n). // When the gcd is 1, then the inverse of a modulo n exists and it's x. // ax + ny = 1 // ax = 1 + (-y)n // ax ≡ 1 (mod n) # x is the inverse of a modulo n // If the remainder is 0 the gcd is n right away. uint256 remainder = a % n; uint256 gcd = n; // Therefore the initial coefficients are: // ax + ny = gcd(a, n) = n // 0a + 1n = n int256 x = 0; int256 y = 1; while (remainder != 0) { uint256 quotient = gcd / remainder; (gcd, remainder) = ( // The old remainder is the next gcd to try. remainder, // Compute the next remainder. // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd // where gcd is at most n (capped to type(uint256).max) gcd - remainder * quotient ); (x, y) = ( // Increment the coefficient of a. y, // Decrement the coefficient of n. // Can overflow, but the result is casted to uint256 so that the // next value of y is "wrapped around" to a value between 0 and n - 1. x - y * int256(quotient) ); } if (gcd != 1) return 0; // No inverse exists. return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative. } } /** * @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`. * * From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is * prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that * `a**(p-2)` is the modular multiplicative inverse of a in Fp. * * NOTE: this function does NOT check that `p` is a prime greater than `2`. */ function invModPrime(uint256 a, uint256 p) internal view returns (uint256) { unchecked { return Math.modExp(a, p - 2, p); } } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m) * * Requirements: * - modulus can't be zero * - underlying staticcall to precompile must succeed * * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make * sure the chain you're using it on supports the precompiled contract for modular exponentiation * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, * the underlying function will succeed given the lack of a revert, but the result may be incorrectly * interpreted as 0. */ function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) { (bool success, uint256 result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m). * It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying * to operate modulo 0 or if the underlying precompile reverted. * * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack * of a revert, but the result may be incorrectly interpreted as 0. */ function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) { if (m == 0) return (false, 0); assembly ("memory-safe") { let ptr := mload(0x40) // | Offset | Content | Content (Hex) | // |-----------|------------|--------------------------------------------------------------------| // | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 | // | 0x60:0x7f | value of b | 0x<.............................................................b> | // | 0x80:0x9f | value of e | 0x<.............................................................e> | // | 0xa0:0xbf | value of m | 0x<.............................................................m> | mstore(ptr, 0x20) mstore(add(ptr, 0x20), 0x20) mstore(add(ptr, 0x40), 0x20) mstore(add(ptr, 0x60), b) mstore(add(ptr, 0x80), e) mstore(add(ptr, 0xa0), m) // Given the result < m, it's guaranteed to fit in 32 bytes, // so we can use the memory scratch space located at offset 0. success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20) result := mload(0x00) } } /** * @dev Variant of {modExp} that supports inputs of arbitrary length. */ function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) { (bool success, bytes memory result) = tryModExp(b, e, m); if (!success) { Panic.panic(Panic.DIVISION_BY_ZERO); } return result; } /** * @dev Variant of {tryModExp} that supports inputs of arbitrary length. */ function tryModExp( bytes memory b, bytes memory e, bytes memory m ) internal view returns (bool success, bytes memory result) { if (_zeroBytes(m)) return (false, new bytes(0)); uint256 mLen = m.length; // Encode call args in result and move the free memory pointer result = abi.encodePacked(b.length, e.length, mLen, b, e, m); assembly ("memory-safe") { let dataPtr := add(result, 0x20) // Write result on top of args to avoid allocating extra memory. success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen) // Overwrite the length. // result.length > returndatasize() is guaranteed because returndatasize() == m.length mstore(result, mLen) // Set the memory pointer after the returned data. mstore(0x40, add(dataPtr, mLen)) } } /** * @dev Returns whether the provided byte array is zero. */ function _zeroBytes(bytes memory byteArray) private pure returns (bool) { for (uint256 i = 0; i < byteArray.length; ++i) { if (byteArray[i] != 0) { return false; } } return true; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * This method is based on Newton's method for computing square roots; the algorithm is restricted to only * using integer operations. */ function sqrt(uint256 a) internal pure returns (uint256) { unchecked { // Take care of easy edge cases when a == 0 or a == 1 if (a <= 1) { return a; } // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between // the current value as `ε_n = | x_n - sqrt(a) |`. // // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is // bigger than any uint256. // // By noticing that // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)` // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar // to the msb function. uint256 aa = a; uint256 xn = 1; if (aa >= (1 << 128)) { aa >>= 128; xn <<= 64; } if (aa >= (1 << 64)) { aa >>= 64; xn <<= 32; } if (aa >= (1 << 32)) { aa >>= 32; xn <<= 16; } if (aa >= (1 << 16)) { aa >>= 16; xn <<= 8; } if (aa >= (1 << 8)) { aa >>= 8; xn <<= 4; } if (aa >= (1 << 4)) { aa >>= 4; xn <<= 2; } if (aa >= (1 << 2)) { xn <<= 1; } // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1). // // We can refine our estimation by noticing that the middle of that interval minimizes the error. // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2). // This is going to be our x_0 (and ε_0) xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2) // From here, Newton's method give us: // x_{n+1} = (x_n + a / x_n) / 2 // // One should note that: // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a // = ((x_n² + a) / (2 * x_n))² - a // = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a // = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²) // = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²) // = (x_n² - a)² / (2 * x_n)² // = ((x_n² - a) / (2 * x_n))² // ≥ 0 // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n // // This gives us the proof of quadratic convergence of the sequence: // ε_{n+1} = | x_{n+1} - sqrt(a) | // = | (x_n + a / x_n) / 2 - sqrt(a) | // = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) | // = | (x_n - sqrt(a))² / (2 * x_n) | // = | ε_n² / (2 * x_n) | // = ε_n² / | (2 * x_n) | // // For the first iteration, we have a special case where x_0 is known: // ε_1 = ε_0² / | (2 * x_0) | // ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2))) // ≤ 2**(2*e-4) / (3 * 2**(e-1)) // ≤ 2**(e-3) / 3 // ≤ 2**(e-3-log2(3)) // ≤ 2**(e-4.5) // // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n: // ε_{n+1} = ε_n² / | (2 * x_n) | // ≤ (2**(e-k))² / (2 * 2**(e-1)) // ≤ 2**(2*e-2*k) / 2**e // ≤ 2**(e-2*k) xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5 xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9 xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18 xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36 xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72 // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either // sqrt(a) or sqrt(a) + 1. return xn - SafeCast.toUint(xn > a / xn); } } /** * @dev Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; uint256 exp; unchecked { exp = 128 * SafeCast.toUint(value > (1 << 128) - 1); value >>= exp; result += exp; exp = 64 * SafeCast.toUint(value > (1 << 64) - 1); value >>= exp; result += exp; exp = 32 * SafeCast.toUint(value > (1 << 32) - 1); value >>= exp; result += exp; exp = 16 * SafeCast.toUint(value > (1 << 16) - 1); value >>= exp; result += exp; exp = 8 * SafeCast.toUint(value > (1 << 8) - 1); value >>= exp; result += exp; exp = 4 * SafeCast.toUint(value > (1 << 4) - 1); value >>= exp; result += exp; exp = 2 * SafeCast.toUint(value > (1 << 2) - 1); value >>= exp; result += exp; result += SafeCast.toUint(value > 1); } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; uint256 isGt; unchecked { isGt = SafeCast.toUint(value > (1 << 128) - 1); value >>= isGt * 128; result += isGt * 16; isGt = SafeCast.toUint(value > (1 << 64) - 1); value >>= isGt * 64; result += isGt * 8; isGt = SafeCast.toUint(value > (1 << 32) - 1); value >>= isGt * 32; result += isGt * 4; isGt = SafeCast.toUint(value > (1 << 16) - 1); value >>= isGt * 16; result += isGt * 2; result += SafeCast.toUint(value > (1 << 8) - 1); } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } /** * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. */ function toUint(bool b) internal pure returns (uint256 u) { assembly ("memory-safe") { u := iszero(iszero(b)) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; import {SafeCast} from "./SafeCast.sol"; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant. * * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone. * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute * one branch when needed, making this function more expensive. */ function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) { unchecked { // branchless ternary works because: // b ^ (a ^ b) == a // b ^ 0 == b return b ^ ((a ^ b) * int256(SafeCast.toUint(condition))); } } /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return ternary(a > b, a, b); } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return ternary(a < b, a, b); } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson. // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift, // taking advantage of the most significant (or "sign" bit) in two's complement representation. // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result, // the mask will either be `bytes32(0)` (if n is positive) or `~bytes32(0)` (if n is negative). int256 mask = n >> 255; // A `bytes32(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it. return uint256((n + mask) ^ mask); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol) pragma solidity ^0.8.20; /** * @dev Helper library for emitting standardized panic codes. * * ```solidity * contract Example { * using Panic for uint256; * * // Use any of the declared internal constants * function foo() { Panic.GENERIC.panic(); } * * // Alternatively * function foo() { Panic.panic(Panic.GENERIC); } * } * ``` * * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil]. * * _Available since v5.1._ */ // slither-disable-next-line unused-state library Panic { /// @dev generic / unspecified error uint256 internal constant GENERIC = 0x00; /// @dev used by the assert() builtin uint256 internal constant ASSERT = 0x01; /// @dev arithmetic underflow or overflow uint256 internal constant UNDER_OVERFLOW = 0x11; /// @dev division or modulo by zero uint256 internal constant DIVISION_BY_ZERO = 0x12; /// @dev enum conversion error uint256 internal constant ENUM_CONVERSION_ERROR = 0x21; /// @dev invalid encoding in storage uint256 internal constant STORAGE_ENCODING_ERROR = 0x22; /// @dev empty array pop uint256 internal constant EMPTY_ARRAY_POP = 0x31; /// @dev array out of bounds access uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32; /// @dev resource error (too large allocation or too large array) uint256 internal constant RESOURCE_ERROR = 0x41; /// @dev calling invalid internal function uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51; /// @dev Reverts with a panic code. Recommended to use with /// the internal constants with predefined codes. function panic(uint256 code) internal pure { assembly ("memory-safe") { mstore(0x00, 0x4e487b71) mstore(0x20, code) revert(0x1c, 0x24) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SafeCast} from "./math/SafeCast.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { using SafeCast for *; bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev The string being parsed contains characters that are not in scope of the given base. */ error StringsInvalidChar(); /** * @dev The string being parsed is not a properly formatted address. */ error StringsInvalidAddressFormat(); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; assembly ("memory-safe") { ptr := add(buffer, add(32, length)) } while (true) { ptr--; assembly ("memory-safe") { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Converts an `address` with fixed length of 20 bytes to its checksummed ASCII `string` hexadecimal * representation, according to EIP-55. */ function toChecksumHexString(address addr) internal pure returns (string memory) { bytes memory buffer = bytes(toHexString(addr)); // hash the hex part of buffer (skip length + 2 bytes, length 40) uint256 hashValue; assembly ("memory-safe") { hashValue := shr(96, keccak256(add(buffer, 0x22), 40)) } for (uint256 i = 41; i > 1; --i) { // possible values for buffer[i] are 48 (0) to 57 (9) and 97 (a) to 102 (f) if (hashValue & 0xf > 7 && uint8(buffer[i]) > 96) { // case shift by xoring with 0x20 buffer[i] ^= 0x20; } hashValue >>= 4; } return string(buffer); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } /** * @dev Parse a decimal string and returns the value as a `uint256`. * * Requirements: * - The string must be formatted as `[0-9]*` * - The result must fit into an `uint256` type */ function parseUint(string memory input) internal pure returns (uint256) { return parseUint(input, 0, bytes(input).length); } /** * @dev Variant of {parseUint} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `[0-9]*` * - The result must fit into an `uint256` type */ function parseUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) { (bool success, uint256 value) = tryParseUint(input, begin, end); if (!success) revert StringsInvalidChar(); return value; } /** * @dev Variant of {parseUint-string} that returns false if the parsing fails because of an invalid character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseUint(string memory input) internal pure returns (bool success, uint256 value) { return _tryParseUintUncheckedBounds(input, 0, bytes(input).length); } /** * @dev Variant of {parseUint-string-uint256-uint256} that returns false if the parsing fails because of an invalid * character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseUint( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, uint256 value) { if (end > bytes(input).length || begin > end) return (false, 0); return _tryParseUintUncheckedBounds(input, begin, end); } /** * @dev Implementation of {tryParseUint} that does not check bounds. Caller should make sure that * `begin <= end <= input.length`. Other inputs would result in undefined behavior. */ function _tryParseUintUncheckedBounds( string memory input, uint256 begin, uint256 end ) private pure returns (bool success, uint256 value) { bytes memory buffer = bytes(input); uint256 result = 0; for (uint256 i = begin; i < end; ++i) { uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i))); if (chr > 9) return (false, 0); result *= 10; result += chr; } return (true, result); } /** * @dev Parse a decimal string and returns the value as a `int256`. * * Requirements: * - The string must be formatted as `[-+]?[0-9]*` * - The result must fit in an `int256` type. */ function parseInt(string memory input) internal pure returns (int256) { return parseInt(input, 0, bytes(input).length); } /** * @dev Variant of {parseInt-string} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `[-+]?[0-9]*` * - The result must fit in an `int256` type. */ function parseInt(string memory input, uint256 begin, uint256 end) internal pure returns (int256) { (bool success, int256 value) = tryParseInt(input, begin, end); if (!success) revert StringsInvalidChar(); return value; } /** * @dev Variant of {parseInt-string} that returns false if the parsing fails because of an invalid character or if * the result does not fit in a `int256`. * * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`. */ function tryParseInt(string memory input) internal pure returns (bool success, int256 value) { return _tryParseIntUncheckedBounds(input, 0, bytes(input).length); } uint256 private constant ABS_MIN_INT256 = 2 ** 255; /** * @dev Variant of {parseInt-string-uint256-uint256} that returns false if the parsing fails because of an invalid * character or if the result does not fit in a `int256`. * * NOTE: This function will revert if the absolute value of the result does not fit in a `uint256`. */ function tryParseInt( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, int256 value) { if (end > bytes(input).length || begin > end) return (false, 0); return _tryParseIntUncheckedBounds(input, begin, end); } /** * @dev Implementation of {tryParseInt} that does not check bounds. Caller should make sure that * `begin <= end <= input.length`. Other inputs would result in undefined behavior. */ function _tryParseIntUncheckedBounds( string memory input, uint256 begin, uint256 end ) private pure returns (bool success, int256 value) { bytes memory buffer = bytes(input); // Check presence of a negative sign. bytes1 sign = begin == end ? bytes1(0) : bytes1(_unsafeReadBytesOffset(buffer, begin)); // don't do out-of-bound (possibly unsafe) read if sub-string is empty bool positiveSign = sign == bytes1("+"); bool negativeSign = sign == bytes1("-"); uint256 offset = (positiveSign || negativeSign).toUint(); (bool absSuccess, uint256 absValue) = tryParseUint(input, begin + offset, end); if (absSuccess && absValue < ABS_MIN_INT256) { return (true, negativeSign ? -int256(absValue) : int256(absValue)); } else if (absSuccess && negativeSign && absValue == ABS_MIN_INT256) { return (true, type(int256).min); } else return (false, 0); } /** * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as a `uint256`. * * Requirements: * - The string must be formatted as `(0x)?[0-9a-fA-F]*` * - The result must fit in an `uint256` type. */ function parseHexUint(string memory input) internal pure returns (uint256) { return parseHexUint(input, 0, bytes(input).length); } /** * @dev Variant of {parseHexUint} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `(0x)?[0-9a-fA-F]*` * - The result must fit in an `uint256` type. */ function parseHexUint(string memory input, uint256 begin, uint256 end) internal pure returns (uint256) { (bool success, uint256 value) = tryParseHexUint(input, begin, end); if (!success) revert StringsInvalidChar(); return value; } /** * @dev Variant of {parseHexUint-string} that returns false if the parsing fails because of an invalid character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseHexUint(string memory input) internal pure returns (bool success, uint256 value) { return _tryParseHexUintUncheckedBounds(input, 0, bytes(input).length); } /** * @dev Variant of {parseHexUint-string-uint256-uint256} that returns false if the parsing fails because of an * invalid character. * * NOTE: This function will revert if the result does not fit in a `uint256`. */ function tryParseHexUint( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, uint256 value) { if (end > bytes(input).length || begin > end) return (false, 0); return _tryParseHexUintUncheckedBounds(input, begin, end); } /** * @dev Implementation of {tryParseHexUint} that does not check bounds. Caller should make sure that * `begin <= end <= input.length`. Other inputs would result in undefined behavior. */ function _tryParseHexUintUncheckedBounds( string memory input, uint256 begin, uint256 end ) private pure returns (bool success, uint256 value) { bytes memory buffer = bytes(input); // skip 0x prefix if present bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(buffer, begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty uint256 offset = hasPrefix.toUint() * 2; uint256 result = 0; for (uint256 i = begin + offset; i < end; ++i) { uint8 chr = _tryParseChr(bytes1(_unsafeReadBytesOffset(buffer, i))); if (chr > 15) return (false, 0); result *= 16; unchecked { // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check). // This guaratees that adding a value < 16 will not cause an overflow, hence the unchecked. result += chr; } } return (true, result); } /** * @dev Parse a hexadecimal string (with or without "0x" prefix), and returns the value as an `address`. * * Requirements: * - The string must be formatted as `(0x)?[0-9a-fA-F]{40}` */ function parseAddress(string memory input) internal pure returns (address) { return parseAddress(input, 0, bytes(input).length); } /** * @dev Variant of {parseAddress} that parses a substring of `input` located between position `begin` (included) and * `end` (excluded). * * Requirements: * - The substring must be formatted as `(0x)?[0-9a-fA-F]{40}` */ function parseAddress(string memory input, uint256 begin, uint256 end) internal pure returns (address) { (bool success, address value) = tryParseAddress(input, begin, end); if (!success) revert StringsInvalidAddressFormat(); return value; } /** * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly * formatted address. See {parseAddress} requirements. */ function tryParseAddress(string memory input) internal pure returns (bool success, address value) { return tryParseAddress(input, 0, bytes(input).length); } /** * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly * formatted address. See {parseAddress} requirements. */ function tryParseAddress( string memory input, uint256 begin, uint256 end ) internal pure returns (bool success, address value) { if (end > bytes(input).length || begin > end) return (false, address(0)); bool hasPrefix = (end > begin + 1) && bytes2(_unsafeReadBytesOffset(bytes(input), begin)) == bytes2("0x"); // don't do out-of-bound (possibly unsafe) read if sub-string is empty uint256 expectedLength = 40 + hasPrefix.toUint() * 2; // check that input is the correct length if (end - begin == expectedLength) { // length guarantees that this does not overflow, and value is at most type(uint160).max (bool s, uint256 v) = _tryParseHexUintUncheckedBounds(input, begin, end); return (s, address(uint160(v))); } else { return (false, address(0)); } } function _tryParseChr(bytes1 chr) private pure returns (uint8) { uint8 value = uint8(chr); // Try to parse `chr`: // - Case 1: [0-9] // - Case 2: [a-f] // - Case 3: [A-F] // - otherwise not supported unchecked { if (value > 47 && value < 58) value -= 48; else if (value > 96 && value < 103) value -= 87; else if (value > 64 && value < 71) value -= 55; else return type(uint8).max; } return value; } /** * @dev Reads a bytes32 from a bytes array without bounds checking. * * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the * assembly block as such would prevent some optimizations. */ function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) { // This is not memory safe in the general case, but all calls to this private function are within bounds. assembly ("memory-safe") { value := mload(add(buffer, add(0x20, offset))) } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "viaIR": true, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint256","name":"_maxSupply","type":"uint256"},{"internalType":"string","name":"_unrevealedSVG","type":"string"},{"internalType":"string","name":"_eliminatedSVG","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721IncorrectOwner","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721InsufficientApproval","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC721InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"ERC721InvalidOperator","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ERC721InvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC721InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC721InvalidSender","type":"error"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721NonexistentToken","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","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":false,"internalType":"uint256","name":"batchNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensRevealed","type":"uint256"}],"name":"BatchRevealCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"batchNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endIndex","type":"uint256"}],"name":"BatchRevealStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BonusClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"winners","type":"uint256[]"}],"name":"BonusWinnersSelected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"voidClass","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"eyeType","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"symmetryType","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"dimensionCount","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"distortionType","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"glitchIntensity","type":"uint8"}],"name":"FinalReveal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isActive","type":"bool"}],"name":"MintingToggled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"totalTokens","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"RevealCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"survivalTime","type":"uint256"}],"name":"TokenEliminated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRevealTime","type":"uint256"}],"name":"TokenFed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"TokenMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"winners","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"finalPool","type":"uint256"}],"name":"TournamentComplete","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"startTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalParticipants","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"initialPool","type":"uint256"}],"name":"TournamentStarted","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newRevealTime","type":"uint256"}],"name":"TransferCountUpdated","type":"event"},{"inputs":[],"name":"acoToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activeTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","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":"","type":"uint256"}],"name":"bonusWinners","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"checkAllRevealed","outputs":[{"internalType":"bool","name":"allRevealed","type":"bool"},{"internalType":"uint256[]","name":"unrevealedTokens","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"checkElimination","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"claimBonus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"claimPrize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentRevealBatch","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eliminateExpiredTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"feedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBonusWinners","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"getNextTokensToEliminate","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"eliminationTimes","type":"uint256[]"},{"internalType":"uint256","name":"currentTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getTokenData","outputs":[{"internalType":"uint256","name":"eliminationTime","type":"uint256"},{"internalType":"uint256","name":"transferCount","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isRevealed","type":"bool"},{"internalType":"uint256","name":"survivalTime","type":"uint256"},{"internalType":"uint8","name":"voidClass","type":"uint8"},{"internalType":"uint8","name":"eyeType","type":"uint8"},{"internalType":"uint8","name":"symmetryType","type":"uint8"},{"internalType":"uint8","name":"dimensionCount","type":"uint8"},{"internalType":"uint8","name":"distortionType","type":"uint8"},{"internalType":"uint8","name":"glitchIntensity","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokensReadyToEliminate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTournamentInfo","outputs":[{"internalType":"bool","name":"isComplete","type":"bool"},{"internalType":"uint256","name":"remainingTokens","type":"uint256"},{"internalType":"uint256","name":"currentPool","type":"uint256"},{"internalType":"uint256[]","name":"winners","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"hasBonusClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"hasClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"lastRevealedIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"lastThreeEliminatedTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxSurvivalTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintingComplete","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"batchSize","type":"uint256"}],"name":"revealBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"revealSingle","outputs":[],"stateMutability":"nonpayable","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":"nonpayable","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":"nonpayable","type":"function"},{"inputs":[],"name":"selectBonusWinners","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"string","name":"svgData","type":"string"}],"name":"setTokenSVG","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":[],"name":"toggleMinting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenData","outputs":[{"internalType":"uint256","name":"eliminationTime","type":"uint256"},{"internalType":"uint256","name":"transferCount","type":"uint256"},{"internalType":"bool","name":"isActive","type":"bool"},{"internalType":"bool","name":"isRevealed","type":"bool"},{"internalType":"uint256","name":"survivalTime","type":"uint256"},{"internalType":"uint8","name":"voidClass","type":"uint8"},{"internalType":"uint8","name":"eyeType","type":"uint8"},{"internalType":"uint8","name":"symmetryType","type":"uint8"},{"internalType":"uint8","name":"dimensionCount","type":"uint8"},{"internalType":"uint8","name":"distortionType","type":"uint8"},{"internalType":"uint8","name":"glitchIntensity","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"totalFeedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tournamentComplete","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tournamentStartTime","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":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"winningTokenIds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawAPE","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a06040523461082b5761616b803803806100198161086e565b92833981019060608183031261082b57805160208201519091906001600160401b03811161082b578361004d918301610893565b60408201519093906001600160401b03811161082b5761006d9201610893565b9060409061007a8261086e565b6004815263159bda5960e21b60208201526100948361086e565b60048152631593d25160e21b6020820152815190916001600160401b0382116105215760005490600182811c92168015610821575b60208310146105015781601f8493116107d3575b50602090601f831160011461076d57600092610762575b50508160011b916000199060031b1c1916176000555b8051906001600160401b0382116105215760015490600182811c92168015610758575b60208310146105015781601f849311610709575b50602090601f83116001146106a157600092610696575b50508160011b916000199060031b1c1916176001555b33156106805760068054336001600160a01b0319821681179092556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a373982eddc7cb6aa589050acbd3c6042864a91352ee608052815161014081016001600160401b03811182821017610521578352600a81526078602082015260c88382015260c860608201526032608082015260c860a0820152602860c082015260c860e082015260c8610100820152605061012082015260005b600a811061066b575050610243610830565b6103ac8152600a602082015260328382015260005b6003811061065657505061026a61084f565b610384815261032060208201526102bc8382015261025860608201526101f4608082015260005b60058110610641575050815160c081016001600160401b03811182821017610521578352610384815261032060208201526102bc8382015261025860608201526101f4608082015261019060a082015260005b6006811061062c5750506102f661084f565b6101f481526102ee60208201526103848382015261012c606082015261012c608082015260005b6005811061061757505061032f610830565b61038481526102bc60208201526101f48382015260005b6003811061060257505060315582516001600160401b03811161052157603554600181811c911680156105f8575b602082101461050157601f81116105a9575b506020601f82116001146105425781929394600092610537575b50508160011b916000199060031b1c1916176035555b81516001600160401b03811161052157603654600181811c91168015610517575b602082101461050157601f81116104a7575b50602092601f82116001146104425792819293600092610437575b50508160011b916000199060031b1c1916176036555b51615855908161091682396080518181816112d501526119900152f35b015190503880610404565b601f198216936036600052806000209160005b86811061048f5750836001959610610476575b505050811b0160365561041a565b015160001960f88460031b161c19169055388080610468565b91926020600181928685015181550194019201610455565b60366000526104f1907f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b8601f840160051c810191602085106104f7575b601f0160051c01906108fe565b386103e9565b90915081906104e4565b634e487b7160e01b600052602260045260246000fd5b90607f16906103d7565b634e487b7160e01b600052604160045260246000fd5b0151905038806103a0565b601f198216906035600052806000209160005b81811061059157509583600195969710610578575b505050811b016035556103b6565b015160001960f88460031b161c1916905538808061056a565b9192602060018192868b015181550194019201610555565b60356000526105f2907fcfa4bec1d3298408bb5afcfcd9c430549c5b31f8aa5c5848151c0a55f473c34d601f840160051c810191602085106104f757601f0160051c01906108fe565b38610386565b90607f1690610374565b60019060208351930192816024015501610346565b6001906020835193019281601f01550161031d565b600190602083519301928160190155016102e4565b60019060208351930192816014015501610291565b60019060208351930192816011015501610258565b60019060208351930192816007015501610231565b631e4fbdf760e01b600052600060045260246000fd5b015190503880610158565b600160009081528281209350601f198516905b8181106106f157509084600195949392106106d8575b505050811b0160015561016e565b015160001960f88460031b161c191690553880806106ca565b929360206001819287860151815501950193016106b4565b6001600052610752907fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6601f850160051c810191602086106104f757601f0160051c01906108fe565b38610141565b91607f169161012d565b0151905038806100f4565b60008080528281209350601f198516905b8181106107bb57509084600195949392106107a2575b505050811b0160005561010a565b015160001960f88460031b161c19169055388080610794565b9293602060018192878601518155019501930161077e565b6000805261081b907f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563601f850160051c810191602086106104f757601f0160051c01906108fe565b386100dd565b91607f16916100c9565b600080fd5b60405190606082016001600160401b0381118382101761052157604052565b6040519060a082016001600160401b0381118382101761052157604052565b6040519190601f01601f191682016001600160401b0381118382101761052157604052565b81601f8201121561082b578051906001600160401b038211610521576108c2601f8301601f191660200161086e565b928284526020838301011161082b5760005b8281106108e957505060206000918301015290565b806020809284010151828287010152016108d4565b818110610909575050565b600081556001016108fe56fe6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806301ffc9a71461037b57806306fdde0314610376578063081812fc14610371578063095ea7b31461036c5780630e9242b114610367578063140719851461036257806318160ddd1461035d57806322604a461461035857806323b872dd1461035357806325fd90f31461034e57806342842e0e14610349578063560cdbc21461034457806358a5b0f61461033f5780636352211e1461033a5780636b80ae171461033557806370a0823114610330578063715018a61461032b578063741c0a091461032657806374689fdf1461032157806378f3af531461031c5780637d55094d146103175780638da5cb5b1461031257806395d89b411461030d57806395f0e45c1461030857806396365d4414610303578063a0712d68146102fe578063a22cb465146102f9578063a58bd127146102f4578063ac8de2b0146102ef578063b09afec1146102ea578063b3c8ee1f146102e5578063b4b5b48f146102e0578063b88d4fde146102db578063b99adbe1146102d6578063c1e99063146102d1578063c47ef875146102cc578063c87b56dd146102c7578063ca9b648b146102c2578063cb6cd4ca146102bd578063ce516507146102b8578063d23e57d2146102b3578063d5abeb01146102ae578063d7098154146102a9578063d7a9dc6b146102a4578063d829055e1461029f578063d91930251461029a578063e985e9c514610295578063f0368dfa14610290578063f2fde38b1461028b578063f4f3b20014610286578063f4fcab7d14610281578063f64c3f0a1461027c578063f88a8f36146102775763fec173d80361000e576123f9565b61236b565b61216e565b612150565b612041565b611fb7565b611f58565b611efb565b611df7565b611d63565b611d45565b611baf565b611b91565b611a0e565b6119dd565b6119bf565b61197a565b611947565b611929565b61181e565b61179f565b611716565b6115df565b61155b565b6114a1565b61124b565b611225565b61116c565b610f37565b610f19565b610ec8565b610e1f565b610df6565b610d8b565b610d5a565b610d34565b610cc6565b610c69565b610c13565b610be7565b610bb7565b610b99565b610b48565b610a13565b6109f0565b6109d9565b6108d3565b6108b5565b61071f565b6106e7565b6105a5565b61053b565b610461565b610397565b6001600160e01b031981160361039257565b600080fd5b346103925760203660031901126103925760206004356103b681610380565b63ffffffff60e01b166380ac58cd60e01b81149081156103f4575b81156103e3575b506040519015158152f35b6301ffc9a760e01b149050386103d8565b635b5e139f60e01b811491506103d1565b60005b8381106104185750506000910152565b8181015183820152602001610408565b9060209161044181518092818552858086019101610405565b601f01601f1916010190565b90602061045e928181520190610428565b90565b3461039257600036600319011261039257604051600080546104828161258b565b808452906001811690811561051757506001146104ba575b6104b6836104aa818503826116ba565b6040519182918261044d565b0390f35b60008080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563939250905b8082106104fd575090915081016020016104aa61049a565b9192600181602092548385880101520191019092916104e5565b60ff191660208086019190915291151560051b840190910191506104aa905061049a565b346103925760203660031901126103925760043561055881613961565b506000526004602052602060018060a01b0360406000205416604051908152f35b600435906001600160a01b038216820361039257565b602435906001600160a01b038216820361039257565b34610392576040366003190112610392576105be610579565b602435906105cb82613961565b331515806106a0575b8061065e575b610649576100199261062a9181906001600160a01b0385811691167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a46000526004602052604060002090565b80546001600160a01b0319166001600160a01b03909216919091179055565b63a9fbf51f60e01b6000523360045260246000fd5b5060ff610698336106818460018060a01b03166000526005602052604060002090565b9060018060a01b0316600052602052604060002090565b5416156105da565b506001600160a01b0381163314156105d4565b906020808351928381520192019060005b8181106106d15750505090565b82518452602093840193909201916001016106c4565b3461039257600036600319011261039257610700612779565b906104b6604051928392151583526040602084015260408301906106b3565b346103925760003660031901126103925761076461075f61075b60325461075261074d8260ff9060081c1690565b612873565b60101c60ff1690565b1590565b6128b6565b60315460001990600090815b818110610842575050805b603154811080610838575b1561082d5761079f81600052602f602052604060002090565b836002820154916107b08360ff1690565b9283610815575b508261080a575b50506107d3575b6107ce906126c9565b61077b565b906107e6906107e1836139f1565b6126c9565b906107f760325460ff9060101c1690565b156107c5575061001991505b15156128f8565b5414905083386107be565b9092506108269060081c60ff161590565b91386107b7565b506100199150610803565b5060198210610786565b61085681600052602f602052604060002090565b600281015460ff811690816108a0575b5080610895575b8061088b575b610881575b50600101610770565b5493506001610878565b5084815410610873565b50805442101561086d565b6108af915060081c60ff161590565b38610866565b34610392576000366003190112610392576020603054604051908152f35b34610392576000366003190112610392576108fe60325460ff8160081c16908161098a575b5061293b565b600080603154905b81811061091857604051838152602090f35b61092c81600052602f602052604060002090565b60028101549060ff82169182610972575b5081610966575b50610952575b600101610906565b9161095e6001916126c9565b92905061094a565b90505442101538610944565b9091506109839060081c60ff161590565b903861093d565b610999915060101c60ff161590565b386108f8565b6060906003190112610392576004356001600160a01b038116810361039257906024356001600160a01b0381168103610392579060443590565b34610392576100196109ea3661099f565b9161297f565b3461039257600036600319011261039257602060ff603254166040519015158152f35b3461039257610019610a243661099f565b9060405192610a346020856116ba565b6000845261302f565b634e487b7160e01b600052603260045260246000fd5b603f54811015610a6e57603f60005260206000200190600090565b610a3d565b603d5415610a6e57603d60009081527fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc391565b603d5460011015610a6e57603d60009081527fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc491565b603d5460021015610a6e57603d60009081527fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc591565b604354811015610a6e57604360005260206000200190600090565b603e54811015610a6e57603e60005260206000200190600090565b3461039257602036600319011261039257600435603d5481101561039257602090603d6000527fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc30154604051908152f35b34610392576000366003190112610392576020603b54604051908152f35b34610392576020366003190112610392576020610bd5600435613961565b6040516001600160a01b039091168152f35b346103925760203660031901126103925760043560005260426020526020604060002054604051908152f35b34610392576020366003190112610392576001600160a01b03610c34610579565b168015610c535760005260036020526020604060002054604051908152f35b6322718ad960e21b600052600060045260246000fd5b3461039257600036600319011261039257610c82613ab3565b600680546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610392576000366003190112610392576040516043548082526020820190604360005260206000209060005b818110610d1e576104b685610d0a818703826116ba565b6040519182916020835260208301906106b3565b8254845260209093019260019283019201610cf3565b3461039257600036600319011261039257602060ff60325460081c166040519015158152f35b3461039257602036600319011261039257600435600052603a602052602060ff604060002054166040519015158152f35b3461039257600036600319011261039257610da4613ab3565b7f6bdfe227d5db299c59aa56d5f846f40dbd73b271aaa78e18ed74fc3e00b8aa6b6020603254610dda60ff8260081c1615612ae2565b60ff8082161516809160ff1916176032556040519015158152a1005b34610392576000366003190112610392576006546040516001600160a01b039091168152602090f35b34610392576000366003190112610392576040516000600154610e418161258b565b80845290600181169081156105175750600114610e68576104b6836104aa818503826116ba565b91905060016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6916000905b808210610eae575090915081016020016104aa61049a565b919260018160209254838588010152019101909291610e96565b3461039257602036600319011261039257600435603e5481101561039257602090603e6000527f8d800d6614d35eed73733ee453164a3b48076eb3138f466adeeb9dec7bb31f700154604051908152f35b34610392576000366003190112610392576020603354604051908152f35b602036600319011261039257600435610f72610f6d61075b603254610f64610f5f8260ff1690565b612b21565b60081c60ff1690565b612ae2565b80151580611157575b610f8490612b62565b610f9d610f9382603054612bda565b6031541015612be7565b610fb0610fa982612c27565b3414612cb6565b610fc4610fbf34603354612bda565b603355565b60005b8181106110765760305460315414610fdb57005b610fef61010060325461ff00191617603255565b610ff842603b55565b60005b60315481101561102c5760019061101142612b9f565b61102582600052602f602052604060002090565b5501610ffb565b50603b54603154603354604080519384526020840192909252908201527f2b4fbc018be75e6ff98b219698828856ce311122193b11596150e17268e2ee319080606081015b0390a1005b60019060305461108d611088826126c9565b603055565b6110978133613adc565b6111076110a26116dc565b60008082526020820152600160408201526000606082015260006080820152600060a0820152600060c0820152600060e082015260006101008201526000610120820152600061014082015261110283600052602f602052604060002090565b612cfd565b61111a6111156034546126c9565b603455565b604051678ac7230489e8000081523391907f2d03118aa776f7008445f6ca8490a6782ede2db364d741513555ba656ab1879f90602090a301610fc7565b506005811115610f7b565b8015150361039257565b3461039257604036600319011261039257611185610579565b60243561119181611162565b6001600160a01b03821691821561121057816111cf6111e09233600052600560205260406000209060018060a01b0316600052602052604060002090565b9060ff801983541691151516179055565b60405190151581527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b82630b61174360e31b60005260045260246000fd5b3461039257600036600319011261039257602060ff60325460101c166040519015158152f35b34610392576040366003190112610392576004356024359061127781600052602f602052604060002090565b61128d611288600283015460ff1690565b612e5d565b60325461129f9060081c60ff16612873565b6112ab81544210612e9c565b6040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692906020816064816000885af1801561140f5761131a91600091611414575b50612efe565b60405163a9059cbb60e01b815261dead60048201526024810185905292602090849060449082906000905af191821561140f577f4f339848d3f9c12eee86898233737164ce0b93d22d4e89bb33b314c21933fc416113c383926113de966113d6966113e2575b5080546113a661139d6005670de0b6b3a76400008c040483612bda565b91821015612f42565b815554604051918291898360209093929193604081019481520152565b0390a26000526042602052604060002090565b918254612bda565b9055005b6114039060203d602011611408575b6113fb81836116ba565b810190612edd565b611380565b503d6113f1565b612ef2565b61142d915060203d602011611408576113fb81836116ba565b38611314565b98969492909b9a99979593916101608a019c8a5260208a01521515604089015215156060880152608087015260ff1660a086015260ff1660c085015260ff1660e084015260ff1661010083015261012082016114909160ff169052565b6101400161149f9160ff169052565b565b34610392576020366003190112610392576004356000818152600260205260409020546114d8906001600160a01b03161515612f7e565b600052602f60205260ff60406000206104b68154916001810154906002810154936115078560ff9060081c1690565b600460038401549301549261151c8460ff1690565b600885901c60ff1691601086901c60ff1693601887901c60ff169561154c602089901c60ff169860281c60ff1690565b986040519c8d9c16918c611433565b3461039257600036600319011261039257611574613ab3565b4780156115a55760065461001991600091829182918291906001600160a01b03165af161159f612fc1565b50612ff1565b60405162461bcd60e51b81526020600482015260126024820152714e6f2041504520746f20776974686472617760701b6044820152606490fd5b3461039257602036600319011261039257600435600052602f60205260406000208054906104b6600182015492600283015490600460038501549401549161162b8360ff9060201c1690565b91602884901c60ff169360405197889760ff8360181c169460ff8460101c169460ff808660081c1695169360ff808460081c169316918c611433565b634e487b7160e01b600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761169957604052565b611667565b60a0810190811067ffffffffffffffff82111761169957604052565b90601f8019910116810190811067ffffffffffffffff82111761169957604052565b6040519061149f610160836116ba565b9061149f60405192836116ba565b67ffffffffffffffff811161169957601f01601f191660200190565b346103925760803660031901126103925761172f610579565b61173761058f565b906044356064359267ffffffffffffffff8411610392573660238501121561039257836004013592611768846116fa565b9361177660405195866116ba565b80855236602482880101116103925760208160009260246100199901838901378601015261302f565b34610392576020366003190112610392576004356043548110156103925760209060436000527f9690ad99d6ce244efa8a0f6c2d04036d3b33a9474db32a71b71135c6951027930154604051908152f35b9392916118199061180b6040936060885260608801906106b3565b9086820360208801526106b3565b930152565b34610392576020366003190112610392576004356118526032546118468160ff9060081c1690565b908161098a575061293b565b61185f6064821115613130565b61186881612733565b9061187281612733565b600090600092603154935b84811080611920575b156119065761189f81600052602f602052604060002090565b600281015460ff811690816118f1575b506118c4575b506118bf906126c9565b61187d565b846118ea91836118d86118bf95988b612765565b52546118e48287612765565b526126c9565b93906118b5565b611900915060081c60ff161590565b386118af565b5050915080835281526104b66040519283924291846117f0565b50818410611886565b34610392576000366003190112610392576020603454604051908152f35b34610392576020366003190112610392576104b6611966600435613216565b604051918291602083526020830190610428565b34610392576000366003190112610392576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b34610392576000366003190112610392576020603c54604051908152f35b34610392576020366003190112610392576004356000526039602052602060ff604060002054166040519015158152f35b3461039257602036600319011261039257600435611a2a613ab3565b611a3b60ff60325460101c16612667565b60315480821015611b5c576004611a90611a86611a81611a7c867f6de67c5b73a0eead4c2c2bf2df73dc1e32f68a73330221df4135e757e7d8f6399661329c565b61327e565b610a53565b90549060031b1c90565b92611ae0611aa885600052602f602052604060002090565b91611ad16002840191611acb611ac661075b855460ff9060081c1690565b6132a9565b846144a5565b805461ff001916610100179055565b015460ff8116611b57600883901c60ff165b92601081901c60ff1690601881901c60ff16611b19602083901c60ff169260281c60ff1690565b92604051968796879460ff60a0958180968180969c9b978160c08d019e168c521660208b015216604089015216606087015216608085015216910152565b0390a2005b60405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b6044820152606490fd5b34610392576000366003190112610392576020603154604051908152f35b3461039257602036600319011261039257600435603254611bd59060101c60ff16612667565b611bf1611be182613961565b6001600160a01b031633146132ee565b611c1a611c1561075b611c0e846000526039602052604060002090565b5460ff1690565b61332c565b611c25611a86610a73565b81148015611d32575b8015611d1a575b611c3e90613370565b611c62611c55826000526039602052604060002090565b805460ff19166001179055565b600090611c70611a86610a73565b8103611cab5750506100196000808080611c95611c8e603354612c72565b6064900490565b611ca08115156133b1565b335af161159f612fc1565b611cb6611a86610aa6565b8103611cd95750506100196000808080611cd4611c8e603354612c5c565b611c95565b611ce4611a86610adc565b14611cf8575b600080808061001994611c95565b506100196000808080611d0f611c8e603354612c46565b945050505050611cea565b50611c3e611d29611a86610adc565b82149050611c35565b50611d3e611a86610aa6565b8114611c2e565b34610392576000366003190112610392576020604054604051908152f35b346103925760003660031901126103925760ff60325460101c166034549060335460405190603d548083526020830190603d60005260206000209060005b818110611de15750505090611dbc836104b6949303836116ba565b60405194859415158552602085015260408401526080606084015260808301906106b3565b8254845260209093019260019283019201611da1565b3461039257602036600319011261039257600435611e19600a604354146133f1565b611e25611be182613961565b611e47611e4261075b611c0e84600052603a602052604060002090565b61343d565b60009060005b600a8110611ed4575b50611e817f69dfeac86fe2e01b0c84ade0a933302dfd88a748855d332f74c26de31c475d279261347b565b611e98611c5582600052603a602052604060002090565b611ea6611c8e603354612c88565b90611ebb600080808086335af161159f612fc1565b6040805191825260208201929092529081908101611071565b81611ee1611a8683610b12565b14611eee57600101611e4d565b5060019150611e81611e56565b3461039257604036600319011261039257602060ff611f4c611f1b610579565b611f2361058f565b6001600160a01b0391821660009081526005865260408082209290931681526020919091522090565b54166040519015158152f35b346103925760403660031901126103925760243560043567ffffffffffffffff821161039257366023830112156103925781600401359067ffffffffffffffff82116103925736602483850101116103925760246100199301906134c7565b3461039257602036600319011261039257611fd0610579565b611fd8613ab3565b6001600160a01b0316801561202b57600680546001600160a01b0319811683179091556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b631e4fbdf760e01b600052600060045260246000fd5b346103925760203660031901126103925761205a610579565b612062613ab3565b6040516370a0823160e01b81523060048201526001600160a01b039190911690602081602481855afa801561140f576120e792602092600092612121575b506120ac8215156136f8565b60065460405163a9059cbb60e01b81526001600160a01b03909116600482015260248101929092529092839190829060009082906044820190565b03925af1801561140f57610019916000916121025750612ff1565b61211b915060203d602011611408576113fb81836116ba565b3861159f565b612142919250833d8511612149575b61213a81836116ba565b8101906136e9565b90386120a0565b503d612130565b34610392576000366003190112610392576020604154604051908152f35b346103925760203660031901126103925760043561218a613ab3565b60325461219c9060101c60ff16612667565b80151580612360575b6121ae9061373c565b6121bb6040549182612bda565b90603154808311612358575b603c54604080519182526020820184905281018490527f6b721a1ca1f979ab7c31f3356629da6eafc64b18f824a7b58e0f79a3389aeb5990606090a16000919003600019015b603154918383038210158061234f575b156122b4577f6de67c5b73a0eead4c2c2bf2df73dc1e32f68a73330221df4135e757e7d8f63960046001612253611a8686610a53565b9361227961226b86600052602f602052604060002090565b9787900360001901886144a5565b60028701805461ff001916610100179055019401546122988160ff1690565b6122a8600883901c60ff16611af2565b0390a26000190161220d565b7fd2f0d1ea4e5b39d0b3762648a29fa2b8012f2b7db2c8906dafae86eec125cae5906122df85604055565b6122f36122ee603c5460010190565b603c55565b603c54604080519182526020820192909252a16040546031548091101561231657005b604080519182524260208301527fecd55f300557b93401c39e249ff8ea87c46796fd2b94d38cfcf819077501898c919081908101611071565b5082821061221d565b9150816121c7565b5060198111156121a5565b346103925760203660031901126103925760043580600052602f602052604060002060ff6032546123a0828260081c16612873565b60101c166123bb57544210156123b257005b610019906139f1565b60405162461bcd60e51b8152602060048201526016602482015275546f75726e616d656e7420697320636f6d706c65746560501b6044820152606490fd5b3461039257600036600319011261039257612412613ab3565b6032546124249060101c60ff1661377d565b612430604354156137c9565b60315461243c81612733565b9060009060005b818110612542575050604051602081019061247c8161246e4442869091604092825260208201520190565b03601f1981018352826116ba565b519020916000925b600a84106124ba577f9e0f277eb74eb2d772adf5fad2c9dbb64a77ee6144274b06cb3b1b573cee7ff46040518061107181613950565b6040805160208101928352908101859052600191906124dc816060810161246e565b519020936124fc6124f66124f0838761329c565b87613815565b82612bda565b6125276125098386612765565b51916125158187612765565b516125208588612765565b5285612765565b5261253b6125358285612765565b51613835565b0192612484565b69152d02c7e14af6800000612561826000526042602052604060002090565b541015612571575b600101612443565b9161258381846118e460019488612765565b929050612569565b90600182811c921680156125bb575b60208310146125a557565b634e487b7160e01b600052602260045260246000fd5b91607f169161259a565b90604051918260008254926125d98461258b565b808452936001811690811561264557506001146125fe575b5061149f925003836116ba565b90506000929192526020600020906000915b81831061262957505090602061149f92820101386125f1565b6020919350806001915483858901015201910190918492612610565b90506020925061149f94915060ff191682840152151560051b820101386125f1565b1561266e57565b60405162461bcd60e51b815260206004820152601760248201527f546f75726e616d656e74206e6f7420636f6d706c6574650000000000000000006044820152606490fd5b634e487b7160e01b600052601160045260246000fd5b60001981146126d85760010190565b6126b3565b67ffffffffffffffff81116116995760051b60200190565b604051906127046020836116ba565b6000808352366020840137565b6040516080919061272283826116ba565b6003815291601f1901366020840137565b9061273d826126dd565b61274a60405191826116ba565b828152809261275b601f19916126dd565b0190602036910137565b8051821015610a6e5760209160051b010190565b60325461278b9060101c60ff16612667565b603154906000805b83811061282b5750801561281b576127aa90612733565b916000805b8281106127bf5750505060009190565b806127ce611a86600193610a53565b6127f561075b60026127ea84600052602f602052604060002090565b015460081c60ff1690565b612801575b50016127af565b61281461280d856126c9565b9488612765565b52386127fa565b5090506128266126f5565b600191565b61285261075b60026127ea612842611a8686610a53565b600052602f602052604060002090565b61285f575b600101612793565b9061286b6001916126c9565b919050612857565b1561287a57565b60405162461bcd60e51b81526020600482015260146024820152734d696e74696e67206e6f7420636f6d706c65746560601b6044820152606490fd5b156128bd57565b60405162461bcd60e51b8152602060048201526013602482015272546f75726e616d656e7420636f6d706c65746560681b6044820152606490fd5b156128ff57565b60405162461bcd60e51b8152602060048201526014602482015273139bc81d1bdad95b9cc8195b1a5b5a5b985d195960621b6044820152606490fd5b1561294257565b60405162461bcd60e51b8152602060048201526015602482015274546f75726e616d656e74206e6f742061637469766560581b6044820152606490fd5b91906001600160a01b03811615612ab75761299c908233916147f1565b6001600160a01b038116929083151580612aaf575b6129e6575b506001600160a01b03168083036129cc57505050565b6364283d7b60e01b60005260045260245260445260646000fd5b6129fa83600052602f602052604060002090565b600281018054612a0e9060081c60ff161590565b612a1a575b50506129b6565b600a60018301612a2a81546126c9565b90819055835460408051838152602081019290925288917fcfc3cbe6ddd550af78e9426b09c1e0841fd5bbfd4f36c74cfefad75b915e45239190a2101580612aa4575b15612a84575050612a7d836139f1565b3880612a13565b5460ff16612a93575b50612a7d565b612a9c42612baf565b905538612a8d565b50805460ff16612a6d565b5060016129b1565b633250574960e11b600052600060045260246000fd5b60405190612adc6020836116ba565b60008252565b15612ae957565b60405162461bcd60e51b815260206004820152601060248201526f4d696e74696e6720636f6d706c65746560801b6044820152606490fd5b15612b2857565b60405162461bcd60e51b81526020600482015260126024820152714d696e74206973206e6f742061637469766560701b6044820152606490fd5b15612b6957565b60405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b6044820152606490fd5b906201518082018092116126d857565b90611c2082018092116126d857565b60300190816030116126d857565b90600282018092116126d857565b919082018092116126d857565b15612bee57565b60405162461bcd60e51b8152602060048201526011602482015270457863656564206d617820737570706c7960781b6044820152606490fd5b9081678ac7230489e800000291678ac7230489e800008304036126d857565b90600a820291808304600a14901517156126d857565b906014820291808304601414901517156126d857565b906032820291808304603214901517156126d857565b908160011b91808304600214901517156126d857565b600281901b91906001600160fe1b038116036126d857565b15612cbd57565b60405162461bcd60e51b8152602060048201526014602482015273125b98dbdc9c9958dd0810541148185b5bdd5b9d60621b6044820152606490fd5b9055565b90612e40610140600461149f948451815560208501516001820155612d5c60028201612d41612d2f6040890151151590565b829060ff801983541691151516179055565b6060870151815461ff00191690151560081b61ff0016179055565b608085015160038201550192612d89612d7960a083015160ff1690565b855460ff191660ff909116178555565b612db5612d9a60c083015160ff1690565b858054909161ff001990911660089190911b61ff0016179055565b612dde612dc660e083015160ff1690565b855462ff0000191660109190911b62ff000016178555565b612e0a612df061010083015160ff1690565b855463ff000000191660189190911b63ff00000016178555565b612e38612e1c61012083015160ff1690565b855464ff00000000191660209190911b64ff0000000016178555565b015160ff1690565b65ff000000000082549160281b169065ff00000000001916179055565b15612e6457565b60405162461bcd60e51b815260206004820152601060248201526f546f6b656e206e6f742061637469766560801b6044820152606490fd5b15612ea357565b60405162461bcd60e51b8152602060048201526012602482015271151bdad95b881d1a5b5948195e1c1a5c995960721b6044820152606490fd5b90816020910312610392575161045e81611162565b6040513d6000823e3d90fd5b15612f0557565b60405162461bcd60e51b8152602060048201526015602482015274151bdad95b881d1c985b9cd9995c8819985a5b1959605a1b6044820152606490fd5b15612f4957565b60405162461bcd60e51b815260206004820152600d60248201526c54696d65206f766572666c6f7760981b6044820152606490fd5b15612f8557565b60405162461bcd60e51b8152602060048201526014602482015273151bdad95b88191bd95cc81b9bdd08195e1a5cdd60621b6044820152606490fd5b3d15612fec573d90612fd2826116fa565b91612fe060405193846116ba565b82523d6000602084013e565b606090565b15612ff857565b60405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b90929161303d81858461297f565b833b61304a575b50505050565b60209161306c6040519485938493630a85bd0160e11b85523360048601613c1a565b038160006001600160a01b0387165af1600091816130ff575b506130c15750613093612fc1565b80519190826130ba57633250574960e11b6000526001600160a01b03821660045260246000fd5b9050602001fd5b6001600160e01b03191663757a42ff60e11b016130e2575038808080613044565b633250574960e11b6000526001600160a01b031660045260246000fd5b61312291925060203d602011613129575b61311a81836116ba565b810190613c05565b9038613085565b503d613110565b1561313757565b60405162461bcd60e51b815260206004820152600e60248201526d098d2dad2e840e8dede40d0d2ced60931b6044820152606490fd5b9061149f61320b600461317e6116dc565b9480548652600181015460208701526131b76131ae6002830154610f646131a58260ff1690565b151560408b0152565b15156060880152565b60038101546080870152015460ff811660a086015260ff600882901c1660c086015260ff601082901c1660e086015260ff601882901c1661010086015260ff602082901c1661012086015260281c60ff1690565b60ff16610140840152565b600081815260026020526040902054613239906001600160a01b03161515612f7e565b80600052602f60205261324f604060002061316d565b606081015115613263575061045e90614138565b60400151156132755761045e90613ecf565b61045e90613d62565b6000198101919082116126d857565b6001198101919082116126d857565b919082039182116126d857565b156132b057565b60405162461bcd60e51b8152602060048201526016602482015275151bdad95b88185b1c9958591e481c995d99585b195960521b6044820152606490fd5b156132f557565b60405162461bcd60e51b815260206004820152600f60248201526e2737ba103a37b5b2b71037bbb732b960891b6044820152606490fd5b1561333357565b60405162461bcd60e51b8152602060048201526015602482015274141c9a5e9948185b1c9958591e4818db185a5b5959605a1b6044820152606490fd5b1561337757565b60405162461bcd60e51b81526020600482015260126024820152712a37b5b2b7103737ba1030903bb4b73732b960711b6044820152606490fd5b156133b857565b60405162461bcd60e51b81526020600482015260116024820152704e6f207072697a6520746f20636c61696d60781b6044820152606490fd5b156133f857565b60405162461bcd60e51b815260206004820152601e60248201527f426f6e75732077696e6e657273206e6f742073656c65637465642079657400006044820152606490fd5b1561344457565b60405162461bcd60e51b815260206004820152600f60248201526e105b1c9958591e4818db185a5b5959608a1b6044820152606490fd5b1561348257565b60405162461bcd60e51b815260206004820152601860248201527f546f6b656e206e6f74206120626f6e75732077696e6e657200000000000000006044820152606490fd5b9190916134d2613ab3565b80600052602f60205260ff60026040600020015460081c161561354a5761353a611c559261149f9461352161351c60ff613516876000526038602052604060002090565b54161590565b613584565b613535846000526037602052604060002090565b61361e565b6000526038602052604060002090565b60405162461bcd60e51b8152602060048201526012602482015271151bdad95b881b9bdd081c995d99585b195960721b6044820152606490fd5b1561358b57565b60405162461bcd60e51b815260206004820152600f60248201526e14d591c8185b1c9958591e481cd95d608a1b6044820152606490fd5b8181106135cd575050565b600081556001016135c2565b9190601f81116135e857505050565b61149f926000526020600020906020601f840160051c83019310613614575b601f0160051c01906135c2565b9091508190613607565b90929167ffffffffffffffff8111611699576136448161363e845461258b565b846135d9565b6000601f8211600114613681578190612cf9939495600092613676575b50508160011b916000199060031b1c19161790565b013590503880613661565b601f1982169461369684600052602060002090565b91805b8781106136d15750836001959697106136b7575b505050811b019055565b0135600019600384901b60f8161c191690553880806136ad565b90926020600181928686013581550194019101613699565b90816020910312610392575190565b156136ff57565b60405162461bcd60e51b81526020600482015260156024820152744e6f20746f6b656e7320746f20776974686472617760581b6044820152606490fd5b1561374357565b60405162461bcd60e51b8152602060048201526012602482015271496e76616c69642062617463682073697a6560701b6044820152606490fd5b1561378457565b60405162461bcd60e51b815260206004820152601b60248201527f546f75726e616d656e74206e6f7420636f6d706c6574652079657400000000006044820152606490fd5b156137d057565b60405162461bcd60e51b815260206004820152601e60248201527f426f6e75732077696e6e65727320616c72656164792073656c656374656400006044820152606490fd5b811561381f570690565b634e487b7160e01b600052601260045260246000fd5b604354600160401b81101561169957600181016043556000604354821015610a6e57604390527f9690ad99d6ce244efa8a0f6c2d04036d3b33a9474db32a71b71135c6951027930155565b603f54600160401b8110156116995760018101603f556000603f54821015610a6e57603f90527fc03004e3ce0784bf68186394306849f9b7b1200073105cd9aeb554a1802b58fd0155565b603e54600160401b8110156116995760018101603e556000603e54821015610a6e57603e90527f8d800d6614d35eed73733ee453164a3b48076eb3138f466adeeb9dec7bb31f700155565b906020825491828152019160005260206000209060005b81811061393a5750505090565b825484526020909301926001928301920161392d565b602061045e91818152016043613916565b6000818152600260205260409020546001600160a01b0316908115613984575090565b637e27328960e01b60005260045260246000fd5b1561399f57565b60405162461bcd60e51b815260206004820152601860248201527f546f6b656e20616c726561647920656c696d696e6174656400000000000000006044820152606490fd5b80156126d8576000190190565b80600052602f6020527fff7eb81bed4ae9152c79e95c8651e3e2b6d9575e7226d09e22648afe709ac970613a8e6040600020613a4760028201613a3d613a38825460ff1690565b613998565b805460ff19169055565b6003613a55603b544261329c565b9101908155613a686111156034546139e4565b613a7184613880565b60036034541115613aa5575b546040519081529081906020820190565b0390a2600160345414613a9d57565b61149f61468a565b613aae846138cb565b613a7d565b6006546001600160a01b03163303613ac757565b63118cdaa760e01b6000523360045260246000fd5b6001600160a01b03811615612ab757600082613af7926147f1565b6001600160a01b0381161515918280613bfd575b613b2e575b5050613b1857565b6339e3563760e11b600052600060045260246000fd5b613b4281600052602f602052604060002090565b9060028201613b5961075b825460ff9060081c1690565b613b65575b5050613b10565b600a60018401613b7581546126c9565b90819055845460408051838152602081019290925285917fcfc3cbe6ddd550af78e9426b09c1e0841fd5bbfd4f36c74cfefad75b915e45239190a2101580613bf2575b15613bd05750613bc891506139f1565b388080613b5e565b5460ff169050613be1575b50613bc8565b613bea42612baf565b905538613bdb565b50805460ff16613bb8565b506001613b0b565b90816020910312610392575161045e81610380565b6001600160a01b03918216815291166020820152604081019190915260806060820181905261045e92910190610428565b90613c5e60209282815194859201610405565b0190565b60365460009291613c728261258b565b9160018116908115613cd95750600114613c8a575050565b6036600090815292935090917f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b85b838210613cc55750500190565b600181602092548486015201910190613cb8565b60ff1916825250811515909102019150565b60355460009291613cfb8261258b565b9160018116908115613cd95750600114613d13575050565b6035600090815292935090917fcfa4bec1d3298408bb5afcfcd9c430549c5b31f8aa5c5848151c0a55f473c34d5b838210613d4e5750500190565b600181602092548486015201910190613d41565b61045e613e99605d613e94613d7961246e956149dd565b61246e613e86613e81613e6b613e5c613e1c6040519889976f7b226e616d65223a2022566f6964202360801b60208a0152613dbe81518092602060308d019101610405565b7f222c20226465736372697074696f6e223a20225468697320766f6964206861736030918a01918201526c01031b7b63630b839b2b211161609d1b60508201526e2261747472696275746573223a205b60881b9101908152600f0190565b7f7b2274726169745f74797065223a2022537461747573222c202276616c75652281526d3a2022436f6c6c6170736564227d60901b6020820152602e0190565b6202e96160ed1b815260030190565b691134b6b0b3b2911d101160b11b8152600a0190565b613c62565b61227d60f01b815260020190565b614a95565b6040517f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000006020820152928391603d830190613c4b565b80600052602f602052604060002090613ee66116dc565b9180548352600181015460208401526002810154613f048160ff1690565b1515604085015260ff600891821c8116151560608601526003830154608086015260049092015480831660a08601529081901c821660c0850152601081901c821660e0850152601881901c8216610100850152602081901c821661012085015260281c16610140830152613f77906149dd565b9051613f82906149dd565b6040516f7b226e616d65223a2022566f6964202360801b60208201529182919060308301613faf91613c4b565b7f222c20226465736372697074696f6e223a20224120766f696420656e7469747981527f206669676874696e6720666f7220737572766976616c222c200000000000000060208201526039016e2261747472696275746573223a205b60881b8152600f017f7b2274726169745f74797065223a2022537461747573222c202276616c75652281526f01d101129bab93b34bb34b733913e96160851b60208201526030017f7b2274726169745f74797065223a2022566f696420436f6c6c61707365222c20815269113b30b63ab2911d101160b11b6020820152602a0161409491613c4b565b61227d60f01b81526002016202e96160ed1b8152600301691134b6b0b3b2911d101160b11b8152600a016140c790613ceb565b61227d60f01b815260020103601f19810182526140e490826116ba565b6140ed90614a95565b6040517f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000006020820152908190603d820161412691613c4b565b03601f198101825261045e90826116ba565b61414c81600052602f602052604060002090565b6141559061316d565b614169826000526037602052604060002090565b614172906125c5565b9161417c906149dd565b9060a081015161418c9060ff1690565b61419590614c80565b9260c08201516141a59060ff1690565b6141ae90614d33565b9160e08101516141be9060ff1690565b6141c790614e1a565b61010082015160ff166141d990614f6d565b906101208301516141ea9060ff1690565b6141f390614ff7565b6101409093015160ff1661420690615071565b9361421090614a95565b6040516f7b226e616d65223a2022566f6964202360801b60208201529788979196916030890161423f91613c4b565b7f222c20226465736372697074696f6e223a202241207472616e7363656e64656481526e0103b37b4b21032b73a34ba3c91161608d1b6020820152602f016e2261747472696275746573223a205b60881b8152600f017f7b2274726169745f74797065223a2022566f696420436c617373222c20227661815266363ab2911d101160c91b60208201526027016142d491613c4b565b630113e96160e51b81526004017f7b2274726169745f74797065223a20224579652054797065222c202276616c7581526432911d101160d91b602082015260250161431e91613c4b565b630113e96160e51b81526004017f7b2274726169745f74797065223a202253796d6d65747279222c202276616c7581526432911d101160d91b602082015260250161436891613c4b565b630113e96160e51b81526004017f7b2274726169745f74797065223a202244696d656e73696f6e73222c20227661815266363ab2911d101160c91b60208201526027016143b491613c4b565b630113e96160e51b81526004017f7b2274726169745f74797065223a2022446973746f7274696f6e222c20227661815266363ab2911d101160c91b602082015260270161440091613c4b565b630113e96160e51b81526004017f7b2274726169745f74797065223a2022476c6974636820496e74656e7369747981526c111610113b30b63ab2911d101160991b6020820152602d0161445291613c4b565b61227d60f01b81526002016202e96160ed1b81526003017f22696d616765223a2022646174613a696d6167652f7376672b786d6c3b626173815263194d8d0b60e21b60208201526024016140c791613c4b565b90611a86611a81611a7c6144bb9360315461329c565b906144c7611a86610a73565b82036144d75761149f915061525d565b6144e2611a86610aa6565b82036144f25761149f9150615242565b6144fd611a86610adc565b82146145315761149f916040516145288161246e602082019444869091604092825260208201520190565b5190209061529c565b61149f91506150f6565b61454f906000526004602052604060002090565b80546001600160a01b0319169055565b1561456657565b60405162461bcd60e51b815260206004820152601b60248201527f546f75726e616d656e7420616c726561647920636f6d706c65746500000000006044820152606490fd5b156145b257565b60405162461bcd60e51b815260206004820152601a60248201527f4d6f7265207468616e206f6e6520746f6b656e206163746976650000000000006044820152606490fd5b80519067ffffffffffffffff821161169957600160401b821161169957602090603d5483603d55808410614656575b5001603d600052602060002060005b8381106146425750505050565b600190602084519401938184015501614635565b61466e90603d600052848460002091820191016135c2565b38614626565b919060408352602061181960408501603d613916565b6146a56146a061075b60325460ff9060101c1690565b61455f565b6146b36001603454146145ab565b6000805b6031548110156147e7576146e260026146da83600052602f602052604060002090565b015460ff1690565b6146ee576001016146b7565b61475c915061472261470a82600052602f602052604060002090565b6003614718603b544261329c565b9101819055604155565b61472b81613880565b61473b614736612711565b6145f7565b614743610a73565b90919082549060031b91821b91600019901b1916179055565b61477d614775611a86614770603e5461327e565b610b2d565b614743610aa6565b614799614791611a86614770603e5461328d565b614743610adc565b6147af6201000060325462ff0000191617603255565b7f214409305b7fb351cee528d611c013826d87ecc660283e9bfa5aab8faf4ad8386147e260335460405191829182614674565b0390a1565b5061475c90614722565b6000828152600260205260409020546001600160a01b03908116939081166148c8575b506001600160a01b0383168061489a575b6001600160a01b0382169161484e9083614876575b61062a856000526002602052604060002090565b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a490565b6001600160a01b03811660009081526003602052604090206001815401905561483a565b6148a38361453b565b6001600160a01b03841660009081526003602052604090208054600019019055614825565b6148e36001600160a01b038216801515908161492d57501590565b1561481457826001600160a01b03851661490b57637e27328960e01b60005260045260246000fd5b63177e802f60e01b6000526001600160a01b0390911660045260245260446000fd5b6001600160a01b0387168082149250821561496e575b50811561494f57501590565b6000868152600460205260409020546001600160a01b03161490501590565b909150600052600560205260ff61499b8460406000209060018060a01b0316600052602052604060002090565b54169038614943565b906149ae826116fa565b6149bb60405191826116ba565b828152809261275b601f19916116fa565b908151811015610a6e570160200190565b908115614a7457600082805b614a555750806149f984926149a4565b915b614a0457509150565b614a10614a4e9161327e565b93614a39614a29614a23600a8406612bbe565b60ff1690565b60f81b6001600160f81b03191690565b60001a614a4686856149cc565b53600a900490565b92836149fb565b9290614a63614a6b916126c9565b93600a900490565b809391936149e9565b9050604051614a846040826116ba565b60018152600360fc1b602082015290565b60405161045e91614aa76060836116ba565b604082527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208301527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f604083015261573b565b60405190614b0b6040836116ba565b6004825263159bda5960e21b6020830152565b60405190614b2d6040836116ba565b600b82526a53696e67756c617269747960a81b6020830152565b60405190614b566040836116ba565b60058252644e6578757360d81b6020830152565b60405190614b796040836116ba565b6007825266456e74726f707960c81b6020830152565b60405190614b9e6040836116ba565b60078252660a0c2e4c2c8def60cb1b6020830152565b60405190614bc36040836116ba565b600982526815195cdcd95c9858dd60ba1b6020830152565b60405190614bea6040836116ba565b6009825268098c2c4f2e4d2dce8d60bb1b6020830152565b60405190614c116040836116ba565b60078252664d616e64616c6160c81b6020830152565b60405190614c366040836116ba565b60068252650acdee4e8caf60d31b6020830152565b60405190614c5a6040836116ba565b600682526523b7b63232b760d11b6020830152565b90600a811015610a6e5760051b0190565b614d1e9060ff60405191614c96610140846116ba565b614c9e614afc565b8352614ca8614b1e565b6020840152614cb5614b47565b6040840152614cc2614b6a565b6060840152614ccf614b8f565b6080840152614cdc614bb4565b60a0840152614ce9614bdb565b60c0840152614cf6614c02565b60e0840152614d03614c27565b610100840152614d11614c4b565b6101208401521690614c6f565b5190565b906003811015610a6e5760051b0190565b614d1e9060ff60405191614d468361167d565b60408051614d5482826116ba565b60048152634e6f6e6560e01b602082015284528051614d7382826116ba565b600981526821bcb1b637b832b0b760b91b60208201526020850152805190614d9b81836116ba565b6008825267547269636c6f707360c01b60208301528401521690614d22565b60405190614dc96040836116ba565b60078252665175616e74756d60c81b6020830152565b60405190614dee6040836116ba565b600c82526b151c985b9cd8d95b99195b9d60a21b6020830152565b906005811015610a6e5760051b0190565b614d1e9060ff60405191614e2d8361169e565b60408051614e3b82826116ba565b60068152651498591a585b60d21b602082015284528051614e5c82826116ba565b6009815268109a5b185d195c985b60ba1b60208201526020850152805190614e8481836116ba565b60078252664368616f74696360c81b6020830152840152614ea3614dba565b6060840152614eb0614ddf565b60808401521690614e09565b60405190614ecb6040836116ba565b60028252610d1160f21b6020830152565b60405190614eeb6040836116ba565b60028252610d5160f21b6020830152565b60405190614f0b6040836116ba565b60028252610d9160f21b6020830152565b60405190614f2b6040836116ba565b60028252610dd160f21b6020830152565b60405190614f4b6040836116ba565b60028252610e1160f21b6020830152565b906006811015610a6e5760051b0190565b60405160c0810181811067ffffffffffffffff82111761169957614d1e9260ff9160405260408051614f9f82826116ba565b60028152610cd160f21b60208201528452614fb8614ebc565b6020850152614fc5614edc565b90840152614fd1614efc565b6060840152614fde614f1c565b6080840152614feb614f3c565b60a08401521690614f5c565b614d1e9060ff6040519161500a8361169e565b6040805161501882826116ba565b60048152635761766560e01b60208201528452805161503782826116ba565b6007815266119c9858dd185b60ca1b60208201526020850152615058614dba565b90840152615064614afc565b6060840152614eb0614b8f565b614d1e9060ff604051916150848361167d565b6040805161509282826116ba565b600581526426b4b737b960d91b6020820152845280516150b282826116ba565b60088152674d6f64657261746560c01b602082015260208501528051906150d981836116ba565b600682526553657665726560d01b60208301528401521690614d22565b600401805460ff1916600517815561523890615225905b80546502030504010065ffffffffff0019821617825561514290611c559060ff165b60ff16600052602d602052604060002090565b615163615150825460ff1690565b60ff166000526027602052604060002090565b61516d81546126c9565b9055805461518e9060081c60ff1660ff166000526028602052604060002090565b61519881546126c9565b905580546151b99060101c60ff1660ff166000526029602052604060002090565b6151c381546126c9565b905580546151e49060181c60ff1660ff16600052602a602052604060002090565b6151ee81546126c9565b9055805461520f9060201c60ff1660ff16600052602b602052604060002090565b61521981546126c9565b90555460281c60ff1690565b60ff16600052602e602052604060002090565b612cf981546126c9565b600401805460ff19166007178155615238906152259061510d565b600401805460ff19168155615238906152259061510d565b600a811015610a6e5760070190600090565b60031b906107f860f88316921682036126d857565b9091906103e88306600a811080615706575b156154aa5750806151426153ce614a236153c761523896976152da6004615225980160ff198154169055565b6152ef6152e78260201c90565b6103e8900690565b6046811080615475575b80615458575b156153ec5750615325611c5561512f60048901611c0e81610100815461ff001916179055565b61535e6004615341614a2361533a8560401c90565b6005900690565b9701805462ff0000191660109890981b62ff000016979097178755565b615392615378614a236153718460601c90565b6006900690565b875463ff000000191660189190911b63ff00000016178755565b6153c16153a5614a2361533a8460801c90565b875464ff00000000191660209190911b64ff0000000016178755565b60a01c90565b6003900690565b825465ff0000000000191660289190911b65ff000000000016178255565b60781180615422575b156154105760048601805461ff001916610200179055615325565b60048601805461ff0019169055615325565b50600260005260286020527fd713ae4f394bfd6aef7af01a08d49ae9377aec9e97dc14f4e41ccaf8d3c793d954601354116153f5565b5061547061075b611c0e61512f60048b015460ff1690565b6152ff565b5060016000526028602052600a7f97f6617e72684f128d84ea8b55c40e794b94716acf5a4e8c39cb395494fddcca54106152f9565b60328110806156d0575b156154e85750806151426153ce614a236153c761523896976154e360046152259801600660ff19825416179055565b6152da565b606481108061569a575b156155215750806151426153ce614a236153c761523896976154e360046152259801600460ff19825416179055565b60b41180615664575b1561555857806151426153ce614a236153c761523896976154e360046152259801600960ff19825416179055565b61556260c06116ec565b600181529260026020850152600360408501526005606085015260076080850152600860a085015260005b600660ff8216106155b6575b50615238929350906151426153ce614a236153c7615225956152da565b6155f16155ea6155e4614a236155da614a236155d187615287565b889060ff161c90565b60ff600691160690565b87614f5c565b5160ff1690565b6156088160ff166000526027602052604060002090565b54615615611a8683615275565b11615626575060010160ff1661558d565b6152389495506151429150614a236153c785946156566153ce94600461522599019060ff1660ff19825416179055565b949550505050849350615599565b50600960005260276020527f44309ed6576ee8f6a63b44a56123242091825645c88723271e17fb9005f0f59b546010541161552a565b50600460005260276020527fd74efdfd87f35d7ac3f29a209600d84a995d8b95ea0c046120a5173a31595f1e54600b54116154f2565b50600660005260276020527fbb667d44c5c0b6514cdde7bab5c9184d7c962f234e8d1a6c42765934eb43306f54600d54116154b4565b506000805260276020527f552d06d8e69b1fc894b5bb152d5c34ccb2ea2834fd646ff017b1562d77bdb85a54600754116152ae565b9190918051156158145761576961576461575f6157588451612bcc565b6003900490565b612c9e565b6149a4565b9060208201908081518201956020870190815192600083525b8881106157c657505060039394959650525106806001146157b3576002146157a8575090565b603d90600019015390565b50603d9081600019820153600119015390565b600360049199969901986001603f8b5182828260121c16870101518453828282600c1c16870101518385015382828260061c1687010151600285015316840101516003820153019497615782565b50905061045e612acd56fea26469706673582212209328de84debe04797f7aaf63e3a99469d4924ca141d03b343c6ceb3674f365b864736f6c634300081c003300000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000e66646174613a696d6167652f7376672b786d6c3b6261736536342c436941674943413863335a6e494868746247357a50534a6f644852774f693876643364334c6e637a4c6d39795a7938794d4441774c334e325a79496764326c6b64476739496a55774d434967614756705a326830505349314d44416950676f6749434167494341385a47566d637a344b494341674943416749434138636d466b6157467352334a685a476c6c626e516761575139496d6c7961584d6949474e34505349314d43556949474e35505349314d43556949484939496a55774a53492b4369416749434167494341674943413863335276634342765a6d5a7a5a585139496a416c4969427a644739774c574e76624739795053496a4d4441774969382b4369416749434167494341674943413863335276634342765a6d5a7a5a585139496a55774a534967633352766343316a62327876636a3069497a45784e43497650676f6749434167494341674943416750484e306233416762325a6d63325630505349334d43556949484e3062334174593239736233493949694d794d6a59694c7a344b4943416749434167494341674944787a644739774947396d5a6e4e6c644430694f44556c4969427a644739774c574e76624739795053496a4d5445304969382b4369416749434167494341674943413863335276634342765a6d5a7a5a585139496a45774d43556949484e3062334174593239736233493949694d774d4441694c7a344b4943416749434167494341384c334a685a476c6862456479595752705a57353050676f674943416749434167494478795957527059577848636d466b61575675644342705a443069634856776157776949474e34505349314d43556949474e35505349314d43556949484939496a55774a53492b4369416749434167494341674943413863335276634342765a6d5a7a5a585139496a45774a534967633352766343316a62327876636a3069497a41774d43497650676f6749434167494341674943416750484e306233416762325a6d63325630505349334d43556949484e3062334174593239736233493949694d774d4449694c7a344b4943416749434167494341674944787a644739774947396d5a6e4e6c644430694d5441774a534967633352766343316a62327876636a3069497a41774d43497650676f67494341674943416749447776636d466b6157467352334a685a476c6c626e512b43694167494341674943416750475a706248526c636942705a443069646d39705a4764736233636950676f6749434167494341674943416750475a6c5232463163334e70595735436248567949484e305a45526c646d6c6864476c76626a30694d54496949484a6c6333567364443069596d7831636a45694c7a344b4943416749434167494341674944786d5a55646864584e7a61574675516d78316369427a644752455a585a705958527062323439496a596949484a6c6333567364443069596d7831636a49694c7a344b4943416749434167494341674944786d5a55316c636d646c50676f67494341674943416749434167494341385a6d564e5a584a6e5a5535765a47556761573439496d4a73645849784969382b436941674943416749434167494341674944786d5a55316c636d646c546d396b5a534270626a3069596d7831636a49694c7a344b4943416749434167494341674943416750475a6c545756795a32564f6232526c49476c7550534a546233567959325648636d467761476c6a4969382b436941674943416749434167494341384c325a6c545756795a32552b4369416749434167494341675043396d615778305a58492b43694167494341674943416750475a706248526c636942705a4430695932397a62576c6a496a344b4943416749434167494341674944786d5a565231636d4a31624756755932556764486c775a5430695a6e4a68593352686245357661584e6c4969426959584e6c526e4a6c6358566c626d4e35505349774c6a6369494735316255396a644746325a584d39496a556949484e306158526a614652706247567a50534a7a64476c30593267694c7a344b4943416749434167494341674944786d5a554e766247397954574630636d6c344948523563475539496e4e68644856795958526c49694232595778315a584d39496a41754d4455694c7a344b4943416749434167494341384c325a706248526c636a344b49434167494341675043396b5a575a7a50676f674943416749434138636d566a6443423361575230614430694d5441774a534967614756705a326830505349784d44416c4969426d6157787350534a696247466a6179497650676f674943416749434138636d566a6443423361575230614430694d5441774a534967614756705a326830505349784d44416c4969426d615778305a584939496e56796243676a5932397a62576c6a4b5349676233426859326c30655430694d4334784e53497650676f6749434167494341385a79426d615778305a584939496e56796243676a646d39705a47647362336370496a344b49434167494341674943413859326c795932786c49474e34505349794e54416949474e35505349794e54416949484939496a45324d434967633352796232746c5053496a4d7a4d344969427a64484a766132557464326c6b64476739496a41754e5349675a6d6c7362443069626d39755a5349676233426859326c30655430694d433479496a344b49434167494341674943416749447868626d6c745958526c4947463064484a70596e56305a55356862575539496e4e30636d39725a5331766347466a6158523549694232595778315a584d39496a41754d6a73774c6a45374d4334794969426b64584939496a687a496942795a58426c5958524462335675644430696157356b5a575a70626d6c305a53497650676f6749434167494341674943416750474675615731686447556759585230636d6c696458526c546d46745a54306963694967646d46736457567a505349784e6a41374d5467774f7a45324d4349675a4856795053493463794967636d56775a57463051323931626e5139496d6c755a47566d61573570644755694c7a344b4943416749434167494341384c324e70636d4e735a54344b49434167494341674943413859326c795932786c49474e34505349794e54416949474e35505349794e54416949484939496a45304d434967633352796232746c5053496a4d7a4d344969427a64484a766132557464326c6b64476739496a456949475a7062477739496d3576626d55694947397759574e7064486b39496a41754d79492b4369416749434167494341674943413859573570625746305a5342686448527961574a316447564f5957316c50534a7a64484a76613255746233426859326c3065534967646d46736457567a505349774c6a4d374d4334784f7a41754d7949675a4856795053493363794967636d56775a57463051323931626e5139496d6c755a47566d61573570644755694c7a344b49434167494341674943416749447868626d6c745958526c4947463064484a70596e56305a55356862575539496e496949485a686248566c637a30694d5451774f7a45314d4473784e44416949475231636a30694e334d6949484a6c6347566864454e766457353050534a70626d526c5a6d6c756158526c4969382b4369416749434167494341675043396a61584a6a6247552b43694167494341674943416750474e70636d4e735a53426a654430694d6a55774969426a655430694d6a557749694279505349784d6a416949484e30636d39725a543069497a51304f534967633352796232746c4c5864705a48526f505349794969426d6157787350534a756232356c496942766347466a61585235505349774c6a516950676f6749434167494341674943416750474675615731686447556759585230636d6c696458526c546d46745a543069633352796232746c4c57397759574e7064486b6949485a686248566c637a30694d4334304f7a41754d6a73774c6a516949475231636a30694e6e4d6949484a6c6347566864454e766457353050534a70626d526c5a6d6c756158526c4969382b4369416749434167494341674943413859573570625746305a5342686448527961574a316447564f5957316c50534a7949694232595778315a584d39496a45794d4473784d7a41374d5449774969426b64584939496a5a7a496942795a58426c5958524462335675644430696157356b5a575a70626d6c305a53497650676f6749434167494341674944777659326c795932786c50676f6749434167494341674944786a61584a6a6247556759336739496a49314d43496759336b39496a49314d434967636a30694d5441774969427a64484a766132553949694d304e47456949484e30636d39725a53313361575230614430694d6a556949475a7062477739496e56796243676a61584a7063796b6950676f6749434167494341674943416750474675615731686447556759585230636d6c696458526c546d46745a543069633352796232746c4c57397759574e7064486b6949485a686248566c637a30694d4334354f7a41754e4473774c6a6b6949475231636a30694e584d6949484a6c6347566864454e766457353050534a70626d526c5a6d6c756158526c4969382b4369416749434167494341675043396a61584a6a6247552b43694167494341674943416750474e70636d4e735a53426a654430694d6a55774969426a655430694d6a557749694279505349304d4349675a6d6c736244306964584a734b434e776458427062436b6950676f6749434167494341674943416750474675615731686447556759585230636d6c696458526c546d46745a54306963694967646d46736457567a505349304d44737a4e5473304d4349675a4856795053493063794967636d56775a57463051323931626e5139496d6c755a47566d61573570644755694c7a344b4943416749434167494341384c324e70636d4e735a54344b49434167494341675043396e50676f67494341675043397a646d632b436941674943413d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080a646174613a696d6167652f7376672b786d6c3b6261736536342c436941674943413863335a6e494868746247357a50534a6f644852774f693876643364334c6e637a4c6d39795a7938794d4441774c334e325a79496764326c6b64476739496a55774d434967614756705a326830505349314d44416950676f6749434167494341385a47566d637a344b494341674943416749434138636d466b6157467352334a685a476c6c626e516761575139496d567361573170636d6c7a4969426a654430694e54416c4969426a655430694e54416c49694279505349314d43556950676f6749434167494341674943416750484e306233416762325a6d63325630505349784d43556949484e3062334174593239736233493949694d794d4441694c7a344b4943416749434167494341674944787a644739774947396d5a6e4e6c644430694e7a416c4969427a644739774c574e76624739795053496a4e4441774969382b4369416749434167494341674943413863335276634342765a6d5a7a5a585139496a6b774a534967633352766343316a62327876636a3069497a59774d43497650676f6749434167494341674943416750484e306233416762325a6d63325630505349784d44416c4969427a644739774c574e76624739795053496a4d6a41774969382b436941674943416749434167504339795957527059577848636d466b615756756444344b4943416749434167494341385a6d6c736447567949476c6b50534a7a6147463064475679496a344b4943416749434167494341674944786d5a565231636d4a31624756755932556764486c775a54306964485679596e56735a57356a5a534967596d467a5a555a795a5846315a57356a655430694d4334774d7a5569494735316255396a644746325a584d39496a55694c7a344b4943416749434167494341674944786d5a5552706333427359574e6c625756756445316863434270626a306955323931636d4e6c52334a68634768705979496763324e6862475539496a4d314969382b4369416749434167494341675043396d615778305a58492b43694167494341674943416750475a706248526c636942705a44306959323973624746776332556950676f6749434167494341674943416750475a6c5232463163334e70595735436248567949484e305a45526c646d6c6864476c76626a30694d54496949484a6c6333567364443069596d7831636a45694c7a344b4943416749434167494341674944786d5a55646864584e7a61574675516d78316369427a644752455a585a705958527062323439496a596949484a6c6333567364443069596d7831636a49694c7a344b4943416749434167494341674944786d5a55316c636d646c50676f67494341674943416749434167494341385a6d564e5a584a6e5a5535765a47556761573439496d4a73645849784969382b436941674943416749434167494341674944786d5a55316c636d646c546d396b5a534270626a3069596d7831636a49694c7a344b4943416749434167494341674943416750475a6c545756795a32564f6232526c49476c7550534a546233567959325648636d467761476c6a4969382b436941674943416749434167494341384c325a6c545756795a32552b4369416749434167494341675043396d615778305a58492b4369416749434167494477765a47566d637a344b494341674943416750484a6c5933516764326c6b64476739496a45774d4355694947686c6157646f644430694d5441774a5349675a6d6c7362443069596d7868593273694c7a344b4943416749434167504763675a6d6c736447567950534a31636d776f49324e766247786863484e6c4b53496764484a68626e4e6d62334a7450534a30636d4675633278686447556f4d6a55774c4449314d436b6950676f6749434167494341674944786e49475a706248526c636a306964584a734b434e7a61474630644756794b53492b43694167494341674943416749434138634746306143426b50534a4e4c5445774d437777494545784d4441734d544177494441674d537778494445774d4377774969427a64484a766132553949694d324d44416949484e30636d39725a53313361575230614430694d6a416949475a7062477739496d3576626d55694947397759574e7064486b39496a41754e53497650676f6749434167494341674943416750484268644767675a443069545445774d437777494545784d4441734d544177494441674d537778494330784d4441734d434967633352796232746c5053496a4e6a41774969427a64484a766132557464326c6b64476739496a49774969426d6157787350534a756232356c496942766347466a61585235505349774c6a5569494852795957357a5a6d397962543069636d39305958526c4b4459774b53497650676f6749434167494341674943416750484268644767675a443069545330784d4441734d4342424d5441774c4445774d434177494445734d5341784d4441734d434967633352796232746c5053496a4e6a41774969427a64484a766132557464326c6b64476739496a49774969426d6157787350534a756232356c496942766347466a61585235505349774c6a5569494852795957357a5a6d397962543069636d39305958526c4b4445794d436b694c7a344b4943416749434167494341384c32632b43694167494341674943416750474e70636d4e735a534279505349324d4349675a6d6c736244306964584a734b434e6c62476c7461584a7063796b694c7a344b49434167494341675043396e50676f67494341675043397a646d632b436941674943413d00000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c806301ffc9a71461037b57806306fdde0314610376578063081812fc14610371578063095ea7b31461036c5780630e9242b114610367578063140719851461036257806318160ddd1461035d57806322604a461461035857806323b872dd1461035357806325fd90f31461034e57806342842e0e14610349578063560cdbc21461034457806358a5b0f61461033f5780636352211e1461033a5780636b80ae171461033557806370a0823114610330578063715018a61461032b578063741c0a091461032657806374689fdf1461032157806378f3af531461031c5780637d55094d146103175780638da5cb5b1461031257806395d89b411461030d57806395f0e45c1461030857806396365d4414610303578063a0712d68146102fe578063a22cb465146102f9578063a58bd127146102f4578063ac8de2b0146102ef578063b09afec1146102ea578063b3c8ee1f146102e5578063b4b5b48f146102e0578063b88d4fde146102db578063b99adbe1146102d6578063c1e99063146102d1578063c47ef875146102cc578063c87b56dd146102c7578063ca9b648b146102c2578063cb6cd4ca146102bd578063ce516507146102b8578063d23e57d2146102b3578063d5abeb01146102ae578063d7098154146102a9578063d7a9dc6b146102a4578063d829055e1461029f578063d91930251461029a578063e985e9c514610295578063f0368dfa14610290578063f2fde38b1461028b578063f4f3b20014610286578063f4fcab7d14610281578063f64c3f0a1461027c578063f88a8f36146102775763fec173d80361000e576123f9565b61236b565b61216e565b612150565b612041565b611fb7565b611f58565b611efb565b611df7565b611d63565b611d45565b611baf565b611b91565b611a0e565b6119dd565b6119bf565b61197a565b611947565b611929565b61181e565b61179f565b611716565b6115df565b61155b565b6114a1565b61124b565b611225565b61116c565b610f37565b610f19565b610ec8565b610e1f565b610df6565b610d8b565b610d5a565b610d34565b610cc6565b610c69565b610c13565b610be7565b610bb7565b610b99565b610b48565b610a13565b6109f0565b6109d9565b6108d3565b6108b5565b61071f565b6106e7565b6105a5565b61053b565b610461565b610397565b6001600160e01b031981160361039257565b600080fd5b346103925760203660031901126103925760206004356103b681610380565b63ffffffff60e01b166380ac58cd60e01b81149081156103f4575b81156103e3575b506040519015158152f35b6301ffc9a760e01b149050386103d8565b635b5e139f60e01b811491506103d1565b60005b8381106104185750506000910152565b8181015183820152602001610408565b9060209161044181518092818552858086019101610405565b601f01601f1916010190565b90602061045e928181520190610428565b90565b3461039257600036600319011261039257604051600080546104828161258b565b808452906001811690811561051757506001146104ba575b6104b6836104aa818503826116ba565b6040519182918261044d565b0390f35b60008080527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563939250905b8082106104fd575090915081016020016104aa61049a565b9192600181602092548385880101520191019092916104e5565b60ff191660208086019190915291151560051b840190910191506104aa905061049a565b346103925760203660031901126103925760043561055881613961565b506000526004602052602060018060a01b0360406000205416604051908152f35b600435906001600160a01b038216820361039257565b602435906001600160a01b038216820361039257565b34610392576040366003190112610392576105be610579565b602435906105cb82613961565b331515806106a0575b8061065e575b610649576100199261062a9181906001600160a01b0385811691167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925600080a46000526004602052604060002090565b80546001600160a01b0319166001600160a01b03909216919091179055565b63a9fbf51f60e01b6000523360045260246000fd5b5060ff610698336106818460018060a01b03166000526005602052604060002090565b9060018060a01b0316600052602052604060002090565b5416156105da565b506001600160a01b0381163314156105d4565b906020808351928381520192019060005b8181106106d15750505090565b82518452602093840193909201916001016106c4565b3461039257600036600319011261039257610700612779565b906104b6604051928392151583526040602084015260408301906106b3565b346103925760003660031901126103925761076461075f61075b60325461075261074d8260ff9060081c1690565b612873565b60101c60ff1690565b1590565b6128b6565b60315460001990600090815b818110610842575050805b603154811080610838575b1561082d5761079f81600052602f602052604060002090565b836002820154916107b08360ff1690565b9283610815575b508261080a575b50506107d3575b6107ce906126c9565b61077b565b906107e6906107e1836139f1565b6126c9565b906107f760325460ff9060101c1690565b156107c5575061001991505b15156128f8565b5414905083386107be565b9092506108269060081c60ff161590565b91386107b7565b506100199150610803565b5060198210610786565b61085681600052602f602052604060002090565b600281015460ff811690816108a0575b5080610895575b8061088b575b610881575b50600101610770565b5493506001610878565b5084815410610873565b50805442101561086d565b6108af915060081c60ff161590565b38610866565b34610392576000366003190112610392576020603054604051908152f35b34610392576000366003190112610392576108fe60325460ff8160081c16908161098a575b5061293b565b600080603154905b81811061091857604051838152602090f35b61092c81600052602f602052604060002090565b60028101549060ff82169182610972575b5081610966575b50610952575b600101610906565b9161095e6001916126c9565b92905061094a565b90505442101538610944565b9091506109839060081c60ff161590565b903861093d565b610999915060101c60ff161590565b386108f8565b6060906003190112610392576004356001600160a01b038116810361039257906024356001600160a01b0381168103610392579060443590565b34610392576100196109ea3661099f565b9161297f565b3461039257600036600319011261039257602060ff603254166040519015158152f35b3461039257610019610a243661099f565b9060405192610a346020856116ba565b6000845261302f565b634e487b7160e01b600052603260045260246000fd5b603f54811015610a6e57603f60005260206000200190600090565b610a3d565b603d5415610a6e57603d60009081527fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc391565b603d5460011015610a6e57603d60009081527fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc491565b603d5460021015610a6e57603d60009081527fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc591565b604354811015610a6e57604360005260206000200190600090565b603e54811015610a6e57603e60005260206000200190600090565b3461039257602036600319011261039257600435603d5481101561039257602090603d6000527fece66cfdbd22e3f37d348a3d8e19074452862cd65fd4b9a11f0336d1ac6d1dc30154604051908152f35b34610392576000366003190112610392576020603b54604051908152f35b34610392576020366003190112610392576020610bd5600435613961565b6040516001600160a01b039091168152f35b346103925760203660031901126103925760043560005260426020526020604060002054604051908152f35b34610392576020366003190112610392576001600160a01b03610c34610579565b168015610c535760005260036020526020604060002054604051908152f35b6322718ad960e21b600052600060045260246000fd5b3461039257600036600319011261039257610c82613ab3565b600680546001600160a01b031981169091556000906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610392576000366003190112610392576040516043548082526020820190604360005260206000209060005b818110610d1e576104b685610d0a818703826116ba565b6040519182916020835260208301906106b3565b8254845260209093019260019283019201610cf3565b3461039257600036600319011261039257602060ff60325460081c166040519015158152f35b3461039257602036600319011261039257600435600052603a602052602060ff604060002054166040519015158152f35b3461039257600036600319011261039257610da4613ab3565b7f6bdfe227d5db299c59aa56d5f846f40dbd73b271aaa78e18ed74fc3e00b8aa6b6020603254610dda60ff8260081c1615612ae2565b60ff8082161516809160ff1916176032556040519015158152a1005b34610392576000366003190112610392576006546040516001600160a01b039091168152602090f35b34610392576000366003190112610392576040516000600154610e418161258b565b80845290600181169081156105175750600114610e68576104b6836104aa818503826116ba565b91905060016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6916000905b808210610eae575090915081016020016104aa61049a565b919260018160209254838588010152019101909291610e96565b3461039257602036600319011261039257600435603e5481101561039257602090603e6000527f8d800d6614d35eed73733ee453164a3b48076eb3138f466adeeb9dec7bb31f700154604051908152f35b34610392576000366003190112610392576020603354604051908152f35b602036600319011261039257600435610f72610f6d61075b603254610f64610f5f8260ff1690565b612b21565b60081c60ff1690565b612ae2565b80151580611157575b610f8490612b62565b610f9d610f9382603054612bda565b6031541015612be7565b610fb0610fa982612c27565b3414612cb6565b610fc4610fbf34603354612bda565b603355565b60005b8181106110765760305460315414610fdb57005b610fef61010060325461ff00191617603255565b610ff842603b55565b60005b60315481101561102c5760019061101142612b9f565b61102582600052602f602052604060002090565b5501610ffb565b50603b54603154603354604080519384526020840192909252908201527f2b4fbc018be75e6ff98b219698828856ce311122193b11596150e17268e2ee319080606081015b0390a1005b60019060305461108d611088826126c9565b603055565b6110978133613adc565b6111076110a26116dc565b60008082526020820152600160408201526000606082015260006080820152600060a0820152600060c0820152600060e082015260006101008201526000610120820152600061014082015261110283600052602f602052604060002090565b612cfd565b61111a6111156034546126c9565b603455565b604051678ac7230489e8000081523391907f2d03118aa776f7008445f6ca8490a6782ede2db364d741513555ba656ab1879f90602090a301610fc7565b506005811115610f7b565b8015150361039257565b3461039257604036600319011261039257611185610579565b60243561119181611162565b6001600160a01b03821691821561121057816111cf6111e09233600052600560205260406000209060018060a01b0316600052602052604060002090565b9060ff801983541691151516179055565b60405190151581527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b82630b61174360e31b60005260045260246000fd5b3461039257600036600319011261039257602060ff60325460101c166040519015158152f35b34610392576040366003190112610392576004356024359061127781600052602f602052604060002090565b61128d611288600283015460ff1690565b612e5d565b60325461129f9060081c60ff16612873565b6112ab81544210612e9c565b6040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b037f000000000000000000000000982eddc7cb6aa589050acbd3c6042864a91352ee1692906020816064816000885af1801561140f5761131a91600091611414575b50612efe565b60405163a9059cbb60e01b815261dead60048201526024810185905292602090849060449082906000905af191821561140f577f4f339848d3f9c12eee86898233737164ce0b93d22d4e89bb33b314c21933fc416113c383926113de966113d6966113e2575b5080546113a661139d6005670de0b6b3a76400008c040483612bda565b91821015612f42565b815554604051918291898360209093929193604081019481520152565b0390a26000526042602052604060002090565b918254612bda565b9055005b6114039060203d602011611408575b6113fb81836116ba565b810190612edd565b611380565b503d6113f1565b612ef2565b61142d915060203d602011611408576113fb81836116ba565b38611314565b98969492909b9a99979593916101608a019c8a5260208a01521515604089015215156060880152608087015260ff1660a086015260ff1660c085015260ff1660e084015260ff1661010083015261012082016114909160ff169052565b6101400161149f9160ff169052565b565b34610392576020366003190112610392576004356000818152600260205260409020546114d8906001600160a01b03161515612f7e565b600052602f60205260ff60406000206104b68154916001810154906002810154936115078560ff9060081c1690565b600460038401549301549261151c8460ff1690565b600885901c60ff1691601086901c60ff1693601887901c60ff169561154c602089901c60ff169860281c60ff1690565b986040519c8d9c16918c611433565b3461039257600036600319011261039257611574613ab3565b4780156115a55760065461001991600091829182918291906001600160a01b03165af161159f612fc1565b50612ff1565b60405162461bcd60e51b81526020600482015260126024820152714e6f2041504520746f20776974686472617760701b6044820152606490fd5b3461039257602036600319011261039257600435600052602f60205260406000208054906104b6600182015492600283015490600460038501549401549161162b8360ff9060201c1690565b91602884901c60ff169360405197889760ff8360181c169460ff8460101c169460ff808660081c1695169360ff808460081c169316918c611433565b634e487b7160e01b600052604160045260246000fd5b6060810190811067ffffffffffffffff82111761169957604052565b611667565b60a0810190811067ffffffffffffffff82111761169957604052565b90601f8019910116810190811067ffffffffffffffff82111761169957604052565b6040519061149f610160836116ba565b9061149f60405192836116ba565b67ffffffffffffffff811161169957601f01601f191660200190565b346103925760803660031901126103925761172f610579565b61173761058f565b906044356064359267ffffffffffffffff8411610392573660238501121561039257836004013592611768846116fa565b9361177660405195866116ba565b80855236602482880101116103925760208160009260246100199901838901378601015261302f565b34610392576020366003190112610392576004356043548110156103925760209060436000527f9690ad99d6ce244efa8a0f6c2d04036d3b33a9474db32a71b71135c6951027930154604051908152f35b9392916118199061180b6040936060885260608801906106b3565b9086820360208801526106b3565b930152565b34610392576020366003190112610392576004356118526032546118468160ff9060081c1690565b908161098a575061293b565b61185f6064821115613130565b61186881612733565b9061187281612733565b600090600092603154935b84811080611920575b156119065761189f81600052602f602052604060002090565b600281015460ff811690816118f1575b506118c4575b506118bf906126c9565b61187d565b846118ea91836118d86118bf95988b612765565b52546118e48287612765565b526126c9565b93906118b5565b611900915060081c60ff161590565b386118af565b5050915080835281526104b66040519283924291846117f0565b50818410611886565b34610392576000366003190112610392576020603454604051908152f35b34610392576020366003190112610392576104b6611966600435613216565b604051918291602083526020830190610428565b34610392576000366003190112610392576040517f000000000000000000000000982eddc7cb6aa589050acbd3c6042864a91352ee6001600160a01b03168152602090f35b34610392576000366003190112610392576020603c54604051908152f35b34610392576020366003190112610392576004356000526039602052602060ff604060002054166040519015158152f35b3461039257602036600319011261039257600435611a2a613ab3565b611a3b60ff60325460101c16612667565b60315480821015611b5c576004611a90611a86611a81611a7c867f6de67c5b73a0eead4c2c2bf2df73dc1e32f68a73330221df4135e757e7d8f6399661329c565b61327e565b610a53565b90549060031b1c90565b92611ae0611aa885600052602f602052604060002090565b91611ad16002840191611acb611ac661075b855460ff9060081c1690565b6132a9565b846144a5565b805461ff001916610100179055565b015460ff8116611b57600883901c60ff165b92601081901c60ff1690601881901c60ff16611b19602083901c60ff169260281c60ff1690565b92604051968796879460ff60a0958180968180969c9b978160c08d019e168c521660208b015216604089015216606087015216608085015216910152565b0390a2005b60405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b6044820152606490fd5b34610392576000366003190112610392576020603154604051908152f35b3461039257602036600319011261039257600435603254611bd59060101c60ff16612667565b611bf1611be182613961565b6001600160a01b031633146132ee565b611c1a611c1561075b611c0e846000526039602052604060002090565b5460ff1690565b61332c565b611c25611a86610a73565b81148015611d32575b8015611d1a575b611c3e90613370565b611c62611c55826000526039602052604060002090565b805460ff19166001179055565b600090611c70611a86610a73565b8103611cab5750506100196000808080611c95611c8e603354612c72565b6064900490565b611ca08115156133b1565b335af161159f612fc1565b611cb6611a86610aa6565b8103611cd95750506100196000808080611cd4611c8e603354612c5c565b611c95565b611ce4611a86610adc565b14611cf8575b600080808061001994611c95565b506100196000808080611d0f611c8e603354612c46565b945050505050611cea565b50611c3e611d29611a86610adc565b82149050611c35565b50611d3e611a86610aa6565b8114611c2e565b34610392576000366003190112610392576020604054604051908152f35b346103925760003660031901126103925760ff60325460101c166034549060335460405190603d548083526020830190603d60005260206000209060005b818110611de15750505090611dbc836104b6949303836116ba565b60405194859415158552602085015260408401526080606084015260808301906106b3565b8254845260209093019260019283019201611da1565b3461039257602036600319011261039257600435611e19600a604354146133f1565b611e25611be182613961565b611e47611e4261075b611c0e84600052603a602052604060002090565b61343d565b60009060005b600a8110611ed4575b50611e817f69dfeac86fe2e01b0c84ade0a933302dfd88a748855d332f74c26de31c475d279261347b565b611e98611c5582600052603a602052604060002090565b611ea6611c8e603354612c88565b90611ebb600080808086335af161159f612fc1565b6040805191825260208201929092529081908101611071565b81611ee1611a8683610b12565b14611eee57600101611e4d565b5060019150611e81611e56565b3461039257604036600319011261039257602060ff611f4c611f1b610579565b611f2361058f565b6001600160a01b0391821660009081526005865260408082209290931681526020919091522090565b54166040519015158152f35b346103925760403660031901126103925760243560043567ffffffffffffffff821161039257366023830112156103925781600401359067ffffffffffffffff82116103925736602483850101116103925760246100199301906134c7565b3461039257602036600319011261039257611fd0610579565b611fd8613ab3565b6001600160a01b0316801561202b57600680546001600160a01b0319811683179091556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b631e4fbdf760e01b600052600060045260246000fd5b346103925760203660031901126103925761205a610579565b612062613ab3565b6040516370a0823160e01b81523060048201526001600160a01b039190911690602081602481855afa801561140f576120e792602092600092612121575b506120ac8215156136f8565b60065460405163a9059cbb60e01b81526001600160a01b03909116600482015260248101929092529092839190829060009082906044820190565b03925af1801561140f57610019916000916121025750612ff1565b61211b915060203d602011611408576113fb81836116ba565b3861159f565b612142919250833d8511612149575b61213a81836116ba565b8101906136e9565b90386120a0565b503d612130565b34610392576000366003190112610392576020604154604051908152f35b346103925760203660031901126103925760043561218a613ab3565b60325461219c9060101c60ff16612667565b80151580612360575b6121ae9061373c565b6121bb6040549182612bda565b90603154808311612358575b603c54604080519182526020820184905281018490527f6b721a1ca1f979ab7c31f3356629da6eafc64b18f824a7b58e0f79a3389aeb5990606090a16000919003600019015b603154918383038210158061234f575b156122b4577f6de67c5b73a0eead4c2c2bf2df73dc1e32f68a73330221df4135e757e7d8f63960046001612253611a8686610a53565b9361227961226b86600052602f602052604060002090565b9787900360001901886144a5565b60028701805461ff001916610100179055019401546122988160ff1690565b6122a8600883901c60ff16611af2565b0390a26000190161220d565b7fd2f0d1ea4e5b39d0b3762648a29fa2b8012f2b7db2c8906dafae86eec125cae5906122df85604055565b6122f36122ee603c5460010190565b603c55565b603c54604080519182526020820192909252a16040546031548091101561231657005b604080519182524260208301527fecd55f300557b93401c39e249ff8ea87c46796fd2b94d38cfcf819077501898c919081908101611071565b5082821061221d565b9150816121c7565b5060198111156121a5565b346103925760203660031901126103925760043580600052602f602052604060002060ff6032546123a0828260081c16612873565b60101c166123bb57544210156123b257005b610019906139f1565b60405162461bcd60e51b8152602060048201526016602482015275546f75726e616d656e7420697320636f6d706c65746560501b6044820152606490fd5b3461039257600036600319011261039257612412613ab3565b6032546124249060101c60ff1661377d565b612430604354156137c9565b60315461243c81612733565b9060009060005b818110612542575050604051602081019061247c8161246e4442869091604092825260208201520190565b03601f1981018352826116ba565b519020916000925b600a84106124ba577f9e0f277eb74eb2d772adf5fad2c9dbb64a77ee6144274b06cb3b1b573cee7ff46040518061107181613950565b6040805160208101928352908101859052600191906124dc816060810161246e565b519020936124fc6124f66124f0838761329c565b87613815565b82612bda565b6125276125098386612765565b51916125158187612765565b516125208588612765565b5285612765565b5261253b6125358285612765565b51613835565b0192612484565b69152d02c7e14af6800000612561826000526042602052604060002090565b541015612571575b600101612443565b9161258381846118e460019488612765565b929050612569565b90600182811c921680156125bb575b60208310146125a557565b634e487b7160e01b600052602260045260246000fd5b91607f169161259a565b90604051918260008254926125d98461258b565b808452936001811690811561264557506001146125fe575b5061149f925003836116ba565b90506000929192526020600020906000915b81831061262957505090602061149f92820101386125f1565b6020919350806001915483858901015201910190918492612610565b90506020925061149f94915060ff191682840152151560051b820101386125f1565b1561266e57565b60405162461bcd60e51b815260206004820152601760248201527f546f75726e616d656e74206e6f7420636f6d706c6574650000000000000000006044820152606490fd5b634e487b7160e01b600052601160045260246000fd5b60001981146126d85760010190565b6126b3565b67ffffffffffffffff81116116995760051b60200190565b604051906127046020836116ba565b6000808352366020840137565b6040516080919061272283826116ba565b6003815291601f1901366020840137565b9061273d826126dd565b61274a60405191826116ba565b828152809261275b601f19916126dd565b0190602036910137565b8051821015610a6e5760209160051b010190565b60325461278b9060101c60ff16612667565b603154906000805b83811061282b5750801561281b576127aa90612733565b916000805b8281106127bf5750505060009190565b806127ce611a86600193610a53565b6127f561075b60026127ea84600052602f602052604060002090565b015460081c60ff1690565b612801575b50016127af565b61281461280d856126c9565b9488612765565b52386127fa565b5090506128266126f5565b600191565b61285261075b60026127ea612842611a8686610a53565b600052602f602052604060002090565b61285f575b600101612793565b9061286b6001916126c9565b919050612857565b1561287a57565b60405162461bcd60e51b81526020600482015260146024820152734d696e74696e67206e6f7420636f6d706c65746560601b6044820152606490fd5b156128bd57565b60405162461bcd60e51b8152602060048201526013602482015272546f75726e616d656e7420636f6d706c65746560681b6044820152606490fd5b156128ff57565b60405162461bcd60e51b8152602060048201526014602482015273139bc81d1bdad95b9cc8195b1a5b5a5b985d195960621b6044820152606490fd5b1561294257565b60405162461bcd60e51b8152602060048201526015602482015274546f75726e616d656e74206e6f742061637469766560581b6044820152606490fd5b91906001600160a01b03811615612ab75761299c908233916147f1565b6001600160a01b038116929083151580612aaf575b6129e6575b506001600160a01b03168083036129cc57505050565b6364283d7b60e01b60005260045260245260445260646000fd5b6129fa83600052602f602052604060002090565b600281018054612a0e9060081c60ff161590565b612a1a575b50506129b6565b600a60018301612a2a81546126c9565b90819055835460408051838152602081019290925288917fcfc3cbe6ddd550af78e9426b09c1e0841fd5bbfd4f36c74cfefad75b915e45239190a2101580612aa4575b15612a84575050612a7d836139f1565b3880612a13565b5460ff16612a93575b50612a7d565b612a9c42612baf565b905538612a8d565b50805460ff16612a6d565b5060016129b1565b633250574960e11b600052600060045260246000fd5b60405190612adc6020836116ba565b60008252565b15612ae957565b60405162461bcd60e51b815260206004820152601060248201526f4d696e74696e6720636f6d706c65746560801b6044820152606490fd5b15612b2857565b60405162461bcd60e51b81526020600482015260126024820152714d696e74206973206e6f742061637469766560701b6044820152606490fd5b15612b6957565b60405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b6044820152606490fd5b906201518082018092116126d857565b90611c2082018092116126d857565b60300190816030116126d857565b90600282018092116126d857565b919082018092116126d857565b15612bee57565b60405162461bcd60e51b8152602060048201526011602482015270457863656564206d617820737570706c7960781b6044820152606490fd5b9081678ac7230489e800000291678ac7230489e800008304036126d857565b90600a820291808304600a14901517156126d857565b906014820291808304601414901517156126d857565b906032820291808304603214901517156126d857565b908160011b91808304600214901517156126d857565b600281901b91906001600160fe1b038116036126d857565b15612cbd57565b60405162461bcd60e51b8152602060048201526014602482015273125b98dbdc9c9958dd0810541148185b5bdd5b9d60621b6044820152606490fd5b9055565b90612e40610140600461149f948451815560208501516001820155612d5c60028201612d41612d2f6040890151151590565b829060ff801983541691151516179055565b6060870151815461ff00191690151560081b61ff0016179055565b608085015160038201550192612d89612d7960a083015160ff1690565b855460ff191660ff909116178555565b612db5612d9a60c083015160ff1690565b858054909161ff001990911660089190911b61ff0016179055565b612dde612dc660e083015160ff1690565b855462ff0000191660109190911b62ff000016178555565b612e0a612df061010083015160ff1690565b855463ff000000191660189190911b63ff00000016178555565b612e38612e1c61012083015160ff1690565b855464ff00000000191660209190911b64ff0000000016178555565b015160ff1690565b65ff000000000082549160281b169065ff00000000001916179055565b15612e6457565b60405162461bcd60e51b815260206004820152601060248201526f546f6b656e206e6f742061637469766560801b6044820152606490fd5b15612ea357565b60405162461bcd60e51b8152602060048201526012602482015271151bdad95b881d1a5b5948195e1c1a5c995960721b6044820152606490fd5b90816020910312610392575161045e81611162565b6040513d6000823e3d90fd5b15612f0557565b60405162461bcd60e51b8152602060048201526015602482015274151bdad95b881d1c985b9cd9995c8819985a5b1959605a1b6044820152606490fd5b15612f4957565b60405162461bcd60e51b815260206004820152600d60248201526c54696d65206f766572666c6f7760981b6044820152606490fd5b15612f8557565b60405162461bcd60e51b8152602060048201526014602482015273151bdad95b88191bd95cc81b9bdd08195e1a5cdd60621b6044820152606490fd5b3d15612fec573d90612fd2826116fa565b91612fe060405193846116ba565b82523d6000602084013e565b606090565b15612ff857565b60405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606490fd5b90929161303d81858461297f565b833b61304a575b50505050565b60209161306c6040519485938493630a85bd0160e11b85523360048601613c1a565b038160006001600160a01b0387165af1600091816130ff575b506130c15750613093612fc1565b80519190826130ba57633250574960e11b6000526001600160a01b03821660045260246000fd5b9050602001fd5b6001600160e01b03191663757a42ff60e11b016130e2575038808080613044565b633250574960e11b6000526001600160a01b031660045260246000fd5b61312291925060203d602011613129575b61311a81836116ba565b810190613c05565b9038613085565b503d613110565b1561313757565b60405162461bcd60e51b815260206004820152600e60248201526d098d2dad2e840e8dede40d0d2ced60931b6044820152606490fd5b9061149f61320b600461317e6116dc565b9480548652600181015460208701526131b76131ae6002830154610f646131a58260ff1690565b151560408b0152565b15156060880152565b60038101546080870152015460ff811660a086015260ff600882901c1660c086015260ff601082901c1660e086015260ff601882901c1661010086015260ff602082901c1661012086015260281c60ff1690565b60ff16610140840152565b600081815260026020526040902054613239906001600160a01b03161515612f7e565b80600052602f60205261324f604060002061316d565b606081015115613263575061045e90614138565b60400151156132755761045e90613ecf565b61045e90613d62565b6000198101919082116126d857565b6001198101919082116126d857565b919082039182116126d857565b156132b057565b60405162461bcd60e51b8152602060048201526016602482015275151bdad95b88185b1c9958591e481c995d99585b195960521b6044820152606490fd5b156132f557565b60405162461bcd60e51b815260206004820152600f60248201526e2737ba103a37b5b2b71037bbb732b960891b6044820152606490fd5b1561333357565b60405162461bcd60e51b8152602060048201526015602482015274141c9a5e9948185b1c9958591e4818db185a5b5959605a1b6044820152606490fd5b1561337757565b60405162461bcd60e51b81526020600482015260126024820152712a37b5b2b7103737ba1030903bb4b73732b960711b6044820152606490fd5b156133b857565b60405162461bcd60e51b81526020600482015260116024820152704e6f207072697a6520746f20636c61696d60781b6044820152606490fd5b156133f857565b60405162461bcd60e51b815260206004820152601e60248201527f426f6e75732077696e6e657273206e6f742073656c65637465642079657400006044820152606490fd5b1561344457565b60405162461bcd60e51b815260206004820152600f60248201526e105b1c9958591e4818db185a5b5959608a1b6044820152606490fd5b1561348257565b60405162461bcd60e51b815260206004820152601860248201527f546f6b656e206e6f74206120626f6e75732077696e6e657200000000000000006044820152606490fd5b9190916134d2613ab3565b80600052602f60205260ff60026040600020015460081c161561354a5761353a611c559261149f9461352161351c60ff613516876000526038602052604060002090565b54161590565b613584565b613535846000526037602052604060002090565b61361e565b6000526038602052604060002090565b60405162461bcd60e51b8152602060048201526012602482015271151bdad95b881b9bdd081c995d99585b195960721b6044820152606490fd5b1561358b57565b60405162461bcd60e51b815260206004820152600f60248201526e14d591c8185b1c9958591e481cd95d608a1b6044820152606490fd5b8181106135cd575050565b600081556001016135c2565b9190601f81116135e857505050565b61149f926000526020600020906020601f840160051c83019310613614575b601f0160051c01906135c2565b9091508190613607565b90929167ffffffffffffffff8111611699576136448161363e845461258b565b846135d9565b6000601f8211600114613681578190612cf9939495600092613676575b50508160011b916000199060031b1c19161790565b013590503880613661565b601f1982169461369684600052602060002090565b91805b8781106136d15750836001959697106136b7575b505050811b019055565b0135600019600384901b60f8161c191690553880806136ad565b90926020600181928686013581550194019101613699565b90816020910312610392575190565b156136ff57565b60405162461bcd60e51b81526020600482015260156024820152744e6f20746f6b656e7320746f20776974686472617760581b6044820152606490fd5b1561374357565b60405162461bcd60e51b8152602060048201526012602482015271496e76616c69642062617463682073697a6560701b6044820152606490fd5b1561378457565b60405162461bcd60e51b815260206004820152601b60248201527f546f75726e616d656e74206e6f7420636f6d706c6574652079657400000000006044820152606490fd5b156137d057565b60405162461bcd60e51b815260206004820152601e60248201527f426f6e75732077696e6e65727320616c72656164792073656c656374656400006044820152606490fd5b811561381f570690565b634e487b7160e01b600052601260045260246000fd5b604354600160401b81101561169957600181016043556000604354821015610a6e57604390527f9690ad99d6ce244efa8a0f6c2d04036d3b33a9474db32a71b71135c6951027930155565b603f54600160401b8110156116995760018101603f556000603f54821015610a6e57603f90527fc03004e3ce0784bf68186394306849f9b7b1200073105cd9aeb554a1802b58fd0155565b603e54600160401b8110156116995760018101603e556000603e54821015610a6e57603e90527f8d800d6614d35eed73733ee453164a3b48076eb3138f466adeeb9dec7bb31f700155565b906020825491828152019160005260206000209060005b81811061393a5750505090565b825484526020909301926001928301920161392d565b602061045e91818152016043613916565b6000818152600260205260409020546001600160a01b0316908115613984575090565b637e27328960e01b60005260045260246000fd5b1561399f57565b60405162461bcd60e51b815260206004820152601860248201527f546f6b656e20616c726561647920656c696d696e6174656400000000000000006044820152606490fd5b80156126d8576000190190565b80600052602f6020527fff7eb81bed4ae9152c79e95c8651e3e2b6d9575e7226d09e22648afe709ac970613a8e6040600020613a4760028201613a3d613a38825460ff1690565b613998565b805460ff19169055565b6003613a55603b544261329c565b9101908155613a686111156034546139e4565b613a7184613880565b60036034541115613aa5575b546040519081529081906020820190565b0390a2600160345414613a9d57565b61149f61468a565b613aae846138cb565b613a7d565b6006546001600160a01b03163303613ac757565b63118cdaa760e01b6000523360045260246000fd5b6001600160a01b03811615612ab757600082613af7926147f1565b6001600160a01b0381161515918280613bfd575b613b2e575b5050613b1857565b6339e3563760e11b600052600060045260246000fd5b613b4281600052602f602052604060002090565b9060028201613b5961075b825460ff9060081c1690565b613b65575b5050613b10565b600a60018401613b7581546126c9565b90819055845460408051838152602081019290925285917fcfc3cbe6ddd550af78e9426b09c1e0841fd5bbfd4f36c74cfefad75b915e45239190a2101580613bf2575b15613bd05750613bc891506139f1565b388080613b5e565b5460ff169050613be1575b50613bc8565b613bea42612baf565b905538613bdb565b50805460ff16613bb8565b506001613b0b565b90816020910312610392575161045e81610380565b6001600160a01b03918216815291166020820152604081019190915260806060820181905261045e92910190610428565b90613c5e60209282815194859201610405565b0190565b60365460009291613c728261258b565b9160018116908115613cd95750600114613c8a575050565b6036600090815292935090917f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b85b838210613cc55750500190565b600181602092548486015201910190613cb8565b60ff1916825250811515909102019150565b60355460009291613cfb8261258b565b9160018116908115613cd95750600114613d13575050565b6035600090815292935090917fcfa4bec1d3298408bb5afcfcd9c430549c5b31f8aa5c5848151c0a55f473c34d5b838210613d4e5750500190565b600181602092548486015201910190613d41565b61045e613e99605d613e94613d7961246e956149dd565b61246e613e86613e81613e6b613e5c613e1c6040519889976f7b226e616d65223a2022566f6964202360801b60208a0152613dbe81518092602060308d019101610405565b7f222c20226465736372697074696f6e223a20225468697320766f6964206861736030918a01918201526c01031b7b63630b839b2b211161609d1b60508201526e2261747472696275746573223a205b60881b9101908152600f0190565b7f7b2274726169745f74797065223a2022537461747573222c202276616c75652281526d3a2022436f6c6c6170736564227d60901b6020820152602e0190565b6202e96160ed1b815260030190565b691134b6b0b3b2911d101160b11b8152600a0190565b613c62565b61227d60f01b815260020190565b614a95565b6040517f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000006020820152928391603d830190613c4b565b80600052602f602052604060002090613ee66116dc565b9180548352600181015460208401526002810154613f048160ff1690565b1515604085015260ff600891821c8116151560608601526003830154608086015260049092015480831660a08601529081901c821660c0850152601081901c821660e0850152601881901c8216610100850152602081901c821661012085015260281c16610140830152613f77906149dd565b9051613f82906149dd565b6040516f7b226e616d65223a2022566f6964202360801b60208201529182919060308301613faf91613c4b565b7f222c20226465736372697074696f6e223a20224120766f696420656e7469747981527f206669676874696e6720666f7220737572766976616c222c200000000000000060208201526039016e2261747472696275746573223a205b60881b8152600f017f7b2274726169745f74797065223a2022537461747573222c202276616c75652281526f01d101129bab93b34bb34b733913e96160851b60208201526030017f7b2274726169745f74797065223a2022566f696420436f6c6c61707365222c20815269113b30b63ab2911d101160b11b6020820152602a0161409491613c4b565b61227d60f01b81526002016202e96160ed1b8152600301691134b6b0b3b2911d101160b11b8152600a016140c790613ceb565b61227d60f01b815260020103601f19810182526140e490826116ba565b6140ed90614a95565b6040517f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000006020820152908190603d820161412691613c4b565b03601f198101825261045e90826116ba565b61414c81600052602f602052604060002090565b6141559061316d565b614169826000526037602052604060002090565b614172906125c5565b9161417c906149dd565b9060a081015161418c9060ff1690565b61419590614c80565b9260c08201516141a59060ff1690565b6141ae90614d33565b9160e08101516141be9060ff1690565b6141c790614e1a565b61010082015160ff166141d990614f6d565b906101208301516141ea9060ff1690565b6141f390614ff7565b6101409093015160ff1661420690615071565b9361421090614a95565b6040516f7b226e616d65223a2022566f6964202360801b60208201529788979196916030890161423f91613c4b565b7f222c20226465736372697074696f6e223a202241207472616e7363656e64656481526e0103b37b4b21032b73a34ba3c91161608d1b6020820152602f016e2261747472696275746573223a205b60881b8152600f017f7b2274726169745f74797065223a2022566f696420436c617373222c20227661815266363ab2911d101160c91b60208201526027016142d491613c4b565b630113e96160e51b81526004017f7b2274726169745f74797065223a20224579652054797065222c202276616c7581526432911d101160d91b602082015260250161431e91613c4b565b630113e96160e51b81526004017f7b2274726169745f74797065223a202253796d6d65747279222c202276616c7581526432911d101160d91b602082015260250161436891613c4b565b630113e96160e51b81526004017f7b2274726169745f74797065223a202244696d656e73696f6e73222c20227661815266363ab2911d101160c91b60208201526027016143b491613c4b565b630113e96160e51b81526004017f7b2274726169745f74797065223a2022446973746f7274696f6e222c20227661815266363ab2911d101160c91b602082015260270161440091613c4b565b630113e96160e51b81526004017f7b2274726169745f74797065223a2022476c6974636820496e74656e7369747981526c111610113b30b63ab2911d101160991b6020820152602d0161445291613c4b565b61227d60f01b81526002016202e96160ed1b81526003017f22696d616765223a2022646174613a696d6167652f7376672b786d6c3b626173815263194d8d0b60e21b60208201526024016140c791613c4b565b90611a86611a81611a7c6144bb9360315461329c565b906144c7611a86610a73565b82036144d75761149f915061525d565b6144e2611a86610aa6565b82036144f25761149f9150615242565b6144fd611a86610adc565b82146145315761149f916040516145288161246e602082019444869091604092825260208201520190565b5190209061529c565b61149f91506150f6565b61454f906000526004602052604060002090565b80546001600160a01b0319169055565b1561456657565b60405162461bcd60e51b815260206004820152601b60248201527f546f75726e616d656e7420616c726561647920636f6d706c65746500000000006044820152606490fd5b156145b257565b60405162461bcd60e51b815260206004820152601a60248201527f4d6f7265207468616e206f6e6520746f6b656e206163746976650000000000006044820152606490fd5b80519067ffffffffffffffff821161169957600160401b821161169957602090603d5483603d55808410614656575b5001603d600052602060002060005b8381106146425750505050565b600190602084519401938184015501614635565b61466e90603d600052848460002091820191016135c2565b38614626565b919060408352602061181960408501603d613916565b6146a56146a061075b60325460ff9060101c1690565b61455f565b6146b36001603454146145ab565b6000805b6031548110156147e7576146e260026146da83600052602f602052604060002090565b015460ff1690565b6146ee576001016146b7565b61475c915061472261470a82600052602f602052604060002090565b6003614718603b544261329c565b9101819055604155565b61472b81613880565b61473b614736612711565b6145f7565b614743610a73565b90919082549060031b91821b91600019901b1916179055565b61477d614775611a86614770603e5461327e565b610b2d565b614743610aa6565b614799614791611a86614770603e5461328d565b614743610adc565b6147af6201000060325462ff0000191617603255565b7f214409305b7fb351cee528d611c013826d87ecc660283e9bfa5aab8faf4ad8386147e260335460405191829182614674565b0390a1565b5061475c90614722565b6000828152600260205260409020546001600160a01b03908116939081166148c8575b506001600160a01b0383168061489a575b6001600160a01b0382169161484e9083614876575b61062a856000526002602052604060002090565b7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef600080a490565b6001600160a01b03811660009081526003602052604090206001815401905561483a565b6148a38361453b565b6001600160a01b03841660009081526003602052604090208054600019019055614825565b6148e36001600160a01b038216801515908161492d57501590565b1561481457826001600160a01b03851661490b57637e27328960e01b60005260045260246000fd5b63177e802f60e01b6000526001600160a01b0390911660045260245260446000fd5b6001600160a01b0387168082149250821561496e575b50811561494f57501590565b6000868152600460205260409020546001600160a01b03161490501590565b909150600052600560205260ff61499b8460406000209060018060a01b0316600052602052604060002090565b54169038614943565b906149ae826116fa565b6149bb60405191826116ba565b828152809261275b601f19916116fa565b908151811015610a6e570160200190565b908115614a7457600082805b614a555750806149f984926149a4565b915b614a0457509150565b614a10614a4e9161327e565b93614a39614a29614a23600a8406612bbe565b60ff1690565b60f81b6001600160f81b03191690565b60001a614a4686856149cc565b53600a900490565b92836149fb565b9290614a63614a6b916126c9565b93600a900490565b809391936149e9565b9050604051614a846040826116ba565b60018152600360fc1b602082015290565b60405161045e91614aa76060836116ba565b604082527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208301527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f604083015261573b565b60405190614b0b6040836116ba565b6004825263159bda5960e21b6020830152565b60405190614b2d6040836116ba565b600b82526a53696e67756c617269747960a81b6020830152565b60405190614b566040836116ba565b60058252644e6578757360d81b6020830152565b60405190614b796040836116ba565b6007825266456e74726f707960c81b6020830152565b60405190614b9e6040836116ba565b60078252660a0c2e4c2c8def60cb1b6020830152565b60405190614bc36040836116ba565b600982526815195cdcd95c9858dd60ba1b6020830152565b60405190614bea6040836116ba565b6009825268098c2c4f2e4d2dce8d60bb1b6020830152565b60405190614c116040836116ba565b60078252664d616e64616c6160c81b6020830152565b60405190614c366040836116ba565b60068252650acdee4e8caf60d31b6020830152565b60405190614c5a6040836116ba565b600682526523b7b63232b760d11b6020830152565b90600a811015610a6e5760051b0190565b614d1e9060ff60405191614c96610140846116ba565b614c9e614afc565b8352614ca8614b1e565b6020840152614cb5614b47565b6040840152614cc2614b6a565b6060840152614ccf614b8f565b6080840152614cdc614bb4565b60a0840152614ce9614bdb565b60c0840152614cf6614c02565b60e0840152614d03614c27565b610100840152614d11614c4b565b6101208401521690614c6f565b5190565b906003811015610a6e5760051b0190565b614d1e9060ff60405191614d468361167d565b60408051614d5482826116ba565b60048152634e6f6e6560e01b602082015284528051614d7382826116ba565b600981526821bcb1b637b832b0b760b91b60208201526020850152805190614d9b81836116ba565b6008825267547269636c6f707360c01b60208301528401521690614d22565b60405190614dc96040836116ba565b60078252665175616e74756d60c81b6020830152565b60405190614dee6040836116ba565b600c82526b151c985b9cd8d95b99195b9d60a21b6020830152565b906005811015610a6e5760051b0190565b614d1e9060ff60405191614e2d8361169e565b60408051614e3b82826116ba565b60068152651498591a585b60d21b602082015284528051614e5c82826116ba565b6009815268109a5b185d195c985b60ba1b60208201526020850152805190614e8481836116ba565b60078252664368616f74696360c81b6020830152840152614ea3614dba565b6060840152614eb0614ddf565b60808401521690614e09565b60405190614ecb6040836116ba565b60028252610d1160f21b6020830152565b60405190614eeb6040836116ba565b60028252610d5160f21b6020830152565b60405190614f0b6040836116ba565b60028252610d9160f21b6020830152565b60405190614f2b6040836116ba565b60028252610dd160f21b6020830152565b60405190614f4b6040836116ba565b60028252610e1160f21b6020830152565b906006811015610a6e5760051b0190565b60405160c0810181811067ffffffffffffffff82111761169957614d1e9260ff9160405260408051614f9f82826116ba565b60028152610cd160f21b60208201528452614fb8614ebc565b6020850152614fc5614edc565b90840152614fd1614efc565b6060840152614fde614f1c565b6080840152614feb614f3c565b60a08401521690614f5c565b614d1e9060ff6040519161500a8361169e565b6040805161501882826116ba565b60048152635761766560e01b60208201528452805161503782826116ba565b6007815266119c9858dd185b60ca1b60208201526020850152615058614dba565b90840152615064614afc565b6060840152614eb0614b8f565b614d1e9060ff604051916150848361167d565b6040805161509282826116ba565b600581526426b4b737b960d91b6020820152845280516150b282826116ba565b60088152674d6f64657261746560c01b602082015260208501528051906150d981836116ba565b600682526553657665726560d01b60208301528401521690614d22565b600401805460ff1916600517815561523890615225905b80546502030504010065ffffffffff0019821617825561514290611c559060ff165b60ff16600052602d602052604060002090565b615163615150825460ff1690565b60ff166000526027602052604060002090565b61516d81546126c9565b9055805461518e9060081c60ff1660ff166000526028602052604060002090565b61519881546126c9565b905580546151b99060101c60ff1660ff166000526029602052604060002090565b6151c381546126c9565b905580546151e49060181c60ff1660ff16600052602a602052604060002090565b6151ee81546126c9565b9055805461520f9060201c60ff1660ff16600052602b602052604060002090565b61521981546126c9565b90555460281c60ff1690565b60ff16600052602e602052604060002090565b612cf981546126c9565b600401805460ff19166007178155615238906152259061510d565b600401805460ff19168155615238906152259061510d565b600a811015610a6e5760070190600090565b60031b906107f860f88316921682036126d857565b9091906103e88306600a811080615706575b156154aa5750806151426153ce614a236153c761523896976152da6004615225980160ff198154169055565b6152ef6152e78260201c90565b6103e8900690565b6046811080615475575b80615458575b156153ec5750615325611c5561512f60048901611c0e81610100815461ff001916179055565b61535e6004615341614a2361533a8560401c90565b6005900690565b9701805462ff0000191660109890981b62ff000016979097178755565b615392615378614a236153718460601c90565b6006900690565b875463ff000000191660189190911b63ff00000016178755565b6153c16153a5614a2361533a8460801c90565b875464ff00000000191660209190911b64ff0000000016178755565b60a01c90565b6003900690565b825465ff0000000000191660289190911b65ff000000000016178255565b60781180615422575b156154105760048601805461ff001916610200179055615325565b60048601805461ff0019169055615325565b50600260005260286020527fd713ae4f394bfd6aef7af01a08d49ae9377aec9e97dc14f4e41ccaf8d3c793d954601354116153f5565b5061547061075b611c0e61512f60048b015460ff1690565b6152ff565b5060016000526028602052600a7f97f6617e72684f128d84ea8b55c40e794b94716acf5a4e8c39cb395494fddcca54106152f9565b60328110806156d0575b156154e85750806151426153ce614a236153c761523896976154e360046152259801600660ff19825416179055565b6152da565b606481108061569a575b156155215750806151426153ce614a236153c761523896976154e360046152259801600460ff19825416179055565b60b41180615664575b1561555857806151426153ce614a236153c761523896976154e360046152259801600960ff19825416179055565b61556260c06116ec565b600181529260026020850152600360408501526005606085015260076080850152600860a085015260005b600660ff8216106155b6575b50615238929350906151426153ce614a236153c7615225956152da565b6155f16155ea6155e4614a236155da614a236155d187615287565b889060ff161c90565b60ff600691160690565b87614f5c565b5160ff1690565b6156088160ff166000526027602052604060002090565b54615615611a8683615275565b11615626575060010160ff1661558d565b6152389495506151429150614a236153c785946156566153ce94600461522599019060ff1660ff19825416179055565b949550505050849350615599565b50600960005260276020527f44309ed6576ee8f6a63b44a56123242091825645c88723271e17fb9005f0f59b546010541161552a565b50600460005260276020527fd74efdfd87f35d7ac3f29a209600d84a995d8b95ea0c046120a5173a31595f1e54600b54116154f2565b50600660005260276020527fbb667d44c5c0b6514cdde7bab5c9184d7c962f234e8d1a6c42765934eb43306f54600d54116154b4565b506000805260276020527f552d06d8e69b1fc894b5bb152d5c34ccb2ea2834fd646ff017b1562d77bdb85a54600754116152ae565b9190918051156158145761576961576461575f6157588451612bcc565b6003900490565b612c9e565b6149a4565b9060208201908081518201956020870190815192600083525b8881106157c657505060039394959650525106806001146157b3576002146157a8575090565b603d90600019015390565b50603d9081600019820153600119015390565b600360049199969901986001603f8b5182828260121c16870101518453828282600c1c16870101518385015382828260061c1687010151600285015316840101516003820153019497615782565b50905061045e612acd56fea26469706673582212209328de84debe04797f7aaf63e3a99469d4924ca141d03b343c6ceb3674f365b864736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000003e800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000f000000000000000000000000000000000000000000000000000000000000000e66646174613a696d6167652f7376672b786d6c3b6261736536342c436941674943413863335a6e494868746247357a50534a6f644852774f693876643364334c6e637a4c6d39795a7938794d4441774c334e325a79496764326c6b64476739496a55774d434967614756705a326830505349314d44416950676f6749434167494341385a47566d637a344b494341674943416749434138636d466b6157467352334a685a476c6c626e516761575139496d6c7961584d6949474e34505349314d43556949474e35505349314d43556949484939496a55774a53492b4369416749434167494341674943413863335276634342765a6d5a7a5a585139496a416c4969427a644739774c574e76624739795053496a4d4441774969382b4369416749434167494341674943413863335276634342765a6d5a7a5a585139496a55774a534967633352766343316a62327876636a3069497a45784e43497650676f6749434167494341674943416750484e306233416762325a6d63325630505349334d43556949484e3062334174593239736233493949694d794d6a59694c7a344b4943416749434167494341674944787a644739774947396d5a6e4e6c644430694f44556c4969427a644739774c574e76624739795053496a4d5445304969382b4369416749434167494341674943413863335276634342765a6d5a7a5a585139496a45774d43556949484e3062334174593239736233493949694d774d4441694c7a344b4943416749434167494341384c334a685a476c6862456479595752705a57353050676f674943416749434167494478795957527059577848636d466b61575675644342705a443069634856776157776949474e34505349314d43556949474e35505349314d43556949484939496a55774a53492b4369416749434167494341674943413863335276634342765a6d5a7a5a585139496a45774a534967633352766343316a62327876636a3069497a41774d43497650676f6749434167494341674943416750484e306233416762325a6d63325630505349334d43556949484e3062334174593239736233493949694d774d4449694c7a344b4943416749434167494341674944787a644739774947396d5a6e4e6c644430694d5441774a534967633352766343316a62327876636a3069497a41774d43497650676f67494341674943416749447776636d466b6157467352334a685a476c6c626e512b43694167494341674943416750475a706248526c636942705a443069646d39705a4764736233636950676f6749434167494341674943416750475a6c5232463163334e70595735436248567949484e305a45526c646d6c6864476c76626a30694d54496949484a6c6333567364443069596d7831636a45694c7a344b4943416749434167494341674944786d5a55646864584e7a61574675516d78316369427a644752455a585a705958527062323439496a596949484a6c6333567364443069596d7831636a49694c7a344b4943416749434167494341674944786d5a55316c636d646c50676f67494341674943416749434167494341385a6d564e5a584a6e5a5535765a47556761573439496d4a73645849784969382b436941674943416749434167494341674944786d5a55316c636d646c546d396b5a534270626a3069596d7831636a49694c7a344b4943416749434167494341674943416750475a6c545756795a32564f6232526c49476c7550534a546233567959325648636d467761476c6a4969382b436941674943416749434167494341384c325a6c545756795a32552b4369416749434167494341675043396d615778305a58492b43694167494341674943416750475a706248526c636942705a4430695932397a62576c6a496a344b4943416749434167494341674944786d5a565231636d4a31624756755932556764486c775a5430695a6e4a68593352686245357661584e6c4969426959584e6c526e4a6c6358566c626d4e35505349774c6a6369494735316255396a644746325a584d39496a556949484e306158526a614652706247567a50534a7a64476c30593267694c7a344b4943416749434167494341674944786d5a554e766247397954574630636d6c344948523563475539496e4e68644856795958526c49694232595778315a584d39496a41754d4455694c7a344b4943416749434167494341384c325a706248526c636a344b49434167494341675043396b5a575a7a50676f674943416749434138636d566a6443423361575230614430694d5441774a534967614756705a326830505349784d44416c4969426d6157787350534a696247466a6179497650676f674943416749434138636d566a6443423361575230614430694d5441774a534967614756705a326830505349784d44416c4969426d615778305a584939496e56796243676a5932397a62576c6a4b5349676233426859326c30655430694d4334784e53497650676f6749434167494341385a79426d615778305a584939496e56796243676a646d39705a47647362336370496a344b49434167494341674943413859326c795932786c49474e34505349794e54416949474e35505349794e54416949484939496a45324d434967633352796232746c5053496a4d7a4d344969427a64484a766132557464326c6b64476739496a41754e5349675a6d6c7362443069626d39755a5349676233426859326c30655430694d433479496a344b49434167494341674943416749447868626d6c745958526c4947463064484a70596e56305a55356862575539496e4e30636d39725a5331766347466a6158523549694232595778315a584d39496a41754d6a73774c6a45374d4334794969426b64584939496a687a496942795a58426c5958524462335675644430696157356b5a575a70626d6c305a53497650676f6749434167494341674943416750474675615731686447556759585230636d6c696458526c546d46745a54306963694967646d46736457567a505349784e6a41374d5467774f7a45324d4349675a4856795053493463794967636d56775a57463051323931626e5139496d6c755a47566d61573570644755694c7a344b4943416749434167494341384c324e70636d4e735a54344b49434167494341674943413859326c795932786c49474e34505349794e54416949474e35505349794e54416949484939496a45304d434967633352796232746c5053496a4d7a4d344969427a64484a766132557464326c6b64476739496a456949475a7062477739496d3576626d55694947397759574e7064486b39496a41754d79492b4369416749434167494341674943413859573570625746305a5342686448527961574a316447564f5957316c50534a7a64484a76613255746233426859326c3065534967646d46736457567a505349774c6a4d374d4334784f7a41754d7949675a4856795053493363794967636d56775a57463051323931626e5139496d6c755a47566d61573570644755694c7a344b49434167494341674943416749447868626d6c745958526c4947463064484a70596e56305a55356862575539496e496949485a686248566c637a30694d5451774f7a45314d4473784e44416949475231636a30694e334d6949484a6c6347566864454e766457353050534a70626d526c5a6d6c756158526c4969382b4369416749434167494341675043396a61584a6a6247552b43694167494341674943416750474e70636d4e735a53426a654430694d6a55774969426a655430694d6a557749694279505349784d6a416949484e30636d39725a543069497a51304f534967633352796232746c4c5864705a48526f505349794969426d6157787350534a756232356c496942766347466a61585235505349774c6a516950676f6749434167494341674943416750474675615731686447556759585230636d6c696458526c546d46745a543069633352796232746c4c57397759574e7064486b6949485a686248566c637a30694d4334304f7a41754d6a73774c6a516949475231636a30694e6e4d6949484a6c6347566864454e766457353050534a70626d526c5a6d6c756158526c4969382b4369416749434167494341674943413859573570625746305a5342686448527961574a316447564f5957316c50534a7949694232595778315a584d39496a45794d4473784d7a41374d5449774969426b64584939496a5a7a496942795a58426c5958524462335675644430696157356b5a575a70626d6c305a53497650676f6749434167494341674944777659326c795932786c50676f6749434167494341674944786a61584a6a6247556759336739496a49314d43496759336b39496a49314d434967636a30694d5441774969427a64484a766132553949694d304e47456949484e30636d39725a53313361575230614430694d6a556949475a7062477739496e56796243676a61584a7063796b6950676f6749434167494341674943416750474675615731686447556759585230636d6c696458526c546d46745a543069633352796232746c4c57397759574e7064486b6949485a686248566c637a30694d4334354f7a41754e4473774c6a6b6949475231636a30694e584d6949484a6c6347566864454e766457353050534a70626d526c5a6d6c756158526c4969382b4369416749434167494341675043396a61584a6a6247552b43694167494341674943416750474e70636d4e735a53426a654430694d6a55774969426a655430694d6a557749694279505349304d4349675a6d6c736244306964584a734b434e776458427062436b6950676f6749434167494341674943416750474675615731686447556759585230636d6c696458526c546d46745a54306963694967646d46736457567a505349304d44737a4e5473304d4349675a4856795053493063794967636d56775a57463051323931626e5139496d6c755a47566d61573570644755694c7a344b4943416749434167494341384c324e70636d4e735a54344b49434167494341675043396e50676f67494341675043397a646d632b436941674943413d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080a646174613a696d6167652f7376672b786d6c3b6261736536342c436941674943413863335a6e494868746247357a50534a6f644852774f693876643364334c6e637a4c6d39795a7938794d4441774c334e325a79496764326c6b64476739496a55774d434967614756705a326830505349314d44416950676f6749434167494341385a47566d637a344b494341674943416749434138636d466b6157467352334a685a476c6c626e516761575139496d567361573170636d6c7a4969426a654430694e54416c4969426a655430694e54416c49694279505349314d43556950676f6749434167494341674943416750484e306233416762325a6d63325630505349784d43556949484e3062334174593239736233493949694d794d4441694c7a344b4943416749434167494341674944787a644739774947396d5a6e4e6c644430694e7a416c4969427a644739774c574e76624739795053496a4e4441774969382b4369416749434167494341674943413863335276634342765a6d5a7a5a585139496a6b774a534967633352766343316a62327876636a3069497a59774d43497650676f6749434167494341674943416750484e306233416762325a6d63325630505349784d44416c4969427a644739774c574e76624739795053496a4d6a41774969382b436941674943416749434167504339795957527059577848636d466b615756756444344b4943416749434167494341385a6d6c736447567949476c6b50534a7a6147463064475679496a344b4943416749434167494341674944786d5a565231636d4a31624756755932556764486c775a54306964485679596e56735a57356a5a534967596d467a5a555a795a5846315a57356a655430694d4334774d7a5569494735316255396a644746325a584d39496a55694c7a344b4943416749434167494341674944786d5a5552706333427359574e6c625756756445316863434270626a306955323931636d4e6c52334a68634768705979496763324e6862475539496a4d314969382b4369416749434167494341675043396d615778305a58492b43694167494341674943416750475a706248526c636942705a44306959323973624746776332556950676f6749434167494341674943416750475a6c5232463163334e70595735436248567949484e305a45526c646d6c6864476c76626a30694d54496949484a6c6333567364443069596d7831636a45694c7a344b4943416749434167494341674944786d5a55646864584e7a61574675516d78316369427a644752455a585a705958527062323439496a596949484a6c6333567364443069596d7831636a49694c7a344b4943416749434167494341674944786d5a55316c636d646c50676f67494341674943416749434167494341385a6d564e5a584a6e5a5535765a47556761573439496d4a73645849784969382b436941674943416749434167494341674944786d5a55316c636d646c546d396b5a534270626a3069596d7831636a49694c7a344b4943416749434167494341674943416750475a6c545756795a32564f6232526c49476c7550534a546233567959325648636d467761476c6a4969382b436941674943416749434167494341384c325a6c545756795a32552b4369416749434167494341675043396d615778305a58492b4369416749434167494477765a47566d637a344b494341674943416750484a6c5933516764326c6b64476739496a45774d4355694947686c6157646f644430694d5441774a5349675a6d6c7362443069596d7868593273694c7a344b4943416749434167504763675a6d6c736447567950534a31636d776f49324e766247786863484e6c4b53496764484a68626e4e6d62334a7450534a30636d4675633278686447556f4d6a55774c4449314d436b6950676f6749434167494341674944786e49475a706248526c636a306964584a734b434e7a61474630644756794b53492b43694167494341674943416749434138634746306143426b50534a4e4c5445774d437777494545784d4441734d544177494441674d537778494445774d4377774969427a64484a766132553949694d324d44416949484e30636d39725a53313361575230614430694d6a416949475a7062477739496d3576626d55694947397759574e7064486b39496a41754e53497650676f6749434167494341674943416750484268644767675a443069545445774d437777494545784d4441734d544177494441674d537778494330784d4441734d434967633352796232746c5053496a4e6a41774969427a64484a766132557464326c6b64476739496a49774969426d6157787350534a756232356c496942766347466a61585235505349774c6a5569494852795957357a5a6d397962543069636d39305958526c4b4459774b53497650676f6749434167494341674943416750484268644767675a443069545330784d4441734d4342424d5441774c4445774d434177494445734d5341784d4441734d434967633352796232746c5053496a4e6a41774969427a64484a766132557464326c6b64476739496a49774969426d6157787350534a756232356c496942766347466a61585235505349774c6a5569494852795957357a5a6d397962543069636d39305958526c4b4445794d436b694c7a344b4943416749434167494341384c32632b43694167494341674943416750474e70636d4e735a534279505349324d4349675a6d6c736244306964584a734b434e6c62476c7461584a7063796b694c7a344b49434167494341675043396e50676f67494341675043397a646d632b436941674943413d00000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _maxSupply (uint256): 1000
Arg [1] : _unrevealedSVG (string): data:image/svg+xml;base64,CiAgICA8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjUwMCIgaGVpZ2h0PSI1MDAiPgogICAgICA8ZGVmcz4KICAgICAgICA8cmFkaWFsR3JhZGllbnQgaWQ9ImlyaXMiIGN4PSI1MCUiIGN5PSI1MCUiIHI9IjUwJSI+CiAgICAgICAgICA8c3RvcCBvZmZzZXQ9IjAlIiBzdG9wLWNvbG9yPSIjMDAwIi8+CiAgICAgICAgICA8c3RvcCBvZmZzZXQ9IjUwJSIgc3RvcC1jb2xvcj0iIzExNCIvPgogICAgICAgICAgPHN0b3Agb2Zmc2V0PSI3MCUiIHN0b3AtY29sb3I9IiMyMjYiLz4KICAgICAgICAgIDxzdG9wIG9mZnNldD0iODUlIiBzdG9wLWNvbG9yPSIjMTE0Ii8+CiAgICAgICAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiMwMDAiLz4KICAgICAgICA8L3JhZGlhbEdyYWRpZW50PgogICAgICAgIDxyYWRpYWxHcmFkaWVudCBpZD0icHVwaWwiIGN4PSI1MCUiIGN5PSI1MCUiIHI9IjUwJSI+CiAgICAgICAgICA8c3RvcCBvZmZzZXQ9IjEwJSIgc3RvcC1jb2xvcj0iIzAwMCIvPgogICAgICAgICAgPHN0b3Agb2Zmc2V0PSI3MCUiIHN0b3AtY29sb3I9IiMwMDIiLz4KICAgICAgICAgIDxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwMCIvPgogICAgICAgIDwvcmFkaWFsR3JhZGllbnQ+CiAgICAgICAgPGZpbHRlciBpZD0idm9pZGdsb3ciPgogICAgICAgICAgPGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMTIiIHJlc3VsdD0iYmx1cjEiLz4KICAgICAgICAgIDxmZUdhdXNzaWFuQmx1ciBzdGREZXZpYXRpb249IjYiIHJlc3VsdD0iYmx1cjIiLz4KICAgICAgICAgIDxmZU1lcmdlPgogICAgICAgICAgICA8ZmVNZXJnZU5vZGUgaW49ImJsdXIxIi8+CiAgICAgICAgICAgIDxmZU1lcmdlTm9kZSBpbj0iYmx1cjIiLz4KICAgICAgICAgICAgPGZlTWVyZ2VOb2RlIGluPSJTb3VyY2VHcmFwaGljIi8+CiAgICAgICAgICA8L2ZlTWVyZ2U+CiAgICAgICAgPC9maWx0ZXI+CiAgICAgICAgPGZpbHRlciBpZD0iY29zbWljIj4KICAgICAgICAgIDxmZVR1cmJ1bGVuY2UgdHlwZT0iZnJhY3RhbE5vaXNlIiBiYXNlRnJlcXVlbmN5PSIwLjciIG51bU9jdGF2ZXM9IjUiIHN0aXRjaFRpbGVzPSJzdGl0Y2giLz4KICAgICAgICAgIDxmZUNvbG9yTWF0cml4IHR5cGU9InNhdHVyYXRlIiB2YWx1ZXM9IjAuMDUiLz4KICAgICAgICA8L2ZpbHRlcj4KICAgICAgPC9kZWZzPgogICAgICA8cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJibGFjayIvPgogICAgICA8cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWx0ZXI9InVybCgjY29zbWljKSIgb3BhY2l0eT0iMC4xNSIvPgogICAgICA8ZyBmaWx0ZXI9InVybCgjdm9pZGdsb3cpIj4KICAgICAgICA8Y2lyY2xlIGN4PSIyNTAiIGN5PSIyNTAiIHI9IjE2MCIgc3Ryb2tlPSIjMzM4IiBzdHJva2Utd2lkdGg9IjAuNSIgZmlsbD0ibm9uZSIgb3BhY2l0eT0iMC4yIj4KICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9InN0cm9rZS1vcGFjaXR5IiB2YWx1ZXM9IjAuMjswLjE7MC4yIiBkdXI9IjhzIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIvPgogICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iciIgdmFsdWVzPSIxNjA7MTgwOzE2MCIgZHVyPSI4cyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiLz4KICAgICAgICA8L2NpcmNsZT4KICAgICAgICA8Y2lyY2xlIGN4PSIyNTAiIGN5PSIyNTAiIHI9IjE0MCIgc3Ryb2tlPSIjMzM4IiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIG9wYWNpdHk9IjAuMyI+CiAgICAgICAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJzdHJva2Utb3BhY2l0eSIgdmFsdWVzPSIwLjM7MC4xOzAuMyIgZHVyPSI3cyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiLz4KICAgICAgICAgIDxhbmltYXRlIGF0dHJpYnV0ZU5hbWU9InIiIHZhbHVlcz0iMTQwOzE1MDsxNDAiIGR1cj0iN3MiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIi8+CiAgICAgICAgPC9jaXJjbGU+CiAgICAgICAgPGNpcmNsZSBjeD0iMjUwIiBjeT0iMjUwIiByPSIxMjAiIHN0cm9rZT0iIzQ0OSIgc3Ryb2tlLXdpZHRoPSIyIiBmaWxsPSJub25lIiBvcGFjaXR5PSIwLjQiPgogICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0ic3Ryb2tlLW9wYWNpdHkiIHZhbHVlcz0iMC40OzAuMjswLjQiIGR1cj0iNnMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIi8+CiAgICAgICAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJyIiB2YWx1ZXM9IjEyMDsxMzA7MTIwIiBkdXI9IjZzIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIvPgogICAgICAgIDwvY2lyY2xlPgogICAgICAgIDxjaXJjbGUgY3g9IjI1MCIgY3k9IjI1MCIgcj0iMTAwIiBzdHJva2U9IiM0NGEiIHN0cm9rZS13aWR0aD0iMjUiIGZpbGw9InVybCgjaXJpcykiPgogICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0ic3Ryb2tlLW9wYWNpdHkiIHZhbHVlcz0iMC45OzAuNDswLjkiIGR1cj0iNXMiIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIi8+CiAgICAgICAgPC9jaXJjbGU+CiAgICAgICAgPGNpcmNsZSBjeD0iMjUwIiBjeT0iMjUwIiByPSI0MCIgZmlsbD0idXJsKCNwdXBpbCkiPgogICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iciIgdmFsdWVzPSI0MDszNTs0MCIgZHVyPSI0cyIgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiLz4KICAgICAgICA8L2NpcmNsZT4KICAgICAgPC9nPgogICAgPC9zdmc+CiAgICA=
Arg [2] : _eliminatedSVG (string): data:image/svg+xml;base64,CiAgICA8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjUwMCIgaGVpZ2h0PSI1MDAiPgogICAgICA8ZGVmcz4KICAgICAgICA8cmFkaWFsR3JhZGllbnQgaWQ9ImVsaW1pcmlzIiBjeD0iNTAlIiBjeT0iNTAlIiByPSI1MCUiPgogICAgICAgICAgPHN0b3Agb2Zmc2V0PSIxMCUiIHN0b3AtY29sb3I9IiMyMDAiLz4KICAgICAgICAgIDxzdG9wIG9mZnNldD0iNzAlIiBzdG9wLWNvbG9yPSIjNDAwIi8+CiAgICAgICAgICA8c3RvcCBvZmZzZXQ9IjkwJSIgc3RvcC1jb2xvcj0iIzYwMCIvPgogICAgICAgICAgPHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjMjAwIi8+CiAgICAgICAgPC9yYWRpYWxHcmFkaWVudD4KICAgICAgICA8ZmlsdGVyIGlkPSJzaGF0dGVyIj4KICAgICAgICAgIDxmZVR1cmJ1bGVuY2UgdHlwZT0idHVyYnVsZW5jZSIgYmFzZUZyZXF1ZW5jeT0iMC4wMzUiIG51bU9jdGF2ZXM9IjUiLz4KICAgICAgICAgIDxmZURpc3BsYWNlbWVudE1hcCBpbj0iU291cmNlR3JhcGhpYyIgc2NhbGU9IjM1Ii8+CiAgICAgICAgPC9maWx0ZXI+CiAgICAgICAgPGZpbHRlciBpZD0iY29sbGFwc2UiPgogICAgICAgICAgPGZlR2F1c3NpYW5CbHVyIHN0ZERldmlhdGlvbj0iMTIiIHJlc3VsdD0iYmx1cjEiLz4KICAgICAgICAgIDxmZUdhdXNzaWFuQmx1ciBzdGREZXZpYXRpb249IjYiIHJlc3VsdD0iYmx1cjIiLz4KICAgICAgICAgIDxmZU1lcmdlPgogICAgICAgICAgICA8ZmVNZXJnZU5vZGUgaW49ImJsdXIxIi8+CiAgICAgICAgICAgIDxmZU1lcmdlTm9kZSBpbj0iYmx1cjIiLz4KICAgICAgICAgICAgPGZlTWVyZ2VOb2RlIGluPSJTb3VyY2VHcmFwaGljIi8+CiAgICAgICAgICA8L2ZlTWVyZ2U+CiAgICAgICAgPC9maWx0ZXI+CiAgICAgIDwvZGVmcz4KICAgICAgPHJlY3Qgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0iYmxhY2siLz4KICAgICAgPGcgZmlsdGVyPSJ1cmwoI2NvbGxhcHNlKSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjUwLDI1MCkiPgogICAgICAgIDxnIGZpbHRlcj0idXJsKCNzaGF0dGVyKSI+CiAgICAgICAgICA8cGF0aCBkPSJNLTEwMCwwIEExMDAsMTAwIDAgMSwxIDEwMCwwIiBzdHJva2U9IiM2MDAiIHN0cm9rZS13aWR0aD0iMjAiIGZpbGw9Im5vbmUiIG9wYWNpdHk9IjAuNSIvPgogICAgICAgICAgPHBhdGggZD0iTTEwMCwwIEExMDAsMTAwIDAgMSwxIC0xMDAsMCIgc3Ryb2tlPSIjNjAwIiBzdHJva2Utd2lkdGg9IjIwIiBmaWxsPSJub25lIiBvcGFjaXR5PSIwLjUiIHRyYW5zZm9ybT0icm90YXRlKDYwKSIvPgogICAgICAgICAgPHBhdGggZD0iTS0xMDAsMCBBMTAwLDEwMCAwIDEsMSAxMDAsMCIgc3Ryb2tlPSIjNjAwIiBzdHJva2Utd2lkdGg9IjIwIiBmaWxsPSJub25lIiBvcGFjaXR5PSIwLjUiIHRyYW5zZm9ybT0icm90YXRlKDEyMCkiLz4KICAgICAgICA8L2c+CiAgICAgICAgPGNpcmNsZSByPSI2MCIgZmlsbD0idXJsKCNlbGltaXJpcykiLz4KICAgICAgPC9nPgogICAgPC9zdmc+CiAgICA=
-----Encoded View---------------
186 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000003e8
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000f00
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000e66
Arg [4] : 646174613a696d6167652f7376672b786d6c3b6261736536342c436941674943
Arg [5] : 413863335a6e494868746247357a50534a6f644852774f693876643364334c6e
Arg [6] : 637a4c6d39795a7938794d4441774c334e325a79496764326c6b64476739496a
Arg [7] : 55774d434967614756705a326830505349314d44416950676f67494341674943
Arg [8] : 41385a47566d637a344b494341674943416749434138636d466b615746735233
Arg [9] : 4a685a476c6c626e516761575139496d6c7961584d6949474e34505349314d43
Arg [10] : 556949474e35505349314d43556949484939496a55774a53492b436941674943
Arg [11] : 4167494341674943413863335276634342765a6d5a7a5a585139496a416c4969
Arg [12] : 427a644739774c574e76624739795053496a4d4441774969382b436941674943
Arg [13] : 4167494341674943413863335276634342765a6d5a7a5a585139496a55774a53
Arg [14] : 4967633352766343316a62327876636a3069497a45784e43497650676f674943
Arg [15] : 4167494341674943416750484e306233416762325a6d63325630505349334d43
Arg [16] : 556949484e3062334174593239736233493949694d794d6a59694c7a344b4943
Arg [17] : 416749434167494341674944787a644739774947396d5a6e4e6c644430694f44
Arg [18] : 556c4969427a644739774c574e76624739795053496a4d5445304969382b4369
Arg [19] : 416749434167494341674943413863335276634342765a6d5a7a5a585139496a
Arg [20] : 45774d43556949484e3062334174593239736233493949694d774d4441694c7a
Arg [21] : 344b4943416749434167494341384c334a685a476c6862456479595752705a57
Arg [22] : 353050676f674943416749434167494478795957527059577848636d466b6157
Arg [23] : 5675644342705a443069634856776157776949474e34505349314d4355694947
Arg [24] : 4e35505349314d43556949484939496a55774a53492b43694167494341674943
Arg [25] : 41674943413863335276634342765a6d5a7a5a585139496a45774a5349676333
Arg [26] : 52766343316a62327876636a3069497a41774d43497650676f67494341674943
Arg [27] : 41674943416750484e306233416762325a6d63325630505349334d4355694948
Arg [28] : 4e3062334174593239736233493949694d774d4449694c7a344b494341674943
Arg [29] : 4167494341674944787a644739774947396d5a6e4e6c644430694d5441774a53
Arg [30] : 4967633352766343316a62327876636a3069497a41774d43497650676f674943
Arg [31] : 41674943416749447776636d466b6157467352334a685a476c6c626e512b4369
Arg [32] : 4167494341674943416750475a706248526c636942705a443069646d39705a47
Arg [33] : 64736233636950676f6749434167494341674943416750475a6c523246316333
Arg [34] : 4e70595735436248567949484e305a45526c646d6c6864476c76626a30694d54
Arg [35] : 496949484a6c6333567364443069596d7831636a45694c7a344b494341674943
Arg [36] : 4167494341674944786d5a55646864584e7a61574675516d78316369427a6447
Arg [37] : 52455a585a705958527062323439496a596949484a6c6333567364443069596d
Arg [38] : 7831636a49694c7a344b4943416749434167494341674944786d5a55316c636d
Arg [39] : 646c50676f67494341674943416749434167494341385a6d564e5a584a6e5a55
Arg [40] : 35765a47556761573439496d4a73645849784969382b43694167494341674943
Arg [41] : 4167494341674944786d5a55316c636d646c546d396b5a534270626a3069596d
Arg [42] : 7831636a49694c7a344b4943416749434167494341674943416750475a6c5457
Arg [43] : 56795a32564f6232526c49476c7550534a546233567959325648636d46776147
Arg [44] : 6c6a4969382b436941674943416749434167494341384c325a6c545756795a32
Arg [45] : 552b4369416749434167494341675043396d615778305a58492b436941674943
Arg [46] : 41674943416750475a706248526c636942705a4430695932397a62576c6a496a
Arg [47] : 344b4943416749434167494341674944786d5a565231636d4a31624756755932
Arg [48] : 556764486c775a5430695a6e4a68593352686245357661584e6c496942695958
Arg [49] : 4e6c526e4a6c6358566c626d4e35505349774c6a6369494735316255396a6447
Arg [50] : 46325a584d39496a556949484e306158526a614652706247567a50534a7a6447
Arg [51] : 6c30593267694c7a344b4943416749434167494341674944786d5a554e766247
Arg [52] : 397954574630636d6c344948523563475539496e4e68644856795958526c4969
Arg [53] : 4232595778315a584d39496a41754d4455694c7a344b49434167494341674943
Arg [54] : 41384c325a706248526c636a344b49434167494341675043396b5a575a7a5067
Arg [55] : 6f674943416749434138636d566a6443423361575230614430694d5441774a53
Arg [56] : 4967614756705a326830505349784d44416c4969426d6157787350534a696247
Arg [57] : 466a6179497650676f674943416749434138636d566a64434233615752306144
Arg [58] : 30694d5441774a534967614756705a326830505349784d44416c4969426d6157
Arg [59] : 78305a584939496e56796243676a5932397a62576c6a4b534967623342685932
Arg [60] : 6c30655430694d4334784e53497650676f6749434167494341385a79426d6157
Arg [61] : 78305a584939496e56796243676a646d39705a47647362336370496a344b4943
Arg [62] : 4167494341674943413859326c795932786c49474e34505349794e5441694947
Arg [63] : 4e35505349794e54416949484939496a45324d434967633352796232746c5053
Arg [64] : 496a4d7a4d344969427a64484a766132557464326c6b64476739496a41754e53
Arg [65] : 49675a6d6c7362443069626d39755a5349676233426859326c30655430694d43
Arg [66] : 3479496a344b49434167494341674943416749447868626d6c745958526c4947
Arg [67] : 463064484a70596e56305a55356862575539496e4e30636d39725a5331766347
Arg [68] : 466a6158523549694232595778315a584d39496a41754d6a73774c6a45374d43
Arg [69] : 34794969426b64584939496a687a496942795a58426c59585244623356756444
Arg [70] : 30696157356b5a575a70626d6c305a53497650676f6749434167494341674943
Arg [71] : 416750474675615731686447556759585230636d6c696458526c546d46745a54
Arg [72] : 306963694967646d46736457567a505349784e6a41374d5467774f7a45324d43
Arg [73] : 49675a4856795053493463794967636d56775a57463051323931626e5139496d
Arg [74] : 6c755a47566d61573570644755694c7a344b4943416749434167494341384c32
Arg [75] : 4e70636d4e735a54344b49434167494341674943413859326c795932786c4947
Arg [76] : 4e34505349794e54416949474e35505349794e54416949484939496a45304d43
Arg [77] : 4967633352796232746c5053496a4d7a4d344969427a64484a76613255746432
Arg [78] : 6c6b64476739496a456949475a7062477739496d3576626d5569494739775957
Arg [79] : 4e7064486b39496a41754d79492b436941674943416749434167494341385957
Arg [80] : 3570625746305a5342686448527961574a316447564f5957316c50534a7a6448
Arg [81] : 4a76613255746233426859326c3065534967646d46736457567a505349774c6a
Arg [82] : 4d374d4334784f7a41754d7949675a4856795053493363794967636d56775a57
Arg [83] : 463051323931626e5139496d6c755a47566d61573570644755694c7a344b4943
Arg [84] : 4167494341674943416749447868626d6c745958526c4947463064484a70596e
Arg [85] : 56305a55356862575539496e496949485a686248566c637a30694d5451774f7a
Arg [86] : 45314d4473784e44416949475231636a30694e334d6949484a6c634756686445
Arg [87] : 4e766457353050534a70626d526c5a6d6c756158526c4969382b436941674943
Arg [88] : 4167494341675043396a61584a6a6247552b4369416749434167494341675047
Arg [89] : 4e70636d4e735a53426a654430694d6a55774969426a655430694d6a55774969
Arg [90] : 4279505349784d6a416949484e30636d39725a543069497a51304f5349676333
Arg [91] : 52796232746c4c5864705a48526f505349794969426d6157787350534a756232
Arg [92] : 356c496942766347466a61585235505349774c6a516950676f67494341674943
Arg [93] : 41674943416750474675615731686447556759585230636d6c696458526c546d
Arg [94] : 46745a543069633352796232746c4c57397759574e7064486b6949485a686248
Arg [95] : 566c637a30694d4334304f7a41754d6a73774c6a516949475231636a30694e6e
Arg [96] : 4d6949484a6c6347566864454e766457353050534a70626d526c5a6d6c756158
Arg [97] : 526c4969382b4369416749434167494341674943413859573570625746305a53
Arg [98] : 42686448527961574a316447564f5957316c50534a7949694232595778315a58
Arg [99] : 4d39496a45794d4473784d7a41374d5449774969426b64584939496a5a7a4969
Arg [100] : 42795a58426c5958524462335675644430696157356b5a575a70626d6c305a53
Arg [101] : 497650676f6749434167494341674944777659326c795932786c50676f674943
Arg [102] : 4167494341674944786a61584a6a6247556759336739496a49314d4349675933
Arg [103] : 6b39496a49314d434967636a30694d5441774969427a64484a76613255394969
Arg [104] : 4d304e47456949484e30636d39725a53313361575230614430694d6a55694947
Arg [105] : 5a7062477739496e56796243676a61584a7063796b6950676f67494341674943
Arg [106] : 41674943416750474675615731686447556759585230636d6c696458526c546d
Arg [107] : 46745a543069633352796232746c4c57397759574e7064486b6949485a686248
Arg [108] : 566c637a30694d4334354f7a41754e4473774c6a6b6949475231636a30694e58
Arg [109] : 4d6949484a6c6347566864454e766457353050534a70626d526c5a6d6c756158
Arg [110] : 526c4969382b4369416749434167494341675043396a61584a6a6247552b4369
Arg [111] : 4167494341674943416750474e70636d4e735a53426a654430694d6a55774969
Arg [112] : 426a655430694d6a557749694279505349304d4349675a6d6c73624430696458
Arg [113] : 4a734b434e776458427062436b6950676f674943416749434167494341675047
Arg [114] : 4675615731686447556759585230636d6c696458526c546d46745a5430696369
Arg [115] : 4967646d46736457567a505349304d44737a4e5473304d4349675a4856795053
Arg [116] : 493063794967636d56775a57463051323931626e5139496d6c755a47566d6157
Arg [117] : 3570644755694c7a344b4943416749434167494341384c324e70636d4e735a54
Arg [118] : 344b49434167494341675043396e50676f67494341675043397a646d632b4369
Arg [119] : 41674943413d0000000000000000000000000000000000000000000000000000
Arg [120] : 000000000000000000000000000000000000000000000000000000000000080a
Arg [121] : 646174613a696d6167652f7376672b786d6c3b6261736536342c436941674943
Arg [122] : 413863335a6e494868746247357a50534a6f644852774f693876643364334c6e
Arg [123] : 637a4c6d39795a7938794d4441774c334e325a79496764326c6b64476739496a
Arg [124] : 55774d434967614756705a326830505349314d44416950676f67494341674943
Arg [125] : 41385a47566d637a344b494341674943416749434138636d466b615746735233
Arg [126] : 4a685a476c6c626e516761575139496d567361573170636d6c7a4969426a6544
Arg [127] : 30694e54416c4969426a655430694e54416c49694279505349314d4355695067
Arg [128] : 6f6749434167494341674943416750484e306233416762325a6d633256305053
Arg [129] : 49784d43556949484e3062334174593239736233493949694d794d4441694c7a
Arg [130] : 344b4943416749434167494341674944787a644739774947396d5a6e4e6c6444
Arg [131] : 30694e7a416c4969427a644739774c574e76624739795053496a4e4441774969
Arg [132] : 382b4369416749434167494341674943413863335276634342765a6d5a7a5a58
Arg [133] : 5139496a6b774a534967633352766343316a62327876636a3069497a59774d43
Arg [134] : 497650676f6749434167494341674943416750484e306233416762325a6d6332
Arg [135] : 5630505349784d44416c4969427a644739774c574e76624739795053496a4d6a
Arg [136] : 41774969382b436941674943416749434167504339795957527059577848636d
Arg [137] : 466b615756756444344b4943416749434167494341385a6d6c73644756794947
Arg [138] : 6c6b50534a7a6147463064475679496a344b4943416749434167494341674944
Arg [139] : 786d5a565231636d4a31624756755932556764486c775a54306964485679596e
Arg [140] : 56735a57356a5a534967596d467a5a555a795a5846315a57356a655430694d43
Arg [141] : 34774d7a5569494735316255396a644746325a584d39496a55694c7a344b4943
Arg [142] : 416749434167494341674944786d5a5552706333427359574e6c625756756445
Arg [143] : 316863434270626a306955323931636d4e6c52334a6863476870597949676332
Arg [144] : 4e6862475539496a4d314969382b4369416749434167494341675043396d6157
Arg [145] : 78305a58492b43694167494341674943416750475a706248526c636942705a44
Arg [146] : 306959323973624746776332556950676f674943416749434167494341675047
Arg [147] : 5a6c5232463163334e70595735436248567949484e305a45526c646d6c686447
Arg [148] : 6c76626a30694d54496949484a6c6333567364443069596d7831636a45694c7a
Arg [149] : 344b4943416749434167494341674944786d5a55646864584e7a61574675516d
Arg [150] : 78316369427a644752455a585a705958527062323439496a596949484a6c6333
Arg [151] : 567364443069596d7831636a49694c7a344b4943416749434167494341674944
Arg [152] : 786d5a55316c636d646c50676f67494341674943416749434167494341385a6d
Arg [153] : 564e5a584a6e5a5535765a47556761573439496d4a73645849784969382b4369
Arg [154] : 41674943416749434167494341674944786d5a55316c636d646c546d396b5a53
Arg [155] : 4270626a3069596d7831636a49694c7a344b4943416749434167494341674943
Arg [156] : 416750475a6c545756795a32564f6232526c49476c7550534a54623356795932
Arg [157] : 5648636d467761476c6a4969382b436941674943416749434167494341384c32
Arg [158] : 5a6c545756795a32552b4369416749434167494341675043396d615778305a58
Arg [159] : 492b4369416749434167494477765a47566d637a344b49434167494341675048
Arg [160] : 4a6c5933516764326c6b64476739496a45774d4355694947686c6157646f6444
Arg [161] : 30694d5441774a5349675a6d6c7362443069596d7868593273694c7a344b4943
Arg [162] : 416749434167504763675a6d6c736447567950534a31636d776f49324e766247
Arg [163] : 786863484e6c4b53496764484a68626e4e6d62334a7450534a30636d46756332
Arg [164] : 78686447556f4d6a55774c4449314d436b6950676f6749434167494341674944
Arg [165] : 786e49475a706248526c636a306964584a734b434e7a61474630644756794b53
Arg [166] : 492b43694167494341674943416749434138634746306143426b50534a4e4c54
Arg [167] : 45774d437777494545784d4441734d544177494441674d537778494445774d43
Arg [168] : 77774969427a64484a766132553949694d324d44416949484e30636d39725a53
Arg [169] : 313361575230614430694d6a416949475a7062477739496d3576626d55694947
Arg [170] : 397759574e7064486b39496a41754e53497650676f6749434167494341674943
Arg [171] : 416750484268644767675a443069545445774d437777494545784d4441734d54
Arg [172] : 4177494441674d537778494330784d4441734d434967633352796232746c5053
Arg [173] : 496a4e6a41774969427a64484a766132557464326c6b64476739496a49774969
Arg [174] : 426d6157787350534a756232356c496942766347466a61585235505349774c6a
Arg [175] : 5569494852795957357a5a6d397962543069636d39305958526c4b4459774b53
Arg [176] : 497650676f6749434167494341674943416750484268644767675a4430695453
Arg [177] : 30784d4441734d4342424d5441774c4445774d434177494445734d5341784d44
Arg [178] : 41734d434967633352796232746c5053496a4e6a41774969427a64484a766132
Arg [179] : 557464326c6b64476739496a49774969426d6157787350534a756232356c4969
Arg [180] : 42766347466a61585235505349774c6a5569494852795957357a5a6d39796254
Arg [181] : 3069636d39305958526c4b4445794d436b694c7a344b49434167494341674943
Arg [182] : 41384c32632b43694167494341674943416750474e70636d4e735a5342795053
Arg [183] : 49324d4349675a6d6c736244306964584a734b434e6c62476c7461584a706379
Arg [184] : 6b694c7a344b49434167494341675043396e50676f67494341675043397a646d
Arg [185] : 632b436941674943413d00000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.