Source Code
Overview
S Balance
0 S
More Info
ContractCreator
Latest 7 from a total of 7 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Set Element Imag... | 17704958 | 13 hrs ago | IN | 0 S | 0.00105694 | ||||
Set Element Imag... | 17704953 | 13 hrs ago | IN | 0 S | 0.00105694 | ||||
Set Element Imag... | 17704947 | 13 hrs ago | IN | 0 S | 0.00105694 | ||||
Set Element Imag... | 17704943 | 13 hrs ago | IN | 0 S | 0.00105694 | ||||
Set Element Imag... | 17704940 | 13 hrs ago | IN | 0 S | 0.00105694 | ||||
Set Element Imag... | 17704935 | 13 hrs ago | IN | 0 S | 0.0010568 | ||||
Set Chibble NFT | 17704587 | 13 hrs ago | IN | 0 S | 0.0000505 |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
ChibbleTokenURIGenerator
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.20; import "@openzeppelin/contracts/utils/Base64.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; interface IChibbleNFT { enum Element { Fire, Water, Earth, Wind, Light, Void } enum Rarity { Common, Uncommon, Rare, Epic } function getChibbleStats(uint256 tokenId) external view returns ( Element element, Rarity rarity, uint256 basePoints, uint256 level, uint256 xp, uint256 wins, uint256 losses, uint256[] memory equippedItems ); function getEffectivePowerScore(uint256 tokenId) external view returns (uint256); function getXPForNextLevel(uint256 tokenId) external view returns (uint256); } struct ElementImageSet { string[10] images; bool isSet; } contract ChibbleTokenURIGenerator is Ownable { using Strings for uint256; IChibbleNFT public chibbleNFT; // Image storage for each element (10 variations each) mapping(uint8 => ElementImageSet) public elementImages; // Track which image variation was assigned to each token mapping(uint256 => uint8) public tokenToImageVariant; // Events event ImageVariantAssigned(uint256 indexed tokenId, uint8 element, uint8 variant); event ElementImagesSet(uint8 indexed element); constructor(address _chibbleNFT) Ownable(msg.sender) { if(_chibbleNFT != address(0)) { chibbleNFT = IChibbleNFT(_chibbleNFT); } } // Admin function to set IPFS images for each element function setElementImages(uint8 element, string[10] calldata ipfsHashes) external onlyOwner { require(element <= 5, "Invalid element"); require(!elementImages[element].isSet, "Element images already set"); for(uint8 i = 0; i < 10; i++) { require(bytes(ipfsHashes[i]).length > 0, "Empty IPFS hash"); elementImages[element].images[i] = ipfsHashes[i]; } elementImages[element].isSet = true; emit ElementImagesSet(element); } // Assign image variant on mint function assignImageVariant(uint256 tokenId, uint8 element) external returns (uint8) { require(msg.sender == address(chibbleNFT), "Only ChibbleNFT can assign"); require(element <= 5, "Invalid element"); require(tokenToImageVariant[tokenId] == 0, "Variant already assigned"); require(elementImages[element].isSet, "Element images not set"); uint8 variant = uint8(uint256(keccak256(abi.encodePacked( block.timestamp, tokenId, block.prevrandao ))) % 10); tokenToImageVariant[tokenId] = variant; emit ImageVariantAssigned(tokenId, element, variant); return variant; } function generateSVG(uint256 tokenId, string memory imageURI) internal view returns (string memory) { ( IChibbleNFT.Element element, IChibbleNFT.Rarity rarity, uint256 basePoints, uint256 level, , // skip xp uint256 wins, uint256 losses, uint256[] memory equippedItems ) = chibbleNFT.getChibbleStats(tokenId); return string(abi.encodePacked( generateSVGHeader(), generateCardBackground(rarity), generateTitleSection(tokenId, rarity), generateImageSection(imageURI), generateEquipmentSection(equippedItems), generateStatsSection(element, level, basePoints, wins, losses), '</svg>' )); } function generateSVGHeader() internal pure returns (string memory) { return string(abi.encodePacked( '<svg width="400" height="560" viewBox="0 0 400 560" xmlns="http://www.w3.org/2000/svg">', '<defs>', '<style type="text/css">@import url("https://fonts.googleapis.com/css2?family=Bungee&display=swap");</style>', generateGradients(), '</defs>' )); } function generateGradients() internal pure returns (string memory) { return string(abi.encodePacked( '<linearGradient id="epicBorder" x1="0%" y1="0%" x2="100%" y2="100%">', '<stop offset="0%" style="stop-color:#FFD700;stop-opacity:1">', '<animate attributeName="stop-color" values="#FFD700;#FFA500;#FFD700" dur="2s" repeatCount="indefinite"/>', '</stop>', '<stop offset="100%" style="stop-color:#FFA500;stop-opacity:1">', '<animate attributeName="stop-color" values="#FFA500;#FFD700;#FFA500" dur="2s" repeatCount="indefinite"/>', '</stop>', '</linearGradient>', '<filter id="equipped-glow">', '<feGaussianBlur stdDeviation="2" result="blur"/>', '<feComposite in="SourceGraphic" in2="blur" operator="over"/>', '</filter>' )); } function generateCardBackground(IChibbleNFT.Rarity rarity) internal pure returns (string memory) { string memory borderStyle = rarity == IChibbleNFT.Rarity.Epic ? 'stroke="url(#epicBorder)"' : 'stroke="#2c4a3e"'; return string(abi.encodePacked( '<rect width="400" height="560" rx="20" fill="#f5efe6"/>', '<rect x="10" y="10" width="380" height="540" rx="15" ', borderStyle, ' stroke-width="4" fill="#ffffff"/>' )); } function generateTitleSection(uint256 tokenId, IChibbleNFT.Rarity rarity) internal pure returns (string memory) { return string(abi.encodePacked( '<rect x="30" y="30" width="340" height="40" rx="10" fill="#2c4a3e"/>', '<text x="40" y="58" font-family="Bungee" font-size="20" fill="#ffffff">Chibble #', tokenId.toString(), '</text>', '<text x="250" y="58" font-family="Bungee" font-size="16" fill="#ffffff">', getRarityString(rarity), '</text>' )); } function generateImageSection(string memory imageURI) internal pure returns (string memory) { return string(abi.encodePacked( '<rect x="40" y="80" width="320" height="320" fill="#f5f5f5" stroke="#2c4a3e" stroke-width="2"/>', '<image x="40" y="80" width="320" height="320" href="', imageURI, '"/>' )); } function generateEquipmentSection(uint256[] memory equippedItems) internal pure returns (string memory) { return string(abi.encodePacked( '<g transform="translate(364, 100)">', generateEquipmentSlot(0, equippedItems.length > 0), generateEquipmentSlot(1, equippedItems.length > 1), generateEquipmentSlot(2, equippedItems.length > 2), '</g>' )); } function generateEquipmentSlot(uint8 slotIndex, bool isEquipped) internal pure returns (string memory) { return string(abi.encodePacked( '<g transform="translate(0,', uint256(slotIndex * 30).toString(), ')">', '<rect width="20" height="20" rx="4" fill="#dcedc1" stroke="#2c4a3e"/>', getEquipmentIcon(slotIndex, isEquipped), '</g>' )); } function getEquipmentIcon(uint8 equipType, bool isEquipped) internal pure returns (string memory) { if (!isEquipped) return ''; if (equipType == 0) { // Weapon return '<path d="M4 4 L16 16 M10 4 L16 4 L16 10" stroke="#2c4a3e" fill="none" stroke-width="2" filter="url(#equipped-glow)"/>'; } else if (equipType == 1) { // Armor return '<path d="M5 5 L15 5 L15 12 L10 15 L5 12 Z" stroke="#2c4a3e" fill="none" stroke-width="2" filter="url(#equipped-glow)"/>'; } else { // Accessory return '<circle cx="10" cy="10" r="5" stroke="#2c4a3e" fill="none" stroke-width="2" filter="url(#equipped-glow)"/>'; } } function generateStatsSection( IChibbleNFT.Element element, uint256 level, uint256 basePoints, uint256 wins, uint256 losses ) internal pure returns (string memory) { return string(abi.encodePacked( generateStatsHeader(element, level), generateBaseStats(basePoints), generateBattleStats(wins, losses) )); } function generateStatsHeader(IChibbleNFT.Element element, uint256 level) internal pure returns (string memory) { return string(abi.encodePacked( '<g transform="translate(40, 410)">', '<rect width="150" height="40" rx="8" fill="#b8c5d6"/>', '<text x="10" y="25" font-family="Bungee" font-size="16" fill="#2c4a3e">LEVEL ', level.toString(), '</text>', '<rect x="170" y="0" width="150" height="40" rx="8" fill="#a8e6cf"/>', '<text x="180" y="25" font-family="Bungee" font-size="16" fill="#2c4a3e">', getElementString(element), '</text>', '</g>' )); } function generateBaseStats(uint256 basePoints) internal pure returns (string memory) { return string(abi.encodePacked( '<g transform="translate(40, 460)">', '<rect width="150" height="30" rx="8" fill="#ffd3b6"/>', '<text x="10" y="20" font-family="Bungee" font-size="12" fill="#2c4a3e">BP: ', basePoints.toString(), '</text>', '</g>' )); } function generateBattleStats(uint256 wins, uint256 losses) internal pure returns (string memory) { return string(abi.encodePacked( '<g transform="translate(40, 500)">', '<rect width="320" height="40" rx="8" fill="#e0e0e0"/>', '<text x="10" y="25" font-family="Bungee" font-size="14">', '<tspan fill="#008000">W: ', wins.toString(), '</tspan>', '<tspan x="160" fill="#FF0000">L: ', losses.toString(), '</tspan>', '</text>', '</g>' )); } function getElementString(IChibbleNFT.Element element) internal pure returns (string memory) { if (element == IChibbleNFT.Element.Fire) return "Fire"; if (element == IChibbleNFT.Element.Water) return "Water"; if (element == IChibbleNFT.Element.Earth) return "Earth"; if (element == IChibbleNFT.Element.Wind) return "Wind"; if (element == IChibbleNFT.Element.Light) return "Light"; return "Void"; } function getRarityString(IChibbleNFT.Rarity rarity) internal pure returns (string memory) { if (rarity == IChibbleNFT.Rarity.Common) return "Common"; if (rarity == IChibbleNFT.Rarity.Uncommon) return "Uncommon"; if (rarity == IChibbleNFT.Rarity.Rare) return "Rare"; return "Epic"; } function tokenURI(uint256 tokenId) external view returns (string memory) { require(address(chibbleNFT) != address(0), "ChibbleNFT not set"); uint8 variant = tokenToImageVariant[tokenId]; require(variant > 0, "Token variant not assigned"); // Get Chibble data ( IChibbleNFT.Element element, IChibbleNFT.Rarity rarity, uint256 basePoints, uint256 level, uint256 xp, uint256 wins, uint256 losses, uint256[] memory equippedItems ) = chibbleNFT.getChibbleStats(tokenId); require(elementImages[uint8(element)].isSet, "Element images not set"); string memory imageURI = elementImages[uint8(element)].images[variant]; // Generate SVG string memory svgImage = generateSVG(tokenId, imageURI); // Get additional data for attributes uint256 effectivePower = chibbleNFT.getEffectivePowerScore(tokenId); uint256 nextLevelXP = chibbleNFT.getXPForNextLevel(tokenId); // Create metadata JSON return string(abi.encodePacked( 'data:application/json;base64,', Base64.encode(bytes(abi.encodePacked( '{', '"name": "Chibble #', tokenId.toString(), '",', '"description": "A mighty Chibble warrior",', '"image": "data:image/svg+xml;base64,', Base64.encode(bytes(svgImage)), '",', '"image_url": "', imageURI, '",', '"attributes": [', '{"trait_type": "Element", "value": "', getElementString(element), '"},', '{"trait_type": "Rarity", "value": "', getRarityString(rarity), '"},', '{"trait_type": "Level", "value": ', level.toString(), '},', '{"trait_type": "Base Points", "value": ', basePoints.toString(), '},', '{"trait_type": "XP", "value": ', xp.toString(), '},', '{"trait_type": "XP Required", "value": ', nextLevelXP.toString(), '},', '{"trait_type": "Power Score", "value": ', effectivePower.toString(), '},', '{"trait_type": "Wins", "value": ', wins.toString(), '},', '{"trait_type": "Losses", "value": ', losses.toString(), '},', '{"trait_type": "Equipment Count", "value": ', equippedItems.length.toString(), '}', ']', '}' ))) )); } function setChibbleNFT(address _chibbleNFT) external onlyOwner { require(_chibbleNFT != address(0), "Invalid address"); chibbleNFT = IChibbleNFT(_chibbleNFT); } }
// 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) (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/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": {} }
[{"inputs":[{"internalType":"address","name":"_chibbleNFT","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"uint8","name":"element","type":"uint8"}],"name":"ElementImagesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"element","type":"uint8"},{"indexed":false,"internalType":"uint8","name":"variant","type":"uint8"}],"name":"ImageVariantAssigned","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"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint8","name":"element","type":"uint8"}],"name":"assignImageVariant","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chibbleNFT","outputs":[{"internalType":"contract IChibbleNFT","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"elementImages","outputs":[{"internalType":"bool","name":"isSet","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_chibbleNFT","type":"address"}],"name":"setChibbleNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"element","type":"uint8"},{"internalType":"string[10]","name":"ipfsHashes","type":"string[10]"}],"name":"setElementImages","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenToImageVariant","outputs":[{"internalType":"uint8","name":"","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":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080346100e357601f612dc238819003918201601f19168301916001600160401b038311848410176100e8578084926020946040528339810103126100e357516001600160a01b038116908190036100e35733156100cd5760008054336001600160a01b0319821681178355604051939290916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3806100b3575b50612cc390816100ff8239f35b600180546001600160a01b031916919091179055386100a6565b631e4fbdf760e01b600052600060045260246000fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe6101c0604052600436101561001357600080fd5b60003560e01c806317033ea0146122b8578063715018a61461225f578063782a4810146122305780638da5cb5b146122075780639ec35298146121de578063c87b56dd14610590578063e31ac76414610417578063e8fff00414610159578063eb6fbbc31461011d5763f2fde38b1461008b57600080fd5b34610118576020366003190112610118576004356001600160a01b03811690819003610118576100b961257f565b801561010257600080546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b600052600060045260246000fd5b600080fd5b346101185760203660031901126101185760ff610138612363565b166000526002602052602060ff600a60406000200154166040519015158152f35b3461011857604036600319011261011857610172612363565b6024359067ffffffffffffffff8211610118578160040191610144369101116101185760ff906101a061257f565b166101ae60058211156124fe565b80600052600260205260ff600a60406000200154166103d25760005b60ff8116600a81101561038e576101e1818561253c565b905015610357576101f2908461253c565b83600052600260205261020983604060002061249e565b9290926103415767ffffffffffffffff821161032b5761022983546124c4565b601f81116102e3575b50600090601f83116001146102795791806001949260ff969460009261026e575b5050600019600383901b1c191690841b1790555b01166101ca565b013590508880610253565b8382526020822091601f198416815b8181106102cb5750926001959392859260ff98968895106102b1575b505050811b019055610267565b0135600019600384901b60f8161c191690558880806102a4565b91936020600181928787013581550195019201610288565b836000526020600020601f840160051c81019160208510610321575b601f0160051c01905b8181106103155750610232565b60008155600101610308565b90915081906102ff565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052600060045260246000fd5b60405162461bcd60e51b815260206004820152600f60248201526e08adae0e8f24092a08ca640d0c2e6d608b1b6044820152606490fd5b82806000526002602052600a604060002001600160ff198254161790557f8f6edc6d1bded7de192a20106afc68dd5b2fdaa1ce918ec7c01d9810e17372f4600080a2005b60405162461bcd60e51b815260206004820152601a60248201527f456c656d656e7420696d6167657320616c7265616479207365740000000000006044820152606490fd5b346101185760403660031901126101185760043560243560ff8116809103610118576001546001600160a01b0316330361054b5761045860058211156124fe565b81600052600360205260ff6040600020541661050657602091816000526002835261048d60ff600a6040600020015416612459565b7fac91436ae04b3b09446a3a44482b73204f66b88802eb4f5c62eb4a6e73bb2834604060ff600a8251878101904282528685820152446060820152606081526104d7608082612373565b5190200616938360005260038652816000208560ff1982541617905581519081528486820152a2604051908152f35b60405162461bcd60e51b815260206004820152601860248201527f56617269616e7420616c72656164792061737369676e656400000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601a60248201527f4f6e6c792043686962626c654e46542063616e2061737369676e0000000000006044820152606490fd5b34610118576020366003190112610118576001546001600160a01b031660a0819052156121a457600435600052600360205260ff60406000205416801561215f5760405190630102953760e71b8252600435600483015260008260248160a0515afa80156121535760009283918490859286918760e05287610120528761014052612120575b50600686101561210a5761065860ff87169586600052600260205261064560ff600a6040600020015416612459565b600096875260026020526040872061249e565b50604051610180528581549161066d836124c4565b928361018051526001811690816000146120e257506001146120a4575b5061069f915061018051900361018051612373565b604051630102953760e71b81526004356004820152858160248160a0515afa6101a0526101a0511561209957859086908791889289928a908b610160526101a05161205f575b5090610b2891610b49600760ec604051602081017f3c6c696e6561724772616469656e742069643d2265706963426f72646572222081527f78313d223025222079313d223025222078323d2231303025222079323d2231306040830152631812911f60e11b60608301527f3c73746f70206f66667365743d22302522207374796c653d2273746f702d636f60648301527f6c6f723a234646443730303b73746f702d6f7061636974793a31223e0000000060848301527f3c616e696d617465206174747269627574654e616d653d2273746f702d636f6c60a08301527f6f72222076616c7565733d22234646443730303b234646413530303b2346464460c08301527f37303022206475723d2232732220726570656174436f756e743d22696e64656660e08301526734b734ba3291179f60c11b610100830152661e17b9ba37b81f60c91b6101088301527f3c73746f70206f66667365743d223130302522207374796c653d2273746f702d61010f8301527f636f6c6f723a234646413530303b73746f702d6f7061636974793a31223e000061012f8301527f3c616e696d617465206174747269627574654e616d653d2273746f702d636f6c61014d8301527f6f72222076616c7565733d22234646413530303b234646443730303b2346464161016d8301527f35303022206475723d2232732220726570656174436f756e743d22696e64656661018d8301526734b734ba3291179f60c11b6101ad830152661e17b9ba37b81f60c91b6101b5830152701e17b634b732b0b923b930b234b2b73a1f60791b6101bc8301527f3c66696c7465722069643d2265717569707065642d676c6f77223e00000000006101cd8301527f3c6665476175737369616e426c757220737464446576696174696f6e3d2232226101e88301526f103932b9bab63a1e9131363ab911179f60811b6102088301527f3c6665436f6d706f7369746520696e3d22536f757263654772617068696322206102188301527f696e323d22626c757222206f70657261746f723d226f766572222f3e00000000610238830152681e17b334b63a32b91f60b91b61025483015261023d8252610a0b61025d83612373565b6040519788927f3c7376672077696474683d2234303022206865696768743d223536302220766960208501527f6577426f783d2230203020343030203536302220786d6c6e733d22687474703a60408501527f2f2f7777772e77332e6f72672f323030302f737667223e0000000000000000006060850152651e3232b3399f60d11b60778501527f3c7374796c6520747970653d22746578742f637373223e40696d706f72742075607d8501527f726c282268747470733a2f2f666f6e74732e676f6f676c65617069732e636f6d609d8501527f2f637373323f66616d696c793d42756e67656526616d703b646973706c61793d60bd8501526e39bbb0b811149d9e17b9ba3cb6329f60891b60dd85015251809285850190612340565b8101661e17b232b3399f60c91b838201520301601819810186520184612373565b600484101561204b578b610100526003841460001461201757604051610b70604082612373565b601981527f7374726f6b653d2275726c282365706963426f726465722922000000000000006020820152610100525b60405160c05260c0516020017f3c726563742077696474683d2234303022206865696768743d22353630222072905260c0516040017f783d223230222066696c6c3d2223663565666536222f3e000000000000000000905260c0516057017f3c7265637420783d2231302220793d223130222077696474683d22333830222090527403432b4b3b43a1e911a9a181110393c1e91189a911605d1b60c05160770152610100515160c051608c01816101005160200191610c5d92612340565b60c05101608c81017f207374726f6b652d77696474683d2234222066696c6c3d222366666666666622905260ac810161179f60f11b905260c0519003608c016002810160c0515260220160c05190610cb491612373565b610cbf6004356125f6565b93610cc9906128b6565b604080517f3c7265637420783d2233302220793d223330222077696474683d2233343022206020808301919091527f6865696768743d223430222072783d223130222066696c6c3d2223326334613392820192909252633291179f60e11b60608201527f3c7465787420783d2234302220793d2235382220666f6e742d66616d696c793d60648201527f2242756e6765652220666f6e742d73697a653d223230222066696c6c3d22236660848201526f6666666666223e43686962626c65202360801b60a482015286519096879392610da991839160b487019101612340565b661e17ba32bc3a1f60c91b60b4918401918201527f3c7465787420783d223235302220793d2235382220666f6e742d66616d696c7960bb8201527f3d2242756e6765652220666f6e742d73697a653d223136222066696c6c3d222360db82015267333333333333111f60c11b60fb820152815191610e31908390610103840190602001612340565b0160b401604f8101661e17ba32bc3a1f60c91b905203604f0160181981018552600701610e5e9085612373565b60405194602086017f3c7265637420783d2234302220793d223830222077696474683d2233323022209052604086017f6865696768743d22333230222066696c6c3d222366356635663522207374726f9052606086017f6b653d222332633461336522207374726f6b652d77696474683d2232222f3e009052607f86017f3c696d61676520783d2234302220793d223830222077696474683d2233323022905273103432b4b3b43a1e911999181110343932b31e9160611b609f87015285610180515160b38201816101805160200191610f3792612340565b81016211179f60e91b60b38201520360b301601c1981018752600301610f5d9087612373565b61016051511515968d610f6f816125f6565b98610f7a9082612a7c565b906040518092602082019b790f19c81d1c985b9cd99bdc9b4f489d1c985b9cdb185d194a0c0b60321b8d5280519081603a85019160200191610fbb92612340565b6214911f60e91b603a918401918201527f3c726563742077696474683d22323022206865696768743d223230222072783d603d8201527f2234222066696c6c3d222364636564633122207374726f6b653d222332633461605d8201526419b291179f60d91b607d82015281519161103b9083906082840190602001612340565b01603a0160488101631e17b39f60e11b905203604801601b19810183526004016110659083612373565b6101605151600110611077601e6125f6565b90611083906001612a7c565b9060405180926020820192790f19c81d1c985b9cd99bdc9b4f489d1c985b9cdb185d194a0c0b60321b845280519081603a850191602001916110c492612340565b6214911f60e91b603a918401918201527f3c726563742077696474683d22323022206865696768743d223230222072783d603d8201527f2234222066696c6c3d222364636564633122207374726f6b653d222332633461605d8201526419b291179f60d91b607d8201528151916111449083906082840190602001612340565b01603a0160488101631e17b39f60e11b905203604801601b198101835260040161116e9083612373565b61016051516002109250611182603c6125f6565b9261118e906002612a7c565b9160405180936020820195790f19c81d1c985b9cd99bdc9b4f489d1c985b9cdb185d194a0c0b60321b875280519081603a850191602001916111cf92612340565b6214911f60e91b603a918401918201527f3c726563742077696474683d22323022206865696768743d223230222072783d603d8201527f2234222066696c6c3d222364636564633122207374726f6b653d222332633461605d8201526419b291179f60d91b607d82015281519161124f9083906082840190602001612340565b01603a0160488101631e17b39f60e11b905203604801601b19810184526004016112799084612373565b6040519c8d95602087017f3c67207472616e73666f726d3d227472616e736c617465283336342c2031303090526214911f60e91b6040880152519081604388016112c292612340565b850190519182604383016112d592612340565b016043019182915180936112e892612340565b01631e17b39f60e11b815203601b19810189526004016113089089612373565b611311906125f6565b9761131b906127aa565b926040518094602082019a7f3c67207472616e73666f726d3d227472616e736c6174652834302c20343130298c5261111f60f11b6040840152604283017f3c726563742077696474683d2231353022206865696768743d223430222072789052741e911c11103334b6361e9111b11c319ab21b11179f60591b6062840152607783017f3c7465787420783d2231302220793d2232352220666f6e742d66616d696c793d9052609783017f2242756e6765652220666f6e742d73697a653d223136222066696c6c3d22233290526c0319a3099b2911f2622ab22a61609d1b60b78401528051908160c48501916020019161141392612340565b661e17ba32bc3a1f60c91b60c4918401918201527f3c7265637420783d223137302220793d2230222077696474683d22313530222060cb8201527f6865696768743d223430222072783d2238222066696c6c3d222361386536636660eb8201526211179f60e91b61010b8201527f3c7465787420783d223138302220793d2232352220666f6e742d66616d696c7961010e8201527f3d2242756e6765652220666f6e742d73697a653d223136222066696c6c3d222361012e8201526719319a3099b2911f60c11b61014e8201528151916114f7908390610156840190602001612340565b0160c40160928101661e17ba32bc3a1f60c91b905260998101631e17b39f60e11b90520360920160141981018552600b016115329085612373565b61153b906125f6565b604051918260208101927f3c67207472616e73666f726d3d227472616e736c6174652834302c2034363029845261111f60f11b6040830152604282017f3c726563742077696474683d2231353022206865696768743d223330222072789052741e911c11103334b6361e9111b3333219b11b11179f60591b6062830152607782017f3c7465787420783d2231302220793d2232302220666f6e742d66616d696c793d9052609782017f2242756e6765652220666f6e742d73697a653d223132222066696c6c3d22233290526a0319a3099b2911f21281d160ad1b60b78301528051908160c28401916020019161163092612340565b810160c28101661e17ba32bc3a1f60c91b905260c98101631e17b39f60e11b90520360c20160141981018452600b016116699084612373565b611672906125f6565b9261167c906125f6565b91604051809360208201957f3c67207472616e73666f726d3d227472616e736c6174652834302c2035303029875261111f60f11b6040840152604283017f3c726563742077696474683d2233323022206865696768743d223430222072789052741e911c11103334b6361e9111b2983298329811179f60591b6062840152607783017f3c7465787420783d2231302220793d2232352220666f6e742d66616d696c793d9052609783017f2242756e6765652220666f6e742d73697a653d223134223e0000000000000000905260af83017f3c747370616e2066696c6c3d2223303038303030223e573a200000000000000090528051908160c88501916020019161178592612340565b671e17ba39b830b71f60c11b60c8918401918201527f3c747370616e20783d22313630222066696c6c3d2223464630303030223e4c3a60d0820152600160fd1b60f08201528151916117e090839060f1840190602001612340565b671e17ba39b830b71f60c11b910160f1810191909152661e17ba32bc3a1f60c91b60f9820152631e17b39f60e11b6101008201520360e481018452611829906101040184612373565b604051998a955190816020880161183f92612340565b8501905191826020830161185292612340565b0160200191829151809361186592612340565b0103601f19810186526118789086612373565b60405160805280519081608051602001916020019161189692612340565b6080510160c0515190602081018260c051602001916118b492612340565b016020018082516020819401916118ca92612340565b018082516020819401916118dd92612340565b018082516020819401916118f092612340565b0180825160208194019161190392612340565b01651e17b9bb339f60d11b815260805190036019198101608051526006016080519061192e91612373565b60405163186e325160e11b81526004356004820152808060a0515a92602491602094fa90811561200c578691611fd6575b50604051634220be2360e01b8152600435600482015260208160248160a0515afa968715611fca578097611f90575b505060043561199c906125f6565b956080516119a990612740565b976119b3906127aa565b956119bd906128b6565b946119c7906125f6565b936119d1906125f6565b926119db906125f6565b906119e5906125f6565b916119ef906125f6565b9260e0516119fc906125f6565b9461012051611a0a906125f6565b966101405151611a19906125f6565b986040519b8c809c60208201607b60f81b905271226e616d65223a202243686962626c65202360701b6021830152805160338193019160200191611a5c92612340565b61088b60f21b6033918e01918201527f226465736372697074696f6e223a202241206d69676874792043686962626c65603582015269081dd85c9c9a5bdc888b60b21b60558201527f22696d616765223a2022646174613a696d6167652f7376672b786d6c3b626173605f82015263194d8d0b60e21b607f820152815191611aed9083906083840190602001612340565b0160330161088b60f21b60508201526d1134b6b0b3b2afbab936111d101160911b605282015261018051519060608101826101805160200191611b2f92612340565b61088b60f21b606092909101918201526e2261747472696275746573223a205b60881b60628201527f7b2274726169745f74797065223a2022456c656d656e74222c202276616c7565607182015263111d101160e11b60918201528151916050820191611ba491849160950190602001612340565b0160100162089f4b60ea1b6035820152603881017f7b2274726169745f74797065223a2022526172697479222c202276616c7565229052621d101160e91b605882015281519182605b83019160200191611bfd92612340565b0160350162089f4b60ea1b6026820152602981017f7b2274726169745f74797065223a20224c6576656c222c202276616c7565223a905260498101600160fd1b905281519182604a83019160200191611c5592612340565b0160260160248101611f4b60f21b9052602681017f7b2274726169745f74797065223a20224261736520506f696e7473222c202276905266030b63ab2911d160cd1b604682015281519182604d83019160200191611cb292612340565b0160240160298101611f4b60f21b9052602b81017f7b2274726169745f74797065223a20225850222c202276616c7565223a200000905281519182604983019160200191611cff92612340565b0160290160208101611f4b60f21b9052602281017f7b2274726169745f74797065223a20225850205265717569726564222c202276905266030b63ab2911d160cd1b604282015281519182604983019160200191611d5c92612340565b0160200160298101611f4b60f21b9052602b81017f7b2274726169745f74797065223a2022506f7765722053636f7265222c202276905266030b63ab2911d160cd1b604b82015281519182605283019160200191611db992612340565b0160290160298101611f4b60f21b9052602b81017f7b2274726169745f74797065223a202257696e73222c202276616c7565223a20905281519182604b83019160200191611e0692612340565b0160290160228101611f4b60f21b9052602481017f7b2274726169745f74797065223a20224c6f73736573222c202276616c7565229052604481016101d160f51b905281519182604683019160200191611e5f92612340565b0160220160248101611f4b60f21b9052602681017f7b2274726169745f74797065223a202245717569706d656e7420436f756e742290526a01610113b30b63ab2911d160ad1b604682015281519182605183019160200191611ec092612340565b01602401602d8101607d60f81b9052602e8101605d60f81b9052602f8101607d60f81b905203602d01601c1981018252600301611efd9082612373565b611f0690612740565b6040518060208101927f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000845280519081603d84019160200191611f4892612340565b810103603d01601f1981018252611f5f9082612373565b6040519182916020835251908160208401528160408401611f7f92612340565b601f1990601f011681010360400190f35b909196506020823d602011611fc2575b81611fad60209383612373565b81010312611fbf57505194878061198e565b80fd5b3d9150611fa0565b604051903d90823e3d90fd5b90506020813d602011612004575b81611ff160209383612373565b8101031261200057518761195f565b8580fd5b3d9150611fe4565b6040513d88823e3d90fd5b604051612025604082612373565b601081526f39ba3937b5b29e911199319a3099b29160811b602082015261010052610b9f565b634e487b7160e01b8c52602160045260248cfd5b9350505050610b28925061208591503d8089833e61207d8183612373565b810190612395565b6101605295969295909493929091506106e5565b6040513d87823e3d90fd5b8752506020862086905b8282106120c957506101805161069f9250016020018861068a565b60018160209254838561018051010152019101906120ae565b90506020925061069f93915060ff191682610180510152151560051b6101805101018861068a565b634e487b7160e01b600052602160045260246000fd5b935050505061213991923d8091833e61207d8183612373565b60e092909252610120526101405293949390919086610616565b6040513d6000823e3d90fd5b60405162461bcd60e51b815260206004820152601a60248201527f546f6b656e2076617269616e74206e6f742061737369676e65640000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601260248201527110da1a58989b19539195081b9bdd081cd95d60721b6044820152606490fd5b34610118576000366003190112610118576001546040516001600160a01b039091168152602090f35b34610118576000366003190112610118576000546040516001600160a01b039091168152602090f35b34610118576020366003190112610118576004356000526003602052602060ff60406000205416604051908152f35b346101185760003660031901126101185761227861257f565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610118576020366003190112610118576004356001600160a01b03811690819003610118576122e661257f565b8015612309576bffffffffffffffffffffffff60a01b6001541617600155600080f35b60405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606490fd5b60005b8381106123535750506000910152565b8181015183820152602001612343565b6004359060ff8216820361011857565b90601f8019910116810190811067ffffffffffffffff82111761032b57604052565b9190610100838203126101185782516006811015610118579260208101516004811015610118579260408201519260608301519260808101519260a08201519260c08301519260e08101519067ffffffffffffffff821161011857019080601f830112156101185781519167ffffffffffffffff831161032b578260051b90604051936124256020840186612373565b845260208085019282010192831161011857602001905b8282106124495750505090565b815181526020918201910161243c565b1561246057565b60405162461bcd60e51b8152602060048201526016602482015275115b195b595b9d081a5b5859d95cc81b9bdd081cd95d60521b6044820152606490fd5b600a8210156124ae570190600090565b634e487b7160e01b600052603260045260246000fd5b90600182811c921680156124f4575b60208310146124de57565b634e487b7160e01b600052602260045260246000fd5b91607f16916124d3565b1561250557565b60405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a5908195b195b595b9d608a1b6044820152606490fd5b90600a8110156124ae5760051b81013590601e198136030182121561011857019081359167ffffffffffffffff8311610118576020018236038113610118579190565b6000546001600160a01b0316330361259357565b63118cdaa760e01b6000523360045260246000fd5b67ffffffffffffffff811161032b57601f01601f191660200190565b906125ce826125a8565b6125db6040519182612373565b82815280926125ec601f19916125a8565b0190602036910137565b8060009172184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b82101561271d575b806d04ee2d6d415b85acef8100000000600a921015612702575b662386f26fc100008110156126ee575b6305f5e1008110156126dd575b6127108110156126ce575b60648110156126c0575b10156126b5575b600a602161267c600185016125c4565b938401015b60001901916f181899199a1a9b1b9c1cb0b131b232b360811b8282061a83530480156126b057600a9091612681565b505090565b60019091019061266c565b606460029104930192612665565b6127106004910493019261265b565b6305f5e10060089104930192612650565b662386f26fc1000060109104930192612643565b6d04ee2d6d415b85acef810000000060209104930192612633565b506040915072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8104612619565b6040516127a791612752606083612373565b604082527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208301527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f604083015261296a565b90565b600681101561210a5780156128935760006001821461286d5750600281146128495760009060038114612825576004915014612802576040516127ee604082612373565b6004815263159bda5960e21b602082015290565b604051612810604082612373565b6005815264131a59da1d60da1b602082015290565b5050604051612835604082612373565b600481526315da5b9960e21b602082015290565b50604051612858604082612373565b600581526408ac2e4e8d60db1b602082015290565b5050604080519061287e9082612373565b60058152642bb0ba32b960d91b602082015290565b506040516128a2604082612373565b60048152634669726560e01b602082015290565b600481101561210a578015612945576000906001811461291d5760029150146128fb576040516128e7604082612373565b60048152634570696360e01b602082015290565b604051612909604082612373565b60048152635261726560e01b602082015290565b505060405161292d604082612373565b60088152672ab731b7b6b6b7b760c11b602082015290565b50604051612954604082612373565b600681526521b7b6b6b7b760d11b602082015290565b919091805115612a6457805160028101809111612a4e5760039004600281901b906001600160fe1b03811603612a4e576129a3906125c4565b9060208201908081518201956020870190815192600083525b888110612a0057505060039394959650525106806001146129ed576002146129e2575090565b603d90600019015390565b50603d9081600019820153600119015390565b600360049199969901986001603f8b5182828260121c16870101518453828282600c1c16870101518385015382828260061c16870101516002850153168401015160038201530194976129bc565b634e487b7160e01b600052601160045260246000fd5b509050604051612a75602082612373565b6000815290565b9015612c7e5760ff1680612b305750604051612a9960a082612373565b607581527f3c7061746820643d224d342034204c3136203136204d31302034204c3136203460208201527f204c313620313022207374726f6b653d2223326334613365222066696c6c3d2260408201527f6e6f6e6522207374726f6b652d77696474683d2232222066696c7465723d227560608201527439361411b2b8bab4b83832b216b3b637bb9491179f60591b608082015290565b600103612be457604051612b4560a082612373565b607781527f3c7061746820643d224d352035204c31352035204c3135203132204c3130203160208201527f35204c35203132205a22207374726f6b653d2223326334613365222066696c6c60408201527f3d226e6f6e6522207374726f6b652d77696474683d2232222066696c7465723d60608201527f2275726c282365717569707065642d676c6f7729222f3e000000000000000000608082015290565b604051612bf260a082612373565b606a81527f3c636972636c652063783d223130222063793d2231302220723d22352220737460208201527f726f6b653d2223326334613365222066696c6c3d226e6f6e6522207374726f6b60408201527f652d77696474683d2232222066696c7465723d2275726c2823657175697070656060820152693216b3b637bb9491179f60b11b608082015290565b50604051612a7560208261237356fea26469706673582212204015f025ddef702d34cc3388f6b468835fcf8880565fabca200c9d3670714f1864736f6c634300081c00330000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6101c0604052600436101561001357600080fd5b60003560e01c806317033ea0146122b8578063715018a61461225f578063782a4810146122305780638da5cb5b146122075780639ec35298146121de578063c87b56dd14610590578063e31ac76414610417578063e8fff00414610159578063eb6fbbc31461011d5763f2fde38b1461008b57600080fd5b34610118576020366003190112610118576004356001600160a01b03811690819003610118576100b961257f565b801561010257600080546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b600052600060045260246000fd5b600080fd5b346101185760203660031901126101185760ff610138612363565b166000526002602052602060ff600a60406000200154166040519015158152f35b3461011857604036600319011261011857610172612363565b6024359067ffffffffffffffff8211610118578160040191610144369101116101185760ff906101a061257f565b166101ae60058211156124fe565b80600052600260205260ff600a60406000200154166103d25760005b60ff8116600a81101561038e576101e1818561253c565b905015610357576101f2908461253c565b83600052600260205261020983604060002061249e565b9290926103415767ffffffffffffffff821161032b5761022983546124c4565b601f81116102e3575b50600090601f83116001146102795791806001949260ff969460009261026e575b5050600019600383901b1c191690841b1790555b01166101ca565b013590508880610253565b8382526020822091601f198416815b8181106102cb5750926001959392859260ff98968895106102b1575b505050811b019055610267565b0135600019600384901b60f8161c191690558880806102a4565b91936020600181928787013581550195019201610288565b836000526020600020601f840160051c81019160208510610321575b601f0160051c01905b8181106103155750610232565b60008155600101610308565b90915081906102ff565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052600060045260246000fd5b60405162461bcd60e51b815260206004820152600f60248201526e08adae0e8f24092a08ca640d0c2e6d608b1b6044820152606490fd5b82806000526002602052600a604060002001600160ff198254161790557f8f6edc6d1bded7de192a20106afc68dd5b2fdaa1ce918ec7c01d9810e17372f4600080a2005b60405162461bcd60e51b815260206004820152601a60248201527f456c656d656e7420696d6167657320616c7265616479207365740000000000006044820152606490fd5b346101185760403660031901126101185760043560243560ff8116809103610118576001546001600160a01b0316330361054b5761045860058211156124fe565b81600052600360205260ff6040600020541661050657602091816000526002835261048d60ff600a6040600020015416612459565b7fac91436ae04b3b09446a3a44482b73204f66b88802eb4f5c62eb4a6e73bb2834604060ff600a8251878101904282528685820152446060820152606081526104d7608082612373565b5190200616938360005260038652816000208560ff1982541617905581519081528486820152a2604051908152f35b60405162461bcd60e51b815260206004820152601860248201527f56617269616e7420616c72656164792061737369676e656400000000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601a60248201527f4f6e6c792043686962626c654e46542063616e2061737369676e0000000000006044820152606490fd5b34610118576020366003190112610118576001546001600160a01b031660a0819052156121a457600435600052600360205260ff60406000205416801561215f5760405190630102953760e71b8252600435600483015260008260248160a0515afa80156121535760009283918490859286918760e05287610120528761014052612120575b50600686101561210a5761065860ff87169586600052600260205261064560ff600a6040600020015416612459565b600096875260026020526040872061249e565b50604051610180528581549161066d836124c4565b928361018051526001811690816000146120e257506001146120a4575b5061069f915061018051900361018051612373565b604051630102953760e71b81526004356004820152858160248160a0515afa6101a0526101a0511561209957859086908791889289928a908b610160526101a05161205f575b5090610b2891610b49600760ec604051602081017f3c6c696e6561724772616469656e742069643d2265706963426f72646572222081527f78313d223025222079313d223025222078323d2231303025222079323d2231306040830152631812911f60e11b60608301527f3c73746f70206f66667365743d22302522207374796c653d2273746f702d636f60648301527f6c6f723a234646443730303b73746f702d6f7061636974793a31223e0000000060848301527f3c616e696d617465206174747269627574654e616d653d2273746f702d636f6c60a08301527f6f72222076616c7565733d22234646443730303b234646413530303b2346464460c08301527f37303022206475723d2232732220726570656174436f756e743d22696e64656660e08301526734b734ba3291179f60c11b610100830152661e17b9ba37b81f60c91b6101088301527f3c73746f70206f66667365743d223130302522207374796c653d2273746f702d61010f8301527f636f6c6f723a234646413530303b73746f702d6f7061636974793a31223e000061012f8301527f3c616e696d617465206174747269627574654e616d653d2273746f702d636f6c61014d8301527f6f72222076616c7565733d22234646413530303b234646443730303b2346464161016d8301527f35303022206475723d2232732220726570656174436f756e743d22696e64656661018d8301526734b734ba3291179f60c11b6101ad830152661e17b9ba37b81f60c91b6101b5830152701e17b634b732b0b923b930b234b2b73a1f60791b6101bc8301527f3c66696c7465722069643d2265717569707065642d676c6f77223e00000000006101cd8301527f3c6665476175737369616e426c757220737464446576696174696f6e3d2232226101e88301526f103932b9bab63a1e9131363ab911179f60811b6102088301527f3c6665436f6d706f7369746520696e3d22536f757263654772617068696322206102188301527f696e323d22626c757222206f70657261746f723d226f766572222f3e00000000610238830152681e17b334b63a32b91f60b91b61025483015261023d8252610a0b61025d83612373565b6040519788927f3c7376672077696474683d2234303022206865696768743d223536302220766960208501527f6577426f783d2230203020343030203536302220786d6c6e733d22687474703a60408501527f2f2f7777772e77332e6f72672f323030302f737667223e0000000000000000006060850152651e3232b3399f60d11b60778501527f3c7374796c6520747970653d22746578742f637373223e40696d706f72742075607d8501527f726c282268747470733a2f2f666f6e74732e676f6f676c65617069732e636f6d609d8501527f2f637373323f66616d696c793d42756e67656526616d703b646973706c61793d60bd8501526e39bbb0b811149d9e17b9ba3cb6329f60891b60dd85015251809285850190612340565b8101661e17b232b3399f60c91b838201520301601819810186520184612373565b600484101561204b578b610100526003841460001461201757604051610b70604082612373565b601981527f7374726f6b653d2275726c282365706963426f726465722922000000000000006020820152610100525b60405160c05260c0516020017f3c726563742077696474683d2234303022206865696768743d22353630222072905260c0516040017f783d223230222066696c6c3d2223663565666536222f3e000000000000000000905260c0516057017f3c7265637420783d2231302220793d223130222077696474683d22333830222090527403432b4b3b43a1e911a9a181110393c1e91189a911605d1b60c05160770152610100515160c051608c01816101005160200191610c5d92612340565b60c05101608c81017f207374726f6b652d77696474683d2234222066696c6c3d222366666666666622905260ac810161179f60f11b905260c0519003608c016002810160c0515260220160c05190610cb491612373565b610cbf6004356125f6565b93610cc9906128b6565b604080517f3c7265637420783d2233302220793d223330222077696474683d2233343022206020808301919091527f6865696768743d223430222072783d223130222066696c6c3d2223326334613392820192909252633291179f60e11b60608201527f3c7465787420783d2234302220793d2235382220666f6e742d66616d696c793d60648201527f2242756e6765652220666f6e742d73697a653d223230222066696c6c3d22236660848201526f6666666666223e43686962626c65202360801b60a482015286519096879392610da991839160b487019101612340565b661e17ba32bc3a1f60c91b60b4918401918201527f3c7465787420783d223235302220793d2235382220666f6e742d66616d696c7960bb8201527f3d2242756e6765652220666f6e742d73697a653d223136222066696c6c3d222360db82015267333333333333111f60c11b60fb820152815191610e31908390610103840190602001612340565b0160b401604f8101661e17ba32bc3a1f60c91b905203604f0160181981018552600701610e5e9085612373565b60405194602086017f3c7265637420783d2234302220793d223830222077696474683d2233323022209052604086017f6865696768743d22333230222066696c6c3d222366356635663522207374726f9052606086017f6b653d222332633461336522207374726f6b652d77696474683d2232222f3e009052607f86017f3c696d61676520783d2234302220793d223830222077696474683d2233323022905273103432b4b3b43a1e911999181110343932b31e9160611b609f87015285610180515160b38201816101805160200191610f3792612340565b81016211179f60e91b60b38201520360b301601c1981018752600301610f5d9087612373565b61016051511515968d610f6f816125f6565b98610f7a9082612a7c565b906040518092602082019b790f19c81d1c985b9cd99bdc9b4f489d1c985b9cdb185d194a0c0b60321b8d5280519081603a85019160200191610fbb92612340565b6214911f60e91b603a918401918201527f3c726563742077696474683d22323022206865696768743d223230222072783d603d8201527f2234222066696c6c3d222364636564633122207374726f6b653d222332633461605d8201526419b291179f60d91b607d82015281519161103b9083906082840190602001612340565b01603a0160488101631e17b39f60e11b905203604801601b19810183526004016110659083612373565b6101605151600110611077601e6125f6565b90611083906001612a7c565b9060405180926020820192790f19c81d1c985b9cd99bdc9b4f489d1c985b9cdb185d194a0c0b60321b845280519081603a850191602001916110c492612340565b6214911f60e91b603a918401918201527f3c726563742077696474683d22323022206865696768743d223230222072783d603d8201527f2234222066696c6c3d222364636564633122207374726f6b653d222332633461605d8201526419b291179f60d91b607d8201528151916111449083906082840190602001612340565b01603a0160488101631e17b39f60e11b905203604801601b198101835260040161116e9083612373565b61016051516002109250611182603c6125f6565b9261118e906002612a7c565b9160405180936020820195790f19c81d1c985b9cd99bdc9b4f489d1c985b9cdb185d194a0c0b60321b875280519081603a850191602001916111cf92612340565b6214911f60e91b603a918401918201527f3c726563742077696474683d22323022206865696768743d223230222072783d603d8201527f2234222066696c6c3d222364636564633122207374726f6b653d222332633461605d8201526419b291179f60d91b607d82015281519161124f9083906082840190602001612340565b01603a0160488101631e17b39f60e11b905203604801601b19810184526004016112799084612373565b6040519c8d95602087017f3c67207472616e73666f726d3d227472616e736c617465283336342c2031303090526214911f60e91b6040880152519081604388016112c292612340565b850190519182604383016112d592612340565b016043019182915180936112e892612340565b01631e17b39f60e11b815203601b19810189526004016113089089612373565b611311906125f6565b9761131b906127aa565b926040518094602082019a7f3c67207472616e73666f726d3d227472616e736c6174652834302c20343130298c5261111f60f11b6040840152604283017f3c726563742077696474683d2231353022206865696768743d223430222072789052741e911c11103334b6361e9111b11c319ab21b11179f60591b6062840152607783017f3c7465787420783d2231302220793d2232352220666f6e742d66616d696c793d9052609783017f2242756e6765652220666f6e742d73697a653d223136222066696c6c3d22233290526c0319a3099b2911f2622ab22a61609d1b60b78401528051908160c48501916020019161141392612340565b661e17ba32bc3a1f60c91b60c4918401918201527f3c7265637420783d223137302220793d2230222077696474683d22313530222060cb8201527f6865696768743d223430222072783d2238222066696c6c3d222361386536636660eb8201526211179f60e91b61010b8201527f3c7465787420783d223138302220793d2232352220666f6e742d66616d696c7961010e8201527f3d2242756e6765652220666f6e742d73697a653d223136222066696c6c3d222361012e8201526719319a3099b2911f60c11b61014e8201528151916114f7908390610156840190602001612340565b0160c40160928101661e17ba32bc3a1f60c91b905260998101631e17b39f60e11b90520360920160141981018552600b016115329085612373565b61153b906125f6565b604051918260208101927f3c67207472616e73666f726d3d227472616e736c6174652834302c2034363029845261111f60f11b6040830152604282017f3c726563742077696474683d2231353022206865696768743d223330222072789052741e911c11103334b6361e9111b3333219b11b11179f60591b6062830152607782017f3c7465787420783d2231302220793d2232302220666f6e742d66616d696c793d9052609782017f2242756e6765652220666f6e742d73697a653d223132222066696c6c3d22233290526a0319a3099b2911f21281d160ad1b60b78301528051908160c28401916020019161163092612340565b810160c28101661e17ba32bc3a1f60c91b905260c98101631e17b39f60e11b90520360c20160141981018452600b016116699084612373565b611672906125f6565b9261167c906125f6565b91604051809360208201957f3c67207472616e73666f726d3d227472616e736c6174652834302c2035303029875261111f60f11b6040840152604283017f3c726563742077696474683d2233323022206865696768743d223430222072789052741e911c11103334b6361e9111b2983298329811179f60591b6062840152607783017f3c7465787420783d2231302220793d2232352220666f6e742d66616d696c793d9052609783017f2242756e6765652220666f6e742d73697a653d223134223e0000000000000000905260af83017f3c747370616e2066696c6c3d2223303038303030223e573a200000000000000090528051908160c88501916020019161178592612340565b671e17ba39b830b71f60c11b60c8918401918201527f3c747370616e20783d22313630222066696c6c3d2223464630303030223e4c3a60d0820152600160fd1b60f08201528151916117e090839060f1840190602001612340565b671e17ba39b830b71f60c11b910160f1810191909152661e17ba32bc3a1f60c91b60f9820152631e17b39f60e11b6101008201520360e481018452611829906101040184612373565b604051998a955190816020880161183f92612340565b8501905191826020830161185292612340565b0160200191829151809361186592612340565b0103601f19810186526118789086612373565b60405160805280519081608051602001916020019161189692612340565b6080510160c0515190602081018260c051602001916118b492612340565b016020018082516020819401916118ca92612340565b018082516020819401916118dd92612340565b018082516020819401916118f092612340565b0180825160208194019161190392612340565b01651e17b9bb339f60d11b815260805190036019198101608051526006016080519061192e91612373565b60405163186e325160e11b81526004356004820152808060a0515a92602491602094fa90811561200c578691611fd6575b50604051634220be2360e01b8152600435600482015260208160248160a0515afa968715611fca578097611f90575b505060043561199c906125f6565b956080516119a990612740565b976119b3906127aa565b956119bd906128b6565b946119c7906125f6565b936119d1906125f6565b926119db906125f6565b906119e5906125f6565b916119ef906125f6565b9260e0516119fc906125f6565b9461012051611a0a906125f6565b966101405151611a19906125f6565b986040519b8c809c60208201607b60f81b905271226e616d65223a202243686962626c65202360701b6021830152805160338193019160200191611a5c92612340565b61088b60f21b6033918e01918201527f226465736372697074696f6e223a202241206d69676874792043686962626c65603582015269081dd85c9c9a5bdc888b60b21b60558201527f22696d616765223a2022646174613a696d6167652f7376672b786d6c3b626173605f82015263194d8d0b60e21b607f820152815191611aed9083906083840190602001612340565b0160330161088b60f21b60508201526d1134b6b0b3b2afbab936111d101160911b605282015261018051519060608101826101805160200191611b2f92612340565b61088b60f21b606092909101918201526e2261747472696275746573223a205b60881b60628201527f7b2274726169745f74797065223a2022456c656d656e74222c202276616c7565607182015263111d101160e11b60918201528151916050820191611ba491849160950190602001612340565b0160100162089f4b60ea1b6035820152603881017f7b2274726169745f74797065223a2022526172697479222c202276616c7565229052621d101160e91b605882015281519182605b83019160200191611bfd92612340565b0160350162089f4b60ea1b6026820152602981017f7b2274726169745f74797065223a20224c6576656c222c202276616c7565223a905260498101600160fd1b905281519182604a83019160200191611c5592612340565b0160260160248101611f4b60f21b9052602681017f7b2274726169745f74797065223a20224261736520506f696e7473222c202276905266030b63ab2911d160cd1b604682015281519182604d83019160200191611cb292612340565b0160240160298101611f4b60f21b9052602b81017f7b2274726169745f74797065223a20225850222c202276616c7565223a200000905281519182604983019160200191611cff92612340565b0160290160208101611f4b60f21b9052602281017f7b2274726169745f74797065223a20225850205265717569726564222c202276905266030b63ab2911d160cd1b604282015281519182604983019160200191611d5c92612340565b0160200160298101611f4b60f21b9052602b81017f7b2274726169745f74797065223a2022506f7765722053636f7265222c202276905266030b63ab2911d160cd1b604b82015281519182605283019160200191611db992612340565b0160290160298101611f4b60f21b9052602b81017f7b2274726169745f74797065223a202257696e73222c202276616c7565223a20905281519182604b83019160200191611e0692612340565b0160290160228101611f4b60f21b9052602481017f7b2274726169745f74797065223a20224c6f73736573222c202276616c7565229052604481016101d160f51b905281519182604683019160200191611e5f92612340565b0160220160248101611f4b60f21b9052602681017f7b2274726169745f74797065223a202245717569706d656e7420436f756e742290526a01610113b30b63ab2911d160ad1b604682015281519182605183019160200191611ec092612340565b01602401602d8101607d60f81b9052602e8101605d60f81b9052602f8101607d60f81b905203602d01601c1981018252600301611efd9082612373565b611f0690612740565b6040518060208101927f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000845280519081603d84019160200191611f4892612340565b810103603d01601f1981018252611f5f9082612373565b6040519182916020835251908160208401528160408401611f7f92612340565b601f1990601f011681010360400190f35b909196506020823d602011611fc2575b81611fad60209383612373565b81010312611fbf57505194878061198e565b80fd5b3d9150611fa0565b604051903d90823e3d90fd5b90506020813d602011612004575b81611ff160209383612373565b8101031261200057518761195f565b8580fd5b3d9150611fe4565b6040513d88823e3d90fd5b604051612025604082612373565b601081526f39ba3937b5b29e911199319a3099b29160811b602082015261010052610b9f565b634e487b7160e01b8c52602160045260248cfd5b9350505050610b28925061208591503d8089833e61207d8183612373565b810190612395565b6101605295969295909493929091506106e5565b6040513d87823e3d90fd5b8752506020862086905b8282106120c957506101805161069f9250016020018861068a565b60018160209254838561018051010152019101906120ae565b90506020925061069f93915060ff191682610180510152151560051b6101805101018861068a565b634e487b7160e01b600052602160045260246000fd5b935050505061213991923d8091833e61207d8183612373565b60e092909252610120526101405293949390919086610616565b6040513d6000823e3d90fd5b60405162461bcd60e51b815260206004820152601a60248201527f546f6b656e2076617269616e74206e6f742061737369676e65640000000000006044820152606490fd5b60405162461bcd60e51b815260206004820152601260248201527110da1a58989b19539195081b9bdd081cd95d60721b6044820152606490fd5b34610118576000366003190112610118576001546040516001600160a01b039091168152602090f35b34610118576000366003190112610118576000546040516001600160a01b039091168152602090f35b34610118576020366003190112610118576004356000526003602052602060ff60406000205416604051908152f35b346101185760003660031901126101185761227861257f565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610118576020366003190112610118576004356001600160a01b03811690819003610118576122e661257f565b8015612309576bffffffffffffffffffffffff60a01b6001541617600155600080f35b60405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606490fd5b60005b8381106123535750506000910152565b8181015183820152602001612343565b6004359060ff8216820361011857565b90601f8019910116810190811067ffffffffffffffff82111761032b57604052565b9190610100838203126101185782516006811015610118579260208101516004811015610118579260408201519260608301519260808101519260a08201519260c08301519260e08101519067ffffffffffffffff821161011857019080601f830112156101185781519167ffffffffffffffff831161032b578260051b90604051936124256020840186612373565b845260208085019282010192831161011857602001905b8282106124495750505090565b815181526020918201910161243c565b1561246057565b60405162461bcd60e51b8152602060048201526016602482015275115b195b595b9d081a5b5859d95cc81b9bdd081cd95d60521b6044820152606490fd5b600a8210156124ae570190600090565b634e487b7160e01b600052603260045260246000fd5b90600182811c921680156124f4575b60208310146124de57565b634e487b7160e01b600052602260045260246000fd5b91607f16916124d3565b1561250557565b60405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a5908195b195b595b9d608a1b6044820152606490fd5b90600a8110156124ae5760051b81013590601e198136030182121561011857019081359167ffffffffffffffff8311610118576020018236038113610118579190565b6000546001600160a01b0316330361259357565b63118cdaa760e01b6000523360045260246000fd5b67ffffffffffffffff811161032b57601f01601f191660200190565b906125ce826125a8565b6125db6040519182612373565b82815280926125ec601f19916125a8565b0190602036910137565b8060009172184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b82101561271d575b806d04ee2d6d415b85acef8100000000600a921015612702575b662386f26fc100008110156126ee575b6305f5e1008110156126dd575b6127108110156126ce575b60648110156126c0575b10156126b5575b600a602161267c600185016125c4565b938401015b60001901916f181899199a1a9b1b9c1cb0b131b232b360811b8282061a83530480156126b057600a9091612681565b505090565b60019091019061266c565b606460029104930192612665565b6127106004910493019261265b565b6305f5e10060089104930192612650565b662386f26fc1000060109104930192612643565b6d04ee2d6d415b85acef810000000060209104930192612633565b506040915072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8104612619565b6040516127a791612752606083612373565b604082527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208301527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f604083015261296a565b90565b600681101561210a5780156128935760006001821461286d5750600281146128495760009060038114612825576004915014612802576040516127ee604082612373565b6004815263159bda5960e21b602082015290565b604051612810604082612373565b6005815264131a59da1d60da1b602082015290565b5050604051612835604082612373565b600481526315da5b9960e21b602082015290565b50604051612858604082612373565b600581526408ac2e4e8d60db1b602082015290565b5050604080519061287e9082612373565b60058152642bb0ba32b960d91b602082015290565b506040516128a2604082612373565b60048152634669726560e01b602082015290565b600481101561210a578015612945576000906001811461291d5760029150146128fb576040516128e7604082612373565b60048152634570696360e01b602082015290565b604051612909604082612373565b60048152635261726560e01b602082015290565b505060405161292d604082612373565b60088152672ab731b7b6b6b7b760c11b602082015290565b50604051612954604082612373565b600681526521b7b6b6b7b760d11b602082015290565b919091805115612a6457805160028101809111612a4e5760039004600281901b906001600160fe1b03811603612a4e576129a3906125c4565b9060208201908081518201956020870190815192600083525b888110612a0057505060039394959650525106806001146129ed576002146129e2575090565b603d90600019015390565b50603d9081600019820153600119015390565b600360049199969901986001603f8b5182828260121c16870101518453828282600c1c16870101518385015382828260061c16870101516002850153168401015160038201530194976129bc565b634e487b7160e01b600052601160045260246000fd5b509050604051612a75602082612373565b6000815290565b9015612c7e5760ff1680612b305750604051612a9960a082612373565b607581527f3c7061746820643d224d342034204c3136203136204d31302034204c3136203460208201527f204c313620313022207374726f6b653d2223326334613365222066696c6c3d2260408201527f6e6f6e6522207374726f6b652d77696474683d2232222066696c7465723d227560608201527439361411b2b8bab4b83832b216b3b637bb9491179f60591b608082015290565b600103612be457604051612b4560a082612373565b607781527f3c7061746820643d224d352035204c31352035204c3135203132204c3130203160208201527f35204c35203132205a22207374726f6b653d2223326334613365222066696c6c60408201527f3d226e6f6e6522207374726f6b652d77696474683d2232222066696c7465723d60608201527f2275726c282365717569707065642d676c6f7729222f3e000000000000000000608082015290565b604051612bf260a082612373565b606a81527f3c636972636c652063783d223130222063793d2231302220723d22352220737460208201527f726f6b653d2223326334613365222066696c6c3d226e6f6e6522207374726f6b60408201527f652d77696474683d2232222066696c7465723d2275726c2823657175697070656060820152693216b3b637bb9491179f60b11b608082015290565b50604051612a7560208261237356fea26469706673582212204015f025ddef702d34cc3388f6b468835fcf8880565fabca200c9d3670714f1864736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _chibbleNFT (address): 0x0000000000000000000000000000000000000000
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.