Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
521237 | 7 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
FirstsSvgGenerator
Compiler Version
v0.8.27+commit.40a35a09
ZkSolc Version
v1.5.9
Optimization Enabled:
Yes with Mode 3
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
/* SPDX-License-Identifier: MIT Author: nix.eth */ pragma solidity ^0.8.27; import "@openzeppelin/contracts/utils/Strings.sol"; import "./FirstsRendererConfig.sol"; import { GenericEncoder } from "./GenericEncoder.sol"; import { IFirstsSvgGenerator } from "./IFirstsSvgGenerator.sol"; contract FirstsSvgGenerator is IFirstsSvgGenerator { using Strings for uint256; using GenericEncoder for bytes32; using GenericEncoder for uint; using GenericEncoder for bytes; struct SvgConfig { uint linesNeeded; uint encodedHashLength; string encodedHash; string stretchedHash; bytes bytesStretchedHash; string encodedId; uint fontSize; uint charsLine; uint lineHeight; uint lines; uint padding; } function _encodingCharset(Encoding encoding) private pure returns(string memory charset) { if (encoding == Encoding.HEX) charset = "0123456789abcdef"; if (encoding == Encoding.PUNCH) charset = unicode" • • • • •"; if (encoding == Encoding.OGHAM) charset = unicode"ᚁᚂᚃᚄᚅᚐᚑᚒᚓᚔᚆᚇᚈᚉᚊᚋᚌᚍᚎᚏ "; if (encoding == Encoding.HUMAN) charset = "0123456789"; if (encoding == Encoding.AUTOGLYPHS) charset = "#+/-|\\O"; if (encoding == Encoding.ATTIC) charset = unicode"ΙΠΔΗΜΧ"; if (encoding == Encoding.DEV) charset = "'\"[](){}`"; if (encoding == Encoding.WIRE) charset = ".-.-.-.-.-"; //had to cheat on binary to keep gas low if (encoding == Encoding.NOVEL) charset = "abcdefghijklmnopqrstuvwxyzAAACDEEEEHIIILMNOOPRSTUaaaaaaeeeeiiiioooorrrrrttnnssll"; } function getSvg(OutputConfig memory config) public pure returns(string memory){ SvgConfig memory svgConfig; string memory encodingCharset = _encodingCharset(config.encoding); if (config.encoding == Encoding.NOVEL) { bytes memory biggerHash = abi.encodePacked(config.hash, keccak256(abi.encodePacked(config.hash))); svgConfig.encodedHash = biggerHash.encode(encodingCharset); } else { svgConfig.encodedHash = config.hash.encode(encodingCharset); } svgConfig.fontSize = config.scale * 10; if (config.spacing == Spacing.COMFORTABLE) { svgConfig.charsLine = 1000 / svgConfig.fontSize; svgConfig.lineHeight = (svgConfig.fontSize * 28) / 10; } else if (config.spacing == Spacing.TIGHT) { svgConfig.charsLine = 3500 / svgConfig.fontSize; svgConfig.lineHeight = svgConfig.fontSize; } else { svgConfig.charsLine = 2000 / svgConfig.fontSize; svgConfig.lineHeight = (svgConfig.fontSize * 14) / 10; } svgConfig.lines = 2000 / svgConfig.lineHeight - 2; if (svgConfig.fontSize >= 30) { svgConfig.lines++; } svgConfig.padding = (2000 - (svgConfig.lines * svgConfig.lineHeight)) / 2; if (config.encoding == Encoding.PUNCH || config.encoding == Encoding.AUTOGLYPHS || config.encoding == Encoding.DEV || config.encoding == Encoding.WIRE || config.encoding == Encoding.NOVEL ) { encodingCharset = _encodingCharset(Encoding.HUMAN); } else { encodingCharset = _encodingCharset(config.encoding); } svgConfig.encodedId = config.id.encode(encodingCharset); if (config.encoding == Encoding.HEX) { if(bytes(svgConfig.encodedId).length % 2 == 0) { svgConfig.encodedId = string.concat("0x", svgConfig.encodedId); } else { svgConfig.encodedId = string.concat("0x0", svgConfig.encodedId); } if(bytes(svgConfig.encodedHash).length % 2 == 0) { svgConfig.encodedHash = string.concat("0x", svgConfig.encodedHash); } else { svgConfig.encodedHash = string.concat("0x0", svgConfig.encodedHash); } } else if (config.encoding == Encoding.OGHAM) { svgConfig.encodedHash = string.concat(unicode"᚛", svgConfig.encodedHash, unicode"᚜"); svgConfig.encodedId = string.concat(unicode"᚛", svgConfig.encodedId, unicode"᚜"); } svgConfig.encodedHashLength = _utf8StringLength(svgConfig.encodedHash); svgConfig.linesNeeded = _ceil(svgConfig.lines, svgConfig.encodedHashLength) * svgConfig.encodedHashLength; if (config.corruption > 0) { _corruptHashWithCharacterSpace(config, svgConfig); } uint stretchedLength = 0; while (stretchedLength < (svgConfig.charsLine + svgConfig.encodedHashLength)) { stretchedLength = stretchedLength + svgConfig.encodedHashLength; svgConfig.stretchedHash = string.concat(svgConfig.stretchedHash, svgConfig.encodedHash); } svgConfig.bytesStretchedHash = bytes(svgConfig.stretchedHash); string memory baseline = "central"; if (config.encoding == Encoding.OGHAM) { baseline = "text-bottom"; } string memory uniqueId = string.concat("first-", config.id.toString()); string memory svgText = string.concat( '<svg id="',uniqueId,'" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2000 2000" style="background-color:black;fill:white;">', '<style>', '#',uniqueId,' text{font-family:"Lucida Console",Monaco,monospace;dominant-baseline:',baseline,';}', '#',uniqueId,' .l{font-size:',svgConfig.fontSize.toString(),'px;line-height:',svgConfig.lineHeight.toString(),'px;}', '#',uniqueId,' .m{text-anchor:middle;font-size:400px;paint-order:stroke;stroke-width:30;stroke:black;}', '#',uniqueId,' .h{display:none;}', '</style>' ); uint offsetIndex; string[] memory lines = new string[](svgConfig.linesNeeded); uint[] memory offsets = _buildUtf8Offsets(svgConfig.bytesStretchedHash); // for (uint i;i < svgConfig.linesNeeded;i++) { lines[i] = _getSvgLine(i, offsetIndex, offsets, config, svgConfig); offsetIndex++; if (offsetIndex >= svgConfig.encodedHashLength) { offsetIndex = 0; } } svgText = string.concat( svgText, _concatStrings(lines), '<text class="m" x="1000" y="1000">', svgConfig.encodedId, '</text>', '<script><![CDATA[ !function(t,e){let l=document.currentScript.parentElement,c=l.querySelectorAll(".l"),r=l.querySelector(".m"),i=Array.from(c,t=>t.textContent),$,a;try{$=r.getAttribute("y"),a=document.documentElement.classList.contains("fix-right-click-save")}catch(n){}let s,o=l,y=!1,u=!1,b=!1,h=[["black","white",!1],["black","white",!0],["white","black",!1],["white","black",!0],["#65DB7E","black",!1],["#65DB7E","black",!0]],f=1;try{a&&((s=document.createElement("img")).style.top=0,s.style.left=0,s.style.width="100%",s.style.height="100%",s.style.opacity="0",s.style.position="fixed",document.body.appendChild(s),o=document.body)}catch(d){a=!1}try{o.addEventListener("mouseover",()=>{u=!0,k()}),o.addEventListener("mouseout",()=>{u=!1}),o.addEventListener("click",()=>{++f>h.length-1&&(f=0),a&&(o.style.backgroundColor=h[f][0]),l.style.backgroundColor=h[f][0],r.style.stroke=h[f][0],l.style.fill=h[f][1],y=!1,h[f][2]?r.setAttribute("y",$):r.setAttribute("y",-2e3),k()})}catch(_){}try{let g=new MutationObserver(t=>{try{for(let e of t)"attributes"===e.type&&"class"===e.attributeName&&(b=!!e.target.classList.contains("pause"))}catch(l){}});g.observe(l,{attributes:!0,attributeFilter:["class"]})}catch(m){}function k(){if(a)try{let t=new XMLSerializer().serializeToString(l),e=new Blob([t],{type:"image/svg+xml;charset=utf-8"}),c=URL.createObjectURL(e),r=new OffscreenCanvas(2e3,2e3),i=new Image;i.onload=()=>{let t=r.getContext("2d");t.fillStyle=h[f][0],t.fillRect(0,0,2e3,2e3),t.drawImage(i,0,0,2e3,2e3),r.convertToBlob().then(t=>{let e=URL.createObjectURL(t);s.src=e})},i.src=c}catch($){}}setInterval(function e(){if(u||b)return;let l=i.shift();if(i.push(l),c.forEach((t,e)=>{t.textContent=i[e]}),y){let $=Number(r.getAttribute("y"))-t;$<-2e3?y=!1:r.setAttribute("y",$)}},e),setTimeout(function t(){y=!0},1100)}(', svgConfig.lineHeight.toString(), ',', (config.speed * 30).toString(), '); ]]></script>', '</svg>' ); return svgText; } function _getSvgLine(uint lineNumber, uint offsetIndex, uint[] memory offsets, OutputConfig memory config, SvgConfig memory svgConfig) private pure returns(string memory) { string memory elementClass = "l"; if (lineNumber >= svgConfig.lines) { elementClass = "l h"; } uint offsetCalculated = _getSvgLineOffset(offsetIndex, config, svgConfig); string memory lineText = _getUtf8SubstringPrecomputed(svgConfig.bytesStretchedHash, offsets, offsetCalculated, svgConfig.charsLine); return string.concat( '<text class="', elementClass, '" x="', svgConfig.padding.toString(), '" y="', (lineNumber * svgConfig.lineHeight + (svgConfig.lineHeight / 2) + svgConfig.padding).toString(), '" textLength="', (2000 - svgConfig.padding - svgConfig.padding).toString(), '">', lineText, '</text>' ); } function _getSvgLineOffset(uint offsetIndex, OutputConfig memory config, SvgConfig memory svgConfig) private pure returns(uint) { uint offset = 0; if (config.drift == Drift.LEFT) { offset = offsetIndex * config.driftIntensity; } else if (config.drift == Drift.RIGHT) { offset = (svgConfig.encodedHashLength - offsetIndex) * config.driftIntensity; } else if (config.drift == Drift.RANDOM) { offset = _deterministicRandomUintForOutput(config, 0, svgConfig.encodedHashLength - 1); } else { //Sync.UNCERTAIN uint subOffset = offsetIndex % svgConfig.encodedHashLength; bool evenId = config.id % 2 == 0; if (evenId && subOffset <= svgConfig.encodedHashLength / 2) { offset = subOffset * config.driftIntensity; } else if (!evenId && subOffset > svgConfig.encodedHashLength / 2) { offset = subOffset * config.driftIntensity; } else { uint doubledLength = svgConfig.encodedHashLength * 2; offset = ((doubledLength - (subOffset % doubledLength)) % doubledLength) * config.driftIntensity; } } while (offset >= svgConfig.encodedHashLength) { offset = offset - svgConfig.encodedHashLength; } return offset; } function _deterministicRandomUintForOutput(OutputConfig memory config, uint256 min, uint256 max) public pure returns (uint256) { bytes32 combinedHash = keccak256(abi.encodePacked(config.hash, config.randomStep++)); uint256 randomUint = uint256(combinedHash); uint256 scaledRandom = randomUint % (max - min + 1) + min; return scaledRandom; } function _corruptHashWithCharacterSpace(OutputConfig memory config, SvgConfig memory svgConfig) public pure { bytes memory data = bytes(svgConfig.encodedHash); (uint[] memory starts, uint[] memory lengths) = _parseUtf8Codepoints(data); uint totalCodePoints = starts.length; bool[] memory replaced = new bool[](totalCodePoints); for (uint i = 0; i < config.corruption; i++) { uint j = _deterministicRandomUintForOutput(config, 0, totalCodePoints - 1); replaced[ j ] = true; } uint finalLength = 0; for (uint i = 0; i < totalCodePoints; i++) { if (replaced[i]) { finalLength += 3; } else { finalLength += lengths[i]; } } bytes memory newData = new bytes(finalLength); bytes3 figureSpace = bytes3(unicode" "); uint writePos = 0; for (uint i = 0; i < totalCodePoints; i++) { if (replaced[i]) { for (uint k = 0; k < 3; k++) { newData[writePos + k] = figureSpace[k]; } writePos += 3; } else { uint startIndex = starts[i]; uint lengthBytes = lengths[i]; for (uint k = 0; k < lengthBytes; k++) { newData[writePos + k] = data[startIndex + k]; } writePos += lengthBytes; } } svgConfig.encodedHash = string(newData); } function _parseUtf8Codepoints(bytes memory data) private pure returns (uint[] memory starts, uint[] memory lengths) { uint[] memory tempStarts = new uint[](data.length); uint[] memory tempLens = new uint[](data.length); uint count = 0; uint i = 0; while (i < data.length) { tempStarts[count] = i; uint cpLen = _utf8CharLength(data, i); tempLens[count] = cpLen; i += cpLen; count++; } starts = new uint[](count); lengths = new uint[](count); for (uint k = 0; k < count; k++) { starts[k] = tempStarts[k]; lengths[k] = tempLens[k]; } return (starts, lengths); } function _getUtf8SubstringPrecomputed(bytes memory strBytes, uint[] memory offsets, uint startChar, uint numChars) internal pure returns (string memory) { if (startChar >= offsets.length - 1) { return ""; } uint endChar = startChar + numChars; if (endChar >= offsets.length) { endChar = offsets.length - 1; } uint byteStart = offsets[startChar]; uint byteEnd = offsets[endChar]; // This is safe because endChar < offsets.length uint length = byteEnd - byteStart; bytes memory result = new bytes(length); for (uint i = 0; i < length; i++) { result[i] = strBytes[byteStart + i]; } return string(result); } function _utf8StringLength(string memory data) private pure returns (uint) { bytes memory bytesData = bytes(data); uint length = 0; uint i = 0; while (i < bytesData.length) { uint charLen = _utf8CharLength(bytesData, i); i += charLen; length++; } return length; } function _utf8CharLength(bytes memory data, uint start) private pure returns (uint) { uint8 b = uint8(data[start]); if ((b & 0x80) == 0) { return 1; } else if ((b & 0xE0) == 0xC0) { return 2; } else if ((b & 0xF0) == 0xE0) { return 3; } else { return 4; } } function _ceil(uint256 a, uint256 b) private pure returns (uint256) { return (a + b - 1) / b; } function _buildUtf8Offsets(bytes memory strBytes) internal pure returns (uint[] memory) { uint lengthBytes = strBytes.length; uint[] memory tempOffsets = new uint[](lengthBytes + 1); uint offsetIndex = 0; uint bytePos = 0; while (bytePos < lengthBytes) { tempOffsets[offsetIndex] = bytePos; offsetIndex++; uint charLen = _utf8CharLength(strBytes, bytePos); bytePos += charLen; } tempOffsets[offsetIndex] = bytePos; // should equal strBytes.length uint[] memory offsets = new uint[](offsetIndex + 1); for (uint i = 0; i <= offsetIndex; i++) { offsets[i] = tempOffsets[i]; } return offsets; } function _concatStrings(string[] memory lines) private pure returns (string memory) { uint256 totalLength = 0; for (uint256 i = 0; i < lines.length; i++) { totalLength += bytes(lines[i]).length; } bytes memory buffer = new bytes(totalLength); uint256 offset = 0; for (uint256 i = 0; i < lines.length; i++) { bytes memory current = bytes(lines[i]); for (uint256 j = 0; j < current.length; j++) { buffer[offset++] = current[j]; } } return string(buffer); } }
/* SPDX-License-Identifier: MIT Author: nix.eth */ pragma solidity ^0.8.27; struct OutputConfig { uint id; bytes32 hash; Encoding encoding; Drift drift; uint driftIntensity; uint speed; uint scale; uint corruption; Spacing spacing; uint randomStep; } enum Encoding { NOVEL, PUNCH, HEX, AUTOGLYPHS, ATTIC, DEV, WIRE, HUMAN, OGHAM } enum Drift { UNCERTAIN, LEFT, RIGHT, RANDOM } enum Spacing { NORMAL, TIGHT, COMFORTABLE }
/* SPDX-License-Identifier: MIT Author: nix.eth */ pragma solidity ^0.8.27; library GenericEncoder { function encode(bytes32 data, string memory charset) internal pure returns (string memory) { if (data == 0) { return encode(abi.encodePacked(uint8(0)), charset); } uint256 nonZero = 32; while (nonZero > 0 && data[32 - nonZero] == 0) { nonZero--; } bytes memory trimmed = new bytes(nonZero); for (uint256 i = 0; i < nonZero; i++) { trimmed[i] = data[32 - nonZero + i]; } return encode(trimmed, charset); } function encode(uint256 data, string memory charset) internal pure returns (string memory) { if (data == 0) { return encode(abi.encodePacked(uint8(0)), charset); } uint256 temp = data; uint256 length; while (temp != 0) { length++; temp >>= 8; } bytes memory buf = new bytes(length); temp = data; for (uint256 i = length; i > 0; i--) { buf[i - 1] = bytes1(uint8(temp)); temp >>= 8; } return encode(buf, charset); } function encode(bytes memory data, string memory charset) internal pure returns (string memory) { if (data.length == 0) { return ""; } bytes memory charBytes = bytes(charset); uint256[] memory charStartIndices = _parseCharset(charBytes); uint256 base = charStartIndices.length; require(base >= 2, "Charset must have at least 2 symbols"); bytes memory num = new bytes(data.length); for (uint256 i = 0; i < data.length; i++) { num[i] = data[i]; } uint256[] memory digits = new uint256[](data.length * 8); uint256 digitCount = 0; while (!_isAllZero(num)) { (uint256 remainder, bytes memory nextVal) = _divmod(num, base); digits[digitCount] = remainder; digitCount++; num = nextVal; } if (digitCount == 0) { digits[digitCount++] = 0; } bytes memory out = new bytes(digitCount * 4); uint256 offset = 0; for (uint256 i = 0; i < digitCount; i++) { uint256 d = digits[digitCount - 1 - i]; offset = _appendUtf8Char(out, offset, charBytes, charStartIndices[d]); } bytes memory trimmed = new bytes(offset); for (uint256 i = 0; i < offset; i++) { trimmed[i] = out[i]; } return string(trimmed); } function _isAllZero(bytes memory num) private pure returns (bool) { for (uint256 i = 0; i < num.length; i++) { if (num[i] != 0) { return false; } } return true; } function _divmod(bytes memory num, uint256 base) private pure returns (uint256, bytes memory) { uint256 r = 0; // remainder uint256 len = num.length; bytes memory quotient = new bytes(len); // same length as num initially for (uint256 i = 0; i < len; i++) { uint256 val = (r << 8) | uint8(num[i]); uint256 digit = val / base; r = val % base; quotient[i] = bytes1(uint8(digit)); } uint256 start = 0; while (start < len - 1 && quotient[start] == 0) { start++; } if (start == 0) { return (r, quotient); } else if (start == len) { bytes memory oneZero = new bytes(1); oneZero[0] = 0x00; return (r, oneZero); } else { bytes memory trimmed = new bytes(len - start); for (uint256 j = 0; j < trimmed.length; j++) { trimmed[j] = quotient[start + j]; } return (r, trimmed); } } function _parseCharset(bytes memory charset) internal pure returns (uint256[] memory) { uint256 length = charset.length; uint256[] memory indices = new uint256[](length); uint256 charCount = 0; for (uint256 i = 0; i < length; i++) { if ((charset[i] & 0xC0) != 0x80) { indices[charCount++] = i; } } uint256[] memory result = new uint256[](charCount); for (uint256 i = 0; i < charCount; i++) { result[i] = indices[i]; } return result; } function _appendUtf8Char( bytes memory result, uint256 offset, bytes memory charset, uint256 startIndex ) internal pure returns (uint256) { uint256 endIndex = startIndex; while (endIndex + 1 < charset.length && (charset[endIndex + 1] & 0xC0) == 0x80) { endIndex++; } for (uint256 i = startIndex; i <= endIndex; i++) { result[offset++] = charset[i]; } return offset; } }
/* SPDX-License-Identifier: MMIITT Author: nix.eth */ pragma solidity ^0.8.27; import "./FirstsRendererConfig.sol"; interface IFirstsSvgGenerator { function getSvg(OutputConfig memory config) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { 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 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)); } }
// 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/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.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)) } } }
{ "optimizer": { "enabled": true, "mode": "3" }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "abi" ] } }, "detectMissingLibraries": false, "forceEVMLA": false, "enableEraVMExtensions": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"enum Encoding","name":"encoding","type":"uint8"},{"internalType":"enum Drift","name":"drift","type":"uint8"},{"internalType":"uint256","name":"driftIntensity","type":"uint256"},{"internalType":"uint256","name":"speed","type":"uint256"},{"internalType":"uint256","name":"scale","type":"uint256"},{"internalType":"uint256","name":"corruption","type":"uint256"},{"internalType":"enum Spacing","name":"spacing","type":"uint8"},{"internalType":"uint256","name":"randomStep","type":"uint256"}],"internalType":"struct OutputConfig","name":"config","type":"tuple"},{"components":[{"internalType":"uint256","name":"linesNeeded","type":"uint256"},{"internalType":"uint256","name":"encodedHashLength","type":"uint256"},{"internalType":"string","name":"encodedHash","type":"string"},{"internalType":"string","name":"stretchedHash","type":"string"},{"internalType":"bytes","name":"bytesStretchedHash","type":"bytes"},{"internalType":"string","name":"encodedId","type":"string"},{"internalType":"uint256","name":"fontSize","type":"uint256"},{"internalType":"uint256","name":"charsLine","type":"uint256"},{"internalType":"uint256","name":"lineHeight","type":"uint256"},{"internalType":"uint256","name":"lines","type":"uint256"},{"internalType":"uint256","name":"padding","type":"uint256"}],"internalType":"struct FirstsSvgGenerator.SvgConfig","name":"svgConfig","type":"tuple"}],"name":"_corruptHashWithCharacterSpace","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"enum Encoding","name":"encoding","type":"uint8"},{"internalType":"enum Drift","name":"drift","type":"uint8"},{"internalType":"uint256","name":"driftIntensity","type":"uint256"},{"internalType":"uint256","name":"speed","type":"uint256"},{"internalType":"uint256","name":"scale","type":"uint256"},{"internalType":"uint256","name":"corruption","type":"uint256"},{"internalType":"enum Spacing","name":"spacing","type":"uint8"},{"internalType":"uint256","name":"randomStep","type":"uint256"}],"internalType":"struct OutputConfig","name":"config","type":"tuple"},{"internalType":"uint256","name":"min","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"_deterministicRandomUintForOutput","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"enum Encoding","name":"encoding","type":"uint8"},{"internalType":"enum Drift","name":"drift","type":"uint8"},{"internalType":"uint256","name":"driftIntensity","type":"uint256"},{"internalType":"uint256","name":"speed","type":"uint256"},{"internalType":"uint256","name":"scale","type":"uint256"},{"internalType":"uint256","name":"corruption","type":"uint256"},{"internalType":"enum Spacing","name":"spacing","type":"uint8"},{"internalType":"uint256","name":"randomStep","type":"uint256"}],"internalType":"struct OutputConfig","name":"config","type":"tuple"}],"name":"getSvg","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"}]
Contract Creation Code
9c4d535b0000000000000000000000000000000000000000000000000000000000000000010004e112efdfe6a72c93c293bdd84e7cf910f4ea411958f8599a32ff154ecf00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x0002000000000002001d00000000000200010000000103550000006003100270000004260030019d0000008004000039000000400040043f00000001002001900000005d0000c13d0000042602300197000000040020008c000000c10000413d000000000301043b000000e003300270000004280030009c0000009a0000613d000004290030009c000000650000613d0000042a0030009c000000c10000c13d000001440020008c000000c10000413d0000000003000416000000000003004b000000c10000c13d000001c003000039000000400030043f0000000403100370000000000303043b000000800030043f0000002403100370000000000803043b000000a00080043f0000004403100370000000000403043b000000080040008c000000c10000213d000000c00040043f0000006403100370000000000303043b000000030030008c000000c10000213d000000e00030043f0000008403100370000000000303043b000001000030043f000000a403100370000000000303043b000001200030043f000000c403100370000000000303043b000001400030043f000000e403100370000000000303043b000001600030043f0000010403100370000000000303043b000000020030008c000000c10000213d000001800030043f0000012403100370000000000303043b000001a00030043f001c01c00000003d001d00800000003d0000032003000039000000400030043f000001c00000043f000001e00000043f0000006005000039000002000050043f000002200050043f000002400050043f000002600050043f000002800000043f000002a00000043f000002c00000043f000002e00000043f000003000000043f000000080040008c000004140004a13e000002440000013d000003a004000039000000400040043f0000005004000039000003200040043f0000043004000041000003400040043f0000043104000041000003600040043f00000432040000410000038005000039000002050000013d0000000001000416000000000001004b000000c10000c13d00000020010000390000010000100443000001200000044300000427010000410000104e0001042e000001840020008c000000c10000413d0000000002000416000000000002004b000000c10000c13d000001c002000039000000400020043f0000000402100370000000000202043b000000800020043f0000002402100370000000000202043b000000a00020043f0000004403100370000000000303043b000000080030008c000000c10000213d000000c00030043f0000006403100370000000000303043b000000030030008c000000c10000213d000000e00030043f0000008403100370000000000303043b000001000030043f000000a403100370000000000303043b000001200030043f000000c403100370000000000303043b000001400030043f000000e403100370000000000303043b000001600030043f0000010403100370000000000303043b000000020030008c000000c10000213d000001800030043f0000012403100370000000000303043b000001a00030043f0000014401100370000000000401043b000000010130003a000001ad0000c13d000004cd01000041000000000010043f0000001101000039000000040010043f000004ce010000410000104f00010430000001640020008c000000c10000413d0000000003000416000000000003004b000000c10000c13d000001c003000039000000400030043f0000000403100370000000000303043b000000800030043f0000002403100370000000000303043b000000a00030043f0000004403100370000000000303043b000000080030008c000000c10000213d000000c00030043f0000006403100370000000000303043b000000030030008c000000c10000213d000000e00030043f0000008403100370000000000303043b000001000030043f000000a403100370000000000303043b000001200030043f000000c403100370000000000303043b000001400030043f000000e403100370000000000303043b000001600030043f0000010403100370000000000303043b000000020030008c000000c30000a13d00000000010000190000104f00010430000001800030043f0000012403100370000000000303043b000001a00030043f0000014403100370000000000403043b0000042b0040009c000000c10000213d00000000034200490000042c0030009c000000c10000213d000001640030008c000000c10000413d0000032006000039000000400060043f0000000403400039000000000531034f000000000505043b000001c00050043f0000002405400039000000000551034f000000000505043b000001e00050043f0000004407400039000000000571034f000000000505043b0000042b0050009c000000c10000213d000000000a4500190000002305a00039000000000025004b000000c10000813d0000000409a00039000000000591034f000000000805043b0000042b0080009c000003cd0000213d0000001f0b800039000004cf0bb001970000003f0bb00039000004cf0bb001970000042d00b0009c000003cd0000213d000000240aa00039000003200bb000390000004000b0043f000003200080043f000000000aa8001900000000002a004b000000c10000213d0000002009900039000000000a91034f000004cf0b8001980000001f0c80018f0000034009b00039000001010000613d000003400d000039000000000e0a034f00000000ef0e043c000000000dfd043600000000009d004b000000fd0000c13d00000000000c004b0000010e0000613d000000000aba034f000000030bc00210000000000c090433000000000cbc01cf000000000cbc022f000000000a0a043b000001000bb00089000000000aba022f000000000aba01cf000000000aca019f0000000000a9043500000340088000390000000000080435000002000060043f0000002006700039000000000761034f000000000707043b0000042b0070009c000000c10000213d00000000094700190000002307900039000000000027004b000000c10000813d000000040a9000390000000007a1034f000000000707043b0000042b0070009c000003cd0000213d0000001f08700039000004cf088001970000003f08800039000004cf0b800197000000400800043d000000000bb8001900000000008b004b000000000c000039000000010c0040390000042b00b0009c000003cd0000213d0000000100c00190000003cd0000c13d000000240c9000390000004000b0043f0000000009780436000000000bc7001900000000002b004b000000c10000213d000000200aa000390017000000a10353000004cf0c7001980000001f0d70018f000000000ac900190000013e0000613d000000170e00035f000000000f09001900000000eb0e043c000000000fbf04360000000000af004b0000013a0000c13d00000000000d004b0000014b0000613d000000170bc0035f000000030cd00210000000000d0a0433000000000dcd01cf000000000dcd022f000000000b0b043b000001000cc00089000000000bcb022f000000000bcb01cf000000000bdb019f0000000000ba043500000000077900190000000000070435000002200080043f0000002006600039000000000761034f000000000707043b0000042b0070009c000000c10000213d00000000084700190000002304800039000000000024004b000000c10000813d0000000409800039000000000491034f000000000404043b0000042b0040009c000003cd0000213d0000001f07400039000004cf077001970000003f07700039000004cf0a700197000000400700043d000000000aa7001900000000007a004b000000000b000039000000010b0040390000042b00a0009c000003cd0000213d0000000100b00190000003cd0000c13d000000240b8000390000004000a0043f0000000008470436000000000ab4001900000000002a004b000000c10000213d0000002009900039000000000991034f000004cf0a4001980000001f0b40018f0000000005a800190000017b0000613d000000000c09034f000000000d08001900000000ce0c043c000000000ded043600000000005d004b000001770000c13d00000000000b004b000001880000613d0000000009a9034f000000030ab00210000000000b050433000000000bab01cf000000000bab022f000000000909043b000001000aa000890000000009a9022f0000000009a901cf0000000009b9019f000000000095043500000000044800190000000000040435000002400070043f001700200060003d0000001701100360000000000101043b0000042b0010009c000000c10000213d0000000001310019104d0bc80000040f000002600010043f000000170300002900000020013000390000000101100367000000000101043b000002800010043f00000040013000390000000101100367000000000101043b000002a00010043f00000060013000390000000101100367000000000101043b000002c00010043f000000a001300039000000010110036700000080033000390000000102300367000000000202043b000002e00020043f000000000101043b000003000010043f0000008001000039000001c002000039104d0c120000040f00000000010000190000104e0001042e001700000004001d000001a00010043f000001e00020043f000002000030043f0000004001000039000001c00010043f0000022001000039000000400010043f0000000001000414000004260010009c0000042601008041000000c0011002100000042e011001c70000801002000039104d10480000040f0000000100200190000000c10000613d000000000101043b00000164020000390000000102200367000000000202043b0000001703000029000000000232004b000000940000413d000000010220003a000000940000613d00000000102100d9000000000031001a000000940000413d0000000001310019000000400200043d0000000000120435000004260020009c000004260200804100000040012002100000042f011001c70000104e0001042e0000036004000039000000400040043f0000000904000039000003200040043f0000043404000041000002040000013d0000036004000039000000400040043f0000001e04000039000003200040043f0000043a04000041000002040000013d0000036004000039000000400040043f0000000c04000039000003200040043f0000043504000041000002040000013d0000038004000039000000400040043f0000003f04000039000003200040043f0000043804000041000003400040043f00000439040000410000036005000039000002050000013d0000036004000039000000400040043f0000001004000039000003200040043f0000043b04000041000002040000013d0000036004000039000000400040043f0000000704000039000003200040043f0000043604000041000002040000013d0000036004000039000000400040043f0000000a04000039000003200040043f0000043304000041000002040000013d0000036004000039000000400040043f0000000a04000039000003200040043f000004370400004100000340050000390000000000450435000000c00400043d000000090040008c0000020f0000413d000004cd01000041000000000010043f0000002101000039000000040010043f000004ce010000410000104f0001043000000000070004150000001a0770008a0000000507700210001a00000000003d000000a00800043d000000000004004b000002490000c13d000000400100043d00000020020000390000000002210436001700000008001d00000000008204350000043c0010009c000003cd0000213d0000004003100039000000400030043f000004260020009c000004260200804100000040022002100000000001010433000004260010009c00000426010080410000006001100210000000000121019f0000000002000414000004260020009c0000042602008041000000c002200210000000000112019f0000043d011001c70000801002000039104d10480000040f00000001002001900000001704000029000000c10000613d000000000201043b000000400100043d0000004003100039000000000023043500000020021000390000000000420435000000400200003900000000002104350000043e0010009c000003cd0000213d0000006002100039000000400020043f0000032002000039104d0dd60000040f00000000020004150000001a0220008a00170005002002180000030d0000013d00000000070004150000001b0770008a00000005077002100000006003000039001b00000000003d000000000008004b001700000007001d000002550000c13d000000400400043d0000000101000039000000000114043600000000000104350000045e0040009c000003cd0000813d0000004001400039000000400010043f0000030a0000013d000000400600003900000020050000390000043f0080009c0000025d0000a13d000000000a08001900000000080000190000000007050019000002e10000013d0000044000800198000002a10000c13d0000044100800198000002a40000c13d000000000a0800190000044200800198000002a70000c13d0000044300a00198000002a90000c13d0000044400a00198000002ab0000c13d0000044500a00198000002ad0000c13d0000044600a00198000002af0000c13d0000044700a00198000002b10000c13d0000044800a00198000002b30000c13d0000044900a00198000002b50000c13d0000044a00a00198000002b70000c13d0000044b00a00198000002b90000c13d0000044c00a00198000002bb0000c13d0000044d00a00198000002bd0000c13d0000044e00a00198000002bf0000c13d0000044f00a00198000002c10000c13d0000045000a00198000002c30000c13d0000045100a00198000002c50000c13d0000045200a00198000002c70000c13d0000045300a00198000002c90000c13d0000045400a00198000002cb0000c13d0000045500a00198000002cd0000c13d0000045600a00198000002cf0000c13d0000045700a00198000002d10000c13d0000045800a00198000002d30000c13d0000045900a00198000002d50000c13d0000045a00a00198000002d70000c13d0000045b00a00198000002d90000c13d0000045c00a00198000002db0000c13d0000ff0000a00190000002dd0000c13d000000ff00a00190000002df0000c13d0000000108000039000000200600003900000000050000190000000007000019000002e10000013d000000000a0800190000001f07000039000002e00000013d000000000a0800190000001e07000039000002e00000013d0000001d07000039000002e00000013d0000001c07000039000002e00000013d0000001b07000039000002e00000013d0000001a07000039000002e00000013d0000001907000039000002e00000013d0000001807000039000002e00000013d0000001707000039000002e00000013d0000001607000039000002e00000013d0000001507000039000002e00000013d0000001407000039000002e00000013d0000001307000039000002e00000013d0000001207000039000002e00000013d0000001107000039000002e00000013d0000001007000039000002e00000013d0000000f07000039000002e00000013d0000000e07000039000002e00000013d0000000d07000039000002e00000013d0000000c07000039000002e00000013d0000000b07000039000002e00000013d0000000a07000039000002e00000013d0000000907000039000002e00000013d0000000807000039000002e00000013d0000000707000039000002e00000013d0000000607000039000002e00000013d0000000507000039000002e00000013d0000000407000039000002e00000013d0000000307000039000002e00000013d0000000207000039000002e00000013d00000001070000390000000008000019000000400400043d0000000009460019000000000069004b000000000600003900000001060040390000042b0090009c000003cd0000213d0000000100600190000003cd0000c13d000000400090043f0000000006740436000000000005004b000002f50000613d000000000121034f00000000025600190000000005060019000000001901043c0000000005950436000000000025004b000002f10000c13d000000000008004b0000030a0000c13d00000000020000190000000005720049000004d00050009c00000a3a0000a13d0000000008040433000000000028004b00000a3a0000a13d0000000305500210000001000550003900000000055a01cf000000000862001900000000090804330000043f099001970000045d05500197000000000559019f00000000005804350000000102200039000000000072004b000002f80000413d00000000010400190000000002030019104d0dd60000040f000002000010043f000001400200043d0000000a012000c9000000000002004b000003150000613d00000000032100d90000000a0030008c000000940000c13d000002800010043f000001800300043d000000020030008c000002090000213d000000010030008c000003260000613d000000020030008c0000032d0000c13d000000000001004b000003390000613d000003e803100119000002a00030043f00000118032000c900000000021300d90000001c0020008c000000940000c13d000003350000013d000000000001004b000003390000613d00000dac02100119000002a00020043f000002c00010043f00000000050100190000033f0000013d000000000001004b000003390000613d000007d003100119000002a00030043f0000008c032000c900000000021300d90000000e0020008c000000940000c13d0000000a0530011a000002c00050043f0000000a0030008c0000033f0000813d000004cd01000041000000000010043f0000001201000039000000040010043f000004ce010000410000104f00010430000003e80050008c000000940000213d0000006002000039000007d004500119000000020340008a000002e00030043f0000001e0010008c0000034a0000413d000000010340008a000002e00030043f0000034d0000013d000000000003004b0000000001000019000003530000613d00000000015300a900000000033100d9000000000053004b000000940000c13d000007d00010008c000000940000213d000007d0011000890000000101100270000003000010043f000000c00100043d000000080010008c000002090000213d0000041d0001a13e000003650000013d000000400100043d0000043c0010009c000003cd0000213d00000000020100190000004001200039000000400010043f0000000a01000039000000000112043600000437030000410000000000310435000000800a00043d00000000000a004b000003810000c13d000000400100043d0000000103000039000000000331043600000000000304350000043c0010009c000003cd0000213d0000004003100039000000400030043f104d0dd60000040f000002600010043f000000c00200043d000000080020008c000003d30000a13d000000170100002900000005011002700000000001010031000004cd0200004100000000002104350000002102000039000000040020043f000004260010009c00000426010080410000004001100210000004ce011001c70000104f0001043000000000040a00190000000003000019000000000103001900000001033000390000000804400272000003830000c13d0000045f0010009c000003cd0000213d00000460051001970000005f015000390000046004100197000000400100043d0000000004410019000000000014004b000000000600003900000001060040390000042b0040009c000003cd0000213d0000000100600190000003cd0000c13d000000400040043f000000000431043600000020065000390000001f0560018f0000046006600198000003a30000613d0000000006640019000000000700003100000001077003670000000008040019000000007907043c0000000008980436000000000068004b0000039f0000c13d000000000005004b000000010330008a0000000005010433000000000035004b00000a3a0000a13d000000000543001900000000060504330000043f06600197000000f807a00210000000000676019f0000000000650435000000080aa00270000000000003004b000003a40000c13d000003700000013d000000400100043d0000043e0010009c000003cd0000213d00000000020100190000006001200039000000400010043f0000002001200039000004380300004100000000003104350000003f01000039000000000012043500000439030000410000004001200039000003640000013d000000400100043d0000043c0010009c000003cd0000213d00000000020100190000004001200039000000400010043f0000000c0100003900000000011204360000043503000041000003640000013d000000400100043d0000043c0010009c0000041b0000a13d000004cd01000041000000000010043f0000004101000039000000040010043f000004ce010000410000104f00010430000000020020008c000004220000613d000000080020008c000004920000c13d000000400200043d0000002001200039000002000400043d0000046103000041000000000031043500000023032000390000000041040434000000000001004b000003e80000613d000000000500001900000000063500190000000007540019000000000707043300000000007604350000002005500039000000000015004b000003e10000413d000000000331001900000462040000410000000000430435000000060310003900000000003204350000004501100039000004cf041001970000000001240019000000000041004b000000000400003900000001040040390000042b0010009c000003cd0000213d0000000100400190000003cd0000c13d000000400010043f000002000020043f0000002002100039000002600500043d0000046104000041000000000042043500000023041000390000000052050434000000000002004b000004090000613d000000000600001900000000074600190000000008650019000000000808043300000000008704350000002006600039000000000026004b000004020000413d000000000442001900000462050000410000000000540435000000060420003900000000004104350000004502200039000004cf032001970000000002130019000000000032004b000000000300003900000001030040390000042b0020009c000003cd0000213d0000000100300190000003cd0000c13d000000400020043f000002600010043f000004920000013d00000000020100190000004001200039000000400010043f000000100100003900000000011204360000043b03000041000003640000013d0000002003100039000000400200043d0000002004200039000000000501043300000001005001900000043c0000c13d0000046405000041000000000054043500000022042000390000000001010433000000000001004b000004360000613d000000000500001900000000064500190000000007350019000000000707043300000000007604350000002005500039000000000015004b0000042f0000413d000000000341001900000000000304350000000203100039000000000032043500000041011000390000044f0000013d0000046305000041000000000054043500000023042000390000000001010433000000000001004b0000044a0000613d000000000500001900000000064500190000000007350019000000000707043300000000007604350000002005500039000000000015004b000004430000413d00000000034100190000000000030435000000030310003900000000003204350000004201100039000004cf031001970000000001230019000000000031004b000000000300003900000001030040390000042b0010009c000003cd0000213d0000000100300190000003cd0000c13d000000400010043f000002600020043f0000002004100039000002000300043d000000200230003900000000050304330000000100500190000004740000c13d0000046405000041000000000054043500000022041000390000000003030433000000000003004b0000046e0000613d000000000500001900000000064500190000000007250019000000000707043300000000007604350000002005500039000000000035004b000004670000413d00000000024300190000000000020435000000020230003900000000002104350000004102300039000004870000013d0000046305000041000000000054043500000023041000390000000003030433000000000003004b000004820000613d000000000500001900000000064500190000000007250019000000000707043300000000007604350000002005500039000000000035004b0000047b0000413d00000000024300190000000000020435000000030230003900000000002104350000004202300039000004cf032001970000000002130019000000000032004b000000000300003900000001030040390000042b0020009c000003cd0000213d0000000100300190000003cd0000c13d000000400020043f000002000010043f000002000100043d0000000032010434000000000002004b0000000001000019000004ae0000613d0000000007000019000000000100001900000000087300190000000009080433000004650090009c0000000108000039000004a60000413d0000046608900197000004670080009c0000000208000039000004a60000613d0000046808900197000004660080009c00000004080000390000000308006039000000000078001a000000940000413d000004d10010009c000000940000613d00000000077800190000000101100039000000000027004b000004990000413d000001e00010043f000002e00200043d000000000012001a000000940000413d000000000212001a000000940000613d000000000001004b000003390000613d000000010420008a00000000031400d900000000021300a9000000000041004b000004be0000213d00000000033200d9000000000013004b000000940000c13d000001c00020043f000001600200043d000000000002004b000004c60000613d0000008001000039000001c002000039104d0c120000040f000001e00100043d000002a00200043d000000000012001a000000940000413d00000000031200190000000002000019000000000032004b000005020000813d000000000012001a000000940000413d000002000500043d000002200400043d000000400300043d00000020063000390000000074040434000000000004004b000004de0000613d00000000080000190000000009680019000000000a870019000000000a0a04330000000000a904350000002008800039000000000048004b000004d70000413d000000000664001900000000000604350000000075050434000000000005004b000004eb0000613d00000000080000190000000009680019000000000a870019000000000a0a04330000000000a904350000002008800039000000000058004b000004e40000413d00000000066500190000000000060435000000000445001900000000004304350000003f04400039000004cf054001970000000004350019000000000054004b000000000500003900000001050040390000042b0040009c000003cd0000213d0000000100500190000003cd0000c13d0000000002120019000000400040043f000002200030043f000002a00400043d000001e00100043d0000000003410019000000000041001a000000940000413d000004cb0000013d000002200100043d000002400010043f001900400000003d000000400500043d0000043c0050009c000003cd0000213d0000004001500039000000400010043f0000000701000039000000000415043600000469010000410000000000140435000000c00100043d000000080010008c000002090000213d0000051b0000c13d000000400500043d0000043c0050009c000003cd0000213d0000004001500039000000400010043f0000000b0100003900000000041504360000046a010000410000000000140435000000800600043d0000046b0060009c000005210000413d00000040070000390000046b0160012a0000052a0000013d0000046d0060009c00000000010600190000046c0110212a000000000700003900000020070020390000046e0010009c00000010077081bf0000046f011081970000046e0110812a000004700010009c00000008077080390000042b01108197000004700110812a000027100010008c00000004077080390000042601108197000027100110811a000000640010008c00000002077080390000ffff0110818f000000640110811a000000090010008c0000000107702039000004cf017001970000005f02100039000004cf03200197000000400900043d0000000002930019000000000032004b000000000300003900000001030040390000042b0020009c000003cd0000213d0000000100300190000003cd0000c13d000000400020043f000000010270003900000000082904360000002001100039000004cf021001980000001f0a10018f0000000003000031000d00010000036b000c00000003001d0000000101300367000005560000613d000000000b280019000000000c01034f000000000308001900000000c20c043c00000000032304360000000000b3004b000005520000c13d00000000000a004b00000000027900190000002107200039000000090060008c0000000a2660011a0000000302200210000000010770008a00000000030704330000043f033001970000043b0220021f0000047102200197000000000232019f0000000000270435000005590000213d000000400700043d000000200670003900000472020000410000000000260435000000260a7000390000000009090433000000000009004b000005740000613d000000000b0000190000000002ab001900000000038b001900000000030304330000000000320435000000200bb0003900000000009b004b0000056d0000413d0000000002a900190000000000020435000000060290003900000000002704350000004502900039000004cf022001970000000008720019000000000028004b000000000200003900000001020040390000042b0080009c000003cd0000213d0000000100200190000003cd0000c13d000000400080043f000002800a00043d0000046b00a0009c000005890000413d000000400b0000390000046b09a0012a000005920000013d0000046d00a0009c00000000090a00190000046c0990212a000000000b000039000000200b0020390000046e0090009c000000100bb081bf0000046f029081970000046e0920812a000004700090009c000000080bb080390000042b02908197000004700920812a000027100090008c000000040bb080390000042602908197000027100920811a000000640090008c000000020bb080390000ffff0290818f000000640920811a000000090090008c000000010bb02039000004cf03b001970000005f02300039000004cf0220019700000000028200190000042b0020009c000003cd0000213d000000400020043f0000000102b0003900000000092804360000002003300039000004cf023001980000001f0c30018f000005b40000613d000000000d290019000000000e01034f000000000309001900000000e20e043c00000000032304360000000000d3004b000005b00000c13d00000000000c004b0000000002b80019000000210b2000390000000900a0008c0000000a2aa0011a0000000302200210000000010bb0008a00000000030b04330000043f033001970000043b0220021f0000047102200197000000000232019f00000000002b0435000005b70000213d000002c00a00043d0000046b00a0009c000005c80000413d000000400d0000390000046b0ba0012a000005d10000013d0000046d00a0009c000000000b0a00190000046c0bb0212a000000000d000039000000200d0020390000046e00b0009c000000100dd081bf0000046f02b081970000046e0b20812a0000047000b0009c000000080dd080390000042b02b08197000004700b20812a0000271000b0008c000000040dd080390000042602b08197000027100b20811a0000006400b0008c000000020dd080390000ffff02b0818f000000640b20811a0000000900b0008c000000010dd02039000004cf0ed001970000005f02e00039000004cf02200197000000400300043d001600000003001d0000000003320019000000000023004b000000000200003900000001020040390000042b0030009c000003cd0000213d0000000100200190000003cd0000c13d000000400030043f0000000102d0003900000016030000290000000002230436000000200be00039000004cf03b001980000001f0eb0018f000005fb0000613d000000000f320019000000000301034f000000000b020019000000003c03043c000000000bcb04360000000000fb004b000005f70000c13d00000000000e004b0000001603d00029000000210d3000390000000900a0008c0000000a3aa0011a0000000303300210000000010dd0008a000000000b0d04330000043f0bb001970000043b0330021f00000471033001970000000003b3019f00000000003d0435000005fe0000213d000000400a00043d00180000000a001d0000002003a00039000004730b0000410000000000b30435000000290ea00039000000000d07043300000000000d004b0000061a0000613d0000000003000019000000000be30019000000000c630019000000000c0c04330000000000cb043500000020033000390000000000d3004b000006130000413d0000000003ed00190000000000030435000000000dad00190000008903d00039000004740b0000410000000000b304350000009103d00039000004750b0000410000000000b304350000006903d00039000004760b0000410000000000b304350000004903d00039000004770b0000410000000000b304350000002903d00039000004780b0000410000000000b304350000009803d00039000004790b0000410000000000b30435000000990fd00039000000000e07043300000000000e004b0000063b0000613d0000000003000019000000000bf30019000000000c630019000000000c0c04330000000000cb043500000020033000390000000000e3004b000006340000413d0000000003fe001900000000000304350000000003de0019000000d90b3000390000047a0c0000410000000000cb0435000000b90b3000390000047b0c0000410000000000cb0435000000990b3000390000047c0c0000410000000000cb0435000000df0e300039000000290d3000390000000005050433000000000005004b000006540000613d0000000003000019000000000be30019000000000c340019000000000c0c04330000000000cb04350000002003300039000000000053004b0000064d0000413d0000000003e50019000000000003043500000000035d0019000000b6043000390000047d050000410000000000540435000000b80430003900000479050000410000000000540435000000b90d30003900000070043000390000000005070433000000000005004b0000066a0000613d0000000003000019000000000bd30019000000000c630019000000000c0c04330000000000cb04350000002003300039000000000053004b000006630000413d0000000003d500190000000000030435000000000354001900000049043000390000047e050000410000000000540435000000570d30003900000046043000390000000005080433000000000005004b0000067d0000613d00000000030000190000000008d30019000000000b930019000000000b0b04330000000000b804350000002003300039000000000053004b000006760000413d0000000003d500190000000000030435000000000354001900000011043000390000047f0500004100000000005404350000002008300039000000030430003900000016030000290000000005030433000000000005004b000006910000613d00000000030000190000000009830019000000000b230019000000000b0b04330000000000b904350000002003300039000000000053004b0000068a0000413d0000000002850019000000000002043500000000025400190000001d032000390000048004000041000000000043043500000021032000390000047904000041000000000043043500000022092000390000000e052000390000000008070433000000000008004b000006a70000613d00000000030000190000000002930019000000000b630019000000000b0b04330000000000b204350000002003300039000000000083004b000006a00000413d0000000002980019000000000002043500000000028500190000005403200039000004810500004100000000005304350000003403200039000004820500004100000000005304350000001403200039000004830500004100000000005304350000006c0320003900000000004304350000006d082000390000000f042000390000000005070433000000000005004b000006c20000613d000000000300001900000000028300190000000007630019000000000707043300000000007204350000002003300039000000000053004b000006bb0000413d0000000002850019000000000002043500000000025400190000005e03200039000004840400004100000000004304350000007003200039000004850400004100000000004304350000000002a20049000000580320003900000000003a04350000009702200039000004cf022001970000000003a20019000000000023004b00000000020000390000000102004039000e00000003001d0000042b0030009c000003cd0000213d0000000100200190000003cd0000c13d0000000e02000029000000400020043f0000001c02000029000a00000002001d0000000025020434000f00000002001d0000042b0050009c000003cd0000213d00000005045002100000003f0240003900000460022001970000000e022000290000042b0020009c000003cd0000213d000000170300002900000005033002700000000003030031000000400020043f0000000e020000290000000002520436001700000002001d000b00000003001d000000000043004b000006f80000813d00000060030000390000000b02000029000000170520002900000000003504350000002002200039000000000042004b000006f30000413d0000000a020000290000008002200039000500000002001d00000000070204330000000098070434000000010580003a000007090000c13d000004cd010000410000000b0200002900000000001204350000001101000039000000040010043f000004260020009c00000426020080410000004001200210000004ce011001c70000104f000104300000045f0080009c000003cd0000213d00000005065002100000003f026000390000046002200197000000400400043d0000000003240019000000000043004b000000000200003900000001020040390000042b0030009c000003cd0000213d0000000100200190000003cd0000c13d000000400030043f00000000055404360000001f0a60018f000000000006004b000007230000613d0000000006650019000000000301034f0000000002050019000000003b03043c0000000002b20436000000000062004b0000071f0000c13d00000000000a004b0000000b0a00002900000000060a00190000072b0000013d00000001066000390000000000a3001a000000000aa30019000000940000413d000000000204043300000000008a004b000007440000813d000000000062004b00000a3a0000a13d000000050260021000000000025200190000000000a2043500000000020704330000000000a2004b00000a3a0000a13d0000000002a90019000000000d0204330000046500d0009c0000000103000039000007270000413d0000046602d00197000004670020009c0000000203000039000007270000613d0000046802d00197000004660020009c00000004030000390000000303006039000007270000013d000000000062004b00000a3a0000a13d000000050260021000000000025200190000000000a204350000045f0060009c000003cd0000213d000000010860003900000005078002100000003f027000390000046002200197000000400900043d0000000003290019001500000009001d000000000093004b000000000200003900000001020040390000042b0030009c000003cd0000213d0000000100200190000003cd0000c13d000000400030043f00000015020000290000000002820436001400000002001d0000001f0870018f000000000007004b000007660000613d00000014020000290000000007720019000000001301043c0000000002320436000000000072004b000007620000c13d000000000008004b0000000b0060006b000007790000213d0000000b030000290000000001040433000000000031004b00000a3a0000a13d00000015010000290000000001010433000000000031004b00000a3a0000a13d00000005013002100000001402100029000000000151001900000000010104330000000000120435000000000063004b00000001033000390000076a0000413d0000000a0100002900000000010104330000000b0010006b000009cd0000813d0000000a01000029000701000010003d001001400010003d000300e00010003d0000001d02000029000600800020003d000100200020003d000401200020003d000200000002001d000800600020003d000901200010003d0013000b0000002d0012000b0000002d000000400100043d001100000001001d0000043c0010009c000003cd0000213d00000011020000290000004001200039000000400010043f000000010100003900000000021204360000048601000041001600000002001d000000000012043500000009010000290000000001010433000000130010006b000007a60000413d000000400100043d001100000001001d0000043c0010009c000003cd0000213d00000011020000290000004001200039000000400010043f000000030100003900000000021204360000048701000041001600000002001d000000000012043500000008010000290000000001010433000000040010008c00000ba40000813d000000010010008c000007dc0000613d000000020010008c000007e50000613d000000030010008c000007ee0000c13d0000000f010000290000000001010433000d00000001001d000000000001004b000006ff0000613d00000004010000290000000002010433000000010120003a000000940000613d0000000103000029000000000303043300000004040000290000000000140435000000400100043d000000400410003900000000002404350000004002000039000000000221043600000000003204350000043e0010009c000003cd0000213d0000006003100039000000400030043f000004260020009c000004260200804100000040022002100000000001010433000004260010009c00000426010080410000006001100210000000000121019f0000000002000414000004260020009c0000042602008041000000c002200210000000000112019f0000043d011001c70000801002000039104d10480000040f0000000100200190000000c10000613d000000000101043b0000000d101000fa000008120000013d000000120000006b000008110000613d0000000601000029000000000201043300000012012000b900000012031000fa000000000023004b000008120000613d000000940000013d0000000f010000290000000001010433000000120210006c000000940000413d0000000601000029000000000301043300000000012300a90000080d0000c13d000008120000013d0000000f010000290000000001010433000000000001004b000003390000613d00000012201000f90000000103100270000000020400002900000000040404330000000100400190000007fd0000c13d000000000032004b000007ff0000213d000000000002004b0000080a0000c13d000008110000013d000000000032004b0000080a0000213d000000010310021000000000011300d9000000020010008c000006ff0000c13d000000000003004b000003390000613d00000000103200d9000000000113004900000000203100d9000000000002004b000008110000613d0000000601000029000000000301043300000000012300a900000000022100d9000000000032004b000008120000613d000000940000013d00000000010000190000000f0200002900000000030204330000000002010019000000000131004b000008140000813d00000015010000290000000001010433000000000001004b000000940000613d000000010410008a000000000024004b000008650000a13d00000003030000290000000003030433000000000023001a000000940000413d0000000003230019000000000013004b0000000003048019000000000021004b00000a3a0000a13d000000000031004b00000a3a0000a13d000000050120021000000014011000290000000001010433000000050230021000000014022000290000000006020433000000000216004b000000940000413d0000042b0020009c000003cd0000213d0000001f03200039000004cf073001970000003f03700039000004cf04300197000000400300043d0000000005430019000000000035004b000000000400003900000001040040390000042b0050009c000003cd0000213d0000000100400190000003cd0000c13d00000005040000290000000004040433000000400050043f0000000005230436000000000007004b0000084e0000613d0000000007750019000000000800003100000001088003670000000009050019000000008a08043c0000000009a90436000000000079004b0000084a0000c13d000000000016004b0000086b0000613d0000002006400039000000000700001900000000081700190000000009040433000000000089004b00000a3a0000a13d0000000009030433000000000079004b00000a3a0000a13d000000000886001900000000080804330000045d088001970000000009570019000000000a0904330000043f0aa0019700000000088a019f00000000008904350000000107700039000000000027004b000008520000413d0000086b0000013d000000400300043d000004880030009c000003cd0000213d0000002001300039000000400010043f0000000000030435000000100100002900000000070104330000046b0070009c000008720000413d0000046b0170012a00000040080000390000087b0000013d0000046d0070009c00000000010700190000046c0110212a000000000800003900000020080020390000046e0010009c00000010088081bf0000046f011081970000046e0110812a000004700010009c00000008088080390000042b01108197000004700110812a000027100010008c00000004088080390000042601108197000027100110811a000000640010008c00000002088080390000ffff0110818f000000640110811a000000090010008c0000000108802039000004cf018001970000005f02100039000004cf04200197000000400500043d0000000002540019000000000042004b000000000400003900000001040040390000042b0020009c000003cd0000213d0000000100400190000003cd0000c13d000000400020043f000000010280003900000000042504360000002009100039000004cf019001980000000006000031000d00010000036b000c00000006001d0000000106600367000008a60000613d000000000a140019000000000106034f0000000002040019000000001b01043c0000000002b204360000000000a2004b000008a20000c13d0000001f0090019000000000018500190000002108100039000000090070008c0000000a1770011a0000000301100210000000010880008a00000000020804330000043f022001970000043b0110021f0000047101100197000000000121019f0000000000180435000008a90000213d0000000701000029000000000101043300000013071000b9000000130000006b000008bc0000613d00000013027000fa000000000012004b000000940000c13d0000000101100270000000000071001a000000940000413d000000000171001900000010020000290000000002020433000000000012001a000000940000413d00000000091200190000046b0090009c000008ca0000413d0000046b0790012a000000400a000039000008d30000013d0000046d0090009c00000000070900190000046c0770212a000000000a000039000000200a0020390000046e0070009c000000100aa081bf0000046f017081970000046e0710812a000004700070009c000000080aa080390000042b01708197000004700710812a000027100070008c000000040aa080390000042601708197000027100710811a000000640070008c000000020aa080390000ffff0170818f000000640710811a000000090070008c000000010aa02039000004cf0ba001970000005f01b00039000004cf02100197000000400800043d0000000001820019000000000021004b000000000200003900000001020040390000042b0010009c000003cd0000213d0000000100200190000003cd0000c13d000000400010043f0000000101a000390000000007180436000000200bb00039000004cf01b00198000008fa0000613d000000000c170019000000000106034f0000000002070019000000001d01043c0000000002d204360000000000c2004b000008f60000c13d0000001f00b001900000000001a80019000000210a100039000000090090008c0000000a1990011a0000000301100210000000010aa0008a00000000020a04330000043f022001970000043b0110021f0000047101100197000000000121019f00000000001a0435000008fd0000213d00000010010000290000000001010433000007d00010008c000006ff0000213d000007d002100089000000000b12004b000000940000413d0000048900b0009c000000000c0000390000004c0c00203900000000090b00190000000b09002039000000640090008c000000020cc081bf0000ffff0190818f000000640910811a000000090090008c000000010cc02039000004cf0dc001970000005f01d00039000004cf02100197000000400a00043d0000000001a20019000000000021004b000000000200003900000001020040390000042b0010009c000003cd0000213d0000000100200190000003cd0000c13d000000400010043f0000000101c0003900000000091a0436000000200dd00039000004cf01d00198000009320000613d000000000e1900190000000001090019000000006206043c00000000012104360000000000e1004b0000092e0000c13d0000001f00d001900000000001ca001900000021061000390000000900b0008c0000000a1bb0011a0000000301100210000000010660008a00000000020604330000043f022001970000043b0110021f0000047101100197000000000121019f0000000000160435000009350000213d000000400600043d00000020016000390000048a0200004100000000002104350000002d0c6000390000001101000029000000000b01043300000000000b004b000009510000613d00000000010000190000000002c10019000000160d100029000000000d0d04330000000000d2043500000020011000390000000000b1004b0000094a0000413d0000000001cb00190000000000010435000000000b6b00190000002d01b000390000048b020000410000000000210435000000320cb000390000000005050433000000000005004b000009630000613d00000000010000190000000002c10019000000000d410019000000000d0d04330000000000d204350000002001100039000000000051004b0000095c0000413d0000000001c5001900000000000104350000000004b5001900000032014000390000048c020000410000000000210435000000370b4000390000000005080433000000000005004b000009750000613d00000000010000190000000002b100190000000008710019000000000808043300000000008204350000002001100039000000000051004b0000096e0000413d0000002d014000390000000002b50019000000000002043500000000045100190000000a014000390000048d020000410000000000210435000000180740003900000000050a0433000000000005004b000009880000613d000000000100001900000000027100190000000008910019000000000808043300000000008204350000002001100039000000000051004b000009810000413d000000050140003900000000027500190000000000020435000000000451001900000013014000390000048e02000041000000000021043500000015054000390000000073030434000000000003004b0000099b0000613d000000000100001900000000025100190000000008170019000000000808043300000000008204350000002001100039000000000031004b000009940000413d000000050140003900000000025300190000000000020435000000000131001900000010021000390000048f0300004100000000003204350000000001610049000000090210008a00000000002604350000003601100039000004cf021001970000000001620019000000000021004b000000000200003900000001020040390000042b0010009c000003cd0000213d0000000100200190000003cd0000c13d000000400010043f0000000e010000290000000001010433000000130010006c00000a3a0000a13d00000013040000290000000501400210000000170110002900000000006104350000000e010000290000000003010433000000000043004b00000a3a0000a13d0000001201000029001200010010003e000000940000613d0000000f010000290000000001010433000000120010006b0000000b0100002900000000020100190000001202004029001200000002001d0000001302000029001300010020003d0000000a010000290000000001010433000000130010006b0000078a0000413d000009cf0000013d0000000e0100002900000000030104330000000b04000029000000000034004b000009de0000813d0000000b0400002900000000050400190000000501500210000000170110002900000000010104330000000001010433000000000041001a000000940000413d00000000044100190000000105500039000000000035004b000009d40000413d0000042b0040009c000003cd0000213d0000001f01400039000004cf031001970000003f01300039000004cf01100197000000400200043d0000000001120019001600000002001d000000000021004b000000000200003900000001020040390000042b0010009c000003cd0000213d0000000100200190000003cd0000c13d000000400010043f00000016010000290000000001410436001500000001001d0000000c020000290000000d0120035f000000000003004b000009fd0000613d00000015040000290000000002340019000000000301034f000000003503043c0000000004540436000000000024004b000009f90000c13d0000000e0200002900000000020204330000000b0020006b00000a400000813d0000000b050000290000000302500210000000000405001900000a0a0000013d00000001044000390000000e060000290000000006060433000000000064004b00000a400000813d00000005064002100000001706600029000000000606043300000000780604340000000b0080006b00000a050000813d0000000b080000290000001f0080008c00000a240000a13d0000000b07000029000004d10050009c000000940000613d00000016080000290000000008080433000000000058004b00000a3a0000a13d000000150850002900000000090804330000043f099001970000000000980435000000010550003900000001077000390000000008060433000000000087004b00000a140000413d00000a050000013d0000000b08000029000004d10050009c000000940000613d00000016090000290000000009090433000000000059004b00000a3a0000a13d000000000987001900000000090904330000045d0990019700000000092901cf000000150a500029000000000b0a04330000043f0bb0019700000000099b019f00000000009a0435000000010550003900000001088000390000000009060433000000000098004b00000a250000413d00000a050000013d000004cd01000041000000000010043f0000003201000039000000040010043f000004ce010000410000104f000104300000000a02000029000001000220003900000000020204330000046b0020009c00000a480000413d00000040030000390000046b0420012a00000a510000013d0000046d0020009c00000000040200190000046c0440212a000000000300003900000020030020390000046e0040009c00000010033081bf0000046f044081970000046e0440812a000004700040009c00000008033080390000042b04408197000004700440812a000027100040008c00000004033080390000042604408197000027100440811a000000640040008c00000002033080390000ffff0440818f000000640440811a000000090040008c0000000103302039000004cf043001970000005f05400039000004cf06500197000000400500043d001700000005001d0000000005560019000000000065004b000000000600003900000001060040390000042b0050009c000003cd0000213d0000000100600190000003cd0000c13d0000000a06000029000000a0066000390000000006060433001100000006001d000000400050043f000000010530003900000017060000290000000005560436001200000005001d0000002004400039000004cf054001980000001f0440018f00000a7f0000613d00000012060000290000000005560019000000001701043c0000000006760436000000000056004b00000a7b0000c13d000000000004004b00000017013000290000002101100039000000090020008c0000000a3220011a0000000303300210000000010110008a00000000040104330000043f044001970000043b0330021f0000047103300197000000000343019f000000000031043500000a820000213d000000a0010000390000001d0110002900000000020104330000001e012000c9000000000002004b00000a960000613d00000000022100d90000001e0020008c000006ff0000c13d104d0ffc0000040f000f00000001001d00000018010000290000000013010434000e00000003001d0000001902000029001300000002001d0000000002020433001400000002001d0000002002200039001000000002001d104d0bbb0000040f0000000e020000290000001402200029000e00000002001d00000016010000290000000003010433001600000003001d00000020022000390000001501000029104d0bbb0000040f00000016020000290000000e012000290000048e020000410000004003100039000000000023043500000490020000410000002003100039001600000003001d00000000002304350000004202100039000000110300002900000020013000390000000003030433001500000003001d104d0bbb0000040f00000015020000290000001604200029001600000004001d0000048f01000041000000220240003900000000001204350000049101000041000007290240003900000000001204350000049201000041000007090240003900000000001204350000049301000041000006e90240003900000000001204350000049401000041000006c90240003900000000001204350000049501000041000006a90240003900000000001204350000049601000041000006890240003900000000001204350000049701000041000006690240003900000000001204350000049801000041000006490240003900000000001204350000049901000041000006290240003900000000001204350000049a01000041000006090240003900000000001204350000049b01000041000005e90240003900000000001204350000049c01000041000005c90240003900000000001204350000049d01000041000005a90240003900000000001204350000049e01000041000005890240003900000000001204350000049f0100004100000569024000390000000000120435000004a00100004100000549024000390000000000120435000004a10100004100000529024000390000000000120435000004a20100004100000509024000390000000000120435000004a301000041000004e9024000390000000000120435000004a401000041000004c9024000390000000000120435000004a501000041000004a9024000390000000000120435000004a60100004100000489024000390000000000120435000004a70100004100000469024000390000000000120435000004a80100004100000449024000390000000000120435000004a90100004100000429024000390000000000120435000004aa0100004100000409024000390000000000120435000004ab01000041000003e9024000390000000000120435000004ac01000041000003c9024000390000000000120435000004ad01000041000003a9024000390000000000120435000004ae0100004100000389024000390000000000120435000004af0100004100000369024000390000000000120435000004b00100004100000349024000390000000000120435000004b10100004100000329024000390000000000120435000004b20100004100000309024000390000000000120435000004b301000041000002e9024000390000000000120435000004b401000041000002c9024000390000000000120435000004b501000041000002a9024000390000000000120435000004b60100004100000289024000390000000000120435000004b70100004100000269024000390000000000120435000004b80100004100000249024000390000000000120435000004b90100004100000229024000390000000000120435000004ba0100004100000209024000390000000000120435000004bb01000041000001e9024000390000000000120435000004bc01000041000001c9024000390000000000120435000004bd01000041000001a9024000390000000000120435000004be0100004100000189024000390000000000120435000004bf0100004100000169024000390000000000120435000004c00100004100000149024000390000000000120435000004c10100004100000129024000390000000000120435000004c20100004100000109024000390000000000120435000004c301000041000000e9024000390000000000120435000004c401000041000000c9024000390000000000120435000004c501000041000000a9024000390000000000120435000004c60100004100000089024000390000000000120435000004c70100004100000069024000390000000000120435000004c80100004100000049024000390000000000120435000004c9010000410000002902400039000000000012043500000017010000290000000003010433001700000003001d00000745024000390000001201000029104d0bbb0000040f00000017020000290000001604200029001700000004001d000004ca01000041000007450240003900000000001204350000000f0200002900000020012000390000000003020433001600000003001d0000074602400039104d0bbb0000040f00000016020000290000001704200029000004cb0200004100000746034000390000000000230435000004cc0200004100000755034000390000000000230435000000140100002900000000031400490000073b0230003900000000002104350000075b02300039104d0ba90000040f000000200100003900000013040000290000000002040433001700000002001d000000000112043600000014030000290000000003030433001600000003001d000000000031043500000000024200190000001001000029104d0bbb0000040f00000016010000290000001f01100039000004cf011001970000001301100029000004260010009c000004260100804100000060011002100000001702000029000004260020009c00000426020080410000004002200210000000000121019f0000104e0001042e000004cd010000410000000b0200002900000000001204350000002101000039000007030000013d0000001f02200039000004cf022001970000000001120019000000000021004b000000000200003900000001020040390000042b0010009c00000bb50000213d000000010020019000000bb50000c13d000000400010043f000000000001042d000004cd01000041000000000010043f0000004101000039000000040010043f000004ce010000410000104f00010430000000000003004b00000bc50000613d000000000400001900000000052400190000000006140019000000000606043300000000006504350000002004400039000000000034004b00000bbe0000413d00000000012300190000000000010435000000000001042d00000000030100190000001f01100039000000000021004b0000000004000019000004650400404100000465052001970000046501100197000000000651013f000000000051004b00000000010000190000046501002041000004650060009c000000000104c019000000000001004b00000c100000613d0000000105000367000000000135034f000000000401043b000004d20040009c00000c0a0000813d0000001f01400039000004cf011001970000003f01100039000004cf07100197000000400100043d0000000007710019000000000017004b000000000800003900000001080040390000042b0070009c00000c0a0000213d000000010080019000000c0a0000c13d0000002008300039000000400070043f00000000034104360000000007840019000000000027004b00000c100000213d000000000585034f000004cf064001980000001f0740018f000000000263001900000bfa0000613d000000000805034f0000000009030019000000008a08043c0000000009a90436000000000029004b00000bf60000c13d000000000007004b00000c070000613d000000000565034f0000000306700210000000000702043300000000076701cf000000000767022f000000000505043b0000010006600089000000000565022f00000000056501cf000000000575019f000000000052043500000000024300190000000000020435000000000001042d000004cd01000041000000000010043f0000004101000039000000040010043f000004ce010000410000104f0001043000000000010000190000104f00010430000e0000000000020000004002200039000100000002001d000000000f02043300000000e20f0434000004d20020009c00000dce0000813d00000005052002100000003f035000390000046004300197000000400300043d0000000004430019000000000034004b000000000600003900000001060040390000042b0040009c00000dce0000213d000000010060019000000dce0000c13d000000400040043f00000000042304360000001f0650018f00000000020000310000000102200367000000000005004b00000c330000613d0000000005540019000000000702034f0000000008040019000000007907043c0000000008980436000000000058004b00000c2f0000c13d000000000006004b00000000060f04330000042b0060009c00000dce0000213d00000005076002100000003f057000390000046008500197000000400500043d0000000008850019000000000058004b000000000900003900000001090040390000042b0080009c00000dce0000213d000000010090019000000dce0000c13d000000400080043f00000000066504360000001f0870018f000000000007004b00000c4f0000613d0000000007760019000000000902034f000000000a060019000000009b09043c000000000aba043600000000007a004b00000c4b0000c13d000000000008004b00000000070f0433000000000007004b00000c7b0000613d000000000a0000190000000007000019000000000b07001900000000070304330000000000b7004b00000dc20000a13d0000000507b00210000000000c4700190000000000ac0435000000000c0f04330000000000ac004b00000dc20000a13d000000000cae0019000000000d0c04330000046500d0009c000000010c00003900000c6c0000413d000004660cd001970000046700c0009c000000020c00003900000c6c0000613d000004680cd001970000046600c0009c000000040c000039000000030c006039000000000d0504330000000000bd004b00000dc20000a13d00000000076700190000000000c704350000000000ac001a00000dc80000413d000000000aac00190000000107b00039000000000c0f04330000000000ca004b00000c550000413d0000045f00b0009c00000c7c0000a13d00000dce0000013d000000000700001900000005087002100000003f09800039000004600a900197000000400b00043d0000000009ab0019000b0000000b001d0000000000b9004b000000000b000039000000010b0040390000042b0090009c00000dce0000213d0000000100b0019000000dce0000c13d00090000000e001d000000400090043f0000000b090000290000000009790436000a00000009001d0000001f0980018f000000000008004b00000c980000613d0000000a0d000029000000000b8d0019000000000c02034f00000000ce0c043c000000000ded04360000000000bd004b00000c940000c13d000000000009004b000000400b00043d000000000aab0019000d0000000b001d0000000000ba004b000000000b000039000000010b0040390000042b00a0009c000000090d00002900000dce0000213d0000000100b0019000000dce0000c13d0000004000a0043f0000000d0a000029000000000a7a0436000c0000000a001d000000000008004b00000cb10000613d0000000c0b00002900000000088b0019000000000a02034f00000000ac0a043c000000000bcb043600000000008b004b00000cad0000c13d000000000009004b000000000007004b00000ccf0000613d00000000080000190000000009030433000000000089004b00000dc20000a13d0000000b090000290000000009090433000000000089004b00000dc20000a13d00000005098002100000000a0a900029000000000b490019000000000b0b04330000000000ba0435000000000a05043300000000008a004b00000dc20000a13d0000000d0a000029000000000a0a043300000000008a004b00000dc20000a13d0000000c0a9000290000000009690019000000000909043300000000009a04350000000108800039000000000078004b00000cb50000413d0000000b03000029000000000b0304330000042b00b0009c00000dce0000213d0000000503b002100000003f043000390000046004400197000000400c00043d00000000044c00190000000000c4004b000000000500003900000001050040390000042b0040009c00000dce0000213d000000010050019000000dce0000c13d000000400040043f000000000ebc04360000001f0430018f000000000003004b00000cea0000613d00000000033e001900000000050e0019000000002602043c0000000005650436000000000035004b00000ce60000c13d000000000004004b000000e002100039000800000002001d0000000002020433000000000002004b00000d320000613d00000000000b004b00000dc80000613d000700200010003d0000012004100039000000000200001900060000000f001d00050000000b001d00040000000c001d00030000000e001d000200000004001d000e00000002001d0000000002040433000000010120003a00000dc80000613d000000070300002900000000030304330000000000140435000000400100043d000000400410003900000000002404350000004002000039000000000221043600000000003204350000043e0010009c00000dce0000213d0000006003100039000000400030043f000004260020009c000004260200804100000040022002100000000001010433000004260010009c00000426010080410000006001100210000000000121019f0000000002000414000004260020009c0000042602008041000000c002200210000000000112019f0000043d011001c70000801002000039104d10480000040f000000010020019000000dd40000613d000000000101043b000000050b0000290000000010b100d9000000040c00002900000000020c0433000000000012004b000000060f000029000000090d000029000000030e00002900000dc20000a13d00000005011002100000000001e10019000000010200003900000000002104350000000e02000029000000010220003900000008010000290000000001010433000000000012004b000000020400002900000cfa0000413d00000000000b004b00000d530000613d00000000010c04330000000004000019000000000200001900000d3b0000013d00000001044000390000000000b4004b00000d500000813d000000000041004b00000dc20000a13d00000005054002100000000006e500190000000006060433000000000006004b00000d460000613d000004d70020009c00000dc80000213d000000030220003900000d380000013d0000000d060000290000000006060433000000000046004b00000dc20000a13d0000000c055000290000000005050433000000000052001a00000dc80000413d000000000252001900000d380000013d0000042b0020009c00000d540000a13d00000dce0000013d00000000020000190000001f01200039000004d3031001970000003f01300039000004d404100197000000400100043d0000000004410019000000000014004b000000000500003900000001050040390000042b0040009c00000dce0000213d000000010050019000000dce0000c13d000000400040043f0000000002210436000000000003004b00000d6d0000613d0000000003320019000000000400003100000001044003670000000005020019000000004604043c0000000005650436000000000035004b00000d690000c13d00000000000b004b00000dbf0000613d0000000003000019000000000400001900000d750000013d00000001033000390000000000b3004b00000dbf0000813d00000000050c0433000000000035004b00000dc20000a13d00000005063002100000000005e600190000000005050433000000000005004b00000d990000613d0000000005010433000000000045004b00000dc20000a13d000000000524001900000000060504330000043f06600197000004d5066001c7000000000065043500000001054000390000000006010433000000000056004b00000dc20000a13d000000000525001900000000060504330000043f0660019700000465066001c7000000000065043500000002054000390000000006010433000000000056004b00000dc20000a13d000000000525001900000000060504330000043f06600197000004d6066001c70000000000650435000000030440003900000d720000013d0000000b050000290000000005050433000000000035004b00000dc20000a13d0000000d050000290000000005050433000000000035004b00000dc20000a13d0000000c056000290000000005050433000000000005004b00000dbb0000613d0000000a0660002900000000060604330000000007000019000000000867001900000000090f0433000000000089004b00000dc20000a13d0000000009740019000000000a01043300000000009a004b00000dc20000a13d000000000929001900000000088d001900000000080804330000045d08800197000000000a0904330000043f0aa0019700000000088a019f00000000008904350000000107700039000000000057004b00000da80000413d000000000054001a00000dc80000413d000000000454001900000d720000013d00000001020000290000000000120435000000000001042d000004cd01000041000000000010043f0000003201000039000000040010043f000004ce010000410000104f00010430000004cd01000041000000000010043f0000001101000039000000040010043f000004ce010000410000104f00010430000004cd01000041000000000010043f0000004101000039000000040010043f000004ce010000410000104f0001043000000000010000190000104f0001043000070000000000020000000093010434000000000003004b00000e1a0000613d00000000460204340000042b0060009c00000fe20000213d00000005056002100000003f035000390000046003300197000000400800043d0000000003380019000000000083004b000000000700003900000001070040390000042b0030009c00000fe20000213d000000010070019000000fe20000c13d000000400030043f000000000a6804360000001f0750018f0000000003000031000100010030036b000000000005004b00000df70000613d00000000055a0019000000010b00035f00000000030a001900000000bc0b043c0000000003c30436000000000053004b00000df30000c13d000000000007004b000000000006004b00000e210000613d0000000007000019000000000b00001900000e040000013d0000000503b002100000000003a300190000000000730435000000010bb000390000000107700039000000000067004b00000e170000813d0000000003020433000000000073004b00000e110000a13d000000000374001900000000030304330000046703300197000004650030009c00000e010000613d000004d100b0009c00000fdc0000613d00000000030804330000000000b3004b00000dfd0000213d000004cd01000041000000000010043f0000003201000039000000040010043f000004ce010000410000104f000104300000042b00b0009c00000e220000a13d00000fe20000013d000000400100043d000004df0010009c00000fe20000813d0000002002100039000000400020043f0000000000010435000000000001042d000000000b000019000000050cb002100000003f03c00039000004d803300197000000400600043d0000000003360019000000000063004b000000000700003900000001070040390000042b0030009c00000fe20000213d000000010070019000000fe20000c13d000000400030043f0000000003b60436000500000003001d0000001f0dc0018f00000000000c004b00000e3b0000613d0000000503000029000000000cc30019000000010e00035f00000000ef0e043c0000000003f304360000000000c3004b00000e370000c13d00000000000d004b00000000000b004b00000e4d0000613d000000000c00001900000000030804330000000000c3004b00000e110000a13d00000000030604330000000000c3004b00000e110000a13d0000000503c00210000000050d3000290000000003a30019000000000303043300000000003d0435000000010cc000390000000000bc004b00000e3f0000413d0000000003060433000200000003001d000000010030008c00000fe80000a13d00000000080104330000042b0080009c00000fe20000213d0000001f03800039000004cf0b3001970000003f03b00039000004cf03300197000000400c00043d00000000033c00190000000000c3004b000000000a000039000000010a0040390000042b0030009c00000fe20000213d0000000100a0019000000fe20000c13d000000400030043f000000000a8c043600000000000b004b00000e6c0000613d0000000008ba0019000000010b00035f00000000030a001900000000bd0b043c0000000003d30436000000000083004b00000e680000c13d0000000008000415000000070880008a00000005088002100000000003010433000000000003004b00000e910000613d000000000800001900000000030c0433000000000083004b00000e110000a13d000000000389001900000000030304330000045d03300197000000000ba80019000000000d0b04330000043f0dd0019700000000033d019f00000000003b04350000000108800039000000000b0104330000000000b8004b00000e730000413d0000000008000415000000070880008a000000050880021000000000000b004b00000e910000613d0000000309b002100000000001b900d9000000080010008c00000fdc0000c13d0000000008000415000000060880008a00000005088002100000042b0090009c00000e930000a13d00000fe20000013d0000000009000019000000000b000019000000080ab00210000004d901a00197000000400700043d00000000011700190000002003100039000400000007001d000000000073004b000000000100003900000001010040390000042b0030009c00000fe20000213d000000010010019000000fe20000c13d000000400030043f00000004010000290000000001910436000300000001001d0000001f09a0018f00000000000a004b00000eae0000613d0000000303000029000000000aa30019000000010b00035f00000000b10b043c00000000031304360000000000a3004b00000eaa0000c13d000000000009004b0000000501800270000000040100002f00000000080c0433000000000008004b00000f4f0000613d000000000b000019000000200ac0003900000000090000190000000001a9001900000000010104330000043f0010009c00000ebf0000213d0000000109900039000000000089004b00000eb70000413d00000f4d0000013d0000042b0080009c00000fe20000213d0000001f01800039000004cf091001970000003f01900039000004cf01100197000000400e00043d00000000031e00190000000000e3004b000000000100003900000001010040390000042b0030009c00000fe20000213d000000010010019000000fe20000c13d000000400030043f000000000d8e0436000000000009004b00000ed90000613d00000000099d0019000000010f00035f00000000030d001900000000f10f043c0000000003130436000000000093004b00000ed50000c13d0000000009000019000000000f00001900000000010c0433000000000091004b00000e110000a13d00000000010e0433000000000091004b00000e110000a13d0000000001a900190000000001010433000000f8011002700000000803f00210000000000113019f00000002f11000fa000000f8011002100000000003d9001900000000070304330000043f07700197000000000117019f00000000001304350000000109900039000000000089004b00000edb0000413d000000010980008c00000f0f0000613d000000000c0e0433000000000a0000190000000000ac004b00000e110000a13d0000000001da00190000000001010433000004da0010009c00000eff0000813d000000010aa0003900000000009a004b00000ef40000413d000000000a09001900000f110000013d00000000000a004b00000f0f0000613d00000000008a004b00000f110000c13d000000400c00043d0000043c00c0009c00000fe20000213d0000004001c00039000000400010043f000000010100003900000000011c0436000000010300035f000000000303043b0000043f03300197000000000031043500000f410000013d000000000c0e001900000f410000013d0000000008a8004b00000fdc0000413d0000042b0080009c00000fe20000213d0000001f01800039000004cf091001970000003f01900039000004cf01100197000000400c00043d00000000031c00190000000000c3004b000000000100003900000001010040390000042b0030009c00000fe20000213d000000010010019000000fe20000c13d000000400030043f00000000018c0436000000000009004b00000f2d0000613d0000000009910019000000010300035f0000000008010019000000003703043c0000000008780436000000000098004b00000f290000c13d00000000030c0433000000000003004b00000f410000613d00000000090000190000000003a9001900000000070e0433000000000037004b00000e110000a13d0000000003d3001900000000030304330000045d03300197000000000719001900000000080704330000043f08800197000000000338019f0000000000370435000000010990003900000000030c0433000000000039004b00000f310000413d000000040100002900000000010104330000000000b1004b00000e110000a13d0000000501b0021000000003011000290000000000f10435000000010bb0003900000000080c0433000000000008004b00000eb50000c13d00000f560000013d00000000000b004b00000f560000c13d00000004010000290000000001010433000000000001004b00000e110000613d00000003010000290000000000010435000000010b0000390000000208b002100000000001b800d9000000040010008c00000fdc0000c13d0000042b0080009c00000fe20000213d0000001f01800039000004cf091001970000003f01900039000004cf01100197000000400a00043d00000000031a00190000000000a3004b000000000100003900000001010040390000042b0030009c00000fe20000213d000000010010019000000fe20000c13d000000400030043f000000000c8a0436000000000009004b00000f740000613d00000000089c0019000000010300035f00000000010c0019000000003703043c0000000001710436000000000081004b00000f700000c13d0000000008000019000000000d00001900000f7a0000013d00000001088000390000000000b8004b00000fad0000813d000004d10180016700000000011b001900000004030000290000000003030433000000000013004b00000e110000a13d0000000501100210000000030110002900000000010104330000000003060433000000000013004b00000e110000a13d00000005011002100000000501100029000000000e01043300000000090e0019000000010090003a00000fdc0000413d000000000f09001900000001099000390000000001020433000000000019004b00000f960000813d000000000194001900000000010104330000046701100197000004650010009c00000f8a0000613d0000000000fe004b00000f770000213d00000000010204330000000000e1004b00000e110000a13d000004d100d0009c00000fdc0000613d00000000010a04330000000000d1004b00000e110000a13d0000000001e4001900000000010104330000045d011001970000000003cd001900000000070304330000043f07700197000000000117019f00000000001304350000000000fe004b000000010ee00039000000010dd0003900000f980000413d00000f770000013d0000042b00d0009c00000fe20000213d0000001f01d00039000004cf041001970000003f01400039000004cf02100197000000400100043d0000000002210019000000000012004b000000000300003900000001030040390000042b0020009c00000fe20000213d000000010030019000000fe20000c13d000000400020043f0000000002d10436000000000004004b000000010600035f00000fc70000613d00000000044200190000000003020019000000006506043c0000000003530436000000000043004b00000fc30000c13d00000000000d004b00000fdb0000613d000000000300001900000000040a0433000000000034004b00000e110000a13d0000000004010433000000000034004b00000e110000a13d0000000004c3001900000000040404330000045d04400197000000000523001900000000060504330000043f06600197000000000446019f000000000045043500000001033000390000000000d3004b00000fca0000413d000000000001042d000004cd01000041000000000010043f0000001101000039000000040010043f000004ce010000410000104f00010430000004cd01000041000000000010043f0000004101000039000000040010043f000004ce010000410000104f00010430000000400100043d0000006402100039000004db0300004100000000003204350000004402100039000004dc030000410000000000320435000000240210003900000024030000390000000000320435000004dd020000410000000000210435000000040210003900000020030000390000000000320435000004260010009c00000426010080410000004001100210000004de011001c70000104f000104300000046b0010009c000010010000413d00000040030000390000046b0210012a0000100a0000013d0000046d0010009c00000000020100190000046c0220212a000000000300003900000020030020390000046e0020009c00000010033081bf0000046f022081970000046e0220812a000004700020009c00000008033080390000042b02208197000004700220812a000027100020008c00000004033080390000042602208197000027100220811a000000640020008c00000002033080390000ffff0220818f000000640220811a000000090020008c0000000103302039000004cf063001970000005f02600039000004cf07200197000000400200043d0000000004270019000000000074004b000000000700003900000001070040390000042b0040009c000010420000213d0000000100700190000010420000c13d000000400040043f000000010430003900000000044204360000002007600039000004cf067001980000001f0570018f000010320000613d000000000664001900000000070000310000000107700367000000007807043c0000000004840436000000000064004b0000102e0000c13d000000000005004b00000000033200190000002103300039000000090010008c0000000a4110011a0000000304400210000000010330008a00000000050304330000043f055001970000043b0440021f0000047104400197000000000445019f0000000000430435000010350000213d0000000001020019000000000001042d000004cd01000041000000000010043f0000004101000039000000040010043f000004ce010000410000104f000104300000104b002104230000000102000039000000000001042d0000000002000019000000000001042d0000104d000004320000104e0001042e0000104f00010430000000000000000000000000000000000000000000000000000000000000005200000000000000000000000000000000000000000000000000000000000001d800000000000000000000000000000000000000000000000000000000000001ed00000000000000000000000000000000000000000000000000000000000001f300000000000000000000000000000000000000000000000000000000000001de00000000000000000000000000000000000000000000000000000000000001d200000000000000000000000000000000000000000000000000000000000001f900000000000000000000000000000000000000000000000000000000000001ff00000000000000000000000000000000000000000000000000000000000001e4000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035b00000000000000000000000000000000000000000000000000000000000003ca000000000000000000000000000000000000000000000000000000000000035b00000000000000000000000000000000000000000000000000000000000003c0000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035b000000000000000000000000000000000000000000000000000000000000035b00000000000000000000000000000000000000000000000000000000000003b200000000000000000000000000000000000000000000000000000000ffffffff000000020000000000000000000000000000004000000100000000000000000000000000000000000000000000000000000000000000000000000000ac7a1a68000000000000000000000000000000000000000000000000000000002d0e7d75000000000000000000000000000000000000000000000000000000001821cec8000000000000000000000000000000000000000000000000ffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000fffffffffffffcdf0200000000000000000000000000000000000040000001e0000000000000000000000000000000000000000000000000000000200000000000000000000000006162636465666768696a6b6c6d6e6f707172737475767778797a414141434445454545484949494c4d4e4f4f505253545561616161616165656565696969696f6f6f6f727272727274746e6e73736c6c000000000000000000000000000000002e2d2e2d2e2d2e2d2e2d0000000000000000000000000000000000000000000027225b5d28297b7d600000000000000000000000000000000000000000000000ce99cea0ce94ce97ce9ccea70000000000000000000000000000000000000000232b2f2d7c5c4f000000000000000000000000000000000000000000000000003031323334353637383900000000000000000000000000000000000000000000e19a81e19a82e19a83e19a84e19a85e19a90e19a91e19a92e19a93e19a94e19a86e19a87e19a88e19a89e19a8ae19a8be19a8ce19a8de19a8ee19a8fe19a8000e28087e280a2e28087e280a2e28087e280a2e28087e280a2e28087e280a200003031323334353637383961626364656600000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbf0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff9f00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000000000000000000000000000000000000000000000000000000000000000ff0000ff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffc0000000000000000000000000000000000000000000000000fffffffffffffffe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0e19a9b0000000000000000000000000000000000000000000000000000000000e19a9c0000000000000000000000000000000000000000000000000000000000307830000000000000000000000000000000000000000000000000000000000030780000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000063656e7472616c00000000000000000000000000000000000000000000000000746578742d626f74746f6d0000000000000000000000000000000000000000000000000000184f03e93ff9f4daa797ed6e38ed64bf6a1f01000000000000000000000000000000000000000000000000000004ee2d6d415b85acef810000000000000000000000000000000000000000000004ee2d6d415b85acef80ffffffff000000000000000000000000000000000000000000000000002386f26fc1000000000000000000000000000000000000ffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000005f5e1007f0000000000000000000000000000000000000000000000000000000000000066697273742d00000000000000000000000000000000000000000000000000003c7376672069643d22000000000000000000000000000000000000000000000077686974653b223e0000000000000000000000000000000000000000000000003c7374796c653e000000000000000000000000000000000000000000000000006c653d226261636b67726f756e642d636f6c6f723a626c61636b3b66696c6c3a737667222076696577426f783d223020302032303030203230303022207374792220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f2300000000000000000000000000000000000000000000000000000000000000656c696e653a000000000000000000000000000000000000000000000000000065222c4d6f6e61636f2c6d6f6e6f73706163653b646f6d696e616e742d62617320746578747b666f6e742d66616d696c793a224c756369646120436f6e736f6c3b7d000000000000000000000000000000000000000000000000000000000000202e6c7b666f6e742d73697a653a00000000000000000000000000000000000070783b6c696e652d6865696768743a000000000000000000000000000000000070783b7d000000000000000000000000000000000000000000000000000000002d77696474683a33303b7374726f6b653a626c61636b3b7d00000000000000003a34303070783b7061696e742d6f726465723a7374726f6b653b7374726f6b65202e6d7b746578742d616e63686f723a6d6964646c653b666f6e742d73697a65202e687b646973706c61793a6e6f6e653b7d00000000000000000000000000003c2f7374796c653e0000000000000000000000000000000000000000000000006c000000000000000000000000000000000000000000000000000000000000006c20680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf0000000000184f03e93ff9f4daa797ed6e38ed64bf6a1f00ffffffffffffffff3c7465787420636c6173733d22000000000000000000000000000000000000002220783d220000000000000000000000000000000000000000000000000000002220793d220000000000000000000000000000000000000000000000000000002220746578744c656e6774683d22000000000000000000000000000000000000223e0000000000000000000000000000000000000000000000000000000000003c2f746578743e000000000000000000000000000000000000000000000000003c7465787420636c6173733d226d2220783d22313030302220793d2231303030742866756e6374696f6e207428297b793d21307d2c31313030297d280000000074417474726962757465282279222c24297d7d2c65292c73657454696d656f75747269627574652822792229292d743b243c2d3265333f793d21313a722e7365743d695b655d7d292c79297b6c657420243d4e756d62657228722e6765744174292c632e666f72456163682828742c65293d3e7b742e74657874436f6e74656e7475726e3b6c6574206c3d692e736869667428293b696628692e70757368286c496e74657276616c2866756e6374696f6e206528297b696628757c7c622972652e7372633d657d297d2c692e7372633d637d63617463682824297b7d7d7365743e7b6c657420653d55524c2e6372656174654f626a65637455524c2874293b73332c326533292c722e636f6e76657274546f426c6f6228292e7468656e28743d2c302c3265332c326533292c742e64726177496d61676528692c302c302c3265742e66696c6c5374796c653d685b665d5b305d2c742e66696c6c526563742830643d28293d3e7b6c657420743d722e676574436f6e746578742822326422293b766173283265332c326533292c693d6e657720496d6167653b692e6f6e6c6f61654f626a65637455524c2865292c723d6e6577204f666673637265656e43616e786d6c3b636861727365743d7574662d38227d292c633d55524c2e6372656174653d6e657720426c6f62285b745d2c7b747970653a22696d6167652f7376672b7269616c697a657228292e73657269616c697a65546f537472696e67286c292c696f6e206b28297b69662861297472797b6c657420743d6e657720584d4c53656c7465723a5b22636c617373225d7d297d6361746368286d297b7d66756e6374727665286c2c7b617474726962757465733a21302c61747472696275746546696e73282270617573652229297d6361746368286c297b7d7d293b672e6f627365262628623d2121652e7461726765742e636c6173734c6973742e636f6e7461692e74797065262622636c617373223d3d3d652e6174747269627574654e616d657b666f72286c65742065206f662074292261747472696275746573223d3d3d657420673d6e6577204d75746174696f6e4f6273657276657228743d3e7b7472792279222c2d326533292c6b28297d297d6361746368285f297b7d7472797b6c65417474726962757465282279222c24293a722e736574417474726962757465282e66696c6c3d685b665d5b315d2c793d21312c685b665d5b325d3f722e7365745d2c722e7374796c652e7374726f6b653d685b665d5b305d2c6c2e7374796c65292c6c2e7374796c652e6261636b67726f756e64436f6c6f723d685b665d5b30286f2e7374796c652e6261636b67726f756e64436f6c6f723d685b665d5b305d222c28293d3e7b2b2b663e682e6c656e6774682d31262628663d30292c612626753d21317d292c6f2e6164644576656e744c697374656e65722822636c69636b64644576656e744c697374656e657228226d6f7573656f7574222c28293d3e7b28226d6f7573656f766572222c28293d3e7b753d21302c6b28297d292c6f2e61682864297b613d21317d7472797b6f2e6164644576656e744c697374656e65726e644368696c642873292c6f3d646f63756d656e742e626f6479297d636174636974696f6e3d226669786564222c646f63756d656e742e626f64792e617070652c732e7374796c652e6f7061636974793d2230222c732e7374796c652e706f736474683d2231303025222c732e7374796c652e6865696768743d2231303025222e746f703d302c732e7374796c652e6c6566743d302c732e7374796c652e77696d656e742e637265617465456c656d656e742822696d672229292e7374796c6522626c61636b222c21305d5d2c663d313b7472797b6126262828733d646f637523363544423745222c22626c61636b222c21315d2c5b2223363544423745222c61636b222c21315d2c5b227768697465222c22626c61636b222c21305d2c5b2222626c61636b222c227768697465222c21305d2c5b227768697465222c22626c312c623d21312c683d5b5b22626c61636b222c227768697465222c21315d2c5b6522297d6361746368286e297b7d6c657420732c6f3d6c2c793d21312c753d2173742e636f6e7461696e7328226669782d72696768742d636c69636b2d736176646f63756d656e742e646f63756d656e74456c656d656e742e636c6173734c69242c613b7472797b243d722e67657441747472696275746528227922292c613d3d41727261792e66726f6d28632c743d3e742e74657874436f6e74656e74292c28222e6c22292c723d6c2e717565727953656c6563746f7228222e6d22292c6972656e74456c656d656e742c633d6c2e717565727953656c6563746f72416c6c7b6c6574206c3d646f63756d656e742e63757272656e745363726970742e70613c7363726970743e3c215b43444154415b202166756e6374696f6e28742c65292c00000000000000000000000000000000000000000000000000000000000000293b205d5d3e3c2f7363726970743e00000000000000000000000000000000003c2f7376673e00000000000000000000000000000000000000000000000000004e487b71000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001ffffffffffffffe0000000000000000000000000000000000000000000000003ffffffffffffffe0e2000000000000000000000000000000000000000000000000000000000000008700000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc00000000000000000000000000000000000000000000003fffffffffffffffe07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000100000000000000000000000000000000000000000000000000000000000000626f6c730000000000000000000000000000000000000000000000000000000043686172736574206d7573742068617665206174206c6561737420322073796d08c379a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffe0ea044705b2611b4cde4dbfc5a6eb4811f3eb931bb37dcf3d9ba0b78d06bd469c
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.