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... | 17457740 | 33 hrs ago | IN | 0 S | 0.00105246 | ||||
Set Element Imag... | 17457733 | 33 hrs ago | IN | 0 S | 0.00105246 | ||||
Set Element Imag... | 17457728 | 33 hrs ago | IN | 0 S | 0.00105246 | ||||
Set Element Imag... | 17457723 | 33 hrs ago | IN | 0 S | 0.00105246 | ||||
Set Element Imag... | 17457718 | 33 hrs ago | IN | 0 S | 0.00105246 | ||||
Set Element Imag... | 17457713 | 33 hrs ago | IN | 0 S | 0.00105233 | ||||
Set Chibble NFT | 17457321 | 33 hrs ago | IN | 0 S | 0.0000505 |
Latest 22 internal transactions
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
17699921 | 9 hrs ago | 0 S | ||||
17699898 | 9 hrs ago | 0 S | ||||
17699819 | 9 hrs ago | 0 S | ||||
17699746 | 9 hrs ago | 0 S | ||||
17699715 | 9 hrs ago | 0 S | ||||
17696731 | 9 hrs ago | 0 S | ||||
17696708 | 9 hrs ago | 0 S | ||||
17696680 | 9 hrs ago | 0 S | ||||
17696604 | 9 hrs ago | 0 S | ||||
17696582 | 9 hrs ago | 0 S | ||||
17696557 | 9 hrs ago | 0 S | ||||
17696498 | 9 hrs ago | 0 S | ||||
17664589 | 12 hrs ago | 0 S | ||||
17664545 | 12 hrs ago | 0 S | ||||
17663190 | 12 hrs ago | 0 S | ||||
17663159 | 12 hrs ago | 0 S | ||||
17663109 | 12 hrs ago | 0 S | ||||
17663032 | 12 hrs ago | 0 S | ||||
17662437 | 12 hrs ago | 0 S | ||||
17460991 | 32 hrs ago | 0 S | ||||
17459380 | 32 hrs ago | 0 S | ||||
17459346 | 33 hrs ago | 0 S |
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); constructor(address _chibbleNFT) Ownable(msg.sender) { 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"); for(uint8 i = 0; i < 10; i++) { elementImages[element].images[i] = ipfsHashes[i]; } elementImages[element].isSet = true; } // Assign image variant on mint function assignImageVariant(uint256 tokenId, uint8 element) external returns (uint8) { require(msg.sender == address(chibbleNFT), "Only ChibbleNFT can assign"); 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(), 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() internal pure returns (string memory) { return string(abi.encodePacked( '<rect width="400" height="560" rx="20" fill="#f5efe6"/>', '<rect x="10" y="10" width="380" height="540" rx="15" stroke="url(#epicBorder)" 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)">', // Weapon Slot '<g>', '<rect width="20" height="20" rx="4" fill="#dcedc1" stroke="#2c4a3e"/>', getEquipmentIcon(0, equippedItems.length > 0), '</g>', // Armor Slot '<g transform="translate(0, 30)">', '<rect width="20" height="20" rx="4" fill="#dcedc1" stroke="#2c4a3e"/>', getEquipmentIcon(1, equippedItems.length > 1), '</g>', // Accessory Slot '<g transform="translate(0, 60)">', '<rect width="20" height="20" rx="4" fill="#dcedc1" stroke="#2c4a3e"/>', getEquipmentIcon(2, equippedItems.length > 2), '</g>', '</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) { // Get token's assigned image variant uint8 variant = tokenToImageVariant[tokenId]; // Get Chibble data (IChibbleNFT.Element element,,,,,,,) = chibbleNFT.getChibbleStats(tokenId); // Get IPFS image URI string memory imageURI = elementImages[uint8(element)].images[variant]; // Generate SVG string memory svgImage = generateSVG(tokenId, imageURI); // 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), '"', '}]', '}' ))) )); } 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":"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
60803460d157601f61238338819003918201601f19168301916001600160401b0383118484101760d65780849260209460405283398101031260d157516001600160a01b0381169081900360d157331560bb5760008054336001600160a01b0319821681178355604051939290916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3600180546001600160a01b03191691909117905561229690816100ed8239f35b631e4fbdf760e01b600052600060045260246000fd5b600080fd5b634e487b7160e01b600052604160045260246000fdfe60a0604052600436101561001257600080fd5b60003560e01c806317033ea0146118e6578063715018a61461188d578063782a48101461185e5780638da5cb5b146118355780639ec352981461180c578063c87b56dd1461048a578063e31ac76414610395578063e8fff00414610158578063eb6fbbc31461011c5763f2fde38b1461008a57600080fd5b34610117576020366003190112610117576004356001600160a01b03811690819003610117576100b8611afd565b801561010157600080546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b600052600060045260246000fd5b600080fd5b346101175760203660031901126101175760ff610137611991565b166000526002602052602060ff600a60406000200154166040519015158152f35b3461011757604036600319011261011757610171611991565b6024359067ffffffffffffffff821161011757366101448301116101175760ff9061019a611afd565b16906005821161035e5736819003602219019160005b600a60ff8216101561033f5760006004611fe08360051b16850101358581121561033b5784019060048201359067ffffffffffffffff821161033857813603602484011361033857848152600260205261020d8460408320611a9d565b9390936103245761021e8454611ac3565b601f81116102df575b5081601f841160011461026e579260019492819260ff979592610260575b5050600019600383901b1c191690841b1790555b01166101b0565b016024013590508980610245565b91601f19841685845260208420935b8181106102c45750926001959392859260ff98968895106102a6575b505050811b019055610259565b602491010135600019600384901b60f8161c19169055898080610299565b6024848401013585556001909401936020928301920161027d565b84835260208320601f850160051c8101916020861061031a575b601f0160051c01905b81811061030f5750610227565b838155600101610302565b90915081906102f9565b634e487b7160e01b82526004829052602482fd5b80fd5b5080fd5b506000908152600260205260409020600a01805460ff19166001179055005b60405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a5908195b195b595b9d608a1b6044820152606490fd5b346101175760403660031901126101175760043560243560ff8116809103610117576001546001600160a01b03163303610445576020917fac91436ae04b3b09446a3a44482b73204f66b88802eb4f5c62eb4a6e73bb2834604060ff600a8251878101904282528685820152446060820152606081526104166080826119a1565b5190200616938360005260038652816000208560ff1982541617905581519081528486820152a2604051908152f35b60405162461bcd60e51b815260206004820152601a60248201527f4f6e6c792043686962626c654e46542063616e2061737369676e0000000000006044820152606490fd5b346101175760203660031901126101175760043580600052600360205260ff6040600020541660018060a01b03600154169160405191630102953760e71b8352816004840152600083602481875afa92831561176b576000936117e8575b5060068310156117d25761050c9060ff841660005260026020526040600020611a9d565b5060405191600082549261051f84611ac3565b9081865260208601946001811690816000146117b55750600114611777575b5050602494956105528560009303866119a1565b60405195868092630102953760e71b82528560048301525afa93841561176b57600080819682918384958593611736575b50604080517f3c6c696e6561724772616469656e742069643d2265706963426f726465722220602082019081527f78313d223025222079313d223025222078323d2231303025222079323d22313092820192909252631812911f60e11b60608201527f3c73746f70206f66667365743d22302522207374796c653d2273746f702d636f60648201527f6c6f723a234646443730303b73746f702d6f7061636974793a31223e0000000060848201527f3c616e696d617465206174747269627574654e616d653d2273746f702d636f6c60a082018190527f6f72222076616c7565733d22234646443730303b234646413530303b2346464460c08301527f37303022206475723d2232732220726570656174436f756e743d22696e64656660e08301526734b734ba3291179f60c11b6101008301819052661e17b9ba37b81f60c91b61010884018190527f3c73746f70206f66667365743d223130302522207374796c653d2273746f702d61010f8501527f636f6c6f723a234646413530303b73746f702d6f7061636974793a31223e000061012f85015261014d8401929092527f6f72222076616c7565733d22234646413530303b234646443730303b2346464161016d8401527f35303022206475723d2232732220726570656174436f756e743d22696e64656661018d8401526101ad8301526101b5820152701e17b634b732b0b923b930b234b2b73a1f60791b6101bc8201527f3c66696c7465722069643d2265717569707065642d676c6f77223e00000000006101cd8201527f3c6665476175737369616e426c757220737464446576696174696f6e3d2232226101e88201526f103932b9bab63a1e9131363ab911179f60811b6102088201527f3c6665436f6d706f7369746520696e3d22536f757263654772617068696322206102188201527f696e323d22626c757222206f70657261746f723d226f766572222f3e00000000610238820152681e17b334b63a32b91f60b91b61025482015261023d815290968a938a93909290919061087d61025d826119a1565b604051998a91602083016080526080517f3c7376672077696474683d2234303022206865696768743d22353630222076699052604083017f6577426f783d2230203020343030203536302220786d6c6e733d22687474703a9052606083017f2f2f7777772e77332e6f72672f323030302f737667223e000000000000000000905260778301651e3232b3399f60d11b9052607d83017f3c7374796c6520747970653d22746578742f637373223e40696d706f727420759052609d83017f726c282268747470733a2f2f666f6e74732e676f6f676c65617069732e636f6d905260bd83017f2f637373323f66616d696c793d42756e67656526616d703b646973706c61793d90526e39bbb0b811149d9e17b9ba3cb6329f60891b60dd84015251908160ec84016109ab9261196e565b810160ec8101661e17b232b3399f60c91b90520360ec0160181981018a526007016109d6908a6119a1565b6040519c8d9160208301927f3c726563742077696474683d2234303022206865696768743d223536302220728452604081017f783d223230222066696c6c3d2223663565666536222f3e0000000000000000009052605781017f3c7265637420783d2231302220793d223130222077696474683d2233383022209052607781017f6865696768743d22353430222072783d22313522207374726f6b653d2275726c9052609781017f282365706963426f726465722922207374726f6b652d77696474683d2234222090526f3334b6361e9111b3333333333311179f60811b60b782015260a7815260c7610ac8916119a1565b610ad18c611b74565b94610adb90611fa3565b93604051809560208201977f3c7265637420783d2233302220793d223330222077696474683d2233343022208952604083017f6865696768743d223430222072783d223130222066696c6c3d222332633461339052633291179f60e11b6060840152606483017f3c7465787420783d2234302220793d2235382220666f6e742d66616d696c793d9052608483017f2242756e6765652220666f6e742d73697a653d223230222066696c6c3d22236690526f6666666666223e43686962626c65202360801b60a48401528051908160b485019160200191610bba9261196e565b661e17ba32bc3a1f60c91b60b4918401918201527f3c7465787420783d223235302220793d2235382220666f6e742d66616d696c7960bb8201527f3d2242756e6765652220666f6e742d73697a653d223136222066696c6c3d222360db82015267333333333333111f60c11b60fb820152815191610c4290839061010384019060200161196e565b0160b401604f8101661e17ba32bc3a1f60c91b905203604f0160181981018652600701610c6f90866119a1565b604051809760208201997f3c7265637420783d2234302220793d223830222077696474683d2233323022208b52604083017f6865696768743d22333230222066696c6c3d222366356635663522207374726f9052606083017f6b653d222332633461336522207374726f6b652d77696474683d2232222f3e009052607f83017f3c696d61676520783d2234302220793d223830222077696474683d2233323022905273103432b4b3b43a1e911999181110343932b31e9160611b609f84015251908160b38401610d3e9261196e565b81016211179f60e91b60b38201520360b301601c1981018852600301610d6490886119a1565b88511515610d7190612057565b998951600110610d809061210f565b9951600210610d8e906121c1565b996040519a8b91602083019d7f3c67207472616e73666f726d3d227472616e736c617465283336342c203130308f526214911f60e91b604085015260438401621e339f60e91b905260468401610de390611e34565b808251602081940191610df59261196e565b01631e17b39f60e11b8152600481017f3c67207472616e73666f726d3d227472616e736c61746528302c20333029223e9052602401610e3390611e34565b808251602081940191610e459261196e565b01631e17b39f60e11b8152600481017f3c67207472616e73666f726d3d227472616e736c61746528302c20363029223e9052602401610e8390611e34565b808251602081940191610e959261196e565b01631e17b39f60e11b815260048101631e17b39f60e11b90520360171981018b52600801610ec3908b6119a1565b610ecc90611b74565b9a610ed690611d28565b926040518094602082019d7f3c67207472616e73666f726d3d227472616e736c6174652834302c20343130298f5261111f60f11b6040840152604283017f3c726563742077696474683d2231353022206865696768743d223430222072789052741e911c11103334b6361e9111b11c319ab21b11179f60591b6062840152607783017f3c7465787420783d2231302220793d2232352220666f6e742d66616d696c793d9052609783017f2242756e6765652220666f6e742d73697a653d223136222066696c6c3d22233290526c0319a3099b2911f2622ab22a61609d1b60b78401528051908160c485019160200191610fce9261196e565b661e17ba32bc3a1f60c91b60c4918401918201527f3c7265637420783d223137302220793d2230222077696474683d22313530222060cb8201527f6865696768743d223430222072783d2238222066696c6c3d222361386536636660eb8201526211179f60e91b61010b8201527f3c7465787420783d223138302220793d2232352220666f6e742d66616d696c7961010e8201527f3d2242756e6765652220666f6e742d73697a653d223136222066696c6c3d222361012e8201526719319a3099b2911f60c11b61014e8201528151916110b290839061015684019060200161196e565b0160c40160928101661e17ba32bc3a1f60c91b905260998101631e17b39f60e11b90520360920160141981018552600b016110ed90856119a1565b6110f690611b74565b604051918260208101927f3c67207472616e73666f726d3d227472616e736c6174652834302c2034363029845261111f60f11b6040830152604282017f3c726563742077696474683d2231353022206865696768743d223330222072789052741e911c11103334b6361e9111b3333219b11b11179f60591b6062830152607782017f3c7465787420783d2231302220793d2232302220666f6e742d66616d696c793d9052609782017f2242756e6765652220666f6e742d73697a653d223132222066696c6c3d22233290526a0319a3099b2911f21281d160ad1b60b78301528051908160c2840191602001916111eb9261196e565b810160c28101661e17ba32bc3a1f60c91b905260c98101631e17b39f60e11b90520360c20160141981018452600b0161122490846119a1565b61122d90611b74565b9261123790611b74565b91604051809360208201957f3c67207472616e73666f726d3d227472616e736c6174652834302c2035303029875261111f60f11b6040840152604283017f3c726563742077696474683d2233323022206865696768743d223430222072789052741e911c11103334b6361e9111b2983298329811179f60591b6062840152607783017f3c7465787420783d2231302220793d2232352220666f6e742d66616d696c793d9052609783017f2242756e6765652220666f6e742d73697a653d223134223e0000000000000000905260af83017f3c747370616e2066696c6c3d2223303038303030223e573a200000000000000090528051908160c8850191602001916113409261196e565b671e17ba39b830b71f60c11b60c8918401918201527f3c747370616e20783d22313630222066696c6c3d2223464630303030223e4c3a60d0820152600160fd1b60f082015281519161139b90839060f184019060200161196e565b671e17ba39b830b71f60c11b910160f1810191909152661e17ba32bc3a1f60c91b60f9820152631e17b39f60e11b6101008201520360e4810184526113e49061010401846119a1565b6040519c8d95519081602088016113fa9261196e565b8501905191826020830161140d9261196e565b016020019182915180936114209261196e565b0103601f198101895261143390896119a1565b6040519c8d995160208b01816080519161144c9261196e565b8a01905191826020830161145f9261196e565b016020019182915180936114729261196e565b019182915180936114829261196e565b019182915180936114929261196e565b018082516020819401916114a59261196e565b01651e17b9bb339f60d11b815203601919810185526006016114c790856119a1565b6114d090611b74565b926114da90611cbe565b936114e490611d28565b9160405194859460208601607b60f81b905271226e616d65223a202243686962626c65202360701b6021870152805190816033880191602001916115279261196e565b61088b60f21b6033918701918201527f226465736372697074696f6e223a202241206d69676874792043686962626c65603582015269081dd85c9c9a5bdc888b60b21b60558201527f22696d616765223a2022646174613a696d6167652f7376672b786d6c3b626173605f82015263194d8d0b60e21b607f8201528151916115b8908390608384019060200161196e565b016033019061088b60f21b60508301526d1134b6b0b3b2afbab936111d101160911b6052830152519182606083016115ef9261196e565b61088b60f21b606092909101918201526f2261747472696275746573223a205b7b60801b60628201527f2274726169745f74797065223a2022456c656d656e74222c0000000000000000607282015269113b30b63ab2911d101160b11b608a820152815191605082019161166b9184916094019060200161196e565b601160f91b91016044810191909152617d5d60f01b6045820152607d60f81b6047820152036028810182526116a390604801826119a1565b6116ac90611cbe565b6040518060208101927f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000845280519081603d840191602001916116ee9261196e565b810103603d01601f198101825261170590826119a1565b60405191829160208352519081602084015281604084016117259261196e565b601f1990601f011681010360400190f35b935050505084965085925061175c913d8091833e61175481836119a1565b8101906119d9565b949b5096929492909150610583565b6040513d6000823e3d90fd5b6000908152602081209092505b81831061179b57505083016020018561055261053e565b6001816020929493945483858a0101520191019190611784565b60ff191686525050151560051b840160200190508561055261053e565b634e487b7160e01b600052602160045260246000fd5b6117fe9193503d806000833e61175481836119a1565b5050505050505091846104e8565b34610117576000366003190112610117576001546040516001600160a01b039091168152602090f35b34610117576000366003190112610117576000546040516001600160a01b039091168152602090f35b34610117576020366003190112610117576004356000526003602052602060ff60406000205416604051908152f35b34610117576000366003190112610117576118a6611afd565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610117576020366003190112610117576004356001600160a01b0381169081900361011757611914611afd565b8015611937576bffffffffffffffffffffffff60a01b6001541617600155600080f35b60405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606490fd5b60005b8381106119815750506000910152565b8181015183820152602001611971565b6004359060ff8216820361011757565b90601f8019910116810190811067ffffffffffffffff8211176119c357604052565b634e487b7160e01b600052604160045260246000fd5b9190610100838203126101175782516006811015610117579260208101516004811015610117579260408201519260608301519260808101519260a08201519260c08301519260e08101519067ffffffffffffffff821161011757019080601f830112156101175781519167ffffffffffffffff83116119c3578260051b9060405193611a6960208401866119a1565b845260208085019282010192831161011757602001905b828210611a8d5750505090565b8151815260209182019101611a80565b600a821015611aad570190600090565b634e487b7160e01b600052603260045260246000fd5b90600182811c92168015611af3575b6020831014611add57565b634e487b7160e01b600052602260045260246000fd5b91607f1691611ad2565b6000546001600160a01b03163303611b1157565b63118cdaa760e01b6000523360045260246000fd5b67ffffffffffffffff81116119c357601f01601f191660200190565b90611b4c82611b26565b611b5960405191826119a1565b8281528092611b6a601f1991611b26565b0190602036910137565b8060009172184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b821015611c9b575b806d04ee2d6d415b85acef8100000000600a921015611c80575b662386f26fc10000811015611c6c575b6305f5e100811015611c5b575b612710811015611c4c575b6064811015611c3e575b1015611c33575b600a6021611bfa60018501611b42565b938401015b60001901916f181899199a1a9b1b9c1cb0b131b232b360811b8282061a8353048015611c2e57600a9091611bff565b505090565b600190910190611bea565b606460029104930192611be3565b61271060049104930192611bd9565b6305f5e10060089104930192611bce565b662386f26fc1000060109104930192611bc1565b6d04ee2d6d415b85acef810000000060209104930192611bb1565b506040915072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8104611b97565b604051611d2591611cd06060836119a1565b604082527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208301527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f6040830152611e91565b90565b60068110156117d2578015611e1157600060018214611deb575060028114611dc75760009060038114611da3576004915014611d8057604051611d6c6040826119a1565b6004815263159bda5960e21b602082015290565b604051611d8e6040826119a1565b6005815264131a59da1d60da1b602082015290565b5050604051611db36040826119a1565b600481526315da5b9960e21b602082015290565b50604051611dd66040826119a1565b600581526408ac2e4e8d60db1b602082015290565b50506040805190611dfc90826119a1565b60058152642bb0ba32b960d91b602082015290565b50604051611e206040826119a1565b60048152634669726560e01b602082015290565b7f3c726563742077696474683d22323022206865696768743d223230222072783d81527f2234222066696c6c3d222364636564633122207374726f6b653d22233263346160208201526419b291179f60d91b604082015260450190565b919091805115611f8b57805160028101809111611f755760039004600281901b906001600160fe1b03811603611f7557611eca90611b42565b9060208201908081518201956020870190815192600083525b888110611f275750506003939495965052510680600114611f1457600214611f09575090565b603d90600019015390565b50603d9081600019820153600119015390565b600360049199969901986001603f8b5182828260121c16870101518453828282600c1c16870101518385015382828260061c1687010151600285015316840101516003820153019497611ee3565b634e487b7160e01b600052601160045260246000fd5b509050604051611f9c6020826119a1565b6000815290565b60048110156117d2578015612032576000906001811461200a576002915014611fe857604051611fd46040826119a1565b60048152634570696360e01b602082015290565b604051611ff66040826119a1565b60048152635261726560e01b602082015290565b505060405161201a6040826119a1565b60088152672ab731b7b6b6b7b760c11b602082015290565b506040516120416040826119a1565b600681526521b7b6b6b7b760d11b602082015290565b156121015760405161206a60a0826119a1565b607581527f3c7061746820643d224d342034204c3136203136204d31302034204c3136203460208201527f204c313620313022207374726f6b653d2223326334613365222066696c6c3d2260408201527f6e6f6e6522207374726f6b652d77696474683d2232222066696c7465723d227560608201527439361411b2b8bab4b83832b216b3b637bb9491179f60591b608082015290565b604051611f9c6020826119a1565b156121015760405161212260a0826119a1565b607781527f3c7061746820643d224d352035204c31352035204c3135203132204c3130203160208201527f35204c35203132205a22207374726f6b653d2223326334613365222066696c6c60408201527f3d226e6f6e6522207374726f6b652d77696474683d2232222066696c7465723d60608201527f2275726c282365717569707065642d676c6f7729222f3e000000000000000000608082015290565b15612101576040516121d460a0826119a1565b606a81527f3c636972636c652063783d223130222063793d2231302220723d22352220737460208201527f726f6b653d2223326334613365222066696c6c3d226e6f6e6522207374726f6b60408201527f652d77696474683d2232222066696c7465723d2275726c2823657175697070656060820152693216b3b637bb9491179f60b11b60808201529056fea26469706673582212208b9a307d53809d37a6318fa36601cb478a27d627f08df54c82902120c5aab3c164736f6c634300081c00330000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x60a0604052600436101561001257600080fd5b60003560e01c806317033ea0146118e6578063715018a61461188d578063782a48101461185e5780638da5cb5b146118355780639ec352981461180c578063c87b56dd1461048a578063e31ac76414610395578063e8fff00414610158578063eb6fbbc31461011c5763f2fde38b1461008a57600080fd5b34610117576020366003190112610117576004356001600160a01b03811690819003610117576100b8611afd565b801561010157600080546001600160a01b03198116831782556001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b631e4fbdf760e01b600052600060045260246000fd5b600080fd5b346101175760203660031901126101175760ff610137611991565b166000526002602052602060ff600a60406000200154166040519015158152f35b3461011757604036600319011261011757610171611991565b6024359067ffffffffffffffff821161011757366101448301116101175760ff9061019a611afd565b16906005821161035e5736819003602219019160005b600a60ff8216101561033f5760006004611fe08360051b16850101358581121561033b5784019060048201359067ffffffffffffffff821161033857813603602484011361033857848152600260205261020d8460408320611a9d565b9390936103245761021e8454611ac3565b601f81116102df575b5081601f841160011461026e579260019492819260ff979592610260575b5050600019600383901b1c191690841b1790555b01166101b0565b016024013590508980610245565b91601f19841685845260208420935b8181106102c45750926001959392859260ff98968895106102a6575b505050811b019055610259565b602491010135600019600384901b60f8161c19169055898080610299565b6024848401013585556001909401936020928301920161027d565b84835260208320601f850160051c8101916020861061031a575b601f0160051c01905b81811061030f5750610227565b838155600101610302565b90915081906102f9565b634e487b7160e01b82526004829052602482fd5b80fd5b5080fd5b506000908152600260205260409020600a01805460ff19166001179055005b60405162461bcd60e51b815260206004820152600f60248201526e125b9d985b1a5908195b195b595b9d608a1b6044820152606490fd5b346101175760403660031901126101175760043560243560ff8116809103610117576001546001600160a01b03163303610445576020917fac91436ae04b3b09446a3a44482b73204f66b88802eb4f5c62eb4a6e73bb2834604060ff600a8251878101904282528685820152446060820152606081526104166080826119a1565b5190200616938360005260038652816000208560ff1982541617905581519081528486820152a2604051908152f35b60405162461bcd60e51b815260206004820152601a60248201527f4f6e6c792043686962626c654e46542063616e2061737369676e0000000000006044820152606490fd5b346101175760203660031901126101175760043580600052600360205260ff6040600020541660018060a01b03600154169160405191630102953760e71b8352816004840152600083602481875afa92831561176b576000936117e8575b5060068310156117d25761050c9060ff841660005260026020526040600020611a9d565b5060405191600082549261051f84611ac3565b9081865260208601946001811690816000146117b55750600114611777575b5050602494956105528560009303866119a1565b60405195868092630102953760e71b82528560048301525afa93841561176b57600080819682918384958593611736575b50604080517f3c6c696e6561724772616469656e742069643d2265706963426f726465722220602082019081527f78313d223025222079313d223025222078323d2231303025222079323d22313092820192909252631812911f60e11b60608201527f3c73746f70206f66667365743d22302522207374796c653d2273746f702d636f60648201527f6c6f723a234646443730303b73746f702d6f7061636974793a31223e0000000060848201527f3c616e696d617465206174747269627574654e616d653d2273746f702d636f6c60a082018190527f6f72222076616c7565733d22234646443730303b234646413530303b2346464460c08301527f37303022206475723d2232732220726570656174436f756e743d22696e64656660e08301526734b734ba3291179f60c11b6101008301819052661e17b9ba37b81f60c91b61010884018190527f3c73746f70206f66667365743d223130302522207374796c653d2273746f702d61010f8501527f636f6c6f723a234646413530303b73746f702d6f7061636974793a31223e000061012f85015261014d8401929092527f6f72222076616c7565733d22234646413530303b234646443730303b2346464161016d8401527f35303022206475723d2232732220726570656174436f756e743d22696e64656661018d8401526101ad8301526101b5820152701e17b634b732b0b923b930b234b2b73a1f60791b6101bc8201527f3c66696c7465722069643d2265717569707065642d676c6f77223e00000000006101cd8201527f3c6665476175737369616e426c757220737464446576696174696f6e3d2232226101e88201526f103932b9bab63a1e9131363ab911179f60811b6102088201527f3c6665436f6d706f7369746520696e3d22536f757263654772617068696322206102188201527f696e323d22626c757222206f70657261746f723d226f766572222f3e00000000610238820152681e17b334b63a32b91f60b91b61025482015261023d815290968a938a93909290919061087d61025d826119a1565b604051998a91602083016080526080517f3c7376672077696474683d2234303022206865696768743d22353630222076699052604083017f6577426f783d2230203020343030203536302220786d6c6e733d22687474703a9052606083017f2f2f7777772e77332e6f72672f323030302f737667223e000000000000000000905260778301651e3232b3399f60d11b9052607d83017f3c7374796c6520747970653d22746578742f637373223e40696d706f727420759052609d83017f726c282268747470733a2f2f666f6e74732e676f6f676c65617069732e636f6d905260bd83017f2f637373323f66616d696c793d42756e67656526616d703b646973706c61793d90526e39bbb0b811149d9e17b9ba3cb6329f60891b60dd84015251908160ec84016109ab9261196e565b810160ec8101661e17b232b3399f60c91b90520360ec0160181981018a526007016109d6908a6119a1565b6040519c8d9160208301927f3c726563742077696474683d2234303022206865696768743d223536302220728452604081017f783d223230222066696c6c3d2223663565666536222f3e0000000000000000009052605781017f3c7265637420783d2231302220793d223130222077696474683d2233383022209052607781017f6865696768743d22353430222072783d22313522207374726f6b653d2275726c9052609781017f282365706963426f726465722922207374726f6b652d77696474683d2234222090526f3334b6361e9111b3333333333311179f60811b60b782015260a7815260c7610ac8916119a1565b610ad18c611b74565b94610adb90611fa3565b93604051809560208201977f3c7265637420783d2233302220793d223330222077696474683d2233343022208952604083017f6865696768743d223430222072783d223130222066696c6c3d222332633461339052633291179f60e11b6060840152606483017f3c7465787420783d2234302220793d2235382220666f6e742d66616d696c793d9052608483017f2242756e6765652220666f6e742d73697a653d223230222066696c6c3d22236690526f6666666666223e43686962626c65202360801b60a48401528051908160b485019160200191610bba9261196e565b661e17ba32bc3a1f60c91b60b4918401918201527f3c7465787420783d223235302220793d2235382220666f6e742d66616d696c7960bb8201527f3d2242756e6765652220666f6e742d73697a653d223136222066696c6c3d222360db82015267333333333333111f60c11b60fb820152815191610c4290839061010384019060200161196e565b0160b401604f8101661e17ba32bc3a1f60c91b905203604f0160181981018652600701610c6f90866119a1565b604051809760208201997f3c7265637420783d2234302220793d223830222077696474683d2233323022208b52604083017f6865696768743d22333230222066696c6c3d222366356635663522207374726f9052606083017f6b653d222332633461336522207374726f6b652d77696474683d2232222f3e009052607f83017f3c696d61676520783d2234302220793d223830222077696474683d2233323022905273103432b4b3b43a1e911999181110343932b31e9160611b609f84015251908160b38401610d3e9261196e565b81016211179f60e91b60b38201520360b301601c1981018852600301610d6490886119a1565b88511515610d7190612057565b998951600110610d809061210f565b9951600210610d8e906121c1565b996040519a8b91602083019d7f3c67207472616e73666f726d3d227472616e736c617465283336342c203130308f526214911f60e91b604085015260438401621e339f60e91b905260468401610de390611e34565b808251602081940191610df59261196e565b01631e17b39f60e11b8152600481017f3c67207472616e73666f726d3d227472616e736c61746528302c20333029223e9052602401610e3390611e34565b808251602081940191610e459261196e565b01631e17b39f60e11b8152600481017f3c67207472616e73666f726d3d227472616e736c61746528302c20363029223e9052602401610e8390611e34565b808251602081940191610e959261196e565b01631e17b39f60e11b815260048101631e17b39f60e11b90520360171981018b52600801610ec3908b6119a1565b610ecc90611b74565b9a610ed690611d28565b926040518094602082019d7f3c67207472616e73666f726d3d227472616e736c6174652834302c20343130298f5261111f60f11b6040840152604283017f3c726563742077696474683d2231353022206865696768743d223430222072789052741e911c11103334b6361e9111b11c319ab21b11179f60591b6062840152607783017f3c7465787420783d2231302220793d2232352220666f6e742d66616d696c793d9052609783017f2242756e6765652220666f6e742d73697a653d223136222066696c6c3d22233290526c0319a3099b2911f2622ab22a61609d1b60b78401528051908160c485019160200191610fce9261196e565b661e17ba32bc3a1f60c91b60c4918401918201527f3c7265637420783d223137302220793d2230222077696474683d22313530222060cb8201527f6865696768743d223430222072783d2238222066696c6c3d222361386536636660eb8201526211179f60e91b61010b8201527f3c7465787420783d223138302220793d2232352220666f6e742d66616d696c7961010e8201527f3d2242756e6765652220666f6e742d73697a653d223136222066696c6c3d222361012e8201526719319a3099b2911f60c11b61014e8201528151916110b290839061015684019060200161196e565b0160c40160928101661e17ba32bc3a1f60c91b905260998101631e17b39f60e11b90520360920160141981018552600b016110ed90856119a1565b6110f690611b74565b604051918260208101927f3c67207472616e73666f726d3d227472616e736c6174652834302c2034363029845261111f60f11b6040830152604282017f3c726563742077696474683d2231353022206865696768743d223330222072789052741e911c11103334b6361e9111b3333219b11b11179f60591b6062830152607782017f3c7465787420783d2231302220793d2232302220666f6e742d66616d696c793d9052609782017f2242756e6765652220666f6e742d73697a653d223132222066696c6c3d22233290526a0319a3099b2911f21281d160ad1b60b78301528051908160c2840191602001916111eb9261196e565b810160c28101661e17ba32bc3a1f60c91b905260c98101631e17b39f60e11b90520360c20160141981018452600b0161122490846119a1565b61122d90611b74565b9261123790611b74565b91604051809360208201957f3c67207472616e73666f726d3d227472616e736c6174652834302c2035303029875261111f60f11b6040840152604283017f3c726563742077696474683d2233323022206865696768743d223430222072789052741e911c11103334b6361e9111b2983298329811179f60591b6062840152607783017f3c7465787420783d2231302220793d2232352220666f6e742d66616d696c793d9052609783017f2242756e6765652220666f6e742d73697a653d223134223e0000000000000000905260af83017f3c747370616e2066696c6c3d2223303038303030223e573a200000000000000090528051908160c8850191602001916113409261196e565b671e17ba39b830b71f60c11b60c8918401918201527f3c747370616e20783d22313630222066696c6c3d2223464630303030223e4c3a60d0820152600160fd1b60f082015281519161139b90839060f184019060200161196e565b671e17ba39b830b71f60c11b910160f1810191909152661e17ba32bc3a1f60c91b60f9820152631e17b39f60e11b6101008201520360e4810184526113e49061010401846119a1565b6040519c8d95519081602088016113fa9261196e565b8501905191826020830161140d9261196e565b016020019182915180936114209261196e565b0103601f198101895261143390896119a1565b6040519c8d995160208b01816080519161144c9261196e565b8a01905191826020830161145f9261196e565b016020019182915180936114729261196e565b019182915180936114829261196e565b019182915180936114929261196e565b018082516020819401916114a59261196e565b01651e17b9bb339f60d11b815203601919810185526006016114c790856119a1565b6114d090611b74565b926114da90611cbe565b936114e490611d28565b9160405194859460208601607b60f81b905271226e616d65223a202243686962626c65202360701b6021870152805190816033880191602001916115279261196e565b61088b60f21b6033918701918201527f226465736372697074696f6e223a202241206d69676874792043686962626c65603582015269081dd85c9c9a5bdc888b60b21b60558201527f22696d616765223a2022646174613a696d6167652f7376672b786d6c3b626173605f82015263194d8d0b60e21b607f8201528151916115b8908390608384019060200161196e565b016033019061088b60f21b60508301526d1134b6b0b3b2afbab936111d101160911b6052830152519182606083016115ef9261196e565b61088b60f21b606092909101918201526f2261747472696275746573223a205b7b60801b60628201527f2274726169745f74797065223a2022456c656d656e74222c0000000000000000607282015269113b30b63ab2911d101160b11b608a820152815191605082019161166b9184916094019060200161196e565b601160f91b91016044810191909152617d5d60f01b6045820152607d60f81b6047820152036028810182526116a390604801826119a1565b6116ac90611cbe565b6040518060208101927f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000845280519081603d840191602001916116ee9261196e565b810103603d01601f198101825261170590826119a1565b60405191829160208352519081602084015281604084016117259261196e565b601f1990601f011681010360400190f35b935050505084965085925061175c913d8091833e61175481836119a1565b8101906119d9565b949b5096929492909150610583565b6040513d6000823e3d90fd5b6000908152602081209092505b81831061179b57505083016020018561055261053e565b6001816020929493945483858a0101520191019190611784565b60ff191686525050151560051b840160200190508561055261053e565b634e487b7160e01b600052602160045260246000fd5b6117fe9193503d806000833e61175481836119a1565b5050505050505091846104e8565b34610117576000366003190112610117576001546040516001600160a01b039091168152602090f35b34610117576000366003190112610117576000546040516001600160a01b039091168152602090f35b34610117576020366003190112610117576004356000526003602052602060ff60406000205416604051908152f35b34610117576000366003190112610117576118a6611afd565b600080546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34610117576020366003190112610117576004356001600160a01b0381169081900361011757611914611afd565b8015611937576bffffffffffffffffffffffff60a01b6001541617600155600080f35b60405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606490fd5b60005b8381106119815750506000910152565b8181015183820152602001611971565b6004359060ff8216820361011757565b90601f8019910116810190811067ffffffffffffffff8211176119c357604052565b634e487b7160e01b600052604160045260246000fd5b9190610100838203126101175782516006811015610117579260208101516004811015610117579260408201519260608301519260808101519260a08201519260c08301519260e08101519067ffffffffffffffff821161011757019080601f830112156101175781519167ffffffffffffffff83116119c3578260051b9060405193611a6960208401866119a1565b845260208085019282010192831161011757602001905b828210611a8d5750505090565b8151815260209182019101611a80565b600a821015611aad570190600090565b634e487b7160e01b600052603260045260246000fd5b90600182811c92168015611af3575b6020831014611add57565b634e487b7160e01b600052602260045260246000fd5b91607f1691611ad2565b6000546001600160a01b03163303611b1157565b63118cdaa760e01b6000523360045260246000fd5b67ffffffffffffffff81116119c357601f01601f191660200190565b90611b4c82611b26565b611b5960405191826119a1565b8281528092611b6a601f1991611b26565b0190602036910137565b8060009172184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b821015611c9b575b806d04ee2d6d415b85acef8100000000600a921015611c80575b662386f26fc10000811015611c6c575b6305f5e100811015611c5b575b612710811015611c4c575b6064811015611c3e575b1015611c33575b600a6021611bfa60018501611b42565b938401015b60001901916f181899199a1a9b1b9c1cb0b131b232b360811b8282061a8353048015611c2e57600a9091611bff565b505090565b600190910190611bea565b606460029104930192611be3565b61271060049104930192611bd9565b6305f5e10060089104930192611bce565b662386f26fc1000060109104930192611bc1565b6d04ee2d6d415b85acef810000000060209104930192611bb1565b506040915072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8104611b97565b604051611d2591611cd06060836119a1565b604082527f4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656660208301527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f6040830152611e91565b90565b60068110156117d2578015611e1157600060018214611deb575060028114611dc75760009060038114611da3576004915014611d8057604051611d6c6040826119a1565b6004815263159bda5960e21b602082015290565b604051611d8e6040826119a1565b6005815264131a59da1d60da1b602082015290565b5050604051611db36040826119a1565b600481526315da5b9960e21b602082015290565b50604051611dd66040826119a1565b600581526408ac2e4e8d60db1b602082015290565b50506040805190611dfc90826119a1565b60058152642bb0ba32b960d91b602082015290565b50604051611e206040826119a1565b60048152634669726560e01b602082015290565b7f3c726563742077696474683d22323022206865696768743d223230222072783d81527f2234222066696c6c3d222364636564633122207374726f6b653d22233263346160208201526419b291179f60d91b604082015260450190565b919091805115611f8b57805160028101809111611f755760039004600281901b906001600160fe1b03811603611f7557611eca90611b42565b9060208201908081518201956020870190815192600083525b888110611f275750506003939495965052510680600114611f1457600214611f09575090565b603d90600019015390565b50603d9081600019820153600119015390565b600360049199969901986001603f8b5182828260121c16870101518453828282600c1c16870101518385015382828260061c1687010151600285015316840101516003820153019497611ee3565b634e487b7160e01b600052601160045260246000fd5b509050604051611f9c6020826119a1565b6000815290565b60048110156117d2578015612032576000906001811461200a576002915014611fe857604051611fd46040826119a1565b60048152634570696360e01b602082015290565b604051611ff66040826119a1565b60048152635261726560e01b602082015290565b505060405161201a6040826119a1565b60088152672ab731b7b6b6b7b760c11b602082015290565b506040516120416040826119a1565b600681526521b7b6b6b7b760d11b602082015290565b156121015760405161206a60a0826119a1565b607581527f3c7061746820643d224d342034204c3136203136204d31302034204c3136203460208201527f204c313620313022207374726f6b653d2223326334613365222066696c6c3d2260408201527f6e6f6e6522207374726f6b652d77696474683d2232222066696c7465723d227560608201527439361411b2b8bab4b83832b216b3b637bb9491179f60591b608082015290565b604051611f9c6020826119a1565b156121015760405161212260a0826119a1565b607781527f3c7061746820643d224d352035204c31352035204c3135203132204c3130203160208201527f35204c35203132205a22207374726f6b653d2223326334613365222066696c6c60408201527f3d226e6f6e6522207374726f6b652d77696474683d2232222066696c7465723d60608201527f2275726c282365717569707065642d676c6f7729222f3e000000000000000000608082015290565b15612101576040516121d460a0826119a1565b606a81527f3c636972636c652063783d223130222063793d2231302220723d22352220737460208201527f726f6b653d2223326334613365222066696c6c3d226e6f6e6522207374726f6b60408201527f652d77696474683d2232222066696c7465723d2275726c2823657175697070656060820152693216b3b637bb9491179f60b11b60808201529056fea26469706673582212208b9a307d53809d37a6318fa36601cb478a27d627f08df54c82902120c5aab3c164736f6c634300081c0033
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.